add real aliases; rewrite lexical scanner
authorSam Leffler <sam@ucbvax.Berkeley.EDU>
Mon, 13 Aug 1984 04:22:30 +0000 (20:22 -0800)
committerSam Leffler <sam@ucbvax.Berkeley.EDU>
Mon, 13 Aug 1984 04:22:30 +0000 (20:22 -0800)
SCCS-vsn: old/dbx/commands.y 1.12
SCCS-vsn: old/dbx/eval.c 1.13
SCCS-vsn: old/dbx/keywords.c 1.5
SCCS-vsn: old/dbx/operators.c 1.7
SCCS-vsn: old/dbx/process.c 1.14
SCCS-vsn: old/dbx/scanner.c 1.10

usr/src/old/dbx/commands.y
usr/src/old/dbx/eval.c
usr/src/old/dbx/keywords.c
usr/src/old/dbx/operators.c
usr/src/old/dbx/process.c
usr/src/old/dbx/scanner.c

index 431d420..98e760f 100644 (file)
@@ -1,8 +1,7 @@
 %{
 %{
-
 /* Copyright (c) 1982 Regents of the University of California */
 
 /* Copyright (c) 1982 Regents of the University of California */
 
-static char sccsid[] = "@(#)commands.y 1.11 (Berkeley) %G%";
+static char sccsid[] = "@(#)commands.y 1.12 (Berkeley) %G%";
 
 /*
  * Yacc grammar for debugger commands.
 
 /*
  * Yacc grammar for debugger commands.
@@ -17,6 +16,7 @@ static        char sccsid[] = "@(#)commands.y 1.11 (Berkeley) %G%";
 #include "scanner.h"
 #include "names.h"
 #include "lists.h"
 #include "scanner.h"
 #include "names.h"
 #include "lists.h"
+#include <signal.h>
 
 private String curformat = "X";
 
 
 private String curformat = "X";
 
@@ -71,8 +71,9 @@ private String curformat = "X";
 %type <y_node>     command rcommand cmd step what where examine
 %type <y_node>     event opt_exp_list opt_cond
 %type <y_node>     exp_list exp term boolean_exp constant address
 %type <y_node>     command rcommand cmd step what where examine
 %type <y_node>     event opt_exp_list opt_cond
 %type <y_node>     exp_list exp term boolean_exp constant address
-%type <y_node>     integer_list alias_command list_command line_number
-%type <y_node>     search_command pattern
+%type <y_node>     int_list alias_command list_command line_number
+%type <y_node>     something search_command pattern
+%type <y_node>     signal_list signal
 %type <y_cmdlist>   actions
 %type <y_list>      sourcepath
 
 %type <y_cmdlist>   actions
 %type <y_list>      sourcepath
 
@@ -80,15 +81,32 @@ private String curformat = "X";
 
 input:
     input command_nl
 
 input:
     input command_nl
+{
+       endshellmode();
+       startaliasing();
+}
 |
     /* empty */
 ;
 |
     /* empty */
 ;
+
 command_nl:
     command_line '\n'
 command_nl:
     command_line '\n'
+{
+       if (istty()) {
+               printf("(%s) ", cmdname);
+               fflush(stdout);
+       }
+}
 |
     command_line ';'
 |
     '\n'
 |
     command_line ';'
 |
     '\n'
+{
+       if (istty()) {
+               printf("(%s) ", cmdname);
+               fflush(stdout);
+       }
+}
 ;
 
 command_line:
 ;
 
 command_line:
@@ -98,6 +116,7 @@ command_line:
             if(debug_flag[2]) {dumptree(stderr,$1); fflush (stderr);}
            eval($1);
        }
             if(debug_flag[2]) {dumptree(stderr,$1); fflush (stderr);}
            eval($1);
        }
+       startaliasing();
 }
 |
     rcommand redirectout
 }
 |
     rcommand redirectout
@@ -113,6 +132,7 @@ command_line:
                eval($1);
            }
        }
                eval($1);
            }
        }
+       startaliasing();
 }
 ;
 redirectout:
 }
 ;
 redirectout:
@@ -136,14 +156,19 @@ command:
        $$ = $1;
 }
 |
        $$ = $1;
 }
 |
-    ASSIGN term '=' exp
+    ASSIGN stopaliasing term '=' exp
 {
 {
-       $$ = build(O_ASSIGN, $2, $4);
+       $$ = build(O_ASSIGN, $3, $5);
 }
 |
 }
 |
-    CATCH INT
+    CATCH
 {
 {
-       $$ = build(O_CATCH, $2);
+       $$ = build(O_CATCH, nil);
+}
+|
+    CATCH stopaliasing signal_list
+{
+       $$ = build(O_CATCH, $3);
 }
 |
     CONT
 }
 |
     CONT
@@ -156,7 +181,7 @@ command:
        $$ = build(O_CONT, $2);
 }
 |
        $$ = build(O_CONT, $2);
 }
 |
-    DELETE integer_list
+    DELETE int_list
 {
        $$ = build(O_DELETE, $2);
 }
 {
        $$ = build(O_DELETE, $2);
 }
@@ -186,9 +211,9 @@ command:
        $$ = build(O_FUNC, nil);
 }
 |
        $$ = build(O_FUNC, nil);
 }
 |
-    FUNC opt_qual_symbol
+    FUNC stopaliasing symbol
 {
 {
-       $$ = build(O_FUNC, $2);
+       $$ = build(O_FUNC, $3);
 }
 |
     GRIPE
 }
 |
     GRIPE
@@ -201,9 +226,14 @@ command:
        $$ = build(O_HELP);
 }
 |
        $$ = build(O_HELP);
 }
 |
-    IGNORE INT
+    IGNORE
+{
+       $$ = build(O_IGNORE, nil);
+}
+|
+    IGNORE stopaliasing signal_list
 {
 {
-       $$ = build(O_IGNORE, $2);
+       $$ = build(O_IGNORE, $3);
 }
 |
     list_command
 }
 |
     list_command
@@ -211,9 +241,9 @@ command:
        $$ = $1;
 }
 |
        $$ = $1;
 }
 |
-    PSYM term
+    PSYM stopaliasing term
 {
 {
-       $$ = build(O_PSYM, $2);
+       $$ = build(O_PSYM, $3);
 }
 |
     QUIT
 }
 |
     QUIT
@@ -230,9 +260,9 @@ command:
        $$ = build(O_RETURN, nil);
 }
 |
        $$ = build(O_RETURN, nil);
 }
 |
-    RETURN opt_qual_symbol
+    RETURN stopaliasing opt_qual_symbol
 {
 {
-       $$ = build(O_RETURN, $2);
+       $$ = build(O_RETURN, $3);
 }
 |
     runcommand
 }
 |
     runcommand
@@ -366,11 +396,50 @@ pattern:
 }
 ;
 
 }
 ;
 
