summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2007-08-23 22:04:25 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2007-08-23 22:04:25 +0000
commitdb3ba137b34582a2810b0fb01b6ba451acbc1c9b (patch)
tree6d2f321cc78d9794a139221463bee6d3f89bde9e
parent437f67718cd03f1d2eff2331827c2e225dee4aaf (diff)
downloadzsh-db3ba137b34582a2810b0fb01b6ba451acbc1c9b.tar.gz
zsh-db3ba137b34582a2810b0fb01b6ba451acbc1c9b.tar.xz
zsh-db3ba137b34582a2810b0fb01b6ba451acbc1c9b.zip
23795: improve ${(Q)...} with $'..'
-rw-r--r--ChangeLog5
-rw-r--r--Config/version.mk4
-rw-r--r--Src/lex.c38
-rw-r--r--Test/D04parameter.ztst5
4 files changed, 50 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index a5b9e08f5..e24d47196 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2007-08-23  Peter Stephenson  <p.w.stephenson@ntlworld.com>
+
+	* 23795: Src/lex.c: make ${(Q)...} handle $'...' correctly,
+	up to the problem of long flies in short ointments.
+
 2007-08-23  Peter Stephenson  <pws@csr.com>
 
 	* unposted: Functions/Calendar/calendar_show: used subscript
diff --git a/Config/version.mk b/Config/version.mk
index 3fe2df89a..31848812e 100644
--- a/Config/version.mk
+++ b/Config/version.mk
@@ -27,5 +27,5 @@
 # This must also serve as a shell script, so do not add spaces around the
 # `=' signs.
 
-VERSION=4.3.4-dev-0
-VERSION_DATE='April 19, 2006'
+VERSION=4.3.4-dev-1
+VERSION_DATE='August 1, 2007'
diff --git a/Src/lex.c b/Src/lex.c
index 8bf90847a..a334dc722 100644
--- a/Src/lex.c
+++ b/Src/lex.c
@@ -1556,6 +1556,7 @@ mod_export int
 parse_subst_string(char *s)
 {
     int c, l = strlen(s), err, olen, lexstop_ret;
+    char *ptr;
 
     if (!*s || !strcmp(s, nulstring))
 	return 0;
@@ -1593,6 +1594,43 @@ parse_subst_string(char *s)
 	return 1;
     }
 #endif
+    /* Check for $'...' quoting.  This needs special handling. */
+    for (ptr = s; *ptr; )
+    {
+	if (*ptr == String && ptr[1] == Snull)
+	{
+	    char *t;
+	    int len, tlen, diff;
+	    t = getkeystring(ptr + 2, &len, GETKEYS_DOLLARS_QUOTE, NULL);
+	    len += 2;
+	    tlen = strlen(t);
+	    diff = len - tlen;
+	    /*
+	     * Yuk.
+	     * parse_subst_string() currently handles strings in-place.
+	     * That's not so easy to fix without knowing whether
+	     * additional memory should come off the heap or
+	     * otherwise.  So we cheat by copying the unquoted string
+	     * into place, unless it's too long.  That's not the
+	     * normal case, but I'm worried there are are pathological
+	     * cases with converting metafied multibyte strings.
+	     * If someone can prove there aren't I will be very happy.
+	     */
+	    if (diff < 0) {
+		DPUTS(1, "$'...' subst too long: fix get_parse_string()");
+		return 1;
+	    }
+	    memcpy(ptr, t, tlen);
+	    ptr += tlen;
+	    if (diff > 0) {
+		char *dptr = ptr;
+		char *sptr = ptr + diff;
+		while ((*dptr++ = *sptr++))
+		    ;
+	    }
+	} else
+	    ptr++;
+    }
     return 0;
 }
 
diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst
index 7f229e9a6..1910e60be 100644
--- a/Test/D04parameter.ztst
+++ b/Test/D04parameter.ztst
@@ -320,6 +320,11 @@
 0:${(Q)...}
 >and now even the pubs are shut.
 
+  foo="X$'\x41'$'\x42'Y"
+  print -r ${(Q)foo}
+0:${(Q)...} with handling of $'...'
+>XABY
+
   psvar=(dog)
   setopt promptsubst
   foo='It shouldn'\''t $(happen) to a %1v.'