m4-patches
[Top][All Lists]
Advanced

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

FYI: 38-gary-inter-module-symbol-importing.patch


From: Gary V. Vaughan
Subject: FYI: 38-gary-inter-module-symbol-importing.patch
Date: Tue, 12 Aug 2003 16:35:24 +0100
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5b) Gecko/20030804

Applied to HEAD.
--
  ())_.  Gary V. Vaughan    gary@(oranda.demon.co.uk|gnu.org)
  ( '/   Research Scientist http://www.oranda.demon.co.uk       ,_())____
  / )=   GNU Hacker         http://www.gnu.org/software/libtool  \'      `&
`(_~)_   Tech' Author       http://sources.redhat.com/autobook   =`---d__/
Index: ChangeLog
from  Gary V. Vaughan  <address@hidden>

        Libltdl already has an excellent mechanism for accessing C symbols
        in modules.  Lets use that!  Remove all the exporting cruft and
        just use lt_dlsym in conjunction with a few conventions to
        simplify module writers' jobs.  Also removed the table address
        caching code and otherwise simplified the module loader quite a
        bit.  To access exported symbols in other modules, first the
        exporting module must name the symbols <modname>_LTX_<symname>,
        and the importing module must define a function type called
        <symname>_func.  The importer then adds
        M4_MODULE_IMPORT(<modname>, <symname>) at the top of any function
        that wishes to call out to the exported functions.  Care must be
        taken that <symname> is non-NULL in the importing module incase
        M4_MODULE_IMPORT fails, but otherwise it can be called as if the
        definition was in the importers source.  Study
        `modules/{gnu.c,m4.{c,h}' for a model example.  At the moment,
        m4_module_import will attempt to automatically load a module
        required for symbol access if it is not loaded already.

        * TODO: Removed the items fixed in this delta.
        * m4/ltdl.c (lt_dlhandle_find): New function to find a handle by
        module name.
        * m4/ltdl.h (lt_dlhandle_find): Declare it.
        * m4/module.c (m4_module_unload): Use it.
        * src/freeze.c (reload_frozen_state): Ditto.
        * m4/m4module.h (m4_export): Deleted.  Removed all references.
        (M4_MODULE_IMPORT): New user convenience macro for importing
        arbitrary symbols from other modules.
        * m4/module.c (m4_module_import): New function to service
        M4_MODULE_IMPORT macro.
        (module_data): Removed.  Looking up the tables on demand with
        lt_dlsym, rather than caching their addresses here simplifies the
        code substantially.
        (m4_get_module_builtin_table, m4_get_module_macro_table):
        Removed.  Changed all callers.
        (set_module_macro_table, set_module_builtin_table): Renamed to
        install_macro_table and install_builtin_table respectively, and
        simplified now that the cache is no more.
        * modules/gnu.c (builtin_symbols): Use this new mechanism to
        import m4_dump_symbols from the m4 module.
        (builtin_esyscmd): Likewise for m4_set_sysval and
        m4_sysval_flush.
        * modules/m4.c (m4_export_table): Removed.  Functions are
        addressed with the new mechanism which doesn't need this.
        (m4_set_sysval): New exported accessor function to prevent
        problems with variable access on inferior architectures.
        * modules/m4.h (m4_sysval_flush_func, m4_set_sysval_func)
        (m4_dump_symbols_func): Typedefs required by M4_MODULE_IMPORT so
        that we can have some type safety.
        * modules/modtest.c (export_test): C level exported function for
        testing the new import mechanism.
        * modules/import.c: New file for the import end of the test.
        * modules/Makefile.am (pkglibexec_LTLIBRARIES): Added import.la.
        * tests/modules.at: New test cases for intermodule symbol
        importing.

Index: TODO
===================================================================
RCS file: /cvsroot/m4/m4/TODO,v
retrieving revision 1.12
diff -u -p -u -r1.12 TODO
--- TODO 29 Jul 2003 15:57:33 -0000 1.12
+++ TODO 12 Aug 2003 15:32:23 -0000
@@ -108,20 +108,6 @@ for any of these ideas or if you have ot
     asked to load a frozen file that requires versions of modules with
     interface versions unsupported by the current release.
 
-  + Some liberties are take with preloaded modules using one another's
-    symbols.  This only works (portably) because the modules that do it
-    (m4.so and gnu.so) are both statically linked into the core.  Need to
-    investigate how this can be supported for any module, on platforms that
-    don't support backlinking.  Maybe exporting symbol name/address pairs
-    into a table maintained by libm4, and only using module symbols through
-    that table in other modules.
-
-  + On a related note, modules should be able to declare that they require
-    other modules to be loaded before they can work -- and the module loader
-    should take care of that.  Should such required modules be fully loaded
-    into the symbol table?  Or merely loaded into memory so that the C level
-    code is callable?
-
   + Setting of the module search path within m4 scripts:
 
        append(__modulepath__, `/some/modules/live/here')
Index: m4/builtin.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/builtin.c,v
retrieving revision 1.20
diff -u -p -u -r1.20 builtin.c
--- m4/builtin.c 17 Jun 2003 15:17:45 -0000 1.20
+++ m4/builtin.c 12 Aug 2003 15:32:24 -0000
@@ -23,44 +23,50 @@
 #include "m4.h"
 #include "m4private.h"
 
-/* Find the builtin, which has NAME.  If BP argument is supplied
-   then search only in table BP.  */
+/* Find the builtin which has NAME.  If HANDLE argument is supplied
+   then search only in HANDLE's builtin table.  */
 const m4_builtin *
