diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-01-07 20:50:00 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-01-07 20:50:00 +0000 |
commit | 369cba5f938d3f804210b6e09d36c6f7ecb017fa (patch) | |
tree | d669ae599d264b3382785aa71f737984df0aece5 | |
parent | 70edb7fbae4f0a38593c0dc1f936838adc6861ac (diff) |
rc: read heredoc when receiving '\n' (thanks Eckard Brauer)
Eckard's test case:
cat <<! | cat
asdf
!
The issue is that we have to continue parsing until we see
the '\n' before consuming the here document.
So we revert to the old approach of having two functions:
heredoc() which remembers if we'v seen a heredoc redirection
and a second readhere() function that reads the doc from
the lexers input and sets Tree.str on thee REDIR node.
-rw-r--r-- | sys/src/cmd/rc/fns.h | 3 | ||||
-rw-r--r-- | sys/src/cmd/rc/here.c | 36 | ||||
-rw-r--r-- | sys/src/cmd/rc/syn.y | 6 |
3 files changed, 35 insertions, 10 deletions
diff --git a/sys/src/cmd/rc/fns.h b/sys/src/cmd/rc/fns.h index a4c33ed7f..387313610 100644 --- a/sys/src/cmd/rc/fns.h +++ b/sys/src/cmd/rc/fns.h @@ -58,7 +58,8 @@ void psubst(io*, unsigned char*); void pushlist(void); void pushredir(int, int, int); word* pushword(char*); -char* readhere(tree*, io*); +void readhere(io*); +void heredoc(tree*); void setstatus(char*); void skipnl(void); void start(code*, int, var*, redir*); diff --git a/sys/src/cmd/rc/here.c b/sys/src/cmd/rc/here.c index c148430ff..76679ad9a 100644 --- a/sys/src/cmd/rc/here.c +++ b/sys/src/cmd/rc/here.c @@ -6,16 +6,12 @@ void psubst(io*, unsigned char*); void pstrs(io*, word*); -char* -readhere(tree *tag, io *in) +static char* +readhere1(tree *tag, io *in) { io *out; char c, *m; - if(tag->type!=WORD){ - yyerror("Bad here tag"); - return 0; - } pprompt(); out = openiostr(); m = tag->str; @@ -47,6 +43,34 @@ readhere(tree *tag, io *in) return closeiostr(out); } +static tree *head, *tail; + +void +heredoc(tree *redir) +{ + if(redir->child[0]->type!=WORD){ + yyerror("Bad here tag"); + return; + } + redir->child[2]=0; + if(head) + tail->child[2]=redir; + else + head=redir; + tail=redir; +} + +void +readhere(io *in) +{ + while(head){ + tail=head->child[2]; + head->child[2]=0; + head->str=readhere1(head->child[0], in); + head=tail; + } +} + void psubst(io *f, unsigned char *s) { diff --git a/sys/src/cmd/rc/syn.y b/sys/src/cmd/rc/syn.y index 7aeb7f571..c29241f55 100644 --- a/sys/src/cmd/rc/syn.y +++ b/sys/src/cmd/rc/syn.y @@ -22,7 +22,7 @@ %type<tree> WORD REDIR DUP PIPE %% rc: { return 1;} -| line '\n' {return !compile($1);} +| line '\n' {readhere(lex->input); return !compile($1);} line: cmd | cmdsa line {$$=tree2(';', $1, $2);} body: cmd @@ -30,13 +30,13 @@ body: cmd cmdsa: cmd ';' | cmd '&' {$$=tree1('&', $1);} cmdsan: cmdsa -| cmd '\n' +| cmd '\n' {readhere(lex->input);} brace: '{' body '}' {$$=tree1(BRACE, $2);} paren: '(' body ')' {$$=tree1(PCMD, $2);} assign: first '=' word {$$=tree2('=', $1, $3);} epilog: {$$=0;} | redir epilog {$$=mung2($1, $1->child[0], $2);} -redir: REDIR word {($$=mung1($1, $2))->str=$1->rtype==HERE?readhere($2,lex->input):0;} +redir: REDIR word {$$=mung1($1, $2); if($$->rtype==HERE) heredoc($$);} | DUP cmd: {$$=0;} | brace epilog {$$=epimung($1, $2);} |