xref: /csrg-svn/usr.bin/pascal/src/hash.c (revision 7955)
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