148092Sbostic /*-
2*62151Sbostic  * Copyright (c) 1980, 1993
3*62151Sbostic  *	The Regents of the University of California.  All rights reserved.
448092Sbostic  *
548092Sbostic  * %sccs.include.redist.c%
622566Sdist  */
75534Slinton 
822566Sdist #ifndef lint
9*62151Sbostic static char sccsid[] = "@(#)symtab.c	8.1 (Berkeley) 06/06/93";
1048092Sbostic #endif /* not lint */
115534Slinton 
125534Slinton /*
136870Slinton  * Symbol table implementation.
145534Slinton  */
155534Slinton 
165534Slinton #include "defs.h"
175534Slinton #include "symtab.h"
185534Slinton #include "sym.h"
195534Slinton #include "sym/classes.h"
205534Slinton #include "sym/sym.rep"
215534Slinton 
225534Slinton /*
236870Slinton  * The symbol table structure is currently assumes no deletions.
245534Slinton  */
255534Slinton 
266870Slinton #define MAXHASHSIZE 1009    /* largest allowable hash table */
275534Slinton 
285534Slinton struct symtab {
296870Slinton     int size;
306870Slinton     int hshsize;
316870Slinton     SYM **symhsh;
326870Slinton     SYM *symarray;
336870Slinton     int symindex;
345534Slinton };
355534Slinton 
365534Slinton /*
376870Slinton  * Macro to hash a string.
385534Slinton  *
395534Slinton  * The hash value is returned through the "h" parameter which should
405534Slinton  * an unsigned integer.  The other parameters are the symbol table, "st",
415534Slinton  * and a pointer to the string to be hashed, "name".
425534Slinton  */
435534Slinton 
445534Slinton #define hash(h, st, name) \
455534Slinton { \
466870Slinton     register char *cp; \
475534Slinton \
486870Slinton     h = 0; \
496870Slinton     for (cp = name; *cp != '\0'; cp++) { \
506870Slinton 	h = (h << 1) | (*cp); \
516870Slinton     } \
526870Slinton     h %= st->hshsize; \
535534Slinton }
545534Slinton 
555534Slinton /*
565534Slinton  * To create a symbol table, we allocate space for the symbols and
575534Slinton  * for a hash table that's twice as big (+1 to make it odd).
585534Slinton  */
595534Slinton 
st_creat(size)605534Slinton SYMTAB *st_creat(size)
615534Slinton int size;
625534Slinton {
636870Slinton     register SYMTAB *st;
646870Slinton     register int i;
655534Slinton 
666870Slinton     st = alloc(1, SYMTAB);
676870Slinton     st->size = size;
686870Slinton     st->hshsize = 2*size + 1;
696870Slinton     if (st->hshsize > MAXHASHSIZE) {
706870Slinton 	st->hshsize = MAXHASHSIZE;
716870Slinton     }
726870Slinton     st->symhsh = alloc(st->hshsize, SYM *);
736870Slinton     st->symarray = alloc(st->size, SYM);
746870Slinton     st->symindex = 0;
756870Slinton     for (i = 0; i < st->hshsize; i++) {
766870Slinton 	st->symhsh[i] = NIL;
776870Slinton     }
786870Slinton     return(st);
795534Slinton }
805534Slinton 
st_destroy(st)815534Slinton st_destroy(st)
825534Slinton SYMTAB *st;
835534Slinton {
846870Slinton     dispose(st->symhsh);
856870Slinton     dispose(st->symarray);
866870Slinton     dispose(st);
875534Slinton }
885534Slinton 
895534Slinton /*
905534Slinton  * insert a symbol into a table
915534Slinton  */
925534Slinton 
st_insert(st,name)935534Slinton SYM *st_insert(st, name)
945534Slinton register SYMTAB *st;
955534Slinton char *name;
965534Slinton {
976870Slinton     register SYM *s;
986870Slinton     register unsigned int h;
996870Slinton     static SYM zerosym;
1005534Slinton 
1016870Slinton     if (st == NIL) {
1026870Slinton 	panic("tried to insert into NIL table");
1036870Slinton     }
1046870Slinton     if (st->symindex >= st->size) {
1056870Slinton 	panic("too many symbols");
1066870Slinton     }
1076870Slinton     hash(h, st, name);
1086870Slinton     s = &(st->symarray[st->symindex++]);
1096870Slinton     *s = zerosym;
1106870Slinton     s->symbol = name;
1116870Slinton     s->next_sym = st->symhsh[h];
1126870Slinton     st->symhsh[h] = s;
1136870Slinton     return(s);
1145534Slinton }
1155534Slinton 
1165534Slinton /*
1175534Slinton  * symbol lookup
1185534Slinton  */
1195534Slinton 
st_lookup(st,name)1205534Slinton SYM *st_lookup(st, name)
1215534Slinton SYMTAB *st;
1225534Slinton char *name;
1235534Slinton {
1246870Slinton     register SYM *s;
1256870Slinton     register unsigned int h;
1265534Slinton 
1276870Slinton     if (st == NIL) {
1286870Slinton 	panic("tried to lookup in NIL table");
1296870Slinton     }
1306870Slinton     hash(h, st, name);
1316870Slinton     for (s = st->symhsh[h]; s != NIL; s = s->next_sym) {
1326870Slinton 	if (strcmp(s->symbol, name) == 0) {
1336870Slinton 	    break;
1345534Slinton 	}
1356870Slinton     }
1366870Slinton     return(s);
1375534Slinton }
1385534Slinton 
1395534Slinton /*
1405534Slinton  * Dump out all the variables associated with the given
1415534Slinton  * procedure, function, or program at the given recursive level.
1425534Slinton  *
1435534Slinton  * This is quite inefficient.  We traverse the entire symbol table
1445534Slinton  * each time we're called.  The assumption is that this routine
1455534Slinton  * won't be called frequently enough to merit improved performance.
1465534Slinton  */
1475534Slinton 
dumpvars(f,frame)1485534Slinton dumpvars(f, frame)
1495534Slinton SYM *f;
1505534Slinton FRAME *frame;
1515534Slinton {
1526870Slinton     register SYM *s;
1536870Slinton     SYM *first, *last;
1545534Slinton 
1556870Slinton     first = symtab->symarray;
1566870Slinton     last = first + symtab->symindex - 1;
1576870Slinton     for (s = first; s <= last; s++) {
1586870Slinton 	if (should_print(s, f)) {
1596870Slinton 	    printv(s, frame);
1606870Slinton 	    putchar('\n');
1615534Slinton 	}
1626870Slinton     }
1635534Slinton }
1645534Slinton 
1655534Slinton /*
1665534Slinton  * Create an alias for a command.
1675534Slinton  *
1685534Slinton  * We put it into the given table with block 1, which is how it
1695534Slinton  * is distinguished for printing purposes.
1705534Slinton  */
1715534Slinton 
enter_alias(table,new,old)1725534Slinton enter_alias(table, new, old)
1735534Slinton SYMTAB *table;
1745534Slinton char *new, *old;
1755534Slinton {
1766870Slinton     SYM *s, *t;
1775534Slinton 
1786870Slinton     if ((s = st_lookup(table, old)) == NIL) {
1796870Slinton 	error("%s is not a known command", old);
1806870Slinton     }
1816870Slinton     if (st_lookup(table, new) != NIL) {
1826870Slinton 	error("cannot alias command names");
1836870Slinton     }
1846870Slinton     make_keyword(table, new, s->symvalue.token.toknum);
1856870Slinton     t = st_insert(table, new);
1866870Slinton     t->blkno = 1;
1876870Slinton     t->symvalue.token.toknum = s->symvalue.token.toknum;
1886870Slinton     t->type = s;
1895534Slinton }
1905534Slinton 
1915534Slinton /*
1925534Slinton  * Print out the currently active aliases.
1935534Slinton  * The kludge is that the type pointer for an alias points to the
1945534Slinton  * symbol it is aliased to.
1955534Slinton  */
1965534Slinton 
print_alias(table,name)1975534Slinton print_alias(table, name)
1985534Slinton SYMTAB *table;
1995534Slinton char *name;
2005534Slinton {
20130851Smckusick     SYM *s;
2026870Slinton     SYM *first, *last;
2035534Slinton 
2046870Slinton     if (name != NIL) {
2056870Slinton 	s = st_lookup(table, name);
2066870Slinton 	if (s == NIL) {
2076870Slinton 	    error("\"%s\" is not an alias", name);
2085534Slinton 	}
2096870Slinton 	printf("%s\n", s->type->symbol);
2106870Slinton     } else {
2116870Slinton 	first = table->symarray;
2126870Slinton 	last = first + table->symindex - 1;
2136870Slinton 	for (s = first; s <= last; s++) {
2146870Slinton 	    if (s->blkno == 1) {
2156870Slinton 		printf("%s\t%s\n", s->symbol, s->type->symbol);
2166870Slinton 	    }
2176870Slinton 	}
2186870Slinton     }
2195534Slinton }
2205534Slinton 
2215534Slinton /*
2225534Slinton  * Find a named type that points to t; return NIL if there is none.
2235534Slinton  * This is necessary because of the way pi keeps symbols.
2245534Slinton  */
2255534Slinton 
2266870Slinton #define NSYMS_BACK 20       /* size of local context to try */
2275534Slinton 
2285534Slinton LOCAL SYM *search();
2295534Slinton 
findtype(t)2305534Slinton SYM *findtype(t)
2315534Slinton SYM *t;
2325534Slinton {
2336870Slinton     SYM *s;
2346870Slinton     SYM *first, *last;
2356870Slinton     SYM *lower;
2365534Slinton 
2376870Slinton     first = symtab->symarray;
2386870Slinton     last = first + symtab->symindex - 1;
2396870Slinton     if ((lower = t - NSYMS_BACK) < first) {
2406870Slinton 	lower = first;
2416870Slinton     }
2426870Slinton     if ((s = search(t, lower, last)) == NIL) {
2436870Slinton 	s = search(t, first, last);
2446870Slinton     }
2456870Slinton     return(s);
2465534Slinton }
2475534Slinton 
2485534Slinton /*
2495534Slinton  * Search the symbol table from first to last, looking for a
2505534Slinton  * named type pointing to the given type symbol.
2515534Slinton  */
2525534Slinton 
search(t,first,last)2535534Slinton LOCAL SYM *search(t, first, last)
2545534Slinton SYM *t;
2555534Slinton register SYM *first, *last;
2565534Slinton {
2576870Slinton     register SYM *s;
2585534Slinton 
2596870Slinton     for (s = first; s <= last; s++) {
2606870Slinton 	if (s->class == TYPE && s->type == t && s->symbol != NIL) {
2616870Slinton 	    return(s);
2625534Slinton 	}
2636870Slinton     }
2646870Slinton     return(NIL);
2655534Slinton }
266