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