+2000-02-02 Gary V. Vaughan <gary@oranda.demon.co.uk>
+
+ * NEWS: updated.
+ * doc/libtool.texi (Libltdl interface): Moved user defined module
+ loader documentation from here...
+ (Module loaders for libltdl) ...to here, and updated the text and
+ added examples.
+ * ltdl.m4 (AC_CHECK_FUNCS): check strcmp for lt_find_dlloader.
+ * libltdl/ltdl.h: Reformatted and commented for readability.
+ (struct lt_user_dlloader): New data type for passing
+ initialisation pointers to lt_add_dlloader.
+ (LTDL_ERROR_INVALID_LOADER): New error message when non loader
+ handles are passed to the user loader API.
+ (LTDL_ERROR_INIT_LOADER): New error when loader initialisation
+ fails.
+ (LTDL_ERROR_REMOVE_LOADER): New error when loader removal fails.
+ (lt_module_open_t): renamed from lt_lib_open_t.
+ (lt_module_close_t): renamed from lt_lib_close_t.
+ (lt_dlloader_exit_t): renamed from lt_dlloader_exit_t.
+ * libltdl/ltdl.c: Reordered builtin loaders so that the "dld"
+ loader no longer occurs before "dlopen" on some platforms and
+ after it on others.
+ (lt_dlloader_t): Moved here from ltdl.h, added a field,
+ "loader_name", for identifying the loader, and renamed from
+ lt_dltype_t. Renamed type variables to loader IFF of type
+ lt_dlloader_t.
+ (lt_module_t): Renamed from lt_syshandle. Renamed handle variables
+ to module IFF of type lt_module_t.
+ (LTDL_TYPE_TOP): Deleted. No longer required.
+ (sys_dl): Initialised as a struct lt_user_dlloader.
+ (sys_dl_init): Deleted. No longer required.
+ (sys_dl_exit): Ditto.
+ (sys_shl): Initialised as a struct lt_user_dlloader.
+ (sys_shl_init): Deleted. No longer required.
+ (sys_shl_exit): Ditto.
+ (sys_wll): Initialised as a struct lt_user_dlloader.
+ (sys_wll_init): Deleted. No longer required.
+ (sys_wll_exit): Ditto.
+ (sys_bedl): Initialised as a struct lt_user_dlloader.
+ (sys_bedl_init): Deleted. No longer required.
+ (sys_bedl_exit): Ditto.
+ (sys_dld): Initialised as a struct lt_user_dlloader.
+ (sys_dld_init): Deleted. No longer required.
+ (sys_dld_exit): Ditto.
+ (sys_presym): Initialised as a struct lt_user_dlloader.
+ (lt_mod_init_t): Moved to here from ltdl.h.
+ (lt_dlinit): Add builtin loaders using the user loader API.
+ (lt_dlexit): Unregister and free all loaders.
+ (lt_add_dlloader): New function to add a new module loader after the
+ loader specified in the argument.
+ (lt_remove_dlloader): New function to remove a module loader.
+ (lt_next_dlloader): New function for iterating over module loaders.
+ (lt_dlloader_name): Accessor function for name of dlloader.
+ (lt_find_dlloader): New function to get a reference to a registered
+ module loader.
+ (strcmp): static implementation incase the host has none.
+ (lt_dlgettypes, lt_dlsettypes): Removed.
+
2000-02-02 Thomas Tanner <tanner@ffii.org>
* libltdl/ltdl.c: replace NULL with 0, remove unused system
(lt_dlsettypes): New function to replace the list of ltdl dynamic
loader types entirely -- e.g. to prepend a new type to the
existing list.
- (sys_dl_open, sys_dl_close, sys_dl_sym): Work with lt_syshandle..
+ (sys_dl_open, sys_dl_close, sys_dl_sym): Work with lt_syshandle.
(sys_shl_open, sys_shl_close, sys_shl_sym): ditto.
(sys_dld_open, sys_dld_close, sys_dld_sym): ditto.
(sys_wll_open, sys_wll_close, sys_wll_sym): ditto.
* Libtool now allows you to link shared libraries against static code.
* New functions lt_dlgetdata, lt_dlsetdata, lt_dlgetinfo, lt_dlforeach
in libltdl can be used to store application specific data in handles.
-* New functions lt_dladdtype, lt_dlgettypes, lt_dlsettypes in libltdl
- can be used for adding new types of module loading.
+* New functions lt_next_dlloader, lt_dlloader_name, lt_find_dlloader,
+ lt_add_dlloader in libltdl can be used for adding new types of module
+ loader to libltdl..
* New functions lt_dladderror, lt_dlseterror in libltdl can be used to
integrate user module loaders with lt_dlerror.
* "-Xcompiler" and "-Wc," does now work in compile mode, too.
* Libltdl interface:: How to use libltdl in your programs.
* Modules for libltdl:: Creating modules that can be @code{dlopen}ed.
* Distributing libltdl:: How to distribute libltdl with your package.
+* Module loaders for libltdl:: Creating user defined module loaders.
Using libtool with other languages
* Libltdl interface:: How to use libltdl in your programs.
* Modules for libltdl:: Creating modules that can be @code{dlopen}ed.
* Distributing libltdl:: How to distribute libltdl with your package.
+* Module loaders for libltdl:: Creating user defined module loaders.
@end menu
@node Libltdl interface
Every lt_dlopened module has a handle associated with it.
@end deftp
-@deftp {Type} lt_syshandle
-@code{lt_syshandle} is a generic system module "handle".
-The dynamic module loader type extensions communicate using these low level
-handles.
-@end deftp
-
@deftypefn {Type} {struct} lt_dlinfo @{ @w{char *@var{filename};} @w{char *@var{name};} @w{int @var{ref_count};} @}
@code{lt_dlinfo} is used to store information about a module.
The @var{filename} attribute is a null-terminated character string of the
the same module is currently loaded.
@end deftypefn
-@deftypefn {Type} {struct} lt_dltype_t @{ @w{struct lt_dltype_t *@var{next};} @w{const char *@var{sym_prefix};} @w{lt_mod_init_t *@var{mod_init};} @w{lt_mod_exit_t *@var{mod_exit};} @w{lt_lib_open_t *@var{lib_open};} @w{lt_lib_close_t *@var{lib_close};} @w{lt_find_sym_t *@var{find_sym};} @}
-@code{lt_dltype_t} is used to store the functions used to access a dynamic
-module loader type. If you want to define a new way to open dynamic modules,
-and have the @code{lt_dlopen} @sc{api} use it, you need to instantiate one of
-these structures and pass it to @code{lt_dladdtype()}.
-@end deftypefn
-
-@deftypefn {Type} int lt_mod_init_t (void)
-The type of an initialisation function for an @code{lt_dltype_t} module
-loader. Implementation of such a function should perform any initialisation
-required by the loader, and return non-zero if an error is encountered. When
-used as part of an @code{lt_dltype_t} registration, if non-NULL, the function
-will be called by @code{lt_dlinit}, or if it is registered after the call to
-@code{lt_dlinit}, the function will be called immediately upon registration.
-@end deftypefn
-
-@deftypefn {Type} int lt_mod_exit_t (void)
-The type of the finalisation function for an @code{lt_dltype_t} module
-loader. Implementation of such a function should free any resources
-associated with the loader. If non-NULL, the function will be called by
-@code{lt_dlexit}.
-@end deftypefn
-
-@deftypefn {Type} lt_syshandle lt_lib_open_t (@w{const char *@var{filename}})
-The type of the loader function for an @code{lt_dltype_t} module loader.
-Implementation of such a function should attempt to load the named module, and
-return an @code{lt_syshandle} suitable for passing in to the associated
-@code{lt_lib_close_t} and @code{lt_sym_find_t} function pointers. If the
-function fails it should return NULL.
-@end deftypefn
-
-@deftypefn {Type} int lt_lib_close_t (@w{lt_syshandle @var{handle}})
-The type of the unloader function for an @code{lt_dltype_t} module loader.
-Implementatation of such a function should attempt to release any resources
-tied up by the @var{handle} module, and then unload it from memory. If the
-function fails for some reason, return non-zero.
-@end deftypefn
-
-@deftypefn {Type} lt_ptr_t lt_find_sym_t (@w{lt_syshandle @var{handle},} @w{const char *@var{symbol}})
-The type of the symbol lookup function for an @code{lt_dltype_t} module
-loader. Implementation of such a function should return the address of the
-named @var{symbol} in the module @var{handle}, or NULL if there is no such
-symbol.
-@end deftypefn
-
@deftp {Type} lt_dlsymlist
@code{lt_dlsymlist} is a symbol list for dlpreopened modules.
This structure is described in @pxref{Dlpreopening}.
Return 0 on success, otherwise the number of errors.
@end deftypefun
-@deftypefun int lt_dladdtype (@w{lt_dltype_t *@var{dltype}})
-Append a new module loader type to the list of all types.
-@var{dltype} should have its @code{next} field set to NULL. If the
-@code{sym_prefix} field is set to NULL, then it will be replaced with a single
-underscore if that is what the platform requires normally (use the empty
-string if you want an unconditional empty prefix). The new type will be added
-to the end of the module loader types list, and hence will be used only if all
-of the preceding methods fail.
-
-If this function is used to add a type after calling @code{lt_dlinit}, then
-the @var{mod_init} function (if any) will be called immediately, otherwise
-it will be called at the same time as the other type initialisation function
-by @code{lt_dlinit}.
-@end deftypefun
-
-@deftypefun lt_dltype_t *lt_dlgettypes (void)
-Return the list of module loader types.
-@end deftypefun
-
-@deftypefun int lt_dlsettypes (@w{lt_dltype_t *@var{dltypes}})
-Change the list of module loader types to be @var{dltypes}.
-This completely replaces the default module loader types determined by libtool
-with the new linked list of types -- which should probably be a superset of
-the original list.
-@end deftypefun
-
@deftypefun int lt_dlexit (void)
Shut down libltdl and close all modules.
This function will only then shut down libltdl when it was called as
or since it was last called.
@end deftypefun
-@deftypefun int lt_dladderror (@w{const char *@var{diagnostic}})
-This function allows you to integrate your own error messages into
-@code{lt_dlerror}. Pass in a suitable diagnostic message for return by
-@code{lt_dlerror}, and an error identifier for use with @code{lt_dlseterror}
-is returned.
-
-If the allocation of an identifier fails, this function returns -1.
-
-@example
-int myerror = lt_dladderror ("Doh!");
-if (myerror < 0)
- perror (lt_dlerror ());
-@end example
-@end deftypefun
-
-@deftypefun int lt_dlseterror (@w{int @var{errorcode}})
-When writing your own module loaders, you should use this function to raise
-errors so that they are propogated through the @code{lt_dlerror} interface.
-All of the standard errors used by libltdl are declared in @file{ltdl.h}, or
-you can add more of your own with @code{lt_dladderror}. This function returns
-0 on success.
-
-@example
-if (lt_dlseterror (LTDL_ERROR_NO_MEMORY) != 0)
- perror (lt_dlerror ());
-@end example
-@end deftypefun
-
@deftypefun int lt_dlpreload (const lt_dlsymlist *@var{preloaded})
Register the list of preloaded modules @var{preloaded}.
If @var{preloaded} is @code{NULL}, then all previously registered
Otherwise 0 is returned.
@end deftypefun
-@deftypevar {lt_ptr_t (*} lt_dlmalloc ) (size_t size)
-@deftypevarx {void (*} lt_dlfree ) (lt_ptr_t ptr)
+@deftypevar {lt_ptr_t (*} lt_dlmalloc ) (size_t @var{size})
+@deftypevarx {void (*} lt_dlfree ) (lt_ptr_t @var{ptr})
These variables are set to @code{malloc} and @code{free}, by default,
but you can set them to any other functions that provides equivalent
functionality. However, you must not modify their values after calling
...
@end example
+
+@node Module loaders for libltdl
+@section How to create and register new module loaders
+
+Sometimes libltdl's many ways of gaining access to modules are not
+sufficient for the purposes of a project. You can write your own
+loader, and register it with libltdl so that @code{lt_dlopen} will be
+able to use it.
+
+Writing a loader involves writing at least three functions which can be
+called by @code{lt_dlopen}, @code{lt_dlsym} and @code{lt_dlclose}.
+Optionally, you can provide a finalisation function to perform any
+cleanup operations when @code{lt_dlexit} executes, and a symbol prefix
+string which will be prepended to any symbols passed to @code{lt_dlsym}.
+These functions must match the function pointer types below, after
+which they can be allocated to an instance of @code{lt_user_dlloader}
+and registered.
+
+Registering the loader requires that you choose a name for it, so that it
+can be recognised by @code{lt_find_dlloader} and removed with
+@code{lt_remove_dlloader}. The name you choose must be unique, and not
+already in use by libltdl's builtin loaders:
+
+@table @asis
+@item "dlopen"
+The system dynamic library loader, if one exists.
+@item "dld"
+The @sc{gnu} dld loader, if @file{libdld} wasinstalled when libltdl was
+built.
+@item "dlpreload"
+The loader for @code{lt_dlopen}ing of preloaded static modules.
+@end table
+
+The prefix "dl" is reserved for loaders supplied with future versions of
+libltdl, so you should not use that for your own loader names.
+
+@noindent
+The following types are defined in @file{ltdl.h}:
+
+@deftp {Type} lt_module_t
+@code{lt_module_t} is a dlloader dependent module.
+The dynamic module loader extensions communicate using these low
+level types.
+@end deftp
+
+@deftp {Type} lt_dlloader_t
+@code{lt_dlloader_t} is a handle for module loader types.
+@end deftp
+
+@deftypefn {Type} {struct} lt_user_dlloader @{@w{const char *@var{sym_prefix};} @w{lt_module_open_t *@var{module_open};} @w{lt_module_close_t *@var{module_close};} @w{lt_find_sym_t *@var{find_sym};} @w{lt_dlloader_exit_t *@var{dlloader_exit};} @}
+If you want to define a new way to open dynamic modules, and have the
+@code{lt_dlopen} @sc{api} use it, you need to instantiate one of these
+structures and pass it to @code{lt_add_dlloader}.
+@end deftypefn
+
+@deftypefn {Type} lt_module_t lt_module_open_t (@w{const char *@var{filename}})
+The type of the loader function for an @code{lt_dlloader_t} module
+loader. Implementation of such a function should attempt to load the
+named module, and return an @code{lt_module_t} suitable for passing in
+to the associated @code{lt_module_close_t} and @code{lt_sym_find_t}
+function pointers. If the function fails it should return NULL, and set
+the error message with @code{lt_dlseterror}.
+@end deftypefn
+
+@deftypefn {Type} int lt_module_close_t (@w{lt_module_t @var{module}})
+The type of the unloader function for a user defined module loader.
+Implementatation of such a function should attempt to release
+any resources tied up by the @var{module} module, and then unload it
+from memory. If the function fails for some reason, set the error
+message with @code{lt_dlseterror} and return non-zero.
+@end deftypefn
+
+@deftypefn {Type} lt_ptr_t lt_find_sym_t (@w{lt_module_t @var{module},} @w{const char *@var{symbol}})
+The type of the symbol lookup function for a user defined module loader.
+Implementation of such a function should return the address of the named
+@var{symbol} in the module @var{module}, or else set the error message
+with @code{lt_dlseterror} and return NULL if lookup fails.
+@end deftypefn
+
+@deftypefn {Type} int lt_dlloader_exit_t (void)
+The type of the finalisation function for a user defined module loader.
+Implementation of such a function should free any resources associated
+with the loader. If non-NULL, the function will be called by
+@code{lt_dlexit}.
+@end deftypefn
+
+For example:
+
+@example
+int
+register_myloader (void)
+@{
+ lt_user_dlloader dlloader;
+
+ /* User modules are responsible for their own initialisation. */
+ if (myloader_init () != 0)
+ return MYLOADER_INIT_ERROR;
+
+ dlloader.sym_prefix = NULL;
+ dlloader.module_open = myloader_open;
+ dlloader.module_close = myloader_close;
+ dlloader.find_sym = myloader_find_sym.
+ dlloader.dlloader_exit = myloader_exit;
+
+ /* Add my loader as the default module loader. */
+ if (lt_add_dlloader (lt_next_dlloader (NULL), &dlloader, "myloader") != 0)
+ return ERROR;
+
+ return OK;
+@}
+@end example
+
+Note that if there is any initialisation required for the loader,
+it must be performed manually before the loader is registered --
+libltdl doesn't handle user loader initialisation.
+
+Finalisation @emph{is} handled by libltdl however, and it is important
+to ensure the @code{dlloader_exit} callback releases any resources claimed
+during the initialisation phase.
+
+@page
+@noindent
+libltdl provides the following functions for writing your own module
+loaders:
+
+@deftypefun int lt_add_dlloader (@w{lt_dlloader_t *@var{place},} @w{lt_user_dlloader *@var{dlloader},} @w{const char *@var{loader_name}})
+Add a new module loader to the list of all loaders, either as the
+last loader (if @var{place} is @code{NULL}), else immediately before the
+loader passed as @var{place}. @var{loader_name} will be returned by
+@code{lt_dlloader_name} if it is subsequently passed a newly
+registered loader. These @var{loader_name}s must be unique, or
+@code{lt_remove_dlloader} and @code{lt_find_dlloader} cannot
+work. Returns 0 for success.
+
+@example
+@{
+ /* Make myloader be the last one. */
+ if (lt_add_dlloader (NULL, myloader) != 0)
+ perror (lt_dlerror ());
+@}
+@end example
+@end deftypefun
+
+@deftypefun int lt_remove_dlloader (@w{const char *@var{loader_name}})
+Remove the loader identified by the unique name, @var{loader_name}.
+Before this can succeed, all modules opened by the named loader must
+have been closed. Returns 0 for success, otherwise an error message can
+be obtained from @code{lt_dlerror}.
+
+@example
+@{
+ /* Remove myloader. */
+ if (lt_remove_dlloader ("myloader") != 0)
+ perror (lt_dlerror ());
+@}
+@end example
+@end deftypefun
+
+@deftypefun lt_dlloader_t *lt_next_dlloader (@w{lt_dlloader_t *@var{place}})
+Iterate over the module loaders, returning the first loader if @var{place} is
+@code{NULL}, and the next one on subsequent calls. The handle is for use with
+@code{lt_add_dlloader}.
+
+@example
+@{
+ /* Make myloader be the first one. */
+ if (lt_add_dlloader (lt_next_dlloader (NULL), myloader) != 0)
+ return ERROR;
+@}
+@end example
+@end deftypefun
+
+@deftypefun lt_dlloader_t *lt_find_dlloader (@w{const char *@var{loader_name}})
+Return the first loader with a matching @var{loader_name} identifier, or else
+@code{NULL}, if the identifier is not found.
+
+The identifiers which may be used by ltdl itself, if the host
+architecture supports them are @dfn{dlopen}@footnote{This is used for
+the host dependent module loading @sc{api} -- @code{shl_load} and
+@code{LoadLibrary} for example}, @dfn{dld} and @dfn{dlpreload}.
+
+@example
+@{
+ /* Add a user loader as the next module loader to be tried if
+ the standard dlopen loader were to fail when lt_dlopening. */
+ if (lt_add_dlloader (lt_find_dlloader ("dlopen"), myloader) != 0)
+ return ERROR;
+@}
+@end example
+@end deftypefun
+
+@deftypefun char *lt_dlloader_name (@w{lt_dlloader_t *@var{place}})
+Return the identifying name of @var{PLACE}, as obtained from
+@code{lt_next_dlloader} or @code{lt_find_dlloader}. If this function fails,
+it will return @code{NULL} and set an error for retrieval with
+@code{lt_dlerror}.
+@end deftypefun
+
+@subsection Error handling within user module loaders
+
+@deftypefun int lt_dladderror (@w{const char *@var{diagnostic}})
+This function allows you to integrate your own error messages into
+@code{lt_dlerror}. Pass in a suitable diagnostic message for return by
+@code{lt_dlerror}, and an error identifier for use with
+@code{lt_dlseterror} is returned.
+
+If the allocation of an identifier fails, this function returns -1.
+
+@example
+int myerror = lt_dladderror ("Doh!");
+if (myerror < 0)
+ perror (lt_dlerror ());
+@end example
+@end deftypefun
+
+@deftypefun int lt_dlseterror (@w{int @var{errorcode}})
+When writing your own module loaders, you should use this function to
+raise errors so that they are propogated through the @code{lt_dlerror}
+interface. All of the standard errors used by libltdl are declared in
+@file{ltdl.h}, or you can add more of your own with
+@code{lt_dladderror}. This function returns 0 on success.
+
+@example
+if (lt_dlseterror (LTDL_ERROR_NO_MEMORY) != 0)
+ perror (lt_dlerror ());
+@end example
+@end deftypefun
+
@node Other languages
@chapter Using libtool with other languages
@cindex C, not using
/* This accounts for the _LTX_ separator */
#define LTDL_SYMBOL_OVERHEAD 5
+/* NOTE: typedefed in ltdl.h
+ This structure is used for the list of registered loaders. */
+struct lt_dlloader_t {
+ struct lt_dlloader_t *next;
+ const char *loader_name; /* identifying name for each loader */
+ const char *sym_prefix; /* prefix for symbols */
+ lt_dlloader_exit_t *dlloader_exit;
+ lt_module_open_t *module_open;
+ lt_module_close_t *module_close;
+ lt_find_sym_t *find_sym;
+};
+
+typedef struct lt_dlhandle_t {
+ struct lt_dlhandle_t *next;
+ lt_dlloader_t *loader; /* dlopening interface */
+ lt_dlinfo info;
+ int depcount; /* number of dependencies */
+ lt_dlhandle *deplibs; /* dependencies */
+ lt_module_t module; /* system module handle */
+ lt_ptr_t system; /* system specific data */
+ lt_ptr_t app_private; /* application private data */
+} lt_dlhandle_t;
+
static const char objdir[] = LTDL_OBJDIR;
#ifdef LTDL_SHLIB_EXT
static const char shlib_ext[] = LTDL_SHLIB_EXT;
LTDL_GLOBAL_DATA lt_ptr_t (*lt_dlmalloc) LTDL_PARAMS((size_t size)) = (lt_ptr_t(*)LTDL_PARAMS((size_t)))malloc;
LTDL_GLOBAL_DATA void (*lt_dlfree) LTDL_PARAMS((lt_ptr_t ptr)) = (void(*)LTDL_PARAMS((lt_ptr_t)))free;
-#define LTDL_TYPE_TOP 0
-
-typedef struct lt_dlhandle_t {
- struct lt_dlhandle_t *next;
- lt_dltype_t *type; /* dlopening interface */
- lt_dlinfo info;
- int depcount; /* number of dependencies */
- lt_dlhandle *deplibs; /* dependencies */
- lt_syshandle handle; /* system handle */
-} lt_dlhandle_t;
-
#undef strdup
#define strdup xstrdup
return tmp;
}
+#if ! HAVE_STRCMP
+
+#undef strcmp
+#define strcmp xstrcmp
+
+static inline int
+strcmp (str1, str2)
+ const char *str1;
+ const char *str2;
+{
+ if (str1 == str2)
+ return 0;
+ if (str1 == 0)
+ return -1;
+ if (str2 == 0)
+ return 1;
+
+ for (;*str1 && *str2; str1++, str2++)
+ if (*str1 != *str2)
+ break;
+
+ return (int)(*str1 - *str2);
+}
+#endif
+
+
#if ! HAVE_STRCHR
# if HAVE_INDEX
# endif
#endif
-static int
-sys_dl_init LTDL_PARAMS((void))
-{
- return 0;
-}
-
-static int
-sys_dl_exit LTDL_PARAMS((void))
-{
- return 0;
-}
-
-static lt_syshandle
+static lt_module_t
sys_dl_open (filename)
const char *filename;
{
- lt_ptr_t handle = dlopen(filename, LTDL_GLOBAL | LTDL_LAZY_OR_NOW);
- if (!handle) {
+ lt_module_t module = dlopen(filename, LTDL_GLOBAL | LTDL_LAZY_OR_NOW);
+ if (!module) {
#if HAVE_DLERROR
last_error = dlerror();
#else
last_error = LT_DLSTRERROR(CANNOT_OPEN);
#endif
}
- return handle;
+ return module;
}
static int
-sys_dl_close (handle)
- lt_syshandle handle;
+sys_dl_close (module)
+ lt_module_t module;
{
- if (dlclose(handle) != 0) {
+ if (dlclose(module) != 0) {
#if HAVE_DLERROR
last_error = dlerror();
#else
}
static lt_ptr_t
-sys_dl_sym (handle, symbol)
- lt_syshandle handle;
+sys_dl_sym (module, symbol)
+ lt_module_t module;
const char *symbol;
{
- lt_ptr_t address = dlsym(handle, symbol);
+ lt_ptr_t address = dlsym(module, symbol);
if (!address)
#if HAVE_DLERROR
return address;
}
-static
-lt_dltype_t
-#ifdef NEED_USCORE
-sys_dl = { LTDL_TYPE_TOP, "_", sys_dl_init, sys_dl_exit,
- sys_dl_open, sys_dl_close, sys_dl_sym };
-#else
-sys_dl = { LTDL_TYPE_TOP, 0, sys_dl_init, sys_dl_exit,
- sys_dl_open, sys_dl_close, sys_dl_sym };
-#endif
-
-#undef LTDL_TYPE_TOP
-#define LTDL_TYPE_TOP &sys_dl
-
+static struct lt_user_dlloader sys_dl = {
+# ifdef NEED_USCORE
+ "_",
+# else
+ 0,
+# endif
+ sys_dl_open, sys_dl_close, sys_dl_sym, 0 };
#endif
#if HAVE_SHL_LOAD
#define LTDL_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
-static int
-sys_shl_init LTDL_PARAMS((void))
-{
- return 0;
-}
-
-static int
-sys_shl_exit LTDL_PARAMS((void))
-{
- return 0;
-}
-
-static lt_syshandle
+static lt_module_t
sys_shl_open (filename)
const char *filename;
{
- lt_syshandle handle = shl_load(filename, LTDL_BIND_FLAGS, 0L);
- if (!handle) {
+ lt_module_t module = shl_load(filename, LTDL_BIND_FLAGS, 0L);
+ if (!module) {
last_error = LT_DLSTRERROR(CANNOT_OPEN);
}
- return handle;
+ return module;
}
static int
-sys_shl_close (handle)
- lt_syshandle handle;
+sys_shl_close (module)
+ lt_module_t module;
{
- if (shl_unload((shl_t) (handle)) != 0) {
+ if (shl_unload((shl_t) (module)) != 0) {
last_error = LT_DLSTRERROR(CANNOT_CLOSE);
return 1;
}
}
static lt_ptr_t
-sys_shl_sym (handle, symbol)
- lt_syshandle handle;
+sys_shl_sym (module, symbol)
+ lt_module_t module;
const char *symbol;
{
lt_ptr_t address;
- if (handle && shl_findsym((shl_t*) &handle,
+ if (module && shl_findsym((shl_t*) &module,
symbol, TYPE_UNDEFINED, &address) == 0)
if (address)
return address;
return 0;
}
-static
-lt_dltype_t
-sys_shl = { LTDL_TYPE_TOP, 0, sys_shl_init, sys_shl_exit,
- sys_shl_open, sys_shl_close, sys_shl_sym };
+static struct lt_user_dlloader
+sys_shl = { 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0 };
#undef LTDL_TYPE_TOP
#define LTDL_TYPE_TOP &sys_shl
#endif
-#if HAVE_DLD
-
-/* dynamic linking with dld */
-
-#if HAVE_DLD_H
-#include <dld.h>
-#endif
-
-static int
-sys_dld_init LTDL_PARAMS((void))
-{
- return 0;
-}
-
-static int
-sys_dld_exit LTDL_PARAMS((void))
-{
- return 0;
-}
-
-static lt_syshandle
-sys_dld_open (filename)
- const char *filename;
-{
- lt_syshandle handle = strdup(filename);
- if (!handle) {
- last_error = LT_DLSTRERROR(NO_MEMORY);
- return 0;
- }
- if (dld_link(filename) != 0) {
- last_error = LT_DLSTRERROR(CANNOT_OPEN);
- lt_dlfree(handle);
- return 0;
- }
- return handle;
-}
-
-static int
-sys_dld_close (handle)
- lt_syshandle handle;
-{
- if (dld_unlink_by_file((char*)(handle), 1) != 0) {
- last_error = LT_DLSTRERROR(CANNOT_CLOSE);
- return 1;
- }
- lt_dlfree(handle);
- return 0;
-}
-
-static lt_ptr_t
-sys_dld_sym (handle, symbol)
- lt_syshandle handle;
- const char *symbol;
-{
- lt_ptr_t address = dld_get_func(symbol);
-
- if (!address)
- last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
- return address;
-}
-
-static
-lt_dltype_t
-sys_dld = { LTDL_TYPE_TOP, 0, sys_dld_init, sys_dld_exit,
- sys_dld_open, sys_dld_close, sys_dld_sym };
-
-#undef LTDL_TYPE_TOP
-#define LTDL_TYPE_TOP &sys_dld
-
-#endif
-
#ifdef _WIN32
/* dynamic linking for Win32 */
/* Forward declaration; required to implement handle search below. */
static lt_dlhandle handles;
-static lt_syshandle
+static lt_module_t
sys_wll_open (filename)
const char *filename;
{
lt_dlhandle cur;
- lt_syshandle handle;
+ lt_module_t module;
char *searchname = 0;
char *ext = strrchr(filename, '.');
strcat(searchname, ".");
}
- handle = LoadLibrary(searchname);
+ module = LoadLibrary(searchname);
lt_dlfree(searchname);
/* libltdl expects this function to fail if it is unable
find one. */
cur = handles;
while (cur) {
- if (!cur->handle) {
+ if (!cur->module) {
cur = 0;
break;
}
- if (cur->handle == handle)
+ if (cur->module == module)
break;
cur = cur->next;
}
- if (cur || !handle) {
+ if (cur || !module) {
last_error = LT_DLSTRERROR(CANNOT_OPEN);
return 0;
}
- return handle;
+ return module;
}
static int
-sys_wll_close (handle)
- lt_syshandle handle;
+sys_wll_close (module)
+ lt_module_t module;
{
- if (FreeLibrary(handle) == 0) {
+ if (FreeLibrary(module) == 0) {
last_error = LT_DLSTRERROR(CANNOT_CLOSE);
return 1;
}
}
static lt_ptr_t
-sys_wll_sym (handle, symbol)
- lt_syshandle handle;
+sys_wll_sym (module, symbol)
+ lt_module_t module;
const char *symbol;
{
- lt_ptr_t address = GetProcAddress(handle, symbol);
+ lt_ptr_t address = GetProcAddress(module, symbol);
if (!address)
last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
return address;
}
-static
-lt_dltype_t
-sys_wll = { LTDL_TYPE_TOP, 0, sys_wll_init, sys_wll_exit,
- sys_wll_open, sys_wll_close, sys_wll_sym };
-
-#undef LTDL_TYPE_TOP
-#define LTDL_TYPE_TOP &sys_wll
+static struct lt_user_dlloader
+sys_wll = { 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0 };
#endif
#include <kernel/image.h>
-static int
-sys_bedl_init LTDL_PARAMS((void))
-{
- return 0;
-}
-
-static int
-sys_bedl_exit LTDL_PARAMS((void))
-{
- return 0;
-}
-
-static lt_syshandle
+static lt_module_t
sys_bedl_open (filename)
const char *filename;
{
return 0;
}
- return (lt_syshandle) image;
+ return (lt_module_t) image;
}
static int
-sys_bedl_close (handle)
- lt_syshandle handle;
+sys_bedl_close (module)
+ lt_module_t module;
{
- if (unload_add_on((image_id)handle) != B_OK) {
+ if (unload_add_on((image_id)module) != B_OK) {
last_error = LT_DLSTRERROR(CANNOT_CLOSE);
return 1;
}
}
static lt_ptr_t
-sys_bedl_sym (handle, symbol)
- lt_syshandle handle;
+sys_bedl_sym (module, symbol)
+ lt_module_t module;
const char *symbol;
{
lt_ptr_t address = 0;
- image_id image = (image_id)handle;
+ image_id image = (image_id)module;
if (get_image_symbol(image, symbol, B_SYMBOL_TYPE_ANY,
&address) != B_OK) {
return address;
}
-static
-lt_dltype_t
-sys_bedl = { LTDL_TYPE_TOP, 0, sys_bedl_init, sys_bedl_exit,
- sys_bedl_open, sys_bedl_close, sys_bedl_sym };
+static struct lt_user_dlloader
+sys_bedl = { 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0 };
-#undef LTDL_TYPE_TOP
-#define LTDL_TYPE_TOP &sys_bedl
+#endif
+
+#if HAVE_DLD
+
+/* dynamic linking with dld */
+
+#if HAVE_DLD_H
+#include <dld.h>
+#endif
+
+static lt_module_t
+sys_dld_open (filename)
+ const char *filename;
+{
+ lt_module_t module = strdup(filename);
+ if (!module) {
+ last_error = LT_DLSTRERROR(NO_MEMORY);
+ return 0;
+ }
+ if (dld_link(filename) != 0) {
+ last_error = LT_DLSTRERROR(CANNOT_OPEN);
+ lt_dlfree(module);
+ return 0;
+ }
+ return module;
+}
+
+static int
+sys_dld_close (module)
+ lt_module_t module;
+{
+ if (dld_unlink_by_file((char*)(module), 1) != 0) {
+ last_error = LT_DLSTRERROR(CANNOT_CLOSE);
+ return 1;
+ }
+ lt_dlfree(module);
+ return 0;
+}
+
+static lt_ptr_t
+sys_dld_sym (module, symbol)
+ lt_module_t module;
+ const char *symbol;
+{
+ lt_ptr_t address = dld_get_func(symbol);
+
+ if (!address)
+ last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
+ return address;
+}
+
+static struct lt_user_dlloader
+sys_dld = { 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0 };
#endif
return 0;
}
-static lt_syshandle
+static lt_module_t
presym_open (filename)
const char *filename;
{
while (syms->name) {
if (!syms->address &&
strcmp(syms->name, filename) == 0) {
- return (lt_syshandle) syms;
+ return (lt_module_t) syms;
}
syms++;
}
}
static int
-presym_close (handle)
- lt_syshandle handle;
+presym_close (module)
+ lt_module_t module;
{
/* Just to silence gcc -Wall */
- handle = 0;
+ module = 0;
return 0;
}
static lt_ptr_t
-presym_sym (handle, symbol)
- lt_syshandle handle;
+presym_sym (module, symbol)
+ lt_module_t module;
const char *symbol;
{
- lt_dlsymlist *syms = (lt_dlsymlist*)(handle);
+ lt_dlsymlist *syms = (lt_dlsymlist*)(module);
syms++;
while (syms->address) {
return 0;
}
-static
-lt_dltype_t
-presym = { LTDL_TYPE_TOP, 0, presym_init, presym_exit,
- presym_open, presym_close, presym_sym };
+static struct lt_user_dlloader
+presym = { 0, presym_open, presym_close, presym_sym, presym_exit };
-#undef LTDL_TYPE_TOP
-#define LTDL_TYPE_TOP &presym
static char *user_search_path = 0;
+static lt_dlloader_t *loaders = 0;
static lt_dlhandle handles = 0;
static int initialized = 0;
-static lt_dltype_t *types = LTDL_TYPE_TOP;
-#undef LTDL_TYPE_TOP
-
int
lt_dlinit LTDL_PARAMS((void))
{
/* initialize libltdl */
- lt_dltype_t **type = &types;
- int typecount = 0;
+ lt_dlloader_t **loader = &loaders;
+ int errors = 0;
if (initialized) { /* Initialize only at first call. */
initialized++;
}
handles = 0;
user_search_path = 0; /* empty search path */
-
- while (*type) {
- if ((*type)->mod_init())
- *type = (*type)->next; /* Remove it from the list */
- else {
- type = &(*type)->next; /* Keep it */
- typecount++;
- }
- }
- if (typecount == 0) {
- last_error = LT_DLSTRERROR(DLOPEN_NOT_SUPPORTED);
- return 1;
- }
- last_error = 0;
- initialized = 1;
- return 0;
-}
-
-int
-lt_dladdtype (dltype)
- lt_dltype_t *dltype;
-{
- lt_dltype_t *type = types;
- if (dltype == 0) { /* diagnose null parameters */
- last_error = LT_DLSTRERROR(INVALID_TYPE);
- return 1;
- }
- if (dltype->next != 0) { /* diagnose invalid contents */
- last_error = LT_DLSTRERROR(INVALID_TYPE);
- return 1;
- }
-
-#ifdef NEED_USCORE
- if (dltype->sym_prefix == 0)
- dltype->sym_prefix = "_";
-#else
- if (dltype->sym_prefix && *dltype->sym_prefix == 0)
- dltype->sym_prefix = 0;
+#if HAVE_LIBDL && !defined(__CYGWIN__)
+ errors += lt_add_dlloader (lt_next_dlloader(0), &sys_dl, "dlopen");
#endif
-
- if (type == 0) {
- type = dltype;
- } else {
- /* This function always appends to the existing list. */
- while (type->next)
- type = type->next;
- type->next = dltype;
- }
-
- /* If lt_dlinit() has already been called, then initialize the
- new type here. */
- if (initialized && dltype->mod_init)
- if ((*dltype->mod_init)()) {
- last_error = LT_DLSTRERROR(INIT_TYPE);
+#if HAVE_SHL_LOAD
+ errors += lt_add_dlloader (lt_next_dlloader(0), &sys_shl, "dlopen");
+#endif
+#ifdef _WIN32
+ errors += lt_add_dlloader (lt_next_dlloader(0), &sys_wll, "dlopen");
+#endif
+#ifdef __BEOS__
+ errors += lt_add_dlloader (lt_next_dlloader(0), &sys_bedl, "dlopen");
+#endif
+#if HAVE_DLD
+ errors += lt_add_dlloader (lt_next_dlloader(0), &sys_dld, "dld");
+#endif
+ errors += lt_add_dlloader (lt_next_dlloader(0), &presym, "dlpreload");
+ if (presym_init()) {
+ last_error = LT_DLSTRERROR(INIT_LOADER);
return 1;
}
- return 0;
-}
-
-lt_dltype_t *
-lt_dlgettypes LTDL_PARAMS((void))
-{
- return types;
-}
-
-int
-lt_dlsettypes (dltypes)
- lt_dltype_t *dltypes;
-{
- if (dltypes == 0) { /* diagnose null parameters */
- last_error = LT_DLSTRERROR(INVALID_TYPE);
+ if (errors != 0) {
+ last_error = LT_DLSTRERROR(DLOPEN_NOT_SUPPORTED);
return 1;
}
- types = dltypes;
+ last_error = 0;
+ initialized = 1;
return 0;
}
lt_dlexit LTDL_PARAMS((void))
{
/* shut down libltdl */
- lt_dltype_t *type = types;
+ lt_dlloader_t *loader = loaders;
int errors, level;
if (!initialized) {
errors++;
}
}
- initialized = 0;
- while (type) {
- if (type->mod_exit())
+ /* close all loaders */
+ while (loader) {
+ lt_dlloader_t *next = loader->next;
+ if (loader->dlloader_exit && loader->dlloader_exit())
errors++;
- type = type->next;
+ lt_dlfree (loader);
+ loader = next;
}
+
+ initialized = 0;
return errors;
}
const char *filename;
{
lt_dlhandle cur;
- lt_dltype_t *type = types;
+ lt_dlloader_t *loader = loaders;
const char *saved_error = last_error;
/* check whether the module was already opened */
}
} else
cur->info.filename = 0;
- while (type) {
- cur->handle = type->lib_open(filename);
- if (cur->handle != 0)
+ while (loader) {
+ cur->module = loader->module_open(filename);
+ if (cur->module != 0)
break;
- type = type->next;
+ loader = loader->next;
}
- if (!type) {
+ if (!loader) {
if (cur->info.filename)
lt_dlfree(cur->info.filename);
return 1;
}
- cur->type = type;
+ cur->loader = loader;
last_error = saved_error;
return 0;
}
last->next = handle->next;
else
handles = handle->next;
- error = handle->type->lib_close(handle->handle);
+ error = handle->loader->module_close(handle->module);
error += unload_deplibs(handle);
if (handle->info.filename)
lt_dlfree(handle->info.filename);
return 0;
}
lensym = strlen(symbol);
- if (handle->type->sym_prefix)
- lensym += strlen(handle->type->sym_prefix);
+ if (handle->loader->sym_prefix)
+ lensym += strlen(handle->loader->sym_prefix);
if (handle->info.name)
lensym += strlen(handle->info.name);
if (lensym + LTDL_SYMBOL_OVERHEAD < LTDL_SYMBOL_LENGTH)
const char *saved_error = last_error;
/* this is a libtool module */
- if (handle->type->sym_prefix) {
- strcpy(sym, handle->type->sym_prefix);
+ if (handle->loader->sym_prefix) {
+ strcpy(sym, handle->loader->sym_prefix);
strcat(sym, handle->info.name);
} else
strcpy(sym, handle->info.name);
strcat(sym, "_LTX_");
strcat(sym, symbol);
/* try "modulename_LTX_symbol" */
- address = handle->type->find_sym(handle->handle, sym);
+ address = handle->loader->find_sym(handle->module, sym);
if (address) {
if (sym != lsym)
lt_dlfree(sym);
last_error = saved_error;
}
/* otherwise try "symbol" */
- if (handle->type->sym_prefix) {
- strcpy(sym, handle->type->sym_prefix);
+ if (handle->loader->sym_prefix) {
+ strcpy(sym, handle->loader->sym_prefix);
strcat(sym, symbol);
} else
strcpy(sym, symbol);
- address = handle->type->find_sym(handle->handle, sym);
+ address = handle->loader->find_sym(handle->module, sym);
if (sym != lsym)
lt_dlfree(sym);
return address;
return 0;
}
+\f
+int
+lt_add_dlloader (place, dlloader, loader_name)
+ lt_dlloader_t *place;
+ const struct lt_user_dlloader *dlloader;
+ const char *loader_name;
+{
+ lt_dlloader_t *node = 0, *ptr = 0;
+
+ if ((dlloader == 0) /* diagnose null parameters */
+ || (dlloader->module_open == 0)
+ || (dlloader->module_close == 0)
+ || (dlloader->find_sym == 0)) {
+ last_error = LT_DLSTRERROR(INVALID_LOADER);
+ return 1;
+ }
+
+ /* Create a new dlloader node with copies of the user callbacks. */
+ node = (lt_dlloader_t *) lt_dlmalloc (sizeof (lt_dlloader_t));
+ if (node == 0) {
+ last_error = LT_DLSTRERROR(NO_MEMORY);
+ return 1;
+ }
+ node->next = 0;
+ node->loader_name = loader_name;
+ node->sym_prefix = dlloader->sym_prefix;
+ node->dlloader_exit = dlloader->dlloader_exit;
+ node->module_open = dlloader->module_open;
+ node->module_close = dlloader->module_close;
+ node->find_sym = dlloader->find_sym;
+
+ if (!loaders)
+ /* If there are no loaders, NODE becomes the list! */
+ loaders = node;
+ else if (!place) {
+ /* If PLACE is not set, add NODE to the end of the
+ LOADERS list. */
+ for (ptr = loaders; ptr->next; ptr = ptr->next)
+ /*NOWORK*/;
+ ptr->next = node;
+ } else if (loaders == place) {
+ /* If PLACE is the first loader, NODE goes first. */
+ node->next = place;
+ loaders = node;
+ } else {
+ /* Find the node immediately preceding PLACE. */
+ for (ptr = loaders; ptr->next != place; ptr = ptr->next)
+ /*NOWORK*/;
+
+ if (ptr->next != place) {
+ last_error = LT_DLSTRERROR(INVALID_LOADER);
+ return 1;
+ }
+
+ /* Insert NODE between PTR and PLACE. */
+ node->next = place;
+ ptr->next = node;
+ }
+
+ return 0;
+}
+
+int
+lt_remove_dlloader (loader_name)
+ const char *loader_name;
+{
+ lt_dlloader_t *place = lt_find_dlloader (loader_name);
+ lt_dlhandle handle;
+ int result = 0;
+
+ if (!place) {
+ last_error = LT_DLSTRERROR(INVALID_LOADER);
+ return 1;
+ }
+
+ /* Fail if there are any open modules which use this loader. */
+ for (handle = handles; handle; handle = handle->next)
+ if (handle->loader = place) {
+ last_error = LT_DLSTRERROR(REMOVE_LOADER);
+ return 1;
+ }
+
+ if (place == loaders)
+ /* PLACE is the first loader in the list. */
+ loaders = loaders->next;
+ else {
+ /* Find the loader before the one being removed. */
+ lt_dlloader_t *prev;
+ for (prev = loaders; prev->next; prev = prev->next)
+ if (!strcmp (prev->next->loader_name, loader_name))
+ break;
+
+ place = prev->next;
+ prev->next = prev->next->next;
+ }
+ if (place->dlloader_exit)
+ result = place->dlloader_exit ();
+ lt_dlfree (place);
+
+ return result;
+}
+
+lt_dlloader_t *
+lt_next_dlloader (place)
+ lt_dlloader_t *place;
+{
+ return place ? place->next : loaders;
+}
+
+const char *
+lt_dlloader_name (place)
+ lt_dlloader_t *place;
+{
+ if (!place)
+ last_error = LT_DLSTRERROR(INVALID_LOADER);
+ return place ? place->loader_name : 0;
+}
+
+lt_dlloader_t *
+lt_find_dlloader (loader_name)
+ const char *loader_name;
+{
+ lt_dlloader_t *place = 0;
+
+ for (place = loaders; place; place = place->next)
+ if (strcmp (place->loader_name, loader_name) == 0)
+ break;
+
+ return place;
+}
+
+\f
static const char **user_error_strings = 0;
static int errorcode = LTDL_ERROR_MAX;
const char *diagnostic;
{
int index = errorcode - LTDL_ERROR_MAX;
- char **temp = 0;
+ const char **temp = 0;
/* realloc is not entirely portable, so simulate it using
lt_dlmalloc and lt_dlfree. */
# endif
#endif
-
#ifdef WIN32
# ifndef __CYGWIN__
/* LTDL_DIRSEP_CHAR is accepted *in addition* to '/' as a directory
#include <stdlib.h>
+\f
+/* Defining error strings alongside their symbolic names in a macro in
+ this way allows us to expand the macro in different contexts with
+ confidence that the enumeration of symbolic names will map correctly
+ onto the table of error strings. */
#define ltdl_error_table \
LTDL_ERROR(UNKNOWN, "unknown error") \
LTDL_ERROR(DLOPEN_NOT_SUPPORTED, "dlopen support not available")\
- LTDL_ERROR(INVALID_TYPE, "invalid dltype") \
- LTDL_ERROR(INIT_TYPE, "dltype initialization failed") \
+ LTDL_ERROR(INVALID_LOADER, "invalid loader") \
+ LTDL_ERROR(INIT_LOADER, "loader initialization failed") \
+ LTDL_ERROR(REMOVE_LOADER, "loader removal failed") \
LTDL_ERROR(FILE_NOT_FOUND, "file not found") \
LTDL_ERROR(DEPLIB_NOT_FOUND, "dependency library not found") \
LTDL_ERROR(NO_SYMBOLS, "no symbols defined") \
LTDL_ERROR(INVALID_ERRORCODE, "invalid errorcode") \
LTDL_ERROR(SHUTDOWN, "library already shutdown")
+/* Enumerate the symbolic error names. */
#ifdef __STDC__
# define LTDL_ERROR(name, diagnostic) LTDL_ERROR_##name,
#else
};
#undef LTDL_ERROR
+\f
+/* An opaque handle for a successfully lt_dlopened module instance. */
#ifdef _LTDL_COMPILE_
typedef struct lt_dlhandle_t *lt_dlhandle;
#else
typedef lt_ptr_t lt_dlhandle;
#endif
-typedef lt_ptr_t lt_syshandle;
-
+/* A preopened symbol. Arrays of this type comprise the exported
+ symbols for a dlpreopened module. */
typedef struct {
const char *name;
lt_ptr_t address;
} lt_dlsymlist;
+/* Read only information pertaining to a loaded module. */
typedef struct {
char *filename; /* file name */
char *name; /* module name */
- int ref_count; /* reference count */
+ int ref_count; /* number of times lt_dlopened minus
+ number of times lt_dlclosed. */
} lt_dlinfo;
-typedef int lt_mod_init_t LTDL_PARAMS((void));
-typedef int lt_mod_exit_t LTDL_PARAMS((void));
-typedef lt_syshandle lt_lib_open_t LTDL_PARAMS((const char *filename));
-typedef int lt_lib_close_t LTDL_PARAMS((lt_syshandle handle));
-typedef lt_ptr_t lt_find_sym_t LTDL_PARAMS((lt_syshandle handle, const char *symbol));
-
-typedef struct lt_dltype_t {
- struct lt_dltype_t *next;
- const char *sym_prefix; /* prefix for symbols */
- lt_mod_init_t *mod_init;
- lt_mod_exit_t *mod_exit;
- lt_lib_open_t *lib_open;
- lt_lib_close_t *lib_close;
- lt_find_sym_t *find_sym;
-} lt_dltype_t;
+/* An opaque handle for a module loaded by a system call. This is only
+ used internally by ltdl loaders, and by user module loaders. */
+typedef lt_ptr_t lt_module_t;
+
+/* An opaque handle for a module loader. */
+#ifdef _LTDL_COMPILE_
+typedef struct lt_dlloader_t lt_dlloader_t;
+#else
+typedef lt_ptr_t lt_dlloader_t;
+#endif
+
+/* Function pointer types for creating user defined module loaders. */
+typedef lt_module_t lt_module_open_t LTDL_PARAMS((const char *filename));
+typedef int lt_module_close_t LTDL_PARAMS((lt_module_t handle));
+typedef lt_ptr_t lt_find_sym_t LTDL_PARAMS((lt_module_t handle, const char *symbol));
+typedef int lt_dlloader_exit_t LTDL_PARAMS((void));
__BEGIN_DECLS
+/* Initialisation and finalisation functions for libltdl. */
extern int lt_dlinit LTDL_PARAMS((void));
-extern int lt_dladdtype LTDL_PARAMS((lt_dltype_t *dltype));
-extern lt_dltype_t *lt_dlgettypes LTDL_PARAMS((void));
-extern int lt_dlsettypes LTDL_PARAMS((lt_dltype_t *dltypes));
-extern int lt_dlpreload LTDL_PARAMS((const lt_dlsymlist *preloaded));
-extern int lt_dlpreload_default LTDL_PARAMS((const lt_dlsymlist *preloaded));
extern int lt_dlexit LTDL_PARAMS((void));
+
+/* Module search path manipultation. */
+extern int lt_dladdsearchdir LTDL_PARAMS((const char *search_dir));
+extern int lt_dlsetsearchpath LTDL_PARAMS((const char *search_path));
+extern const char *lt_dlgetsearchpath LTDL_PARAMS((void));
+
+/* Portable libltdl versions of the system dlopen() API. */
extern lt_dlhandle lt_dlopen LTDL_PARAMS((const char *filename));
extern lt_dlhandle lt_dlopenext LTDL_PARAMS((const char *filename));
-extern int lt_dlclose LTDL_PARAMS((lt_dlhandle handle));
extern lt_ptr_t lt_dlsym LTDL_PARAMS((lt_dlhandle handle, const char *name));
extern const char *lt_dlerror LTDL_PARAMS((void));
-extern int lt_dladdsearchdir LTDL_PARAMS((const char *search_dir));
-extern int lt_dlsetsearchpath LTDL_PARAMS((const char *search_path));
-extern const char *lt_dlgetsearchpath LTDL_PARAMS((void));
-extern const lt_dlinfo *lt_dlgetinfo LTDL_PARAMS((lt_dlhandle handle));
-extern int lt_dlforeach LTDL_PARAMS((
- int (*func)(lt_dlhandle handle, lt_ptr_t data), lt_ptr_t data));
-extern int lt_dladderror LTDL_PARAMS((const char *diagnostic));
-extern int lt_dlseterror LTDL_PARAMS((int errorcode));
+extern int lt_dlclose LTDL_PARAMS((lt_dlhandle handle));
+
+/* Support for preloaded modules through lt_dlopen() API. */
+extern int lt_dlpreload LTDL_PARAMS((const lt_dlsymlist *preloaded));
+extern int lt_dlpreload_default LTDL_PARAMS((const lt_dlsymlist *preloaded));
#define LTDL_SET_PRELOADED_SYMBOLS() LTDL_STMT_START{ \
extern const lt_dlsymlist lt_preloaded_symbols[]; \
lt_dlpreload_default(lt_preloaded_symbols); \
}LTDL_STMT_END
+/* Managing user data associated with a loaded modules. */
+extern const lt_dlinfo *lt_dlgetinfo LTDL_PARAMS((lt_dlhandle handle));
+extern int lt_dlforeach LTDL_PARAMS((
+ int (*func)(lt_dlhandle handle, lt_ptr_t data), lt_ptr_t data));
+
+\f
+/* User module loader API. */
+struct lt_user_dlloader {
+ const char *sym_prefix;
+ lt_module_open_t *module_open;
+ lt_module_close_t *module_close;
+ lt_find_sym_t *find_sym;
+ lt_dlloader_exit_t *dlloader_exit;
+};
+
+extern lt_dlloader_t *lt_next_dlloader LTDL_PARAMS((lt_dlloader_t *place));
+extern const char *lt_dlloader_name LTDL_PARAMS((lt_dlloader_t *place));
+extern lt_dlloader_t *lt_find_dlloader LTDL_PARAMS((const char *loader_name));
+extern int lt_add_dlloader LTDL_PARAMS((lt_dlloader_t *place, const struct lt_user_dlloader *dlloader, const char *loader_name));
+
+/* Integrated lt_dlerror() messages for user loaders. */
+extern int lt_dladderror LTDL_PARAMS((const char *diagnostic));
+extern int lt_dlseterror LTDL_PARAMS((int errorcode));
+
+/* Pointers to memory management functions to be used by libltdl. */
LTDL_SCOPE lt_ptr_t (*lt_dlmalloc)LTDL_PARAMS((size_t size));
LTDL_SCOPE void (*lt_dlfree)LTDL_PARAMS((lt_ptr_t ptr));
AC_CHECK_HEADERS(string.h strings.h, break)
AC_CHECK_FUNCS(strchr index, break)
AC_CHECK_FUNCS(strrchr rindex, break)
+AC_CHECK_FUNCS(strcmp)
AC_REQUIRE([AC_LTDL_ENABLE_INSTALL])dnl
AC_REQUIRE([AC_LTDL_SHLIBEXT])dnl