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