m4-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU M4 source repository branch, master, updated. cvs-readonly-306


From: Gary V. Vaughan
Subject: [SCM] GNU M4 source repository branch, master, updated. cvs-readonly-306-g7781a59
Date: Fri, 20 Sep 2013 15:20:12 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU M4 source repository".

http://git.sv.gnu.org/gitweb/?p=m4.git;a=commitdiff;h=7781a595d8236fe0cc6bd2f2fdd2d67c5707eb50

The branch, master has been updated
       via  7781a595d8236fe0cc6bd2f2fdd2d67c5707eb50 (commit)
       via  7b5142a2fd0939e5209e1d375843b8e9d94eb114 (commit)
       via  af658bcf69e62f75ec6ea084ccd84fe052e8e367 (commit)
       via  1d0cc3149668703ee990fdd562582dccc73c8864 (commit)
       via  b466ccc6137f2255220c87f74baf86a67884a3d8 (commit)
       via  aeb92bcb25e253b55650961f341640f93ec3b54e (commit)
       via  9114cb2e988dabdf4c8561f62eb448aa24117574 (commit)
      from  8cb4718e3308c3bc0d917403132601fae3d428b7 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 7781a595d8236fe0cc6bd2f2fdd2d67c5707eb50
Author: Gary V. Vaughan <address@hidden>
Date:   Fri Sep 20 21:54:01 2013 +0700

    modules: speed up multiple includes of the same module.
    
    * m4/module.c (m4_module_load): If we already have the module
    loaded, reuse that.  Otherwise, open the module afresh and
    register it's builtins and macros on success.
    
    Signed-off-by: Gary V. Vaughan <address@hidden>

commit 7b5142a2fd0939e5209e1d375843b8e9d94eb114
Author: Gary V. Vaughan <address@hidden>
Date:   Fri Sep 20 21:20:05 2013 +0700

    modules: simplify module lookup by name.
    
    * m4/m4private.h (m4:namemap): New field for hash table to lookup
    module structures by name string.
    * m4/m4.c (hashfn): Hash function for plain strings.
    (m4_create): Initialise namemap field to a hash table using hashfn
    for inserting and looking up keys.
    * m4/module.c (m4__module_find): Replace the fussy libltdl
    twiddling with a hash lookup in m4:namemap.
    Add a new context parameter. Adjust all callers.
    
    Signed-off-by: Gary V. Vaughan <address@hidden>

commit af658bcf69e62f75ec6ea084ccd84fe052e8e367
Author: Gary V. Vaughan <address@hidden>
Date:   Fri Sep 20 18:17:02 2013 +0700

    modules: store loaded modules in context struct.
    
    * m4/m4private.h (struct m4_module): Add a next pointer.
    (struct m4): Add a module list pointer.
    * m4/module.c (m4__module_open): Initialise the next pointer and
    update the list head when a new module is successfully opened.
    (m4_module_next): Replace the ugly libltdl twiddling with a
    straight forward module list traversal one-liner!
    Add a context parameter. Adjust all callers.
    
    Signed-off-by: Gary V. Vaughan <address@hidden>

commit 1d0cc3149668703ee990fdd562582dccc73c8864
Author: Gary V. Vaughan <address@hidden>
Date:   Fri Sep 20 17:26:42 2013 +0700

    modules: store module name in the module struct.
    
    * m4/m4private.h (m4_module): Add name field.
    * m4/module.c (m4__module_open): Save the name field.
    * m4/path.c (m4_load_filename): Pass the raw filename to
    m4_module_load.
    * m4/module.c (m4_get_module_name): Replace all the ltdl
    twiddling with returning the saved name field.
    
    Signed-off-by: Gary V. Vaughan <address@hidden>

commit b466ccc6137f2255220c87f74baf86a67884a3d8
Author: Gary V. Vaughan <address@hidden>
Date:   Fri Sep 20 16:01:31 2013 +0700

    modules: allow only a single function access point.
    
    Exporting non-function symbols barely works on Windows, so change
    the module loading API to use a single function access point which
    is then responsible for calling back to install symbols and macros.
    * m4/m4module.h, m4/m4module.c (m4_install_builtins)
    (m4_install_macros): New APIs for saving builtins and macros into
    the module struct.
    * m4/m4module.c (install_macro_table, install_builtin_table):
    Adjust accordingly.
    (m4__module_open): Simplify accordingly.
    * m4/m4private.h (BUILTIN_SYMBOL, MACRO_SYMBOL): Remove.
    * modules/gnu.c, modules/import.c, modules/m4.c, modules/modtest.c,
    modules/mpeval.c, modules/shadow.c, modules/time.c,
    modules/traditional.c (m4_builtin_table, m4_macro_table): Make
    static, and remove LTX symbol mangling macros.
    (M4INIT_HANDLER): Call m4_install_builtins and/or m4_install_macros.
    * tests/options.at: Now that init_func is always called, adjust
    expected debug output.
    
    Signed-off-by: Gary V. Vaughan <address@hidden>

commit aeb92bcb25e253b55650961f341640f93ec3b54e
Author: Gary V. Vaughan <address@hidden>
Date:   Fri Sep 20 12:00:02 2013 +0700

    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 <address@hidden>

