summaryrefslogtreecommitdiff
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-rw-r--r--Src/Modules/mapfile.c2
-rw-r--r--Src/Modules/parameter.c10
-rw-r--r--Src/Zle/complete.c2
-rw-r--r--Src/glob.c2
-rw-r--r--Src/options.c5
-rw-r--r--Src/params.c89
-rw-r--r--Src/subst.c14
-rw-r--r--Src/zsh.h8
8 files changed, 80 insertions, 52 deletions
diff --git a/Src/Modules/mapfile.c b/Src/Modules/mapfile.c
index 25b506f03..fb46df885 100644
--- a/Src/Modules/mapfile.c
+++ b/Src/Modules/mapfile.c
@@ -149,7 +149,7 @@ setpmmapfiles(Param pm, HashTable ht)
for (hn = ht->nodes[i]; hn; hn = hn->next) {
struct value v;
- v.isarr = v.inv = v.start = 0;
+ v.isarr = v.flags = v.start = 0;
v.end = -1;
v.arr = NULL;
v.pm = (Param) hn;
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c
index 9d52bcd3f..bf21b5cda 100644
--- a/Src/Modules/parameter.c
+++ b/Src/Modules/parameter.c
@@ -180,7 +180,7 @@ setpmcommands(UNUSED(Param pm), HashTable ht)
Cmdnam cn = zshcalloc(sizeof(*cn));
struct value v;
- v.isarr = v.inv = v.start = 0;
+ v.isarr = v.flags = v.start = 0;
v.end = -1;
v.arr = NULL;
v.pm = (Param) hn;
@@ -341,7 +341,7 @@ setfunctions(UNUSED(Param pm), HashTable ht, int dis)
for (hn = ht->nodes[i]; hn; hn = hn->next) {
struct value v;
- v.isarr = v.inv = v.start = 0;
+ v.isarr = v.flags = v.start = 0;
v.end = -1;
v.arr = NULL;
v.pm = (Param) hn;
@@ -701,7 +701,7 @@ setpmoptions(UNUSED(Param pm), HashTable ht)
struct value v;
char *val;
- v.isarr = v.inv = v.start = 0;
+ v.isarr = v.flags = v.start = 0;
v.end = -1;
v.arr = NULL;
v.pm = (Param) hn;
@@ -1325,7 +1325,7 @@ setpmnameddirs(UNUSED(Param pm), HashTable ht)
struct value v;
char *val;
- v.isarr = v.inv = v.start = 0;
+ v.isarr = v.flags = v.start = 0;
v.end = -1;
v.arr = NULL;
v.pm = (Param) hn;
@@ -1554,7 +1554,7 @@ setaliases(HashTable alht, UNUSED(Param pm), HashTable ht, int flags)
struct value v;
char *val;
- v.isarr = v.inv = v.start = 0;
+ v.isarr = v.flags = v.start = 0;
v.end = -1;
v.arr = NULL;
v.pm = (Param) hn;
diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c
index 245f73126..a2af30c65 100644
--- a/Src/Zle/complete.c
+++ b/Src/Zle/complete.c
@@ -1139,7 +1139,7 @@ set_compstate(UNUSED(Param pm), HashTable ht)
for (cp = compkparams,
pp = compkpms; cp->name; cp++, pp++)
if (!strcmp(hn->nam, cp->name)) {
- v.isarr = v.inv = v.start = 0;
+ v.isarr = v.flags = v.start = 0;
v.end = -1;
v.arr = NULL;
v.pm = (Param) hn;
diff --git a/Src/glob.c b/Src/glob.c
index afd362c08..d95eced35 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -1470,7 +1470,7 @@ zglob(LinkList list, LinkNode np, int nountok)
v.isarr = SCANPM_WANTVALS;
v.pm = NULL;
v.end = -1;
- v.inv = 0;
+ v.flags = 0;
if (getindex(&s, &v, 0) || s == os) {
zerr("invalid subscript");
restore_globstate(saved);
diff --git a/Src/options.c b/Src/options.c
index f3135759b..b46986495 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -153,9 +153,10 @@ static struct optname optns[] = {
{{NULL, "interactivecomments",OPT_BOURNE}, INTERACTIVECOMMENTS},
{{NULL, "ksharrays", OPT_EMULATE|OPT_BOURNE}, KSHARRAYS},
{{NULL, "kshautoload", OPT_EMULATE|OPT_BOURNE}, KSHAUTOLOAD},
-{{NULL, "kshglob", OPT_EMULATE|OPT_KSH}, KSHGLOB},
+{{NULL, "kshglob", OPT_EMULATE|OPT_KSH}, KSHGLOB},
{{NULL, "kshoptionprint", OPT_EMULATE|OPT_KSH}, KSHOPTIONPRINT},
-{{NULL, "kshtypeset", OPT_EMULATE|OPT_KSH}, KSHTYPESET},
+{{NULL, "kshtypeset", OPT_EMULATE|OPT_KSH}, KSHTYPESET},
+{{NULL, "kshzerosubscript", 0}, KSHZEROSUBSCRIPT},
{{NULL, "listambiguous", OPT_ALL}, LISTAMBIGUOUS},
{{NULL, "listbeep", OPT_ALL}, LISTBEEP},
{{NULL, "listpacked", 0}, LISTPACKED},
diff --git a/Src/params.c b/Src/params.c
index a44f21402..5609437a2 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -520,7 +520,7 @@ scanparamvals(HashNode hn, int flags)
return;
}
v.isarr = (PM_TYPE(v.pm->node.flags) & (PM_ARRAY|PM_HASHED));
- v.inv = 0;
+ v.flags = 0;
v.start = 0;
v.end = -1;
paramvals[numparamvals] = getstrvalue(&v);
@@ -1298,7 +1298,7 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w,
(*ta || ((v->isarr & SCANPM_MATCHMANY) &&
(v->isarr & (SCANPM_MATCHKEY | SCANPM_MATCHVAL |
SCANPM_KEYMATCH))))) {
- *inv = v->inv;
+ *inv = (v->flags & VALFLAG_INV) ? 1 : 0;
*w = v->end;
return 1;
}
@@ -1317,19 +1317,6 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w,
if (pprog && pattry(pprog, *p) && !--num)
return r;
}
- /*
- * Failed to match.
- * If we're returning an index, return 0 to show
- * we've gone off the start. Unfortunately this
- * is ambiguous with KSH_ARRAYS set, but we're
- * stuck with that now.
- *
- * If the index is to be turned into an element,
- * return an index that does not point to a valid
- * element (since 0 is treated the same as 1).
- */
- if (!ind)
- r = len + 1;
} else
for (r = 1 + beg, p = ta + beg; *p; r++, p++)
if (pprog && pattry(pprog, *p) && !--num)
@@ -1549,13 +1536,7 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w,
}
}
}
- /*
- * Failed to match.
- * If the argument selects an element rather than
- * its index, ensure the element is empty.
- * See comments on the array case above.
- */
- return (down && ind) ? 0 : slen + 1;
+ return down ? 0 : slen + 1;
}
}
return r;
@@ -1563,13 +1544,14 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w,
/**/
int
-getindex(char **pptr, Value v, int dq)
+getindex(char **pptr, Value v, int flags)
{
int start, end, inv = 0;
char *s = *pptr, *tbrack;
*s++ = '[';
- s = parse_subscript(s, dq); /* Error handled after untokenizing */
+ /* Error handled after untokenizing */
+ s = parse_subscript(s, flags & SCANPM_DQUOTED);
/* Now we untokenize everything except inull() markers so we can check *
* for the '*' and '@' special subscripts. The inull()s are removed *
* in getarg() after we know whether we're doing reverse indexing. */
@@ -1654,7 +1636,7 @@ getindex(char **pptr, Value v, int dq)
if (start > 0 && (isset(KSHARRAYS) || (v->pm->node.flags & PM_HASHED)))
start--;
if (v->isarr != SCANPM_WANTINDEX) {
- v->inv = 1;
+ v->flags |= VALFLAG_INV;
v->isarr = 0;
v->start = start;
v->end = start + 1;
@@ -1686,7 +1668,32 @@ getindex(char **pptr, Value v, int dq)
if (start > 0)
start -= startprevlen;
else if (start == 0 && end == 0)
- end = startnextlen;
+ {
+ /*
+ * Strictly, this range is entirely off the
+ * start of the available index range.
+ * This can't happen with KSH_ARRAYS; we already
+ * altered the start index in getarg().
+ * Are we being strict?
+ */
+ if (isset(KSHZEROSUBSCRIPT)) {
+ /*
+ * We're not.
+ * Treat this as accessing the first element of the
+ * array.
+ */
+ end = startnextlen;
+ } else {
+ /*
+ * We are. Flag that this range is invalid
+ * for setting elements. Set the indexes
+ * to a range that returns empty for other accesses.
+ */
+ v->flags |= VALFLAG_EMPTY;
+ start = -1;
+ com = 1;
+ }
+ }
if (s == tbrack) {
s++;
if (v->isarr && !com &&
@@ -1755,7 +1762,7 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
else
v = (Value) hcalloc(sizeof *v);
v->pm = argvparam;
- v->inv = 0;
+ v->flags = 0;
v->start = ppar - 1;
v->end = ppar;
if (sav)
@@ -1786,11 +1793,11 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
v->isarr = SCANPM_MATCHMANY;
}
v->pm = pm;
- v->inv = 0;
+ v->flags = 0;
v->start = 0;
v->end = -1;
if (bracks > 0 && (*s == '[' || *s == Inbrack)) {
- if (getindex(&s, v, (flags & SCANPM_DQUOTED))) {
+ if (getindex(&s, v, flags)) {
*pptr = s;
return v;
}
@@ -1830,7 +1837,7 @@ getstrvalue(Value v)
if (!v)
return hcalloc(1);
- if (v->inv && !(v->pm->node.flags & PM_HASHED)) {
+ if ((v->flags & VALFLAG_INV) && !(v->pm->node.flags & PM_HASHED)) {
sprintf(buf, "%d", v->start);
s = dupstring(buf);
return s;
@@ -1911,7 +1918,7 @@ getarrvalue(Value v)
return arrdup(nular);
else if (IS_UNSET_VALUE(v))
return arrdup(&nular[1]);
- if (v->inv) {
+ if (v->flags & VALFLAG_INV) {
char buf[DIGBUFSIZE];
s = arrdup(nular);
@@ -1943,7 +1950,7 @@ getintvalue(Value v)
{
if (!v)
return 0;
- if (v->inv)
+ if (v->flags & VALFLAG_INV)
return v->start;
if (v->isarr) {
char **arr = getarrvalue(v);
@@ -1970,7 +1977,7 @@ getnumvalue(Value v)
if (!v) {
mn.u.l = 0;
- } else if (v->inv) {
+ } else if (v->flags & VALFLAG_INV) {
mn.u.l = v->start;
} else if (v->isarr) {
char **arr = getarrvalue(v);
@@ -2000,7 +2007,7 @@ export_param(Param pm)
if (emulation == EMULATE_KSH /* isset(KSHARRAYS) */) {
struct value v;
v.isarr = 1;
- v.inv = 0;
+ v.flags = 0;
v.start = 0;
v.end = -1;
val = getstrvalue(&v);
@@ -2037,6 +2044,11 @@ setstrvalue(Value v, char *val)
zsfree(val);
return;
}
+ if (v->flags & VALFLAG_EMPTY) {
+ zerr("%s: assignment to invalid subscript range", v->pm->node.nam);
+ zsfree(val);
+ return;
+ }
v->pm->node.flags &= ~PM_UNSET;
switch (PM_TYPE(v->pm->node.flags)) {
case PM_SCALAR:
@@ -2051,7 +2063,7 @@ setstrvalue(Value v, char *val)
z = dupstring(v->pm->gsu.s->getfn(v->pm));
zlen = strlen(z);
- if (v->inv && unset(KSHARRAYS))
+ if ((v->flags & VALFLAG_INV) && unset(KSHARRAYS))
v->start--, v->end--;
if (v->start < 0) {
v->start += zlen;
@@ -2176,6 +2188,11 @@ setarrvalue(Value v, char **val)
v->pm->node.nam);
return;
}
+ if (v->flags & VALFLAG_EMPTY) {
+ zerr("%s: assignment to invalid subscript range", v->pm->node.nam);
+ freearray(val);
+ return;
+ }
if (v->start == 0 && v->end == -1) {
if (PM_TYPE(v->pm->node.flags) == PM_HASHED)
arrhashsetfn(v->pm, val, 0);
@@ -2194,7 +2211,7 @@ setarrvalue(Value v, char **val)
v->pm->node.nam);
return;
}
- if (v->inv && unset(KSHARRAYS)) {
+ if ((v->flags & VALFLAG_INV) && unset(KSHARRAYS)) {
if (v->start > 0)
v->start--;
v->end--;
diff --git a/Src/subst.c b/Src/subst.c
index 5d7a44b05..0cb8d48bf 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -2008,7 +2008,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
v->isarr = isarr;
v->pm = pm;
v->end = -1;
- if (getindex(&s, v, qt) || s == os)
+ if (getindex(&s, v, qt ? SCANPM_DQUOTED : 0) || s == os)
break;
}
/*
@@ -2025,8 +2025,11 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
* in the subexp stuff or immediately above.
*/
if ((isarr = v->isarr)) {
- /* No way to get here with v->inv != 0, so getvaluearr() *
- * is called by getarrvalue(); needn't test PM_HASHED. */
+ /*
+ * No way to get here with v->flags & VALFLAG_INV, so
+ * getvaluearr() is called by getarrvalue(); needn't test
+ * PM_HASHED.
+ */
if (v->isarr == SCANPM_WANTINDEX) {
isarr = v->isarr = 0;
val = dupstring(v->pm->node.nam);
@@ -2048,8 +2051,9 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
int tmplen = arrlen(v->pm->gsu.a->getfn(v->pm));
if (v->start < 0)
- v->start += tmplen + v->inv;
- if (!v->inv && (v->start >= tmplen || v->start < 0))
+ v->start += tmplen + ((v->flags & VALFLAG_INV) ? 1 : 0);
+ if (!(v->flags & VALFLAG_INV) &&
+ (v->start >= tmplen || v->start < 0))
vunset = 1;
}
if (!vunset) {
diff --git a/Src/zsh.h b/Src/zsh.h
index f7255c6e7..4f11b19ad 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -585,12 +585,17 @@ struct asgment {
struct value {
int isarr;
Param pm; /* parameter node */
- int inv; /* should we return the index ? */
+ int flags; /* flags defined below */
int start; /* first element of array slice, or -1 */
int end; /* 1-rel last element of array slice, or -1 */
char **arr; /* cache for hash turned into array */
};
+enum {
+ VALFLAG_INV = 0x0001, /* We are performing inverse subscripting */
+ VALFLAG_EMPTY = 0x0002 /* Subscripted range is empty */
+};
+
#define MAX_ARRLEN 262144
/********************************************/
@@ -1725,6 +1730,7 @@ enum {
KSHGLOB,
KSHOPTIONPRINT,
KSHTYPESET,
+ KSHZEROSUBSCRIPT,
LISTAMBIGUOUS,
LISTBEEP,
LISTPACKED,