Commit | Line | Data |
---|---|---|
2a24676e DF |
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 | */ | |
9a3f3b7b | 6 | |
2a24676e | 7 | #ifndef lint |
8d7bc982 | 8 | static char sccsid[] = "@(#)keywords.c 5.2 (Berkeley) %G%"; |
2a24676e | 9 | #endif not lint |
0022c355 ML |
10 | |
11 | static char rcsid[] = "$Header: keywords.c,v 1.5 84/12/26 10:39:45 linton Exp $"; | |
9a3f3b7b ML |
12 | |
13 | /* | |
0022c355 | 14 | * Keywords, variables, and aliases (oh my!). |
9a3f3b7b ML |
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" | |
0022c355 ML |
23 | #include "lists.h" |
24 | #include "main.h" | |
9a3f3b7b ML |
25 | #include "y.tab.h" |
26 | ||
27 | #ifndef public | |
0022c355 | 28 | |
9a3f3b7b | 29 | #include "scanner.h" |
0022c355 ML |
30 | #include "tree.h" |
31 | ||
9a3f3b7b ML |
32 | #endif |
33 | ||
34 | private String reserved[] ={ | |
35 | "alias", "and", "assign", "at", "call", "catch", "cont", | |
2fd0f574 | 36 | "debug", "delete", "div", "down", "dump", "edit", "file", "func", |
9a3f3b7b ML |
37 | "gripe", "help", "if", "ignore", "in", |
38 | "list", "mod", "next", "nexti", "nil", "not", "or", | |
2fd0f574 | 39 | "print", "psym", "quit", "rerun", "return", "run", |
0022c355 ML |
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", "->" | |
9a3f3b7b ML |
44 | }; |
45 | ||
46 | /* | |
47 | * The keyword table is a traditional hash table with collisions | |
48 | * resolved by chaining. | |
49 | */ | |
0022c355 ML |
50 | |
51 | #define HASHTABLESIZE 1007 | |
52 | ||
53 | typedef enum { ISKEYWORD, ISALIAS, ISVAR } KeywordType; | |
54 | ||
9a3f3b7b ML |
55 | typedef struct Keyword { |
56 | Name name; | |
0022c355 ML |
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; | |
9a3f3b7b ML |
71 | struct Keyword *chain; |
72 | } *Keyword; | |
73 | ||
74 | typedef unsigned int Hashvalue; | |
75 | ||
0022c355 | 76 | private Keyword hashtab[HASHTABLESIZE]; |
f7adfe8e | 77 | |
0022c355 | 78 | #define hash(n) ((((unsigned) n) >> 2) mod HASHTABLESIZE) |
9a3f3b7b ML |
79 | |
80 | /* | |
81 | * Enter all the reserved words into the keyword table. | |
0022c355 ML |
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. | |
9a3f3b7b | 86 | */ |
0022c355 | 87 | |
9a3f3b7b ML |
88 | public enterkeywords() |
89 | { | |
0022c355 | 90 | register integer i; |
9a3f3b7b | 91 | |
0022c355 | 92 | for (i = ALIAS; i <= WHICH; i++) { |
f7adfe8e | 93 | keyword(reserved[ord(i) - ord(ALIAS)], i); |
0022c355 ML |
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 | } | |
9a3f3b7b ML |
111 | } |
112 | ||
113 | /* | |
0022c355 | 114 | * Deallocate the keyword table. |
9a3f3b7b | 115 | */ |
0022c355 | 116 | |
9a3f3b7b ML |
117 | public keywords_free() |
118 | { | |
119 | register Integer i; | |
120 | register Keyword k, nextk; | |
121 | ||
0022c355 ML |
122 | for (i = 0; i < HASHTABLESIZE; i++) { |
123 | k = hashtab[i]; | |
124 | while (k != nil) { | |
9a3f3b7b ML |
125 | nextk = k->chain; |
126 | dispose(k); | |
0022c355 | 127 | k = nextk; |
9a3f3b7b ML |
128 | } |
129 | hashtab[i] = nil; | |
130 | } | |
0022c355 ML |
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; | |
f7adfe8e | 194 | } |
0022c355 ML |
195 | dispose(k); |
196 | } else { | |
197 | b = false; | |
f7adfe8e | 198 | } |
0022c355 | 199 | return b; |
9a3f3b7b ML |
200 | } |
201 | ||
202 | /* | |
0022c355 | 203 | * Enter a keyword into the table. It is assumed to not be there already. |
9a3f3b7b ML |
204 | * The string is assumed to be statically allocated. |
205 | */ | |
0022c355 ML |
206 | |
207 | private keyword (s, t) | |
9a3f3b7b ML |
208 | String s; |
209 | Token t; | |
9a3f3b7b | 210 | { |
0022c355 | 211 | Keyword k; |
9a3f3b7b ML |
212 | Name n; |
213 | ||
214 | n = identname(s, true); | |
0022c355 ML |
215 | k = keywords_insert(n); |
216 | k->class = ISKEYWORD; | |
217 | k->value.toknum = t; | |
9a3f3b7b ML |
218 | } |
219 | ||
220 | /* | |
0022c355 | 221 | * Define a builtin command name alias. |
9a3f3b7b | 222 | */ |
0022c355 ML |
223 | |
224 | private defalias (s1, s2) | |
225 | String s1, s2; | |
9a3f3b7b | 226 | { |
0022c355 | 227 | alias(identname(s1, true), nil, s2); |
9a3f3b7b ML |
228 | } |
229 | ||
230 | /* | |
0022c355 | 231 | * Look for a word of a particular class. |
9a3f3b7b ML |
232 | */ |
233 | ||
0022c355 | 234 | private Keyword findword (n, class) |
9a3f3b7b | 235 | Name n; |
0022c355 | 236 | KeywordType class; |
9a3f3b7b | 237 | { |
9a3f3b7b | 238 | register Keyword k; |
9a3f3b7b | 239 | |
0022c355 ML |
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; | |
2fd0f574 SL |
266 | } |
267 | ||
0022c355 ML |
268 | /* |
269 | * Return the associated string if there is an alias with the given name. | |
270 | */ | |
271 | ||
272 | public boolean findalias (n, pl, str) | |
2fd0f574 | 273 | Name n; |
0022c355 ML |
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; | |
8d7bc982 | 286 | b = true; |
0022c355 ML |
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; | |
2fd0f574 | 310 | { |
0022c355 | 311 | Keyword k; |
2fd0f574 | 312 | |
0022c355 ML |
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 | } | |
9a3f3b7b ML |
324 | } |
325 | ||
326 | /* | |
0022c355 | 327 | * Print out an alias. |
9a3f3b7b | 328 | */ |
0022c355 ML |
329 | |
330 | private print_alias (cmd) | |
f7adfe8e | 331 | Name cmd; |
9a3f3b7b | 332 | { |
0022c355 ML |
333 | register Keyword k; |
334 | register Integer i; | |
f7adfe8e SL |
335 | Name n; |
336 | ||
0022c355 ML |
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 | } | |
9a3f3b7b | 361 | } |
f7adfe8e SL |
362 | } |
363 | ||
0022c355 ML |
364 | private printparams (pl) |
365 | List pl; | |
f7adfe8e | 366 | { |
0022c355 | 367 | Name n; |
f7adfe8e | 368 | |
0022c355 ML |
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(")"); | |
f7adfe8e | 378 | } |
0022c355 ML |
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)); | |
59475aff SL |
390 | } |
391 | } | |
392 | ||
0022c355 ML |
393 | /* |
394 | * Define a variable. | |
395 | */ | |
396 | ||
397 | public defvar (n, val) | |
398 | Name n; | |
399 | Node val; | |
59475aff | 400 | { |
0022c355 | 401 | Keyword k; |
59475aff | 402 | |
0022c355 ML |
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 | } | |
9a3f3b7b ML |
419 | } |
420 | ||
421 | /* | |
0022c355 | 422 | * Return the value associated with a variable. |
9a3f3b7b | 423 | */ |
0022c355 ML |
424 | |
425 | public Node findvar (n) | |
426 | Name n; | |
9a3f3b7b | 427 | { |
0022c355 ML |
428 | Keyword k; |
429 | Node val; | |
9a3f3b7b | 430 | |
0022c355 ML |
431 | k = findword(n, ISVAR); |
432 | if (k == nil) { | |
433 | val = nil; | |
434 | } else { | |
435 | val = k->value.var; | |
f7adfe8e | 436 | } |
0022c355 ML |
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 | } | |
9a3f3b7b ML |
487 | } |
488 | } | |
489 | } |