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