about summary refs log tree commit diff
path: root/Src/params.c
diff options
context:
space:
mode:
authorPeter Stephenson <pws@zsh.org>2017-09-27 09:41:50 +0100
committerPeter Stephenson <pws@zsh.org>2017-09-27 09:41:50 +0100
commit6230e82d44da25773437c5438c83a5d5fe275420 (patch)
tree123f2cfd0c646b662208cd231e5431b97024feb9 /Src/params.c
parent03af5fdbeed0930b5f1d3715ee1080fb993ed145 (diff)
downloadzsh-6230e82d44da25773437c5438c83a5d5fe275420.tar.gz
zsh-6230e82d44da25773437c5438c83a5d5fe275420.tar.xz
zsh-6230e82d44da25773437c5438c83a5d5fe275420.zip
41764 (test tweaked): allow [key]+=value when modifying arrays
Diffstat (limited to 'Src/params.c')
-rw-r--r--Src/params.c39
1 files changed, 32 insertions, 7 deletions
diff --git a/Src/params.c b/Src/params.c
index 4d4d08085..3236f7165 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -3208,13 +3208,15 @@ assignaparam(char *s, char **val, int flags)
 	     * This is an ordinary array with key / value pairs.
 	     */
 	    int maxlen, origlen, nextind;
-	    char **fullval;
+	    char **fullval, **origptr;
 	    zlong *subscripts = (zlong *)zhalloc(arrlen(val) * sizeof(zlong));
 	    zlong *iptr = subscripts;
 	    if (flags & ASSPM_AUGMENT) {
-		maxlen = origlen = arrlen(v->pm->gsu.a->getfn(v->pm));
+		origptr = v->pm->gsu.a->getfn(v->pm);
+		maxlen = origlen = arrlen(origptr);
 	    } else {
 		maxlen = origlen = 0;
+		origptr = NULL;
 	    }
 	    nextind = 0;
 	    for (aptr = val; *aptr; ) {
@@ -3245,25 +3247,36 @@ assignaparam(char *s, char **val, int flags)
 	    }
 	    fullval[maxlen] = NULL;
 	    if (flags & ASSPM_AUGMENT) {
-		char **srcptr = v->pm->gsu.a->getfn(v->pm);
+		char **srcptr = origptr;
 		for (aptr = fullval; aptr <= fullval + origlen; aptr++) {
-		    *aptr = ztrdup(*srcptr); 
+		    *aptr = ztrdup(*srcptr);
 		    srcptr++;
 		}
 	    }
 	    iptr = subscripts;
 	    nextind = 0;
 	    for (aptr = val; *aptr; ++aptr) {
+		char *old;
 		if (**aptr == Marker) {
+		    int augment = ((*aptr)[1] == '+');
 		    zsfree(*aptr);
 		    zsfree(*++aptr); /* Index, no longer needed */
-		    fullval[*iptr] = *++aptr;
+		    old = fullval[*iptr];
+		    if (augment && old) {
+			fullval[*iptr] = bicat(old, *++aptr);
+			zsfree(*aptr);
+		    } else {
+			fullval[*iptr] = *++aptr;
+		    }
 		    nextind = *iptr + 1;
 		    ++iptr;
 		} else {
+		    old = fullval[nextind];
 		    fullval[nextind] = *aptr;
 		    ++nextind;
 		}
+		if (old)
+		    zsfree(old);
 		/* aptr now on value in both cases */
 	    }
 	    if (*aptr) {		/* Shouldn't be possible */
@@ -3828,8 +3841,20 @@ arrhashsetfn(Param pm, char **val, int flags)
 	ht = paramtab = newparamtable(17, pm->node.nam);
     }
     for (aptr = val; *aptr; ) {
-	if (**aptr == Marker)
+	int eltflags = 0;
+	if (**aptr == Marker) {
+	    /* Either all elements have Marker or none. Checked in caller. */
+	    if ((*aptr)[1] == '+') {
+		/* Actually, assignstrvalue currently doesn't handle this... */
+		eltflags = ASSPM_AUGMENT;
+		/* ...so we'll use the trick from setsparam(). */
+		v->start = INT_MAX;
+	    } else {
+		v->start = 0;
+	    }
+	    v->end = -1;
 	    zsfree(*aptr++);
+	}
 	/* The parameter name is ztrdup'd... */
 	v->pm = createparam(*aptr, PM_SCALAR|PM_UNSET);
 	/*
@@ -3840,7 +3865,7 @@ arrhashsetfn(Param pm, char **val, int flags)
 	    v->pm = (Param) paramtab->getnode(paramtab, *aptr);
 	zsfree(*aptr++);
 	/* ...but we can use the value without copying. */
-	setstrvalue(v, *aptr++);
+	assignstrvalue(v, *aptr++, eltflags);
     }
     paramtab = opmtab;
     pm->gsu.h->setfn(pm, ht);