From 3caf5c238a886d06b438ec6d42f2609b8625463f Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 4 May 2020 22:52:27 -0400 Subject: rc: move newline handling into parser --- src/cmd/rc/checkparse | 6 ++++-- src/cmd/rc/lex.c | 24 ++++++++++++++++-------- src/cmd/rc/parse.c | 27 +++++++++++++++------------ src/cmd/rc/pcmd.c | 5 ++++- src/cmd/rc/syn.y | 2 +- src/cmd/rc/test.rc | 27 +++++++++++++++++++++++++++ 6 files changed, 67 insertions(+), 24 deletions(-) (limited to 'src/cmd') diff --git a/src/cmd/rc/checkparse b/src/cmd/rc/checkparse index cccc4058..1ff84667 100755 --- a/src/cmd/rc/checkparse +++ b/src/cmd/rc/checkparse @@ -9,6 +9,8 @@ fi for i in $files do - echo '#' $i - diff <(./o.rc -DY $i 2>&1) <(./o.rc -D $i 2>&1) + if ! diff <(./o.rc -DY $i 2>&1) <(./o.rc -D $i 2>&1); then + echo '#' $i + exit 1 + fi done diff --git a/src/cmd/rc/lex.c b/src/cmd/rc/lex.c index 0bdbbb4b..58338479 100644 --- a/src/cmd/rc/lex.c +++ b/src/cmd/rc/lex.c @@ -102,15 +102,17 @@ pprompt(void) doprompt = 0; } -void +int skipwhite(void) { - int c; + int c, skipped; + skipped = 0; for(;;){ c = nextc(); /* Why did this used to be if(!inquote && c=='#') ?? */ if(c=='#'){ incomm = 1; + skipped = 1; for(;;){ c = nextc(); if(c=='\n' || c==EOF) { @@ -120,9 +122,12 @@ skipwhite(void) advance(); } } - if(c==' ' || c=='\t') + if(c==' ' || c=='\t') { + skipped = 1; advance(); - else return; + } + else + return skipped; } } @@ -210,7 +215,8 @@ yylex(void) } } inquote = 0; - skipwhite(); + if(skipwhite() && flag['Z']) + return SP; switch(c = advance()){ case EOF: lastdol = 0; @@ -231,7 +237,8 @@ yylex(void) case '&': lastdol = 0; if(nextis('&')){ - skipnl(); + if(flag['Y']) + skipnl(); strcpy(tok, "&&"); return ANDAND; } @@ -240,7 +247,8 @@ yylex(void) case '|': lastdol = 0; if(nextis(c)){ - skipnl(); + if(flag['Y']) + skipnl(); strcpy(tok, "||"); return OROR; } @@ -329,7 +337,7 @@ yylex(void) } *w='\0'; yylval.tree = t; - if(t->type==PIPE) + if(t->type==PIPE && flag['Y']) skipnl(); if(t->type==REDIR) { skipwhite(); diff --git a/src/cmd/rc/parse.c b/src/cmd/rc/parse.c index 6071bdff..466b7da2 100644 --- a/src/cmd/rc/parse.c +++ b/src/cmd/rc/parse.c @@ -20,6 +20,14 @@ static tree* words(int tok, int *ptok); static jmp_buf yyjmp; +static int +dropnl(int tok) +{ + while(tok == '\n') + tok = yylex(); + return tok; +} + static void syntax(int tok) { @@ -191,13 +199,11 @@ cmd(int tok, int *ptok) tok = yylex(); if(tok == NOT) { t1 = yylval.tree; - skipnl(); - t2 = cmd(yylex(), ptok); + t2 = cmd(dropnl(yylex()), ptok); return mung1(t1, t2); } t2 = paren(tok); - skipnl(); - t3 = cmd(yylex(), ptok); + t3 = cmd(dropnl(yylex()), ptok); return mung2(t1, t2, t3); case FOR: @@ -224,8 +230,7 @@ cmd(int tok, int *ptok) syntax(tok); break; } - skipnl(); - t4 = cmd(yylex(), ptok); + t4 = cmd(dropnl(yylex()), ptok); return mung3(t1, t2, t3, t4); case WHILE: @@ -233,16 +238,14 @@ cmd(int tok, int *ptok) // {$$=mung2($1, $2, $4);} t1 = yylval.tree; t2 = paren(yylex()); - skipnl(); - t3 = cmd(yylex(), ptok); + t3 = cmd(dropnl(yylex()), ptok); return mung2(t1, t2, t3); case SWITCH: // | SWITCH word {skipnl();} brace // {$$=tree2(SWITCH, $2, $4);} t1 = yyword(yylex(), &tok); - while(tok == '\n') - tok = yylex(); + tok = dropnl(tok); // doesn't work in yacc grammar but works here! t2 = brace(tok); *ptok = yylex(); return tree2(SWITCH, t1, t2); @@ -261,7 +264,7 @@ cmd2(int tok, int *ptok) t1 = cmd3(tok, &tok); while(tok == ANDAND || tok == OROR) { op = tok; - t2 = cmd3(yylex(), &tok); + t2 = cmd3(dropnl(yylex()), &tok); t1 = tree2(op, t1, t2); } *ptok = tok; @@ -277,7 +280,7 @@ cmd3(int tok, int *ptok) t1 = cmd4(tok, &tok); while(tok == PIPE) { t2 = yylval.tree; - t3 = cmd4(yylex(), &tok); + t3 = cmd4(dropnl(yylex()), &tok); t1 = mung2(t2, t1, t3); } *ptok = tok; diff --git a/src/cmd/rc/pcmd.c b/src/cmd/rc/pcmd.c index 26bd883b..cae84737 100644 --- a/src/cmd/rc/pcmd.c +++ b/src/cmd/rc/pcmd.c @@ -244,7 +244,10 @@ pcmdu(io *f, tree *t) /* unambiguous */ pfmt(f, "[%d]", t->fd0); break; } - pfmt(f, "%u %u)", c0, c1); + if(t->rtype == HERE) + pfmt(f, "HERE %u)", c1); + else + pfmt(f, "%u %u)", c0, c1); break; case '=': pfmt(f, "(%u=%u %u)", c0, c1, c2); diff --git a/src/cmd/rc/syn.y b/src/cmd/rc/syn.y index 5c98ef80..e3decd41 100644 --- a/src/cmd/rc/syn.y +++ b/src/cmd/rc/syn.y @@ -1,4 +1,4 @@ -%term FOR IN WHILE IF NOT TWIDDLE BANG SUBSHELL SWITCH FN +%term FOR IN WHILE IF NOT TWIDDLE BANG SUBSHELL SWITCH FN SP %term WORD REDIR REDIRW DUP PIPE SUB %term SIMPLE ARGLIST WORDS BRACE PAREN PCMD PIPEFD /* not used in syntax */ /* operator priorities -- lowest first */ diff --git a/src/cmd/rc/test.rc b/src/cmd/rc/test.rc index 8cb11e0f..5c658132 100644 --- a/src/cmd/rc/test.rc +++ b/src/cmd/rc/test.rc @@ -36,3 +36,30 @@ $#$x x for in while if not ~ ! @ switch fn x not$y a;b;c +if(x) +y +if(x) +{ +y +} +if not +z +for(x) +y +for(x in y) +z +while(x) +y +# yacc doesn't accept a newline before the brace +# even though the rule is written as if it would +switch x { +} +switch (x) { +} +z +x && +y +x || +y +x | +y -- cgit v1.2.3