BSD 4_4 release
[unix-history] / usr / src / old / dbx / keywords.c
index f7de1e4..f120598 100644 (file)
@@ -1,9 +1,42 @@
-/* Copyright (c) 1982 Regents of the University of California */
+/*
+ * Copyright (c) 1983 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
 
 
-static char sccsid[] = "@(#)keywords.c 1.3 %G%";
+#ifndef lint
+static char sccsid[] = "@(#)keywords.c 5.4 (Berkeley) 6/1/90";
+#endif /* not lint */
 
 /*
 
 /*
- * Keyword management.
+ * Keywords, variables, and aliases (oh my!).
  */
 
 #include "defs.h"
  */
 
 #include "defs.h"
@@ -12,23 +45,27 @@ static char sccsid[] = "@(#)keywords.c 1.3 %G%";
 #include "names.h"
 #include "symbols.h"
 #include "tree.h"
 #include "names.h"
 #include "symbols.h"
 #include "tree.h"
+#include "lists.h"
+#include "main.h"
 #include "y.tab.h"
 
 #ifndef public
 #include "y.tab.h"
 
 #ifndef public
+
 #include "scanner.h"
 #include "scanner.h"
+#include "tree.h"
+
 #endif
 
 private String reserved[] ={
     "alias", "and", "assign", "at", "call", "catch", "cont",
 #endif
 
 private String reserved[] ={
     "alias", "and", "assign", "at", "call", "catch", "cont",
-    "debug", "delete", "div", "dump", "edit", "file", "func",
+    "debug", "delete", "div", "down", "dump", "edit", "file", "func",
     "gripe", "help", "if", "ignore", "in",
     "list", "mod", "next", "nexti", "nil", "not", "or",
     "gripe", "help", "if", "ignore", "in",
     "list", "mod", "next", "nexti", "nil", "not", "or",
-    "print", "psym", "quit", "run",
-    "sh", "skip", "source", "status", "step", "stepi",
-    "stop", "stopi", "trace", "tracei",
-    "use", "whatis", "when", "where", "whereis", "which",
-    "INT", "REAL", "NAME", "STRING",
-    "LFORMER", "RFORMER", "#^", "->"
+    "print", "psym", "quit", "rerun", "return", "run",
+    "set", "sh", "skip", "source", "status", "step", "stepi",
+    "stop", "stopi", "trace", "tracei", "unalias", "unset", "up", "use",
+    "whatis", "when", "where", "whereis", "which",
+    "INT", "CHAR", "REAL", "NAME", "STRING", "->"
 };
 
 /*
 };
 
 /*
@@ -36,12 +73,26 @@ private String reserved[] ={
  * resolved by chaining.
  */
 
  * resolved by chaining.
  */
 
-#define HASHTABLESIZE 503
+#define HASHTABLESIZE 1007
+
+typedef enum { ISKEYWORD, ISALIAS, ISVAR } KeywordType;
 
 typedef struct Keyword {
     Name name;
 
 typedef struct Keyword {
     Name name;
-    Token toknum : 16;
-    Boolean isalias : 16;
+    KeywordType class : 16;
+    union {
+       /* ISKEYWORD: */
+           Token toknum;
+
+       /* ISALIAS: */
+           struct {
+               List paramlist;
+               String expansion;
+           } alias;
+
+       /* ISVAR: */
+           Node var;
+    } value;
     struct Keyword *chain;
 } *Keyword;
 
     struct Keyword *chain;
 } *Keyword;
 
@@ -53,16 +104,35 @@ private Keyword hashtab[HASHTABLESIZE];
 
 /*
  * Enter all the reserved words into the keyword table.
 
 /*
  * Enter all the reserved words into the keyword table.
+ *
+ * If the vaddrs flag is set (through the -k command line option) then
+ * set the special "$mapaddrs" variable.  This assumes that the
+ * command line arguments are scanned before this routine is called.
  */
 
 public enterkeywords()
 {
  */
 
 public enterkeywords()
 {
-    register Integer i;
+    register integer i;
 
     for (i = ALIAS; i <= WHICH; i++) {
 
     for (i = ALIAS; i <= WHICH; i++) {
-       keyword(reserved[ord(i) - ord(ALIAS)], i, false);
+       keyword(reserved[ord(i) - ord(ALIAS)], i);
+    }
+    defalias("c", "cont");
+    defalias("d", "delete");
+    defalias("h", "help");
+    defalias("e", "edit");
+    defalias("l", "list");
+    defalias("n", "next");
+    defalias("p", "print");
+    defalias("q", "quit");
+    defalias("r", "run");
+    defalias("s", "step");
+    defalias("st", "stop");
+    defalias("j", "status");
+    defalias("t", "where");
+    if (vaddrs) {
+       defvar(identname("$mapaddrs", true), nil);
     }
     }
-    keyword("set", ASSIGN, false);
 }
 
 /*
 }
 
 /*
@@ -86,79 +156,195 @@ public keywords_free()
 }
 
 /*
 }
 
 /*
- * Enter a keyword into the name table.  It is assumed to not be there already.
- * The string is assumed to be statically allocated.
+ * Insert a name into the keyword table and return the keyword for it.
  */
 
  */
 
-private keyword(s, t, isalias)
-String s;
-Token t;
-Boolean isalias;
+private Keyword keywords_insert (n)
+Name n;
 {
 {
-    register Hashvalue h;
-    register Keyword k;
-    Name n;
+    Hashvalue h;
+    Keyword k;
 
 
-    n = identname(s, true);
     h = hash(n);
     k = new(Keyword);
     k->name = n;
     h = hash(n);
     k = new(Keyword);
     k->name = n;
-    k->toknum = t;
-    k->isalias = isalias;
     k->chain = hashtab[h];
     hashtab[h] = k;
     k->chain = hashtab[h];
     hashtab[h] = k;
+    return k;
 }
 
 /*
 }
 
 /*
- * Return the string associated with a token corresponding to a keyword.
+ * Find the keyword associated with the given name.
  */
 
  */
 
-public String keywdstring(t)
-Token t;
+private Keyword keywords_lookup (n)
+Name n;
 {
 {
-    return reserved[ord(t) - ord(ALIAS)];
+    Hashvalue h;
+    register Keyword k;
+
+    h = hash(n);
+    k = hashtab[h];
+    while (k != nil and k->name != n) {
+       k = k->chain;
+    }
+    return k;
 }
 
 /*
 }
 
 /*
- * Find a keyword in the keyword table.
- * We assume that tokens cannot legitimately be nil (0).
+ * Delete the given keyword of the given class.
  */
 
  */
 
-public Token findkeyword(n)
+private boolean keywords_delete (n, class)
 Name n;
 Name n;
+KeywordType class;
 {
 {
-    register Hashvalue h;
-    register Keyword k;
-    Token t;
+    Hashvalue h;
+    register Keyword k, prevk;
+    boolean b;
 
     h = hash(n);
     k = hashtab[h];
 
     h = hash(n);
     k = hashtab[h];
-    while (k != nil and k->name != n) {
+    prevk = nil;
+    while (k != nil and (k->name != n or k->class != class)) {
+       prevk = k;
        k = k->chain;
     }
        k = k->chain;
     }
+    if (k != nil) {
+       b = true;
+       if (prevk == nil) {
+           hashtab[h] = k->chain;
+       } else {
+           prevk->chain = k->chain;
+       }
+       dispose(k);
+    } else {
+       b = false;
+    }
+    return b;
+}
+
+/*
+ * Enter a keyword into the table.  It is assumed to not be there already.
+ * The string is assumed to be statically allocated.
+ */
+
+private keyword (s, t)
+String s;
+Token t;
+{
+    Keyword k;
+    Name n;
+
+    n = identname(s, true);
+    k = keywords_insert(n);
+    k->class = ISKEYWORD;
+    k->value.toknum = t;
+}
+
+/*
+ * Define a builtin command name alias.
+ */
+
+private defalias (s1, s2)
+String s1, s2;
+{
+    alias(identname(s1, true), nil, s2);
+}
+
+/*
+ * Look for a word of a particular class.
+ */
+
+private Keyword findword (n, class)
+Name n;
+KeywordType class;
+{
+    register Keyword k;
+
+    k = keywords_lookup(n);
+    while (k != nil and (k->name != n or k->class != class)) {
+       k = k->chain;
+    }
+    return k;
+}
+
+/*
+ * Return the token associated with a given keyword string.
+ * If there is none, return the given default value.
+ */
+
+public Token findkeyword (n, def)
+Name n;
+Token def;
+{
+    Keyword k;
+    Token t;
+
+    k = findword(n, ISKEYWORD);
     if (k == nil) {
     if (k == nil) {
-       t = nil;
+       t = def;
     } else {
     } else {
-       t = k->toknum;
+       t = k->value.toknum;
     }
     return t;
 }
 
 /*
     }
     return t;
 }
 
 /*
- * Create an alias.
+ * Return the associated string if there is an alias with the given name.
+ */
+
+public boolean findalias (n, pl, str)
+Name n;
+List *pl;
+String *str;
+{
+    Keyword k;
+    boolean b;
+
+    k = findword(n, ISALIAS);
+    if (k == nil) {
+       b = false;
+    } else {
+       *pl = k->value.alias.paramlist;
+       *str = k->value.alias.expansion;
+       b = true;
+    }
+    return b;
+}
+
+/*
+ * Return the string associated with a token corresponding to a keyword.
  */
 
  */
 
-public enter_alias(newcmd, oldcmd)
+public String keywdstring (t)
+Token t;
+{
+    return reserved[ord(t) - ord(ALIAS)];
+}
+
+/*
+ * Process an alias command, either entering a new alias or printing out
+ * an existing one.
+ */
+
+public alias (newcmd, args, str)
 Name newcmd;
 Name newcmd;
-Name oldcmd;
+List args;
+String str;
 {
 {
-    Token t;
+    Keyword k;
 
 
-    t = findkeyword(oldcmd);
-    if (t == nil) {
-       error("\"%s\" is not a command", ident(oldcmd));
+    if (str == nil) {
+       print_alias(newcmd);
     } else {
     } else {
-       keyword(ident(newcmd), t, true);
+       k = findword(newcmd, ISALIAS);
+       if (k == nil) {
+           k = keywords_insert(newcmd);
+       }
+       k->class = ISALIAS;
+       k->value.alias.paramlist = args;
+       k->value.alias.expansion = str;
     }
 }
 
     }
 }
 
@@ -166,30 +352,163 @@ Name oldcmd;
  * Print out an alias.
  */
 
  * Print out an alias.
  */
 
-public print_alias(cmd)
+private print_alias (cmd)
 Name cmd;
 {
     register Keyword k;
     register Integer i;
 Name cmd;
 {
     register Keyword k;
     register Integer i;
-    Token t;
+    Name n;
 
     if (cmd == nil) {
        for (i = 0; i < HASHTABLESIZE; i++) {
            for (k = hashtab[i]; k != nil; k = k->chain) {
 
     if (cmd == nil) {
        for (i = 0; i < HASHTABLESIZE; i++) {
            for (k = hashtab[i]; k != nil; k = k->chain) {
-               if (k->isalias) {
+               if (k->class == ISALIAS) {
                    if (isredirected()) {
                    if (isredirected()) {
-                       printf("alias ");
+                       printf("alias %s", ident(k->name));
+                       printparams(k->value.alias.paramlist);
+                       printf("\t\"%s\"\n", k->value.alias.expansion);
+                   } else {
+                       printf("%s", ident(k->name));
+                       printparams(k->value.alias.paramlist);
+                       printf("\t%s\n", k->value.alias.expansion);
                    }
                    }
-                   printf("%s\t%s\n", ident(k->name), keywdstring(k->toknum));
                }
            }
        }
     } else {
                }
            }
        }
     } else {
-       t = findkeyword(cmd);
-       if (t == nil) {
+       k = findword(cmd, ISALIAS);
+       if (k == nil) {
            printf("\n");
        } else {
            printf("\n");
        } else {
-           printf("%s\n", keywdstring(t));
+           printparams(k->value.alias.paramlist);
+           printf("%s\n", k->value.alias.expansion);
+       }
+    }
+}
+
+private printparams (pl)
+List pl;
+{
+    Name n;
+
+    if (pl != nil) {
+       printf("(");
+       foreach(Name, n, pl)
+           printf("%s", ident(n));
+           if (not list_islast()) {
+               printf(", ");
+           }
+       endfor
+       printf(")");
+    }
+}
+
+/*
+ * Remove an alias.
+ */
+
+public unalias (n)
+Name n;
+{
+    if (not keywords_delete(n, ISALIAS)) {
+       error("%s is not aliased", ident(n));
+    }
+}
+
+/*
+ * Define a variable.
+ */
+
+public defvar (n, val)
+Name n;
+Node val;
+{
+    Keyword k;
+
+    if (n == nil) {
+       print_vars();
+    } else {
+       if (lookup(n) != nil) {
+           error("\"%s\" is a program symbol -- use assign", ident(n));
+       }
+       k = findword(n, ISVAR);
+       if (k == nil) {
+           k = keywords_insert(n);
+       }
+       k->class = ISVAR;
+       k->value.var = val;
+       if (n == identname("$mapaddrs", true)) {
+           vaddrs = true;
+       }
+    }
+}
+
+/*
+ * Return the value associated with a variable.
+ */
+
+public Node findvar (n)
+Name n;
+{
+    Keyword k;
+    Node val;
+
+    k = findword(n, ISVAR);
+    if (k == nil) {
+       val = nil;
+    } else {
+       val = k->value.var;
+    }
+    return val;
+}
+
+/*
+ * Return whether or not a variable is set.
+ */
+
+public boolean varIsSet (s)
+String s;
+{
+    return (boolean) (findword(identname(s, false), ISVAR) != nil);
+}
+
+/*
+ * Delete a variable.
+ */
+
+public undefvar (n)
+Name n;
+{
+    if (not keywords_delete(n, ISVAR)) {
+       error("%s is not set", ident(n));
+    }
+    if (n == identname("$mapaddrs", true)) {
+       vaddrs = false;
+    }
+}
+
+/*
+ * Print out all the values of set variables.
+ */
+
+private print_vars ()
+{
+    register integer i;
+    register Keyword k;
+
+    for (i = 0; i < HASHTABLESIZE; i++) {
+       for (k = hashtab[i]; k != nil; k = k->chain) {
+           if (k->class == ISVAR) {
+               if (isredirected()) {
+                   printf("set ");
+               }
+               printf("%s", ident(k->name));
+               if (k->value.var != nil) {
+                   printf("\t");
+                   prtree(stdout, k->value.var);
+               }
+               printf("\n");
+           }
        }
     }
 }
        }
     }
 }