m4-commit
[Top][All Lists]
Advanced

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

Changes to m4/m4/module.c,v


From: Eric Blake
Subject: Changes to m4/m4/module.c,v
Date: Thu, 06 Sep 2007 22:58:28 +0000

CVSROOT:        /sources/m4
Module name:    m4
Changes by:     Eric Blake <ericb>      07/09/06 22:58:27

Index: m4/module.c
===================================================================
RCS file: /sources/m4/m4/m4/module.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -b -r1.52 -r1.53
--- m4/module.c 7 Aug 2007 03:15:27 -0000       1.52
+++ m4/module.c 6 Sep 2007 22:58:26 -0000       1.53
@@ -82,13 +82,13 @@
 #define MODULE_SELF_NAME       "!myself!"
 
 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,
+static int         module_remove  (m4 *context, m4_module *handle,
                                    m4_obstack *obs);
+//static void      module_close   (m4 *context, m4_module *handle,
+//                                 m4_obstack *obs);
 
-static const m4_builtin * install_builtin_table (m4*, lt_dlhandle);
-static const m4_macro *   install_macro_table   (m4*, lt_dlhandle);
+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);
@@ -96,13 +96,13 @@
 static lt_dlinterface_id iface_id = NULL;
 
 const char *
-m4_get_module_name (lt_dlhandle handle)
+m4_get_module_name (const m4_module *m4_handle)
 {
   const lt_dlinfo *info;
 
-  assert (handle);
+  assert (m4_handle && m4_handle->handle);
 
-  info = lt_dlgetinfo (handle);
+  info = lt_dlgetinfo (m4_handle->handle);
 
   return info ? info->name : 0;
 }
@@ -111,35 +111,37 @@
 m4_module_import (m4 *context, const char *module_name,
                  const char *symbol_name, m4_obstack *obs)
 {
-  lt_dlhandle  handle          = m4__module_find (module_name);
-  lt_ptr       symbol_address  = NULL;
+  m4_module *  handle          = m4__module_find (module_name);
+  void *       symbol_address  = NULL;
 
   /* Try to load the module if it is not yet available (errors are
      diagnosed by m4_module_load).  */
+  /* FIXME - should this use m4__module_open instead, to avoid
+     polluting the symbol table when importing a function?  */
   if (!handle)
     handle = m4_module_load (context, module_name, obs);
 
   if (handle)
     {
-      symbol_address = lt_dlsym (handle, symbol_name);
+      symbol_address = lt_dlsym (handle->handle, symbol_name);
 
       if (!symbol_address)
        m4_error (context, 0, 0, _("cannot load symbol `%s' from module `%s'"),
                  symbol_name, module_name);
     }
 
-  return (void *) symbol_address;
+  return symbol_address;
 }
 
-static const m4_builtin *
-install_builtin_table (m4 *context, lt_dlhandle handle)
+static void
+install_builtin_table (m4 *context, m4_module *handle)
 {
   const m4_builtin *bp;
 
   assert (context);
   assert (handle);
 
-  bp = (m4_builtin *) lt_dlsym (handle, BUILTIN_SYMBOL);
+  bp = (m4_builtin *) lt_dlsym (handle->handle, BUILTIN_SYMBOL);
   if (bp)
     {
       for (; bp->name != NULL; bp++)
@@ -175,19 +177,17 @@
                        _("module %s: builtins loaded"),
                        m4_get_module_name (handle));
     }
-
-  return bp;
 }
 
-static const m4_macro *
-install_macro_table (m4 *context, lt_dlhandle handle)
+static void
+install_macro_table (m4 *context, m4_module *handle)
 {
   const m4_macro *mp;
 
   assert (context);
   assert (handle);
 
-  mp = (const m4_macro *) lt_dlsym (handle, MACRO_SYMBOL);
+  mp = (const m4_macro *) lt_dlsym (handle->handle, MACRO_SYMBOL);
 
   if (mp)
     {
@@ -205,18 +205,16 @@
                        _("module %s: macros loaded"),
                        m4_get_module_name (handle));
     }
-
-  return mp;
 }
 
