summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog19
-rw-r--r--Doc/Zsh/builtins.yo22
-rw-r--r--Src/Builtins/rlimits.mdd2
-rw-r--r--Src/Builtins/sched.mdd3
-rw-r--r--Src/Modules/cap.mdd2
-rw-r--r--Src/Modules/clone.mdd2
-rw-r--r--Src/Modules/datetime.mdd2
-rw-r--r--Src/Modules/example.mdd7
-rw-r--r--Src/Modules/files.mdd2
-rw-r--r--Src/Modules/langinfo.mdd2
-rw-r--r--Src/Modules/mapfile.mdd2
-rw-r--r--Src/Modules/mathfunc.mdd2
-rw-r--r--Src/Modules/parameter.mdd2
-rw-r--r--Src/Modules/pcre.mdd2
-rw-r--r--Src/Modules/regex.mdd2
-rw-r--r--Src/Modules/socket.mdd2
-rw-r--r--Src/Modules/stat.mdd2
-rw-r--r--Src/Modules/system.mdd4
-rw-r--r--Src/Modules/tcp.mdd2
-rw-r--r--Src/Modules/termcap.mdd3
-rw-r--r--Src/Modules/terminfo.mdd3
-rw-r--r--Src/Modules/zftp.mdd2
-rw-r--r--Src/Modules/zprof.mdd2
-rw-r--r--Src/Modules/zpty.mdd2
-rw-r--r--Src/Modules/zselect.mdd2
-rw-r--r--Src/Modules/zutil.mdd2
-rw-r--r--Src/Zle/compctl.mdd2
-rw-r--r--Src/Zle/complete.mdd4
-rw-r--r--Src/Zle/computil.mdd2
-rw-r--r--Src/Zle/zle.mdd2
-rw-r--r--Src/Zle/zleparameter.mdd2
-rw-r--r--Src/mkbltnmlst.sh28
-rw-r--r--Src/module.c378
33 files changed, 344 insertions, 173 deletions
diff --git a/ChangeLog b/ChangeLog
index 91fdaaa4f..f07aeddc8 100644
--- a/ChangeLog
+++ b/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:
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index ca73499e2..2b61bb9b7 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -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) ...)
diff --git a/Src/Builtins/rlimits.mdd b/Src/Builtins/rlimits.mdd
index 98a80b09c..63ca7f9f3 100644
--- a/Src/Builtins/rlimits.mdd
+++ b/Src/Builtins/rlimits.mdd
@@ -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"
diff --git a/Src/Builtins/sched.mdd b/Src/Builtins/sched.mdd
index f440d6a19..4a9eb6488 100644
--- a/Src/Builtins/sched.mdd
+++ b/Src/Builtins/sched.mdd
@@ -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"
diff --git a/Src/Modules/cap.mdd b/Src/Modules/cap.mdd
index 4e7ee7216..905f7ca47 100644
--- a/Src/Modules/cap.mdd
+++ b/Src/Modules/cap.mdd
@@ -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"
diff --git a/Src/Modules/clone.mdd b/Src/Modules/clone.mdd
index 8e4181bd4..47fca4ce8 100644
--- a/Src/Modules/clone.mdd
+++ b/Src/Modules/clone.mdd
@@ -2,6 +2,6 @@ name=zsh/clone
link=dynamic
load=no
-autobins="clone"
+autofeatures="b:clone"
objects="clone.o"
diff --git a/Src/Modules/datetime.mdd b/Src/Modules/datetime.mdd
index 853b3bc79..0e5ffffb2 100644
--- a/Src/Modules/datetime.mdd
+++ b/Src/Modules/datetime.mdd
@@ -4,6 +4,6 @@ link=either
load=no
functions='Functions/Calendar/*'
-autobins="strftime"
+autofeatures="b:strftime p:EPOCHSECONDS"
objects="datetime.o"
diff --git a/Src/Modules/example.mdd b/Src/Modules/example.mdd
index b3fcc92f7..3a00e3ed2 100644
--- a/Src/Modules/example.mdd
+++ b/Src/Modules/example.mdd
@@ -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"
diff --git a/Src/Modules/files.mdd b/Src/Modules/files.mdd
index 18e69a45c..43b9f985a 100644
--- a/Src/Modules/files.mdd
+++ b/Src/Modules/files.mdd
@@ -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"
diff --git a/Src/Modules/langinfo.mdd b/Src/Modules/langinfo.mdd
index 66c4cd452..d56898d42 100644
--- a/Src/Modules/langinfo.mdd
+++ b/Src/Modules/langinfo.mdd
@@ -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"
diff --git a/Src/Modules/mapfile.mdd b/Src/Modules/mapfile.mdd
index 0a96caa0a..5e5e2ff89 100644
--- a/Src/Modules/mapfile.mdd
+++ b/Src/Modules/mapfile.mdd
@@ -2,6 +2,6 @@ name=zsh/mapfile
link=dynamic
load=no
-autoparams="mapfile"
+autofeatures="p:mapfile"
objects="mapfile.o"
diff --git a/Src/Modules/mathfunc.mdd b/Src/Modules/mathfunc.mdd
index 4d3dd934a..b19a17316 100644
--- a/Src/Modules/mathfunc.mdd
+++ b/Src/Modules/mathfunc.mdd
@@ -2,6 +2,4 @@ name=zsh/mathfunc
link=dynamic
load=no
-autobins="mathfunc"
-
objects="mathfunc.o"
diff --git a/Src/Modules/parameter.mdd b/Src/Modules/parameter.mdd
index 083ee622d..d506dacb3 100644
--- a/Src/Modules/parameter.mdd
+++ b/Src/Modules/parameter.mdd
@@ -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"
diff --git a/Src/Modules/pcre.mdd b/Src/Modules/pcre.mdd
index 724911ca0..3e1579117 100644
--- a/Src/Modules/pcre.mdd
+++ b/Src/Modules/pcre.mdd
@@ -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"
diff --git a/Src/Modules/regex.mdd b/Src/Modules/regex.mdd
index d025cabde..d532a8dd2 100644
--- a/Src/Modules/regex.mdd
+++ b/Src/Modules/regex.mdd
@@ -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"
diff --git a/Src/Modules/socket.mdd b/Src/Modules/socket.mdd
index 7147456d3..f405a92c3 100644
--- a/Src/Modules/socket.mdd
+++ b/Src/Modules/socket.mdd
@@ -3,4 +3,4 @@ link=dynamic
load=no
objects="socket.o"
-autobins="zsocket"
+autofeatures="b:zsocket"
diff --git a/Src/Modules/stat.mdd b/Src/Modules/stat.mdd
index 2534b1bdb..7be78e6ab 100644
--- a/Src/Modules/stat.mdd
+++ b/Src/Modules/stat.mdd
@@ -2,6 +2,6 @@ name=zsh/stat
link=dynamic
load=no
-autobins="stat"
+autofeatures="b:stat b:zstat"
objects="stat.o"
diff --git a/Src/Modules/system.mdd b/Src/Modules/system.mdd
index 556f9f2ac..46f02d166 100644
--- a/Src/Modules/system.mdd
+++ b/Src/Modules/system.mdd
@@ -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"
diff --git a/Src/Modules/tcp.mdd b/Src/Modules/tcp.mdd
index 88874cd7d..69fd4d6bf 100644
--- a/Src/Modules/tcp.mdd
+++ b/Src/Modules/tcp.mdd
@@ -4,4 +4,4 @@ load=no
functions='Functions/TCP/*'
objects="tcp.o"
-autobins="ztcp"
+autofeatures="b:ztcp"
diff --git a/Src/Modules/termcap.mdd b/Src/Modules/termcap.mdd
index a3ee39e02..f83cafef8 100644
--- a/Src/Modules/termcap.mdd
+++ b/Src/Modules/termcap.mdd
@@ -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"
diff --git a/Src/Modules/terminfo.mdd b/Src/Modules/terminfo.mdd
index 7d88dfb27..ee6d39f08 100644
--- a/Src/Modules/terminfo.mdd
+++ b/Src/Modules/terminfo.mdd
@@ -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"
diff --git a/Src/Modules/zftp.mdd b/Src/Modules/zftp.mdd
index 2614042b7..e96b367f9 100644
--- a/Src/Modules/zftp.mdd
+++ b/Src/Modules/zftp.mdd
@@ -3,7 +3,7 @@ link=dynamic
load=no
functions='Functions/Zftp/*'
-autobins="zftp"
+autofeatures="b:zftp"
moddeps="zsh/net/tcp"
diff --git a/Src/Modules/zprof.mdd b/Src/Modules/zprof.mdd
index c6cf563fa..6cf7f2723 100644
--- a/Src/Modules/zprof.mdd
+++ b/Src/Modules/zprof.mdd
@@ -2,6 +2,6 @@ name=zsh/zprof
link=dynamic
load=no
-autobins="zprof"
+autofeatures="b:zprof"
objects="zprof.o"
diff --git a/Src/Modules/zpty.mdd b/Src/Modules/zpty.mdd
index c6a9c5a7f..89857b782 100644
--- a/Src/Modules/zpty.mdd
+++ b/Src/Modules/zpty.mdd
@@ -2,6 +2,6 @@ name=zsh/zpty
link=dynamic
load=no
-autobins="zpty"
+autofeatures="b:zpty"
objects="zpty.o"
diff --git a/Src/Modules/zselect.mdd b/Src/Modules/zselect.mdd
index b9ee28535..73948e5d8 100644
--- a/Src/Modules/zselect.mdd
+++ b/Src/Modules/zselect.mdd
@@ -3,4 +3,4 @@ link=dynamic
load=no
objects="zselect.o"
-autobins="zselect"
+autofeatures="b:zselect"
diff --git a/Src/Modules/zutil.mdd b/Src/Modules/zutil.mdd
index 587677dc2..8064814aa 100644
--- a/Src/Modules/zutil.mdd
+++ b/Src/Modules/zutil.mdd
@@ -6,4 +6,4 @@ moddeps="zsh/complete"
objects="zutil.o"
-autobins="zformat zstyle zregexparse zparseopts"
+autofeatures="b:zformat b:zstyle b:zregexparse b:zparseopts"
diff --git a/Src/Zle/compctl.mdd b/Src/Zle/compctl.mdd
index f4fc1d0b4..ea7470998 100644
--- a/Src/Zle/compctl.mdd
+++ b/Src/Zle/compctl.mdd
@@ -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"
diff --git a/Src/Zle/complete.mdd b/Src/Zle/complete.mdd
index 519ab26b3..7bc693aa6 100644
--- a/Src/Zle/complete.mdd
+++ b/Src/Zle/complete.mdd
@@ -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"
diff --git a/Src/Zle/computil.mdd b/Src/Zle/computil.mdd
index 161177859..4017fffef 100644
--- a/Src/Zle/computil.mdd
+++ b/Src/Zle/computil.mdd
@@ -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"
diff --git a/Src/Zle/zle.mdd b/Src/Zle/zle.mdd
index 9981cec90..c6e4d11c2 100644
--- a/Src/Zle/zle.mdd
+++ b/Src/Zle/zle.mdd
@@ -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 \
diff --git a/Src/Zle/zleparameter.mdd b/Src/Zle/zleparameter.mdd
index ef3e1d5f5..872df3f99 100644
--- a/Src/Zle/zleparameter.mdd
+++ b/Src/Zle/zleparameter.mdd
@@ -4,6 +4,6 @@ load=yes
moddeps="zsh/zle"
-autoparams="widgets keymaps"
+autofeatures="p:widgets p:keymaps"
objects="zleparameter.o"
diff --git a/Src/mkbltnmlst.sh b/Src/mkbltnmlst.sh
index a3785cb8c..5bd510add 100644
--- a/Src/mkbltnmlst.sh
+++ b/Src/mkbltnmlst.sh
@@ -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
diff --git a/Src/module.c b/Src/module.c
index d40bb133a..ef158c6a3 100644
--- a/Src/module.c
+++ b/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;
+
+ if (strchr(cnam, '/')) {
+ zwarnnam(cmdnam, "%s: `/' is illegal in a condition", cnam);
+ return 1;
+ }
+
+ c = (Conddef) zalloc(sizeof(*c));
- c->name = ztrdup(nam);
+ 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;
+
+ if (strchr(pnam, '/')) {
+ zwarnnam(cmdnam, "%s: `/' is illegal in a parameter", pnam);
+ return 1;
+ }
queue_signals();
- if (checkaddparam(nam)) {
+ if ((ret = checkaddparam(pnam, opt_i))) {
unqueue_signals();
- return;
+ /*
+ * 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(nam, ztrdup(module));
+ 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;
+
+ if (strchr(fnam, '/')) {
+ zwarnnam(cmdnam, "%s: `/' is illegal in a math function", fnam);
+ return 1;
+ }
- f->name = ztrdup(nam);
+ 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;
+}