1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-01-01 05:16:05 +01:00

23578: make standard features autoloadable,

use feature notation for .mdd autoloads
This commit is contained in:
Peter Stephenson 2007-06-20 20:59:15 +00:00
parent a197b1173a
commit 0a1de76213
33 changed files with 346 additions and 175 deletions

View file

@ -1,3 +1,22 @@
2007-06-20 Peter Stephenson <p.w.stephenson@ntlworld.com>
* 23578: Doc/Zsh/builtins.yo, Src/mkbltnmlst.sh, Src/module.c,
Src/Builtins/rlimits.mdd, Src/Builtins/sched.mdd,
Src/Modules/cap.mdd, Src/Modules/clone.mdd,
Src/Modules/datetime.mdd, Src/Modules/example.mdd,
Src/Modules/files.mdd, Src/Modules/langinfo.mdd,
Src/Modules/mapfile.mdd, Src/Modules/mathfunc.mdd,
Src/Modules/parameter.mdd, Src/Modules/pcre.mdd,
Src/Modules/regex.mdd, Src/Modules/socket.mdd,
Src/Modules/stat.mdd, Src/Modules/system.mdd, Src/Modules/tcp.mdd,
Src/Modules/termcap.mdd, Src/Modules/terminfo.mdd,
Src/Modules/zftp.mdd, Src/Modules/zprof.mdd, Src/Modules/zpty.mdd,
Src/Modules/zselect.mdd, Src/Modules/zutil.mdd,
Src/Zle/compctl.mdd, Src/Zle/complete.mdd, Src/Zle/computil.mdd,
Src/Zle/zle.mdd, Src/Zle/zleparameter.mdd: make standard
features autoloadable and use feature notation for predefined
autoloads.
2007-06-19 Peter Stephenson <p.w.stephenson@ntlworld.com>
* 23575: Src/Modules/newuser.c: yet another problem on AIX:

View file

