zsh-workers
 help / color / mirror / code / Atom feed
From: Bart Schaefer <schaefer@brasslantern.com>
To: zsh-workers@zsh.org
Cc: jdh <dhenman@gmail.com>
Subject: PATCH Re: zparseopts default associative array
Date: Sat, 15 Feb 2014 13:15:18 -0800	[thread overview]
Message-ID: <140215131518.ZM29024@torch.brasslantern.com> (raw)
In-Reply-To: <20140214081434.1580@binki>

[Moving to zsh-workers]

On Feb 14,  8:14am, jdh wrote:
}
} Bart Schaefer <schaefer@brasslantern.com> 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 = '-';


       reply	other threads:[~2014-02-15 21:15 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CABABwVH+Yu-oFiE8OYkmNHxRGSwfYT8331oA0=0s9quom3CTGA@mail.gmail.com>
     [not found] ` <140213085618.ZM26934@torch.brasslantern.com>
     [not found]   ` <20140214081434.1580@binki>
2014-02-15 21:15     ` Bart Schaefer [this message]
2014-02-15 22:19       ` Peter Stephenson
2014-02-15 22:56         ` Bart Schaefer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=140215131518.ZM29024@torch.brasslantern.com \
    --to=schaefer@brasslantern.com \
    --cc=dhenman@gmail.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).