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