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