diff options
author | Axel Beckert <abe@deuxchevaux.org> | 2022-04-11 00:17:48 +0200 |
---|---|---|
committer | Axel Beckert <abe@deuxchevaux.org> | 2022-04-11 00:17:48 +0200 |
commit | b09f4483416c54c1782824633dfabaf2ec0265b6 (patch) | |
tree | 304bc82642862525ae680c7fbaa249663b10ad57 /Src/Zle/computil.c | |
parent | 12eb3e5356f2fc3351eed58ef1cef1b8fb83b504 (diff) | |
parent | 6e55c920503071e917619b8cb1a188cd35d772db (diff) | |
download | zsh-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.c | 114 |
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; |