diff options
Diffstat (limited to 'Src/Zle/compcore.c')
-rw-r--r-- | Src/Zle/compcore.c | 1500 |
1 files changed, 842 insertions, 658 deletions
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c index ea9ff5b20..3cc080cac 100644 --- a/Src/Zle/compcore.c +++ b/Src/Zle/compcore.c @@ -28,9 +28,6 @@ */ #include "complete.mdh" -#define GLOBAL_PROTOTYPES -#include "zle_tricky.pro" -#undef GLOBAL_PROTOTYPES #include "compcore.pro" /* The last completion widget called. */ @@ -40,11 +37,17 @@ static Widget lastcompwidget; /* Flags saying what we have to do with the result. */ /**/ -int useexact, useline, uselist; +int useexact, useline, uselist, forcelist, startauto; + +/* Non-zero if we should go back to the last prompt. */ + +/**/ +int dolastprompt; /* Non-zero if we should keep an old list. */ /**/ +mod_export int oldlist, oldins; /* This is used to decide when the cursor should be moved to the end of * @@ -57,17 +60,17 @@ int movetoend; /* The match and group number to insert when starting menucompletion. */ /**/ -int insmnum, insgnum, insgroup, insspace; +mod_export int insmnum, insgnum, insgroup, insspace; /* Information about menucompletion. */ /**/ -struct menuinfo minfo; +mod_export struct menuinfo minfo; /* Number of matches accepted with accept-and-menu-complete */ /**/ -int menuacc; +mod_export int menuacc; /* Brace insertion stuff. */ @@ -77,7 +80,7 @@ int hasunqu, useqbr, brpcs, brscs; /* Flags saying in what kind of string we are. */ /**/ -int ispar, linwhat; +mod_export int ispar, linwhat; /* A parameter expansion prefix (like ${). */ @@ -92,7 +95,7 @@ int parflags; /* Match flags for all matches in this group. */ /**/ -int mflags; +mod_export int mflags; /* Flags saying how the parameter expression we are in is quoted. */ @@ -101,17 +104,18 @@ int parq, eparq; /* We store the following prefixes/suffixes: * * ipre,ripre -- the ignored prefix (quoted and unquoted) * - * isuf -- the ignored suffix * - * autoq -- quotes to automatically insert */ + * isuf -- the ignored suffix */ /**/ -char *ipre, *ripre, *isuf; +mod_export char *ipre, *ripre, *isuf; /* The list of matches. fmatches contains the matches we first ignore * * because of fignore. */ /**/ -LinkList matches, fmatches; +mod_export LinkList matches; +/**/ +LinkList fmatches; /* This holds the list of matches-groups. lastmatches holds the last list of * permanently allocated matches, pmatches is the same for the list @@ -120,47 +124,49 @@ LinkList matches, fmatches; * lmatches/lastlmatches is a pointer to the last element in the lists. */ /**/ -Cmgroup lastmatches, pmatches, amatches, lmatches, lastlmatches; +mod_export Cmgroup lastmatches, pmatches, amatches, lmatches, lastlmatches; /* Non-zero if we have permanently allocated matches (old and new). */ /**/ -int hasoldlist, hasperm; +mod_export int hasoldlist, hasperm; /* Non-zero if we have newly added matches. */ /**/ -int newmatches; +mod_export int newmatches; /* Number of permanently allocated matches and groups. */ /**/ -int permmnum, permgnum, lastpermmnum, lastpermgnum; +mod_export int permmnum, permgnum, lastpermmnum, lastpermgnum; /* The total number of matches and the number of matches to be listed. */ /**/ -int nmatches, smatches; +mod_export int nmatches; +/**/ +mod_export int smatches; /* != 0 if only explanation strings should be printed */ /**/ -int onlyexpl; +mod_export int onlyexpl; /* Information about the matches for listing. */ /**/ -struct cldata listdat; +mod_export struct cldata listdat; /* This flag is non-zero if we are completing a pattern (with globcomplete) */ /**/ -int ispattern, haspattern; +mod_export int ispattern, haspattern; -/* Non-zero if at least one match was added without -U. */ +/* Non-zero if at least one match was added without/with -U. */ /**/ -int hasmatched; +mod_export int hasmatched, hasunmatched; /* The current group of matches. */ @@ -170,12 +176,12 @@ Cmgroup mgroup; /* Match counter: all matches. */ /**/ -int mnum; +mod_export int mnum; /* The match counter when unambig_data() was called. */ /**/ -int unambig_mnum; +mod_export int unambig_mnum; /* Length of longest/shortest match. */ @@ -189,37 +195,37 @@ int maxmlen, minmlen; LinkList expls; /**/ -Cexpl curexpl; +mod_export Cexpl curexpl; /* A stack of completion matchers to be used. */ /**/ -Cmlist mstack; +mod_export Cmlist mstack; /* The completion matchers used when building new stuff for the line. */ /**/ -Cmlist bmatchers; +mod_export Cmlist bmatchers; /* A list with references to all matchers we used. */ /**/ -LinkList matchers; +mod_export LinkList matchers; /* A heap of free Cline structures. */ /**/ -Cline freecl; +mod_export Cline freecl; /* Ambiguous information. */ /**/ -Aminfo ainfo, fainfo; +mod_export Aminfo ainfo, fainfo; /* The memory heap to use for new style completion generation. */ /**/ -Heap compheap; +mod_export Heap compheap; /* A list of some data. * @@ -227,7 +233,7 @@ Heap compheap; * conceptually we don't know anything about compctls here... */ /**/ -LinkList allccs; +mod_export LinkList allccs; /* This says what of the state the line is in when completion is started * * came from a previous completion. If the FC_LINE bit is set, the * @@ -246,10 +252,6 @@ int fromcomp; /**/ int lastend; -/* Convenience macro for calling bslashquote() (formerly quotename()). */ - -#define quotename(s, e) bslashquote(s, e, instring) - #define inststr(X) inststrlen((X),1,-1) /* Main completion entry point, called from zle. */ @@ -260,153 +262,165 @@ do_completion(Hookdef dummy, Compldat dat) { int ret = 0, lst = dat->lst, incmd = dat->incmd; char *s = dat->s; + char *opm; + LinkNode n; - HEAPALLOC { - char *opm; - LinkNode n; - - pushheap(); - - ainfo = fainfo = NULL; - matchers = newlinklist(); - - hasunqu = 0; - useline = (lst != COMP_LIST_COMPLETE); - useexact = isset(RECEXACT); - uselist = (useline ? - ((isset(AUTOLIST) && !isset(BASHAUTOLIST)) ? - (isset(LISTAMBIGUOUS) ? 3 : 2) : 0) : 1); - zsfree(comppatmatch); - opm = comppatmatch = ztrdup(useglob ? "*" : ""); - zsfree(comppatinsert); - comppatinsert = ztrdup("menu"); - zsfree(compforcelist); - compforcelist = ztrdup(""); - haspattern = 0; - complistmax = getiparam("LISTMAX"); - zsfree(complastprompt); - complastprompt = ztrdup(((isset(ALWAYSLASTPROMPT) && zmult == 1) || - (unset(ALWAYSLASTPROMPT) && zmult != 1)) ? - "yes" : ""); - movetoend = ((cs == we || isset(ALWAYSTOEND)) ? 2 : 1); - showinglist = 0; - hasmatched = 0; - minmlen = 1000000; - maxmlen = -1; - - /* Make sure we have the completion list and compctl. */ - if (makecomplist(s, incmd, lst)) { - /* Error condition: feeeeeeeeeeeeep(). */ - cs = 0; - foredel(ll); - inststr(origline); - cs = origcs; - clearlist = 1; - ret = 1; - minfo.cur = NULL; - goto compend; - } - zsfree(lastprebr); - zsfree(lastpostbr); - lastprebr = lastpostbr = NULL; - - if (comppatmatch && *comppatmatch && comppatmatch != opm) - haspattern = 1; - if (!useline && uselist) { - /* All this and the guy only wants to see the list, sigh. */ - cs = 0; - foredel(ll); - inststr(origline); - cs = origcs; - showinglist = -2; - } else if (useline == 2 && nmatches > 1) { - int first = 1, nm = nmatches; - Cmatch *mc; + pushheap(); + + ainfo = fainfo = NULL; + matchers = newlinklist(); + + zsfree(compqstack); + compqstack = ztrdup("\\"); + if (instring == 2) + compqstack[0] = '"'; + else if (instring) + compqstack[0] = '\''; + + hasunqu = 0; + useline = (lst != COMP_LIST_COMPLETE); + useexact = isset(RECEXACT); + zsfree(compexactstr); + compexactstr = ztrdup(""); + uselist = (useline ? + ((isset(AUTOLIST) && !isset(BASHAUTOLIST)) ? + (isset(LISTAMBIGUOUS) ? 3 : 2) : 0) : 1); + zsfree(comppatmatch); + opm = comppatmatch = ztrdup(useglob ? "*" : ""); + zsfree(comppatinsert); + comppatinsert = ztrdup("menu"); + forcelist = 0; + haspattern = 0; + complistmax = getiparam("LISTMAX"); + zsfree(complastprompt); + complastprompt = ztrdup(((isset(ALWAYSLASTPROMPT) && zmult == 1) || + (unset(ALWAYSLASTPROMPT) && zmult != 1)) ? + "yes" : ""); + dolastprompt = 1; + zsfree(complist); + complist = ztrdup(isset(LISTROWSFIRST) ? + (isset(LISTPACKED) ? "packed rows" : "rows") : + (isset(LISTPACKED) ? "packed" : "")); + startauto = isset(AUTOMENU); + movetoend = ((cs == we || isset(ALWAYSTOEND)) ? 2 : 1); + showinglist = 0; + hasmatched = hasunmatched = 0; + minmlen = 1000000; + maxmlen = -1; + compignored = 0; + + /* Make sure we have the completion list and compctl. */ + if (makecomplist(s, incmd, lst)) { + /* Error condition: feeeeeeeeeeeeep(). */ + cs = 0; + foredel(ll); + inststr(origline); + cs = origcs; + clearlist = 1; + ret = 1; + minfo.cur = NULL; + goto compend; + } + zsfree(lastprebr); + zsfree(lastpostbr); + lastprebr = lastpostbr = NULL; + + if (comppatmatch && *comppatmatch && comppatmatch != opm) + haspattern = 1; + if (!useline && uselist) { + /* All this and the guy only wants to see the list, sigh. */ + cs = 0; + foredel(ll); + inststr(origline); + cs = origcs; + showinglist = -2; + } else if (useline == 2 && nmatches > 1) { + int first = 1, nm = nmatches; + Cmatch *mc; - menucmp = 1; - menuacc = 0; + menucmp = 1; + menuacc = 0; - for (minfo.group = amatches; - minfo.group && !(minfo.group)->mcount; - minfo.group = (minfo.group)->next); + for (minfo.group = amatches; + minfo.group && !(minfo.group)->mcount; + minfo.group = (minfo.group)->next); - mc = (minfo.group)->matches; + mc = (minfo.group)->matches; - while (1) { - if (!first) - acceptlast(); - first = 0; + while (1) { + if (!first) + accept_last(); + first = 0; - if (!--nm) - menucmp = 0; + if (!--nm) + menucmp = 0; - do_single(*mc); - minfo.cur = mc; + do_single(*mc); + minfo.cur = mc; - if (!*++(minfo.cur)) { - do { - if (!(minfo.group = (minfo.group)->next)) - break; - } while (!(minfo.group)->mcount); - if (!minfo.group) + if (!*++(minfo.cur)) { + do { + if (!(minfo.group = (minfo.group)->next)) break; - minfo.cur = minfo.group->matches; - } - mc = minfo.cur; + } while (!(minfo.group)->mcount); + if (!minfo.group) + break; + minfo.cur = minfo.group->matches; } - menucmp = 0; - minfo.cur = NULL; - - if (compforcelist && *compforcelist && uselist) - showinglist = -2; - else - invalidatelist(); - } else if (useline) { - /* We have matches. */ - if (nmatches > 1) { - /* There is more than one match. */ - ret = do_ambiguous(); - } else if (nmatches == 1) { - /* Only one match. */ - Cmgroup m = amatches; - - while (!m->mcount) - m = m->next; - minfo.cur = NULL; - minfo.asked = 0; - do_single(m->matches[0]); - if (compforcelist && *compforcelist) { - if (uselist) - showinglist = -2; - else - clearlist = 1; - } else - invalidatelist(); - } - } else { - invalidatelist(); - if (compforcelist && *compforcelist) - clearlist = 1; - cs = 0; - foredel(ll); - inststr(origline); - cs = origcs; + mc = minfo.cur; } - /* Print the explanation strings if needed. */ - if (!showinglist && validlist && usemenu != 2 && nmatches != 1 && - useline != 2 && (!oldlist || !listshown)) { - onlyexpl = 1; + menucmp = 0; + minfo.cur = NULL; + + if (forcelist) showinglist = -2; + else + invalidatelist(); + } else if (useline) { + /* We have matches. */ + if (nmatches > 1) { + /* There is more than one match. */ + ret = do_ambiguous(); + } else if (nmatches == 1) { + /* Only one match. */ + Cmgroup m = amatches; + + while (!m->mcount) + m = m->next; + minfo.cur = NULL; + minfo.asked = 0; + do_single(m->matches[0]); + if (forcelist) { + if (uselist) + showinglist = -2; + else + clearlist = 1; + } else + invalidatelist(); } - compend: - for (n = firstnode(matchers); n; incnode(n)) - freecmatcher((Cmatcher) getdata(n)); + } else { + invalidatelist(); + if (forcelist) + clearlist = 1; + cs = 0; + foredel(ll); + inststr(origline); + cs = origcs; + } + /* Print the explanation strings if needed. */ + if (!showinglist && validlist && usemenu != 2 && nmatches != 1 && + useline != 2 && (!oldlist || !listshown)) { + onlyexpl = 1; + showinglist = -2; + } + compend: + for (n = firstnode(matchers); n; incnode(n)) + freecmatcher((Cmatcher) getdata(n)); - ll = strlen((char *)line); - if (cs > ll) - cs = ll; - popheap(); - } LASTALLOC; + ll = strlen((char *)line); + if (cs > ll) + cs = ll; + popheap(); return ret; } @@ -428,7 +442,7 @@ before_complete(Hookdef dummy, int *lst) /* If we are doing a menu-completion... */ if (menucmp && *lst != COMP_LIST_EXPAND && - (!compwidget || compwidget == lastcompwidget)) { + (menucmp != 1 || !compwidget || compwidget == lastcompwidget)) { do_menucmp(*lst); return 1; } @@ -442,13 +456,12 @@ before_complete(Hookdef dummy, int *lst) /* We may have to reset the cursor to its position after the * * string inserted by the last completion. */ - if (fromcomp & FC_INWORD) - if ((cs = lastend) > ll) - cs = ll; + if ((fromcomp & FC_INWORD) && (cs = lastend) > ll) + cs = ll; /* Check if we have to start a menu-completion (via automenu). */ - if (isset(AUTOMENU) && lastambig && + if (startauto && lastambig && (!isset(BASHAUTOLIST) || lastambig == 2)) usemenu = 2; @@ -477,11 +490,11 @@ after_complete(Hookdef dummy, Compldat dat) static void callcompfunc(char *s, char *fn) { - List list; + Eprog prog; int lv = lastval; char buf[20]; - if ((list = getshfunc(fn)) != &dummy_list) { + if ((prog = getshfunc(fn)) != &dummy_eprog) { char **p, *tmp; int aadd = 0, usea = 1, icf = incompfunc, osc = sfcontext; unsigned int rset, kset; @@ -493,7 +506,7 @@ callcompfunc(char *s, char *fn) rset = CP_ALLREALS; kset = CP_ALLKEYS & ~(CP_PARAMETER | CP_REDIRECT | CP_QUOTE | CP_QUOTING | - CP_EXACTSTR | CP_FORCELIST | CP_OLDLIST | CP_OLDINS | + CP_EXACTSTR | CP_OLDLIST | CP_OLDINS | (useglob ? 0 : CP_PATMATCH)); zsfree(compvared); if (varedarg) { @@ -566,16 +579,11 @@ callcompfunc(char *s, char *fn) if (usea && (!aadd || clwords[0])) { char **q; - PERMALLOC { - q = compwords = (char **) - zalloc((clwnum + 1) * sizeof(char *)); - for (p = clwords + aadd; *p; p++, q++) { - tmp = dupstring(*p); - untokenize(tmp); - *q = ztrdup(tmp); - } - *q = NULL; - } LASTALLOC; + q = compwords = (char **) + zalloc((clwnum + 1) * sizeof(char *)); + for (p = clwords + aadd; *p; p++, q++) + untokenize(*q = ztrdup(*p)); + *q = NULL; } else compwords = (char **) zcalloc(sizeof(char *)); @@ -603,7 +611,7 @@ callcompfunc(char *s, char *fn) zsfree(compprefix); zsfree(compsuffix); if (unset(COMPLETEINWORD)) { - tmp = quotename(s, NULL); + tmp = multiquote(s, 0); untokenize(tmp); compprefix = ztrdup(tmp); compsuffix = ztrdup(""); @@ -614,11 +622,11 @@ callcompfunc(char *s, char *fn) sav = *ss; *ss = '\0'; - tmp = quotename(s, NULL); + tmp = multiquote(s, 0); untokenize(tmp); compprefix = ztrdup(tmp); *ss = sav; - ss = quotename(ss, NULL); + ss = multiquote(ss, 0); untokenize(ss); compsuffix = ztrdup(ss); } @@ -639,11 +647,20 @@ callcompfunc(char *s, char *fn) case 2: complist = "autolist"; break; case 3: complist = "ambiguous"; break; } + if (isset(LISTPACKED)) + complist = dyncat(complist, " packed"); + if (isset(LISTROWSFIRST)) + complist = dyncat(complist, " rows"); + complist = ztrdup(complist); zsfree(compinsert); if (useline) { switch (usemenu) { - case 0: compinsert = "unambiguous"; break; + case 0: + compinsert = (isset(AUTOMENU) ? + "automenu-unambiguous" : + "unambiguous"); + break; case 1: compinsert = "menu"; break; case 2: compinsert = "automenu"; break; } @@ -701,7 +718,7 @@ callcompfunc(char *s, char *fn) while (*p) addlinknode(largs, dupstring(*p++)); } - doshfunc(fn, list, largs, 0, 0); + doshfunc(fn, prog, largs, 0, 0); cfret = lastval; lastval = olv; } OLDHEAPS; @@ -720,13 +737,14 @@ callcompfunc(char *s, char *fn) uselist = 3; else uselist = 0; - + forcelist = (complist && strstr(complist, "force")); onlyexpl = (complist && strstr(complist, "expl")); if (!compinsert) useline = 0; else if (!strcmp(compinsert, "unambig") || - !strcmp(compinsert, "unambiguous")) + !strcmp(compinsert, "unambiguous") || + !strcmp(compinsert, "automenu-unambiguous")) useline = 1, usemenu = 0; else if (!strcmp(compinsert, "menu")) useline = 1, usemenu = 1; @@ -747,6 +765,8 @@ callcompfunc(char *s, char *fn) insspace = (compinsert[strlen(compinsert) - 1] == ' '); } else useline = usemenu = 0; + startauto = (compinsert && + !strcmp(compinsert, "automenu-unambiguous")); useexact = (compexact && !strcmp(compexact, "accept")); if (!comptoend || !*comptoend) @@ -782,60 +802,21 @@ callcompfunc(char *s, char *fn) static int makecomplist(char *s, int incmd, int lst) { - struct cmlist ms; - Cmlist m; - char *p, *os = s; - int onm = nmatches, osi = movefd(0); + char *p; /* Inside $... ? */ if (compfunc && (p = check_param(s, 0, 0))) - os = s = p; - - /* We build a copy of the list of matchers to use to make sure that this - * works even if a shell function called from the completion code changes - * the global matchers. */ - - if ((m = cmatcher)) { - Cmlist mm, *mp = &mm; - int n; - - for (n = 0; m; m = m->next, n++) { - if (m->matcher) { - *mp = (Cmlist) zhalloc(sizeof(struct cmlist)); - (*mp)->matcher = m->matcher; - (*mp)->next = NULL; - (*mp)->str = dupstring(m->str); - mp = &((*mp)->next); - addlinknode(matchers, m->matcher); - m->matcher->refc++; - } - } - m = mm; - compmatcher = 1; - compmatchertot = n; - } else - compmatcher = 0; + s = p; linwhat = inwhat; - /* Walk through the global matchers. */ - for (;;) { + if (compfunc) { + char *os = s; + int onm = nmatches, osi = movefd(0); + bmatchers = NULL; - zsfree(compmatcherstr); - if (m) { - ms.next = NULL; - ms.matcher = m->matcher; - mstack = &ms; - - /* Store the matchers used in the bmatchers list which is used - * when building new parts for the string to insert into the - * line. */ - add_bmatchers(m->matcher); - compmatcherstr = ztrdup(m->str); - } else { - mstack = NULL; - compmatcherstr = ztrdup(""); - } + mstack = NULL; + ainfo = (Aminfo) hcalloc(sizeof(struct aminfo)); fainfo = (Aminfo) hcalloc(sizeof(struct aminfo)); @@ -852,23 +833,12 @@ makecomplist(char *s, int incmd, int lst) begcmgroup("default", 0); menucmp = menuacc = newmatches = onlyexpl = 0; - runhookdef(COMPCTLBEFOREHOOK, NULL); - s = dupstring(os); - if (compfunc) - callcompfunc(s, compfunc); - else { - struct ccmakedat dat; - - dat.str = s; - dat.incmd = incmd; - dat.lst = lst; - runhookdef(COMPCTLMAKEHOOK, (void *) &dat); - } + callcompfunc(s, compfunc); endcmgroup(NULL); - runhookdef(COMPCTLAFTERHOOK, - (void *) ((amatches && !oldlist) ? 1L : 0L)); + /* Needed for compcall. */ + runhookdef(COMPCTLCLEANUPHOOK, NULL); if (oldlist) { nmatches = onm; @@ -884,16 +854,14 @@ makecomplist(char *s, int incmd, int lst) return 0; } - PERMALLOC { - if (lastmatches) { - freematches(lastmatches); - lastmatches = NULL; - } - permmatches(1); - amatches = pmatches; - lastpermmnum = permmnum; - lastpermgnum = permgnum; - } LASTALLOC; + if (lastmatches) { + freematches(lastmatches); + lastmatches = NULL; + } + permmatches(1); + amatches = pmatches; + lastpermmnum = permmnum; + lastpermgnum = permgnum; lastmatches = pmatches; lastlmatches = lmatches; @@ -908,20 +876,69 @@ makecomplist(char *s, int incmd, int lst) return 0; } - if (!m || !(m = m->next)) - break; + redup(osi, 0); + return 1; + } else { + struct ccmakedat dat; + + dat.str = s; + dat.incmd = incmd; + dat.lst = lst; + runhookdef(COMPCTLMAKEHOOK, (void *) &dat); + + /* Needed for compcall. */ + runhookdef(COMPCTLCLEANUPHOOK, NULL); + + return dat.lst; + } +} + +/**/ +mod_export char * +multiquote(char *s, int ign) +{ + if (s) { + char *os = s, *p = compqstack; + + if (p && *p && (ign < 1 || p[ign])) { + if (ign > 0) + p += ign; + while (*p) { + if (ign >= 0 || p[1]) + s = bslashquote(s, NULL, + (*p == '\'' ? 1 : (*p == '"' ? 2 : 0))); + p++; + } + } + return (s == os ? dupstring(s) : s); + } + DPUTS(1, "BUG: null pointer in multiquote()"); + return NULL; +} - errflag = 0; - compmatcher++; +/**/ +mod_export char * +tildequote(char *s, int ign) +{ + if (s) { + int tilde; + + if ((tilde = (*s == '~'))) + *s = 'x'; + s = multiquote(s, ign); + if (tilde) + *s = '~'; + + return s; } - redup(osi, 0); - return 1; + DPUTS(1, "BUG: null pointer in tildequote()"); + return NULL; } /* Check if we have to complete a parameter name. */ /**/ -char * +mod_export char * check_param(char *s, int set, int test) { char *p; @@ -1046,7 +1063,7 @@ check_param(char *s, int set, int test) /* Copy the given string and remove backslashes from the copy and return it. */ /**/ -char * +mod_export char * rembslash(char *s) { char *t = s = dupstring(s); @@ -1065,7 +1082,7 @@ rembslash(char *s) /* This should probably be moved into tokenize(). */ /**/ -char * +mod_export char * ctokenize(char *p) { char *r = p; @@ -1091,7 +1108,7 @@ ctokenize(char *p) } /**/ -char * +mod_export char * comp_str(int *ipl, int *pl, int untok) { char *p = dupstring(compprefix); @@ -1122,23 +1139,21 @@ comp_str(int *ipl, int *pl, int untok) return str; } -/* This is for compset -q. */ - /**/ int set_comp_sep(void) { int lip, lp; - char *s = comp_str(&lip, &lp, 0); + char *s = comp_str(&lip, &lp, 1); 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; - int ois = instring, oib = inbackt, noffs = lip + lp; - char *tmp, *p, *ns, *ol = (char *) line, sav, oaq = autoq, *qp, *qs; + int tl, got = 0, i = 0, cur = -1, oll = ll, sl, remq; + int ois = instring, oib = inbackt, noffs = lp; + char *tmp, *p, *ns, *ol = (char *) line, sav, *qp, *qs, *ts, qc = '\0'; - if (compisuffix) - s = dyncat(s, compisuffix); + s += lip; + wb += lip; untokenize(s); swb = swe = soffs = 0; @@ -1155,7 +1170,8 @@ set_comp_sep(void) memcpy(tmp + 1, s, noffs); tmp[(scs = cs = 1 + noffs)] = 'x'; strcpy(tmp + 2 + noffs, s + noffs); - tmp = rembslash(tmp); + if ((remq = (*compqstack == '\\'))) + tmp = rembslash(tmp); inpush(dupstrspace(tmp), 0, NULL); line = (unsigned char *) tmp; ll = tl - 1; @@ -1218,21 +1234,31 @@ set_comp_sep(void) *p = '\''; } offs = owb; + + untokenize(ts = dupstring(ns)); + if (*ns == Snull || *ns == Dnull) { instring = (*ns == Snull ? 1 : 2); inbackt = 0; swb++; if (ns[strlen(ns) - 1] == *ns && ns[1]) swe--; - autoq = (*ns == Snull ? '\'' : '"'); + zsfree(autoq); + autoq = ztrdup(compqstack[1] ? "" : + multiquote(*ns == Snull ? "'" : "\"", 1)); + qc = (*ns == Snull ? '\'' : '"'); + ts++; } else { instring = 0; - autoq = '\0'; + zsfree(autoq); + autoq = NULL; } for (p = ns, i = swb; *p; p++, i++) { if (INULL(*p)) { - if (i < scs) - soffs--; + if (i < scs) { + if (remq && *p == Bnull && p[1]) + swb -= 2; + } if (p[1] || *p != Bnull) { if (*p == Bnull) { if (scs == i + 1) @@ -1248,17 +1274,28 @@ set_comp_sep(void) chuck(p--); } } + ns = ts; + + if (instring && strchr(compqstack, '\\')) { + int rl = strlen(ns), ql = strlen(multiquote(ns, !!compqstack[1])); + + if (ql > rl) + swb -= ql - rl; + } sav = s[(i = swb - 1)]; s[i] = '\0'; - qp = tricat(qipre, rembslash(s), ""); + qp = rembslash(s); s[i] = sav; if (swe < swb) swe = swb; swe--; sl = strlen(s); - if (swe > sl) - swe = sl, ns[swe - swb + 1] = '\0'; - qs = tricat(rembslash(s + swe), qisuf, ""); + if (swe > sl) { + swe = sl; + if (strlen(ns) > swe - swb + 1) + ns[swe - swb + 1] = '\0'; + } + qs = rembslash(s + swe); sl = strlen(ns); if (soffs > sl) soffs = sl; @@ -1266,6 +1303,11 @@ set_comp_sep(void) { int set = CP_QUOTE | CP_QUOTING, unset = 0; + p = tricat((instring ? (instring == 1 ? "'" : "\"") : "\\"), + compqstack, ""); + zsfree(compqstack); + compqstack = p; + zsfree(compquote); zsfree(compquoting); if (instring == 2) { @@ -1283,11 +1325,11 @@ set_comp_sep(void) compquoting = ztrdup(compquoting); comp_setunset(0, 0, set, unset); + zsfree(compprefix); + zsfree(compsuffix); if (unset(COMPLETEINWORD)) { untokenize(ns); - zsfree(compprefix); compprefix = ztrdup(ns); - zsfree(compsuffix); compsuffix = ztrdup(""); } else { char *ss, sav; @@ -1302,21 +1344,16 @@ set_comp_sep(void) untokenize(ss); compsuffix = ztrdup(ss); } + tmp = tricat(compqiprefix, compiprefix, multiquote(qp, 1)); + zsfree(compqiprefix); + compqiprefix = tmp; + tmp = tricat(multiquote(qs, 1), compisuffix, compqisuffix); + zsfree(compqisuffix); + compqisuffix = tmp; zsfree(compiprefix); compiprefix = ztrdup(""); zsfree(compisuffix); compisuffix = ztrdup(""); - zsfree(compqiprefix); - zsfree(compqisuffix); - if (ois) { - compqiprefix = qp; - compqisuffix = qs; - } else { - compqiprefix = ztrdup(quotename(qp, NULL)); - zsfree(qp); - compqisuffix = ztrdup(quotename(qs, NULL)); - zsfree(qs); - } freearray(compwords); i = countlinknodes(foo); compwords = (char **) zalloc((i + 1) * sizeof(char *)); @@ -1327,7 +1364,6 @@ set_comp_sep(void) compcurrent = cur + 1; compwords[i] = NULL; } - autoq = oaq; instring = ois; inbackt = oib; @@ -1337,7 +1373,7 @@ set_comp_sep(void) /* This stores the strings from the list in an array. */ /**/ -void +mod_export void set_list_array(char *name, LinkList l) { char **a, **p; @@ -1354,7 +1390,7 @@ set_list_array(char *name, LinkList l) /* Get the words from a variable or a (list of words). */ /**/ -char ** +mod_export char ** get_user_var(char *nam) { if (!nam) @@ -1423,19 +1459,37 @@ int 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; + char **aign = NULL, **dparr = NULL, *oaq = autoq, *oppre = dat->ppre; + char *oqp = qipre, *oqs = qisuf, qc, **disp = NULL, *ibuf = NULL; int lpl, lsl, pl, sl, bcp = 0, bcs = 0, bpadd = 0, bsadd = 0; + int ppl = 0, psl = 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; Cmlist oms = mstack; - Patprog cp = NULL; + 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; + + 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) @@ -1447,300 +1501,373 @@ addmatches(Cadata dat, char **argv) if (qc == '`') { instring = 0; inbackt = 0; - autoq = '\0'; + autoq = ""; } else { + char buf[2]; + instring = (qc == '\'' ? 1 : 2); inbackt = 0; - autoq = qc; + buf[0] = qc; + buf[1] = '\0'; + autoq = multiquote(buf, 1); } } else { instring = inbackt = 0; - autoq = '\0'; + autoq = NULL; } qipre = ztrdup(compqiprefix ? compqiprefix : ""); qisuf = ztrdup(compqisuffix ? compqisuffix : ""); + useexact = (compexact && !strcmp(compexact, "accept")); + /* Switch back to the heap that was used when the completion widget * was invoked. */ SWITCHHEAPS(compheap) { - HEAPALLOC { - if ((doadd = (!dat->apar && !dat->opar && !dat->dpar)) && - (dat->aflags & CAF_MATCH)) + if ((doadd = (!dat->apar && !dat->opar && !dat->dpar))) { + if (dat->aflags & CAF_MATCH) hasmatched = 1; - if (dat->apar) - aparl = newlinklist(); - if (dat->opar) - oparl = newlinklist(); - if (dat->dpar) { - if (*(dat->dpar) == '(') - dparr = NULL; - else if ((dparr = get_user_var(dat->dpar)) && !*dparr) - 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; + else + hasunmatched = 1; + } + if (dat->apar) + aparl = newlinklist(); + if (dat->opar) + oparl = newlinklist(); + if (dat->dpar) { + if (*(dat->dpar) == '(') + dparr = NULL; + else if ((dparr = get_user_var(dat->dpar)) && !*dparr) + 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; - mst.matcher = dat->match; - mstack = &mst; + /* Store the matcher in our stack of matchers. */ + if (dat->match) { + mst.next = mstack; + mst.matcher = dat->match; + mstack = &mst; - if (!mnum) - add_bmatchers(dat->match); + add_bmatchers(dat->match); - addlinknode(matchers, dat->match); - dat->match->refc++; + addlinknode(matchers, dat->match); + dat->match->refc++; + } + if (mnum && (mstack || bmatchers)) + update_bmatchers(); + + /* Get the suffixes to ignore. */ + if (dat->ign && (aign = get_user_var(dat->ign))) { + char **ap, **sp, *tmp; + Patprog *pp, prog; + + pign = (Patprog *) zhalloc((arrlen(aign) + 1) * sizeof(Patprog)); + + for (ap = sp = aign, pp = pign; (tmp = *ap); ap++) { + tokenize(tmp); + remnulargs(tmp); + if (((tmp[0] == Quest && tmp[1] == Star) || + (tmp[1] == Quest && tmp[0] == Star)) && + tmp[2] && !haswilds(tmp + 2)) + untokenize(*sp++ = tmp + 2); + else if ((prog = patcompile(tmp, 0, NULL))) + *pp++ = prog; } - if (mnum && (mstack || bmatchers)) - update_bmatchers(); - - /* Get the suffixes to ignore. */ - if (dat->ign) - aign = get_user_var(dat->ign); - /* Get the display strings. */ - if (dat->disp) - if ((disp = get_user_var(dat->disp))) - disp--; - /* Get the contents of the completion variables if we have - * to perform matching. */ - if (dat->aflags & CAF_MATCH) { - lipre = dupstring(compiprefix); - lisuf = dupstring(compisuffix); - lpre = dupstring(compprefix); - lsuf = dupstring(compsuffix); - llpl = strlen(lpre); - llsl = strlen(lsuf); - /* Test if there is an existing -P prefix. */ - if (dat->pre && *dat->pre) { - char *dp = rembslash(dat->pre); - - pl = pfxlen(dp, lpre); - llpl -= pl; - lpre += pl; + *sp = NULL; + *pp = NULL; + if (!*aign) + aign = NULL; + if (!*pign) + pign = NULL; + } + /* Get the display strings. */ + if (dat->disp) + if ((disp = get_user_var(dat->disp))) + disp--; + /* Get the contents of the completion variables if we have + * to perform matching. */ + if (dat->aflags & CAF_MATCH) { + lipre = dupstring(compiprefix); + lisuf = dupstring(compisuffix); + lpre = dupstring(compprefix); + lsuf = dupstring(compsuffix); + llpl = strlen(lpre); + llsl = strlen(lsuf); + /* Test if there is an existing -P prefix. */ + if (dat->pre && *dat->pre) { + pl = pfxlen(dat->pre, lpre); + llpl -= pl; + lpre += pl; + } + } + /* Now duplicate the strings we have from the command line. */ + if (dat->ipre) + dat->ipre = (lipre ? dyncat(lipre, dat->ipre) : + dupstring(dat->ipre)); + else if (lipre) + dat->ipre = lipre; + if (dat->isuf) + dat->isuf = (lisuf ? dyncat(lisuf, dat->isuf) : + dupstring(dat->isuf)); + else if (lisuf) + dat->isuf = lisuf; + if (dat->ppre) { + dat->ppre = ((dat->flags & CMF_FILE) ? + tildequote(dat->ppre, !!(dat->aflags & CAF_QUOTE)) : + multiquote(dat->ppre, !!(dat->aflags & CAF_QUOTE))); + lpl = strlen(dat->ppre); + } else + lpl = 0; + if (dat->psuf) { + dat->psuf = multiquote(dat->psuf, !!(dat->aflags & CAF_QUOTE)); + lsl = strlen(dat->psuf); + } else + lsl = 0; + if (dat->aflags & CAF_MATCH) { + int ml, gfl = 0; + char *globflag = NULL; + + if (comppatmatch && *comppatmatch && + dat->ppre && lpre[0] == '(' && lpre[1] == '#') { + char *p; + + for (p = lpre + 2; *p && *p != ')'; p++); + + if (*p == ')') { + char sav = p[1]; + + p[1] = '\0'; + globflag = dupstring(lpre); + gfl = p - lpre + 1; + p[1] = sav; + + lpre = p + 1; + llpl -= gfl; } } - /* Now duplicate the strings we have from the command line. */ - if (dat->ipre) - dat->ipre = (lipre ? dyncat(lipre, dat->ipre) : - dupstring(dat->ipre)); - else if (lipre) - dat->ipre = lipre; - if (dat->isuf) - dat->isuf = (lisuf ? dyncat(lisuf, dat->isuf) : - dupstring(dat->isuf)); - else if (lisuf) - dat->isuf = lisuf; - if (dat->ppre) { - if (!(dat->aflags & CAF_QUOTE)) { - dat->ppre = quotename(dat->ppre, NULL); - if ((dat->flags & CMF_FILE) && - dat->ppre[0] == '\\' && dat->ppre[1] == '~') - chuck(dat->ppre); - } else - dat->ppre = dupstring(dat->ppre); - lpl = strlen(dat->ppre); - } else - lpl = 0; - if (dat->psuf) { - if (!(dat->aflags & CAF_QUOTE)) - dat->psuf = quotename(dat->psuf, NULL); - else - dat->psuf = dupstring(dat->psuf); - lsl = strlen(dat->psuf); - } else - lsl = 0; - if (dat->aflags & CAF_MATCH) { - int ml; - - 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; - else - matchparts = tmp; - } - pline = matchparts; - lpre += ml; - bcp = ml; - bpadd = strlen(s) - ml; - } else { - if (llpl <= lpl && strpfx(lpre, s)) - lpre = ""; - else if (llpl > lpl && strpfx(s, lpre)) - lpre += lpl; + 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; else - *argv = NULL; - bcp = lpl; + matchparts = tmp; } - - 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; - else - matchparts = tmp; - } - sline = revert_cline(matchparts); - lsuf[llsl - ml] = '\0'; - 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'; + 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; else - *argv = NULL; - bcs = lsl; + matchparts = tmp; } - if (comppatmatch && *comppatmatch) { - int is = (*comppatmatch == '*'); - char *tmp = (char *) zhalloc(2 + llpl + llsl); + 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 == '*'); + char *tmp = (char *) zhalloc(2 + llpl + llsl + gfl); + if (gfl) { + strcpy(tmp, globflag); + strcat(tmp, lpre); + } else strcpy(tmp, lpre); - tmp[llpl] = 'x'; - strcpy(tmp + llpl + is, lsuf); - - tokenize(tmp); - remnulargs(tmp); - if (haswilds(tmp)) { - if (is) - tmp[llpl] = Star; - if ((cp = patcompile(tmp, 0, NULL))) - haspattern = 1; - } + tmp[llpl + gfl] = 'x'; + strcpy(tmp + llpl + gfl + is, lsuf); + + tokenize(tmp); + remnulargs(tmp); + if (haswilds(tmp)) { + if (is) + tmp[llpl + gfl] = Star; + if ((cp = patcompile(tmp, 0, NULL))) + haspattern = 1; } } - if (*argv) { - if (dat->pre) - dat->pre = dupstring(dat->pre); - if (dat->suf) - dat->suf = dupstring(dat->suf); - if (!dat->prpre && (dat->prpre = oppre)) { - singsub(&(dat->prpre)); - untokenize(dat->prpre); - } else - dat->prpre = dupstring(dat->prpre); - /* 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); - } - /* Select the set of matches. */ - oisalt = (dat->aflags & CAF_ALT); - - if (dat->remf) { - dat->remf = dupstring(dat->remf); - dat->rems = NULL; - } else if (dat->rems) - dat->rems = dupstring(dat->rems); + } + /* 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); + if (dat->suf) + dat->suf = dupstring(dat->suf); + if (!dat->prpre && (dat->prpre = oppre)) { + singsub(&(dat->prpre)); + untokenize(dat->prpre); + } else + dat->prpre = dupstring(dat->prpre); + /* Select the set of matches. */ + + if (dat->remf) { + dat->remf = dupstring(dat->remf); + dat->rems = NULL; + } else if (dat->rems) + dat->rems = dupstring(dat->rems); + + if (lpre) + lpre = ((!(dat->aflags & CAF_QUOTE) && + (!dat->ppre && (dat->flags & CMF_FILE))) ? + tildequote(lpre, 1) : multiquote(lpre, 1)); + if (lsuf) + lsuf = multiquote(lsuf, 1); + } + /* Walk through the matches given. */ + obpl = bpl; + obsl = bsl; + if (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); + } + for (; (s = *argv); argv++) { + bpl = obpl; + bsl = obsl; + if (disp) { + if (!*++disp) + disp = NULL; } - /* Walk through the matches given. */ - obpl = bpl; - obsl = bsl; - for (; (s = *argv); argv++) { - bpl = obpl; - bsl = obsl; - if (disp) { - if (!*++disp) - disp = NULL; - } - sl = strlen(s); - isalt = oisalt; - if ((!dat->psuf || !*(dat->psuf)) && aign) { + sl = strlen(s); + if (aign || pign) { + int il = ppl + sl + psl, addit = 1; + + if (ppl) + memcpy(ibuf, dat->ppre, ppl); + strcpy(ibuf + ppl, s); + if (psl) + strcpy(ibuf + ppl + sl, dat->psuf); + + if (aign) { /* Do the suffix-test. If the match has one of the - * suffixes from ign, we put it in the alternate set. */ + * suffixes from aign, we put it in the alternate set. */ char **pt = aign; int filell; - for (isalt = 0; !isalt && *pt; pt++) - if ((filell = strlen(*pt)) < sl - && !strcmp(*pt, s + sl - filell)) - isalt = 1; + for (; addit && *pt; pt++) + addit = !((filell = strlen(*pt)) < il && + !strcmp(*pt, ibuf + il - filell)); + } + if (addit && pign) { + Patprog *pt = pign; - if (isalt && !doadd) { - if (dparr && !*++dparr) - dparr = NULL; - continue; - } + for (; addit && *pt; pt++) + addit = !pattry(*pt, ibuf); } - if (!(dat->aflags & CAF_MATCH)) { - if (dat->aflags & CAF_QUOTE) - ms = dupstring(s); - else - sl = strlen(ms = quotename(s, NULL)); - lc = bld_parts(ms, sl, -1, NULL); - isexact = 0; - } else if (!(ms = comp_match(lpre, lsuf, s, cp, &lc, - (!(dat->aflags & CAF_QUOTE) ? - ((dat->ppre && dat->ppre) || - !(dat->flags & CMF_FILE) ? 1 : 2) : 0), - &bpl, bcp, &bsl, bcs, - &isexact))) { + if (!addit) { + compignored++; if (dparr && !*++dparr) dparr = NULL; continue; } - if (doadd) { - Brinfo bp; - - for (bp = obpl; bp; bp = bp->next) - bp->curpos += bpadd; - for (bp = obsl; bp; bp = bp->next) - bp->curpos += bsadd; - - if ((cm = add_match_data(isalt, ms, lc, dat->ipre, NULL, - dat->isuf, dat->pre, dat->prpre, - dat->ppre, pline, - dat->psuf, sline, - dat->suf, dat->flags, isexact))) { - cm->rems = dat->rems; - cm->remf = dat->remf; - if (disp) - cm->disp = dupstring(*disp); - } - } else { - if (dat->apar) - addlinknode(aparl, ms); - if (dat->opar) - addlinknode(oparl, s); - if (dat->dpar && dparr) { - addlinknode(dparl, *dparr); - if (!*++dparr) - dparr = NULL; - } - free_cline(lc); + } + if (!(dat->aflags & CAF_MATCH)) { + if (dat->aflags & CAF_QUOTE) + ms = dupstring(s); + else + sl = strlen(ms = multiquote(s, 0)); + lc = bld_parts(ms, sl, -1, NULL); + isexact = 0; + } else if (!(ms = comp_match(lpre, lsuf, s, cp, &lc, + (!(dat->aflags & CAF_QUOTE) ? + (dat->ppre || + !(dat->flags & CMF_FILE) ? 1 : 2) : 0), + &bpl, bcp, &bsl, bcs, + &isexact))) { + if (dparr && !*++dparr) + dparr = NULL; + continue; + } + if (doadd) { + Brinfo bp; + + for (bp = obpl; bp; bp = bp->next) + bp->curpos += bpadd; + for (bp = obsl; bp; bp = bp->next) + bp->curpos += bsadd; + + if ((cm = add_match_data(0, ms, lc, dat->ipre, NULL, + dat->isuf, dat->pre, dat->prpre, + dat->ppre, pline, + dat->psuf, sline, + dat->suf, dat->flags, isexact))) { + cm->rems = dat->rems; + cm->remf = dat->remf; + if (disp) + cm->disp = dupstring(*disp); } + } else { + if (dat->apar) + addlinknode(aparl, ms); + if (dat->opar) + addlinknode(oparl, s); + if (dat->dpar && dparr) { + addlinknode(dparl, *dparr); + if (!*++dparr) + dparr = NULL; + } + free_cline(lc); } - if (dat->apar) - set_list_array(dat->apar, aparl); - if (dat->opar) - set_list_array(dat->opar, oparl); - if (dat->dpar) - set_list_array(dat->dpar, dparl); - if (dat->exp) - addexpl(); - } LASTALLOC; + } + if (dat->apar) + set_list_array(dat->apar, aparl); + if (dat->opar) + set_list_array(dat->opar, oparl); + if (dat->dpar) + set_list_array(dat->dpar, dparl); + if (dat->exp) + addexpl(); } SWITCHBACKHEAPS; /* We switched back to the current heap, now restore the stack of @@ -1764,7 +1891,7 @@ addmatches(Cadata dat, char **argv) /* This adds all the data we have for a match. */ /**/ -Cmatch +mod_export Cmatch add_match_data(int alt, char *str, Cline line, char *ipre, char *ripre, char *isuf, char *pre, char *prpre, @@ -1797,21 +1924,12 @@ add_match_data(int alt, char *str, Cline line, salen += (qisl = strlen(qisuf)); if (salen) { - char *asuf = (char *) zhalloc(salen); Cline pp, p, s, sl = NULL; - - - if (psl) - memcpy(asuf, psuf, psl); - if (isl) - memcpy(asuf + psl, isuf, isl); - if (qisl) - memcpy(asuf + psl + isl, qisuf, qisl); for (pp = NULL, p = line; p->next; pp = p, p = p->next); - if (salen > qisl) { - s = bld_parts(asuf, salen - qisl, salen - qisl, &sl); + if (psl) { + s = bld_parts(psuf, psl, psl, &sl); if (sline) { Cline sp; @@ -1821,6 +1939,7 @@ add_match_data(int alt, char *str, Cline line, for (sp = sline; sp->next; sp = sp->next); sp->next = s; s = sline; + sline = NULL; } if (!(p->flags & (CLF_SUF | CLF_MID)) && !p->llen && !p->wlen && !p->olen) { @@ -1832,7 +1951,7 @@ add_match_data(int alt, char *str, Cline line, s->prefix = p->prefix; p->prefix = NULL; } - s->flags |= (p->flags & CLF_MATCHED); + s->flags |= (p->flags & CLF_MATCHED) | CLF_MID; free_cline(p); if (pp) pp->next = s; @@ -1841,8 +1960,29 @@ add_match_data(int alt, char *str, Cline line, } else p->next = s; } + if (isl) { + Cline tsl; + + s = bld_parts(isuf, isl, isl, &tsl); + + if (sl) + sl->next = s; + else if (sline) { + Cline sp; + + sline = cp_cline(sline, 1); + + for (sp = sline; sp->next; sp = sp->next); + sp->next = s; + p->next = sline; + sline = NULL; + } else + p->next = s; + + sl = tsl; + } if (qisl) { - Cline qsl = bld_parts(asuf + psl + isl, qisl, qisl, NULL); + Cline qsl = bld_parts(qisuf, qisl, qisl, NULL); qsl->flags |= CLF_SUF; qsl->suffix = qsl->prefix; @@ -1888,7 +2028,7 @@ add_match_data(int alt, char *str, Cline line, p = bld_parts(ppre, ppl, ppl, &lp); if (lp->prefix && !(line->flags & (CLF_SUF | CLF_MID)) && - !p->llen && !p->wlen && !p->olen) { + !lp->llen && !lp->wlen && !lp->olen) { Cline lpp; for (lpp = lp->prefix; lpp->next; lpp = lpp->next); @@ -1952,8 +2092,8 @@ add_match_data(int alt, char *str, Cline line, } else for (p = lp = cp_cline(pline, 1); lp->next; lp = lp->next); - if (lp->prefix && !(line->flags & (CLF_SUF | CLF_MID)) && - !p->llen && !p->wlen && !p->olen) { + if (lp->prefix && !(line->flags & CLF_SUF) && + !lp->llen && !lp->wlen && !lp->olen) { Cline lpp; for (lpp = lp->prefix; lpp->next; lpp = lpp->next); @@ -1994,7 +2134,14 @@ add_match_data(int alt, char *str, Cline line, cm->isuf = (isuf && *isuf ? isuf : NULL); cm->pre = pre; cm->suf = suf; - cm->flags = flags; + cm->flags = (flags | + (complist ? + ((strstr(complist, "packed") ? CMF_PACKED : 0) | + (strstr(complist, "rows") ? CMF_ROWS : 0)) : 0)); + + if ((*compqstack == '\\' && compqstack[1]) || + (autoq && *compqstack && compqstack[1] == '\\')) + cm->flags |= CMF_NOSPACE; if (nbrbeg) { int *p; Brinfo bp; @@ -2017,7 +2164,7 @@ add_match_data(int alt, char *str, Cline line, cm->brsl = NULL; cm->qipl = qipl; cm->qisl = qisl; - cm->autoq = (autoq ? autoq : (inbackt ? '`' : '\0')); + cm->autoq = dupstring(autoq ? autoq : (inbackt ? "`" : NULL)); cm->rems = cm->remf = cm->disp = NULL; if ((lastprebr || lastpostbr) && !hasbrpsfx(cm, lastprebr, lastpostbr)) @@ -2032,7 +2179,12 @@ add_match_data(int alt, char *str, Cline line, addlinknode((alt ? fmatches : matches), cm); newmatches = 1; + mgroup->new = 1; + if (alt) + compignored++; + if (!complastprompt || !*complastprompt) + dolastprompt = 0; /* One more match for this explanation. */ if (curexpl) { if (alt) @@ -2056,8 +2208,8 @@ add_match_data(int alt, char *str, Cline line, /* Do we have an exact match? More than one? */ if (exact) { if (!ai->exact) { - ai->exact = 1; - if (incompfunc) { + ai->exact = useexact; + if (incompfunc && (!compexactstr || !*compexactstr)) { /* If a completion widget is active, we make the exact * string available in `compstate'. */ @@ -2076,7 +2228,7 @@ add_match_data(int alt, char *str, Cline line, comp_setunset(0, 0, CP_EXACTSTR, 0); } ai->exactm = cm; - } else { + } else if (useexact) { ai->exact = 2; ai->exactm = NULL; if (incompfunc) @@ -2089,7 +2241,7 @@ add_match_data(int alt, char *str, Cline line, /* This begins a new group of matches. */ /**/ -void +mod_export void begcmgroup(char *n, int flags) { if (n) { @@ -2118,6 +2270,8 @@ begcmgroup(char *n, int flags) mgroup->matches = NULL; mgroup->ylist = NULL; mgroup->expls = NULL; + mgroup->perm = NULL; + mgroup->new = 0; mgroup->lexpls = expls = newlinklist(); mgroup->lmatches = matches = newlinklist(); @@ -2132,7 +2286,7 @@ begcmgroup(char *n, int flags) /* End the current group for now. */ /**/ -void +mod_export void endcmgroup(char **ylist) { mgroup->ylist = ylist; @@ -2141,7 +2295,7 @@ endcmgroup(char **ylist) /* Add an explanation string to the current group, joining duplicates. */ /**/ -void +mod_export void addexpl(void) { LinkNode n; @@ -2221,7 +2375,7 @@ makearray(LinkList l, int type, int flags, int *np, int *nlp, int *llp) int n, nl = 0, ll = 0; /* Build an array for the matches. */ - rp = ap = (Cmatch *) ncalloc(((n = countlinknodes(l)) + 1) * + rp = ap = (Cmatch *) hcalloc(((n = countlinknodes(l)) + 1) * sizeof(Cmatch)); /* And copy them into it. */ @@ -2252,22 +2406,28 @@ makearray(LinkList l, int type, int flags, int *np, int *nlp, int *llp) (int (*) _((const void *, const void *)))matchcmp); if (!(flags & CGF_UNIQCON)) { + int dup; + /* And delete the ones that occur more than once. */ for (ap = cp = rp; *ap; ap++) { *cp++ = *ap; for (bp = ap; bp[1] && matcheq(*ap, bp[1]); bp++, n--); ap = bp; /* Mark those, that would show the same string in the list. */ - for (; bp[1] && !(*ap)->disp && !(bp[1])->disp && - !strcmp((*ap)->str, (bp[1])->str); bp++) - (bp[1])->flags |= CMF_NOLIST; + for (dup = 0; bp[1] && !(*ap)->disp && !(bp[1])->disp && + !strcmp((*ap)->str, (bp[1])->str); bp++) { + (bp[1])->flags |= CMF_MULT; + dup = 1; + } + if (dup) + (*ap)->flags |= CMF_FMULT; } *cp = NULL; } for (ap = rp; *ap; ap++) { if ((*ap)->disp && ((*ap)->flags & CMF_DISPLINE)) ll++; - if ((*ap)->flags & CMF_NOLIST) + if ((*ap)->flags & (CMF_NOLIST | CMF_MULT)) nl++; } } else { @@ -2282,20 +2442,26 @@ makearray(LinkList l, int type, int flags, int *np, int *nlp, int *llp) *cp = NULL; } } else if (!(flags & CGF_UNIQCON)) { + int dup; + for (ap = cp = rp; *ap; ap++) { *cp++ = *ap; for (bp = ap; bp[1] && matcheq(*ap, bp[1]); bp++, n--); ap = bp; - for (; bp[1] && !(*ap)->disp && !(bp[1])->disp && - !strcmp((*ap)->str, (bp[1])->str); bp++) - (bp[1])->flags |= CMF_NOLIST; + for (dup = 0; bp[1] && !(*ap)->disp && !(bp[1])->disp && + !strcmp((*ap)->str, (bp[1])->str); bp++) { + (bp[1])->flags |= CMF_MULT; + dup = 1; + } + if (dup) + (*ap)->flags |= CMF_FMULT; } *cp = NULL; } for (ap = rp; *ap; ap++) { if ((*ap)->disp && ((*ap)->flags & CMF_DISPLINE)) ll++; - if ((*ap)->flags & CMF_NOLIST) + if ((*ap)->flags & (CMF_NOLIST | CMF_MULT)) nl++; } } @@ -2317,7 +2483,7 @@ dupmatch(Cmatch m, int nbeg, int nend) { Cmatch r; - r = (Cmatch) ncalloc(sizeof(struct cmatch)); + r = (Cmatch) zcalloc(sizeof(struct cmatch)); r->str = ztrdup(m->str); r->ipre = ztrdup(m->ipre); @@ -2349,10 +2515,10 @@ dupmatch(Cmatch m, int nbeg, int nend) r->brsl = NULL; r->rems = ztrdup(m->rems); r->remf = ztrdup(m->remf); - r->autoq = m->autoq; + r->autoq = ztrdup(m->autoq); r->qipl = m->qipl; r->qisl = m->qisl; - r->disp = dupstring(m->disp); + r->disp = ztrdup(m->disp); return r; } @@ -2360,24 +2526,24 @@ dupmatch(Cmatch m, int nbeg, int nend) /* This duplicates all groups of matches. */ /**/ -int +mod_export int permmatches(int last) { - Cmgroup g = amatches, n; + Cmgroup g = amatches, n, opm; Cmatch *p, *q; Cexpl *ep, *eq, e, o; LinkList mlist; static int fi = 0; - int nn, nl, ll, gn = 1, mn = 1, rn; + int nn, nl, ll, gn = 1, mn = 1, rn, ofi = fi; - if (pmatches && !newmatches) + if (pmatches && !newmatches) { + if (last && fi) + ainfo = fainfo; return fi; - + } newmatches = fi = 0; - if (pmatches) - freematches(pmatches); - + opm = pmatches; pmatches = lmatches = NULL; nmatches = smatches = 0; @@ -2387,8 +2553,8 @@ permmatches(int last) fi = 1; } while (g) { - HEAPALLOC { - if (empty(g->lmatches)) + if (fi != ofi || !g->perm || g->new) { + if (fi) /* We have no matches, try ignoring fignore. */ mlist = g->lfmatches; else @@ -2407,51 +2573,67 @@ permmatches(int last) NULL, NULL); g->ccount = 0; - } LASTALLOC; - - nmatches += g->mcount; - smatches += g->lcount; - - n = (Cmgroup) ncalloc(sizeof(struct cmgroup)); - - if (!lmatches) - lmatches = n; - if (pmatches) - pmatches->prev = n; - n->next = pmatches; - pmatches = n; - n->prev = 0; - n->num = gn++; - - n->flags = g->flags; - n->mcount = g->mcount; - n->matches = p = (Cmatch *) ncalloc((n->mcount + 1) * - sizeof(Cmatch)); - for (q = g->matches; *q; q++, p++) - *p = dupmatch(*q, nbrbeg, nbrend); - *p = NULL; - - n->lcount = g->lcount; - n->llcount = g->llcount; - if (g->ylist) - n->ylist = arrdup(g->ylist); - else - n->ylist = NULL; - - if ((n->ecount = g->ecount)) { - n->expls = ep = (Cexpl *) ncalloc((n->ecount + 1) * - sizeof(Cexpl)); - for (eq = g->expls; (o = *eq); eq++, ep++) { - *ep = e = (Cexpl) ncalloc(sizeof(struct cexpl)); - e->count = (fi ? o->fcount : o->count); - e->str = ztrdup(o->str); - } - *ep = NULL; - } else - n->expls = NULL; - n->widths = NULL; + nmatches += g->mcount; + smatches += g->lcount; + + n = (Cmgroup) zcalloc(sizeof(struct cmgroup)); + + if (g->perm) { + g->perm->next = NULL; + freematches(g->perm); + } + g->perm = n; + + if (!lmatches) + lmatches = n; + if (pmatches) + pmatches->prev = n; + n->next = pmatches; + pmatches = n; + n->prev = NULL; + n->num = gn++; + n->flags = g->flags; + n->mcount = g->mcount; + n->matches = p = (Cmatch *) zcalloc((n->mcount + 1) * sizeof(Cmatch)); + n->name = ztrdup(g->name); + for (q = g->matches; *q; q++, p++) + *p = dupmatch(*q, nbrbeg, nbrend); + *p = NULL; + + n->lcount = g->lcount; + n->llcount = g->llcount; + if (g->ylist) + n->ylist = zarrdup(g->ylist); + else + n->ylist = NULL; + + if ((n->ecount = g->ecount)) { + n->expls = ep = (Cexpl *) zcalloc((n->ecount + 1) * sizeof(Cexpl)); + for (eq = g->expls; (o = *eq); eq++, ep++) { + *ep = e = (Cexpl) zcalloc(sizeof(struct cexpl)); + e->count = (fi ? o->fcount : o->count); + e->str = ztrdup(o->str); + } + *ep = NULL; + } else + n->expls = NULL; + n->widths = NULL; + } else { + if (!lmatches) + lmatches = g->perm; + if (pmatches) + pmatches->prev = g->perm; + g->perm->next = pmatches; + pmatches = g->perm; + g->perm->prev = NULL; + + nmatches += g->mcount; + smatches += g->lcount; + g->num = gn++; + } + g->new = 0; g = g->next; } for (g = pmatches; g; g = g->next) { @@ -2490,6 +2672,7 @@ freematch(Cmatch m, int nbeg, int nend) zsfree(m->rems); zsfree(m->remf); zsfree(m->disp); + zsfree(m->autoq); zfree(m->brpl, nbeg * sizeof(int)); zfree(m->brsl, nend * sizeof(int)); @@ -2499,7 +2682,7 @@ freematch(Cmatch m, int nbeg, int nend) /* This frees the groups of matches. */ /**/ -void +mod_export void freematches(Cmgroup g) { Cmgroup n; @@ -2508,7 +2691,7 @@ freematches(Cmgroup g) while (g) { n = g->next; - + for (m = g->matches; *m; m++) freematch(*m, g->nbrbeg, g->nbrend); @@ -2523,6 +2706,7 @@ freematches(Cmgroup g) } free(g->expls); } + zsfree(g->name); free(g); g = n; |