diff options
author | Ron Yorston | 2015-10-29 11:30:55 +0000 |
---|---|---|
committer | Denys Vlasenko | 2015-10-29 21:44:11 +0100 |
commit | c0e007663d30f83b0e5e074db34dcffaa8915e99 (patch) | |
tree | 4fe5fc1aced6973b4e6dfe758cef56127f10b343 /shell/ash.c | |
parent | 6bd2fabc52fa76b69a65772878e2e745c0fff3ff (diff) | |
download | busybox-c0e007663d30f83b0e5e074db34dcffaa8915e99.zip busybox-c0e007663d30f83b0e5e074db34dcffaa8915e99.tar.gz |
ash: simplify EOF/newline handling in list parser
Processing of here documents in ash has had a couple of breakages
which are now the subject of tests. This commit should fix both.
It is based on the following commit in dash git by Herbert Xu:
<7c245aa> [PARSER] Simplify EOF/newline handling in list parser
(See git://git.kernel.org/pub/scm/utils/dash/dash.git)
Reported-by: Natanael Copa <ncopa@alpinelinux.org>
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell/ash.c')
-rw-r--r-- | shell/ash.c | 63 |
1 files changed, 29 insertions, 34 deletions
diff --git a/shell/ash.c b/shell/ash.c index 72fc7d5..9a8bab5 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -10524,7 +10524,7 @@ static union node *andor(void); static union node *pipeline(void); static union node *parse_command(void); static void parseheredoc(void); -static char peektoken(void); +static int peektoken(void); static int readtoken(void); static union node * @@ -10533,11 +10533,27 @@ list(int nlflag) union node *n1, *n2, *n3; int tok; - checkkwd = CHKNL | CHKKWD | CHKALIAS; - if (nlflag == 2 && peektoken()) - return NULL; n1 = NULL; for (;;) { + switch (peektoken()) { + case TNL: + if (!(nlflag & 1)) + break; + parseheredoc(); + return n1; + + case TEOF: + if (!n1 && (nlflag & 1)) + n1 = NODE_EOF; + parseheredoc(); + return n1; + } + + checkkwd = CHKNL | CHKKWD | CHKALIAS; + if (nlflag == 2 && tokname_array[peektoken()][0]) + return n1; + nlflag |= 2; + n2 = andor(); tok = readtoken(); if (tok == TBACKGND) { @@ -10563,30 +10579,15 @@ list(int nlflag) n1 = n3; } switch (tok) { + case TNL: + case TEOF: + tokpushback = 1; + /* fall through */ case TBACKGND: case TSEMI: - tok = readtoken(); - /* fall through */ - case TNL: - if (tok == TNL) { - parseheredoc(); - if (nlflag == 1) - return n1; - } else { - tokpushback = 1; - } - checkkwd = CHKNL | CHKKWD | CHKALIAS; - if (peektoken()) - return n1; break; - case TEOF: - if (heredoclist) - parseheredoc(); - else - pungetc(); /* push back EOF on input */ - return n1; default: - if (nlflag == 1) + if ((nlflag & 1)) raise_error_unexpected_syntax(-1); tokpushback = 1; return n1; @@ -11954,14 +11955,14 @@ readtoken(void) return t; } -static char +static int peektoken(void) { int t; t = readtoken(); tokpushback = 1; - return tokname_array[t][0]; + return t; } /* @@ -11971,18 +11972,12 @@ peektoken(void) static union node * parsecmd(int interact) { - int t; - tokpushback = 0; + checkkwd = 0; + heredoclist = 0; doprompt = interact; setprompt_if(doprompt, doprompt); needprompt = 0; - t = readtoken(); - if (t == TEOF) - return NODE_EOF; - if (t == TNL) - return NULL; - tokpushback = 1; return list(1); } |