From abae4fe16e26cf027e7c8165d27b93d74bbd18b2 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 18 Jun 2007 13:25:03 +0000 Subject: 23562: add KSH_ZERO_SUBSCRIPT option and leave off by default --- Src/Modules/mapfile.c | 2 +- Src/Modules/parameter.c | 10 +++--- Src/Zle/complete.c | 2 +- Src/glob.c | 2 +- Src/options.c | 5 +-- Src/params.c | 89 +++++++++++++++++++++++++++++-------------------- Src/subst.c | 14 +++++--- Src/zsh.h | 8 ++++- 8 files changed, 80 insertions(+), 52 deletions(-) (limited to 'Src') 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, -- cgit 1.4.1