15534Slinton /* Copyright (c) 1982 Regents of the University of California */
25534Slinton 
3*6870Slinton static char sccsid[] = "@(#)symtab.c 1.2 05/19/82";
45534Slinton 
55534Slinton /*
6*6870Slinton  * Symbol table implementation.
75534Slinton  */
85534Slinton 
95534Slinton #include "defs.h"
105534Slinton #include "symtab.h"
115534Slinton #include "sym.h"
125534Slinton #include "sym/classes.h"
135534Slinton #include "sym/sym.rep"
145534Slinton 
155534Slinton /*
16*6870Slinton  * The symbol table structure is currently assumes no deletions.
175534Slinton  */
185534Slinton 
19*6870Slinton #define MAXHASHSIZE 1009    /* largest allowable hash table */
205534Slinton 
215534Slinton struct symtab {
22*6870Slinton     int size;
23*6870Slinton     int hshsize;
24*6870Slinton     SYM **symhsh;
25*6870Slinton     SYM *symarray;
26*6870Slinton     int symindex;
275534Slinton };
285534Slinton 
295534Slinton /*
30*6870Slinton  * Macro to hash a string.
315534Slinton  *
325534Slinton  * The hash value is returned through the "h" parameter which should
335534Slinton  * an unsigned integer.  The other parameters are the symbol table, "st",
345534Slinton  * and a pointer to the string to be hashed, "name".
355534Slinton  */
365534Slinton 
375534Slinton #define hash(h, st, name) \
385534Slinton { \
39*6870Slinton     register char *cp; \
405534Slinton \
41*6870Slinton     h = 0; \
42*6870Slinton     for (cp = name; *cp != '\0'; cp++) { \
43*6870Slinton 	h = (h << 1) | (*cp); \
44*6870Slinton     } \
45*6870Slinton     h %= st->hshsize; \
465534Slinton }
475534Slinton 
485534Slinton /*
495534Slinton  * To create a symbol table, we allocate space for the symbols and
505534Slinton  * for a hash table that's twice as big (+1 to make it odd).
515534Slinton  */
525534Slinton 
535534Slinton SYMTAB *st_creat(size)
545534Slinton int size;
555534Slinton {
56*6870Slinton     register SYMTAB *st;
57*6870Slinton     register int i;
585534Slinton 
59*6870Slinton     st = alloc(1, SYMTAB);
60*6870Slinton     st->size = size;
61*6870Slinton     st->hshsize = 2*size + 1;
62*6870Slinton     if (st->hshsize > MAXHASHSIZE) {
63*6870Slinton 	st->hshsize = MAXHASHSIZE;
64*6870Slinton     }
65*6870Slinton     st->symhsh = alloc(st->hshsize, SYM *);
66*6870Slinton     st->symarray = alloc(st->size, SYM);
67*6870Slinton     st->symindex = 0;
68*6870Slinton     for (i = 0; i < st->hshsize; i++) {
69*6870Slinton 	st->symhsh[i] = NIL;
70*6870Slinton     }
71*6870Slinton     return(st);
725534Slinton }
735534Slinton 
745534Slinton st_destroy(st)
755534Slinton SYMTAB *st;
765534Slinton {
77*6870Slinton     dispose(st->symhsh);
78*6870Slinton     dispose(st->symarray);
79*6870Slinton     dispose(st);
805534Slinton }
815534Slinton 
825534Slinton /*
835534Slinton  * insert a symbol into a table
845534Slinton  */
855534Slinton 
865534Slinton SYM *st_insert(st, name)
875534Slinton register SYMTAB *st;
885534Slinton char *name;
895534Slinton {
90*6870Slinton     register SYM *s;
91*6870Slinton     register unsigned int h;
92*6870Slinton     static SYM zerosym;
935534Slinton 
94*6870Slinton     if (st == NIL) {
95*6870Slinton 	panic("tried to insert into NIL table");
96*6870Slinton     }
97*6870Slinton     if (st->symindex >= st->size) {
98*6870Slinton 	panic("too many symbols");
99*6870Slinton     }
100*6870Slinton     hash(h, st, name);
101*6870Slinton     s = &(st->symarray[st->symindex++]);
102*6870Slinton     *s = zerosym;
103*6870Slinton     s->symbol = name;
104*6870Slinton     s->next_sym = st->symhsh[h];
105*6870Slinton     st->symhsh[h] = s;
106*6870Slinton     return(s);
1075534Slinton }
1085534Slinton 
1095534Slinton /*
1105534Slinton  * symbol lookup
1115534Slinton  */
1125534Slinton 
1135534Slinton SYM *st_lookup(st, name)
1145534Slinton SYMTAB *st;
1155534Slinton char *name;
1165534Slinton {
117*6870Slinton     register SYM *s;
118*6870Slinton     register unsigned int h;
1195534Slinton 
120*6870Slinton     if (st == NIL) {
121*6870Slinton 	panic("tried to lookup in NIL table");
122*6870Slinton     }
123*6870Slinton     hash(h, st, name);
124*6870Slinton     for (s = st->symhsh[h]; s != NIL; s = s->next_sym) {
125*6870Slinton 	if (strcmp(s->symbol, name) == 0) {
126*6870Slinton 	    break;
1275534Slinton 	}
128*6870Slinton     }
129*6870Slinton     return(s);
1305534Slinton }
1315534Slinton 
1325534Slinton /*
1335534Slinton  * Dump out all the variables associated with the given
1345534Slinton  * procedure, function, or program at the given recursive level.
1355534Slinton  *
1365534Slinton  * This is quite inefficient.  We traverse the entire symbol table
1375534Slinton  * each time we're called.  The assumption is that this routine
1385534Slinton  * won't be called frequently enough to merit improved performance.
1395534Slinton  */
1405534Slinton 
1415534Slinton dumpvars(f, frame)
1425534Slinton SYM *f;
1435534Slinton FRAME *frame;
1445534Slinton {
145*6870Slinton     register SYM *s;
146*6870Slinton     SYM *first, *last;
1475534Slinton 
148*6870Slinton     first = symtab->symarray;
149*6870Slinton     last = first + symtab->symindex - 1;
150*6870Slinton     for (s = first; s <= last; s++) {
151*6870Slinton 	if (should_print(s, f)) {
152*6870Slinton 	    printv(s, frame);
153*6870Slinton 	    putchar('\n');
1545534Slinton 	}
155*6870Slinton     }
1565534Slinton }
1575534Slinton 
1585534Slinton /*
1595534Slinton  * Create an alias for a command.
1605534Slinton  *
1615534Slinton  * We put it into the given table with block 1, which is how it
1625534Slinton  * is distinguished for printing purposes.
1635534Slinton  */
1645534Slinton 
1655534Slinton enter_alias(table, new, old)
1665534Slinton SYMTAB *table;
1675534Slinton char *new, *old;
1685534Slinton {
169*6870Slinton     SYM *s, *t;
1705534Slinton 
171*6870Slinton     if ((s = st_lookup(table, old)) == NIL) {
172*6870Slinton 	error("%s is not a known command", old);
173*6870Slinton     }
174*6870Slinton     if (st_lookup(table, new) != NIL) {
175*6870Slinton 	error("cannot alias command names");
176*6870Slinton     }
177*6870Slinton     make_keyword(table, new, s->symvalue.token.toknum);
178*6870Slinton     t = st_insert(table, new);
179*6870Slinton     t->blkno = 1;
180*6870Slinton     t->symvalue.token.toknum = s->symvalue.token.toknum;
181*6870Slinton     t->type = s;
1825534Slinton }
1835534Slinton 
1845534Slinton /*
1855534Slinton  * Print out the currently active aliases.
1865534Slinton  * The kludge is that the type pointer for an alias points to the
1875534Slinton  * symbol it is aliased to.
1885534Slinton  */
1895534Slinton 
1905534Slinton print_alias(table, name)
1915534Slinton SYMTAB *table;
1925534Slinton char *name;
1935534Slinton {
194*6870Slinton     SYM *s, *t;
195*6870Slinton     SYM *first, *last;
1965534Slinton 
197*6870Slinton     if (name != NIL) {
198*6870Slinton 	s = st_lookup(table, name);
199*6870Slinton 	if (s == NIL) {
200*6870Slinton 	    error("\"%s\" is not an alias", name);
2015534Slinton 	}
202*6870Slinton 	printf("%s\n", s->type->symbol);
203*6870Slinton     } else {
204*6870Slinton 	first = table->symarray;
205*6870Slinton 	last = first + table->symindex - 1;
206*6870Slinton 	for (s = first; s <= last; s++) {
207*6870Slinton 	    if (s->blkno == 1) {
208*6870Slinton 		printf("%s\t%s\n", s->symbol, s->type->symbol);
209*6870Slinton 	    }
210*6870Slinton 	}
211*6870Slinton     }
2125534Slinton }
2135534Slinton 
2145534Slinton /*
2155534Slinton  * Find a named type that points to t; return NIL if there is none.
2165534Slinton  * This is necessary because of the way pi keeps symbols.
2175534Slinton  */
2185534Slinton 
219*6870Slinton #define NSYMS_BACK 20       /* size of local context to try */
2205534Slinton 
2215534Slinton LOCAL SYM *search();
2225534Slinton 
2235534Slinton SYM *findtype(t)
2245534Slinton SYM *t;
2255534Slinton {
226*6870Slinton     SYM *s;
227*6870Slinton     SYM *first, *last;
228*6870Slinton     SYM *lower;
2295534Slinton 
230*6870Slinton     first = symtab->symarray;
231*6870Slinton     last = first + symtab->symindex - 1;
232*6870Slinton     if ((lower = t - NSYMS_BACK) < first) {
233*6870Slinton 	lower = first;
234*6870Slinton     }
235*6870Slinton     if ((s = search(t, lower, last)) == NIL) {
236*6870Slinton 	s = search(t, first, last);
237*6870Slinton     }
238*6870Slinton     return(s);
2395534Slinton }
2405534Slinton 
2415534Slinton /*
2425534Slinton  * Search the symbol table from first to last, looking for a
2435534Slinton  * named type pointing to the given type symbol.
2445534Slinton  */
2455534Slinton 
2465534Slinton LOCAL SYM *search(t, first, last)
2475534Slinton SYM *t;
2485534Slinton register SYM *first, *last;
2495534Slinton {
250*6870Slinton     register SYM *s;
2515534Slinton 
252*6870Slinton     for (s = first; s <= last; s++) {
253*6870Slinton 	if (s->class == TYPE && s->type == t && s->symbol != NIL) {
254*6870Slinton 	    return(s);
2555534Slinton 	}
256*6870Slinton     }
257*6870Slinton     return(NIL);
2585534Slinton }
259