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