From 0a1de76213c4012a8b17b30eb08a77c4aa05d4bc Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 20 Jun 2007 20:59:15 +0000 Subject: 23578: make standard features autoloadable, use feature notation for .mdd autoloads --- ChangeLog | 19 +++ Doc/Zsh/builtins.yo | 22 ++- Src/Builtins/rlimits.mdd | 2 +- Src/Builtins/sched.mdd | 3 +- Src/Modules/cap.mdd | 2 +- Src/Modules/clone.mdd | 2 +- Src/Modules/datetime.mdd | 2 +- Src/Modules/example.mdd | 7 +- Src/Modules/files.mdd | 2 +- Src/Modules/langinfo.mdd | 2 +- Src/Modules/mapfile.mdd | 2 +- Src/Modules/mathfunc.mdd | 2 - Src/Modules/parameter.mdd | 2 +- Src/Modules/pcre.mdd | 2 +- Src/Modules/regex.mdd | 2 - Src/Modules/socket.mdd | 2 +- Src/Modules/stat.mdd | 2 +- Src/Modules/system.mdd | 4 +- Src/Modules/tcp.mdd | 2 +- Src/Modules/termcap.mdd | 3 +- Src/Modules/terminfo.mdd | 3 +- Src/Modules/zftp.mdd | 2 +- Src/Modules/zprof.mdd | 2 +- Src/Modules/zpty.mdd | 2 +- Src/Modules/zselect.mdd | 2 +- Src/Modules/zutil.mdd | 2 +- Src/Zle/compctl.mdd | 2 +- Src/Zle/complete.mdd | 4 +- Src/Zle/computil.mdd | 2 +- Src/Zle/zle.mdd | 2 +- Src/Zle/zleparameter.mdd | 2 +- Src/mkbltnmlst.sh | 28 ++-- Src/module.c | 378 +++++++++++++++++++++++++++++++++------------- 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 + + * 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 * 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; +} -- cgit 1.4.1