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