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 DF |
7 | #ifndef lint |
8 | static char sccsid[] = "@(#)keywords.c 5.1 (Berkeley) %G%"; | |
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; | |
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 | } |