Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
PATCH: support negative LEN in ${VAR:OFFSET:LEN}
- X-seq: zsh-workers 29224
- From: Mikael Magnusson <mikachu@xxxxxxxxx>
- To: zsh-workers@xxxxxxx
- Subject: PATCH: support negative LEN in ${VAR:OFFSET:LEN}
- Date: Wed, 11 May 2011 17:39:33 +0200
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:from:to:subject:date:message-id:x-mailer :in-reply-to:references; bh=agJ7PVDblAFgofejCz2tbtLnFlGZ8lkpfUIxzfowKOo=; b=o5YZ97/Q9jW/L5dkFcToq0iLPFy2cQJWpPxKZeLgH9iPb2IZs3BcWzbOVwBcMj7Gw0 ou/q9JXU8va7dtyX/77Dhewe4/LfynN1J+XsYnHjDb3TyEA73eYJ2YTxve+6q72clfmx EyBXuJxfqNOD1YNF0erea22BeUvteVIfw5b80=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:subject:date:message-id:x-mailer:in-reply-to:references; b=kRKpUXIGkDypeKUbKYZc2lHJvNvMEB8hNOMB/2Sr5uAEK9eNuwwuVXQiQLSS8k/aVp tn1Y6heDBALNALnnvST77BOclyZ+qeHpC4LDBBKqQguqh22EDPDafOtKKx0sceNK/ZXg PhouCUSkSIyMxhy+mxPOwkk3aEMSucB6g9UL8=
- In-reply-to: <110316092120.ZM19292@torch.brasslantern.com>
- List-help: <mailto:zsh-workers-help@zsh.org>
- List-id: Zsh Workers List <zsh-workers.zsh.org>
- List-post: <mailto:zsh-workers@zsh.org>
- Mailing-list: contact zsh-workers-help@xxxxxxx; run by ezmlm
- References: <110316092120.ZM19292@torch.brasslantern.com>
Updated with your docs and error messages.
% echo ${path:10:-5}
zsh: substring expression: 8 < 10
% echo ${PATH:150:-150}
zsh: substring expression: 85 < 150
---
Doc/Zsh/expn.yo | 12 ++++++++----
Src/subst.c | 40 +++++++++++++++++++++++++++++++---------
Test/D04parameter.ztst | 14 ++++++++++++++
3 files changed, 53 insertions(+), 13 deletions(-)
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index 3a1c372..5d69dbd 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -588,7 +588,7 @@ remove the non-matched elements).
xitem(tt(${)var(name)tt(:)var(offset)tt(}))
item(tt(${)var(name)tt(:)var(offset)tt(:)var(length)tt(}))(
This syntax gives effects similar to parameter subscripting
-in the form tt($)var(name)tt({)var(start)tt(,)var(end)tt(}), but is
+in the form tt($)var(name)tt([)var(start)tt(,)var(end)tt(]), but is
compatible with other shells; note that both var(offset) and var(length)
are interpreted differently from the components of a subscript.
@@ -608,8 +608,12 @@ the option tt(KSH_ARRAYS).
A negative offset counts backwards from the end of the scalar or array,
so that -1 corresponds to the last character or element, and so on.
-var(length) is always treated directly as a length and hence may not be
-negative. The option tt(MULTIBYTE) is obeyed, i.e. the offset and length
+When positive, var(length) counts from the var(offset) position
+toward the end of the scalar or array. When negative, var(length)
+counts back from the end. If this results in a position smaller
+than var(offset), a diagnostic is printed and nothing is substituted.
+
+The option tt(MULTIBYTE) is obeyed, i.e. the offset and length
count multibyte characters where appropriate.
var(offset) and var(length) undergo the same set of shell substitutions
@@ -635,7 +639,7 @@ tt(${)var(name)tt(:-)var(word)tt(}) form of substitution. Instead, 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. To substitute a value from a
-variable, the recommended approach is to proceed it with a tt($) as this
+variable, the recommended approach is to precede it with a tt($) as this
signifies the intention (parameter substitution can easily be rendered
unreadable); however, as arithmetic substitution is performed, the
expression tt(${var: offs}) does work, retrieving the offset from
diff --git a/Src/subst.c b/Src/subst.c
index 723bb25..ce4dbe6 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -2834,7 +2834,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
char *check_offset = check_colon_subscript(s, &check_offset2);
if (check_offset) {
zlong offset = mathevali(check_offset);
- zlong length = (zlong)-1;
+ zlong length;
+ int length_set = 0;
int offset_hack_argzero = 0;
if (errflag)
return NULL;
@@ -2849,14 +2850,11 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
zerr("invalid length: %s", check_offset);
return NULL;
}
- if (check_offset) {
+ if (check_offset) {
length = mathevali(check_offset);
+ length_set = 1;
if (errflag)
return NULL;
- if (length < (zlong)0) {
- zerr("invalid length: %s", check_offset);
- return NULL;
- }
}
}
if (horrible_offset_hack) {
@@ -2884,8 +2882,16 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
}
if (offset_hack_argzero)
alen++;
- if (length < 0)
- length = alen;
+ if (length_set) {
+ if (length < 0)
+ length += alen - offset;
+ if (length < 0) {
+ zerr("substring expression: %d < %d",
+ length + offset, offset);
+ return NULL;
+ }
+ } else
+ length = alen;
if (offset > alen)
offset = alen;
if (offset + length > alen)
@@ -2904,6 +2910,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
aval = newarr;
} else {
char *sptr, *eptr;
+ int given_offset;
if (offset < 0) {
MB_METACHARINIT();
for (sptr = val; *sptr; ) {
@@ -2913,12 +2920,27 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
if (offset < 0)
offset = 0;
}
+ given_offset = offset;
MB_METACHARINIT();
+ if (length_set && length < 0)
+ length -= offset;
for (sptr = val; *sptr && offset; ) {
sptr += MB_METACHARLEN(sptr);
offset--;
}
- if (length >= 0) {
+ if (length_set) {
+ if (length < 0) {
+ MB_METACHARINIT();
+ for (eptr = val; *eptr; ) {
+ eptr += MB_METACHARLEN(eptr);
+ length++;
+ }
+ if (length < 0) {
+ zerr("substring expression: %d < %d",
+ length + given_offset, given_offset);
+ return NULL;
+ }
+ }
for (eptr = sptr; *eptr && length; ) {
eptr += MB_METACHARLEN(eptr);
length--;
diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst
index 3646245..b91caaa 100644
--- a/Test/D04parameter.ztst
+++ b/Test/D04parameter.ztst
@@ -1346,6 +1346,7 @@
print ${foo:$(echo 3 + 3):`echo 4 - 3`}
print ${foo: -1}
print ${foo: -10}
+ print ${foo:5:-2}
0:Bash-style offsets, scalar
>456789
>56789
@@ -1357,6 +1358,7 @@
>7
>9
>123456789
+>67
foo=(1 2 3 4 5 6 7 8 9)
print ${foo:3}
@@ -1369,6 +1371,7 @@
print ${foo:$(echo 3 + 3):`echo 4 - 3`}
print ${foo: -1}
print ${foo: -10}
+ print ${foo:5:-2}
0:Bash-style offsets, array
>4 5 6 7 8 9
>5 6 7 8 9
@@ -1380,6 +1383,7 @@
>7
>9
>1 2 3 4 5 6 7 8 9
+>6 7
testfn() {
emulate -L sh
@@ -1418,3 +1422,13 @@
print ${str:0:}
1:Regression test for missing length after offset
?(eval):2: unrecognized modifier
+
+ foo="123456789"
+ print ${foo:5:-6}
+1:Regression test for total length < 0 in string
+?(eval):2: substring expression: 3 < 5
+
+ foo=(1 2 3 4 5 6 7 8 9)
+ print ${foo:5:-6}
+1:Regression test for total length < 0 in array
+?(eval):2: substring expression: 3 < 5
--
1.7.4-rc1
Messages sorted by:
Reverse Date,
Date,
Thread,
Author