From 2a59e22f73bb2ba0a96daf0e84b6da4fe48c1280 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 21 Mar 2005 18:58:28 +0000 Subject: 21045: fix some uses of Meta characters in completion --- ChangeLog | 5 + Src/Zle/compcore.c | 840 ++++++++++++++++++++++++++++++++++++++--------------- Src/Zle/complete.c | 402 +++++++++++++++++-------- 3 files changed, 891 insertions(+), 356 deletions(-) diff --git a/ChangeLog b/ChangeLog index fb3be9e25..55901aa0d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2005-03-21 Peter Stephenson + + * 21045: Src/Zle/compcore.c, Src/Zle/complete.c: more places + where completion didn't handled Meta characters. + 2005-03-16 Peter Stephenson * 20983: Test/D02glob.ztst, Src/glob.c: fixed string segments diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c index 48189ab31..084895ae1 100644 --- a/Src/Zle/compcore.c +++ b/Src/Zle/compcore.c @@ -39,16 +39,23 @@ static Widget lastcompwidget; /**/ int useexact, useline, uselist, forcelist, startauto; +/**/ +mod_export int iforcemenu; + /* Non-zero if we should go back to the last prompt. */ /**/ -int dolastprompt; +mod_export int dolastprompt; /* Non-zero if we should keep an old list. */ /**/ -mod_export -int oldlist, oldins; +mod_export int oldlist, oldins; + +/* Original prefix/suffix lengths. Flag saying if they changed. */ + +/**/ +int origlpre, origlsuf, lenchanged; /* This is used to decide when the cursor should be moved to the end of * * the inserted word: 0 - never, 1 - only when a single match is inserted, * @@ -60,7 +67,12 @@ int movetoend; /* The match and group number to insert when starting menucompletion. */ /**/ -mod_export int insmnum, insgnum, insgroup, insspace; +mod_export int insmnum, insspace; + +#if 0 +/* group-numbers in compstate[insert] */ +int insgnum, insgroup; /* mod_export */ +#endif /* Information about menucompletion. */ @@ -131,6 +143,11 @@ mod_export Cmgroup lastmatches, pmatches, amatches, lmatches, lastlmatches; /**/ mod_export int hasoldlist, hasperm; +/* Non-zero if we have a match representing all other matches. */ + +/**/ +int hasallmatch; + /* Non-zero if we have newly added matches. */ /**/ @@ -148,6 +165,16 @@ mod_export int nmatches; /**/ mod_export int smatches; +/* != 0 if more than one match and at least two different matches */ + +/**/ +mod_export int diffmatches; + +/* The number of messages. */ + +/**/ +mod_export int nmessages; + /* != 0 if only explanation strings should be printed */ /**/ @@ -250,7 +277,7 @@ int fromcomp; /* This holds the end-position of the last string inserted into the line. */ /**/ -int lastend; +mod_export int lastend; #define inststr(X) inststrlen((X),1,-1) @@ -258,9 +285,9 @@ int lastend; /**/ int -do_completion(Hookdef dummy, Compldat dat) +do_completion(UNUSED(Hookdef dummy), Compldat dat) { - int ret = 0, lst = dat->lst, incmd = dat->incmd; + int ret = 0, lst = dat->lst, incmd = dat->incmd, osl = showinglist; char *s = dat->s; char *opm; LinkNode n; @@ -278,7 +305,7 @@ do_completion(Hookdef dummy, Compldat dat) compqstack[0] = '\''; hasunqu = 0; - useline = (lst != COMP_LIST_COMPLETE); + useline = (wouldinstab ? -1 : (lst != COMP_LIST_COMPLETE)); useexact = isset(RECEXACT); zsfree(compexactstr); compexactstr = ztrdup(""); @@ -307,6 +334,9 @@ do_completion(Hookdef dummy, Compldat dat) hasmatched = hasunmatched = 0; minmlen = 1000000; maxmlen = -1; + compignored = 0; + nmessages = 0; + hasallmatch = 0; /* Make sure we have the completion list and compctl. */ if (makecomplist(s, incmd, lst)) { @@ -318,6 +348,8 @@ do_completion(Hookdef dummy, Compldat dat) clearlist = 1; ret = 1; minfo.cur = NULL; + if (useline < 0) + ret = selfinsert(zlenoargs); goto compend; } zsfree(lastprebr); @@ -326,7 +358,13 @@ do_completion(Hookdef dummy, Compldat dat) if (comppatmatch && *comppatmatch && comppatmatch != opm) haspattern = 1; - if (!useline && uselist) { + if (iforcemenu) { + if (nmatches) + do_ambig_menu(); + ret = !nmatches; + } else if (useline < 0) + ret = selfinsert(zlenoargs); + else if (!useline && uselist) { /* All this and the guy only wants to see the list, sigh. */ cs = 0; foredel(ll); @@ -334,41 +372,8 @@ do_completion(Hookdef dummy, Compldat dat) cs = origcs; showinglist = -2; } else if (useline == 2 && nmatches > 1) { - int first = 1, nm = nmatches; - Cmatch *mc; - - menucmp = 1; - menuacc = 0; - - for (minfo.group = amatches; - minfo.group && !(minfo.group)->mcount; - minfo.group = (minfo.group)->next); + do_allmatches(1); - mc = (minfo.group)->matches; - - while (1) { - if (!first) - accept_last(); - first = 0; - - if (!--nm) - menucmp = 0; - - do_single(*mc); - minfo.cur = mc; - - if (!*++(minfo.cur)) { - do { - if (!(minfo.group = (minfo.group)->next)) - break; - } while (!(minfo.group)->mcount); - if (!minfo.group) - break; - minfo.cur = minfo.group->matches; - } - mc = minfo.cur; - } - menucmp = 0; minfo.cur = NULL; if (forcelist) @@ -377,10 +382,13 @@ do_completion(Hookdef dummy, Compldat dat) invalidatelist(); } else if (useline) { /* We have matches. */ - if (nmatches > 1) { + if (nmatches > 1 && diffmatches) { /* There is more than one match. */ ret = do_ambiguous(); - } else if (nmatches == 1) { + + if (!showinglist && uselist && listshown && (usemenu == 2 || oldlist)) + showinglist = osl; + } else if (nmatches == 1 || (nmatches > 1 && !diffmatches)) { /* Only one match. */ Cmgroup m = amatches; @@ -396,6 +404,11 @@ do_completion(Hookdef dummy, Compldat dat) clearlist = 1; } else invalidatelist(); + } else if (nmessages && forcelist) { + if (uselist) + showinglist = -2; + else + clearlist = 1; } } else { invalidatelist(); @@ -407,9 +420,10 @@ do_completion(Hookdef dummy, Compldat dat) cs = origcs; } /* Print the explanation strings if needed. */ - if (!showinglist && validlist && usemenu != 2 && nmatches != 1 && - useline != 2 && (!oldlist || !listshown)) { - onlyexpl = 1; + if (!showinglist && validlist && usemenu != 2 && uselist && + (nmatches != 1 || diffmatches) && + useline >= 0 && useline != 2 && (!oldlist || !listshown)) { + onlyexpl = 3; showinglist = -2; } compend: @@ -430,7 +444,7 @@ static int oldmenucmp; /**/ int -before_complete(Hookdef dummy, int *lst) +before_complete(UNUSED(Hookdef dummy), int *lst) { oldmenucmp = menucmp; @@ -469,22 +483,40 @@ before_complete(Hookdef dummy, int *lst) /**/ int -after_complete(Hookdef dummy, Compldat dat) +after_complete(UNUSED(Hookdef dummy), int *dat) { if (menucmp && !oldmenucmp) { - struct chdata dat; - - dat.matches = amatches; - dat.num = nmatches; - dat.cur = NULL; - if (runhookdef(MENUSTARTHOOK, (void *) &dat)) + struct chdata cdat; + int ret; + + cdat.matches = amatches; + cdat.num = nmatches; + cdat.nmesg = nmessages; + cdat.cur = NULL; + if ((ret = runhookdef(MENUSTARTHOOK, (void *) &cdat))) { + dat[1] = 0; menucmp = menuacc = 0; + minfo.cur = NULL; + if (ret >= 2) { + fixsuffix(); + cs = 0; + foredel(ll); + inststr(origline); + cs = origcs; + if (ret == 2) { + clearlist = 1; + invalidatelist(); + } + } + } } return 0; } /* This calls the given completion widget function. */ +static int parwb, parwe, paroffs; + /**/ static void callcompfunc(char *s, char *fn) @@ -521,6 +553,8 @@ callcompfunc(char *s, char *fn) compparameter = compredirect = ""; if (ispar) compcontext = (ispar == 2 ? "brace_parameter" : "parameter"); + else if (linwhat == IN_PAR) + compcontext = "assign_parameter"; else if (linwhat == IN_MATH) { if (insubscr) { compcontext = "subscript"; @@ -584,7 +618,14 @@ callcompfunc(char *s, char *fn) untokenize(*q = ztrdup(*p)); *q = NULL; } else - compwords = (char **) zcalloc(sizeof(char *)); + compwords = (char **) zshcalloc(sizeof(char *)); + + if (compredirs) + freearray(compredirs); + if (rdstrs) + compredirs = bld_list_array(rdstrs); + else + compredirs = (char **) zshcalloc(sizeof(char *)); compparameter = ztrdup(compparameter); compredirect = ztrdup(compredirect); @@ -610,7 +651,7 @@ callcompfunc(char *s, char *fn) zsfree(compprefix); zsfree(compsuffix); if (unset(COMPLETEINWORD)) { - tmp = multiquote(s, 0); + tmp = (linwhat == IN_MATH ? dupstring(s) : multiquote(s, 0)); untokenize(tmp); compprefix = ztrdup(tmp); compsuffix = ztrdup(""); @@ -621,22 +662,46 @@ callcompfunc(char *s, char *fn) sav = *ss; *ss = '\0'; - tmp = multiquote(s, 0); + tmp = (linwhat == IN_MATH ? dupstring(s) : multiquote(s, 0)); untokenize(tmp); compprefix = ztrdup(tmp); *ss = sav; - ss = multiquote(ss, 0); + ss = (linwhat == IN_MATH ? dupstring(ss) : multiquote(ss, 0)); untokenize(ss); compsuffix = ztrdup(ss); } + zsfree(complastprefix); + zsfree(complastsuffix); + complastprefix = ztrdup(compprefix); + complastsuffix = ztrdup(compsuffix); zsfree(compiprefix); - compiprefix = ztrdup(""); zsfree(compisuffix); - compisuffix = ztrdup(""); + if (parwb < 0) { + compiprefix = ztrdup(""); + compisuffix = ztrdup(""); + } else { + int l; + + compiprefix = (char *) zalloc((l = wb - parwb) + 1); + memcpy(compiprefix, line + parwb, l); + compiprefix[l] = '\0'; + compisuffix = (char *) zalloc((l = parwe - we) + 1); + memcpy(compisuffix, line + we, l); + compisuffix[l] = '\0'; + + wb = parwb; + we = parwe; + offs = paroffs; + } zsfree(compqiprefix); compqiprefix = ztrdup(qipre ? qipre : ""); zsfree(compqisuffix); compqisuffix = ztrdup(qisuf ? qisuf : ""); + origlpre = (strlen(compqiprefix) + strlen(compiprefix) + + strlen(compprefix)); + origlsuf = (strlen(compqisuffix) + strlen(compisuffix) + + strlen(compsuffix)); + lenchanged = 0; compcurrent = (usea ? (clwpos + 1 - aadd) : 0); zsfree(complist); @@ -667,7 +732,9 @@ callcompfunc(char *s, char *fn) compinsert = ""; kset &= ~CP_INSERT; } - compinsert = ztrdup(compinsert); + compinsert = (useline < 0 ? tricat("tab ", "", compinsert) : + ztrdup(compinsert)); + zsfree(compexact); if (useexact) compexact = ztrdup("accept"); else { @@ -737,35 +804,59 @@ callcompfunc(char *s, char *fn) else uselist = 0; forcelist = (complist && strstr(complist, "force")); - onlyexpl = (complist && strstr(complist, "expl")); + onlyexpl = (complist ? ((strstr(complist, "expl") ? 1 : 0) | + (strstr(complist, "messages") ? 2 : 0)) : 0); if (!compinsert) useline = 0; + else if (strstr(compinsert, "tab")) + useline = -1; else if (!strcmp(compinsert, "unambig") || !strcmp(compinsert, "unambiguous") || !strcmp(compinsert, "automenu-unambiguous")) useline = 1, usemenu = 0; - else if (!strcmp(compinsert, "menu")) - useline = 1, usemenu = 1; - else if (!strcmp(compinsert, "auto") || - !strcmp(compinsert, "automenu")) - useline = 1, usemenu = 2; else if (!strcmp(compinsert, "all")) useline = 2, usemenu = 0; else if (idigit(*compinsert)) { +#if 0 + /* group-numbers in compstate[insert] */ char *m; - +#endif useline = 1; usemenu = 3; insmnum = atoi(compinsert); +#if 0 + /* group-numbers in compstate[insert] */ if ((m = strchr(compinsert, ':'))) { insgroup = 1; insgnum = atoi(m + 1); } +#endif insspace = (compinsert[strlen(compinsert) - 1] == ' '); - } else - useline = usemenu = 0; - startauto = (compinsert && - !strcmp(compinsert, "automenu-unambiguous")); + } else { + char *p; + + if (strpfx("menu", compinsert)) + useline = 1, usemenu = 1; + else if (strpfx("auto", compinsert)) + useline = 1, usemenu = 2; + else + useline = usemenu = 0; + + if (useline && (p = strchr(compinsert, ':'))) { + insmnum = atoi(++p); +#if 0 + /* group-numbers in compstate[insert] */ + if ((p = strchr(p, ':'))) { + insgroup = 1; + insgnum = atoi(p + 1); + } +#endif + } + } + startauto = ((compinsert && + !strcmp(compinsert, "automenu-unambiguous")) || + (bashlistfirst && isset(AUTOMENU) && + (!compinsert || !*compinsert))); useexact = (compexact && !strcmp(compexact, "accept")); if (!comptoend || !*comptoend) @@ -802,16 +893,22 @@ static int makecomplist(char *s, int incmd, int lst) { char *p; + int owb = wb, owe = we, ooffs = offs; /* Inside $... ? */ - if (compfunc && (p = check_param(s, 0, 0))) + if (compfunc && (p = check_param(s, 0, 0))) { s = p; + parwb = owb; + parwe = owe; + paroffs = ooffs; + } else + parwb = -1; linwhat = inwhat; if (compfunc) { char *os = s; - int onm = nmatches, osi = movefd(0); + int onm = nmatches, odm = diffmatches, osi = movefd(0); bmatchers = NULL; mstack = NULL; @@ -827,8 +924,13 @@ makecomplist(char *s, int incmd, int lst) mnum = 0; unambig_mnum = -1; isuf = NULL; - insmnum = insgnum = 1; - insgroup = oldlist = oldins = 0; + insmnum = 1; +#if 0 + /* group-numbers in compstate[insert] */ + insgnum = 1; + insgroup = 0; +#endif + oldlist = oldins = 0; begcmgroup("default", 0); menucmp = menuacc = newmatches = onlyexpl = 0; @@ -841,11 +943,12 @@ makecomplist(char *s, int incmd, int lst) if (oldlist) { nmatches = onm; + diffmatches = odm; validlist = 1; amatches = lastmatches; lmatches = lastlmatches; if (pmatches) { - freematches(pmatches); + freematches(pmatches, 1); pmatches = NULL; hasperm = 0; } @@ -854,7 +957,7 @@ makecomplist(char *s, int incmd, int lst) return 0; } if (lastmatches) { - freematches(lastmatches); + freematches(lastmatches, 1); lastmatches = NULL; } permmatches(1); @@ -868,7 +971,7 @@ makecomplist(char *s, int incmd, int lst) hasperm = 0; hasoldlist = 1; - if (nmatches && !errflag) { + if ((nmatches || nmessages) && !errflag) { validlist = 1; redup(osi, 0); @@ -1041,7 +1144,7 @@ check_param(char *s, int set, int test) } /* Save the prefix. */ if (compfunc) { - parflags = (br >= 2 ? CMF_PARBR : 0); + parflags = (br >= 2 ? CMF_PARBR | (nest ? CMF_PARNEST : 0) : 0); sav = *b; *b = '\0'; untokenize(parpre = ztrdup(s)); @@ -1078,6 +1181,30 @@ rembslash(char *s) return t; } +/* Remove one of every pair of single quotes, without copying. Return + * the number of removed quotes. */ + +/**/ +mod_export int +remsquote(char *s) +{ + int ret = 0, qa = (isset(RCQUOTES) ? 1 : 3); + char *t = s; + + while (*s) + if (qa == 1 ? + (s[0] == '\'' && s[1] == '\'') : + (s[0] == '\'' && s[1] == '\\' && s[2] == '\'' && s[3] == '\'')) { + ret += qa; + *t++ = '\''; + s += qa + 1; + } else + *t++ = *s++; + *t = '\0'; + + return ret; +} + /* This should probably be moved into tokenize(). */ /**/ @@ -1147,8 +1274,9 @@ set_comp_sep(void) LinkList foo = newlinklist(); LinkNode n; int owe = we, owb = wb, ocs = cs, swb, swe, scs, soffs, ne = noerrs; - int tl, got = 0, i = 0, cur = -1, oll = ll, sl, remq; - int ois = instring, oib = inbackt, noffs = lp; + int tl, got = 0, i = 0, j, cur = -1, oll = ll, sl, css = 0; + int remq = 0, dq = 0, odq, sq = 0, osq, issq = 0, sqq = 0, lsq = 0, qa = 0; + int ois = instring, oib = inbackt, noffs = lp, ona = noaliases; char *tmp, *p, *ns, *ol = (char *) line, sav, *qp, *qs, *ts, qc = '\0'; s += lip; @@ -1169,8 +1297,37 @@ set_comp_sep(void) memcpy(tmp + 1, s, noffs); tmp[(scs = cs = 1 + noffs)] = 'x'; strcpy(tmp + 2 + noffs, s + noffs); - if ((remq = (*compqstack == '\\'))) + + switch (*compqstack) { + case '\\': + remq = 1; tmp = rembslash(tmp); + break; + case '\'': + issq = 1; + if (isset(RCQUOTES)) + qa = 1; + else + qa = 3; + + sq = remsquote(tmp); + + break; + case '"': + for (j = 0, p = tmp; *p; p++, j++) + if (*p == '\\' && p[1] == '\\') { + dq++; + chuck(p); + if (j > cs) { + cs++; + css++; + } + if (!*p) + break; + } + } + odq = dq; + osq = sq; inpush(dupstrspace(tmp), 0, NULL); line = (unsigned char *) tmp; ll = tl - 1; @@ -1183,9 +1340,10 @@ set_comp_sep(void) if (!tokstr) break; - for (j = 0, p = tokstr; *p; p++) + for (j = 0, p = tokstr; *p; p++) { if (*p == Snull || *p == Dnull) j++; + } if (j & 1) { tok = STRING; if (p > tokstr && p[-1] == ' ') @@ -1194,23 +1352,44 @@ set_comp_sep(void) } if (tok == ENDINPUT || tok == LEXERR) break; - if (tokstr && *tokstr) + if (tokstr && *tokstr) { + for (p = tokstr; dq && *p; p++) { + if (*p == Bnull) { + dq--; + if (p[1] == '\\') + dq--; + } + } + if (issq) { + for (p = tokstr, lsq = 0; *p; p++) { + if (sq && *p == Snull) + sq -= qa; + if (*p == '\'') { + sq -= qa; + lsq += qa; + } + } + } + else + lsq = 0; addlinknode(foo, (p = ztrdup(tokstr))); + } else p = NULL; if (!got && !zleparse) { DPUTS(!p, "no current word in substr"); got = 1; cur = i; - swb = wb - 1; - swe = we - 1; - soffs = cs - swb; + swb = wb - 1 - dq - sq; + swe = we - 1 - dq - sq; + sqq = lsq; + soffs = cs - swb - css; chuck(p + soffs); ns = dupstring(p); } i++; } while (tok != ENDINPUT && tok != LEXERR); - noaliases = 0; + noaliases = ona; strinend(); inpop(); errflag = zleparse = 0; @@ -1255,8 +1434,15 @@ set_comp_sep(void) for (p = ns, i = swb; *p; p++, i++) { if (INULL(*p)) { if (i < scs) { - if (remq && *p == Bnull && p[1]) - swb -= 2; + if (*p == Bnull) { + if (p[1] && remq) + swb -= 2; + if (odq) { + swb--; + if (p[1] == '\\') + swb--; + } + } } if (p[1] || *p != Bnull) { if (*p == Bnull) { @@ -1281,9 +1467,9 @@ set_comp_sep(void) if (ql > rl) swb -= ql - rl; } - sav = s[(i = swb - 1)]; + sav = s[(i = swb - 1 - sqq)]; s[i] = '\0'; - qp = rembslash(s); + qp = (issq ? dupstring(s) : rembslash(s)); s[i] = sav; if (swe < swb) swe = swb; @@ -1291,14 +1477,17 @@ set_comp_sep(void) sl = strlen(s); if (swe > sl) { swe = sl; - if (strlen(ns) > swe - swb + 1) + if ((int)strlen(ns) > swe - swb + 1) ns[swe - swb + 1] = '\0'; } - qs = rembslash(s + swe); + qs = (issq ? dupstring(s + swe) : rembslash(s + swe)); sl = strlen(ns); if (soffs > sl) soffs = sl; - + if (issq) { + remsquote(qp); + remsquote(qs); + } { int set = CP_QUOTE | CP_QUOTING, unset = 0; @@ -1343,6 +1532,10 @@ set_comp_sep(void) untokenize(ss); compsuffix = ztrdup(ss); } + if ((i = strlen(compprefix)) > 1 && compprefix[i - 1] == '\\' && + compprefix[i - 2] != '\\' && compprefix[i - 2] != Meta) + compprefix[i - 1] = '\0'; + tmp = tricat(compqiprefix, compiprefix, multiquote(qp, 1)); zsfree(compqiprefix); compqiprefix = tmp; @@ -1369,11 +1562,11 @@ set_comp_sep(void) return 0; } -/* This stores the strings from the list in an array. */ +/* This builds an array from a list of strings. */ /**/ -mod_export void -set_list_array(char *name, LinkList l) +mod_export char ** +bld_list_array(LinkList l) { char **a, **p; LinkNode n; @@ -1383,7 +1576,16 @@ set_list_array(char *name, LinkList l) *p++ = ztrdup((char *) getdata(n)); *p = NULL; - setaparam(name, a); + return a; +} + +/* This stores the strings from the list in an array. */ + +/**/ +mod_export void +set_list_array(char *name, LinkList l) +{ + setaparam(name, bld_list_array(l)); } /* Get the words from a variable or a (list of words). */ @@ -1437,18 +1639,72 @@ get_user_var(char *nam) /* Otherwise it should be a parameter name. */ char **arr = NULL, *val; + queue_signals(); if ((arr = getaparam(nam)) || (arr = gethparam(nam))) - return (incompfunc ? arrdup(arr) : arr); - - if ((val = getsparam(nam))) { + arr = (incompfunc ? arrdup(arr) : arr); + else if ((val = getsparam(nam))) { arr = (char **) zhalloc(2*sizeof(char *)); arr[0] = (incompfunc ? dupstring(val) : val); arr[1] = NULL; } + unqueue_signals(); return arr; } } +static char ** +get_data_arr(char *name, int keys) +{ + struct value vbuf; + char **ret; + Value v; + + queue_signals(); + if (!(v = fetchvalue(&vbuf, &name, 1, + (keys ? SCANPM_WANTKEYS : SCANPM_WANTVALS) | + SCANPM_MATCHMANY))) + ret = NULL; + else + ret = getarrvalue(v); + unqueue_signals(); + + return ret; +} + +static void +addmatch(char *str, int flags, char ***dispp, int line) +{ + Cmatch cm = (Cmatch) zhalloc(sizeof(struct cmatch)); + char **disp = *dispp; + + memset(cm, 0, sizeof(struct cmatch)); + cm->str = dupstring(str); + cm->flags = (flags | + (complist ? + ((strstr(complist, "packed") ? CMF_PACKED : 0) | + (strstr(complist, "rows") ? CMF_ROWS : 0)) : 0)); + if (disp) { + if (!*++disp) + disp = NULL; + if (disp) + cm->disp = dupstring(*disp); + } else if (line) { + cm->disp = dupstring(""); + cm->flags |= CMF_DISPLINE; + } + mnum++; + ainfo->count++; + if (curexpl) + curexpl->count++; + + addlinknode(matches, cm); + + newmatches = 1; + mgroup->new = 1; + + *dispp = disp; +} + /* This is used by compadd to add a couple of matches. The arguments are * the strings given via options. The last argument is the array with * the matches. */ @@ -1460,10 +1716,11 @@ addmatches(Cadata dat, char **argv) char *s, *ms, *lipre = NULL, *lisuf = NULL, *lpre = NULL, *lsuf = NULL; char **aign = NULL, **dparr = NULL, *oaq = autoq, *oppre = dat->ppre; char *oqp = qipre, *oqs = qisuf, qc, **disp = NULL, *ibuf = NULL; + char **arrays = NULL; int lpl, lsl, pl, sl, bcp = 0, bcs = 0, bpadd = 0, bsadd = 0; - int ppl = 0, psl = 0; + int ppl = 0, psl = 0, ilen = 0; int llpl = 0, llsl = 0, nm = mnum, gflags = 0, ohp = haspattern; - int oisalt = 0, isalt, isexact, doadd, ois = instring, oib = inbackt; + int isexact, doadd, ois = instring, oib = inbackt; Cline lc = NULL, pline = NULL, sline = NULL; Cmatch cm; struct cmlist mst; @@ -1471,24 +1728,38 @@ addmatches(Cadata dat, char **argv) Patprog cp = NULL, *pign = NULL; LinkList aparl = NULL, oparl = NULL, dparl = NULL; Brinfo bp, bpl = brbeg, obpl, bsl = brend, obsl; - - if (!*argv) { - SWITCHHEAPS(compheap) { - /* Select the group in which to store the matches. */ - gflags = (((dat->aflags & CAF_NOSORT ) ? CGF_NOSORT : 0) | - ((dat->aflags & CAF_UNIQALL) ? CGF_UNIQALL : 0) | - ((dat->aflags & CAF_UNIQCON) ? CGF_UNIQCON : 0)); - if (dat->group) { - endcmgroup(NULL); - begcmgroup(dat->group, gflags); - } else { - endcmgroup(NULL); - begcmgroup("default", 0); - } - } SWITCHBACKHEAPS; - + Heap oldheap; + + SWITCHHEAPS(oldheap, compheap) { + if (dat->dummies) + dat->aflags = ((dat->aflags | CAF_NOSORT | CAF_UNIQCON) & + ~CAF_UNIQALL); + + /* Select the group in which to store the matches. */ + gflags = (((dat->aflags & CAF_NOSORT ) ? CGF_NOSORT : 0) | + ((dat->aflags & CAF_UNIQALL) ? CGF_UNIQALL : 0) | + ((dat->aflags & CAF_UNIQCON) ? CGF_UNIQCON : 0)); + if (dat->group) { + endcmgroup(NULL); + begcmgroup(dat->group, gflags); + } else { + endcmgroup(NULL); + begcmgroup("default", 0); + } + if (dat->mesg || dat->exp) { + curexpl = (Cexpl) zhalloc(sizeof(struct cexpl)); + curexpl->always = !!dat->mesg; + curexpl->count = curexpl->fcount = 0; + curexpl->str = dupstring(dat->mesg ? dat->mesg : dat->exp); + if (dat->mesg) + addexpl(1); + } else + curexpl = NULL; + } SWITCHBACKHEAPS(oldheap); + + if (!*argv && !dat->dummies && !(dat->aflags & CAF_ALL)) return 1; - } + for (bp = brbeg; bp; bp = bp->next) bp->curpos = ((dat->aflags & CAF_QUOTE) ? bp->pos : bp->qpos); for (bp = brend; bp; bp = bp->next) @@ -1521,7 +1792,7 @@ addmatches(Cadata dat, char **argv) /* Switch back to the heap that was used when the completion widget * was invoked. */ - SWITCHHEAPS(compheap) { + SWITCHHEAPS(oldheap, compheap) { if ((doadd = (!dat->apar && !dat->opar && !dat->dpar))) { if (dat->aflags & CAF_MATCH) hasmatched = 1; @@ -1539,13 +1810,6 @@ addmatches(Cadata dat, char **argv) dparr = NULL; dparl = newlinklist(); } - if (dat->exp) { - curexpl = (Cexpl) zhalloc(sizeof(struct cexpl)); - curexpl->count = curexpl->fcount = 0; - curexpl->str = dupstring(dat->exp); - } else - curexpl = NULL; - /* Store the matcher in our stack of matchers. */ if (dat->match) { mst.next = mstack; @@ -1597,6 +1861,11 @@ addmatches(Cadata dat, char **argv) lsuf = dupstring(compsuffix); llpl = strlen(lpre); llsl = strlen(lsuf); + + if (llpl + (int)strlen(compqiprefix) + (int)strlen(lipre) != origlpre + || llsl + (int)strlen(compqisuffix) + (int)strlen(lisuf) != origlsuf) + lenchanged = 1; + /* Test if there is an existing -P prefix. */ if (dat->pre && *dat->pre) { pl = pfxlen(dat->pre, lpre); @@ -1649,55 +1918,57 @@ addmatches(Cadata dat, char **argv) llpl -= gfl; } } - s = dat->ppre ? dat->ppre : ""; - if ((ml = match_str(lpre, s, &bpl, 0, NULL, 0, 0, 1)) >= 0) { - if (matchsubs) { - Cline tmp = get_cline(NULL, 0, NULL, 0, NULL, 0, 0); - - tmp->prefix = matchsubs; - if (matchlastpart) - matchlastpart->next = tmp; + if ((s = dat->ppre)) { + if ((ml = match_str(lpre, s, &bpl, 0, NULL, 0, 0, 1)) >= 0) { + if (matchsubs) { + Cline tmp = get_cline(NULL, 0, NULL, 0, NULL, 0, 0); + + tmp->prefix = matchsubs; + if (matchlastpart) + matchlastpart->next = tmp; + else + matchparts = tmp; + } + pline = matchparts; + lpre += ml; + llpl -= ml; + bcp = ml; + bpadd = strlen(s) - ml; + } else { + if (llpl <= lpl && strpfx(lpre, s)) + lpre = dupstring(""); + else if (llpl > lpl && strpfx(s, lpre)) + lpre += lpl; else - matchparts = tmp; + *argv = NULL; + bcp = lpl; } - pline = matchparts; - lpre += ml; - llpl -= ml; - bcp = ml; - bpadd = strlen(s) - ml; - } else { - if (llpl <= lpl && strpfx(lpre, s)) - lpre = ""; - else if (llpl > lpl && strpfx(s, lpre)) - lpre += lpl; - else - *argv = NULL; - bcp = lpl; } - s = dat->psuf ? dat->psuf : ""; - if ((ml = match_str(lsuf, s, &bsl, 0, NULL, 1, 0, 1)) >= 0) { - if (matchsubs) { - Cline tmp = get_cline(NULL, 0, NULL, 0, NULL, 0, CLF_SUF); - - tmp->suffix = matchsubs; - if (matchlastpart) - matchlastpart->next = tmp; + if ((s = dat->psuf)) { + if ((ml = match_str(lsuf, s, &bsl, 0, NULL, 1, 0, 1)) >= 0) { + if (matchsubs) { + Cline tmp = get_cline(NULL, 0, NULL, 0, NULL, 0, CLF_SUF); + + tmp->suffix = matchsubs; + if (matchlastpart) + matchlastpart->next = tmp; + else + matchparts = tmp; + } + sline = revert_cline(matchparts); + lsuf[llsl - ml] = '\0'; + llsl -= ml; + bcs = ml; + bsadd = strlen(s) - ml; + } else { + if (llsl <= lsl && strsfx(lsuf, s)) + lsuf = dupstring(""); + else if (llsl > lsl && strsfx(s, lsuf)) + lsuf[llsl - lsl] = '\0'; else - matchparts = tmp; + *argv = NULL; + bcs = lsl; } - sline = revert_cline(matchparts); - lsuf[llsl - ml] = '\0'; - llsl -= ml; - bcs = ml; - bsadd = strlen(s) - ml; - } else { - if (llsl <= lsl && strsfx(lsuf, s)) - lsuf = ""; - else if (llsl > lsl && strsfx(s, lsuf)) - lsuf[llsl - lsl] = '\0'; - else - *argv = NULL; - bcs = lsl; } if (comppatmatch && *comppatmatch) { int is = (*comppatmatch == '*'); @@ -1721,17 +1992,6 @@ addmatches(Cadata dat, char **argv) } } } - /* Select the group in which to store the matches. */ - gflags = (((dat->aflags & CAF_NOSORT ) ? CGF_NOSORT : 0) | - ((dat->aflags & CAF_UNIQALL) ? CGF_UNIQALL : 0) | - ((dat->aflags & CAF_UNIQCON) ? CGF_UNIQCON : 0)); - if (dat->group) { - endcmgroup(NULL); - begcmgroup(dat->group, gflags); - } else { - endcmgroup(NULL); - begcmgroup("default", 0); - } if (*argv) { if (dat->pre) dat->pre = dupstring(dat->pre); @@ -1743,7 +2003,6 @@ addmatches(Cadata dat, char **argv) } else dat->prpre = dupstring(dat->prpre); /* Select the set of matches. */ - oisalt = (dat->aflags & CAF_ALT); if (dat->remf) { dat->remf = dupstring(dat->remf); @@ -1761,17 +2020,28 @@ addmatches(Cadata dat, char **argv) /* Walk through the matches given. */ obpl = bpl; obsl = bsl; - if (!oisalt && (aign || pign)) { - int max = 0; - char **ap = argv; - - ppl = (dat->ppre ? strlen(dat->ppre) : 0); - while ((s = *ap++)) - if ((sl = strlen(s)) > max) - max = sl; - psl = (dat->psuf ? strlen(dat->psuf) : 0); - ibuf = (char *) zhalloc(1 + ppl + max + psl); + if (dat->aflags & CAF_ARRAYS) { + Heap oldheap2; + + SWITCHHEAPS(oldheap2, oldheap) { + arrays = argv; + argv = NULL; + while (*arrays && + (!(argv = get_data_arr(*arrays, + (dat->aflags & CAF_KEYS))) || + !*argv)) + arrays++; + arrays++; + if (!argv) { + ms = NULL; + argv = &ms; + } + } SWITCHBACKHEAPS(oldheap2); } + if (dat->ppre) + ppl = strlen(dat->ppre); + if (dat->psuf) + psl = strlen(dat->psuf); for (; (s = *argv); argv++) { bpl = obpl; bsl = obsl; @@ -1780,9 +2050,11 @@ addmatches(Cadata dat, char **argv) disp = NULL; } sl = strlen(s); - isalt = oisalt; - if (!isalt && (aign || pign)) { - int il = ppl + sl + psl; + if (aign || pign) { + int il = ppl + sl + psl, addit = 1; + + if (il + 1> ilen) + ibuf = (char *) zhalloc((ilen = il) + 2); if (ppl) memcpy(ibuf, dat->ppre, ppl); @@ -1796,15 +2068,21 @@ addmatches(Cadata dat, char **argv) char **pt = aign; int filell; - for (isalt = 0; !isalt && *pt; pt++) - isalt = ((filell = strlen(*pt)) < il && - !strcmp(*pt, ibuf + il - filell)); + for (; addit && *pt; pt++) + addit = !((filell = strlen(*pt)) < il && + !strcmp(*pt, ibuf + il - filell)); } - if (!isalt && pign) { + if (addit && pign) { Patprog *pt = pign; - for (isalt = 0; !isalt && *pt; pt++) - isalt = pattry(*pt, ibuf); + for (; addit && *pt; pt++) + addit = !pattry(*pt, ibuf); + } + if (!addit) { + compignored++; + if (dparr && !*++dparr) + dparr = NULL; + goto next_array; } } if (!(dat->aflags & CAF_MATCH)) { @@ -1822,7 +2100,7 @@ addmatches(Cadata dat, char **argv) &isexact))) { if (dparr && !*++dparr) dparr = NULL; - continue; + goto next_array; } if (doadd) { Brinfo bp; @@ -1832,7 +2110,7 @@ addmatches(Cadata dat, char **argv) for (bp = obsl; bp; bp = bp->next) bp->curpos += bsadd; - if ((cm = add_match_data(isalt, ms, lc, dat->ipre, NULL, + if ((cm = add_match_data(0, ms, s, lc, dat->ipre, NULL, dat->isuf, dat->pre, dat->prpre, dat->ppre, pline, dat->psuf, sline, @@ -1854,6 +2132,25 @@ addmatches(Cadata dat, char **argv) } free_cline(lc); } + next_array: + if ((dat->aflags & CAF_ARRAYS) && !argv[1]) { + Heap oldheap2; + + SWITCHHEAPS(oldheap2, oldheap) { + argv = NULL; + while (*arrays && + (!(argv = get_data_arr(*arrays, + (dat->aflags & CAF_KEYS))) || + !*argv)) + arrays++; + arrays++; + if (!argv) { + ms = NULL; + argv = &ms; + } + argv--; + } SWITCHBACKHEAPS(oldheap2); + } } if (dat->apar) set_list_array(dat->apar, aparl); @@ -1862,8 +2159,15 @@ addmatches(Cadata dat, char **argv) if (dat->dpar) set_list_array(dat->dpar, dparl); if (dat->exp) - addexpl(); - } SWITCHBACKHEAPS; + addexpl(0); + if (!hasallmatch && (dat->aflags & CAF_ALL)) { + addmatch("", dat->flags | CMF_ALL, &disp, 1); + hasallmatch = 1; + } + while (dat->dummies--) + addmatch("", dat->flags | CMF_DUMMY, &disp, 0); + + } SWITCHBACKHEAPS(oldheap); /* We switched back to the current heap, now restore the stack of * matchers. */ @@ -1887,7 +2191,7 @@ addmatches(Cadata dat, char **argv) /**/ mod_export Cmatch -add_match_data(int alt, char *str, Cline line, +add_match_data(int alt, char *str, char *orig, Cline line, char *ipre, char *ripre, char *isuf, char *pre, char *prpre, char *ppre, Cline pline, @@ -1977,7 +2281,7 @@ add_match_data(int alt, char *str, Cline line, sl = tsl; } if (qisl) { - Cline qsl = bld_parts(qisuf, qisl, qisl, NULL); + Cline qsl = bld_parts(dupstring(qisuf), qisl, qisl, NULL); qsl->flags |= CLF_SUF; qsl->suffix = qsl->prefix; @@ -2060,7 +2364,7 @@ add_match_data(int alt, char *str, Cline line, line = p; } if (qipl) { - Cline lp, p = bld_parts(qipre, qipl, qipl, &lp); + Cline lp, p = bld_parts(dupstring(qipre), qipl, qipl, &lp); lp->next = line; line = p; @@ -2115,6 +2419,7 @@ add_match_data(int alt, char *str, Cline line, /* Allocate and fill the match structure. */ cm = (Cmatch) zhalloc(sizeof(struct cmatch)); cm->str = str; + cm->orig = dupstring(orig); cm->ppre = (ppre && *ppre ? ppre : NULL); cm->psuf = (psuf && *psuf ? psuf : NULL); cm->prpre = ((flags & CMF_FILE) && prpre && *prpre ? prpre : NULL); @@ -2133,7 +2438,22 @@ add_match_data(int alt, char *str, Cline line, (complist ? ((strstr(complist, "packed") ? CMF_PACKED : 0) | (strstr(complist, "rows") ? CMF_ROWS : 0)) : 0)); - + cm->mode = 0; + cm->modec = '\0'; + if ((flags & CMF_FILE) && orig[0] && orig[strlen(orig) - 1] != '/') { + struct stat buf; + char *pb; + + pb = (char *) zhalloc((cm->prpre ? strlen(cm->prpre) : 0) + + 3 + strlen(orig)); + sprintf(pb, "%s%s", (cm->prpre ? cm->prpre : "./"), orig); + + if (!ztat(pb, &buf, 1)) { + cm->mode = buf.st_mode; + if ((cm->modec = file_type(buf.st_mode)) == ' ') + cm->modec = '\0'; + } + } if ((*compqstack == '\\' && compqstack[1]) || (autoq && *compqstack && compqstack[1] == '\\')) cm->flags |= CMF_NOSPACE; @@ -2175,6 +2495,8 @@ add_match_data(int alt, char *str, Cline line, newmatches = 1; mgroup->new = 1; + if (alt) + compignored++; if (!complastprompt || !*complastprompt) dolastprompt = 0; @@ -2221,7 +2543,7 @@ add_match_data(int alt, char *str, Cline line, comp_setunset(0, 0, CP_EXACTSTR, 0); } ai->exactm = cm; - } else if (useexact) { + } else if (useexact && !matcheq(cm, ai->exactm)) { ai->exact = 2; ai->exactm = NULL; if (incompfunc) @@ -2258,13 +2580,14 @@ begcmgroup(char *n, int flags) } mgroup = (Cmgroup) zhalloc(sizeof(struct cmgroup)); mgroup->name = dupstring(n); - mgroup->lcount = mgroup->llcount = mgroup->mcount = 0; + mgroup->lcount = mgroup->llcount = mgroup->mcount = mgroup->ecount = + mgroup->ccount = 0; mgroup->flags = flags; mgroup->matches = NULL; mgroup->ylist = NULL; mgroup->expls = NULL; mgroup->perm = NULL; - mgroup->new = 0; + mgroup->new = mgroup->num = mgroup->nbrbeg = mgroup->nbrend = 0; mgroup->lexpls = expls = newlinklist(); mgroup->lmatches = matches = newlinklist(); @@ -2272,7 +2595,9 @@ begcmgroup(char *n, int flags) mgroup->lallccs = allccs = ((flags & CGF_NOSORT) ? NULL : newlinklist()); - mgroup->next = amatches; + if ((mgroup->next = amatches)) + amatches->prev = mgroup; + mgroup->prev = NULL; amatches = mgroup; } @@ -2289,7 +2614,7 @@ endcmgroup(char **ylist) /**/ mod_export void -addexpl(void) +addexpl(int always) { LinkNode n; Cexpl e; @@ -2299,12 +2624,21 @@ addexpl(void) if (!strcmp(curexpl->str, e->str)) { e->count += curexpl->count; e->fcount += curexpl->fcount; - + if (always) { + e->always = 1; + nmessages++; + newmatches = 1; + mgroup->new = 1; + } return; } } addlinknode(expls, curexpl); newmatches = 1; + if (always) { + mgroup->new = 1; + nmessages++; + } } /* The comparison function for matches (used for sorting). */ @@ -2425,6 +2759,8 @@ makearray(LinkList l, int type, int flags, int *np, int *nlp, int *llp) } } else { if (!(flags & CGF_UNIQALL) && !(flags & CGF_UNIQCON)) { + int dup; + for (ap = rp; *ap; ap++) { for (bp = cp = ap + 1; *bp; bp++) { if (!matcheq(*ap, *bp)) @@ -2433,6 +2769,17 @@ makearray(LinkList l, int type, int flags, int *np, int *nlp, int *llp) n--; } *cp = NULL; + if (!(*ap)->disp) { + for (dup = 0, bp = ap + 1; *bp; bp++) + if (!(*bp)->disp && + !((*bp)->flags & CMF_MULT) && + !strcmp((*ap)->str, (*bp)->str)) { + (*bp)->flags |= CMF_MULT; + dup = 1; + } + if (dup) + (*ap)->flags |= CMF_FMULT; + } } } else if (!(flags & CGF_UNIQCON)) { int dup; @@ -2476,9 +2823,10 @@ dupmatch(Cmatch m, int nbeg, int nend) { Cmatch r; - r = (Cmatch) zcalloc(sizeof(struct cmatch)); + r = (Cmatch) zshcalloc(sizeof(struct cmatch)); r->str = ztrdup(m->str); + r->orig = ztrdup(m->orig); r->ipre = ztrdup(m->ipre); r->ripre = ztrdup(m->ripre); r->isuf = ztrdup(m->isuf); @@ -2488,7 +2836,7 @@ dupmatch(Cmatch m, int nbeg, int nend) r->pre = ztrdup(m->pre); r->suf = ztrdup(m->suf); r->flags = m->flags; - if (nbeg) { + if (m->brpl) { int *p, *q, i; r->brpl = (int *) zalloc(nbeg * sizeof(int)); @@ -2497,7 +2845,7 @@ dupmatch(Cmatch m, int nbeg, int nend) *p = *q; } else r->brpl = NULL; - if (nend) { + if (m->brsl) { int *p, *q, i; r->brsl = (int *) zalloc(nend * sizeof(int)); @@ -2512,6 +2860,8 @@ dupmatch(Cmatch m, int nbeg, int nend) r->qipl = m->qipl; r->qisl = m->qisl; r->disp = ztrdup(m->disp); + r->mode = m->mode; + r->modec = m->modec; return r; } @@ -2538,7 +2888,7 @@ permmatches(int last) opm = pmatches; pmatches = lmatches = NULL; - nmatches = smatches = 0; + nmatches = smatches = diffmatches = 0; if (!ainfo->count) { if (last) @@ -2570,11 +2920,14 @@ permmatches(int last) nmatches += g->mcount; smatches += g->lcount; - n = (Cmgroup) zcalloc(sizeof(struct cmgroup)); + if (g->mcount > 1) + diffmatches = 1; + + n = (Cmgroup) zshcalloc(sizeof(struct cmgroup)); if (g->perm) { g->perm->next = NULL; - freematches(g->perm); + freematches(g->perm, 0); } g->perm = n; @@ -2588,7 +2941,7 @@ permmatches(int last) n->num = gn++; n->flags = g->flags; n->mcount = g->mcount; - n->matches = p = (Cmatch *) zcalloc((n->mcount + 1) * sizeof(Cmatch)); + n->matches = p = (Cmatch *) zshcalloc((n->mcount + 1) * sizeof(Cmatch)); n->name = ztrdup(g->name); for (q = g->matches; *q; q++, p++) *p = dupmatch(*q, nbrbeg, nbrend); @@ -2602,10 +2955,12 @@ permmatches(int last) n->ylist = NULL; if ((n->ecount = g->ecount)) { - n->expls = ep = (Cexpl *) zcalloc((n->ecount + 1) * sizeof(Cexpl)); + n->expls = ep = (Cexpl *) zshcalloc((n->ecount + 1) * sizeof(Cexpl)); for (eq = g->expls; (o = *eq); eq++, ep++) { - *ep = e = (Cexpl) zcalloc(sizeof(struct cexpl)); + *ep = e = (Cexpl) zshcalloc(sizeof(struct cexpl)); e->count = (fi ? o->fcount : o->count); + e->always = o->always; + e->fcount = 0; e->str = ztrdup(o->str); } *ep = NULL; @@ -2624,18 +2979,29 @@ permmatches(int last) nmatches += g->mcount; smatches += g->lcount; + + if (g->mcount > 1) + diffmatches = 1; + g->num = gn++; } g->new = 0; g = g->next; } - for (g = pmatches; g; g = g->next) { + for (g = pmatches, p = NULL; g; g = g->next) { g->nbrbeg = nbrbeg; g->nbrend = nbrend; for (rn = 1, q = g->matches; *q; q++) { (*q)->rnum = rn++; (*q)->gnum = mn++; } + if (!diffmatches && *g->matches) { + if (p) { + if (!matcheq(*g->matches, *p)) + diffmatches = 1; + } else + p = g->matches; + } } hasperm = 1; permmnum = mn - 1; @@ -2654,6 +3020,7 @@ freematch(Cmatch m, int nbeg, int nend) if (!m) return; zsfree(m->str); + zsfree(m->orig); zsfree(m->ipre); zsfree(m->ripre); zsfree(m->isuf); @@ -2666,8 +3033,10 @@ freematch(Cmatch m, int nbeg, int nend) zsfree(m->remf); zsfree(m->disp); zsfree(m->autoq); - zfree(m->brpl, nbeg * sizeof(int)); - zfree(m->brsl, nend * sizeof(int)); + if (m->brpl) + zfree(m->brpl, nbeg * sizeof(int)); + if (m->brsl) + zfree(m->brsl, nend * sizeof(int)); zfree(m, sizeof(m)); } @@ -2676,7 +3045,7 @@ freematch(Cmatch m, int nbeg, int nend) /**/ mod_export void -freematches(Cmgroup g) +freematches(Cmgroup g, int cm) { Cmgroup n; Cmatch *m; @@ -2687,6 +3056,7 @@ freematches(Cmgroup g) for (m = g->matches; *m; m++) freematch(*m, g->nbrbeg, g->nbrend); + free(g->matches); if (g->ylist) freearray(g->ylist); @@ -2704,4 +3074,6 @@ freematches(Cmgroup g) g = n; } + if (cm) + minfo.cur = NULL; } diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c index f625c34cd..d1f3366e7 100644 --- a/Src/Zle/complete.c +++ b/Src/Zle/complete.c @@ -33,16 +33,21 @@ /* global variables for shell parameters in new style completion */ /**/ -mod_export zlong compcurrent; +mod_export +zlong compcurrent, + complistmax; /**/ -zlong complistmax, - complistlines; +zlong complistlines, + compignored; /**/ mod_export char **compwords, + **compredirs, *compprefix, *compsuffix, + *complastprefix, + *complastsuffix, *compisuffix, *compqiprefix, *compqisuffix, @@ -181,66 +186,99 @@ parse_cmatcher(char *name, char *s) { Cmatcher ret = NULL, r = NULL, n; Cpattern line, word, left, right; - int fl, ll, wl, lal, ral, err; + int fl, fl2, ll, wl, lal, ral, err, both; if (!*s) return NULL; while (*s) { + lal = ral = both = fl2 = 0; + left = right = NULL; + while (*s && inblank(*s)) s++; if (!*s) break; switch (*s) { + case 'b': fl2 = CMF_INTER; case 'l': fl = CMF_LEFT; break; + case 'e': fl2 = CMF_INTER; case 'r': fl = CMF_RIGHT; break; case 'm': fl = 0; break; + case 'B': fl2 = CMF_INTER; case 'L': fl = CMF_LEFT | CMF_LINE; break; + case 'E': fl2 = CMF_INTER; case 'R': fl = CMF_RIGHT | CMF_LINE; break; case 'M': fl = CMF_LINE; break; default: - zwarnnam(name, "unknown match specification character `%c'", NULL, *s); + if (name) + zwarnnam(name, "unknown match specification character `%c'", + NULL, *s); return pcm_err; } if (s[1] != ':') { - zwarnnam(name, "missing `:'", NULL, 0); + if (name) + zwarnnam(name, "missing `:'", NULL, 0); return pcm_err; } s += 2; if (!*s) { - zwarnnam(name, "missing patterns", NULL, 0); + if (name) + zwarnnam(name, "missing patterns", NULL, 0); return pcm_err; } - if (fl & CMF_LEFT) { + if ((fl & CMF_LEFT) && !fl2) { left = parse_pattern(name, &s, &lal, '|', &err); if (err) return pcm_err; + + if ((both = (*s && s[1] == '|'))) + s++; + if (!*s || !*++s) { - zwarnnam(name, "missing line pattern", NULL, 0); + if (name) + zwarnnam(name, "missing line pattern", NULL, 0); return pcm_err; } } else left = NULL; - line = parse_pattern(name, &s, &ll, ((fl & CMF_RIGHT) ? '|' : '='), + line = parse_pattern(name, &s, &ll, + (((fl & CMF_RIGHT) && !fl2) ? '|' : '='), &err); if (err) return pcm_err; - if ((fl & CMF_RIGHT) && (!*s || !*++s)) { - zwarnnam(name, "missing right anchor", NULL, 0); - } else if (!(fl & CMF_RIGHT)) { + if (both) { + right = line; + ral = ll; + line = NULL; + ll = 0; + } + if ((fl & CMF_RIGHT) && !fl2 && (!*s || !*++s)) { + if (name) + zwarnnam(name, "missing right anchor", NULL, 0); + } else if (!(fl & CMF_RIGHT) || fl2) { if (!*s) { - zwarnnam(name, "missing word pattern", NULL, 0); + if (name) + zwarnnam(name, "missing word pattern", NULL, 0); return pcm_err; } s++; } - if (fl & CMF_RIGHT) { + if ((fl & CMF_RIGHT) && !fl2) { + if (*s == '|') { + left = line; + lal = ll; + line = NULL; + ll = 0; + s++; + } right = parse_pattern(name, &s, &ral, '=', &err); if (err) return pcm_err; if (!*s) { - zwarnnam(name, "missing word pattern", NULL, 0); + if (name) + zwarnnam(name, "missing word pattern", NULL, 0); return pcm_err; } s++; @@ -249,7 +287,8 @@ parse_cmatcher(char *name, char *s) if (*s == '*') { if (!(fl & (CMF_LEFT | CMF_RIGHT))) { - zwarnnam(name, "need anchor for `*'", NULL, 0); + if (name) + zwarnnam(name, "need anchor for `*'", NULL, 0); return pcm_err; } word = NULL; @@ -262,16 +301,18 @@ parse_cmatcher(char *name, char *s) word = parse_pattern(name, &s, &wl, 0, &err); if (!word && !line) { - zwarnnam(name, "need non-empty word or line pattern", NULL, 0); + if (name) + zwarnnam(name, "need non-empty word or line pattern", + NULL, 0); return pcm_err; } } if (err) return pcm_err; - n = (Cmatcher) zcalloc(sizeof(*ret)); + n = (Cmatcher) hcalloc(sizeof(*ret)); n->next = NULL; - n->flags = fl; + n->flags = fl | fl2; n->line = line; n->llen = ll; n->word = word; @@ -365,7 +406,7 @@ parse_class(Cpattern p, unsigned char *s, unsigned char e) n = !n; while (*s && (k || *s != e)) { - if (s[1] == '-' && s[2] != e) { + if (s[1] == '-' && s[2] && s[2] != e) { /* a run of characters */ for (j = (int) *s; j <= (int) s[2]; j++) p->tab[j] = (eq ? i++ : n); @@ -380,7 +421,7 @@ parse_class(Cpattern p, unsigned char *s, unsigned char e) /**/ static int -bin_compadd(char *name, char **argv, char *ops, int func) +bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) { struct cadata dat; char *p, **sp, *e, *m = NULL, *mstr = NULL; @@ -391,12 +432,13 @@ bin_compadd(char *name, char **argv, char *ops, int func) zwarnnam(name, "can only be called from completion function", NULL, 0); return 1; } - dat.ipre = dat.isuf = dat.ppre = dat.psuf = dat.prpre = + dat.ipre = dat.isuf = dat.ppre = dat.psuf = dat.prpre = dat.mesg = dat.pre = dat.suf = dat.group = dat.rems = dat.remf = dat.disp = dat.ign = dat.exp = dat.apar = dat.opar = dat.dpar = NULL; dat.match = NULL; dat.flags = 0; dat.aflags = CAF_MATCH; + dat.dummies = 0; for (; *argv && **argv == '-'; argv++) { if (!(*argv)[1]) { @@ -414,12 +456,21 @@ bin_compadd(char *name, char **argv, char *ops, int func) case 'Q': dat.aflags |= CAF_QUOTE; break; + case 'C': + dat.aflags |= CAF_ALL; + break; case 'f': dat.flags |= CMF_FILE; break; case 'e': dat.flags |= CMF_ISPAR; break; + case 'a': + dat.aflags |= CAF_ARRAYS; + break; + case 'k': + dat.aflags |= CAF_ARRAYS|CAF_KEYS; + break; case 'F': sp = &(dat.ign); e = "string expected after -%c"; @@ -476,9 +527,6 @@ bin_compadd(char *name, char **argv, char *ops, int func) sp = &(dat.prpre); e = "string expected after -%c"; break; - case 'a': - dat.aflags |= CAF_ALT; - break; case 'M': sp = &m; e = "matching specification expected after -%c"; @@ -488,6 +536,10 @@ bin_compadd(char *name, char **argv, char *ops, int func) sp = &(dat.exp); e = "string expected after -%c"; break; + case 'x': + sp = &(dat.mesg); + e = "string expected after -%c"; + break; case 'r': dat.flags |= CMF_REMOVE; sp = &(dat.rems); @@ -517,6 +569,23 @@ bin_compadd(char *name, char **argv, char *ops, int func) case 'l': dat.flags |= CMF_DISPLINE; break; + case 'E': + if (p[1]) { + dat.dummies = atoi(p + 1); + p = "" - 1; + } else if (argv[1]) { + argv++; + dat.dummies = atoi(*argv); + p = "" - 1; + } else { + zwarnnam(name, "number expected after -%c", NULL, *p); + return 1; + } + if (dat.dummies < 0) { + zwarnnam(name, "invalid number: %d", NULL, dat.dummies); + return 1; + } + break; case '-': argv++; goto ca_args; @@ -539,25 +608,28 @@ bin_compadd(char *name, char **argv, char *ops, int func) return 1; } if (dm) { - if (mstr) - mstr = tricat(mstr, " ", m); - else + if (mstr) { + char *tmp = tricat(mstr, " ", m); + zsfree(mstr); + mstr = tmp; + } else mstr = ztrdup(m); m = NULL; } } } } + + ca_args: + if (mstr && (match = parse_cmatcher(name, mstr)) == pcm_err) { zsfree(mstr); return 1; } zsfree(mstr); - ca_args: - - if (!*argv && !dat.group && - !(dat.aflags & (CAF_NOSORT|CAF_UNIQALL|CAF_UNIQCON))) + if (!*argv && !dat.group && !dat.mesg && + !(dat.aflags & (CAF_NOSORT|CAF_UNIQALL|CAF_UNIQCON|CAF_ALL))) return 1; dat.match = match = cpcmatcher(match); @@ -635,7 +707,7 @@ restrict_range(int b, int e) e = wl; i = e - b + 1; - p = (char **) zcalloc((i + 1) * sizeof(char *)); + p = (char **) zshcalloc((i + 1) * sizeof(char *)); for (q = p, pp = compwords + b; i; i--, q++, pp++) *q = ztrdup(*pp); @@ -716,7 +788,7 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod) if (!na) return 1; if (na > 0 && - strlen(test == CVT_PRENUM ? compprefix : compsuffix) >= na) { + (int)strlen(test == CVT_PRENUM ? compprefix : compsuffix) >= na) { if (mod) { if (test == CVT_PRENUM) ignore_prefix(na); @@ -742,25 +814,39 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod) char *p, sav; if (!(l = strlen(compprefix))) - return 0; + return ((na == 1 || na == -1) && pattry(pp, compprefix)); if (na < 0) { p = compprefix + l; na = -na; add = -1; } else { p = compprefix + 1; + if (*p == Meta) + p++; add = 1; } - for (; l; l--, p += add) { + for (;;) { sav = *p; *p = '\0'; test = pattry(pp, compprefix); *p = sav; if (test && !--na) break; + if (add > 0) { + if (p == compprefix + l) + return 0; + if (*p == Meta) + p += 2; + else + p++; + } else { + if (p == compprefix) + return 0; + p--; + if (p > compprefix && p[-1] == Meta) + p--; + } } - if (!l) - return 0; if (mod) ignore_prefix(p - compprefix); } else { @@ -768,21 +854,37 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod) char *p; if (!(ol = l = strlen(compsuffix))) - return 0; + return ((na == 1 || na == -1) && pattry(pp, compsuffix)); if (na < 0) { p = compsuffix; na = -na; add = 1; } else { p = compsuffix + l - 1; + if (p > compsuffix && p[-1] == Meta) + p--; add = -1; } - for (; l; l--, p += add) + for (;;) { if (pattry(pp, p) && !--na) break; - if (!l) - return 0; + if (add > 0) { + if (p == compsuffix + l) + return 0; + if (*p == Meta) + p += 2; + else + p++; + } else { + if (p == compsuffix) + return 0; + p--; + if (p > compsuffix && p[-1] == Meta) + p--; + } + } + if (mod) ignore_suffix(ol - (p - compsuffix)); } @@ -794,7 +896,7 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod) /**/ static int -bin_compset(char *name, char **argv, char *ops, int func) +bin_compset(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) { int test = 0, na = 0, nb = 0; char *sa = NULL, *sb = NULL; @@ -871,51 +973,82 @@ bin_compset(char *name, char **argv, char *ops, int func) * order of the CP_* bits in comp.h */ #define VAL(X) ((void *) (&(X))) +#define GSU(X) ((GsuScalar)(void *) (&(X))) struct compparam { char *name; int type; - void *var, *set, *get; + void *var; + GsuScalar gsu; }; +static const struct gsu_scalar compvarscalar_gsu = +{ strvargetfn, strvarsetfn, compunsetfn }; +static const struct gsu_scalar complist_gsu = +{ get_complist, set_complist, compunsetfn }; +static const struct gsu_scalar unambig_gsu = +{ get_unambig, nullstrsetfn, compunsetfn }; +static const struct gsu_scalar unambig_pos_gsu = +{ get_unambig_pos, nullstrsetfn, compunsetfn }; +static const struct gsu_scalar insert_pos_gsu = +{ get_insert_pos, nullstrsetfn, compunsetfn }; + +static const struct gsu_integer compvarinteger_gsu = +{ intvargetfn, intvarsetfn, compunsetfn }; +static const struct gsu_integer nmatches_gsu = +{ get_nmatches, NULL, compunsetfn }; +static const struct gsu_integer unambig_curs_gsu = +{ get_unambig_curs, NULL, compunsetfn }; +static const struct gsu_integer listlines_gsu = +{ get_listlines, NULL, compunsetfn }; + +static const struct gsu_array compvararray_gsu = +{ arrvargetfn, arrvarsetfn, compunsetfn }; + + static struct compparam comprparams[] = { - { "words", PM_ARRAY, VAL(compwords), NULL, NULL }, - { "CURRENT", PM_INTEGER, VAL(compcurrent), NULL, NULL }, - { "PREFIX", PM_SCALAR, VAL(compprefix), NULL, NULL }, - { "SUFFIX", PM_SCALAR, VAL(compsuffix), NULL, NULL }, - { "IPREFIX", PM_SCALAR, VAL(compiprefix), NULL, NULL }, - { "ISUFFIX", PM_SCALAR, VAL(compisuffix), NULL, NULL }, - { "QIPREFIX", PM_SCALAR | PM_READONLY, VAL(compqiprefix), NULL, NULL }, - { "QISUFFIX", PM_SCALAR | PM_READONLY, VAL(compqisuffix), NULL, NULL }, - { NULL, 0, NULL, NULL, NULL } + { "words", PM_ARRAY, VAL(compwords), NULL }, + { "redirections", PM_ARRAY, VAL(compredirs), NULL }, + { "CURRENT", PM_INTEGER, VAL(compcurrent), NULL }, + { "PREFIX", PM_SCALAR, VAL(compprefix), NULL }, + { "SUFFIX", PM_SCALAR, VAL(compsuffix), NULL }, + { "IPREFIX", PM_SCALAR, VAL(compiprefix), NULL }, + { "ISUFFIX", PM_SCALAR, VAL(compisuffix), NULL }, + { "QIPREFIX", PM_SCALAR | PM_READONLY, VAL(compqiprefix), NULL }, + { "QISUFFIX", PM_SCALAR | PM_READONLY, VAL(compqisuffix), NULL }, + { NULL, 0, NULL, NULL } }; static struct compparam compkparams[] = { - { "nmatches", PM_INTEGER | PM_READONLY, NULL, NULL, VAL(get_nmatches) }, - { "context", PM_SCALAR, VAL(compcontext), NULL, NULL }, - { "parameter", PM_SCALAR, VAL(compparameter), NULL, NULL }, - { "redirect", PM_SCALAR, VAL(compredirect), NULL, NULL }, - { "quote", PM_SCALAR | PM_READONLY, VAL(compquote), NULL, NULL }, - { "quoting", PM_SCALAR | PM_READONLY, VAL(compquoting), NULL, NULL }, - { "restore", PM_SCALAR, VAL(comprestore), NULL, NULL }, - { "list", PM_SCALAR, NULL, VAL(set_complist), VAL(get_complist) }, - { "insert", PM_SCALAR, VAL(compinsert), NULL, NULL }, - { "exact", PM_SCALAR, VAL(compexact), NULL, NULL }, - { "exact_string", PM_SCALAR, VAL(compexactstr), NULL, NULL }, - { "pattern_match", PM_SCALAR, VAL(comppatmatch), NULL, NULL }, - { "pattern_insert", PM_SCALAR, VAL(comppatinsert), NULL, NULL }, - { "unambiguous", PM_SCALAR | PM_READONLY, NULL, NULL, VAL(get_unambig) }, - { "unambiguous_cursor", PM_INTEGER | PM_READONLY, NULL, NULL, - VAL(get_unambig_curs) }, - { "list_max", PM_INTEGER, VAL(complistmax), NULL, NULL }, - { "last_prompt", PM_SCALAR, VAL(complastprompt), NULL, NULL }, - { "to_end", PM_SCALAR, VAL(comptoend), NULL, NULL }, - { "old_list", PM_SCALAR, VAL(compoldlist), NULL, NULL }, - { "old_insert", PM_SCALAR, VAL(compoldins), NULL, NULL }, - { "vared", PM_SCALAR, VAL(compvared), NULL, NULL }, - { "alternate_nmatches", PM_INTEGER | PM_READONLY, NULL, NULL, VAL(get_anmatches) }, - { "list_lines", PM_INTEGER | PM_READONLY, NULL, NULL, VAL(get_listlines) }, - { "all_quotes", PM_SCALAR | PM_READONLY, VAL(compqstack), NULL, NULL }, - { NULL, 0, NULL, NULL, NULL } + { "nmatches", PM_INTEGER | PM_READONLY, NULL, GSU(nmatches_gsu) }, + { "context", PM_SCALAR, VAL(compcontext), NULL }, + { "parameter", PM_SCALAR, VAL(compparameter), NULL }, + { "redirect", PM_SCALAR, VAL(compredirect), NULL }, + { "quote", PM_SCALAR | PM_READONLY, VAL(compquote), NULL }, + { "quoting", PM_SCALAR | PM_READONLY, VAL(compquoting), NULL }, + { "restore", PM_SCALAR, VAL(comprestore), NULL }, + { "list", PM_SCALAR, NULL, GSU(complist_gsu) }, + { "insert", PM_SCALAR, VAL(compinsert), NULL }, + { "exact", PM_SCALAR, VAL(compexact), NULL }, + { "exact_string", PM_SCALAR, VAL(compexactstr), NULL }, + { "pattern_match", PM_SCALAR, VAL(comppatmatch), NULL }, + { "pattern_insert", PM_SCALAR, VAL(comppatinsert), NULL }, + { "unambiguous", PM_SCALAR | PM_READONLY, NULL, GSU(unambig_gsu) }, + { "unambiguous_cursor", PM_INTEGER | PM_READONLY, NULL, + GSU(unambig_curs_gsu) }, + { "unambiguous_positions", PM_SCALAR | PM_READONLY, NULL, + GSU(unambig_pos_gsu) }, + { "insert_positions", PM_SCALAR | PM_READONLY, NULL, + GSU(insert_pos_gsu) }, + { "list_max", PM_INTEGER, VAL(complistmax), NULL }, + { "last_prompt", PM_SCALAR, VAL(complastprompt), NULL }, + { "to_end", PM_SCALAR, VAL(comptoend), NULL }, + { "old_list", PM_SCALAR, VAL(compoldlist), NULL }, + { "old_insert", PM_SCALAR, VAL(compoldins), NULL }, + { "vared", PM_SCALAR, VAL(compvared), NULL }, + { "list_lines", PM_INTEGER | PM_READONLY, NULL, GSU(listlines_gsu) }, + { "all_quotes", PM_SCALAR | PM_READONLY, VAL(compqstack), NULL }, + { "ignored", PM_INTEGER | PM_READONLY, VAL(compignored), NULL }, + { NULL, 0, NULL, NULL } }; #define COMPSTATENAME "compstate" @@ -935,27 +1068,25 @@ addcompparams(struct compparam *cp, Param *pp) if ((pm->u.data = cp->var)) { switch(PM_TYPE(cp->type)) { case PM_SCALAR: - pm->sets.cfn = strvarsetfn; - pm->gets.cfn = strvargetfn; + pm->gsu.s = &compvarscalar_gsu; break; case PM_INTEGER: - pm->sets.ifn = intvarsetfn; - pm->gets.ifn = intvargetfn; - pm->ct = 10; + pm->gsu.i = &compvarinteger_gsu; + pm->base = 10; break; case PM_ARRAY: - pm->sets.afn = arrvarsetfn; - pm->gets.afn = arrvargetfn; + pm->gsu.a = &compvararray_gsu; break; } } else { - pm->sets.cfn = (void (*) _((Param, char *))) cp->set; - pm->gets.cfn = (char *(*) _((Param))) cp->get; + pm->gsu.s = cp->gsu; } - pm->unsetfn = compunsetfn; } } +static const struct gsu_hash compstate_gsu = +{ get_compstate, set_compstate, compunsetfn }; + /**/ void makecompparams(void) @@ -973,9 +1104,7 @@ makecompparams(void) comprpms[CPN_COMPSTATE] = cpm; tht = paramtab; cpm->level = locallevel + 1; - cpm->gets.hfn = get_compstate; - cpm->sets.hfn = set_compstate; - cpm->unsetfn = compunsetfn; + cpm->gsu.h = &compstate_gsu; cpm->u.hash = paramtab = newparamtable(31, COMPSTATENAME); addcompparams(compkparams, compkpms); paramtab = tht; @@ -990,7 +1119,7 @@ get_compstate(Param pm) /**/ static void -set_compstate(Param pm, HashTable ht) +set_compstate(UNUSED(Param pm), HashTable ht) { struct compparam *cp; Param *pp; @@ -999,13 +1128,16 @@ set_compstate(Param pm, HashTable ht) struct value v; char *str; + if (!ht) + return; + for (i = 0; i < ht->hsize; i++) for (hn = ht->nodes[i]; hn; hn = hn->next) for (cp = compkparams, pp = compkpms; cp->name; cp++, pp++) if (!strcmp(hn->nam, cp->name)) { - v.isarr = v.inv = v.a = 0; - v.b = -1; + v.isarr = v.inv = v.start = 0; + v.end = -1; v.arr = NULL; v.pm = (Param) hn; if (cp->type == PM_INTEGER) @@ -1023,57 +1155,72 @@ set_compstate(Param pm, HashTable ht) /**/ static zlong -get_nmatches(Param pm) +get_nmatches(UNUSED(Param pm)) { - return num_matches(1); + return (permmatches(0) ? 0 : nmatches); } /**/ static zlong -get_anmatches(Param pm) -{ - return num_matches(0); -} - -/**/ -static zlong -get_listlines(Param pm) +get_listlines(UNUSED(Param pm)) { return list_lines(); } /**/ static void -set_complist(Param pm, char *v) +set_complist(UNUSED(Param pm), char *v) { comp_list(v); } /**/ static char * -get_complist(Param pm) +get_complist(UNUSED(Param pm)) { return complist; } /**/ static char * -get_unambig(Param pm) +get_unambig(UNUSED(Param pm)) { - return unambig_data(NULL); + return unambig_data(NULL, NULL, NULL); } /**/ static zlong -get_unambig_curs(Param pm) +get_unambig_curs(UNUSED(Param pm)) { int c; - unambig_data(&c); + unambig_data(&c, NULL, NULL); return c; } +/**/ +static char * +get_unambig_pos(UNUSED(Param pm)) +{ + char *p; + + unambig_data(NULL, &p, NULL); + + return p; +} + +/**/ +static char * +get_insert_pos(UNUSED(Param pm)) +{ + char *p; + + unambig_data(NULL, NULL, &p); + + return p; +} + /**/ static void compunsetfn(Param pm, int exp) @@ -1085,7 +1232,7 @@ compunsetfn(Param pm, int exp) *((char **) pm->u.data) = ztrdup(""); } else if (PM_TYPE(pm->flags) == PM_ARRAY) { freearray(*((char ***) pm->u.data)); - *((char ***) pm->u.data) = zcalloc(sizeof(char *)); + *((char ***) pm->u.data) = zshcalloc(sizeof(char *)); } else if (PM_TYPE(pm->flags) == PM_HASHED) { deleteparamtable(pm->u.hash); pm->u.hash = NULL; @@ -1148,13 +1295,13 @@ comp_wrapper(Eprog prog, FuncWrap w, char *name) if (incompfunc != 1) return 1; else { - char *orest, *opre, *osuf, *oipre, *oisuf, **owords; + char *orest, *opre, *osuf, *oipre, *oisuf, **owords, **oredirs; char *oqipre, *oqisuf, *oq, *oqi, *oqs, *oaq; zlong ocur; unsigned int runset = 0, kunset = 0, m, sm; Param *pp; - m = CP_WORDS | CP_CURRENT | CP_PREFIX | CP_SUFFIX | + m = CP_WORDS | CP_REDIRS | CP_CURRENT | CP_PREFIX | CP_SUFFIX | CP_IPREFIX | CP_ISUFFIX | CP_QIPREFIX | CP_QISUFFIX; for (pp = comprpms, sm = 1; m; pp++, m >>= 1, sm <<= 1) { if ((m & 1) && ((*pp)->flags & PM_UNSET)) @@ -1176,6 +1323,7 @@ comp_wrapper(Eprog prog, FuncWrap w, char *name) oqs = ztrdup(compqstack); oaq = ztrdup(autoq); owords = zarrdup(compwords); + oredirs = zarrdup(compredirs); runshfunc(prog, w, name); @@ -1202,11 +1350,14 @@ comp_wrapper(Eprog prog, FuncWrap w, char *name) zsfree(autoq); autoq = oaq; freearray(compwords); + freearray(compredirs); compwords = owords; + compredirs = oredirs; comp_setunset(CP_COMPSTATE | - (~runset & (CP_WORDS | CP_CURRENT | CP_PREFIX | - CP_SUFFIX | CP_IPREFIX | CP_ISUFFIX | - CP_QIPREFIX | CP_QISUFFIX)), + (~runset & (CP_WORDS | CP_REDIRS | + CP_CURRENT | CP_PREFIX | + CP_SUFFIX | CP_IPREFIX | CP_ISUFFIX | + CP_QIPREFIX | CP_QISUFFIX)), (runset & CP_ALLREALS), (~kunset & CP_RESTORE), (kunset & CP_ALLKEYS)); } else { @@ -1223,6 +1374,7 @@ comp_wrapper(Eprog prog, FuncWrap w, char *name) zsfree(oqs); zsfree(oaq); freearray(owords); + freearray(oredirs); } zsfree(comprestore); comprestore = orest; @@ -1294,12 +1446,12 @@ struct hookdef comphooks[] = { /**/ int -setup_(Module m) +setup_(UNUSED(Module m)) { hasperm = 0; comprpms = compkpms = NULL; - compwords = NULL; + compwords = compredirs = NULL; compprefix = compsuffix = compiprefix = compisuffix = compqiprefix = compqisuffix = compcontext = compparameter = compredirect = compquote = @@ -1307,7 +1459,9 @@ setup_(Module m) compexact = compexactstr = comppatmatch = comppatinsert = complastprompt = comptoend = compoldlist = compoldins = compvared = compqstack = NULL; - + complastprefix = ztrdup(""); + complastsuffix = ztrdup(""); + complistmax = 0; hascompmod = 1; return 0; @@ -1352,12 +1506,16 @@ cleanup_(Module m) /**/ int -finish_(Module m) +finish_(UNUSED(Module m)) { if (compwords) freearray(compwords); + if (compredirs) + freearray(compredirs); zsfree(compprefix); zsfree(compsuffix); + zsfree(complastprefix); + zsfree(complastsuffix); zsfree(compiprefix); zsfree(compisuffix); zsfree(compqiprefix); -- cgit 1.4.1