diff options
Diffstat (limited to 'Src')
-rw-r--r-- | Src/.distfiles | 7 | ||||
-rw-r--r-- | Src/Modules/.distfiles | 1 | ||||
-rw-r--r-- | Src/Modules/mapfile.c | 1 | ||||
-rw-r--r-- | Src/Zle/.distfiles | 4 | ||||
-rw-r--r-- | Src/Zle/comp.h | 118 | ||||
-rw-r--r-- | Src/Zle/comp1.c | 18 | ||||
-rw-r--r-- | Src/Zle/comp1.export | 5 | ||||
-rw-r--r-- | Src/Zle/compctl.c | 131 | ||||
-rw-r--r-- | Src/Zle/zle_hist.c | 19 | ||||
-rw-r--r-- | Src/Zle/zle_main.c | 5 | ||||
-rw-r--r-- | Src/Zle/zle_misc.c | 5 | ||||
-rw-r--r-- | Src/Zle/zle_move.c | 2 | ||||
-rw-r--r-- | Src/Zle/zle_refresh.c | 3 | ||||
-rw-r--r-- | Src/Zle/zle_tricky.c | 649 | ||||
-rw-r--r-- | Src/glob.c | 3 | ||||
-rw-r--r-- | Src/hist.c | 6 | ||||
-rw-r--r-- | Src/init.c | 42 | ||||
-rw-r--r-- | Src/loop.c | 13 | ||||
-rw-r--r-- | Src/main.c | 24 | ||||
-rw-r--r-- | Src/options.c | 11 | ||||
-rw-r--r-- | Src/subst.c | 15 | ||||
-rw-r--r-- | Src/zsh.export | 2 | ||||
-rw-r--r-- | Src/zsh.mdd | 3 |
23 files changed, 837 insertions, 250 deletions
diff --git a/Src/.distfiles b/Src/.distfiles index 727c855cc..ce135a00e 100644 --- a/Src/.distfiles +++ b/Src/.distfiles @@ -1,11 +1,12 @@ DISTFILES_SRC=' .cvsignore .distfiles .exrc .indent.pro Makefile.in Makemod.in.in - ansi2knr.c + signames1.awk signames2.awk + ansi2knr.c modentry.c builtin.c compat.c cond.c exec.c glob.c hashtable.c hashtable.h hist.c init.c input.c jobs.c lex.c linklist.c loop.c main.c makepro.awk math.c mem.c mkbltnmlst.sh mkmakemod.sh mkmodindex.sh module.c options.c params.c parse.c prompt.c prototypes.h - signals.c signals.h signames.awk subst.c system.h text.c utils.c - watch.c xmods.conf zsh.h zsh.mdd ztype.h + signals.c signals.h subst.c system.h text.c utils.c + watch.c xmods.conf zsh.h zsh.mdd ztype.h zsh.export ' diff --git a/Src/Modules/.distfiles b/Src/Modules/.distfiles index dbc152fa8..dc851bf9b 100644 --- a/Src/Modules/.distfiles +++ b/Src/Modules/.distfiles @@ -4,6 +4,7 @@ DISTFILES_SRC=' clone.mdd clone.c example.mdd example.c files.mdd files.c + mapfile.mdd mapfile.c parameter.mdd parameter.c stat.mdd stat.c zftp.mdd zftp.c diff --git a/Src/Modules/mapfile.c b/Src/Modules/mapfile.c index e98da7889..41cae80b8 100644 --- a/Src/Modules/mapfile.c +++ b/Src/Modules/mapfile.c @@ -149,6 +149,7 @@ setpmmapfile(Param pm, char *value) * pages. Honestly, I tried it without, and you need both. */ ftruncate(fd, len); + munmap(mmptr, len); } #else /* don't USE_MMAP */ /* can't be bothered to do anything too clever here */ diff --git a/Src/Zle/.distfiles b/Src/Zle/.distfiles index 42c62efe9..9dbf27758 100644 --- a/Src/Zle/.distfiles +++ b/Src/Zle/.distfiles @@ -1,10 +1,10 @@ DISTFILES_SRC=' .cvsignore .distfiles .exrc - comp1.mdd comp.h comp1.c + comp1.mdd comp.h comp1.c comp1.export compctl.mdd compctl.c deltochar.mdd deltochar.c zle.mdd iwidgets.list zle.h zle_bindings.c zle_hist.c zle_keymap.c zle_main.c zle_misc.c zle_move.c zle_params.c zle_refresh.c zle_things.sed zle_thingy.c zle_tricky.c - zle_utils.c zle_vi.c zle_widget.sed zle_word.c + zle_utils.c zle_vi.c zle_widget.sed zle_word.c zle.export ' diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h index caeb4d6c3..bf3ea816f 100644 --- a/Src/Zle/comp.h +++ b/Src/Zle/comp.h @@ -91,6 +91,7 @@ struct compcond { #define CCT_NUMWORDS 10 #define CCT_RANGESTR 11 #define CCT_RANGEPAT 12 +#define CCT_QUOTE 13 /* Contains the real description for compctls */ @@ -107,6 +108,7 @@ struct compctl { char *ylist; /* for -y (user-defined desc. for listing) */ char *prefix, *suffix; /* for -P and -S (prefix, suffix) */ char *subcmd; /* for -l (command name to use) */ + char *substr; /* for -1 (command name to use) */ char *withd; /* for -w (with directory */ char *hpat; /* for -H (history pattern) */ int hnum; /* for -H (number of events to search) */ @@ -209,6 +211,7 @@ struct cmatch { char *prpre; /* path prefix for opendir */ char *pre; /* prefix string from -P */ char *suf; /* suffix string from -S */ + char autoq; /* closing quote to add automatically */ int flags; /* see CMF_* below */ int brpl; /* the place where to put the brace prefix */ int brsl; /* ...and the suffix */ @@ -297,42 +300,79 @@ struct cadata { /* 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_ISUFFIX (1 << 5) -#define CP_COMPSTATE (1 << 6) - -#define CP_REALPARAMS 7 - -#define CP_NMATCHES (1 << 7) -#define CP_MATCHER (1 << 8) -#define CP_MATCHERSTR (1 << 9) -#define CP_MATCHERTOT (1 << 10) -#define CP_CONTEXT (1 << 11) -#define CP_PARAMETER (1 << 12) -#define CP_REDIRECT (1 << 13) -#define CP_QUOTE (1 << 14) -#define CP_QUOTING (1 << 15) -#define CP_RESTORE (1 << 16) -#define CP_LIST (1 << 17) -#define CP_FORCELIST (1 << 18) -#define CP_INSERT (1 << 19) -#define CP_EXACT (1 << 20) -#define CP_EXACTSTR (1 << 21) -#define CP_PATMATCH (1 << 22) -#define CP_PATINSERT (1 << 23) -#define CP_UNAMBIG (1 << 24) -#define CP_UNAMBIGC (1 << 25) -#define CP_LISTMAX (1 << 26) -#define CP_LASTPROMPT (1 << 27) -#define CP_TOEND (1 << 28) -#define CP_OLDLIST (1 << 29) -#define CP_OLDINS (1 << 30) -#define CP_VARED (1 << 31) - -#define CP_NUM 32 - -#define CP_ALLMASK ((unsigned int) 0xffffffff) +#define CPN_WORDS 0 +#define CP_WORDS (1 << CPN_WORDS) +#define CPN_CURRENT 1 +#define CP_CURRENT (1 << CPN_CURRENT) +#define CPN_PREFIX 2 +#define CP_PREFIX (1 << CPN_PREFIX) +#define CPN_SUFFIX 3 +#define CP_SUFFIX (1 << CPN_SUFFIX) +#define CPN_IPREFIX 4 +#define CP_IPREFIX (1 << CPN_IPREFIX) +#define CPN_ISUFFIX 5 +#define CP_ISUFFIX (1 << CPN_ISUFFIX) +#define CPN_QIPREFIX 6 +#define CP_QIPREFIX (1 << CPN_QIPREFIX) +#define CPN_QISUFFIX 7 +#define CP_QISUFFIX (1 << CPN_QISUFFIX) +#define CPN_COMPSTATE 8 +#define CP_COMPSTATE (1 << CPN_COMPSTATE) + +#define CP_REALPARAMS 9 +#define CP_ALLREALS ((unsigned int) 0x1ff) + + +#define CPN_NMATCHES 0 +#define CP_NMATCHES (1 << CPN_NMATCHES) +#define CPN_MATCHER 1 +#define CP_MATCHER (1 << CPN_MATCHER) +#define CPN_MATCHERSTR 2 +#define CP_MATCHERSTR (1 << CPN_MATCHERSTR) +#define CPN_MATCHERTOT 3 +#define CP_MATCHERTOT (1 << CPN_MATCHERTOT) +#define CPN_CONTEXT 4 +#define CP_CONTEXT (1 << CPN_CONTEXT) +#define CPN_PARAMETER 5 +#define CP_PARAMETER (1 << CPN_PARAMETER) +#define CPN_REDIRECT 6 +#define CP_REDIRECT (1 << CPN_REDIRECT) +#define CPN_QUOTE 7 +#define CP_QUOTE (1 << CPN_QUOTE) +#define CPN_QUOTING 8 +#define CP_QUOTING (1 << CPN_QUOTING) +#define CPN_RESTORE 9 +#define CP_RESTORE (1 << CPN_RESTORE) +#define CPN_LIST 10 +#define CP_LIST (1 << CPN_LIST) +#define CPN_FORCELIST 11 +#define CP_FORCELIST (1 << CPN_FORCELIST) +#define CPN_INSERT 12 +#define CP_INSERT (1 << CPN_INSERT) +#define CPN_EXACT 13 +#define CP_EXACT (1 << CPN_EXACT) +#define CPN_EXACTSTR 14 +#define CP_EXACTSTR (1 << CPN_EXACTSTR) +#define CPN_PATMATCH 15 +#define CP_PATMATCH (1 << CPN_PATMATCH) +#define CPN_PATINSERT 16 +#define CP_PATINSERT (1 << CPN_PATINSERT) +#define CPN_UNAMBIG 17 +#define CP_UNAMBIG (1 << CPN_UNAMBIG) +#define CPN_UNAMBIGC 18 +#define CP_UNAMBIGC (1 << CPN_UNAMBIGC) +#define CPN_LISTMAX 19 +#define CP_LISTMAX (1 << CPN_LISTMAX) +#define CPN_LASTPROMPT 20 +#define CP_LASTPROMPT (1 << CPN_LASTPROMPT) +#define CPN_TOEND 21 +#define CP_TOEND (1 << CPN_TOEND) +#define CPN_OLDLIST 22 +#define CP_OLDLIST (1 << CPN_OLDLIST) +#define CPN_OLDINS 23 +#define CP_OLDINS (1 << CPN_OLDINS) +#define CPN_VARED 24 +#define CP_VARED (1 << CPN_VARED) + +#define CP_KEYPARAMS 25 +#define CP_ALLKEYS ((unsigned int) 0xffffff) diff --git a/Src/Zle/comp1.c b/Src/Zle/comp1.c index 071a8e64a..ba8bcc868 100644 --- a/Src/Zle/comp1.c +++ b/Src/Zle/comp1.c @@ -47,7 +47,7 @@ Cmlist cmatcher; void (*makecompparamsptr) _((void)); /**/ -void (*comp_setunsetptr) _((unsigned int, unsigned int)); +void (*comp_setunsetptr) _((int, int, int, int)); /* pointers to functions required by compctl and defined by zle */ @@ -69,6 +69,9 @@ int (*makecomplistctlptr) _((int)); /**/ char *(*unambig_dataptr) _((int *)); +/**/ +int (*set_comp_sepptr) _((void)); + /* Hash table for completion info for commands */ /**/ @@ -112,6 +115,8 @@ char **compwords, *compsuffix, *compiprefix, *compisuffix, + *compqiprefix, + *compqisuffix, *compmatcherstr, *compcontext, *compparameter, @@ -133,7 +138,7 @@ char **compwords, *compvared; /**/ -Param *comppms; +Param *comprpms, *compkpms; /* The function rembslash() came from zle_tricky.c, but is now used * * in compctl.c, too. */ @@ -193,6 +198,7 @@ freecompctl(Compctl cc) zsfree(cc->hpat); zsfree(cc->gname); zsfree(cc->subcmd); + zsfree(cc->substr); if (cc->cond) freecompcond(cc->cond); if (cc->ext) { @@ -440,9 +446,10 @@ setup_comp1(Module m) cc_first.refc = 10000; cc_first.mask = 0; cc_first.mask2 = CC_CCCONT; - comppms = NULL; + comprpms = compkpms = NULL; compwords = NULL; - compprefix = compsuffix = compiprefix = compisuffix = compmatcherstr = + compprefix = compsuffix = compiprefix = compisuffix = + compqiprefix = compqisuffix = compmatcherstr = compcontext = compparameter = compredirect = compquote = compquoting = comprestore = complist = compinsert = compexact = compexactstr = comppatmatch = comppatinsert = @@ -450,6 +457,7 @@ setup_comp1(Module m) compoldlist = compoldins = compvared = NULL; makecompparamsptr = NULL; comp_setunsetptr = NULL; + set_comp_sepptr = NULL; return 0; } @@ -481,6 +489,8 @@ finish_comp1(Module m) zsfree(compsuffix); zsfree(compiprefix); zsfree(compisuffix); + zsfree(compqiprefix); + zsfree(compqisuffix); zsfree(compmatcherstr); zsfree(compcontext); zsfree(compparameter); diff --git a/Src/Zle/comp1.export b/Src/Zle/comp1.export index 2dc285d3a..9b738cc78 100644 --- a/Src/Zle/comp1.export +++ b/Src/Zle/comp1.export @@ -19,6 +19,7 @@ compforcelist compinsert compiprefix compisuffix +compkpms complastprompt complist complistmax @@ -34,9 +35,12 @@ comppatmatch comppms compprefix compredirect +compqiprefix +compqisuffix compquote compquoting comprestore +comprpms comp_setunsetptr comp_strptr compsuffix @@ -56,4 +60,5 @@ makecomplistctlptr makecompparamsptr patcomps rembslash +set_comp_sepptr unambig_dataptr diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index f644dfc38..c5b24714e 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -688,6 +688,22 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef, int cl) *argv = "" - 1; } break; + case 'h': + if (cl) { + zerrnam(name, "illegal option -%c", NULL, **argv); + return 1; + } else if ((*argv)[1]) { + cct.substr = (*argv) + 1; + *argv = "" - 1; + } else if (!argv[1]) { + zwarnnam(name, "command name expected after -%c", NULL, + **argv); + return 1; + } else { + cct.substr = *++argv; + *argv = "" - 1; + } + break; case 'W': if ((*argv)[1]) { cct.withd = (*argv) + 1; @@ -933,6 +949,9 @@ get_xcompctl(char *name, char ***av, Compctl cc, int isdef) t++; /* First get the condition code */ switch (*t) { + case 'q': + c->type = CCT_QUOTE; + break; case 's': c->type = CCT_CURSUF; break; @@ -1017,7 +1036,8 @@ get_xcompctl(char *name, char ***av, Compctl cc, int isdef) c->u.r.a = (int *)zcalloc(n * sizeof(int)); c->u.r.b = (int *)zcalloc(n * sizeof(int)); } else if (c->type == CCT_CURSUF || - c->type == CCT_CURPRE) + c->type == CCT_CURPRE || + c->type == CCT_QUOTE) c->u.s.s = (char **)zcalloc(n * sizeof(char *)); else if (c->type == CCT_RANGESTR || @@ -1059,7 +1079,8 @@ get_xcompctl(char *name, char ***av, Compctl cc, int isdef) c->u.r.b[l] = atoi(tt); } } else if (c->type == CCT_CURSUF || - c->type == CCT_CURPRE) { + c->type == CCT_CURPRE || + c->type == CCT_QUOTE) { /* -s[..] or -S[..]: single string expected */ for (; *t && *t != '\200'; t++) if (*t == '\201') @@ -1218,6 +1239,7 @@ cc_assign(char *name, Compctl *ccptr, Compctl cct, int reass) zsfree(cc->prefix); zsfree(cc->suffix); zsfree(cc->subcmd); + zsfree(cc->substr); zsfree(cc->withd); zsfree(cc->hpat); zsfree(cc->gname); @@ -1239,6 +1261,7 @@ cc_assign(char *name, Compctl *ccptr, Compctl cct, int reass) cc->prefix = ztrdup(cct->prefix); cc->suffix = ztrdup(cct->suffix); cc->subcmd = ztrdup(cct->subcmd); + cc->substr = ztrdup(cct->substr); cc->withd = ztrdup(cct->withd); cc->gname = ztrdup(cct->gname); cc->hpat = ztrdup(cct->hpat); @@ -1366,7 +1389,7 @@ printcompctl(char *s, Compctl cc, int printflags, int ispat) { Compctl cc2; char *css = "fcqovbAIFpEjrzBRGudeNOZUnQmw/"; - char *mss = " pcCwWsSnNmrR"; + char *mss = " pcCwWsSnNmrRq"; unsigned long t = 0x7fffffff; unsigned long flags = cc->mask, flags2 = cc->mask2; unsigned long oldshowmask; @@ -1448,6 +1471,7 @@ printcompctl(char *s, Compctl cc, int printflags, int ispat) printif(cc->glob, 'g'); printif(cc->str, 's'); printif(cc->subcmd, 'l'); + printif(cc->substr, 'h'); printif(cc->withd, 'W'); if (cc->hpat) { printf(" -H %d ", cc->hnum); @@ -1484,6 +1508,7 @@ printcompctl(char *s, Compctl cc, int printflags, int ispat) break; case CCT_CURSUF: case CCT_CURPRE: + case CCT_QUOTE: printqt(c->u.s.s[i]); break; case CCT_RANGESTR: @@ -2067,6 +2092,9 @@ bin_compset(char *name, char **argv, char *ops, int func) case 'P': test = CVT_PREPAT; break; case 's': test = CVT_SUFNUM; break; case 'S': test = CVT_SUFPAT; break; + case 'q': return !(compquote && *compquote && + (*compquote == '\'' || *compquote == '"') && + !set_comp_sepptr()); default: zerrnam(name, "bad option -%c", NULL, argv[0][1]); return 1; @@ -2135,19 +2163,25 @@ bin_compcall(char *name, char **argv, char *ops, int func) * order of the CP_* bits in comp.h */ #define VAL(X) ((void *) (&(X))) -static struct compparam { +struct compparam { char *name; int type; void *var, *set, *get; -} compparams[] = { +}; + +static struct compparam comprparams[] = { { "words", PM_ARRAY, VAL(compwords), NULL, NULL }, { "CURRENT", PM_INTEGER, VAL(compcurrent), NULL, NULL }, { "PREFIX", PM_SCALAR, VAL(compprefix), NULL, NULL }, { "SUFFIX", PM_SCALAR, VAL(compsuffix), NULL, NULL }, { "IPREFIX", PM_SCALAR, VAL(compiprefix), NULL, NULL }, { "ISUFFIX", PM_SCALAR, VAL(compisuffix), NULL, NULL }, - { NULL, 0, NULL, NULL, NULL }, + { "QIPREFIX", PM_SCALAR | PM_READONLY, VAL(compqiprefix), NULL, NULL }, + { "QISUFFIX", PM_SCALAR | PM_READONLY, VAL(compqisuffix), NULL, NULL }, + { NULL, 0, NULL, NULL, NULL } +}; +static struct compparam compkparams[] = { { "nmatches", PM_INTEGER, VAL(compnmatches), NULL, NULL }, { "matcher", PM_INTEGER, VAL(compmatcher), NULL, NULL }, { "matcher_string", PM_SCALAR, VAL(compmatcherstr), NULL, NULL }, @@ -2155,8 +2189,8 @@ static struct compparam { { "context", PM_SCALAR, VAL(compcontext), NULL, NULL }, { "parameter", PM_SCALAR, VAL(compparameter), NULL, NULL }, { "redirect", PM_SCALAR, VAL(compredirect), NULL, NULL }, - { "quote", PM_SCALAR, VAL(compquote), NULL, NULL }, - { "quoting", PM_SCALAR, VAL(compquoting), NULL, NULL }, + { "quote", PM_SCALAR | PM_READONLY, VAL(compquote), NULL, NULL }, + { "quoting", PM_SCALAR | PM_READONLY, VAL(compquoting), NULL, NULL }, { "restore", PM_SCALAR, VAL(comprestore), NULL, NULL }, { "list", PM_SCALAR, VAL(complist), NULL, NULL }, { "force_list", PM_SCALAR, VAL(compforcelist), NULL, NULL }, @@ -2179,11 +2213,9 @@ static struct compparam { #define COMPSTATENAME "compstate" -static struct compparam * -addcompparams(struct compparam *cp) +static void +addcompparams(struct compparam *cp, Param *pp) { - Param *pp = comppms + (cp - compparams); - for (; cp->name; cp++, pp++) { Param pm = createparam(cp->name, cp->type | PM_SPECIAL | PM_REMOVABLE); if (!pm) @@ -2214,31 +2246,29 @@ addcompparams(struct compparam *cp) } pm->unsetfn = compunsetfn; } - return cp; } /**/ void makecompparams(void) { - struct compparam *cp; Param cpm; HashTable tht; - cp = addcompparams(compparams); + addcompparams(comprparams, comprpms); 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; + comprpms[CPN_COMPSTATE] = 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); + cpm->u.hash = paramtab = newparamtable(31, COMPSTATENAME); + addcompparams(compkparams, compkpms); paramtab = tht; } @@ -2262,8 +2292,8 @@ set_compstate(Param pm, HashTable ht) 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++) + for (cp = compkparams, + pp = compkpms; cp->name; cp++, pp++) if (!strcmp(hn->nam, cp->name)) { v.isarr = v.inv = v.a = 0; v.b = -1; @@ -2318,20 +2348,25 @@ compunsetfn(Param pm, int exp) /**/ void -comp_setunset(unsigned int set, unsigned int unset) +comp_setunset(int rset, int runset, int kset, int kunset) { 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; + if (comprpms && (rset >= 0 || runset >= 0)) { + for (p = comprpms; rset || runset; rset >>= 1, runset >>= 1, p++) { + if (rset & 1) + (*p)->flags &= ~PM_UNSET; + if (runset & 1) + (*p)->flags |= PM_UNSET; + } + } + if (comprpms && (kset >= 0 || kunset >= 0)) { + for (p = compkpms; kset || kunset; kset >>= 1, kunset >>= 1, p++) { + if (kset & 1) + (*p)->flags &= ~PM_UNSET; + if (kunset & 1) + (*p)->flags |= PM_UNSET; + } } } @@ -2343,16 +2378,19 @@ comp_wrapper(List list, FuncWrap w, char *name) return 1; else { char *orest, *opre, *osuf, *oipre, *oisuf, **owords; + char *oqipre, *oqisuf, *oq, *oqi; zlong ocur; - unsigned int unset = 0, m, sm; + unsigned int runset = 0, kunset = 0, m, sm; Param *pp; m = CP_WORDS | CP_CURRENT | CP_PREFIX | CP_SUFFIX | - CP_IPREFIX | CP_ISUFFIX | CP_RESTORE; - for (pp = comppms, sm = 1; m; pp++, m >>= 1, sm <<= 1) { + CP_IPREFIX | CP_ISUFFIX | CP_QIPREFIX | CP_QISUFFIX; + for (pp = comprpms, sm = 1; m; pp++, m >>= 1, sm <<= 1) { if ((m & 1) && ((*pp)->flags & PM_UNSET)) - unset |= sm; + runset |= sm; } + if (compkpms[CPN_RESTORE]->flags & PM_UNSET) + kunset = CP_RESTORE; orest = comprestore; comprestore = ztrdup("auto"); ocur = compcurrent; @@ -2360,6 +2398,10 @@ comp_wrapper(List list, FuncWrap w, char *name) osuf = dupstring(compsuffix); oipre = dupstring(compiprefix); oisuf = dupstring(compisuffix); + oqipre = dupstring(compqiprefix); + oqisuf = dupstring(compqisuffix); + oq = dupstring(compquote); + oqi = dupstring(compquoting); HEAPALLOC { owords = arrdup(compwords); @@ -2377,18 +2419,27 @@ comp_wrapper(List list, FuncWrap w, char *name) compiprefix = ztrdup(oipre); zsfree(compisuffix); compisuffix = ztrdup(oisuf); + zsfree(compqiprefix); + compqiprefix = ztrdup(oqipre); + zsfree(compqisuffix); + compqisuffix = ztrdup(oqisuf); + zsfree(compquote); + compquote = ztrdup(oq); + zsfree(compquoting); + compquoting = ztrdup(oqi); freearray(compwords); PERMALLOC { compwords = arrdup(owords); } LASTALLOC; comp_setunset(CP_COMPSTATE | - (~unset & (CP_WORDS | CP_CURRENT | CP_PREFIX | + (~runset & (CP_WORDS | CP_CURRENT | CP_PREFIX | CP_SUFFIX | CP_IPREFIX | CP_ISUFFIX | - CP_RESTORE)), - unset); + CP_QIPREFIX | CP_QISUFFIX)), + (runset & CP_ALLREALS), + (~kunset & CP_RESTORE), (kunset & CP_ALLKEYS)); } else - comp_setunset(CP_COMPSTATE | (~unset & CP_RESTORE), - (unset & CP_RESTORE)); + comp_setunset(CP_COMPSTATE, 0, (~kunset & CP_RESTORE), + (kunset & CP_RESTORE)); zsfree(comprestore); comprestore = orest; diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c index d2b9a3233..2fc55e98c 100644 --- a/Src/Zle/zle_hist.c +++ b/Src/Zle/zle_hist.c @@ -76,7 +76,8 @@ forget_edits(void) void uphistory(void) { - if (!zle_goto_hist(histline, -zmult) && isset(HISTBEEP)) + int nodups = isset(HISTIGNOREDUPS); + if (!zle_goto_hist(histline, -zmult, nodups) && isset(HISTBEEP)) feep(); } @@ -267,7 +268,8 @@ acceptlineanddownhistory(void) void downhistory(void) { - if (!zle_goto_hist(histline, zmult) && isset(HISTBEEP)) + int nodups = isset(HISTIGNOREDUPS); + if (!zle_goto_hist(histline, zmult, nodups) && isset(HISTBEEP)) feep(); } @@ -370,7 +372,7 @@ beginningofbufferorhistory(void) void beginningofhistory(void) { - if (!zle_goto_hist(firsthist(), 0) && isset(HISTBEEP)) + if (!zle_goto_hist(firsthist(), 0, 0) && isset(HISTBEEP)) feep(); } @@ -388,7 +390,7 @@ endofbufferorhistory(void) void endofhistory(void) { - zle_goto_hist(curhist, 0); + zle_goto_hist(curhist, 0, 0); } /**/ @@ -472,9 +474,14 @@ setlocalhistory(void) /**/ int -zle_goto_hist(int ev, int n) +zle_goto_hist(int ev, int n, int skipdups) { Histent he = movehistent(quietgethist(ev), n, hist_skip_flags); + if (skipdups && n) { + n = n < 0? -1 : 1; + while (he && !metadiffer(ZLETEXT(he), (char *) line, ll)) + he = movehistent(he, n, hist_skip_flags); + } if (!he) return 0; zle_setline(he); @@ -906,7 +913,7 @@ vifetchhistory(void) return; } } - if (!zle_goto_hist((zmod.flags & MOD_MULT) ? zmult : curhist, 0) && + if (!zle_goto_hist((zmod.flags & MOD_MULT) ? zmult : curhist, 0, 0) && isset(HISTBEEP)) feep(); } diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index dfb437308..13f3cc402 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -640,7 +640,7 @@ execzlefunc(Thingy func) zsfree(msg); feep(); } else { - int osc = sfcontext; + int osc = sfcontext, osi = movefd(0); startparamscope(); makezleparams(0); @@ -650,6 +650,7 @@ execzlefunc(Thingy func) endparamscope(); lastcmd = 0; r = 1; + redup(osi, 0); } } if (r) { @@ -952,6 +953,7 @@ setup_zle(Module m) makecomplistcallptr = makecomplistcall; makecomplistctlptr = makecomplistctl; unambig_dataptr = unambig_data; + set_comp_sepptr = set_comp_sep; /* initialise the thingies */ init_thingies(); @@ -1027,6 +1029,7 @@ finish_zle(Module m) makecomplistcallptr = NULL; makecomplistctlptr = NULL; unambig_dataptr = NULL; + set_comp_sepptr = NULL; return 0; } diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index 30c31c358..c12c5894b 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -127,6 +127,7 @@ killwholeline(void) for (i = cs; i != ll && line[i] != '\n'; i++); forekill(i - cs + (i != ll), fg); } + clearlist = 1; } /**/ @@ -787,7 +788,9 @@ static char *suffixfunc; void makesuffix(int n) { - suffixlen[256] = suffixlen[' '] = suffixlen['\t'] = suffixlen['\n'] = n; + suffixlen[256] = suffixlen[' '] = suffixlen['\t'] = suffixlen['\n'] = + suffixlen[';'] = suffixlen['|'] = suffixlen['&'] = + suffixlen['<'] = suffixlen['>'] = n; } /* Set up suffix for parameter names: the last n characters are a suffix * diff --git a/Src/Zle/zle_move.c b/Src/Zle/zle_move.c index 7169f5700..aec1c1767 100644 --- a/Src/Zle/zle_move.c +++ b/Src/Zle/zle_move.c @@ -476,7 +476,7 @@ vigotomark(void) feep(); return; } - if (curhist != vimarkline[ch] && !zle_goto_hist(vimarkline[ch], 0)) { + if (curhist != vimarkline[ch] && !zle_goto_hist(vimarkline[ch], 0, 0)) { vimarkline[ch] = 0; feep(); return; diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c index 9742ba501..ac18f52f0 100644 --- a/Src/Zle/zle_refresh.c +++ b/Src/Zle/zle_refresh.c @@ -268,10 +268,13 @@ zrefresh(void) if (clearlist && listshown) { if (tccan(TCCLEAREOD)) { int ovln = vln, ovcs = vcs; + char *nb = nbuf[vln]; + nbuf[vln] = obuf[vln]; moveto(nlnct, 0); tcout(TCCLEAREOD); moveto(ovln, ovcs); + nbuf[vln] = nb; } else { invalidatelist(); moveto(0, 0); diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index 41ea12e77..281fe211d 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -63,6 +63,11 @@ dopestring; #define inststr(X) inststrlen((X),1,-1) +/* The line before completion was tried. */ + +static char *origline; +static int origcs; + /* wb and we hold the beginning/end position of the word we are completing. */ static int wb, we; @@ -177,6 +182,8 @@ static Comp patcomp, filecomp; * prpre -- ppre in expanded form usable for opendir * * ipre,ripre -- the ignored prefix (quoted and unquoted) * * isuf -- the ignored suffix * + * qipre, qisuf-- ingnored quoted string * + * autoq -- quotes to automatically insert * * * * The integer variables hold the lengths of lpre, lsuf, rpre, rsuf, * * fpre, fsuf, lppre, and lpsuf. noreal is non-zero if we have rpre/rsuf. */ @@ -188,6 +195,7 @@ static char *fpre, *fsuf; static char *ipre, *ripre; static char *isuf; static char *qfpre, *qfsuf, *qrpre, *qrsuf, *qlpre, *qlsuf; +static char *qipre, *qisuf, autoq; static int lpl, lsl, rpl, rsl, fpl, fsl, lppl, lpsl; static int noreal; @@ -559,7 +567,7 @@ acceptandmenucomplete(void) /* These are flags saying if we are completing in the command * * position, in a redirection, or in a parameter expansion. */ -static int lincmd, linredir, ispar, linwhat, linarr; +static int lincmd, linredir, ispar, parq, eparq, linwhat, linarr; /* The string for the redirection operator. */ @@ -673,21 +681,24 @@ cmphaswilds(char *str) /* Check if we have to complete a parameter name. */ static char * -check_param(char *s, int set) +check_param(char *s, int set, char **ep) { char *p; + int bq = 0, eq = 0, i; - ispar = 0; + if (!ep) + ispar = parq = eparq = 0; /* Try to find a `$'. */ - for (p = s + offs; p > s && *p != String; p--); - if (*p == String) { + for (p = s + offs; p > s && *p != String && *p != Qstring; p--); + if (*p == String || *p == Qstring) { /* Handle $$'s */ - while (p > s && p[-1] == String) + while (p > s && (p[-1] == String || p[-1] == Qstring)) p--; - while (p[1] == String && p[2] == String) + while ((p[1] == String || p[1] == Qstring) && + (p[2] == String || p[2] == Qstring)) p += 2; } - if (*p == String && p[1] != Inpar && p[1] != Inbrack) { + if ((*p == String || *p == Qstring) && 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; @@ -714,6 +725,12 @@ check_param(char *s, int set) b++; e = b; + if (br) { + while (*e == (ep ? Dnull : '"')) + e++, parq++, bq++; + if (!ep) + b = e; + } /* Find the end of the name. */ if (*e == Quest || *e == Star || *e == String || *e == Qstring || *e == '?' || *e == '*' || *e == '$' || @@ -730,22 +747,44 @@ check_param(char *s, int set) /* Now make sure that the cursor is inside the name. */ if (offs <= e - s && offs >= b - s && n <= 0) { + if (br) { + p = e; + while (*p == (ep ? Dnull : '"')) + p++, parq--, eparq++, eq++; + } /* It is. */ + if (ep) { + *ep = e; + return b; + } /* 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)); + for (i = eq, p = e; i; i--, p++) + *p = '.'; + isuf = quotename(e, NULL); + for (i = eq, p = isuf; i; i--, p++) + *p = '"'; *e = '\0'; - lpsl = strlen(lpsuf); ripre = dupstring(s); ripre[b - s] = '\0'; - ipre = dupstring(quotename(ripre, NULL)); + for (i = bq, p = ripre + (b - s) - 1; i; i--, p--) + *p = '.'; + ipre = quotename(ripre, NULL); + for (i = bq, p = ripre + strlen(ripre) - 1; i; i--, p--) + *p = '"'; + for (i = bq, p = ipre + strlen(ipre) - 1; i; i--, p--) + *p = '"'; untokenize(ipre); } + else + parq = eparq = 0; + /* And adjust wb, we, and offs again. */ offs -= b - s; wb = cs - offs; @@ -817,8 +856,15 @@ docomplete(int lst) ol = NULL; inwhat = IN_NOTHING; qword = NULL; + zsfree(qipre); + qipre = ztrdup(""); + zsfree(qisuf); + qisuf = ztrdup(""); + autoq = '\0'; /* Get the word to complete. */ noerrs = 1; + origline = dupstring((char *) line); + origcs = cs; s = get_comp_string(); DPUTS(wb < 0 || cs < wb || cs > we, "BUG: 0 <= wb <= cs <= we is not true!"); @@ -1152,7 +1198,8 @@ get_comp_string(void) noaliases = isset(COMPLETEALIASES); /* Find out if we are somewhere in a `string', i.e. inside '...', * - * "...", `...`, or ((...)). */ + * "...", `...`, or ((...)). Nowadays this is only used to find * + * out if we are inside `...`. */ for (i = j = k = 0, p = (char *)line; p < (char *)line + cs; p++) if (*p == '`' && !(k & 1)) @@ -1163,28 +1210,9 @@ get_comp_string(void) k++; else if (*p == '\\' && p[1] && !(k & 1)) p++; - instring = (j & 1) ? 2 : (k & 1); inbackt = (i & 1); + instring = 0; addx(&tmp); - if (instring) { - /* Yes, we are in a string. */ - if (!tmp) { - tmp = (char *)line; - line = (unsigned char *) dupstring((char *) line); - } - /* Now remove the quotes. * - * 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 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 * - * yet anyway. */ - for (p = (char *)line; *p; p++) - if (*p == '"' || *p == '\'') - *p = ' '; - } linptr = (char *)line; pushheap(); HEAPALLOC { @@ -1227,6 +1255,16 @@ get_comp_string(void) if (linarr) incmdpos = 0; ctxtlex(); + + if (tok == LEXERR) { + if (!tokstr) + break; + for (j = 0, p = tokstr; *p; p++) + if (*p == Snull || *p == Dnull) + j++; + if (j & 1) + tok = STRING; + } if (tok == ENVARRAY) { linarr = 1; zsfree(varname); @@ -1496,8 +1534,28 @@ get_comp_string(void) } /* This variable will hold the current word in quoted form. */ qword = ztrdup(s); - /* While building the quoted form, we also clean up the command line. */ offs = cs - wb; + if ((p = check_param(s, 0, &tt))) { + for (; *p == Dnull; p++) + *p = '"'; + for (; *tt == Dnull; tt++) + *tt = '"'; + } + if (*s == Snull || *s == Dnull) { + char *q = (*s == Snull ? "'" : "\""), *n = tricat(qipre, q, ""); + int sl = strlen(s); + + instring = (*s == Snull ? 1 : 2); + zsfree(qipre); + qipre = n; + if (sl > 1 && s[sl - 1] == *s) { + n = tricat(q, qisuf, ""); + zsfree(qisuf); + qisuf = n; + } + autoq = *q; + } + /* While building the quoted form, we also clean up the command line. */ for (p = s, tt = qword, i = wb; *p; p++, tt++, i++) if (INULL(*p)) { if (i < cs) @@ -3367,7 +3425,9 @@ add_match_data(int alt, char *str, Cline line, { Cmatch cm; Aminfo ai = (alt ? fainfo : ainfo); - int palen = 0, salen = 0, ipl = 0, pl = 0, ppl = 0, isl = 0, psl = 0; + int palen, salen, qipl, ipl, pl, ppl, qisl, isl, psl; + + palen = salen = qipl = ipl = pl = ppl = isl = psl = 0; DPUTS(!line, "BUG: add_match_data() without cline"); @@ -3377,41 +3437,60 @@ add_match_data(int alt, char *str, Cline line, salen = (psl = strlen(psuf)); if (isuf) salen += (isl = strlen(isuf)); + if (qisuf) + salen += (qisl = strlen(qisuf)); if (salen) { char *asuf = (char *) zhalloc(salen); - Cline pp, p, s; + Cline pp, p, s, sl = NULL; if (psl) memcpy(asuf, psuf, psl); if (isl) memcpy(asuf + psl, isuf, isl); - - s = bld_parts(asuf, salen, salen, NULL); + if (qisl) + memcpy(asuf + psl + isl, qisuf, qisl); for (pp = NULL, p = line; p->next; pp = p, p = p->next); - if (!(p->flags & (CLF_SUF | CLF_MID)) && - !p->llen && !p->wlen && !p->olen) { - if (p->prefix) { - Cline q; + if (salen > qisl) { + s = bld_parts(asuf, salen - qisl, salen - qisl, &sl); - for (q = p->prefix; q->next; q = q->next); - q->next = s->prefix; - s->prefix = p->prefix; - p->prefix = NULL; - } - free_cline(p); - if (pp) - pp->next = s; + if (!(p->flags & (CLF_SUF | CLF_MID)) && + !p->llen && !p->wlen && !p->olen) { + if (p->prefix) { + Cline q; + + for (q = p->prefix; q->next; q = q->next); + q->next = s->prefix; + s->prefix = p->prefix; + p->prefix = NULL; + } + free_cline(p); + if (pp) + pp->next = s; + else + line = s; + } else + p->next = s; + } + if (qisl) { + Cline qsl = bld_parts(asuf + psl + isl, qisl, qisl, NULL); + + qsl->flags |= CLF_SUF; + qsl->suffix = qsl->prefix; + qsl->prefix = NULL; + if (sl) + sl->next = qsl; else - line = s; - } else - p->next = s; + p->next = qsl; + } } /* And the same for the prefix. */ + if (qipre) + palen = (qipl = strlen(qipre)); if (ipre) - palen = (ipl = strlen(ipre)); + palen += (ipl = strlen(ipre)); if (pre) palen += (pl = strlen(pre)); if (ppre) @@ -3421,12 +3500,14 @@ add_match_data(int alt, char *str, Cline line, char *apre = (char *) zhalloc(palen); Cline p, lp; + if (qipl) + memcpy(apre, qipre, qipl); if (ipl) - memcpy(apre, ipre, ipl); + memcpy(apre + qipl, ipre, ipl); if (pl) - memcpy(apre + ipl, pre, pl); + memcpy(apre + qipl + ipl, pre, pl); if (ppl) - memcpy(apre + ipl + pl, ppre, ppl); + memcpy(apre + qipl + ipl + pl, ppre, ppl); p = bld_parts(apre, palen, palen, &lp); if (lp->prefix && !(line->flags & (CLF_SUF | CLF_MID))) { @@ -3461,14 +3542,21 @@ add_match_data(int alt, char *str, Cline line, cm->ppre = (ppre && *ppre ? ppre : NULL); cm->psuf = (psuf && *psuf ? psuf : NULL); cm->prpre = ((flags & CMF_FILE) && prpre && *prpre ? prpre : NULL); - cm->ipre = (ipre && *ipre ? ipre : NULL); + if (qipre && *qipre) + cm->ipre = (ipre && *ipre ? dyncat(qipre, ipre) : dupstring(qipre)); + else + cm->ipre = (ipre && *ipre ? ipre : NULL); cm->ripre = (ripre && *ripre ? ripre : NULL); - cm->isuf = (isuf && *isuf ? isuf : NULL); + if (qisuf && *qisuf) + cm->isuf = (isuf && *isuf ? dyncat(isuf, qisuf) : dupstring(qisuf)); + else + cm->isuf = (isuf && *isuf ? isuf : NULL); cm->pre = pre; cm->suf = suf; cm->flags = flags; cm->brpl = bpl; cm->brsl = bsl; + cm->autoq = (autoq ? autoq : (inbackt ? '`' : '\0')); cm->rems = cm->remf = NULL; addlinknode((alt ? fmatches : matches), cm); @@ -3505,14 +3593,14 @@ add_match_data(int alt, char *str, Cline line, e += sl; if (cm->psuf) strcpy(e, cm->psuf); - comp_setunsetptr(CP_EXACTSTR, 0); + comp_setunsetptr(0, 0, CP_EXACTSTR, 0); } ai->exactm = cm; } else { ai->exact = 2; ai->exactm = NULL; if (incompfunc) - comp_setunsetptr(0, CP_EXACTSTR); + comp_setunsetptr(0, 0, 0, CP_EXACTSTR); } } return cm; @@ -3543,9 +3631,10 @@ int addmatches(Cadata dat, char **argv) { char *s, *ms, *lipre = NULL, *lisuf = NULL, *lpre = NULL, *lsuf = NULL; - char **aign = NULL, **dparr = NULL; + char **aign = NULL, **dparr = NULL, oaq = autoq; + char *oqp = qipre, *oqs = qisuf, qc; int lpl, lsl, pl, sl, bpl, bsl, llpl = 0, llsl = 0, nm = mnum; - int oisalt = 0, isalt, isexact, doadd; + int oisalt = 0, isalt, isexact, doadd, ois = instring, oib = inbackt; Cline lc = NULL; Cmatch cm; struct cmlist mst; @@ -3553,6 +3642,23 @@ addmatches(Cadata dat, char **argv) Comp cp = NULL; LinkList aparl = NULL, oparl = NULL, dparl = NULL; + if (compquote && (qc = *compquote)) { + if (qc == '`') { + instring = 0; + inbackt = 0; + autoq = '\0'; + } else { + instring = (qc == '\'' ? 1 : 2); + inbackt = 0; + autoq = qc; + } + } else { + instring = inbackt = 0; + autoq = '\0'; + } + qipre = ztrdup(compqiprefix ? compqiprefix : ""); + qisuf = ztrdup(compqisuffix ? compqisuffix : ""); + /* Switch back to the heap that was used when the completion widget * was invoked. */ SWITCHHEAPS(compheap) { @@ -3778,6 +3884,14 @@ addmatches(Cadata dat, char **argv) * matchers. */ mstack = oms; + instring = ois; + inbackt = oib; + autoq = oaq; + zsfree(qipre); + zsfree(qisuf); + qipre = oqp; + qisuf = oqs; + return (mnum == nm); } @@ -4222,6 +4336,10 @@ docompletion(char *s, int lst, int incmd) /* 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; feep(); clearlist = 1; goto compend; @@ -4308,23 +4426,25 @@ callcompfunc(char *s, char *fn) if ((list = getshfunc(fn)) != &dummy_list) { char **p, *tmp; int aadd = 0, usea = 1, icf = incompfunc, osc = sfcontext; - unsigned int set; - Param *ocpms = comppms; + unsigned int rset, kset; + Param *ocrpms = comprpms, *ockpms = compkpms; - comppms = (Param *) zalloc(CP_NUM * sizeof(Param)); + comprpms = (Param *) zalloc(CP_REALPARAMS * sizeof(Param)); + compkpms = (Param *) zalloc(CP_KEYPARAMS * sizeof(Param)); - set = CP_ALLMASK & + rset = CP_ALLREALS; + kset = CP_ALLKEYS & ~(CP_PARAMETER | CP_REDIRECT | CP_QUOTE | CP_QUOTING | CP_EXACTSTR | CP_FORCELIST | CP_OLDLIST | CP_OLDINS | (useglob ? 0 : CP_PATMATCH)); zsfree(compvared); if (varedarg) { compvared = ztrdup(varedarg); - set |= CP_VARED; + kset |= CP_VARED; } else compvared = ztrdup(""); if (!*complastprompt) - set &= ~CP_LASTPROMPT; + kset &= ~CP_LASTPROMPT; zsfree(compcontext); zsfree(compparameter); zsfree(compredirect); @@ -4336,7 +4456,7 @@ callcompfunc(char *s, char *fn) compcontext = "subscript"; if (varname) { compparameter = varname; - set |= CP_PARAMETER; + kset |= CP_PARAMETER; } } else compcontext = "math"; @@ -4344,20 +4464,20 @@ callcompfunc(char *s, char *fn) } else if (lincmd) { if (insubscr) { compcontext = "subscript"; - set |= CP_PARAMETER; + kset |= CP_PARAMETER; } else compcontext = "command"; } else if (linredir) { compcontext = "redirect"; if (rdstr) compredirect = rdstr; - set |= CP_REDIRECT; + kset |= CP_REDIRECT; } else switch (linwhat) { case IN_ENV: compcontext = (linarr ? "array_value" : "value"); compparameter = varname; - set |= CP_PARAMETER; + kset |= CP_PARAMETER; if (!clwpos) { clwpos = 1; zsfree(clwords[1]); @@ -4373,7 +4493,7 @@ callcompfunc(char *s, char *fn) compcontext = "command"; else { compcontext = "value"; - set |= CP_PARAMETER; + kset |= CP_PARAMETER; if (clwords[0]) compparameter = clwords[0]; aadd = 1; @@ -4410,10 +4530,11 @@ callcompfunc(char *s, char *fn) compquote = ztrdup("\""); compquoting = ztrdup("double"); } - set |= CP_QUOTE | CP_QUOTING; + kset |= CP_QUOTE | CP_QUOTING; } else if (inbackt) { compquote = ztrdup("`"); compquoting = ztrdup("backtick"); + kset |= CP_QUOTE | CP_QUOTING; } else { compquote = ztrdup(""); compquoting = ztrdup(""); @@ -4444,12 +4565,16 @@ callcompfunc(char *s, char *fn) compiprefix = ztrdup(""); zsfree(compisuffix); compisuffix = ztrdup(""); + zsfree(compqiprefix); + compqiprefix = ztrdup(qipre ? qipre : ""); + zsfree(compqisuffix); + compqisuffix = ztrdup(qisuf ? qisuf : ""); compcurrent = (usea ? (clwpos + 1 - aadd) : 0); compnmatches = mnum; zsfree(complist); switch (uselist) { - case 0: complist = ""; set &= ~CP_LIST; break; + case 0: complist = ""; kset &= ~CP_LIST; break; case 1: complist = "list"; break; case 2: complist = "autolist"; break; case 3: complist = "ambiguous"; break; @@ -4464,14 +4589,14 @@ callcompfunc(char *s, char *fn) } } else { compinsert = ""; - set &= ~CP_INSERT; + kset &= ~CP_INSERT; } compinsert = ztrdup(compinsert); if (useexact) compexact = ztrdup("accept"); else { compexact = ztrdup(""); - set &= ~CP_EXACT; + kset &= ~CP_EXACT; } zsfree(comptoend); if (movetoend == 1) @@ -4485,11 +4610,11 @@ callcompfunc(char *s, char *fn) compoldlist = "shown"; else compoldlist = "yes"; - set |= CP_OLDLIST; + kset |= CP_OLDLIST; if (menucur) { sprintf(buf, "%d", (*menucur)->gnum); compoldins = buf; - set |= CP_OLDINS; + kset |= CP_OLDINS; } else compoldins = ""; } else @@ -4500,7 +4625,8 @@ callcompfunc(char *s, char *fn) incompfunc = 1; startparamscope(); makecompparamsptr(); - comp_setunsetptr(set, ~set); + comp_setunsetptr(rset, (~rset & CP_ALLREALS), + kset, (~kset & CP_ALLKEYS)); makezleparams(1); sfcontext = SFC_CWIDGET; NEWHEAPS(compheap) { @@ -4557,8 +4683,10 @@ callcompfunc(char *s, char *fn) oldins = (hasperm && menucur && compoldins && !strcmp(compoldins, "keep")); - zfree(comppms, CP_NUM * sizeof(Param)); - comppms = ocpms; + zfree(comprpms, CP_REALPARAMS * sizeof(Param)); + zfree(compkpms, CP_KEYPARAMS * sizeof(Param)); + comprpms = ocrpms; + compkpms = ockpms; } lastval = lv; } @@ -4586,10 +4714,10 @@ makecomplist(char *s, int incmd, int lst) struct cmlist ms; Cmlist m; char *p, *os = s; - int onm = nmatches; + int onm = nmatches, osi = movefd(0); /* Inside $... ? */ - if (compfunc && (p = check_param(s, 0))) + if (compfunc && (p = check_param(s, 0, NULL))) os = s = p; /* We build a copy of the list of matchers to use to make sure that this @@ -4676,6 +4804,8 @@ makecomplist(char *s, int incmd, int lst) validlist = 1; amatches = pmatches; + redup(osi, 0); + return 0; } PERMALLOC { @@ -4685,6 +4815,8 @@ makecomplist(char *s, int incmd, int lst) if (nmatches && !errflag) { validlist = 1; + redup(osi, 0); + return 0; } if (!m || !(m = m->next)) @@ -4693,6 +4825,7 @@ makecomplist(char *s, int incmd, int lst) errflag = 0; compmatcher++; } + redup(osi, 0); return 1; } @@ -4760,25 +4893,279 @@ comp_str(int *ipl, int *pl, int untok) /**/ int +set_comp_sep(void) +{ + int lip, lp; + char *s = comp_str(&lip, &lp, 0); + + if (compisuffix) + s = dyncat(s, compisuffix); + + return sep_comp_string("", s, lip + lp, 0); +} + +/**/ +static int +sep_comp_string(char *ss, char *s, int noffs, int rec) +{ + LinkList foo = newlinklist(); + LinkNode n; + int owe = we, owb = wb, ocs = cs, swb, swe, scs, soffs, ne = noerrs; + int sl = strlen(ss), tl, got = 0, i = 0, cur = -1, oll = ll; + int ois = instring, oib = inbackt; + char *tmp, *p, *ns, *ol = (char *) line, sav, oaq = autoq, *qp, *qs; + + /* Put the string in the lexer buffer and call the lexer to * + * get the words we have to expand. */ + zleparse = 1; + addedx = 1; + noerrs = 1; + lexsave(); + tmp = (char *) zhalloc(tl = sl + 3 + strlen(s)); + strcpy(tmp, ss); + tmp[sl] = ' '; + memcpy(tmp + sl + 1, s, noffs); + tmp[(scs = cs = sl + 1 + noffs)] = 'x'; + strcpy(tmp + sl + 2 + noffs, s + noffs); + inpush(dupstrspace(tmp), 0, NULL); + line = (unsigned char *) tmp; + ll = tl - 1; + strinbeg(); + stophist = 2; + noaliases = 1; + do { + ctxtlex(); + if (tok == LEXERR) { + int j; + + if (!tokstr) + break; + for (j = 0, p = tokstr; *p; p++) + if (*p == Snull || *p == Dnull) + j++; + if (j & 1) { + tok = STRING; + if (p > tokstr && p[-1] == ' ') + p[-1] = '\0'; + } + } + if (tok == ENDINPUT || tok == LEXERR) + break; + if (tokstr && *tokstr) + addlinknode(foo, (p = ztrdup(tokstr))); + else + p = NULL; + if (!got && !zleparse) { + DPUTS(!p, "no current word in substr"); + cur = i; + swb = wb - 1; + swe = we - 1; + soffs = cs - swb; + chuck(p + soffs); + ns = dupstring(p); + } + i++; + } while (tok != ENDINPUT && tok != LEXERR); + noaliases = 0; + strinend(); + inpop(); + errflag = zleparse = 0; + noerrs = ne; + lexrestore(); + wb = owb; + we = owe; + cs = ocs; + line = (unsigned char *) ol; + ll = oll; + if (cur < 0 || i < 1) + return 1; + if (*ns == Snull || *ns == Dnull) { + instring = (*ns == Snull ? 1 : 2); + inbackt = 0; + swb++; + if (ns[strlen(ns) - 1] == *ns) + swe--; + autoq = (*ns == Snull ? '\'' : '"'); + } else { + instring = 0; + autoq = '\0'; + } + for (p = ns, i = swb; *p; p++, i++) { + if (INULL(*p)) { + if (i < scs) + soffs--; + if (p[1] || *p != Bnull) { + if (*p == Bnull) { + if (scs == i + 1) + scs++, soffs++; + } else { + if (scs > i--) + scs--; + } + } else { + if (scs == swe) + scs--; + } + chuck(p--); + } + } + sav = s[(i = swb - sl - 1)]; + s[i] = '\0'; + qp = tricat(qipre, s, ""); + s[i] = sav; + if (swe < swb) + swe = swb; + swe -= sl + 1; + sl = strlen(s); + if (swe > sl) + swe = sl, ns[swe - swb + 1] = '\0'; + qs = tricat(s + swe, qisuf, ""); + sl = strlen(ns); + if (soffs > sl) + soffs = sl; + + if (rec) { + char **ow = clwords, *os = cmdstr, *oqp = qipre, *oqs = qisuf; + int olws = clwsize, olwn = clwnum, olwp = clwpos; + int obr = brange, oer = erange, oof = offs; + + clwsize = clwnum = countlinknodes(foo); + clwords = (char **) zalloc((clwnum + 1) * sizeof(char *)); + for (n = firstnode(foo), i = 0; n; incnode(n), i++) { + p = clwords[i] = (char *) getdata(n); + untokenize(p); + } + clwords[i] = NULL; + clwpos = cur; + cmdstr = ztrdup(clwords[0]); + brange = 0; + erange = clwnum - 1; + qipre = qp; + qisuf = qs; + offs = soffs; + makecomplistcmd(ns, !clwpos, CFN_FIRST); + offs = oof; + zsfree(cmdstr); + cmdstr = os; + freearray(clwords); + clwords = ow; + clwsize = olws; + clwnum = olwn; + clwpos = olwp; + brange = obr; + erange = oer; + zsfree(qipre); + qipre = oqp; + zsfree(qisuf); + qisuf = oqs; + } else { + int set = CP_QUOTE | CP_QUOTING, unset = 0; + + zsfree(compquote); + zsfree(compquoting); + if (instring == 2) { + compquote = "\""; + compquoting = "double"; + } else if (instring == 1) { + compquote = "'"; + compquoting = "single"; + } else { + compquote = compquoting = ""; + unset = set; + set = 0; + } + compquote = ztrdup(compquote); + compquoting = ztrdup(compquoting); + comp_setunsetptr(0, 0, set, unset); + + if (unset(COMPLETEINWORD)) { + untokenize(ns); + zsfree(compprefix); + compprefix = ztrdup(ns); + zsfree(compsuffix); + compsuffix = ztrdup(""); + } else { + char *ss, sav; + + ss = ns + soffs; + + sav = *ss; + *ss = '\0'; + untokenize(ns); + compprefix = ztrdup(ns); + *ss = sav; + untokenize(ss); + compsuffix = ztrdup(ss); + } + zsfree(compiprefix); + compiprefix = ztrdup(""); + zsfree(compisuffix); + compisuffix = ztrdup(""); + zsfree(compqiprefix); + compqiprefix = qp; + zsfree(compqisuffix); + compqisuffix = qs; + + freearray(compwords); + i = countlinknodes(foo); + compwords = (char **) zalloc((i + 1) * sizeof(char *)); + for (n = firstnode(foo), i = 0; n; incnode(n), i++) { + p = compwords[i] = (char *) getdata(n); + untokenize(p); + } + compwords[i] = NULL; + } + autoq = oaq; + instring = ois; + inbackt = oib; + + return 0; +} + +/**/ +int makecomplistcall(Compctl cc) { int nm = mnum; SWITCHHEAPS(compheap) { HEAPALLOC { - int ooffs = offs, lip, lp; - char *str = comp_str(&lip, &lp, 0); - char *oisuf = isuf; - + int ooffs = offs, lip, lp, ois = instring, oib = inbackt; + char *str = comp_str(&lip, &lp, 0), qc; + char *oisuf = isuf, *oqp = qipre, *oqs = qisuf, oaq = autoq; + + if (compquote && (qc = *compquote)) { + if (qc == '`') { + instring = 0; + inbackt = 0; + autoq = '\0'; + } else { + instring = (qc == '\'' ? 1 : 2); + inbackt = 0; + autoq = qc; + } + } else { + instring = inbackt = 0; + autoq = '\0'; + } isuf = dupstring(compisuffix); ctokenize(isuf); remnulargs(isuf); + qipre = ztrdup(compqiprefix ? compqiprefix : ""); + qisuf = ztrdup(compqisuffix ? compqisuffix : ""); offs = lip + lp; cc->refc++; ccont = 0; makecomplistor(cc, str, lincmd, lip, 0); offs = ooffs; isuf = oisuf; + zsfree(qipre); + zsfree(qisuf); + qipre = oqp; + qisuf = oqs; + instring = ois; + inbackt = oib; + autoq = oaq; compnmatches = mnum; } LASTALLOC; } SWITCHBACKHEAPS; @@ -4807,10 +5194,26 @@ makecomplistctl(int flags) HEAPALLOC { int ooffs = offs, lip, lp; char *str = comp_str(&lip, &lp, 0), *t; - char *os = cmdstr, **ow = clwords, **p, **q; - int on = clwnum, op = clwpos; - char *oisuf = isuf; - + char *os = cmdstr, **ow = clwords, **p, **q, qc; + int on = clwnum, op = clwpos, ois = instring, oib = inbackt; + char *oisuf = isuf, *oqp = qipre, *oqs = qisuf, oaq = autoq; + + if (compquote && (qc = *compquote)) { + if (qc == '`') { + instring = 0; + inbackt = 0; + autoq = '\0'; + } else { + instring = (qc == '\'' ? 1 : 2); + inbackt = 0; + autoq = qc; + } + } else { + instring = inbackt = 0; + autoq = '\0'; + } + qipre = ztrdup(compqiprefix ? compqiprefix : ""); + qisuf = ztrdup(compqisuffix ? compqisuffix : ""); isuf = dupstring(compisuffix); ctokenize(isuf); remnulargs(isuf); @@ -4830,6 +5233,13 @@ makecomplistctl(int flags) ret = makecomplistglobal(str, !clwpos, COMP_COMPLETE, flags); incompfunc = 1; isuf = oisuf; + zsfree(qipre); + zsfree(qisuf); + qipre = oqp; + qisuf = oqs; + instring = ois; + inbackt = oib; + autoq = oaq; offs = ooffs; compnmatches = mnum; zsfree(cmdstr); @@ -5078,9 +5488,11 @@ makecomplistext(Compctl occ, char *os, int incmd) Compctl compc; Compcond or, cc; Comp comp; - int compadd, m = 0, d = 0, t, tt, i, j, a, b; + int compadd, m = 0, d = 0, t, tt, i, j, a, b, ins; char *sc = NULL, *s, *ss; + ins = (instring ? instring : (inbackt ? 3 : 0)); + /* This loops over the patterns separated by `-'s. */ for (compc = occ->ext; compc; compc = compc->next) { compadd = t = brange = 0; @@ -5096,6 +5508,11 @@ makecomplistext(Compctl occ, char *os, int incmd) brange = 0; erange = clwnum - 1; switch (cc->type) { + case CCT_QUOTE: + t = ((cc->u.s.s[i][0] == 's' && ins == 1) || + (cc->u.s.s[i][0] == 'd' && ins == 2) || + (cc->u.s.s[i][0] == 'b' && ins == 3)); + break; case CCT_POS: tt = clwpos; goto cct_num; @@ -5366,7 +5783,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) ic = 0; /* Check if we have to complete a parameter name... */ - if (!incompfunc && (p = check_param(s, 1))) { + if (!incompfunc && (p = check_param(s, 1, NULL))) { s = p; /* And now make sure that we complete parameter names. */ cc = &cc_dummy; @@ -5917,7 +6334,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) opts[NULLGLOB] = 1; - /* Put the strin in the lexer buffer and call the lexer to * + /* Put the string in the lexer buffer and call the lexer to * * get the words we have to expand. */ zleparse = 1; lexsave(); @@ -6127,6 +6544,8 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) clwords[brange - 1] = ops; ccont = occ; } + if (cc->substr) + sep_comp_string(cc->substr, s, offs, 1); uremnode(ccstack, firstnode(ccstack)); if (cc->matcher) mstack = mstack->next; @@ -6417,6 +6836,7 @@ dupmatch(Cmatch m) r->brsl = m->brsl; r->rems = ztrdup(m->rems); r->remf = ztrdup(m->remf); + r->autoq = m->autoq; return r; } @@ -6938,7 +7358,7 @@ do_ambiguous(void) * completion options. */ do_ambig_menu(); } else if (ainfo) { - int atend = (cs == we), oll = ll, la; + int atend = (cs == we), oll = ll, la, eq, tcs; VARARR(char, oline, ll); menucur = NULL; @@ -6954,7 +7374,13 @@ do_ambiguous(void) /* Now get the unambiguous string and insert it into the line. */ cline_str(ainfo->line, 1, NULL); - + if (eparq) { + tcs = cs; + cs = lastend; + for (eq = eparq; eq; eq--) + inststrlen("\"", 0, 1); + cs = tcs; + } /* la is non-zero if listambiguous may be used. Copying and * comparing the line looks like BFI but it is the easiest * solution. Really. */ @@ -7078,12 +7504,18 @@ do_single(Cmatch m) * so generate one automagically. */ cs = scs; if (m->ripre && (m->flags & CMF_PARBR)) { + int pq; + /*{{*/ /* Completing a parameter in braces. Add a removable `}' suffix. */ + cs += eparq; + for (pq = parq; pq; pq--) + inststrlen("\"", 1, 1); + menuinsc += parq; inststrlen("}", 1, 1); menuinsc++; if (menuwe) - menuend++; + menuend += menuinsc; } if ((m->flags & CMF_FILE) || (m->ripre && isset(AUTOPARAMSLASH))) { /* If we have a filename or we completed a parameter name * @@ -7105,6 +7537,7 @@ do_single(Cmatch m) noerrs = 1; parsestr(p); singsub(&p); + errflag = 0; noerrs = ne; } else { p = (char *) zhalloc(strlen(prpre) + strlen(str) + @@ -7153,24 +7586,30 @@ do_single(Cmatch m) if ((!menucmp || menuwe) && isset(AUTOPARAMKEYS)) suffixlen[','] = suffixlen['}'] = 1; } - } else if (!menucmp && !havesuff && (!(m->flags & CMF_FILE) || !sr)) { + } else if (!havesuff && (!(m->flags & CMF_FILE) || !sr)) { /* If we didn't add a suffix, add a space, unless we are * * doing menu completion or we are completing files and * * the string doesn't name an existing file. */ - inststrlen(" ", 1, 1); - menuinsc++; - if (menuwe) - makesuffix(1); + if (m->autoq && (!m->isuf || m->isuf[0] != m->autoq)) { + inststrlen(&(m->autoq), 1, 1); + menuinsc++; + } + if (!menucmp) { + inststrlen(" ", 1, 1); + menuinsc++; + if (menuwe) + makesuffix(1); + } } if (menuwe && m->ripre && isset(AUTOPARAMKEYS)) - makeparamsuffix(((m->flags & CMF_PARBR) ? 1 : 0), menuinsc); + makeparamsuffix(((m->flags & CMF_PARBR) ? 1 : 0), menuinsc - parq); if ((menucmp && !menuwe) || !movetoend) cs = menuend; } /* This maps the value in v into the range [0,m-1], decrementing v - * if it is non-negative and making negative values cound backwards. */ + * if it is non-negative and making negative values count backwards. */ static int comp_mod(int v, int m) diff --git a/Src/glob.c b/Src/glob.c index 596a05ebf..35aa447de 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -97,6 +97,7 @@ typedef struct stat *Statptr; /* This makes the Ultrix compiler happy. Go figu #define TT_MINS 2 #define TT_WEEKS 3 #define TT_MONTHS 4 +#define TT_SECONDS 5 #define TT_BYTES 0 #define TT_POSIX_BLOCKS 1 @@ -1615,6 +1616,8 @@ glob(LinkList list, LinkNode np) units = TT_WEEKS, ++s; else if (*s == 'M') units = TT_MONTHS, ++s; + else if (*s == 's') + units = TT_SECONDS, ++s; } /* See if it's greater than, equal to, or less than */ if ((range = *s == '+' ? 1 : *s == '-' ? -1 : 0)) diff --git a/Src/hist.c b/Src/hist.c index 6b2c2a653..4d672deab 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -58,8 +58,8 @@ int excs, exlast; * the line does not get added to the list until hend(), if at all. * However, curhist is incremented to reflect the current line anyway * and a temporary history entry is inserted while the user is editing. - * If the resulting line was not added to the list, curhist is - * decremented in hend(). + * If the resulting line was not added to the list, a flag is set so + * that curhist will be decremented in hbegin(). */ /**/ @@ -984,6 +984,8 @@ hend(void) void remhist(void) { + if (hist_ring == &curline) + return; if (!(histactive & HA_ACTIVE)) { if (!(histactive & HA_JUNKED)) { freehistnode((HashNode)hist_ring); diff --git a/Src/init.c b/Src/init.c index 7f1b2153a..f9e6574dd 100644 --- a/Src/init.c +++ b/Src/init.c @@ -550,7 +550,11 @@ setupvals(void) cdpath = mkarray(NULL); manpath = mkarray(NULL); fignore = mkarray(NULL); +#ifdef FUNCTION_DIR + fpath = mkarray(ztrdup(FUNCTION_DIR)); +#else fpath = mkarray(NULL); +#endif mailpath = mkarray(NULL); watch = mkarray(NULL); psvar = mkarray(NULL); @@ -758,33 +762,31 @@ run_init_scripts(void) #ifdef GLOBAL_ZSHENV source(GLOBAL_ZSHENV); #endif - if (isset(RCS)) { - if (unset(PRIVILEGED)) - sourcehome(".zshenv"); - if (islogin) { + if (isset(RCS) && unset(PRIVILEGED)) + sourcehome(".zshenv"); + if (islogin) { #ifdef GLOBAL_ZPROFILE - if (isset(GLOBALRCS)) + if (isset(RCS) && isset(GLOBALRCS)) source(GLOBAL_ZPROFILE); #endif - if (unset(PRIVILEGED)) - sourcehome(".zprofile"); - } - if (interact) { + if (isset(RCS) && unset(PRIVILEGED)) + sourcehome(".zprofile"); + } + if (interact) { #ifdef GLOBAL_ZSHRC - if (isset(GLOBALRCS)) - source(GLOBAL_ZSHRC); + if (isset(RCS) && isset(GLOBALRCS)) + source(GLOBAL_ZSHRC); #endif - if (unset(PRIVILEGED)) - sourcehome(".zshrc"); - } - if (islogin) { + if (isset(RCS) && unset(PRIVILEGED)) + sourcehome(".zshrc"); + } + if (islogin) { #ifdef GLOBAL_ZLOGIN - if (isset(GLOBALRCS)) - source(GLOBAL_ZLOGIN); + if (isset(RCS) && isset(GLOBALRCS)) + source(GLOBAL_ZLOGIN); #endif - if (unset(PRIVILEGED)) - sourcehome(".zlogin"); - } + if (isset(RCS) && unset(PRIVILEGED)) + sourcehome(".zlogin"); } } noerrexit = 0; diff --git a/Src/loop.c b/Src/loop.c index 95ec4832a..070173fa2 100644 --- a/Src/loop.c +++ b/Src/loop.c @@ -138,6 +138,7 @@ execselect(Cmd cmd) LinkNode n; int i; FILE *inp; + size_t more; node = cmd->u.forcmd; args = cmd->args; @@ -154,7 +155,7 @@ execselect(Cmd cmd) lastval = 0; pushheap(); inp = fdopen(dup((SHTTY == -1) ? 0 : SHTTY), "r"); - selectlist(args); + more = selectlist(args, 0); for (;;) { for (;;) { if (empty(bufstack)) { @@ -181,7 +182,7 @@ execselect(Cmd cmd) *s = '\0'; if (*str) break; - selectlist(args); + more = selectlist(args, more); } setsparam("REPLY", ztrdup(str)); i = atoi(str); @@ -217,8 +218,8 @@ execselect(Cmd cmd) /* And this is used to print select lists. */ /**/ -static void -selectlist(LinkList l) +size_t +selectlist(LinkList l, size_t start) { size_t longest = 1, fct, fw = 0, colsz, t0, t1, ct; LinkNode n; @@ -245,7 +246,7 @@ selectlist(LinkList l) else fw = (columns - 1) / fct; colsz = (ct + fct - 1) / fct; - for (t1 = 0; t1 != colsz; t1++) { + for (t1 = start; t1 != colsz && t1 - start < lines - 2; t1++) { ap = arr + t1; do { int t2 = strlen(*ap) + 2, t3; @@ -271,6 +272,8 @@ selectlist(LinkList l) } while (*ap);*/ fflush(stderr); + + return t1 < colsz ? t1 : 0; } /**/ diff --git a/Src/main.c b/Src/main.c index 7ec8f07bd..762e06b90 100644 --- a/Src/main.c +++ b/Src/main.c @@ -45,12 +45,24 @@ main(int argc, char **argv) for (t = argv; *t; *t = metafy(*t, -1, META_ALLOC), t++); - if (!(zsh_name = strrchr(argv[0], '/'))) - zsh_name = argv[0]; - else - zsh_name++; - if (*zsh_name == '-') - zsh_name++; + zsh_name = argv[0]; + do { + char *arg0 = zsh_name; + if (!(zsh_name = strrchr(arg0, '/'))) + zsh_name = arg0; + else + zsh_name++; + if (*zsh_name == '-') + zsh_name++; + if (strcmp(zsh_name, "su") == 0) { + char *sh = zgetenv("SHELL"); + if (sh && *sh && arg0 != sh) + zsh_name = sh; + else + break; + } else + break; + } while (zsh_name); fdtable_size = OPEN_MAX; fdtable = zcalloc(fdtable_size); diff --git a/Src/options.c b/Src/options.c index 5725d27c0..504ccdf7e 100644 --- a/Src/options.c +++ b/Src/options.c @@ -438,17 +438,6 @@ emulate(const char *zsh_name, int fully) { char ch = *zsh_name; - if (!strcmp("su", zsh_name)) { - /* We haven't set up the paramtable yet, so just use zgetenv */ - char *ptr = zgetenv("SHELL"); - if (ptr && *ptr) { - zsh_name = ptr; - if ((ptr = strrchr(zsh_name, '/'))) - zsh_name = ptr+1; - ch = *zsh_name; - } else - ch = 'z'; - } if (ch == 'r') ch = zsh_name[1]; diff --git a/Src/subst.c b/Src/subst.c index 47b59e793..0017b205e 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -976,7 +976,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) zerr("bad substitution", NULL, 0); return NULL; } - } else if (INULL(*s)) + } else if (inbrace && INULL(*s)) s++; else break; @@ -984,7 +984,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) globsubst = globsubst && !qt; idbeg = s; - if ((subexp = (s[-1] && isstring(*s) && + if ((subexp = (inbrace && s[-1] && isstring(*s) && (s[1] == Inbrace || s[1] == Inpar)))) { int sav; int quoted = *s == Qstring; @@ -1168,6 +1168,9 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) } idend = s; + if (inbrace) + while (INULL(*s)) + s++; if ((colf = *s == ':')) s++; @@ -1484,6 +1487,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) val = dupstring(""); isarr = 0; } else if (isarr && aval && aval[0] && !aval[1]) { + /* treat a one-element array as a scalar for purposes of * + * concatenation with surrounding text (some${param}thing) * + * and rc_expand_param handling. Note: mult_isarr (above) * + * propagates the true array type from nested expansions. */ val = aval[0]; isarr = 0; } @@ -1500,8 +1507,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) val = aval[0]; else isarr = 2; - mult_isarr = isarr; } + mult_isarr = isarr; } if (casmod) { if (isarr) { @@ -1665,7 +1672,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) return NULL; xlen = strlen(x); *str = strcatsub(&y, ostr, aptr, x, xlen, fstr, globsubst); - if (qt && !*y && isarr != 2) + if (qt && !*y) y = dupstring(nulstring); setdata(n, (void *) y); } diff --git a/Src/zsh.export b/Src/zsh.export index 7595f1d2e..ef9fca8c6 100644 --- a/Src/zsh.export +++ b/Src/zsh.export @@ -145,6 +145,7 @@ metadiffer metafy metalen mode_to_octal +movefd movehistent mypgrp mypid @@ -194,6 +195,7 @@ quietgethist quotedzputs readoutput realparamtab +redup refreshptr remlpaths remnulargs diff --git a/Src/zsh.mdd b/Src/zsh.mdd index 214f26681..bd9aabc2e 100644 --- a/Src/zsh.mdd +++ b/Src/zsh.mdd @@ -30,6 +30,9 @@ version.h: $(sdir_top)/Config/version.mk zshpaths.h: FORCE Makemod @echo '#define MODULE_DIR "'$(MODDIR)'"' > zshpaths.h.tmp + @if test x$(fndir) != xno; then \ + echo '#define FUNCTION_DIR "'$(fndir)'"' >> zshpaths.h.tmp; \ + fi @if cmp -s zshpaths.h zshpaths.h.tmp; then \ rm -f zshpaths.h.tmp; \ echo "\`zshpaths.h' is up to date." ; \ |