From 601e07b63653d0fed91594ebba261b733d017653 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 5 May 2020 08:29:45 -0400 Subject: [PATCH] rc: clean up parser levels, disallow free carats on lists --- src/cmd/rc/checkparse | 13 ++++++++++--- src/cmd/rc/lex.c | 2 +- src/cmd/rc/parse.c | 45 +++++++++++++++++-------------------------- src/cmd/rc/test.rc | 8 ++++++++ 4 files changed, 37 insertions(+), 31 deletions(-) diff --git a/src/cmd/rc/checkparse b/src/cmd/rc/checkparse index 1ff84667b..0a1472b2e 100755 --- a/src/cmd/rc/checkparse +++ b/src/cmd/rc/checkparse @@ -1,16 +1,23 @@ #!/bin/bash +aflag=false +if [ "$1" = -a ]; then + aflag=true + shift +fi + files="$@" if [ $# = 0 ]; then files=$(echo ./test.rc; grep -l '^#!/usr/local/plan9/bin/rc' /usr/local/plan9/bin/{*,*/*} 2>/dev/null; - grep -l '^#!/bin/rc' $HOME/pub/plan9/rc/bin/{*,*/*} 2>/dev/null) + grep -R -l '^#!/bin/rc' $HOME/pub/plan9 | egrep -v 'plan9/(lib/(oui|pci)|sys/man|sys/lib/man|sys/lib/scsicodes)' 2>/dev/null) fi for i in $files do if ! diff <(./o.rc -DY $i 2>&1) <(./o.rc -D $i 2>&1); then - echo '#' $i - exit 1 + echo '^^^' $i + ! $aflag && exit 1 fi done + diff --git a/src/cmd/rc/lex.c b/src/cmd/rc/lex.c index 48bd70ded..e4410c002 100644 --- a/src/cmd/rc/lex.c +++ b/src/cmd/rc/lex.c @@ -206,7 +206,7 @@ yylex(void) lastword = 0; if(d=='('){ advance(); - strcpy(tok, "( [SUB]"); + strcpy(tok, "("); return SUB; } if(wordchr(d) || d=='\'' || d=='`' || d=='$' || d=='"'){ diff --git a/src/cmd/rc/parse.c b/src/cmd/rc/parse.c index a46931dcf..dd1021903 100644 --- a/src/cmd/rc/parse.c +++ b/src/cmd/rc/parse.c @@ -7,7 +7,6 @@ static tree* brace(int tok); static tree* cmd(int tok, int *ptok); static tree* cmd2(int tok, int *ptok); static tree* cmd3(int tok, int *ptok); -static tree* cmd4(int tok, int *ptok); static tree* cmds(int tok, int *ptok, int nlok); static tree* epilog(int tok, int *ptok); static int iswordtok(int tok); @@ -39,9 +38,8 @@ dropsp(int tok) static void syntax(int tok) { - char buf[100]; - snprint(buf, sizeof buf, "syntax error %d", tok); - yyerror(buf); + USED(tok); + yyerror("syntax error"); longjmp(yyjmp, 1); } @@ -196,17 +194,6 @@ yyredir(int tok, int *ptok) static tree* cmd(int tok, int *ptok) -{ - tok = dropsp(tok); - switch(tok) { - default: - return cmd2(tok, ptok); - - } -} - -static tree* -cmd2(int tok, int *ptok) { int op; tree *t1, *t2; @@ -214,10 +201,11 @@ cmd2(int tok, int *ptok) // | cmd ANDAND cmd {$$=tree2(ANDAND, $1, $3);} // | cmd OROR cmd {$$=tree2(OROR, $1, $3);} - t1 = cmd3(tok, &tok); + tok = dropsp(tok); + t1 = cmd2(tok, &tok); while(tok == ANDAND || tok == OROR) { op = tok; - t2 = cmd3(dropnl(yylex()), &tok); + t2 = cmd2(dropnl(yylex()), &tok); t1 = tree2(op, t1, t2); } *ptok = tok; @@ -225,15 +213,15 @@ cmd2(int tok, int *ptok) } static tree* -cmd3(int tok, int *ptok) +cmd2(int tok, int *ptok) { tree *t1, *t2, *t3; // | cmd PIPE cmd {$$=mung2($2, $1, $3);} - t1 = cmd4(tok, &tok); + t1 = cmd3(tok, &tok); while(tok == PIPE) { t2 = yylval.tree; - t3 = cmd4(dropnl(yylex()), &tok); + t3 = cmd3(dropnl(yylex()), &tok); t1 = mung2(t2, t1, t3); } *ptok = tok; @@ -241,7 +229,7 @@ cmd3(int tok, int *ptok) } static tree* -cmd4(int tok, int *ptok) +cmd3(int tok, int *ptok) { tree *t1, *t2, *t3, *t4; @@ -336,16 +324,16 @@ cmd4(int tok, int *ptok) case SUBSHELL: // | BANG cmd {$$=mung1($1, $2);} // | SUBSHELL cmd {$$=mung1($1, $2);} - // Note: cmd3: ! x | y is !{x | y} not {!x} | y. + // Note: cmd2: ! x | y is !{x | y} not {!x} | y. t1 = yylval.tree; - return mung1(t1, cmd3(yylex(), ptok)); + return mung1(t1, cmd2(yylex(), ptok)); case REDIR: case DUP: // | redir cmd %prec BANG {$$=mung2($1, $1->child[0], $2);} - // Note: cmd3: {>x echo a | tr a-z A-Z} writes A to x. + // Note: cmd2: {>x echo a | tr a-z A-Z} writes A to x. t1 = yyredir(tok, &tok); - t2 = cmd3(tok, ptok); + t2 = cmd2(tok, ptok); return mung2(t1, t1->child[0], t2); case '{': @@ -372,9 +360,9 @@ cmd4(int tok, int *ptok) t1 = yyword(tok, &tok, 0); if(tok == '=') { // assignment - // Note: cmd3: {x=1 true | echo $x} echoes 1. + // Note: cmd2: {x=1 true | echo $x} echoes 1. t1 = tree2('=', t1, yyword(yylex(), &tok, 1)); - t2 = cmd3(tok, ptok); + t2 = cmd2(tok, ptok); return mung3(t1, t1->child[0], t1->child[1], t2); } @@ -440,6 +428,9 @@ yyword(int tok, int *ptok, int eqok) goto out; for(;;) { if(iswordtok(tok)) { + // No free carats around parens. + if(t->type == PAREN || tok == '(') + syntax(tok); t = tree2('^', t, word1(tok, &tok)); continue; } diff --git a/src/cmd/rc/test.rc b/src/cmd/rc/test.rc index f667b8401..4a33d87c1 100644 --- a/src/cmd/rc/test.rc +++ b/src/cmd/rc/test.rc @@ -83,3 +83,11 @@ x = y # x y=z # x =y # x -flag=y + +>z x | y + +# rejected now, was like parens were spaces before. +# echo Formatting Venti arenas and indices (this takes a while). + + +# echo $STATLINE(1)^$STATLINE(3)' '$STATLINE(2)' '$STATLINE(4)' '$LSLINE(6)