Skip to content

Commit

Permalink
rc: clean up parser levels, disallow free carats on lists
Browse files Browse the repository at this point in the history
  • Loading branch information
rsc committed May 5, 2020
1 parent ff74f7c commit 601e07b
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 31 deletions.
13 changes: 10 additions & 3 deletions src/cmd/rc/checkparse
Original file line number Diff line number Diff line change
@@ -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

2 changes: 1 addition & 1 deletion src/cmd/rc/lex.c
Original file line number Diff line number Diff line change
Expand Up @@ -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=='"'){
Expand Down
45 changes: 18 additions & 27 deletions src/cmd/rc/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -196,52 +194,42 @@ 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;
return t1;
}

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;
return t1;
}

static tree*
cmd4(int tok, int *ptok)
cmd3(int tok, int *ptok)
{
tree *t1, *t2, *t3, *t4;

Expand Down Expand Up @@ -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 '{':
Expand All @@ -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);
}

Expand Down Expand Up @@ -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;
}
Expand Down
8 changes: 8 additions & 0 deletions src/cmd/rc/test.rc
Original file line number Diff line number Diff line change
Expand Up @@ -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)

0 comments on commit 601e07b

Please sign in to comment.