+int_list:
+    INT
+{
+       $$ = build(O_COMMA, build(O_LCON, $1), nil);
+}
+|
+    INT int_list
+{
+       $$ = build(O_COMMA, build(O_LCON, $1), $2);
+}
+;
+
+signal_list:
+     signal
+{
+       $$ = build(O_COMMA, $1, nil);
+}
+|
+    signal signal_list
+{
+       $$ = build(O_COMMA, $1, $2);
+}
+;
+
+signal:
+    INT
+{
+       if ($1 < 1 || $1 > NSIG)
+               error("Invalid signal %d.", $1);
+       $$ = build(O_LCON, $1);
+}
+|
+    NAME
+{
+       $$ = build(O_LCON, signalname(ident($1)));
+}
+;
+
 runcommand:
     run arglist
 |
     run
 ;
 runcommand:
     run arglist
 |
     run
 ;
+
 run:
     RUN shellmode
 {
 run:
     RUN shellmode
 {
@@ -389,12 +458,12 @@ arglist:
     arg
 ;
 arg:
     arg
 ;
 arg:
-    NAME
+     NAME
 {
        newarg(ident($1));
 }
 |
 {
        newarg(ident($1));
 }
 |
-    STRING
+     STRING
 {
        newarg($1);
 }
 {
        newarg($1);
 }
@@ -410,22 +479,22 @@ arg:
 }
 ;
 step:
 }
 ;
 step:
-    STEP
+    STEP stopaliasing
 {
        $$ = build(O_STEP, true, false);
 }
 |
 {
        $$ = build(O_STEP, true, false);
 }
 |
-    STEPI
+    STEPI stopaliasing
 {
        $$ = build(O_STEP, false, false);
 }
 |
 {
        $$ = build(O_STEP, false, false);
 }
 |
-    NEXT
+    NEXT stopaliasing
 {
        $$ = build(O_STEP, true, true);
 }
 |
 {
        $$ = build(O_STEP, true, true);
 }
 |
-    NEXTI
+    NEXTI stopaliasing
 {
        $$ = build(O_STEP, false, true);
 }
 {
        $$ = build(O_STEP, false, true);
 }
@@ -476,9 +545,9 @@ cmd:
  * Redirectable commands.
  */
 rcommand:
  * Redirectable commands.
  */
 rcommand:
-    PRINT exp_list
+    PRINT stopaliasing exp_list
 {
 {
-       $$ = build(O_PRINT, $2);
+       $$ = build(O_PRINT, $3);
 }
 |
     WHERE
 }
 |
     WHERE
@@ -491,9 +560,9 @@ rcommand:
        $$ = $1;
 }
 |
        $$ = $1;
 }
 |
-    CALL term '(' opt_exp_list ')'
+    CALL stopaliasing term '(' opt_exp_list ')'
 {
 {
-       $$ = build(O_CALL, $2, $4);
+       $$ = build(O_CALL, $3, $5);
 }
 |
     DEBUG INT
 }
 |
     DEBUG INT
@@ -512,39 +581,51 @@ rcommand:
 }
 ;
 alias_command:
 }
 ;
 alias_command:
-    ALIAS name name
+    alias name something
 {
 {
-       $$ = build(O_ALIAS, build(O_NAME, $2), build(O_NAME, $3));
+       $$ = build(O_ALIAS, build(O_NAME, $2), $3);
 }
 |
 }
 |
-    ALIAS name
+    alias name
 {
        $$ = build(O_ALIAS, build(O_NAME, $2), nil);
 }
 |
 {
        $$ = build(O_ALIAS, build(O_NAME, $2), nil);
 }
 |
-    ALIAS
+    alias
 {
        $$ = build(O_ALIAS, nil, nil);
 }
 ;
 {
        $$ = build(O_ALIAS, nil, nil);
 }
 ;
+
+alias:
+     ALIAS stopaliasing
+;
+
+stopaliasing:
+    /* empty */
+{
+       stopaliasing();
+}
+;
+
 trace:
 trace:
-    TRACE
+    TRACE stopaliasing
 {
        $$ = O_TRACE;
 }
 |
 {
        $$ = O_TRACE;
 }
 |
-    TRACEI
+    TRACEI stopaliasing
 {
        $$ = O_TRACEI;
 }
 ;
 stop:
 {
        $$ = O_TRACEI;
 }
 ;
 stop:
-    STOP
+    STOP stopaliasing
 {
        $$ = O_STOP;
 }
 |
 {
        $$ = O_STOP;
 }
 |
-    STOPI
+    STOPI stopaliasing
 {
        $$ = O_STOPI;
 }
 {
        $$ = O_STOPI;
 }
@@ -605,7 +686,7 @@ opt_exp_list:
 }
 ;
 list_command:
 }
 ;
 list_command:
-    LIST
+    list
 {
        $$ = build(O_LIST,
            build(O_LCON, (long) cursrcline),
 {
        $$ = build(O_LIST,
            build(O_LCON, (long) cursrcline),
@@ -613,32 +694,26 @@ list_command:
        );
 }
 |
        );
 }
 |
-    LIST line_number
+    list line_number
 {
        $$ = build(O_LIST, $2, $2);
 }
 |
 {
        $$ = build(O_LIST, $2, $2);
 }
 |
-    LIST line_number ',' line_number
+    list line_number ',' line_number
 {
        $$ = build(O_LIST, $2, $4);
 }
 |
 {
        $$ = build(O_LIST, $2, $4);
 }
 |
-    LIST opt_qual_symbol
+    list symbol
 {
 {
-       $$ = build(O_LIST, $2);
+       $$ = build(O_LIST, $2, nil);
 }
 ;
 }
 ;
-integer_list:
-    INT
-{
-       $$ = build(O_LCON, $1);
-}
-|
-    INT integer_list
-{
-       $$ = build(O_COMMA, build(O_LCON, $1), $2);
-}
+
+list:
+    LIST stopaliasing
 ;
 ;
