1755Speter /* Copyright (c) 1979 Regents of the University of California */ 2755Speter 3*1833Speter static char sccsid[] = "@(#)hash.c 1.2 11/24/80"; 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 "assert", YASSERT, 27755Speter "begin", YBEGIN, 28755Speter "case", YCASE, 29755Speter "const", YCONST, 30755Speter "div", YDIV, 31755Speter "do", YDO, 32755Speter "downto", YDOWNTO, 33755Speter "else", YELSE, 34755Speter "end", YEND, 35755Speter "file", YFILE, 36755Speter "for", YFOR, 37755Speter "forward", YFORWARD, 38755Speter "function", YFUNCTION, 39755Speter "goto", YGOTO, 40755Speter "if", YIF, 41755Speter "in", YIN, 42755Speter "label", YLABEL, 43755Speter "mod", YMOD, 44755Speter "nil", YNIL, 45755Speter "not", YNOT, 46755Speter "of", YOF, 47755Speter "or", YOR, 48755Speter "packed", YPACKED, 49755Speter "procedure", YPROCEDURE, 50755Speter "program", YPROG, 51755Speter "record", YRECORD, 52755Speter "repeat", YREPEAT, 53755Speter "set", YSET, 54755Speter "then", YTHEN, 55755Speter "to", YTO, 56755Speter "type", YTYPE, 57755Speter "until", YUNTIL, 58755Speter "var", YVAR, 59755Speter "while", YWHILE, 60755Speter "with", YWITH, 61755Speter "oct", YOCT, /* non-standard Pascal */ 62755Speter "hex", YHEX, /* non-standard Pascal */ 63755Speter "external", YEXTERN, /* non-standard Pascal */ 64755Speter 0 65755Speter }; 66755Speter 67755Speter char *lastkey = &yykey[sizeof yykey/sizeof yykey[0]]; 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; 90755Speter } 91755Speter 92755Speter /* 93755Speter * Hash looks up the s(ymbol) argument 94755Speter * in the string table, entering it if 95755Speter * it is not found. If save is 0, then 96755Speter * the argument string is already in 97755Speter * a safe place. Otherwise, if hash is 98755Speter * entering the symbol for the first time 99755Speter * it will save the symbol in the string 100755Speter * table using savestr. 101755Speter */ 102755Speter int *hash(s, save) 103755Speter char *s; 104755Speter int save; 105755Speter { 106755Speter register int *h; 107755Speter register i; 108755Speter register char *cp; 109755Speter int *sym; 110755Speter struct ht *htp; 111755Speter int sh; 112755Speter 113755Speter /* 114755Speter * The hash function is a modular hash of 115755Speter * the sum of the characters with the sum 116755Speter * doubled before each successive character 117755Speter * is added. 118755Speter */ 119755Speter cp = s; 120755Speter if (cp == NIL) 121755Speter cp = token; /* default symbol to be hashed */ 122755Speter i = 0; 123755Speter while (*cp) 124755Speter i = i*2 + *cp++; 125755Speter sh = (i&077777) % HASHINC; 126755Speter cp = s; 127755Speter if (cp == NIL) 128755Speter cp = token; 129755Speter /* 130755Speter * There are as many as MAXHASH active 131755Speter * hash tables at any given point in time. 132755Speter * The search starts with the first table 133755Speter * and continues through the active tables 134755Speter * as necessary. 135755Speter */ 136755Speter for (htp = htab; htp < &htab[MAXHASH]; htp++) { 137755Speter if (htp->ht_low == NIL) { 138755Speter cp = (char *) calloc(sizeof ( int * ), HASHINC); 139*1833Speter if (cp == 0) { 140755Speter yerror("Ran out of memory (hash)"); 141755Speter pexit(DIED); 142755Speter } 143755Speter htp->ht_low = cp; 144755Speter htp->ht_high = htp->ht_low + HASHINC; 145755Speter cp = s; 146755Speter if (cp == NIL) 147755Speter cp = token; 148755Speter } 149755Speter h = htp->ht_low + sh; 150755Speter /* 151755Speter * quadratic rehash increment 152755Speter * starts at 1 and incremented 153755Speter * by two each rehash. 154755Speter */ 155755Speter i = 1; 156755Speter do { 157755Speter if (*h == 0) { 158755Speter if (htp->ht_used > (HASHINC * 3)/4) 159755Speter break; 160755Speter htp->ht_used++; 161755Speter if (save != 0) { 162755Speter *h = (int) savestr(cp); 163755Speter } else 164755Speter *h = s; 165755Speter return (h); 166755Speter } 167755Speter sym = *h; 168755Speter if (sym < lastkey && sym >= yykey) 169755Speter sym = *sym; 170755Speter if (sym->pchar == *cp && strcmp(sym, cp) == 0) 171755Speter return (h); 172755Speter h += i; 173755Speter i += 2; 174755Speter if (h >= htp->ht_high) 175755Speter h -= HASHINC; 176755Speter } while (i < HASHINC); 177755Speter } 178755Speter yerror("Ran out of hash tables"); 179755Speter pexit(DIED); 180755Speter } 181