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) 06/04/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 } 490