summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2005-10-11 16:48:05 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2005-10-11 16:48:05 +0000
commitcca66ab341ffa330908aa6ea8da03e991aa6903c (patch)
tree0b15ce734ec264fdd72c27d68e48bc65bdaf6d14
parent1eaa7fee0d111b999c44385eb4fda1ad604e3606 (diff)
downloadzsh-cca66ab341ffa330908aa6ea8da03e991aa6903c.tar.gz
zsh-cca66ab341ffa330908aa6ea8da03e991aa6903c.zip
21862/21863: GLOB_SUBST shouldn't swallow up backslashes in parameter
substitutions that don't match anything.
-rw-r--r--ChangeLog7
-rw-r--r--Src/glob.c40
-rw-r--r--Src/lex.c2
-rw-r--r--Src/pattern.c13
-rw-r--r--Src/subst.c6
-rw-r--r--Src/zsh.h29
-rw-r--r--Test/D04parameter.ztst14
-rwxr-xr-xTest/ztst.zsh2
8 files changed, 92 insertions, 21 deletions
diff --git a/ChangeLog b/ChangeLog
index b082f2c0f..3806ac2cc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2005-10-11 Peter Stephenson <pws@csr.com>
+
+ * 21862/21863: Src/glob.c, Src/lex.c, Src/pattern.c, Src/subst.c,
+ Src/zsh.h, Test/D04parameter.ztst, Test/ztst.zsh: Ensure that
+ backslashes in parameters substituted by GLOB_SUBST are not
+ swallowed up if there is no pattern match.
+
2005-10-07 Peter Stephenson <pws@csr.com>
* Stephen RĂ¼ger: 21846: Completion/Unix/Command/_chmod: too
diff --git a/Src/glob.c b/Src/glob.c
index 93d5e3312..be2dcd5ec 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -2487,19 +2487,29 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr)
mod_export void
tokenize(char *s)
{
- zshtokenize(s, 0);
+ zshtokenize(s, 0, 0);
}
+/*
+ * shtokenize is used when we tokenize a string with GLOB_SUBST set.
+ * In that case we need to retain backslashes when we turn the
+ * pattern back into a string, so that the string is not
+ * modified if it failed to match a pattern.
+ *
+ * It may be modified by the effect of SH_GLOB which turns off
+ * various zsh-specific options.
+ */
+
/**/
mod_export void
shtokenize(char *s)
{
- zshtokenize(s, isset(SHGLOB));
+ zshtokenize(s, 1, isset(SHGLOB));
}
/**/
static void
-zshtokenize(char *s, int shglob)
+zshtokenize(char *s, int glbsbst, int shglob)
{
char *t;
int bslash = 0;
@@ -2508,9 +2518,10 @@ zshtokenize(char *s, int shglob)
cont:
switch (*s) {
case Bnull:
+ case Bnullkeep:
case '\\':
if (bslash) {
- s[-1] = Bnull;
+ s[-1] = glbsbst ? Bnullkeep : Bnull;
break;
}
bslash = 1;
@@ -2519,7 +2530,7 @@ zshtokenize(char *s, int shglob)
if (shglob)
break;
if (bslash) {
- s[-1] = Bnull;
+ s[-1] = glbsbst ? Bnullkeep : Bnull;
break;
}
t = s;
@@ -2549,7 +2560,7 @@ zshtokenize(char *s, int shglob)
for (t = ztokens; *t; t++)
if (*t == *s) {
if (bslash)
- s[-1] = Bnull;
+ s[-1] = glbsbst ? Bnullkeep : Bnull;
else
*s = (t - ztokens) + Pound;
break;
@@ -2569,12 +2580,23 @@ remnulargs(char *s)
char *o = s, c;
while ((c = *s++))
- if (INULL(c)) {
+ if (c == Bnullkeep) {
+ /*
+ * An active backslash that needs to be turned back into
+ * a real backslash for output. However, we don't
+ * do that yet since we need to ignore it during
+ * pattern matching.
+ */
+ continue;
+ } else if (INULL(c)) {
char *t = s - 1;
- while ((c = *s++))
- if (!INULL(c))
+ while ((c = *s++)) {
+ if (c == Bnullkeep)
+ *t++ = '\\';
+ else if (!INULL(c))
*t++ = c;
+ }
*t = '\0';
if (!*o) {
o[0] = Nularg;
diff --git a/Src/lex.c b/Src/lex.c
index bf2adb1dc..3ab099daf 100644
--- a/Src/lex.c
+++ b/Src/lex.c
@@ -33,7 +33,7 @@
/* tokens */
/**/
-mod_export char ztokens[] = "#$^*()$=|{}[]`<>?~`,'\"\\";
+mod_export char ztokens[] = "#$^*()$=|{}[]`<>?~`,'\"\\\\";
/* parts of the current token */
diff --git a/Src/pattern.c b/Src/pattern.c
index 36578226c..aa95a46bd 100644
--- a/Src/pattern.c
+++ b/Src/pattern.c
@@ -260,13 +260,13 @@ static char endseg[] = {
static char endstr[] = {
'/', /* file only */
- '\0', Bar, Outpar, Quest, Star, Inbrack, Inpar, Inang,
+ '\0', Bar, Outpar, Quest, Star, Inbrack, Inpar, Inang, Bnullkeep,
/* all patterns */
Tilde, Hat, Pound /* extended glob only */
};
-#define PATENDSTRLEN_NORM 9
-#define PATENDSTRLEN_EXT 12
+#define PATENDSTRLEN_NORM 10
+#define PATENDSTRLEN_EXT 13
/* Default size for pattern buffer */
@@ -1240,6 +1240,13 @@ patcomppiece(int *flagp)
*/
return 0;
break;
+ case Bnullkeep:
+ /*
+ * Marker for restoring a backslash in output:
+ * does not match a character.
+ */
+ return patcomppiece(flagp);
+ break;
#ifdef DEBUG
default:
dputs("BUG: character not handled in patcomppiece");
diff --git a/Src/subst.c b/Src/subst.c
index defb53bd9..67de61418 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -1945,7 +1945,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
*/
for (ptr = s; (c = *ptr) && c != '/'; ptr++)
{
- if ((c == Bnull || c == '\\') && ptr[1])
+ if ((c == Bnull || c == Bnullkeep || c == '\\') && ptr[1])
{
if (ptr[1] == '/')
chuck(ptr);
@@ -2846,11 +2846,11 @@ modify(char **str, char **ptr)
}
zsfree(hsubr);
for (tt = hsubl; *tt; tt++)
- if (INULL(*tt))
+ if (INULL(*tt) && *tt != Bnullkeep)
chuck(tt--);
untokenize(hsubl);
for (tt = hsubr = ztrdup(ptr2); *tt; tt++)
- if (INULL(*tt))
+ if (INULL(*tt) && *tt != Bnullkeep)
chuck(tt--);
ptr2[-1] = del;
if (sav)
diff --git a/Src/zsh.h b/Src/zsh.h
index b10f0bea2..19cfe216d 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -120,7 +120,10 @@ struct mathfunc {
#define DEFAULT_IFS " \t\n\203 "
-/* Character tokens */
+/*
+ * Character tokens.
+ * These should match the characters in ztokens, defined in lex.c
+ */
#define Pound ((char) 0x84)
#define String ((char) 0x85)
#define Hat ((char) 0x86)
@@ -141,15 +144,33 @@ struct mathfunc {
#define Tilde ((char) 0x95)
#define Qtick ((char) 0x96)
#define Comma ((char) 0x97)
+/*
+ * Null arguments: placeholders for single and double quotes
+ * and backslashes.
+ */
#define Snull ((char) 0x98)
#define Dnull ((char) 0x99)
#define Bnull ((char) 0x9a)
-#define Nularg ((char) 0x9b)
+/*
+ * Backslash which will be returned to "\" instead of being stripped
+ * when we turn the string into a printable format.
+ */
+#define Bnullkeep ((char) 0x9b)
+/*
+ * Null argument that does not correspond to any character.
+ * This should be last as it does not appear in ztokens and
+ * is used to initialise the IMETA type in inittyptab().
+ */
+#define Nularg ((char) 0x9c)
-#define INULL(x) (((x) & 0xfc) == 0x98)
+#define INULL(x) (((x) & 0xf8) == 0x98)
+/*
+ * Take care to update the use of IMETA appropriately when adding
+ * tokens here.
+ */
/* Marker used in paramsubst for rc_expand_param */
-#define Marker ((char) 0x9c)
+#define Marker ((char) 0xa0)
/* chars that need to be quoted if meant literally */
diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst
index 3ad19368d..6abba0ab3 100644
--- a/Test/D04parameter.ztst
+++ b/Test/D04parameter.ztst
@@ -196,6 +196,20 @@
>* boringfile evenmoreboringfile boringfile evenmoreboringfile
>boringfile evenmoreboringfile
+# The following tests a bug where globsubst didn't preserve
+# backslashes when printing out the original string.
+ str1='\\*\\'
+ (
+ setopt globsubst nonomatch
+ [[ \\\\ = $str1 ]] && print -r '\\ matched by' $str1
+ [[ \\foo\\ = $str1 ]] && print -r '\\foo matched by' $str1
+ [[ a\\b\\ = $str1 ]] || print -r 'a\\b not matched by' $str1
+ )
+0:globsubst with backslashes
+>\\ matched by \\*\\
+>\\foo matched by \\*\\
+>a\\b not matched by \\*\\
+
print -l "${$(print one word)}" "${=$(print two words)}"
0:splitting of $(...) inside ${...}
>one word
diff --git a/Test/ztst.zsh b/Test/ztst.zsh
index 0f0c704c7..c0fbc179f 100755
--- a/Test/ztst.zsh
+++ b/Test/ztst.zsh
@@ -280,7 +280,7 @@ ZTST_diff() {
diff_out=$(diff "$@")
diff_ret="$?"
if [[ "$diff_ret" != "0" ]]; then
- echo "$diff_out"
+ print -r "$diff_out"
fi
return "$diff_ret"