-lt_dlhandle
+m4_module *
 m4_module_load (m4 *context, const char *name, m4_obstack *obs)
 {
-  const lt_dlhandle handle = m4__module_open (context, name, obs);
+  m4_module *handle = m4__module_open (context, name, obs);
 
   if (handle)
     {
-      const lt_dlinfo  *info   = lt_dlgetinfo (handle);
+      const lt_dlinfo  *info   = lt_dlgetinfo (handle->handle);
 
       if (!info)
        {
@@ -239,11 +237,36 @@
   return handle;
 }
 
+/* Make the module HANDLE resident.  Return NULL on success, or a
+   pre-translated error string on failure.  */
+const char *
+m4_module_makeresident (m4_module *m4_handle)
+{
+  assert (m4_handle);
+  return lt_dlmakeresident (m4_handle->handle) ? module_dlerror () : NULL;
+}
+
+/* Return the current refcount, or times that module HANDLE has been
+   opened.  */
+int
+m4_module_refcount (const m4_module *handle)
+{
+  /* FIXME - we should track refcounts in struct m4_module, since it
+     is conceivable that the m4 load refcount could be different than
+     the libltdl refcount, if a single module can be loaded both by
+     m4_module_load and as a dependent of some other module.  */
+  const lt_dlinfo *info;
+  assert (handle);
+  info = lt_dlgetinfo (handle->handle);
+  assert (info);
+  return info->ref_count;
+}
+
 /* Unload a module.  */
 void
 m4_module_unload (m4 *context, const char *name, m4_obstack *obs)
 {
-  lt_dlhandle  handle  = NULL;
+  m4_module *  handle  = NULL;
   int          errors  = 0;
 
   assert (context);
@@ -284,22 +307,53 @@
 
 /* Return successive loaded modules that pass the interface test registered
    with the interface id.  */
-lt_dlhandle
-m4__module_next (lt_dlhandle handle)
+m4_module *
+m4__module_next (m4_module *m4_handle)
 {
+  lt_dlhandle handle = m4_handle ? m4_handle->handle : NULL;
   assert (iface_id);
 
-  return lt_dlhandle_iterate (iface_id, handle);
+  /* 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;
+      m4_handle = (m4_module *) lt_dlcaller_get_data (iface_id, handle);
+      if (m4_handle)
+       assert (m4_handle->handle == handle);
+      else
+       {
+         assert (lt_dlisresident (handle));
+         assert (lt_dlgetinfo (handle)->ref_count <= 1);
+       }
+    }
+  while (!m4_handle);
+  return m4_handle;
 }
 
 /* Return the first loaded module that passes the registered interface test
    and is called NAME.  */
-lt_dlhandle
+m4_module *
 m4__module_find (const char *name)
 {
+  lt_dlhandle handle;
+  m4_module *m4_handle;
   assert (iface_id);
 
-  return lt_dlhandle_fetch (iface_id, name);
+  handle = lt_dlhandle_fetch (iface_id, name);
+  if (!handle)
+    return NULL;
+  m4_handle = (m4_module *) lt_dlcaller_get_data (iface_id, handle);
+  if (m4_handle)
+    assert (m4_handle->handle == handle);
+  else
+    {
+      assert (lt_dlisresident (handle));
+      assert (lt_dlgetinfo (handle)->ref_count <= 1);
+    }
+  return m4_handle;
 }
 
 
@@ -369,10 +423,11 @@
 /* Load a module.  NAME can be a absolute file name or, if relative,
    it is searched for in the module path.  The module is unloaded in
    case of error.  */
-lt_dlhandle
+m4_module *
 m4__module_open (m4 *context, const char *name, m4_obstack *obs)
 {
   lt_dlhandle          handle          = lt_dlopenext (name);
+  m4_module *          m4_handle       = NULL;
   m4_module_init_func *        init_func       = NULL;
 
   assert (context);
@@ -389,19 +444,41 @@
                        _("module %s: opening file `%s'"),
                        name ? name : MODULE_SELF_NAME, info->filename);
 
+      /* Provide the m4_module correpsonding to the lt_dlhandle, if
+        not yet created.  */
+      m4_handle = (m4_module *) lt_dlcaller_get_data (iface_id, handle);
+      if (!m4_handle)
+       {
+         void *old;
+         const char *err;
+
+         assert (info->ref_count == 1);
+         m4_handle = (m4_module *) xzalloc (sizeof *m4_handle);
+         m4_handle->handle = handle;
+
+         /* clear out any stale errors, since we have to use
+            lt_dlerror to distinguish between success and
+            failure.  */
+         lt_dlerror ();
+         old = lt_dlcaller_set_data (iface_id, handle, m4_handle);
+         assert (!old);
+         err = lt_dlerror ();
+         if (err)
+           m4_error (context, EXIT_FAILURE, 0,
+                     _("unable to load module `%s': %s"), name, err);
+       }
+
       /* Find and run any initializing function in the opened module,
         each time the module is opened.  */
       init_func = (m4_module_init_func *) lt_dlsym (handle, INIT_SYMBOL);
       if (init_func)
        {
-         (*init_func) (context, handle, obs);
+         init_func (context, m4_handle, obs);
 
          m4_debug_message (context, M4_DEBUG_TRACE_MODULE,
                            _("module %s: init hook called"), name);
        }
-
-      if (!init_func
-         && !lt_dlsym (handle, FINISH_SYMBOL)
+      else if (!lt_dlsym (handle, FINISH_SYMBOL)
          && !lt_dlsym (handle, BUILTIN_SYMBOL)
          && !lt_dlsym (handle, MACRO_SYMBOL))
        {
@@ -419,19 +496,19 @@
                name, module_dlerror ());
     }
 
-  return handle;
+  return m4_handle;
 }
 
 void
 m4__module_exit (m4 *context)
 {
-  lt_dlhandle  handle  = m4__module_next (0);
+  m4_module *  handle  = m4__module_next (NULL);
   int          errors  = 0;
 
   while (handle && !errors)
     {
-      const lt_dlinfo *info    = lt_dlgetinfo (handle);
-      lt_dlhandle      pending = handle;
+      const lt_dlinfo *info    = lt_dlgetinfo (handle->handle);
+      m4_module *      pending = handle;
 
       /* If we are about to unload the final reference, move on to the
         next handle before we unload the current one.  */
@@ -457,6 +534,7 @@
 
 
 
+/* FIXME - libtool doesn't expose lt_dlerror strings for translation.  */
 static const char *
 module_dlerror (void)
 {
@@ -468,66 +546,30 @@
   return dlerror;
 }
 
-static void
-module_close (m4 *context, lt_dlhandle handle, m4_obstack *obs)
-{
-  m4_module_finish_func *finish_func;
-  const char           *name;
-  int                   errors         = 0;
-
-  assert (handle);
-
-  /* Be careful when closing myself.  */
-  name = m4_get_module_name (handle);
-  name = xstrdup (name ? name : MODULE_SELF_NAME);
-
-  /* Run any finishing function for the opened module. */
-  finish_func = (m4_module_finish_func *) lt_dlsym (handle, FINISH_SYMBOL);
-
-  if (finish_func)
-    {
-      (*finish_func) (context, handle, obs);
-
-      m4_debug_message (context, M4_DEBUG_TRACE_MODULE,
-                       _("module %s: finish hook called"), name);
-    }
-
-  if (!lt_dlisresident (handle))
-    {
-      errors = lt_dlclose (handle);
-      if (!errors)
-       {
-         m4_debug_message (context, M4_DEBUG_TRACE_MODULE,
-                           _("module %s: closed"), name);
-       }
-    }
-  else
-    m4_debug_message (context, M4_DEBUG_TRACE_MODULE,
-                     _("module %s: resident module not closed"), name);
-
-  if (errors)
-    {
-      m4_error (context, EXIT_FAILURE, 0, _("cannot close module `%s': %s"),
-               name, module_dlerror ());
-    }
-
-  DELETE (name);
-}
-
+/* Close one reference to the module M4_HANDLE, and output to OBS any
+   information from the finish hook of the module.  If no references
+   to M4_HANDLE remain, also remove all symbols and other memory
+   associated with the module.  */
 static int
-module_remove (m4 *context, lt_dlhandle handle, m4_obstack *obs)
+module_remove (m4 *context, m4_module *m4_handle, m4_obstack *obs)
 {
-  const lt_dlinfo *info;
+  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 (handle);
+  assert (m4_handle && m4_handle->handle);
 
   /* Be careful when closing myself.  */
-  name = m4_get_module_name (handle);
+  handle = m4_handle->handle;
+  name = m4_get_module_name (m4_handle);
   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. */
@@ -535,7 +577,7 @@
   if (info->ref_count > 1)
     {
       fprintf (stderr, "module %s: now has %d references.",
-              name, info->ref_count -1);
+              name, info->ref_count - 1);
     }
 #endif /* DEBUG_MODULES */
 
@@ -545,14 +587,58 @@
         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, handle);
+      m4__symtab_remove_module_references (M4SYMTAB, m4_handle);
 
       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, m4_handle, 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,
+                 _("unable to close module `%s': %s"), name,
+                 module_dlerror());
+      assert (old == m4_handle);
+      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)
-    module_close (context, handle, obs);
+       {
+         m4_debug_message (context, M4_DEBUG_TRACE_MODULE,
+                           _("module %s: closed"), name);
+       }
+    }
+
+  if (errors)
+    m4_error (context, EXIT_FAILURE, 0, _("cannot close module `%s': %s"),
+             name, module_dlerror ());
+  if (last_reference)
+    free (m4_handle);
 
   DELETE (name);
 




reply via email to

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