diff options
Diffstat (limited to 'Src/Zle')
-rw-r--r-- | Src/Zle/comp.h | 39 | ||||
-rw-r--r-- | Src/Zle/comp1.c | 57 | ||||
-rw-r--r-- | Src/Zle/comp1.export | 15 | ||||
-rw-r--r-- | Src/Zle/compctl.c | 260 | ||||
-rw-r--r-- | Src/Zle/zle_hist.c | 6 | ||||
-rw-r--r-- | Src/Zle/zle_main.c | 4 | ||||
-rw-r--r-- | Src/Zle/zle_misc.c | 6 | ||||
-rw-r--r-- | Src/Zle/zle_params.c | 21 | ||||
-rw-r--r-- | Src/Zle/zle_refresh.c | 8 | ||||
-rw-r--r-- | Src/Zle/zle_tricky.c | 912 | ||||
-rw-r--r-- | Src/Zle/zle_word.c | 2 |
11 files changed, 896 insertions, 434 deletions
diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h index 76ac67114..d7f3610f1 100644 --- a/Src/Zle/comp.h +++ b/Src/Zle/comp.h @@ -103,6 +103,7 @@ struct compctl { char *glob; /* for -g (globbing) */ char *str; /* for -s (expansion) */ char *func; /* for -K (function) */ + char *widget; /* for -i (function) */ char *explain; /* for -X (explanation) */ char *ylist; /* for -y (user-defined desc. for listing) */ char *prefix, *suffix; /* for -P and -S (prefix, suffix) */ @@ -284,7 +285,37 @@ struct cline { /* Flags for compadd and addmatches(). */ #define CAF_QUOTE 1 -#define CAF_MENU 2 -#define CAF_NOSORT 4 -#define CAF_ALT 8 -#define CAF_MATCH 16 +#define CAF_NOSORT 2 +#define CAF_ALT 4 +#define CAF_MATCH 8 + +/* Flags for special parameters. */ + +#define CP_WORDS (1 << 0) +#define CP_CURRENT (1 << 1) +#define CP_PREFIX (1 << 2) +#define CP_SUFFIX (1 << 3) +#define CP_IPREFIX (1 << 4) +#define CP_COMPSTATE (1 << 5) + +#define CP_REALPARAMS 6 + +#define CP_NMATCHES (1 << 6) +#define CP_MATCHER (1 << 7) +#define CP_MATCHERSTR (1 << 8) +#define CP_MATCHERTOT (1 << 9) +#define CP_CONTEXT (1 << 10) +#define CP_PARAMETER (1 << 11) +#define CP_REDIRECT (1 << 12) +#define CP_QUOTE (1 << 13) +#define CP_QUOTING (1 << 14) +#define CP_RESTORE (1 << 15) +#define CP_LIST (1 << 16) +#define CP_INSERT (1 << 17) +#define CP_EXACT (1 << 18) +#define CP_EXACTSTR (1 << 19) +#define CP_PATMATCH (1 << 20) + +#define CP_NUM 21 + +#define CP_ALLMASK ((1 << CP_NUM) - 1) diff --git a/Src/Zle/comp1.c b/Src/Zle/comp1.c index 72f3cea53..ccccf5a34 100644 --- a/Src/Zle/comp1.c +++ b/Src/Zle/comp1.c @@ -46,10 +46,13 @@ Cmlist cmatcher; /**/ void (*makecompparamsptr) _((void)); +/**/ +void (*comp_setunsetptr) _((int, int)); + /* pointers to functions required by compctl and defined by zle */ /**/ -void (*addmatchesptr) _((char *, char *, char *, char *, char *, char *, char *, char *, char *, char *, int, int, Cmatcher, char *, char **)); +int (*addmatchesptr) _((char *, char *, char *, char *, char *, char *, char *, char *, char *, char *, int, int, Cmatcher, char *, char **)); /**/ char *(*comp_strptr) _((int*, int*, int)); @@ -58,7 +61,7 @@ char *(*comp_strptr) _((int*, int*, int)); int (*getcpatptr) _((char *, int, char *, int)); /**/ -void (*makecomplistcallptr) _((Compctl)); +int (*makecomplistcallptr) _((Compctl)); /**/ int (*makecomplistctlptr) _((int)); @@ -96,14 +99,29 @@ int incompfunc; /**/ long compcurrent, compnmatches, - compmatcher; + compmatcher, + compmatchertot; /**/ -char *compcontext, - *compcommand, +char **compwords, *compprefix, *compsuffix, - *compiprefix; + *compiprefix, + *compmatcherstr, + *compcontext, + *compparameter, + *compredirect, + *compquote, + *compquoting, + *comprestore, + *complist, + *compinsert, + *compexact, + *compexactstr, + *comppatmatch; + +/**/ +Param *comppms; /* The function rembslash() came from zle_tricky.c, but is now used * * in compctl.c, too. */ @@ -154,6 +172,7 @@ freecompctl(Compctl cc) zsfree(cc->glob); zsfree(cc->str); zsfree(cc->func); + zsfree(cc->widget); zsfree(cc->explain); zsfree(cc->ylist); zsfree(cc->prefix); @@ -408,9 +427,14 @@ setup_comp1(Module m) cc_first.refc = 10000; cc_first.mask = 0; cc_first.mask2 = CC_CCCONT; - compcontext = compcommand = compprefix = compsuffix = - compiprefix = NULL; + comppms = NULL; + compwords = NULL; + compprefix = compsuffix = compiprefix = compmatcherstr = + compcontext = compparameter = compredirect = compquote = + compquoting = comprestore = complist = compinsert = + compexact = compexactstr = comppatmatch = NULL; makecompparamsptr = NULL; + comp_setunsetptr = NULL; return 0; } @@ -437,11 +461,22 @@ finish_comp1(Module m) deletehashtable(compctltab); zfree(clwords, clwsize * sizeof(char *)); compctlreadptr = fallback_compctlread; - zsfree(compcontext); - zsfree(compcommand); + freearray(compwords); zsfree(compprefix); - zsfree(compiprefix); zsfree(compsuffix); + zsfree(compiprefix); + zsfree(compmatcherstr); + zsfree(compcontext); + zsfree(compparameter); + zsfree(compredirect); + zsfree(compquote); + zsfree(compquoting); + zsfree(comprestore); + zsfree(complist); + zsfree(compinsert); + zsfree(compexact); + zsfree(compexactstr); + zsfree(comppatmatch); return 0; } diff --git a/Src/Zle/comp1.export b/Src/Zle/comp1.export index 278006b6a..35b63e7d3 100644 --- a/Src/Zle/comp1.export +++ b/Src/Zle/comp1.export @@ -13,12 +13,27 @@ compcommand compcontext compctltab compcurrent +compexact +compexactstr +compinsert compiprefix +complist compmatcher +compmatcherstr +compmatchertot compnmatches +compparameter +comppatmatch +comppms compprefix +compredirect +compquote +compquoting +comprestore +comp_setunsetptr comp_strptr compsuffix +compwords freecmatcher freecmlist freecompcond diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index f71d67510..b5c8e4b3f 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -140,7 +140,7 @@ get_gmatcher(char *name, char **argv) while (*argv) { if ((m = parse_cmatcher(name, *argv)) == pcm_err) return 2; - *q = n = (Cmlist) halloc(sizeof(struct cmlist)); + *q = n = (Cmlist) zhalloc(sizeof(struct cmlist)); n->next = NULL; n->matcher = m; n->str = *argv++; @@ -578,6 +578,19 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef, int cl) *argv = "" - 1; } break; + case 'i': + if ((*argv)[1]) { + cct.widget = (*argv) + 1; + *argv = "" - 1; + } else if (!argv[1]) { + zwarnnam(name, "function name expected after -%c", NULL, + **argv); + return 1; + } else { + cct.widget = *++argv; + *argv = "" - 1; + } + break; case 'Y': cct.mask |= CC_EXPANDEXPL; goto expl; @@ -1197,6 +1210,7 @@ cc_assign(char *name, Compctl *ccptr, Compctl cct, int reass) zsfree(cc->glob); zsfree(cc->str); zsfree(cc->func); + zsfree(cc->widget); zsfree(cc->explain); zsfree(cc->ylist); zsfree(cc->prefix); @@ -1217,6 +1231,7 @@ cc_assign(char *name, Compctl *ccptr, Compctl cct, int reass) cc->glob = ztrdup(cct->glob); cc->str = ztrdup(cct->str); cc->func = ztrdup(cct->func); + cc->widget = ztrdup(cct->widget); cc->explain = ztrdup(cct->explain); cc->ylist = ztrdup(cct->ylist); cc->prefix = ztrdup(cct->prefix); @@ -1423,6 +1438,7 @@ printcompctl(char *s, Compctl cc, int printflags, int ispat) printif(cc->gname, 'J'); printif(cc->keyvar, 'k'); printif(cc->func, 'K'); + printif(cc->widget, 'i'); printif(cc->explain, (cc->mask & CC_EXPANDEXPL) ? 'Y' : 'X'); printif(cc->ylist, 'y'); printif(cc->prefix, 'P'); @@ -1644,7 +1660,7 @@ bin_compctl(char *name, char **argv, char *ops, int func) /**/ static int -bin_complist(char *name, char **argv, char *ops, int func) +bin_compgen(char *name, char **argv, char *ops, int func) { Compctl cc; int ret = 0; @@ -1663,7 +1679,7 @@ bin_complist(char *name, char **argv, char *ops, int func) zerrnam(name, "command names illegal", NULL, 0); ret = 1; } else - makecomplistcallptr(cc); + ret = makecomplistcallptr(cc); freecompctl(cc); return ret; @@ -1677,7 +1693,7 @@ bin_compadd(char *name, char **argv, char *ops, int func) char *ipre = NULL, *ppre = NULL, *psuf = NULL, *prpre = NULL; char *pre = NULL, *suf = NULL, *group = NULL, *m = NULL, *rs = NULL; char *ign = NULL, *rf = NULL, *expl = NULL; - int f = 0, a = 0, dm; + int f = 0, a = CAF_MATCH, dm; Cmatcher match = NULL; if (incompfunc != 1) { @@ -1710,7 +1726,7 @@ bin_compadd(char *name, char **argv, char *ops, int func) f |= CMF_NOLIST; break; case 'U': - a |= CAF_MENU; + a &= ~CAF_MATCH; break; case 'P': sp = ⪯ @@ -1749,9 +1765,6 @@ bin_compadd(char *name, char **argv, char *ops, int func) case 'a': a |= CAF_ALT; break; - case 'm': - a |= CAF_MATCH; - break; case 'M': sp = &m; e = "matching specification expected after -%c"; @@ -1805,11 +1818,11 @@ bin_compadd(char *name, char **argv, char *ops, int func) return 1; match = cpcmatcher(match); - addmatchesptr(ipre, ppre, psuf, prpre, pre, suf, group, - rs, rf, ign, f, a, match, expl, argv); + a = addmatchesptr(ipre, ppre, psuf, prpre, pre, suf, group, + rs, rf, ign, f, a, match, expl, argv); freecmatcher(match); - return 0; + return a; } /**/ @@ -1824,34 +1837,54 @@ bin_compcall(char *name, char **argv, char *ops, int func) (ops['D'] ? 0 : CFN_DEFAULT)); } +/* Definitions for the special parameters. Note that these have to match the + * order of the CP_* bits in comp.h */ + #define VAR(X) ((void *) (&(X))) static struct compparam { char *name; int type; void *var; } compparams[] = { + { "words", PM_ARRAY, VAR(compwords) }, { "CURRENT", PM_INTEGER, VAR(compcurrent) }, - { "CONTEXT", PM_SCALAR, VAR(compcontext) }, - { "COMMAND", PM_SCALAR, VAR(compcommand) }, { "PREFIX", PM_SCALAR, VAR(compprefix) }, { "SUFFIX", PM_SCALAR, VAR(compsuffix) }, { "IPREFIX", PM_SCALAR, VAR(compiprefix) }, - { "NMATCHES", PM_INTEGER, VAR(compnmatches) }, - { "MATCHER", PM_INTEGER, VAR(compmatcher) }, + { NULL, 0, NULL }, + + { "nmatches", PM_INTEGER, VAR(compnmatches) }, + { "matcher", PM_INTEGER, VAR(compmatcher) }, + { "matcher_string", PM_SCALAR, VAR(compmatcherstr) }, + { "total_matchers", PM_INTEGER, VAR(compmatchertot) }, + { "context", PM_SCALAR, VAR(compcontext) }, + { "parameter", PM_SCALAR, VAR(compparameter) }, + { "redirect", PM_SCALAR, VAR(compredirect) }, + { "quote", PM_SCALAR, VAR(compquote) }, + { "quoting", PM_SCALAR, VAR(compquoting) }, + { "restore", PM_SCALAR, VAR(comprestore) }, + { "list", PM_SCALAR, VAR(complist) }, + { "insert", PM_SCALAR, VAR(compinsert) }, + { "exact", PM_SCALAR, VAR(compexact) }, + { "exact_string", PM_SCALAR, VAR(compexactstr) }, + { "pattern_match", PM_SCALAR, VAR(comppatmatch) }, { NULL, 0, NULL } }; -/**/ -void makecompparams(void) +#define COMPSTATENAME "compstate" + +static struct compparam * +addcompparams(struct compparam *cp) { - struct compparam *cp; + Param *pp = comppms + (cp - compparams); - for (cp = compparams; cp->name; cp++) { + for (; cp->name; cp++, pp++) { Param pm = createparam(cp->name, cp->type | PM_SPECIAL|PM_REMOVABLE); if (!pm) pm = (Param) paramtab->getnode(paramtab, cp->name); - DPUTS(!pm, "param not set in makecompparams"); + DPUTS(!pm, "param not set in addcompparams"); + *pp = pm; pm->level = locallevel; pm->u.data = cp->var; switch(PM_TYPE(cp->type)) { @@ -1862,18 +1895,115 @@ void makecompparams(void) case PM_INTEGER: pm->sets.ifn = intvarsetfn; pm->gets.ifn = intvargetfn; + pm->ct = 10; + break; + case PM_ARRAY: + pm->sets.afn = arrvarsetfn; + pm->gets.afn = arrvargetfn; break; } pm->unsetfn = compunsetfn; } + return cp; +} + +/**/ +void +makecompparams(void) +{ + struct compparam *cp; + Param cpm; + HashTable tht; + + cp = addcompparams(compparams); + + if (!(cpm = createparam(COMPSTATENAME, PM_SPECIAL|PM_REMOVABLE|PM_HASHED))) + cpm = (Param) paramtab->getnode(paramtab, COMPSTATENAME); + DPUTS(!cpm, "param not set in makecompparams"); + + comppms[cp - compparams] = cpm; + tht = paramtab; + cpm->level = locallevel; + cpm->gets.hfn = get_compstate; + cpm->sets.hfn = set_compstate; + cpm->unsetfn = compunsetfn; + cpm->u.hash = paramtab = newparamtable(17, COMPSTATENAME); + addcompparams(cp + 1); + paramtab = tht; +} + +/**/ +static HashTable +get_compstate(Param pm) +{ + return pm->u.hash; +} + +/**/ +static void +set_compstate(Param pm, HashTable ht) +{ + struct compparam *cp; + Param *pp; + HashNode hn; + int i; + struct value v; + char *str; + + for (i = 0; i < ht->hsize; i++) + for (hn = ht->nodes[i]; hn; hn = hn->next) + for (cp = compparams + CP_REALPARAMS, + pp = comppms + CP_REALPARAMS; cp->name; cp++, pp++) + if (!strcmp(hn->nam, cp->name)) { + v.isarr = v.inv = v.a = 0; + v.b = -1; + v.arr = NULL; + v.pm = (Param) hn; + if (cp->type == PM_INTEGER) + *((long *) cp->var) = getintvalue(&v); + else if ((str = getstrvalue(&v))) { + zsfree(*((char **) cp->var)); + *((char **) cp->var) = ztrdup(str); + } + (*pp)->flags &= ~PM_UNSET; + + break; + } } /**/ static void compunsetfn(Param pm, int exp) { - if (exp) - stdunsetfn(pm, exp); + if (exp) { + if (PM_TYPE(pm->flags) == PM_SCALAR) { + zsfree(*((char **) pm->u.data)); + *((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 *)); + } + pm->flags |= PM_UNSET; + } +} + +/**/ +void +comp_setunset(int set, int unset) +{ + Param *p; + + if (!comppms) + return; + + set &= CP_ALLMASK; + unset &= CP_ALLMASK; + for (p = comppms; set || unset; set >>= 1, unset >>= 1, p++) { + if (set & 1) + (*p)->flags &= ~PM_UNSET; + if (unset & 1) + (*p)->flags |= PM_UNSET; + } } /**/ @@ -1883,29 +2013,51 @@ comp_wrapper(List list, FuncWrap w, char *name) if (incompfunc != 1) return 1; else { - char *octxt, *ocmd, *opre, *osuf, *oipre; + char *orest, *opre, *osuf, *oipre, **owords; long ocur; - + int unset = 0, m, sm; + Param *pp; + + m = CP_WORDS | CP_CURRENT | CP_PREFIX | CP_SUFFIX | + CP_IPREFIX | CP_RESTORE; + for (pp = comppms, sm = 1; m; pp++, m >>= 1, sm <<= 1) { + if ((m & 1) && ((*pp)->flags & PM_UNSET)) + unset |= sm; + } + orest = comprestore; + comprestore = ztrdup("auto"); ocur = compcurrent; - octxt = dupstring(compcontext); - ocmd = dupstring(compcommand); opre = dupstring(compprefix); osuf = dupstring(compsuffix); oipre = dupstring(compiprefix); + HEAPALLOC { + owords = arrdup(compwords); + } LASTALLOC; + runshfunc(list, w, name); - compcurrent = ocur; - zsfree(compcontext); - compcontext = ztrdup(octxt); - zsfree(compcommand); - compcommand = ztrdup(ocmd); - zsfree(compprefix); - compprefix = ztrdup(opre); - zsfree(compsuffix); - compsuffix = ztrdup(osuf); - zsfree(compiprefix); - compiprefix = ztrdup(oipre); + if (comprestore && !strcmp(comprestore, "auto")) { + compcurrent = ocur; + zsfree(compprefix); + compprefix = ztrdup(opre); + zsfree(compsuffix); + compsuffix = ztrdup(osuf); + zsfree(compiprefix); + compiprefix = ztrdup(oipre); + freearray(compwords); + PERMALLOC { + compwords = arrdup(owords); + } LASTALLOC; + comp_setunset(CP_COMPSTATE | + (~unset & (CP_WORDS | CP_CURRENT | CP_PREFIX | + CP_SUFFIX | CP_IPREFIX | CP_RESTORE)), + unset); + } else + comp_setunset(CP_COMPSTATE | (~unset & CP_RESTORE), + (unset & CP_RESTORE)); + zsfree(comprestore); + comprestore = orest; return 0; } @@ -1942,20 +2094,14 @@ comp_check(void) static void restrict_range(int b, int e) { - int i = e - b; + int i = e - b + 1; char **p = (char **) zcalloc((i + 1) * sizeof(char *)), **q, **pp; - for (q = p, pp = pparams + b + 1; i; i--, q++, pp++) + for (q = p, pp = compwords + b; i; i--, q++, pp++) *q = ztrdup(*pp); - zsfree(compcommand); - compcommand = ztrdup(pparams[b]); - freearray(pparams); - pparams = p; - zsfree(compcontext); - if ((compcurrent -= b + 1)) - compcontext = ztrdup("argument"); - else - compcontext = ztrdup("command"); + freearray(compwords); + compwords = p; + compcurrent -= b; } /**/ @@ -1988,7 +2134,7 @@ cond_position(char **a, int id) { if (comp_check()) { int b = cond_val(a, 0), e = (a[1] ? cond_val(a, 1) : b); - int l = arrlen(pparams), t, i = compcurrent - 1; + int l = arrlen(compwords), t, i = compcurrent - 1; if (b > 0) b--; @@ -2018,7 +2164,7 @@ cond_word(char **a, int id) { if (comp_check()) { int o = ((id & 2) ? compcurrent : 0) + cond_val(a, 0); - int l = arrlen(pparams); + int l = arrlen(compwords); char *s; if (o < 0) @@ -2028,7 +2174,7 @@ cond_word(char **a, int id) if (o < 0 || o >= l) return 0; - s = pparams[o]; + s = compwords[o]; return ((id & 1) ? cond_match(a, 1, s) : !strcmp(s, cond_str(a, 1))); } return 0; @@ -2068,7 +2214,7 @@ cond_words(char **a, int id) { if (comp_check()) { int b = cond_val(a, 0), e = (a[1] ? cond_val(a, 1) : -1); - int l = arrlen(pparams); + int l = arrlen(compwords); return (l >= b && l <= e); } @@ -2081,7 +2227,7 @@ cond_range(char **a, int id) { if (comp_check()) { char *s, **p; - int i, l = arrlen(pparams), t = 0, b = 0, e = l - 1; + int i, l = arrlen(compwords), t = 0, b = 0, e = l - 1; Comp c; i = compcurrent - 1; @@ -2095,7 +2241,7 @@ cond_range(char **a, int id) } else s = cond_str(a, 0); - for (i--, p = pparams + i; i >= 0; p--, i--) { + for (i--, p = compwords + i; i >= 0; p--, i--) { if (((id & 1) ? domatch(*p, c, 0) : !strcmp(*p, s))) { b = i + 1; t = 1; @@ -2112,7 +2258,7 @@ cond_range(char **a, int id) } else s = cond_str(a, 1); - for (i++, p = pparams + i; i < l; p++, i++) { + for (i++, p = compwords + i; i < l; p++, i++) { if (((id & 1) ? domatch(*p, c, 0) : !strcmp(*p, s))) { e = i - 1; tt = 1; @@ -2151,7 +2297,7 @@ cond_matcher(char **a, int id) static struct builtin bintab[] = { BUILTIN("compctl", 0, bin_compctl, 0, -1, 0, NULL, NULL), - BUILTIN("complist", 0, bin_complist, 1, -1, 0, NULL, NULL), + BUILTIN("compgen", 0, bin_compgen, 1, -1, 0, NULL, NULL), BUILTIN("compadd", 0, bin_compadd, 0, -1, 0, NULL, NULL), BUILTIN("compcall", 0, bin_compcall, 0, 0, 0, "TD", NULL), }; @@ -2185,6 +2331,7 @@ setup_compctl(Module m) { compctltab->printnode = printcompctlp; makecompparamsptr = makecompparams; + comp_setunsetptr = comp_setunset; return 0; } @@ -2217,6 +2364,7 @@ finish_compctl(Module m) { compctltab->printnode = NULL; makecompparamsptr = NULL; + comp_setunsetptr = NULL; return 0; } diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c index a4b3866e5..2def5f03a 100644 --- a/Src/Zle/zle_hist.c +++ b/Src/Zle/zle_hist.c @@ -653,7 +653,7 @@ get_isrch_spot(int num, int *hlp, int *posp, int *csp, int *lenp, int *dirp, int static void doisearch(int dir) { - char *s, *ibuf = halloc(80), *sbuf = ibuf + FIRST_SEARCH_CHAR; + char *s, *ibuf = zhalloc(80), *sbuf = ibuf + FIRST_SEARCH_CHAR; int sbptr = 0, top_spot = 0, pos, sibuf = 80; int nomatch = 0, skip_line = 0, skip_pos = 0; int odir = dir, sens = zmult == 1 ? 3 : 1; @@ -936,7 +936,7 @@ static int visrchsense; static int getvisrchstr(void) { - char *sbuf = halloc(80); + char *sbuf = zhalloc(80); int sptr = 1, ret = 0, ssbuf = 80; Thingy cmd; char *okeymap = curkeymapname; @@ -1001,7 +1001,7 @@ getvisrchstr(void) } ins: if(sptr == ssbuf - 1) { - char *newbuf = halloc(ssbuf *= 2); + char *newbuf = zhalloc(ssbuf *= 2); strcpy(newbuf, sbuf); statusline = sbuf = newbuf; } diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 277d154a6..97d012f7b 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -154,10 +154,14 @@ zsetterm(void) # ifdef OXTABS ti.tio.c_oflag &= ~OXTABS; # else +# ifdef XTABS ti.tio.c_oflag &= ~XTABS; +# endif # endif # endif +#ifdef ONLCR ti.tio.c_oflag |= ONLCR; +#endif ti.tio.c_cc[VQUIT] = # ifdef VDISCARD ti.tio.c_cc[VDISCARD] = diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index ea8874010..1c25cd7eb 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -567,7 +567,7 @@ makequote(char *str, size_t *len) if (*l == '\'') qtct++; *len += 2 + qtct*3; - l = ol = (char *)halloc(*len); + l = ol = (char *)zhalloc(*len); *l++ = '\''; for (; str < end; str++) if (*str == '\'') { @@ -613,7 +613,7 @@ executenamedcommand(char *prmt) char *okeymap = curkeymapname; clearlist = 1; - cmdbuf = halloc(l + NAMLEN + 2); + cmdbuf = zhalloc(l + NAMLEN + 2); strcpy(cmdbuf, prmt); statusline = cmdbuf; selectkeymap("main", 1); @@ -794,7 +794,7 @@ makeparamsuffix(int br, int n) if(br) { suffixlen['#'] = suffixlen['%'] = suffixlen['?'] = n; suffixlen['-'] = suffixlen['+'] = suffixlen['='] = n; - /*{*/ suffixlen['}'] = n; + /*{*/ suffixlen['}'] = suffixlen['/'] = n; } } diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c index 7e15d3d8b..2a35ac416 100644 --- a/Src/Zle/zle_params.c +++ b/Src/Zle/zle_params.c @@ -67,6 +67,8 @@ static struct zleparam { zleunsetfn, NULL }, { "keys", PM_ARRAY | PM_READONLY, NULL, FN(get_keys), zleunsetfn, NULL }, + { "NUMERIC", PM_INTEGER | PM_READONLY, FN(set_numeric), FN(get_numeric), + zleunsetfn, NULL }, { NULL, 0, NULL, NULL, NULL, NULL } }; @@ -97,6 +99,7 @@ makezleparams(int ro) case PM_INTEGER: pm->sets.ifn = (void (*) _((Param, long))) zp->setfn; pm->gets.ifn = (long (*) _((Param))) zp->getfn; + pm->ct = 10; break; } pm->unsetfn = zp->unsetfn; @@ -225,9 +228,9 @@ get_keys(Param pm) { char **r, **q, *p, *k, c; - r = (char **) halloc((strlen(keybuf) + 1) * sizeof(char *)); + r = (char **) zhalloc((strlen(keybuf) + 1) * sizeof(char *)); for (q = r, p = keybuf; (c = *p); q++, p++) { - k = *q = (char *) halloc(5); + k = *q = (char *) zhalloc(5); if (c & 0x80) { *k++ = 'M'; *k++ = '-'; @@ -244,3 +247,17 @@ get_keys(Param pm) return r; } + +/**/ +static void +set_numeric(Param pm, long x) +{ + zmult = x; +} + +/**/ +static long +get_numeric(Param pm) +{ + return zmult; +} diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c index 9e07676e8..b9f39b70b 100644 --- a/Src/Zle/zle_refresh.c +++ b/Src/Zle/zle_refresh.c @@ -266,7 +266,11 @@ zrefresh(void) /* Nov 96: <mason> I haven't checked how complete this is. sgtty stuff may or may not work */ +#if defined(SGTABTYPE) oxtabs = ((SGTTYFLAG & SGTABTYPE) == SGTABTYPE); +#else + oxtabs = 0; +#endif cleareol = 0; /* unset */ more_start = more_end = 0; /* unset */ @@ -615,7 +619,7 @@ refreshline(int ln) if (cleareol /* request to clear to end of line */ || !nllen /* no line buffer given */ || (ln == 0 && (put_rpmpt != oput_rpmpt))) { /* prompt changed */ - p1 = halloc(winw + 2); + p1 = zhalloc(winw + 2); if (nllen) strncpy(p1, nl, nllen); memset(p1 + nllen, ' ', winw - nllen); @@ -627,7 +631,7 @@ refreshline(int ln) nl = p1; /* don't keep the padding for prompt line */ nllen = winw; } else if (ollen > nllen) { /* make new line at least as long as old */ - p1 = halloc(ollen + 1); + p1 = zhalloc(ollen + 1); strncpy(p1, nl, nllen); memset(p1 + nllen, ' ', ollen - nllen); p1[ollen] = '\0'; diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index 4b42640e1..f01ffbf1c 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -73,9 +73,10 @@ static int wb, we; static int offs; /* These control the type of completion that will be done. They are * - * affected by the choice of ZLE command and by relevant shell options. */ + * affected by the choice of ZLE command and by relevant shell options. * + * usemenu is set to 2 if we have to start automenu. */ -static int usemenu, useglob; +static int usemenu, useglob, useexact, useline, uselist; /* != 0 if we are in the middle of a menu completion */ @@ -125,7 +126,7 @@ static int validlist; /* This flag is non-zero if we are completing a pattern (with globcomplete) */ -static int ispattern; +static int ispattern, haspattern; /* Two patterns used when doing glob-completion. The first one is built * * from the whole word we are completing and the second one from that * @@ -168,12 +169,6 @@ static int addwhat; static char *qword; -/* This is non-zero if we are doing a menu-completion and this is not the * - * first call (e.g. when automenu is set and menu-completion was entered * - * due to this). */ - -static int amenu; - /* The current group of matches. */ static Cmgroup mgroup; @@ -322,7 +317,7 @@ completecall(void) void completeword(void) { - usemenu = isset(MENUCOMPLETE); + usemenu = !!isset(MENUCOMPLETE); useglob = isset(GLOBCOMPLETE); if (c == '\t' && usetab()) selfinsert(); @@ -351,7 +346,7 @@ menucomplete(void) void listchoices(void) { - usemenu = isset(MENUCOMPLETE); + usemenu = !!isset(MENUCOMPLETE); useglob = isset(GLOBCOMPLETE); docomplete(COMP_LIST_COMPLETE); } @@ -371,7 +366,7 @@ deletecharorlist(void) Cmgroup mg = menugrp; Cmatch *mc = menucur; - usemenu = isset(MENUCOMPLETE); + usemenu = !!isset(MENUCOMPLETE); useglob = isset(GLOBCOMPLETE); if (cs != ll) { fixsuffix(); @@ -398,7 +393,7 @@ expandword(void) void expandorcomplete(void) { - usemenu = isset(MENUCOMPLETE); + usemenu = !!isset(MENUCOMPLETE); useglob = isset(GLOBCOMPLETE); if (c == '\t' && usetab()) selfinsert(); @@ -427,7 +422,7 @@ menuexpandorcomplete(void) void listexpand(void) { - usemenu = isset(MENUCOMPLETE); + usemenu = !!isset(MENUCOMPLETE); useglob = isset(GLOBCOMPLETE); docomplete(COMP_LIST_EXPAND); } @@ -492,9 +487,9 @@ acceptandmenucomplete(void) } /* These are flags saying if we are completing in the command * - * position or in a redirection. */ + * position, in a redirection, or in a parameter expansion. */ -static int lincmd, linredir; +static int lincmd, linredir, ispar; /* The string for the redirection operator. */ @@ -513,10 +508,10 @@ static char *varname; static int insubscr; -/* 1 if we are completing in a string */ +/* 1 if we are completing in a quoted string (or inside `...`) */ /**/ -int instring; +int instring, inbackt; /* Convenience macro for calling bslashquote() (formerly quotename()). * * This uses the instring variable above. */ @@ -601,6 +596,87 @@ cmphaswilds(char *str) return 0; } +/* Check if we have to complete a parameter name. */ + +static char * +check_param(char *s, int set) +{ + char *p; + + ispar = 0; + /* Try to find a `$'. */ + for (p = s + offs; p > s && *p != String; p--); + if (*p == String) { + /* Handle $$'s */ + while (p > s && p[-1] == String) + p--; + while (p[1] == String && p[2] == String) + p += 2; + } + if (*p == String && p[1] != Inpar && p[1] != Inbrack) { + /* This is really a parameter expression (not $(...) or $[...]). */ + char *b = p + 1, *e = b; + int n = 0, br = 1; + + if (*b == Inbrace) { + /* If this is a ${...}, ignore the possible (...) flags. */ + b++, br++; + n = skipparens(Inpar, Outpar, &b); + } + + /* Ignore the stuff before the parameter name. */ + for (; *b; b++) + if (*b != '^' && *b != Hat && + *b != '=' && *b != Equals && + *b != '~' && *b != Tilde) + break; + if (*b == '#' || *b == Pound || *b == '+') + b++; + + e = b; + /* Find the end of the name. */ + if (*e == Quest || *e == Star || *e == String || *e == Qstring || + *e == '?' || *e == '*' || *e == '$' || + *e == '-' || *e == '!' || *e == '@') + e++; + else if (idigit(*e)) + while (idigit(*e)) + e++; + else if (iident(*e)) + while (iident(*e) || + (comppatmatch && *comppatmatch && + (*e == Star || *e == Quest))) + e++; + + /* Now make sure that the cursor is inside the name. */ + if (offs <= e - s && offs >= b - s && n <= 0) { + /* It is. */ + /* If we were called from makecomplistflags(), we have to set the + * global variables. */ + if (set) { + if (br >= 2) + mflags |= CMF_PARBR; + + /* Get the prefix (anything up to the character before the name). */ + lpsuf = dupstring(quotename(e, NULL, NULL, NULL)); + *e = '\0'; + lpsl = strlen(lpsuf); + ripre = dupstring(s); + ripre[b - s] = '\0'; + ipre = dupstring(quotename(ripre, NULL, NULL, NULL)); + untokenize(ipre); + } + /* And adjust wb, we, and offs again. */ + offs -= b - s; + wb = cs - offs; + we = wb + e - b; + ispar = (br >= 2 ? 2 : 1); + return b; + } + } + return NULL; +} + /* The main entry point for completion. */ /**/ @@ -625,9 +701,9 @@ docomplete(int lst) /* Check if we have to start a menu-completion (via automenu). */ - if ((amenu = (isset(AUTOMENU) && lastambig && - (!isset(BASHAUTOLIST) || lastambig == 2)))) - usemenu = 1; + if (isset(AUTOMENU) && lastambig && + (!isset(BASHAUTOLIST) || lastambig == 2)) + usemenu = 2; /* Expand history references before starting completion. If anything * * changed, do no more. */ @@ -910,7 +986,7 @@ addx(char **ptmp) (instring && (line[cs] == '"' || line[cs] == '\'')) || (addspace = (comppref && !iblank(line[cs])))) { *ptmp = (char *)line; - line = (unsigned char *)halloc(strlen((char *)line) + 3 + addspace); + line = (unsigned char *)zhalloc(strlen((char *)line) + 3 + addspace); memcpy(line, *ptmp, cs); line[cs] = 'x'; if (addspace) @@ -999,6 +1075,7 @@ get_comp_string(void) else if (*p == '\\' && p[1] && !(k & 1)) p++; instring = (j & 1) ? 2 : (k & 1); + inbackt = (i & 1); addx(&tmp); if (instring) { /* Yes, we are in a string. */ @@ -1010,7 +1087,7 @@ get_comp_string(void) * What?? Why that?? Well, we want to be able to complete * * inside strings. The lexer code gives us no help here, * * so we have to cheat. We remove the quotes, the lexer * - * will than treat the words in the strings normally and we * + * will then treat the words in the strings normally and we * * can complete them. * * This is completely the wrong thing to do, but it's * * occasionally useful, and we can't handle quotes properly * @@ -1551,7 +1628,7 @@ getcline(char *l, int ll, char *w, int wl, int fl) if ((r = freecl)) freecl = r->next; else - r = (Cline) halloc(sizeof(*r)); + r = (Cline) zhalloc(sizeof(*r)); r->next = NULL; r->line = l; @@ -1626,7 +1703,7 @@ add_bmatchers(Cmatcher m) for (; m; m = m->next) { if ((!m->flags && m->wlen > 0 && m->llen > 0) || (m->flags == CMF_RIGHT && m->wlen == -1 && !m->llen)) { - *q = n = (Cmlist) halloc(sizeof(struct cmlist)); + *q = n = (Cmlist) zhalloc(sizeof(struct cmlist)); n->matcher = m; q = &(n->next); } @@ -1796,7 +1873,7 @@ join_strs(int la, char *sa, int lb, char *sb) if (!t) break; } else { - if (rr <= mp->llen) { + if (rr <= 1) { char *or = rs; rs = realloc(rs, (rl += 20)); @@ -1850,7 +1927,7 @@ join_ends(Cline o, Cline n, int *olp, int *nlp) } else { /* Different anchors, see if we can find matching anchors * further down the lists. */ - Cline to, tn; + Cline to, tn = NULL; int t = 0; /* But first build the common prefix. */ @@ -3337,6 +3414,7 @@ match_pfx(char *l, char *w, Cline *nlp, int *lp, Cline *rlp, int *bplp) } } while (ll && lw) { + t = 0; /* First try the matchers. */ for (ms = mstack; ms; ms = ms->next) { for (mp = ms->matcher; mp; mp = mp->next) { @@ -3578,6 +3656,7 @@ match_sfx(char *l, char *w, Cline *nlp, int *lp, int *bslp) } } while (ll && lw) { + t = 0; for (ms = mstack; ms; ms = ms->next) { for (mp = ms->matcher; mp; mp = mp->next) { if (lm == mp) @@ -3774,7 +3853,7 @@ comp_match(char *pfx, char *sfx, char *w, Cline *clp, int qu, int *bpl, int *bsl * in the cline struct in the middle. */ pml = strlen(p); sml = strlen(s); - r = (char *) halloc(pml + sml + last->llen + 1); + r = (char *) zhalloc(pml + sml + last->llen + 1); strcpy(r, p); strncpy(r + pml, last->line, last->llen); strcpy(r + pml + last->llen, s); @@ -3824,7 +3903,7 @@ comp_match(char *pfx, char *sfx, char *w, Cline *clp, int qu, int *bpl, int *bsl static void inststrlen(char *str, int move, int len) { - if (!len) + if (!len || !str) return; if (len == -1) len = strlen(str); @@ -3902,30 +3981,28 @@ instmatch(Cmatch m) * the matches. */ /**/ -void +int addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, char *suf, char *group, char *rems, char *remf, char *ign, int flags, int aflags, Cmatcher match, char *exp, char **argv) { - char *s, *t, *e, *me, *ms, *lipre = NULL, *lpre, *lsuf, **aign = NULL; - int lpl, lsl, i, pl, sl, test, bpl, bsl, llpl, llsl; - Aminfo ai; + char *s, *t, *e, *me, *ms, *lipre = NULL, *lpre = NULL, *lsuf = NULL; + char **aign = NULL; + int lpl, lsl, i, pl, sl, test, bpl, bsl, llpl = 0, llsl = 0, nm = mnum; + Aminfo ai = NULL; Cline lc = NULL; - LinkList l; + LinkList l = NULL; Cmatch cm; struct cmlist mst; Cmlist oms = mstack; - - /* Use menu-completion (-U)? */ - if ((aflags & CAF_MENU) && isset(AUTOMENU)) - usemenu = 1; + Comp cp = NULL; /* Switch back to the heap that was used when the completion widget * was invoked. */ SWITCHHEAPS(compheap) { HEAPALLOC { if (exp) { - expl = (Cexpl) halloc(sizeof(struct cexpl)); + expl = (Cexpl) zhalloc(sizeof(struct cexpl)); expl->count = expl->fcount = 0; expl->str = dupstring(exp); } else @@ -3954,9 +4031,30 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, if (aflags & CAF_MATCH) { lipre = dupstring(compiprefix); lpre = dupstring(compprefix); - llpl = strlen(lpre); lsuf = dupstring(compsuffix); + llpl = strlen(lpre); llsl = strlen(lsuf); + /* Test if there is an existing -P prefix. */ + if (pre && *pre) { + pl = pfxlen(pre, lpre); + llpl -= pl; + lpre += pl; + } + if (comppatmatch && *comppatmatch) { + char *tmp = (char *) zhalloc(2 + llpl + llsl); + + strcpy(tmp, lpre); + tmp[llpl] = 'x'; + strcpy(tmp + llpl + 1, lsuf); + + tokenize(tmp); + remnulargs(tmp); + if (haswilds(tmp)) { + tmp[llpl] = Star; + if ((cp = parsereg(tmp))) + haspattern = 1; + } + } } /* Now duplicate the strings we have from the command line. */ if (ipre) @@ -3973,50 +4071,71 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, lsl = strlen(psuf); } else lsl = 0; - if (pre) - pre = dupstring(pre); - if (suf) - suf = dupstring(suf); - if (!prpre && (prpre = ppre)) { - singsub(&prpre); - untokenize(prpre); - } else - prpre = dupstring(prpre); - /* Select the group in which to store the matches. */ - if (group) { - endcmgroup(NULL); - begcmgroup(group, (aflags & CAF_NOSORT)); - if (aflags & CAF_NOSORT) - mgroup->flags |= CGF_NOSORT; - } else { - endcmgroup(NULL); - begcmgroup("default", 0); - } - /* Select the set of matches. */ - if (aflags & CAF_ALT) { - l = fmatches; - ai = fainfo; - } else { - l = matches; - ai = ainfo; + if (aflags & CAF_MATCH) { + s = ppre ? ppre : ""; + if (llpl <= lpl && strpfx(lpre, s)) { + llpl = 0; + lpre = ""; + } else if (llpl > lpl && strpfx(s, lpre)) { + llpl -= lpl; + lpre += lpl; + } else + *argv = NULL; + s = psuf ? psuf : ""; + if (llsl <= lsl && strsfx(lsuf, s)) { + llsl = 0; + lsuf = ""; + } else if (llsl > lsl && strsfx(s, lsuf)) { + lsuf[llsl - lsl] = '\0'; + llsl -= lsl; + } else + *argv = NULL; } - if (remf) { - remf = dupstring(remf); - rems = NULL; - } else if (rems) - rems = dupstring(rems); - /* Build the common -P prefix. */ - if (ai->pprefix) { + if (*argv) { if (pre) - ai->pprefix[pfxlen(ai->pprefix, pre)] = '\0'; - else - ai->pprefix[0] = '\0'; - } else - ai->pprefix = dupstring(pre ? pre : ""); - + pre = dupstring(pre); + if (suf) + suf = dupstring(suf); + if (!prpre && (prpre = ppre)) { + singsub(&prpre); + untokenize(prpre); + } else + prpre = dupstring(prpre); + /* Select the group in which to store the matches. */ + if (group) { + endcmgroup(NULL); + begcmgroup(group, (aflags & CAF_NOSORT)); + if (aflags & CAF_NOSORT) + mgroup->flags |= CGF_NOSORT; + } else { + endcmgroup(NULL); + begcmgroup("default", 0); + } + /* Select the set of matches. */ + if (aflags & CAF_ALT) { + l = fmatches; + ai = fainfo; + } else { + l = matches; + ai = ainfo; + } + if (remf) { + remf = dupstring(remf); + rems = NULL; + } else if (rems) + rems = dupstring(rems); + /* Build the common -P prefix. */ + if (ai->pprefix) { + if (pre) + ai->pprefix[pfxlen(ai->pprefix, pre)] = '\0'; + else + ai->pprefix[0] = '\0'; + } else + ai->pprefix = dupstring(pre ? pre : ""); + } /* Walk through the matches given. */ for (; (s = dupstring(*argv)); argv++) { - sl = strlen(s); + sl = pl = strlen(s); lc = NULL; ms = NULL; bpl = brpl; @@ -4042,19 +4161,26 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, } if (aflags & CAF_MATCH) { /* Do the matching. */ - test = (sl >= llpl + llsl && - strpfx(lpre, s) && strsfx(lsuf, s)); - if (!test && mstack && - (ms = comp_match(lpre, lsuf, s, - &lc, (aflags & CAF_QUOTE), - &bpl, &bsl))) - test = 1; - - if (!test) - continue; - pl = sl - llsl; - me = s + sl - llsl; - e = s + llpl; + if (cp) { + if ((test = domatch(s, cp, 0))) + e = me = s + sl; + else + continue; + } else { + test = (sl >= llpl + llsl && + strpfx(lpre, s) && strsfx(lsuf, s)); + if (!test && mstack && + (ms = comp_match(lpre, lsuf, s, + &lc, (aflags & CAF_QUOTE), + &bpl, &bsl))) + test = 1; + + if (!test) + continue; + pl = sl - llsl; + me = s + sl - llsl; + e = s + llpl; + } } else { e = s; me = s + sl; @@ -4072,14 +4198,15 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, if (!ms) { if (sl < ai->minlen) ai->minlen = sl; - if (!mstack && ai->firstm && + if (!cp && !mstack && ai->firstm && (i = sfxlen(ai->firstm->str, s)) < ai->suflen) ai->suflen = i; } t = s; if (ppre) t = dyncat(ppre, t); - if (!ms && mstack) { + lc = NULL; + if (!cp && !ms && (mstack || psuf)) { int bl = ((aflags & CAF_MATCH) ? llpl : 0); Cline *clp = &lc, tlc; char *ss = dupstring(s), *ee = me + (ss - s); @@ -4109,7 +4236,7 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, clp = &(tlc->next); } *clp = NULL; - } else if (mstack) { + } else if (!cp && mstack) { Cline tlc; if (ppre && *ppre) { @@ -4148,7 +4275,7 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, lc = tlc; } else ai->iprefix = ""; - if (!ms && !mstack) { + if (!ms && !mstack && !lc) { if ((aflags & CAF_MATCH) || ai->cpl > pl) ai->cpl = pl; if ((aflags & CAF_MATCH) || ai->csl > lsl) @@ -4164,12 +4291,12 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, ai->count++; /* Finally add the match. */ - cm = (Cmatch) halloc(sizeof(struct cmatch)); + cm = (Cmatch) zhalloc(sizeof(struct cmatch)); cm->ppre = ppre; cm->psuf = psuf; cm->prpre = prpre; cm->str = (ms ? ms : dupstring(s)); - cm->ipre = cm->ripre = ipre; + cm->ipre = cm->ripre = (ipre && *ipre ? ipre : NULL); cm->pre = pre; cm->suf = suf; cm->flags = flags; @@ -4179,7 +4306,7 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, cm->rems = rems; addlinknode(l, cm); - if (expl) { + if (exp) { if (l == matches) expl->count++; else @@ -4188,12 +4315,24 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, if (!ms) { if (!ai->firstm) ai->firstm = cm; - if ((aflags & CAF_MATCH) && !(e - (s + pl))) { - if (!ai->exact) + if (!cp && (aflags & CAF_MATCH) && !(e - (s + pl))) { + if (!ai->exact) { ai->exact = 1; - else { + zsfree(compexactstr); + compexactstr = e = (char *) zalloc(lpl + sl + lsl + 1); + if (ppre) { + strcpy(e, ppre); + e += lpl; + } + strcpy(e, s); + e += sl; + if (psuf) + strcpy(e, psuf); + comp_setunsetptr(CP_EXACTSTR, 0); + } else { ai->exact = 2; cm = NULL; + comp_setunsetptr(0, CP_EXACTSTR); } ai->exactm = cm; } @@ -4208,6 +4347,8 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre, /* We switched back to the current heap, now restore the stack of * matchers. */ mstack = oms; + + return (mnum == nm); } /* This adds a match to the list of matches. The string to add is given * @@ -4252,6 +4393,7 @@ addmatch(char *s, char *t) if (incompfunc) s = dupstring(s); + e = s + sl; if (!addwhat) { test = 1; } else if (addwhat == -1 || addwhat == -5 || addwhat == -6 || @@ -4318,7 +4460,7 @@ addmatch(char *s, char *t) e += s - t; } if (cc) { - tt = (char *)halloc(lppl + lpsl + sl + 1); + tt = (char *)zhalloc(lppl + lpsl + sl + 1); tt[0] = '\0'; if (lppre) strcpy(tt, lppre); @@ -4353,7 +4495,7 @@ addmatch(char *s, char *t) (((addwhat & CC_DISCMDS) && (hn->flags & DISABLED)) || ((addwhat & CC_EXCMDS) && !(hn->flags & DISABLED)))) || ((addwhat & CC_BINDINGS) && !(hn->flags & DISABLED))))) { - if (sl >= rpl + rsl || mstack) { + if (sl >= rpl + rsl || mstack || cp) { if (cp) { test = domatch(s, patcomp, 0); e = s + sl; @@ -4413,7 +4555,7 @@ addmatch(char *s, char *t) t = s; if (lppre) t = dyncat(lppre, t); - if (!ms && mstack) { + if (!ispattern && !ms && mstack) { Cline *clp = &lc, tlc; char *ss = dupstring(s), *ee = e + (ss - s); @@ -4481,7 +4623,7 @@ addmatch(char *s, char *t) ai->count++; /* Allocate and fill the match structure. */ - cm = (Cmatch) halloc(sizeof(struct cmatch)); + cm = (Cmatch) zhalloc(sizeof(struct cmatch)); if (ispattern) { if (lpsuf && *lpsuf && strsfx(lpsuf, s)) { s[sl - lpsl] = '\0'; @@ -4532,11 +4674,29 @@ addmatch(char *s, char *t) /* Do we have an exact match? More than one? */ if (!ispattern && !(e - (s + pl))) { - if (!ai->exact) + if (!ai->exact) { ai->exact = 1; - else { + if (incompfunc) { + int lpl = (cm->ppre ? strlen(cm->ppre) : 0); + int lsl = (cm->psuf ? strlen(cm->psuf) : 0); + + zsfree(compexactstr); + compexactstr = e = (char *) zalloc(lpl + sl + lsl + 1); + if (cm->ppre) { + strcpy(e, cm->ppre); + e += lpl; + } + strcpy(e, s); + e += sl; + if (cm->psuf) + strcpy(e, cm->psuf); + comp_setunsetptr(CP_EXACTSTR, 0); + } + } else { ai->exact = 2; cm = NULL; + if (incompfunc) + comp_setunsetptr(0, CP_EXACTSTR); } ai->exactm = cm; } @@ -4688,7 +4848,6 @@ dumphashtable(HashTable ht, int what) for (i = 0; i < ht->hsize; i++) for (hn = ht->nodes[i]; hn; hn = hn->next) addmatch(hn->nam, (char *) hn); - } /* ScanFunc used by maketildelist() et al. */ @@ -4797,7 +4956,7 @@ gen_matches_files(int dirs, int execs, int all) strcpy(p + o, psuf); /* Do we have to use globbing? */ - if (ispattern || (ns && isset(GLOBCOMPLETE))) { + if (ispattern || (ns && comppatmatch && *comppatmatch)) { /* Yes, so append a `*' if needed. */ if (ns) { int tl = strlen(p); @@ -4847,6 +5006,15 @@ docompletion(char *s, int lst, int incmd) ainfo = fainfo = NULL; matchers = newlinklist(); + useline = (lst != COMP_LIST_COMPLETE); + useexact = (isset(RECEXACT) && usemenu != 1); + uselist = (useline ? + ((isset(AUTOLIST) && !isset(BASHAUTOLIST)) ? + (isset(LISTAMBIGUOUS) ? 3 : 2) : 0) : 1); + zsfree(comppatmatch); + comppatmatch = ztrdup(useglob ? "yes" : ""); + haspattern = 0; + /* Make sure we have the completion list and compctl. */ if (makecomplist(s, incmd, lst)) { /* Error condition: feeeeeeeeeeeeep(). */ @@ -4854,23 +5022,26 @@ docompletion(char *s, int lst, int incmd) clearlist = 1; goto compend; } - if (lst == COMP_LIST_COMPLETE) + if (!useline && uselist) /* All this and the guy only wants to see the list, sigh. */ showinglist = -2; - else { + else if (useline) { /* We have matches. */ if (nmatches > 1) - /* There are more than one match. */ + /* There is more than one match. */ do_ambiguous(); else if (nmatches == 1) { /* Only one match. */ - while (!amatches->mcount) - amatches = amatches->next; - do_single(amatches->matches[0]); + Cmgroup m = amatches; + + while (!m->mcount) + m = m->next; + do_single(m->matches[0]); invalidatelist(); } - } + } else + invalidatelist(); /* Print the explanation strings if needed. */ if (!showinglist && validlist && nmatches != 1) { @@ -4928,33 +5099,47 @@ callcompfunc(char *s, char *fn) int lv = lastval; if ((list = getshfunc(fn)) != &dummy_list) { - LinkList args = newlinklist(); char **p, *tmp; - int aadd = 0, usea = 1, icf = incompfunc, osc = sfcontext; - - addlinknode(args, fn); - + int set, aadd = 0, usea = 1, icf = incompfunc, osc = sfcontext; + Param *ocpms = comppms; + + comppms = (Param *) zalloc(CP_NUM * sizeof(Param)); + + set = -1 & ~(CP_PARAMETER | CP_REDIRECT | CP_QUOTE | CP_QUOTING | + CP_EXACTSTR | (useglob ? 0 : CP_PATMATCH)); zsfree(compcontext); - zsfree(compcommand); - compcommand = ""; - if (inwhat == IN_MATH) { + zsfree(compparameter); + zsfree(compredirect); + compparameter = compredirect = ""; + if (ispar) + compcontext = (ispar == 2 ? "brace_parameter" : "parameter"); + else if (inwhat == IN_MATH) { if (insubscr) { compcontext = "subscript"; - compcommand = varname ? varname : ""; + if (varname) { + compparameter = varname; + set |= CP_PARAMETER; + } } else compcontext = "math"; usea = 0; - } else if (lincmd) - compcontext = (insubscr ? "subscript" : "command"); - else if (linredir) { + } else if (lincmd) { + if (insubscr) { + compcontext = "subscript"; + set |= CP_PARAMETER; + } else + compcontext = "command"; + } else if (linredir) { compcontext = "redirect"; if (rdstr) - compcommand = rdstr; + compredirect = rdstr; + set |= CP_REDIRECT; } else switch (inwhat) { case IN_ENV: - compcontext = "value"; - compcommand = varname; + compcontext = "array_value"; + compparameter = varname; + set |= CP_PARAMETER; if (!clwpos) { clwpos = 1; zsfree(clwords[1]); @@ -4966,61 +5151,141 @@ callcompfunc(char *s, char *fn) compcontext = "condition"; break; default: - if (cmdstr) { - compcontext = "argument"; - compcommand = cmdstr; - } else { + if (cmdstr) + compcontext = "command"; + else { compcontext = "value"; + set |= CP_PARAMETER; if (clwords[0]) - compcommand = clwords[0]; + compparameter = clwords[0]; + aadd = 1; } - aadd = 1; } compcontext = ztrdup(compcontext); - tmp = quotename(compcommand, NULL, NULL, NULL); - untokenize(tmp); - compcommand = ztrdup(tmp); - if (usea && (!aadd || clwords[0])) - for (p = clwords + aadd; *p; p++) { - tmp = dupstring(*p); - untokenize(tmp); - addlinknode(args, tmp); + if (compwords) + freearray(compwords); + if (usea && (!aadd || clwords[0])) { + char **q; + + PERMALLOC { + q = compwords = (char **) + zalloc((clwnum - aadd + 1) * sizeof(char *)); + for (p = clwords + aadd; *p; p++, q++) { + tmp = dupstring(*p); + untokenize(tmp); + *q = ztrdup(tmp); + } + *q = NULL; + } LASTALLOC; + } else + compwords = (char **) zcalloc(sizeof(char *)); + + compparameter = ztrdup(compparameter); + compredirect = ztrdup(compredirect); + zsfree(compquote); + zsfree(compquoting); + if (instring) { + if (instring == 1) { + compquote = ztrdup("\'"); + compquoting = ztrdup("single"); + } else { + compquote = ztrdup("\""); + compquoting = ztrdup("double"); } + set |= CP_QUOTE | CP_QUOTING; + } else if (inbackt) { + compquote = ztrdup("`"); + compquoting = ztrdup("backtick"); + } else { + compquote = ztrdup(""); + compquoting = ztrdup(""); + } + untokenize(s = dupstring(s)); zsfree(compprefix); zsfree(compsuffix); if (unset(COMPLETEINWORD)) { - tmp = quotename(s, NULL, NULL, NULL); - untokenize(tmp); - compprefix = ztrdup(tmp); + compprefix = ztrdup(s); compsuffix = ztrdup(""); } else { char *ss = s + offs, sav; - - tmp = quotename(s, &ss, NULL, NULL); + sav = *ss; *ss = '\0'; - untokenize(tmp); - compprefix = ztrdup(tmp); + compprefix = ztrdup(s); *ss = sav; - untokenize(ss); compsuffix = ztrdup(ss); } zsfree(compiprefix); compiprefix = ztrdup(""); - compcurrent = (usea ? (clwpos + 1 - aadd) : 1); + compcurrent = (usea ? (clwpos + 1 - aadd) : 0); compnmatches = mnum; + + zsfree(complist); + switch (uselist) { + case 0: complist = ""; set &= ~CP_LIST; break; + case 1: complist = "list"; break; + case 2: complist = "autolist"; break; + case 3: complist = "ambiguous"; break; + } + complist = ztrdup(complist); + zsfree(compinsert); + if (useline) { + switch (usemenu) { + case 0: compinsert = "unambiguous"; break; + case 1: compinsert = "menu"; break; + case 2: compinsert = "automenu"; break; + } + } else { + compinsert = ""; + set &= ~CP_INSERT; + } + compinsert = ztrdup(compinsert); + if (useexact) + compexact = ztrdup("accept"); + else { + compexact = ztrdup(""); + set &= ~CP_EXACT; + } incompfunc = 1; startparamscope(); makecompparamsptr(); + comp_setunsetptr(set, ~set); makezleparams(1); sfcontext = SFC_CWIDGET; NEWHEAPS(compheap) { - doshfunc(fn, list, args, 0, 1); + doshfunc(fn, list, NULL, 0, 1); } OLDHEAPS; sfcontext = osc; endparamscope(); lastcmd = 0; incompfunc = icf; + + if (!complist) + uselist = 0; + else if (!strcmp(complist, "list")) + uselist = 1; + else if (!strcmp(complist, "auto") || !strcmp(complist, "autolist")) + uselist = 2; + else if (!strcmp(complist, "ambig") || !strcmp(complist, "ambiguous")) + uselist = 3; + else + uselist = 0; + if (!compinsert) + useline = 0; + else if (!strcmp(compinsert, "unambig") || + !strcmp(compinsert, "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 + useline = usemenu = 0; + useexact = (compexact && !strcmp(compexact, "accept")); + + zfree(comppms, CP_NUM * sizeof(Param)); + comppms = ocpms; } lastval = lv; } @@ -5047,7 +5312,11 @@ makecomplist(char *s, int incmd, int lst) { struct cmlist ms; Cmlist m; - char *os = s; + char *p, *os = s; + + /* Inside $... ? */ + if ((p = check_param(s, 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 @@ -5055,22 +5324,27 @@ makecomplist(char *s, int incmd, int lst) if ((m = cmatcher)) { Cmlist mm, *mp = &mm; + int n; - for (; m; m = m->next) { - *mp = (Cmlist) halloc(sizeof(struct cmlist)); + for (n = 0; m; m = m->next, n++) { + *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; + compmatcher = 1; + compmatchertot = n; + } else + compmatcher = 0; /* Walk through the global matchers. */ for (;;) { bmatchers = NULL; + zsfree(compmatcherstr); if (m) { ms.next = NULL; ms.matcher = m->matcher; @@ -5080,9 +5354,11 @@ makecomplist(char *s, int incmd, int lst) * when building new parts for the string to insert into the * line. */ add_bmatchers(m->matcher); - } else + compmatcherstr = ztrdup(m->str); + } else { mstack = NULL; - + compmatcherstr = ztrdup(""); + } ainfo = (Aminfo) hcalloc(sizeof(struct aminfo)); fainfo = (Aminfo) hcalloc(sizeof(struct aminfo)); @@ -5140,33 +5416,6 @@ makecomplist(char *s, int incmd, int lst) /* This should probably be moved into tokenize(). */ /**/ -static char * -ctokenize(char *p) -{ - char *r = p; - int bslash = 0; - - tokenize(p); - - for (p = r; *p; p++) { - if (*p == '\\') - bslash = 1; - else { - if (*p == '$' || *p == '=' || *p == '{' || *p == '}') { - if (bslash) - p[-1] = Bnull; - else - *p = (*p == '$' ? String : - (*p == '=' ? Equals : - (*p == '{' ? Inbrace : Outbrace))); - } - bslash = 0; - } - } - return r; -} - -/**/ char * comp_str(int *ipl, int *pl, int untok) { @@ -5177,17 +5426,17 @@ comp_str(int *ipl, int *pl, int untok) int lp, ls, lip; if (!untok) { - ctokenize(p); + tokenize(p); remnulargs(p); - ctokenize(s); + tokenize(s); remnulargs(s); - ctokenize(ip); + tokenize(ip); remnulargs(ip); } ls = strlen(s); lip = strlen(ip); lp = strlen(p); - str = halloc(lip + lp + ls + 1); + str = zhalloc(lip + lp + ls + 1); strcpy(str, ip); strcat(str, p); strcat(str, s); @@ -5201,9 +5450,11 @@ comp_str(int *ipl, int *pl, int untok) } /**/ -void +int makecomplistcall(Compctl cc) { + int nm = mnum; + SWITCHHEAPS(compheap) { HEAPALLOC { int ooffs = offs, lip, lp; @@ -5217,6 +5468,8 @@ makecomplistcall(Compctl cc) compnmatches = mnum; } LASTALLOC; } SWITCHBACKHEAPS; + + return (mnum == nm); } /* A simple counter to avoid endless recursion between old and new style * @@ -5243,24 +5496,20 @@ makecomplistctl(int flags) char *os = cmdstr, **ow = clwords, **p, **q; int on = clwnum, op = clwpos; - clwnum = arrlen(pparams) + 1; + clwnum = arrlen(compwords); clwpos = compcurrent - 1; - cmdstr = ztrdup(compcommand); + cmdstr = ztrdup(compwords[0]); clwords = (char **) zalloc((clwnum + 1) * sizeof(char *)); - clwords[0] = ztrdup(cmdstr); - for (p = pparams, q = clwords + 1; *p; p++, q++) { + for (p = compwords, q = clwords; *p; p++, q++) { t = dupstring(*p); - ctokenize(t); + tokenize(t); remnulargs(t); *q = ztrdup(t); } *q = NULL; offs = lip + lp; incompfunc = 2; - ret = makecomplistglobal(str, - (!clwpos && - !strcmp(compcontext, "command")), - COMP_COMPLETE, flags); + ret = makecomplistglobal(str, !clwpos, COMP_COMPLETE, flags); incompfunc = 1; offs = ooffs; compnmatches = mnum; @@ -5499,7 +5748,7 @@ makecomplistext(Compctl occ, char *os, int incmd) Compcond or, cc; Comp comp; int compadd, m = 0, d = 0, t, tt, i, j, a, b; - char *sc, *s, *ss; + char *sc = NULL, *s, *ss; /* This loops over the patterns separated by `-'s. */ for (compc = occ->ext; compc; compc = compc->next) { @@ -5669,7 +5918,7 @@ findnode(LinkList list, void *dat) static void makecomplistflags(Compctl cc, char *s, int incmd, int compadd) { - int t, sf1, sf2, ooffs, um = usemenu, delit, ispar = 0; + int t, sf1, sf2, ooffs, um = usemenu, delit, oaw; char *p, *sd = NULL, *tt, *s1, *s2, *os = dupstring(s); struct cmlist ms; @@ -5678,6 +5927,8 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) if (incompfunc != 1 && findnode(ccstack, cc)) return; + MUSTUSEHEAP("complistflags"); + addlinknode(ccstack, cc); if (incompfunc != 1 && allccs) { @@ -5711,7 +5962,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) if (cc->mask2 & CC_NOSORT) mgroup->flags |= CGF_NOSORT; if (cc->explain) { - expl = (Cexpl) halloc(sizeof(struct cexpl)); + expl = (Cexpl) zhalloc(sizeof(struct cexpl)); expl->count = expl->fcount = 0; } else @@ -5781,79 +6032,16 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) s[suffixll - sl] = '\0'; } /* Do we have one of the special characters `~' and `=' at the beginning? */ - if ((ic = *s) != Tilde && ic != Equals) + if (incompfunc || ((ic = *s) != Tilde && ic != Equals)) ic = 0; /* Check if we have to complete a parameter name... */ - - /* Try to find a `$'. */ - for (p = s + offs; p > s && *p != String; p--); - if (*p == String) { - /* Handle $$'s */ - while (p > s && p[-1] == String) - p--; - while (p[1] == String && p[2] == String) - p += 2; - } - if (*p == String && p[1] != Inpar && p[1] != Inbrack) { - /* This is really a parameter expression (not $(...) or $[...]). */ - char *b = p + 1, *e = b; - int n = 0, br = 1; - - if (*b == Inbrace) { - /* If this is a ${...}, ignore the possible (...) flags. */ - b++, br++; - n = skipparens(Inpar, Outpar, &b); - } - - /* Ignore the stuff before the parameter name. */ - for (; *b; b++) - if (*b != '^' && *b != Hat && - *b != '=' && *b != Equals && - *b != '~' && *b != Tilde) - break; - if (*b == '#' || *b == Pound || *b == '+') - b++; - - e = b; - /* Find the end of the name. */ - if (*e == Quest || *e == Star || *e == String || *e == Qstring || - *e == '?' || *e == '*' || *e == '$' || - *e == '-' || *e == '!' || *e == '@') - e++; - else if (idigit(*e)) - while (idigit(*e)) - e++; - else if (iident(*e)) - while (iident(*e) || - (useglob && (*e == Star || *e == Quest))) - e++; - - /* Now make sure that the cursor is inside the name. */ - if (offs <= e - s && offs >= b - s && n <= 0) { - /* It is. */ - if (br >= 2) - mflags |= CMF_PARBR; - - /* Get the prefix (anything up to the character before the name). */ - lpsuf = dupstring(quotename(e, NULL, NULL, NULL)); - *e = '\0'; - lpsl = strlen(lpsuf); - ripre = dupstring(s); - ripre[b - s] = '\0'; - ipre = dupstring(quotename(ripre, NULL, NULL, NULL)); - untokenize(ipre); - ispar = 1; - /* And adjust wb, we, and offs again. */ - offs -= b - s; - wb = cs - offs; - we = wb + e - b; - s = b; - /* And now make sure that we complete parameter names. */ - cc = &cc_dummy; - cc_dummy.refc = 10000; - cc_dummy.mask = CC_PARAMS | CC_ENVVARS; - } + if (!incompfunc && (p = check_param(s, 1))) { + s = p; + /* And now make sure that we complete parameter names. */ + cc = &cc_dummy; + cc_dummy.refc = 10000; + cc_dummy.mask = CC_PARAMS | CC_ENVVARS; } ooffs = offs; /* If we have to ignore the word, do that. */ @@ -5861,12 +6049,13 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) delit = 1; *s = '\0'; offs = 0; - if (isset(AUTOMENU)) usemenu = 1; + if (isset(AUTOMENU)) + usemenu = 1; } /* Compute line prefix/suffix. */ lpl = offs; - lpre = halloc(lpl + 1); + lpre = zhalloc(lpl + 1); memcpy(lpre, s, lpl); lpre[lpl] = '\0'; lsuf = dupstring(s + offs); @@ -5905,6 +6094,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) if (!s1) s1 = p; } + rsl = strlen(rsuf); for (s2 = NULL, sf2 = t = 0, p = rsuf; *p && (!t || !sf2); p++) if (itok(*p)) t |= sf2 ? 4 : 2; @@ -5917,7 +6107,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) /* But if we were asked not to do glob completion, we never treat the * * thing as a pattern. */ - if (!useglob) + if (!comppatmatch || !*comppatmatch) ispattern = 0; if (ispattern) { @@ -5930,6 +6120,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) } else strcpy(p + rpl, rsuf); patcomp = parsereg(p); + haspattern = 1; } if (!patcomp) { untokenize(rpre); @@ -5963,6 +6154,8 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) line[cs] = 0; lppre = dupstring((char *) (line + wb)); line[cs] = save; + if (brbeg && *brbeg) + strcpy(lppre + brpl, lppre + brpl + strlen(brbeg)); if ((p = strrchr(lppre, '/'))) { p[1] = '\0'; lppl = strlen(lppre); @@ -5979,8 +6172,14 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) char save = line[we]; line[we] = 0; - lpsuf = strchr(dupstring((char *) (line + cs)), '/'); + lpsuf = dupstring((char *) (line + cs)); line[we] = save; + if (brend && *brend) { + char *p = lpsuf + brsl - (cs - wb); + + strcpy(p, p + strlen(brend)); + } + lpsuf = strchr(lpsuf, '/'); lpsl = (lpsuf ? strlen(lpsuf) : 0); } else { @@ -5994,7 +6193,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) /* And the suffix. */ fsuf = dupstrpfx(rsuf, s2 - rsuf); - if (useglob && (ispattern & 2)) { + if (comppatmatch && *comppatmatch && (ispattern & 2)) { int t2; /* We have to use globbing, so compute the pattern from * @@ -6079,10 +6278,10 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) if ((pp = get_user_var(cc->withd))) { dirs = npp = - (char**) halloc(sizeof(char *)*(arrlen(pp)+1)); + (char**) zhalloc(sizeof(char *)*(arrlen(pp)+1)); while (*pp) { pl = strlen(*pp); - tp = (char *) halloc(strlen(*pp) + tl); + tp = (char *) zhalloc(strlen(*pp) + tl); strcpy(tp, *pp); tp[pl] = '/'; strcpy(tp + pl + 1, ppre); @@ -6098,7 +6297,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) char *tp; int pl = strlen(cc->withd); - ta[0] = tp = (char *) halloc(strlen(ppre) + pl + 2); + ta[0] = tp = (char *) zhalloc(strlen(ppre) + pl + 2); strcpy(tp, cc->withd); tp[pl] = '/'; strcpy(tp + pl + 1, ppre); @@ -6270,7 +6469,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) if (isset(AUTOCD) && isset(CDABLEVARS)) dumphashtable(paramtab, -4); } - addwhat = (cc->mask & CC_QUOTEFLAG) ? -2 : CC_QUOTEFLAG; + oaw = addwhat = (cc->mask & CC_QUOTEFLAG) ? -2 : CC_QUOTEFLAG; if (cc->mask & CC_NAMED) /* Add named directories. */ @@ -6278,12 +6477,16 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) if (cc->mask & CC_OPTIONS) /* Add option names. */ dumphashtable(optiontab, addwhat); - if (cc->mask & CC_VARS) + if (cc->mask & CC_VARS) { /* And parameter names. */ dumphashtable(paramtab, -9); - if (cc->mask & CC_BINDINGS) + addwhat = oaw; + } + if (cc->mask & CC_BINDINGS) { /* And zle function names... */ dumphashtable(thingytab, CC_BINDINGS); + addwhat = oaw; + } if (cc->keyvar) { /* This adds things given to the compctl -k flag * * (from a parameter or a list of words). */ @@ -6293,54 +6496,53 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) while (*usr) addmatch(*usr++, NULL); } - if (cc->mask & CC_USERS) + if (cc->mask & CC_USERS) { /* Add user names. */ maketildelist(); + addwhat = oaw; + } + if (cc->widget) + callcompfunc(os, cc->widget); if (cc->func) { - if (cc->func[0] == ' ') - /* Temporary hack for access to new style completione. */ - callcompfunc(os, cc->func + 1); - else { - /* This handles the compctl -K flag. */ - List list; - char **r; - int lv = lastval; + /* This handles the compctl -K flag. */ + List list; + char **r; + int lv = lastval; - /* Get the function. */ - if ((list = getshfunc(cc->func)) != &dummy_list) { - /* We have it, so build a argument list. */ - LinkList args = newlinklist(); - int osc = sfcontext; - - addlinknode(args, cc->func); + /* Get the function. */ + if ((list = getshfunc(cc->func)) != &dummy_list) { + /* We have it, so build a argument list. */ + LinkList args = newlinklist(); + int osc = sfcontext; - if (delit) { - p = dupstrpfx(os, ooffs); - untokenize(p); - addlinknode(args, p); - p = dupstring(os + ooffs); - untokenize(p); - addlinknode(args, p); - } else { - addlinknode(args, lpre); - addlinknode(args, lsuf); - } + addlinknode(args, cc->func); - /* This flag allows us to use read -l and -c. */ - if (incompfunc != 1) - incompctlfunc = 1; - sfcontext = SFC_COMPLETE; - /* Call the function. */ - doshfunc(cc->func, list, args, 0, 1); - sfcontext = osc; - incompctlfunc = 0; - /* And get the result from the reply parameter. */ - if ((r = get_user_var("reply"))) - while (*r) - addmatch(*r++, NULL); + if (delit) { + p = dupstrpfx(os, ooffs); + untokenize(p); + addlinknode(args, p); + p = dupstring(os + ooffs); + untokenize(p); + addlinknode(args, p); + } else { + addlinknode(args, lpre); + addlinknode(args, lsuf); } - lastval = lv; + + /* This flag allows us to use read -l and -c. */ + if (incompfunc != 1) + incompctlfunc = 1; + sfcontext = SFC_COMPLETE; + /* Call the function. */ + doshfunc(cc->func, list, args, 0, 1); + sfcontext = osc; + incompctlfunc = 0; + /* And get the result from the reply parameter. */ + if ((r = get_user_var("reply"))) + while (*r) + addmatch(*r++, NULL); } + lastval = lv; } if (cc->mask & (CC_JOBS | CC_RUNNING | CC_STOPPED)) { /* Get job names. */ @@ -6378,7 +6580,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) * get the words we have to expand. */ zleparse = 1; lexsave(); - tmpbuf = (char *)halloc(strlen(cc->str) + 5); + tmpbuf = (char *)zhalloc(strlen(cc->str) + 5); sprintf(tmpbuf, "foo %s", cc->str); /* KLUDGE! */ inpush(tmpbuf, 0, NULL); strinbeg(); @@ -6456,9 +6658,12 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) if ((t = cc->mask & CC_BUILTINS)) /* Add builtins. */ dumphashtable(builtintab, t | (cc->mask & (CC_DISCMDS|CC_EXCMDS))); - if ((t = cc->mask & CC_EXTCMDS)) + if ((t = cc->mask & CC_EXTCMDS)) { /* Add external commands */ + if (isset(HASHLISTALL)) + cmdnamtab->filltable(cmdnamtab); dumphashtable(cmdnamtab, t | (cc->mask & (CC_DISCMDS|CC_EXCMDS))); + } if ((t = cc->mask & CC_RESWDS)) /* Add reserved words */ dumphashtable(reswdtab, t | (cc->mask & (CC_DISCMDS|CC_EXCMDS))); @@ -6486,7 +6691,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) for (ln = firstnode(matches); ln; ln = nextnode(ln)) { m = (Cmatch) getdata(ln); if (m->ppre) { - char *p = (char *) halloc(strlen(m->ppre) + strlen(m->str) + + char *p = (char *) zhalloc(strlen(m->ppre) + strlen(m->str) + strlen(m->psuf) + 1); sprintf(p, "%s%s%s", m->ppre, m->str, m->psuf); @@ -6654,7 +6859,7 @@ get_user_var(char *nam) if ((val = getsparam(nam))) { arr = (char **)ncalloc(2*sizeof(char *)); - arr[0] = val; + arr[0] = (incompfunc ? dupstring(val) : val); arr[1] = NULL; } return arr; @@ -6763,7 +6968,10 @@ makearray(LinkList l, int s, int *np, int *nlp) if ((*ap)->flags & CMF_NOLIST) nl++; *cp = NULL; - } + } else + for (ap = rp; *ap; ap++) + if ((*ap)->flags & CMF_NOLIST) + nl++; if (np) *np = n; if (nlp) @@ -6795,7 +7003,7 @@ begcmgroup(char *n, int nu) p = p->next; } } - mgroup = (Cmgroup) halloc(sizeof(struct cmgroup)); + mgroup = (Cmgroup) zhalloc(sizeof(struct cmgroup)); mgroup->name = dupstring(n); mgroup->flags = mgroup->lcount = mgroup->mcount = 0; mgroup->matches = NULL; @@ -6858,8 +7066,8 @@ dupmatch(Cmatch m) r->ppre = ztrdup(m->ppre); r->psuf = ztrdup(m->psuf); r->prpre = ztrdup(m->prpre); - r->pre = m->pre; - r->suf = m->suf; + r->pre = ztrdup(m->pre); + r->suf = ztrdup(m->suf); r->flags = m->flags; r->brpl = m->brpl; r->brsl = m->brsl; @@ -6975,6 +7183,8 @@ freematch(Cmatch m) zsfree(m->ripre); zsfree(m->ppre); zsfree(m->psuf); + zsfree(m->pre); + zsfree(m->suf); zsfree(m->prpre); zsfree(m->rems); zsfree(m->remf); @@ -7030,15 +7240,14 @@ freematches(void) static void do_ambiguous(void) { - int p = (usemenu || ispattern), atend = (cs == we); + int p = (usemenu || haspattern), atend = (cs == we); menucmp = 0; /* If we have to insert the first match, call do_single(). This is * * how REC_EXACT takes effect. We effectively turn the ambiguous * * completion into an unambiguous one. */ - if (ainfo && ainfo->exact == 1 && isset(RECEXACT) && !(fromcomp & FC_LINE) && - (usemenu == 0 || unset(AUTOMENU))) { + if (ainfo && ainfo->exact == 1 && useexact && !(fromcomp & FC_LINE)) { do_single(ainfo->exactm); invalidatelist(); return; @@ -7049,7 +7258,7 @@ do_ambiguous(void) * unambiguous prefix. */ lastambig = 1; - if(p) { + if (p) { /* p is set if we are in a position to start using menu completion * * due to one of the menu completion options, or due to the * * menu-complete-word command, or due to using GLOB_COMPLETE which * @@ -7152,7 +7361,7 @@ do_ambiguous(void) * prefix was inserted, return now, bypassing the list-displaying * * code. On the way, invalidate the list and note that we don't * * want to enter an AUTO_MENU imediately. */ - if(isset(LISTAMBIGUOUS) && la) { + if (uselist == 3 && la) { int fc = fromcomp; invalidatelist(); @@ -7165,8 +7374,7 @@ do_ambiguous(void) * if it is needed. */ if (isset(LISTBEEP)) feep(); - if (isset(AUTOLIST) && !isset(BASHAUTOLIST) && !amenu && !showinglist && - smatches >= 2) + if (uselist && usemenu != 2 && !showinglist && smatches >= 2) showinglist = -2; } @@ -7264,7 +7472,7 @@ do_single(Cmatch m) struct stat buf; /* Build the path name. */ - if (ispattern || ic || m->ripre) { + if (haspattern || ic || m->ripre) { int ne = noerrs; noerrs = 1; @@ -7620,14 +7828,14 @@ listmatches(void) char **pp = g->ylist; if ((e = g->expls)) { - if (pnl) { - putc('\n', shout); - pnl = 0; - } while (*e) { if ((*e)->count) { + if (pnl) { + putc('\n', shout); + pnl = 0; + } printfmt((*e)->str, (*e)->count, 1); - putc('\n', shout); + pnl = 1; } e++; } @@ -7670,7 +7878,7 @@ listmatches(void) } } else if (g->lcount) { - int n = g->lcount, nl = (n + ncols - 1) / ncols, nc = nl, i, j, a; + int n = g->lcount, nl = (n + ncols - 1) / ncols, nc = nl, i, j, a = 0; Cmatch *q; if (n && pnl) { @@ -7691,7 +7899,7 @@ listmatches(void) struct stat buf; char *pb; - pb = (char *) halloc((m->prpre ? strlen(m->prpre) : 0) + + pb = (char *) zhalloc((m->prpre ? strlen(m->prpre) : 0) + 3 + strlen(m->str)); sprintf(pb, "%s%s", (m->prpre ? m->prpre : "./"), m->str); diff --git a/Src/Zle/zle_word.c b/Src/Zle/zle_word.c index afd860066..f446d1769 100644 --- a/Src/Zle/zle_word.c +++ b/Src/Zle/zle_word.c @@ -465,7 +465,7 @@ transposewords(void) return; } for (p1 = p2; p1 && iword(line[p1 - 1]); p1--); - pp = temp = (char *)halloc(p4 - p1 + 1); + pp = temp = (char *)zhalloc(p4 - p1 + 1); struncpy(&pp, (char *) line + p3, p4 - p3); struncpy(&pp, (char *) line + p2, p3 - p2); struncpy(&pp, (char *) line + p1, p2 - p1); |