about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2010-02-27 00:18:13 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2010-02-27 00:18:13 +0000
commit21193d7f0128dc66f4c41c7b06d1d20c5b9339fc (patch)
tree63fef850d047a07a8bd31b5c8cca124f8e74297e /Src
parent31123a118472ee4e4afbfae5dff904bb40113e65 (diff)
downloadzsh-21193d7f0128dc66f4c41c7b06d1d20c5b9339fc.tar.gz
zsh-21193d7f0128dc66f4c41c7b06d1d20c5b9339fc.tar.xz
zsh-21193d7f0128dc66f4c41c7b06d1d20c5b9339fc.zip
users/14905 + 14906: problems with :s in parameter expansion
Diffstat (limited to 'Src')
-rw-r--r--Src/subst.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/Src/subst.c b/Src/subst.c
index 462d0b3a0..a5ed289be 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -3282,6 +3282,13 @@ modify(char **str, char **ptr)
 		ptr1 += charlen;
 		for (ptr2 = ptr1, charlen = 0; *ptr2; ptr2 += charlen) {
 		    convchar_t del2;
+		    if ((*ptr2 == Bnull || *ptr2 == '\\') && ptr2[1]) {
+			/* in double quotes, the backslash isn't tokenized */
+			if (*ptr2 == '\\')
+			    *ptr2 = Bnull;
+			charlen = 2;
+			continue;
+		    }
 		    charlen = MB_METACHARLENCONV(ptr2, &del2);
 #ifdef MULTIBYTE_SUPPORT
 		    if (del2 == WEOF)
@@ -3301,6 +3308,13 @@ modify(char **str, char **ptr)
 		*ptr1end = '\0';
 		for (ptr3 = ptr2, charlen = 0; *ptr3; ptr3 += charlen) {
 		    convchar_t del3;
+		    if ((*ptr3 == Bnull || *ptr3 == '\\') && ptr3[1]) {
+			/* in double quotes, the backslash isn't tokenized */
+			if (*ptr3 == '\\')
+			    *ptr3 = Bnull;
+			charlen = 2;
+			continue;
+		    }
 		    charlen = MB_METACHARLENCONV(ptr3, &del3);
 #ifdef MULTIBYTE_SUPPORT
 		    if (del3 == WEOF)
@@ -3326,9 +3340,20 @@ modify(char **str, char **ptr)
 			chuck(tt--);
 		if (!isset(HISTSUBSTPATTERN))
 		    untokenize(hsubl);
-		for (tt = hsubr = ztrdup(ptr2); *tt; tt++)
-		    if (inull(*tt) && *tt != Bnullkeep)
-			chuck(tt--);
+		for (tt = hsubr = ztrdup(ptr2); *tt; tt++) {
+		    if (inull(*tt) && *tt != Bnullkeep) {
+			if (*tt == Bnull && (tt[1] == '&' || tt[1] == '\\')) {
+			    /*
+			     * The substitution will treat \& and \\
+			     * specially.  We need to leave real \'s
+			     * as the first character for this to work.
+			     */
+			    *tt = '\\';
+			} else {
+			    chuck(tt--);
+			}
+		    }
+		}
 		*ptr1end = sav1;
 		*ptr3 = sav;
 		*ptr = ptr3 - 1;