aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/rc
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2020-06-19 14:44:54 -0700
committerNicholas Noll <nbnoll@eml.cc>2020-06-19 14:44:54 -0700
commit91c673b37782d4cd90e5cf9a8e4491723e6c04bf (patch)
tree0c334edf4729283b08cd95ae577f890b089f26fc /sys/cmd/rc
parent765ff8b3423599396d0aa33885e2495ad86dbb19 (diff)
fix: many small bug fixes with parser and lexer
Diffstat (limited to 'sys/cmd/rc')
-rw-r--r--sys/cmd/rc/code.c52
-rw-r--r--sys/cmd/rc/io.c80
-rw-r--r--sys/cmd/rc/lex.c48
-rw-r--r--sys/cmd/rc/main.c4
-rw-r--r--sys/cmd/rc/parse.c226
-rw-r--r--sys/cmd/rc/rc.h23
-rw-r--r--sys/cmd/rc/tree.c10
-rw-r--r--sys/cmd/rc/var.c16
8 files changed, 267 insertions, 192 deletions
diff --git a/sys/cmd/rc/code.c b/sys/cmd/rc/code.c
index f38dd43..9aa1037 100644
--- a/sys/cmd/rc/code.c
+++ b/sys/cmd/rc/code.c
@@ -36,7 +36,7 @@ stuffdot(Code *p)
a = p - code.buf;
if (code.ip <= p || p < code.buf)
panic("bad address %d in stuffdot", a);
- codebuf[a].i = code.ip-code.buf;
+ code.buf[a].i = code.ip-code.buf;
}
static
@@ -63,7 +63,7 @@ rcc(Tree *t, int eflag)
rcc(c0, eflag);
emitf(Xqdol);
break;
- case Asub:
+ case Tsub:
emitf(Xmark);
rcc(c0, eflag);
emitf(Xmark);
@@ -101,31 +101,31 @@ rcc(Tree *t, int eflag)
} else
emits(fnstr(c0));
break;
- case Aandand:
+ case Tandand:
rcc(c0, 0);
emitf(Xtrue);
p = emiti(0);
rcc(c1, eflag);
stuffdot(p);
break;
- case Aargs:
+ case Targs:
rcc(c1, eflag);
rcc(c0, eflag);
break;
- case Kbang:
+ case Tbang:
rcc(c0, eflag);
emitf(Xbang);
break;
- case Aparen:
- case Abrace:
+ case Tparen:
+ case Tbrace:
rcc(c0, eflag);
break;
- case Acount:
+ case Tcount:
emitf(Xmark);
rcc(c0, eflag);
emitf(Xcount);
break;
- case Kfunc:
+ case Tfunc:
emitf(Xmark);
rcc(c0, eflag);
if(c1){
@@ -140,7 +140,7 @@ rcc(Tree *t, int eflag)
else
emitf(Xdelfn);
break;
- case Kif:
+ case Tif:
rcc(c0, 0);
emitf(Xif);
p = emiti(0);
@@ -148,7 +148,7 @@ rcc(Tree *t, int eflag)
emitf(Xwastrue);
stuffdot(p);
break;
- case Kelse:
+ case Telse:
if(!runq->iflast)
error("`else' does not follow `if(...)'");
emitf(Xelse);
@@ -156,24 +156,24 @@ rcc(Tree *t, int eflag)
rcc(c0, eflag);
stuffdot(p);
break;
- case Aoror:
+ case Toror:
rcc(c0, 0);
emitf(Xfalse);
p = emiti(0);
rcc(c1, eflag);
stuffdot(p);
break;
- case Aparen:
+ case Tparen:
rcc(c0, eflag);
break;
- case Asimple:
+ case Tsimple:
emitf(Xmark);
rcc(c0, eflag);
emitf(Xsimple);
if(eflag)
emitf(Xeflag);
break;
- case Ksubsh:
+ case Tsubshell:
emitf(Xsubshell);
if(havefork){
p = emiti(0);
@@ -185,10 +185,10 @@ rcc(Tree *t, int eflag)
if(eflag)
emitf(Xeflag);
break;
- case Kswitch:
+ case Tswitch:
codeswitch(t, eflag);
break;
- case Ktwiddle:
+ case Ttwiddle:
emitf(Xmark);
rcc(c1, eflag);
emitf(Xmark);
@@ -209,11 +209,11 @@ rcc(Tree *t, int eflag)
emiti(q);
stuffdot(p);
break;
- case Awords:
+ case Twords:
rcc(c1, eflag);
rcc(c0, eflag);
break;
- case Kfor:
+ case Tfor:
emitf(Xmark);
if(c1){
rcc(c1, eflag);
@@ -237,12 +237,12 @@ rcc(Tree *t, int eflag)
stuffdot(q);
emitf(Xunlocal);
break;
- case Aword:
+ case Tword:
emitf(Xword);
emits(strdup(t->str));
break;
- case Adup:
- if(t->rtype==Adupfd){
+ case Tdup:
+ if(t->rtype==Tdupfd){
emitf(Xdup);
emiti(t->fd0);
emiti(t->fd1);
@@ -254,7 +254,7 @@ rcc(Tree *t, int eflag)
rcc(c1, eflag);
emitf(Xpopredir);
break;
- case Apipefd:
+ case Tpipefd:
emitf(Xpipefd);
emiti(t->rtype);
if(havefork){
@@ -266,7 +266,7 @@ rcc(Tree *t, int eflag)
emits(fnstr(c0));
}
break;
- case Aredir:
+ case Tredir:
emitf(Xmark);
rcc(c0, eflag);
emitf(Xglob);
@@ -315,7 +315,7 @@ rcc(Tree *t, int eflag)
}
t = tt; /* so tests below will work */
break;
- case Apipe:
+ case Tpipe:
emitf(Xpipe);
emiti(t->fd0);
emiti(t->fd1);
@@ -335,7 +335,7 @@ rcc(Tree *t, int eflag)
emitf(Xpipewait);
break;
}
- if(t->type!=Kelse && t->type!=';')
+ if(t->type!=Telse && t->type!=';')
runq->iflast = t->type==IF;
else if(c0) runq->iflast = c0->type==IF;
}
diff --git a/sys/cmd/rc/io.c b/sys/cmd/rc/io.c
index 8cc2f5b..2fbe57f 100644
--- a/sys/cmd/rc/io.c
+++ b/sys/cmd/rc/io.c
@@ -1,10 +1,10 @@
#include "rc.h"
-#undef bufsize
#define c0 t->child[0]
#define c1 t->child[1]
#define c2 t->child[2]
+#undef bufsize
#define bufsize 512
#define strsize 100
@@ -169,6 +169,11 @@ pptr(Io *f, void *v)
int n;
uintptr p;
+ if (!v) {
+ pstr(f, "<nil>");
+ return;
+ }
+
p = (uintptr)v;
if ((sizeof(uintptr) == sizeof(uvlong)) && p >>32)
for (n = 60; n >= 32; n-=4)
@@ -252,49 +257,50 @@ pcmd(Io *f, Tree *t)
return;
switch(t->type){
- default: pfmt(f, "bad %d %p %p %p", t->type, c0, c1, c2);
+ default: pfmt(f, "bad<%d> %p %p %p", t->type, c0, c1, c2);
break;
- case '$': pfmt(f, "$%t", c0);
+ case Tdol: pfmt(f, "$%t", c0);
break;
- case '"': pfmt(f, "$\"%t", c0);
+ case Tquote: pfmt(f, "$\"%t", c0);
break;
- case '&': pfmt(f, "%t&", c0);
+ case Tand: pfmt(f, "%t&", c0);
break;
- case '^': pfmt(f, "%t^%t", c0, c1);
+ case Tcarot: pfmt(f, "%t^%t", c0, c1);
break;
- case '`': pfmt(f, "`%t", c0);
+ case Ttick: pfmt(f, "`%t", c0);
break;
- case Aandand: pfmt(f, "%t && %t", c0, c1);
+ case Tandand: pfmt(f, "%t && %t", c0, c1);
break;
- case Kbang: pfmt(f, "! %t", c0);
+ case Tbang: pfmt(f, "! %t", c0);
break;
- case Abrace: pfmt(f, "{%t}", c0);
+ case Tbrace: pfmt(f, "{%t}", c0);
break;
- case Acount: pfmt(f, "$#%t", c0);
+ case Tcount: pfmt(f, "$#%t", c0);
break;
- case Kfunc: pfmt(f, "fn %t %t", c0, c1);
+ case Tfunc: pfmt(f, "func %t %t", c0, c1);
break;
- case Kif: pfmt(f, "if%t%t", c0, c1);
+ case Tif: (c2) ? pfmt(f, "if%t%t else %t", c0, c1, c2): pfmt(f, "if%t%t", c0, c1);
break;
- case Kelse: pfmt(f, "else %t", c0);
+ case Toror: pfmt(f, "%t || %t", c0, c1);
break;
- case Aoror: pfmt(f, "%t || %t", c0, c1);
+ case Tpcmd: /* fallthrough */
+ case Tparen: pfmt(f, "(%t)", c0);
break;
- case Aparen: pfmt(f, "(%t)", c0);
+ case Tsub: pfmt(f, "$%t(%t)", c0, c1);
break;
- case Asub: pfmt(f, "$%t(%t)", c0, c1);
+ case Tsimple: pfmt(f, "%t", c0);
break;
- case Asimple: pfmt(f, "%t", c0);
+ case Tsubshell: pfmt(f, "@ %t", c0);
break;
- case Ksubsh: pfmt(f, "@ %t", c0);
+ case Tswitch: pfmt(f, "switch %t %t", c0, c1);
break;
- case Kswitch: pfmt(f, "switch %t %t", c0, c1);
+ case Tcase: pfmt(f, "case %t:\n%t", c0, c1);
break;
- case Ktwiddle: pfmt(f, "~ %t %t", c0, c1);
+ case Ttwiddle: pfmt(f, "~ %t %t", c0, c1);
break;
- case Kwhile: pfmt(f, "while %t%t", c0, c1);
+ case Twhile: pfmt(f, "while %t%t", c0, c1);
break;
- case Aargs:
+ case Targs:
if(c0==0)
pfmt(f, "%t", c1);
else if(c1==0)
@@ -302,40 +308,41 @@ pcmd(Io *f, Tree *t)
else
pfmt(f, "%t %t", c0, c1);
break;
- case ';':
- if(c0){
+ case Tsemi:
+ if(c0) {
if(c1)
pfmt(f, "%t%c%t", c0, '\n', c1);
- else pfmt(f, "%t", c0);
- }
- else pfmt(f, "%t", c1);
+ else
+ pfmt(f, "%t", c0);
+ } else
+ pfmt(f, "%t", c1);
break;
- case Awords:
+ case Twords:
if(c0)
pfmt(f, "%t ", c0);
pfmt(f, "%t", c1);
break;
- case Kfor:
+ case Tfor:
pfmt(f, "for(%t", c0);
if(c1)
pfmt(f, " in %t", c1);
pfmt(f, ")%t", c2);
break;
- case Aword:
+ case Tword:
if(t->quoted)
pfmt(f, "%Q", t->str);
else
pdeglob(f, t->str);
break;
- case Adup:
+ case Tdup:
if(t->redir.type==Rdupfd)
pfmt(f, ">[%d=%d]", t->redir.fd[1], t->redir.fd[0]); /* yes, fd1, then fd0; read lex.c */
else
pfmt(f, ">[%d=]", t->redir.fd[0]);
pfmt(f, "%t", c1);
break;
- case Apipefd:
- case Aredir:
+ case Tpipefd:
+ case Tredir:
switch(t->redir.type){
case Rhere:
pchr(f, '<');
@@ -359,12 +366,12 @@ pcmd(Io *f, Tree *t)
if(c1)
pfmt(f, " %t", c1);
break;
- case '=':
+ case Teq:
pfmt(f, "%t=%t", c0, c1);
if(c2)
pfmt(f, " %t", c2);
break;
- case Apipe:
+ case Tpipe:
pfmt(f, "%t|", c0);
if(t->redir.fd[1]==0){
if(t->redir.fd[0]!=1)
@@ -419,6 +426,7 @@ vpfmt(Io *f, char *fmt, va_list args)
pval(f, va_arg(args, Word*));
break;
}
+
if (--pfmtlev==0)
flush(&f);
}
diff --git a/sys/cmd/rc/lex.c b/sys/cmd/rc/lex.c
index 1415f5c..8b4cdec 100644
--- a/sys/cmd/rc/lex.c
+++ b/sys/cmd/rc/lex.c
@@ -35,7 +35,7 @@ static uchar nwordc[256] =
};
int
-wordchr(char c)
+wordchr(int c)
{
return !nwordc[c] && c!=EOF;
}
@@ -111,9 +111,9 @@ lookahead(void)
if(nextc != EOF)
return nextc;
-
if(shell->cmd.eof)
return EOF;
+
if(doprompt)
prompt();
@@ -248,6 +248,8 @@ rcerror(char *fmt, ...)
lastword = lastdol = 0;
while (lastc != '\n' && lastc != EOF)
advance();
+ /* for debugging only */
+ abort();
}
/* word is only modified in the event of a lexed word */
@@ -267,10 +269,10 @@ lex(Tree **node)
c = lookahead();
if(c=='('){
advance();
- return Alparen;
+ return Tlparen;
}
if(quotechr(c))
- return Acarot;
+ return Tcarot;
}
skipws();
@@ -281,37 +283,37 @@ lex(Tree **node)
case '$':
lastdol = 1;
if(nextis('#'))
- return Acount;
+ return Tcount;
if (nextis('"'))
- return Aquote;
- return Adol;
+ return Tquote;
+ return Tdol;
case '&':
lastdol = 0;
if(nextis('&'))
- return Aandand;
- return Aand;
+ return Tandand;
+ return Tand;
case '!':
- return Kbang;
+ return Tbang;
case '@':
- return Ksubsh;
+ return Tsubshell;
case '~':
- return Ktwiddle;
+ return Ttwiddle;
case '|':
lastdol = 0;
if(nextis('|')){
skipnl();
- return Aoror;
+ return Toror;
}
(*node) = newtree();
- (*node)->type = Apipe;
+ (*node)->type = Tpipe;
(*node)->redir.fd[0] = 0;
(*node)->redir.fd[1] = 1;
goto redir;
case '>':
(*node) = newtree();
- (*node)->type = Aredir;
+ (*node)->type = Tredir;
if (nextis(c))
(*node)->redir.type = Rappend;
else
@@ -320,7 +322,7 @@ lex(Tree **node)
goto redir;
case '<':
(*node) = newtree();
- (*node)->type = Aredir;
+ (*node)->type = Tredir;
if(nextis(c))
(*node)->redir.type = Rhere;
else if(nextis('>'))
@@ -344,8 +346,8 @@ lex(Tree **node)
} while('0'<=c && c<='9');
if(c == '=') {
- if((*node)->type == Aredir)
- (*node)->type = Adup;
+ if((*node)->type == Tredir)
+ (*node)->type = Tdup;
c = advance();
if('0'<=c && c<='9') {
(*node)->redir.type = Rdupfd;
@@ -356,16 +358,16 @@ lex(Tree **node)
c = advance();
} while('0'<=c && c<='9');
} else {
- if((*node)->type == Apipe)
+ if((*node)->type == Tpipe)
goto redirerr;
(*node)->redir.type = Rclose;
}
}
if (c != ']'
- ||(*node)->type==Adup && ((*node)->redir.type==Rhere || (*node)->redir.type==Rappend))
+ ||(*node)->type==Tdup && ((*node)->redir.type==Rhere || (*node)->redir.type==Rappend))
goto redirerr;
}
- if ((c = ((*node)->type)) == Apipe)
+ if ((c = ((*node)->type)) == Tpipe)
skipnl();
return c;
@@ -386,7 +388,7 @@ lex(Tree **node)
*w = 0;
*node = wordnode(buf);
(*node)->quoted = 1;
- return Aword;
+ return Tword;
}
if (!wordchr(c)) {
lastdol = 0;
@@ -405,7 +407,7 @@ lex(Tree **node)
if ((c = kwlookup(buf)) == -1) {
(*node) = wordnode(buf);
- (*node)->type = c = Aword;
+ (*node)->type = c = Tword;
(*node)->quoted = 0;
lastword = 1;
}
diff --git a/sys/cmd/rc/main.c b/sys/cmd/rc/main.c
index baaf6bc..b4a355e 100644
--- a/sys/cmd/rc/main.c
+++ b/sys/cmd/rc/main.c
@@ -76,10 +76,10 @@ main(int argc, char *argv[])
dotrap();
}
#else
-
bootup(sh, 1, nil);
shell->cmd.io = openfd(0);
- parse();
+ while (parse())
+ ;
#endif
exit(0);
diff --git a/sys/cmd/rc/parse.c b/sys/cmd/rc/parse.c
index d963c12..c5c77d3 100644
--- a/sys/cmd/rc/parse.c
+++ b/sys/cmd/rc/parse.c
@@ -3,17 +3,18 @@
// -----------------------------------------------------------------------
// global data
-static int lasta, nexta=EOF;
+static int lastt, nextt=EOF;
static Tree *node; /* if token was lexed as a tree node (redirs and words), its here */
+/* anything that is not listed will automatically terminate parsing the given command */
static uchar prectab[256] = {
- [Kif] = 1, [Kfor] = 1, [Kswitch] = 1, [Kelse] = 1,
- [Aandand] = 2, [Aoror] = 2,
- [Kbang] = 3, [Ksubsh] = 3,
- [Apipe] = 4,
- [Acarot] = 5,
- [Adol] = 6, [Acount] = 6, [Aquote] = 6,
- [Asub] = 7,
+ [Tif] = 1, [Tfor] = 1, [Tswitch] = 1, /* NOTE: we give else lower precedence than if [Telse] = 1, */
+ [Tandand] = 2, [Toror] = 2,
+ [Tbang] = 3, [Tsubshell] = 3,
+ [Tpipe] = 4,
+ [Tcarot] = 5,
+ [Tdol] = 6, [Tcount] = 6, [Tquote] = 6,
+ [Tsub] = 7,
};
// -----------------------------------------------------------------------
@@ -25,11 +26,11 @@ lookahead(void)
{
int tok;
- if (nexta != EOF)
- return nexta;
+ if (nextt != EOF)
+ return nextt;
tok = lex(&node);
- return nexta = tok;
+ return nextt = tok;
}
static
@@ -37,7 +38,7 @@ int
advance(void)
{
int tok = lookahead();
- lasta = nexta, nexta = EOF;
+ lastt = nextt, nextt = EOF;
node = nil;
return tok;
@@ -57,17 +58,48 @@ nextis(int tok)
// -----------------------------------------------------------------------
// subparsers
+/* forward declarations */
static Tree *word(void);
+static Tree *words(void);
+static Tree* body(int c);
static Tree *comword(void);
static Tree *cmd(int prec);
+/* implementations */
+
+/*
+ * TODO:
+ * i don't like all this branching.
+ * think of a better way
+ */
+
+static
+Tree*
+case_or_cmd(int c)
+{
+ Tree *t;
+ if (!c || !nextis(Tcase))
+ return cmd(1);
+
+ t = words();
+ if (!nextis(';') && !nextis('\n'))
+ rcerror("case: missing terminator: recieved %d", nextt);
+
+ t = tree2(Tcase, t, body(0));
+ pfmt(errio, "%t\n", t);
+
+ return t;
+}
+
static
Tree*
-body(void)
+body(int c)
{
int tok;
Tree *l, *r;
- l = cmd(1);
+
+ skipnl();
+ l = case_or_cmd(c);
loop:
switch((tok=lookahead())){
case '&':
@@ -75,9 +107,13 @@ loop:
/* fallthrough */
case ';': case '\n':
advance();
- r = cmd(1);
- l = tree2(';', l, r);
- goto loop;
+ /* fallthrough */
+ case Tcase:
+ if ((r = case_or_cmd(c))) {
+ l = tree2(';', l, r);
+ goto loop;
+ }
+ /* fallthrough */
default:
;
}
@@ -87,15 +123,15 @@ loop:
static
Tree*
-brace(void)
+brace(int c)
{
Tree *t;
if (!nextis('{'))
- rcerror("not a brace");
- t = tree1(Abrace, body());
+ rcerror("brace: expected { found: %c", nextt);
+ t = tree1(Tbrace, body(c));
if (!nextis('}'))
- rcerror("unmatched brace");
+ rcerror("brace: expected } found: %c", nextt);
return t;
}
@@ -108,7 +144,7 @@ paren(void)
if (!nextis('('))
rcerror("not a paren");
- t = tree1(Aparen, body());
+ t = tree1(Tparen, body(0));
if (!nextis(')'))
rcerror("unmatched paren");
@@ -131,13 +167,14 @@ redir(void)
Tree *t;
switch (tok = lookahead()) {
- case Adup:
+ case Tdup:
t = node;
advance();
break;
- case Aredir:
+ case Tredir:
+ t = node;
advance();
- t = hang1(node, (node->redir.type == Rhere) ? heredoc(word()) : word());
+ t = hang1(t, (t->redir.type == Rhere) ? heredoc(word()) : word());
break;
default:
t = nil;
@@ -192,11 +229,17 @@ words(void)
Tree *t, *tt;
t = word();
while((tt=word()))
- t = tree2(Awords, t, tt);
+ t = tree2(Twords, t, tt);
return t;
}
+/*
+ * NOTE: we divergence from Duff's yacc grammar here.
+ * he has [dol|count|"]->word, we have [dol|count]->sword
+ * calling sword ensures we don't cat strings
+ * this was done in Tom's version by setting precedence
+ */
static
Tree*
comword(void)
@@ -205,29 +248,31 @@ comword(void)
Tree *t, *tt;
switch(tok=lookahead()){
- case Adol:
+ case Tdol:
advance();
- t = word();
+ t = sword();
if(nextis('(')) {
- t = tree2(Asub, t, words());
+ t = tree2(Tsub, t, words());
if (!nextis(')'))
rcerror("malformed index expression");
}
- return tree1(Adol, t);
- case Acount:
+ return tree1(Tdol, t);
+ case Tquote:
+ return tree1(Tquote, sword());
+ case Tcount:
advance();
- return tree1(Acount, word());
- case Atick:
+ return tree1(Tcount, sword());
+ case Ttick:
advance();
- return tree1(Atick, brace());
- case Alparen:
+ return tree1(Ttick, brace(0));
+ case Tlparen:
return paren();
- case Aredir:
+ case Tredir:
advance();
- t = hang1(node, brace());
- t->type = Apipefd;
+ t = hang1(node, brace(0));
+ t->type = Tpipefd;
return t;
- case Aword:
+ case Tword:
t = node;
advance();
return t;
@@ -264,19 +309,21 @@ simple_or_assign(void)
/* is an assignment */
assign:
- if(nextis('='))
- return tree3(Aeq, t, word(), cmd(prectab[Kbang]));
+ if(nextis('=')) {
+ tt = word();
+ return tree3(Teq, t, tt, cmd(prectab[Tbang]));
+ }
/* is a 'simple' */
simple:
switch ((tok=lookahead())) {
- case Aredir:
- case Adup:
- t = tree2(Aargs, t, redir());
+ case Tredir:
+ case Tdup:
+ t = tree2(Targs, t, redir());
goto simple;
default:
if ((tt = word())) {
- t = tree2(Aargs, t, tt);
+ t = tree2(Targs, t, tt);
goto simple;
}
/* fallthrough */
@@ -293,79 +340,91 @@ opand(void)
Tree *t, *tt;
switch(tok=lookahead()) {
- case Kif:
+ case Tif:
advance();
t = paren();
skipnl();
- tt = cmd(prectab[Kif]);
- t = tree2(Kif, t, tt);
+ tt = cmd(prectab[Tif]);
+ if (nextis(Telse)) {
+ skipnl();
+ t = tree3(Tif, t, tt, cmd(prectab[Tif]));
+ } else
+ t = tree3(Tif, t, tt, nil);
return t;
+ case Telse:
+ rcerror("invalid hanging else");
+ break;
- case Kelse:
+ case Tswitch:
advance();
+ t = word();
skipnl();
- t = tree1(Kelse, cmd(prectab[Kelse]));
+ tt = brace(1);
+ t = tree2(Tswitch, t, tt);
return t;
- case Kfor:
+ case Tfor:
advance();
+
if (!nextis('('))
- rcerror("malformed for statement");
+ rcerror("for: missing opening paren");
t = word();
- if (nextis(Kin)) {
+ if (nextis(Tin)) {
advance();
tt = words();
- t = tree3(Kin, t, tt, nil);
+ t = tree3(Tfor, t, tt, nil);
} else
- t = tree3(Kin, t, nil, nil);
+ t = tree3(Tfor, t, nil, nil);
+ if (!nextis(')'))
+ rcerror("for: missing closing paren");
+
skipnl();
- tt = cmd(prectab[Kfor]);
+ tt = cmd(prectab[Tfor]);
t->child[2] = tt;
return t;
- case Kswitch:
+ case Twhile:
advance();
- t = word();
+ t = paren();
skipnl();
- tt = brace();
- t = tree2(Kswitch, t, tt);
- return t;
+ tt = cmd(1);
+ return tree2(Twhile, t, tt);
- case Kfunc:
+ case Tfunc:
advance();
t = words();
if ((tok=lookahead()) == '{') {
- tt = brace();
- t = tree2(Kfunc, t, tt);
+ tt = brace(0);
+ t = tree2(Tfunc, t, tt);
} else
- t = tree1(Kfunc, t);
+ t = tree1(Tfunc, t);
return t;
- case Ksubsh:
+ case Tsubshell:
advance();
- t = tree1(Ksubsh, cmd(prectab[Ksubsh]));
+ t = tree1(Tsubshell, cmd(prectab[Tsubshell]));
return t;
- case Kbang:
+ case Tbang:
advance();
- t = tree1(Kbang, cmd(prectab[Kbang]));
+ t = tree1(Tbang, cmd(prectab[Tbang]));
return t;
- case Ktwiddle:
+ case Ttwiddle:
advance();
tt = word();
- t = tree2(Ktwiddle, tt, words());
+ t = tree2(Ttwiddle, tt, words());
return t;
- case Albrace:
- t = brace();
+ case Tlbrace:
+ t = brace(0);
tt = epilog();
return epihang(t, tt);
- case Aredir: /* fallthrough */
- case Adup:
+ case Tredir: /* fallthrough */
+ case Tdup:
t = redir();
- tt = cmd(prectab[Kbang]);
+ tt = cmd(prectab[Tbang]);
t = hang2(t, t->child[0], tt);
return t;
}
@@ -391,7 +450,7 @@ cmd(int prec)
p = node;
advance();
r = cmd(np+1);
- if (tok == Apipe)
+ if (tok == Tpipe)
l = hang2(p, l, r);
else
l = tree2(tok, l, r);
@@ -420,11 +479,16 @@ loop:
tt = cmd(1);
t = tree2(';', t, tt);
goto loop;
- case '\n': case EOF:
- pfmt(errio, "%t", t);
+ case '\n':
+ advance();
+ case EOF:
+ pfmt(errio, "%t\n", t);
break;
default:
- rcerror("unrecognized token: %d", tok);
+ if (tok > 0x20)
+ rcerror("unrecognized token: %c[%d]", tok, tok);
+ else
+ rcerror("unrecognized token: %d", tok, tok);
}
- return 0;
+ return tok != EOF;
}
diff --git a/sys/cmd/rc/rc.h b/sys/cmd/rc/rc.h
index ad46a77..7146aa0 100644
--- a/sys/cmd/rc/rc.h
+++ b/sys/cmd/rc/rc.h
@@ -13,22 +13,23 @@
#define GLOB 0x01
-/* TODO: make sure there are no collisions */
enum
{
/* keywords */
- Kstart=11, Kfor, Kin, Kwhile, Kif, Kelse,
- Kswitch, Kcase, Kfunc, Ktwiddle,
- Kbang, Ksubsh, Kend,
+ Kstart = 11,
+ Tfor, Tin, Twhile, Tif, Telse,
+ Tswitch, Tcase, Tfunc, Ttwiddle,
+ Tbang, Tsubshell,
+ Kend,
/* tokens */
- Aword='w', Aredir='r', Adup='d', Asimple='s',
- Aargs='A', Awords='W', Abrace='b', Aparen='p', Asub='S',
- Apcmd='c', Apipefd='-', Aandand='%', Aoror='@', Acount='#',
+ Tword='w', Tredir='r', Tdup='d', Tsimple='s',
+ Targs='A', Twords='W', Tbrace='b', Tparen='p', Tsub='S',
+ Tpcmd='c', Tpipefd='-', Tandand='%', Toror='@', Tcount='#',
- Atick='`', Apipe = '|', Adol='$', Aquote='"', Aand='&',
- Alparen = '(', Arparen = ')', Albrace='{', Arbrace='}',
- Asemi=';', Acarot='^', Aeq='=',
+ Ttick='`', Tpipe = '|', Tdol='$', Tquote='"', Tand='&',
+ Tlparen = '(', Trparen = ')', Tlbrace='{', Trbrace='}',
+ Tsemi=';', Tcarot='^', Teq='=',
};
enum
@@ -236,7 +237,7 @@ void initkw(void);
*/
void skipnl(void);
-int wordchr(char c);
+int wordchr(int c);
void rcerror(char *msg, ...);
int lex(Tree **node);
diff --git a/sys/cmd/rc/tree.c b/sys/cmd/rc/tree.c
index 8dca67f..14049e5 100644
--- a/sys/cmd/rc/tree.c
+++ b/sys/cmd/rc/tree.c
@@ -121,10 +121,10 @@ Tree*
simplehang(Tree *t)
{
Tree *u;
- t = tree1(Asimple, t);
- for(u = t->child[0];u->type==Aargs;u=u->child[0]) {
- if (u->child[1]->type==Adup
- || u->child[1]->type==Aredir){
+ t = tree1(Tsimple, t);
+ for(u = t->child[0];u->type==Targs;u=u->child[0]) {
+ if (u->child[1]->type==Tdup
+ || u->child[1]->type==Tredir){
u->child[1]->child[1] = t;
t = u->child[1];
u->child[1] = nil;
@@ -137,7 +137,7 @@ Tree*
wordnode(char *w)
{
Tree *t = newtree();
- t->type = Aword;
+ t->type = Tword;
t->str = strdup(w);
return t;
diff --git a/sys/cmd/rc/var.c b/sys/cmd/rc/var.c
index dbe7c14..ef339d7 100644
--- a/sys/cmd/rc/var.c
+++ b/sys/cmd/rc/var.c
@@ -43,14 +43,14 @@ putkw(int type, char *name)
void
initkw(void)
{
- putkw(Kfor, "for");
- putkw(Kin, "in");
- putkw(Kwhile, "while");
- putkw(Kif, "if");
- putkw(Kelse, "else");
- putkw(Kswitch, "switch");
- putkw(Kcase, "case");
- putkw(Kfunc, "func");
+ putkw(Tfor, "for");
+ putkw(Tin, "in");
+ putkw(Twhile, "while");
+ putkw(Tif, "if");
+ putkw(Telse, "else");
+ putkw(Tswitch, "switch");
+ putkw(Tcase, "case");
+ putkw(Tfunc, "func");
}
int