diff options
Diffstat (limited to 'Src')
-rw-r--r-- | Src/Modules/example.c | 39 | ||||
-rw-r--r-- | Src/Modules/example.mdd | 1 | ||||
-rw-r--r-- | Src/Modules/zftp.c | 3 | ||||
-rw-r--r-- | Src/Zle/comp.h | 30 | ||||
-rw-r--r-- | Src/Zle/comp1.c | 8 | ||||
-rw-r--r-- | Src/Zle/comp1.export | 1 | ||||
-rw-r--r-- | Src/Zle/compctl.c | 86 | ||||
-rw-r--r-- | Src/Zle/compctl.mdd | 2 | ||||
-rw-r--r-- | Src/Zle/zle_main.c | 14 | ||||
-rw-r--r-- | Src/Zle/zle_misc.c | 10 | ||||
-rw-r--r-- | Src/Zle/zle_refresh.c | 17 | ||||
-rw-r--r-- | Src/Zle/zle_tricky.c | 306 | ||||
-rw-r--r-- | Src/builtin.c | 14 | ||||
-rw-r--r-- | Src/glob.c | 8 | ||||
-rw-r--r-- | Src/mkbltnmlst.sh | 5 | ||||
-rw-r--r-- | Src/mkmakemod.sh | 3 | ||||
-rw-r--r-- | Src/module.c | 160 | ||||
-rw-r--r-- | Src/params.c | 42 | ||||
-rw-r--r-- | Src/prompt.c | 19 | ||||
-rw-r--r-- | Src/zsh.export | 2 | ||||
-rw-r--r-- | Src/zsh.h | 24 |
21 files changed, 603 insertions, 191 deletions
diff --git a/Src/Modules/example.c b/Src/Modules/example.c index 95545172f..50b8c1626 100644 --- a/Src/Modules/example.c +++ b/Src/Modules/example.c @@ -30,22 +30,45 @@ #include "example.mdh" #include "example.pro" +/* parameters */ + +static long intparam; +static char *strparam; +static char **arrparam; + + /**/ static int bin_example(char *nam, char **args, char *ops, int func) { unsigned char c; + char **oargs = args, **p = arrparam; + long i = 0; printf("Options: "); for (c = 32; ++c < 128;) if (ops[c]) putchar(c); printf("\nArguments:"); - for (; *args; args++) { + for (; *args; i++, args++) { putchar(' '); fputs(*args, stdout); } printf("\nName: %s\n", nam); + printf("\nInteger Parameter: %ld\n", intparam); + printf("String Parameter: %s\n", strparam ? strparam : ""); + printf("Array Parameter:"); + if (p) + while (*p) printf(" %s", *p++); + printf("\n"); + + intparam = i; + zsfree(strparam); + strparam = ztrdup(*oargs ? *oargs : ""); + freearray(arrparam); + PERMALLOC { + arrparam = arrdup(oargs); + } LASTALLOC; return 0; } @@ -103,6 +126,12 @@ static struct conddef cotab[] = { CONDDEF("ex", CONDF_INFIX, cond_i_ex, 0, 0, 0), }; +static struct paramdef patab[] = { + INTPARAMDEF("exint", &intparam), + STRPARAMDEF("exstr", &strparam), + ARRPARAMDEF("exarr", &arrparam), +}; + static struct funcwrap wrapper[] = { WRAPDEF(ex_wrapper), }; @@ -120,8 +149,15 @@ setup_example(Module m) int boot_example(Module m) { + intparam = 42; + strparam = ztrdup("example"); + arrparam = (char **) zalloc(3 * sizeof(char *)); + arrparam[0] = ztrdup("example"); + arrparam[1] = ztrdup("array"); + arrparam[2] = NULL; return !(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) | addconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab)) | + addparamdefs(m->nam, patab, sizeof(patab)/sizeof(*patab)) | !addwrapper(m, wrapper)); } @@ -133,6 +169,7 @@ cleanup_example(Module m) { deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); deleteconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab)); + deleteparamdefs(m->nam, patab, sizeof(patab)/sizeof(*patab)); deletewrapper(m, wrapper); return 0; } diff --git a/Src/Modules/example.mdd b/Src/Modules/example.mdd index f2cd50693..5ed55e6f1 100644 --- a/Src/Modules/example.mdd +++ b/Src/Modules/example.mdd @@ -2,5 +2,6 @@ autobins="example" autoinfixconds="ex" autoprefixconds="len" +autoparams="exint exstr exarr" objects="example.o" diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c index 126aa061e..651a5c952 100644 --- a/Src/Modules/zftp.c +++ b/Src/Modules/zftp.c @@ -71,6 +71,9 @@ #ifdef HAVE_POLL_H # include <poll.h> #endif +#if defined(HAVE_POLL) && !defined(POLLIN) && !defined(POLLNORM) +# undef HAVE_POLL +#endif /* pinch the definition from <netinet/in.h> for deficient headers */ #ifndef INADDR_NONE diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h index c9d6aa859..caeb4d6c3 100644 --- a/Src/Zle/comp.h +++ b/Src/Zle/comp.h @@ -270,6 +270,31 @@ struct cpattern { #define CAF_ALT 4 #define CAF_MATCH 8 +/* Data for compadd and addmatches() */ + +typedef struct cadata *Cadata; + +struct cadata { + char *ipre; /* ignored prefix (-i) */ + char *isuf; /* ignored suffix (-I) */ + char *ppre; /* `path' prefix (-p) */ + char *psuf; /* `path' suffix (-s) */ + char *prpre; /* expanded `path' prefix (-W) */ + char *pre; /* prefix to insert (-P) */ + char *suf; /* suffix to insert (-S) */ + char *group; /* name of the group (-[JV]) */ + char *rems; /* remove suffix on chars... (-r) */ + char *remf; /* function to remove suffix (-R) */ + char *ign; /* ignored suffixes (-F) */ + int flags; /* CMF_* flags (-[fqn]) */ + int aflags; /* CAF_* flags (-[QUa]) */ + Cmatcher match; /* match spec (parsed from -M) */ + char *exp; /* explanation (-X) */ + char *apar; /* array to store matches in (-A) */ + char *opar; /* array to store originals in (-O) */ + char *dpar; /* array to delete non-matches in (-D) */ +}; + /* Flags for special parameters. */ #define CP_WORDS (1 << 0) @@ -306,7 +331,8 @@ struct cpattern { #define CP_TOEND (1 << 28) #define CP_OLDLIST (1 << 29) #define CP_OLDINS (1 << 30) +#define CP_VARED (1 << 31) -#define CP_NUM 31 +#define CP_NUM 32 -#define CP_ALLMASK ((int) ((((unsigned int) 1) << CP_NUM) - 1)) +#define CP_ALLMASK ((unsigned int) 0xffffffff) diff --git a/Src/Zle/comp1.c b/Src/Zle/comp1.c index fe21b1dfc..c51aad297 100644 --- a/Src/Zle/comp1.c +++ b/Src/Zle/comp1.c @@ -52,7 +52,7 @@ void (*comp_setunsetptr) _((int, int)); /* pointers to functions required by compctl and defined by zle */ /**/ -int (*addmatchesptr) _((char *, char *, char *, char *, char *, char *, char *, char *, char *, char *, char *, int, int, Cmatcher, char *, char *, char *, char **)); +int (*addmatchesptr) _((Cadata, char **)); /**/ char *(*comp_strptr) _((int *, int *, int)); @@ -129,7 +129,8 @@ char **compwords, *complastprompt, *comptoend, *compoldlist, - *compoldins; + *compoldins, + *compvared; /**/ Param *comppms; @@ -445,7 +446,7 @@ setup_comp1(Module m) compquoting = comprestore = complist = compinsert = compexact = compexactstr = comppatmatch = comppatinsert = compforcelist = complastprompt = comptoend = - compoldlist = compoldins = NULL; + compoldlist = compoldins = compvared = NULL; makecompparamsptr = NULL; comp_setunsetptr = NULL; return 0; @@ -497,6 +498,7 @@ finish_comp1(Module m) zsfree(comptoend); zsfree(compoldlist); zsfree(compoldins); + zsfree(compvared); return 0; } diff --git a/Src/Zle/comp1.export b/Src/Zle/comp1.export index 4f9fb143d..2dc285d3a 100644 --- a/Src/Zle/comp1.export +++ b/Src/Zle/comp1.export @@ -41,6 +41,7 @@ comp_setunsetptr comp_strptr compsuffix comptoend +compvared compwords freecmatcher freecmlist diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index 28c7cb7b7..a06d558e3 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -1691,17 +1691,22 @@ bin_compgen(char *name, char **argv, char *ops, int func) static int bin_compadd(char *name, char **argv, char *ops, int func) { - char *p, **sp, *e; - char *ipre = NULL, *isuf = 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, *apar = NULL, *opar = NULL; - int f = 0, a = CAF_MATCH, dm; + struct cadata dat; + char *p, **sp, *e, *m = NULL; + int dm; Cmatcher match = NULL; if (incompfunc != 1) { zerrnam(name, "can only be called from completion function", NULL, 0); return 1; } + dat.ipre = dat.isuf = dat.ppre = dat.psuf = dat.prpre = + dat.pre = dat.suf = dat.group = dat.rems = dat.remf = + dat.ign = dat.exp = dat.apar = dat.opar = dat.dpar = NULL; + dat.match = NULL; + dat.flags = 0; + dat.aflags = CAF_MATCH; + for (; *argv && **argv == '-'; argv++) { if (!(*argv)[1]) { argv++; @@ -1713,64 +1718,64 @@ bin_compadd(char *name, char **argv, char *ops, int func) dm = 0; switch (*p) { case 'q': - f |= CMF_REMOVE; + dat.flags |= CMF_REMOVE; break; case 'Q': - a |= CAF_QUOTE; + dat.aflags |= CAF_QUOTE; break; case 'f': - f |= CMF_FILE; + dat.flags |= CMF_FILE; break; case 'F': - sp = &ign; + sp = &(dat.ign); e = "string expected after -%c"; break; case 'n': - f |= CMF_NOLIST; + dat.flags |= CMF_NOLIST; break; case 'U': - a &= ~CAF_MATCH; + dat.aflags &= ~CAF_MATCH; break; case 'P': - sp = ⪯ + sp = &(dat.pre); e = "string expected after -%c"; break; case 'S': - sp = &suf; + sp = &(dat.suf); e = "string expected after -%c"; break; case 'J': - sp = &group; + sp = &(dat.group); e = "group name expected after -%c"; break; case 'V': - if (!group) - a |= CAF_NOSORT; - sp = &group; + if (!dat.group) + dat.aflags |= CAF_NOSORT; + sp = &(dat.group); e = "group name expected after -%c"; break; case 'i': - sp = &ipre; + sp = &(dat.ipre); e = "string expected after -%c"; break; case 'I': - sp = &isuf; + sp = &(dat.isuf); e = "string expected after -%c"; break; case 'p': - sp = &ppre; + sp = &(dat.ppre); e = "string expected after -%c"; break; case 's': - sp = &psuf; + sp = &(dat.psuf); e = "string expected after -%c"; break; case 'W': - sp = &prpre; + sp = &(dat.prpre); e = "string expected after -%c"; break; case 'a': - a |= CAF_ALT; + dat.aflags |= CAF_ALT; break; case 'M': sp = &m; @@ -1778,25 +1783,29 @@ bin_compadd(char *name, char **argv, char *ops, int func) dm = 1; break; case 'X': - sp = &expl; + sp = &(dat.exp); e = "string expected after -%c"; break; case 'r': - f |= CMF_REMOVE; - sp = &rs; + dat.flags |= CMF_REMOVE; + sp = &(dat.rems); e = "string expected after -%c"; break; case 'R': - f |= CMF_REMOVE; - sp = &rf; + dat.flags |= CMF_REMOVE; + sp = &(dat.remf); e = "function name expected after -%c"; break; case 'A': - sp = &apar; + sp = &(dat.apar); e = "parameter name expected after -%c"; break; case 'O': - sp = ⦷ + sp = &(dat.opar); + e = "parameter name expected after -%c"; + break; + case 'D': + sp = &(dat.dpar); e = "parameter name expected after -%c"; break; case '-': @@ -1830,12 +1839,11 @@ bin_compadd(char *name, char **argv, char *ops, int func) if (!*argv) return 1; - match = cpcmatcher(match); - a = addmatchesptr(ipre, isuf, ppre, psuf, prpre, pre, suf, group, - rs, rf, ign, f, a, match, expl, apar, opar, argv); + dat.match = match = cpcmatcher(match); + dm = addmatchesptr(&dat, argv); freecmatcher(match); - return a; + return dm; } #define CVT_RANGENUM 0 @@ -2165,6 +2173,7 @@ static struct compparam { { "to_end", PM_SCALAR, VAL(comptoend), NULL, NULL }, { "old_list", PM_SCALAR, VAL(compoldlist), NULL, NULL }, { "old_insert", PM_SCALAR, VAL(compoldins), NULL, NULL }, + { "vared", PM_SCALAR, VAL(compvared), NULL, NULL }, { NULL, 0, NULL, NULL, NULL } }; @@ -2308,7 +2317,7 @@ compunsetfn(Param pm, int exp) /**/ void -comp_setunset(int set, int unset) +comp_setunset(unsigned int set, unsigned int unset) { Param *p; @@ -2334,11 +2343,11 @@ comp_wrapper(List list, FuncWrap w, char *name) else { char *orest, *opre, *osuf, *oipre, *oisuf, **owords; long ocur; - int unset = 0, m, sm; + unsigned int unset = 0, m, sm; Param *pp; m = CP_WORDS | CP_CURRENT | CP_PREFIX | CP_SUFFIX | - CP_IPREFIX | CP_RESTORE; + CP_IPREFIX | CP_ISUFFIX | CP_RESTORE; for (pp = comppms, sm = 1; m; pp++, m >>= 1, sm <<= 1) { if ((m & 1) && ((*pp)->flags & PM_UNSET)) unset |= sm; @@ -2373,7 +2382,8 @@ comp_wrapper(List list, FuncWrap w, char *name) } LASTALLOC; comp_setunset(CP_COMPSTATE | (~unset & (CP_WORDS | CP_CURRENT | CP_PREFIX | - CP_SUFFIX | CP_IPREFIX | CP_RESTORE)), + CP_SUFFIX | CP_IPREFIX | CP_ISUFFIX | + CP_RESTORE)), unset); } else comp_setunset(CP_COMPSTATE | (~unset & CP_RESTORE), diff --git a/Src/Zle/compctl.mdd b/Src/Zle/compctl.mdd index 113eef27e..e7b2cfb68 100644 --- a/Src/Zle/compctl.mdd +++ b/Src/Zle/compctl.mdd @@ -1,6 +1,6 @@ moddeps="comp1" -autobins="compctl complist compadd compset" +autobins="compctl compgen compadd compset" autoprefixconds="prefix suffix between after" diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 4d9c99f87..a5da84b66 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -413,7 +413,6 @@ zleread(char *lp, char *rp, int flags) baud = getiparam("BAUD"); costmult = (baud) ? 3840000L / baud : 0; - tv.tv_sec = 0; #endif /* ZLE doesn't currently work recursively. This is needed in case a * @@ -523,6 +522,7 @@ zleread(char *lp, char *rp, int flags) #ifdef HAVE_SELECT if (baud && !(lastcmd & ZLE_MENUCMP)) { FD_SET(SHTTY, &foofd); + tv.tv_sec = 0; if ((tv.tv_usec = cost * costmult) > 500000) tv.tv_usec = 500000; if (!kungetct && select(SHTTY+1, (SELECT_ARG_2_T) & foofd, @@ -656,14 +656,18 @@ handleprefixes(void) initmodifier(&zmod); } +/* this exports the argument we are currently vared'iting if != NULL */ + +/**/ +char *varedarg; + /* vared: edit (literally) a parameter value */ /**/ static int bin_vared(char *name, char **args, char *ops, int func) { - char *s; - char *t; + char *s, *t, *ova = varedarg; Value v; Param pm = 0; int create = 0; @@ -753,7 +757,9 @@ bin_vared(char *name, char **args, char *ops, int func) PERMALLOC { pushnode(bufstack, ztrdup(s)); } LASTALLOC; + varedarg = *args; t = (char *) zleread(p1, p2, ops['h'] ? ZLRF_HISTORY : 0); + varedarg = ova; if (!t || errflag) { /* error in editing */ errflag = 0; @@ -927,6 +933,8 @@ setup_zle(Module m) /* initialise the keymap system */ init_keymaps(); + varedarg = NULL; + return 0; } diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index e7f1744d5..30c31c358 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -611,7 +611,7 @@ Thingy executenamedcommand(char *prmt) { Thingy cmd; - int len, l = strlen(prmt); + int len, l = strlen(prmt), ols = listshown; char *ptr; char *okeymap = curkeymapname; @@ -629,6 +629,10 @@ executenamedcommand(char *prmt) if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) { statusline = NULL; selectkeymap(okeymap, 1); + if ((listshown = ols)) + showinglist = -2; + else + clearlist = 1; return NULL; } if(cmd == Th(z_clearscreen)) { @@ -669,6 +673,10 @@ executenamedcommand(char *prmt) unrefthingy(r); statusline = NULL; selectkeymap(okeymap, 1); + if ((listshown = ols)) + showinglist = -2; + else + clearlist = 1; return r; } unrefthingy(r); diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c index 6b0239961..2377b70fa 100644 --- a/Src/Zle/zle_refresh.c +++ b/Src/Zle/zle_refresh.c @@ -96,6 +96,7 @@ static int more_start, /* more text before start of screen? */ olnct, /* previous number of lines */ ovln, /* previous video cursor position line */ lpromptw, rpromptw, /* prompt widths on screen */ + lpromptwof, /* left prompt width with real end position */ lprompth, /* lines taken up by the prompt */ rprompth, /* right prompt height */ vcs, vln, /* video cursor position column & line */ @@ -141,8 +142,14 @@ resetvideo(void) *obuf[ln] = '\0'; } - countprompt(lpromptbuf, &lpromptw, &lprompth); - countprompt(rpromptbuf, &rpromptw, &rprompth); + countprompt(lpromptbuf, &lpromptwof, &lprompth, 1); + countprompt(rpromptbuf, &rpromptw, &rprompth, 0); + if (lpromptwof != winw) + lpromptw = lpromptwof; + else { + lpromptw = 0; + lprompth++; + } if (lpromptw) { memset(nbuf[0], ' ', lpromptw); @@ -271,7 +278,7 @@ zrefresh(void) clearflag = 0; resetneeded = 1; } - listshown = 0; + listshown = showinglist = 0; } clearlist = 0; @@ -327,7 +334,7 @@ zrefresh(void) vcs = 0; else if (!clearflag && lpromptbuf[0]) { zputs(lpromptbuf, shout); - if (lpromptw == 0 && lprompth == 1) + if (lpromptwof == winw) zputs("\n", shout); /* works with both hasam and !hasam */ } if (clearflag) { @@ -947,7 +954,7 @@ tc_rightcurs(int cl) zputc('\r', shout); tc_upcurs(lprompth - 1); zputs(lpromptbuf, shout); - if (lpromptw == 0 && lprompth == 1) + if (lpromptwof == winw) zputs("\n", shout); /* works with both hasam and !hasam */ } i = lpromptw; diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index 92b167cfe..8db571d0b 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -87,6 +87,10 @@ static int usemenu, useglob, useexact, useline, uselist; static int oldlist, oldins; +/* Non-zero if we have to redisplay the list of matches. */ + +static int showagain = 0; + /* The match and group number to insert when starting menucompletion. */ static int insmnum, insgnum, insgroup; @@ -555,7 +559,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; +static int lincmd, linredir, ispar, linwhat, linarr; /* The string for the redirection operator. */ @@ -758,10 +762,14 @@ docomplete(int lst) char *s, *ol; int olst = lst, chl = 0, ne = noerrs, ocs; + if (showagain && validlist) + showinglist = -2; + showagain = 0; + /* If we are doing a menu-completion... */ - if (menucmp && lst != COMP_LIST_EXPAND && compwidget && - compwidget == lastcompwidget) { + if (menucmp && lst != COMP_LIST_EXPAND && + (!compwidget || compwidget == lastcompwidget)) { do_menucmp(lst); return; } @@ -872,7 +880,7 @@ docomplete(int lst) } if (lst == COMP_EXPAND_COMPLETE) do { - /* check if there is a parameter expresiion. */ + /* Check if there is a parameter expression. */ for (; *q && *q != String; q++); if (*q == String && q[1] != Inpar && q[1] != Inbrack) { if (*++q == Inbrace) { @@ -1128,7 +1136,7 @@ unmetafy_line(void) static char * get_comp_string(void) { - int t0, tt0, i, j, k, cp, rd, sl, ocs, ins, oins, inarr, ia, parct; + int t0, tt0, i, j, k, cp, rd, sl, ocs, ins, oins, ia, parct; char *s = NULL, *linptr, *tmp, *p, *tt = NULL; zsfree(brbeg); @@ -1192,7 +1200,7 @@ get_comp_string(void) inpush(dupstrspace((char *) linptr), 0, NULL); strinbeg(); stophist = 2; - i = tt0 = cp = rd = ins = oins = inarr = parct = ia = 0; + i = tt0 = cp = rd = ins = oins = linarr = parct = ia = 0; /* This loop is possibly the wrong way to do this. It goes through * * the previously massaged command line using the lexer. It stores * @@ -1211,11 +1219,11 @@ get_comp_string(void) linredir = (inredir && !ins); oins = ins; /* Get the next token. */ - if (inarr) + if (linarr) incmdpos = 0; ctxtlex(); if (tok == ENVARRAY) { - inarr = 1; + linarr = 1; zsfree(varname); varname = ztrdup(tokstr); } else if (tok == INPAR) @@ -1224,7 +1232,7 @@ get_comp_string(void) if (parct) parct--; else - inarr = 0; + linarr = 0; } if (inredir) rdstr = tokstrings[tok]; @@ -1267,7 +1275,7 @@ get_comp_string(void) clwpos = i; cp = lincmd; rd = linredir; - ia = inarr; + ia = linarr; if (inwhat == IN_NOTHING && incond) inwhat = IN_COND; } else if (linredir) @@ -1515,12 +1523,53 @@ get_comp_string(void) */ for (i = 0, p = s; *p; p++, i++) { /* careful, ${... is not a brace expansion... - * in fact, if it's got a substitution in it's too - * hard for us anyway. sorry. + * we try to get braces after a parameter expansion right, + * but this may fail sometimes. sorry. */ if (*p == String || *p == Qstring) { - tt = NULL; - break; + if (p[1] == Inbrace || p[1] == Inpar || p[1] == Inbrack) { + char *tp = p + 1; + if (skipparens(*tp, (*tp == Inbrace ? Outbrace : + (*tp == Inpar ? Outpar : Outbrack)), + &tp)) { + tt = NULL; + break; + } + i += tp - p; + p = tp; + } else { + char *tp = p + 1; + + for (; *tp == '^' || *tp == Hat || + *tp == '=' || *tp == Equals || + *tp == '~' || *tp == Tilde || + *tp == '#' || *tp == Pound || *tp == '+'; + tp++); + if (*tp == Quest || *tp == Star || *tp == String || + *tp == Qstring || *tp == '?' || *tp == '*' || + *tp == '$' || *tp == '-' || *tp == '!' || + *tp == '@') + p++, i++; + else { + if (idigit(*tp)) + while (idigit(*tp)) + tp++; + else if (iident(*tp)) + while (iident(*tp)) + tp++; + else { + tt = NULL; + break; + } + if (*tp == Inbrace) { + tt = NULL; + break; + } + tp--; + i += tp - p; + p = tp; + } + } } else if (*p == Inbrace) { if (tt) { /* too many inbraces */ @@ -3472,14 +3521,10 @@ set_param(char *name, LinkList l) /**/ int -addmatches(char *ipre, char *isuf, - 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 *apar, char *opar, char **argv) +addmatches(Cadata dat, char **argv) { char *s, *ms, *lipre = NULL, *lisuf = NULL, *lpre = NULL, *lsuf = NULL; - char **aign = NULL; + char **aign = NULL, **dparr; int lpl, lsl, pl, sl, bpl, bsl, llpl = 0, llsl = 0, nm = mnum; int oisalt = 0, isalt, isexact, doadd; Cline lc = NULL; @@ -3487,45 +3532,52 @@ addmatches(char *ipre, char *isuf, struct cmlist mst; Cmlist oms = mstack; Comp cp = NULL; - LinkList aparl = NULL, oparl = NULL; + LinkList aparl = NULL, oparl = NULL, dparl = NULL; /* Switch back to the heap that was used when the completion widget * was invoked. */ SWITCHHEAPS(compheap) { HEAPALLOC { - doadd = (!apar && !opar); - if (apar) + doadd = (!dat->apar && !dat->opar && !dat->dpar); + if (dat->apar) aparl = newlinklist(); - if (opar) + if (dat->opar) oparl = newlinklist(); - if (exp) { + if (dat->dpar) { + if (*(dat->dpar) == '(') + dparr = NULL; + else if ((dparr = get_user_var(dat->dpar)) && !*dparr) + dparr = NULL; + dparl = newlinklist(); + } + if (dat->exp) { expl = (Cexpl) zhalloc(sizeof(struct cexpl)); expl->count = expl->fcount = 0; - expl->str = dupstring(exp); + expl->str = dupstring(dat->exp); } else expl = NULL; /* Store the matcher in our stack of matchers. */ - if (match) { + if (dat->match) { mst.next = mstack; - mst.matcher = match; + mst.matcher = dat->match; mstack = &mst; if (!mnum) - add_bmatchers(match); + add_bmatchers(dat->match); - addlinknode(matchers, match); - match->refc++; + addlinknode(matchers, dat->match); + dat->match->refc++; } if (mnum && (mstack || bmatchers)) update_bmatchers(); /* Get the suffixes to ignore. */ - if (ign) - aign = get_user_var(ign); + if (dat->ign) + aign = get_user_var(dat->ign); /* Get the contents of the completion variables if we have * to perform matching. */ - if (aflags & CAF_MATCH) { + if (dat->aflags & CAF_MATCH) { lipre = dupstring(compiprefix); lisuf = dupstring(compisuffix); lpre = dupstring(compprefix); @@ -3533,8 +3585,8 @@ addmatches(char *ipre, char *isuf, llpl = strlen(lpre); llsl = strlen(lsuf); /* Test if there is an existing -P prefix. */ - if (pre && *pre) { - pl = pfxlen(pre, lpre); + if (dat->pre && *dat->pre) { + pl = pfxlen(dat->pre, lpre); llpl -= pl; lpre += pl; } @@ -3557,79 +3609,76 @@ addmatches(char *ipre, char *isuf, } } /* Now duplicate the strings we have from the command line. */ - if (ipre) - ipre = (lipre ? dyncat(lipre, ipre) : dupstring(ipre)); + if (dat->ipre) + dat->ipre = (lipre ? dyncat(lipre, dat->ipre) : + dupstring(dat->ipre)); else if (lipre) - ipre = lipre; - if (isuf) - isuf = (lisuf ? dyncat(lisuf, isuf) : dupstring(isuf)); + dat->ipre = lipre; + if (dat->isuf) + dat->isuf = (lisuf ? dyncat(lisuf, dat->isuf) : + dupstring(dat->isuf)); else if (lisuf) - isuf = lisuf; - if (ppre) { - ppre = dupstring(ppre); - lpl = strlen(ppre); + dat->isuf = lisuf; + if (dat->ppre) { + dat->ppre = dupstring(dat->ppre); + lpl = strlen(dat->ppre); } else lpl = 0; - if (psuf) { - psuf = dupstring(psuf); - lsl = strlen(psuf); + if (dat->psuf) { + dat->psuf = dupstring(dat->psuf); + lsl = strlen(dat->psuf); } else lsl = 0; - if (aflags & CAF_MATCH) { - s = ppre ? ppre : ""; - if (llpl <= lpl && strpfx(lpre, s)) { - llpl = 0; + if (dat->aflags & CAF_MATCH) { + s = dat->ppre ? dat->ppre : ""; + if (llpl <= lpl && strpfx(lpre, s)) lpre = ""; - } else if (llpl > lpl && strpfx(s, lpre)) { - llpl -= lpl; + else if (llpl > lpl && strpfx(s, lpre)) lpre += lpl; - } else + else *argv = NULL; - s = psuf ? psuf : ""; - if (llsl <= lsl && strsfx(lsuf, s)) { - llsl = 0; + s = dat->psuf ? dat->psuf : ""; + if (llsl <= lsl && strsfx(lsuf, s)) lsuf = ""; - } else if (llsl > lsl && strsfx(s, lsuf)) { + else if (llsl > lsl && strsfx(s, lsuf)) lsuf[llsl - lsl] = '\0'; - llsl -= lsl; - } else + else *argv = NULL; } if (*argv) { - if (pre) - pre = dupstring(pre); - if (suf) - suf = dupstring(suf); - if (!prpre && (prpre = ppre)) { - singsub(&prpre); - untokenize(prpre); + if (dat->pre) + dat->pre = dupstring(dat->pre); + if (dat->suf) + dat->suf = dupstring(dat->suf); + if (!dat->prpre && (dat->prpre = dat->ppre)) { + singsub(&(dat->prpre)); + untokenize(dat->prpre); } else - prpre = dupstring(prpre); + dat->prpre = dupstring(dat->prpre); /* Select the group in which to store the matches. */ - if (group) { + if (dat->group) { endcmgroup(NULL); - begcmgroup(group, (aflags & CAF_NOSORT)); - if (aflags & CAF_NOSORT) + begcmgroup(dat->group, (dat->aflags & CAF_NOSORT)); + if (dat->aflags & CAF_NOSORT) mgroup->flags |= CGF_NOSORT; } else { endcmgroup(NULL); begcmgroup("default", 0); } /* Select the set of matches. */ - oisalt = (aflags & CAF_ALT); + oisalt = (dat->aflags & CAF_ALT); - if (remf) { - remf = dupstring(remf); - rems = NULL; - } else if (rems) - rems = dupstring(rems); + if (dat->remf) { + dat->remf = dupstring(dat->remf); + dat->rems = NULL; + } else if (dat->rems) + dat->rems = dupstring(dat->rems); /* Probably quote the prefix and suffix for testing. */ - if (!cp && (aflags & CAF_MATCH) && !(aflags & CAF_QUOTE)) { + if (!cp && (dat->aflags & CAF_MATCH) && + !(dat->aflags & CAF_QUOTE)) { lpre = quotename(lpre, NULL); lsuf = quotename(lsuf, NULL); - llpl = strlen(lpre); - llsl = strlen(lsuf); } } /* Walk through the matches given. */ @@ -3638,7 +3687,7 @@ addmatches(char *ipre, char *isuf, bpl = brpl; bsl = brsl; isalt = oisalt; - if ((!psuf || !*psuf) && aign) { + if ((!dat->psuf || !*(dat->psuf)) && aign) { /* Do the suffix-test. If the match has one of the * suffixes from ign, we put it in the alternate set. */ char **pt = aign; @@ -3649,39 +3698,52 @@ addmatches(char *ipre, char *isuf, && !strcmp(*pt, s + sl - filell)) isalt = 1; - if (isalt && !doadd) + if (isalt && !doadd) { + if (dparr && !*++dparr) + dparr = NULL; continue; + } } - if (!(aflags & CAF_MATCH)) { + if (!(dat->aflags & CAF_MATCH)) { ms = dupstring(s); lc = bld_parts(ms, sl, -1, NULL); isexact = 0; } else if (!(ms = comp_match(lpre, lsuf, s, cp, &lc, - !(aflags & CAF_QUOTE), - &bpl, &bsl, &isexact))) + !(dat->aflags & CAF_QUOTE), + &bpl, &bsl, &isexact))) { + if (dparr && !*++dparr) + dparr = NULL; continue; - + } if (doadd) { - cm = add_match_data(isalt, ms, lc, ipre, ipre, isuf, pre, - prpre, ppre, psuf, suf, bpl, bsl, - flags, isexact); - cm->rems = rems; - cm->remf = remf; + cm = add_match_data(isalt, ms, lc, dat->ipre, dat->ipre, + dat->isuf, dat->pre, dat->prpre, + dat->ppre, dat->psuf, dat->suf, + bpl, bsl, dat->flags, isexact); + cm->rems = dat->rems; + cm->remf = dat->remf; } else { - if (apar) + if (dat->apar) addlinknode(aparl, ms); - if (opar) + if (dat->opar) addlinknode(oparl, s); + if (dat->dpar && dparr) { + addlinknode(dparl, *dparr); + if (!*++dparr) + dparr = NULL; + } free_cline(lc); } } compnmatches = mnum; - if (exp) + if (dat->exp) addexpl(); - if (apar) - set_param(apar, aparl); - if (opar) - set_param(opar, oparl); + if (dat->apar) + set_param(dat->apar, aparl); + if (dat->opar) + set_param(dat->opar, oparl); + if (dat->dpar) + set_param(dat->dpar, dparl); } LASTALLOC; } SWITCHBACKHEAPS; @@ -4128,6 +4190,7 @@ docompletion(char *s, int lst, int incmd) (unset(ALWAYSLASTPROMPT) && zmult != 1)) ? "yes" : ""); movetoend = ((cs == we || isset(ALWAYSTOEND)) ? 2 : 1); + showinglist = 0; /* Make sure we have the completion list and compctl. */ if (makecomplist(s, incmd, lst)) { @@ -4217,14 +4280,22 @@ callcompfunc(char *s, char *fn) if ((list = getshfunc(fn)) != &dummy_list) { char **p, *tmp; - int set, aadd = 0, usea = 1, icf = incompfunc, osc = sfcontext; + int aadd = 0, usea = 1, icf = incompfunc, osc = sfcontext; + unsigned int set; Param *ocpms = comppms; comppms = (Param *) zalloc(CP_NUM * sizeof(Param)); - set = -1 & ~(CP_PARAMETER | CP_REDIRECT | CP_QUOTE | CP_QUOTING | - CP_EXACTSTR | CP_FORCELIST | CP_OLDLIST | CP_OLDINS | - (useglob ? 0 : CP_PATMATCH)); + set = CP_ALLMASK & + ~(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; + } else + compvared = ztrdup(""); if (!*complastprompt) set &= ~CP_LASTPROMPT; zsfree(compcontext); @@ -4257,7 +4328,7 @@ callcompfunc(char *s, char *fn) } else switch (linwhat) { case IN_ENV: - compcontext = "array_value"; + compcontext = (linarr ? "array_value" : "value"); compparameter = varname; set |= CP_PARAMETER; if (!clwpos) { @@ -4551,6 +4622,7 @@ makecomplist(char *s, int incmd, int lst) insmnum = insgnum = 1; insgroup = oldlist = oldins = 0; begcmgroup("default", 0); + menucmp = 0; ccused = newlinklist(); ccstack = newlinklist(); @@ -6717,11 +6789,13 @@ unambig_data(int *cp) return scache; } -/* Insert the given match. This returns the number of characters inserted.*/ +/* Insert the given match. This returns the number of characters inserted. + * scs is used to return the position where a automatically created suffix + * has to be inserted. */ /**/ static int -instmatch(Cmatch m) +instmatch(Cmatch m, int *scs) { int l, r = 0, ocs, a = cs; @@ -6771,6 +6845,7 @@ instmatch(Cmatch m) } else brscs = -1; /* -S suffix */ + *scs = cs; if (m->suf) { inststrlen(m->suf, 1, (l = strlen(m->suf))); r += l; @@ -6842,13 +6917,13 @@ do_ambiguous(void) /* If REC_EXACT and AUTO_MENU are set and what we inserted is an * * exact match, we want menu completion the next time round * - * so we set fromcomp,to ensure that the word on the line is not * + * so we set fromcomp, to ensure that the word on the line is not * * taken as an exact match. Also we remember if we just moved the * * cursor into the word. */ fromcomp = ((isset(AUTOMENU) ? FC_LINE : 0) | ((atend && cs != lastend) ? FC_INWORD : 0)); - /* Probably move the cursor to then end. */ + /* Probably move the cursor to the end. */ if (movetoend == 3) cs = lastend; @@ -6907,7 +6982,7 @@ ztat(char *nam, struct stat *buf, int ls) static void do_single(Cmatch m) { - int l, sr = 0; + int l, sr = 0, scs; int havesuff = 0; char *str = m->str, *ppre = m->ppre, *psuf = m->psuf, *prpre = m->prpre; @@ -6937,7 +7012,7 @@ do_single(Cmatch m) foredel(l); /* And then we insert the new string. */ - menulen = instmatch(m); + menulen = instmatch(m, &scs); menuend = cs; cs = menupos + menulen; @@ -6956,6 +7031,7 @@ do_single(Cmatch m) } else { /* There is no user-specified suffix, * * so generate one automagically. */ + cs = scs; if (m->ripre && (m->flags & CMF_PARBR)) { /*{{*/ /* Completing a parameter in braces. Add a removable `}' suffix. */ @@ -7006,6 +7082,8 @@ do_single(Cmatch m) } } } + if (!menuinsc) + cs = menupos + menulen; } /* If completing in a brace expansion... */ if (brbeg) { @@ -7018,7 +7096,7 @@ do_single(Cmatch m) } else if (!menucmp) { /*{{*/ /* Otherwise, add a `,' suffix, and let `}' remove it. */ - cs = menuend; + cs = scs; havesuff = 1; inststrlen(",", 1, 1); menuinsc++; @@ -7492,7 +7570,12 @@ listlist(LinkList l) struct cmgroup dg; Cmgroup am = amatches; int vl = validlist, sm = smatches; + char *oclp = complastprompt; + + if (listshown) + showagain = 1; + complastprompt = ((zmult == 1) == !!isset(ALWAYSLASTPROMPT) ? "yes" : NULL); smatches = 1; validlist = 1; amatches = &dg; @@ -7503,6 +7586,7 @@ listlist(LinkList l) amatches = am; validlist = vl; smatches = sm; + complastprompt = oclp; } /* Expand the history references. */ diff --git a/Src/builtin.c b/Src/builtin.c index c042537f4..9ffcad1b3 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -120,7 +120,7 @@ static struct builtin builtins[] = BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsw", "c"), #ifdef DYNAMIC - BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "LaudicI", NULL), + BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "LaudicIp", NULL), #endif }; @@ -1485,7 +1485,7 @@ typeset_single(char *cname, char *pname, Param pm, int func, int usepm, tc, keeplocal = 0; /* use the existing pm? */ - usepm = pm && !(pm->flags & PM_UNSET); + usepm = pm && !(pm->flags & (PM_UNSET | PM_AUTOLOAD)); /* Always use an existing pm if special at current locallevel */ if (pm && (pm->flags & PM_SPECIAL) && pm->level == locallevel) @@ -1793,7 +1793,9 @@ bin_typeset(char *name, char **argv, char *ops, int func) continue; } if (!typeset_single(name, asg->name, - (Param)paramtab->getnode(paramtab, asg->name), + (Param) (paramtab == realparamtab ? + gethashnode2(paramtab, asg->name) : + paramtab->getnode(paramtab, asg->name)), func, on, off, roff, asg->value, NULL)) returnval = 1; } @@ -1945,7 +1947,7 @@ bin_unset(char *name, char **argv, char *ops, int func) next = (Param) pm->next; if ((!(pm->flags & PM_RESTRICTED) || unset(RESTRICTED)) && domatch(pm->nam, com, 0)) { - unsetparam(pm->nam); + unsetparam_pm(pm, 0, 1); match++; } } @@ -1974,7 +1976,9 @@ bin_unset(char *name, char **argv, char *ops, int func) } *ss = 0; } - pm = (Param) paramtab->getnode(paramtab, s); + pm = (Param) (paramtab == realparamtab ? + gethashnode2(paramtab, s) : + paramtab->getnode(paramtab, s)); if (!pm) returnval = 1; else if ((pm->flags & PM_RESTRICTED) && isset(RESTRICTED)) { diff --git a/Src/glob.c b/Src/glob.c index 47ca1d659..79a86bbef 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -3379,16 +3379,14 @@ tokenize(char *s) *t = Inang; *s = Outang; break; - case '^': - case '#': - case '~': - if (unset(EXTENDEDGLOB)) - break; case '(': case '|': case ')': if (isset(SHGLOB)) break; + case '^': + case '#': + case '~': case '[': case ']': case '*': diff --git a/Src/mkbltnmlst.sh b/Src/mkbltnmlst.sh index b58d1e1dd..c174cbac6 100644 --- a/Src/mkbltnmlst.sh +++ b/Src/mkbltnmlst.sh @@ -24,7 +24,7 @@ for x_mod in $x_mods; do *" $x_mod "*) ;; *) echo "/* non-linked-in known module \`$x_mod' */" eval "loc=\$loc_$x_mod" - unset moddeps autobins autoinfixconds autoprefixconds + unset moddeps autobins autoinfixconds autoprefixconds autoparams . $srcdir/../$loc/${x_mod}.mdd for bin in $autobins; do echo " add_autobin(\"$bin\", \"$x_mod\");" @@ -35,6 +35,9 @@ for x_mod in $x_mods; do for cond in $autoprefixconds; do echo " add_autocond(\"$cond\", 0, \"$x_mod\");" done + for param in $autoparams; do + echo " add_autoparam(\"$param\", \"$x_mod\");" + done for dep in $moddeps; do case $bin_mods in *" $dep "*) diff --git a/Src/mkmakemod.sh b/Src/mkmakemod.sh index 2f79acbc3..cd92c7f07 100644 --- a/Src/mkmakemod.sh +++ b/Src/mkmakemod.sh @@ -24,6 +24,7 @@ # autoinfixconds infix condition codes defined by the module, for # autoloading (without the leading `-') # autoprefixconds like autoinfixconds, but for prefix condition codes +# autoparams parameters defined by the module, for autoloading # objects .o files making up this module (*must* be defined) # proto .pro files for this module (default generated from $objects) # headers extra headers for this module (default none) @@ -170,7 +171,7 @@ if $first_stage; then for module in $here_modules; do unset moddeps nozshdep alwayslink hasexport - unset autobins autoinfixconds autoprefixconds + unset autobins autoinfixconds autoprefixconds autoparams unset objects proto headers hdrdeps otherincs . $top_srcdir/$the_subdir/${module}.mdd test -n "${moddeps+set}" || moddeps= diff --git a/Src/module.c b/Src/module.c index ff386c630..09f1fd5db 100644 --- a/Src/module.c +++ b/Src/module.c @@ -539,18 +539,24 @@ load_module(char const *name) m = zcalloc(sizeof(*m)); m->nam = ztrdup(name); m->handle = handle; + m->flags |= MOD_SETUP; + PERMALLOC { + node = addlinknode(modules, m); + } LASTALLOC; if (setup_module(m) || init_module(m)) { finish_module(m); + remnode(modules, node); zsfree(m->nam); zfree(m, sizeof(*m)); + m->flags &= ~MOD_SETUP; return NULL; } - PERMALLOC { - addlinknode(modules, m); - } LASTALLOC; + m->flags &= ~MOD_SETUP; return m; } m = (Module) getdata(node); + if (m->flags & MOD_SETUP) + return m; if (m->flags & MOD_UNLOAD) m->flags &= ~MOD_UNLOAD; else if (m->handle) @@ -570,17 +576,22 @@ load_module(char const *name) if (!m->handle) { if (!(m->handle = do_load_module(name))) return NULL; + m->flags |= MOD_SETUP; if (setup_module(m)) { finish_module(m->handle); m->handle = NULL; + m->flags &= ~MOD_SETUP; return NULL; } } + m->flags |= MOD_SETUP; if (init_module(m)) { finish_module(m->handle); m->handle = NULL; + m->flags &= ~MOD_SETUP; return NULL; } + m->flags &= ~MOD_SETUP; return m; } @@ -690,6 +701,8 @@ bin_zmodload(char *nam, char **args, char *ops, int func) return bin_zmodload_auto(nam, args, ops); else if (ops['c'] || ops['C']) return bin_zmodload_cond(nam, args, ops); + else if (ops['p']) + return bin_zmodload_param(nam, args, ops); else return bin_zmodload_load(nam, args, ops); } @@ -888,6 +901,66 @@ bin_zmodload_cond(char *nam, char **args, char *ops) } } +static void +printautoparams(HashNode hn, int lon) +{ + Param pm = (Param) hn; + + if (pm->flags & PM_AUTOLOAD) { + if (lon) + printf("zmodload -p %s %s\n", pm->u.str, pm->nam); + else + printf("%s (%s)\n", pm->nam, pm->u.str); + } +} + +/**/ +static int +bin_zmodload_param(char *nam, char **args, char *ops) +{ + int ret = 0; + + if (ops['u']) { + /* remove autoloaded parameters */ + for (; *args; args++) { + Param pm = (Param) gethashnode2(paramtab, *args); + + if (!pm) { + if (!ops['i']) { + zwarnnam(nam, "%s: no such parameter", *args, 0); + ret = 1; + } + } else if (!(pm->flags & PM_AUTOLOAD)) { + zwarnnam(nam, "%s: parameter is already defined", *args, 0); + ret = 1; + } else + unsetparam_pm(pm, 0, 1); + } + return ret; + } else if (!*args) { + scanhashtable(paramtab, 1, 0, 0, printautoparams, ops['L']); + return 0; + } else { + /* add autoloaded parameters */ + char *modnam; + + modnam = *args++; + if(isset(RESTRICTED) && strchr(modnam, '/')) { + zwarnnam(nam, "%s: restricted", modnam, 0); + return 1; + } + do { + char *pnam = *args ? *args++ : modnam; + if (strchr(pnam, '/')) { + zwarnnam(nam, "%s: `/' is illegal in a parameter", pnam, 0); + ret = 1; + } else + add_autoparam(pnam, modnam); + } while(*args); + return ret; + } +} + /**/ int unload_module(Module m, LinkNode node) @@ -1114,6 +1187,71 @@ addconddefs(char const *nam, Conddef c, int size) return hadf ? hads : 1; } +/* This adds the given parameter definition. The return value is zero on * + * success and 1 on failure. */ + +/**/ +int +addparamdef(Paramdef d) +{ + Param pm; + + if ((pm = (Param) gethashnode2(paramtab, d->name))) + unsetparam_pm(pm, 0, 1); + + if (!(pm = createparam(d->name, d->flags)) && + !(pm = (Param) paramtab->getnode(paramtab, d->name))) + return 1; + + pm->level = 0; + pm->u.data = d->var; + pm->sets.ifn = (void (*)(Param, long)) d->set; + pm->gets.ifn = (long (*)(Param)) d->get; + pm->unsetfn = (void (*)(Param, int)) d->unset; + + return 0; +} + +/* This adds multiple parameter definitions. This is like addbuiltins(). */ + +/**/ +int +addparamdefs(char const *nam, Paramdef d, int size) +{ + int hads = 0, hadf = 0; + + while (size--) { + if (addparamdef(d)) { + zwarnnam(nam, "error when adding parameter `%s'", d->name, 0); + hadf = 1; + } else + hads = 2; + d++; + } + return hadf ? hads : 1; +} + +/* Delete parameters defined. No error checking yet. */ + +/**/ +int +deleteparamdef(Paramdef d) +{ + unsetparam(d->name); + return 0; +} + +/**/ +int +deleteparamdefs(char const *nam, Paramdef d, int size) +{ + while (size--) { + deleteparamdef(d); + d++; + } + return 1; +} + #ifdef DYNAMIC /* This adds a definition for autoloading a module for a condition. */ @@ -1188,4 +1326,20 @@ deleteconddefs(char const *nam, Conddef c, int size) return hadf ? hads : 1; } +/* This adds a definition for autoloading a module for a parameter. */ + +/**/ +void +add_autoparam(char *nam, char *module) +{ + Param pm; + + if ((pm = (Param) gethashnode2(paramtab, nam))) + unsetparam_pm(pm, 0, 1); + + pm = setsparam(ztrdup(nam), ztrdup(module)); + + pm->flags |= PM_AUTOLOAD; +} + #endif diff --git a/Src/params.c b/Src/params.c index dbc6ce8d8..d60f91990 100644 --- a/Src/params.c +++ b/Src/params.c @@ -255,7 +255,11 @@ static Param argvparam; /* hash table containing the parameters */ /**/ -HashTable paramtab; +HashTable paramtab, realparamtab; + +#ifndef DYNAMIC +#define getparamnode gethashnode2 +#endif /* DYNAMIC */ /**/ HashTable @@ -267,8 +271,8 @@ newparamtable(int size, char const *name) ht->emptytable = emptyhashtable; ht->filltable = NULL; ht->addnode = addhashnode; - ht->getnode = gethashnode2; - ht->getnode2 = gethashnode2; + ht->getnode = getparamnode; + ht->getnode2 = getparamnode; ht->removenode = removehashnode; ht->disablenode = NULL; ht->enablenode = NULL; @@ -278,6 +282,25 @@ newparamtable(int size, char const *name) return ht; } +#ifdef DYNAMIC +/**/ +static HashNode +getparamnode(HashTable ht, char *nam) +{ + HashNode hn = gethashnode2(ht, nam); + Param pm = (Param) hn; + + if (pm && pm->u.str && (pm->flags & PM_AUTOLOAD)) { + char *mn = dupstring(pm->u.str); + + if (!load_module(mn)) + return NULL; + hn = gethashnode2(ht, nam); + } + return hn; +} +#endif /* DYNAMIC */ + /* Copy a parameter hash table */ static HashTable outtable; @@ -402,7 +425,7 @@ createparamtable(void) char buf[50], *str, *iname; int num_env; - paramtab = newparamtable(151, "paramtab"); + paramtab = realparamtab = newparamtable(151, "paramtab"); /* Add the special parameters to the hash table */ for (ip = special_params; ip->nam; ip++) @@ -542,7 +565,9 @@ createparam(char *name, int flags) Param pm, oldpm; if (name != nulstring) { - oldpm = (Param) paramtab->getnode(paramtab, name); + oldpm = (Param) (paramtab == realparamtab ? + gethashnode2(paramtab, name) : + paramtab->getnode(paramtab, name)); if (oldpm && oldpm->level == locallevel) { if (!(oldpm->flags & PM_UNSET) || (oldpm->flags & PM_SPECIAL)) { @@ -2703,6 +2728,8 @@ printparamnode(HashNode hn, int printflags) /* Print the attributes of the parameter */ if (printflags & PRINT_TYPE) { + if (p->flags & PM_AUTOLOAD) + printf("undefined "); if (p->flags & PM_INTEGER) printf("integer "); else if (p->flags & PM_ARRAY) @@ -2736,6 +2763,11 @@ printparamnode(HashNode hn, int printflags) } quotedzputs(p->nam, stdout); + + if (p->flags & PM_AUTOLOAD) { + putchar('\n'); + return; + } if (printflags & PRINT_KV_PAIR) putchar(' '); else diff --git a/Src/prompt.c b/Src/prompt.c index 69823a5e3..ad7cdbc31 100644 --- a/Src/prompt.c +++ b/Src/prompt.c @@ -232,7 +232,7 @@ putpromptchar(int doprint, int endchar) break; case 'l': *bp = '\0'; - countprompt(bufline, &t0, 0); + countprompt(bufline, &t0, 0, 0); if (t0 >= arg) test = 1; break; @@ -678,11 +678,15 @@ putstr(int d) /**/ void -countprompt(char *str, int *wp, int *hp) +countprompt(char *str, int *wp, int *hp, int overf) { int w = 0, h = 1; int s = 1; for(; *str; str++) { + if(w >= columns) { + w = 0; + h++; + } if(*str == Meta) str++; if(*str == Inpar) @@ -694,12 +698,15 @@ countprompt(char *str, int *wp, int *hp) else if(s) { if(*str == '\t') w = (w | 7) + 1; - else if(*str == '\n') - w = columns; - else + else if(*str == '\n') { + w = 0; + h++; + } else w++; } - if(w >= columns) { + } + if(w >= columns) { + if (!overf || w > columns) { w = 0; h++; } diff --git a/Src/zsh.export b/Src/zsh.export index dcee683f6..7f994bf29 100644 --- a/Src/zsh.export +++ b/Src/zsh.export @@ -4,6 +4,7 @@ addbuiltins addconddefs addedx addhashnode +addparamdefs addwrapper arrvargetfn arrvarsetfn @@ -40,6 +41,7 @@ current_limits deletebuiltins deleteconddefs deletehashtable +deleteparamdefs deletewrapper domatch doshfunc diff --git a/Src/zsh.h b/Src/zsh.h index c3c853dfd..1eefc51c1 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -231,6 +231,7 @@ typedef struct hashtable *HashTable; typedef struct reswd *Reswd; typedef struct alias *Alias; typedef struct param *Param; +typedef struct paramdef *Paramdef; typedef struct cmdnam *Cmdnam; typedef struct shfunc *Shfunc; typedef struct funcwrap *FuncWrap; @@ -850,6 +851,7 @@ struct module { #define MOD_BUSY (1<<0) #define MOD_UNLOAD (1<<1) +#define MOD_SETUP (1<<2) /* node used in parameter hash table (paramtab) */ @@ -923,6 +925,7 @@ struct param { #define PM_RESTRICTED (1<<15) /* cannot be changed in restricted mode */ #define PM_UNSET (1<<16) /* has null value */ #define PM_REMOVABLE (1<<17) /* special can be removed from paramtab */ +#define PM_AUTOLOAD (1<<18) /* autoloaded from module */ /* Flags for extracting elements of arrays and associative arrays */ #define SCANPM_WANTVALS (1<<0) @@ -955,6 +958,27 @@ struct param { #define PF_ASSIGN 0x02 /* argument handled like the RHS of foo=bar */ #define PF_SINGLE 0x04 /* single word substitution */ +struct paramdef { + char *name; + int flags; + void *var; + void *set; + void *get; + void *unset; +}; + +#define PARAMDEF(name, flags, var, set, get, unset) \ + { name, flags, (void *) var, (void *) set, (void *) get, (void *) unset } +#define INTPARAMDEF(name, var) \ + { name, PM_INTEGER, (void *) var, (void *) intvarsetfn, \ + (void *) intvargetfn, (void *) stdunsetfn } +#define STRPARAMDEF(name, var) \ + { name, PM_SCALAR, (void *) var, (void *) strvarsetfn, \ + (void *) strvargetfn, (void *) stdunsetfn } +#define ARRPARAMDEF(name, var) \ + { name, PM_ARRAY, (void *) var, (void *) arrvarsetfn, \ + (void *) arrvargetfn, (void *) stdunsetfn } + /* node for named directory hash table (nameddirtab) */ struct nameddir { |