public inbox for dash@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Handle line continuation in unquoted heredocs
@ 2025-08-07 20:10 Denys Vlasenko
  2025-08-07 20:50 ` Harald van Dijk
  2025-08-28  9:47 ` Herbert Xu
  0 siblings, 2 replies; 3+ messages in thread
From: Denys Vlasenko @ 2025-08-07 20:10 UTC (permalink / raw)
  To: dash, Herbert Xu; +Cc: Denys Vlasenko

Testcases:

cat <<nice
heredoc1
ni\
ce
nice # this isn't heredoc end, the end is above

cat <<-nice
	heredoc2
	\
	ni\
ce
nice # this isn't heredoc end, the end is above

cat <<"nice"
heredoc3
ni\
ce
nice

cat <<-"nice"
	heredoc4
	\
	ni\
ce
	nice

Correct output:

heredoc1
0
heredoc2
0
heredoc3
ni\
ce
heredoc4
\
ni\
ce

Before patch, cases 1 and 2 are mishandled.

A more simplistic apparent solution for cases 1 and 2,
s/pgetc/pgetc_eatbnl/, breaks cases 3 and 4

Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
---
 src/parser.c | 33 ++++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/src/parser.c b/src/parser.c
index aecc18f..edef0ba 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -74,7 +74,7 @@
 
 
 /* Used by expandstr to get here-doc like behaviour. */
-#define FAKEEOFMARK (char *)1
+#define FAKEEOFMARK (struct heredoc *)1
 
 
 
@@ -123,7 +123,7 @@ STATIC void parseheredoc(void);
 STATIC int readtoken(void);
 STATIC int xxreadtoken(void);
 STATIC int pgetc_eatbnl();
-STATIC int readtoken1(int, char const *, char *, int);
+STATIC int readtoken1(int, char const *, struct heredoc *);
 STATIC void synexpect(int) __attribute__((__noreturn__));
 STATIC void synerror(const char *) __attribute__((__noreturn__));
 STATIC void setprompt(int);
@@ -143,7 +143,7 @@ int issimplecmd(union node *n, const char *name)
 	       equal(n->ncmd.args->narg.text, name);
 }
 
-static inline int realeofmark(const char *eofmark)
+static inline int realeofmark(struct heredoc *eofmark)
 {
 	return eofmark && eofmark != FAKEEOFMARK;
 }
@@ -685,9 +685,9 @@ parseheredoc(void)
 			setprompt(2);
 		}
 		if (here->here->type == NHERE)
-			readtoken1(pgetc(), SQSYNTAX, here->eofmark, here->striptabs);
+			readtoken1(pgetc(), SQSYNTAX, here);
 		else
-			readtoken1(pgetc_eatbnl(), DQSYNTAX, here->eofmark, here->striptabs);
+			readtoken1(pgetc_eatbnl(), DQSYNTAX, here);
 		n = (union node *)stalloc(sizeof (struct narg));
 		n->narg.type = NARG;
 		n->narg.next = NULL;
@@ -840,7 +840,7 @@ xxreadtoken(void)
 		case ')':
 			RETURN(TRP);
 		}
-		tok = readtoken1(c, BASESYNTAX, (char *)NULL, 0);
+		tok = readtoken1(c, BASESYNTAX, (struct heredoc *)NULL);
 		if (tok != TBLANK)
 			return tok;
 	}
@@ -994,7 +994,7 @@ static char *dollarsq_escape(char *out)
 #define	PARSEARITH()	{goto parsearith; parsearith_return:;}
 
 STATIC int
-readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs)
+readtoken1(int firstc, char const *syntax, struct heredoc *eofmark)
 {
 	struct synstack synbase = { .syntax = syntax };
 	int chkeofmark = checkkwd & CHKEOFMARK;
@@ -1233,17 +1233,24 @@ checkend: {
 		int markloc;
 		char *p;
 
-		if (striptabs) {
-			while (c == '\t')
-				c = pgetc();
+		if (eofmark->striptabs) {
+			while (c == '\t') {
+				if (eofmark->here->type == NHERE)
+					c = pgetc();
+				else /* NXHERE */
+					c = pgetc_eatbnl();
+			}
 		}
 
 		markloc = out - (char *)stackblock();
-		for (p = eofmark; STPUTC(c, out), *p; p++) {
+		for (p = eofmark->eofmark; STPUTC(c, out), *p; p++) {
 			if (c != *p)
 				goto more_heredoc;
 
-			c = pgetc();
+			if (eofmark->here->type == NHERE)
+				c = pgetc();
+			else /* NXHERE */
+				c = pgetc_eatbnl();
 		}
 
 		if (c == '\n' || c == PEOF) {
@@ -1748,7 +1755,7 @@ expandstr(const char *ps)
 		goto out;
 	handler = &jmploc;
 
-	readtoken1(pgetc_eatbnl(), DQSYNTAX, FAKEEOFMARK, 0);
+	readtoken1(pgetc_eatbnl(), DQSYNTAX, FAKEEOFMARK);
 
 	n.narg.type = NARG;
 	n.narg.next = NULL;
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2025-08-28  9:47 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-07 20:10 [PATCH] Handle line continuation in unquoted heredocs Denys Vlasenko
2025-08-07 20:50 ` Harald van Dijk
2025-08-28  9:47 ` Herbert Xu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox