From 8f20b2361cc2e3911ba67b92f6aa89e7457d17de Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 18 Nov 2010 13:57:18 +0000 Subject: 28419: Doc/Zsh/expn.yo, Src/subst.c, Test/D04parameter.ztst: KSH_ARRAY ${*:0:1} gives $0, etc. --- ChangeLog | 5 ++++- Doc/Zsh/expn.yo | 10 ++++++++++ Src/subst.c | 36 ++++++++++++++++++++++++++++++++++-- Test/D04parameter.ztst | 29 +++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 91b8d964d..947b84777 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2010-11-18 Peter Stephenson + * 28419: Doc/Zsh/expn.yo, Src/subst.c, Test/D04parameter.ztst: + KSH_ARRAY ${*:0:1} gives $0 etc. + * 28418: Doc/Zsh/expn.yo, Src/lex.c, Src/params.c, Src/subst.c, Test/D04parameter.ztst: add ${NAME:OFFSET} and ${NAME:OFFSET:LENGTH} substitution syntax. @@ -13825,5 +13828,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5122 $ +* $Revision: 1.5123 $ ***************************************************** diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 6f29a8778..416d46407 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -623,6 +623,16 @@ tt(${)var(name)tt(:-)var(word)tt(}) form of substitution; a space may be inserted before the tt(-). Furthermore, neither var(offset) nor var(length) may begin with an alphabetic character or tt(&) as these are used to indicate history-style modifiers. + +For further compatibility with other shells there is a special case +when the tt(KSH_ARRAYS) option is active, as in emulation of +Bourne-style shells. In this case array subscript 0 usually refers to the +first element of the array. However, if the substitution refers to the +positional parameter array, e.g. tt($@) or tt($*), then offset 0 +instead refers to tt($0), offset 1 refers to tt($1), and so on. In +other words, the positional parameter array is effectively extended by +prepending tt($0). Hence tt(${*:0:1}) substitutes tt($0) and +tt(${*:1:1}) substitutes tt($1). ) xitem(tt(${)var(name)tt(/)var(pattern)tt(/)var(repl)tt(})) item(tt(${)var(name)tt(//)var(pattern)tt(/)var(repl)tt(}))( diff --git a/Src/subst.c b/Src/subst.c index c0fb38a48..23c3a7bb5 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -1636,6 +1636,12 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) * and the argument passing to fetchvalue has another kludge. */ int subexp; + /* + * If we're referring to the positional parameters, then + * e.g ${*:1:1} refers to $1 even if KSH_ARRAYS is in effect. + * This is for compatibility. + */ + int horrible_offset_hack = 0; *s++ = '\0'; /* @@ -2281,6 +2287,12 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) val = getstrvalue(v); } } + /* See if this is a reference to the positional parameters. */ + if (v && v->pm && v->pm->gsu.a == &vararray_gsu && + (char ***)v->pm->u.data == &pparams) + horrible_offset_hack = 1; + else + horrible_offset_hack = 0; /* * Finished with the original parameter and its indices; * carry on looping to see if we need to do more indexing. @@ -2732,6 +2744,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) if (check_offset) { zlong offset = mathevali(check_offset); zlong length = (zlong)-1; + int offset_hack_argzero = 0; if (errflag) return NULL; if ((*check_offset2 && *check_offset2 != ':')) { @@ -2753,8 +2766,21 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) return NULL; } } - if (!isset(KSHARRAYS) && offset > 0) - offset--; + if (!isset(KSHARRAYS) || horrible_offset_hack) { + /* + * As part of the 'orrible hoffset 'ack, + * (what hare you? Han 'orrible hoffset 'ack, + * sergeant major), if we are given a ksh/bash/POSIX + * style array which includes offset 0, we use + * $0. + */ + if (isset(KSHARRAYS) && horrible_offset_hack && + offset == 0 && isarr) { + offset_hack_argzero = 1; + } else if (offset > 0) { + offset--; + } + } if (isarr) { int alen = arrlen(aval), count; char **srcptr, **dstptr, **newarr; @@ -2764,6 +2790,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) if (offset < 0) offset = 0; } + if (offset_hack_argzero) + alen++; if (length < 0) length = alen; if (offset > alen) @@ -2774,6 +2802,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) srcptr = aval + offset; newarr = dstptr = (char **) zhalloc((length+1)*sizeof(char *)); + if (count && offset_hack_argzero) { + *dstptr++ = dupstring(argzero); + count--; + } while (count--) *dstptr++ = dupstring(*srcptr++); *dstptr = (char *)NULL; diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index 7c6a465af..46565a121 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -1302,3 +1302,32 @@ >6 >9 >1 2 3 4 5 6 7 8 9 + + testfn() { + emulate -L sh + set -A foo 1 2 3 + set -- 1 2 3 + str=abc + echo ${foo[*]:0:1} + echo ${foo[*]:1:1} + echo ${foo[*]: -1:1} + : + echo ${*:0:1} + echo ${*:1:1} + echo ${*: -1:1} + : + echo ${str:0:1} + echo ${str:1:1} + echo ${str: -1:1} + } + testfn +0:Bash-style subscripts, Bourne-style indexing +>1 +>2 +>3 +>testfn +>1 +>3 +>a +>b +>c -- cgit 1.4.1