summary refs log tree commit diff
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,