diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | load.c | 123 |
2 files changed, 71 insertions, 59 deletions
@@ -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. @@ -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 |