commit 9114cb2e988dabdf4c8561f62eb448aa24117574
Author: Gary V. Vaughan <address@hidden>
Date:   Fri Sep 20 09:52:03 2013 +0700

    refactor: remove dead M4MODPATH code.
    
    * m4/m4private.h (USER_MODULE_PATH_ENV): Remove.
    * m4/module.c: Correct doc-comment header details.
    (m4__module_init): Remove PKGLIBEXECDIR and M4MODPATH handling.
    Move configmake.h include from here...
    * m4/path.c: ...to here.
    (m4__include_init): Append PKGLIBDIR to search path.
    
    Signed-off-by: Gary V. Vaughan <address@hidden>

-----------------------------------------------------------------------

Summary of changes:
 Makefile.am           |    4 -
 doc/m4.texi           |   82 +---------
 m4/builtin.c          |   12 +-
 m4/m4.c               |   15 ++
 m4/m4module.h         |   24 +--
 m4/m4private.h        |   20 +--
 m4/module.c           |  447 +++++++++++--------------------------------------
 m4/path.c             |    6 +-
 modules/gnu.c         |   62 ++++---
 modules/import.c      |    8 +-
 modules/load.c        |  126 --------------
 modules/m4.c          |   14 +--
 modules/modtest.c     |   21 +--
 modules/mpeval.c      |   16 +-
 modules/shadow.c      |   17 +-
 modules/stdlib.c      |   14 +-
 modules/time.c        |   13 +-
 modules/traditional.c |   10 +-
 src/freeze.c          |   18 +-
 src/main.c            |    1 -
 tests/modules.at      |  247 ++-------------------------
 tests/options.at      |    6 +-
 22 files changed, 253 insertions(+), 930 deletions(-)
 delete mode 100644 modules/load.c

diff --git a/Makefile.am b/Makefile.am
index 7920b9d..e9807a0 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 7def990..77c3a5f 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
address@hidden/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
 
