diff options
Diffstat (limited to 'm4/module.c')
-rw-r--r-- | m4/module.c | 229 |
1 files changed, 11 insertions, 218 deletions
diff --git a/m4/module.c b/m4/module.c index ec2913ad..ebedcffe 100644 --- a/m4/module.c +++ b/m4/module.c @@ -63,25 +63,12 @@ * Each time a module is loaded, the module function prototyped as * "M4INIT_HANDLER (<module name>)" is called, if defined. Any value * stored in OBS by this function becomes the expansion of the macro - * which called it. Before M4 exits, all modules are unloaded and the - * function prototyped as "M4FINISH_HANDLER (<module name>)" is called, - * if defined. It is safe to load the same module several times: the - * init and finish functions will also be called multiple times in this - * case. - * - * To unload a module, use m4_module_unload(). which uses - * m4__symtab_remove_module_references() to remove the builtins defined by - * the unloaded module from the symbol table. If the module has been - * loaded several times with calls to m4_module_load, then the module will - * not be unloaded until the same number of calls to m4_module_unload() - * have been made (nor will the symbol table be purged). + * which called it. **/ #define MODULE_SELF_NAME "!myself!" static const char* module_dlerror (void); -static int module_remove (m4 *context, m4_module *module, - m4_obstack *obs); static void install_builtin_table (m4*, m4_module *); static void install_macro_table (m4*, m4_module *); @@ -196,55 +183,20 @@ m4_module_load (m4 *context, const char *name, m4_obstack *obs) { m4_module *module = m4__module_open (context, name, obs); - if (module && module->refcount == 1) - { - install_builtin_table (context, module); - install_macro_table (context, module); - } - - return module; -} - -/* Make the module MODULE resident. Return NULL on success, or a - pre-translated error string on failure. */ -const char * -m4_module_makeresident (m4_module *module) -{ - assert (module); - return lt_dlmakeresident (module->handle) ? module_dlerror () : NULL; -} - -/* Unload a module. */ -void -m4_module_unload (m4 *context, const char *name, m4_obstack *obs) -{ - m4_module * module = NULL; - int errors = 0; - - assert (context); - - if (name) - module = m4__module_find (name); - - if (!module) + if (module) { - const char *error_msg = _("module not loaded"); + const lt_dlinfo *info = lt_dlgetinfo (module->handle); - lt_dlseterror (lt_dladderror (error_msg)); - ++errors; + if (info->ref_count == 1) + { + install_builtin_table (context, module); + install_macro_table (context, module); + } } - else - errors = module_remove (context, module, obs); - if (errors) - { - m4_error (context, EXIT_FAILURE, 0, NULL, - _("cannot unload module `%s': %s"), - name ? name : MODULE_SELF_NAME, module_dlerror ()); - } + return module; } - static int m4__module_interface (lt_dlhandle handle, const char *id_string) @@ -258,7 +210,6 @@ m4__module_interface (lt_dlhandle handle, const char *id_string) /* A valid m4 module must provide at least one of these symbols. */ return !(lt_dlsym (handle, INIT_SYMBOL) - || lt_dlsym (handle, FINISH_SYMBOL) || lt_dlsym (handle, BUILTIN_SYMBOL) || lt_dlsym (handle, MACRO_SYMBOL)); } @@ -267,7 +218,7 @@ m4__module_interface (lt_dlhandle handle, const char *id_string) /* Return successive loaded modules that pass the interface test registered with the interface id. */ m4_module * -m4__module_next (m4_module *module) +m4_module_next (m4_module *module) { lt_dlhandle handle = module ? module->handle : NULL; assert (iface_id); @@ -482,7 +433,6 @@ m4__module_open (m4 *context, const char *name, m4_obstack *obs) /* Find and run any initializing function in the opened module, each time the module is opened. */ - module->refcount++; init_func = (m4_module_init_func *) lt_dlsym (handle, INIT_SYMBOL); if (init_func) { @@ -491,8 +441,7 @@ m4__module_open (m4 *context, const char *name, m4_obstack *obs) m4_debug_message (context, M4_DEBUG_TRACE_MODULE, _("module %s: init hook called"), name); } - else if (!lt_dlsym (handle, FINISH_SYMBOL) - && !lt_dlsym (handle, BUILTIN_SYMBOL) + else if (!lt_dlsym (handle, BUILTIN_SYMBOL) && !lt_dlsym (handle, MACRO_SYMBOL)) { m4_error (context, EXIT_FAILURE, 0, NULL, @@ -512,39 +461,6 @@ m4__module_open (m4 *context, const char *name, m4_obstack *obs) return module; } -void -m4__module_exit (m4 *context) -{ - m4_module * module = m4__module_next (NULL); - int errors = 0; - - while (module && !errors) - { - m4_module *pending = module; - - /* If we are about to unload the final reference, move on to the - next module before we unload the current one. */ - if (pending->refcount <= 1) - module = m4__module_next (module); - - errors = module_remove (context, pending, NULL); - } - - assert (iface_id); /* need to have called m4__module_init */ - lt_dlinterface_free (iface_id); - iface_id = NULL; - - if (!errors) - errors = lt_dlexit (); - - if (errors) - { - m4_error (context, EXIT_FAILURE, 0, NULL, - _("cannot unload all modules: %s"), module_dlerror ()); - } -} - - /* FIXME - libtool doesn't expose lt_dlerror strings for translation. */ static const char * @@ -557,126 +473,3 @@ module_dlerror (void) return dlerror; } - -/* Close one reference to the module MODULE, and output to OBS any - information from the finish hook of the module. If no references - to MODULE remain, also remove all symbols and other memory - associated with the module. */ -static int -module_remove (m4 *context, m4_module *module, m4_obstack *obs) -{ - const lt_dlinfo * info; - int errors = 0; - const char * name; - lt_dlhandle handle; - bool last_reference = false; - bool resident = false; - m4_module_finish_func * finish_func; - - assert (module && module->handle); - - /* Be careful when closing myself. */ - handle = module->handle; - name = m4_get_module_name (module); - name = xstrdup (name ? name : MODULE_SELF_NAME); - - info = lt_dlgetinfo (handle); - resident = info->is_resident; - - /* Only do the actual close when the number of calls to close this - module is equal to the number of times it was opened. */ -#ifdef DEBUG_MODULES - if (info->ref_count > 1) - { - xfprintf (stderr, "module %s: now has %d libtool references.", - name, info->ref_count - 1); - } -#endif /* DEBUG_MODULES */ - - if (module->refcount-- == 1) - { - /* Remove the table references only when ref_count is *exactly* - equal to 1. If module_close is called again on a - resident module after the references have already been - removed, we needn't try to remove them again! */ - m4__symtab_remove_module_references (M4SYMTAB, module); - - m4_debug_message (context, M4_DEBUG_TRACE_MODULE, - _("module %s: symbols unloaded"), name); - last_reference = true; - } - - finish_func = (m4_module_finish_func *) lt_dlsym (handle, FINISH_SYMBOL); - if (finish_func) - { - finish_func (context, module, obs); - - m4_debug_message (context, M4_DEBUG_TRACE_MODULE, - _("module %s: finish hook called"), name); - } - - if (last_reference && resident) - { - /* Special case when closing last reference to resident module - - we need to remove the association of the m4_module wrapper - with the dlhandle, because we are about to free the wrapper, - but the module will still show up in lt_dlhandle_iterate. - Still call lt_dlclose to reduce the ref count, but ignore the - failure about not closing a resident module. */ - void *old = lt_dlcaller_set_data (iface_id, handle, NULL); - if (!old) - m4_error (context, EXIT_FAILURE, 0, NULL, - _("unable to close module `%s': %s"), name, - module_dlerror()); - assert (old == module); - lt_dlclose (handle); - m4_debug_message (context, M4_DEBUG_TRACE_MODULE, - _("module %s: resident module not closed"), name); - } - else - { - errors = lt_dlclose (handle); - /* Ignore the error expected if the module was resident. */ - if (resident) - errors = 0; - if (!errors) - { - m4_debug_message (context, M4_DEBUG_TRACE_MODULE, - _("module %s: closed"), name); - } - } - - if (errors) - m4_error (context, EXIT_FAILURE, 0, NULL, - _("cannot close module `%s': %s"), name, module_dlerror ()); - if (last_reference) - { - size_t i; - for (i = 0; i < module->builtins_len; i++) - DELETE (module->builtins[i].builtin.name); - free (module->builtins); - free (module); - } - - DELETE (name); - - return errors; -} - - -/* Below here are the accessor functions behind fast macros. Declare - them last, so the rest of the file can use the macros. */ - -/* Return the current refcount, or times that module MODULE has been - opened. */ -#undef m4_module_refcount -int -m4_module_refcount (const m4_module *module) -{ - const lt_dlinfo *info; - assert (module); - info = lt_dlgetinfo (module->handle); - assert (info); - assert (module->refcount <= info->ref_count); - return module->refcount; -} |