@ -1897,7 +1897,7 @@ Each module has a boot and a cleanup function. The module
will not be loaded if its boot function fails. Similarly a module
can only be unloaded if its cleanup function runs successfully.
)
item(tt(zmodload -F) [ tt(-lLe) tt(-P) tt(param) ] var(module) [tt(PLUS()-)]var(feature...))(
item(tt(zmodload -F) [ tt(-alLe) tt(-P) tt(param) ] var(module) [tt(PLUS()-)]var(feature...))(
tt(zmodload -F) allows more selective control over the features provided
by modules. With no options apart from tt(-F), the module named
var(module) is loaded, if it was not already loaded, and the list of
@ -1914,12 +1914,13 @@ not be set (for example, a parameter couldn't be added because there
was a different parameter of the same name) but the module was loaded.
The standard features are builtins, conditions, parameters and math
functions; these are indicated by the prefix `tt(b:)', `tt(c:)', `tt(p:)'
and `tt(f:)', respectively, followed by the name that the corresponding
feature would have in the shell. For example, `tt(b:strftime)' indicates
a builtin named tt(strftime) and tt(p:EPOCHSECONDS) indicates a parameter
named tt(EPOCHSECONDS). The module may provide other (`abstract') features
of its own as indicated by its documentation; these have no prefix.
functions; these are indicated by the prefix `tt(b:)', `tt(c:)'
(`tt(C:)' for an infix condition), `tt(p:)' and `tt(f:)', respectively,
followed by the name that the corresponding feature would have in the
shell. For example, `tt(b:strftime)' indicates a builtin named
tt(strftime) and tt(p:EPOCHSECONDS) indicates a parameter named
tt(EPOCHSECONDS). The module may provide other (`abstract') features of
its own as indicated by its documentation; these have no prefix.
With tt(-l) or tt(-L), features provided by the module are listed. With
tt(-l) alone, a list of features together with their states is shown, one
@ -1944,6 +1945,13 @@ given with no prefix is simply tested to see if the module provides it;
any feature given with a prefix tt(PLUS()) or tt(-) is tested to
see if is provided and in the given state. If the tests on all features
in the list succeed, status 0 is returned, else status 1.
With tt(-a), the given list of features is marked for autoload from
the specified module, which may not be loaded. An optional tt(PLUS())
may appear before the feature name. If the feature is prefixed with
tt(-), the existing autoload is deleted. Note that only standard
features as described above can be autoloaded; other features require
the module to be loaded.
)
xitem(tt(zmodload) tt(-d) [ tt(-L) ] [ var(name) ])
xitem(tt(zmodload) tt(-d) var(name) var(dep) ...)

View file

@ -2,7 +2,7 @@ name=zsh/rlimits
link=either
load=yes
autobins="limit ulimit unlimit"
autofeatures="b:limit b:ulimit b:unlimit"
objects="rlimits.o"

View file

@ -2,7 +2,6 @@ name=zsh/sched
link=either
load=yes
autobins="sched"
autoparams="zsh_scheduled_events"
autofeatures="b:sched p:zsh_scheduled_events"
objects="sched.o"

View file

@ -2,6 +2,6 @@ name=zsh/cap
link=dynamic
load=no
autobins="cap getcap setcap"
autofeatures="b:cap b:getcap b:setcap"
objects="cap.o"

View file

@ -2,6 +2,6 @@ name=zsh/clone
link=dynamic
load=no
autobins="clone"
autofeatures="b:clone"
objects="clone.o"

View file

@ -4,6 +4,6 @@ link=either
load=no
functions='Functions/Calendar/*'
autobins="strftime"
autofeatures="b:strftime p:EPOCHSECONDS"
objects="datetime.o"

View file

@ -2,11 +2,6 @@ name=zsh/example
link=dynamic
load=no
autobins="example"
autoinfixconds="ex"
autoprefixconds="len"
autoparams="exint exstr exarr"
automathfuncs="sum length"
autofeatures="b:example C:ex c:len p:exint p:exstr p:exarr f:sum f:length"
objects="example.o"

View file

@ -2,6 +2,6 @@ name=zsh/files
link=dynamic
load=no
autobins="chgrp chown ln mkdir mv rm rmdir sync"
autofeatures="b:chgrp b:chown b:ln b:mkdir b:mv b:rm b:rmdir b:sync"
objects="files.o"

View file

@ -3,6 +3,6 @@ name=zsh/langinfo
link=`if test x$ac_cv_func_nl_langinfo; then echo either; else echo no; fi`
load=no
autoparams="langinfo"
autofeatures="p:langinfo"
objects="langinfo.o"

View file

@ -2,6 +2,6 @@ name=zsh/mapfile
link=dynamic
load=no
autoparams="mapfile"
autofeatures="p:mapfile"
objects="mapfile.o"

View file

@ -2,6 +2,4 @@ name=zsh/mathfunc
link=dynamic
load=no
autobins="mathfunc"
objects="mathfunc.o"

View file

@ -2,6 +2,6 @@ name=zsh/parameter
link=either
load=yes
autoparams="parameters commands functions dis_functions funcstack functrace builtins dis_builtins reswords dis_reswords options modules dirstack history historywords jobtexts jobdirs jobstates nameddirs userdirs aliases dis_aliases galiases dis_galiases saliases dis_saliases"
autofeatures="p:parameters p:commands p:functions p:dis_functions p:funcstack p:functrace p:builtins p:dis_builtins p:reswords p:dis_reswords p:options p:modules p:dirstack p:history p:historywords p:jobtexts p:jobdirs p:jobstates p:nameddirs p:userdirs p:aliases p:dis_aliases p:galiases p:dis_galiases p:saliases p:dis_saliases"
objects="parameter.o"

View file

@ -2,6 +2,6 @@ name=zsh/pcre
link=`if test x$enable_pcre = xyes; then echo dynamic; else echo no; fi`
load=no
autobins="pcre_compile pcre_study pcre_match"
autofeatures="b:pcre_compile b:pcre_study b:pcre_match"
objects="pcre.o"

View file

@ -5,6 +5,4 @@ link=`if test x$ac_cv_func_regcomp = xyes && \
test x$ac_cv_func_regfree = xyes; then echo dynamic; else echo no; fi`
load=no
autobins=""
objects="regex.o"

View file

@ -3,4 +3,4 @@ link=dynamic
load=no
objects="socket.o"
autobins="zsocket"
autofeatures="b:zsocket"

View file

@ -2,6 +2,6 @@ name=zsh/stat
link=dynamic
load=no
autobins="stat"
autofeatures="b:stat b:zstat"
objects="stat.o"

View file

@ -2,9 +2,7 @@ name=zsh/system
link=dynamic
load=no
autobins="sysread syswrite syserror"
autoparams="errnos"
autofeatures="b:sysread b:syswrite b:syserror p:errnos"
objects="system.o errnames.o"

View file

@ -4,4 +4,4 @@ load=no
functions='Functions/TCP/*'
objects="tcp.o"
autobins="ztcp"
autofeatures="b:ztcp"

View file

@ -12,7 +12,6 @@ link='if test "x$ac_cv_func_tgetent" = xyes; then
'
load=yes
autobins="echotc"
autoparams="termcap"
autofeatures="b:echotc p:termcap"
objects="termcap.o"

View file

@ -12,7 +12,6 @@ link='if test "x$ac_cv_func_tigetflag" = xyes -a "x$ac_cv_header_curses_h" = xye
'
load=yes
autobins="echoti"
autoparams="terminfo"
autofeatures="b:echoti p:terminfo"
objects="terminfo.o"

View file

@ -3,7 +3,7 @@ link=dynamic
load=no
functions='Functions/Zftp/*'
autobins="zftp"
autofeatures="b:zftp"
moddeps="zsh/net/tcp"

View file

@ -2,6 +2,6 @@ name=zsh/zprof
link=dynamic
load=no
autobins="zprof"
autofeatures="b:zprof"
objects="zprof.o"

View file

@ -2,6 +2,6 @@ name=zsh/zpty
link=dynamic
load=no
autobins="zpty"
autofeatures="b:zpty"
objects="zpty.o"

View file

@ -3,4 +3,4 @@ link=dynamic
load=no
objects="zselect.o"
autobins="zselect"
autofeatures="b:zselect"

View file

@ -6,4 +6,4 @@ moddeps="zsh/complete"
objects="zutil.o"
autobins="zformat zstyle zregexparse zparseopts"
autofeatures="b:zformat b:zstyle b:zregexparse b:zparseopts"

View file

@ -4,7 +4,7 @@ load=yes
moddeps="zsh/complete zsh/zle"
autobins="compctl compcall"
autofeatures="b:compctl b:compcall"
headers="compctl.h"
objects="compctl.o"

View file

@ -5,9 +5,7 @@ functions='Completion/*comp* Completion/AIX/*/* Completion/BSD/*/* Completion/Ba
moddeps="zsh/zle"
autobins="compadd compset"
autoprefixconds="prefix suffix between after"
autofeatures="b:compadd b:compset c:prefix c:suffix c:between c:after"
headers="comp.h"

View file

@ -6,4 +6,4 @@ moddeps="zsh/complete zsh/zle"
objects="computil.o"
autobins="compdescribe comparguments compvalues compquote comptags comptry compfiles compgroups"
autofeatures="b:compdescribe b:comparguments b:compvalues b:compquote b:comptags b:comptry b:compfiles b:compgroups"

View file

@ -3,7 +3,7 @@ link=either
load=yes
functions='Functions/Zle/*'
autobins="bindkey vared zle"
autofeatures="b:bindkey b:vared b:zle"
objects="zle_bindings.o zle_hist.o zle_keymap.o zle_main.o \
zle_misc.o zle_move.o zle_params.o zle_refresh.o \

View file

@ -4,6 +4,6 @@ load=yes
moddeps="zsh/zle"
autoparams="widgets keymaps"
autofeatures="p:widgets p:keymaps"
objects="zleparameter.o"

View file

@ -40,23 +40,17 @@ for x_mod in $x_mods; do
unset moddeps autobins autoinfixconds autoprefixconds autoparams
unset automathfuncs
. $srcdir/../$modfile
echo " if (emulation == EMULATE_ZSH) {"
for bin in $autobins; do
echo " add_autobin(\"$bin\", \"$x_mod\");"
done
for cond in $autoinfixconds; do
echo " add_autocond(\"$cond\", 1, \"$x_mod\");"
done
for cond in $autoprefixconds; do
echo " add_autocond(\"$cond\", 0, \"$x_mod\");"
done
for param in $autoparams; do
echo " add_autoparam(\"$param\", \"$x_mod\");"
done
for mfunc in $automathfuncs; do
echo " add_automathfunc(\"$mfunc\", \"$x_mod\");"
done
echo " }"
if test "x$autofeatures" != x; then
echo " if (emulation == EMULATE_ZSH) {"
echo " char *features[] = { "
for feature in $autofeatures; do
echo " \"$feature\","
done
echo " NULL"
echo " }; "
echo " autofeatures(\"zsh\", features, \"$x_mod\", 1);"
echo " }"
fi
for dep in $moddeps; do
echo " add_dep(\"$x_mod\", \"$dep\");"
done

View file

@ -197,14 +197,24 @@ addbuiltin(Builtin b)
/**/
int
add_autobin(char *nam, char *module)
add_autobin(char *cmdnam, char *bnam, char *module, int opt_i)
{
Builtin bn = zshcalloc(sizeof(*bn));
bn->node.nam = ztrdup(nam);
Builtin bn;
if (strchr(bnam, '/')) {
zwarnnam(cmdnam, "%s: `/' is illegal in a builtin", bnam);
return 1;
}
bn = zshcalloc(sizeof(*bn));
bn->node.nam = ztrdup(bnam);
bn->optstr = ztrdup(module);
if (addbuiltin(bn)) {
builtintab->freenode(&bn->node);
return 1;
if (!opt_i) {
zwarnnam(cmdnam, "failed to add builtin %s", bnam);
return 1;
}
}
return 0;
}
@ -225,6 +235,27 @@ deletebuiltin(char *nam)
return 0;
}
/* Remove an autoloaded added by add_autobin */
/**/
static int
del_autobin(char *cmdnam, char *bnam, int opt_i)
{
Builtin bn = (Builtin) builtintab->getnode2(builtintab, bnam);
if (!bn) {
if(!opt_i) {
zwarnnam(cmdnam, "%s: no such builtin", bnam);
return 1;
}
} else if (bn->node.flags & BINF_ADDED) {
zwarnnam(cmdnam, "%s: builtin is already defined", bnam);
return 1;
} else
deletebuiltin(bnam);
return 0;
}
/*
* Manipulate a set of builtins. This should be called
* via setfeatureenables() (or, usually, via the next level up,
@ -406,10 +437,14 @@ getconddef(int inf, char *name, int autol)
break;
}
if (autol && p && p->module) {
/* This is a definition for an autoloaded condition, load the *
* module if we haven't tried that already. */
/*
* This is a definition for an autoloaded condition; load the
* module if we haven't tried that already.
*/
if (f) {
(void)ensurefeature(p->module, "c:", name);
(void)ensurefeature(p->module,
(p->flags & CONDF_INFIX) ?
"C:" : "c:", name);
f = 0;
p = NULL;
} else {
@ -523,11 +558,18 @@ setconddefs(char const *nam, Conddef c, int size, int *e)
/**/
int
add_autocond(char *nam, int inf, char *module)
add_autocond(char *cmdnam, char *cnam, int inf, char *module, int opt_i)
{
Conddef c = (Conddef) zalloc(sizeof(*c));
Conddef c;
c->name = ztrdup(nam);
if (strchr(cnam, '/')) {
zwarnnam(cmdnam, "%s: `/' is illegal in a condition", cnam);
return 1;
}
c = (Conddef) zalloc(sizeof(*c));
c->name = ztrdup(cnam);
c->flags = (inf ? CONDF_INFIX : 0);
c->module = ztrdup(module);
@ -536,11 +578,35 @@ add_autocond(char *nam, int inf, char *module)
zsfree(c->module);
zfree(c, sizeof(*c));
return 1;
if (!opt_i) {
zwarnnam(cmdnam, "failed to add condition `%s'", cnam);
return 1;
}
}
return 0;
}
/* Remove a condition added with add_autocond */
/**/
static int
del_autocond(char *cmdnam, char *cnam, int infix, int opt_i)
{
Conddef cd = getconddef(infix, cnam, 0);
if (!cd) {
if (!opt_i) {
zwarnnam(cmdnam, "%s: no such condition", cnam);
return 1;
}
} else if (cd->flags & CONDF_ADDED) {
zwarnnam(cmdnam, "%s: condition is already defined", cnam);
return 1;
} else
deleteconddef(cd);
return 0;
}
/************************************************************************
* Hook functions.
@ -722,10 +788,13 @@ runhookdef(Hookdef h, void *d)
* Check that it's possible to add a parameter. This
* requires that either there's no parameter already present,
* or it's a global parameter marked for autoloading.
*
* The special status 2 is to indicate it didn't work but
* -i was in use so we didn't print a warning.
*/
static int
checkaddparam(char *nam)
checkaddparam(char *nam, int opt_i)
{
Param pm;
@ -733,11 +802,22 @@ checkaddparam(char *nam)
return 0;
if (pm->level || !(pm->node.flags & PM_AUTOLOAD)) {
zwarn("Can't add module parameter `%s': %s",
nam, pm->level ?
"local parameter exists" :
"parameter already exists");
return 1;
/*
* -i suppresses "it's already that way" warnings,
* but not "this can't possibly work" warnings, so we print
* the message anyway if there's a local parameter blocking
* the parameter we want to add, not if there's a
* non-autoloadable parameter already there. This
* is consistent with the way add_auto* functions work.
*/
if (!opt_i || !pm->level) {
zwarn("Can't add module parameter `%s': %s",
nam, pm->level ?
"local parameter exists" :
"parameter already exists");
return 1;
}
return 2;
}
unsetparam_pm(pm, 0, 1);
@ -753,7 +833,7 @@ addparamdef(Paramdef d)
{
Param pm;
if (checkaddparam(d->name))
if (checkaddparam(d->name, 0))
return 1;
if (d->getnfn) {
@ -879,23 +959,60 @@ setparamdefs(char const *nam, Paramdef d, int size, int *e)
/* This adds a definition for autoloading a module for a parameter. */
/**/
void
add_autoparam(char *nam, char *module)
int
add_autoparam(char *cmdnam, char *pnam, char *module, int opt_i)
{
Param pm;
int ret;
queue_signals();
if (checkaddparam(nam)) {
unqueue_signals();
return;
if (strchr(pnam, '/')) {
zwarnnam(cmdnam, "%s: `/' is illegal in a parameter", pnam);
return 1;
}
pm = setsparam(nam, ztrdup(module));
queue_signals();
if ((ret = checkaddparam(pnam, opt_i))) {
unqueue_signals();
/*
* checkaddparam() has already printed a message
* if one was needed. If it wasn't because of -i,
* ret is 2; for consistency with other add_auto*
* functions we return status 0 to indicate there's
* already such a parameter and we've been told not
* to worry if so.
*/
return ret == 2 ? 0 : 1;
}
pm = setsparam(pnam, ztrdup(module));
pm->node.flags |= PM_AUTOLOAD;
unqueue_signals();
return 0;
}
/* Remove a parameter added with add_autoparam() */
/**/
static int
del_autoparam(char *cmdnam, char *pnam, int opt_i)
{
Param pm = (Param) gethashnode2(paramtab, pnam);
if (!pm) {
if (!opt_i) {
zwarnnam(cmdnam, "%s: no such parameter", pnam);
return 1;
}
} else if (!(pm->node.flags & PM_AUTOLOAD)) {
zwarnnam(cmdnam, "%s: parameter is already defined", pnam);
return 1;
} else
unsetparam_pm(pm, 0, 1);
return 0;
}
/************************************************************************
* Math functions.
@ -1053,11 +1170,18 @@ setmathfuncs(char const *nam, MathFunc f, int size, int *e)
/**/
int
add_automathfunc(char *nam, char *module)
add_automathfunc(char *cmdnam, char *fnam, char *module, int opt_i)
{
MathFunc f = (MathFunc) zalloc(sizeof(*f));
MathFunc f;
f->name = ztrdup(nam);
if (strchr(fnam, '/')) {
zwarnnam(cmdnam, "%s: `/' is illegal in a math function", fnam);
return 1;
}
f = (MathFunc) zalloc(sizeof(*f));
f->name = ztrdup(fnam);
f->module = ztrdup(module);
f->flags = 0;
@ -1066,12 +1190,36 @@ add_automathfunc(char *nam, char *module)
zsfree(f->module);
zfree(f, sizeof(*f));
return 1;
if (!opt_i) {
zwarnnam(cmdnam, "failed to add math function `%s'", fnam);
return 1;
}
}
return 0;
}
/* Remove a math function added with add_automathfunc() */
/**/
static int
del_automathfunc(char *cmdnam, char *fnam, int opt_i)
{
MathFunc f = getmathfunc(fnam, 0);
if (!f) {
if (!opt_i) {
zwarnnam(cmdnam, "%s: no such math function", fnam);
return 1;
}
} else if (f->flags & MFF_ADDED) {
zwarnnam(cmdnam, "%s: math function is already defined", fnam);
return 1;
} else
deletemathfunc(f);
return 0;
}
/************************************************************************
* Now support for dynamical loading and the fallback functions
@ -2002,15 +2150,13 @@ bin_zmodload(char *nam, char **args, Options ops, UNUSED(int func))
/* options only allowed with -F */
char *fonly = "lP", *fp;
if (ops_bcpf) {
if (!ops_au) {
zwarnnam(nam, "-b, -c, -f, and -p must be combined with -a or -u");
return 1;
}
if (OPT_ISSET(ops,'F')) {
zwarnnam(nam, "-b, -c, -f, and -p cannot be combined with -F");
return 1;
}
if (ops_bcpf && !ops_au) {
zwarnnam(nam, "-b, -c, -f, and -p must be combined with -a or -u");
return 1;
}
if (OPT_ISSET(ops,'F') && (ops_bcpf || OPT_ISSET(ops,'u'))) {
zwarnnam(nam, "-b, -c, -f, -p and -u cannot be combined with -F");
return 1;
}
if (OPT_ISSET(ops,'A') || OPT_ISSET(ops,'R')) {
if (ops_bcpf || ops_au || OPT_ISSET(ops,'d') ||
@ -2304,20 +2450,11 @@ static int
bin_zmodload_auto(char *nam, char **args, Options ops)
{
int ret = 0;
if(OPT_ISSET(ops,'u')) {
/* remove autoloaded builtins */
if (OPT_ISSET(ops,'u')) {
/* removed autoloaded builtins */
for (; *args; args++) {
Builtin bn = (Builtin) builtintab->getnode2(builtintab, *args);
if (!bn) {
if(!OPT_ISSET(ops,'i')) {
zwarnnam(nam, "%s: no such builtin", *args);
ret = 1;
}
} else if (bn->node.flags & BINF_ADDED) {
zwarnnam(nam, "%s: builtin is already defined", *args);
if (del_autobin(nam, *args, OPT_ISSET(ops,'i')))
ret = 1;
} else
deletebuiltin(*args);
}
return ret;
} else if(!*args) {
@ -2331,13 +2468,8 @@ bin_zmodload_auto(char *nam, char **args, Options ops)
modnam = *args++;
do {
char *bnam = *args ? *args++ : modnam;
if (strchr(bnam, '/')) {
zwarnnam(nam, "%s: `/' is illegal in a builtin", bnam);
if (add_autobin(nam, bnam, modnam, OPT_ISSET(ops,'i')))
ret = 1;
} else if (add_autobin(bnam, modnam) && !OPT_ISSET(ops,'i')) {
zwarnnam(nam, "failed to add builtin %s", bnam);
ret = 1;
}
} while(*args);
return ret;
}
@ -2354,18 +2486,9 @@ bin_zmodload_cond(char *nam, char **args, Options ops)
if (OPT_ISSET(ops,'u')) {
/* remove autoloaded conditions */
for (; *args; args++) {
Conddef cd = getconddef(OPT_ISSET(ops,'I'), *args, 0);
if (!cd) {
if (!OPT_ISSET(ops,'i')) {
zwarnnam(nam, "%s: no such condition", *args);
ret = 1;
}
} else if (cd->flags & CONDF_ADDED) {
zwarnnam(nam, "%s: condition is already defined", *args);
if (del_autocond(nam, *args, OPT_ISSET(ops,'I'),
OPT_ISSET(ops,'i')))
ret = 1;
} else
deleteconddef(cd);
}
return ret;
} else if (!*args) {
@ -2396,14 +2519,9 @@ bin_zmodload_cond(char *nam, char **args, Options ops)
modnam = *args++;
do {
char *cnam = *args ? *args++ : modnam;
if (strchr(cnam, '/')) {
zwarnnam(nam, "%s: `/' is illegal in a condition", cnam);
if (add_autocond(nam, cnam, OPT_ISSET(ops, 'I'),
modnam, OPT_ISSET(ops,'i')))
ret = 1;
} else if (add_autocond(cnam, OPT_ISSET(ops,'I'), modnam) &&
!OPT_ISSET(ops,'i')) {
zwarnnam(nam, "failed to add condition `%s'", cnam);
ret = 1;
}
} while(*args);
return ret;
}
@ -2420,18 +2538,8 @@ bin_zmodload_math(char *nam, char **args, Options ops)
if (OPT_ISSET(ops,'u')) {
/* remove autoloaded math functions */
for (; *args; args++) {
MathFunc f = getmathfunc(*args, 0);
if (!f) {
if (!OPT_ISSET(ops,'i')) {
zwarnnam(nam, "%s: no such math function", *args);
ret = 1;
}
} else if (f->flags & MFF_ADDED) {
zwarnnam(nam, "%s: math function is already defined", *args);
if (del_automathfunc(nam, *args, OPT_ISSET(ops,'i')))
ret = 1;
} else
deletemathfunc(f);
}
return ret;
} else if (!*args) {
@ -2455,13 +2563,8 @@ bin_zmodload_math(char *nam, char **args, Options ops)
modnam = *args++;
do {
char *fnam = *args ? *args++ : modnam;
if (strchr(fnam, '/')) {
zwarnnam(nam, "%s: `/' is illegal in a math function", fnam);
if (add_automathfunc(nam, fnam, modnam, OPT_ISSET(ops,'i')))
ret = 1;
} else if (add_automathfunc(fnam, modnam) && !OPT_ISSET(ops,'i')) {
zwarnnam(nam, "failed to add math function `%s'", fnam);
ret = 1;
}
} while(*args);
return ret;
}
@ -2496,18 +2599,8 @@ bin_zmodload_param(char *nam, char **args, Options ops)
if (OPT_ISSET(ops,'u')) {
/* remove autoloaded parameters */
for (; *args; args++) {
Param pm = (Param) gethashnode2(paramtab, *args);
if (!pm) {
if (!OPT_ISSET(ops,'i')) {
zwarnnam(nam, "%s: no such parameter", *args);
ret = 1;
}
} else if (!(pm->node.flags & PM_AUTOLOAD)) {
zwarnnam(nam, "%s: parameter is already defined", *args);
if (del_autoparam(nam, *args, OPT_ISSET(ops,'i')))
ret = 1;
} else
unsetparam_pm(pm, 0, 1);
}
return ret;
} else if (!*args) {
@ -2520,11 +2613,8 @@ bin_zmodload_param(char *nam, char **args, Options ops)
modnam = *args++;
do {
char *pnam = *args ? *args++ : modnam;
if (strchr(pnam, '/')) {
zwarnnam(nam, "%s: `/' is illegal in a parameter", pnam);
if (add_autoparam(nam, pnam, modnam, OPT_ISSET(ops,'i')))
ret = 1;
} else
add_autoparam(pnam, modnam);
} while(*args);
return ret;
}
@ -2733,6 +2823,8 @@ 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;
@ -2856,6 +2948,8 @@ bin_zmodload_features(char *nam, char **args, Options ops)
} else if (OPT_ISSET(ops,'P')) {
zwarnnam(nam, "-P can only be used with -l or -L");
return 1;
} else if (OPT_ISSET(ops,'a')) {
return autofeatures(nam, args, modname, OPT_ISSET(ops,'i'));
}
return require_module(modname, args);
@ -2891,8 +2985,11 @@ featuresarray(char const *nam, Features f)
while (bn_size--)
*featurep++ = dyncat("b:", (bnp++)->node.nam);
while (cd_size--)
*featurep++ = dyncat("c:", (cdp++)->name);
while (cd_size--) {
*featurep++ = dyncat((cdp->flags & CONDF_INFIX) ? "C:" : "c:",
cdp->name);
cdp++;
}
while (pd_size--)
*featurep++ = dyncat("p:", (pdp++)->name);
while (mf_size--)
@ -3011,3 +3108,72 @@ ensurefeature(char *modname, char *prefix, char *feature)
features[1] = NULL;
return require_module(modname, features);
}
/*
* Add autoloadable features for a given module.
*/
/**/
int
autofeatures(char *cmdnam, char **features, char *module, int opt_i)
{
int ret = 0, infix;
while (*features) {
char *feature = *features, *fnam;
int add;
if (*feature == '-') {
add = 0;
feature ++;
} else {
add = 1;
if (*feature == '+')
feature++;
}
if (!*feature || feature[1] != ':') {
zwarnnam(cmdnam, "bad format for autoloadable feature: `%s'",
feature);
ret = 1;
}
fnam = feature + 2;
switch (feature[0]) {
case 'b':
if (add ? add_autobin(cmdnam, fnam, module, opt_i) :
del_autobin(cmdnam, fnam, opt_i));
ret = 1;
break;
case 'c':
case 'C':
infix = (feature[0] == 'C');
if (add ? add_autocond(cmdnam, fnam, infix, module, opt_i) :
del_autocond(cmdnam, fnam, infix, opt_i))
ret = 1;
break;
case 'p':
if (add ? add_autoparam(cmdnam, fnam, module, opt_i) :
del_autoparam(cmdnam, fnam, opt_i));
ret = 1;
break;
case 'f':
if (add ? add_automathfunc(cmdnam, fnam, module, opt_i) :
del_automathfunc(cmdnam, fnam, opt_i))
ret = 1;
break;
default:
zwarnnam(cmdnam, "bad autoloadable feature type: `%s'",
feature);
ret = 1;
break;
}
features++;
}
return ret;
}