1*5534Slinton /* Copyright (c) 1982 Regents of the University of California */
2*5534Slinton 
3*5534Slinton static char sccsid[] = "@(#)symtab.c 1.1 01/18/82";
4*5534Slinton 
5*5534Slinton /*
6*5534Slinton  * symbol table implementation
7*5534Slinton  */
8*5534Slinton 
9*5534Slinton #include "defs.h"
10*5534Slinton #include "symtab.h"
11*5534Slinton #include "sym.h"
12*5534Slinton #include "sym/classes.h"
13*5534Slinton #include "sym/sym.rep"
14*5534Slinton 
15*5534Slinton /*
16*5534Slinton  * symbol table structure definition, no deletions allowed.
17*5534Slinton  */
18*5534Slinton 
19*5534Slinton #define MAXHASHSIZE 1009	/* largest allowable hash table */
20*5534Slinton 
21*5534Slinton struct symtab {
22*5534Slinton 	int size;
23*5534Slinton 	int hshsize;
24*5534Slinton 	SYM **symhsh;
25*5534Slinton 	SYM *symarray;
26*5534Slinton 	int symindex;
27*5534Slinton };
28*5534Slinton 
29*5534Slinton /*
30*5534Slinton  * symbol table hash macro
31*5534Slinton  *
32*5534Slinton  * The hash value is returned through the "h" parameter which should
33*5534Slinton  * an unsigned integer.  The other parameters are the symbol table, "st",
34*5534Slinton  * and a pointer to the string to be hashed, "name".
35*5534Slinton  */
36*5534Slinton 
37*5534Slinton #define hash(h, st, name) \
38*5534Slinton { \
39*5534Slinton 	register char *cp; \
40*5534Slinton \
41*5534Slinton 	h = 0; \
42*5534Slinton 	for (cp = name; *cp != '\0'; cp++) { \
43*5534Slinton 		h = (h << 1) | (*cp); \
44*5534Slinton 	} \
45*5534Slinton 	h %= st->hshsize; \
46*5534Slinton }
47*5534Slinton 
48*5534Slinton /*
49*5534Slinton  * To create a symbol table, we allocate space for the symbols and
50*5534Slinton  * for a hash table that's twice as big (+1 to make it odd).
51*5534Slinton  */
52*5534Slinton 
53*5534Slinton SYMTAB *st_creat(size)
54*5534Slinton int size;
55*5534Slinton {
56*5534Slinton 	register SYMTAB *st;
57*5534Slinton 	register int i;
58*5534Slinton 
59*5534Slinton 	st = alloc(1, SYMTAB);
60*5534Slinton 	st->size = size;
61*5534Slinton 	st->hshsize = 2*size + 1;
62*5534Slinton 	if (st->hshsize > MAXHASHSIZE) {
63*5534Slinton 		st->hshsize = MAXHASHSIZE;
64*5534Slinton 	}
65*5534Slinton 	st->symhsh = alloc(st->hshsize, SYM *);
66*5534Slinton 	st->symarray = alloc(st->size, SYM);
67*5534Slinton 	st->symindex = 0;
68*5534Slinton 	for (i = 0; i < st->hshsize; i++) {
69*5534Slinton 		st->symhsh[i] = NIL;
70*5534Slinton 	}
71*5534Slinton 	return(st);
72*5534Slinton }
73*5534Slinton 
74*5534Slinton st_destroy(st)
75*5534Slinton SYMTAB *st;
76*5534Slinton {
77*5534Slinton 	dispose(st->symhsh);
78*5534Slinton 	dispose(st->symarray);
79*5534Slinton 	dispose(st);
80*5534Slinton }
81*5534Slinton 
82*5534Slinton /*
83*5534Slinton  * insert a symbol into a table
84*5534Slinton  */
85*5534Slinton 
86*5534Slinton SYM *st_insert(st, name)
87*5534Slinton register SYMTAB *st;
88*5534Slinton char *name;
89*5534Slinton {
90*5534Slinton 	register SYM *s;
91*5534Slinton 	register unsigned int h;
92*5534Slinton 	static SYM zerosym;
93*5534Slinton 
94*5534Slinton 	if (st == NIL) {
95*5534Slinton 		panic("tried to insert into NIL table");
96*5534Slinton 	}
97*5534Slinton 	if (st->symindex >= st->size) {
98*5534Slinton 		panic("too many symbols");
99*5534Slinton 	}
100*5534Slinton 	hash(h, st, name);
101*5534Slinton 	s = &(st->symarray[st->symindex++]);
102*5534Slinton 	*s = zerosym;
103*5534Slinton 	s->symbol = name;
104*5534Slinton 	s->next_sym = st->symhsh[h];
105*5534Slinton 	st->symhsh[h] = s;
106*5534Slinton 	return(s);
107*5534Slinton }
108*5534Slinton 
109*5534Slinton /*
110*5534Slinton  * symbol lookup
111*5534Slinton  */
112*5534Slinton 
113*5534Slinton SYM *st_lookup(st, name)
114*5534Slinton SYMTAB *st;
115*5534Slinton char *name;
116*5534Slinton {
117*5534Slinton 	register SYM *s;
118*5534Slinton 	register unsigned int h;
119*5534Slinton 
120*5534Slinton 	if (st == NIL) {
121*5534Slinton 		panic("tried to lookup in NIL table");
122*5534Slinton 	}
123*5534Slinton 	hash(h, st, name);
124*5534Slinton 	for (s = st->symhsh[h]; s != NIL; s = s->next_sym) {
125*5534Slinton 		if (strcmp(s->symbol, name) == 0) {
126*5534Slinton 			break;
127*5534Slinton 		}
128*5534Slinton 	}
129*5534Slinton 	return(s);
130*5534Slinton }
131*5534Slinton 
132*5534Slinton /*
133*5534Slinton  * Dump out all the variables associated with the given
134*5534Slinton  * procedure, function, or program at the given recursive level.
135*5534Slinton  *
136*5534Slinton  * This is quite inefficient.  We traverse the entire symbol table
137*5534Slinton  * each time we're called.  The assumption is that this routine
138*5534Slinton  * won't be called frequently enough to merit improved performance.
139*5534Slinton  */
140*5534Slinton 
141*5534Slinton dumpvars(f, frame)
142*5534Slinton SYM *f;
143*5534Slinton FRAME *frame;
144*5534Slinton {
145*5534Slinton 	register SYM *s;
146*5534Slinton 	SYM *first, *last;
147*5534Slinton 
148*5534Slinton 	first = symtab->symarray;
149*5534Slinton 	last = first + symtab->symindex - 1;
150*5534Slinton 	for (s = first; s <= last; s++) {
151*5534Slinton 		if (should_print(s, f)) {
152*5534Slinton 			printv(s, frame);
153*5534Slinton 			putchar('\n');
154*5534Slinton 		}
155*5534Slinton 	}
156*5534Slinton }
157*5534Slinton 
158*5534Slinton /*
159*5534Slinton  * Create an alias for a command.
160*5534Slinton  *
161*5534Slinton  * We put it into the given table with block 1, which is how it
162*5534Slinton  * is distinguished for printing purposes.
163*5534Slinton  */
164*5534Slinton 
165*5534Slinton enter_alias(table, new, old)
166*5534Slinton SYMTAB *table;
167*5534Slinton char *new, *old;
168*5534Slinton {
169*5534Slinton 	SYM *s, *t;
170*5534Slinton 
171*5534Slinton 	if ((s = st_lookup(table, old)) == NIL) {
172*5534Slinton 		error("%s is not a known command", old);
173*5534Slinton 	}
174*5534Slinton 	if (st_lookup(table, new) != NIL) {
175*5534Slinton 		error("cannot alias command names");
176*5534Slinton 	}
177*5534Slinton 	make_keyword(table, new, s->symvalue.token.toknum);
178*5534Slinton 	t = st_insert(table, new);
179*5534Slinton 	t->blkno = 1;
180*5534Slinton 	t->symvalue.token.toknum = s->symvalue.token.toknum;
181*5534Slinton 	t->type = s;
182*5534Slinton }
183*5534Slinton 
184*5534Slinton /*
185*5534Slinton  * Print out the currently active aliases.
186*5534Slinton  * The kludge is that the type pointer for an alias points to the
187*5534Slinton  * symbol it is aliased to.
188*5534Slinton  */
189*5534Slinton 
190*5534Slinton print_alias(table, name)
191*5534Slinton SYMTAB *table;
192*5534Slinton char *name;
193*5534Slinton {
194*5534Slinton 	SYM *s, *t;
195*5534Slinton 	SYM *first, *last;
196*5534Slinton 
197*5534Slinton 	if (name != NIL) {
198*5534Slinton 		s = st_lookup(table, name);
199*5534Slinton 		if (s == NIL) {
200*5534Slinton 			error("\"%s\" is not an alias", name);
201*5534Slinton 		}
202*5534Slinton 		printf("%s\n", s->type->symbol);
203*5534Slinton 	} else {
204*5534Slinton 		first = table->symarray;
205*5534Slinton 		last = first + table->symindex - 1;
206*5534Slinton 		for (s = first; s <= last; s++) {
207*5534Slinton 			if (s->blkno == 1) {
208*5534Slinton 				printf("%s\t%s\n", s->symbol, s->type->symbol);
209*5534Slinton 			}
210*5534Slinton 		}
211*5534Slinton 	}
212*5534Slinton }
213*5534Slinton 
214*5534Slinton /*
215*5534Slinton  * Find a named type that points to t; return NIL if there is none.
216*5534Slinton  * This is necessary because of the way pi keeps symbols.
217*5534Slinton  */
218*5534Slinton 
219*5534Slinton #define NSYMS_BACK 20		/* size of local context to try */
220*5534Slinton 
221*5534Slinton LOCAL SYM *search();
222*5534Slinton 
223*5534Slinton SYM *findtype(t)
224*5534Slinton SYM *t;
225*5534Slinton {
226*5534Slinton 	SYM *s;
227*5534Slinton 	SYM *first, *last;
228*5534Slinton 	SYM *lower;
229*5534Slinton 
230*5534Slinton 	first = symtab->symarray;
231*5534Slinton 	last = first + symtab->symindex - 1;
232*5534Slinton 	if ((lower = t - NSYMS_BACK) < first) {
233*5534Slinton 		lower = first;
234*5534Slinton 	}
235*5534Slinton 	if ((s = search(t, lower, last)) == NIL) {
236*5534Slinton 		s = search(t, first, last);
237*5534Slinton 	}
238*5534Slinton 	return(s);
239*5534Slinton }
240*5534Slinton 
241*5534Slinton /*
242*5534Slinton  * Search the symbol table from first to last, looking for a
243*5534Slinton  * named type pointing to the given type symbol.
244*5534Slinton  */
245*5534Slinton 
246*5534Slinton LOCAL SYM *search(t, first, last)
247*5534Slinton SYM *t;
248*5534Slinton register SYM *first, *last;
249*5534Slinton {
250*5534Slinton 	register SYM *s;
251*5534Slinton 
252*5534Slinton 	for (s = first; s <= last; s++) {
253*5534Slinton 		if (s->class == TYPE && s->type == t && s->symbol != NIL) {
254*5534Slinton 			return(s);
255*5534Slinton 		}
256*5534Slinton 	}
257*5534Slinton 	return(NIL);
258*5534Slinton }
259