address@hidden {Builtin (load)} m4modules
address@hidden {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:
 
address@hidden options: load -
 @example
-$ @kbd{m4 load -}
-m4modules
address@hidden,gnu,m4
address@hidden example
-
address@hidden Unload
address@hidden Removing loaded modules
-
address@hidden {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
address@hidden 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.
address@hidden deffn
-
address@hidden options: mpeval load -
address@hidden
-$ @kbd{m4 mpeval load -}
-m4modules
address@hidden,mpeval,gnu,m4
-unload(`mpeval')
address@hidden
-m4modules
address@hidden,gnu,m4
address@hidden example
-
address@hidden Refcount
address@hidden Tracking module references
-
address@hidden {Builtin (load)} refcount (@var{module-name})
-This macro expands to an integer representing the number of times
address@hidden 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.
address@hidden deffn
-
-This example demonstrates tracking the reference count of the gnu
-module.
-
address@hidden options: load -
address@hidden
-$ @kbd{m4 load -}
-m4modules
address@hidden,gnu,m4
-refcount(`gnu')
address@hidden
-m4modules
address@hidden,gnu,m4
-include(`gnu')
address@hidden
-refcount(`gnu')
address@hidden
-unload(`gnu')
address@hidden
-m4modules
address@hidden,gnu,m4
-refcount(`gnu')
address@hidden
-unload(`gnu')
address@hidden
+$ @kbd{m4}
 m4modules
address@hidden,m4
-refcount(`gnu')
address@hidden
-refcount(`NoSuchModule')
address@hidden
address@hidden,m4
 @end example
 
 @node Standard Modules
diff --git a/m4/builtin.c b/m4/builtin.c
index 51f636e..b495e5c 100644
--- a/m4/builtin.c
+++ b/m4/builtin.c
@@ -39,9 +39,9 @@ compare_builtin_name_CB (const void *name, const void *b)
    symbol value, suitable for use in the symbol table or for an
    argument to m4_push_builtin.  */
 m4_symbol_value * M4_GNUC_PURE
-m4_builtin_find_by_name (m4_module *module, const char *name)
+m4_builtin_find_by_name (m4 *context, m4_module *module, const char *name)
 {
-  m4_module *cur = module ? module : m4__module_next (NULL);
+  m4_module *cur = module ? module : m4_module_next (context, 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 (context, cur)));
 
   return NULL;
 }
@@ -65,9 +65,9 @@ m4_builtin_find_by_name (m4_module *module, const char *name)
    malloc'd symbol value, suitable for use in the symbol table or for
    an argument to m4_push_builtin.  */
 m4_symbol_value * M4_GNUC_PURE
-m4_builtin_find_by_func (m4_module *module, m4_builtin_func *func)
+m4_builtin_find_by_func (m4 *context, m4_module *module, m4_builtin_func *func)
 {
-  m4_module *cur = module ? module : m4__module_next (NULL);
+  m4_module *cur = module ? module : m4_module_next (context, 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 (context, cur)));
 
   return 0;
 }
diff --git a/m4/m4.c b/m4/m4.c
index 0497799..d916665 100644
--- a/m4/m4.c
+++ b/m4/m4.c
@@ -20,9 +20,21 @@
 
 #include <config.h>
 
+#include "bitrotate.h"
 #include "m4private.h"
 
 #define DEFAULT_NESTING_LIMIT  1024
+#define DEFAULT_NAMEMAP_SIZE    61
+
+static size_t
+hashfn (const void *ptr)
+{
+  const char *s = (const char *) ptr;
+  size_t val = DEFAULT_NAMEMAP_SIZE;
+  while (*s)
+    val = rotl_sz (val, 7) + to_uchar (*s++);
+  return val;
+}
 
 
 m4 *
@@ -33,6 +45,9 @@ m4_create (void)
   context->symtab = m4_symtab_create (0);
   context->syntax = m4_syntax_create ();
 
+  context->namemap =
+    m4_hash_new (DEFAULT_NAMEMAP_SIZE, hashfn, (m4_hash_cmp_func *) strcmp);
+
   context->debug_file   = stderr;
   obstack_init (&context->trace_messages);
 
diff --git a/m4/m4module.h b/m4/m4module.h
index 8c249f0..038a428 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,16 @@ 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 void         m4_install_builtins (m4*, m4_module *, const m4_builtin*);
+extern void         m4_install_macros   (m4*, m4_module *, const m4_macro*);
+
 extern const char * m4_get_module_name (const m4_module *);
-extern void         m4__module_exit    (m4 *);
+extern m4_module *  m4_module_next     (m4*, m4_module *);
 
 
 
@@ -342,8 +330,8 @@ extern void             m4_set_symbol_value_placeholder 
(m4_symbol_value *,
 
 /* --- BUILTIN MANAGEMENT --- */
 
-extern m4_symbol_value  *m4_builtin_find_by_name (m4_module *, const char *);
-extern m4_symbol_value  *m4_builtin_find_by_func (m4_module *,
+extern m4_symbol_value  *m4_builtin_find_by_name (m4 *, m4_module *, const 
char *);
+extern m4_symbol_value  *m4_builtin_find_by_func (m4 *, m4_module *,
                                                   m4_builtin_func *);
 
 
diff --git a/m4/m4private.h b/m4/m4private.h
index 7dc207a..926df58 100644
--- a/m4/m4private.h
+++ b/m4/m4private.h
@@ -59,6 +59,8 @@ typedef unsigned int bool_bitfield;
 struct m4 {
   m4_symbol_table *     symtab;
   m4_syntax_table *     syntax;
+  m4_module *           modules;
+  m4_hash *             namemap;
 
   const char *          current_file;   /* Current input file.  */
   int                   current_line;   /* Current input line.  */
@@ -173,33 +175,23 @@ extern void m4__builtin_print (m4_obstack *, const 
m4__builtin *, bool,
 
 /* --- MODULE MANAGEMENT --- */
 
-#define USER_MODULE_PATH_ENV    "M4MODPATH"
-#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
 {
+  const char *name;             /* Name of the module.  */
   lt_dlhandle handle;           /* All ltdl module information.  */
-  int refcount;                 /* Count of loads not matched by unload.  */
   m4__builtin *builtins;        /* Sorted array of builtins.  */
+  m4_macro *macros;            /* Unsorted array of macros.  */
   size_t builtins_len;          /* Number of builtins.  */
+  m4_module *next;
 };
 
 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
+extern m4_module *  m4__module_find (m4 *context, const char *name);
 
 
 /* --- SYMBOL TABLE MANAGEMENT --- */
diff --git a/m4/module.c b/m4/module.c
index 6256bca..39cd2d2 100644
--- a/m4/module.c
+++ b/m4/module.c
@@ -20,7 +20,6 @@
 
 #include <config.h>
 
-#include "configmake.h"
 #include "m4private.h"
 #include "xvasprintf.h"
 
@@ -40,76 +39,55 @@
  * libdld or lt_dlpreload from libtool if shared libraries are not
  * available on the host machine.
  *
- * An M4 module will usually define an external symbol called
- * `m4_builtin_table'.  This symbol points to a table of `m4_builtin'.
- * The table is saved as libltdl caller data and each definition therein
- * is added to the symbol table.
+ * An M4 module will usually define an external symbol named after the
+ * basename of the loadable module:
  *
- * To load a module, call m4_module_load(), which uses the libltdl
- * API to find the module in the module search path.  The search
- * path is initialized from the environment variable M4MODPATH, followed
- * by the configuration time default where the modules shipped with M4
- * itself are installed.  Libltdl reads the libtool .la file to
- * get the real library name (which can be system dependent), returning
- * NULL on failure or else a libtool module handle for the newly mapped
- * vm segment containing the module code.  If the module is not already
- * loaded, m4_module_load() retrieves its value for the symbol
- * `m4_builtin_table', which is installed using set_module_builtin_table().
+ *   void
+ *   mymod_LTX_m4_init_module (m4 *context, m4_module *module,
+ *                             m4_obstack *obs)
  *
- * In addition to builtin functions, you can also define static macro
- * expansions in the `m4_macro_table' symbol.  If you define this symbol
- * in your modules, it should be an array of `m4_macro's, mapping macro
- * names to the expansion text.  Any macros defined in `m4_macro_table'
- * are installed into the M4 symbol table with set_module_macro_table().
+ * The function is only called the first time the module is included
+ * and generally uses either `m4_install_builtins' or
+ * `m4_install_macros' (or both!) to register whatever builtins and
+ * macros are provided by the module.
  *
- * 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).
+ * To load a module, call m4_module_load(), which searches for the
+ * module in directories from M4PATH. The search path is initialized
+ * from the environment variable M4PATH, followed by the configuration
+ * time default where the modules shipped with M4 itself are installed.
+ * `m4_module_load' returns NULL on failure, or else an opaque module
+ * handle for the newly mapped vm segment containing the module code.
+ * If the module is not already loaded, m4_module_load() the builtins
+ * and macros registered by `mymod_LTX_m4_init_module' are installed
+ * into the symbol table using `install_builtin_table' and `install_
+ * macro_table' respectively.
  **/
 
 #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 *);
 
-static int          m4__module_interface        (lt_dlhandle handle,
-                                                 const char *id_string);
+static int          compare_builtin_CB    (const void *a, const void *b);
+static int          m4__module_interface  (lt_dlhandle handle,
+                                           const char *id_string);
 
 static lt_dlinterface_id iface_id = NULL;
 
 const char *
 m4_get_module_name (const m4_module *module)
 {
-  const lt_dlinfo *info;
-
-  assert (module && module->handle);
-
-  info = lt_dlgetinfo (module->handle);
-
-  return info ? info->name : NULL;
+  assert (module);
+  return module->name;
 }
 
 void *
 m4_module_import (m4 *context, const char *module_name,
                   const char *symbol_name, m4_obstack *obs)
 {
-  m4_module *   module          = m4__module_find (module_name);
+  m4_module *   module          = m4__module_find (context, module_name);
   void *        symbol_address  = NULL;
 
   /* Try to load the module if it is not yet available (errors are
@@ -132,6 +110,36 @@ m4_module_import (m4 *context, const char *module_name,
   return symbol_address;
 }
 
+void
+m4_install_builtins (m4 *context, m4_module *module, const m4_builtin *bp)
+{
+  assert (context);
+  assert (module);
+  assert (bp);
+
+  const m4_builtin *tmp;
+  m4__builtin *builtin;
+  for (tmp = bp; tmp->name; tmp++)
+    module->builtins_len++;
+  module->builtins = (m4__builtin *) xnmalloc (module->builtins_len,
+                                               sizeof *module->builtins);
+  for (builtin = module->builtins; bp->name != NULL; bp++, builtin++)
+    {
+      /* Sanity check that builtins meet the required interface. */
+      assert (bp->min_args <= bp->max_args);
+      assert (bp->min_args > 0 ||
+              (bp->flags & (M4_BUILTIN_BLIND|M4_BUILTIN_SIDE_EFFECT)) == 0);
+      assert (bp->max_args ||
+              (bp->flags & M4_BUILTIN_FLATTEN_ARGS) == 0);
+      assert ((bp->flags & ~M4_BUILTIN_FLAGS_MASK) == 0);
+      memcpy (&builtin->builtin, bp, sizeof *bp);
+      builtin->builtin.name = xstrdup (bp->name);
+      builtin->module = module;
+    }
+  qsort (module->builtins, module->builtins_len,
+         sizeof *module->builtins, compare_builtin_CB);
+}
+
 static void
 install_builtin_table (m4 *context, m4_module *module)
 {
@@ -159,6 +167,16 @@ install_builtin_table (m4 *context, m4_module *module)
                       m4_get_module_name (module));
 }
 
+void
+m4_install_macros (m4 *context, m4_module *module, const m4_macro *mp)
+{
+  assert (context);
+  assert (module);
+  assert (mp);
+
+  module->macros = (m4_macro *) mp;
+}
+
 static void
 install_macro_table (m4 *context, m4_module *module)
 {
@@ -167,7 +185,7 @@ install_macro_table (m4 *context, m4_module *module)
   assert (context);
   assert (module);
 
-  mp = (const m4_macro *) lt_dlsym (module->handle, MACRO_SYMBOL);
+  mp = module->macros;
 
   if (mp)
     {
@@ -196,57 +214,22 @@ install_macro_table (m4 *context, m4_module *module)
 m4_module *
 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);
-
+  m4_module *module = m4__module_find (context, name);
+  
   if (!module)
     {
-      const char *error_msg = _("module not loaded");
+      module = m4__module_open (context, name, obs);
 
-      lt_dlseterror (lt_dladderror (error_msg));
-      ++errors;
+      if (module)
+        {
+          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)
@@ -259,51 +242,24 @@ m4__module_interface (lt_dlhandle handle, const char 
*id_string)
     return 0;
 
   /* 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));
+  return !(lt_dlsym (handle, INIT_SYMBOL));
 }
 
 
-/* Return successive loaded modules that pass the interface test registered
-   with the interface id.  */
+/* Return successive loaded modules. */
 m4_module *
-m4__module_next (m4_module *module)
+m4_module_next (m4 *context, m4_module *module)
 {
-  lt_dlhandle handle = module ? module->handle : NULL;
-  assert (iface_id);
-
-  /* Resident modules still show up in the lt_dlhandle_iterate loop
-     after they have been unloaded from m4.  */
-  do
-    {
-      handle = lt_dlhandle_iterate (iface_id, handle);
-      if (!handle)
-        return NULL;
-      module = (m4_module *) lt_dlcaller_get_data (iface_id, handle);
-    }
-  while (!module);
-  assert (module->handle == handle);
-  return module;
+  return module ? module->next : context->modules;
 }
 
 /* Return the first loaded module that passes the registered interface test
    and is called NAME.  */
 m4_module *
-m4__module_find (const char *name)
+m4__module_find (m4 *context, const char *name)
 {
-  lt_dlhandle handle;
-  m4_module *module;
-  assert (iface_id);
-
-  handle = lt_dlhandle_fetch (iface_id, name);
-  if (!handle)
-    return NULL;
-  module = (m4_module *) lt_dlcaller_get_data (iface_id, handle);
-  if (module)
-    assert (module->handle == handle);
-  return module;
+  m4_module **pmodule = (m4_module **) m4_hash_lookup (context->namemap, name);
+  return pmodule ? *pmodule : NULL;
 }
 
 
@@ -346,19 +302,6 @@ m4__module_init (m4 *context)
         }
     }
 
-  if (!errors)
-    errors = lt_dlsetsearchpath (PKGLIBEXECDIR);
-
-  /* If the user set M4MODPATH, then use that as the start of the module
-     search path.  */
-  if (!errors)
-    {
-      char *path = getenv (USER_MODULE_PATH_ENV);
-
-      if (path)
-        errors = lt_dlinsertsearchdir (lt_dlgetsearchpath (), path);
-    }
-
   /* Couldn't initialize the module system; diagnose and exit.  */
   if (errors)
     m4_error (context, EXIT_FAILURE, 0, NULL,
@@ -443,45 +386,14 @@ m4__module_open (m4 *context, const char *name, 
m4_obstack *obs)
         {
           void *old;
           const char *err;
-          const m4_builtin *bp;
 
           module = (m4_module *) xzalloc (sizeof *module);
+          module->name   = xstrdup (name);
           module->handle = handle;
+         module->next   = context->modules;
 
-          /* TODO - change module interface to return function pointer
-             that supplies both table and length of table, rather than
-             returning data pointer that must have a sentinel
-             entry?  */
-          bp = (m4_builtin *) lt_dlsym (module->handle, BUILTIN_SYMBOL);
-          if (bp)
-            {
-              const m4_builtin *tmp;
-              m4__builtin *builtin;
-              for (tmp = bp; tmp->name; tmp++)
-                module->builtins_len++;
-              module->builtins =
-                (m4__builtin *) xnmalloc (module->builtins_len,
-                                          sizeof *module->builtins);
-              for (builtin = module->builtins; bp->name != NULL;
-                   bp++, builtin++)
-                {
-                  /* Sanity check that builtins meet the required
-                     interface.  */
-                  assert (bp->min_args <= bp->max_args);
-                  assert (bp->min_args > 0
-                          || (bp->flags & (M4_BUILTIN_BLIND
-                                           | M4_BUILTIN_SIDE_EFFECT)) == 0);
-                  assert (bp->max_args
-                          || (bp->flags & M4_BUILTIN_FLATTEN_ARGS) == 0);
-                  assert ((bp->flags & ~M4_BUILTIN_FLAGS_MASK) == 0);
-
-                  memcpy (&builtin->builtin, bp, sizeof *bp);
-                  builtin->builtin.name = xstrdup (bp->name);
-                  builtin->module = module;
-                }
-            }
-          qsort (module->builtins, module->builtins_len,
-                 sizeof *module->builtins, compare_builtin_CB);
+         context->modules = module;
+         m4_hash_insert (context->namemap, xstrdup (name), module);
 
           /* clear out any stale errors, since we have to use
              lt_dlerror to distinguish between success and
@@ -493,25 +405,22 @@ m4__module_open (m4 *context, const char *name, 
m4_obstack *obs)
           if (err)
             m4_error (context, EXIT_FAILURE, 0, NULL,
                       _("unable to load module `%s': %s"), name, err);
-        }
 
-      /* 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)
-        {
-          init_func (context, module, obs);
+          /* Find and run any initializing function in the opened module,
+             the first time the module is opened.  */
+          init_func = (m4_module_init_func *) lt_dlsym (handle, INIT_SYMBOL);
+          if (init_func)
+            {
+              init_func (context, module, 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)
-               && !lt_dlsym (handle, MACRO_SYMBOL))
-        {
-          m4_error (context, EXIT_FAILURE, 0, NULL,
-                    _("module `%s' has no entry points"), name);
+              m4_debug_message (context, M4_DEBUG_TRACE_MODULE,
+                                _("module %s: init hook called"), name);
+            }
+          else
+            {
+              m4_error (context, EXIT_FAILURE, 0, NULL,
+                        _("module `%s' has no entry point"), name);
+            }
         }
 
       m4_debug_message (context, M4_DEBUG_TRACE_MODULE,
@@ -527,39 +436,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 *
@@ -572,126 +448,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/m4/path.c b/m4/path.c
index 37115d0..9437e93 100644
--- a/m4/path.c
+++ b/m4/path.c
@@ -30,6 +30,7 @@
 
 #include "m4private.h"
 
+#include "configmake.h"
 #include "dirname.h"
 #include "filenamecat.h"
 
@@ -298,7 +299,7 @@ m4_load_filename (m4 *context, const m4_call_info *caller,
       && suffix
       && (STREQ (suffix, LT_MODULE_EXT) || STREQ (suffix, ".la")))
     {
-      m4_module_load (context, filepath, obs);
+      m4_module_load (context, filename, obs);
     }
   else
     {
@@ -338,6 +339,9 @@ m4__include_init (m4 *context)
     assert (info);
     if (info->list_end == NULL)
       search_path_add (info, "", false);
+
+    /* Non-core modules installation directory. */
+    search_path_add (info, PKGLIBDIR, false);
   }
 
 #ifdef DEBUG_INCL
diff --git a/modules/gnu.c b/modules/gnu.c
index c69862e..96c7547 100644
--- a/modules/gnu.c
+++ b/modules/gnu.c
@@ -32,11 +32,6 @@
 #include "spawn-pipe.h"
 #include "wait-process.h"
 
-/* Rename exported symbols for dlpreload()ing.  */
-#define m4_builtin_table        gnu_LTX_m4_builtin_table
-#define m4_macro_table          gnu_LTX_m4_macro_table
-
-
 /* Maintain each of the builtins implemented in this modules along
    with their details in a single table for easy maintenance.
 
@@ -58,6 +53,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  )    \
 
@@ -69,7 +65,7 @@
 
 
 /* Generate a table for mapping m4 symbol names to handler functions. */
-const m4_builtin m4_builtin_table[] =
+static const m4_builtin m4_builtin_table[] =
 {
 #define BUILTIN(handler, macros, blind, side, min, max)                 \
   M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max)
@@ -82,7 +78,7 @@ const m4_builtin m4_builtin_table[] =
 
 
 /* A table for mapping m4 symbol names to simple expansion text. */
-const m4_macro m4_macro_table[] =
+static const m4_macro m4_macro_table[] =
 {
   /* name               text    min     max */
 #if UNIX
@@ -101,6 +97,13 @@ const m4_macro m4_macro_table[] =
 };
 
 
+M4INIT_HANDLER (gnu)
+{
+  m4_install_builtins (context, module, m4_builtin_table);
+  m4_install_macros   (context, module, m4_macro_table);
+}
+
+
 
 /* Regular expressions.  Reuse re_registers among multiple
    re_pattern_buffer allocations to reduce malloc usage.  */
@@ -352,25 +355,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__
@@ -433,7 +417,7 @@ M4BUILTIN_HANDLER (builtin)
           name = M4ARG (2);
           len = M4ARGLEN (2);
           if (len == strlen (name))
-            value = m4_builtin_find_by_name (NULL, name);
+            value = m4_builtin_find_by_name (context, NULL, name);
           if (value)
             {
               m4_push_builtin (context, obs, value);
@@ -451,7 +435,7 @@ M4BUILTIN_HANDLER (builtin)
       name = M4ARG (1);
       len = M4ARGLEN (1);
       if (len == strlen (name))
-        value = m4_builtin_find_by_name (NULL, name);
+        value = m4_builtin_find_by_name (context, NULL, name);
       if (value == NULL)
         {
           if (m4_is_debug_bit (context, M4_DEBUG_TRACE_DEREF))
@@ -1016,6 +1000,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 (context, NULL);
+
+  if (module)
+    do
+      {
+        m4_shipout_string (context, obs, m4_get_module_name (module), SIZE_MAX,
+                           true);
+
+        if ((module = m4_module_next (context, 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/import.c b/modules/import.c
index ebce6e4..679a50d 100644
--- a/modules/import.c
+++ b/modules/import.c
@@ -41,7 +41,7 @@
   builtin_functions
 #undef BUILTIN
 
-const m4_builtin m4_builtin_table[] =
+static const m4_builtin m4_builtin_table[] =
 {
 #define BUILTIN(handler, macros, blind, side, min, max)                 \
   M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max)
@@ -53,6 +53,12 @@ const m4_builtin m4_builtin_table[] =
 };
 
 
+M4INIT_HANDLER (import)
+{
+  m4_install_builtins (context, module, m4_builtin_table);
+}
+
+
 
 typedef bool export_test_func (const char *);
 typedef bool no_such_func (const char *);
diff --git a/modules/load.c b/modules/load.c
deleted file mode 100644
index 0b0eb1b..0000000
--- 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 64abdae..ecae4c3 100644
--- a/modules/m4.c
+++ b/modules/m4.c
@@ -39,8 +39,6 @@
 #include <modules/m4.h>
 
 /* Rename exported symbols for dlpreload()ing.  */
-#define m4_builtin_table        m4_LTX_m4_builtin_table
-
 #define m4_set_sysval           m4_LTX_m4_set_sysval
 #define m4_sysval_flush         m4_LTX_m4_sysval_flush
 #define m4_dump_symbols         m4_LTX_m4_dump_symbols
@@ -127,16 +125,9 @@ 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);
+  m4_install_builtins (context, module, m4_builtin_table);
 }
 
 
@@ -840,9 +831,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 5febf08..75450f7 100644
--- a/modules/modtest.c
+++ b/modules/modtest.c
@@ -29,9 +29,6 @@
 #endif
 
 /* Rename exported symbols for dlpreload()ing.  */
-#define m4_builtin_table        modtest_LTX_m4_builtin_table
-#define m4_macro_table          modtest_LTX_m4_macro_table
-
 #define export_test             modtest_LTX_export_test
 
 extern bool export_test (const char *foo);
@@ -44,7 +41,7 @@ extern bool export_test (const char *foo);
   builtin_functions
 #undef BUILTIN
 
-const m4_builtin m4_builtin_table[] =
+static const m4_builtin m4_builtin_table[] =
 {
 #define BUILTIN(handler, macros, blind, side, min, max)                 \
   M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max)
@@ -55,7 +52,7 @@ const m4_builtin m4_builtin_table[] =
   { NULL, NULL, 0, 0, 0 },
 };
 
-const m4_macro m4_macro_table[] =
+static const m4_macro m4_macro_table[] =
 {
   /* name               text            min     max */
   { "__test__",         "`modtest'",    0,      0 },
@@ -73,18 +70,8 @@ M4INIT_HANDLER (modtest)
 {
   const char *s = "Test module loaded.\n";
 
-  /* Don't depend on OBS so that the traces are the same when used
-     directly, or via a frozen file.  */
-  fputs (s, stderr);
-}
-
-
-/**
- * modtest()
- **/
-M4FINISH_HANDLER (modtest)
-{
-  const char *s = "Test module unloaded.\n";
+  m4_install_builtins (context, module, m4_builtin_table);
+  m4_install_macros   (context, module, m4_macro_table);
 
   /* Don't depend on OBS so that the traces are the same when used
      directly, or via a frozen file.  */
diff --git a/modules/mpeval.c b/modules/mpeval.c
index 7928a28..49afd76 100644
--- a/modules/mpeval.c
+++ b/modules/mpeval.c
@@ -32,11 +32,6 @@
 #  include <gmp.h>
 #endif
 
-/* Rename exported symbols for dlpreload()ing.  */
-#define m4_builtin_table        mpeval_LTX_m4_builtin_table
-#define m4_macro_table          mpeval_LTX_m4_macro_table
-
-
 /* Maintain each of the builtins implemented in this modules along
    with their details in a single table for easy maintenance.
 
@@ -106,7 +101,7 @@
 
 
 /* Generate a table for mapping m4 symbol names to handler functions. */
-const m4_builtin m4_builtin_table[] =
+static const m4_builtin m4_builtin_table[] =
 {
 #define BUILTIN(handler, macros, blind, side, min, max)                 \
   M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max)
@@ -119,7 +114,7 @@ const m4_builtin m4_builtin_table[] =
 
 
 /* A table for mapping m4 symbol names to simple expansion text. */
-const m4_macro m4_macro_table[] =
+static const m4_macro m4_macro_table[] =
 {
   /* name               text    min     max */
   { "__mpeval__",       "",     0,      0 },
@@ -127,6 +122,13 @@ const m4_macro m4_macro_table[] =
 };
 
 
+M4INIT_HANDLER (mpeval)
+{
+  m4_install_builtins (context, module, m4_builtin_table);
+  m4_install_macros   (context, module, m4_macro_table);
+}
+
+
 /* GMP defines mpq_t as a 1-element array of struct.  Therefore, `mpq_t'
    is not compatible with `const mpq_t'.  */
 typedef mpq_t number;
diff --git a/modules/shadow.c b/modules/shadow.c
index 16260f1..5382993 100644
--- a/modules/shadow.c
+++ b/modules/shadow.c
@@ -28,10 +28,6 @@
 #  include "m4private.h"
 #endif
 
-/* Rename exported symbols for dlpreload()ing.  */
-#define m4_builtin_table        shadow_LTX_m4_builtin_table
-#define m4_macro_table          shadow_LTX_m4_macro_table
-
 /*         function     macros  blind   side    minargs maxargs */
 #define builtin_functions                       \
   BUILTIN (shadow,      false,  false,  false,  0,      -1 )    \
@@ -42,7 +38,7 @@
   builtin_functions
 #undef BUILTIN
 
-const m4_builtin m4_builtin_table[] =
+static const m4_builtin m4_builtin_table[] =
 {
 #define BUILTIN(handler, macros, blind, side, min, max)                 \
   M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max)
@@ -53,7 +49,7 @@ const m4_builtin m4_builtin_table[] =
   { NULL, NULL, 0, 0, 0 },
 };
 
-const m4_macro m4_macro_table[] =
+static const m4_macro m4_macro_table[] =
 {
   /* name               text            min     max */
   { "__test__",         "`shadow'",     0,      0 },
@@ -65,11 +61,12 @@ const m4_macro m4_macro_table[] =
 M4INIT_HANDLER (shadow)
 {
   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)
+      obstack_grow (obs, s, strlen (s));
+
+  m4_install_builtins (context, module, m4_builtin_table);
+  m4_install_macros   (context, module, m4_macro_table);
 }
 
 
diff --git a/modules/stdlib.c b/modules/stdlib.c
index d8f839c..b01326d 100644
--- a/modules/stdlib.c
+++ b/modules/stdlib.c
@@ -36,12 +36,9 @@
 #  include "m4private.h"
 #endif
 
-/* Rename exported symbols for dlpreload()ing.  */
-#define m4_builtin_table        stdlib_LTX_m4_builtin_table
-
 /*         function     macros  blind   side    minargs maxargs */
 #define builtin_functions                                       \
-  BUILTIN (getcwd,      false,  false,  false,  0,      0  )    \
+    BUILTIN (getcwd,    false,  false,  false,  0,      0  )    \
     BUILTIN (getenv,    false,  true,   false,  1,      1  )    \
     BUILTIN (getlogin,  false,  false,  false,  0,      0  )    \
     BUILTIN (getpid,    false,  false,  false,  0,      0  )    \
@@ -61,7 +58,7 @@
   builtin_functions
 #undef BUILTIN
 
-const m4_builtin m4_builtin_table[] =
+static const m4_builtin m4_builtin_table[] =
 {
 #define BUILTIN(handler, macros, blind, side, min, max)                 \
   M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max)
@@ -71,6 +68,13 @@ const m4_builtin m4_builtin_table[] =
 
   { NULL, NULL, 0, 0, 0 },
 };
+
+
+M4INIT_HANDLER (stdlib)
+{
+  m4_install_builtins (context, module, m4_builtin_table);
+}
+
 
 /**
  * getcwd()
diff --git a/modules/time.c b/modules/time.c
index 573d14d..39db75f 100644
--- a/modules/time.c
+++ b/modules/time.c
@@ -34,9 +34,6 @@
 #  include "m4private.h"
 #endif
 
-/* Rename exported symbols for dlpreload()ing.  */
-#define m4_builtin_table        time_LTX_m4_builtin_table
-
 /*         function     macros  blind   side    minargs maxargs */
 #define builtin_functions                                       \
   BUILTIN (currenttime, false,  false,  false,  0,      0  )    \
@@ -61,7 +58,7 @@
 # endif
 #undef BUILTIN
 
-const m4_builtin m4_builtin_table[] =
+static const m4_builtin m4_builtin_table[] =
 {
 #define BUILTIN(handler, macros, blind, side, min, max)                 \
   M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max)
@@ -77,6 +74,14 @@ const m4_builtin m4_builtin_table[] =
 
   { NULL, NULL, 0, 0, 0 },
 };
+
+
+M4INIT_HANDLER (time)
+{
+  m4_install_builtins (context, module, m4_builtin_table);
+}
+
+
 
 /**
  * currenttime()
diff --git a/modules/traditional.c b/modules/traditional.c
index cb9a32b..88a4966 100644
--- a/modules/traditional.c
+++ b/modules/traditional.c
@@ -28,11 +28,8 @@
 #  include "m4private.h"
 #endif
 
-/* Rename exported symbols for dlpreload()ing.  */
-#define m4_macro_table          traditional_LTX_m4_macro_table
-
 /* A table for mapping m4 symbol names to simple expansion text. */
-const m4_macro m4_macro_table[] =
+static const m4_macro m4_macro_table[] =
 {
   /* name               text    min     max */
 #if UNIX
@@ -47,3 +44,8 @@ const m4_macro m4_macro_table[] =
   { "__traditional__",  "",     0,      0 },
   { NULL,               NULL,   0,      0 },
 };
+
+M4INIT_HANDLER (traditional)
+{
+  m4_install_macros (context, module, m4_macro_table);
+}
diff --git a/src/freeze.c b/src/freeze.c
index 9f36e8c..3b1fdd9 100644
--- a/src/freeze.c
+++ b/src/freeze.c
@@ -33,7 +33,7 @@
 static  void  produce_mem_dump          (FILE *, const char *, size_t);
 static  void  produce_resyntax_dump     (m4 *, FILE *);
 static  void  produce_syntax_dump       (FILE *, m4_syntax_table *, char);
-static  void  produce_module_dump       (FILE *, m4_module *);
+static  void  produce_module_dump       (m4 *, FILE *, m4_module *);
 static  void  produce_symbol_dump       (m4 *, FILE *, m4_symbol_table *);
 static  void *dump_symbol_CB            (m4_symbol_table *, const char *,
                                          size_t, m4_symbol *, void *);
@@ -148,17 +148,17 @@ produce_debugmode_state (FILE *file, int flags)
 }
 
 /* The modules must be dumped in the order in which they will be
-   reloaded from the frozen file.  libltdl stores handles in a push
+   reloaded from the frozen file.  We store handles in a push
    down stack, so we need to dump them in the reverse order to that.  */
 static void
-produce_module_dump (FILE *file, m4_module *module)
+produce_module_dump (m4 *context, 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 (context, module);
   if (module)
-    produce_module_dump (file, module);
+    produce_module_dump (context, file, module);
 
   xfprintf (file, "M%zu\n", len);
   produce_mem_dump (file, name, len);
@@ -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 (context, file, m4_module_next (context, NULL));
 
   /* Dump all symbols.  */
   produce_symbol_dump (context, file, M4SYMTAB);
@@ -711,9 +711,9 @@ ill-formed frozen file, invalid builtin %s encountered"),
 ill-formed frozen file, invalid module %s encountered"),
                             quotearg_style_mem (locale_quoting_style,
                                                 string[2], number[2]));
-                module = m4__module_find (string[2]);
+                module = m4__module_find (context, string[2]);
               }
-            token = m4_builtin_find_by_name (module, string[1]);
+            token = m4_builtin_find_by_name (context, module, string[1]);
 
             if (token == NULL)
               {
@@ -966,7 +966,7 @@ ill-formed frozen file, version 2 directive `%c' 
encountered"), 'T');
 ill-formed frozen file, invalid module %s encountered"),
                             quotearg_style_mem (locale_quoting_style,
                                                 string[2], number[2]));
-                module = m4__module_find (string[2]);
+                module = m4__module_find (context, string[2]);
               }
 
             m4_set_symbol_value_text (token, xmemdup0 (string[1], number[1]),
diff --git a/src/main.c b/src/main.c
index 1e3e706..5330545 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 623f531..dddba9e 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 921c6fe..8503f8f 100644
--- a/tests/options.at
+++ b/tests/options.at
@@ -427,6 +427,7 @@ m4debug: module m4: init hook called
 m4debug: module m4: opened
 m4debug: module m4: builtins loaded
 m4debug: module gnu: opening file
+m4debug: module gnu: init hook called
 m4debug: module gnu: opened
 m4debug: module gnu: builtins loaded
 m4debug: module gnu: macros loaded
@@ -451,11 +452,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.


hooks/post-receive
-- 
GNU M4 source repository



reply via email to

[Prev in Thread] Current Thread [Next in Thread]