summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2011-05-07 14:32:16 +0000
committerjilles <jilles@FreeBSD.org>2011-05-07 14:32:16 +0000
commit8bbce85526c337676cfa1f717dac02d86742cf0a (patch)
tree56cf1ceba22fd77045407a8fa8188f0feeecf4b6
parent11604ee85b5b347285de99920d04978997c18508 (diff)
downloadFreeBSD-src-8bbce85526c337676cfa1f717dac02d86742cf0a.zip
FreeBSD-src-8bbce85526c337676cfa1f717dac02d86742cf0a.tar.gz
sh: Add UTF-8 support to ${#var}.
If the current locale uses UTF-8, ${#var} counts codepoints (more precisely, bytes b with (b & 0xc0) != 0x80).
-rw-r--r--bin/sh/expand.c16
-rw-r--r--tools/regression/bin/sh/expansion/length7.014
-rw-r--r--tools/regression/bin/sh/expansion/length8.014
3 files changed, 41 insertions, 3 deletions
diff --git a/bin/sh/expand.c b/bin/sh/expand.c
index c343977..dcef74e 100644
--- a/bin/sh/expand.c
+++ b/bin/sh/expand.c
@@ -665,6 +665,7 @@ evalvar(char *p, int flag)
int special;
int startloc;
int varlen;
+ int varlenb;
int easy;
int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
@@ -712,8 +713,15 @@ again: /* jump here after setting a variable with ${var=text} */
if (special) {
varvalue(var, varflags & VSQUOTE, subtype, flag);
if (subtype == VSLENGTH) {
- varlen = expdest - stackblock() - startloc;
- STADJUST(-varlen, expdest);
+ varlenb = expdest - stackblock() - startloc;
+ varlen = varlenb;
+ if (localeisutf8) {
+ val = stackblock() + startloc;
+ for (;val != expdest; val++)
+ if ((*val & 0xC0) == 0x80)
+ varlen--;
+ }
+ STADJUST(-varlenb, expdest);
}
} else {
char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX
@@ -721,7 +729,9 @@ again: /* jump here after setting a variable with ${var=text} */
if (subtype == VSLENGTH) {
for (;*val; val++)
- varlen++;
+ if (!localeisutf8 ||
+ (*val & 0xC0) != 0x80)
+ varlen++;
}
else {
if (quotes)
diff --git a/tools/regression/bin/sh/expansion/length7.0 b/tools/regression/bin/sh/expansion/length7.0
new file mode 100644
index 0000000..b79b116
--- /dev/null
+++ b/tools/regression/bin/sh/expansion/length7.0
@@ -0,0 +1,14 @@
+# $FreeBSD$
+
+unset LC_ALL
+LC_CTYPE=en_US.UTF-8
+export LC_CTYPE
+
+# a umlaut
+s=$(printf '\303\244')
+# euro sign
+s=$s$(printf '\342\202\254')
+# some sort of 't' outside BMP
+s=$s$(printf '\360\235\225\245')
+set -- "$s"
+[ ${#s} = 3 ] && [ ${#1} = 3 ]
diff --git a/tools/regression/bin/sh/expansion/length8.0 b/tools/regression/bin/sh/expansion/length8.0
new file mode 100644
index 0000000..3cc6c15
--- /dev/null
+++ b/tools/regression/bin/sh/expansion/length8.0
@@ -0,0 +1,14 @@
+# $FreeBSD$
+
+unset LC_ALL
+LC_CTYPE=en_US.ISO8859-1
+export LC_CTYPE
+
+# a umlaut
+s=$(printf '\303\244')
+# euro sign
+s=$s$(printf '\342\202\254')
+# some sort of 't' outside BMP
+s=$s$(printf '\360\235\225\245')
+set -- "$s"
+[ ${#s} = 9 ] && [ ${#1} = 9 ]
OpenPOWER on IntegriCloud