summaryrefslogtreecommitdiff
path: root/Src/subst.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/subst.c')
-rw-r--r--Src/subst.c40
1 files changed, 31 insertions, 9 deletions
diff --git a/Src/subst.c b/Src/subst.c
index 822b24a40..5628c11d2 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -2839,7 +2839,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;
@@ -2854,14 +2855,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) {
@@ -2889,8 +2887,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)
@@ -2909,6 +2915,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; ) {
@@ -2918,12 +2925,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--;