summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary V. Vaughan <gary@gnu.org>2013-09-20 12:00:02 +0700
committerGary V. Vaughan <gary@gnu.org>2013-09-20 15:57:49 +0700
commitaeb92bcb25e253b55650961f341640f93ec3b54e (patch)
treeee8d364c67cc33c342aa8d181918709fe9fcb557
parent9114cb2e988dabdf4c8561f62eb448aa24117574 (diff)
downloadm4-aeb92bcb25e253b55650961f341640f93ec3b54e.tar.gz
modules: remove support for module unload and refcount.
Module management is horrifically more complex than it needs to be for the simple purpose of providing a means to implement new builtins using C. Fussing about reference counting or needing to maintain and test a facility to unload modules is an easy 600 lines to cut as a start at simplification. * src/main.c (main): Don't call m4__module_exit to unload all modules just prior to exiting the application. * m4/m4private.h (FINISH_SYMBOL, m4_module:refcount) (m4__module_exit, m4_module_refcount): Remove. (m4__module_next): Rename from this... * m4/m4module.h (m4_module_next): ...to this. Adjust all callers. (M4FINISH_HANDLER, m4_module_finish_func, m4_module_makeresident) (m4_module_refcount, m4_module_unload, m4_module_exit): Remove. * m4/m4module.c (m4__module_next): Rename from this... (m4_module_next): ...to this. (module_remove, m4_module_makeresident, m4_module_unload) (m4_module_exit, m4_module_refcount): Remove. * modules/load.c: Remove. (m4modules): Move from here... * modules/gnu.c (m4modules): ...to here. Update all callers. (M4FINISH_HANDLER(gnu)): Remove. * modules/m4.c (M4INIT_HANDLER(m4)): Remove. * modules/modtest.c (M4FINISH_HANDLER(modtest)): Remove. * modules/shadow.c (M4INIT_HANDLER(shadow)): Rewrite to work without refcount. * Makefile.am (pkglib_LTLIBRARIES): Remove modules/load.la. (modules_load_la_LDFLAGS, modules_load_la_LIBADD): Remove. * tests/modules.at: Remove references to load module, and tests of unload builtin. * tests/options.at: Remove obsolute finish hook and module unload trace output. * doc/m4.texi (Unload, Refcount): Remove. (M4modules): Change module reference from load to gnu. Signed-off-by: Gary V. Vaughan <gary@gnu.org>
-rw-r--r--Makefile.am4
-rw-r--r--doc/m4.texi82
-rw-r--r--m4/builtin.c8
-rw-r--r--m4/m4module.h17
-rw-r--r--m4/m4private.h10
-rw-r--r--m4/module.c229
-rw-r--r--modules/gnu.c42
-rw-r--r--modules/load.c126
-rw-r--r--modules/m4.c16
-rw-r--r--modules/modtest.c13
-rw-r--r--modules/shadow.c10
-rw-r--r--src/freeze.c4
-rw-r--r--src/main.c1
-rw-r--r--tests/modules.at247
-rw-r--r--tests/options.at6
15 files changed, 67 insertions, 748 deletions
diff --git a/Makefile.am b/Makefile.am
index 7920b9df..e9807a0f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -160,7 +160,6 @@ pkgmodinclude_HEADERS = modules/m4.h
pkglib_LTLIBRARIES = \
modules/gnu.la \
- modules/load.la \
modules/m4.la \
modules/traditional.la
@@ -169,9 +168,6 @@ modules_gnu_la_LDFLAGS = $(module_ldflags)
modules_gnu_la_LIBADD = $(module_libadd)
EXTRA_DIST += $(EXTRA_modules_gnu_la_SOURCES)
-modules_load_la_LDFLAGS = $(module_ldflags)
-modules_load_la_LIBADD = $(module_libadd)
-
EXTRA_modules_m4_la_SOURCES = modules/evalparse.c
modules_m4_la_LDFLAGS = $(module_ldflags)
modules_m4_la_LIBADD = $(module_libadd)
diff --git a/doc/m4.texi b/doc/m4.texi
index 7def990a..77c3a5fe 100644
--- a/doc/m4.texi
+++ b/doc/m4.texi
@@ -235,8 +235,6 @@ Diverting and undiverting output
Extending M4 with dynamic runtime modules
* M4modules:: Listing loaded modules
-* Unload:: Removing loaded modules
-* Refcount:: Tracking module references
* Standard Modules:: Standard bundled modules
Macros for text handling
@@ -6669,8 +6667,8 @@ extensions by configuring the distribution with @kbd{./configure
--with-modules=m4}. For a binary built with that option to understand
code that uses GNU extensions, you must then run @kbd{m4 gnu}.
It is also possible to build a @emph{fatter} binary with additional
-modules preloaded: adding, say, the @code{load} module usingr
- @kbd{./configure --with-modules="m4 gnu load"}.
+modules preloaded: adding, say, the @code{load} module using
+@kbd{./configure --with-modules="m4 gnu load"}.
GNU M4 now has a facility for defining additional builtins without
recompiling the sources. In actual fact, all of the builtins provided
@@ -6686,15 +6684,13 @@ two modes of startup.
@menu
* M4modules:: Listing loaded modules
-* Unload:: Removing loaded modules
-* Refcount:: Tracking module references
* Standard Modules:: Standard bundled modules
@end menu
@node M4modules
@section Listing loaded modules
-@deffn {Builtin (load)} m4modules
+@deffn {Builtin (gnu)} m4modules
Expands to a quoted ordered list of currently loaded modules,
with the most recently loaded module at the front of the list. Loading
a module multiple times will not affect the order of this list, the
@@ -6704,78 +6700,10 @@ position depends on when the module was @emph{first} loaded.
For example, if GNU @code{m4} is started with the
@option{load} module, @code{m4modules} will yield the following:
-@comment options: load -
@example
-$ @kbd{m4 load -}
-m4modules
-@result{}load,gnu,m4
-@end example
-
-@node Unload
-@section Removing loaded modules
-
-@deffn {Builtin (load)} unload (@var{module-name})
-Any loaded modules that can be listed by the @code{m4modules} macro can be
-removed by naming them as the @var{module-name} parameter of the
-@code{unload} macro. Unloading a module consists of removing all of the
-macros it provides from the internal table of visible macros, and
-running the module's finalization method (if any).
-
-The macro @code{unload} is recognized only with parameters.
-@end deffn
-
-@comment options: mpeval load -
-@example
-$ @kbd{m4 mpeval load -}
-m4modules
-@result{}load,mpeval,gnu,m4
-unload(`mpeval')
-@result{}
-m4modules
-@result{}load,gnu,m4
-@end example
-
-@node Refcount
-@section Tracking module references
-
-@deffn {Builtin (load)} refcount (@var{module-name})
-This macro expands to an integer representing the number of times
-@var{module-name} has been loaded but not yet unloaded. No warning is
-issued, even if @var{module-name} does not represent a valid module.
-
-The macro @code{refcount} is recognized only with parameters.
-@end deffn
-
-This example demonstrates tracking the reference count of the gnu
-module.
-
-@comment options: load -
-@example
-$ @kbd{m4 load -}
-m4modules
-@result{}load,gnu,m4
-refcount(`gnu')
-@result{}1
-m4modules
-@result{}load,gnu,m4
-include(`gnu')
-@result{}
-refcount(`gnu')
-@result{}2
-unload(`gnu')
-@result{}
-m4modules
-@result{}load,gnu,m4
-refcount(`gnu')
-@result{}1
-unload(`gnu')
-@result{}
+$ @kbd{m4}
m4modules
-@result{}load,m4
-refcount(`gnu')
-@result{}0
-refcount(`NoSuchModule')
-@result{}0
+@result{}gnu,m4
@end example
@node Standard Modules
diff --git a/m4/builtin.c b/m4/builtin.c
index 51f636e4..c5107534 100644
--- a/m4/builtin.c
+++ b/m4/builtin.c
@@ -41,7 +41,7 @@ compare_builtin_name_CB (const void *name, const void *b)
m4_symbol_value * M4_GNUC_PURE
m4_builtin_find_by_name (m4_module *module, const char *name)
{
- m4_module *cur = module ? module : m4__module_next (NULL);
+ m4_module *cur = module ? module : m4_module_next (NULL);
m4__builtin *bp;
do
@@ -55,7 +55,7 @@ m4_builtin_find_by_name (m4_module *module, const char *name)
return token;
}
}
- while (!module && (cur = m4__module_next (cur)));
+ while (!module && (cur = m4_module_next (cur)));
return NULL;
}
@@ -67,7 +67,7 @@ m4_builtin_find_by_name (m4_module *module, const char *name)
m4_symbol_value * M4_GNUC_PURE
m4_builtin_find_by_func (m4_module *module, m4_builtin_func *func)
{
- m4_module *cur = module ? module : m4__module_next (NULL);
+ m4_module *cur = module ? module : m4_module_next (NULL);
size_t i;
do
@@ -81,7 +81,7 @@ m4_builtin_find_by_func (m4_module *module, m4_builtin_func *func)
return token;
}
}
- while (!module && (cur = m4__module_next (cur)));
+ while (!module && (cur = m4_module_next (cur)));
return 0;
}
diff --git a/m4/m4module.h b/m4/m4module.h
index 8c249f04..a6bd5139 100644
--- a/m4/m4module.h
+++ b/m4/m4module.h
@@ -122,17 +122,6 @@ struct m4_string_pair
void name ## _LTX_m4_init_module \
(m4 *context, m4_module *module, m4_obstack *obs)
-/* Declare a prototype, then begin the implementation of the function
- "<NAME>_LTX_m4_init_module", which will automatically be registered
- as the cleanup function for module NAME. Note that NAME is
- intentionally used literally, rather than subjected to macro
- expansion. */
-#define M4FINISH_HANDLER(name) \
- void name ## _LTX_m4_finish_module \
- (m4 *, m4_module *, m4_obstack *); \
- void name ## _LTX_m4_finish_module \
- (m4 *context, m4_module *module, m4_obstack *obs)
-
/* Declare a variable S of type "<S>_func" to be a pointer to the
function named S imported from the module M, or NULL if the import
fails. Note that M and S are intentionally used literally rather
@@ -243,17 +232,13 @@ m4_context_opt_bit_table
/* --- MODULE MANAGEMENT --- */
typedef void m4_module_init_func (m4 *, m4_module *, m4_obstack *);
-typedef void m4_module_finish_func (m4 *, m4_module *, m4_obstack *);
extern m4_module * m4_module_load (m4 *, const char *, m4_obstack *);
-extern const char * m4_module_makeresident (m4_module *);
-extern int m4_module_refcount (const m4_module *);
-extern void m4_module_unload (m4 *, const char *, m4_obstack *);
extern void * m4_module_import (m4 *, const char *, const char *,
m4_obstack *);
extern const char * m4_get_module_name (const m4_module *);
-extern void m4__module_exit (m4 *);
+extern m4_module * m4_module_next (m4_module *);
diff --git a/m4/m4private.h b/m4/m4private.h
index bffc57b5..29f2bfe9 100644
--- a/m4/m4private.h
+++ b/m4/m4private.h
@@ -176,13 +176,11 @@ extern void m4__builtin_print (m4_obstack *, const m4__builtin *, bool,
#define BUILTIN_SYMBOL "m4_builtin_table"
#define MACRO_SYMBOL "m4_macro_table"
#define INIT_SYMBOL "m4_init_module"
-#define FINISH_SYMBOL "m4_finish_module"
/* Representation of a loaded m4 module. */
struct m4_module
{
lt_dlhandle handle; /* All ltdl module information. */
- int refcount; /* Count of loads not matched by unload. */
m4__builtin *builtins; /* Sorted array of builtins. */
size_t builtins_len; /* Number of builtins. */
};
@@ -190,16 +188,8 @@ struct m4_module
extern void m4__module_init (m4 *context);
extern m4_module * m4__module_open (m4 *context, const char *name,
m4_obstack *obs);
-extern void m4__module_exit (m4 *context);
-extern m4_module * m4__module_next (m4_module *);
extern m4_module * m4__module_find (const char *name);
-/* Fast macro versions of symbol table accessor functions, that also
- have an identically named function exported in m4module.h. */
-#ifdef NDEBUG
-# define m4_module_refcount(M) ((M)->refcount)
-#endif
-
/* --- SYMBOL TABLE MANAGEMENT --- */
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;
-}
diff --git a/modules/gnu.c b/modules/gnu.c
index c69862e8..ae3024f7 100644
--- a/modules/gnu.c
+++ b/modules/gnu.c
@@ -58,6 +58,7 @@
BUILTIN (patsubst, false, true, true, 2, 4 ) \
BUILTIN (regexp, false, true, true, 2, 4 ) \
BUILTIN (renamesyms, false, true, false, 2, 3 ) \
+ BUILTIN (m4modules, false, false, false, 0, 0 ) \
BUILTIN (m4symbols, true, false, false, 0, -1 ) \
BUILTIN (syncoutput, false, true, false, 1, 1 ) \
@@ -352,25 +353,6 @@ regexp_substitute (m4 *context, m4_obstack *obs, const m4_call_info *caller,
}
-/* Reclaim memory used by this module. */
-M4FINISH_HANDLER(gnu)
-{
- int i;
- for (i = 0; i < REGEX_CACHE_SIZE; i++)
- if (regex_cache[i].str)
- {
- free (regex_cache[i].str);
- regfree (regex_cache[i].pat);
- free (regex_cache[i].pat);
- free (regex_cache[i].regs.start);
- free (regex_cache[i].regs.end);
- }
- /* If this module was preloaded, then we need to explicitly reset
- the memory in case it gets reloaded. */
- memset (&regex_cache, 0, sizeof regex_cache);
-}
-
-
/**
* __file__
@@ -1016,6 +998,28 @@ M4BUILTIN_HANDLER (renamesyms)
}
+/**
+ * m4modules()
+ **/
+M4BUILTIN_HANDLER (m4modules)
+{
+ /* The expansion of this builtin is a comma separated list of
+ loaded modules. */
+ m4_module *module = m4_module_next (NULL);
+
+ if (module)
+ do
+ {
+ m4_shipout_string (context, obs, m4_get_module_name (module), SIZE_MAX,
+ true);
+
+ if ((module = m4_module_next (module)))
+ obstack_1grow (obs, ',');
+ }
+ while (module);
+}
+
+
/* Implementation of "m4symbols". It builds up a table of pointers to
symbols, sorts it and ships out the symbol names. */
diff --git a/modules/load.c b/modules/load.c
deleted file mode 100644
index 0b0eb1be..00000000
--- a/modules/load.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/* GNU m4 -- A simple macro processor
- Copyright (C) 2000, 2005-2008, 2010, 2013 Free Software Foundation,
- Inc.
-
- This file is part of GNU M4.
-
- GNU M4 is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- GNU M4 is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-/* This module needs private symbols, and may not compile correctly if
- m4private.h isn't included. */
-#include "m4private.h"
-
-
-/* Rename exported symbols for dlpreload()ing. */
-#define m4_builtin_table load_LTX_m4_builtin_table
-#define m4_macro_table load_LTX_m4_macro_table
-
-
-/* Maintain each of the builtins implemented in this modules along
- with their details in a single table for easy maintenance.
-
- function macros blind side minargs maxargs */
-#define builtin_functions \
- BUILTIN (m4modules, false, false, false, 0, 0 ) \
- BUILTIN (refcount, false, true, false, 1, 1 ) \
- BUILTIN (unload, false, true, false, 1, 1 ) \
-
-
-/* Generate prototypes for each builtin handler function. */
-#define BUILTIN(handler, macros, blind, side, min, max) M4BUILTIN (handler)
- builtin_functions
-#undef BUILTIN
-
-
-/* Generate a table for mapping m4 symbol names to handler functions. */
-const m4_builtin m4_builtin_table[] =
-{
-#define BUILTIN(handler, macros, blind, side, min, max) \
- M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max)
-
- builtin_functions
-#undef BUILTIN
-
- { NULL, NULL, 0, 0, 0 },
-};
-
-
-/* A table for mapping m4 symbol names to simple expansion text. */
-const m4_macro m4_macro_table[] =
-{
- /* name text min max */
- { "__load__", "", 0, 0 },
- { NULL, NULL, 0, 0 },
-};
-
-
-/* This module cannot be safely unloaded from memory, incase the unload
- is triggered by the unload builtin, and the module is removed while
- unload is in progress. */
-M4INIT_HANDLER (load)
-{
- const char *err = m4_module_makeresident (module);
- if (err)
- m4_error (context, 0, 0, NULL, _("cannot make module `%s' resident: %s"),
- m4_get_module_name (module), err);
-}
-
-
-
-/* Loading an external module at runtime.
- The following functions provide the implementation for each
- of the m4 builtins declared in `m4_builtin_table[]' above. */
-
-/**
- * m4modules()
- **/
-M4BUILTIN_HANDLER (m4modules)
-{
- /* The expansion of this builtin is a comma separated list of
- loaded modules. */
- m4_module *module = m4__module_next (NULL);
-
- if (module)
- do
- {
- m4_shipout_string (context, obs, m4_get_module_name (module), SIZE_MAX,
- true);
-
- if ((module = m4__module_next (module)))
- obstack_1grow (obs, ',');
- }
- while (module);
-}
-
-/**
- * refcount(module)
- **/
-M4BUILTIN_HANDLER (refcount)
-{
- m4_module *module = m4__module_find (M4ARG (1));
- m4_shipout_int (obs, module ? m4_module_refcount (module) : 0);
-}
-
-/**
- * unload(MODULE-NAME)
- **/
-M4BUILTIN_HANDLER (unload)
-{
- /* Remove all builtins and macros installed by the named module,
- and then unload the module from memory entirely. */
- m4_module_unload (context, M4ARG(1), obs);
-}
diff --git a/modules/m4.c b/modules/m4.c
index 64abdae0..f9449fe0 100644
--- a/modules/m4.c
+++ b/modules/m4.c
@@ -128,19 +128,6 @@ const m4_builtin m4_builtin_table[] =
-/* This module cannot be safely unloaded from memory, incase the unload
- is triggered by m4exit, and the module is removed while m4exit is in
- progress. */
-M4INIT_HANDLER (m4)
-{
- const char *err = m4_module_makeresident (module);
- if (err)
- m4_error (context, 0, 0, NULL, _("cannot make module `%s' resident: %s"),
- m4_get_module_name (module), err);
-}
-
-
-
/* The rest of this file is code for builtins and expansion of user
defined macros. All the functions for builtins have a prototype as:
@@ -840,9 +827,6 @@ M4BUILTIN_HANDLER (m4exit)
if (exit_code != EXIT_SUCCESS)
m4_set_exit_failure (exit_code);
- /* Ensure any module exit callbacks are executed. */
- m4__module_exit (context);
-
/* Change debug stream back to stderr, to force flushing debug
stream and detect any errors. */
m4_debug_set_output (context, me, NULL);
diff --git a/modules/modtest.c b/modules/modtest.c
index 5febf086..385049b4 100644
--- a/modules/modtest.c
+++ b/modules/modtest.c
@@ -80,19 +80,6 @@ M4INIT_HANDLER (modtest)
/**
- * modtest()
- **/
-M4FINISH_HANDLER (modtest)
-{
- const char *s = "Test module unloaded.\n";
-
- /* Don't depend on OBS so that the traces are the same when used
- directly, or via a frozen file. */
- fputs (s, stderr);
-}
-
-
-/**
* test()
**/
M4BUILTIN_HANDLER (test)
diff --git a/modules/shadow.c b/modules/shadow.c
index 16260f12..529425c4 100644
--- a/modules/shadow.c
+++ b/modules/shadow.c
@@ -64,12 +64,16 @@ const m4_macro m4_macro_table[] =
M4INIT_HANDLER (shadow)
{
+ static bool loaded = false;
+
const char *s = "Shadow module loaded.";
- int refcount = m4_module_refcount (module);
/* Only display the message on first load. */
- if (obs && refcount == 1)
- obstack_grow (obs, s, strlen (s));
+ if (obs && !loaded)
+ {
+ loaded = true;
+ obstack_grow (obs, s, strlen (s));
+ }
}
diff --git a/src/freeze.c b/src/freeze.c
index 9f36e8cc..5ac913d8 100644
--- a/src/freeze.c
+++ b/src/freeze.c
@@ -156,7 +156,7 @@ produce_module_dump (FILE *file, m4_module *module)
const char *name = m4_get_module_name (module);
size_t len = strlen (name);
- module = m4__module_next (module);
+ module = m4_module_next (module);
if (module)
produce_module_dump (file, module);
@@ -322,7 +322,7 @@ produce_frozen_state (m4 *context, const char *name)
produce_debugmode_state (file, m4_get_debug_level_opt (context));
/* Dump all loaded modules. */
- produce_module_dump (file, m4__module_next (NULL));
+ produce_module_dump (file, m4_module_next (NULL));
/* Dump all symbols. */
produce_symbol_dump (context, file, M4SYMTAB);
diff --git a/src/main.c b/src/main.c
index 1e3e706f..53305451 100644
--- a/src/main.c
+++ b/src/main.c
@@ -744,7 +744,6 @@ main (int argc, char *const *argv, char *const *envp)
Strictly, we don't need to do this, but it makes leak detection
a whole lot easier! */
- m4__module_exit (context);
m4_output_exit ();
m4_input_exit ();
diff --git a/tests/modules.at b/tests/modules.at
index 623f531d..dddba9ee 100644
--- a/tests/modules.at
+++ b/tests/modules.at
@@ -51,14 +51,14 @@ test3
# First generate the `expout' ouput by running over the sources before
# freezing.
-AT_CHECK_M4([-I "$abs_builddir" load frozen.m4 unfrozen.m4],
+AT_CHECK_M4([-I "$abs_builddir" frozen.m4 unfrozen.m4],
[0], [stdout], [stderr])
mv stdout expout
mv stderr experr
# Now freeze the first source file.
-AT_CHECK_M4([-I "$abs_builddir" load -F frozen.m4f frozen.m4],
+AT_CHECK_M4([-I "$abs_builddir" -F frozen.m4f frozen.m4],
[0], [], [ignore])
# Now rerun the original sequence, but using the frozen file.
@@ -68,33 +68,6 @@ AT_CHECK_M4([-I "$abs_builddir" -R frozen.m4f unfrozen.m4],
AT_CLEANUP([frozen.m4f])
-## ------------------ ##
-## module test macros ##
-## ------------------ ##
-
-AT_SETUP([module test macros])
-AT_CHECK_DYNAMIC_MODULE
-AT_CHECK_GMP
-
-AT_DATA([in], [[include(`mpeval')
--__load__-__mpeval__-
-unload(`mpeval')
--__load__-__mpeval__-
-unload(`load')
--__load__-__mpeval__-
-]])
-
-AT_CHECK_M4([load in], [0], [[
----
-
---__mpeval__-
-
--__load__-__mpeval__-
-]])
-
-AT_CLEANUP
-
-
## ---------------------------- ##
## Exercising the test module. ##
## ---------------------------- ##
@@ -108,10 +81,9 @@ m4_define([AT_CHECK_M4_MODTEST],
AT_CHECK_DYNAMIC_MODULE
AT_DATA([input.m4],
-[[include(`modtest')
-test
+[[test
Dumpdef: dumpdef(`test').
-unload(`modtest')
+include(`modtest')
test
Dumpdef: dumpdef(`test').
]])
@@ -122,18 +94,16 @@ dnl carry over to the next AT_SETUP.
m4_ifval([$2], [$2
export m4_substr([$2], [0], m4_index([$2], [=]))])
-AT_CHECK_M4([load $3 input.m4], [0],
-[[
-Test module called.
+AT_CHECK_M4([$3 input.m4], [0],
+[[test
Dumpdef: .
-test
+Test module called.
Dumpdef: .
]],
-[[Test module loaded.
+[[m4:input.m4:2: warning: dumpdef: undefined macro 'test'
+Test module loaded.
test: <test>
-Test module unloaded.
-m4:input.m4:6: warning: dumpdef: undefined macro 'test'
]])
AT_CLEANUP
@@ -196,26 +166,6 @@ dumpdef(`test')
dumpdef(`shadow')
test
shadow
-
-# Unloading Modtest will unshadow the test definition in Shadow
-unload(`modtest')
-dumpdef(`test')
-dumpdef(`shadow')
-test
-shadow
-
-# Unloading Shadow once has no effect (we loaded it twice)
-unload(`shadow')
-dumpdef(`test')
-dumpdef(`shadow')
-test
-shadow
-
-# Unloading Shadow again will revert to copying `test' and the local
-# `shadow' macro.
-unload(`shadow')
-test
-shadow
]])
AT_DATA([[expout]],
@@ -252,26 +202,6 @@ Shadow::shadow called.
Test module called.
Shadow::shadow called.
-
-# Unloading Modtest will unshadow the test definition in Shadow
-
-
-
-Shadow::test called.
-Shadow::shadow called.
-
-# Unloading Shadow once has no effect (we loaded it twice)
-
-
-
-Shadow::test called.
-Shadow::shadow called.
-
-# Unloading Shadow again will revert to copying `test' and the local
-# `shadow' macro.
-
-local::test
-local::shadow
]])
AT_DATA([[experr]],
@@ -282,88 +212,15 @@ test: <test>
shadow: <shadow>
test: <test>
shadow: <shadow>
-Test module unloaded.
-test: <test>
-shadow: <shadow>
-test: <test>
-shadow: <shadow>
]])
-AT_CHECK_M4([-I "$abs_builddir" load input.m4], [0],
+AT_CHECK_M4([-I "$abs_builddir" input.m4], [0],
[expout], [experr])
AT_CLEANUP
-## ------ ##
-## unload ##
-## ------ ##
-
-AT_SETUP([modules: unload])
-AT_CHECK_DYNAMIC_MODULE
-
-AT_DATA([[input.m4]],
-[[test
-__test__
-include(`modtest')
-test
-__test__
-include(`shadow')
-test
-__test__
-unload(`modtest')
-test
-__test__
-include(`modtest')
-test
-__test__
-unload(`modtest')
-test
-__test__
-unload(`shadow')
-test
-__test__
-]])
-
-AT_DATA([[expout]],
-[[test
-__test__
-
-Test module called.
-modtest
-Shadow module loaded.
-Shadow::test called.
-shadow
-
-Shadow::test called.
-shadow
-
-Test module called.
-modtest
-
-Shadow::test called.
-shadow
-
-test
-__test__
-]])
-
-AT_DATA([[experr]],
-[[Test module loaded.
-Test module unloaded.
-Test module loaded.
-Test module unloaded.
-]])
-
-
-AT_CHECK_M4([-I "$abs_builddir" load input.m4],
- [0], [expout], [experr])
-
-AT_CLEANUP
-
-
-
## ----------------------- ##
## module symbol importing ##
## ----------------------- ##
@@ -382,7 +239,6 @@ AT_DATA([[input.m4]],
[[import
include(`import')
import
-unload(`modtest')
import
symbol_fail
module_fail
@@ -392,7 +248,6 @@ AT_DATA([[expout]],
[[import
import::import called.
-
import::import called.
import::symbol_fail called.
]])
@@ -401,17 +256,15 @@ AT_DATA([[experr]],
[[Test module loaded.
TRUE
-Test module unloaded.
-Test module loaded.
TRUE
-m4:input.m4:6: cannot load symbol `no_such' from module `modtest'
-m4:input.m4:7: cannot open module `no_such'
+m4:input.m4:5: cannot load symbol `no_such' from module `modtest'
+m4:input.m4:6: cannot open module `no_such'
]])
ls "$abs_builddir"
-AT_CHECK_M4([-I "$abs_builddir" load input.m4],
+AT_CHECK_M4([-I "$abs_builddir" input.m4],
[1], [expout], [experr])
AT_CLEANUP
@@ -454,7 +307,6 @@ m4:input.m4:2: warning: __test__: extra arguments ignored: 1 > 0
m4:input.m4:3: warning: __test__: extra arguments ignored: 2 > 0
m4:input.m4:4: warning: onearg: too few arguments: 0 < 1
m4:input.m4:6: warning: onearg: extra arguments ignored: 2 > 1
-Test module unloaded.
]])
AT_CLEANUP
@@ -474,8 +326,6 @@ AT_DATA([[input.m4]],
[[test
include(`shadow')
test
-unload(`shadow')
-test
include(`shadow')
test
]])
@@ -485,8 +335,6 @@ AT_DATA([[expout]],
Shadow module loaded.
Shadow::test called.
-test
-Shadow module loaded.
Shadow::test called.
]])
@@ -496,74 +344,7 @@ m4trace: -1- test -> `Shadow::`test' called.'
]])
-AT_CHECK_M4([-I "$abs_builddir" load -t test input.m4],
+AT_CHECK_M4([-I "$abs_builddir" -t test input.m4],
[0], [expout], [experr])
AT_CLEANUP
-
-
-## ----------------- ##
-## unload gnu module ##
-## ----------------- ##
-
-AT_SETUP([unload gnu module])
-AT_CHECK_DYNAMIC_MODULE
-
-dnl Ensure that the gnu module does not leak memory. I don't know how
-dnl to portably artificially limit the heap to cause an out-of-memory
-dnl condition in the case of a leak, but examining the run of this test
-dnl in a debugger can show whether it is leaking.
-AT_DATA([input.m4], [[divert(-1)
-define(`forloop',
- `pushdef(`$1', `$2')_forloop(`$1', `$2', `$3', `$4')popdef(`$1')')
-define(`_forloop',
- `$4`'ifelse($1, `$3', `',
- `define(`$1', incr($1))_forloop(`$1', `$2', `$3', `$4')')')
-forloop(`i', `1', `5000', `unload(`gnu')include(`gnu')regexp(`123', `\(4\)?2')')
-]])
-
-AT_CHECK_M4([load input.m4], [0])
-
-AT_CLEANUP
-
-
-## ------------------ ##
-## unload load module ##
-## ------------------ ##
-
-AT_SETUP([unload load module])
-AT_CHECK_DYNAMIC_MODULE
-
-dnl Ensure that the load module can be unloaded and reloaded (obviously,
-dnl it can't reload itself; the reload occurs on the command line). Since
-dnl the module must be resident (after all, the `unload' builtin had better
-dnl not unmap the memory for the code it is currently executing), make sure
-dnl that resident modules are handled gracefully.
-AT_DATA([in1.m4], [[__load__ 1
-unload(`load') 2
-__load__ 3
-]])
-
-AT_DATA([in2.m4], [[__load__ 4
-include(`load') 5
-__load__ 6
-unload(`load') 7
-__load__ 8
-unload(`load') 9
-__load__ 10
-]])
-
-AT_CHECK_M4([load in1.m4 load in2.m4], [0],
-[[ 1
- 2
-__load__ 3
- 4
- 5
- 6
- 7
- 8
- 9
-__load__ 10
-]])
-
-AT_CLEANUP
diff --git a/tests/options.at b/tests/options.at
index 921c6fe5..5848fa80 100644
--- a/tests/options.at
+++ b/tests/options.at
@@ -423,7 +423,6 @@ dnl Test all flags.
AT_CHECK_M4([-dV in], [0], [[3
0
]], [[m4debug: module m4: opening file
-m4debug: module m4: init hook called
m4debug: module m4: opened
m4debug: module m4: builtins loaded
m4debug: module gnu: opening file
@@ -451,11 +450,6 @@ m4debug: input from m4wrap recursion level 1
m4trace:nested:1: -1- id 6: divnum ... = <divnum>{m4}
m4trace:nested:1: -1- id 6: divnum -> `0'
m4debug: input from m4wrap exhausted
-m4debug: module gnu: symbols unloaded
-m4debug: module gnu: finish hook called
-m4debug: module gnu: closed
-m4debug: module m4: symbols unloaded
-m4debug: module m4: resident module not closed
]])
dnl Test addition and subtraction of flags.