about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Doc/Zsh/expn.yo4
-rw-r--r--Src/subst.c13
-rw-r--r--Src/utils.c26
3 files changed, 31 insertions, 12 deletions
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index da6b43cb8..1008ea4ae 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -584,7 +584,9 @@ that result from field splitting.
 item(tt(q))(
 Quote the resulting words with backslashes. If this flag is given
 twice, the resulting words are quoted in single quotes and if it is
-given three times, the words are quoted in double quotes.
+given three times, the words are quoted in double quotes. If it is
+given four times, no real quoting is done, but any special characters
+in the resulting words will be in a human-readable form.
 )
 item(tt(Q))(
 Remove one level of quotes from the resulting words.
diff --git a/Src/subst.c b/Src/subst.c
index 5b08d0bfb..45b58aef6 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -1618,8 +1618,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	opts[PROMPTPERCENT] = opp;
     }
     if (quotemod) {
-	if (--quotetype > 2)
-	    quotetype = 2;
+	if (--quotetype > 3)
+	    quotetype = 3;
 	if (isarr) {
 	    char **ap;
 
@@ -1628,7 +1628,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	    ap = aval;
 
 	    if (quotemod > 0) {
-		if (quotetype) {
+		if (quotetype == 3)
+		    for (; *ap; ap++)
+			*ap = nicedupstring(*ap);
+		else if (quotetype) {
 		    int sl;
 		    char *tmp;
 
@@ -1665,7 +1668,9 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	    if (!copied)
 		val = dupstring(val), copied = 1;
 	    if (quotemod > 0) {
-		if (quotetype) {
+		if (quotetype == 3)
+		    val = nicedupstring(val);
+		else if (quotetype) {
 		    int sl;
 		    char *tmp;
 
diff --git a/Src/utils.c b/Src/utils.c
index 38276faee..da4bcffaa 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -2867,12 +2867,12 @@ zputs(char const *s, FILE *stream)
 /* Create a visibly-represented duplicate of a string. */
 
 /**/
-char *
-niceztrdup(char const *s)
+static char *
+nicedup(char const *s, int heap)
 {
     int c, len = strlen(s) * 5;
-    char *buf = zalloc(len);
-    char *p = buf, *n, *ret;
+    VARARR(char, buf, len);
+    char *p = buf, *n;
 
     while ((c = *s++)) {
 	if (itok(c)) {
@@ -2887,9 +2887,21 @@ niceztrdup(char const *s)
 	while(*n)
 	    *p++ = *n++;
     }
-    ret = metafy(buf, p - buf, META_DUP);
-    zfree(buf, len);
-    return ret;
+    return metafy(buf, p - buf, (heap ? META_HEAPDUP : META_DUP));
+}
+
+/**/
+char *
+niceztrdup(char const *s)
+{
+    return nicedup(s, 0);
+}
+
+/**/
+char *
+nicedupstring(char const *s)
+{
+    return nicedup(s, 1);
 }
 
 /* Unmetafy and output a string, displaying special characters readably. */