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