-m4_builtin_find_by_name (const m4_builtin *bp, const char *name)
+m4_builtin_find_by_name (lt_dlhandle handle, const char *name)
 {
-  lt_dlhandle  handle  = NULL;
+  lt_dlhandle cur = handle ? handle : lt_dlhandle_next (0);
 
-  while ((handle = lt_dlhandle_next (handle)))
+  do
     {
-      m4_builtin *builtin = m4_get_module_builtin_table (handle);
+      const m4_builtin *builtin =
+       (const m4_builtin *) lt_dlsym (cur, BUILTIN_SYMBOL);
 
-      if (builtin && (bp == NULL || bp == builtin))
+      if (builtin)
        {
          for (; builtin->name != NULL; builtin++)
-           if (strcmp (builtin->name, name) == 0)
+           if (!strcmp (builtin->name, name))
              return builtin;
        }
     }
+  while (!handle && (cur = lt_dlhandle_next (cur)));
 
-  return NULL;
+  return 0;
 }
 
+/* Find the builtin which has FUNC.  If HANDLE argument is supplied
+   then search only in HANDLE's builtin table.  */
 const m4_builtin *
-m4_builtin_find_by_func (const m4_builtin *bp, m4_builtin_func *func)
+m4_builtin_find_by_func (lt_dlhandle handle, m4_builtin_func *func)
 {
-  lt_dlhandle  handle  = NULL;
+  lt_dlhandle cur = handle ? handle : lt_dlhandle_next (0);
 
-  while ((handle = lt_dlhandle_next (handle)))
+  do
     {
-      m4_builtin *builtin = m4_get_module_builtin_table (handle);
+      const m4_builtin *builtin =
+       (const m4_builtin *) lt_dlsym (cur, BUILTIN_SYMBOL);
 
-      if (builtin && (bp == NULL || bp == builtin))
+      if (builtin)
        {
          for (; builtin->name != NULL; builtin++)
            if (builtin->func == func)
              return builtin;
        }
     }
+  while (!handle && (cur = lt_dlhandle_next (cur)));
 
-  return NULL;
+  return 0;
 }
Index: m4/ltdl.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/ltdl.c,v
retrieving revision 1.13
diff -u -p -u -r1.13 ltdl.c
--- m4/ltdl.c 30 May 2003 15:13:32 -0000 1.13
+++ m4/ltdl.c 12 Aug 2003 15:32:24 -0000
@@ -4135,6 +4135,22 @@ lt_dlhandle_next (place)
   return place ? place->next : handles;
 }
 
+lt_dlhandle
+lt_dlhandle_find (module_name)
+     const char *module_name;
+{
+  lt_dlhandle cur = handles;
+
+  if (cur)
+    do
+      {
+       if (cur->info.name && strcmp (cur->info.name, module_name) == 0)
+         break;
+      } while (cur = cur->next);
+
+  return cur;
+}
+
 int
 lt_dlforeach (func, data)
      int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
