1*48116Sbostic /*- 2*48116Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48116Sbostic * All rights reserved. 4*48116Sbostic * 5*48116Sbostic * %sccs.include.redist.c% 622170Sdist */ 7755Speter 814733Sthien #ifndef lint 9*48116Sbostic static char sccsid[] = "@(#)hash.c 5.2 (Berkeley) 04/16/91"; 10*48116Sbostic #endif /* not lint */ 11755Speter 12755Speter #include "whoami.h" 13755Speter #include "0.h" 1414733Sthien #include "tree_ty.h" /* must be included for yy.h */ 15755Speter #include "yy.h" 16755Speter 17755Speter /* 18755Speter * The definition for the segmented hash tables. 19755Speter */ 20755Speter struct ht { 21755Speter int *ht_low; 22755Speter int *ht_high; 23755Speter int ht_used; 24755Speter } htab[MAXHASH]; 25755Speter 26755Speter /* 27755Speter * This is the array of keywords and their 28755Speter * token values, which are hashed into the table 29755Speter * by inithash. 30755Speter */ 31755Speter struct kwtab yykey[] = { 32755Speter "and", YAND, 33755Speter "array", YARRAY, 34755Speter "begin", YBEGIN, 35755Speter "case", YCASE, 36755Speter "const", YCONST, 37755Speter "div", YDIV, 38755Speter "do", YDO, 39755Speter "downto", YDOWNTO, 40755Speter "else", YELSE, 41755Speter "end", YEND, 42755Speter "file", YFILE, 43755Speter "for", YFOR, 44755Speter "forward", YFORWARD, 45755Speter "function", YFUNCTION, 46755Speter "goto", YGOTO, 47755Speter "if", YIF, 48755Speter "in", YIN, 49755Speter "label", YLABEL, 50755Speter "mod", YMOD, 51755Speter "nil", YNIL, 52755Speter "not", YNOT, 53755Speter "of", YOF, 54755Speter "or", YOR, 55755Speter "packed", YPACKED, 56755Speter "procedure", YPROCEDURE, 57755Speter "program", YPROG, 58755Speter "record", YRECORD, 59755Speter "repeat", YREPEAT, 60755Speter "set", YSET, 61755Speter "then", YTHEN, 62755Speter "to", YTO, 63755Speter "type", YTYPE, 64755Speter "until", YUNTIL, 65755Speter "var", YVAR, 66755Speter "while", YWHILE, 67755Speter "with", YWITH, 687955Smckusick 0, 0, /* the following keywords are non-standard */ 697955Smckusick "oct", YOCT, 707955Smckusick "hex", YHEX, 717955Smckusick "external", YEXTERN, 72755Speter 0 73755Speter }; 74755Speter 757955Smckusick char *lastkey; 76755Speter 77755Speter /* 78755Speter * Inithash initializes the hash table routines 79755Speter * by allocating the first hash table segment using 80755Speter * an already existing memory slot. 81755Speter */ 82755Speter #ifndef PI0 83755Speter inithash() 84755Speter #else 85755Speter inithash(hshtab) 86755Speter int *hshtab; 87755Speter #endif 88755Speter { 89755Speter register int *ip; 90755Speter #ifndef PI0 91755Speter static int hshtab[HASHINC]; 92755Speter #endif 93755Speter 94755Speter htab[0].ht_low = hshtab; 95755Speter htab[0].ht_high = &hshtab[HASHINC]; 9614733Sthien for (ip = ((int *)yykey); *ip; ip += 2) 9714733Sthien hash((char *) ip[0], 0)[0] = ((int) ip); 987955Smckusick /* 997955Smckusick * If we are not running in "standard-only" mode, 1007955Smckusick * we load the non-standard keywords. 1017955Smckusick */ 1027955Smckusick if (!opt('s')) 1037955Smckusick for (ip += 2; *ip; ip += 2) 10414733Sthien hash((char *) ip[0], 0)[0] = ((int) ip); 1057955Smckusick lastkey = (char *)ip; 106755Speter } 107755Speter 108755Speter /* 109755Speter * Hash looks up the s(ymbol) argument 110755Speter * in the string table, entering it if 111755Speter * it is not found. If save is 0, then 112755Speter * the argument string is already in 113755Speter * a safe place. Otherwise, if hash is 114755Speter * entering the symbol for the first time 115755Speter * it will save the symbol in the string 116755Speter * table using savestr. 117755Speter */ 118755Speter int *hash(s, save) 119755Speter char *s; 120755Speter int save; 121755Speter { 122755Speter register int *h; 123755Speter register i; 124755Speter register char *cp; 125755Speter int *sym; 12614733Sthien struct cstruct *temp; 127755Speter struct ht *htp; 128755Speter int sh; 129755Speter 130755Speter /* 131755Speter * The hash function is a modular hash of 132755Speter * the sum of the characters with the sum 133755Speter * doubled before each successive character 134755Speter * is added. 135755Speter */ 136755Speter cp = s; 137755Speter if (cp == NIL) 138755Speter cp = token; /* default symbol to be hashed */ 139755Speter i = 0; 140755Speter while (*cp) 141755Speter i = i*2 + *cp++; 142755Speter sh = (i&077777) % HASHINC; 143755Speter cp = s; 144755Speter if (cp == NIL) 145755Speter cp = token; 146755Speter /* 147755Speter * There are as many as MAXHASH active 148755Speter * hash tables at any given point in time. 149755Speter * The search starts with the first table 150755Speter * and continues through the active tables 151755Speter * as necessary. 152755Speter */ 153755Speter for (htp = htab; htp < &htab[MAXHASH]; htp++) { 154755Speter if (htp->ht_low == NIL) { 15514733Sthien cp = (char *) pcalloc(sizeof ( int * ), HASHINC); 1561833Speter if (cp == 0) { 157755Speter yerror("Ran out of memory (hash)"); 158755Speter pexit(DIED); 159755Speter } 16014733Sthien htp->ht_low = ((int *)cp); 161755Speter htp->ht_high = htp->ht_low + HASHINC; 162755Speter cp = s; 163755Speter if (cp == NIL) 164755Speter cp = token; 165755Speter } 166755Speter h = htp->ht_low + sh; 167755Speter /* 168755Speter * quadratic rehash increment 169755Speter * starts at 1 and incremented 170755Speter * by two each rehash. 171755Speter */ 172755Speter i = 1; 173755Speter do { 174755Speter if (*h == 0) { 175755Speter if (htp->ht_used > (HASHINC * 3)/4) 176755Speter break; 177755Speter htp->ht_used++; 178755Speter if (save != 0) { 179755Speter *h = (int) savestr(cp); 180755Speter } else 18114733Sthien *h = ((int) s); 182755Speter return (h); 183755Speter } 18414733Sthien sym = ((int *) *h); 18514733Sthien if (sym < ((int *) lastkey) && sym >= ((int *) yykey)) 18614733Sthien sym = ((int *) *sym); 18714733Sthien temp = ((struct cstruct *) sym); 18814733Sthien if (temp->pchar == *cp && pstrcmp((char *) sym, cp) == 0) 189755Speter return (h); 190755Speter h += i; 191755Speter i += 2; 192755Speter if (h >= htp->ht_high) 193755Speter h -= HASHINC; 194755Speter } while (i < HASHINC); 195755Speter } 196755Speter yerror("Ran out of hash tables"); 197755Speter pexit(DIED); 19814733Sthien return (NIL); 19914733Sthien 200755Speter } 201