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

PATCH Re: zparseopts default associative array



[Moving to zsh-workers]

On Feb 14,  8:14am, jdh wrote:
}
} Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
} 
} > Yes, it would probably make sense for associative arrays if -K retained
} > individual elements
} 
} Not having that natural functionality cuts its utility down to
} almost nothing.

Obviously it's not THAT difficult to replace

  declare -A opt
  opt=(-a AAA -b BBB)
  zparseopts -K -A opt a: b:
  ... $opt[-a] ...

with

  declare -a opt_a opt_b
  opt_a=(-a AAA) opt_b=(-b BBB)
  zparseopts -K a:=opt_a b:=opt_b
  ... $opt_a[2] ...

} I am writing that based on the assumption that the normal usage
} would be to set the array to inital default values, and then simply
} overwrite only those values which were supplied on the command line.

Part of the original intention was that any elements in the array that
were NOT described by the optspecs would be erased.  However, as that
also only happens when at least one described option is parsed, it seems
plausible to abandon that side-effect as well.

I suspect I may have missed something with respect to multibyte and/or
(un)metafication in zalloc_default_array()?


diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo
index 726b0f0..ee9ec3a 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 399c45f..46b29f2 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 = '-';



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