Commit | Line | Data |
---|---|---|
2a24676e | 1 | /* |
8a90f3aa KB |
2 | * Copyright (c) 1983 The Regents of the University of California. |
3 | * All rights reserved. | |
4 | * | |
6ecf3d85 | 5 | * %sccs.include.redist.c% |
2a24676e | 6 | */ |
9a3f3b7b | 7 | |
2a24676e | 8 | #ifndef lint |
6ecf3d85 | 9 | static char sccsid[] = "@(#)keywords.c 5.4 (Berkeley) %G%"; |
8a90f3aa | 10 | #endif /* not lint */ |
9a3f3b7b ML |
11 | |
12 | /* | |
0022c355 | 13 | * Keywords, variables, and aliases (oh my!). |
9a3f3b7b ML |
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" | |
0022c355 ML |
22 | #include "lists.h" |
23 | #include "main.h" | |
9a3f3b7b ML |
24 | #include "y.tab.h" |
25 | ||
26 | #ifndef public | |
0022c355 | 27 | |
9a3f3b7b | 28 | #include "scanner.h" |
0022c355 ML |
29 | #include "tree.h" |
30 | ||
9a3f3b7b ML |
31 | #endif |
32 | ||
33 | private String reserved[] ={ | |
34 | "alias", "and", "assign", "at", "call", "catch", "cont", | |
2fd0f574 | 35 | "debug", "delete", "div", "down", "dump", "edit", "file", "func", |
9a3f3b7b ML |
36 | "gripe", "help", "if", "ignore", "in", |
37 | "list", "mod", "next", "nexti", "nil", "not", "or", | |
2fd0f574 | 38 | "print", "psym", "quit", "rerun", "return", "run", |
0022c355 ML |
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", "->" | |
9a3f3b7b ML |
43 | }; |
44 | ||
45 | /* | |
46 | * The keyword table is a traditional hash table with collisions | |
47 | * resolved by chaining. | |
48 | */ | |
0022c355 ML |
49 | |
50 | #define HASHTABLESIZE 1007 | |
51 | ||
52 | typedef enum { ISKEYWORD, ISALIAS, ISVAR } KeywordType; | |
53 | ||
9a3f3b7b ML |
54 | typedef struct Keyword { |
55 | Name name; | |
0022c355 ML |
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; | |
9a3f3b7b ML |
70 | struct Keyword *chain; |
71 | } *Keyword; | |
72 | ||
73 | typedef unsigned int Hashvalue; | |
74 | ||
0022c355 | 75 | private Keyword hashtab[HASHTABLESIZE]; |
f7adfe8e | 76 | |
0022c355 | 77 | #define hash(n) ((((unsigned) n) >> 2) mod HASHTABLESIZE) |
9a3f3b7b ML |
78 | |
79 | /* | |
80 | * Enter all the reserved words into the keyword table. | |
0022c355 ML |
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. | |
9a3f3b7b | 85 | */ |
0022c355 | 86 | |
9a3f3b7b ML |
87 | public enterkeywords() |
88 | { | |
0022c355 | 89 | register integer i; |
9a3f3b7b | 90 | |
0022c355 | 91 | for (i = ALIAS; i <= WHICH; i++) { |
f7adfe8e | 92 | keyword(reserved[ord(i) - ord(ALIAS)], i); |
0022c355 ML |
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 | } | |
9a3f3b7b ML |
110 | } |
111 | ||
112 | /* | |
0022c355 | 113 | * Deallocate the keyword table. |
9a3f3b7b | 114 | */ |
0022c355 | 115 | |
9a3f3b7b ML |
116 | public keywords_free() |
117 | { | |
118 | register Integer i; | |
119 | register Keyword k, nextk; | |
120 | ||
0022c355 ML |
121 | for (i = 0; i < HASHTABLESIZE; i++) { |
122 | k = hashtab[i]; | |
123 | while (k != nil) { | |
9a3f3b7b ML |
124 | nextk = k->chain; |
125 | dispose(k); | |
0022c355 | 126 | k = nextk; |
9a3f3b7b ML |
127 | } |
128 | hashtab[i] = nil; | |
129 | } | |
0022c355 ML |
130 | } |
131 | ||
132 | /* | |
133 | * Insert a name into the keyword table and return the keyword for it. | |
134 | */ | |
135 | ||
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 | ||
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 | ||
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; | |
f7adfe8e | 193 | } |
0022c355 ML |
194 | dispose(k); |
195 | } else { | |
196 | b = false; | |
f7adfe8e | 197 | } |
0022c355 | 198 | return b; |
9a3f3b7b ML |
199 | } |
200 | ||
201 | /* | |
0022c355 | 202 | * Enter a keyword into the table. It is assumed to not be there already. |
9a3f3b7b ML |
203 | * The string is assumed to be statically allocated. |
204 | */ | |
0022c355 ML |
205 | |
206 | private keyword (s, t) | |
9a3f3b7b ML |
207 | String s; |
208 | Token t; | |
9a3f3b7b | 209 | { |
0022c355 | 210 | Keyword k; |
9a3f3b7b ML |
211 | Name n; |
212 | ||
213 | n = identname(s, true); | |
0022c355 ML |
214 | k = keywords_insert(n); |
215 | k->class = ISKEYWORD; | |
216 | k->value.toknum = t; | |
9a3f3b7b ML |
217 | } |
218 | ||
219 | /* | |
0022c355 | 220 | * Define a builtin command name alias. |
9a3f3b7b | 221 | */ |
0022c355 ML |
222 | |
223 | private defalias (s1, s2) | |
224 | String s1, s2; | |
9a3f3b7b | 225 | { |
0022c355 | 226 | alias(identname(s1, true), nil, s2); |
9a3f3b7b ML |
227 | } |
228 | ||
229 | /* | |
0022c355 | 230 | * Look for a word of a particular class. |
9a3f3b7b ML |
231 | */ |
232 | ||
0022c355 | 233 | private Keyword findword (n, class) |
9a3f3b7b | 234 | Name n; |
0022c355 | 235 | KeywordType class; |
9a3f3b7b | 236 | { |
9a3f3b7b | 237 | register Keyword k; |
9a3f3b7b | 238 | |
0022c355 ML |
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 | ||
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; | |
2fd0f574 SL |
265 | } |
266 | ||
0022c355 ML |
267 | /* |
268 | * Return the associated string if there is an alias with the given name. | |
269 | */ | |
270 | ||
271 | public boolean findalias (n, pl, str) | |
2fd0f574 | 272 | Name n; |
0022c355 ML |
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; | |
8d7bc982 | 285 | b = true; |
0022c355 ML |
286 | } |
287 | return b; | |
288 | } | |
289 | ||
290 | /* | |
291 | * Return the string associated with a token corresponding to a keyword. | |
292 | */ | |
293 | ||
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 | ||
305 | public alias (newcmd, args, str) | |
306 | Name newcmd; | |
307 | List args; | |
308 | String str; | |
2fd0f574 | 309 | { |
0022c355 | 310 | Keyword k; |
2fd0f574 | 311 | |
0022c355 ML |
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 | } | |
9a3f3b7b ML |
323 | } |
324 | ||
325 | /* | |
0022c355 | 326 | * Print out an alias. |
9a3f3b7b | 327 | */ |
0022c355 ML |
328 | |
329 | private print_alias (cmd) | |
f7adfe8e | 330 | Name cmd; |
9a3f3b7b | 331 | { |
0022c355 ML |
332 | register Keyword k; |
333 | register Integer i; | |
f7adfe8e SL |
334 | Name n; |
335 | ||
0022c355 ML |
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 | } | |
9a3f3b7b | 360 | } |
f7adfe8e SL |
361 | } |
362 | ||
0022c355 ML |
363 | private printparams (pl) |
364 | List pl; | |
f7adfe8e | 365 | { |
0022c355 | 366 | Name n; |
f7adfe8e | 367 | |
0022c355 ML |
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(")"); | |
f7adfe8e | 377 | } |
0022c355 ML |
378 | } |
379 | ||
380 | /* | |
381 | * Remove an alias. | |
382 | */ | |
383 | ||
384 | public unalias (n) | |
385 | Name n; | |
386 | { | |
387 | if (not keywords_delete(n, ISALIAS)) { | |
388 | error("%s is not aliased", ident(n)); | |
59475aff SL |
389 | } |
390 | } | |
391 | ||
0022c355 ML |
392 | /* |
393 | * Define a variable. | |
394 | */ | |
395 | ||
396 | public defvar (n, val) | |
397 | Name n; | |
398 | Node val; | |
59475aff | 399 | { |
0022c355 | 400 | Keyword k; |
59475aff | 401 | |
0022c355 ML |
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 | } | |
9a3f3b7b ML |
418 | } |
419 | ||
420 | /* | |
0022c355 | 421 | * Return the value associated with a variable. |
9a3f3b7b | 422 | */ |
0022c355 ML |
423 | |
424 | public Node findvar (n) | |
425 | Name n; | |
9a3f3b7b | 426 | { |
0022c355 ML |
427 | Keyword k; |
428 | Node val; | |
9a3f3b7b | 429 | |
0022c355 ML |
430 | k = findword(n, ISVAR); |
431 | if (k == nil) { | |
432 | val = nil; | |
433 | } else { | |
434 | val = k->value.var; | |
f7adfe8e | 435 | } |
0022c355 ML |
436 | return val; |
437 | } | |
438 | ||
439 | /* | |
440 | * Return whether or not a variable is set. | |
441 | */ | |
442 | ||
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 | ||
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 | ||
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 | } | |
9a3f3b7b ML |
486 | } |
487 | } | |
488 | } |