Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Array slices (PWS's unposted Etc/NEWS change)



OK, I went ahead and changed the array code to use "end" instead of
"len".  The "end" value is a 1--relative index of the last item (or
you can think of it as pointing one past the last item).  This fixes
the case where the starting offset is negative (relative to the end of
the array) but the end value is positive (relative to the start of the
array).

I also checked in a set of array-indexing tests in the "Test" dir.
The new code I just committed now passes all these tests.

..wayne..

---8<------8<------8<------8<---cut here--->8------>8------>8------>8---
Index: Src/glob.c
@@ -921,8 +921,8 @@
     Complist q;				/* pattern after parsing         */
     char *ostr = (char *)getdata(np);	/* the pattern before the parser */
 					/* chops it up                   */
-    int first = 0, count = -1;		/* index of first match to return */
-					/* plus number of items		 */
+    int first = 0, end = -1;		/* index of first match to return */
+					/* and index+1 of the last match */
     struct globdata saved;		/* saved glob state              */
 
     if (unset(GLOBOPT) || !haswilds(ostr)) {
@@ -1334,7 +1334,7 @@
 
 			    v.isarr = SCANPM_WANTVALS;
 			    v.pm = NULL;
-			    v.len = -1;
+			    v.end = -1;
 			    v.inv = 0;
 			    if (getindex(&s, &v) || s == os) {
 				zerr("invalid subscript", NULL, 0);
@@ -1342,7 +1342,7 @@
 				return;
 			    }
 			    first = v.start;
-			    count = v.len;
+			    end = v.end;
 			    break;
 			}
 		    default:
@@ -1426,17 +1426,18 @@
     qsort((void *) & matchbuf[0], matchct, sizeof(struct gmatch),
 	       (int (*) _((const void *, const void *)))gmatchcmp);
 
-    if (first < 0)
+    if (first < 0) {
 	first += matchct;
-    if (count < 0)
-	count += matchct + 1;
-    if (first < 0)
-	first = 0;
-    if (count > matchct - first)
-	count = matchct - first;
-    if (count > 0) {
-	matchptr = matchbuf + matchct - first - count;
-	while (count-- > 0) {		/* insert matches in the arg list */
+	if (first < 0)
+	    first = 0;
+    }
+    if (end < 0)
+	end += matchct + 1;
+    else if (end > matchct)
+	end = matchct;
+    if (end -= first > 0) {
+	matchptr = matchbuf + matchct - first - end;
+	while (end-- > 0) {		/* insert matches in the arg list */
 	    insertlinknode(list, node, matchptr->name);
 	    matchptr++;
 	}
Index: Src/params.c
@@ -398,7 +398,7 @@
     v.isarr = (PM_TYPE(v.pm->flags) & (PM_ARRAY|PM_HASHED));
     v.inv = 0;
     v.start = 0;
-    v.len = -1;
+    v.end = -1;
     paramvals[numparamvals] = getstrvalue(&v);
     if (flags & SCANPM_MATCHVAL) {
 	if (pattry(scanprog, paramvals[numparamvals])) {
@@ -441,7 +441,7 @@
 	v->arr = paramvalarr(v->pm->gets.hfn(v->pm), v->isarr);
 	/* Can't take numeric slices of associative arrays */
 	v->start = 0;
-	v->len = numparamvals + 1;
+	v->end = numparamvals + 1;
 	return v->arr;
     } else
 	return NULL;
@@ -937,7 +937,7 @@
 	    v->isarr = (*inv ? SCANPM_WANTINDEX : 0);
 	    v->start = 0;
 	    *inv = 0;	/* We've already obtained the "index" (key) */
-	    *w = v->len = -1;
+	    *w = v->end = -1;
 	    r = isset(KSHARRAYS) ? 1 : 0;
 	} else {
 	    r = mathevalarg(s, &s);
@@ -960,7 +960,7 @@
 		return 0;
 
 	    if (!a2 && *tt != ',')
-		*w = (zlong)(s - d) - 1;
+		*w = (zlong)(s - t);
 
 	    return (a2 ? s : d + 1) - t;
 	} else if (!v->isarr && !word) {
@@ -1019,7 +1019,7 @@
 				 (v->isarr & (SCANPM_MATCHKEY | SCANPM_MATCHVAL |
 					      SCANPM_KEYMATCH))))) {
 			*inv = v->inv;
-			*w = v->len;
+			*w = v->end;
 			return 1;
 		    }
 		} else
@@ -1070,7 +1070,7 @@
 		    if (!--r) {
 			r = (zlong)(t - s + (a2 ? -1 : 1));
 			if (!a2 && *tt != ',')
-			    *w = strlen(ta[i]) - 1;
+			    *w = r + strlen(ta[i]) - 1;
 			return r;
 		    }
 		return a2 ? -1 : 0;
@@ -1134,7 +1134,7 @@
 int
 getindex(char **pptr, Value v)
 {
-    int start, len, inv = 0;
+    int start, end, inv = 0;
     char *s = *pptr, *tbrack;
 
     *s++ = '[';
@@ -1147,12 +1147,12 @@
 	if ((v->isarr || IS_UNSET_VALUE(v)) && s[0] == '@')
 	    v->isarr |= SCANPM_ISVAR_AT;
 	v->start = 0;
-	v->len = -1;
+	v->end = -1;
 	s += 2;
     } else {
-	zlong wlen = 0, dummy;
+	zlong we = 0, dummy;
 
-	start = getarg(&s, &inv, v, 0, &wlen);
+	start = getarg(&s, &inv, v, 0, &we);
 
 	if (inv) {
 	    if (!v->isarr && start != 0) {
@@ -1171,7 +1171,7 @@
 		v->inv = 1;
 		v->isarr = 0;
 		v->start = start;
-		v->len = 1;
+		v->end = start + 1;
 	    }
 	    if (*s == ',') {
 		zerr("invalid subscript", NULL, 0);
@@ -1187,26 +1187,23 @@
 
 	    if ((com = (*s == ','))) {
 		s++;
-		len = getarg(&s, &inv, v, 1, &dummy);
-		if (len >= 0) {
-		    len -= start - 1;
-		    if (len < 0)
-			len = 0;
-		}
+		end = getarg(&s, &inv, v, 1, &dummy);
 	    } else {
-		len = wlen ? wlen : 1;
+		end = we ? we : start;
 	    }
 	    if (start > 0)
 		start--;
+	    else if (start == 0 && end == 0)
+		end++;
 	    if (*s == ']' || *s == Outbrack) {
 		s++;
-		if (v->isarr && len == 1 && !com &&
+		if (v->isarr && start == end-1 && !com &&
 		    (!(v->isarr & SCANPM_MATCHMANY) ||
 		     !(v->isarr & (SCANPM_MATCHKEY | SCANPM_MATCHVAL |
 				   SCANPM_KEYMATCH))))
 		    v->isarr = 0;
 		v->start = start;
-		v->len = len;
+		v->end = end;
 	    } else
 		s = *pptr;
 	}
@@ -1268,7 +1265,7 @@
 	v->pm = argvparam;
 	v->inv = 0;
 	v->start = ppar - 1;
-	v->len = 1;
+	v->end = ppar;
 	if (sav)
 	    *s = sav;
     } else {
@@ -1299,7 +1296,7 @@
 	v->pm = pm;
 	v->inv = 0;
 	v->start = 0;
-	v->len = -1;
+	v->end = -1;
 	if (bracks > 0 && (*s == '[' || *s == Inbrack)) {
 	    if (getindex(&s, v)) {
 		*pptr = s;
@@ -1307,21 +1304,25 @@
 	    }
 	} else if (!(flags & SCANPM_ASSIGNING) && v->isarr &&
 		   iident(*t) && isset(KSHARRAYS))
-	    v->len = 1, v->isarr = 0;
+	    v->end = 1, v->isarr = 0;
     }
     if (!bracks && *s)
 	return NULL;
     *pptr = s;
-    if (v->start > MAX_ARRLEN ||
-	v->start < -MAX_ARRLEN) {
-	zerr("subscript too %s: %d", (v->start < 0) ? "small" : "big",
-	     v->start + !isset(KSHARRAYS));
+    if (v->start > MAX_ARRLEN) {
+	zerr("subscript too %s: %d", "big", v->start + !isset(KSHARRAYS));
+	return NULL;
+    }
+    if (v->start < -MAX_ARRLEN) {
+	zerr("%s: subscript too %s: %d", "small", v->start);
+	return NULL;
+    }
+    if (v->end > MAX_ARRLEN+1) {
+	zerr("%s: subscript too %s: %d", "big", v->end - !!isset(KSHARRAYS));
 	return NULL;
     }
-    if (v->start + v->len > MAX_ARRLEN ||
-	v->start + v->len < -MAX_ARRLEN) {
-	zerr("subscript too %s: %d", (v->len < 0) ? "small" : "big",
-	     v->start + v->len - !!isset(KSHARRAYS));
+    if (v->end < -MAX_ARRLEN) {
+	zerr("%s: subscript too %s: %d", "small", v->end);
 	return NULL;
     }
     return v;
@@ -1380,18 +1381,18 @@
 	break;
     }
 
-    if (v->start == 0 && v->len == -1)
+    if (v->start == 0 && v->end == -1)
 	return s;
 
     if (v->start < 0)
 	v->start += strlen(s);
-    if (v->len < 0)
-	v->len += strlen(s) - v->start + 1;
+    if (v->end < 0)
+	v->end += strlen(s) + 1;
     s = (v->start > (int)strlen(s)) ? dupstring("") : dupstring(s + v->start);
-    if (v->len <= 0)
+    if (v->end <= v->start)
 	s[0] = '\0';
-    else if (v->len <= (int)strlen(s))
-	s[v->len + (s[v->len - 1] == Meta)] = '\0';
+    else if (v->end - v->start <= (int)strlen(s))
+	s[v->end - v->start + (s[v->end - v->start - 1] == Meta)] = '\0';
 
     return s;
 }
@@ -1417,20 +1418,20 @@
 	return s;
     }
     s = getvaluearr(v);
-    if (v->start == 0 && v->len == -1)
+    if (v->start == 0 && v->end == -1)
 	return s;
     if (v->start < 0)
 	v->start += arrlen(s);
-    if (v->len < 0)
-	v->len += arrlen(s) - v->start + 1;
+    if (v->end < 0)
+	v->end += arrlen(s) + 1;
     if (v->start > arrlen(s) || v->start < 0)
 	s = arrdup(nular);
     else
 	s = arrdup(s + v->start);
-    if (v->len <= 0)
+    if (v->end <= v->start)
 	s[0] = NULL;
-    else if (v->len <= arrlen(s))
-	s[v->len] = NULL;
+    else if (v->end - v->start <= arrlen(s))
+	s[v->end - v->start] = NULL;
     return s;
 }
 
@@ -1508,7 +1509,7 @@
     v->pm->flags &= ~PM_UNSET;
     switch (PM_TYPE(v->pm->flags)) {
     case PM_SCALAR:
-	if (v->start == 0 && v->len == -1) {
+	if (v->start == 0 && v->end == -1) {
 	    (v->pm->sets.cfn) (v->pm, val);
 	    if (v->pm->flags & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z) && !v->pm->ct)
 		v->pm->ct = strlen(val);
@@ -1519,7 +1520,7 @@
 	    z = dupstring((v->pm->gets.cfn) (v->pm));
 	    zlen = strlen(z);
 	    if (v->inv && unset(KSHARRAYS))
-		v->start--;
+		v->start--, v->end--;
 	    if (v->start < 0) {
 		v->start += zlen;
 		if (v->start < 0)
@@ -1527,14 +1528,14 @@
 	    }
 	    if (v->start > zlen)
 		v->start = zlen;
-	    if (v->len < 0)
-		v->len += zlen - v->start + 1;
-	    if (v->len > zlen - v->start)
-		v->len = zlen - v->start;
-	    x = (char *) zalloc(strlen(val) + zlen - v->len + 1);
+	    if (v->end < 0)
+		v->end += zlen + 1;
+	    else if (v->end > zlen)
+		v->end = zlen;
+	    x = (char *) zalloc(v->start + strlen(val) + zlen - v->end + 1);
 	    strncpy(x, z, v->start);
 	    strcpy(x + v->start, val);
-	    strcat(x + v->start, z + v->start + v->len);
+	    strcat(x + v->start, z + v->end);
 	    (v->pm->sets.cfn) (v->pm, x);
 	    zsfree(val);
 	}
@@ -1631,7 +1632,7 @@
 	zerr("attempt to assign array value to non-array", NULL, 0);
 	return;
     }
-    if (v->start == 0 && v->len == -1) {
+    if (v->start == 0 && v->end == -1) {
 	if (PM_TYPE(v->pm->flags) == PM_HASHED)
 	    arrhashsetfn(v->pm, val);
 	else
@@ -1646,21 +1647,23 @@
 	    return;
 	}
 	if (v->inv && unset(KSHARRAYS))
-	    v->start--;
+	    v->start--, v->end--;
 	q = old = v->pm->gets.afn(v->pm);
 	n = arrlen(old);
-	if (v->start < 0)
+	if (v->start < 0) {
 	    v->start += n;
-	if (v->len < 0)
-	    v->len += n - v->start + 1;
-	if (v->start < 0)
-	    v->start = 0;
-	if (v->len < 0)
-	    v->len = 0;
+	    if (v->start < 0)
+		v->start = 0;
+	}
+	if (v->end < 0) {
+	    v->end += n + 1;
+	    if (v->end < 0)
+		v->end = 0;
+	}
 
 	ll = v->start + arrlen(val);
-	if (v->start + v->len - 1 < n)
-	    ll += n - (v->start + v->len - 1);
+	if (v->end <= n)
+	    ll += n - v->end + 1;
 
 	p = new = (char **) zcalloc(sizeof(char *) * (ll + 1));
 
@@ -1668,8 +1671,8 @@
 	    *p++ = i < n ? ztrdup(*q++) : ztrdup("");
 	for (r = val; *r;)
 	    *p++ = ztrdup(*r++);
-	if (v->start + v->len < n)
-	    for (q = old + v->start + v->len; *q;)
+	if (v->end < n)
+	    for (q = old + v->end; *q;)
 		*p++ = ztrdup(*q++);
 	*p = NULL;
 
@@ -2164,7 +2167,7 @@
     HashTable opmtab = paramtab, ht = 0;
     char **aptr = val;
     Value v = (Value) hcalloc(sizeof *v);
-    v->len = -1;
+    v->end = -1;
 
     if (alen % 2) {
 	freearray(val);
Index: Src/subst.c
@@ -1138,7 +1138,7 @@
 	    v = (Value) hcalloc(sizeof *v);
 	    v->isarr = isarr;
 	    v->pm = pm;
-	    v->len = -1;
+	    v->end = -1;
 	    if (getindex(&s, v) || s == os)
 		break;
 	}
Index: Src/zsh.h
@@ -468,7 +468,7 @@
     Param pm;		/* parameter node                      */
     int inv;		/* should we return the index ?        */
     int start;		/* first element of array slice, or -1 */
-    int len;		/* length of array slice, or -1        */
+    int end;		/* 1-rel last element of array slice, or -1 */
     char **arr;		/* cache for hash turned into array */
 };
 
Index: Src/Modules/mapfile.c
@@ -203,7 +203,7 @@
 		struct value v;
 
 		v.isarr = v.inv = v.start = 0;
-		v.len = -1;
+		v.end = -1;
 		v.arr = NULL;
 		v.pm = (Param) hn;
 
Index: Src/Modules/parameter.c
@@ -230,7 +230,7 @@
 	    struct value v;
 
 	    v.isarr = v.inv = v.start = 0;
-	    v.len = -1;
+	    v.end = -1;
 	    v.arr = NULL;
 	    v.pm = (Param) hn;
 
@@ -401,7 +401,7 @@
 	    struct value v;
 
 	    v.isarr = v.inv = v.start = 0;
-	    v.len = -1;
+	    v.end = -1;
 	    v.arr = NULL;
 	    v.pm = (Param) hn;
 
@@ -755,7 +755,7 @@
 	    char *val;
 
 	    v.isarr = v.inv = v.start = 0;
-	    v.len = -1;
+	    v.end = -1;
 	    v.arr = NULL;
 	    v.pm = (Param) hn;
 
@@ -1434,7 +1434,7 @@
 	    char *val;
 
 	    v.isarr = v.inv = v.start = 0;
-	    v.len = -1;
+	    v.end = -1;
 	    v.arr = NULL;
 	    v.pm = (Param) hn;
 
@@ -1660,7 +1660,7 @@
 	    char *val;
 
 	    v.isarr = v.inv = v.start = 0;
-	    v.len = -1;
+	    v.end = -1;
 	    v.arr = NULL;
 	    v.pm = (Param) hn;
 
Index: Src/Zle/complete.c
@@ -1034,7 +1034,7 @@
 		 pp = compkpms; cp->name; cp++, pp++)
 		if (!strcmp(hn->nam, cp->name)) {
 		    v.isarr = v.inv = v.start = 0;
-		    v.len = -1;
+		    v.end = -1;
 		    v.arr = NULL;
 		    v.pm = (Param) hn;
 		    if (cp->type == PM_INTEGER)
---8<------8<------8<------8<---cut here--->8------>8------>8------>8---



Messages sorted by: Reverse Date, Date, Thread, Author