diff --git a/check.t b/check.t index b2f83a8..0e77d4c 100644 --- a/check.t +++ b/check.t @@ -1,4 +1,4 @@ -# $MirOS: src/bin/mksh/check.t,v 1.340 2009/11/21 22:32:05 tg Exp $ +# $MirOS: src/bin/mksh/check.t,v 1.341 2009/11/21 23:23:16 tg Exp $ # $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $ @@ -25,7 +25,7 @@ # http://www.research.att.com/~gsf/public/ifs.sh expected-stdout: - @(#)MIRBSD KSH R39 2009/11/09 + @(#)MIRBSD KSH R39 2009/11/21 description: Check version of shell. stdin: @@ -6680,3 +6680,62 @@ expected-stdout: done expected-stderr-pattern: /.*-x.*option/ --- +name: wcswidth-1 +description: + Check the new wcswidth feature +stdin: + s=何 + set +U + print octets: ${#s} ${%s} . + set -U + print characters: ${#s} . + print columns: ${%s} . +expected-stdout: + octets: 3 3 . + characters: 1 . + columns: 2 . +--- +name: wcswidth-2 +description: + Check some corner cases +stdin: + print % $% . +expected-stdout: + % $% . +--- +name: wcswidth-3 +description: + Check some corner cases +stdin: + print ${%} . +expected-stderr-pattern: + /bad substitution/ +expected-exit: 1 +--- +name: wcswidth-4a +description: + Check some corner cases +stdin: + print ${%*} . +expected-stderr-pattern: + /bad substitution/ +expected-exit: 1 +--- +name: wcswidth-4b +description: + Check some corner cases +stdin: + print ${%@} . +expected-stderr-pattern: + /bad substitution/ +expected-exit: 1 +--- +name: wcswidth-4c +description: + Check some corner cases +stdin: + : + print ${%?} . +expected-stdout: + 1 . +--- diff --git a/eval.c b/eval.c index ccebf57..a8370b5 100644 --- a/eval.c +++ b/eval.c @@ -22,7 +22,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.72 2009/11/21 22:32:08 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.73 2009/11/21 23:23:17 tg Exp $"); /* * string expansion @@ -911,14 +911,20 @@ varsub(Expand *xp, const char *sp, const char *word, struct tbl *vp; bool zero_ok = false; - if (sp[0] == '\0') /* Bad variable name */ + if ((stype = sp[0]) == '\0') /* Bad variable name */ return (-1); xp->var = NULL; - /* ${#var}, string length or array size */ - if (sp[0] == '#' && (c = sp[1]) != '\0') { - /* Can't have any modifiers for ${#...} */ + /*- + * ${#var}, string length (-U: characters, +U: octets) or array size + * ${%var}, string width (-U: screen columns, +U: octets) + */ + c = sp[1]; + if (stype == '%' && c == '\0') + return (-1); + if ((stype == '#' || stype == '%') && c != '\0') { + /* Can't have any modifiers for ${#...} or ${%...} */ if (*word != CSUBST) return (-1); sp++; @@ -927,6 +933,8 @@ varsub(Expand *xp, const char *sp, const char *word, p[2] == ']') { int n = 0; + if (stype != '#') + return (-1); vp = global(arrayname(sp)); if (vp->flag & (ISSET|ARRAY)) zero_ok = true; @@ -934,17 +942,19 @@ varsub(Expand *xp, const char *sp, const char *word, if (vp->flag & ISSET) n++; c = n; - } else if (c == '*' || c == '@') + } else if (c == '*' || c == '@') { + if (stype != '#') + return (-1); c = e->loc->argc; - else { + } else { p = str_val(global(sp)); zero_ok = p != null; - c = utflen(p); + c = stype == '#' ? (int)utflen(p) : utf_mbswidth(p); } if (Flag(FNOUNSET) && c == 0 && !zero_ok) errorf("%s: parameter not set", sp); *stypep = 0; /* unqualified variable/string substitution */ - xp->str = shf_smprintf("%lu", (unsigned long)c); + xp->str = shf_smprintf("%u", (unsigned int)c); return (XSUB); } diff --git a/lex.c b/lex.c index a320a61..c8782a8 100644 --- a/lex.c +++ b/lex.c @@ -22,7 +22,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.100 2009/10/04 12:45:22 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.101 2009/11/21 23:23:18 tg Exp $"); /* * states while lexing word @@ -1548,7 +1548,7 @@ get_brace_var(XString *wsp, char *wp) /* State machine to figure out where the variable part ends. */ switch (state) { case PS_INITIAL: - if (c == '#' || c == '!') { + if (c == '#' || c == '!' || c == '%') { state = PS_SAW_HASH; break; } diff --git a/mksh.1 b/mksh.1 index 3934a9f..a43d7bb 100644 --- a/mksh.1 +++ b/mksh.1 @@ -1,4 +1,4 @@ -.\" $MirOS: src/bin/mksh/mksh.1,v 1.197 2009/11/21 23:21:23 tg Exp $ +.\" $MirOS: src/bin/mksh/mksh.1,v 1.198 2009/11/21 23:23:18 tg Exp $ .\" $OpenBSD: ksh.1,v 1.129 2009/05/28 06:09:06 jmc Exp $ .\"- .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 @@ -1449,6 +1449,12 @@ of the string value of parameter The number of elements in the array .Ar name . .Pp +.It Pf ${% Ns Ar name Ns \&} +The width +.Pq in screen columns +of the string value of parameter +.Ar name . +.Pp .It Pf ${! Ns Ar name Ns } The name of the variable referred to by .Ar name . diff --git a/sh.h b/sh.h index 5ce64af..01bb7a2 100644 --- a/sh.h +++ b/sh.h @@ -134,9 +134,9 @@ #endif #ifdef EXTERN -__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.360 2009/11/09 23:35:11 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.361 2009/11/21 23:23:20 tg Exp $"); #endif -#define MKSH_VERSION "R39 2009/11/09" +#define MKSH_VERSION "R39 2009/11/21" #ifndef MKSH_INCLUDES_ONLY