122566Sdist /*
222566Sdist  * Copyright (c) 1980 Regents of the University of California.
322566Sdist  * All rights reserved.  The Berkeley software License Agreement
422566Sdist  * specifies the terms and conditions for redistribution.
522566Sdist  */
65534Slinton 
722566Sdist #ifndef lint
8*30851Smckusick static char sccsid[] = "@(#)symtab.c	5.2 (Berkeley) 04/07/87";
922566Sdist #endif not lint
105534Slinton 
115534Slinton /*
126870Slinton  * Symbol table implementation.
135534Slinton  */
145534Slinton 
155534Slinton #include "defs.h"
165534Slinton #include "symtab.h"
175534Slinton #include "sym.h"
185534Slinton #include "sym/classes.h"
195534Slinton #include "sym/sym.rep"
205534Slinton 
215534Slinton /*
226870Slinton  * The symbol table structure is currently assumes no deletions.
235534Slinton  */
245534Slinton 
256870Slinton #define MAXHASHSIZE 1009    /* largest allowable hash table */
265534Slinton 
275534Slinton struct symtab {
286870Slinton     int size;
296870Slinton     int hshsize;
306870Slinton     SYM **symhsh;
316870Slinton     SYM *symarray;
326870Slinton     int symindex;
335534Slinton };
345534Slinton 
355534Slinton /*
366870Slinton  * Macro to hash a string.
375534Slinton  *
385534Slinton  * The hash value is returned through the "h" parameter which should
395534Slinton  * an unsigned integer.  The other parameters are the symbol table, "st",
405534Slinton  * and a pointer to the string to be hashed, "name".
415534Slinton  */
425534Slinton 
435534Slinton #define hash(h, st, name) \
445534Slinton { \
456870Slinton     register char *cp; \
465534Slinton \
476870Slinton     h = 0; \
486870Slinton     for (cp = name; *cp != '\0'; cp++) { \
496870Slinton 	h = (h << 1) | (*cp); \
506870Slinton     } \
516870Slinton     h %= st->hshsize; \
525534Slinton }
535534Slinton 
545534Slinton /*
555534Slinton  * To create a symbol table, we allocate space for the symbols and
565534Slinton  * for a hash table that's twice as big (+1 to make it odd).
575534Slinton  */
585534Slinton 
595534Slinton SYMTAB *st_creat(size)
605534Slinton int size;
615534Slinton {
626870Slinton     register SYMTAB *st;
636870Slinton     register int i;
645534Slinton 
656870Slinton     st = alloc(1, SYMTAB);
666870Slinton     st->size = size;
676870Slinton     st->hshsize = 2*size + 1;
686870Slinton     if (st->hshsize > MAXHASHSIZE) {
696870Slinton 	st->hshsize = MAXHASHSIZE;
706870Slinton     }
716870Slinton     st->symhsh = alloc(st->hshsize, SYM *);
726870Slinton     st->symarray = alloc(st->size, SYM);
736870Slinton     st->symindex = 0;
746870Slinton     for (i = 0; i < st->hshsize; i++) {
756870Slinton 	st->symhsh[i] = NIL;
766870Slinton     }
776870Slinton     return(st);
785534Slinton }
795534Slinton 
805534Slinton st_destroy(st)
815534Slinton SYMTAB *st;
825534Slinton {
836870Slinton     dispose(st->symhsh);
846870Slinton     dispose(st->symarray);
856870Slinton     dispose(st);
865534Slinton }
875534Slinton 
885534Slinton /*
895534Slinton  * insert a symbol into a table
905534Slinton  */
915534Slinton 
925534Slinton SYM *st_insert(st, name)
935534Slinton register SYMTAB *st;
945534Slinton char *name;
955534Slinton {
966870Slinton     register SYM *s;
976870Slinton     register unsigned int h;
986870Slinton     static SYM zerosym;
995534Slinton 
1006870Slinton     if (st == NIL) {
1016870Slinton 	panic("tried to insert into NIL table");
1026870Slinton     }
1036870Slinton     if (st->symindex >= st->size) {
1046870Slinton 	panic("too many symbols");
1056870Slinton     }
1066870Slinton     hash(h, st, name);
1076870Slinton     s = &(st->symarray[st->symindex++]);
1086870Slinton     *s = zerosym;
1096870Slinton     s->symbol = name;
1106870Slinton     s->next_sym = st->symhsh[h];
1116870Slinton     st->symhsh[h] = s;
1126870Slinton     return(s);
1135534Slinton }
1145534Slinton 
1155534Slinton /*
1165534Slinton  * symbol lookup
1175534Slinton  */
1185534Slinton 
1195534Slinton SYM *st_lookup(st, name)
1205534Slinton SYMTAB *st;
1215534Slinton char *name;
1225534Slinton {
1236870Slinton     register SYM *s;
1246870Slinton     register unsigned int h;
1255534Slinton 
1266870Slinton     if (st == NIL) {
1276870Slinton 	panic("tried to lookup in NIL table");
1286870Slinton     }
1296870Slinton     hash(h, st, name);
1306870Slinton     for (s = st->symhsh[h]; s != NIL; s = s->next_sym) {
1316870Slinton 	if (strcmp(s->symbol, name) == 0) {
1326870Slinton 	    break;
1335534Slinton 	}
1346870Slinton     }
1356870Slinton     return(s);
1365534Slinton }
1375534Slinton 
1385534Slinton /*
1395534Slinton  * Dump out all the variables associated with the given
1405534Slinton  * procedure, function, or program at the given recursive level.
1415534Slinton  *
1425534Slinton  * This is quite inefficient.  We traverse the entire symbol table
1435534Slinton  * each time we're called.  The assumption is that this routine
1445534Slinton  * won't be called frequently enough to merit improved performance.
1455534Slinton  */
1465534Slinton 
1475534Slinton dumpvars(f, frame)
1485534Slinton SYM *f;
1495534Slinton FRAME *frame;
1505534Slinton {
1516870Slinton     register SYM *s;
1526870Slinton     SYM *first, *last;
1535534Slinton 
1546870Slinton     first = symtab->symarray;
1556870Slinton     last = first + symtab->symindex - 1;
1566870Slinton     for (s = first; s <= last; s++) {
1576870Slinton 	if (should_print(s, f)) {
1586870Slinton 	    printv(s, frame);
1596870Slinton 	    putchar('\n');
1605534Slinton 	}
1616870Slinton     }
1625534Slinton }
1635534Slinton 
1645534Slinton /*
1655534Slinton  * Create an alias for a command.
1665534Slinton  *
1675534Slinton  * We put it into the given table with block 1, which is how it
1685534Slinton  * is distinguished for printing purposes.
1695534Slinton  */
1705534Slinton 
1715534Slinton enter_alias(table, new, old)
1725534Slinton SYMTAB *table;
1735534Slinton char *new, *old;
1745534Slinton {
1756870Slinton     SYM *s, *t;
1765534Slinton 
1776870Slinton     if ((s = st_lookup(table, old)) == NIL) {
1786870Slinton 	error("%s is not a known command", old);
1796870Slinton     }
1806870Slinton     if (st_lookup(table, new) != NIL) {
1816870Slinton 	error("cannot alias command names");
1826870Slinton     }
1836870Slinton     make_keyword(table, new, s->symvalue.token.toknum);
1846870Slinton     t = st_insert(table, new);
1856870Slinton     t->blkno = 1;
1866870Slinton     t->symvalue.token.toknum = s->symvalue.token.toknum;
1876870Slinton     t->type = s;
1885534Slinton }
1895534Slinton 
1905534Slinton /*
1915534Slinton  * Print out the currently active aliases.
1925534Slinton  * The kludge is that the type pointer for an alias points to the
1935534Slinton  * symbol it is aliased to.
1945534Slinton  */
1955534Slinton 
1965534Slinton print_alias(table, name)
1975534Slinton SYMTAB *table;
1985534Slinton char *name;
1995534Slinton {
200*30851Smckusick     SYM *s;
2016870Slinton     SYM *first, *last;
2025534Slinton 
2036870Slinton     if (name != NIL) {
2046870Slinton 	s = st_lookup(table, name);
2056870Slinton 	if (s == NIL) {
2066870Slinton 	    error("\"%s\" is not an alias", name);
2075534Slinton 	}
2086870Slinton 	printf("%s\n", s->type->symbol);
2096870Slinton     } else {
2106870Slinton 	first = table->symarray;
2116870Slinton 	last = first + table->symindex - 1;
2126870Slinton 	for (s = first; s <= last; s++) {
2136870Slinton 	    if (s->blkno == 1) {
2146870Slinton 		printf("%s\t%s\n", s->symbol, s->type->symbol);
2156870Slinton 	    }
2166870Slinton 	}
2176870Slinton     }
2185534Slinton }
2195534Slinton 
2205534Slinton /*
2215534Slinton  * Find a named type that points to t; return NIL if there is none.
2225534Slinton  * This is necessary because of the way pi keeps symbols.
2235534Slinton  */
2245534Slinton 
2256870Slinton #define NSYMS_BACK 20       /* size of local context to try */
2265534Slinton 
2275534Slinton LOCAL SYM *search();
2285534Slinton 
2295534Slinton SYM *findtype(t)
2305534Slinton SYM *t;
2315534Slinton {
2326870Slinton     SYM *s;
2336870Slinton     SYM *first, *last;
2346870Slinton     SYM *lower;
2355534Slinton 
2366870Slinton     first = symtab->symarray;
2376870Slinton     last = first + symtab->symindex - 1;
2386870Slinton     if ((lower = t - NSYMS_BACK) < first) {
2396870Slinton 	lower = first;
2406870Slinton     }
2416870Slinton     if ((s = search(t, lower, last)) == NIL) {
2426870Slinton 	s = search(t, first, last);
2436870Slinton     }
2446870Slinton     return(s);
2455534Slinton }
2465534Slinton 
2475534Slinton /*
2485534Slinton  * Search the symbol table from first to last, looking for a
2495534Slinton  * named type pointing to the given type symbol.
2505534Slinton  */
2515534Slinton 
2525534Slinton LOCAL SYM *search(t, first, last)
2535534Slinton SYM *t;
2545534Slinton register SYM *first, *last;
2555534Slinton {
2566870Slinton     register SYM *s;
2575534Slinton 
2586870Slinton     for (s = first; s <= last; s++) {
2596870Slinton 	if (s->class == TYPE && s->type == t && s->symbol != NIL) {
2606870Slinton 	    return(s);
2615534Slinton 	}
2626870Slinton     }
2636870Slinton     return(NIL);
2645534Slinton }
265