19664Slinton /* Copyright (c) 1982 Regents of the University of California */ 29664Slinton 3*18220Slinton static char sccsid[] = "@(#)keywords.c 1.7 (Berkeley) 03/01/85"; 49664Slinton 5*18220Slinton static char rcsid[] = "$Header: keywords.c,v 1.5 84/12/26 10:39:45 linton Exp $"; 6*18220Slinton 79664Slinton /* 8*18220Slinton * Keywords, variables, and aliases (oh my!). 99664Slinton */ 109664Slinton 119664Slinton #include "defs.h" 129664Slinton #include "keywords.h" 139664Slinton #include "scanner.h" 149664Slinton #include "names.h" 159664Slinton #include "symbols.h" 169664Slinton #include "tree.h" 17*18220Slinton #include "lists.h" 18*18220Slinton #include "main.h" 199664Slinton #include "y.tab.h" 209664Slinton 219664Slinton #ifndef public 22*18220Slinton 239664Slinton #include "scanner.h" 24*18220Slinton #include "tree.h" 25*18220Slinton 269664Slinton #endif 279664Slinton 289664Slinton private String reserved[] ={ 299664Slinton "alias", "and", "assign", "at", "call", "catch", "cont", 3016611Ssam "debug", "delete", "div", "down", "dump", "edit", "file", "func", 319664Slinton "gripe", "help", "if", "ignore", "in", 329664Slinton "list", "mod", "next", "nexti", "nil", "not", "or", 3316611Ssam "print", "psym", "quit", "rerun", "return", "run", 34*18220Slinton "set", "sh", "skip", "source", "status", "step", "stepi", 35*18220Slinton "stop", "stopi", "trace", "tracei", "unalias", "unset", "up", "use", 36*18220Slinton "whatis", "when", "where", "whereis", "which", 37*18220Slinton "INT", "CHAR", "REAL", "NAME", "STRING", "->" 389664Slinton }; 399664Slinton 409664Slinton /* 419664Slinton * The keyword table is a traditional hash table with collisions 429664Slinton * resolved by chaining. 439664Slinton */ 44*18220Slinton 45*18220Slinton #define HASHTABLESIZE 1007 46*18220Slinton 47*18220Slinton typedef enum { ISKEYWORD, ISALIAS, ISVAR } KeywordType; 48*18220Slinton 499664Slinton typedef struct Keyword { 509664Slinton Name name; 51*18220Slinton KeywordType class : 16; 52*18220Slinton union { 53*18220Slinton /* ISKEYWORD: */ 54*18220Slinton Token toknum; 55*18220Slinton 56*18220Slinton /* ISALIAS: */ 57*18220Slinton struct { 58*18220Slinton List paramlist; 59*18220Slinton String expansion; 60*18220Slinton } alias; 61*18220Slinton 62*18220Slinton /* ISVAR: */ 63*18220Slinton Node var; 64*18220Slinton } value; 659664Slinton struct Keyword *chain; 669664Slinton } *Keyword; 679664Slinton 689664Slinton typedef unsigned int Hashvalue; 699664Slinton 70*18220Slinton private Keyword hashtab[HASHTABLESIZE]; 719664Slinton 72*18220Slinton #define hash(n) ((((unsigned) n) >> 2) mod HASHTABLESIZE) 739664Slinton 749664Slinton /* 759664Slinton * Enter all the reserved words into the keyword table. 76*18220Slinton * 77*18220Slinton * If the vaddrs flag is set (through the -k command line option) then 78*18220Slinton * set the special "$mapaddrs" variable. This assumes that the 79*18220Slinton * command line arguments are scanned before this routine is called. 809664Slinton */ 81*18220Slinton 829664Slinton public enterkeywords() 839664Slinton { 84*18220Slinton register integer i; 859664Slinton 86*18220Slinton for (i = ALIAS; i <= WHICH; i++) { 8716928Ssam keyword(reserved[ord(i) - ord(ALIAS)], i); 88*18220Slinton } 89*18220Slinton defalias("c", "cont"); 90*18220Slinton defalias("d", "delete"); 91*18220Slinton defalias("h", "help"); 92*18220Slinton defalias("e", "edit"); 93*18220Slinton defalias("l", "list"); 94*18220Slinton defalias("n", "next"); 95*18220Slinton defalias("p", "print"); 96*18220Slinton defalias("q", "quit"); 97*18220Slinton defalias("r", "run"); 98*18220Slinton defalias("s", "step"); 99*18220Slinton defalias("st", "stop"); 100*18220Slinton defalias("j", "status"); 101*18220Slinton defalias("t", "where"); 102*18220Slinton if (vaddrs) { 103*18220Slinton defvar(identname("$mapaddrs", true), nil); 104*18220Slinton } 1059664Slinton } 1069664Slinton 1079664Slinton /* 108*18220Slinton * Deallocate the keyword table. 1099664Slinton */ 110*18220Slinton 1119664Slinton public keywords_free() 1129664Slinton { 1139664Slinton register Integer i; 1149664Slinton register Keyword k, nextk; 1159664Slinton 116*18220Slinton for (i = 0; i < HASHTABLESIZE; i++) { 117*18220Slinton k = hashtab[i]; 118*18220Slinton while (k != nil) { 1199664Slinton nextk = k->chain; 1209664Slinton dispose(k); 121*18220Slinton k = nextk; 1229664Slinton } 1239664Slinton hashtab[i] = nil; 1249664Slinton } 125*18220Slinton } 126*18220Slinton 127*18220Slinton /* 128*18220Slinton * Insert a name into the keyword table and return the keyword for it. 129*18220Slinton */ 130*18220Slinton 131*18220Slinton private Keyword keywords_insert (n) 132*18220Slinton Name n; 133*18220Slinton { 134*18220Slinton Hashvalue h; 135*18220Slinton Keyword k; 136*18220Slinton 137*18220Slinton h = hash(n); 138*18220Slinton k = new(Keyword); 139*18220Slinton k->name = n; 140*18220Slinton k->chain = hashtab[h]; 141*18220Slinton hashtab[h] = k; 142*18220Slinton return k; 143*18220Slinton } 144*18220Slinton 145*18220Slinton /* 146*18220Slinton * Find the keyword associated with the given name. 147*18220Slinton */ 148*18220Slinton 149*18220Slinton private Keyword keywords_lookup (n) 150*18220Slinton Name n; 151*18220Slinton { 152*18220Slinton Hashvalue h; 153*18220Slinton register Keyword k; 154*18220Slinton 155*18220Slinton h = hash(n); 156*18220Slinton k = hashtab[h]; 157*18220Slinton while (k != nil and k->name != n) { 158*18220Slinton k = k->chain; 159*18220Slinton } 160*18220Slinton return k; 161*18220Slinton } 162*18220Slinton 163*18220Slinton /* 164*18220Slinton * Delete the given keyword of the given class. 165*18220Slinton */ 166*18220Slinton 167*18220Slinton private boolean keywords_delete (n, class) 168*18220Slinton Name n; 169*18220Slinton KeywordType class; 170*18220Slinton { 171*18220Slinton Hashvalue h; 172*18220Slinton register Keyword k, prevk; 173*18220Slinton boolean b; 174*18220Slinton 175*18220Slinton h = hash(n); 176*18220Slinton k = hashtab[h]; 177*18220Slinton prevk = nil; 178*18220Slinton while (k != nil and (k->name != n or k->class != class)) { 179*18220Slinton prevk = k; 180*18220Slinton k = k->chain; 181*18220Slinton } 182*18220Slinton if (k != nil) { 183*18220Slinton b = true; 184*18220Slinton if (prevk == nil) { 185*18220Slinton hashtab[h] = k->chain; 186*18220Slinton } else { 187*18220Slinton prevk->chain = k->chain; 18816928Ssam } 189*18220Slinton dispose(k); 190*18220Slinton } else { 191*18220Slinton b = false; 19216928Ssam } 193*18220Slinton return b; 1949664Slinton } 1959664Slinton 1969664Slinton /* 197*18220Slinton * Enter a keyword into the table. It is assumed to not be there already. 1989664Slinton * The string is assumed to be statically allocated. 1999664Slinton */ 200*18220Slinton 201*18220Slinton private keyword (s, t) 2029664Slinton String s; 2039664Slinton Token t; 2049664Slinton { 205*18220Slinton Keyword k; 2069664Slinton Name n; 2079664Slinton 2089664Slinton n = identname(s, true); 209*18220Slinton k = keywords_insert(n); 210*18220Slinton k->class = ISKEYWORD; 211*18220Slinton k->value.toknum = t; 2129664Slinton } 2139664Slinton 2149664Slinton /* 215*18220Slinton * Define a builtin command name alias. 2169664Slinton */ 217*18220Slinton 218*18220Slinton private defalias (s1, s2) 219*18220Slinton String s1, s2; 2209664Slinton { 221*18220Slinton alias(identname(s1, true), nil, s2); 2229664Slinton } 2239664Slinton 2249664Slinton /* 225*18220Slinton * Look for a word of a particular class. 2269664Slinton */ 2279664Slinton 228*18220Slinton private Keyword findword (n, class) 2299664Slinton Name n; 230*18220Slinton KeywordType class; 2319664Slinton { 2329664Slinton register Keyword k; 2339664Slinton 234*18220Slinton k = keywords_lookup(n); 235*18220Slinton while (k != nil and (k->name != n or k->class != class)) { 236*18220Slinton k = k->chain; 237*18220Slinton } 238*18220Slinton return k; 23916611Ssam } 24016611Ssam 241*18220Slinton /* 242*18220Slinton * Return the token associated with a given keyword string. 243*18220Slinton * If there is none, return the given default value. 244*18220Slinton */ 245*18220Slinton 246*18220Slinton public Token findkeyword (n, def) 24716611Ssam Name n; 248*18220Slinton Token def; 24916611Ssam { 250*18220Slinton Keyword k; 251*18220Slinton Token t; 25216611Ssam 253*18220Slinton k = findword(n, ISKEYWORD); 254*18220Slinton if (k == nil) { 255*18220Slinton t = def; 256*18220Slinton } else { 257*18220Slinton t = k->value.toknum; 258*18220Slinton } 259*18220Slinton return t; 2609664Slinton } 2619664Slinton 2629664Slinton /* 263*18220Slinton * Return the associated string if there is an alias with the given name. 2649664Slinton */ 265*18220Slinton 266*18220Slinton public boolean findalias (n, pl, str) 267*18220Slinton Name n; 268*18220Slinton List *pl; 269*18220Slinton String *str; 270*18220Slinton { 271*18220Slinton Keyword k; 272*18220Slinton boolean b; 273*18220Slinton 274*18220Slinton k = findword(n, ISALIAS); 275*18220Slinton if (k == nil) { 276*18220Slinton b = false; 277*18220Slinton } else { 278*18220Slinton *pl = k->value.alias.paramlist; 279*18220Slinton *str = k->value.alias.expansion; 280*18220Slinton } 281*18220Slinton return b; 282*18220Slinton } 283*18220Slinton 284*18220Slinton /* 285*18220Slinton * Return the string associated with a token corresponding to a keyword. 286*18220Slinton */ 287*18220Slinton 288*18220Slinton public String keywdstring (t) 289*18220Slinton Token t; 290*18220Slinton { 291*18220Slinton return reserved[ord(t) - ord(ALIAS)]; 292*18220Slinton } 293*18220Slinton 294*18220Slinton /* 295*18220Slinton * Process an alias command, either entering a new alias or printing out 296*18220Slinton * an existing one. 297*18220Slinton */ 298*18220Slinton 299*18220Slinton public alias (newcmd, args, str) 300*18220Slinton Name newcmd; 301*18220Slinton List args; 302*18220Slinton String str; 303*18220Slinton { 304*18220Slinton Keyword k; 305*18220Slinton 306*18220Slinton if (str == nil) { 307*18220Slinton print_alias(newcmd); 308*18220Slinton } else { 309*18220Slinton k = findword(newcmd, ISALIAS); 310*18220Slinton if (k == nil) { 311*18220Slinton k = keywords_insert(newcmd); 312*18220Slinton } 313*18220Slinton k->class = ISALIAS; 314*18220Slinton k->value.alias.paramlist = args; 315*18220Slinton k->value.alias.expansion = str; 316*18220Slinton } 317*18220Slinton } 318*18220Slinton 319*18220Slinton /* 320*18220Slinton * Print out an alias. 321*18220Slinton */ 322*18220Slinton 323*18220Slinton private print_alias (cmd) 32416928Ssam Name cmd; 3259664Slinton { 326*18220Slinton register Keyword k; 327*18220Slinton register Integer i; 32816928Ssam Name n; 3299664Slinton 330*18220Slinton if (cmd == nil) { 331*18220Slinton for (i = 0; i < HASHTABLESIZE; i++) { 332*18220Slinton for (k = hashtab[i]; k != nil; k = k->chain) { 333*18220Slinton if (k->class == ISALIAS) { 334*18220Slinton if (isredirected()) { 335*18220Slinton printf("alias %s", ident(k->name)); 336*18220Slinton printparams(k->value.alias.paramlist); 337*18220Slinton printf("\t\"%s\"\n", k->value.alias.expansion); 338*18220Slinton } else { 339*18220Slinton printf("%s", ident(k->name)); 340*18220Slinton printparams(k->value.alias.paramlist); 341*18220Slinton printf("\t%s\n", k->value.alias.expansion); 342*18220Slinton } 343*18220Slinton } 344*18220Slinton } 345*18220Slinton } 346*18220Slinton } else { 347*18220Slinton k = findword(cmd, ISALIAS); 348*18220Slinton if (k == nil) { 349*18220Slinton printf("\n"); 350*18220Slinton } else { 351*18220Slinton printparams(k->value.alias.paramlist); 352*18220Slinton printf("%s\n", k->value.alias.expansion); 353*18220Slinton } 3549664Slinton } 3559664Slinton } 3569664Slinton 357*18220Slinton private printparams (pl) 358*18220Slinton List pl; 35916928Ssam { 360*18220Slinton Name n; 36116928Ssam 362*18220Slinton if (pl != nil) { 363*18220Slinton printf("("); 364*18220Slinton foreach(Name, n, pl) 365*18220Slinton printf("%s", ident(n)); 366*18220Slinton if (not list_islast()) { 367*18220Slinton printf(", "); 368*18220Slinton } 369*18220Slinton endfor 370*18220Slinton printf(")"); 37116928Ssam } 372*18220Slinton } 373*18220Slinton 374*18220Slinton /* 375*18220Slinton * Remove an alias. 376*18220Slinton */ 377*18220Slinton 378*18220Slinton public unalias (n) 379*18220Slinton Name n; 380*18220Slinton { 381*18220Slinton if (not keywords_delete(n, ISALIAS)) { 382*18220Slinton error("%s is not aliased", ident(n)); 38316949Ssam } 38416928Ssam } 38516928Ssam 386*18220Slinton /* 387*18220Slinton * Define a variable. 388*18220Slinton */ 389*18220Slinton 390*18220Slinton public defvar (n, val) 391*18220Slinton Name n; 392*18220Slinton Node val; 39316949Ssam { 394*18220Slinton Keyword k; 39516949Ssam 396*18220Slinton if (n == nil) { 397*18220Slinton print_vars(); 398*18220Slinton } else { 399*18220Slinton if (lookup(n) != nil) { 400*18220Slinton error("\"%s\" is a program symbol -- use assign", ident(n)); 401*18220Slinton } 402*18220Slinton k = findword(n, ISVAR); 403*18220Slinton if (k == nil) { 404*18220Slinton k = keywords_insert(n); 405*18220Slinton } 406*18220Slinton k->class = ISVAR; 407*18220Slinton k->value.var = val; 408*18220Slinton if (n == identname("$mapaddrs", true)) { 409*18220Slinton vaddrs = true; 410*18220Slinton } 411*18220Slinton } 41216949Ssam } 41316949Ssam 4149664Slinton /* 415*18220Slinton * Return the value associated with a variable. 4169664Slinton */ 417*18220Slinton 418*18220Slinton public Node findvar (n) 419*18220Slinton Name n; 4209664Slinton { 421*18220Slinton Keyword k; 422*18220Slinton Node val; 4239664Slinton 424*18220Slinton k = findword(n, ISVAR); 425*18220Slinton if (k == nil) { 426*18220Slinton val = nil; 427*18220Slinton } else { 428*18220Slinton val = k->value.var; 42916928Ssam } 430*18220Slinton return val; 431*18220Slinton } 432*18220Slinton 433*18220Slinton /* 434*18220Slinton * Return whether or not a variable is set. 435*18220Slinton */ 436*18220Slinton 437*18220Slinton public boolean varIsSet (s) 438*18220Slinton String s; 439*18220Slinton { 440*18220Slinton return (boolean) (findword(identname(s, false), ISVAR) != nil); 441*18220Slinton } 442*18220Slinton 443*18220Slinton /* 444*18220Slinton * Delete a variable. 445*18220Slinton */ 446*18220Slinton 447*18220Slinton public undefvar (n) 448*18220Slinton Name n; 449*18220Slinton { 450*18220Slinton if (not keywords_delete(n, ISVAR)) { 451*18220Slinton error("%s is not set", ident(n)); 452*18220Slinton } 453*18220Slinton if (n == identname("$mapaddrs", true)) { 454*18220Slinton vaddrs = false; 455*18220Slinton } 456*18220Slinton } 457*18220Slinton 458*18220Slinton /* 459*18220Slinton * Print out all the values of set variables. 460*18220Slinton */ 461*18220Slinton 462*18220Slinton private print_vars () 463*18220Slinton { 464*18220Slinton register integer i; 465*18220Slinton register Keyword k; 466*18220Slinton 467*18220Slinton for (i = 0; i < HASHTABLESIZE; i++) { 468*18220Slinton for (k = hashtab[i]; k != nil; k = k->chain) { 469*18220Slinton if (k->class == ISVAR) { 470*18220Slinton if (isredirected()) { 471*18220Slinton printf("set "); 472*18220Slinton } 473*18220Slinton printf("%s", ident(k->name)); 474*18220Slinton if (k->value.var != nil) { 475*18220Slinton printf("\t"); 476*18220Slinton prtree(stdout, k->value.var); 477*18220Slinton } 478*18220Slinton printf("\n"); 479*18220Slinton } 4809664Slinton } 4819664Slinton } 4829664Slinton } 483