+
 line_number:
     INT
 {
 line_number:
     INT
 {
@@ -982,3 +1057,20 @@ keyword:
     STOP | STOPI | TRACE | TRACEI | UP |
     USE | WHATIS | WHEN | WHERE | WHEREIS | WHICH
 ;
     STOP | STOPI | TRACE | TRACEI | UP |
     USE | WHATIS | WHEN | WHERE | WHEREIS | WHICH
 ;
+
+something:
+    NAME
+{
+       $$ = build(O_NAME, $1);
+}
+|
+    keyword
+{
+       $$ = build(O_NAME, $1);
+}
+|
+    STRING
+{
+       $$ = build(O_SCON, $1);
+}
+;
index 90a3c3e..27bd27c 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (c) 1982 Regents of the University of California */
 
 /* Copyright (c) 1982 Regents of the University of California */
 
-static char sccsid[] = "@(#)eval.c     1.12 (Berkeley) %G%";
+static char sccsid[] = "@(#)eval.c     1.13 (Berkeley) %G%";
 
 /*
  * Tree evaluation.
 
 /*
  * Tree evaluation.
@@ -457,7 +457,7 @@ register Node p;
            } else if (n2 == nil) {
                print_alias(n1->value.name);
            } else {
            } else if (n2 == nil) {
                print_alias(n1->value.name);
            } else {
-               enter_alias(n1->value.name, n2->value.name);
+               enter_alias(n1->value.name, n2);
            }
            break;
 
            }
            break;
 
index dec7f3e..bf67e14 100644 (file)
@@ -1,9 +1,9 @@
 /* Copyright (c) 1982 Regents of the University of California */
 
 /* Copyright (c) 1982 Regents of the University of California */
 
-static char sccsid[] = "@(#)keywords.c 1.4 (Berkeley) %G%";
+static char sccsid[] = "@(#)keywords.c 1.5 (Berkeley) %G%";
 
 /*
 
 /*
- * Keyword management.
+ * Keyword and alias management.
  */
 
 #include "defs.h"
  */
 
 #include "defs.h"
@@ -35,89 +35,102 @@ private String reserved[] ={
  * The keyword table is a traditional hash table with collisions
  * resolved by chaining.
  */
  * The keyword table is a traditional hash table with collisions
  * resolved by chaining.
  */
-
-#define HASHTABLESIZE 503
-
 typedef struct Keyword {
     Name name;
     Token toknum : 16;
 typedef struct Keyword {
     Name name;
     Token toknum : 16;
-    Boolean isalias : 16;
     struct Keyword *chain;
 } *Keyword;
 
 typedef unsigned int Hashvalue;
 
     struct Keyword *chain;
 } *Keyword;
 
 typedef unsigned int Hashvalue;
 
-private Keyword hashtab[HASHTABLESIZE];
+#define KEYWORDHASH    101
+private Keyword hashtab[KEYWORDHASH];
+#define keyhash(n) ((((unsigned) n) >> 2) mod KEYWORDHASH)
+
+/*
+ * The alias table is virtually the same, just
+ * replace the token id with a string to which
+ * the alias expands.
+ */
+typedef struct Alias {
+     Name name;
+     Name expansion;
+     struct Alias *chain;
+} *Alias;
 
 
-#define hash(n) ((((unsigned) n) >> 2) mod HASHTABLESIZE)
+#define        ALIASHASH       503
+private        Alias aliashashtab[ALIASHASH];
+#define aliashash(n) ((((unsigned) n) >> 2) mod ALIASHASH)
 
 /*
  * Enter all the reserved words into the keyword table.
  */
 
 /*
  * Enter all the reserved words into the keyword table.
  */
-
 public enterkeywords()
 {
     register Integer i;
 
 public enterkeywords()
 {
     register Integer i;
 
-    for (i = ALIAS; i <= WHICH; i++) {
-       keyword(reserved[ord(i) - ord(ALIAS)], i, false);
-    }
-    keyword("set", ASSIGN, false);
-    keyword("c", CONT, true);
-    keyword("d", DELETE, true);
-    keyword("h", HELP, true);
-    keyword("e", EDIT, true);
-    keyword("l", LIST, true);
-    keyword("n", NEXT, true);
-    keyword("p", PRINT, true);
-    keyword("q", QUIT, true);
-    keyword("r", RUN, true);
-    keyword("s", STEP, true);
-    keyword("st", STOP, true);
-    keyword("j", STATUS, true);
-    keyword("t", WHERE, true);
+    for (i = ALIAS; i <= WHICH; i++)
+       keyword(reserved[ord(i) - ord(ALIAS)], i);
+    keyword("set", ASSIGN);
+
+    alias(identname("c", true), identname(keywdstring(CONT), true));
+    alias(identname("d", true), identname(keywdstring(DELETE), true));
+    alias(identname("h", true), identname(keywdstring(HELP), true));
+    alias(identname("e", true), identname(keywdstring(EDIT), true));
+    alias(identname("l", true), identname(keywdstring(LIST), true));
+    alias(identname("n", true), identname(keywdstring(NEXT), true));
+    alias(identname("p", true), identname(keywdstring(PRINT), true));
+    alias(identname("q", true), identname(keywdstring(QUIT), true));
+    alias(identname("r", true), identname(keywdstring(RUN), true));
+    alias(identname("s", true), identname(keywdstring(STEP), true));
+    alias(identname("st", true), identname(keywdstring(STOP), true));
+    alias(identname("j", true), identname(keywdstring(STATUS), true));
+    alias(identname("t", true), identname(keywdstring(WHERE), true));
 }
 
 /*
 }
 
 /*
- * Deallocate the keyword table.
+ * Deallocate the keyword and alias tables.
  */
  */
-
 public keywords_free()
 {
     register Integer i;
     register Keyword k, nextk;
 public keywords_free()
 {
     register Integer i;
     register Keyword k, nextk;
+    register Alias a, nexta;
 
 
-    for (i = 0; i < HASHTABLESIZE; i++) {
-       k = hashtab[i];
-       while (k != nil) {
+    for (i = 0; i < KEYWORDHASH; i++) {
+       for (k = hashtab[i]; k != nil; k = nextk) {
            nextk = k->chain;
            dispose(k);
            nextk = k->chain;
            dispose(k);
-           k = nextk;
        }
        hashtab[i] = nil;
     }
        }
        hashtab[i] = nil;
     }
+    for (i = 0; i < ALIASHASH; i++) {
+       for (a = aliashashtab[i]; a != nil; a = nexta) {
+           nexta = a->chain;
+           dispose(a);
+       }
+       aliashashtab[i] = nil;
+    }
 }
 
 /*
 }
 
 /*
- * Enter a keyword into the name table.  It is assumed to not be there already.
+ * Enter a keyword into the name table. 
+ * It is assumed to not be there already.
  * The string is assumed to be statically allocated.
  */
  * The string is assumed to be statically allocated.
  */
-
-private keyword(s, t, isalias)
+private keyword(s, t)
 String s;
 Token t;
 String s;
 Token t;
-Boolean isalias;
 {
 {
-    register Hashvalue h;
     register Keyword k;
     register Keyword k;
+    Hashvalue h;
     Name n;
 
     n = identname(s, true);
     Name n;
 
     n = identname(s, true);
-    h = hash(n);
+    h = keyhash(n);
     k = new(Keyword);
     k->name = n;
     k->toknum = t;
     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;
 }
@@ -125,7 +138,6 @@ Boolean isalias;
 /*
  * Return the string associated with a token corresponding to a keyword.
  */
 /*
  * Return the string associated with a token corresponding to a keyword.
  */
-
 public String keywdstring(t)
 Token t;
 {
 public String keywdstring(t)
 Token t;
 {
@@ -133,95 +145,95 @@ Token t;
 }
 
 /*
 }
 
 /*
- * Find the keyword associated with the given string.
+ * Return the token associated with a given keyword string.
+ * We assume that tokens cannot legitimately be nil (0).
  */
 
  */
 
-private Keyword kwlookup (n)
+public Token findkeyword(n)
 Name n;
 {
 Name n;
 {
-    Hashvalue h;
     register Keyword k;
 
     register Keyword k;
 
-    h = hash(n);
-    k = hashtab[h];
-    while (k != nil and k->name != n) {
-       k = k->chain;
-    }
-    return k;
+    for (k = hashtab[keyhash(n)]; k != nil && k->name != n; k = k->chain)
+       ;
+    return (k == nil ? nil : k->toknum);
 }
 
 }
 
-/*
- * Return the token associated with a given keyword string.
- * We assume that tokens cannot legitimately be nil (0).
- */
-
-public Token findkeyword(n)
+public String findalias(n)
 Name n;
 {
 Name n;
 {
-    Keyword k;
-    Token t;
+    register Alias a;
 
 
-    k = kwlookup(n);
-    if (k == nil) {
-       t = nil;
-    } else {
-       t = k->toknum;
-    }
-    return t;
+    for (a = aliashashtab[aliashash(n)]; a != nil && a->name != n; a = a->chain)
+       ;
+    return (a == nil ? nil : ident(a->expansion));
 }
 
 /*
  * Create an alias.
  */
 }
 
 /*
  * Create an alias.
  */
-
-public enter_alias(newcmd, oldcmd)
-Name newcmd;
-Name oldcmd;
+public enter_alias(cmd, p)
+Name cmd;
+Node p;
 {
     Token t;
 {
     Token t;
-    Keyword k;
-
-    t = findkeyword(oldcmd);
-    if (t == nil) {
-       error("\"%s\" is not a command", ident(oldcmd));
-    } else {
-       k = kwlookup(newcmd);
-       if (k == nil) {
-           keyword(ident(newcmd), t, true);
-       } else {
-           k->toknum = t;
-       }
+    Name n;
+
+    t = findkeyword(cmd);
+    if (t != nil) {
+       error("\"%s\" can't redefine a command", ident(cmd));
+       return;
     }
     }
+    if (p->op == O_SCON)
+       n = identname(p->value.scon, true);
+    else
+       n = identname(ident(p->value.name), true);
+    alias(cmd, n);
+}
+
+private alias(cmd, n)
+Name cmd, n;
+{
+    register Alias a;
+    Hashvalue h;
+
+    h = aliashash(cmd);
+    for (a = aliashashtab[h]; a != nil && a->name != cmd; a = a->chain)
+       ;
+    if (a != nil) {
+       a->expansion = n;
+       return;
+    }
+    a = new(Alias);
+    a->name = cmd;
+    a->expansion = n;
+    a->chain = aliashashtab[h];
+    aliashashtab[h] = a;
 }
 
 /*
  * Print out an alias.
  */
 }
 
 /*
  * Print out an alias.
  */
-
 public print_alias(cmd)
 Name cmd;
 {
 public print_alias(cmd)
 Name cmd;
 {
-    register Keyword k;
+    register Alias a;
     register Integer i;
     register Integer i;
-    Token t;
+    String s;
 
 
-    if (cmd == nil) {
-       for (i = 0; i < HASHTABLESIZE; i++) {
-           for (k = hashtab[i]; k != nil; k = k->chain) {
-               if (k->isalias) {
-                   if (isredirected()) {
-                       printf("alias ");
-                   }
-                   printf("%s\t%s\n", ident(k->name), keywdstring(k->toknum));
-               }
-           }
-       }
-    } else {
-       t = findkeyword(cmd);
-       if (t == nil) {
-           printf("\n");
-       } else {
-           printf("%s\n", keywdstring(t));
+    if (cmd != nil) {
+       s = findalias(cmd);
+       printf(s == nil ? "\n" : "%s\n", s);
+       return;
+    }
+    /*
+     * Dump the alias table.
+     */
+    for (i = 0; i < ALIASHASH; i++) {
+       for (a = aliashashtab[i]; a != nil; a = a->chain) {
+           if (isredirected())
+               printf("alias ");
+           printf("%s\t%s\n", ident(a->name), ident(a->expansion));
        }
     }
 }
        }
     }
 }
index 250c83c..b687fe0 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (c) 1982 Regents of the University of California */
 
 /* Copyright (c) 1982 Regents of the University of California */
 
-static char sccsid[] = "@(#)operators.c        1.6 (Berkeley) %G%";
+static char sccsid[] = "@(#)operators.c        1.7 (Berkeley) %G%";
 
 /*
  * Tree node classes.
 
 /*
  * Tree node classes.
@@ -158,7 +158,7 @@ public Opinfo opinfo[] ={
 /* O_ALIAS */          2,      null,           "alias",
 /* O_ASSIGN */         2,      BINARY,         " := ",
 /* O_CALL */           2,      null,           "call",
 /* O_ALIAS */          2,      null,           "alias",
 /* O_ASSIGN */         2,      BINARY,         " := ",
 /* O_CALL */           2,      null,           "call",
-/* O_CATCH */          0,      null,           "catch",
+/* O_CATCH */          1,      null,           "catch",
 /* O_CHFILE */         0,      null,           "file",
 /* O_CONT */           0,      null,           "cont",
 /* O_DEBUG */          0,      null,           "debug",
 /* O_CHFILE */         0,      null,           "file",
 /* O_CONT */           0,      null,           "cont",
 /* O_DEBUG */          0,      null,           "debug",
@@ -168,7 +168,7 @@ public Opinfo opinfo[] ={
 /* O_FUNC */           1,      null,           "func",
 /* O_GRIPE */          0,      null,           "gripe",
 /* O_HELP */           0,      null,           "help",
 /* O_FUNC */           1,      null,           "func",
 /* O_GRIPE */          0,      null,           "gripe",
 /* O_HELP */           0,      null,           "help",
-/* O_IGNORE */         0,      null,           "ignore",
+/* O_IGNORE */         1,      null,           "ignore",
 /* O_LIST */           2,      null,           "list",
 /* O_PRINT */          1,      null,           "print",
 /* O_PSYM */           1,      null,           "psym",
 /* O_LIST */           2,      null,           "list",
 /* O_PRINT */          1,      null,           "print",
 /* O_PSYM */           1,      null,           "psym",
index 04100b5..32c957f 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (c) 1982 Regents of the University of California */
 
 /* Copyright (c) 1982 Regents of the University of California */
 
-static char sccsid[] = "@(#)process.c  1.13 (Berkeley) %G%";
+static char sccsid[] = "@(#)process.c  1.14 (Berkeley) %G%";
 
 /*
  * Process management.
 
 /*
  * Process management.
@@ -1280,3 +1280,94 @@ Fileid newfd;
        close(newfd);
     }
 }
        close(newfd);
     }
 }
+
+#define        bit(i)          (1 << ((i)-1))
+/*
+ * Signal manipulation routines.
+ */
+static String signames[NSIG] = {
+       0,
+       "HUP",
+       "INT",
+       "QUIT",
+       "ILL",
+       "TRAP",
+       "IOT",
+       "EMT",
+       "FPE",
+       "KILL",
+       "BUS",
+       "SEGV",
+       "SYS",
+       "PIPE",
+       "ALRM",
+       "TERM",
+       0,
+       "STOP",
+       "TSTP",
+       "CONT",
+       "CHLD",
+       "TTIN",
+       "TTOU",
+       "TINT",
+       "XCPU",
+       "XFSZ",
+};
+
+/*
+ * Map a signal name to a number.
+ */
+public signalname(s)
+String s;
+{
+       register String *p;
+
+       for (p = signames; p < &signames[NSIG]; p++)
+               if (*p && streq(*p, s))
+                       return (p - signames);
+       error("%s: Unknown signal.", s);
+}
+
+/*
+ * Print all signals being ignored by the
+ * debugger.  These signals are auotmatically
+ * passed on to the debugged process.
+ */
+public printsigsignored(vec)
+long vec;
+{
+       register Integer s;
+       String sep = "";
+
+       for (s = 1; s < NSIG; s++)
+               if ((vec & bit(s)) && signames[s]) {
+                       printf("%s%s", sep, signames[s]);
+                       sep = " ";
+               }
+       if (*sep != '\0') {
+               putchar('\n');
+               fflush(stdout);
+       }
+}
+
+/*
+ * Print all signals being intercepted by
+ * the debugger for the specified process.
+ */
+public printsigscaught(vec)
+long vec;
+{
+       register Integer s;
+       String sep = "";
+
+       for (s = 1; s < NSIG; s++)
+               if ((vec & bit(s)) == 0 && signames[s]) {
+                       printf("%s%s", sep, signames[s]);
+                       sep = " ";
+               }
+       if (*sep != '\0') {
+               putchar('\n');
+               fflush(stdout);
+       }
+}
+
index 6e66ba9..5aacce1 100644 (file)
@@ -1,11 +1,12 @@
 /* Copyright (c) 1982 Regents of the University of California */
 
 /* Copyright (c) 1982 Regents of the University of California */
 
-static char sccsid[] = "@(#)scanner.c  1.9 (Berkeley) %G%";
+static char sccsid[] = "@(#)scanner.c  1.10 (Berkeley) %G%";
 
 /*
  * Debugger scanner.
  */
 
 
 /*
  * Debugger scanner.
  */
 
+#include <ctype.h>
 #include "defs.h"
 #include "scanner.h"
 #include "main.h"
 #include "defs.h"
 #include "scanner.h"
 #include "main.h"
@@ -19,620 +20,624 @@ static    char sccsid[] = "@(#)scanner.c  1.9 (Berkeley) %G%";
 typedef int Token;
 #endif
 
 typedef int Token;
 #endif
 
-public String initfile = ".dbxinit";
-
-typedef enum { WHITE, ALPHA, NUM, OTHER } Charclass;
-
-private Charclass class[256 + 1];
-private Charclass *lexclass = class + 1;
-
-#define isdigit(c) (lexclass[c] == NUM)
-#define isalnum(c) (lexclass[c] == ALPHA or lexclass[c] == NUM)
-#define ishexdigit(c) ( \
-    isdigit(c) or (c >= 'a' and c <= 'f') or (c >= 'A' and c <= 'F') \
-)
-
-#define MAXLINESIZE 1024
+typedef struct {
+       int     s_type;
+#define        ST_FILE         0
+#define        ST_ALIAS        1
+       char    *s_name;
+       int     s_lineno;
+       union {
+               File    su_file;
+               struct sum {
+                       char    *sum_data;
+                       char    *sum_cur;
+               } su_macro;
+       } su;
+#define        s_file  su.su_file
+#define        s_macro su.su_macro
+#define        s_data  s_macro.sum_data
+#define        s_cur   s_macro.sum_cur
+} STREAM;
+
+#define        NSTREAMS        10
+private        STREAM stack[NSTREAMS];
+private        STREAM *sp = &stack[-1];
 
 
-private File in;
-private Char linebuf[MAXLINESIZE];
-private Char *curchar, *prevchar;
-
-#define MAXINCLDEPTH 10
-
-private struct {
-    File savefile;
-    Filename savefn;
-    int savelineno;
-} inclinfo[MAXINCLDEPTH];
-
-private unsigned int curinclindex;
+public String initfile = ".dbxinit";
 
 private Token getident();
 private Token getnum();
 private Token getstring();
 
 private Token getident();
 private Token getnum();
 private Token getstring();
-private Boolean eofinput();
 private Char charcon();
 private Char charcon();
-private Char charlookup();
-
-private enterlexclass(class, s)
-Charclass class;
-String s;
-{
-    register char *p;
 
 
-    for (p = s; *p != '\0'; p++) {
-       lexclass[*p] = class;
-    }
-}
+#define MAXLINESIZE 1024
+private Char yytext[MAXLINESIZE];
+private Boolean shellmode;
+private        Boolean doaliases;
 
 public scanner_init()
 {
 
 public scanner_init()
 {
-    register Integer i;
-
-    for (i = 0; i < 257; i++) {
-       class[i] = OTHER;
-    }
-    enterlexclass(WHITE, " \t");
-    enterlexclass(ALPHA, "abcdefghijklmnopqrstuvwxyz");
-    enterlexclass(ALPHA, "ABCDEFGHIJKLMNOPQRSTUVWXYZ_$");
-    enterlexclass(NUM, "0123456789");
-    in = stdin;
-    errfilename = nil;
-    errlineno = 0;
-    curchar = linebuf;
-    linebuf[0] = '\0';
+       register Integer i;
+
+       if (sp < stack)
+               (void) pushinput(ST_FILE, nil, stdin);
+       shellmode = false;
+       doaliases = true;
+       errfilename = nil;
+       errlineno = sp->s_lineno = 0;
+       yytext[0] = '\0';
 }
 
 }
 
+#define        MAXDEPTH        25
 /*
  * Read a single token.
 /*
  * Read a single token.
- *
- * Input is line buffered.
- *
  * There are two "modes" of operation:  one as in a compiler,
  * and one for reading shell-like syntax.
  */
  * There are two "modes" of operation:  one as in a compiler,
  * and one for reading shell-like syntax.
  */
-
-private Boolean shellmode;
-
 public Token yylex()
 {
 public Token yylex()
 {
-    register int c;
-    register char *p;
-    register Token t;
-    String line;
-
-    p = curchar;
-    if (*p == '\0') {
-       do {
-           if (isterm(in)) {
-               printf("(%s) ", cmdname);
-               fflush(stdout);
-           }
-           line = fgets(linebuf, MAXLINESIZE, in);
-       } while (line == nil and not eofinput());
-       if (line == nil) {
-           c = EOF;
-       } else {
-           p = linebuf;
-           while (lexclass[*p] == WHITE) {
-               p++;
-           }
-           shellmode = false;
+       register int c;
+       register char *p;
+       register Token t;
+       static int depth = 0;
+
+       depth++;
+       if (depth > MAXDEPTH) {
+           depth = 0;
+           error("Alias loop (maximum %d deep).\n", MAXDEPTH);
        }
        }
-    } else {
-       while (lexclass[*p] == WHITE) {
-           p++;
+again:
+       do
+               c = getch();
+       while (c == ' ' || c == '\t');
+       if (isalpha(c) || c == '_' || c == '$') {
+               t = getident(c);
+               if (t == NAME && doaliases) {
+                       p = findalias(yylval.y_name);
+                       if (p != nil) {
+                               if (lexdebug)
+                                       fprintf(stderr, "alias %s to \"%s\"\n",
+                                           ident(yylval.y_name), p);
+                               if (!pushinput(ST_ALIAS, "", p)) {
+                                       unwindinput(ST_ALIAS);
+                                       error("Alias stack overflow.");
+                               }
+                               t = yylex();
+                       }
+               }
+               goto done;
        }
        }
-    }
-    curchar = p;
-    prevchar = curchar;
-    c = *p;
-    if (lexclass[c] == ALPHA) {
-       t = getident();
-    } else if (lexclass[c] == NUM) {
-       if (shellmode) {
-           t = getident();
-       } else {
-           t = getnum();
+       if (isdigit(c)) {
+               t = shellmode ? getident(c) : getnum(c);
+               goto done;
        }
        }
-    } else {
-       ++curchar;
        switch (c) {
        switch (c) {
-           case '\n':
+
+       case '\n':
                t = '\n';
                t = '\n';
-               if (errlineno != 0) {
-                   errlineno++;
+               if (sp->s_lineno != 0) {
+                       sp->s_lineno++;
+                       if (sp->s_type == ST_FILE)
+                               errlineno = sp->s_lineno;
                }
                break;
 
                }
                break;
 
-           case '"':
-           case '\'':
-               t = getstring();
+       case '"':
+       case '\'':
+               t = getstring(c);
                break;
 
                break;
 
-           case '.':
+       case '.':
                if (shellmode) {
                if (shellmode) {
-                   --curchar;
-                   t = getident();
-               } else if (isdigit(*curchar)) {
-                   --curchar;
-                   t = getnum();
-               } else {
-                   t = '.';
+                       t = getident(c);
+                       break;
                }
                }
+               c = getch();
+               ungetch(c);
+               t = isdigit(c) ? getnum('.') : '.';
                break;
 
                break;
 
-           case '<':
-               if (not shellmode and *curchar == '<') {
-                   ++curchar;
-                   t = LFORMER;
-               } else {
-                   t = '<';
-               }
+       case '<':
+               c = getch();
+               if (shellmode || c != '<') {
+                       ungetch(c);
+                       t = '<';
+               } else
+                       t = LFORMER;
                break;
 
                break;
 
-           case '>':
-               if (not shellmode and *curchar == '>') {
-                   ++curchar;
-                   t = RFORMER;
-               } else {
-                   t = '>';
-               }
+       case '>':
+               c = getch();
+               if (shellmode || c != '>') {
+                       ungetch(c);
+                       t = '>';
+               } else
+                       t = RFORMER;
                break;
 
                break;
 
-           case '#':
-               if (*curchar == '^') {
-                   ++curchar;
-                   t = ABSTRACTION;
-               } else {
-                   t = '#';
-               }
+       case '#':
+               c = getch();
+               if (c != '^') {
+                       ungetch(c);
+                       t = '#';
+               } else
+                       t = ABSTRACTION;
                break;
 
                break;
 
-           case '-':
+       case '-':
                if (shellmode) {
                if (shellmode) {
-                   --curchar;
-                   t = getident();
-               } else if (*curchar == '>') {
-                   ++curchar;
-                   t = ARROW;
-               } else {
-                   t = '-';
+                       t = getident(c);
+                       break;
                }
                }
+               c = getch();
+               if (c != '>') {
+                       ungetch(c);
+                       t = '-';
+               } else
+                       t = ARROW;
                break;
 
                break;
 
-           case EOF:
+       case EOF:
                t = 0;
                break;
 
                t = 0;
                break;
 
-           default:
-               if (shellmode and index("!&*()[]", c) == nil) {
-                   --curchar;
-                   t = getident();
-               } else {
-                   t = c;
-               }
+       default:
+               t = shellmode && index("!&*()[];", c) == nil ?
+                   getident(c) : c;
                break;
        }
                break;
        }
-    }
-#   ifdef LEXDEBUG
+done:
        if (lexdebug) {
        if (lexdebug) {
-           fprintf(stderr, "yylex returns ");
-           print_token(stderr, t);
-           fprintf(stderr, "\n");
+               fprintf(stderr, "token ");
+               print_token(stderr, t);
+               fprintf(stderr, "\n");
        }
        }
-#   endif
-    return t;
+       depth--;
+       return (t);
 }
 
 /*
 }
 
 /*
- * Parser error handling.
+ * Scan an identifier and check to see if it's a keyword.
  */
  */
-
-public yyerror(s)
-String s;
+private Token getident(c)
+Char c;
 {
 {
-    register char *p;
-    register integer start;
-
-    if (streq(s, "syntax error")) {
-       beginerrmsg();
-       p = prevchar;
-       start = p - &linebuf[0];
-       if (p > &linebuf[0]) {
-           while (lexclass[*p] == WHITE and p > &linebuf[0]) {
-               --p;
-           }
-       }
-       fprintf(stderr, "%s", linebuf);
-       if (start != 0) {
-           fprintf(stderr, "%*c", start, ' ');
-       }
-       if (p == &linebuf[0]) {
-           fprintf(stderr, "^ unrecognized command");
+       register Char *p, *q;
+       Token t;
+
+       q = yytext;
+       if (shellmode) {
+               do {
+                       *q++ = c;
+                       c = getch();
+               } while (index(" \t\n!&<>*[]();", c) == nil);
        } else {
        } else {
-           fprintf(stderr, "^ syntax error");
+               do {
+                       *q++ = c;
+                       c = getch();
+               } while (isalnum(c) || c == '_' || c == '$');
        }
        }
-       enderrmsg();
-    } else {
-       error(s);
-    }
-}
-
-/*
- * Eat the current line.
- */
-
-public gobble()
-{
-    curchar = linebuf;
-    linebuf[0] = '\0';
-}
-
-/*
- * Scan an identifier and check to see if it's a keyword.
- */
-
-private Token getident()
-{
-    char buf[256];
-    register Char *p, *q;
-    register Token t;
-
-    p = curchar;
-    q = buf;
-    if (shellmode) {
-       do {
-           *q++ = *p++;
-       } while (index(" \t\n!&<>*[]()'\"", *p) == nil);
-    } else {
-       do {
-           *q++ = *p++;
-       } while (isalnum(*p));
-    }
-    curchar = p;
-    *q = '\0';
-    yylval.y_name = identname(buf, false);
-    if (not shellmode) {
+       ungetch(c);
+       *q = '\0';
+       yylval.y_name = identname(yytext, false);
+       if (shellmode)
+               return (NAME);
        t = findkeyword(yylval.y_name);
        t = findkeyword(yylval.y_name);
-       if (t == nil) {
-           t = NAME;
-       }
-    } else {
-       t = NAME;
-    }
-    return t;
+       return (t == nil ? NAME : t);
 }
 
 /*
  * Scan a number.
  */
 }
 
 /*
  * Scan a number.
  */
-
-private Token getnum()
+private Token getnum(c)
+Char c;
 {
 {
-    char buf[256];
-    register Char *p, *q;
-    register Token t;
-    Integer base;
-
-    p = curchar;
-    q = buf;
-    if (*p == '0') {
-       if (*(p+1) == 'x') {
-           p += 2;
-           base = 16;
+       register Char *q;
+       register Token t;
+       Integer base = 10;
+
+       q = yytext;
+       if (c == '0') {
+               c = getch();
+               if (c == 'x') {
+                       base = 16;
+               } else {
+                       base = 8;
+                       ungetch(c);
+                       c = '0';
+               }
+       }
+       if (base == 16) {
+               while (isdigit(c = getch()) ||
+                   (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
+                       *q++ = c;
        } else {
        } else {
-           base = 8;
+               do {
+                       *q++ = c;
+                       c = getch();
+               } while (isdigit(c));
        }
        }
-    } else {
-       base = 10;
-    }
-    if (base == 16) {
-       do {
-           *q++ = *p++;
-       } while (ishexdigit(*p));
-    } else {
-       do {
-           *q++ = *p++;
-       } while (isdigit(*p));
-    }
-    if (*p == '.') {
-       do {
-           *q++ = *p++;
-       } while (isdigit(*p));
-       if (*p == 'e' or *p == 'E') {
-           p++;
-           if (*p == '+' or *p == '-' or isdigit(*p)) {
-               *q++ = 'e';
+       if (c == '.') {
                do {
                do {
-                   *q++ = *p++;
-               } while (isdigit(*p));
-           }
+                       *q++ = c;
+                       c = getch();
+               } while (isdigit(c));
+               if (c == 'e' || c == 'E') {
+                       c = getch();
+                       if (c == '+' || c == '-' || isdigit(c)) {
+                               *q++ = 'e';
+                               do {
+                                       *q++ = c;
+                                       c = getch();
+                               } while (isdigit(c));
+                       }
+               }
+               ungetch(c);
+               *q = '\0';
+               yylval.y_real = atof(yytext);
+               return (REAL);
        }
        }
-       *q = '\0';
-       yylval.y_real = atof(buf);
-       t = REAL;
-    } else {
+       ungetch(c);
        *q = '\0';
        switch (base) {
        *q = '\0';
        switch (base) {
-           case 10:
-               yylval.y_int = atol(buf);
+
+       case 10:
+               yylval.y_int = atol(yytext);
                break;
 
                break;
 
-           case 8:
-               yylval.y_int = octal(buf);
+       case 8:
+               yylval.y_int = octal(yytext);
                break;
 
                break;
 
-           case 16:
-               yylval.y_int = hex(buf);
+       case 16:
+               yylval.y_int = hex(yytext);
                break;
 
                break;
 
-           default:
+       default:
                badcaseval(base);
        }
                badcaseval(base);
        }
-       t = INT;
-    }
-    curchar = p;
-    return t;
+       return (INT);
 }
 
 /*
  * Convert a string of octal digits to an integer.
  */
 }
 
 /*
  * Convert a string of octal digits to an integer.
  */
-
 private int octal(s)
 String s;
 {
 private int octal(s)
 String s;
 {
-    register Char *p;
-    register Integer n;
-
-    n = 0;
-    for (p = s; *p != '\0'; p++) {
-       n = 8*n + (*p - '0');
-    }
-    return n;
+       register Char *p;
+       register Integer n;
+
+       n = 0;
+       for (p = s; *p != '\0'; p++)
+               n = (n << 3) + (*p - '0');
+       return (n);
 }
 
 /*
  * Convert a string of hexadecimal digits to an integer.
  */
 }
 
 /*
  * Convert a string of hexadecimal digits to an integer.
  */
-
 private int hex(s)
 String s;
 {
 private int hex(s)
 String s;
 {
-    register Char *p;
-    register Integer n;
-
-    n = 0;
-    for (p = s; *p != '\0'; p++) {
-       n *= 16;
-       if (*p >= 'a' and *p <= 'f') {
-           n += (*p - 'a' + 10);
-       } else if (*p >= 'A' and *p <= 'F') {
-           n += (*p - 'A' + 10);
-       } else {
-           n += (*p - '0');
+       register Char *p;
+       register Integer n;
+
+       n = 0;
+       for (p = s; *p != '\0'; p++) {
+               n <<= 4;
+               if (*p >= 'a' && *p <= 'f')
+                       n += (*p - 'a' + 10);
+               else if (*p >= 'A' && *p <= 'F')
+                       n += (*p - 'A' + 10);
+               else
+                       n += (*p - '0');
        }
        }
-    }
-    return n;
+       return (n);
 }
 
 /*
  * Scan a string.
  */
 }
 
 /*
  * Scan a string.
  */
-
-private Token getstring()
+private Token getstring(match)
+Char match;
 {
 {
-    char buf[256];
-    register Char *p, *q;
-    Boolean endofstring;
-
-    p = curchar;
-    q = buf;
-    endofstring = false;
-    while (not endofstring) {
-       if (*p == '\n' or *p == '\0') {
-           error("non-terminated string");
-           endofstring = true;
-       } else if (*p == '"' or *p == '\'') {
-           if (*(p+1) != *p) {
-               endofstring = true;
-           } else {
-               *q++ = *p;
-           }
-       } else {
-           curchar = p;
-           *q++ = charcon(p);
-           p = curchar;
+       register Char *q, c;
+
+       q = yytext;
+       for (;;) {
+               c = getch();
+               if (c == '\n' || c == EOF) {
+                       error("Unterminated string.");
+                       break;
+               }
+               if (c == match)
+                       break;
+               *q++ = charcon(c);
        }
        }
-       p++;
-    }
-    curchar = p;
-    *q = '\0';
-    yylval.y_string = strdup(buf);
-    return STRING;
+       *q = '\0';
+       yylval.y_string = strdup(yytext);
+       return (STRING);
 }
 
 /*
  * Process a character constant.
  * Watch out for backslashes.
  */
 }
 
 /*
  * Process a character constant.
  * Watch out for backslashes.
  */
-
-private Char charcon(p)
-char *p;
+private Char charcon(c)
+Char c;
 {
 {
-    char c, buf[10], *q;
-
-    if (*p == '\\') {
-       ++p;
-       if (*p != '\\') {
-           q = buf;
-           do {
-               *q++ = *p++;
-           } while (*p != '\\' and *p != '\'' and *p != '\n' and *p != '\0');
-           *q = '\0';
-           if (isdigit(buf[0])) {
-               c = (Char) octal(buf);
-           } else {
-               c = charlookup(buf);
-           }
-           curchar = p - 1;
-       } else {
-           c = '\\';
+       register char *cp;
+
+       if (c == '\\') {
+               c = getch();
+               if (isdigit(c)) {
+                       int v;
+
+                       v = 0;
+                       do {
+                               v = (v << 3) + (c - '0');
+                               c = getch();
+                       } while (isdigit(c));
+                       ungetch(c);
+                       return (v);
+               }
+               for (cp = "f\ft\tb\bn\nr\rv\v"; *cp != c; cp += 2)
+                       ;
+               if (*cp != '\0')
+                       c = *cp;
        }
        }
-    } else {
-       c = *p;
-    }
-    return c;
+       return (c);
 }
 
 /*
 }
 
 /*
- * Do a lookup for a ASCII character name.
+ * Parser error handling.
  */
  */
-
-private String ascii[] = {
-    "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
-    "BS",  "HT",  "NL",  "VT",  "NP",  "CR",  "SO",  "SI",
-    "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
-    "CAN", "EM",  "SUB", "ESC", "FS",  "GS",  "RS",  "US",
-    "SP", nil
-};
-
-private char charlookup(s)
+public yyerror(s)
 String s;
 {
 String s;
 {
-    register int i;
 
 
-    for (i = 0; ascii[i] != NULL; i++) {
-       if (streq(s, ascii[i])) {
-           return i;
+       if (streq(s, "syntax error")) {
+               beginerrmsg();
+               fprintf(stderr, "Syntax error");
+               if (yytext[0] != '\0')
+                       fprintf(stderr, " on \"%s\".", yytext);
+               enderrmsg();
+               return;
        }
        }
-    }
-    if (streq(s, "DEL")) {
-       return 0177;
-    }
-    error("unknown ascii name \"%s\"", s);
-    return '?';
+       error(s);
 }
 
 /*
 }
 
 /*
- * Input file management routines.
+ * Eat the current line.
  */
  */
+private Char lastc = '\0';
+
+public gobble()
+{
+       register char c;
+
+       if (lastc != '\n' && lastc != EOF)
+               while ((c = getch()) != EOF && c != '\n')
+                       ;
+}
 
 
+/*
+ * Input file management routines.
+ */
 public setinput(filename)
 Filename filename;
 {
 public setinput(filename)
 Filename filename;
 {
-    File f;
-
-    f = fopen(filename, "r");
-    if (f == nil) {
-       error("can't open %s", filename);
-    } else {
-       if (curinclindex >= MAXINCLDEPTH) {
-           error("unreasonable input nesting on \"%s\"", filename);
+       File f;
+
+       f = fopen(filename, "r");
+       if (f == nil)
+               error("%s: Can't open.", filename);
+       if (!pushinput(ST_FILE, filename, f)) {
+               unwindinput(ST_FILE);
+               error("Source file nesting too deep.");
        }
        }
-       inclinfo[curinclindex].savefile = in;
-       inclinfo[curinclindex].savefn = errfilename;
-       inclinfo[curinclindex].savelineno = errlineno;
-       curinclindex++;
-       in = f;
-       errfilename = filename;
-       errlineno = 1;
-    }
 }
 
 }
 
-private Boolean eofinput()
+/*
+ * Send the current line to the shell.
+ */
+public shellline()
 {
 {
-    register Boolean b;
+       register Char *p, c;
 
 
-    if (curinclindex == 0) {
-       if (isterm(in)) {
-           putchar('\n');
-           clearerr(in);
-           b = false;
-       } else {
-           b = true;
-       }
-    } else {
-       fclose(in);
-       --curinclindex;
-       in = inclinfo[curinclindex].savefile;
-       errfilename = inclinfo[curinclindex].savefn;
-       errlineno = inclinfo[curinclindex].savelineno;
-       b = false;
-    }
-    return b;
+       for (p = yytext; (c = getch()) != EOF && c != '\n'; *p++ = c)
+               ;
+       *p = '\0';
+       shell(yytext);
+       erecover();
 }
 
 /*
 }
 
 /*
- * Pop the current input.  Return whether successful.
+ * Read the rest of the current line in "shell mode".
  */
  */
+public beginshellmode()
+{
+
+       shellmode = true;
+}
+
+public endshellmode()
+{
 
 
-public Boolean popinput()
+       shellmode = false;
+}
+
+public stopaliasing()
 {
 {
-    Boolean b;
-
-    if (curinclindex == 0) {
-       b = false;
-    } else {
-       b = (Boolean) (not eofinput());
-    }
-    return b;
+
+       doaliases = false;
+}
+
+public startaliasing()
+{
+
+       doaliases = true;
 }
 
 /*
 }
 
 /*
- * Return whether we are currently reading from standard input.
+ * Print out a token for debugging.
  */
  */
+public print_token(f, t)
+File f;
+Token t;
+{
 
 
-public Boolean isstdin()
+       switch (t) {
+
+       case '\n':
+               fprintf(f, "char '\\n'");
+               return;
+
+       case EOF:
+               fprintf(f, "EOF");
+               return;
+
+       case NAME:
+       case STRING:
+               fprintf(f, "%s, \"%s\"", keywdstring(t), ident(yylval.y_name));
+               return;
+       }
+       if (t < 256)
+               fprintf(f, "char '%c'", t);
+       else
+               fprintf(f, "%s", keywdstring(t));
+}
+
+public int getch()
 {
 {
-    return (Boolean) (in == stdin);
+       int c;
+
+again:
+       switch (sp->s_type) {
+
+       case ST_FILE:
+               c = getc(sp->s_file);
+               if (c == EOF && isterm(sp->s_file)) {
+                       clearerr(sp->s_file);
+                       putchar('\n');
+                       c = '\n';
+               }
+               break;
+
+       case ST_ALIAS:
+               c = *sp->s_cur++;
+               if (c == '\0') {
+                       c = EOF;
+                       --sp->s_cur;
+               }
+               break;
+
+       default:
+               panic("Invalid input stream (type %d) to getch.",
+                   sp->s_type);
+       }
+       if (c == EOF && popinput())
+               goto again;
+       return (lastc = c);
+}
+
+private int ungetch(c)
+Char c;
+{
+       Char uc;
+
+       if (c != EOF) switch (sp->s_type) {
+
+       case ST_FILE:
+               uc = ungetc(c, sp->s_file);
+               break;
+
+       case ST_ALIAS:
+               if (sp->s_cur == sp->s_data)
+                       panic("Illegal ungetch on alias.");
+               *--sp->s_cur = c;
+               uc = c;
+               break;
+
+       default:
+               panic("Invalid input stream (type %d) to ungetch.",
+                   sp->s_type);
+       }
+       lastc = '\0';
+       return (uc);
 }
 
 /*
 }
 
 /*
- * Send the current line to the shell.
+ * Push the current input stream and
+ * make the supplied stream the current.
  */
  */
+/*VARARGS3*/
+public pushinput(type, name, info)
+int type;
+Filename name;
+{
 
 
-public shellline()
+       if (sp >= &stack[NSTREAMS])
+               return (0);
+       ++sp;
+       sp->s_type = type;
+       switch (type) {
+
+       case ST_FILE:
+               sp->s_file = (File)info;
+               errfilename = sp->s_name = name;
+               errlineno = sp->s_lineno = 1;
+               break;
+
+       case ST_ALIAS:
+               sp->s_cur = sp->s_data = (char *)info;
+               break;
+
+       default:
+               panic("Invalid input stream (type %d) to pushinput.", type);
+       }
+       return (1);
+}
+
+public popinput()
 {
 {
-    register char *p;
-
-    p = curchar;
-    while (*p != '\0' and (*p == '\n' or lexclass[*p] == WHITE)) {
-       ++p;
-    }
-    shell(p);
-    if (*p == '\0' and isterm(in)) {
-       putchar('\n');
-    }
-    erecover();
+
+       if (sp <= &stack[0])            /* never pop stdin or equivalent */
+               return (0);
+       if (sp->s_type == ST_FILE && sp->s_file != stdin)
+               fclose(sp->s_file);
+       --sp;
+       if (sp->s_type == ST_FILE)
+               errfilename = sp->s_name;
+       errlineno = sp->s_lineno;
+       return (1);
 }
 
 /*
 }
 
 /*
- * Read the rest of the current line in "shell mode".
+ * Unwind the input stack of all input types specified.
+ * This is called to recover from an infinite
+ * loop in alias processing or source file including.
  */
  */
-
-public beginshellmode()
+public unwindinput(type)
+Integer type;
 {
 {
-    shellmode = true;
+
+       while (sp->s_type == type && popinput())
+               ;
 }
 
 /*
 }
 
 /*
- * Print out a token for debugging.
+ * Return whether we are currently reading from standard input.
  */
  */
+public Boolean isstdin()
+{
 
 
-public print_token(f, t)
-File f;
-Token t;
+       return ((Boolean)(sp->s_type == ST_FILE && sp->s_file == stdin));
+}
+
+public Boolean istty()
 {
 {
-    if (t == '\n') {
-       fprintf(f, "char '\\n'");
-    } else if (t == EOF) {
-       fprintf(f, "EOF");
-    } else if (t < 256) {
-       fprintf(f, "char '%c'", t);
-    } else {
-       fprintf(f, "\"%s\"", keywdstring(t));
-    }
+
+       return ((Boolean)isterm(sp->s_file));
 }
 }