commit 601e07b63653d0fed91594ebba261b733d017653 from: Russ Cox date: Tue May 05 12:30:14 2020 UTC rc: clean up parser levels, disallow free carats on lists commit - ff74f7cdda7b08da6fe7c8bbcca990305fd6b547 commit + 601e07b63653d0fed91594ebba261b733d017653 blob - 1ff84667b59d9fcfb646a3b1b9e9684cef45d775 blob + 0a1472b2ed3a31f2706a579b04ab485ad3df13f8 --- src/cmd/rc/checkparse +++ 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 + blob - 48bd70deddbec479756021e1f21ec3040a8944dd blob + e4410c00266a8ed192440a7c16b68a7ce0093a32 --- src/cmd/rc/lex.c +++ 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=='"'){ blob - a46931dcf32dfcf548ea15deb7cd03187306d288 blob + dd102190335f2fee362f41db5244b1d40e2692bf --- src/cmd/rc/parse.c +++ 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); } @@ -197,27 +195,17 @@ 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; // | 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; } blob - f667b84015bca41c032ab585cfbc6dacdb686c54 blob + 4a33d87c1be5a1a1ac0a3400b626c5a25460b746 --- src/cmd/rc/test.rc +++ 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)