about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorDaniel Shahaf <d.s@daniel.shahaf.name>2020-04-27 19:30:40 +0000
committerDaniel Shahaf <d.s@daniel.shahaf.name>2020-05-03 01:27:36 +0000
commitdeca7c928520fba5a73383f1cac0b3ace8e0e45d (patch)
tree9e8e04cd5fbc8297fb033141ed8b0018b1eb2654 /Src
parent4d2bcf2fe7637b641ccde31a8ca7c4875f0699c1 (diff)
downloadzsh-deca7c928520fba5a73383f1cac0b3ace8e0e45d.tar.gz
zsh-deca7c928520fba5a73383f1cac0b3ace8e0e45d.tar.xz
zsh-deca7c928520fba5a73383f1cac0b3ace8e0e45d.zip
45730: _arguments: Add the -0 flag, which makes $opt_args be populated sanely.
Also, write/extend docstrings for sepjoin() and zjoin().
Diffstat (limited to 'Src')
-rw-r--r--Src/Zle/computil.c40
-rw-r--r--Src/utils.c15
2 files changed, 49 insertions, 6 deletions
diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c
index ddfa70077..e08788e89 100644
--- a/Src/Zle/computil.c
+++ b/Src/Zle/computil.c
@@ -2375,6 +2375,23 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first)
     return 0;
 }
 
+/* Build a NUL-separated from a list.
+ *
+ * This is only used to populate values of $opt_args.
+ */
+
+static char *
+ca_nullist(LinkList l)
+{
+    if (l) {
+	char **array = zlinklist2array(l, 0 /* don't dup elements */);
+	char *ret = zjoin(array, '\0', 0 /* permanent allocation */);
+	free(array); /* the elements are owned by the list */
+	return ret;
+    } else
+	return ztrdup("");
+}
+
 /* Build a colon-list from a list.
  *
  * This is only used to populate values of $opt_args.
@@ -2563,7 +2580,7 @@ bin_comparguments(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
     case 's': min = 1; max =  1; break;
     case 'M': min = 1; max =  1; break;
     case 'a': min = 0; max =  0; break;
-    case 'W': min = 2; max =  2; break;
+    case 'W': min = 3; max =  3; break;
     case 'n': min = 1; max =  1; break;
     default:
 	zwarnnam(nam, "invalid option: %s", args[0]);
@@ -2795,11 +2812,20 @@ bin_comparguments(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
 		return 0;
 	return 1;
     case 'W':
-        /* This gets two parameter names as arguments.  The first is set to
-         * the current word sans any option prefixes handled by comparguments.
+        /* This gets two parameter names and one integer as arguments.
+         *
+         * The first parameter is set to the current word sans any option
+         * prefixes handled by comparguments.
+         *
          * The second parameter is set to an array containing the options on
          * the line and their arguments.  I.e. the stuff _arguments returns
-         * to its caller in the `line' and `opt_args' parameters. */
+         * to its caller in the `line' and `opt_args' parameters.
+         *
+         * The integer is one if the second parameter (which is just $opt_args,
+         * you know) should encode multiple values by joining them with NULs
+         * and zero if it should encode multiple values by joining them with
+         * colons after backslash-escaping colons and backslashes.
+         */
 	{
 	    Castate s;
 	    char **ret, **p;
@@ -2807,6 +2833,7 @@ bin_comparguments(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
 	    LinkList *a;
 	    Caopt o;
 	    int num;
+	    int opt_args_use_NUL_separators = (args[3][0] != '0');
 
 	    for (num = 0, s = lstate; s; s = s->snext)
 		num += countlinknodes(s->args);
@@ -2832,7 +2859,10 @@ bin_comparguments(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
 		    if (*a) {
 			*p++ = (o->gsname ? tricat(o->gsname, o->name, "") :
 				ztrdup(o->name));
-			*p++ = ca_colonlist(*a);
+			if (opt_args_use_NUL_separators)
+			    *p++ = ca_nullist(*a);
+			else
+			    *p++ = ca_colonlist(*a);
 		    }
 	    *p = NULL;
 
diff --git a/Src/utils.c b/Src/utils.c
index e258ef836..5158a70b1 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -3596,6 +3596,17 @@ strftimehandling:
     return buf - origbuf;
 }
 
+/*
+ * Return a string consisting of the elements of 'arr' joined by the character
+ * 'delim', which will be metafied if necessary.  The string will be allocated
+ * on the heap iff 'heap'.
+ *
+ * Comparable to:
+ *
+ *     char metafied_delim[] = { Meta, delim ^ 32, '\0' };
+ *     sepjoin(arr, metafied_delim, heap)
+ */
+
 /**/
 mod_export char *
 zjoin(char **arr, int delim, int heap)
@@ -3894,10 +3905,12 @@ wordcount(char *s, char *sep, int mul)
 
 /*
  * 's' is a NULL-terminated array of strings.
- * 'sep' is a string.
+ * 'sep' is a string, or NULL to split on ${IFS[1]}.
  *
  * Return a string consisting of the elements of 's' joined by 'sep',
  * allocated on the heap iff 'heap'.
+ *
+ * See also zjoin().
  */
 
 /**/