1755Speter /* Copyright (c) 1979 Regents of the University of California */ 2755Speter 3*7955Smckusick static char sccsid[] = "@(#)hash.c 1.4 08/29/82"; 4755Speter 5755Speter #include "whoami.h" 6755Speter #include "0.h" 7755Speter #include "yy.h" 8755Speter 9755Speter /* 10755Speter * The definition for the segmented hash tables. 11755Speter */ 12755Speter struct ht { 13755Speter int *ht_low; 14755Speter int *ht_high; 15755Speter int ht_used; 16755Speter } htab[MAXHASH]; 17755Speter 18755Speter /* 19755Speter * This is the array of keywords and their 20755Speter * token values, which are hashed into the table 21755Speter * by inithash. 22755Speter */ 23755Speter struct kwtab yykey[] = { 24755Speter "and", YAND, 25755Speter "array", YARRAY, 26755Speter "begin", YBEGIN, 27755Speter "case", YCASE, 28755Speter "const", YCONST, 29755Speter "div", YDIV, 30755Speter "do", YDO, 31755Speter "downto", YDOWNTO, 32755Speter "else", YELSE, 33755Speter "end", YEND, 34755Speter "file", YFILE, 35755Speter "for", YFOR, 36755Speter "forward", YFORWARD, 37755Speter "function", YFUNCTION, 38755Speter "goto", YGOTO, 39755Speter "if", YIF, 40755Speter "in", YIN, 41755Speter "label", YLABEL, 42755Speter "mod", YMOD, 43755Speter "nil", YNIL, 44755Speter "not", YNOT, 45755Speter "of", YOF, 46755Speter "or", YOR, 47755Speter "packed", YPACKED, 48755Speter "procedure", YPROCEDURE, 49755Speter "program", YPROG, 50755Speter "record", YRECORD, 51755Speter "repeat", YREPEAT, 52755Speter "set", YSET, 53755Speter "then", YTHEN, 54755Speter "to", YTO, 55755Speter "type", YTYPE, 56755Speter "until", YUNTIL, 57755Speter "var", YVAR, 58755Speter "while", YWHILE, 59755Speter "with", YWITH, 60*7955Smckusick 0, 0, /* the following keywords are non-standard */ 61*7955Smckusick "oct", YOCT, 62*7955Smckusick "hex", YHEX, 63*7955Smckusick "external", YEXTERN, 64755Speter 0 65755Speter }; 66755Speter 67*7955Smckusick char *lastkey; 68755Speter 69755Speter /* 70755Speter * Inithash initializes the hash table routines 71755Speter * by allocating the first hash table segment using 72755Speter * an already existing memory slot. 73755Speter */ 74755Speter #ifndef PI0 75755Speter inithash() 76755Speter #else 77755Speter inithash(hshtab) 78755Speter int *hshtab; 79755Speter #endif 80755Speter { 81755Speter register int *ip; 82755Speter #ifndef PI0 83755Speter static int hshtab[HASHINC]; 84755Speter #endif 85755Speter 86755Speter htab[0].ht_low = hshtab; 87755Speter htab[0].ht_high = &hshtab[HASHINC]; 88755Speter for (ip = yykey; *ip; ip += 2) 89755Speter hash(ip[0], 0)[0] = ip; 90*7955Smckusick /* 91*7955Smckusick * If we are not running in "standard-only" mode, 92*7955Smckusick * we load the non-standard keywords. 93*7955Smckusick */ 94*7955Smckusick if (!opt('s')) 95*7955Smckusick for (ip += 2; *ip; ip += 2) 96*7955Smckusick hash(ip[0], 0)[0] = ip; 97*7955Smckusick lastkey = (char *)ip; 98755Speter } 99755Speter 100755Speter /* 101755Speter * Hash looks up the s(ymbol) argument 102755Speter * in the string table, entering it if 103755Speter * it is not found. If save is 0, then 104755Speter * the argument string is already in 105755Speter * a safe place. Otherwise, if hash is 106755Speter * entering the symbol for the first time 107755Speter * it will save the symbol in the string 108755Speter * table using savestr. 109755Speter */ 110755Speter int *hash(s, save) 111755Speter char *s; 112755Speter int save; 113755Speter { 114755Speter register int *h; 115755Speter register i; 116755Speter register char *cp; 117755Speter int *sym; 118755Speter struct ht *htp; 119755Speter int sh; 120755Speter 121755Speter /* 122755Speter * The hash function is a modular hash of 123755Speter * the sum of the characters with the sum 124755Speter * doubled before each successive character 125755Speter * is added. 126755Speter */ 127755Speter cp = s; 128755Speter if (cp == NIL) 129755Speter cp = token; /* default symbol to be hashed */ 130755Speter i = 0; 131755Speter while (*cp) 132755Speter i = i*2 + *cp++; 133755Speter sh = (i&077777) % HASHINC; 134755Speter cp = s; 135755Speter if (cp == NIL) 136755Speter cp = token; 137755Speter /* 138755Speter * There are as many as MAXHASH active 139755Speter * hash tables at any given point in time. 140755Speter * The search starts with the first table 141755Speter * and continues through the active tables 142755Speter * as necessary. 143755Speter */ 144755Speter for (htp = htab; htp < &htab[MAXHASH]; htp++) { 145755Speter if (htp->ht_low == NIL) { 146755Speter cp = (char *) calloc(sizeof ( int * ), HASHINC); 1471833Speter if (cp == 0) { 148755Speter yerror("Ran out of memory (hash)"); 149755Speter pexit(DIED); 150755Speter } 151755Speter htp->ht_low = cp; 152755Speter htp->ht_high = htp->ht_low + HASHINC; 153755Speter cp = s; 154755Speter if (cp == NIL) 155755Speter cp = token; 156755Speter } 157755Speter h = htp->ht_low + sh; 158755Speter /* 159755Speter * quadratic rehash increment 160755Speter * starts at 1 and incremented 161755Speter * by two each rehash. 162755Speter */ 163755Speter i = 1; 164755Speter do { 165755Speter if (*h == 0) { 166755Speter if (htp->ht_used > (HASHINC * 3)/4) 167755Speter break; 168755Speter htp->ht_used++; 169755Speter if (save != 0) { 170755Speter *h = (int) savestr(cp); 171755Speter } else 172755Speter *h = s; 173755Speter return (h); 174755Speter } 175755Speter sym = *h; 176755Speter if (sym < lastkey && sym >= yykey) 177755Speter sym = *sym; 178755Speter if (sym->pchar == *cp && strcmp(sym, cp) == 0) 179755Speter return (h); 180755Speter h += i; 181755Speter i += 2; 182755Speter if (h >= htp->ht_high) 183755Speter h -= HASHINC; 184755Speter } while (i < HASHINC); 185755Speter } 186755Speter yerror("Ran out of hash tables"); 187755Speter pexit(DIED); 188755Speter } 189