On Wed, Feb 21, 2018 at 11:47:58PM +0100, Harald van Dijk wrote:
> On 2/21/18 2:50 PM, Denys Vlasenko wrote:
> >I propose replacing this:
>
> Agreed, that looks better. Thanks!
Good work guys. However, could you check to see if this patch
works too? It passes all my tests so far.
---8<---
The commit "[EXPAND] Move parse-time quote flag detection to
run-time" broke the following case:
case \\zzzz in "\*") echo bad;; esac
The reason is that the naked backslash gets attached to the newly
added backslash added for the special character "*" in preglob,
IOW you end up with "\\*" instead of just "\*" as it should be.
The reason the naked backslash exists in the first place is because
otherwise we cannot tell the difference between "\[" and "\\[" when
it occurs in a quoted pattern context such as "${var#\[}"
This patch restores the original behaviour for the buggy case
while keeping the naked backslash for the quoted pattern case.
Fixes: 7cfd8be0dc83 ("[EXPAND] Move parse-time quote flag...")
Reported-by: Denys Vlasenko <[email protected]>
Suggested-by: Harald van Dijk <[email protected]>
Signed-off-by: Herbert Xu <[email protected]>
diff --git a/src/Makefile.am b/src/Makefile.am
index 139355e..b5bff06 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -60,7 +60,7 @@ init.c: mkinit $(dash_CFILES)
nodes.c nodes.h: mknodes nodetypes nodes.c.pat
./$^
-syntax.c syntax.h: mksyntax
+syntax.c syntax.h: mksyntax parser.h
./$^
signames.c: mksignames
diff --git a/src/expand.c b/src/expand.c
index 2a50830..aeffe82 100644
--- a/src/expand.c
+++ b/src/expand.c
@@ -244,6 +244,7 @@ argstr(char *p, int flag)
CTLVAR,
CTLBACKQ,
CTLENDARI,
+ CTLBACK,
0
};
const char *reject = spclchars;
@@ -330,6 +331,7 @@ addquote:
startloc++;
}
break;
+ case CTLBACK:
case CTLESC:
startloc++;
length++;
@@ -340,7 +342,7 @@ addquote:
* backslash.
*/
if (((flag | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
- EXP_QPAT && *p != '\\')
+ EXP_QPAT && (*p != '\\' || c == CTLBACK))
break;
goto addquote;
@@ -373,6 +375,7 @@ exptilde(char *startp, char *p, int flag)
while ((c = *++p) != '\0') {
switch(c) {
+ case CTLBACK:
case CTLESC:
return (startp);
case CTLQUOTEMARK:
@@ -594,7 +597,7 @@ scanleft(
*loc2 = c;
if (match)
return loc;
- if (quotes && *loc == (char)CTLESC)
+ if (quotes && (*loc == (char)CTLESC || *loc == (char)CTLBACK))
loc++;
loc++;
loc2++;
@@ -821,7 +824,8 @@ end:
if (subtype != VSNORMAL) { /* skip to end of alternative */
int nesting = 1;
for (;;) {
- if ((c = (signed char)*p++) == CTLESC)
+ if ((c = (signed char)*p++) == CTLESC ||
+ c == CTLBACK)
p++;
else if (c == CTLBACKQ) {
if (varlen >= 0)
@@ -1052,7 +1056,7 @@ ifsbreakup(char *string, int maxargs, struct arglist
*arglist)
q = p;
c = *p++;
- if (c == (char)CTLESC)
+ if (c == (char)CTLESC || c == (char)CTLBACK)
c = *p++;
isifs = strchr(ifs, c);
@@ -1684,7 +1688,7 @@ _rmescapes(char *str, int flag)
notescaped = globbing;
continue;
}
- if (*p == (char)CTLESC) {
+ if (*p == (char)CTLESC || *p == (char)CTLBACK) {
p++;
if (notescaped)
*q++ = '\\';
diff --git a/src/jobs.c b/src/jobs.c
index 4f02e38..a3aef20 100644
--- a/src/jobs.c
+++ b/src/jobs.c
@@ -1386,6 +1386,7 @@ cmdputs(const char *s)
while ((c = *p++) != 0) {
str = 0;
switch (c) {
+ case CTLBACK:
case CTLESC:
c = *p++;
break;
diff --git a/src/mystring.c b/src/mystring.c
index 0106bd2..2573d1f 100644
--- a/src/mystring.c
+++ b/src/mystring.c
@@ -62,7 +62,7 @@ const char spcstr[] = " ";
const char snlfmt[] = "%s\n";
const char dolatstr[] = { CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=',
CTLQUOTEMARK, '\0' };
-const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
+const char qchars[] = { CTLESC, CTLQUOTEMARK, CTLBACK, 0 };
const char illnum[] = "Illegal number: %s";
const char homestr[] = "HOME";
diff --git a/src/parser.c b/src/parser.c
index 382658e..22fc84a 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -930,7 +930,7 @@ readtoken1(int firstc, char const *syntax, char *eofmark,
int striptabs)
case CBACK:
c = pgetc2();
if (c == PEOF) {
- USTPUTC(CTLESC, out);
+ USTPUTC(CTLBACK, out);
USTPUTC('\\', out);
pungetc();
} else if (c == '\n') {
@@ -944,6 +944,7 @@ readtoken1(int firstc, char const *syntax, char *eofmark,
int striptabs)
eofmark != NULL
)
) {
+ USTPUTC(CTLBACK, out);
USTPUTC('\\', out);
}
USTPUTC(CTLESC, out);
diff --git a/src/parser.h b/src/parser.h
index 2875cce..54c02eb 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -45,7 +45,8 @@
#define CTLARI -122 /* arithmetic expression */
#define CTLENDARI -121
#define CTLQUOTEMARK -120
-#define CTL_LAST -120 /* last 'special' character */
+#define CTLBACK -119
+#define CTL_LAST -119 /* last 'special' character */
/* variable substitution byte (follows CTLVAR) */
#define VSTYPE 0x0f /* type of variable substitution */
diff --git a/src/show.c b/src/show.c
index 4a049e9..ed840aa 100644
--- a/src/show.c
+++ b/src/show.c
@@ -166,6 +166,7 @@ sharg(union node *arg, FILE *fp)
bqlist = arg->narg.backquote;
for (p = arg->narg.text ; *p ; p++) {
switch ((signed char)*p) {
+ case CTLBACK:
case CTLESC:
putc(*++p, fp);
break;
@@ -311,6 +312,7 @@ trstring(char *s)
case '\r': c = 'r'; goto backslash;
case '"': c = '"'; goto backslash;
case '\\': c = '\\'; goto backslash;
+ case CTLBACK:
case CTLESC: c = 'e'; goto backslash;
case CTLVAR: c = 'v'; goto backslash;
case CTLBACKQ: c = 'q'; goto backslash;
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line "unsubscribe dash" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html