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