summaryrefslogtreecommitdiff
path: root/Src/Zle/computil.c
diff options
context:
space:
mode:
authorAxel Beckert <abe@deuxchevaux.org>2022-04-11 00:17:48 +0200
committerAxel Beckert <abe@deuxchevaux.org>2022-04-11 00:17:48 +0200
commitb09f4483416c54c1782824633dfabaf2ec0265b6 (patch)
tree304bc82642862525ae680c7fbaa249663b10ad57 /Src/Zle/computil.c
parent12eb3e5356f2fc3351eed58ef1cef1b8fb83b504 (diff)
parent6e55c920503071e917619b8cb1a188cd35d772db (diff)
downloadzsh-b09f4483416c54c1782824633dfabaf2ec0265b6.tar.gz
zsh-b09f4483416c54c1782824633dfabaf2ec0265b6.zip
New upstream version 5.8.1.2-test
Diffstat (limited to 'Src/Zle/computil.c')
-rw-r--r--Src/Zle/computil.c114
1 files changed, 88 insertions, 26 deletions
diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c
index 90db8b4b8..59abb4cc4 100644
--- a/Src/Zle/computil.c
+++ b/Src/Zle/computil.c
@@ -1035,7 +1035,7 @@ freecadef(Cadef d)
freecaargs(d->rest);
zsfree(d->nonarg);
if (d->single)
- zfree(d->single, 256 * sizeof(Caopt));
+ zfree(d->single, 188 * sizeof(Caopt));
zfree(d, sizeof(*d));
d = s;
}
@@ -1079,6 +1079,21 @@ bslashcolon(char *s)
return r;
}
+/* Get an index into the single array used in struct cadef
+ * opt is the option letter and pre is either - or +
+ * we only keep an array for the 94 ASCII characters from ! to ~ so
+ * with - and + prefixes, the array is double that at 188 elements
+ * returns -1 if opt is out-of-range
+ */
+static int
+single_index(char pre, char opt)
+{
+ if (opt <= 0x20 || opt > 0x7e)
+ return -1;
+
+ return opt + (pre == '-' ? -0x21 : 94 - 0x21);
+}
+
/* Parse an argument definition. */
static Caarg
@@ -1151,8 +1166,8 @@ alloc_cadef(char **args, int single, char *match, char *nonarg, int flags)
ret->lastt = time(0);
ret->set = NULL;
if (single) {
- ret->single = (Caopt *) zalloc(256 * sizeof(Caopt));
- memset(ret->single, 0, 256 * sizeof(Caopt));
+ ret->single = (Caopt *) zalloc(188 * sizeof(Caopt));
+ memset(ret->single, 0, 188 * sizeof(Caopt));
} else
ret->single = NULL;
ret->match = ztrdup(match);
@@ -1558,9 +1573,10 @@ parse_cadef(char *nam, char **args)
* pointer for the definition in the array for fast lookup.
* But don't treat '--' as a single option called '-' */
-
- if (single && name[1] && !name[2] && name[1] != '-')
- ret->single[STOUC(name[1])] = opt;
+ if (single && name[1] && !name[2] && name[1] != '-') {
+ int sidx = single_index(*name, name[1]);
+ if (sidx >= 0) ret->single[sidx] = opt;
+ }
if (again == 1) {
/* Do it all again for `*-...'. */
@@ -1738,11 +1754,12 @@ ca_get_sopt(Cadef d, char *line, char **end, LinkList *lp)
Caopt p, pp = NULL;
char pre = *line++;
LinkList l = NULL;
+ int sidx;
*lp = NULL;
for (p = NULL; *line; line++) {
- if ((p = d->single[STOUC(*line)]) && p->active &&
- p->args && p->name[0] == pre) {
+ if ((sidx = single_index(pre, *line)) != -1 &&
+ (p = d->single[sidx]) && p->active && p->args) {
if (p->type == CAO_NEXT) {
if (!l)
*lp = l = newlinklist();
@@ -1813,7 +1830,7 @@ ca_get_arg(Cadef d, int n)
/* Mark options as inactive.
* d: option definitions for a set
* pass either:
- * xor: a list if exclusions
+ * xor: a list of exclusions
* opts: if set, all options excluded leaving only nornal/rest arguments */
static void
@@ -2031,9 +2048,9 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first)
state.def = state.ddef = NULL;
state.curopt = state.dopt = NULL;
state.argbeg = state.optbeg = state.nargbeg = state.restbeg = state.actopts =
- state.nth = state.inopt = state.inarg = state.opt = state.arg = 1;
+ state.nth = state.inarg = state.opt = state.arg = 1;
state.argend = argend = arrlen(compwords) - 1;
- state.singles = state.oopt = 0;
+ state.inopt = state.singles = state.oopt = 0;
state.curpos = compcurrent;
state.args = znewlinklist();
state.oargs = (LinkList *) zalloc(d->nopts * sizeof(LinkList));
@@ -2080,9 +2097,14 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first)
remnulargs(line);
untokenize(line);
- ca_inactive(d, argxor, cur - 1, 0);
- if ((d->flags & CDF_SEP) && cur != compcurrent && !strcmp(line, "--")) {
+ if (argxor) {
+ ca_inactive(d, argxor, cur - 1, 0);
+ argxor = NULL;
+ }
+ if ((d->flags & CDF_SEP) && cur != compcurrent && state.actopts &&
+ !strcmp(line, "--")) {
ca_inactive(d, NULL, cur, 1);
+ state.actopts = 0;
continue;
}
@@ -2136,7 +2158,8 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first)
/* See if it's an option. */
- if (state.opt == 2 && (state.curopt = ca_get_opt(d, line, 0, &pe)) &&
+ if (state.opt == 2 && (*line == '-' || *line == '+') &&
+ (state.curopt = ca_get_opt(d, line, 0, &pe)) &&
(state.curopt->type == CAO_OEQUAL ?
(compwords[cur] || pe[-1] == '=') :
(state.curopt->type == CAO_EQUAL ?
@@ -2184,12 +2207,14 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first)
state.curopt = NULL;
}
} else if (state.opt == 2 && d->single &&
+ (*line == '-' || *line == '+') &&
((state.curopt = ca_get_sopt(d, line, &pe, &sopts)) ||
(cur != compcurrent && sopts && nonempty(sopts)))) {
/* Or maybe it's a single-letter option? */
char *p;
Caopt tmpopt;
+ int sidx;
if (cur != compcurrent && sopts && nonempty(sopts))
state.curopt = (Caopt) uremnode(sopts, firstnode(sopts));
@@ -2207,7 +2232,8 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first)
state.singles = (!pe || !*pe);
for (p = line + 1; p < pe; p++) {
- if ((tmpopt = d->single[STOUC(*p)])) {
+ if ((sidx = single_index(*line, *p)) != -1 &&
+ (tmpopt = d->single[sidx])) {
if (!state.oargs[tmpopt->num])
state.oargs[tmpopt->num] = znewlinklist();
@@ -2235,11 +2261,17 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first)
} else if (multi && (*line == '-' || *line == '+') && cur != compcurrent
&& (ca_foreign_opt(d, all, line)))
return 1;
- else if (state.arg &&
- (!napat || cur <= compcurrent || !pattry(napat, line))) {
+ else if (state.arg && cur <= compcurrent) {
/* Otherwise it's a normal argument. */
- if (napat && cur <= compcurrent)
+
+ /* test pattern passed to -A. if it matches treat this as an unknown
+ * option and continue to the next word */
+ if (napat && cur < compcurrent && state.actopts) {
+ if (pattry(napat, line))
+ continue;
ca_inactive(d, NULL, cur + 1, 1);
+ state.actopts = 0;
+ }
arglast = 1;
/* if this is the first normal arg after an option, may have been
@@ -2293,7 +2325,7 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first)
if (adef)
state.oopt = adef->num - state.nth;
- if (state.def)
+ if (state.def && cur != compcurrent)
argxor = state.def->xor;
if (state.def && state.def->type != CAA_NORMAL &&
@@ -2375,6 +2407,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 +2612,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 +2844,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 +2865,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 +2891,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;
@@ -3591,7 +3653,7 @@ bin_compvalues(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
if (cv_laststate.vals) {
char **ret;
- ret = zlinklist2array(cv_laststate.vals);
+ ret = zlinklist2array(cv_laststate.vals, 1);
sethparam(args[1], ret);
return 0;
@@ -4016,7 +4078,7 @@ bin_comptry(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
set = (Ctset) zalloc(sizeof(*set));
- set->tags = zlinklist2array(list);
+ set->tags = zlinklist2array(list, 1);
set->next = NULL;
set->ptr = NULL;
set->tag = NULL;