From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22855 invoked from network); 24 Nov 1999 16:01:00 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 24 Nov 1999 16:01:00 -0000 Received: (qmail 13822 invoked by alias); 24 Nov 1999 16:00:53 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 8770 Received: (qmail 13813 invoked from network); 24 Nov 1999 16:00:49 -0000 Date: Wed, 24 Nov 1999 17:00:47 +0100 (MET) Message-Id: <199911241600.RAA02291@beta.informatik.hu-berlin.de> From: Sven Wischnowsky To: zsh-workers@sunsite.auc.dk Subject: PATCH: module non-loading This patch tries to make modules behave the same independent of the way they are made available: linked in or dynamically loaded. User-visible changes: - There is only one zmodload builtin now, behaving the same in shells with and without dynamic loading. - This also means that even if you have selected module to be linked in, you have to cal zmodload to get at the builtins and others tuff defined by the module. Unless the module defined theses things to be autoloaded, then it will happen automatically as usual. - The -e option of zmodload now only prints the `loaded' modules. I.e. the same ones shown by zmodload without arguments. In other words: -e is now only useful for testing if a modules is available. Maybe we should remove that option altogether and just use -i for such things? Internal changes: - DYNAMIC is used only in module.c now. And especially modules should not use it (nor MODULE), to ensure that they behave the same when loaded or linked in. - Linked-in modules still call register_module() but that now also gives the four setup/cleanup functions. These are stored in a list and called directly when needed (instead of trying to do some symbol lookup or whatever). - The functions for the zsh module are now explicitly called in init.c. - The cleanup and finish functions of all modules that were used are called when the shell exits. I've put that in a function that is called from zexit(), hope that's the right place. this means that modules can now rely on these functions being called, so if they have to ensure that something is done when the shell exits or the module is unloaded, they can now be sure that it will be executed. Open questions: - The zshxmods.h stuff may need some more looking-after. Maybe we can even remove it altogether? - Of course I couldn't test it on systems like AIX and HPUX where we have special module-loading code. But I *did* test it with dynamically loaded and linked in modules both in a shell with and one without dynamic loading. Even if it may not be perfect yet, I hope it's a step in the right direction. Bye Sven diff -u -r oldsrc/Builtins/rlimits.c Src/Builtins/rlimits.c --- oldsrc/Builtins/rlimits.c Wed Nov 24 12:58:52 1999 +++ Src/Builtins/rlimits.c Wed Nov 24 13:39:15 1999 @@ -637,8 +637,6 @@ return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); } -#ifdef MODULE - /**/ int cleanup_rlimits(Module m) @@ -653,5 +651,3 @@ { return 0; } - -#endif diff -u -r oldsrc/Builtins/sched.c Src/Builtins/sched.c --- oldsrc/Builtins/sched.c Wed Nov 24 12:58:52 1999 +++ Src/Builtins/sched.c Wed Nov 24 13:39:32 1999 @@ -200,8 +200,6 @@ return 0; } -#ifdef MODULE - /**/ int cleanup_sched(Module m) @@ -224,5 +222,3 @@ { return 0; } - -#endif diff -u -r oldsrc/Modules/cap.c Src/Modules/cap.c --- oldsrc/Modules/cap.c Wed Nov 24 12:58:37 1999 +++ Src/Modules/cap.c Wed Nov 24 13:39:47 1999 @@ -136,8 +136,6 @@ return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); } -#ifdef MODULE - /**/ int cleanup_cap(Module m) @@ -152,5 +150,3 @@ { return 0; } - -#endif diff -u -r oldsrc/Modules/clone.c Src/Modules/clone.c --- oldsrc/Modules/clone.c Wed Nov 24 12:58:37 1999 +++ Src/Modules/clone.c Wed Nov 24 13:39:56 1999 @@ -110,8 +110,6 @@ return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); } -#ifdef MODULE - /**/ int cleanup_clone(Module m) @@ -126,5 +124,3 @@ { return 0; } - -#endif diff -u -r oldsrc/Modules/example.c Src/Modules/example.c --- oldsrc/Modules/example.c Wed Nov 24 12:58:38 1999 +++ Src/Modules/example.c Wed Nov 24 13:40:10 1999 @@ -212,8 +212,6 @@ !addwrapper(m, wrapper)); } -#ifdef MODULE - /**/ int cleanup_example(Module m) @@ -234,5 +232,3 @@ fflush(stdout); return 0; } - -#endif diff -u -r oldsrc/Modules/files.c Src/Modules/files.c --- oldsrc/Modules/files.c Wed Nov 24 12:58:38 1999 +++ Src/Modules/files.c Wed Nov 24 13:40:22 1999 @@ -523,8 +523,6 @@ return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); } -#ifdef MODULE - /**/ int cleanup_files(Module m) @@ -539,5 +537,3 @@ { return 0; } - -#endif diff -u -r oldsrc/Modules/mapfile.c Src/Modules/mapfile.c --- oldsrc/Modules/mapfile.c Wed Nov 24 12:58:38 1999 +++ Src/Modules/mapfile.c Wed Nov 24 13:40:45 1999 @@ -346,8 +346,6 @@ return 0; } -#ifdef MODULE - /**/ int cleanup_mapfile(Module m) @@ -370,5 +368,3 @@ { return 0; } - -#endif diff -u -r oldsrc/Modules/mathfunc.c Src/Modules/mathfunc.c --- oldsrc/Modules/mathfunc.c Wed Nov 24 12:58:38 1999 +++ Src/Modules/mathfunc.c Wed Nov 24 13:41:04 1999 @@ -462,8 +462,6 @@ return !addmathfuncs(m->nam, mftab, sizeof(mftab)/sizeof(*mftab)); } -#ifdef MODULE - /**/ int cleanup_mathfunc(Module m) @@ -478,5 +476,3 @@ { return 0; } - -#endif diff -u -r oldsrc/Modules/parameter.c Src/Modules/parameter.c --- oldsrc/Modules/parameter.c Wed Nov 24 12:58:38 1999 +++ Src/Modules/parameter.c Wed Nov 24 14:48:49 1999 @@ -901,18 +901,12 @@ pm->old = NULL; pm->level = 0; - for (node = firstnode(bltinmodules); node; incnode(node)) - if (!strcmp(name, (char *) getdata(node))) { - type = "builtin"; - break; - } -#ifdef DYNAMIC if (!type) { Module m; for (node = firstnode(modules); node; incnode(node)) { m = (Module) getdata(node); - if (m->handle && !(m->flags & MOD_UNLOAD) && + if (m->u.handle && !(m->flags & MOD_UNLOAD) && !strcmp(name, m->nam)) { type = "loaded"; break; @@ -937,7 +931,6 @@ if (modpmfound) type = "autoloaded"; } -#endif if (type) pm->u.str = dupstring(type); else { @@ -972,16 +965,10 @@ pm.level = 0; pm.u.str = dupstring("builtin"); - for (node = firstnode(bltinmodules); node; incnode(node)) { - pm.nam = (char *) getdata(node); - addlinknode(done, pm.nam); - func((HashNode) &pm, flags); - } -#ifdef DYNAMIC pm.u.str = dupstring("loaded"); for (node = firstnode(modules); node; incnode(node)) { m = (Module) getdata(node); - if (m->handle && !(m->flags & MOD_UNLOAD)) { + if (m->u.handle && !(m->flags & MOD_UNLOAD)) { pm.nam = m->nam; addlinknode(done, pm.nam); func((HashNode) &pm, flags); @@ -1012,7 +999,6 @@ func((HashNode) &pm, flags); } } -#endif } /* Functions for the dirstack special parameter. */ @@ -1919,8 +1905,6 @@ return 0; } -#ifdef MODULE - /**/ int cleanup_parameter(Module m) @@ -1949,5 +1933,3 @@ { return 0; } - -#endif diff -u -r oldsrc/Modules/stat.c Src/Modules/stat.c --- oldsrc/Modules/stat.c Wed Nov 24 12:58:38 1999 +++ Src/Modules/stat.c Wed Nov 24 13:41:24 1999 @@ -602,8 +602,6 @@ return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); } -#ifdef MODULE - /**/ int cleanup_stat(Module m) @@ -618,5 +616,3 @@ { return 0; } - -#endif diff -u -r oldsrc/Modules/zftp.c Src/Modules/zftp.c --- oldsrc/Modules/zftp.c Wed Nov 24 12:58:38 1999 +++ Src/Modules/zftp.c Wed Nov 24 13:41:52 1999 @@ -3213,8 +3213,6 @@ return !ret; } -#ifdef MODULE - /**/ int cleanup_zftp(Module m) @@ -3249,5 +3247,3 @@ { return 0; } - -#endif diff -u -r oldsrc/Zle/compctl.c Src/Zle/compctl.c --- oldsrc/Zle/compctl.c Wed Nov 24 09:03:40 1999 +++ Src/Zle/compctl.c Wed Nov 24 13:42:09 1999 @@ -3764,8 +3764,6 @@ return (addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) != 1); } -#ifdef MODULE - /**/ int cleanup_compctl(Module m) @@ -3789,5 +3787,3 @@ compctlreadptr = fallback_compctlread; return 0; } - -#endif diff -u -r oldsrc/Zle/complete.c Src/Zle/complete.c --- oldsrc/Zle/complete.c Wed Nov 24 09:03:40 1999 +++ Src/Zle/complete.c Wed Nov 24 15:45:42 1999 @@ -1389,8 +1389,6 @@ return 0; } -#ifdef MODULE - /**/ int cleanup_complete(Module m) @@ -1414,7 +1412,8 @@ int finish_complete(Module m) { - freearray(compwords); + if (compwords) + freearray(compwords); zsfree(compprefix); zsfree(compsuffix); zsfree(compiprefix); @@ -1446,5 +1445,3 @@ return 0; } - -#endif diff -u -r oldsrc/Zle/complist.c Src/Zle/complist.c --- oldsrc/Zle/complist.c Wed Nov 24 09:03:40 1999 +++ Src/Zle/complist.c Wed Nov 24 13:42:31 1999 @@ -935,8 +935,6 @@ return 0; } -#ifdef MODULE - /**/ int cleanup_complist(Module m) @@ -957,5 +955,3 @@ { return 0; } - -#endif diff -u -r oldsrc/Zle/computil.c Src/Zle/computil.c --- oldsrc/Zle/computil.c Wed Nov 24 09:03:40 1999 +++ Src/Zle/computil.c Wed Nov 24 13:42:44 1999 @@ -2837,8 +2837,6 @@ return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); } -#ifdef MODULE - /**/ int cleanup_computil(Module m) @@ -2865,5 +2863,3 @@ return 0; } - -#endif diff -u -r oldsrc/Zle/deltochar.c Src/Zle/deltochar.c --- oldsrc/Zle/deltochar.c Wed Nov 24 09:03:40 1999 +++ Src/Zle/deltochar.c Wed Nov 24 13:42:55 1999 @@ -98,8 +98,6 @@ return -1; } -#ifdef MODULE - /**/ int cleanup_deltochar(Module m) @@ -115,5 +113,3 @@ { return 0; } - -#endif diff -u -r oldsrc/Zle/zle_hist.c Src/Zle/zle_hist.c --- oldsrc/Zle/zle_hist.c Wed Nov 24 09:03:41 1999 +++ Src/Zle/zle_hist.c Wed Nov 24 13:43:22 1999 @@ -612,17 +612,11 @@ static int max_spot = 0; /**/ -#ifdef MODULE - -/**/ void free_isrch_spots(void) { zfree(isrch_spots, max_spot * sizeof(*isrch_spots)); } - -/**/ -#endif /* MODULE */ /**/ static void diff -u -r oldsrc/Zle/zle_keymap.c Src/Zle/zle_keymap.c --- oldsrc/Zle/zle_keymap.c Wed Nov 24 09:03:41 1999 +++ Src/Zle/zle_keymap.c Wed Nov 24 13:43:38 1999 @@ -1000,8 +1000,6 @@ lastnamed = refthingy(t_undefinedkey); } -#ifdef MODULE - /* cleanup entry point (for unloading the zle module) */ /**/ @@ -1012,8 +1010,6 @@ deletehashtable(keymapnamtab); zfree(keybuf, keybufsz); } - -#endif /* MODULE */ /* Create the default keymaps. For efficiency reasons, this function * * assigns directly to the km->first array. It knows that there are no * diff -u -r oldsrc/Zle/zle_main.c Src/Zle/zle_main.c --- oldsrc/Zle/zle_main.c Wed Nov 24 09:03:41 1999 +++ Src/Zle/zle_main.c Wed Nov 24 13:43:52 1999 @@ -1043,8 +1043,6 @@ return 0; } -#ifdef MODULE - /**/ int cleanup_zle(Module m) @@ -1093,5 +1091,3 @@ return 0; } - -#endif /* MODULE */ diff -u -r oldsrc/Zle/zle_thingy.c Src/Zle/zle_thingy.c --- oldsrc/Zle/zle_thingy.c Wed Nov 24 09:03:42 1999 +++ Src/Zle/zle_thingy.c Wed Nov 24 13:36:18 1999 @@ -286,8 +286,6 @@ return w; } -#ifdef DYNAMIC - /* Delete an internal widget provided by a module. Don't try to delete * * a widget from the fixed table -- it would be bad. (Thanks, Egon.) */ @@ -309,8 +307,6 @@ } } -#endif /* DYNAMIC */ - /***************/ /* zle builtin */ /***************/ @@ -550,18 +546,10 @@ Thingy t; Widget w, cw; -#ifdef DYNAMIC if (!require_module(name, "complete", 0, 0)) { zerrnam(name, "can't load complete module", NULL, 0); return 1; } -#else - if (!module_linked("complete")) { - zerrnam(name, "complete module not available", NULL, 0); - return 1; - } -#endif - t = rthingy((args[1][0] == '.') ? args[1] : dyncat(".", args[1])); cw = t->widget; unrefthingy(t); diff -u -r oldsrc/Zle/zleparameter.c Src/Zle/zleparameter.c --- oldsrc/Zle/zleparameter.c Wed Nov 24 09:03:42 1999 +++ Src/Zle/zleparameter.c Wed Nov 24 13:44:04 1999 @@ -230,8 +230,6 @@ return 0; } -#ifdef MODULE - /**/ int cleanup_zleparameter(Module m) @@ -255,5 +253,3 @@ { return 0; } - -#endif diff -u -r oldsrc/builtin.c Src/builtin.c --- oldsrc/builtin.c Wed Nov 24 09:03:35 1999 +++ Src/builtin.c Wed Nov 24 15:59:15 1999 @@ -123,12 +123,7 @@ BUILTIN("whence", 0, bin_whence, 0, -1, 0, "acmpvfsw", NULL), BUILTIN("where", 0, bin_whence, 0, -1, 0, "pmsw", "ca"), BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsw", "c"), - -#ifdef DYNAMIC BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "ILabcfdipue", NULL), -#else - BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "ei", NULL), -#endif }; /****************************************/ @@ -229,14 +224,11 @@ arg = (char *) ugetnode(args); -#ifdef DYNAMIC if (!bn->handlerfunc) { zwarnnam(name, "autoload failed", NULL, 0); deletebuiltin(bn->nam); return 1; } -#endif - /* get some information about the command */ flags = bn->flags; optstr = bn->optstr; @@ -3209,6 +3201,8 @@ if (in_exit++ && from_signal) { LASTALLOC_RETURN; } + exit_modules(); + if (isset(MONITOR)) { /* send SIGHUP to any jobs left running */ killrunjobs(from_signal); diff -u -r oldsrc/exec.c Src/exec.c --- oldsrc/exec.c Wed Nov 24 09:03:36 1999 +++ Src/exec.c Wed Nov 24 15:30:44 1999 @@ -1504,13 +1504,12 @@ } if (!(hn->flags & BINF_PREFIX)) { is_builtin = 1; -#ifdef DYNAMIC + /* autoload the builtin if necessary */ if (!((Builtin) hn)->handlerfunc) { load_module(((Builtin) hn)->optstr); hn = builtintab->getnode(builtintab, cmdarg); } -#endif assign = (hn->flags & BINF_MAGICEQUALS); break; } @@ -1619,13 +1618,12 @@ } if (!(hn->flags & BINF_PREFIX)) { is_builtin = 1; -#ifdef DYNAMIC + /* autoload the builtin if necessary */ if (!((Builtin) hn)->handlerfunc) { load_module(((Builtin) hn)->optstr); hn = builtintab->getnode(builtintab, cmdarg); } -#endif break; } cflags &= ~BINF_BUILTIN & ~BINF_COMMAND; @@ -3072,11 +3070,11 @@ wrap->module->wrapper++; cont = wrap->handler(list, wrap->next, name); wrap->module->wrapper--; -#ifdef DYNAMIC + if (!wrap->module->wrapper && (wrap->module->flags & MOD_UNLOAD)) - unload_module(wrap->module, NULL); -#endif + unload_module(wrap->module, NULL, 0); + if (!cont) return; wrap = wrap->next; diff -u -r oldsrc/init.c Src/init.c --- oldsrc/init.c Wed Nov 24 09:03:36 1999 +++ Src/init.c Wed Nov 24 16:38:01 1999 @@ -599,11 +599,9 @@ mailpath = mkarray(NULL); watch = mkarray(NULL); psvar = mkarray(NULL); -#ifdef DYNAMIC module_path = mkarray(ztrdup(MODULE_DIR)); modules = newlinklist(); -#endif - bltinmodules = newlinklist(); + linkedmodules = newlinklist(); /* Set default prompts */ if(unset(INTERACTIVE)) { @@ -940,9 +938,10 @@ void init_bltinmods(void) { - static struct module mod = { NULL, 0, NULL, NULL }; + #include "bltinmods.list" - mod.nam = NULL; + + load_module("zsh"); } /**/ @@ -969,13 +968,13 @@ /**/ ZleVoidFn trashzleptr = noop_function; /**/ -ZleVoidFn gotwordptr; +ZleVoidFn gotwordptr = noop_function; /**/ -ZleVoidFn refreshptr; +ZleVoidFn refreshptr = noop_function; /**/ -ZleVoidIntFn spaceinlineptr; +ZleVoidIntFn spaceinlineptr = noop_function_int; /**/ -ZleReadFn zlereadptr; +ZleReadFn zlereadptr = autoload_zleread; #else /* !LINKED_XMOD_zle */ @@ -989,11 +988,10 @@ ZleReadFn zlereadptr = fallback_zleread; # endif /* !UNLINKED_XMOD_zle */ -/**/ -# ifdef UNLINKED_XMOD_zle +#endif /* !LINKED_XMOD_zle */ /**/ -static unsigned char * +unsigned char * autoload_zleread(char *lp, char *rp, int ha) { zlereadptr = fallback_zleread; @@ -1002,9 +1000,6 @@ } /**/ -# endif /* UNLINKED_XMOD_zle */ - -/**/ unsigned char * fallback_zleread(char *lp, char *rp, int ha) { @@ -1016,8 +1011,6 @@ free(pptbuf); return (unsigned char *)shingetline(); } - -#endif /* !LINKED_XMOD_zle */ /* compctl entry point pointers. Similar to the ZLE ones. */ diff -u -r oldsrc/mkbltnmlst.sh Src/mkbltnmlst.sh --- oldsrc/mkbltnmlst.sh Wed Nov 24 13:47:28 1999 +++ Src/mkbltnmlst.sh Wed Nov 24 14:41:43 1999 @@ -4,6 +4,7 @@ # # Written by Andrew Main # + srcdir=${srcdir-`echo $0|sed 's%/[^/][^/]*$%%'`} test "x$srcdir" = "x$0" && srcdir=. test "x$srcdir" = "x" && srcdir=. @@ -18,40 +19,32 @@ exec > $1 -echo "#ifdef DYNAMIC" for x_mod in $x_mods; do - case $bin_mods in - *" $x_mod "*) ;; - *) echo "/* non-linked-in known module \`$x_mod' */" - eval "loc=\$loc_$x_mod" - unset moddeps autobins autoinfixconds autoprefixconds autoparams - unset automathfuncs - . $srcdir/../$loc/${x_mod}.mdd - 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_automath(\"$mfunc\", \"$x_mod\");" - done - for dep in $moddeps; do - case $bin_mods in - *" $dep "*) - echo " /* depends on \`$dep' */" ;; - *) echo " add_dep(\"$x_mod\", \"$dep\");" ;; - esac - done ;; - esac + echo "/* non-linked-in known module \`$x_mod' */" + eval "loc=\$loc_$x_mod" + unset moddeps autobins autoinfixconds autoprefixconds autoparams + unset automathfuncs + . $srcdir/../$loc/${x_mod}.mdd + 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_automath(\"$mfunc\", \"$x_mod\");" + done + for dep in $moddeps; do + echo " add_dep(\"$x_mod\", \"$dep\");" + done done -echo "#endif /* DYNAMIC */" + echo done_mods=" " for bin_mod in $bin_mods; do @@ -68,6 +61,15 @@ exit 1 ;; esac done - echo " register_module(mod.nam = \"$bin_mod\"); setup_$bin_mod(&mod); boot_$bin_mod(&mod);" + echo " {" + echo " extern int setup_${bin_mod} _((Module));" + echo " extern int boot_${bin_mod} _((Module));" + echo " extern int cleanup_${bin_mod} _((Module));" + echo " extern int finish_${bin_mod} _((Module));" + echo + echo " register_module(\"$bin_mod\"," + echo " setup_${bin_mod}, boot_${bin_mod}," + echo " cleanup_${bin_mod}, finish_${bin_mod});" + echo " }" done_mods="$done_mods$bin_mod " done diff -u -r oldsrc/module.c Src/module.c --- oldsrc/module.c Wed Nov 24 09:41:48 1999 +++ Src/module.c Wed Nov 24 16:25:29 1999 @@ -30,10 +30,10 @@ #include "zsh.mdh" #include "module.pro" -/* List of builtin modules. */ +/* List of linked-in modules. */ /**/ -LinkList bltinmodules; +LinkList linkedmodules; /* The `zsh' module contains all the base code that can't actually be built * @@ -54,30 +54,55 @@ return 0; } +/**/ +int +cleanup_zsh(Module m) +{ + return 0; +} + +/**/ +int +finish_zsh(Module m) +{ + return 0; +} + /* This registers a builtin module. */ /**/ void -register_module(char *n) +register_module(char *n, Module_func setup, Module_func boot, + Module_func cleanup, Module_func finish) { + Linkedmod m; + PERMALLOC { - addlinknode(bltinmodules, n); + m = (Linkedmod) zalloc(sizeof(*m)); + + m->name = ztrdup(n); + m->setup = setup; + m->boot = boot; + m->cleanup = cleanup; + m->finish = finish; + + addlinknode(linkedmodules, m); } LASTALLOC; } /* Check if a module is linked in. */ /**/ -int -module_linked(char *name) +Linkedmod +module_linked(char const *name) { LinkNode node; - for (node = firstnode(bltinmodules); node; incnode(node)) - if (!strcmp((char *) getdata(node), name)) - return 1; + for (node = firstnode(linkedmodules); node; incnode(node)) + if (!strcmp(((Linkedmod) getdata(node))->name, name)) + return (Linkedmod) getdata(node); - return 0; + return NULL; } /* addbuiltin() can be used to add a new builtin. It returns zero on * @@ -157,9 +182,6 @@ return 0; } -/**/ -#ifdef DYNAMIC - /* $module_path ($MODULE_PATH) */ /**/ @@ -255,6 +277,9 @@ } /**/ +#ifdef DYNAMIC + +/**/ #ifdef AIXDYNAMIC #include @@ -271,8 +296,8 @@ int err = loadbind(0, (void *) addbuiltin, ret); for (node = firstnode(modules); !err && node; incnode(node)) { Module m = (Module) getdata(node); - if (m->handle) - err |= loadbind(0, m->handle, ret); + if (m->u.handle) + err |= loadbind(0, m->u.handle, ret); } if (err) { @@ -361,8 +386,6 @@ # define RTLD_GLOBAL 0 #endif -typedef int (*Module_func) _((Module)); - /**/ static void * try_load_module(char const *name) @@ -415,6 +438,19 @@ } /**/ +#else /* !DYNAMIC */ + +/**/ +static void * +do_load_module(char const *name) +{ + return NULL; +} + +/**/ +#endif /* !DYNAMIC */ + +/**/ static LinkNode find_module(const char *name) { @@ -430,34 +466,37 @@ } /**/ +#ifdef DYNAMIC + +/**/ #ifdef AIXDYNAMIC /**/ static int -setup_module(Module m) +dyn_setup_module(Module m) { - return ((int (*)_((int,Module))) m->handle)(0, m); + return ((int (*)_((int,Module))) m->u.handle)(0, m); } /**/ static int -init_module(Module m) +dyn_boot_module(Module m) { - return ((int (*)_((int,Module))) m->handle)(1, m); + return ((int (*)_((int,Module))) m->u.handle)(1, m); } /**/ static int -cleanup_module(Module m) +dyn_cleanup_module(Module m) { - return ((int (*)_((int,Module))) m->handle)(2, m); + return ((int (*)_((int,Module))) m->u.handle)(2, m); } /**/ static int -finish_module(Module m) +dyn_finish_module(Module m) { - return ((int (*)_((int,Module))) m->handle)(3, m); + return ((int (*)_((int,Module))) m->u.handle)(3, m); } /**/ @@ -480,19 +519,19 @@ if ((t = strrchr(s, '.'))) *t = '\0'; #ifdef DYNAMIC_NAME_CLASH_OK - fn = (Module_func) dlsym(m->handle, name); + fn = (Module_func) dlsym(m->u.handle, name); #else /* !DYNAMIC_NAME_CLASH_OK */ if (strlen(s) + 6 > PATH_MAX) return NULL; sprintf(buf, name_s, s); - fn = (Module_func) dlsym(m->handle, buf); + fn = (Module_func) dlsym(m->u.handle, buf); #endif /* !DYNAMIC_NAME_CLASH_OK */ return fn; } /**/ static int -setup_module(Module m) +dyn_setup_module(Module m) { Module_func fn = module_func(m, STR_SETUP, STR_SETUP_S); @@ -504,7 +543,7 @@ /**/ static int -init_module(Module m) +dyn_boot_module(Module m) { Module_func fn = module_func(m, STR_BOOT, STR_BOOT_S); @@ -516,7 +555,7 @@ /**/ static int -cleanup_module(Module m) +dyn_cleanup_module(Module m) { Module_func fn = module_func(m, STR_CLEANUP, STR_CLEANUP_S); @@ -531,7 +570,7 @@ /**/ static int -finish_module(Module m) +dyn_finish_module(Module m) { Module_func fn = module_func(m, STR_FINISH, STR_FINISH_S); int r; @@ -542,7 +581,7 @@ zwarnnam(m->nam, "no finish function", NULL, 0); r = 1; } - dlclose(m->handle); + dlclose(m->u.handle); return r; } @@ -550,34 +589,107 @@ #endif /* !AIXDYNAMIC */ /**/ +static int +setup_module(Module m) +{ + return ((m->flags & MOD_LINKED) ? + (m->u.linked->setup)(m) : dyn_setup_module(m)); +} + +/**/ +static int +boot_module(Module m) +{ + return ((m->flags & MOD_LINKED) ? + (m->u.linked->boot)(m) : dyn_boot_module(m)); +} + +/**/ +static int +cleanup_module(Module m) +{ + return ((m->flags & MOD_LINKED) ? + (m->u.linked->cleanup)(m) : dyn_cleanup_module(m)); +} + +/**/ +static int +finish_module(Module m) +{ + return ((m->flags & MOD_LINKED) ? + (m->u.linked->finish)(m) : dyn_finish_module(m)); +} + +/**/ +#else /* !DYNAMIC */ + +/**/ +static int +setup_module(Module m) +{ + return ((m->flags & MOD_LINKED) ? (m->u.linked->setup)(m) : 1); +} + +/**/ +static int +boot_module(Module m) +{ + return ((m->flags & MOD_LINKED) ? (m->u.linked->boot)(m) : 1); +} + +/**/ +static int +cleanup_module(Module m) +{ + return ((m->flags & MOD_LINKED) ? (m->u.linked->cleanup)(m) : 1); +} + +/**/ +static int +finish_module(Module m) +{ + return ((m->flags & MOD_LINKED) ? (m->u.linked->finish)(m) : 1); +} + +/**/ +#endif /* !DYNAMIC */ + +/**/ int load_module(char const *name) { Module m; - void *handle; + void *handle = NULL; + Linkedmod linked; LinkNode node, n; - - if (module_linked(name)) - return 1; + int set; if (!(node = find_module(name))) { - if (!(handle = do_load_module(name))) - return NULL; + if (!(linked = module_linked(name)) && + !(handle = do_load_module(name))) + return 0; m = zcalloc(sizeof(*m)); m->nam = ztrdup(name); - m->handle = handle; - m->flags |= MOD_SETUP; + if (handle) { + m->u.handle = handle; + m->flags |= MOD_SETUP; + } else { + m->u.linked = linked; + m->flags |= MOD_SETUP | MOD_LINKED; + } PERMALLOC { node = addlinknode(modules, m); } LASTALLOC; - if (setup_module(m) || init_module(m)) { - finish_module(m); + if ((set = setup_module(m)) || boot_module(m)) { + if (!set) + finish_module(m); remnode(modules, node); zsfree(m->nam); zfree(m, sizeof(*m)); m->flags &= ~MOD_SETUP; - return NULL; + return 0; } + m->flags |= MOD_INIT_S | MOD_INIT_B; m->flags &= ~MOD_SETUP; return 1; } @@ -586,7 +698,7 @@ return 1; if (m->flags & MOD_UNLOAD) m->flags &= ~MOD_UNLOAD; - else if (m->handle) + else if ((m->flags & MOD_LINKED) ? m->u.linked : m->u.handle) return 1; if (m->flags & MOD_BUSY) { zerr("circular dependencies for module %s", name, 0); @@ -600,24 +712,39 @@ return 0; } m->flags &= ~MOD_BUSY; - if (!m->handle) { - if (!(m->handle = do_load_module(name))) + if (!m->u.handle) { + handle = NULL; + if (!(linked = module_linked(name)) && + !(handle = do_load_module(name))) return 0; - m->flags |= MOD_SETUP; + if (handle) { + m->u.handle = handle; + m->flags |= MOD_SETUP; + } else { + m->u.linked = linked; + m->flags |= MOD_SETUP | MOD_LINKED; + } if (setup_module(m)) { - finish_module(m->handle); - m->handle = NULL; + if (handle) + m->u.handle = NULL; + else + m->u.linked = NULL; m->flags &= ~MOD_SETUP; return 0; } + m->flags |= MOD_INIT_S; } m->flags |= MOD_SETUP; - if (init_module(m)) { - finish_module(m->handle); - m->handle = NULL; + if (boot_module(m)) { + finish_module(m); + if (m->flags & MOD_LINKED) + m->u.linked = NULL; + else + m->u.handle = NULL; m->flags &= ~MOD_SETUP; return 0; } + m->flags |= MOD_INIT_B; m->flags &= ~MOD_SETUP; return 1; } @@ -638,12 +765,12 @@ LinkNode node; /* First see if the module is linked in. */ - for (node = firstnode(bltinmodules); node; incnode(node)) { + for (node = firstnode(linkedmodules); node; incnode(node)) { if (!strcmp((char *) getdata(node), nam)) return 1; } node = find_module(module); - if (node && (m = ((Module) getdata(node)))->handle && + if (node && (m = ((Module) getdata(node)))->u.handle && !(m->flags & MOD_UNLOAD)) { if (test) { zwarnnam(nam, "module %s already loaded.", module, 0); @@ -710,6 +837,47 @@ putchar('\n'); } +/* Cleanup and finish all modules. */ + +/**/ +void +exit_modules(void) +{ + Module m; + char *name; + LinkNode node, next, mn, dn; + int del, used; + + while (nonempty(modules)) { + for (node = firstnode(modules); (next = node); node = next) { + incnode(next); + del = used = 0; + name = ((Module) getdata(node))->nam; + for (mn = firstnode(modules); !used && mn; incnode(mn)) { + m = (Module) getdata(mn); + if (m->deps && m->u.handle) + for (dn = firstnode(m->deps); dn; incnode(dn)) + if (!strcmp((char *) getdata(dn), name)) { + if (m->flags & MOD_UNLOAD) + del = 1; + else { + used = 1; + break; + } + } + } + if (!used) { + m = (Module) getdata(node); + if (del) + m->wrapper++; + unload_module(m, NULL, 1); + if (del) + m->wrapper--; + } + } + } +} + /**/ int bin_zmodload(char *nam, char **args, char *ops, int func) @@ -761,13 +929,9 @@ Module m; if (!*args) { - for (node = firstnode(bltinmodules); node; incnode(node)) { - nicezputs((char *) getdata(node), stdout); - putchar('\n'); - } for (node = firstnode(modules); node; incnode(node)) { m = (Module) getdata(node); - if (m->handle && !(m->flags & MOD_UNLOAD)) { + if (m->u.handle && !(m->flags & MOD_UNLOAD)) { nicezputs(m->nam, stdout); putchar('\n'); } @@ -778,13 +942,10 @@ for (; !ret && *args; args++) { f = 0; - for (node = firstnode(bltinmodules); - !f && node; incnode(node)) - f = !strcmp(*args, (char *) getdata(node)); for (node = firstnode(modules); !f && node; incnode(node)) { m = (Module) getdata(node); - if (m->handle && !(m->flags & MOD_UNLOAD)) + if (m->u.handle && !(m->flags & MOD_UNLOAD)) f = !strcmp(*args, m->nam); } ret = !f; @@ -825,7 +986,7 @@ m->deps = NULL; } } - if (!m->deps && !m->handle) { + if (!m->deps && !m->u.handle) { remnode(modules, node); zsfree(m->nam); zfree(m, sizeof(*m)); @@ -1111,9 +1272,13 @@ /**/ int -unload_module(Module m, LinkNode node) +unload_module(Module m, LinkNode node, int force) { - if (m->handle && !(m->flags & MOD_UNLOAD) && cleanup_module(m)) + if ((m->flags & MOD_INIT_S) && + !(m->flags & MOD_UNLOAD) && + ((m->flags & MOD_LINKED) ? + (m->u.linked && m->u.linked->cleanup(m)) : + (m->u.handle && cleanup_module(m)))) return 1; else { int del = (m->flags & MOD_UNLOAD); @@ -1123,9 +1288,19 @@ return 0; } m->flags &= ~MOD_UNLOAD; - if (m->handle) - finish_module(m); - m->handle = NULL; + if (m->flags & MOD_INIT_B) { + if (m->flags & MOD_LINKED) { + if (m->u.linked) { + m->u.linked->finish(m); + m->u.linked = NULL; + } + } else { + if (m->u.handle) { + finish_module(m); + m->u.handle = NULL; + } + } + } if (del && m->deps) { /* The module was unloaded delayed, unload all modules * * on which it depended. */ @@ -1145,7 +1320,9 @@ for (an = firstnode(modules); du && an; incnode(an)) { am = (Module) getdata(an); - if (am != m && am->handle && am->deps) { + if (am != m && am->deps && + ((am->flags & MOD_LINKED) ? + am->u.linked : am->u.handle)) { LinkNode sn; for (sn = firstnode(am->deps); du && sn; @@ -1156,11 +1333,11 @@ } } if (du) - unload_module(dm, NULL); + unload_module(dm, NULL, 0); } } } - if(!m->deps) { + if(!m->deps || force) { if (!node) { for (node = firstnode(modules); node; incnode(node)) if (m == (Module) getdata(node)) @@ -1193,7 +1370,7 @@ for (mn = firstnode(modules); mn; incnode(mn)) { m = (Module) getdata(mn); - if (m->deps && m->handle) + if (m->deps && m->u.handle) for (dn = firstnode(m->deps); dn; incnode(dn)) if (!strcmp((char *) getdata(dn), *args)) { if (m->flags & MOD_UNLOAD) @@ -1208,7 +1385,7 @@ m = (Module) getdata(node); if (del) m->wrapper++; - if (unload_module(m, node)) + if (unload_module(m, node, 0)) ret = 1; if (del) m->wrapper--; @@ -1223,7 +1400,7 @@ /* list modules */ for (node = firstnode(modules); node; incnode(node)) { m = (Module) getdata(node); - if (m->handle && !(m->flags & MOD_UNLOAD)) { + if (m->u.handle && !(m->flags & MOD_UNLOAD)) { if(ops['L']) { printf("zmodload "); if(m->nam[0] == '-') @@ -1245,46 +1422,6 @@ } } -/**/ -#else /* DYNAMIC */ - -/* This is the version for shells without dynamic linking. */ - -/**/ -int -bin_zmodload(char *nam, char **args, char *ops, int func) -{ - /* We understand only the -e option (and ignore -i). */ - - if (ops['e'] || *args) { - LinkNode node; - - if (!*args) { - for (node = firstnode(bltinmodules); node; incnode(node)) { - nicezputs((char *) getdata(node), stdout); - putchar('\n'); - } - } else { - for (; *args; args++) { - for (node = firstnode(bltinmodules); node; incnode(node)) - if (!strcmp(*args, (char *) getdata(node))) - break; - if (!node) { - if (!ops['e']) - zerrnam(nam, "cannot load module: `%s'", *args, 0); - return 1; - } - } - } - return 0; - } - /* Otherwise we return 1 -- different from the dynamic version. */ - return 1; -} - -/**/ -#endif /* DYNAMIC */ - /* The list of module-defined conditions. */ /**/ @@ -1299,9 +1436,7 @@ getconddef(int inf, char *name, int autol) { Conddef p; -#ifdef DYNAMIC int f = 1; -#endif do { for (p = condtab; p; p = p->next) { @@ -1309,7 +1444,6 @@ !strcmp(name, p->name)) break; } -#ifdef DYNAMIC if (autol && p && p->module) { /* This is a definition for an autoloaded condition, load the * * module if we haven't tried that already. */ @@ -1322,7 +1456,6 @@ return NULL; } } else -#endif break; } while (!p); return p; @@ -1341,11 +1474,9 @@ if (p) { if (!p->module || (p->flags & CONDF_ADDED)) return 1; -#ifdef DYNAMIC /* There is an autoload definition. */ deleteconddef(p); -#endif } c->next = condtab; condtab = c; @@ -1616,9 +1747,6 @@ return 1; } -/**/ -#ifdef DYNAMIC - /* This adds a definition for autoloading a module for a condition. */ /**/ @@ -1709,9 +1837,6 @@ pm->flags |= PM_AUTOLOAD; } -/**/ -#endif - /* List of math functions. */ /**/ @@ -1725,7 +1850,6 @@ for (p = mathfuncs; p; q = p, p = p->next) if (!strcmp(name, p->name)) { -#ifdef DYNAMIC if (autol && p->module) { char *n = dupstring(p->module); @@ -1741,7 +1865,6 @@ return getmathfunc(name, 0); } -#endif return p; } @@ -1790,8 +1913,6 @@ return hadf ? hads : 1; } -#ifdef DYNAMIC - /**/ int add_automathfunc(char *nam, char *module) @@ -1859,5 +1980,3 @@ } return hadf ? hads : 1; } - -#endif /* DYNAMIC */ diff -u -r oldsrc/params.c Src/params.c --- oldsrc/params.c Wed Nov 24 09:03:37 1999 +++ Src/params.c Wed Nov 24 14:47:36 1999 @@ -203,10 +203,8 @@ IPDEF8("PATH", &path, "path", PM_RESTRICTED), IPDEF8("PSVAR", &psvar, "psvar", 0), -#ifdef DYNAMIC /* MODULE_PATH is not imported for security reasons */ IPDEF8("MODULE_PATH", &module_path, "module_path", PM_DONTIMPORT|PM_RESTRICTED), -#endif #define IPDEF9F(A,B,C,D) {NULL,A,D|PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT,BR((void *)B),SFN(arrvarsetfn),GFN(arrvargetfn),stdunsetfn,0,NULL,C,NULL,0} #define IPDEF9(A,B,C) IPDEF9F(A,B,C,0) @@ -234,9 +232,7 @@ IPDEF9("psvar", &psvar, "PSVAR"), IPDEF9("watch", &watch, "WATCH"), -#ifdef DYNAMIC IPDEF9F("module_path", &module_path, "MODULE_PATH", PM_RESTRICTED), -#endif IPDEF9F("path", &path, "PATH", PM_RESTRICTED), {NULL, NULL} @@ -254,10 +250,6 @@ /**/ HashTable paramtab, realparamtab; -#ifndef DYNAMIC -#define getparamnode gethashnode2 -#endif /* DYNAMIC */ - /**/ HashTable newparamtable(int size, char const *name) @@ -281,8 +273,6 @@ } /**/ -#ifdef DYNAMIC -/**/ static HashNode getparamnode(HashTable ht, char *nam) { @@ -302,8 +292,6 @@ } return hn; } -/**/ -#endif /* DYNAMIC */ /* Copy a parameter hash table */ diff -u -r oldsrc/zsh.h Src/zsh.h --- oldsrc/zsh.h Wed Nov 24 09:03:39 1999 +++ Src/zsh.h Wed Nov 24 15:34:29 1999 @@ -300,6 +300,7 @@ typedef struct builtin *Builtin; typedef struct nameddir *Nameddir; typedef struct module *Module; +typedef struct linkedmod *Linkedmod; typedef struct patprog *Patprog; typedef struct process *Process; @@ -917,7 +918,10 @@ struct module { char *nam; int flags; - void *handle; + union { + void *handle; + Linkedmod linked; + } u; LinkList deps; int wrapper; }; @@ -925,6 +929,19 @@ #define MOD_BUSY (1<<0) #define MOD_UNLOAD (1<<1) #define MOD_SETUP (1<<2) +#define MOD_LINKED (1<<3) +#define MOD_INIT_S (1<<4) +#define MOD_INIT_B (1<<5) + +typedef int (*Module_func) _((Module)); + +struct linkedmod { + char *name; + Module_func setup; + Module_func boot; + Module_func cleanup; + Module_func finish; +}; /* C-function hooks */ diff -u olddoc/Zsh/builtins.yo Doc/Zsh/builtins.yo --- olddoc/Zsh/builtins.yo Wed Nov 24 09:04:30 1999 +++ Doc/Zsh/builtins.yo Wed Nov 24 15:57:47 1999 @@ -1390,20 +1390,20 @@ Equivalent to tt(-ab) and tt(-ub). ) item(tt(zmodload -e) [ var(string) ... ])( -The tt(-e) option without arguments lists all modules loaded or linked -into the shell. With arguments only the return status is set to zero -if all var(string)s given as arguments are names of modules loaded or -linked in and to one if at least on var(string) is not the name of a -module loaded or linked. This can be used to test for the availability +The tt(-e) option without arguments lists all loaded modules loaded. +With arguments only the return status is set to zero +if all var(string)s given as arguments are names of loaded modules +and to one if at least on var(string) is not the name of a +loaded module. This can be used to test for the availability of things implemented by modules. ) enditem() -In a shell without dynamic loading only the tt(-e) option is -supported and the tt(-i) option is ignored. In such a shell the return -status of tt(zmodload) without arguments or options is one whereas in -a shell with dynamic loading the return status without arguments or -options is always zero. This can be used to test if the shell supports -dynamic loading of modules or not. +Note that tt(zsh) makes no difference between modules that were linked +into the shell and modules that are loaded dynamically. In both cases +this builtin command has to be used to make available the builtins and +other things defined by modules (unless the module is autoloaded on +these definitions). This is even true for systems that don't support +dynamic loading of modules. ) enditem() --- Etc/zsh-development-guide.old Wed Nov 24 15:52:17 1999 +++ Etc/zsh-development-guide Wed Nov 24 15:52:45 1999 @@ -151,9 +151,7 @@ user tries to unload a module and should de-register the builtins etc. The last function, `finish_foo' is called when the module is actually unloaded and should finalize all the data initialized in the -`setup'-function. Since the last two functions are only executed when -the module is used as an dynamically loaded module you can surround -it with `#ifdef MODULE' and `#endif'. +`setup'-function. In short, the `cleanup'-function should undo what the `boot'-function did, and the `finish'-function should undo what the `setup'-function did. -- Sven Wischnowsky wischnow@informatik.hu-berlin.de