[PATCH 3/3] ash: simplify EOF/newline handling in list parser

Ron Yorston rmy at pobox.com
Thu Oct 29 11:30:55 UTC 2015


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 at alpinelinux.org>
Signed-off-by: Ron Yorston <rmy at pobox.com>
---
 shell/ash.c | 63 ++++++++++++++++++++++++++++---------------------------------
 1 file changed, 29 insertions(+), 34 deletions(-)

diff --git a/shell/ash.c b/shell/ash.c
index 86d648a..9d0226c 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -10516,7 +10516,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 *
@@ -10525,11 +10525,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) {
@@ -10555,30 +10571,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;
@@ -11947,14 +11948,14 @@ readtoken(void)
 	return t;
 }
 
-static char
+static int
 peektoken(void)
 {
 	int t;
 
 	t = readtoken();
 	tokpushback = 1;
-	return tokname_array[t][0];
+	return t;
 }
 
 /*
@@ -11964,18 +11965,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);
 }
 
-- 
2.4.3



More information about the busybox mailing list