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.
This commit is contained in:
cinap_lenrek 2022-01-07 20:50:00 +00:00
parent 70edb7fbae
commit 369cba5f93
3 changed files with 35 additions and 10 deletions

View file

@ -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*);

View file

@ -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)
{

View file

@ -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);}