From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1523 invoked from network); 17 Dec 1998 11:28:05 -0000 Received: from math.gatech.edu (list@130.207.146.50) by ns1.primenet.com.au with SMTP; 17 Dec 1998 11:28:05 -0000 Received: (from list@localhost) by math.gatech.edu (8.9.1/8.9.1) id GAA00702; Thu, 17 Dec 1998 06:02:10 -0500 (EST) Resent-Date: Thu, 17 Dec 1998 06:02:10 -0500 (EST) Date: Thu, 17 Dec 1998 12:00:30 +0100 (MET) Message-Id: <199812171100.MAA09011@beta.informatik.hu-berlin.de> From: Sven Wischnowsky To: zsh-workers@math.gatech.edu Subject: PATCH: module cleanup Resent-Message-ID: <"yMfGn.0.vA.oIEUs"@math> Resent-From: zsh-workers@math.gatech.edu X-Mailing-List: archive/latest/4830 X-Loop: zsh-workers@math.gatech.edu Precedence: list Resent-Sender: zsh-workers-request@math.gatech.edu Hi Here is the promised cleanup patch. - The setup- and finish-function are now mandatory. - The setup-funtions are always called for linked-in modules. - That required to remove the uses of AIXDYNAMIC in the modules. - I also changed the order of the four function in the modules to the order in which they are invoked. - In the modules comp1, compctl, and zle setup and finish are used for all non-user-interface-isms. - I added a global variable `sfcontext' and some constants in zsh.h (SFC_*). This can be used to test in which context the shell function is called. Currently only the following are distinguished: SFC_DIRECT - called directly by the user SFC_SIGNAL - called as a signal handler SFC_HOOK - automatically called from the shell (like chpwd) SFC_WIDGET - called as a user-defined widget SFC_COMPLETE - called from the completion code - For this I added save/set/restore sequences in various places. - The documentation now describes the setup/boot/cleanup/finish things more correctly. I also added a bit about the mdd files, mainly taken from mkmakemd.sh. With all that the patch has become rather biggish... And I have a question: the cleanup/finish functions are currently *not* called for linked-in modules and for loaded builtins if the shell is exited without first unloading the modules. Now, if someone writes a module that really needs to cleanup things (e.g. it has some kind of write-cache without write-through) this will fail utterly. Shouldn't we ensure that these functions are always called? Or was there some reason not to do it? Bye Sven diff -cr os/Builtins/rlimits.c Src/Builtins/rlimits.c *** os/Builtins/rlimits.c Thu Dec 17 10:19:31 1998 --- Src/Builtins/rlimits.c Thu Dec 17 10:24:01 1998 *************** *** 576,581 **** --- 576,588 ---- /**/ int + setup_rlimits(Module m) + { + return 0; + } + + /**/ + int boot_rlimits(Module m) { return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); *************** *** 591,610 **** return 0; } - #ifdef AIXDYNAMIC - /**/ - int - setup_rlimits(Module m) - { - return 0; - } - /**/ int finish_rlimits(Module m) { return 0; } - #endif #endif --- 598,608 ---- diff -cr os/Builtins/sched.c Src/Builtins/sched.c *** os/Builtins/sched.c Thu Dec 17 10:19:31 1998 --- Src/Builtins/sched.c Thu Dec 17 10:24:16 1998 *************** *** 185,190 **** --- 185,197 ---- /**/ int + setup_sched(Module m) + { + return 0; + } + + /**/ + int boot_sched(Module m) { if(!addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab))) *************** *** 211,230 **** return 0; } - #ifdef AIXDYNAMIC - /**/ - int - setup_sched(Module m) - { - return 0; - } - /**/ int finish_sched(Module m) { return 0; } - #endif #endif --- 218,228 ---- diff -cr os/Modules/cap.c Src/Modules/cap.c *** os/Modules/cap.c Thu Dec 17 10:19:11 1998 --- Src/Modules/cap.c Thu Dec 17 10:21:35 1998 *************** *** 124,129 **** --- 124,136 ---- /**/ int + setup_cap(Module m) + { + return 0; + } + + /**/ + int boot_cap(Module m) { return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); *************** *** 139,158 **** return 0; } - #ifdef AIXDYNAMIC - /**/ - int - setup_cap(Module m) - { - return 0; - } - /**/ int finish_cap(Module m) { return 0; } - #endif #endif --- 146,156 ---- diff -cr os/Modules/clone.c Src/Modules/clone.c *** os/Modules/clone.c Thu Dec 17 10:19:11 1998 --- Src/Modules/clone.c Thu Dec 17 10:21:55 1998 *************** *** 98,103 **** --- 98,110 ---- /**/ int + setup_clone(Module m) + { + return 0; + } + + /**/ + int boot_clone(Module m) { return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); *************** *** 113,132 **** return 0; } - #ifdef AIXDYNAMIC - /**/ - int - setup_clone(Module m) - { - return 0; - } - /**/ int finish_clone(Module m) { return 0; } - #endif #endif --- 120,130 ---- diff -cr os/Modules/example.c Src/Modules/example.c *** os/Modules/example.c Thu Dec 17 10:19:11 1998 --- Src/Modules/example.c Thu Dec 17 10:22:14 1998 *************** *** 109,114 **** --- 109,123 ---- /**/ int + setup_example(Module m) + { + printf("The example module has now been set up.\n"); + fflush(stdout); + return 0; + } + + /**/ + int boot_example(Module m) { return !(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) | *************** *** 125,139 **** deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); deleteconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab)); deletewrapper(m, wrapper); - return 0; - } - - /**/ - int - setup_example(Module m) - { - printf("The example module has now been set up.\n"); - fflush(stdout); return 0; } --- 134,139 ---- diff -cr os/Modules/files.c Src/Modules/files.c *** os/Modules/files.c Thu Dec 17 10:19:12 1998 --- Src/Modules/files.c Thu Dec 17 10:22:38 1998 *************** *** 511,516 **** --- 511,523 ---- /**/ int + setup_files(Module m) + { + return 0; + } + + /**/ + int boot_files(Module m) { return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); *************** *** 526,545 **** return 0; } - #ifdef AIXDYNAMIC - /**/ - int - setup_files(Module m) - { - return 0; - } - /**/ int finish_files(Module m) { return 0; } - #endif #endif --- 533,543 ---- diff -cr os/Modules/stat.c Src/Modules/stat.c *** os/Modules/stat.c Thu Dec 17 10:19:12 1998 --- Src/Modules/stat.c Thu Dec 17 10:23:05 1998 *************** *** 571,576 **** --- 571,583 ---- /**/ int + setup_stat(Module m) + { + return 0; + } + + /**/ + int boot_stat(Module m) { return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); *************** *** 586,605 **** return 0; } - #ifdef AIXDYNAMIC - /**/ - int - setup_stat(Module m) - { - return 0; - } - /**/ int finish_stat(Module m) { return 0; } - #endif #endif --- 593,603 ---- diff -cr os/Modules/zftp.c Src/Modules/zftp.c *** os/Modules/zftp.c Thu Dec 17 10:19:12 1998 --- Src/Modules/zftp.c Thu Dec 17 11:02:50 1998 *************** *** 1354,1360 **** --- 1354,1364 ---- * We do this here in case we needed to wait for a RETR * command to tell us how many bytes are coming. */ + int osc = sfcontext; + + sfcontext = SFC_HOOK; doshfunc("zftp_progress", l, NULL, 0, 1); + sfcontext = osc; /* Now add in the bit of the file we've got/sent already */ sofar = last_sofar = startat; } *************** *** 1482,1489 **** --- 1486,1497 ---- break; if (!ret && sofar != last_sofar && progress && (l = getshfunc("zftp_progress")) != &dummy_list) { + int osc = sfcontext; + zfsetparam("ZFTP_COUNT", &sofar, ZFPM_READONLY|ZFPM_INTEGER); + sfcontext = SFC_HOOK; doshfunc("zftp_progress", l, NULL, 0, 1); + sfcontext = osc; last_sofar = sofar; } } *************** *** 2102,2110 **** * front end. By putting it here, and in close when ZFTP_PWD is unset, * we at least cover the bases. */ ! if ((l = getshfunc("zftp_chpwd")) != &dummy_list) ! doshfunc("zftp_chpwd", l, NULL, 0, 1); return 0; } --- 2110,2122 ---- * front end. By putting it here, and in close when ZFTP_PWD is unset, * we at least cover the bases. */ ! if ((l = getshfunc("zftp_chpwd")) != &dummy_list) { ! int osc = sfcontext; + sfcontext = SFC_HOOK; + doshfunc("zftp_chpwd", l, NULL, 0, 1); + sfcontext = osc; + } return 0; } *************** *** 2303,2311 **** --- 2315,2327 ---- zsfree(ln); if (progress && (l = getshfunc("zftp_progress")) != &dummy_list) { /* progress to finish: ZFTP_TRANSFER set to GF or PF */ + int osc = sfcontext; + zfsetparam("ZFTP_TRANSFER", ztrdup(recv ? "GF" : "PF"), ZFPM_READONLY); + sfcontext = SFC_HOOK; doshfunc("zftp_progress", l, NULL, 0, 1); + sfcontext = osc; } if (rest) { zsfree(rest); *************** *** 2428,2436 **** zfunsetparam(*aptr); /* Now ZFTP_PWD is unset. It's up to zftp_chpwd to notice. */ ! if ((l = getshfunc("zftp_chpwd")) != &dummy_list) ! doshfunc("zftp_chpwd", l, NULL, 0, 1); /* tidy up status variables, because mess is bad */ zfclosing = zfdrrrring = 0; --- 2444,2456 ---- zfunsetparam(*aptr); /* Now ZFTP_PWD is unset. It's up to zftp_chpwd to notice. */ ! if ((l = getshfunc("zftp_chpwd")) != &dummy_list) { ! int osc = sfcontext; + sfcontext = SFC_HOOK; + doshfunc("zftp_chpwd", l, NULL, 0, 1); + sfcontext = osc; + } /* tidy up status variables, because mess is bad */ zfclosing = zfdrrrring = 0; *************** *** 2558,2563 **** --- 2578,2590 ---- /**/ int + setup_zftp(Module m) + { + return 0; + } + + /**/ + int boot_zftp(Module m) { int ret; *************** *** 2593,2612 **** return 0; } - #ifdef AIXDYNAMIC - /**/ - int - setup_zftp(Module m) - { - return 0; - } - /**/ int finish_zftp(Module m) { return 0; } - #endif #endif --- 2620,2630 ---- diff -cr os/Zle/comp1.c Src/Zle/comp1.c *** os/Zle/comp1.c Thu Dec 17 10:19:44 1998 --- Src/Zle/comp1.c Thu Dec 17 10:26:08 1998 *************** *** 430,436 **** /**/ int ! boot_comp1(Module m) { compctlreadptr = compctlread; clwords = (char **) zcalloc((clwsize = 16) * sizeof(char *)); --- 430,436 ---- /**/ int ! setup_comp1(Module m) { compctlreadptr = compctlread; clwords = (char **) zcalloc((clwsize = 16) * sizeof(char *)); *************** *** 446,467 **** return 0; } - #ifdef MODULE - /**/ int ! cleanup_comp1(Module m) { - deletehashtable(compctltab); - zfree(clwords, clwsize * sizeof(char *)); - compctlreadptr = fallback_compctlread; return 0; } ! #ifdef AIXDYNAMIC /**/ int ! setup_comp1(Module m) { return 0; } --- 446,463 ---- return 0; } /**/ int ! boot_comp1(Module m) { return 0; } ! #ifdef MODULE ! /**/ int ! cleanup_comp1(Module m) { return 0; } *************** *** 470,477 **** int finish_comp1(Module m) { return 0; } - #endif #endif /* MODULE */ --- 466,475 ---- int finish_comp1(Module m) { + deletehashtable(compctltab); + zfree(clwords, clwsize * sizeof(char *)); + compctlreadptr = fallback_compctlread; return 0; } #endif /* MODULE */ diff -cr os/Zle/compctl.c Src/Zle/compctl.c *** os/Zle/compctl.c Thu Dec 17 10:19:44 1998 --- Src/Zle/compctl.c Thu Dec 17 10:27:06 1998 *************** *** 1638,1671 **** /**/ int ! boot_compctl(Module m) { - if(!addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab))) - return 1; compctltab->printnode = printcompctlp; printcompctlptr = printcompctl; compctl_widgetptr = compctl_widget; return 0; } - #ifdef MODULE - /**/ int ! cleanup_compctl(Module m) { ! compctltab->printnode = NULL; ! deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); ! printcompctlptr = NULL; ! compctl_widgetptr = NULL; return 0; } ! #ifdef AIXDYNAMIC /**/ int ! setup_compctl(Module m) { return 0; } --- 1638,1667 ---- /**/ int ! setup_compctl(Module m) { compctltab->printnode = printcompctlp; printcompctlptr = printcompctl; compctl_widgetptr = compctl_widget; return 0; } /**/ int ! boot_compctl(Module m) { ! if(!addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab))) ! return 1; return 0; } ! #ifdef MODULE ! /**/ int ! cleanup_compctl(Module m) { + deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); return 0; } *************** *** 1673,1680 **** int finish_compctl(Module m) { return 0; } - #endif #endif --- 1669,1678 ---- int finish_compctl(Module m) { + compctltab->printnode = NULL; + printcompctlptr = NULL; + compctl_widgetptr = NULL; return 0; } #endif diff -cr os/Zle/deltochar.c Src/Zle/deltochar.c *** os/Zle/deltochar.c Thu Dec 17 10:19:44 1998 --- Src/Zle/deltochar.c Thu Dec 17 10:27:51 1998 *************** *** 73,78 **** --- 73,85 ---- /**/ int + setup_deltochar(Module m) + { + return 0; + } + + /**/ + int boot_deltochar(Module m) { w_deletetochar = addzlefunction("delete-to-char", deltochar, *************** *** 94,113 **** return 0; } - #ifdef AIXDYNAMIC - /**/ - int - setup_deltochar(Module m) - { - return 0; - } - /**/ int finish_deltochar(Module m) { return 0; } - #endif #endif --- 101,111 ---- diff -cr os/Zle/zle_main.c Src/Zle/zle_main.c *** os/Zle/zle_main.c Thu Dec 17 10:19:45 1998 --- Src/Zle/zle_main.c Thu Dec 17 10:47:06 1998 *************** *** 603,613 **** zsfree(msg); feep(); } else { ! startparamscope(); ! makezleparams(); ! doshfunc(w->u.fnnam, l, NULL, 0, 1); ! endparamscope(); ! lastcmd = 0; } } } --- 603,617 ---- zsfree(msg); feep(); } else { ! int osc = sfcontext; ! ! startparamscope(); ! makezleparams(); ! sfcontext = SFC_WIDGET; ! doshfunc(w->u.fnnam, l, NULL, 0, 1); ! sfcontext = osc; ! endparamscope(); ! lastcmd = 0; } } } *************** *** 856,862 **** /**/ int ! boot_zle(Module m) { /* Set up editor entry points */ trashzleptr = trashzle; --- 860,866 ---- /**/ int ! setup_zle(Module m) { /* Set up editor entry points */ trashzleptr = trashzle; *************** *** 875,880 **** --- 879,891 ---- /* initialise the keymap system */ init_keymaps(); + return 0; + } + + /**/ + int + boot_zle(Module m) + { addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); return 0; } *************** *** 885,899 **** int cleanup_zle(Module m) { - int i; - if(zleactive) { zerrnam(m->nam, "can't unload the zle module while zle is active", NULL, 0); return 1; } - deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); cleanup_keymaps(); deletehashtable(thingytab); --- 896,916 ---- int cleanup_zle(Module m) { if(zleactive) { zerrnam(m->nam, "can't unload the zle module while zle is active", NULL, 0); return 1; } deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); + return 0; + } + + /**/ + int + finish_zle(Module m) + { + int i; + cleanup_keymaps(); deletehashtable(thingytab); *************** *** 916,936 **** return 0; } - - #ifdef AIXDYNAMIC - /**/ - int - setup_zle(Module m) - { - return 0; - } - - /**/ - int - finish_zle(Module m) - { - return 0; - } - #endif #endif /* MODULE */ --- 933,937 ---- diff -cr os/Zle/zle_tricky.c Src/Zle/zle_tricky.c *** os/Zle/zle_tricky.c Thu Dec 17 10:19:46 1998 --- Src/Zle/zle_tricky.c Thu Dec 17 10:48:31 1998 *************** *** 4090,4095 **** --- 4090,4096 ---- if ((list = getshfunc(cc->func)) != &dummy_list) { /* We have it, so build a argument list. */ LinkList args = newlinklist(); + int osc = sfcontext; addlinknode(args, cc->func); *************** *** 4107,4114 **** --- 4108,4117 ---- /* This flag allows us to use read -l and -c. */ incompctlfunc = 1; + sfcontext = SFC_COMPLETE; /* Call the function. */ doshfunc(cc->func, list, args, 0, 1); + sfcontext = osc; incompctlfunc = 0; /* And get the result from the reply parameter. */ if ((r = get_user_var("reply"))) *************** *** 4254,4259 **** --- 4257,4263 ---- LinkList args = newlinklist(); LinkNode ln; Cmatch m; + int osc = sfcontext; addlinknode(args, cc->ylist); for (ln = firstnode(matches); ln; ln = nextnode(ln)) { *************** *** 4271,4277 **** --- 4275,4283 ---- /* No harm in allowing read -l and -c here, too */ incompctlfunc = 1; + sfcontext = SFC_COMPLETE; doshfunc(cc->ylist, list, args, 0, 1); + sfcontext = osc; incompctlfunc = 0; uv = "reply"; } diff -cr os/builtin.c Src/builtin.c *** os/builtin.c Thu Dec 17 09:00:07 1998 --- Src/builtin.c Thu Dec 17 10:50:29 1998 *************** *** 992,1000 **** --- 992,1004 ---- /* execute the chpwd function */ if ((l = getshfunc("chpwd")) != &dummy_list) { + int osc = sfcontext; + fflush(stdout); fflush(stderr); + sfcontext = SFC_HOOK; doshfunc("chpwd", l, NULL, 0, 1); + sfcontext = osc; } dirstacksize = getiparam("DIRSTACKSIZE"); diff -cr os/exec.c Src/exec.c *** os/exec.c Thu Dec 17 09:00:07 1998 --- Src/exec.c Thu Dec 17 10:44:36 1998 *************** *** 113,119 **** /**/ int cmdoutval; ! /* Stack to save some variables before executing a signal handler function */ /**/ --- 113,124 ---- /**/ int cmdoutval; ! ! /* The context in which a shell function is called, see SFC_* in zsh.h. */ ! ! /**/ ! int sfcontext; ! /* Stack to save some variables before executing a signal handler function */ /**/ diff -cr os/init.c Src/init.c *** os/init.c Thu Dec 17 09:00:07 1998 --- Src/init.c Thu Dec 17 10:49:53 1998 *************** *** 111,123 **** --- 111,127 ---- if (toplevel && (prelist = getshfunc("preexec")) != &dummy_list) { Histent he = gethistent(curhist); LinkList args; + int osc = sfcontext; + PERMALLOC { args = newlinklist(); addlinknode(args, "preexec"); if (he && he->text) addlinknode(args, he->text); } LASTALLOC; + sfcontext = SFC_HOOK; doshfunc("preexec", prelist, args, 0, 1); + sfcontext = osc; freelinklist(args, (FreeFunc) NULL); errflag = 0; } *************** *** 613,618 **** --- 617,623 ---- breaks = loops = 0; lastmailcheck = time(NULL); locallevel = sourcelevel = 0; + sfcontext = SFC_DIRECT; trapreturn = 0; noerrexit = -1; nohistsave = 1; diff -cr os/mkbltnmlst.sh Src/mkbltnmlst.sh *** os/mkbltnmlst.sh Thu Dec 17 10:20:12 1998 --- Src/mkbltnmlst.sh Thu Dec 17 10:20:41 1998 *************** *** 45,51 **** echo "/* linked-in module \`$bin_mod' */" eval "loc=\$loc_$bin_mod" unset moddeps - hassetup=0 . $srcdir/../$loc/${bin_mod}.mdd for dep in $moddeps; do case $done_mods in --- 45,50 ---- *************** *** 56,65 **** exit 1 ;; esac done ! if [ $hassetup != 0 ]; then ! echo " mod.nam = \"$bin_mod\"; setup_$bin_mod(&mod); boot_$bin_mod(&mod);" ! else ! echo " mod.nam = \"$bin_mod\"; boot_$bin_mod(&mod);" ! fi done_mods="$done_mods$bin_mod " done --- 55,60 ---- exit 1 ;; esac done ! echo " mod.nam = \"$bin_mod\"; setup_$bin_mod(&mod); boot_$bin_mod(&mod);" done_mods="$done_mods$bin_mod " done diff -cr os/module.c Src/module.c *** os/module.c Thu Dec 17 09:00:08 1998 --- Src/module.c Thu Dec 17 11:06:05 1998 *************** *** 36,41 **** --- 36,48 ---- /**/ int + setup_zsh(Module m) + { + return 0; + } + + /**/ + int boot_zsh(Module m) { return 0; *************** *** 389,398 **** #ifdef AIXDYNAMIC /**/ ! static void setup_module(Module m) { ! ((int (*)_((int,Module))) m->handle)(0, m); } /**/ --- 396,405 ---- #ifdef AIXDYNAMIC /**/ ! static int setup_module(Module m) { ! return ((int (*)_((int,Module))) m->handle)(0, m); } /**/ *************** *** 410,419 **** } /**/ ! static void finish_module(Module m) { ! ((int (*)_((int,Module))) m->handle)(3, m); } #else --- 417,426 ---- } /**/ ! static int finish_module(Module m) { ! return ((int (*)_((int,Module))) m->handle)(3, m); } #else *************** *** 446,458 **** } /**/ ! static void setup_module(Module m) { Module_func fn = module_func(m, STR_SETUP, STR_SETUP_S); if (fn) ! fn(m); } /**/ --- 453,467 ---- } /**/ ! static int setup_module(Module m) { Module_func fn = module_func(m, STR_SETUP, STR_SETUP_S); if (fn) ! return fn(m); ! zwarnnam(m->nam, "no setup function", NULL, 0); ! return 1; } /**/ *************** *** 479,494 **** return 1; } /**/ ! static void finish_module(Module m) { Module_func fn = module_func(m, STR_FINISH, STR_FINISH_S); if (fn) ! fn(m); ! dlclose(m->handle); } #endif /* !AIXDYNAMIC */ --- 488,511 ---- return 1; } + /* Note that this function does more than just calling finish_foo(), * + * it really unloads the module. */ + /**/ ! static int finish_module(Module m) { Module_func fn = module_func(m, STR_FINISH, STR_FINISH_S); + int r; if (fn) ! r = fn(m); ! else { ! zwarnnam(m->nam, "no finish function", NULL, 0); ! r = 1; ! } dlclose(m->handle); + return r; } #endif /* !AIXDYNAMIC */ *************** *** 507,514 **** m = zcalloc(sizeof(*m)); m->nam = ztrdup(name); m->handle = handle; ! setup_module(m); ! if (init_module(m)) { finish_module(m); zsfree(m->nam); zfree(m, sizeof(*m)); --- 524,530 ---- m = zcalloc(sizeof(*m)); m->nam = ztrdup(name); m->handle = handle; ! if (setup_module(m) || init_module(m)) { finish_module(m); zsfree(m->nam); zfree(m, sizeof(*m)); *************** *** 539,545 **** if (!m->handle) { if (!(m->handle = do_load_module(name))) return NULL; ! setup_module(m); } if (init_module(m)) { finish_module(m->handle); --- 555,565 ---- if (!m->handle) { if (!(m->handle = do_load_module(name))) return NULL; ! if (setup_module(m)) { ! finish_module(m->handle); ! m->handle = NULL; ! return NULL; ! } } if (init_module(m)) { finish_module(m->handle); diff -cr os/signals.c Src/signals.c *** os/signals.c Thu Dec 17 09:00:09 1998 --- Src/signals.c Thu Dec 17 10:45:26 1998 *************** *** 703,708 **** --- 703,710 ---- execsave(); breaks = 0; if (*sigtr & ZSIG_FUNC) { + int osc = sfcontext; + PERMALLOC { args = newlinklist(); name = (char *) zalloc(5 + strlen(sigs[sig])); *************** *** 712,718 **** --- 714,722 ---- addlinknode(args, num); } LASTALLOC; trapreturn = -1; + sfcontext = SFC_SIGNAL; doshfunc(name, sigfn, args, 0, 1); + sfcontext = osc; freelinklist(args, (FreeFunc) NULL); zsfree(name); } else HEAPALLOC { diff -cr os/utils.c Src/utils.c *** os/utils.c Thu Dec 17 09:00:09 1998 --- Src/utils.c Thu Dec 17 10:51:26 1998 *************** *** 630,637 **** /* If a shell function named "precmd" exists, * * then execute it. */ ! if ((list = getshfunc("precmd")) != &dummy_list) doshfunc("precmd", list, NULL, 0, 1); if (errflag) return; --- 630,642 ---- /* If a shell function named "precmd" exists, * * then execute it. */ ! if ((list = getshfunc("precmd")) != &dummy_list) { ! int osc = sfcontext; ! ! sfcontext = SFC_HOOK; doshfunc("precmd", list, NULL, 0, 1); + sfcontext = osc; + } if (errflag) return; *************** *** 640,646 **** --- 645,655 ---- * executed "periodic", then execute it now. */ if (period && (time(NULL) > lastperiodic + period) && (list = getshfunc("periodic")) != &dummy_list) { + int osc = sfcontext; + + sfcontext = SFC_HOOK; doshfunc("periodic", list, NULL, 0, 1); + sfcontext = osc; lastperiodic = time(NULL); } if (errflag) diff -cr os/zsh.h Src/zsh.h *** os/zsh.h Thu Dec 17 09:00:10 1998 --- Src/zsh.h Thu Dec 17 10:46:18 1998 *************** *** 772,777 **** --- 772,785 ---- List funcdef; /* function definition */ }; + /* Shell function context types. */ + + #define SFC_DIRECT 0 /* called directly from the user */ + #define SFC_SIGNAL 1 /* signal handler */ + #define SFC_HOOK 2 /* one of the special functions */ + #define SFC_WIDGET 3 /* user defined widget */ + #define SFC_COMPLETE 4 /* called from completion code */ + /* node in list of function call wrappers */ typedef int (*WrapFunc) _((List, FuncWrap, char *)); *** Util/zsh-development-guide.old Thu Dec 17 10:54:30 1998 --- Util/zsh-development-guide Thu Dec 17 11:34:21 1998 *************** *** 115,129 **** Modules ------- ! Modules should define should define two functions which will ! automatically called by the zsh core. The first one, named `boot_foo' ! for a module name `foo', should register all builtins, conditional ! codes, and function wrappers. The second one, named `cleanup_foo' for ! module `foo' is called when the module is unloaded and should ! de-register the builtins etc. Since this second function is only ! executed when the module is used as an dynamically loaded module you ! should surround it bei `#ifdef MODULE' and `#endif'. ! Both of these functions should return zero if they succeded and non-zero otherwise. Builtins are described in a table, for example: --- 115,157 ---- Modules ------- ! Modules are described by a file named `foo.mdd' for a module ! `foo'. This file is actually a shell script that will sourced when zsh ! is build. To describe the module it can/should set the following shell ! variables: ! ! - moddeps modules on which this module depends (default none) ! - nozshdep non-empty indicates no dependence on the `zsh' pseudo-module ! - alwayslink if non-empty, always link the module into the executable ! - autobins builtins defined by the module, for autoloading ! - objects .o files making up this module (*must* be defined) ! - proto .pro files for this module (default generated from $objects) ! - headers extra headers for this module (default none) ! - hdrdeps extra headers on which the .mdh depends (default none) ! - otherincs extra headers that are included indirectly (default none) ! ! Be sure to put the values in quotes. For further enlightenment have a ! look at the `mkmakemod.sh' script in the Src directory of the ! distribution. ! ! Modules have to define four functions which will automatically called ! by the zsh core. The first one, named `setup_foo' for a module named ! `foo', should set up any data needed in the module, at least any data ! other modules may be interested in. The second one, named `boot_foo', ! should register all builtins, conditional codes, and function wrappers ! (i.e. anything that will be visible to the user) and will be called ! after the `setup'-function. ! The third one, named `cleanup_foo' for module `foo' is called when the ! 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'. ! In short, the `cleanup'-function should undo what the `boot'-function ! did, and the `finish'-function should undo what the `setup'-function ! did. ! All of these functions should return zero if they succeeded and non-zero otherwise. Builtins are described in a table, for example: *************** *** 335,372 **** return 1; } There is a problem when the user tries to unload a module that has ! defined wrapper from a shell function. In this case the module can't be unloaded immediately since the wrapper function is still on the call stack. The zsh code delays unloading modules until all wrappers from them have finished. To hide this from the user, the module's cleanup function is run immediatly so that all builtins, condition codes, and wrapper function defined by the module are de-registered. But if there is some module-global state that has to be ! finalised (e.g. some memory that has to be freed) and that is used by the wrapper functions finalizing this data in the cleanup function won't work. ! Therefore two more module-functions may be called from zsh. When a ! module is really loaded zsh first tries to run the function ! `setup_foo' (for module `foo'). After that the function `boot_foo' is ! run and this function is also run if a module is still in memory but ! the user issued a `zmodload -u' call for it (i.e. zsh detected that it ! can't immediately unload the module). Correspondingly, the cleanup ! function is run whenever the user calls `zmodload -u' for a module and ! the function `finish_foo' (for module `foo') only if the module is ! actually unloaded. So, if you have some state accessed by a wrapper ! function put the initialization for it in the setup-function and the ! finalization for it in the finish-function. The boot- and ! cleanup-function are then only used to register and de-register ! builtins, condition codes, and wrapper functions. This way it is ! guaranteed that the data needed by the wrapper function is still valid ! when wrappers are active and that the user-visible interface defined ! by the module disappears as soon as the user tries to unload a module. ! Modules other modules which are currently delayed unloaded depend upon ! are unloaded delayed, too. This means that whenever you write a module ! that exports some data or functions which might be interesting to ! other modules you make sure that they are initialized and finalized in ! the setup- und finish-functions, not in the boot- and cleanup-functions. Documentation ------------- --- 363,404 ---- return 1; } + Inside these wrapper functions the global variable `sfcontext' will be + set to a vlue indicating the circumstances under which the shell + function was called. It can have any of the following values: + + - SFC_DIRECT: the function was invoked directly by the user + - SFC_SIGNAL: the function was invoked as a signal handler + - SFC_HOOK: the function was automatically invoked as one of the + special functions known by the shell (like `chpwd') + - SFC_WIDGET: the function was called from the zsh line editor as a + user-defined widget + - SFC_COMPLETE: the function was called from the completion code + (e.g. with `compctl -K func') + + If a module invokes a shell function (e.g. as a hook function), the + value of this variable should only be changed temporarily and restored + to its previous value after the shell function has finished. + There is a problem when the user tries to unload a module that has ! defined wrappers from a shell function. In this case the module can't be unloaded immediately since the wrapper function is still on the call stack. The zsh code delays unloading modules until all wrappers from them have finished. To hide this from the user, the module's cleanup function is run immediatly so that all builtins, condition codes, and wrapper function defined by the module are de-registered. But if there is some module-global state that has to be ! finalized (e.g. some memory that has to be freed) and that is used by the wrapper functions finalizing this data in the cleanup function won't work. ! This is why ther are two functions each for the initialization and ! finalization of modules. The `boot'- and `cleanup'-functions are run ! whenever the user calls `zmodload' or `zmodload -u' and should only ! register or de-register the module's interface that is visible to the ! user. Anything else should be done in the `setup'- and ! `finish'-functions. Otherwise modules that other modules depend upon ! may destroy their state too early and wrapper functions in the latter ! modules may stop working since the state they use is already destroyed. Documentation ------------- -- Sven Wischnowsky wischnow@informatik.hu-berlin.de