Index: m4/ltdl.h
===================================================================
RCS file: /cvsroot/m4/m4/m4/ltdl.h,v
retrieving revision 1.5
diff -u -p -u -r1.5 ltdl.h
--- m4/ltdl.h 13 Aug 2001 23:37:44 -0000 1.5
+++ m4/ltdl.h 12 Aug 2003 15:32:24 -0000
@@ -243,6 +243,8 @@ typedef     struct {
 
 extern const lt_dlinfo *lt_dlgetinfo       LT_PARAMS((lt_dlhandle handle));
 extern lt_dlhandle     lt_dlhandle_next    LT_PARAMS((lt_dlhandle place));
+extern lt_dlhandle     lt_dlhandle_find    LT_PARAMS((
+                                               const char *module_name));
 extern int             lt_dlforeach        LT_PARAMS((
                                int (*func) (lt_dlhandle handle, lt_ptr data),
                                lt_ptr data));
Index: m4/m4module.h
===================================================================
RCS file: /cvsroot/m4/m4/m4/m4module.h,v
retrieving revision 1.64
diff -u -p -u -r1.64 m4module.h
--- m4/m4module.h 7 Aug 2003 14:42:48 -0000 1.64
+++ m4/m4module.h 12 Aug 2003 15:32:24 -0000
@@ -29,26 +29,31 @@ BEGIN_C_DECLS
 
 
 
-/* Various declarations.  */
+/* --- MODULE AUTHOR DECLARATIONS --- */
 
 typedef struct m4              m4;
-typedef struct obstack         m4_obstack;
+typedef struct m4_builtin      m4_builtin;
+typedef struct m4_macro                m4_macro;
 typedef struct m4_symbol_value m4_symbol_value;
+
+typedef struct obstack         m4_obstack;
+typedef lt_dlsymlist           m4_export;
+
 typedef void   m4_builtin_func  (m4 *, m4_obstack *, int, m4_symbol_value **);
 
-typedef struct {
+struct m4_builtin
+{
   const char *     name;
   m4_builtin_func * func;
   boolean          groks_macro_args, blind_if_no_args;
   int              min_args, max_args;
-} m4_builtin;
+};
 
-typedef struct {
+struct m4_macro
+{
   const char *name;
   const char *value;
-} m4_macro;
-
-typedef lt_dlsymlist m4_export;
+};
 
 
 #define M4BUILTIN(name)                                        \
@@ -71,6 +76,10 @@ typedef lt_dlsymlist m4_export;
   void CONC(name, CONC(_LTX_, m4_finish_module))               \
        (m4 *context, lt_dlhandle handle, m4_obstack *obs)
 
+#define M4_MODULE_IMPORT(M, S)                                 \
+  CONC(S, _func) *S = (CONC(S, _func) *)                       \
+       m4_module_import (context, STR(M), STR(S), obs)
+
 #define M4ARG(i)       (argc > (i) ? m4_get_symbol_value_text (argv[i]) : "")
 
 extern boolean             m4_bad_argc       (m4 *, int, m4_symbol_value **,
@@ -143,12 +152,12 @@ m4_context_opt_bit_table
 typedef void m4_module_init_func   (m4 *, lt_dlhandle, m4_obstack*);
 typedef void m4_module_finish_func (m4 *, lt_dlhandle, m4_obstack*);
 
-extern lt_dlhandle  m4_module_load   (m4 *, const char*, m4_obstack*);
-extern void        m4_module_unload (m4 *, const char*, m4_obstack*);
+extern lt_dlhandle  m4_module_load     (m4 *, const char*, m4_obstack*);
+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         (lt_dlhandle);
-extern m4_builtin  *m4_get_module_builtin_table        (lt_dlhandle);
-extern m4_macro           *m4_get_module_macro_table   (lt_dlhandle);
+extern const char * m4_get_module_name (lt_dlhandle);
 
 
 
@@ -207,10 +216,9 @@ extern void                m4_set_symbol_value_func  (
 
 /* --- BUILTIN MANAGEMENT --- */
 
-extern const m4_builtin *m4_builtin_find_by_name (
-                               const m4_builtin *, const char *);
-extern const m4_builtin *m4_builtin_find_by_func (
-                               const m4_builtin *, m4_builtin_func *);
+extern const m4_builtin *m4_builtin_find_by_name (lt_dlhandle, const char *);
+extern const m4_builtin *m4_builtin_find_by_func (lt_dlhandle,
+                                                 m4_builtin_func *);
 
 
 
Index: m4/module.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/module.c,v
retrieving revision 1.26
diff -u -p -u -r1.26 module.c
--- m4/module.c 23 Jul 2003 16:20:50 -0000 1.26
+++ m4/module.c 12 Aug 2003 15:32:24 -0000
@@ -79,19 +79,14 @@
 
 #define MODULE_SELF_NAME       "!myself!"
 
-typedef struct {
-  m4_builtin    *builtin_table;
-  m4_macro     *macro_table;
-} module_data;
-
 static const char*  module_dlerror (void);
 static int         module_remove  (m4 *context, lt_dlhandle handle,
                                    m4_obstack *obs);
 static void        module_close   (m4 *context, lt_dlhandle handle,
                                    m4_obstack *obs);
 
-static void set_module_macro_table   (m4*, lt_dlhandle, const m4_macro*);
-static void set_module_builtin_table (m4*, lt_dlhandle, const m4_builtin*);
+static const m4_builtin * install_builtin_table (m4*, lt_dlhandle);
+static const m4_macro *   install_macro_table   (m4*, lt_dlhandle);
 
 static lt_dlcaller_id caller_id = 0;
 
@@ -107,93 +102,112 @@ m4_get_module_name (lt_dlhandle handle)
   return info ? info->name : 0;
 }
 
-m4_builtin *
-m4_get_module_builtin_table (lt_dlhandle handle)
+void *
+m4_module_import (m4 *context, const char *module_name,
+                 const char *symbol_name, m4_obstack *obs)
 {
-  module_data *data;
+  lt_dlhandle  handle          = lt_dlhandle_find (module_name);
+  lt_ptr       symbol_address  = 0;
 
-  assert (handle);
+  /* Try to load the module if it is not yet available (errors are
+     diagnosed by m4_module_load).  */
+  if (!handle)
+    handle = m4_module_load (context, module_name, obs);
 
-  data = lt_dlcaller_get_data (caller_id, handle);
+  if (handle)
+    {
+      symbol_address = lt_dlsym (handle, symbol_name);
 
-  return data ? data->builtin_table : 0;
+      if (!symbol_address)
+       M4ERROR ((m4_get_warning_status_opt (context), 0,
+                 _("Warning: cannot load symbol `%s' from module `%s'"),
+                   symbol_name, module_name));
+    }
+
+  return (void *) symbol_address;
 }
 
-static void
-set_module_builtin_table (m4 *context, lt_dlhandle handle,
-                         const m4_builtin *table)
+static const m4_builtin *
+install_builtin_table (m4 *context, lt_dlhandle handle)
 {
   const m4_builtin *bp;
 
   assert (context);
   assert (handle);
-  assert (table);
 
-  for (bp = table; bp->name != NULL; bp++)
+  bp = (const m4_builtin *) lt_dlsym (handle, BUILTIN_SYMBOL);
+  if (bp)
     {
-      m4_symbol_value *value = m4_symbol_value_create ();
-      char *   name;
-
-      m4_set_symbol_value_func (value, bp->func);
-      VALUE_HANDLE (value)     = handle;
-      VALUE_MIN_ARGS (value)   = bp->min_args;
-      VALUE_MAX_ARGS (value)   = bp->max_args;
-
-      if (bp->groks_macro_args)
-       BIT_SET (VALUE_FLAGS (value), VALUE_MACRO_ARGS_BIT);
-      if (bp->blind_if_no_args)
-       BIT_SET (VALUE_FLAGS (value), VALUE_BLIND_ARGS_BIT);
-
-      if (m4_get_prefix_builtins_opt (context))
+      for (; bp->name != NULL; bp++)
        {
-         static const char prefix[] = "m4_";
-         size_t len = strlen (prefix) + strlen (bp->name);
+         m4_symbol_value *value = m4_symbol_value_create ();
+         char *           name;
 
-         name = (char *) xmalloc (1+ len);
-         snprintf (name, 1+ len, "%s%s", prefix, bp->name);
-       }
-      else
-       name = (char *) bp->name;
+         m4_set_symbol_value_func (value, bp->func);
+         VALUE_HANDLE   (value)        = handle;
+         VALUE_MIN_ARGS (value)        = bp->min_args;
+         VALUE_MAX_ARGS (value)        = bp->max_args;
+
+         if (bp->groks_macro_args)
+           BIT_SET (VALUE_FLAGS (value), VALUE_MACRO_ARGS_BIT);
+         if (bp->blind_if_no_args)
+           BIT_SET (VALUE_FLAGS (value), VALUE_BLIND_ARGS_BIT);
 
+         if (m4_get_prefix_builtins_opt (context))
+           {
+             static const char prefix[] = "m4_";
+             size_t len = strlen (prefix) + strlen (bp->name);
 
-      m4_symbol_pushdef (M4SYMTAB, name, value);
+             name = (char *) xmalloc (1+ len);
+             snprintf (name, 1+ len, "%s%s", prefix, bp->name);
+           }
+         else
+           name = (char *) bp->name;
 
-      if (m4_get_prefix_builtins_opt (context))
-       xfree (name);
-    }
-}
+         m4_symbol_pushdef (M4SYMTAB, name, value);
 
-m4_macro *
-m4_get_module_macro_table (lt_dlhandle handle)
-{
-  module_data *data;
-
-  assert (handle);
+         if (m4_get_prefix_builtins_opt (context))
+           xfree (name);
+       }
 
-  data = lt_dlcaller_get_data (caller_id, handle);
+#ifdef DEBUG_MODULES
+      M4_DEBUG_MESSAGE1("module %s: builtins loaded",
+                       m4_get_module_name (handle));
+#endif /* DEBUG_MODULES */
+    }
 
-  return data ? data->macro_table : 0;
+  return bp;
 }
 
