1 /*
2 * Copyright (c) 1983 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)keywords.c 5.4 (Berkeley) 06/01/90";
10 #endif /* not lint */
11
12 /*
13 * Keywords, variables, and aliases (oh my!).
14 */
15
16 #include "defs.h"
17 #include "keywords.h"
18 #include "scanner.h"
19 #include "names.h"
20 #include "symbols.h"
21 #include "tree.h"
22 #include "lists.h"
23 #include "main.h"
24 #include "y.tab.h"
25
26 #ifndef public
27
28 #include "scanner.h"
29 #include "tree.h"
30
31 #endif
32
33 private String reserved[] ={
34 "alias", "and", "assign", "at", "call", "catch", "cont",
35 "debug", "delete", "div", "down", "dump", "edit", "file", "func",
36 "gripe", "help", "if", "ignore", "in",
37 "list", "mod", "next", "nexti", "nil", "not", "or",
38 "print", "psym", "quit", "rerun", "return", "run",
39 "set", "sh", "skip", "source", "status", "step", "stepi",
40 "stop", "stopi", "trace", "tracei", "unalias", "unset", "up", "use",
41 "whatis", "when", "where", "whereis", "which",
42 "INT", "CHAR", "REAL", "NAME", "STRING", "->"
43 };
44
45 /*
46 * The keyword table is a traditional hash table with collisions
47 * resolved by chaining.
48 */
49
50 #define HASHTABLESIZE 1007
51
52 typedef enum { ISKEYWORD, ISALIAS, ISVAR } KeywordType;
53
54 typedef struct Keyword {
55 Name name;
56 KeywordType class : 16;
57 union {
58 /* ISKEYWORD: */
59 Token toknum;
60
61 /* ISALIAS: */
62 struct {
63 List paramlist;
64 String expansion;
65 } alias;
66
67 /* ISVAR: */
68 Node var;
69 } value;
70 struct Keyword *chain;
71 } *Keyword;
72
73 typedef unsigned int Hashvalue;
74
75 private Keyword hashtab[HASHTABLESIZE];
76
77 #define hash(n) ((((unsigned) n) >> 2) mod HASHTABLESIZE)
78
79 /*
80 * Enter all the reserved words into the keyword table.
81 *
82 * If the vaddrs flag is set (through the -k command line option) then
83 * set the special "$mapaddrs" variable. This assumes that the
84 * command line arguments are scanned before this routine is called.
85 */
86
enterkeywords()87 public enterkeywords()
88 {
89 register integer i;
90
91 for (i = ALIAS; i <= WHICH; i++) {
92 keyword(reserved[ord(i) - ord(ALIAS)], i);
93 }
94 defalias("c", "cont");
95 defalias("d", "delete");
96 defalias("h", "help");
97 defalias("e", "edit");
98 defalias("l", "list");
99 defalias("n", "next");
100 defalias("p", "print");
101 defalias("q", "quit");
102 defalias("r", "run");
103 defalias("s", "step");
104 defalias("st", "stop");
105 defalias("j", "status");
106 defalias("t", "where");
107 if (vaddrs) {
108 defvar(identname("$mapaddrs", true), nil);
109 }
110 }
111
112 /*
113 * Deallocate the keyword table.
114 */
115
keywords_free()116 public keywords_free()
117 {
118 register Integer i;
119 register Keyword k, nextk;
120
121 for (i = 0; i < HASHTABLESIZE; i++) {
122 k = hashtab[i];
123 while (k != nil) {
124 nextk = k->chain;
125 dispose(k);
126 k = nextk;
127 }
128 hashtab[i] = nil;
129 }
130 }
131
132 /*
133 * Insert a name into the keyword table and return the keyword for it.
134 */
135
keywords_insert(n)136 private Keyword keywords_insert (n)
137 Name n;
138 {
139 Hashvalue h;
140 Keyword k;
141
142 h = hash(n);
143 k = new(Keyword);
144 k->name = n;
145 k->chain = hashtab[h];
146 hashtab[h] = k;
147 return k;
148 }
149
150 /*
151 * Find the keyword associated with the given name.
152 */
153
keywords_lookup(n)154 private Keyword keywords_lookup (n)
155 Name n;
156 {
157 Hashvalue h;
158 register Keyword k;
159
160 h = hash(n);
161 k = hashtab[h];
162 while (k != nil and k->name != n) {
163 k = k->chain;
164 }
165 return k;
166 }
167
168 /*
169 * Delete the given keyword of the given class.
170 */
171
keywords_delete(n,class)172 private boolean keywords_delete (n, class)
173 Name n;
174 KeywordType class;
175 {
176 Hashvalue h;
177 register Keyword k, prevk;
178 boolean b;
179
180 h = hash(n);
181 k = hashtab[h];
182 prevk = nil;
183 while (k != nil and (k->name != n or k->class != class)) {
184 prevk = k;
185 k = k->chain;
186 }
187 if (k != nil) {
188 b = true;
189 if (prevk == nil) {
190 hashtab[h] = k->chain;
191 } else {
192 prevk->chain = k->chain;
193 }
194 dispose(k);
195 } else {
196 b = false;
197 }
198 return b;
199 }
200
201 /*
202 * Enter a keyword into the table. It is assumed to not be there already.
203 * The string is assumed to be statically allocated.
204 */
205
keyword(s,t)206 private keyword (s, t)
207 String s;
208 Token t;
209 {
210 Keyword k;
211 Name n;
212
213 n = identname(s, true);
214 k = keywords_insert(n);
215 k->class = ISKEYWORD;
216 k->value.toknum = t;
217 }
218
219 /*
220 * Define a builtin command name alias.
221 */
222
defalias(s1,s2)223 private defalias (s1, s2)
224 String s1, s2;
225 {
226 alias(identname(s1, true), nil, s2);
227 }
228
229 /*
230 * Look for a word of a particular class.
231 */
232
findword(n,class)233 private Keyword findword (n, class)
234 Name n;
235 KeywordType class;
236 {
237 register Keyword k;
238
239 k = keywords_lookup(n);
240 while (k != nil and (k->name != n or k->class != class)) {
241 k = k->chain;
242 }
243 return k;
244 }
245
246 /*
247 * Return the token associated with a given keyword string.
248 * If there is none, return the given default value.
249 */
250
findkeyword(n,def)251 public Token findkeyword (n, def)
252 Name n;
253 Token def;
254 {
255 Keyword k;
256 Token t;
257
258 k = findword(n, ISKEYWORD);
259 if (k == nil) {
260 t = def;
261 } else {
262 t = k->value.toknum;
263 }
264 return t;
265 }
266
267 /*
268 * Return the associated string if there is an alias with the given name.
269 */
270
findalias(n,pl,str)271 public boolean findalias (n, pl, str)
272 Name n;
273 List *pl;
274 String *str;
275 {
276 Keyword k;
277 boolean b;
278
279 k = findword(n, ISALIAS);
280 if (k == nil) {
281 b = false;
282 } else {
283 *pl = k->value.alias.paramlist;
284 *str = k->value.alias.expansion;
285 b = true;
286 }
287 return b;
288 }
289
290 /*
291 * Return the string associated with a token corresponding to a keyword.
292 */
293
keywdstring(t)294 public String keywdstring (t)
295 Token t;
296 {
297 return reserved[ord(t) - ord(ALIAS)];
298 }
299
300 /*
301 * Process an alias command, either entering a new alias or printing out
302 * an existing one.
303 */
304
alias(newcmd,args,str)305 public alias (newcmd, args, str)
306 Name newcmd;
307 List args;
308 String str;
309 {
310 Keyword k;
311
312 if (str == nil) {
313 print_alias(newcmd);
314 } else {
315 k = findword(newcmd, ISALIAS);
316 if (k == nil) {
317 k = keywords_insert(newcmd);
318 }
319 k->class = ISALIAS;
320 k->value.alias.paramlist = args;
321 k->value.alias.expansion = str;
322 }
323 }
324
325 /*
326 * Print out an alias.
327 */
328
print_alias(cmd)329 private print_alias (cmd)
330 Name cmd;
331 {
332 register Keyword k;
333 register Integer i;
334 Name n;
335
336 if (cmd == nil) {
337 for (i = 0; i < HASHTABLESIZE; i++) {
338 for (k = hashtab[i]; k != nil; k = k->chain) {
339 if (k->class == ISALIAS) {
340 if (isredirected()) {
341 printf("alias %s", ident(k->name));
342 printparams(k->value.alias.paramlist);
343 printf("\t\"%s\"\n", k->value.alias.expansion);
344 } else {
345 printf("%s", ident(k->name));
346 printparams(k->value.alias.paramlist);
347 printf("\t%s\n", k->value.alias.expansion);
348 }
349 }
350 }
351 }
352 } else {
353 k = findword(cmd, ISALIAS);
354 if (k == nil) {
355 printf("\n");
356 } else {
357 printparams(k->value.alias.paramlist);
358 printf("%s\n", k->value.alias.expansion);
359 }
360 }
361 }
362
printparams(pl)363 private printparams (pl)
364 List pl;
365 {
366 Name n;
367
368 if (pl != nil) {
369 printf("(");
370 foreach(Name, n, pl)
371 printf("%s", ident(n));
372 if (not list_islast()) {
373 printf(", ");
374 }
375 endfor
376 printf(")");
377 }
378 }
379
380 /*
381 * Remove an alias.
382 */
383
unalias(n)384 public unalias (n)
385 Name n;
386 {
387 if (not keywords_delete(n, ISALIAS)) {
388 error("%s is not aliased", ident(n));
389 }
390 }
391
392 /*
393 * Define a variable.
394 */
395
defvar(n,val)396 public defvar (n, val)
397 Name n;
398 Node val;
399 {
400 Keyword k;
401
402 if (n == nil) {
403 print_vars();
404 } else {
405 if (lookup(n) != nil) {
406 error("\"%s\" is a program symbol -- use assign", ident(n));
407 }
408 k = findword(n, ISVAR);
409 if (k == nil) {
410 k = keywords_insert(n);
411 }
412 k->class = ISVAR;
413 k->value.var = val;
414 if (n == identname("$mapaddrs", true)) {
415 vaddrs = true;
416 }
417 }
418 }
419
420 /*
421 * Return the value associated with a variable.
422 */
423
findvar(n)424 public Node findvar (n)
425 Name n;
426 {
427 Keyword k;
428 Node val;
429
430 k = findword(n, ISVAR);
431 if (k == nil) {
432 val = nil;
433 } else {
434 val = k->value.var;
435 }
436 return val;
437 }
438
439 /*
440 * Return whether or not a variable is set.
441 */
442
varIsSet(s)443 public boolean varIsSet (s)
444 String s;
445 {
446 return (boolean) (findword(identname(s, false), ISVAR) != nil);
447 }
448
449 /*
450 * Delete a variable.
451 */
452
undefvar(n)453 public undefvar (n)
454 Name n;
455 {
456 if (not keywords_delete(n, ISVAR)) {
457 error("%s is not set", ident(n));
458 }
459 if (n == identname("$mapaddrs", true)) {
460 vaddrs = false;
461 }
462 }
463
464 /*
465 * Print out all the values of set variables.
466 */
467
print_vars()468 private print_vars ()
469 {
470 register integer i;
471 register Keyword k;
472
473 for (i = 0; i < HASHTABLESIZE; i++) {
474 for (k = hashtab[i]; k != nil; k = k->chain) {
475 if (k->class == ISVAR) {
476 if (isredirected()) {
477 printf("set ");
478 }
479 printf("%s", ident(k->name));
480 if (k->value.var != nil) {
481 printf("\t");
482 prtree(stdout, k->value.var);
483 }
484 printf("\n");
485 }
486 }
487 }
488 }
489