Rework the implementation of load.c to increase portability.
authorPaul Smith <psmith@gnu.org>
Sat, 27 Apr 2013 20:57:05 +0000 (16:57 -0400)
committerPaul Smith <psmith@gnu.org>
Sat, 27 Apr 2013 20:57:05 +0000 (16:57 -0400)
It should be sufficient, now, to write a new version of the load_object()
function.  That function won't be called unless we really want to load, so all
checking and parsing is taken care of before that.

ChangeLog
load.c

index bf91028..57528a9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2013-04-27  Paul Smith  <psmith@gnu.org>
+
+       * load.c (load_object): Extract all POSIX-isms into a separate
+       function for portability.
+       (load_file): Check the .LOADED variable first and don't invoke
+       load_object() if it's already been loaded.
+
 2013-04-27  Eli Zaretskii  <eliz@gnu.org>
 
        * read.c (record_files): Pay attention to .ONESHELL in MS-Windows.
diff --git a/load.c b/load.c
index 081d66f..95529c2 100644 (file)
--- a/load.c
+++ b/load.c
@@ -26,53 +26,68 @@ this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #define SYMBOL_EXTENSION        "_gmk_setup"
 
-static void *global_dl = NULL;
-
 #include "debug.h"
 #include "filedef.h"
 #include "variable.h"
 
-static int
-init_symbol (const gmk_floc *flocp, const char *ldname, load_func_t symp)
+static load_func_t
+load_object (const gmk_floc *flocp, int noerror,
+             const char *ldname, const char *symname)
 {
-  int r;
-  const char *p;
-  int nmlen = strlen (ldname);
-  char *loaded = allocated_variable_expand("$(.LOADED)");
+  static void *global_dl = NULL;
+  load_func_t symp;
 
-  /* If it's already been loaded don't do it again.  */
-  p = strstr (loaded, ldname);
-  r = p && (p==loaded || p[-1]==' ') && (p[nmlen]=='\0' || p[nmlen]==' ');
-  free (loaded);
-  if (r)
-    return 1;
+  if (! global_dl)
+    {
+      global_dl = dlopen (NULL, RTLD_NOW|RTLD_GLOBAL);
+      if (! global_dl)
+        fatal (flocp, _("Failed to open global symbol table: %s"), dlerror());
+    }
 
-  /* Now invoke the symbol.  */
-  r = (*symp) (flocp);
+  symp = (load_func_t) dlsym (global_dl, symname);
+  if (! symp) {
+    void *dlp = NULL;
 
-  /* If it succeeded, add the symbol to the loaded variable.  */
-  if (r > 0)
-    do_variable_definition (flocp, ".LOADED", ldname, o_default, f_append, 0);
+    /* If the path has no "/", try the current directory first.  */
+    if (! strchr (ldname, '/'))
+      dlp = dlopen (concat (2, "./", ldname), RTLD_LAZY|RTLD_GLOBAL);
 
-  return r;
+    /* If we haven't opened it yet, try the default search path.  */
+    if (! dlp)
+      dlp = dlopen (ldname, RTLD_LAZY|RTLD_GLOBAL);
+
+    /* Still no?  Then fail.  */
+    if (! dlp)
+      {
+        if (noerror)
+          DB (DB_BASIC, ("%s", dlerror()));
+        else
+          error (flocp, "%s", dlerror());
+        return NULL;
+      }
+
+    symp = dlsym (dlp, symname);
+    if (! symp)
+      fatal (flocp, _("Failed to load symbol %s from %s: %s"),
+             symname, ldname, dlerror());
+  }
+
+  return symp;
 }
 
 int
 load_file (const gmk_floc *flocp, const char **ldname, int noerror)
 {
-  load_func_t symp;
-  const char *fp;
+  int nmlen = strlen (*ldname);
+  char *new = alloca (nmlen + CSTRLEN (SYMBOL_EXTENSION) + 1);
   char *symname = NULL;
-  char *new = alloca (strlen (*ldname) + CSTRLEN (SYMBOL_EXTENSION) + 1);
-
-  if (! global_dl)
-    {
-      global_dl = dlopen (NULL, RTLD_NOW|RTLD_GLOBAL);
-      if (! global_dl)
-        fatal (flocp, _("Failed to open global symbol table: %s"), dlerror());
-    }
+  char *loaded;
+  const char *fp;
+  int r;
+  load_func_t symp;
 
-  /* If a symbol name was provided, use it.  */
+  /* Break the input into an object file name and a symbol name.  If no symbol
+     name was provided, compute one from the object file name.  */
   fp = strchr (*ldname, '(');
   if (fp)
     {
@@ -105,6 +120,14 @@ load_file (const gmk_floc *flocp, const char **ldname, int noerror)
   /* Add this name to the string cache so it can be reused later.  */
   *ldname = strcache_add (*ldname);
 
+  /* If this object has been loaded, we're done.  */
+  loaded = allocated_variable_expand("$(.LOADED)");
+  fp = strstr (loaded, *ldname);
+  r = fp && (fp==loaded || fp[-1]==' ') && (fp[nmlen]=='\0' || fp[nmlen]==' ');
+  free (loaded);
+  if (r)
+    return 1;
+
   /* If we didn't find a symbol name yet, construct it from the ldname.  */
   if (! symname)
     {
@@ -123,37 +146,19 @@ load_file (const gmk_floc *flocp, const char **ldname, int noerror)
 
   DB (DB_VERBOSE, (_("Loading symbol %s from %s\n"), symname, *ldname));
 
-  /* See if it's already defined.  */
-  symp = (load_func_t) dlsym (global_dl, symname);
-  if (! symp) {
-    void *dlp = NULL;
-
-    /* If the path has no "/", try the current directory first.  */
-    if (! strchr (*ldname, '/'))
-      dlp = dlopen (concat (2, "./", *ldname), RTLD_LAZY|RTLD_GLOBAL);
+  /* Load it!  */
+  symp = load_object(flocp, noerror, *ldname, symname);
+  if (! symp)
+    return 0;
 
-    /* If we haven't opened it yet, try the default search path.  */
-    if (! dlp)
-      dlp = dlopen (*ldname, RTLD_LAZY|RTLD_GLOBAL);
-
-    /* Still no?  Then fail.  */
-    if (! dlp)
-      {
-        if (noerror)
-          DB (DB_BASIC, ("%s", dlerror()));
-        else
-          error (flocp, "%s", dlerror());
-        return 0;
-      }
+  /* Invoke the symbol.  */
+  r = (*symp) (flocp);
 
-    symp = dlsym (dlp, symname);
-    if (! symp)
-      fatal (flocp, _("Failed to load symbol %s from %s: %s"),
-             symname, *ldname, dlerror());
-  }
+  /* If it succeeded, add the load file to the loaded variable.  */
+  if (r > 0)
+    do_variable_definition (flocp, ".LOADED", *ldname, o_default, f_append, 0);
 
-  /* Invoke the symbol to initialize the loaded object.  */
-  return init_symbol(flocp, *ldname, symp);
+  return r;
 }
 
 #else