-static void
-set_module_macro_table (m4 *context, lt_dlhandle handle,
-                          const m4_macro *table)
+static const m4_macro *
+install_macro_table (m4 *context, lt_dlhandle handle)
 {
   const m4_macro *mp;
 
   assert (context);
   assert (handle);
-  assert (table);
 
-  for (mp = table; mp->name != NULL; mp++)
+  mp = (const m4_macro *) lt_dlsym (handle, MACRO_SYMBOL);
+
+  if (mp)
     {
-      m4_symbol_value *value = m4_symbol_value_create ();
+      for (; mp->name != NULL; mp++)
+       {
+         m4_symbol_value *value = m4_symbol_value_create ();
+
+         m4_set_symbol_value_text (value, xstrdup (mp->value));
+         VALUE_HANDLE (value) = handle;
 
-      m4_set_symbol_value_text (value, xstrdup (mp->value));
-      VALUE_HANDLE (value) = handle;
+         m4_symbol_pushdef (M4SYMTAB, mp->name, value);
+       }
 
-      m4_symbol_pushdef (M4SYMTAB, mp->name, value);
+#ifdef DEBUG_MODULES
+      M4_DEBUG_MESSAGE1("module %s: macros loaded",
+                       m4_get_module_name (handle));
+#endif /* DEBUG_MODULES */
     }
+
+  return mp;
 }
 
 lt_dlhandle
