summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2010-11-18 13:57:18 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2010-11-18 13:57:18 +0000
commit8f20b2361cc2e3911ba67b92f6aa89e7457d17de (patch)
treeb65be3bf863eb33c6118d0b6326be99832049684
parent23bdfc7fd2a012d5205ed22d18eb39e41c8fbc95 (diff)
downloadzsh-8f20b2361cc2e3911ba67b92f6aa89e7457d17de.tar.gz
zsh-8f20b2361cc2e3911ba67b92f6aa89e7457d17de.zip
28419: Doc/Zsh/expn.yo, Src/subst.c, Test/D04parameter.ztst:
KSH_ARRAY ${*:0:1} gives $0, etc.
-rw-r--r--ChangeLog5
-rw-r--r--Doc/Zsh/expn.yo10
-rw-r--r--Src/subst.c36
-rw-r--r--Test/D04parameter.ztst29
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 <pws@csr.com>
+ * 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