148116Sbostic /*-
2*62213Sbostic * Copyright (c) 1980, 1993
3*62213Sbostic * The Regents of the University of California. All rights reserved.
448116Sbostic *
548116Sbostic * %sccs.include.redist.c%
622170Sdist */
7755Speter
814733Sthien #ifndef lint
9*62213Sbostic static char sccsid[] = "@(#)hash.c 8.1 (Berkeley) 06/06/93";
1048116Sbostic #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
inithash()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 */
hash(s,save)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