diff options
Diffstat (limited to 'Src')
42 files changed, 1169 insertions, 749 deletions
diff --git a/Src/Builtins/rlimits.c b/Src/Builtins/rlimits.c index 8d55d022d..16ef276f2 100644 --- a/Src/Builtins/rlimits.c +++ b/Src/Builtins/rlimits.c @@ -908,7 +908,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -916,7 +916,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -930,7 +930,7 @@ boot_(Module m) int cleanup_(Module m) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); return 0; } diff --git a/Src/Builtins/sched.c b/Src/Builtins/sched.c index 21a2aad32..df4b9ecf9 100644 --- a/Src/Builtins/sched.c +++ b/Src/Builtins/sched.c @@ -381,8 +381,8 @@ static struct paramdef partab[] = { static struct features module_features = { bintab, sizeof(bintab)/sizeof(*bintab), NULL, 0, - partab, sizeof(partab)/sizeof(*partab), NULL, 0, + partab, sizeof(partab)/sizeof(*partab), 0 }; @@ -397,7 +397,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -405,7 +405,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -430,7 +430,7 @@ cleanup_(Module m) zfree(sch, sizeof(*sch)); } delprepromptfn(&checksched); - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/cap.c b/Src/Modules/cap.c index 2886c42b4..9d41a4e90 100644 --- a/Src/Modules/cap.c +++ b/Src/Modules/cap.c @@ -141,7 +141,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -149,7 +149,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -163,7 +163,7 @@ boot_(UNUSED(Module m)) int cleanup_(Module m) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/clone.c b/Src/Modules/clone.c index adab4cb59..6fdf534c0 100644 --- a/Src/Modules/clone.c +++ b/Src/Modules/clone.c @@ -128,7 +128,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -136,7 +136,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -150,7 +150,7 @@ boot_(UNUSED(Module m)) int cleanup_(Module m) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/datetime.c b/Src/Modules/datetime.c index 06bf52046..169369d5f 100644 --- a/Src/Modules/datetime.c +++ b/Src/Modules/datetime.c @@ -161,8 +161,8 @@ static struct paramdef patab[] = { static struct features module_features = { bintab, sizeof(bintab)/sizeof(*bintab), NULL, 0, - patab, sizeof(patab)/sizeof(*patab), NULL, 0, + patab, sizeof(patab)/sizeof(*patab), 0 }; @@ -177,7 +177,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -185,7 +185,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -199,7 +199,7 @@ boot_(Module m) int cleanup_(Module m) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/example.c b/Src/Modules/example.c index 88e910814..fa86f260c 100644 --- a/Src/Modules/example.c +++ b/Src/Modules/example.c @@ -165,19 +165,19 @@ static struct builtin bintab[] = { }; static struct conddef cotab[] = { - CONDDEF("len", 0, cond_p_len, 1, 2, 0), CONDDEF("ex", CONDF_INFIX, cond_i_ex, 0, 0, 0), + CONDDEF("len", 0, cond_p_len, 1, 2, 0), }; static struct paramdef patab[] = { + ARRPARAMDEF("exarr", &arrparam), INTPARAMDEF("exint", &intparam), STRPARAMDEF("exstr", &strparam), - ARRPARAMDEF("exarr", &arrparam), }; static struct mathfunc mftab[] = { - NUMMATHFUNC("sum", math_sum, 1, -1, 0), STRMATHFUNC("length", math_length, 0), + NUMMATHFUNC("sum", math_sum, 1, -1, 0), }; static struct funcwrap wrapper[] = { @@ -187,8 +187,8 @@ static struct funcwrap wrapper[] = { static struct features module_features = { bintab, sizeof(bintab)/sizeof(*bintab), cotab, sizeof(cotab)/sizeof(*cotab), - patab, sizeof(patab)/sizeof(*patab), mftab, sizeof(mftab)/sizeof(*mftab), + patab, sizeof(patab)/sizeof(*patab), 0 }; @@ -205,7 +205,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -213,7 +213,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -234,7 +234,7 @@ int cleanup_(Module m) { deletewrapper(m, wrapper); - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/files.c b/Src/Modules/files.c index ba742cc50..0ce6d78d0 100644 --- a/Src/Modules/files.c +++ b/Src/Modules/files.c @@ -725,7 +725,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -733,7 +733,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -747,7 +747,7 @@ boot_(Module m) int cleanup_(Module m) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/langinfo.c b/Src/Modules/langinfo.c index cfbdeed44..f10fdfef5 100644 --- a/Src/Modules/langinfo.c +++ b/Src/Modules/langinfo.c @@ -376,7 +376,7 @@ static nl_item nl_vals[] = { }; static nl_item * -liitem(char *name) +liitem(const char *name) { char **element; nl_item *nlcode; @@ -393,16 +393,17 @@ liitem(char *name) /**/ static HashNode -getlanginfo(UNUSED(HashTable ht), char *name) +getlanginfo(UNUSED(HashTable ht), const char *name) { int len, *elem; - char *listr; + char *listr, *nameu; Param pm = NULL; - unmetafy(name, &len); + nameu = dupstring(name); + unmetafy(nameu, &len); pm = (Param) hcalloc(sizeof(struct param)); - pm->node.nam = dupstring(name); + pm->node.nam = nameu; pm->node.flags = PM_READONLY | PM_SCALAR; pm->gsu.s = &nullsetscalar_gsu; @@ -456,12 +457,12 @@ static struct paramdef partab[] = { static struct features module_features = { NULL, 0, NULL, 0, + NULL, 0, #ifdef HAVE_NL_LANGINFO partab, sizeof(partab)/sizeof(*partab), #else NULL, 0, #endif - NULL, 0, 0 }; @@ -476,7 +477,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -484,7 +485,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -498,7 +499,7 @@ boot_(UNUSED(Module m)) int cleanup_(UNUSED(Module m)) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/mapfile.c b/Src/Modules/mapfile.c index fb46df885..d825c7faa 100644 --- a/Src/Modules/mapfile.c +++ b/Src/Modules/mapfile.c @@ -213,7 +213,7 @@ static struct paramdef partab[] = { /**/ static HashNode -getpmmapfile(UNUSED(HashTable ht), char *name) +getpmmapfile(UNUSED(HashTable ht), const char *name) { char *contents; Param pm = NULL; @@ -268,8 +268,8 @@ scanpmmapfile(UNUSED(HashTable ht), ScanFunc func, int flags) static struct features module_features = { NULL, 0, NULL, 0, - partab, sizeof(partab)/sizeof(*partab), NULL, 0, + partab, sizeof(partab)/sizeof(*partab), 0 }; @@ -284,7 +284,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -292,7 +292,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -306,7 +306,7 @@ boot_(UNUSED(Module m)) int cleanup_(UNUSED(Module m)) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/mathfunc.c b/Src/Modules/mathfunc.c index a473476e3..04483b555 100644 --- a/Src/Modules/mathfunc.c +++ b/Src/Modules/mathfunc.c @@ -125,12 +125,6 @@ enum { static struct mathfunc mftab[] = { - /* Functions taking string arguments */ -#ifdef HAVE_ERAND48 - /* here to avoid comma hassle */ - STRMATHFUNC("rand48", math_string, MS_RAND48), -#endif - NUMMATHFUNC("abs", math_func, 1, 1, MF_ABS | BFLAG(BF_FRAC) | TFLAG(TF_NOCONV|TF_NOASS)), NUMMATHFUNC("acos", math_func, 1, 1, MF_ACOS | BFLAG(BF_FRAC)), @@ -167,6 +161,9 @@ static struct mathfunc mftab[] = { NUMMATHFUNC("log1p", math_func, 1, 1, MF_LOG1P | BFLAG(BF_GTRM1)), NUMMATHFUNC("logb", math_func, 1, 1, MF_LOGB | BFLAG(BF_NONZ)), NUMMATHFUNC("nextafter", math_func, 2, 2, MF_NEXTAFTER), +#ifdef HAVE_ERAND48 + STRMATHFUNC("rand48", math_string, MS_RAND48), +#endif NUMMATHFUNC("rint", math_func, 1, 1, MF_RINT), NUMMATHFUNC("scalb", math_func, 2, 2, MF_SCALB | TFLAG(TF_INT2)), #ifdef HAVE_SIGNGAM @@ -564,8 +561,8 @@ math_string(UNUSED(char *name), char *arg, int id) static struct features module_features = { NULL, 0, NULL, 0, - NULL, 0, mftab, sizeof(mftab)/sizeof(*mftab), + NULL, 0, 0 }; @@ -580,7 +577,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -588,7 +585,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -602,7 +599,7 @@ boot_(Module m) int cleanup_(Module m) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c index 9112e64f1..3c7264a09 100644 --- a/Src/Modules/parameter.c +++ b/Src/Modules/parameter.c @@ -93,7 +93,7 @@ paramtypestr(Param pm) /**/ static HashNode -getpmparameter(UNUSED(HashTable ht), char *name) +getpmparameter(UNUSED(HashTable ht), const char *name) { Param rpm, pm = NULL; @@ -199,7 +199,7 @@ static const struct gsu_scalar pmcommand_gsu = /**/ static HashNode -getpmcommand(UNUSED(HashTable ht), char *name) +getpmcommand(UNUSED(HashTable ht), const char *name) { Cmdnam cmd; Param pm = NULL; @@ -372,7 +372,7 @@ static const struct gsu_scalar pmdisfunction_gsu = /**/ static HashNode -getfunction(UNUSED(HashTable ht), char *name, int dis) +getfunction(UNUSED(HashTable ht), const char *name, int dis) { Shfunc shf; Param pm = NULL; @@ -416,14 +416,14 @@ getfunction(UNUSED(HashTable ht), char *name, int dis) /**/ static HashNode -getpmfunction(HashTable ht, char *name) +getpmfunction(HashTable ht, const char *name) { return getfunction(ht, name, 0); } /**/ static HashNode -getpmdisfunction(HashTable ht, char *name) +getpmdisfunction(HashTable ht, const char *name) { return getfunction(ht, name, DISABLED); } @@ -542,7 +542,7 @@ functracegetfn(UNUSED(Param pm)) /**/ static HashNode -getbuiltin(UNUSED(HashTable ht), char *name, int dis) +getbuiltin(UNUSED(HashTable ht), const char *name, int dis) { Param pm = NULL; Builtin bn; @@ -566,14 +566,14 @@ getbuiltin(UNUSED(HashTable ht), char *name, int dis) /**/ static HashNode -getpmbuiltin(HashTable ht, char *name) +getpmbuiltin(HashTable ht, const char *name) { return getbuiltin(ht, name, 0); } /**/ static HashNode -getpmdisbuiltin(HashTable ht, char *name) +getpmdisbuiltin(HashTable ht, const char *name) { return getbuiltin(ht, name, DISABLED); } @@ -721,7 +721,7 @@ static const struct gsu_scalar pmoption_gsu = /**/ static HashNode -getpmoption(UNUSED(HashTable ht), char *name) +getpmoption(UNUSED(HashTable ht), const char *name) { Param pm = NULL; int n; @@ -771,69 +771,29 @@ scanpmoptions(UNUSED(HashTable ht), ScanFunc func, int flags) /* Functions for the modules special parameter. */ -static char *modpmname; -static int modpmfound; - -/**/ -static void -modpmbuiltinscan(HashNode hn, UNUSED(int dummy)) -{ - if (!(((Builtin) hn)->node.flags & BINF_ADDED) && - !strcmp(((Builtin) hn)->optstr, modpmname)) - modpmfound = 1; -} - -/**/ -static void -modpmparamscan(HashNode hn, UNUSED(int dummy)) -{ - if ((((Param) hn)->node.flags & PM_AUTOLOAD) && - !strcmp(((Param) hn)->u.str, modpmname)) - modpmfound = 1; -} - /**/ static HashNode -getpmmodule(UNUSED(HashTable ht), char *name) +getpmmodule(UNUSED(HashTable ht), const char *name) { Param pm = NULL; char *type = NULL; - LinkNode node; + Module m; pm = (Param) hcalloc(sizeof(struct param)); pm->node.nam = dupstring(name); pm->node.flags = PM_SCALAR | PM_READONLY; pm->gsu.s = &nullsetscalar_gsu; - if (!type) { - Module m; - - for (node = firstnode(modules); node; incnode(node)) { - m = (Module) getdata(node); - if (m->u.handle && !(m->flags & MOD_UNLOAD) && - !strcmp(name, m->nam)) { - type = ((m->flags & MOD_ALIAS) ? - dyncat("alias:", m->u.alias) : "loaded"); - break; - } - } + m = (Module)modulestab->getnode2(modulestab, name); + + if (!m) + return NULL; + if (m->u.handle && !(m->node.flags & MOD_UNLOAD)) { + type = ((m->node.flags & MOD_ALIAS) ? + dyncat("alias:", m->u.alias) : "loaded"); } - modpmname = name; - modpmfound = 0; if (!type) { - scanhashtable(builtintab, 0, 0, 0, modpmbuiltinscan, 0); - if (!modpmfound) { - Conddef p; - - for (p = condtab; p; p = p->next) - if (p->module && !strcmp(name, p->module)) { - modpmfound = 1; - break; - } - if (!modpmfound) - scanhashtable(realparamtab, 0, 0, 0, modpmparamscan, 0); - } - if (modpmfound) + if (m->autoloads && firstnode(m->autoloads)) type = "autoloaded"; } if (type) @@ -853,7 +813,6 @@ scanpmmodules(UNUSED(HashTable ht), ScanFunc func, int flags) int i; HashNode hn; LinkList done = newlinklist(); - LinkNode node; Module m; Conddef p; char *loaded = dupstring("loaded"); @@ -862,14 +821,16 @@ scanpmmodules(UNUSED(HashTable ht), ScanFunc func, int flags) pm.node.flags = PM_SCALAR | PM_READONLY; pm.gsu.s = &nullsetscalar_gsu; - for (node = firstnode(modules); node; incnode(node)) { - m = (Module) getdata(node); - if (m->u.handle && !(m->flags & MOD_UNLOAD)) { - pm.node.nam = m->nam; - pm.u.str = ((m->flags & MOD_ALIAS) ? - dyncat("alias:", m->u.alias) : loaded); - addlinknode(done, pm.node.nam); - func(&pm.node, flags); + for (i = 0; i < modulestab->hsize; i++) { + for (hn = modulestab->nodes[i]; hn; hn = hn->next) { + m = (Module) hn; + if (m->u.handle && !(m->node.flags & MOD_UNLOAD)) { + pm.node.nam = m->node.nam; + pm.u.str = ((m->node.flags & MOD_ALIAS) ? + dyncat("alias:", m->u.alias) : loaded); + addlinknode(done, pm.node.nam); + func(&pm.node, flags); + } } } pm.u.str = dupstring("autoloaded"); @@ -928,11 +889,11 @@ dirsgetfn(UNUSED(Param pm)) /**/ static HashNode -getpmhistory(UNUSED(HashTable ht), char *name) +getpmhistory(UNUSED(HashTable ht), const char *name) { Param pm = NULL; Histent he; - char *p; + const char *p; int ok = 1; pm = (Param) hcalloc(sizeof(struct param)); @@ -1042,7 +1003,7 @@ pmjobtext(int job) /**/ static HashNode -getpmjobtext(UNUSED(HashTable ht), char *name) +getpmjobtext(UNUSED(HashTable ht), const char *name) { Param pm = NULL; int job; @@ -1139,7 +1100,7 @@ pmjobstate(int job) /**/ static HashNode -getpmjobstate(UNUSED(HashTable ht), char *name) +getpmjobstate(UNUSED(HashTable ht), const char *name) { Param pm = NULL; int job; @@ -1201,7 +1162,7 @@ pmjobdir(int job) /**/ static HashNode -getpmjobdir(UNUSED(HashTable ht), char *name) +getpmjobdir(UNUSED(HashTable ht), const char *name) { Param pm = NULL; int job; @@ -1329,7 +1290,7 @@ static const struct gsu_scalar pmnamedir_gsu = /**/ static HashNode -getpmnameddir(UNUSED(HashTable ht), char *name) +getpmnameddir(UNUSED(HashTable ht), const char *name) { Param pm = NULL; Nameddir nd; @@ -1378,7 +1339,7 @@ scanpmnameddirs(UNUSED(HashTable ht), ScanFunc func, int flags) /**/ static HashNode -getpmuserdir(UNUSED(HashTable ht), char *name) +getpmuserdir(UNUSED(HashTable ht), const char *name) { Param pm = NULL; Nameddir nd; @@ -1631,7 +1592,7 @@ assignaliasdefs(Param pm, int flags) /**/ static HashNode -getalias(HashTable alht, UNUSED(HashTable ht), char *name, int flags) +getalias(HashTable alht, UNUSED(HashTable ht), const char *name, int flags) { Param pm = NULL; Alias al; @@ -1653,45 +1614,45 @@ getalias(HashTable alht, UNUSED(HashTable ht), char *name, int flags) /**/ static HashNode -getpmralias(HashTable ht, char *name) +getpmralias(HashTable ht, const char *name) { return getalias(aliastab, ht, name, 0); } /**/ static HashNode -getpmdisralias(HashTable ht, char *name) +getpmdisralias(HashTable ht, const char *name) { return getalias(aliastab, ht, name, DISABLED); } /**/ static HashNode -getpmgalias(HashTable ht, char *name) +getpmgalias(HashTable ht, const char *name) { return getalias(aliastab, ht, name, ALIAS_GLOBAL); } /**/ static HashNode -getpmdisgalias(HashTable ht, char *name) +getpmdisgalias(HashTable ht, const char *name) { return getalias(aliastab, ht, name, ALIAS_GLOBAL|DISABLED); } /**/ static HashNode -getpmsalias(HashTable ht, char *name) +getpmsalias(HashTable ht, const char *name) { return getalias(sufaliastab, ht, name, ALIAS_SUFFIX); } /**/ static HashNode -getpmdissalias(HashTable ht, char *name) +getpmdissalias(HashTable ht, const char *name) { return getalias(sufaliastab, ht, name, ALIAS_SUFFIX|DISABLED); -} +} /**/ static void @@ -1809,63 +1770,63 @@ static const struct gsu_array historywords_gsu = { histwgetfn, arrsetfn, stdunsetfn }; static struct paramdef partab[] = { - SPECIALPMDEF("parameters", PM_READONLY, - NULL, getpmparameter, scanpmparameters), + SPECIALPMDEF("aliases", 0, + &pmraliases_gsu, getpmralias, scanpmraliases), + SPECIALPMDEF("builtins", PM_READONLY, NULL, getpmbuiltin, scanpmbuiltins), SPECIALPMDEF("commands", 0, &pmcommands_gsu, getpmcommand, scanpmcommands), - SPECIALPMDEF("functions", 0, &pmfunctions_gsu, getpmfunction, - scanpmfunctions), + SPECIALPMDEF("dirstack", PM_ARRAY, + &dirs_gsu, NULL, NULL), + SPECIALPMDEF("dis_aliases", 0, + &pmdisraliases_gsu, getpmdisralias, scanpmdisraliases), + SPECIALPMDEF("dis_builtins", PM_READONLY, + NULL, getpmdisbuiltin, scanpmdisbuiltins), SPECIALPMDEF("dis_functions", 0, &pmdisfunctions_gsu, getpmdisfunction, scanpmdisfunctions), + SPECIALPMDEF("dis_galiases", 0, + &pmdisgaliases_gsu, getpmdisgalias, scanpmdisgaliases), + SPECIALPMDEF("dis_reswords", PM_ARRAY|PM_READONLY, + &disreswords_gsu, NULL, NULL), + SPECIALPMDEF("dis_saliases", 0, + &pmdissaliases_gsu, getpmdissalias, scanpmdissaliases), SPECIALPMDEF("funcstack", PM_ARRAY|PM_READONLY, &funcstack_gsu, NULL, NULL), + SPECIALPMDEF("functions", 0, &pmfunctions_gsu, getpmfunction, + scanpmfunctions), SPECIALPMDEF("functrace", PM_ARRAY|PM_READONLY, &functrace_gsu, NULL, NULL), - SPECIALPMDEF("builtins", PM_READONLY, NULL, getpmbuiltin, scanpmbuiltins), - SPECIALPMDEF("dis_builtins", PM_READONLY, - NULL, getpmdisbuiltin, scanpmdisbuiltins), - SPECIALPMDEF("reswords", PM_ARRAY|PM_READONLY, - &reswords_gsu, NULL, NULL), - SPECIALPMDEF("dis_reswords", PM_ARRAY|PM_READONLY, - &disreswords_gsu, NULL, NULL), - SPECIALPMDEF("options", 0, - &pmoptions_gsu, getpmoption, scanpmoptions), - SPECIALPMDEF("modules", PM_READONLY, - NULL, getpmmodule, scanpmmodules), - SPECIALPMDEF("dirstack", PM_ARRAY, - &dirs_gsu, NULL, NULL), + SPECIALPMDEF("galiases", 0, + &pmgaliases_gsu, getpmgalias, scanpmgaliases), SPECIALPMDEF("history", PM_READONLY, NULL, getpmhistory, scanpmhistory), SPECIALPMDEF("historywords", PM_ARRAY|PM_READONLY, &historywords_gsu, NULL, NULL), - SPECIALPMDEF("jobtexts", PM_READONLY, - NULL, getpmjobtext, scanpmjobtexts), - SPECIALPMDEF("jobstates", PM_READONLY, - NULL, getpmjobstate, scanpmjobstates), SPECIALPMDEF("jobdirs", PM_READONLY, NULL, getpmjobdir, scanpmjobdirs), + SPECIALPMDEF("jobstates", PM_READONLY, + NULL, getpmjobstate, scanpmjobstates), + SPECIALPMDEF("jobtexts", PM_READONLY, + NULL, getpmjobtext, scanpmjobtexts), + SPECIALPMDEF("modules", PM_READONLY, + NULL, getpmmodule, scanpmmodules), SPECIALPMDEF("nameddirs", 0, &pmnameddirs_gsu, getpmnameddir, scanpmnameddirs), - SPECIALPMDEF("userdirs", PM_READONLY, - NULL, getpmuserdir, scanpmuserdirs), - SPECIALPMDEF("aliases", 0, - &pmraliases_gsu, getpmralias, scanpmraliases), - SPECIALPMDEF("galiases", 0, - &pmgaliases_gsu, getpmgalias, scanpmgaliases), + SPECIALPMDEF("options", 0, + &pmoptions_gsu, getpmoption, scanpmoptions), + SPECIALPMDEF("parameters", PM_READONLY, + NULL, getpmparameter, scanpmparameters), + SPECIALPMDEF("reswords", PM_ARRAY|PM_READONLY, + &reswords_gsu, NULL, NULL), SPECIALPMDEF("saliases", 0, &pmsaliases_gsu, getpmsalias, scanpmsaliases), - SPECIALPMDEF("dis_aliases", 0, - &pmdisraliases_gsu, getpmdisralias, scanpmdisraliases), - SPECIALPMDEF("dis_galiases", 0, - &pmdisgaliases_gsu, getpmdisgalias, scanpmdisgaliases), - SPECIALPMDEF("dis_saliases", 0, - &pmdissaliases_gsu, getpmdissalias, scanpmdissaliases) + SPECIALPMDEF("userdirs", PM_READONLY, + NULL, getpmuserdir, scanpmuserdirs) }; static struct features module_features = { NULL, 0, NULL, 0, - partab, sizeof(partab)/sizeof(*partab), NULL, 0, + partab, sizeof(partab)/sizeof(*partab), 0 }; @@ -1880,7 +1841,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -1894,7 +1855,7 @@ enables_(Module m, int **enables) * on the main shell, so set the flag to indicate. */ incleanup = 1; - ret = handlefeatures(m->nam, &module_features, enables); + ret = handlefeatures(m, &module_features, enables); incleanup = 0; return ret; } @@ -1912,7 +1873,7 @@ cleanup_(Module m) { int ret; incleanup = 1; - ret = setfeatureenables(m->nam, &module_features, NULL); + ret = setfeatureenables(m, &module_features, NULL); incleanup = 0; return ret; } diff --git a/Src/Modules/pcre.c b/Src/Modules/pcre.c index 45c38eba0..4f8daff80 100644 --- a/Src/Modules/pcre.c +++ b/Src/Modules/pcre.c @@ -290,8 +290,8 @@ static struct conddef cotab[] = { static struct builtin bintab[] = { BUILTIN("pcre_compile", 0, bin_pcre_compile, 1, 1, 0, "aimx", NULL), - BUILTIN("pcre_study", 0, bin_pcre_study, 0, 0, 0, NULL, NULL), - BUILTIN("pcre_match", 0, bin_pcre_match, 1, 1, 0, "a:v:", NULL) + BUILTIN("pcre_match", 0, bin_pcre_match, 1, 1, 0, "a:v:", NULL), + BUILTIN("pcre_study", 0, bin_pcre_study, 0, 0, 0, NULL, NULL) }; @@ -319,7 +319,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -327,7 +327,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -341,7 +341,7 @@ boot_(Module m) int cleanup_(Module m) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/regex.c b/Src/Modules/regex.c index a3d956055..00ed46b3b 100644 --- a/Src/Modules/regex.c +++ b/Src/Modules/regex.c @@ -152,7 +152,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -160,7 +160,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -174,7 +174,7 @@ boot_(Module m) int cleanup_(Module m) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/socket.c b/Src/Modules/socket.c index 413625dcf..469568a11 100644 --- a/Src/Modules/socket.c +++ b/Src/Modules/socket.c @@ -276,7 +276,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -284,7 +284,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -298,7 +298,7 @@ boot_(Module m) int cleanup_(Module m) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/stat.c b/Src/Modules/stat.c index 1d55317ea..a3e95bb59 100644 --- a/Src/Modules/stat.c +++ b/Src/Modules/stat.c @@ -643,7 +643,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -651,7 +651,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -665,7 +665,7 @@ boot_(Module m) int cleanup_(Module m) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/system.c b/Src/Modules/system.c index f8a188d42..4af464db0 100644 --- a/Src/Modules/system.c +++ b/Src/Modules/system.c @@ -365,7 +365,7 @@ static const struct gsu_array errnos_gsu = /**/ static void -fillpmsysparams(Param pm, char *name) +fillpmsysparams(Param pm, const char *name) { char buf[DIGBUFSIZE]; int num; @@ -390,7 +390,7 @@ fillpmsysparams(Param pm, char *name) /**/ static HashNode -getpmsysparams(UNUSED(HashTable ht), char *name) +getpmsysparams(UNUSED(HashTable ht), const char *name) { Param pm; @@ -423,8 +423,8 @@ static struct paramdef partab[] = { static struct features module_features = { bintab, sizeof(bintab)/sizeof(*bintab), NULL, 0, - partab, sizeof(partab)/sizeof(*partab), NULL, 0, + partab, sizeof(partab)/sizeof(*partab), 0 }; @@ -441,7 +441,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -449,7 +449,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -464,7 +464,7 @@ boot_(Module m) int cleanup_(Module m) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/tcp.c b/Src/Modules/tcp.c index 1bf9b3776..d1d4e5002 100644 --- a/Src/Modules/tcp.c +++ b/Src/Modules/tcp.c @@ -696,7 +696,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -704,7 +704,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -722,7 +722,7 @@ cleanup_(Module m) { tcp_cleanup(); freelinklist(ztcp_sessions, (FreeFunc) ztcp_free_session); - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/termcap.c b/Src/Modules/termcap.c index c19db4892..351324a68 100644 --- a/Src/Modules/termcap.c +++ b/Src/Modules/termcap.c @@ -164,10 +164,10 @@ static struct builtin bintab[] = { /**/ static HashNode -gettermcap(UNUSED(HashTable ht), char *name) +gettermcap(UNUSED(HashTable ht), const char *name) { int len, num; - char *tcstr, buf[2048], *u; + char *tcstr, buf[2048], *u, *nameu; Param pm = NULL; /* This depends on the termcap stuff in init.c */ @@ -176,16 +176,18 @@ gettermcap(UNUSED(HashTable ht), char *name) if ((termflags & TERM_UNKNOWN) && (isset(INTERACTIVE) || !init_term())) return NULL; - unmetafy(name, &len); + + nameu = dupstring(name); + unmetafy(nameu, &len); pm = (Param) hcalloc(sizeof(struct param)); - pm->node.nam = dupstring(name); + pm->node.nam = nameu; pm->node.flags = PM_READONLY; u = buf; /* logic in the following cascade copied from echotc, above */ - if ((num = tgetnum(name)) != -1) { + if ((num = tgetnum(nameu)) != -1) { pm->gsu.i = &nullsetinteger_gsu; pm->u.val = num; pm->node.flags |= PM_INTEGER; @@ -193,7 +195,7 @@ gettermcap(UNUSED(HashTable ht), char *name) } pm->gsu.s = &nullsetscalar_gsu; - switch (ztgetflag(name)) { + switch (ztgetflag(nameu)) { case -1: break; case 0: @@ -205,7 +207,7 @@ gettermcap(UNUSED(HashTable ht), char *name) pm->node.flags |= PM_SCALAR; return &pm->node; } - if ((tcstr = tgetstr(name, &u)) != NULL && tcstr != (char *)-1) { + if ((tcstr = tgetstr(nameu, &u)) != NULL && tcstr != (char *)-1) { pm->u.str = dupstring(tcstr); pm->node.flags |= PM_SCALAR; } else { @@ -324,12 +326,12 @@ static struct features module_features = { NULL, 0, #endif NULL, 0, + NULL, 0, #ifdef HAVE_TGETENT partab, sizeof(partab)/sizeof(*partab), #else NULL, 0, #endif - NULL, 0, 0 }; @@ -344,7 +346,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -352,7 +354,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -371,7 +373,7 @@ boot_(Module m) int cleanup_(Module m) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/terminfo.c b/Src/Modules/terminfo.c index d324c3a6c..63cbd2abc 100644 --- a/Src/Modules/terminfo.c +++ b/Src/Modules/terminfo.c @@ -129,10 +129,10 @@ static struct builtin bintab[] = { /**/ static HashNode -getterminfo(UNUSED(HashTable ht), char *name) +getterminfo(UNUSED(HashTable ht), const char *name) { int len, num; - char *tistr; + char *tistr, *nameu; Param pm = NULL; /* This depends on the termcap stuff in init.c */ @@ -141,21 +141,22 @@ getterminfo(UNUSED(HashTable ht), char *name) if ((termflags & TERM_UNKNOWN) && (isset(INTERACTIVE) || !init_term())) return NULL; - unmetafy(name, &len); + nameu = dupstring(name); + unmetafy(nameu, &len); pm = (Param) hcalloc(sizeof(struct param)); - pm->node.nam = dupstring(name); + pm->node.nam = nameu; pm->node.flags = PM_READONLY; - if (((num = tigetnum(name)) != -1) && (num != -2)) { + if (((num = tigetnum(nameu)) != -1) && (num != -2)) { pm->u.val = num; pm->node.flags |= PM_INTEGER; pm->gsu.i = &nullsetinteger_gsu; - } else if ((num = tigetflag(name)) != -1) { + } else if ((num = tigetflag(nameu)) != -1) { pm->u.str = num ? dupstring("yes") : dupstring("no"); pm->node.flags |= PM_SCALAR; pm->gsu.s = &nullsetscalar_gsu; - } else if ((tistr = (char *)tigetstr(name)) != NULL && tistr != (char *)-1) { + } else if ((tistr = (char *)tigetstr(nameu)) != NULL && tistr != (char *)-1) { pm->u.str = dupstring(tistr); pm->node.flags |= PM_SCALAR; pm->gsu.s = &nullsetscalar_gsu; @@ -298,12 +299,12 @@ static struct features module_features = { NULL, 0, #endif NULL, 0, + NULL, 0, #ifdef USE_TERMINFO_MODULE partab, sizeof(partab)/sizeof(*partab), #else NULL, 0, #endif - NULL, 0, 0 }; @@ -318,7 +319,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -326,7 +327,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -349,7 +350,7 @@ boot_(Module m) int cleanup_(Module m) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c index 5c8822cc5..af48e80aa 100644 --- a/Src/Modules/zftp.c +++ b/Src/Modules/zftp.c @@ -3181,7 +3181,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -3189,7 +3189,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -3221,7 +3221,7 @@ cleanup_(Module m) { deletehookfunc("exit", zftpexithook); zftp_cleanup(); - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/zprof.c b/Src/Modules/zprof.c index b30e44432..bc97771c0 100644 --- a/Src/Modules/zprof.c +++ b/Src/Modules/zprof.c @@ -225,7 +225,7 @@ zprof_wrapper(Eprog prog, FuncWrap w, char *name) struct timezone dummy; double prev = 0, now; - if (zprof_module && !(zprof_module->flags & MOD_UNLOAD)) { + if (zprof_module && !(zprof_module->node.flags & MOD_UNLOAD)) { active = 1; if (!(f = findpfunc(name))) { f = (Pfunc) zalloc(sizeof(*f)); @@ -260,7 +260,7 @@ zprof_wrapper(Eprog prog, FuncWrap w, char *name) } runshfunc(prog, w, name); if (active) { - if (zprof_module && !(zprof_module->flags & MOD_UNLOAD)) { + if (zprof_module && !(zprof_module->node.flags & MOD_UNLOAD)) { tv.tv_sec = tv.tv_usec = 0; gettimeofday(&tv, &dummy); @@ -315,7 +315,7 @@ setup_(Module m) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -323,7 +323,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -345,7 +345,7 @@ cleanup_(Module m) freepfuncs(calls); freeparcs(arcs); deletewrapper(m, wrapper); - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/zpty.c b/Src/Modules/zpty.c index 3280b8175..7e140102e 100644 --- a/Src/Modules/zpty.c +++ b/Src/Modules/zpty.c @@ -750,7 +750,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -758,7 +758,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -777,7 +777,7 @@ cleanup_(Module m) { deletehookfunc("exit", ptyhook); deleteallptycmds(); - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/zselect.c b/Src/Modules/zselect.c index 3e71fa3bd..c02074646 100644 --- a/Src/Modules/zselect.c +++ b/Src/Modules/zselect.c @@ -294,7 +294,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -302,7 +302,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -317,7 +317,7 @@ boot_(Module m) int cleanup_(Module m) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c index 127509b01..76056308f 100644 --- a/Src/Modules/zutil.c +++ b/Src/Modules/zutil.c @@ -1801,10 +1801,10 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) } static struct builtin bintab[] = { - BUILTIN("zstyle", 0, bin_zstyle, 0, -1, 0, NULL, NULL), BUILTIN("zformat", 0, bin_zformat, 3, -1, 0, NULL, NULL), - BUILTIN("zregexparse", 0, bin_zregexparse, 3, -1, 0, "c", NULL), BUILTIN("zparseopts", 0, bin_zparseopts, 1, -1, 0, NULL, NULL), + BUILTIN("zregexparse", 0, bin_zregexparse, 3, -1, 0, "c", NULL), + BUILTIN("zstyle", 0, bin_zstyle, 0, -1, 0, NULL, NULL), }; static struct features module_features = { @@ -1828,7 +1828,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -1836,7 +1836,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -1850,7 +1850,7 @@ boot_(Module m) int cleanup_(Module m) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index bafbb2f68..143c93682 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -3938,8 +3938,8 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) static struct builtin bintab[] = { - BUILTIN("compctl", 0, bin_compctl, 0, -1, 0, NULL, NULL), BUILTIN("compcall", 0, bin_compcall, 0, 0, 0, "TD", NULL), + BUILTIN("compctl", 0, bin_compctl, 0, -1, 0, NULL, NULL), }; static struct features module_features = { @@ -3974,7 +3974,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -3982,7 +3982,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -4000,7 +4000,7 @@ cleanup_(Module m) { deletehookfunc("compctl_make", (Hookfn) ccmakehookfn); deletehookfunc("compctl_cleanup", (Hookfn) cccleanuphookfn); - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c index a2af30c65..36c4c8a3d 100644 --- a/Src/Zle/complete.c +++ b/Src/Zle/complete.c @@ -1445,10 +1445,10 @@ static struct builtin bintab[] = { }; static struct conddef cotab[] = { + CONDDEF("after", 0, cond_range, 1, 1, 0), + CONDDEF("between", 0, cond_range, 2, 2, 1), CONDDEF("prefix", 0, cond_psfix, 1, 2, CVT_PREPAT), CONDDEF("suffix", 0, cond_psfix, 1, 2, CVT_SUFPAT), - CONDDEF("between", 0, cond_range, 2, 2, 1), - CONDDEF("after", 0, cond_range, 1, 1, 0), }; static struct funcwrap wrapper[] = { @@ -1502,7 +1502,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -1510,7 +1510,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -1524,7 +1524,7 @@ boot_(Module m) addhookfunc("reverse_menu", (Hookfn) reverse_menu); addhookfunc("list_matches", (Hookfn) list_matches); addhookfunc("invalidate_list", (Hookfn) invalidate_list); - (void)addhookdefs(m->nam, comphooks, sizeof(comphooks)/sizeof(*comphooks)); + (void)addhookdefs(m, comphooks, sizeof(comphooks)/sizeof(*comphooks)); return addwrapper(m, wrapper); } @@ -1539,10 +1539,10 @@ cleanup_(Module m) deletehookfunc("reverse_menu", (Hookfn) reverse_menu); deletehookfunc("list_matches", (Hookfn) list_matches); deletehookfunc("invalidate_list", (Hookfn) invalidate_list); - (void)deletehookdefs(m->nam, comphooks, + (void)deletehookdefs(m, comphooks, sizeof(comphooks)/sizeof(*comphooks)); deletewrapper(m, wrapper); - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c index 787b7b25c..64d7e50ce 100644 --- a/Src/Zle/complist.c +++ b/Src/Zle/complist.c @@ -3238,7 +3238,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -3246,7 +3246,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -3261,7 +3261,8 @@ boot_(Module m) w_menuselect = addzlefunction("menu-select", menuselect, ZLE_MENUCMP|ZLE_KEEPSUFFIX|ZLE_ISCOMP); if (!w_menuselect) { - zwarnnam(m->nam, "name clash when adding ZLE function `menu-select'"); + zwarnnam(m->node.nam, + "name clash when adding ZLE function `menu-select'"); return -1; } addhookfunc("comp_list_matches", (Hookfn) complistmatches); @@ -3302,7 +3303,7 @@ cleanup_(Module m) deletehookfunc("menu_start", (Hookfn) domenuselect); unlinkkeymap("menuselect", 1); unlinkkeymap("listscroll", 1); - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c index b9df1e418..9ba38101a 100644 --- a/Src/Zle/computil.c +++ b/Src/Zle/computil.c @@ -4544,14 +4544,14 @@ bin_compgroups(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) } static struct builtin bintab[] = { - BUILTIN("compdescribe", 0, bin_compdescribe, 3, -1, 0, NULL, NULL), BUILTIN("comparguments", 0, bin_comparguments, 1, -1, 0, NULL, NULL), - BUILTIN("compvalues", 0, bin_compvalues, 1, -1, 0, NULL, NULL), + BUILTIN("compdescribe", 0, bin_compdescribe, 3, -1, 0, NULL, NULL), + BUILTIN("compfiles", 0, bin_compfiles, 1, -1, 0, NULL, NULL), + BUILTIN("compgroups", 0, bin_compgroups, 1, -1, 0, NULL, NULL), BUILTIN("compquote", 0, bin_compquote, 1, -1, 0, "p", NULL), BUILTIN("comptags", 0, bin_comptags, 1, -1, 0, NULL, NULL), BUILTIN("comptry", 0, bin_comptry, 0, -1, 0, NULL, NULL), - BUILTIN("compfiles", 0, bin_compfiles, 1, -1, 0, NULL, NULL), - BUILTIN("compgroups", 0, bin_compgroups, 1, -1, 0, NULL, NULL), + BUILTIN("compvalues", 0, bin_compvalues, 1, -1, 0, NULL, NULL) }; static struct features module_features = { @@ -4581,7 +4581,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -4589,7 +4589,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -4603,7 +4603,7 @@ boot_(Module m) int cleanup_(Module m) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Zle/deltochar.c b/Src/Zle/deltochar.c index 0c64cf18d..d56798687 100644 --- a/Src/Zle/deltochar.c +++ b/Src/Zle/deltochar.c @@ -95,7 +95,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -103,7 +103,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -119,7 +119,7 @@ boot_(Module m) return 0; deletezlefunction(w_deletetochar); } - zwarnnam(m->nam, "deltochar: name clash when adding ZLE functions"); + zwarnnam(m->node.nam, "deltochar: name clash when adding ZLE functions"); return -1; } @@ -129,7 +129,7 @@ cleanup_(Module m) { deletezlefunction(w_deletetochar); deletezlefunction(w_zaptochar); - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index d2a665188..463ff157f 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -1827,7 +1827,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -1835,7 +1835,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -1844,7 +1844,7 @@ boot_(Module m) { addhookfunc("before_trap", (Hookfn) zlebeforetrap); addhookfunc("after_trap", (Hookfn) zleaftertrap); - (void)addhookdefs(m->nam, zlehooks, sizeof(zlehooks)/sizeof(*zlehooks)); + (void)addhookdefs(m, zlehooks, sizeof(zlehooks)/sizeof(*zlehooks)); return 0; } @@ -1853,13 +1853,14 @@ int cleanup_(Module m) { if(zleactive) { - zerrnam(m->nam, "can't unload the zle module while zle is active"); + zerrnam(m->node.nam, + "can't unload the zle module while zle is active"); return 1; } deletehookfunc("before_trap", (Hookfn) zlebeforetrap); deletehookfunc("after_trap", (Hookfn) zleaftertrap); - (void)deletehookdefs(m->nam, zlehooks, sizeof(zlehooks)/sizeof(*zlehooks)); - return setfeatureenables(m->nam, &module_features, NULL); + (void)deletehookdefs(m, zlehooks, sizeof(zlehooks)/sizeof(*zlehooks)); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/Zle/zleparameter.c b/Src/Zle/zleparameter.c index 1b84fdff7..ab988d6df 100644 --- a/Src/Zle/zleparameter.c +++ b/Src/Zle/zleparameter.c @@ -56,7 +56,7 @@ widgetstr(Widget w) /**/ static HashNode -getpmwidgets(UNUSED(HashTable ht), char *name) +getpmwidgets(UNUSED(HashTable ht), const char *name) { Param pm = NULL; Thingy th; @@ -129,16 +129,16 @@ static const struct gsu_array keymaps_gsu = { keymapsgetfn, arrsetfn, stdunsetfn }; static struct paramdef partab[] = { - SPECIALPMDEF("widgets", PM_READONLY, - &zlestdhash_gsu, getpmwidgets, scanpmwidgets), SPECIALPMDEF("keymaps", PM_ARRAY|PM_READONLY, &keymaps_gsu, NULL, NULL), + SPECIALPMDEF("widgets", PM_READONLY, + &zlestdhash_gsu, getpmwidgets, scanpmwidgets) }; static struct features module_features = { NULL, 0, NULL, 0, - partab, sizeof(partab)/sizeof(*partab), NULL, 0, + partab, sizeof(partab)/sizeof(*partab), 0 }; @@ -153,7 +153,7 @@ setup_(UNUSED(Module m)) int features_(Module m, char ***features) { - *features = featuresarray(m->nam, &module_features); + *features = featuresarray(m, &module_features); return 0; } @@ -161,7 +161,7 @@ features_(Module m, char ***features) int enables_(Module m, int **enables) { - return handlefeatures(m->nam, &module_features, enables); + return handlefeatures(m, &module_features, enables); } /**/ @@ -175,7 +175,7 @@ boot_(UNUSED(Module m)) int cleanup_(Module m) { - return setfeatureenables(m->nam, &module_features, NULL); + return setfeatureenables(m, &module_features, NULL); } /**/ diff --git a/Src/builtin.c b/Src/builtin.c index 20bc37c21..7420ed887 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -250,7 +250,7 @@ execbuiltin(LinkList args, Builtin bn) name = (char *) ugetnode(args); if (!bn->handlerfunc) { - zwarnnam(name, "autoload failed"); + DPUTS(1, "Missing builtin detected too late"); deletebuiltin(bn->node.nam); return 1; } diff --git a/Src/cond.c b/Src/cond.c index 4356e5d66..e455882bb 100644 --- a/Src/cond.c +++ b/Src/cond.c @@ -96,11 +96,7 @@ evalcond(Estate state, char *fromtest) { char *modname = isset(REMATCHPCRE) ? "zsh/pcre" : "zsh/regex"; sprintf(overridename = overridebuf, "-%s-match", modname+4); - if (ensurefeature(modname, "c:", overridename+1)) { - zwarnnam(fromtest, "%s not available for regex", - modname); - return 2; - } + (void)ensurefeature(modname, "c:", overridename+1); ctype = COND_MODI; } /*FALLTHROUGH*/ @@ -129,7 +125,7 @@ evalcond(Estate state, char *fromtest) if ((cd = getconddef((ctype == COND_MODI), name + 1, 1))) { if (ctype == COND_MOD && (l < cd->min || (cd->max >= 0 && l > cd->max))) { - zwarnnam(fromtest, "unrecognized condition: `%s'", name); + zwarnnam(fromtest, "unknown condition: -%s", name); return 2; } if (tracingcond) @@ -139,13 +135,23 @@ evalcond(Estate state, char *fromtest) else { char *s = strs[0]; + if (overridename) { + /* + * Standard regex function not available: this + * is a hard error. + */ + zerrnam(fromtest, "%s not available for regex", + overridename); + return 2; + } + strs[0] = dupstring(name); name = s; if (name && name[0] == '-' && (cd = getconddef(0, name + 1, 1))) { if (l < cd->min || (cd->max >= 0 && l > cd->max)) { - zwarnnam(fromtest, "unrecognized condition: `%s'", + zwarnnam(fromtest, "unknown condition: -%s", name); return 2; } @@ -154,7 +160,7 @@ evalcond(Estate state, char *fromtest) return !cd->handler(strs, cd->condid); } else { zwarnnam(fromtest, - "unrecognized condition: `%s'", + "unknown condition: -%s", name ? name : "<null>"); } } diff --git a/Src/exec.c b/Src/exec.c index 0aee2d6a9..015753a83 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -871,7 +871,7 @@ execlist(Estate state, int dont_change_job, int exiting) /* Loop over all sets of comands separated by newline, * * semi-colon or ampersand (`sublists'). */ code = *state->pc++; - while (wc_code(code) == WC_LIST && !breaks && !retflag) { + while (wc_code(code) == WC_LIST && !breaks && !retflag && !errflag) { int donedebug; ltype = WC_LIST_TYPE(code); @@ -1915,6 +1915,34 @@ execsubst(LinkList strs) } } +/* + * Check if a builtin requires an autoload and if so + * deal with it. This may return NULL. + */ + +/**/ +static HashNode +resolvebuiltin(const char *cmdarg, HashNode hn) +{ + if (!((Builtin) hn)->handlerfunc) { + /* + * Ensure the module is loaded and the + * feature corresponding to the builtin + * is enabled. + */ + (void)ensurefeature(((Builtin) hn)->optstr, "b:", + (hn->flags & BINF_AUTOALL) ? NULL : + hn->nam); + hn = builtintab->getnode(builtintab, cmdarg); + if (!hn) { + lastval = 1; + zerr("unknown builtin: %s"); + return NULL; + } + } + return hn; +} + /**/ static void execcmd(Estate state, int input, int output, int how, int last1) @@ -2011,16 +2039,9 @@ execcmd(Estate state, int input, int output, int how, int last1) is_builtin = 1; /* autoload the builtin if necessary */ - if (!((Builtin) hn)->handlerfunc) { - /* - * Ensure the module is loaded and the - * feature corresponding to the builtin - * is enabled. - */ - (void)ensurefeature(((Builtin) hn)->optstr, "b:", hn->nam); - hn = builtintab->getnode(builtintab, cmdarg); - } - assign = (hn && (hn->flags & BINF_MAGICEQUALS)); + if (!(hn = resolvebuiltin(cmdarg, hn))) + return; + assign = (hn->flags & BINF_MAGICEQUALS); break; } cflags &= ~BINF_BUILTIN & ~BINF_COMMAND; @@ -2233,10 +2254,8 @@ execcmd(Estate state, int input, int output, int how, int last1) is_builtin = 1; /* autoload the builtin if necessary */ - if (!((Builtin) hn)->handlerfunc) { - (void)ensurefeature(((Builtin) hn)->optstr, "b:", cmdarg); - hn = builtintab->getnode(builtintab, cmdarg); - } + if (!(hn = resolvebuiltin(cmdarg, hn))) + return; break; } cflags &= ~BINF_BUILTIN & ~BINF_COMMAND; @@ -4104,8 +4123,8 @@ runshfunc(Eprog prog, FuncWrap wrap, char *name) wrap->module->wrapper--; if (!wrap->module->wrapper && - (wrap->module->flags & MOD_UNLOAD)) - unload_module(wrap->module, NULL); + (wrap->module->node.flags & MOD_UNLOAD)) + unload_module(wrap->module); if (!cont) return; diff --git a/Src/hashtable.c b/Src/hashtable.c index 669990566..d820c4fd4 100644 --- a/Src/hashtable.c +++ b/Src/hashtable.c @@ -78,7 +78,7 @@ static HashTable firstht, lastht; /**/ mod_export unsigned -hasher(char *str) +hasher(const char *str) { unsigned hashval = 0, c; @@ -223,7 +223,7 @@ addhashnode2(HashTable ht, char *nam, void *nodeptr) /**/ mod_export HashNode -gethashnode(HashTable ht, char *nam) +gethashnode(HashTable ht, const char *nam) { unsigned hashval; HashNode hp; @@ -247,7 +247,7 @@ gethashnode(HashTable ht, char *nam) /**/ mod_export HashNode -gethashnode2(HashTable ht, char *nam) +gethashnode2(HashTable ht, const char *nam) { unsigned hashval; HashNode hp; @@ -267,7 +267,7 @@ gethashnode2(HashTable ht, char *nam) /**/ mod_export HashNode -removehashnode(HashTable ht, char *nam) +removehashnode(HashTable ht, const char *nam) { unsigned hashval; HashNode hp, hq; @@ -795,7 +795,7 @@ createshfunctable(void) /**/ static HashNode -removeshfuncnode(UNUSED(HashTable ht), char *nam) +removeshfuncnode(UNUSED(HashTable ht), const char *nam) { HashNode hn; int signum; @@ -1378,7 +1378,7 @@ addnameddirnode(HashTable ht, char *nam, void *nodeptr) /**/ static HashNode -removenameddirnode(HashTable ht, char *nam) +removenameddirnode(HashTable ht, const char *nam) { HashNode hn = removehashnode(ht, nam); @@ -1453,7 +1453,7 @@ createhisttable(void) /**/ unsigned -histhasher(char *str) +histhasher(const char *str) { unsigned hashval = 0; diff --git a/Src/init.c b/Src/init.c index 13078ea2e..e885c79b6 100644 --- a/Src/init.c +++ b/Src/init.c @@ -701,7 +701,7 @@ setupvals(void) close(tmppipe[1]); } - (void)addhookdefs(argzero, zshhooks, sizeof(zshhooks)/sizeof(*zshhooks)); + (void)addhookdefs(NULL, zshhooks, sizeof(zshhooks)/sizeof(*zshhooks)); init_eprog(); @@ -769,7 +769,7 @@ setupvals(void) watch = mkarray(NULL); psvar = mkarray(NULL); module_path = mkarray(ztrdup(MODULE_DIR)); - modules = znewlinklist(); + modulestab = newmoduletable(17, "modules"); linkedmodules = znewlinklist(); /* Set default prompts */ diff --git a/Src/jobs.c b/Src/jobs.c index b02922a03..129da7d57 100644 --- a/Src/jobs.c +++ b/Src/jobs.c @@ -2147,7 +2147,7 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) /**/ mod_export int -getsignum(char *s) +getsignum(const char *s) { int x, i; @@ -2205,7 +2205,7 @@ gettrapnode(int sig, int ignoredisable) { char fname[20]; HashNode hn; - HashNode (*getptr)(HashTable ht, char *name); + HashNode (*getptr)(HashTable ht, const char *name); int i; if (ignoredisable) getptr = shfunctab->getnode2; diff --git a/Src/mkbltnmlst.sh b/Src/mkbltnmlst.sh index d636550ac..005e2ef81 100644 --- a/Src/mkbltnmlst.sh +++ b/Src/mkbltnmlst.sh @@ -37,8 +37,7 @@ for x_mod in $x_mods; do echo "/* non-linked-in known module \`$x_mod' */" linked=no esac - unset moddeps autobins autoinfixconds autoprefixconds autoparams - unset automathfuncs + unset moddeps autofeatures . $srcdir/../$modfile if test "x$autofeatures" != x; then echo " if (emulation == EMULATE_ZSH) {" diff --git a/Src/module.c b/Src/module.c index c82d77373..765f7c941 100644 --- a/Src/module.c +++ b/Src/module.c @@ -24,13 +24,16 @@ * provided hereunder is on an "as is" basis, and Zoltán Hidvégi and the * Zsh Development Group have no obligation to provide maintenance, * support, updates, enhancements, or modifications. - * */ #include "zsh.mdh" #include "module.pro" -/* List of linked-in modules. */ +/* + * List of linked-in modules. + * This is set up at boot and remains for the life of the shell; + * entries do not appear in "zmodload" listings. + */ /**/ LinkList linkedmodules; @@ -40,19 +43,42 @@ LinkList linkedmodules; /**/ char **module_path; -/* List of modules */ +/* Hash of modules */ /**/ -mod_export LinkList modules; +mod_export HashTable modulestab; /* * Bit flags passed as the "flags" argument of a autofeaturefn_t. + * Used in other places, such as the final argument to + * do_module_features(). */ enum { - /* `-i' option: ignore errors pertaining to redefinitions */ - AUTOFEAT_IGNORE = 0x0001, + /* + * `-i' option: ignore errors pertaining to redefinitions, + * or indicate to do_module_features() that it should be + * silent. + */ + FEAT_IGNORE = 0x0001, /* If a condition, condition is infix rather than prefix */ - AUTOFEAT_INFIX = 0x0002 + FEAT_INFIX = 0x0002, + /* + * Enable all features in the module when autoloading. + * This is the traditional zmodload -a behaviour; + * zmodload -Fa only enables features explicitly marked for + * autoloading. + */ + FEAT_AUTOALL = 0x0004, + /* + * Remove feature: alternative to "-X:NAME" used if + * X is passed separately from NAME. + */ + FEAT_REMOVE = 0x0008, + /* + * For do_module_features(). Check that any autoloads + * for the module are actually provided. + */ + FEAT_CHECKAUTO = 0x0010 }; /* @@ -65,7 +91,7 @@ enum { * * "flags" is a set of the bits above. * - * The return value is 0 for success, a negative value for failure with no + * The return value is 0 for success, -1 for failure with no * message needed, and one of the following to indicate the calling * function should print a message: * @@ -73,7 +99,199 @@ enum { * 2: [feature]: no such [type] * 3: [feature]: [type] is already defined */ -typedef int (*autofeaturefn_t)(char *module, char *feature, int flags); +typedef int (*autofeaturefn_t)(const char *module, const char *feature, + int flags); + +/* Bits in the second argument to find_module. */ +enum { + /* + * Resolve any aliases to the underlying module. + */ + FINDMOD_ALIASP = 0x0001, + /* + * Create an element for the module in the list if + * it is not found. + */ + FINDMOD_CREATE = 0x0002, +}; + +static void +freemodulenode(HashNode hn) +{ + Module m = (Module) hn; + + if (m->node.flags & MOD_ALIAS) + zsfree(m->u.alias); + zsfree(m->node.nam); + if (m->autoloads) + freelinklist(m->autoloads, freestr); + if (m->deps) + freelinklist(m->deps, freestr); + zfree(m, sizeof(*m)); +} + +/* flags argument to printmodulenode */ +enum { + /* -L flag, output zmodload commands */ + PRINTMOD_LIST = 0x0001, + /* -e flag */ + PRINTMOD_EXIST = 0x0002, + /* -A flag */ + PRINTMOD_ALIAS = 0x0004, + /* -d flag */ + PRINTMOD_DEPS = 0x0008, + /* -F flag */ + PRINTMOD_FEATURES = 0x0010, + /* -l flag in combination with -L flag */ + PRINTMOD_LISTALL = 0x0020, + /* -a flag */ + PRINTMOD_AUTO = 0x0040 +}; + +/* Scan function for printing module details */ + +static void +printmodulenode(HashNode hn, int flags) +{ + Module m = (Module)hn; + /* + * If we check for a module loaded under an alias, we + * need the name of the alias. We can use it in other + * cases, too. + */ + const char *modname = m->node.nam; + + if (flags & PRINTMOD_DEPS) { + /* + * Print the module's dependencies. + */ + LinkNode n; + + if (!m->deps) + return; + + if (flags & PRINTMOD_LIST) { + printf("zmodload -d "); + if (modname[0] == '-') + fputs("-- ", stdout); + quotedzputs(modname, stdout); + } else { + nicezputs(modname, stdout); + putchar(':'); + } + for (n = firstnode(m->deps); n; incnode(n)) { + putchar(' '); + if (flags & PRINTMOD_LIST) + quotedzputs((char *) getdata(n), stdout); + else + nicezputs((char *) getdata(n), stdout); + } + } else if (flags & PRINTMOD_EXIST) { + /* + * Just print the module name, provided the module is + * present under an alias or otherwise. + */ + if (m->node.flags & MOD_ALIAS) { + if (!(flags & PRINTMOD_ALIAS) || + !(m = find_module(m->u.alias, FINDMOD_ALIASP, NULL))) + return; + } + if (!m->u.handle || (m->node.flags & MOD_UNLOAD)) + return; + nicezputs(modname, stdout); + } else if (m->node.flags & MOD_ALIAS) { + /* + * Normal listing, but for aliases. + */ + if (flags & PRINTMOD_LIST) { + printf("zmodload -A "); + if (modname[0] == '-') + fputs("-- ", stdout); + quotedzputs(modname, stdout); + putchar('='); + quotedzputs(m->u.alias, stdout); + } else { + nicezputs(modname, stdout); + fputs(" -> ", stdout); + nicezputs(m->u.alias, stdout); + } + } else if (m->u.handle) { + /* + * Loaded module. + */ + if (flags & PRINTMOD_LIST) { + /* + * List with -L format. Possibly we are printing + * features, either enables or autoloads. + */ + char **features = NULL; + int *enables = NULL; + if (flags & PRINTMOD_AUTO) { + if (!m->autoloads || !firstnode(m->autoloads)) + return; + } else if (flags & PRINTMOD_FEATURES) { + if (features_module(m, &features) || + enables_module(m, &enables) || + !*features) + return; + } + printf("zmodload "); + if (flags & PRINTMOD_AUTO) { + fputs("-Fa ", stdout); + } else if (features) + fputs("-F ", stdout); + if(modname[0] == '-') + fputs("-- ", stdout); + quotedzputs(modname, stdout); + if (flags & PRINTMOD_AUTO) { + LinkNode an; + for (an = firstnode(m->autoloads); an; incnode(an)) { + putchar(' '); + quotedzputs((char *)getdata(an), stdout); + } + } else if (features) { + const char *f; + while ((f = *features++)) { + int on = *enables++; + if (flags & PRINTMOD_LISTALL) + printf(" %s", on ? "+" : "-"); + else if (!on) + continue; + else + putchar(' '); + quotedzputs(f, stdout); + } + } + } else /* -l */ + nicezputs(modname, stdout); + } else + return; + putchar('\n'); +} + +/**/ +HashTable +newmoduletable(int size, char const *name) +{ + HashTable ht; + ht = newhashtable(size, name, NULL); + + ht->hash = hasher; + ht->emptytable = emptyhashtable; + ht->filltable = NULL; + ht->cmpnodes = strcmp; + ht->addnode = addhashnode; + /* DISABLED is not supported */ + ht->getnode = gethashnode2; + ht->getnode2 = gethashnode2; + ht->removenode = removehashnode; + ht->disablenode = NULL; + ht->enablenode = NULL; + ht->freenode = freemodulenode; + ht->printnode = printmodulenode; + + return ht; +} /************************************************************************ * zsh/main standard module functions @@ -160,27 +378,6 @@ register_module(char *n, Module_void_func setup, zaddlinknode(linkedmodules, m); } -/* Print an alias. */ - -/**/ -static void -printmodalias(Module m, Options ops) -{ - if (OPT_ISSET(ops,'L')) { - printf("zmodload -A "); - if (m->nam[0] == '-') - fputs("-- ", stdout); - quotedzputs(m->nam, stdout); - putchar('='); - quotedzputs(m->u.alias, stdout); - } else { - nicezputs(m->nam, stdout); - fputs(" -> ", stdout); - nicezputs(m->u.alias, stdout); - } - putchar('\n'); -} - /* Check if a module is linked in. */ /**/ @@ -208,7 +405,7 @@ module_linked(char const *name) * builtin can be replaced using this function. */ /**/ -int +static int addbuiltin(Builtin b) { Builtin bn = (Builtin) builtintab->getnode2(builtintab, b->node.nam); @@ -226,16 +423,19 @@ addbuiltin(Builtin b) /**/ static int -add_autobin(char *module, char *bnam, int flags) +add_autobin(const char *module, const char *bnam, int flags) { Builtin bn; + int ret; bn = zshcalloc(sizeof(*bn)); bn->node.nam = ztrdup(bnam); bn->optstr = ztrdup(module); - if (addbuiltin(bn)) { + if (flags & FEAT_AUTOALL) + bn->node.flags |= BINF_AUTOALL; + if ((ret = addbuiltin(bn))) { builtintab->freenode(&bn->node); - if (!(flags & AUTOFEAT_IGNORE)) + if (!(flags & FEAT_IGNORE)) return 1; } return 0; @@ -246,7 +446,7 @@ add_autobin(char *module, char *bnam, int flags) /**/ int -deletebuiltin(char *nam) +deletebuiltin(const char *nam) { Builtin bn; @@ -261,14 +461,15 @@ deletebuiltin(char *nam) /**/ static int -del_autobin(UNUSED(char *module), char *bnam, int flags) +del_autobin(UNUSED(const char *module), const char *bnam, int flags) { Builtin bn = (Builtin) builtintab->getnode2(builtintab, bnam); if (!bn) { - if(!(flags & AUTOFEAT_IGNORE)) + if(!(flags & FEAT_IGNORE)) return 2; } else if (bn->node.flags & BINF_ADDED) { - return 3; + if (!(flags & FEAT_IGNORE)) + return 3; } else deletebuiltin(bnam); @@ -383,7 +584,7 @@ addwrapper(Module m, FuncWrap w) * happen since we usually add wrappers when a real module is * loaded. */ - if (m->flags & MOD_ALIAS) + if (m->node.flags & MOD_ALIAS) return 1; if (w->flags & WRAPF_ADDED) @@ -409,7 +610,7 @@ deletewrapper(Module m, FuncWrap w) { FuncWrap p, q; - if (m->flags & MOD_ALIAS) + if (m->node.flags & MOD_ALIAS) return 1; if (w->flags & WRAPF_ADDED) { @@ -444,7 +645,7 @@ mod_export Conddef condtab; /**/ Conddef -getconddef(int inf, char *name, int autol) +getconddef(int inf, const char *name, int autol) { Conddef p; int f = 1; @@ -462,8 +663,8 @@ getconddef(int inf, char *name, int autol) */ if (f) { (void)ensurefeature(p->module, - (p->flags & CONDF_INFIX) ? - "C:" : "c:", name); + (p->flags & CONDF_INFIX) ? "C:" : "c:", + (p->flags & CONDF_AUTOALL) ? NULL : name); f = 0; p = NULL; } else { @@ -577,14 +778,16 @@ setconddefs(char const *nam, Conddef c, int size, int *e) /**/ static int -add_autocond(char *module, char *cnam, int flags) +add_autocond(const char *module, const char *cnam, int flags) { Conddef c; c = (Conddef) zalloc(sizeof(*c)); c->name = ztrdup(cnam); - c->flags = ((flags & AUTOFEAT_INFIX) ? CONDF_INFIX : 0); + c->flags = ((flags & FEAT_INFIX) ? CONDF_INFIX : 0); + if (flags & FEAT_AUTOALL) + c->flags |= CONDF_AUTOALL; c->module = ztrdup(module); if (addconddef(c)) { @@ -592,7 +795,7 @@ add_autocond(char *module, char *cnam, int flags) zsfree(c->module); zfree(c, sizeof(*c)); - if (!(flags & AUTOFEAT_IGNORE)) + if (!(flags & FEAT_IGNORE)) return 1; } return 0; @@ -602,16 +805,17 @@ add_autocond(char *module, char *cnam, int flags) /**/ static int -del_autocond(UNUSED(char *modnam), char *cnam, int flags) +del_autocond(UNUSED(const char *modnam), const char *cnam, int flags) { - Conddef cd = getconddef((flags & AUTOFEAT_INFIX) ? 1 : 0, cnam, 0); + Conddef cd = getconddef((flags & FEAT_INFIX) ? 1 : 0, cnam, 0); if (!cd) { - if (!(flags & AUTOFEAT_IGNORE)) { + if (!(flags & FEAT_IGNORE)) { return 2; } } else if (cd->flags & CONDF_ADDED) { - return 3; + if (!(flags & FEAT_IGNORE)) + return 3; } else deleteconddef(cd); @@ -658,17 +862,21 @@ addhookdef(Hookdef h) return 0; } -/* This adds multiple hook definitions. This is like addbuiltins(). */ +/* + * This adds multiple hook definitions. This is like addbuiltins(). + * This allows a NULL module because we call it from init.c. + */ /**/ mod_export int -addhookdefs(char const *nam, Hookdef h, int size) +addhookdefs(Module m, Hookdef h, int size) { int ret = 0; while (size--) { if (addhookdef(h)) { - zwarnnam(nam, "name clash when adding hook `%s'", h->name); + zwarnnam(m ? m->node.nam : NULL, + "name clash when adding hook `%s'", h->name); ret = 1; } h++; @@ -701,7 +909,7 @@ deletehookdef(Hookdef h) /**/ mod_export int -deletehookdefs(UNUSED(char const *nam), Hookdef h, int size) +deletehookdefs(UNUSED(Module m), Hookdef h, int size) { int ret = 0; @@ -804,7 +1012,7 @@ runhookdef(Hookdef h, void *d) */ static int -checkaddparam(char *nam, int opt_i) +checkaddparam(const char *nam, int opt_i) { Param pm; @@ -970,13 +1178,13 @@ setparamdefs(char const *nam, Paramdef d, int size, int *e) /**/ static int -add_autoparam(char *module, char *pnam, int flags) +add_autoparam(const char *module, const char *pnam, int flags) { Param pm; int ret; queue_signals(); - if ((ret = checkaddparam(pnam, (flags & AUTOFEAT_IGNORE)))) { + if ((ret = checkaddparam(pnam, (flags & FEAT_IGNORE)))) { unqueue_signals(); /* * checkaddparam() has already printed a message if one was @@ -988,9 +1196,11 @@ add_autoparam(char *module, char *pnam, int flags) return ret == 2 ? 0 : -1; } - pm = setsparam(pnam, ztrdup(module)); + pm = setsparam(dupstring(pnam), ztrdup(module)); pm->node.flags |= PM_AUTOLOAD; + if (flags & FEAT_AUTOALL) + pm->node.flags |= PM_AUTOALL; unqueue_signals(); return 0; @@ -1000,15 +1210,16 @@ add_autoparam(char *module, char *pnam, int flags) /**/ static int -del_autoparam(UNUSED(char *modnam), char *pnam, int flags) +del_autoparam(UNUSED(const char *modnam), const char *pnam, int flags) { Param pm = (Param) gethashnode2(paramtab, pnam); if (!pm) { - if (!(flags & AUTOFEAT_IGNORE)) + if (!(flags & FEAT_IGNORE)) return 2; } else if (!(pm->node.flags & PM_AUTOLOAD)) { - return 3; + if (!(flags & FEAT_IGNORE)) + return 3; } else unsetparam_pm(pm, 0, 1); @@ -1047,7 +1258,7 @@ removemathfunc(MathFunc previous, MathFunc current) /**/ MathFunc -getmathfunc(char *name, int autol) +getmathfunc(const char *name, int autol) { MathFunc p, q = NULL; @@ -1058,7 +1269,8 @@ getmathfunc(char *name, int autol) removemathfunc(q, p); - (void)ensurefeature(n, "f:", name); + (void)ensurefeature(n, "f:", (p->flags & MFF_AUTOALL) ? NULL : + name); return getmathfunc(name, 0); } @@ -1171,7 +1383,7 @@ setmathfuncs(char const *nam, MathFunc f, int size, int *e) /**/ static int -add_automathfunc(char *module, char *fnam, int flags) +add_automathfunc(const char *module, const char *fnam, int flags) { MathFunc f; @@ -1186,7 +1398,7 @@ add_automathfunc(char *module, char *fnam, int flags) zsfree(f->module); zfree(f, sizeof(*f)); - if (!(flags & AUTOFEAT_IGNORE)) + if (!(flags & FEAT_IGNORE)) return 1; } @@ -1197,15 +1409,16 @@ add_automathfunc(char *module, char *fnam, int flags) /**/ static int -del_automathfunc(UNUSED(char *modnam), char *fnam, int flags) +del_automathfunc(UNUSED(const char *modnam), const char *fnam, int flags) { MathFunc f = getmathfunc(fnam, 0); if (!f) { - if (!(flags & AUTOFEAT_IGNORE)) + if (!(flags & FEAT_IGNORE)) return 2; } else if (f->flags & MFF_ADDED) { - return 3; + if (!(flags & FEAT_IGNORE)) + return 3; } else deletemathfunc(f); @@ -1233,13 +1446,15 @@ load_and_bind(const char *fn) void *ret = (void *) load((char *) fn, L_NOAUTODEFER, NULL); if (ret) { - LinkNode node; - int err = loadbind(0, (void *) addbuiltin, ret); - for (node = firstnode(modules); !err && node; incnode(node)) { - Module m = (Module) getdata(node); - if (!(m->flags & MOD_ALIAS) && - m->u.handle && !(m->flags & MOD_LINKED)) - err |= loadbind(0, m->u.handle, ret); + Module m; + int i, err = loadbind(0, (void *) addbuiltin, ret); + for (i = 0; i < modulestab->hsize && !err; i++) { + for (m = (Module)modulestab->nodes[i]; m && !err; + m = m->node.next) { + if (!(m->flags & MOD_ALIAS) && + m->u.handle && !(m->flags & MOD_LINKED)) + err |= loadbind(0, m->u.handle, ret); + } } if (err) { @@ -1256,6 +1471,9 @@ load_and_bind(const char *fn) #define dlopen(X,Y) load_and_bind(X) #define dlclose(X) unload(X) #define dlerror() (dlerrstr[0]) +#ifndef HAVE_DLERROR +# define HAVE_DLERROR 1 +#endif /**/ #else @@ -1294,7 +1512,9 @@ hpux_dlsym(void *handle, char *name) } # define dlsym(handle,name) hpux_dlsym(handle,name) -# define dlerror() 0 +# ifdef HAVE_DLERROR /* paranoia */ +# undef HAVE_DLERROR +# endif #else # ifndef HAVE_DLCLOSE # define dlclose(X) ((X), 0) @@ -1366,8 +1586,13 @@ do_load_module(char const *name, int silent) void *ret; ret = try_load_module(name); - if (!ret && !silent) + if (!ret && !silent) { +#ifdef HAVE_DLERROR + zwarn("failed to load module `%s': %s", name, dlerror()); +#else zwarn("failed to load module: %s", name); +#endif + } return ret; } @@ -1391,19 +1616,6 @@ do_load_module(char const *name, int silent) /**/ #endif /* !DYNAMIC */ -/* Bits in the second argument to find_module. */ -enum { - /* - * Resolve any aliases to the underlying module. - */ - FINDMOD_ALIASP = 0x0001, - /* - * Create an element for the module in the list if - * it is not found. - */ - FINDMOD_CREATE = 0x0002, -}; - /* * Find a module in the list. * flags is a set of bits defined in the enum above. @@ -1413,35 +1625,29 @@ enum { * Return NULL if the module named is not stored as a structure, or if we were * resolving aliases and the final module named is not stored as a * structure. - * - * TODO: now we have aliases, there may be some merit in using a hash - * table instead of a linked list. */ /**/ -static LinkNode +static Module find_module(const char *name, int flags, const char **namep) { Module m; - LinkNode node; - for (node = firstnode(modules); node; incnode(node)) { - m = (Module) getdata(node); - if (!strcmp(m->nam, name)) { - if ((flags & FINDMOD_ALIASP) && (m->flags & MOD_ALIAS)) { - if (namep) - *namep = m->u.alias; - return find_module(m->u.alias, flags, namep); - } + m = (Module)modulestab->getnode2(modulestab, name); + if (m) { + if ((flags & FINDMOD_ALIASP) && (m->node.flags & MOD_ALIAS)) { if (namep) - *namep = m->nam; - return node; + *namep = m->u.alias; + return find_module(m->u.alias, flags, namep); } + if (namep) + *namep = m->node.nam; + return m; } if (!(flags & FINDMOD_CREATE)) return NULL; m = zshcalloc(sizeof(*m)); - m->nam = ztrdup(name); - return zaddlinknode(modules, m); + modulestab->addnode(modulestab, ztrdup(name), m); + return m; } /* @@ -1450,16 +1656,11 @@ find_module(const char *name, int flags, const char **namep) /**/ static void -delete_module(LinkNode node) +delete_module(Module m) { - Module m = (Module) remnode(modules, node); + modulestab->removenode(modulestab, m->node.nam); - if (m->flags & MOD_ALIAS) - zsfree(m->u.alias); - zsfree(m->nam); - if (m->deps) - freelinklist(m->deps, freestr); - zfree(m, sizeof(*m)); + modulestab->freenode(&m->node); } /* @@ -1473,12 +1674,11 @@ delete_module(LinkNode node) mod_export int module_loaded(const char *name) { - LinkNode node; Module m; - return ((node = find_module(name, FINDMOD_ALIASP, NULL)) && - (m = ((Module) getdata(node)))->u.handle && - !(m->flags & MOD_UNLOAD)); + return ((m = find_module(name, FINDMOD_ALIASP, NULL)) && + m->u.handle && + !(m->node.flags & MOD_UNLOAD)); } /* @@ -1575,7 +1775,7 @@ dyn_setup_module(Module m) if (fn) return fn(m); - zwarnnam(m->nam, "no setup function"); + zwarnnam(m->node.nam, "no setup function"); return 1; } @@ -1612,7 +1812,7 @@ dyn_boot_module(Module m) if(fn) return fn(m); - zwarnnam(m->nam, "no boot function"); + zwarnnam(m->node.nam, "no boot function"); return 1; } @@ -1624,7 +1824,7 @@ dyn_cleanup_module(Module m) if(fn) return fn(m); - zwarnnam(m->nam, "no cleanup function"); + zwarnnam(m->node.nam, "no cleanup function"); return 1; } @@ -1641,7 +1841,7 @@ dyn_finish_module(Module m) if (fn) r = fn(m); else { - zwarnnam(m->nam, "no finish function"); + zwarnnam(m->node.nam, "no finish function"); r = 1; } dlclose(m->u.handle); @@ -1655,7 +1855,7 @@ dyn_finish_module(Module m) static int setup_module(Module m) { - return ((m->flags & MOD_LINKED) ? + return ((m->node.flags & MOD_LINKED) ? (m->u.linked->setup)(m) : dyn_setup_module(m)); } @@ -1663,7 +1863,7 @@ setup_module(Module m) static int features_module(Module m, char ***features) { - return ((m->flags & MOD_LINKED) ? + return ((m->node.flags & MOD_LINKED) ? (m->u.linked->features)(m, features) : dyn_features_module(m, features)); } @@ -1672,7 +1872,7 @@ features_module(Module m, char ***features) static int enables_module(Module m, int **enables) { - return ((m->flags & MOD_LINKED) ? + return ((m->node.flags & MOD_LINKED) ? (m->u.linked->enables)(m, enables) : dyn_enables_module(m, enables)); } @@ -1681,7 +1881,7 @@ enables_module(Module m, int **enables) static int boot_module(Module m) { - return ((m->flags & MOD_LINKED) ? + return ((m->node.flags & MOD_LINKED) ? (m->u.linked->boot)(m) : dyn_boot_module(m)); } @@ -1689,7 +1889,7 @@ boot_module(Module m) static int cleanup_module(Module m) { - return ((m->flags & MOD_LINKED) ? + return ((m->node.flags & MOD_LINKED) ? (m->u.linked->cleanup)(m) : dyn_cleanup_module(m)); } @@ -1697,7 +1897,7 @@ cleanup_module(Module m) static int finish_module(Module m) { - return ((m->flags & MOD_LINKED) ? + return ((m->node.flags & MOD_LINKED) ? (m->u.linked->finish)(m) : dyn_finish_module(m)); } @@ -1708,14 +1908,14 @@ finish_module(Module m) static int setup_module(Module m) { - return ((m->flags & MOD_LINKED) ? (m->u.linked->setup)(m) : 1); + return ((m->node.flags & MOD_LINKED) ? (m->u.linked->setup)(m) : 1); } /**/ static int features_module(Module m, char ***features) { - return ((m->flags & MOD_LINKED) ? (m->u.linked->features)(m, features) + return ((m->node.flags & MOD_LINKED) ? (m->u.linked->features)(m, features) : 1); } @@ -1723,7 +1923,7 @@ features_module(Module m, char ***features) static int enables_module(Module m, int **enables) { - return ((m->flags & MOD_LINKED) ? (m->u.linked->enables)(m, enables) + return ((m->node.flags & MOD_LINKED) ? (m->u.linked->enables)(m, enables) : 1); } @@ -1731,21 +1931,21 @@ enables_module(Module m, int **enables) static int boot_module(Module m) { - return ((m->flags & MOD_LINKED) ? (m->u.linked->boot)(m) : 1); + return ((m->node.flags & MOD_LINKED) ? (m->u.linked->boot)(m) : 1); } /**/ static int cleanup_module(Module m) { - return ((m->flags & MOD_LINKED) ? (m->u.linked->cleanup)(m) : 1); + return ((m->node.flags & MOD_LINKED) ? (m->u.linked->cleanup)(m) : 1); } /**/ static int finish_module(Module m) { - return ((m->flags & MOD_LINKED) ? (m->u.linked->finish)(m) : 1); + return ((m->node.flags & MOD_LINKED) ? (m->u.linked->finish)(m) : 1); } /**/ @@ -1761,14 +1961,16 @@ finish_module(Module m) * by now (though may not be fully set up). * * Return 0 for success, 1 for failure, 2 if some features - * couldn't be set. + * couldn't be set by the module itself (non-existent features + * are tested here and cause 1 to be returned). */ /**/ static int -do_module_features(Module m, char **enablesstr, int silent) +do_module_features(Module m, char **enablesstr, int flags) { char **features; + int ret = 0; if (features_module(m, &features) == 0) { /* @@ -1781,12 +1983,62 @@ do_module_features(Module m, char **enablesstr, int silent) int *enables = NULL; if (enables_module(m, &enables)) { /* If features are supported, enables should be, too */ - if (!silent) + if (!(flags & FEAT_IGNORE)) zwarn("error getting enabled features for module `%s'", - m->nam); + m->node.nam); return 1; } + if ((flags & FEAT_CHECKAUTO) && m->autoloads) { + /* + * Check autoloads are available. Since these + * have been requested at some other point, they + * don't affect the return status unless something + * in enablesstr doesn't work. + */ + LinkNode an, nextn; + for (an = firstnode(m->autoloads); an; an = nextn) { + char *al = (char *)getdata(an), **ptr; + /* careful, we can delete the current node */ + nextn = nextnode(an); + for (ptr = features; *ptr; ptr++) + if (!strcmp(al, *ptr)) + break; + if (!*ptr) { + char *arg[2]; + if (!(flags & FEAT_IGNORE)) + zwarn( + "module `%s' has no such feature: `%s': autoload cancelled", + m->node.nam, al); + /* + * This shouldn't happen, so it's not worth optimising + * the call to autofeatures... + */ + arg[0] = al = dupstring(al); + arg[1] = NULL; + (void)autofeatures(NULL, m->node.nam, arg, 0, + FEAT_IGNORE|FEAT_REMOVE); + /* + * don't want to try to enable *that*... + * expunge it from the enable string. + */ + if (enablesstr) { + for (ptr = enablesstr; *ptr; ptr++) { + if (!strcmp(al, *ptr)) { + /* can't enable it after all, so return 1 */ + ret = 1; + while (*ptr) { + *ptr = ptr[1]; + ptr++; + } + break; + } + } + } + } + } + } + if (enablesstr) { char **ep; for (ep = enablesstr; *ep; ep++) { @@ -1804,9 +2056,9 @@ do_module_features(Module m, char **enablesstr, int silent) break; } if (!*fp) { - if (!silent) - zwarn("module `%s' has no such feature: %s", - m->nam, esp); + if (!(flags & FEAT_IGNORE)) + zwarn("module `%s' has no such feature: `%s'", + m->node.nam, esp); return 1; } } @@ -1824,13 +2076,13 @@ do_module_features(Module m, char **enablesstr, int silent) if (enables_module(m, &enables)) return 2; } else if (enablesstr) { - if (!silent) - zwarn("module `%s' does not support features", m->nam); + if (!(flags & FEAT_IGNORE)) + zwarn("module `%s' does not support features", m->node.nam); return 1; } /* Else it doesn't support features but we don't care. */ - return 0; + return ret; } /* @@ -1847,7 +2099,9 @@ do_module_features(Module m, char **enablesstr, int silent) static int do_boot_module(Module m, char **enablesstr, int silent) { - int ret = do_module_features(m, enablesstr, silent); + int ret = do_module_features(m, enablesstr, + silent ? FEAT_IGNORE|FEAT_CHECKAUTO : + FEAT_CHECKAUTO); if (ret == 1) return 1; @@ -1865,7 +2119,7 @@ do_boot_module(Module m, char **enablesstr, int silent) static int do_cleanup_module(Module m) { - return (m->flags & MOD_LINKED) ? + return (m->node.flags & MOD_LINKED) ? (m->u.linked && m->u.linked->cleanup(m)) : (m->u.handle && cleanup_module(m)); } @@ -1910,7 +2164,6 @@ load_module(char const *name, char **enablesstr, int silent) Module m; void *handle = NULL; Linkedmod linked; - LinkNode node, n; int set, bootret; if (!modname_ok(name)) { @@ -1924,66 +2177,65 @@ load_module(char const *name, char **enablesstr, int silent) * is the right one. */ queue_signals(); - if (!(node = find_module(name, FINDMOD_ALIASP, &name))) { + if (!(m = find_module(name, FINDMOD_ALIASP, &name))) { if (!(linked = module_linked(name)) && !(handle = do_load_module(name, silent))) { unqueue_signals(); return 1; } m = zshcalloc(sizeof(*m)); - m->nam = ztrdup(name); if (handle) { m->u.handle = handle; - m->flags |= MOD_SETUP; + m->node.flags |= MOD_SETUP; } else { m->u.linked = linked; - m->flags |= MOD_SETUP | MOD_LINKED; + m->node.flags |= MOD_SETUP | MOD_LINKED; } - node = zaddlinknode(modules, m); + modulestab->addnode(modulestab, ztrdup(name), m); if ((set = setup_module(m)) || (bootret = do_boot_module(m, enablesstr, silent)) == 1) { - if (!set) { + if (!set) do_cleanup_module(m); - finish_module(m); - } - delete_module(node); + finish_module(m); + delete_module(m); unqueue_signals(); return 1; } - m->flags |= MOD_INIT_S | MOD_INIT_B; - m->flags &= ~MOD_SETUP; + m->node.flags |= MOD_INIT_S | MOD_INIT_B; + m->node.flags &= ~MOD_SETUP; unqueue_signals(); return bootret; } - m = (Module) getdata(node); - if (m->flags & MOD_SETUP) { + if (m->node.flags & MOD_SETUP) { unqueue_signals(); return 0; } - if (m->flags & MOD_UNLOAD) - m->flags &= ~MOD_UNLOAD; - else if ((m->flags & MOD_LINKED) ? m->u.linked : m->u.handle) { + if (m->node.flags & MOD_UNLOAD) + m->node.flags &= ~MOD_UNLOAD; + else if ((m->node.flags & MOD_LINKED) ? m->u.linked : m->u.handle) { unqueue_signals(); return 0; } - if (m->flags & MOD_BUSY) { - zerr("circular dependencies for module %s", name); + if (m->node.flags & MOD_BUSY) { + zerr("circular dependencies for module ;%s", name); return 1; } - m->flags |= MOD_BUSY; + m->node.flags |= MOD_BUSY; /* * TODO: shouldn't we unload the module if one of * its dependencies fails? */ - if (m->deps) + if (m->deps) { + LinkNode n; for (n = firstnode(m->deps); n; incnode(n)) if (load_module((char *) getdata(n), NULL, silent) == 1) { - m->flags &= ~MOD_BUSY; + m->node.flags &= ~MOD_BUSY; unqueue_signals(); return 1; } - m->flags &= ~MOD_BUSY; + } + m->node.flags &= ~MOD_BUSY; if (!m->u.handle) { handle = NULL; if (!(linked = module_linked(name)) && @@ -1993,36 +2245,37 @@ load_module(char const *name, char **enablesstr, int silent) } if (handle) { m->u.handle = handle; - m->flags |= MOD_SETUP; + m->node.flags |= MOD_SETUP; } else { m->u.linked = linked; - m->flags |= MOD_SETUP | MOD_LINKED; + m->node.flags |= MOD_SETUP | MOD_LINKED; } if (setup_module(m)) { + finish_module(m); if (handle) m->u.handle = NULL; else m->u.linked = NULL; - m->flags &= ~MOD_SETUP; + m->node.flags &= ~MOD_SETUP; unqueue_signals(); return 1; } - m->flags |= MOD_INIT_S; + m->node.flags |= MOD_INIT_S; } - m->flags |= MOD_SETUP; + m->node.flags |= MOD_SETUP; if ((bootret = do_boot_module(m, enablesstr, silent)) == 1) { do_cleanup_module(m); finish_module(m); - if (m->flags & MOD_LINKED) + if (m->node.flags & MOD_LINKED) m->u.linked = NULL; else m->u.handle = NULL; - m->flags &= ~MOD_SETUP; + m->node.flags &= ~MOD_SETUP; unqueue_signals(); return 1; } - m->flags |= MOD_INIT_B; - m->flags &= ~MOD_SETUP; + m->node.flags |= MOD_INIT_B; + m->node.flags &= ~MOD_SETUP; unqueue_signals(); return bootret; } @@ -2030,7 +2283,8 @@ load_module(char const *name, char **enablesstr, int silent) /* This ensures that the module with the name given as the first argument * is loaded. * The other argument is the array of features to set. If this is NULL - * and the module needs to be loaded, all features are enabled. + * all features are enabled (even if the module was already loaded). + * * If this is non-NULL the module features are set accordingly * whether or not the module is loaded; it is an error if the * module does not support the features passed (even if the feature @@ -2050,14 +2304,13 @@ mod_export int require_module(const char *module, char **features) { Module m = NULL; - LinkNode node; int ret = 0; /* Resolve aliases and actual loadable module as for load_module */ queue_signals(); - node = find_module(module, 1, &module); - if (!node || !(m = ((Module) getdata(node)))->u.handle || - (m->flags & MOD_UNLOAD)) + m = find_module(module, FINDMOD_ALIASP, &module); + if (!m || !m->u.handle || + (m->node.flags & MOD_UNLOAD)) ret = load_module(module, features, 0); else ret = do_module_features(m, features, 0); @@ -2090,7 +2343,7 @@ add_dep(const char *name, char *from) * Better make sure. (There's no problem making a an alias which * *points* to a module with dependencies, of course.) */ - m = getdata(find_module(name, FINDMOD_ALIASP|FINDMOD_CREATE, &name)); + m = find_module(name, FINDMOD_ALIASP|FINDMOD_CREATE, &name); if (!m->deps) m->deps = znewlinklist(); for (node = firstnode(m->deps); @@ -2179,7 +2432,8 @@ bin_zmodload(char *nam, char **args, Options ops, UNUSED(int func)) return 1; } if (OPT_ISSET(ops,'e') && (OPT_ISSET(ops,'I') || OPT_ISSET(ops,'L') || - OPT_ISSET(ops,'a') || OPT_ISSET(ops,'d') || + (OPT_ISSET(ops,'a') && !OPT_ISSET(ops,'F')) + || OPT_ISSET(ops,'d') || OPT_ISSET(ops,'i') || OPT_ISSET(ops,'u'))) { zwarnnam(nam, "-e cannot be combined with other options"); /* except -F ... */ @@ -2233,7 +2487,6 @@ bin_zmodload_alias(char *nam, char **args, Options ops) * suppose other names are aliased to the same file? It might be * kettle of fish best left unwormed. */ - LinkNode node; Module m; if (!*args) { @@ -2241,11 +2494,9 @@ bin_zmodload_alias(char *nam, char **args, Options ops) zwarnnam(nam, "no module alias to remove"); return 1; } - for (node = firstnode(modules); node; incnode(node)) { - m = (Module) getdata(node); - if (m->flags & MOD_ALIAS) - printmodalias(m, ops); - } + scanhashtable(modulestab, 1, MOD_ALIAS, 0, + modulestab->printnode, + OPT_ISSET(ops,'L') ? PRINTMOD_LIST : 0); return 0; } @@ -2264,14 +2515,13 @@ bin_zmodload_alias(char *nam, char **args, Options ops) *args); return 1; } - node = find_module(*args, 0, NULL); - if (node) { - m = (Module) getdata(node); - if (!(m->flags & MOD_ALIAS)) { + m = find_module(*args, 0, NULL); + if (m) { + if (!(m->node.flags & MOD_ALIAS)) { zwarnnam(nam, "module is not an alias: %s", *args); return 1; } - delete_module(node); + delete_module(m); } else { zwarnnam(nam, "no such module alias: %s", *args); return 1; @@ -2289,29 +2539,28 @@ bin_zmodload_alias(char *nam, char **args, Options ops) *args); return 1; } - } while ((node = find_module(mname, 0, NULL)) - && ((m = (Module) getdata(node))->flags & MOD_ALIAS) + } while ((m = find_module(mname, 0, NULL)) + && (m->node.flags & MOD_ALIAS) && (mname = m->u.alias)); - node = find_module(*args, 0, NULL); - if (node) { - m = (Module) getdata(node); - if (!(m->flags & MOD_ALIAS)) { + m = find_module(*args, 0, NULL); + if (m) { + if (!(m->node.flags & MOD_ALIAS)) { zwarnnam(nam, "module is not an alias: %s", *args); return 1; } zsfree(m->u.alias); } else { m = (Module) zshcalloc(sizeof(*m)); - m->nam = ztrdup(*args); - m->flags = MOD_ALIAS; - zaddlinknode(modules, m); + m->node.flags = MOD_ALIAS; + modulestab->addnode(modulestab, ztrdup(*args), m); } m->u.alias = ztrdup(aliasname); } else { - if ((node = find_module(*args, 0, NULL))) { - m = (Module) getdata(node); - if (m->flags & MOD_ALIAS) - printmodalias(m, ops); + if ((m = find_module(*args, 0, NULL))) { + if (m->node.flags & MOD_ALIAS) + modulestab->printnode(&m->node, + OPT_ISSET(ops,'L') ? + PRINTMOD_LIST : 0); else { zwarnnam(nam, "module is not an alias: %s", *args); return 1; @@ -2333,35 +2582,20 @@ bin_zmodload_alias(char *nam, char **args, Options ops) static int bin_zmodload_exist(UNUSED(char *nam), char **args, Options ops) { - LinkNode node; Module m; - char *modname; if (!*args) { - for (node = firstnode(modules); node; incnode(node)) { - m = (Module) getdata(node); - modname = m->nam; - if (m->flags & MOD_ALIAS) { - LinkNode node2; - if (OPT_ISSET(ops,'A') && - (node2 = find_module(m->u.alias, FINDMOD_ALIASP, NULL))) - m = (Module) getdata(node2); - else - continue; - } - if (m->u.handle && !(m->flags & MOD_UNLOAD)) { - nicezputs(modname, stdout); - putchar('\n'); - } - } + scanhashtable(modulestab, 1, 0, 0, modulestab->printnode, + OPT_ISSET(ops,'A') ? PRINTMOD_EXIST|PRINTMOD_ALIAS : + PRINTMOD_EXIST); return 0; } else { int ret = 0; for (; !ret && *args; args++) { - if (!(node = find_module(*args, FINDMOD_ALIASP, NULL)) - || !(m = (Module) getdata(node))->u.handle - || (m->flags & MOD_UNLOAD)) + if (!(m = find_module(*args, FINDMOD_ALIASP, NULL)) + || !m->u.handle + || (m->node.flags & MOD_UNLOAD)) ret = 1; } return ret; @@ -2374,15 +2608,13 @@ bin_zmodload_exist(UNUSED(char *nam), char **args, Options ops) static int bin_zmodload_dep(UNUSED(char *nam), char **args, Options ops) { - LinkNode node; Module m; if (OPT_ISSET(ops,'u')) { /* remove dependencies, which can't pertain to aliases */ const char *tnam = *args++; - node = find_module(tnam, FINDMOD_ALIASP, &tnam); - if (!node) + m = find_module(tnam, FINDMOD_ALIASP, &tnam); + if (!m) return 0; - m = (Module) getdata(node); if (*args && m->deps) { do { LinkNode dnode; @@ -2404,32 +2636,18 @@ bin_zmodload_dep(UNUSED(char *nam), char **args, Options ops) } } if (!m->deps && !m->u.handle) - delete_module(node); + delete_module(m); return 0; } else if (!args[0] || !args[1]) { /* list dependencies */ - for (node = firstnode(modules); node; incnode(node)) { - m = (Module) getdata(node); - if (m->deps && (!args[0] || !strcmp(args[0], m->nam))) { - LinkNode n; - if (OPT_ISSET(ops,'L')) { - printf("zmodload -d "); - if(m->nam[0] == '-') - fputs("-- ", stdout); - quotedzputs(m->nam, stdout); - } else { - nicezputs(m->nam, stdout); - putchar(':'); - } - for (n = firstnode(m->deps); n; incnode(n)) { - putchar(' '); - if(OPT_ISSET(ops,'L')) - quotedzputs((char *) getdata(n), stdout); - else - nicezputs((char *) getdata(n), stdout); - } - putchar('\n'); - } + int depflags = OPT_ISSET(ops,'L') ? + PRINTMOD_DEPS|PRINTMOD_LIST : PRINTMOD_DEPS; + if (args[0]) { + if ((m = (Module)modulestab->getnode2(modulestab, args[0]))) + modulestab->printnode(&m->node, depflags); + } else { + scanhashtable(modulestab, 1, 0, 0, modulestab->printnode, + depflags); } return 0; } else { @@ -2467,7 +2685,7 @@ printautoparams(HashNode hn, int lon) static int bin_zmodload_auto(char *nam, char **args, Options ops) { - int fchar; + int fchar, flags; char *modnam; if (OPT_ISSET(ops,'c')) { @@ -2530,9 +2748,12 @@ bin_zmodload_auto(char *nam, char **args, Options ops) fchar = 'b'; } + flags = FEAT_AUTOALL; + if (OPT_ISSET(ops,'i')) + flags |= FEAT_IGNORE; if (OPT_ISSET(ops,'u')) { /* remove autoload */ - fchar *= -1; + flags |= FEAT_REMOVE; modnam = NULL; } else { /* add autoload */ @@ -2541,94 +2762,113 @@ bin_zmodload_auto(char *nam, char **args, Options ops) if (args[1]) args++; } - return autofeatures(nam, modnam, args, fchar, OPT_ISSET(ops,'i')); + return autofeatures(nam, modnam, args, fchar, flags); } /* Backend handler for zmodload -u */ /**/ int -unload_module(Module m, LinkNode node) +unload_module(Module m) { + int del; + /* * Only unload the real module, so resolve aliases. */ - if (m->flags & MOD_ALIAS) { - LinkNode node = find_module(m->u.alias, FINDMOD_ALIASP, NULL); - if (!node) + if (m->node.flags & MOD_ALIAS) { + m = find_module(m->u.alias, FINDMOD_ALIASP, NULL); + if (!m) return 1; - m = (Module) getdata(node); } - if ((m->flags & MOD_INIT_S) && - !(m->flags & MOD_UNLOAD) && + /* + * We may need to clean up the module any time setup_ has been + * called. After cleanup_ is successful we are no longer in the + * booted state (because features etc. are deregistered), so remove + * MOD_INIT_B, and also MOD_INIT_S since we won't need to cleanup + * again if this succeeded. + */ + if ((m->node.flags & MOD_INIT_S) && + !(m->node.flags & MOD_UNLOAD) && do_cleanup_module(m)) return 1; - else { - int del = (m->flags & MOD_UNLOAD); + m->node.flags &= ~(MOD_INIT_B|MOD_INIT_S); - if (m->wrapper) { - m->flags |= MOD_UNLOAD; - return 0; + del = (m->node.flags & MOD_UNLOAD); + + if (m->wrapper) { + m->node.flags |= MOD_UNLOAD; + return 0; + } + m->node.flags &= ~MOD_UNLOAD; + + /* + * We always need to finish the module (and unload it) + * if it is present. + */ + if (m->node.flags & MOD_LINKED) { + if (m->u.linked) { + m->u.linked->finish(m); + m->u.linked = NULL; } - m->flags &= ~MOD_UNLOAD; - if (m->flags & MOD_INIT_B) { - if (m->flags & MOD_LINKED) { - if (m->u.linked) { - m->u.linked->finish(m); - m->u.linked = NULL; - } - } else { - if (m->u.handle) { - finish_module(m); - m->u.handle = NULL; - } - } + } else { + if (m->u.handle) { + finish_module(m); + m->u.handle = NULL; } - if (del && m->deps) { - /* The module was unloaded delayed, unload all modules * - * on which it depended. */ - LinkNode n; - - for (n = firstnode(m->deps); n; incnode(n)) { - LinkNode dn = find_module((char *) getdata(n), - FINDMOD_ALIASP, NULL); - Module dm; - - if (dn && (dm = (Module) getdata(dn)) && - (dm->flags & MOD_UNLOAD)) { - /* See if this is the only module depending on it. */ - - LinkNode an; - Module am; - int du = 1; - - for (an = firstnode(modules); du && an; incnode(an)) { - am = (Module) getdata(an); - if (am != m && am->deps && - ((am->flags & MOD_LINKED) ? - am->u.linked : am->u.handle)) { - LinkNode sn; - - for (sn = firstnode(am->deps); du && sn; - incnode(sn)) { - if (!strcmp((char *) getdata(sn), dm->nam)) - du = 0; - } + } + + if (del && m->deps) { + /* The module was unloaded delayed, unload all modules * + * on which it depended. */ + LinkNode n; + + for (n = firstnode(m->deps); n; incnode(n)) { + Module dm = find_module((char *) getdata(n), + FINDMOD_ALIASP, NULL); + + if (dm && + (dm->node.flags & MOD_UNLOAD)) { + /* See if this is the only module depending on it. */ + Module am; + int du = 1, i; + /* Scan hash table the hard way */ + for (i = 0; du && i < modulestab->hsize; i++) { + for (am = (Module)modulestab->nodes[i]; du && am; + am = (Module)am->node.next) { + LinkNode sn; + /* + * Don't scan the module we're unloading; + * ignore if no dependencies. + */ + if (am == m || !am->deps) + continue; + /* Don't scan if not loaded nor linked */ + if ((am->node.flags & MOD_LINKED) ? + !am->u.linked : !am->u.handle) + continue; + for (sn = firstnode(am->deps); du && sn; + incnode(sn)) { + if (!strcmp((char *) getdata(sn), + dm->node.nam)) + du = 0; } } - if (du) - unload_module(dm, NULL); } + if (du) + unload_module(dm); } } - if(!m->deps) { - if (!node) { - node = linknodebydatum(modules, m); - if (!node) - return 1; - } - delete_module(node); - } + } + if (m->autoloads && firstnode(m->autoloads)) { + /* + * Module has autoloadable features. Restore them + * so that the module will be reloaded when needed. + */ + autofeatures("zsh", m->node.nam, + hlinklist2array(m->autoloads, 0), 0, FEAT_IGNORE); + } else if (!m->deps) { + delete_module(m); } return 0; } @@ -2644,32 +2884,35 @@ int unload_named_module(char *modname, char *nam, int silent) { const char *mname; - LinkNode node; Module m; int ret = 0; - node = find_module(modname, FINDMOD_ALIASP, &mname); - if (node) { - LinkNode mn, dn; - int del = 0; + m = find_module(modname, FINDMOD_ALIASP, &mname); + if (m) { + int i, del = 0; + Module dm; - for (mn = firstnode(modules); mn; incnode(mn)) { - m = (Module) getdata(mn); - if (m->deps && m->u.handle) - for (dn = firstnode(m->deps); dn; incnode(dn)) + for (i = 0; i < modulestab->hsize; i++) { + for (dm = (Module)modulestab->nodes[i]; dm; + dm = (Module)dm->node.next) { + LinkNode dn; + if (!dm->deps || !dm->u.handle) + continue; + for (dn = firstnode(dm->deps); dn; incnode(dn)) { if (!strcmp((char *) getdata(dn), mname)) { - if (m->flags & MOD_UNLOAD) + if (dm->node.flags & MOD_UNLOAD) del = 1; else { zwarnnam(nam, "module %s is in use by another module and cannot be unloaded", mname); return 1; } } + } + } } - m = (Module) getdata(node); if (del) m->wrapper++; - if (unload_module(m, node)) + if (unload_module(m)) ret = 1; if (del) m->wrapper--; @@ -2687,8 +2930,6 @@ unload_named_module(char *modname, char *nam, int silent) static int bin_zmodload_load(char *nam, char **args, Options ops) { - LinkNode node; - Module m; int ret = 0; if(OPT_ISSET(ops,'u')) { /* unload modules */ @@ -2699,19 +2940,9 @@ bin_zmodload_load(char *nam, char **args, Options ops) return ret; } else if(!*args) { /* list modules */ - for (node = firstnode(modules); node; incnode(node)) { - m = (Module) getdata(node); - if (m->u.handle && !(m->flags & (MOD_UNLOAD|MOD_ALIAS))) { - if(OPT_ISSET(ops,'L')) { - printf("zmodload "); - if(m->nam[0] == '-') - fputs("-- ", stdout); - quotedzputs(m->nam, stdout); - } else - nicezputs(m->nam, stdout); - putchar('\n'); - } - } + scanhashtable(modulestab, 1, 0, MOD_UNLOAD|MOD_ALIAS, + modulestab->printnode, + OPT_ISSET(ops,'L') ? PRINTMOD_LIST : 0); return 0; } else { /* load modules */ @@ -2729,15 +2960,31 @@ bin_zmodload_load(char *nam, char **args, Options ops) /**/ static int -bin_zmodload_features(char *nam, char **args, Options ops) +bin_zmodload_features(const char *nam, char **args, Options ops) { char *modname = *args; + if (modname) + args++; + else if (OPT_ISSET(ops,'L')) { + int printflags = PRINTMOD_LIST|PRINTMOD_FEATURES; + if (OPT_ISSET(ops,'P')) { + zwarnnam(nam, "-P is only allowed with a module name"); + return 1; + } + if (OPT_ISSET(ops,'l')) + printflags |= PRINTMOD_LISTALL; + if (OPT_ISSET(ops,'a')) + printflags |= PRINTMOD_AUTO; + scanhashtable(modulestab, 1, 0, MOD_ALIAS, + modulestab->printnode, printflags); + return 0; + } + if (!modname) { zwarnnam(nam, "-F requires a module name"); return 1; } - args++; if (OPT_ISSET(ops,'l') || OPT_ISSET(ops,'L') || OPT_ISSET(ops,'e')) { /* @@ -2746,32 +2993,74 @@ bin_zmodload_features(char *nam, char **args, Options ops) * only options turned on. * With both options, list as zmodload showing options * to be turned both on and off. - * - * TODO: handle -a, list only autoloads. */ - LinkNode node; - Module m = NULL; + Module m; char **features, **fp, **arrset = NULL, **arrp = NULL; int *enables = NULL, *ep; char *param = OPT_ARG_SAFE(ops,'P'); - node = find_module(modname, FINDMOD_ALIASP, NULL); - if (node) - m = ((Module) getdata(node)); - if (!m || !m->u.handle || (m->flags & MOD_UNLOAD)) { + m = find_module(modname, FINDMOD_ALIASP, NULL); + if (OPT_ISSET(ops,'a')) { + LinkNode ln; + /* + * If there are no autoloads defined, return status 1. + */ + if (!m || !m->autoloads) + return 1; + if (OPT_ISSET(ops,'e')) { + for (fp = args; *fp; fp++) { + char *fstr = *fp; + int sense = 1; + if (*fstr == '+') + fstr++; + else if (*fstr == '-') { + fstr++; + sense = 0; + } + if ((linknodebystring(m->autoloads, fstr) != NULL) != + sense) + return 1; + } + return 0; + } + if (param) { + arrp = arrset = (char **)zalloc(sizeof(char*) * + (countlinknodes(m->autoloads)+1)); + } else if (OPT_ISSET(ops,'L')) { + printf("zmodload -aF %s%c", m->node.nam, + m->autoloads && firstnode(m->autoloads) ? ' ' : '\n'); + arrp = NULL; + } + for (ln = firstnode(m->autoloads); ln; incnode(ln)) { + char *al = (char *)getdata(ln); + if (param) + *arrp++ = ztrdup(al); + else + printf("%s%c", al, + OPT_ISSET(ops,'L') && nextnode(ln) ? ' ' : '\n'); + } + if (param) { + *arrp = NULL; + if (!setaparam(param, arrset)) + return 1; + } + return 0; + } + if (!m || !m->u.handle || (m->node.flags & MOD_UNLOAD)) { if (!OPT_ISSET(ops,'e')) zwarnnam(nam, "module `%s' is not yet loaded", modname); return 1; } if (features_module(m, &features)) { if (!OPT_ISSET(ops,'e')) - zwarnnam(nam, "module `%s' does not support features", m->nam); + zwarnnam(nam, "module `%s' does not support features", + m->node.nam); return 1; } if (enables_module(m, &enables)) { /* this shouldn't ever happen, so don't silence this error */ zwarnnam(nam, "error getting enabled features for module `%s'", - m->nam); + m->node.nam); return 1; } for (arrp = args; *arrp; arrp++) { @@ -2796,14 +3085,14 @@ bin_zmodload_features(char *nam, char **args, Options ops) } if (!*fp) { if (!OPT_ISSET(ops,'e')) - zwarnnam(nam, "module `%s' has no such feature: %s", + zwarnnam(nam, "module `%s' has no such feature: `%s'", *arrp); return 1; } } if (OPT_ISSET(ops,'e')) /* yep, everything we want exists */ return 0; - if (OPT_ISSET(ops,'P')) { + if (param) { int arrlen = 0; for (fp = features, ep = enables; *fp; fp++, ep++) { if (OPT_ISSET(ops, 'L') && !OPT_ISSET(ops, 'l') && @@ -2826,7 +3115,7 @@ bin_zmodload_features(char *nam, char **args, Options ops) } arrp = arrset = zalloc(sizeof(char *) * (arrlen+1)); } else if (OPT_ISSET(ops, 'L')) - printf("zmodload -F %s ", m->nam); + printf("zmodload -F %s ", m->node.nam); for (fp = features, ep = enables; *fp; fp++, ep++) { char *onoff; int term; @@ -2872,7 +3161,18 @@ bin_zmodload_features(char *nam, char **args, Options ops) zwarnnam(nam, "-P can only be used with -l or -L"); return 1; } else if (OPT_ISSET(ops,'a')) { - return autofeatures(nam, modname, args, 0, OPT_ISSET(ops,'i')); + /* + * With zmodload -aF, we always use the effect of -i. + * The thinking is that marking a feature for + * autoload is separate from enabling or disabling it. + * Arguably we could do this with the zmodload -ab method + * but I've kept it there for old time's sake. + * The decoupling has meant FEAT_IGNORE/-i also + * suppresses an error for attempting to remove an + * autoload when the feature is enabled, which used + * to be a hard error before. + */ + return autofeatures(nam, modname, args, 0, FEAT_IGNORE); } return require_module(modname, args); @@ -2894,15 +3194,15 @@ bin_zmodload_features(char *nam, char **args, Options ops) /**/ mod_export char ** -featuresarray(char const *nam, Features f) +featuresarray(UNUSED(Module m), Features f) { int bn_size = f->bn_size, cd_size = f->cd_size; - int pd_size = f->pd_size, mf_size = f->mf_size; + int mf_size = f->mf_size, pd_size = f->pd_size; int features_size = bn_size + cd_size + pd_size + mf_size + f->n_abstract; Builtin bnp = f->bn_list; Conddef cdp = f->cd_list; - Paramdef pdp = f->pd_list; MathFunc mfp = f->mf_list; + Paramdef pdp = f->pd_list; char **features = (char **)zhalloc((features_size + 1) * sizeof(char *)); char **featurep = features; @@ -2913,10 +3213,10 @@ featuresarray(char const *nam, Features f) cdp->name); cdp++; } - while (pd_size--) - *featurep++ = dyncat("p:", (pdp++)->name); while (mf_size--) *featurep++ = dyncat("f:", (mfp++)->name); + while (pd_size--) + *featurep++ = dyncat("p:", (pdp++)->name); features[features_size] = NULL; return features; @@ -2929,15 +3229,15 @@ featuresarray(char const *nam, Features f) */ /**/ mod_export int * -getfeatureenables(char const *nam, Features f) +getfeatureenables(UNUSED(Module m), Features f) { int bn_size = f->bn_size, cd_size = f->cd_size; - int pd_size = f->pd_size, mf_size = f->mf_size; - int features_size = bn_size + cd_size + pd_size + mf_size + f->n_abstract; + int mf_size = f->mf_size, pd_size = f->pd_size; + int features_size = bn_size + cd_size + mf_size + pd_size + f->n_abstract; Builtin bnp = f->bn_list; Conddef cdp = f->cd_list; - Paramdef pdp = f->pd_list; MathFunc mfp = f->mf_list; + Paramdef pdp = f->pd_list; int *enables = zhalloc(sizeof(int) * features_size); int *enablep = enables; @@ -2945,10 +3245,10 @@ getfeatureenables(char const *nam, Features f) *enablep++ = ((bnp++)->node.flags & BINF_ADDED) ? 1 : 0; while (cd_size--) *enablep++ = ((cdp++)->flags & CONDF_ADDED) ? 1 : 0; - while (pd_size--) - *enablep++ = (pdp++)->pm ? 1 : 0; while (mf_size--) *enablep++ = ((mfp++)->flags & MFF_ADDED) ? 1 : 0; + while (pd_size--) + *enablep++ = (pdp++)->pm ? 1 : 0; return enables; } @@ -2965,32 +3265,32 @@ getfeatureenables(char const *nam, Features f) /**/ mod_export int -setfeatureenables(char const *nam, Features f, int *e) +setfeatureenables(Module m, Features f, int *e) { int ret = 0; if (f->bn_size) { - if (setbuiltins(nam, f->bn_list, f->bn_size, e)) + if (setbuiltins(m->node.nam, f->bn_list, f->bn_size, e)) ret = 1; if (e) e += f->bn_size; } if (f->cd_size) { - if (setconddefs(nam, f->cd_list, f->cd_size, e)) + if (setconddefs(m->node.nam, f->cd_list, f->cd_size, e)) ret = 1; if (e) e += f->cd_size; } + if (f->mf_size) { + if (setmathfuncs(m->node.nam, f->mf_list, f->mf_size, e)) + ret = 1; + } if (f->pd_size) { - if (setparamdefs(nam, f->pd_list, f->pd_size, e)) + if (setparamdefs(m->node.nam, f->pd_list, f->pd_size, e)) ret = 1; if (e) e += f->pd_size; } - if (f->mf_size) { - if (setmathfuncs(nam, f->mf_list, f->mf_size, e)) - ret = 1; - } return ret; } @@ -3001,31 +3301,40 @@ setfeatureenables(char const *nam, Features f, int *e) /**/ mod_export int -handlefeatures(char *nam, Features f, int **enables) +handlefeatures(Module m, Features f, int **enables) { if (!enables || *enables) - return setfeatureenables(nam, f, *enables); - *enables = getfeatureenables(nam, f); + return setfeatureenables(m, f, *enables); + *enables = getfeatureenables(m, f); return 0; } /* * Ensure module "modname" is providing feature with "prefix" - * and "feature" (e.g. "b:", "limit"). + * and "feature" (e.g. "b:", "limit"). If feature is NULL, + * ensure all features are loaded (used for compatibility + * with the pre-feature autoloading behaviour). * * This will usually be called from the main shell to handle * loading of an autoloadable feature. * * Returns 0 on success, 1 for error in module, 2 for error - * setting the feature. + * setting the feature. However, this isn't actually all + * that useful for testing immediately on an autoload since + * it could be a failure to autoload a different feature + * from the one we want. We could fix this but it's + * possible to test other ways. */ /**/ mod_export int -ensurefeature(char *modname, char *prefix, char *feature) +ensurefeature(const char *modname, const char *prefix, const char *feature) { - char *f = dyncat(prefix, feature); - char *features[2]; + char *f, *features[2]; + + if (!feature) + return require_module(modname, NULL); + f = dyncat(prefix, feature); features[0] = f; features[1] = NULL; @@ -3038,28 +3347,38 @@ ensurefeature(char *modname, char *prefix, char *feature) /**/ int -autofeatures(char *cmdnam, char *module, char **features, int prefchar, - int opt_i) +autofeatures(const char *cmdnam, const char *module, char **features, + int prefchar, int defflags) { int ret = 0, subret; - int defflags = opt_i ? AUTOFEAT_IGNORE : 0; + Module defm, m; + char **modfeatures = NULL; + if (module) { + defm = (Module)find_module(module, + FINDMOD_ALIASP|FINDMOD_CREATE, NULL); + if ((defm->node.flags & MOD_LINKED) ? defm->u.linked : + defm->u.handle) + (void)features_module(defm, &modfeatures); + } else + defm = NULL; - while (*features) { - char *fnam, *typnam; + for (; *features; features++) { + char *fnam, *typnam, *feature; int add, fchar, flags = defflags; autofeaturefn_t fn; if (prefchar) { - if (prefchar < 0) { - add = 0; - fchar = - prefchar; - } else { - add = 1; - fchar = prefchar; - } + /* + * "features" is list of bare features with no + * type prefix; prefchar gives type character. + */ + add = 1; /* unless overridden by flag */ + fchar = prefchar; fnam = *features; + feature = zhalloc(strlen(fnam) + 3); + sprintf(feature, "%c:%s", fchar, fnam); } else { - char *feature = *features; + feature = *features; if (*feature == '-') { add = 0; feature++; @@ -3073,12 +3392,13 @@ autofeatures(char *cmdnam, char *module, char **features, int prefchar, zwarnnam(cmdnam, "bad format for autoloadable feature: `%s'", feature); ret = 1; + continue; } fnam = feature + 2; fchar = feature[0]; } - - features++; + if (flags & FEAT_REMOVE) + add = 0; switch (fchar) { case 'b': @@ -3087,23 +3407,23 @@ autofeatures(char *cmdnam, char *module, char **features, int prefchar, break; case 'C': - flags |= AUTOFEAT_INFIX; + flags |= FEAT_INFIX; /* FALLTHROUGH */ case 'c': fn = add ? add_autocond : del_autocond; typnam = "condition"; break; - case 'p': - fn = add ? add_autoparam : del_autoparam; - typnam = "parameter"; - break; - case 'f': fn = add ? add_automathfunc : del_automathfunc; typnam = "math function"; break; + case 'p': + fn = add ? add_autoparam : del_autoparam; + typnam = "parameter"; + break; + default: zwarnnam(cmdnam, "bad autoloadable feature type: `%c'", fchar); @@ -3116,10 +3436,91 @@ autofeatures(char *cmdnam, char *module, char **features, int prefchar, ret = 1; continue; } - subret = fn(module, fnam, flags); + + if (!module) { + /* + * Traditional un-autoload syntax doesn't tell us + * which module this came from. + */ + int i; + for (i = 0, m = NULL; !m && i < modulestab->hsize; i++) { + for (m = (Module)modulestab->nodes[i]; m; + m = (Module)m->node.next) { + if (m->autoloads && + linknodebystring(m->autoloads, feature)) + break; + } + } + if (!m) { + if (!(flags & FEAT_IGNORE)) { + ret = 1; + zwarnnam(cmdnam, "%s: no such %s", fnam, typnam); + } + continue; + } + } else + m = defm; + + subret = 0; + if (add) { + char **ptr; + if (modfeatures) { + /* + * If the module is already available, check that + * it does in fact provide the necessary feature. + */ + for (ptr = modfeatures; *ptr; ptr++) + if (!strcmp(*ptr, feature)) + break; + if (!*ptr) { + zwarnnam(cmdnam, "module `%s' has no such feature: `%s'", + m->node.nam, feature); + ret = 1; + continue; + } + } + if (!m->autoloads) { + m->autoloads = znewlinklist(); + zaddlinknode(m->autoloads, ztrdup(feature)); + } else { + /* Insert in lexical order */ + LinkNode ln, prev = (LinkNode)m->autoloads; + while ((ln = nextnode(prev))) { + int cmp = strcmp(feature, (char *)getdata(ln)); + if (cmp == 0) { + /* Already there. Never an error. */ + break; + } + if (cmp < 0) { + zinsertlinknode(m->autoloads, prev, + ztrdup(feature)); + break; + } + prev = ln; + } + if (!ln) + zaddlinknode(m->autoloads, ztrdup(feature)); + } + } else if (m->autoloads) { + LinkNode ln; + if ((ln = linknodebystring(m->autoloads, feature))) + zsfree((char *)remnode(m->autoloads, ln)); + else { + /* + * With -i (or zmodload -Fa), removing an autoload + * that's not there is not an error. + */ + subret = (flags & FEAT_IGNORE) ? -2 : 2; + } + } + + if (subret == 0) + subret = fn(module, fnam, flags); if (subret != 0) { - ret = 1; + /* -2 indicates not an error, just skip running fn() */ + if (subret != -2) + ret = 1; switch (subret) { case 1: zwarnnam(cmdnam, "failed to add %s `%s'", typnam, fnam); diff --git a/Src/params.c b/Src/params.c index 5609437a2..46da87580 100644 --- a/Src/params.c +++ b/Src/params.c @@ -411,7 +411,7 @@ newparamtable(int size, char const *name) /**/ static HashNode -getparamnode(HashTable ht, char *nam) +getparamnode(HashTable ht, const char *nam) { HashNode hn = gethashnode2(ht, nam); Param pm = (Param) hn; @@ -419,12 +419,16 @@ getparamnode(HashTable ht, char *nam) if (pm && pm->u.str && (pm->node.flags & PM_AUTOLOAD)) { char *mn = dupstring(pm->u.str); - if (ensurefeature(mn, "p:", nam)) - return NULL; + (void)ensurefeature(mn, "p:", (pm->node.flags & PM_AUTOALL) ? NULL : + nam); hn = gethashnode2(ht, nam); - if (((Param) hn) == pm && (pm->node.flags & PM_AUTOLOAD)) { - pm->node.flags &= ~PM_AUTOLOAD; - zwarnnam(nam, "autoload failed"); + if (!hn) { + /* + * This used to be a warning, but surely if we allow + * stuff to go ahead with the autoload stub with + * no error status we're in for all sorts of mayhem? + */ + zerr("unknown parameter: %s", nam); } } return hn; diff --git a/Src/string.c b/Src/string.c index 190ca2d57..2bd1baea3 100644 --- a/Src/string.c +++ b/Src/string.c @@ -109,7 +109,7 @@ zhtricat(char const *s1, char const *s2, char const *s3) /**/ mod_export char * -dyncat(char *s1, char *s2) +dyncat(const char *s1, const char *s2) { /* This version always uses space from the current heap. */ char *ptr; diff --git a/Src/zsh.h b/Src/zsh.h index 4f11b19ad..5354e9663 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -92,6 +92,8 @@ struct mathfunc { #define MFF_ADDED 2 /* Math function is implemented by a shell function */ #define MFF_USERFUNC 4 +/* When autoloading, enable all features in module */ +#define MFF_AUTOALL 8 #define NUMMATHFUNC(name, func, min, max, id) \ @@ -538,8 +540,12 @@ struct conddef { char *module; /* module to autoload */ }; -#define CONDF_INFIX 1 -#define CONDF_ADDED 2 +/* Condition is an infix */ +#define CONDF_INFIX 1 +/* Condition has been loaded from library */ +#define CONDF_ADDED 2 +/* When autoloading, enable all features in library */ +#define CONDF_AUTOALL 4 #define CONDDEF(name, flags, handler, min, max, condid) \ { NULL, name, flags, handler, min, max, condid, NULL } @@ -928,11 +934,16 @@ struct dirsav { typedef void *(*VFunc) _((void *)); typedef void (*FreeFunc) _((void *)); -typedef unsigned (*HashFunc) _((char *)); +typedef unsigned (*HashFunc) _((const char *)); typedef void (*TableFunc) _((HashTable)); +/* + * Note that this is deliberately "char *", not "const char *", + * since the AddNodeFunc is passed a pointer to a string that + * will be stored and later freed. + */ typedef void (*AddNodeFunc) _((HashTable, char *, void *)); -typedef HashNode (*GetNodeFunc) _((HashTable, char *)); -typedef HashNode (*RemoveNodeFunc) _((HashTable, char *)); +typedef HashNode (*GetNodeFunc) _((HashTable, const char *)); +typedef HashNode (*RemoveNodeFunc) _((HashTable, const char *)); typedef void (*FreeNodeFunc) _((HashNode)); typedef int (*CompareFunc) _((const char *, const char *)); @@ -1152,25 +1163,37 @@ struct builtin { #define BINF_SKIPDASH (1<<14) /* Treat `-' as argument (maybe `+') */ #define BINF_DASHDASHVALID (1<<15) /* Handle `--' even if SKIPINVALD */ #define BINF_CLEARENV (1<<16) /* new process started with cleared env */ +#define BINF_AUTOALL (1<<17) /* autoload all features at once */ struct module { - char *nam; - int flags; + struct hashnode node; union { void *handle; Linkedmod linked; char *alias; } u; + LinkList autoloads; LinkList deps; int wrapper; }; +/* We are in the process of loading the module */ #define MOD_BUSY (1<<0) +/* + * We are in the process of unloading the module. + * Note this is not needed to indicate a module is actually + * unloaded: for that, the handle (or linked pointer) is set to NULL. + */ #define MOD_UNLOAD (1<<1) +/* We are in the process of setting up the module */ #define MOD_SETUP (1<<2) +/* Module is statically linked into the main binary */ #define MOD_LINKED (1<<3) +/* Module setup has been carried out (and module has not been finished) */ #define MOD_INIT_S (1<<4) +/* Module boot has been carried out (and module has not been finished) */ #define MOD_INIT_B (1<<5) +/* Module record is an alias */ #define MOD_ALIAS (1<<6) typedef int (*Module_generic_func) _((void)); @@ -1199,12 +1222,12 @@ struct features { /* List of conditions provided by the module and the size thereof */ Conddef cd_list; int cd_size; - /* List of parameters provided by the module and the size thereof */ - Paramdef pd_list; - int pd_size; /* List of math functions provided by the module and the size thereof */ MathFunc mf_list; int mf_size; + /* List of parameters provided by the module and the size thereof */ + Paramdef pd_list; + int pd_size; /* Number of abstract features */ int n_abstract; }; @@ -1408,6 +1431,10 @@ struct tieddata { #define PM_REMOVABLE (1<<26) /* special can be removed from paramtab */ #define PM_AUTOLOAD (1<<27) /* autoloaded from module */ #define PM_NORESTORE (1<<28) /* do not restore value of local special */ +#define PM_AUTOALL (1<<28) /* autoload all features in module + * when loading: valid only if PM_AUTOLOAD + * is also present. + */ #define PM_HASHELEM (1<<29) /* is a hash-element */ #define PM_NAMEDDIR (1<<30) /* has a corresponding nameddirtab entry */ |