@@ -201,46 +215,26 @@ m4_module_load (m4 *context, const char 
 {
   const lt_dlhandle handle = m4__module_open (context, name, obs);
 
-  /* If name is not set we are getting a reflective handle, but we
-     might need to display an error message later so we set an appropriate
-     value here.  */
-  if (!name)
-    name = MODULE_SELF_NAME;
-
   if (handle)
     {
       const lt_dlinfo  *info   = lt_dlgetinfo (handle);
 
       if (!info)
        {
+         /* If name is not set we are getting a reflective handle, but we
+            need to display an error message so we set an appropriate
+            value here.  */
+         if (!name)
+           name = MODULE_SELF_NAME;
+
          M4ERROR ((m4_get_warning_status_opt (context), 0,
                    _("Warning: cannot load module `%s': %s"),
                    name, module_dlerror ()));
        }
       else if (info->ref_count == 1)
        {
-         const m4_builtin *builtin_table
-           = m4_get_module_builtin_table (handle);
-         const m4_macro   *macro_table
-           = m4_get_module_macro_table (handle);
-
-         /* Install the macro functions.  */
-         if (builtin_table)
-           {
-             set_module_builtin_table (context, handle, builtin_table);
-#ifdef DEBUG_MODULES
-             M4_DEBUG_MESSAGE1("module %s: builtins loaded", name);
-#endif /* DEBUG_MODULES */
-           }
-
-         /* Install the user macros. */
-         if (macro_table)
-           {
-             set_module_macro_table (context, handle, macro_table);
-#ifdef DEBUG_MODULES
-             M4_DEBUG_MESSAGE1("module %s: macros loaded", name);
-#endif /* DEBUG_MODULES */
-           }
+         install_builtin_table (context, handle);
+         install_macro_table (context, handle);
        }
     }
 
@@ -254,12 +248,10 @@ m4_module_unload (m4 *context, const cha
   lt_dlhandle  handle  = 0;
   int          errors  = 0;
 
-  /* Scan the list for the first module with a matching name.  */
-  while ((handle = lt_dlhandle_next (handle)))
-    {
-      if (name && (strcmp (name, m4_get_module_name (handle)) == 0))
-       break;
-    }
+  assert (context);
+
+  if (name)
+    handle = lt_dlhandle_find (name);
 
   if (!handle)
     {
@@ -358,22 +350,22 @@ lt_dlhandle
 m4__module_open (m4 *context, const char *name, m4_obstack *obs)
 {
   lt_dlhandle          handle          = lt_dlopenext (name);
-  m4_module_init_func  *init_func      = 0;
-  m4_builtin          *builtin_table           = 0;
-  m4_macro            *macro_table             = 0;
+  m4_module_init_func *        init_func       = 0;
+
+  assert (context);
+  assert (caller_id);
 
   if (handle)
     {
-#ifdef DEBUG_MODULES
       const lt_dlinfo *info = lt_dlgetinfo (handle);
-      M4_DEBUG_MESSAGE2("module %s: opening at %s", name, info->filename);
-#endif
 
-      /* Find the builtin table in the opened module. */
-      builtin_table = (m4_builtin *) lt_dlsym (handle, BUILTIN_SYMBOL);
+      /* If we have a handle, there must be handle info.  */
+      assert (info);
 
-      /* Find the macro table in the opened module. */
-      macro_table = (m4_macro *) lt_dlsym (handle, MACRO_SYMBOL);
+#ifdef DEBUG_MODULES
+      M4_DEBUG_MESSAGE2("module %s: opening at %s",
+                       name ? name : MODULE_SELF_NAME, info->filename);
+#endif
 
       /* Find and run any initialising function in the opened module,
         each time the module is opened.  */
@@ -386,6 +378,20 @@ m4__module_open (m4 *context, const char
          M4_DEBUG_MESSAGE1("module %s: init hook called", name);
 #endif /* DEBUG_MODULES */
        }
+
+      if (!init_func
+         && !lt_dlsym (handle, FINISH_SYMBOL)
+         && !lt_dlsym (handle, BUILTIN_SYMBOL)
+         && !lt_dlsym (handle, MACRO_SYMBOL))
+       {
+           M4ERROR ((EXIT_FAILURE, 0,
+                     _("module `%s' has no entry points"),
+                     name));
+       }
+
+#ifdef DEBUG_MODULES
+      M4_DEBUG_MESSAGE1("module %s: opened", name);
+#endif /* DEBUG_MODULES */
     }
   else
     {
@@ -395,48 +401,6 @@ m4__module_open (m4 *context, const char
                name, module_dlerror ()));
     }
 
-  if (!builtin_table && !macro_table && !init_func)
-    {
-      /* Since we don't use it here, only check for the finish hook
-        if we were about to diagnose a module with no entry points.  */
-      if (!lt_dlsym (handle, FINISH_SYMBOL))
-       M4ERROR ((EXIT_FAILURE, 0,
-                 _("module `%s' has no entry points"),
-                 name));
-    }
-
-  /* If the module was correctly opened and has the necessary
-     symbols, then store some client data for the new module
-     on the first open only.  */
-  if (handle)
-    {
-      const lt_dlinfo  *info   = lt_dlgetinfo (handle);
-
-      if (info && (info->ref_count == 1))
-       {
-         module_data *data     = XMALLOC (module_data, 1);
-         module_data *stale    = 0;
-
-         data->builtin_table   = builtin_table;
-         data->macro_table     = macro_table;
-
-         stale = lt_dlcaller_set_data (caller_id, handle, data);
-
-         if (stale)
-           {
-             xfree (stale);
-
-             M4ERROR ((m4_get_warning_status_opt (context), 0,
-                       _("Warning: overiding stale caller data in module 
`%s'"),
-                       name));
-           }
-
-#ifdef DEBUG_MODULES
-         M4_DEBUG_MESSAGE1("module %s: opened", name);
-#endif /* DEBUG_MODULES */
-       }
-    }
-
   return handle;
 }
 
@@ -451,15 +415,6 @@ m4__module_exit (m4 *context)
       lt_dlhandle      pending = handle;
       const lt_dlinfo *info    = lt_dlgetinfo (pending);
 
-      /* We are *really* shutting down here, so freeing the module
-        data is required.  */
-      if (info)
-       {
-         module_data *stale
-           = lt_dlcaller_set_data (caller_id, handle, 0);
-         XFREE (stale);
-       }
-
       /* If we are about to unload the final reference, move on to the
         next handle before we unload the current one.  */
       if (info->ref_count <= 1)
@@ -519,17 +474,6 @@ module_close (m4 *context, lt_dlhandle h
 
   if (!lt_dlisresident (handle))
     {
-      const lt_dlinfo  *info   = lt_dlgetinfo (handle);
-
-      /* When we are about to unload the module for the final
-        time, be sure to release any client data memory.  */
-      if (info && (info->ref_count == 1))
-       {
-         module_data *stale
-           = lt_dlcaller_set_data (caller_id, handle, 0);
-         XFREE (stale);
-       }
-
       errors = lt_dlclose (handle);
       if (!errors)
        {
Index: m4/path.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/path.c,v
retrieving revision 1.5
diff -u -p -u -r1.5 path.c
--- m4/path.c 29 Jul 2003 15:57:34 -0000 1.5
+++ m4/path.c 12 Aug 2003 15:32:26 -0000
@@ -169,7 +169,7 @@ m4_path_search (m4 *context, const char 
 #ifdef DEBUG_INCL
 
 static void
-include_dump (void)
+include_dump (m4 *context)
 {
   m4__search_path *incl;
 
Index: m4/symtab.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/symtab.c,v
retrieving revision 1.42
diff -u -p -u -r1.42 symtab.c
--- m4/symtab.c 24 Jul 2003 14:21:02 -0000 1.42
+++ m4/symtab.c 12 Aug 2003 15:32:26 -0000
@@ -524,8 +524,7 @@ static void *dump_symbol_CB (m4_symbol_t
        break;
 
       case M4_SYMBOL_FUNC:
-       bp = m4_builtin_find_by_func (m4_get_module_builtin_table (handle),
-                                     m4_get_symbol_func (symbol));
+       bp = m4_builtin_find_by_func (handle, m4_get_symbol_func (symbol));
        fprintf (stderr, "<%s>",
                 bp ? bp->name : "!ERROR!");
        break;
Index: modules/Makefile.am
===================================================================
RCS file: /cvsroot/m4/m4/modules/Makefile.am,v
retrieving revision 1.20
diff -u -p -u -r1.20 Makefile.am
--- modules/Makefile.am 24 Jul 2003 14:21:03 -0000 1.20
+++ modules/Makefile.am 12 Aug 2003 15:32:26 -0000
@@ -36,7 +36,7 @@ AM_LDFLAGS = -no-undefined
 pkgmodinc_HEADERS = m4.h
 pkglibexec_LTLIBRARIES = gnu.la load.la m4.la \
                          traditional.la perl.la \
-                         modtest.la shadow.la stdlib.la time.la
+                         modtest.la shadow.la import.la stdlib.la time.la
 
 if USE_GMP
 pkglibexec_LTLIBRARIES += mpeval.la
@@ -63,6 +63,9 @@ traditional_la_LDFLAGS = -module
 
 modtest_la_SOURCES = modtest.c
 modtest_la_LDFLAGS = -module
+
+import_la_SOURCES = import.c
+import_la_LDFLAGS = -module
 
 perl_la_SOURCES = perl.c
 perl_la_CFLAGS = `perl -MExtUtils::Embed -e ccopts`
Index: modules/gnu.c
===================================================================
RCS file: /cvsroot/m4/m4/modules/gnu.c,v
retrieving revision 1.29
diff -u -p -u -r1.29 gnu.c
--- modules/gnu.c 24 Jul 2003 14:21:03 -0000 1.29
+++ modules/gnu.c 12 Aug 2003 15:32:26 -0000
@@ -90,7 +90,7 @@ int errno;
 
 
 /* Generate prototypes for each builtin handler function. */
-#define BUILTIN(handler, macros,  blind, min, max)  M4BUILTIN(handler)
+#define BUILTIN(handler, macros, blind, min, max)  M4BUILTIN(handler)
   builtin_functions
 #undef BUILTIN
 
@@ -452,29 +452,30 @@ M4BUILTIN_HANDLER (epatsubst)
 /* Implementation of "symbols".  It builds up a table of pointers to
    symbols, sorts it and ships out the symbol names.  */
 
-/* TODO:  Import this through the m4_export list of m4 module.  */
-extern void m4_dump_symbols (m4 *context, m4_dump_symbol_data *data, int argc,
-                            m4_symbol_value **argv, boolean complain);
-
 /**
  * symbols([...])
  **/
 M4BUILTIN_HANDLER (symbols)
 {
-  m4_dump_symbol_data data;
-  m4_obstack data_obs;
-
-  obstack_init (&data_obs);
-  data.obs = &data_obs;
-  m4_dump_symbols (context, &data, argc, argv, FALSE);
+  M4_MODULE_IMPORT (m4, m4_dump_symbols);
 
-  for (; data.size > 0; --data.size, data.base++)
+  if (m4_dump_symbols)
     {
-      m4_shipout_string (context, obs, data.base[0], 0, TRUE);
-      if (data.size > 1)
-       obstack_1grow (obs, ',');
+      m4_dump_symbol_data data;
+      m4_obstack data_obs;
+
+      obstack_init (&data_obs);
+      data.obs = &data_obs;
+      m4_dump_symbols (context, &data, argc, argv, FALSE);
+
+      for (; data.size > 0; --data.size, data.base++)
+       {
+         m4_shipout_string (context, obs, data.base[0], 0, TRUE);
+         if (data.size > 1)
+           obstack_1grow (obs, ',');
+       }
+      obstack_free (&data_obs, NULL);
     }
-  obstack_free (&data_obs, NULL);
 }
 
 
@@ -506,28 +507,30 @@ M4BUILTIN_HANDLER (syncoutput)
  * esyscmd(SHELL-COMMAND)
  **/
 
-/* TODO:  Import these through the m4_export list of m4 module.  */
-extern int  m4_sysval;
-extern void m4_sysval_flush (m4 *);
-
 M4BUILTIN_HANDLER (esyscmd)
 {
-  FILE *pin;
-  int ch;
+  M4_MODULE_IMPORT (m4, m4_set_sysval);
+  M4_MODULE_IMPORT (m4, m4_sysval_flush);
 
-  m4_sysval_flush (context);
-  pin = popen (M4ARG (1), "r");
-  if (pin == NULL)
-    {
-      M4ERROR ((m4_get_warning_status_opt (context), errno,
-               _("Cannot open pipe to command `%s'"), M4ARG (1)));
-      m4_sysval = 0xff << 8;
-    }
-  else
+  if (m4_set_sysval && m4_sysval_flush)
     {
-      while ((ch = getc (pin)) != EOF)
-       obstack_1grow (obs, (char) ch);
-      m4_sysval = pclose (pin);
+      FILE *pin;
+      int ch;
+
+      m4_sysval_flush (context);
+      pin = popen (M4ARG (1), "r");
+      if (pin == NULL)
+       {
+         M4ERROR ((m4_get_warning_status_opt (context), errno,
+                   _("Cannot open pipe to command `%s'"), M4ARG (1)));
+         m4_set_sysval (0xff << 8);
+       }
+      else
+       {
+         while ((ch = getc (pin)) != EOF)
+           obstack_1grow (obs, (char) ch);
+         m4_set_sysval (pclose (pin));
+       }
     }
 }
 
Index: modules/import.c
===================================================================
RCS file: modules/import.c
diff -N modules/import.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ modules/import.c 12 Aug 2003 15:32:26 -0000
@@ -0,0 +1,102 @@
+/* GNU m4 -- A simple macro processor
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This program 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 2 of the License, or
+   (at your option) any later version.
+
+   This program 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307  USA
+*/
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <m4module.h>
+
+#include <assert.h>
+
+#define m4_builtin_table       import_LTX_m4_builtin_table
+
+/*             function        macros  blind minargs maxargs */
+#define builtin_functions                                      \
+       BUILTIN (import,        FALSE,  FALSE,  1,      2)      \
+       BUILTIN (symbol_fail,   FALSE,  FALSE,  1,      2)      \
+       BUILTIN (module_fail,   FALSE,  FALSE,  1,      2)
+
+#define BUILTIN(handler, macros,  blind, min, max) M4BUILTIN(handler)
+  builtin_functions
+#undef BUILTIN
+
+m4_builtin m4_builtin_table[] =
+{
+#define BUILTIN(handler, macros, blind, min, max)              \
+       { STR(handler), CONC(builtin_, handler), macros, blind, min, max },
+
+  builtin_functions
+#undef BUILTIN
+
+  { 0, 0, FALSE, FALSE, 0, 0 },
+};
+
+
+
+typedef boolean export_test_func (const char *);
+typedef boolean no_such_func (const char *);
+
+/**
+ * import()
+ **/
+M4BUILTIN_HANDLER (import)
+{
+  M4_MODULE_IMPORT (modtest, export_test);
+
+  const char *s = "`import'::`import' called.";
+
+  assert (obs != 0);
+  obstack_grow (obs, s, strlen(s));
+
+  if (export_test && export_test (M4ARG (1)))
+    fprintf (stderr, "TRUE\n");
+}
+
+/**
+ * symbol_fail()
+ **/
+M4BUILTIN_HANDLER (symbol_fail)
+{
+  M4_MODULE_IMPORT (modtest, no_such);
+
+  const char *s = "`import'::`symbol_fail' called.";
+
+  assert (obs != 0);
+  obstack_grow (obs, s, strlen(s));
+
+  if (no_such && no_such (M4ARG (1)))
+    fprintf (stderr, "TRUE\n");
+}
+
+/**
+ * module_fail()
+ **/
+M4BUILTIN_HANDLER (module_fail)
+{
+  M4_MODULE_IMPORT (no_such, no_such);
+
+  const char *s = "`import'::`module_fail' called.";
+
+  assert (obs != 0);
+  obstack_grow (obs, s, strlen(s));
+
+  if (no_such && no_such (M4ARG (1)))
+    fprintf (stderr, "TRUE\n");
+}
Index: modules/m4.c
===================================================================
RCS file: /cvsroot/m4/m4/modules/m4.c,v
retrieving revision 1.51
diff -u -p -u -r1.51 m4.c
--- modules/m4.c 24 Jul 2003 14:21:03 -0000 1.51
+++ modules/m4.c 12 Aug 2003 15:32:26 -0000
@@ -1,5 +1,5 @@
 /* GNU m4 -- A simple macro processor
-   Copyright 2000 Free Software Foundation, Inc.
+   Copyright 2000, 2002, 2003 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -49,20 +49,9 @@ extern int errno;
 #define m4_export_table                m4_LTX_m4_export_table
 #define m4_builtin_table       m4_LTX_m4_builtin_table
 
-/* Exit code from last "syscmd" command.  */
-int  m4_sysval = 0;
-
-void m4_sysval_flush (m4 *context);
-void m4_dump_symbols (m4 *context, m4_dump_symbol_data *data, int argc,
-                     m4_symbol_value **argv, boolean complain);
-
-m4_export m4_export_table[] = {
-  { "m4_sysval",               &m4_sysval },
-  { "m4_sysval_flush",         &m4_sysval_flush },
-  { "m4_dump_symbols",         &m4_dump_symbols },
-
-  { NULL,                      NULL }
-};
+#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
 
 /* Maintain each of the builtins implemented in this modules along
    with their details in a single table for easy maintenance.
@@ -422,6 +411,15 @@ M4BUILTIN_HANDLER (defn)
 
 /* This section contains macros to handle the builtins "syscmd"
    and "sysval".  */
+
+/* Exit code from last "syscmd" command.  */
+int  m4_sysval = 0;
+
+void
+m4_set_sysval (int value)
+{
+  m4_sysval = value;
+}
 
 void
 m4_sysval_flush (m4 *context)
Index: modules/m4.h
===================================================================
RCS file: /cvsroot/m4/m4/modules/m4.h,v
retrieving revision 1.1
diff -u -p -u -r1.1 m4.h
--- modules/m4.h 24 Jul 2003 14:21:03 -0000 1.1
+++ modules/m4.h 12 Aug 2003 15:32:26 -0000
@@ -33,6 +33,14 @@ typedef struct
   int size;                    /* size of table */
 } m4_dump_symbol_data;
 
+
+/* Types used to cast imported symbols to, so we get type checking
+   across the interface boundary.  */
+typedef void m4_sysval_flush_func (m4 *context);
+typedef void m4_set_sysval_func (int value);
+typedef void m4_dump_symbols_func (m4 *context, m4_dump_symbol_data *data,
+               int argc, m4_symbol_value **argv, boolean complain);
+
 END_C_DECLS
 
 #endif /* !MODULES_M4_H */
Index: modules/modtest.c
===================================================================
RCS file: /cvsroot/m4/m4/modules/modtest.c,v
retrieving revision 1.7
diff -u -p -u -r1.7 modtest.c
--- modules/modtest.c 12 Oct 2001 19:57:29 -0000 1.7
+++ modules/modtest.c 12 Aug 2003 15:32:26 -0000
@@ -1,5 +1,5 @@
 /* GNU m4 -- A simple macro processor
-   Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -28,6 +28,9 @@
 #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
+
+
 /*             function        macros  blind minargs maxargs */
 #define builtin_functions                                      \
        BUILTIN (test,          FALSE,  FALSE,  1,      1)
@@ -91,4 +94,16 @@ M4BUILTIN_HANDLER (test)
 
   assert (obs != 0);
   obstack_grow (obs, s, strlen(s));
+}
+
+
+/**
+ * export_test()
+ **/
+boolean
+export_test (const char *foo)
+{
+  if (foo)
+    fprintf (stderr, "%s\n", foo);
+  return (boolean) (foo != 0);
 }
Index: src/freeze.c
===================================================================
RCS file: /cvsroot/m4/m4/src/freeze.c,v
retrieving revision 1.33
diff -u -p -u -r1.33 freeze.c
--- src/freeze.c 17 Jul 2003 19:57:06 -0000 1.33
+++ src/freeze.c 12 Aug 2003 15:32:26 -0000
@@ -162,9 +162,8 @@ dump_symbol_CB (m4_symbol_table *symtab,
     }
   else if (m4_is_symbol_func (symbol))
     {
-      const m4_builtin *bp = m4_builtin_find_by_func
-               (m4_get_module_builtin_table (SYMBOL_HANDLE (symbol)),
-                m4_get_symbol_func (symbol));
+      const m4_builtin *bp = m4_builtin_find_by_func (SYMBOL_HANDLE (symbol),
+                                               m4_get_symbol_func (symbol));
 
       if (bp == NULL)
        return "INTERNAL ERROR: Builtin not found in builtin table!";
@@ -456,23 +455,13 @@ reload_frozen_state (m4 *context, const 
 
        /* Enter a macro having a builtin function as a definition.  */
        {
-         lt_dlhandle handle = 0;
-         m4_builtin *bt = NULL;
+         lt_dlhandle handle   = 0;
 
          if (number[2] > 0)
-           {
-             while ((handle = lt_dlhandle_next (handle)))
-               if (strcmp (m4_get_module_name (handle), string[2]) == 0)
-                 break;
-
-             if (handle)
-               {
-                 bt = m4_get_module_builtin_table (handle);
-               }
-           }
+           handle = lt_dlhandle_find (string[2]);
 
-         if (bt)
-           bp = m4_builtin_find_by_name (bt, string[1]);
+         if (handle)
+           bp = m4_builtin_find_by_name (handle, string[1]);
 
          if (bp)
            {
@@ -666,9 +655,7 @@ reload_frozen_state (m4 *context, const 
          lt_dlhandle handle = 0;
 
          if (number[2] > 0)
-           while ((handle = lt_dlhandle_next (handle)))
-             if (strcmp (m4_get_module_name (handle), string[2]) == 0)
-               break;
+           handle = lt_dlhandle_find (string[2]);
 
          m4_set_symbol_value_text (token, xstrdup (string[1]));
          VALUE_HANDLE (token)          = handle;
Index: tests/modules.at
===================================================================
RCS file: /cvsroot/m4/m4/tests/modules.at,v
retrieving revision 1.6
diff -u -p -u -r1.6 modules.at
--- tests/modules.at 11 Oct 2001 21:09:16 -0000 1.6
+++ tests/modules.at 12 Aug 2003 15:32:26 -0000
@@ -333,6 +333,52 @@ AT_CHECK_M4([-m load input.m4], 0, expou
 AT_CLEANUP
 
 
+
+## ----------------------- ##
+## module symbol importing ##
+## ----------------------- ##
+
+# Importing a symbol from a not yet loaded module
+
+AT_SETUP([modules: importing])
+
+AT_DATA([[input.m4]],
+[[import
+load(`import')
+import
+unload(`modtest')
+import
+symbol_fail
+module_fail
+]])
+
+AT_DATA([[expout]],
+[[import
+
+import::import called.
+
+import::import called.
+import::symbol_fail called.
+]])
+
+AT_DATA([[experr]],
+[[Test module loaded.
+
+TRUE
+Test module unloaded.
+Test module loaded.
+
+TRUE
+m4: input.m4: 6: Warning: cannot load symbol `no_such' from module `modtest'
+m4: input.m4: 7: cannot open module `no_such': no_such.so: cannot open shared 
object file: No such file or directory
+]])
+
+AT_CHECK_M4([-m load input.m4], 1, expout, experr)
+
+AT_CLEANUP
+
+
+
 ## -------------------- ##
 ## trace module symbols ##
 ## -------------------- ##

reply via email to

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