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:
parent
a197b1173a
commit
0a1de76213
33 changed files with 346 additions and 175 deletions
19
ChangeLog
19
ChangeLog
|
@ -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:
|
||||
|
|
|
@ -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) ...)
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -2,6 +2,6 @@ name=zsh/clone
|
|||
link=dynamic
|
||||
load=no
|
||||
|
||||
autobins="clone"
|
||||
autofeatures="b:clone"
|
||||
|
||||
objects="clone.o"
|
||||
|
|
|
@ -4,6 +4,6 @@ link=either
|
|||
load=no
|
||||
|
||||
functions='Functions/Calendar/*'
|
||||
autobins="strftime"
|
||||
autofeatures="b:strftime p:EPOCHSECONDS"
|
||||
|
||||
objects="datetime.o"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -2,6 +2,6 @@ name=zsh/mapfile
|
|||
link=dynamic
|
||||
load=no
|
||||
|
||||
autoparams="mapfile"
|
||||
autofeatures="p:mapfile"
|
||||
|
||||
objects="mapfile.o"
|
||||
|
|
|
@ -2,6 +2,4 @@ name=zsh/mathfunc
|
|||
link=dynamic
|
||||
load=no
|
||||
|
||||
autobins="mathfunc"
|
||||
|
||||
objects="mathfunc.o"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -3,4 +3,4 @@ link=dynamic
|
|||
load=no
|
||||
|
||||
objects="socket.o"
|
||||
autobins="zsocket"
|
||||
autofeatures="b:zsocket"
|
||||
|
|
|
@ -2,6 +2,6 @@ name=zsh/stat
|
|||
link=dynamic
|
||||
load=no
|
||||
|
||||
autobins="stat"
|
||||
autofeatures="b:stat b:zstat"
|
||||
|
||||
objects="stat.o"
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -4,4 +4,4 @@ load=no
|
|||
functions='Functions/TCP/*'
|
||||
|
||||
objects="tcp.o"
|
||||
autobins="ztcp"
|
||||
autofeatures="b:ztcp"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -3,7 +3,7 @@ link=dynamic
|
|||
load=no
|
||||
functions='Functions/Zftp/*'
|
||||
|
||||
autobins="zftp"
|
||||
autofeatures="b:zftp"
|
||||
|
||||
moddeps="zsh/net/tcp"
|
||||
|
||||
|
|
|
@ -2,6 +2,6 @@ name=zsh/zprof
|
|||
link=dynamic
|
||||
load=no
|
||||
|
||||
autobins="zprof"
|
||||
autofeatures="b:zprof"
|
||||
|
||||
objects="zprof.o"
|
||||
|
|
|
@ -2,6 +2,6 @@ name=zsh/zpty
|
|||
link=dynamic
|
||||
load=no
|
||||
|
||||
autobins="zpty"
|
||||
autofeatures="b:zpty"
|
||||
|
||||
objects="zpty.o"
|
||||
|
|
|
@ -3,4 +3,4 @@ link=dynamic
|
|||
load=no
|
||||
|
||||
objects="zselect.o"
|
||||
autobins="zselect"
|
||||
autofeatures="b:zselect"
|
||||
|
|
|
@ -6,4 +6,4 @@ moddeps="zsh/complete"
|
|||
|
||||
objects="zutil.o"
|
||||
|
||||
autobins="zformat zstyle zregexparse zparseopts"
|
||||
autofeatures="b:zformat b:zstyle b:zregexparse b:zparseopts"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -4,6 +4,6 @@ load=yes
|
|||
|
||||
moddeps="zsh/zle"
|
||||
|
||||
autoparams="widgets keymaps"
|
||||
autofeatures="p:widgets p:keymaps"
|
||||
|
||||
objects="zleparameter.o"
|
||||
|
|
|
@ -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
|
||||
|
|
382
Src/module.c
382
Src/module.c
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue