From 956d35ef12a061ec41396b1e0469bd166f6ef007 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 15 Feb 2014 13:49:26 -0800 Subject: 32388: zparseopts -K preserves individual associative array elements --- ChangeLog | 3 +++ Doc/Zsh/mod_zutil.yo | 10 ++++++---- Src/Modules/zutil.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 14aac0671..cef2af0ce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,9 @@ * 32389 (with Jun Takimoto): Test/X02zlevi.ztst, Test/comptest: additional PTY and keybinding adjustments + * 32388: Doc/Zsh/mod_zutil.yo, Src/Modules/zutil.c: zparseopts -K + preserves individual associative array elements + 2014-02-14 Oliver Kiddle * 32361: Src/Zle/zle_tricky.c: don't reset lastline before completion diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo index 726b0f055..ee9ec3adf 100644 --- a/Doc/Zsh/mod_zutil.yo +++ b/Doc/Zsh/mod_zutil.yo @@ -251,10 +251,12 @@ any not described by the var(specs). This is similar to using the tt(shift) builtin. ) item(tt(-K))( -With this option, the arrays specified with the tt(-a) and tt(-A) -options and with the `tt(=)var(array)' forms are kept unchanged when none -of the var(specs) for them is used. This allows assignment of default -values to them before calling tt(zparseopts). +With this option, the arrays specified with the tt(-a) option and with the +`tt(=)var(array)' forms are kept unchanged when none of the var(specs) for +them is used. Otherwise the entire array is replaced when any of the +var(specs) is used. Individual elements of associative arrays specified +with the tt(-A) option are preserved by tt(-K). This allows assignment of +default values to arrays before calling tt(zparseopts). ) item(tt(-M))( This changes the assignment rules to implement a map among equivalent diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c index 399c45f46..46b29f237 100644 --- a/Src/Modules/zutil.c +++ b/Src/Modules/zutil.c @@ -1543,6 +1543,45 @@ add_opt_val(Zoptdesc d, char *arg) } } +/* + * For "zparseopts -K -A assoc ..." this function copies the keys and + * values from the default and allocates the extra space for any parsed + * values having the same keys. If there are no new values, creates an + * empty array. Returns a pointer to the NULL element marking the end. + * + * aval = pointer to the newly allocated array + * assoc = name of the default hash param to copy + * keep = whether we need to make the copy at all + * num = count of new values to add space for + */ +static char ** +zalloc_default_array(char ***aval, char *assoc, int keep, int num) +{ + char **ap = 0; + + *aval = 0; + if (keep && num) { + struct value vbuf; + Value v = fetchvalue(&vbuf, &assoc, 0, + SCANPM_WANTKEYS|SCANPM_WANTVALS|SCANPM_MATCHMANY); + if (v && v->isarr) { + char **dp, **dval = getarrvalue(v); + int dnum = (dval ? arrlen(dval) : 0) + 1; + *aval = (char **) zalloc(((num * 2) + dnum) * sizeof(char *)); + for (ap = *aval, dp = dval; dp && *dp; dp++) { + *ap = (char *) zalloc(strlen(*dp) + 1); + strcpy(*ap++, *dp); + } + *ap = NULL; + } + } + if (!ap) { + ap = *aval = (char **) zalloc(((num * 2) + 1) * sizeof(char *)); + *ap = NULL; + } + return ap; +} + static int bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) { @@ -1825,8 +1864,8 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) num++; if (!keep || num) { - aval = (char **) zalloc(((num * 2) + 1) * sizeof(char *)); - for (ap = aval, d = opt_descs; d; d = d->next) { + ap = zalloc_default_array(&aval, assoc, keep, num); + for (d = opt_descs; d; d = d->next) { if (d->vals) { *ap++ = n = (char *) zalloc(strlen(d->name) + 2); *n = '-'; -- cgit 1.4.1