]> git.ipfire.org Git - thirdparty/libtool.git/commitdiff
* NEWS: updated.
authorGary V. Vaughan <gary@gnu.org>
Wed, 2 Feb 2000 22:43:14 +0000 (22:43 +0000)
committerGary V. Vaughan <gary@gnu.org>
Wed, 2 Feb 2000 22:43:14 +0000 (22:43 +0000)
* 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.

ChangeLog
NEWS
doc/libtool.texi
libltdl/ltdl.c
libltdl/ltdl.h
ltdl.m4

index 0db740be85ee146a6bb817b037a490631257a6e6..7b26592dd63b6713d87b5f8dea4c0c3c4aa5d4a1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,61 @@
+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.
diff --git a/NEWS b/NEWS
index 066e48a076124f9182d7334930ea88dc49576b33..797bd0a42865d0c93b789d5d5bb1188e81d0f655 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,8 +10,9 @@ New in 1.3d: 2000-??-??; CVS version 1.3c, Libtool team:
 * 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.
index 1a7c70c2e90bbf1cfca5138b17d0a36d337fb8b3..ce679b433527328d024ea874922dd4d87a55f2cc 100644 (file)
@@ -181,6 +181,7 @@ Using libltdl
 * 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
 
@@ -2785,6 +2786,7 @@ distribution terms that you use for the rest of that program.
 * 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
@@ -2823,12 +2825,6 @@ The following types are defined in @file{ltdl.h}:
 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
@@ -2839,51 +2835,6 @@ The @var{ref_count} attribute is a reference counter that describes how often
 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}.
@@ -2900,32 +2851,6 @@ and may be called several times.
 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 
@@ -3013,34 +2938,6 @@ Return @code{NULL} if no errors have occurred since initialization
 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
@@ -3105,8 +3002,8 @@ As soon as @var{func} returns a non-zero value for one of the handles,
 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
@@ -3318,6 +3215,234 @@ myprog_DEPENDENCIES = $(LIBLTDL) libfoo.la
 ...
 @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
index eb6e5d55ec6048f4d0cff5109929497d9871ecca..76d90c2b59d3b20c0bcc9d0afae7fc455f299269 100644 (file)
@@ -87,6 +87,29 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 /* 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;
@@ -115,17 +138,6 @@ static const char *last_error = 0;
 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
 
@@ -143,6 +155,32 @@ strdup(str)
        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
@@ -244,38 +282,26 @@ strrchr(str, ch)
 # 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
@@ -287,11 +313,11 @@ sys_dl_close (handle)
 }
 
 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
@@ -302,19 +328,13 @@ sys_dl_sym (handle, symbol)
        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
@@ -360,34 +380,22 @@ sys_dl = { LTDL_TYPE_TOP, 0, sys_dl_init, sys_dl_exit,
 
 #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;
        }
@@ -395,13 +403,13 @@ sys_shl_close (handle)
 }
 
 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;
@@ -409,87 +417,14 @@ sys_shl_sym (handle, symbol)
        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 */
@@ -511,12 +446,12 @@ sys_wll_exit LTDL_PARAMS((void))
 /* 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, '.');
 
@@ -535,7 +470,7 @@ sys_wll_open (filename)
                strcat(searchname, ".");
        }
 
-       handle = LoadLibrary(searchname);
+       module = LoadLibrary(searchname);
        lt_dlfree(searchname);
        
        /* libltdl expects this function to fail if it is unable
@@ -548,28 +483,28 @@ sys_wll_open (filename)
           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;
        }
@@ -577,24 +512,19 @@ sys_wll_close (handle)
 }
 
 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
 
@@ -604,19 +534,7 @@ sys_wll = { LTDL_TYPE_TOP, 0, sys_wll_init, sys_wll_exit,
 
 #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;
 {
@@ -635,14 +553,14 @@ sys_bedl_open (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;
        }
@@ -650,12 +568,12 @@ sys_bedl_close (handle)
 }
 
 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) {
@@ -665,13 +583,62 @@ sys_bedl_sym (handle, symbol)
        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
 
@@ -740,7 +707,7 @@ presym_add_symlist (preloaded)
        return 0;
 }
 
-static lt_syshandle
+static lt_module_t
 presym_open (filename)
        const char *filename;
 {
@@ -758,7 +725,7 @@ presym_open (filename)
                while (syms->name) {
                        if (!syms->address &&
                            strcmp(syms->name, filename) == 0) {
-                               return (lt_syshandle) syms;
+                               return (lt_module_t) syms;
                        }
                        syms++;
                }
@@ -769,20 +736,20 @@ presym_open (filename)
 }
 
 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) {
@@ -794,27 +761,21 @@ presym_sym (handle, symbol)
        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++;
@@ -822,82 +783,34 @@ lt_dlinit LTDL_PARAMS((void))
        }
        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;
 }
 
@@ -925,7 +838,7 @@ int
 lt_dlexit LTDL_PARAMS((void))
 {
        /* shut down libltdl */
-       lt_dltype_t *type = types;
+       lt_dlloader_t *loader = loaders;
        int     errors, level;
        
        if (!initialized) {
@@ -948,12 +861,16 @@ lt_dlexit LTDL_PARAMS((void))
                                        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;
 }
 
@@ -963,7 +880,7 @@ tryall_dlopen (handle, filename)
        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 */
@@ -992,18 +909,18 @@ tryall_dlopen (handle, filename)
                }
        } 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;
 }
@@ -1679,7 +1596,7 @@ lt_dlclose (handle)
                        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);
@@ -1710,8 +1627,8 @@ lt_dlsym (handle, symbol)
                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)
@@ -1726,15 +1643,15 @@ lt_dlsym (handle, symbol)
                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);
@@ -1743,12 +1660,12 @@ lt_dlsym (handle, symbol)
                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;
@@ -1838,6 +1755,138 @@ lt_dlforeach (func, data)
        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;
 
@@ -1846,7 +1895,7 @@ lt_dladderror (diagnostic)
        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. */
index 2e42c7f5a00700c4e7b5342f02f674814eb4cbfd..605f72774ce60f6cf5491c5b6fdece3efd9297b7 100644 (file)
@@ -83,7 +83,6 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 #  endif
 #endif
 
-
 #ifdef WIN32
 #  ifndef __CYGWIN__
 /* LTDL_DIRSEP_CHAR is accepted *in addition* to '/' as a directory
@@ -114,11 +113,17 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 
 #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")                    \
@@ -131,6 +136,7 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
        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
@@ -142,68 +148,97 @@ enum {
 };
 #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));
 
diff --git a/ltdl.m4 b/ltdl.m4
index f5590b061782b80ce8be4232cea106d794ffdaa5..d6b776a28ad15524c24086fca0d5144d1265bde3 100644 (file)
--- a/ltdl.m4
+++ b/ltdl.m4
@@ -37,6 +37,7 @@ AC_CHECK_HEADERS(malloc.h memory.h stdlib.h stdio.h ctype.h dlfcn.h dl.h dld.h)
 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