summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--Doc/Zsh/expn.yo3
-rw-r--r--Src/subst.c39
3 files changed, 31 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 5d88aff9b..7f8a29e2f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2006-06-28  Peter Stephenson  <pws@csr.com>
 
+	* 22526: Doc/Zsh/expn.yo, Src/subst.c: enhance${(#)...} to output
+	Unicode.
+
 	* 22525: Completion/compinit, Src/hist.c, Src/jobs.c,
 	Src/pattern.c, Src/subst.c, Src/utils.c, Src/zsh.h,
 	Test/D07multibyte.ztst: lengths and cases of multibyte strings
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index 146750098..fe16af735 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -649,6 +649,9 @@ item(tt(#))(
 Evaluate the resulting words as numeric expressions and output the
 characters corresponding to the resulting integer.  Note that this form is
 entirely distinct from use of the tt(#) without parentheses.
+
+If the tt(MULTIBYTE) option is set and the number is greater than 127
+(i.e. not an ASCII character) it is treated as a Unicode character.
 )
 item(tt(%))(
 Expand all tt(%) escapes in the resulting words in the same way as in in
diff --git a/Src/subst.c b/Src/subst.c
index d69f34c4b..12df115a0 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -889,6 +889,29 @@ subst_parse_str(char **sp, int single, int err)
     return 1;
 }
 
+/* Evaluation for (#) flag */
+
+static char *
+substevalchar(char *ptr)
+{
+    zlong ires = mathevali(ptr);
+
+    if (errflag)
+	return NULL;
+    if (isset(MULTIBYTE) && ires > 127) {
+	char buf[10];
+	int dummy;
+
+	/* inefficient: should separate out \U handling from getkeystring */
+	sprintf(buf, "\\U%.8x", (unsigned int)ires);
+	return getkeystring(buf, &dummy, 2, NULL);
+    } else {
+	ptr = zhalloc(2);
+	sprintf(ptr, "%c", (int)ires);
+	return ptr;
+    }
+}
+
 /* parameter substitution */
 
 #define	isstring(c) ((c) == '$' || (char)(c) == String || (char)(c) == Qstring)
@@ -2269,13 +2292,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	/*
 	 * Evaluate the value numerically and output the result as
 	 * a character.
-	 *
-	 * Note this doesn't yet handle Unicode or multibyte characters:
-	 * that will need handling more generally probably by
-	 * an additional flag of some sort.
 	 */
-	zlong ires;
-
 	if (isarr) {
 	    char **aval2, **avptr, **av2ptr;
 
@@ -2283,20 +2300,14 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 
 	    for (avptr = aval, av2ptr = aval2; *avptr; avptr++, av2ptr++)
 	    {
-		ires = mathevali(*avptr);
-		if (errflag)
+		if (!(*av2ptr = substevalchar(*avptr)))
 		    return NULL;
-		*av2ptr = zhalloc(2);
-		sprintf(*av2ptr, "%c", (int)ires);
 	    }
 	    *av2ptr = NULL;
 	    aval = aval2;
 	} else {
-	    ires = mathevali(val);
-	    if (errflag)
+	    if (!(val = substevalchar(val)))
 		return NULL;
-	    val = zhalloc(2);
-	    sprintf(val, "%c", (int)ires);
 	}
     }
     /*