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