summaryrefslogtreecommitdiff
path: root/Src
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
parent03af5fdbeed0930b5f1d3715ee1080fb993ed145 (diff)
downloadzsh-6230e82d44da25773437c5438c83a5d5fe275420.tar.gz
zsh-6230e82d44da25773437c5438c83a5d5fe275420.zip
41764 (test tweaked): allow [key]+=value when modifying arrays
Diffstat (limited to 'Src')
-rw-r--r--Src/params.c39
-rw-r--r--Src/subst.c17
-rw-r--r--Src/zsh.h4
3 files changed, 48 insertions, 12 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);
diff --git a/Src/subst.c b/Src/subst.c
index 55b5444c6..eef0dc75b 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -53,16 +53,25 @@ keyvalpairelement(LinkList list, LinkNode node)
if ((start = (char *)getdata(node)) &&
start[0] == Inbrack &&
(end = strchr(start+1, Outbrack)) &&
- end[1] == Equals) {
+ /* ..]=value or ]+=Value */
+ (end[1] == Equals ||
+ (end[1] == '+' && end[2] == Equals))) {
static char marker[2] = { Marker, '\0' };
+ static char marker_plus[3] = { Marker, '+', '\0' };
*end = '\0';
dat = start + 1;
singsub(&dat);
untokenize(dat);
- setdata(node, marker);
- node = insertlinknode(list, node, dat);
- dat = end + 2;
+ if (end[1] == '+') {
+ setdata(node, marker_plus);
+ node = insertlinknode(list, node, dat);
+ dat = end + 3;
+ } else {
+ setdata(node, marker);
+ node = insertlinknode(list, node, dat);
+ dat = end + 2;
+ }
singsub(&dat);
untokenize(dat);
return insertlinknode(list, node, dat);
diff --git a/Src/zsh.h b/Src/zsh.h
index b6e2001fb..c1138bfab 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -228,7 +228,9 @@ struct mathfunc {
* - In pattern character arrays as guaranteed not to mark a character in
* a string.
* - In assignments with the ASSPM_KEY_VALUE flag set in order to
- * mark that there is a key / value pair following.
+ * mark that there is a key / value pair following. If this
+ * comes from [key]=value the Marker is followed by a null;
+ * if from [key]+=value the Marker is followed by a '+' then a null.
* All the above are local uses --- any case where the Marker has
* escaped beyond the context in question is an error.
*/