* doc/libtool.texi (User defined module data): Document it all.
* ltdl.m4: Check for memcpy, or else bcopy.
* ltdl.c (lt_caller_data): New type.
(lt_dl_handle_struct): Add an lt_caller_data field.
(lt_dlcaller_register, lt_dlcaller_set_data,
lt_dlcaller_get_data): New functions.
(rpl_memcpy): A minimal fallback implementation.
(rpl_realloc): A realloc implemented with lt_dlmalloc and
lt_dlfree.
(LT_DLMALLOC, LT_DLFREE, LT_DLREALLOC, LT_DLMEM_REASSIGN):
New memory handling convenience macros. Use them
appropriately throughout the rest of this file.
* ltdl.h (lt_dlcaller_register, lt_dlcaller_set_data,
lt_dlcaller_get_data): Prototyped.
+2001-01-05 Gary V. Vaughan <gvv@techie.com>
+
+ * NEWS: Updated.
+ * doc/libtool.texi (User defined module data): Document it all.
+ * ltdl.m4: Check for memcpy, or else bcopy.
+ * ltdl.c (lt_caller_data): New type.
+ (lt_dl_handle_struct): Add an lt_caller_data field.
+ (lt_dlcaller_register, lt_dlcaller_set_data,
+ lt_dlcaller_get_data): New functions.
+ (rpl_memcpy): A minimal fallback implementation.
+ (rpl_realloc): A realloc implemented with lt_dlmalloc and
+ lt_dlfree.
+ (LT_DLMALLOC, LT_DLFREE, LT_DLREALLOC, LT_DLMEM_REASSIGN):
+ New memory handling convenience macros. Use them
+ appropriately throughout the rest of this file.
+ * ltdl.h (lt_dlcaller_register, lt_dlcaller_set_data,
+ lt_dlcaller_get_data): Prototyped.
+
2001-01-04 Gary V. Vaughan <gvv@techie.com>
* libltdl/ltdl.h: formatting change.
* Libtool now allows you to link shared libraries against static code.
* New functions in libltdl:
lt_dlgetinfo, lt_dlforeach provide access to module specific data in handles.
+ lt_dlcaller_register, lt_dlcaller_set_data and lt_dlcaller_get_data provide
+ management for user storage of per module data.
lt_dlloader_next, lt_dlloader_name, lt_dlloader_find, lt_dlloader_add and
lt_dlloader_remove can be used for adding new types of module loaders.
lt_dladderror, lt_dlseterror integrate user module loaders with lt_dlerror.
* 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.
+* User defined module data:: Associating data with loaded modules.
* Module loaders for libltdl:: Creating user defined module loaders.
+* Distributing libltdl:: How to distribute libltdl with your package.
Using libtool with other languages
@menu
* 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.
+* User defined module data:: Associating data with loaded modules.
* Module loaders for libltdl:: Creating user defined module loaders.
+* Distributing libltdl:: How to distribute libltdl with your package.
@end menu
@node Libltdl interface
Every lt_dlopened module has a handle associated with it.
@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
-real module file name. If the module is a libtool module then @var{name}
-is its module name (e.g. @code{"libfoo"} for @code{"dir/libfoo.la"}),
-otherwise it is set to @code{NULL}.
-The @var{ref_count} attribute is a reference counter that describes how often
-the same module is currently loaded.
-@end deftypefn
-
@deftp {Type} lt_dlsymlist
@code{lt_dlsymlist} is a symbol list for dlpreopened modules.
This structure is described in @pxref{Dlpreopening}.
@code{lt_dlerror}.
@end deftypefun
-@deftypefun {const lt_dlinfo *}lt_dlgetinfo (lt_dlhandle @var{handle})
-Return a pointer to a struct that contains some information about
-the module @var{handle}. The contents of the struct must not be modified.
-Return @code{NULL} on failure.
-@end deftypefun
-
-@deftypefun int lt_dlforeach (int (*@var{func})(lt_dlhandle @var{handle}, lt_ptr @var{data}), lt_ptr @var{data})
-For each loaded module call the function @var{func}. The argument
-@var{handle} is the handle of one of the loaded modules, @var{data} is
-the @var{data} argument passed to @code{lt_dlforeach}.
-As soon as @var{func} returns a non-zero value for one of the handles,
-@code{lt_dlforeach} will stop calling @var{func} and immediately return 1.
-Otherwise 0 is returned.
-@end deftypefun
-
@deftypevar {lt_ptr (*) (size_t @var{size})} lt_dlmalloc
@deftypevarx {void (*) (lt_ptr @var{ptr})} lt_dlfree
These variables are set to @code{malloc} and @code{free}, by default,
...
@end example
-@node Distributing libltdl
-@section How to distribute libltdl with your package
-Even though libltdl is installed together with libtool, you may wish to
-include libltdl in the distribution of your package, for the convenience
-of users of your package that don't have libtool or libltdl installed.
-In this case, you must decide whether to manually add the @code{ltdl}
-objects to your package, or else which flavor of libltdl you want to use:
-a convenience library or an installable libtool library.
+@node User defined module data
+@section Data associated with loaded modules
-The most simplistic way to add @code{libltdl} to your package is to copy
-the source files, @file{ltdl.c} and @file{ltdl.h}, to a source directory
-withing your package and to build and link them along with the rest of
-your sources. To help you do this, the m4 macros for autoconf are
-available in @file{ltdl.m4}. You must ensure that they are available in
-@file{aclocal.m4} before you run autoconf -- by appending the contents
-of @file{ltdl.m4} to @file{acinclude.m4}, if you are using automake, or
-to @file{aclocal.m4} if you are not. Having made the macros available,
-you must add a call to the @samp{AC_LIB_LTDL} macro to your package's
-@file{configure.in} to perform the configure time checks required to
-build @file{ltdl.o} correctly. This method has problems if you then try
-to link the package binaries with an installed libltdl, or a library
-which depends on libltdl: you may have problems with duplicate symbol
-definitions.
+Some of the internal information about each loaded module that is
+maintained by libltdl is available to the user, in the form of this
+structure:
-One advantage of the convenience library is that it is not installed, so
-the fact that you use libltdl will not be apparent to the user, and it
-will not overwrite a pre-installed version of libltdl a user might have.
-On the other hand, if you want to upgrade libltdl for any reason
-(e.g. a bugfix) you'll have to recompile your package instead of just
-replacing an installed version of libltdl.
-However, if your programs or libraries are linked with other libraries
-that use such a pre-installed version of libltdl, you may get linker
-errors or run-time crashes. Another problem is that you cannot link the
-convenience library into more than one libtool library, then link a
-single program with these libraries, because you may get duplicate
-symbols. In general you can safely use the convenience library in programs
-which don't depend on other libraries that might use libltdl too.
-In order to enable this flavor of libltdl, you should add the
-line @samp{AC_LIBLTDL_CONVENIENCE} to your @file{configure.in},
-@emph{before} @samp{AC_PROG_LIBTOOL}.
+@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 real module file name. If the module is a libtool module then
+@var{name} is its module name (e.g. @code{"libfoo"} for
+@code{"dir/libfoo.la"}), otherwise it is set to @code{NULL}. The
+@var{ref_count} attribute is a reference counter that describes how
+often the same module is currently loaded.
+@end deftypefn
-In order to select the installable version of libltdl, you should add a
-call of the macro @samp{AC_LIBLTDL_INSTALLABLE} to your
-@file{configure.in} @emph{before} @samp{AC_PROG_LIBTOOL}. This macro
-will check whether libltdl is already installed and, if not, request the
-libltdl embedded in your package to be built and installed. Note,
-however, that no version checking is performed. The user may override
-the test and determine that the libltdl embedded must be installed,
-regardless of the existence of another version, using the configure
-switch @samp{--enable-ltdl-install}.
+The following function will return a pointer to libltdl's internal copy
+of this structure for the given @var{handle}:
-In order to embed libltdl into your package, just add @samp{--ltdl} to
-the @code{libtoolize} command line. It will copy the libltdl sources
-to a subdirectory @samp{libltdl} in your package.
-Both macros accept an optional argument to specify the location
-of the @samp{libltdl} directory. By the default both macros assume that it
-is @samp{$@{top_srcdir@}/libltdl}.
-
-Whatever macro you use, it is up to you to ensure that your
-@file{configure.in} will configure libltdl, using
-@samp{AC_CONFIG_SUBDIRS}, and that your @file{Makefile}s will start
-sub-makes within libltdl's directory, using automake's @var{SUBDIRS},
-for example. Both macros define the shell variables @var{LIBLTDL}, to
-the link flag that you should use to link with libltdl, and
-@var{INCLTDL}, to the preprocessor flag that you should use to compile
-with programs that include @file{ltdl.h}. It is up to you to use
-@samp{AC_SUBST} to ensure that this variable will be available in
-@file{Makefile}s, or add them to variables that are @samp{AC_SUBST}ed by
-default, such as @var{LIBS} and @var{CPPFLAGS}.
+@deftypefun {const lt_dlinfo *} lt_dlgetinfo (@w{lt_dlhandle @var{handle}})
+Return a pointer to a struct that contains some information about
+the module @var{handle}. The contents of the struct must not be modified.
+Return @code{NULL} on failure.
+@end deftypefun
-If you're using the convenience libltdl, @var{LIBLTDL} will be the
-pathname for the convenience version of libltdl and @var{INCLTDL} will be
-@samp{-I} followed by the directory that contains libltdl, both starting
-with @samp{$@{top_builddir@}/} or @samp{$@{top_srcdir@}/}, respectively.
+Furthermore, in order to save you from having to keep a list of the
+handles of all the modules you have loaded, this function will supply
+the @var{handle} for each loaded module to a given callback:
-If you request an installed version of libltdl and one is
-found@footnote{Even if libltdl is installed,
-@samp{AC_LIBLTDL_INSTALLABLE} may fail to detect it, if libltdl depends
-on symbols provided by libraries other than the C library. In this
-case, it will needlessly build and install libltdl.}, @var{LIBLTDL} will
-be set to @samp{-lltdl} and @var{INCLTDL} will be empty (which is just a
-blind assumption that @file{ltdl.h} is somewhere in the include path if
-libltdl is in the library path). If an installable version of libltdl
-must be built, its pathname, starting with @samp{$@{top_builddir@}/},
-will be stored in @var{LIBLTDL}, and @var{INCLTDL} will be set just like
-in the case of convenience library.
+@deftypefun int lt_dlforeach (@w{int (*@var{func}) (lt_dlhandle @var{handle}, lt_ptr @var{data})}, @w{lt_ptr @var{data}})
+For each loaded module call the function @var{func}. The argument
+@var{handle} is the handle of one of the loaded modules, @var{data} is
+the @var{data} argument passed to @code{lt_dlforeach}.
+As soon as @var{func} returns a non-zero value for one of the handles,
+@code{lt_dlforeach} will stop calling @var{func} and immediately return 1.
+Otherwise 0 is returned.
+@end deftypefun
-So, when you want to link a program with libltdl, be it a convenience,
-installed or installable library, just compile with @samp{$(INCLTDL)}
-and link it with @samp{$(LIBLTDL)}, using libtool.
+Of course, you would still need to maintain your own list of loaded
+module handles to parallel the list maintained by libltdl if there are
+any other data that you need to associate with each handle for the
+purposes of your application. However, if you use the following
+@sc{api} calls to associate your application data with individual module
+handles as they are loaded there is actually no need to do that. You
+must first obtain a unique caller id from libltdl which you subsequently
+use to retrieve the data you stored earlier. This allows for different
+libraries that each wish to store their own data against loaded modules
+to do so without interfering with one another's data.
+
+@deftp {Type} lt_dlcaller_id
+The opaque type used to hold individual data set keys.
+@end deftp
-You should probably also add @samp{AC_LIBTOOL_DLOPEN} to your
-@file{configure.in} @emph{before} @samp{AC_PROG_LIBTOOL}, otherwise
-libtool will assume no dlopening mechanism is supported, and revert to
-dlpreopening, which is probably not what you want.
+@deftypefun lt_dlcaller_id lt_dlcaller_register (void)
+Use this to obtain a unique key to store and retrieve individual sets of
+per module data.
+@end deftypefun
-Avoid using the @code{-static} or @code{-all-static} switches when
-linking programs with libltdl. This will not work on all platforms,
-because the dlopening functions may not be available for static linking.
+@deftypefun lt_ptr lt_dlcaller_set_data (@w{lt_dlcaller_id @var{key}}, @w{lt_dlhandle @var{handle}}, @w{lt_ptr @var{data}})
+Set @var{data} as the set of data uniquely associated with @var{key} and
+@var{handle} for later retrieval. This function returns the @var{data}
+previously associated with @var{key} and @var{handle} if any. A result of
+0, may indicate that a diagnostic for the last error (if any) is available
+from @code{lt_dlerror()}.
-The following example shows you how to embed the convenience libltdl in
-your package. In order to use the installable variant just replace
-@samp{AC_LIBLTDL_CONVENIENCE} with @samp{AC_LIBLTDL_INSTALLABLE}. We
-assume that libltdl was embedded using @samp{libtoolize --ltdl}.
+For example, to correctly remove some associated data:
-configure.in:
@example
-...
-dnl Enable building of the convenience library
-dnl and set LIBLTDL accordingly
-AC_LIBLTDL_CONVENIENCE
-dnl Substitute INCLTDL and LIBLTDL in the Makefiles
-AC_SUBST(INCLTDL)
-AC_SUBST(LIBLTDL)
-dnl Check for dlopen support
-AC_LIBTOOL_DLOPEN
-dnl Configure libtool
-AC_PROG_LIBTOOL
-dnl Configure libltdl
-AC_CONFIG_SUBDIRS(libltdl)
-...
+ lt_ptr stale = lt_dlcaller_set_data (key, handle, 0);
+ if (stale == NULL)
+ @{
+ char *error_msg = lt_dlerror ();
+
+ if (error_msg != NULL)
+ @{
+ my_error_handler (error_msg);
+ return STATUS_FAILED;
+ @}
+ @}
+ else
+ @{
+ free (stale);
+ @}
@end example
+@end deftypefun
+
+@deftypefun lt_ptr lt_dlcaller_get_data (@w{lt_dlcaller_id @var{key}}, @w{lt_dlhandle @var{handle}})
+Return the address of the data associated with @var{key} and
+@var{handle}, or else @code{NULL} if there is none.
+@end deftypefun
+
+The preceding functions can be combined with @code{lt_dlforeach} to
+implement search and apply operations without the need for your
+application to track the modules that have been loaded and unloaded:
-Makefile.am:
@example
-...
-SUBDIRS = libltdl
+int
+my_dlcaller_callback (lt_dlhandle handle, lt_ptr key_ptr)
+@{
+ struct my_module_data *my_data;
-INCLUDES = $(INCLTDL)
+ my_data = lt_dlcaller_get_data (handle, (lt_dlcaller_id) *key_ptr);
-myprog_LDFLAGS = -export-dynamic
-# The quotes around -dlopen below fool automake <= 1.4 into accepting it
-myprog_LDADD = $(LIBLTDL) "-dlopen" self "-dlopen" foo1.la
-myprog_DEPENDENCIES = $(LIBLTDL) foo1.la
-...
+ return process (my_data);
+@}
+
+int
+my_dlcaller_foreach (lt_dlcaller_id key)
+@{
+ lt_dlforeach (my_dlcaller_callback, (lt_ptr) &key);
+@}
@end example
+
@node Module loaders for libltdl
@section How to create and register new module loaders
@end example
@end deftypefun
+@node Distributing libltdl
+@section How to distribute libltdl with your package
+
+Even though libltdl is installed together with libtool, you may wish to
+include libltdl in the distribution of your package, for the convenience
+of users of your package that don't have libtool or libltdl installed.
+In this case, you must decide whether to manually add the @code{ltdl}
+objects to your package, or else which flavor of libltdl you want to use:
+a convenience library or an installable libtool library.
+
+The most simplistic way to add @code{libltdl} to your package is to copy
+the source files, @file{ltdl.c} and @file{ltdl.h}, to a source directory
+withing your package and to build and link them along with the rest of
+your sources. To help you do this, the m4 macros for autoconf are
+available in @file{ltdl.m4}. You must ensure that they are available in
+@file{aclocal.m4} before you run autoconf -- by appending the contents
+of @file{ltdl.m4} to @file{acinclude.m4}, if you are using automake, or
+to @file{aclocal.m4} if you are not. Having made the macros available,
+you must add a call to the @samp{AC_LIB_LTDL} macro to your package's
+@file{configure.in} to perform the configure time checks required to
+build @file{ltdl.o} correctly. This method has problems if you then try
+to link the package binaries with an installed libltdl, or a library
+which depends on libltdl: you may have problems with duplicate symbol
+definitions.
+
+One advantage of the convenience library is that it is not installed, so
+the fact that you use libltdl will not be apparent to the user, and it
+will not overwrite a pre-installed version of libltdl a user might have.
+On the other hand, if you want to upgrade libltdl for any reason
+(e.g. a bugfix) you'll have to recompile your package instead of just
+replacing an installed version of libltdl.
+However, if your programs or libraries are linked with other libraries
+that use such a pre-installed version of libltdl, you may get linker
+errors or run-time crashes. Another problem is that you cannot link the
+convenience library into more than one libtool library, then link a
+single program with these libraries, because you may get duplicate
+symbols. In general you can safely use the convenience library in programs
+which don't depend on other libraries that might use libltdl too.
+In order to enable this flavor of libltdl, you should add the
+line @samp{AC_LIBLTDL_CONVENIENCE} to your @file{configure.in},
+@emph{before} @samp{AC_PROG_LIBTOOL}.
+
+In order to select the installable version of libltdl, you should add a
+call of the macro @samp{AC_LIBLTDL_INSTALLABLE} to your
+@file{configure.in} @emph{before} @samp{AC_PROG_LIBTOOL}. This macro
+will check whether libltdl is already installed and, if not, request the
+libltdl embedded in your package to be built and installed. Note,
+however, that no version checking is performed. The user may override
+the test and determine that the libltdl embedded must be installed,
+regardless of the existence of another version, using the configure
+switch @samp{--enable-ltdl-install}.
+
+In order to embed libltdl into your package, just add @samp{--ltdl} to
+the @code{libtoolize} command line. It will copy the libltdl sources
+to a subdirectory @samp{libltdl} in your package.
+Both macros accept an optional argument to specify the location
+of the @samp{libltdl} directory. By the default both macros assume that it
+is @samp{$@{top_srcdir@}/libltdl}.
+
+Whatever macro you use, it is up to you to ensure that your
+@file{configure.in} will configure libltdl, using
+@samp{AC_CONFIG_SUBDIRS}, and that your @file{Makefile}s will start
+sub-makes within libltdl's directory, using automake's @var{SUBDIRS},
+for example. Both macros define the shell variables @var{LIBLTDL}, to
+the link flag that you should use to link with libltdl, and
+@var{INCLTDL}, to the preprocessor flag that you should use to compile
+with programs that include @file{ltdl.h}. It is up to you to use
+@samp{AC_SUBST} to ensure that this variable will be available in
+@file{Makefile}s, or add them to variables that are @samp{AC_SUBST}ed by
+default, such as @var{LIBS} and @var{CPPFLAGS}.
+
+If you're using the convenience libltdl, @var{LIBLTDL} will be the
+pathname for the convenience version of libltdl and @var{INCLTDL} will be
+@samp{-I} followed by the directory that contains libltdl, both starting
+with @samp{$@{top_builddir@}/} or @samp{$@{top_srcdir@}/}, respectively.
+
+If you request an installed version of libltdl and one is
+found@footnote{Even if libltdl is installed,
+@samp{AC_LIBLTDL_INSTALLABLE} may fail to detect it, if libltdl depends
+on symbols provided by libraries other than the C library. In this
+case, it will needlessly build and install libltdl.}, @var{LIBLTDL} will
+be set to @samp{-lltdl} and @var{INCLTDL} will be empty (which is just a
+blind assumption that @file{ltdl.h} is somewhere in the include path if
+libltdl is in the library path). If an installable version of libltdl
+must be built, its pathname, starting with @samp{$@{top_builddir@}/},
+will be stored in @var{LIBLTDL}, and @var{INCLTDL} will be set just like
+in the case of convenience library.
+
+So, when you want to link a program with libltdl, be it a convenience,
+installed or installable library, just compile with @samp{$(INCLTDL)}
+and link it with @samp{$(LIBLTDL)}, using libtool.
+
+You should probably also add @samp{AC_LIBTOOL_DLOPEN} to your
+@file{configure.in} @emph{before} @samp{AC_PROG_LIBTOOL}, otherwise
+libtool will assume no dlopening mechanism is supported, and revert to
+dlpreopening, which is probably not what you want.
+
+Avoid using the @code{-static} or @code{-all-static} switches when
+linking programs with libltdl. This will not work on all platforms,
+because the dlopening functions may not be available for static linking.
+
+The following example shows you how to embed the convenience libltdl in
+your package. In order to use the installable variant just replace
+@samp{AC_LIBLTDL_CONVENIENCE} with @samp{AC_LIBLTDL_INSTALLABLE}. We
+assume that libltdl was embedded using @samp{libtoolize --ltdl}.
+
+configure.in:
+@example
+...
+dnl Enable building of the convenience library
+dnl and set LIBLTDL accordingly
+AC_LIBLTDL_CONVENIENCE
+dnl Substitute INCLTDL and LIBLTDL in the Makefiles
+AC_SUBST(INCLTDL)
+AC_SUBST(LIBLTDL)
+dnl Check for dlopen support
+AC_LIBTOOL_DLOPEN
+dnl Configure libtool
+AC_PROG_LIBTOOL
+dnl Configure libltdl
+AC_CONFIG_SUBDIRS(libltdl)
+...
+@end example
+
+Makefile.am:
+@example
+...
+SUBDIRS = libltdl
+
+INCLUDES = $(INCLTDL)
+
+myprog_LDFLAGS = -export-dynamic
+# The quotes around -dlopen below fool automake <= 1.4 into accepting it
+myprog_LDADD = $(LIBLTDL) "-dlopen" self "-dlopen" foo1.la
+myprog_DEPENDENCIES = $(LIBLTDL) foo1.la
+...
+@end example
+
@node Other languages
@chapter Using libtool with other languages
@cindex C, not using
#undef LT_SYMBOL_OVERHEAD
#define LT_SYMBOL_OVERHEAD 5
+
+
+\f
+/* --- TYPE DEFINITIONS -- */
+
+
+/* This type is used for the array of caller data sets in each handler. */
+typedef struct {
+ lt_dlcaller_id key;
+ lt_ptr data;
+} lt_caller_data;
+
+
+
\f
/* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
lt_dlhandle *deplibs; /* dependencies */
lt_module module; /* system module handle */
lt_ptr system; /* system specific data */
+ lt_caller_data *caller_data; /* per caller associated data */
int flags; /* various boolean stats */
};
static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
#endif
+
+
+\f
+/* --- MEMORY HANDLING --- */
+
+
LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size))
= (lt_ptr (*) LT_PARAMS((size_t))) malloc;
LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr))
= (void (*) LT_PARAMS((lt_ptr))) free;
+static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr,
+ size_t size));
+
+#define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
+#define LT_DLREALLOC(tp, p, n) ((tp *) rpl_realloc ((p), (n) * sizeof(tp)))
+#define LT_DLFREE(p) \
+ LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
+
+#define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \
+ if ((p) != (q)) { lt_dlfree (p); (p) = (q); } \
+ } LT_STMT_END
+
\f
/* --- ERROR MESSAGES --- */
const char *diagnostic;
{
int index = errorcode - LT_ERROR_MAX;
- const char **temp = 0;
+ const char **temp = 0;
- /* realloc is not entirely portable, so simulate it using
- lt_dlmalloc and lt_dlfree. */
- temp = (const char **) lt_dlmalloc ((1+index) * sizeof (const char*));
+ temp = LT_DLREALLOC (const char *, user_error_strings, 1 + index);
if (temp == 0)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
return -1;
}
-
- /* Build the new vector in the memory addressed by temp. */
- temp[index] = diagnostic;
- while (--index >= 0)
+ else
{
- temp[index] = user_error_strings[index];
+ user_error_strings = temp;
}
- lt_dlfree (user_error_strings);
- user_error_strings = temp;
+ user_error_strings[index] = diagnostic;
return errorcode++;
}
last_error = LT_DLSTRERROR (INVALID_ERRORCODE);
return 1;
}
-
+
if (index < LT_ERROR_MAX)
{
last_error = lt_dlerror_strings[errorcode];
if (str)
{
- tmp = (char*) lt_dlmalloc (1+ strlen (str));
+ tmp = LT_DLMALLOC (char, 1+ strlen (str));
if (tmp)
{
strcpy(tmp, str);
return -1;
if (str2 == 0)
return 1;
-
+
for (;*str1 && *str2; ++str1, ++str2)
{
if (*str1 != *str2)
break;
}
-
+
return (int)(*str1 - *str2);
}
#endif
-
+
#if ! HAVE_STRCHR
# endif
#endif
+/* NOTE: Neither bcopy nor the memcpy implementation below can
+ reliably handle copying in overlapping areas of memory, so
+ do not rely on this behaviour when invoking memcpy later. */
+#if ! HAVE_MEMCPY
+
+# if HAVE_BCOPY
+# define memcpy(dest, src, size) bcopy (src, dest, size)
+# else
+# define memcpy rpl_memcpy
+
+static inline char *
+memcpy (dest, src, size)
+ char *dest;
+ const char *src;
+ size_t size;
+{
+ size_t i = 0;
+
+ for (i = 0; i < size; ++i)
+ {
+ dest[i] = src[i];
+ }
+
+ return dest;
+}
+
+# endif
+#endif
+
+/* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
+ ``realloc is not entirely portable''
+ In any case we want to use the allocator supplied by the user without
+ burdening them with an lt_dlrealloc function pointer to maintain.
+ Instead implement our own version (with known boundary conditions)
+ using lt_dlmalloc and lt_dlfree. */
+static lt_ptr
+rpl_realloc (ptr, size)
+ lt_ptr ptr;
+ size_t size;
+{
+ if (size < 1)
+ {
+ /* For zero or less bytes, free the original memory */
+ if (ptr != 0)
+ {
+ lt_dlfree (ptr);
+ }
+
+ return (lt_ptr) 0;
+ }
+ else if (ptr == 0)
+ {
+ /* Allow reallocation of a NULL pointer. */
+ return lt_dlmalloc (size);
+ }
+ else
+ {
+ /* Allocate a new block, copy and free the old block. */
+ lt_ptr mem = lt_dlmalloc (size);
+
+ if (mem)
+ {
+ memcpy (mem, ptr, size);
+ lt_dlfree (ptr);
+ }
+
+ /* Note that the contents of PTR are not damaged if there is
+ insufficient memory to realloc. */
+ return mem;
+ }
+}
+
\f
const char *symbol;
{
lt_ptr address = dlsym (module, symbol);
-
+
if (!address)
{
last_error = DLERROR (SYMBOL_NOT_FOUND);
}
-
+
return address;
}
*
* Optionally:
* BIND_FIRST - Place the library at the head of the symbol search
- * order.
+ * order.
* BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all
* unsatisfied symbols as fatal. This flag allows
* binding of unsatisfied code symbols to be deferred
* when the library is loaded, nor on a future call to
* shl_unload().
* BIND_VERBOSE - Print verbose messages concerning possible
- * unsatisfied symbols.
+ * unsatisfied symbols.
*
* hp9000s700/hp9000s800:
* BIND_RESTRICTED - Restrict symbols visible by the library to those
{
/* Append a `.' to stop Windows from adding an
implicit `.dll' extension. */
- searchname = (char*) lt_dlmalloc (2+ strlen (filename));
+ searchname = LT_DLMALLOC (char, 2+ strlen (filename));
if (!searchname)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
}
module = LoadLibrary (searchname);
- lt_dlfree (searchname);
-
+ LT_DLFREE (searchname);
+
/* libltdl expects this function to fail if it is unable
to physically load the library. Sadly, LoadLibrary
will search the loaded libraries for a match and return
const char *symbol;
{
lt_ptr address = GetProcAddress (module, symbol);
-
+
if (!address)
{
last_error = LT_DLSTRERROR (SYMBOL_NOT_FOUND);
const char *filename;
{
image_id image = 0;
-
+
if (filename)
{
image = load_add_on (filename);
}
else
{
- image_info info;
- int32 cookie = 0;
+ image_info info;
+ int32 cookie = 0;
if (get_next_image_info (0, &cookie, &info) == B_OK)
image = load_add_on (info.name);
}
-
+
if (image <= 0)
{
last_error = LT_DLSTRERROR (CANNOT_OPEN);
{
lt_ptr address = 0;
image_id image = (image_id) module;
-
+
if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
{
last_error = LT_DLSTRERROR (SYMBOL_NOT_FOUND);
last_error = LT_DLSTRERROR (NO_MEMORY);
return 0;
}
-
+
if (dld_link (filename) != 0)
{
last_error = LT_DLSTRERROR (CANNOT_OPEN);
- lt_dlfree(module);
+ LT_DLFREE (module);
return 0;
}
last_error = LT_DLSTRERROR (CANNOT_CLOSE);
return 1;
}
- lt_dlfree (module);
+ LT_DLFREE (module);
return 0;
}
{
last_error = LT_DLSTRERROR (SYMBOL_NOT_FOUND);
}
-
+
return address;
}
{
return lt_dlpreload (default_preloaded_symbols);
}
-
+
return 0;
}
presym_free_symlists ()
{
lt_dlsymlists_t *lists = preloaded_symbols;
-
+
while (lists)
{
lt_dlsymlists_t *tmp = lists;
-
+
lists = lists->next;
- lt_dlfree (tmp);
+ LT_DLFREE (tmp);
}
preloaded_symbols = 0;
{
lt_dlsymlists_t *tmp;
lt_dlsymlists_t *lists = preloaded_symbols;
-
+
while (lists)
{
if (lists->syms == preloaded)
lists = lists->next;
}
- tmp = (lt_dlsymlists_t*) lt_dlmalloc (sizeof (lt_dlsymlists_t));
+ tmp = LT_DLMALLOC (lt_dlsymlists_t, 1);
if (!tmp)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
while (lists)
{
const lt_dlsymlist *syms = lists->syms;
-
+
while (syms->name)
{
if (!syms->address && strcmp(syms->name, filename) == 0)
{
return syms->address;
}
-
+
++syms;
}
{
handles = 0;
user_search_path = 0; /* empty search path */
-
+
#if HAVE_LIBDL && !defined(__CYGWIN__)
errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
-#endif
+#endif
#if HAVE_SHL_LOAD
errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
#endif
last_error = 0;
}
}
-
+
return errors;
}
/* shut down libltdl */
lt_dlloader *loader = loaders;
int errors = 0;
-
+
if (!initialized)
{
last_error = LT_DLSTRERROR (SHUTDOWN);
return 1;
}
-
+
/* shut down only at last call. */
if (--initialized == 0)
{
}
}
}
-
+
/* close all loaders */
while (loader)
{
++errors;
}
- lt_dlfree (loader);
- loader = next;
+ LT_DLMEM_REASSIGN (loader, next);
}
loaders = 0;
}
lt_dlhandle cur = handles;
lt_dlloader *loader = loaders;
const char *saved_error = last_error;
-
+
/* check whether the module was already opened */
while (cur)
{
*handle = cur;
return 0;
}
-
+
cur = *handle;
if (filename)
{
if (!loader)
{
- if (cur->info.filename)
- {
- lt_dlfree(cur->info.filename);
- }
+ LT_DLFREE (cur->info.filename);
return 1;
}
int error;
char *filename;
- /* try to open the old library first; if it was dlpreopened,
+ /* try to open the old library first; if it was dlpreopened,
we want the preopened version of it, even if a dlopenable
module is available */
if (old_name && tryall_dlopen(handle, old_name) == 0)
if (dlname)
{
size_t len;
-
+
/* try to open the installed module */
if (installed && libdir)
{
len = strlen (libdir) + 1 + strlen (dlname);
- filename = (char*) lt_dlmalloc (1+ len);
+ filename = LT_DLMALLOC (char, 1+ len);
if (!filename)
{
sprintf (filename, "%s/%s", libdir, dlname);
error = (tryall_dlopen (handle, filename) != 0);
- lt_dlfree (filename);
+ LT_DLFREE (filename);
if (!error)
{
if (!installed)
{
len = (dir ? strlen (dir) : 0) + strlen (objdir) + strlen (dlname);
- filename = (char*) lt_dlmalloc(1+ len);
+ filename = LT_DLMALLOC (char, 1+ len);
if (!filename)
{
strcat(filename, dlname);
error = tryall_dlopen (handle, filename) != 0;
- lt_dlfree (filename);
+ LT_DLFREE (filename);
if (!error)
{
return 0;
/* maybe it was moved to another directory */
{
len = (dir ? strlen (dir) : 0) + strlen (dlname);
- filename = (char*) lt_dlmalloc (1+ len);
+ filename = LT_DLMALLOC (char, 1+ len);
if (dir)
{
strcat(filename, dlname);
error = (tryall_dlopen (handle, filename) != 0);
- lt_dlfree (filename);
+ LT_DLFREE (filename);
if (!error)
{
return 0;
const char *path;
{
char *canonical = 0;
-
+
if (path && *path)
{
char *ptr = strdup (path);
int lenbase = strlen (basename);
char *canonical = 0;
char *next = 0;
-
+
if (!search_path || !*search_path)
{
last_error = LT_DLSTRERROR (FILE_NOT_FOUND);
if (lendir + 1 + lenbase >= filenamesize)
{
- if (filename)
- {
- lt_dlfree (filename);
- }
-
+ LT_DLFREE (filename);
filenamesize = lendir + 1 + lenbase + 1;
- filename = (char*) lt_dlmalloc(filenamesize);
+ filename = LT_DLMALLOC (char, filenamesize);
if (!filename)
{
FILE *file = fopen (filename, LT_READTEXT_MODE);
if (file)
{
- if (*pdir)
- {
- lt_dlfree (*pdir);
- }
+ LT_DLFREE (*pdir);
filename[lendir] = '\0';
*pdir = strdup(filename);
}
}
}
-
+
last_error = LT_DLSTRERROR (FILE_NOT_FOUND);
cleanup:
- if (filename) lt_dlfree (filename);
- if (canonical) lt_dlfree (canonical);
+ LT_DLFREE (filename);
+ LT_DLFREE (canonical);
return result;
}
goto cleanup;
}
- names = (char**) lt_dlmalloc (depcount * sizeof (char*));
+ names = LT_DLMALLOC (char *, depcount * sizeof (char*));
if (!names)
{
goto cleanup;
}
- handles = (lt_dlhandle*) lt_dlmalloc (depcount * sizeof (lt_dlhandle*));
+ handles = (lt_dlhandle*) LT_DLMALLOC (lt_dlhandle *, depcount);
if (!handles)
{
goto cleanup;
*end = 0; /* set a temporary string terminator */
if (strncmp(p, "-l", 2) == 0)
{
- name = lt_dlmalloc(3+ /* "lib" */
- strlen(p+2)+1);
+ name = LT_DLMALLOC (char, 3+ /* "lib" */ strlen (p+2) + 1);
if (name)
{
sprintf (name, "lib%s", p+2);
goto cleanup_names;
}
- handles[i] = handle;
+ handles[i] = handle;
}
handle->depcount = depcount;
cleanup_names:
for (i = 0; i < depcount; ++i)
{
- lt_dlfree(names[i]);
+ LT_DLFREE (names[i]);
}
cleanup:
- if (names) lt_dlfree(names);
- if (handles) lt_dlfree(handles);
+ LT_DLFREE (names);
+ LT_DLFREE (handles);
/* restore the old search path */
- if (user_search_path) lt_dlfree (user_search_path);
+ LT_DLFREE (user_search_path);
user_search_path = save_search_path;
return ret;
{
int i;
int errors = 0;
-
+
if (handle->depcount)
{
for (i = 0; i < handle->depcount; ++i)
char **dest;
const char *str;
{
- /* remove the leading and trailing "'" from str
+ /* remove the leading and trailing "'" from str
and store the result in dest */
const char *end = strrchr (str, '\'');
int len = strlen (str);
char *tmp;
- if (*dest)
- {
- lt_dlfree(*dest);
- }
-
+ LT_DLFREE (*dest);
+
if (len > 3 && str[0] == '\'')
{
- tmp = (char*) lt_dlmalloc(end - str);
+ tmp = LT_DLMALLOC (char, end - str);
if (!tmp)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
{
*dest = 0;
}
-
+
return 0;
}
char *libdir;
char *deplibs;
{
- if (dlname) lt_dlfree(dlname);
- if (oldname) lt_dlfree(oldname);
- if (libdir) lt_dlfree(libdir);
- if (deplibs) lt_dlfree(deplibs);
+ LT_DLFREE (dlname);
+ LT_DLFREE (oldname);
+ LT_DLFREE (libdir);
+ LT_DLFREE (deplibs);
return 0;
}
const char *ext;
const char *saved_error = last_error;
char *canonical = 0, *basename = 0, *dir = 0, *name = 0;
-
+
/* dlopen self? */
if (!filename)
{
- handle = (lt_dlhandle) lt_dlmalloc (sizeof (struct lt_dlhandle_struct));
+ handle = (lt_dlhandle) LT_DLMALLOC (struct lt_dlhandle_struct, 1);
if (!handle)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
handle->info.ref_count = 0;
handle->depcount = 0;
handle->deplibs = 0;
+ handle->caller_data = 0;
newhandle = handle;
/* lt_dlclose()ing yourself is very bad! Disallow it. */
if (tryall_dlopen (&newhandle, 0) != 0)
{
- lt_dlfree(handle);
+ LT_DLFREE (handle);
return 0;
}
goto register_handle;
if (!canonical)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
- if (handle)
- {
- lt_dlfree(handle);
- }
+ LT_DLFREE (handle);
return 0;
}
if (basename)
{
++basename;
- dir = (char*) lt_dlmalloc (basename - canonical + 1);
+ dir = LT_DLMALLOC (char, basename - canonical + 1);
if (!dir)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
/* if we can't find the installed flag, it is probably an
installed libtool archive, produced with an old version
of libtool */
- int installed = 1;
+ int installed = 1;
/* extract the module name from the file name */
- name = (char*) lt_dlmalloc(ext - basename + 1);
+ name = LT_DLMALLOC (char, ext - basename + 1);
if (!name)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
file = (FILE*) find_file(basename, getenv("LTDL_LIBRARY_PATH"),
&dir, 0);
}
-
+
#ifdef LTDL_SHLIBPATH_VAR
if (!file)
{
{
last_error = LT_DLSTRERROR (FILE_NOT_FOUND);
}
-
+
if (!file)
{
handle = 0;
goto cleanup;
}
- line = (char*) lt_dlmalloc (LT_FILENAME_MAX);
+ line = LT_DLMALLOC (char, LT_FILENAME_MAX);
if (!line)
{
fclose (file);
{
error = trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
}
-
+
#undef STR_OLD_LIBRARY
#define STR_OLD_LIBRARY "old_library="
else if (strncmp (line, STR_OLD_LIBRARY,
(last_libname = strrchr (dlname, ' ')) != NULL)
{
last_libname = strdup (last_libname + 1);
- lt_dlfree (dlname);
- dlname = last_libname;
+ LT_DLMEM_REASSIGN (dlname, last_libname);
}
}
}
fclose (file);
- lt_dlfree (line);
+ LT_DLFREE (line);
/* allocate the handle */
- handle = (lt_dlhandle) lt_dlmalloc (sizeof (struct lt_dlhandle_struct));
+ handle = (lt_dlhandle) LT_DLMALLOC (struct lt_dlhandle_struct, 1);
if (!handle || error)
{
- if (handle)
- {
- lt_dlfree(handle);
- }
+ LT_DLFREE (handle);
if (!error)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
free_vars (dlname, old_name, libdir, deplibs);
if (error)
{
- lt_dlfree (handle);
- handle = 0;
+ LT_DLFREE (handle);
goto cleanup;
}
else
{
/* not a libtool module */
- handle = (lt_dlhandle) lt_dlmalloc (sizeof (struct lt_dlhandle_struct));
+ handle = (lt_dlhandle) LT_DLMALLOC (struct lt_dlhandle_struct, 1);
if (!handle)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
#endif
)) && tryall_dlopen (&newhandle, filename))
{
- lt_dlfree (handle);
- handle = 0;
+ LT_DLFREE (handle);
goto cleanup;
}
}
register_handle:
- if (newhandle != handle)
- {
- lt_dlfree(handle);
- handle = newhandle;
- }
+ LT_DLMEM_REASSIGN (handle, newhandle);
if (handle->info.ref_count == 0)
{
last_error = saved_error;
cleanup:
- if (dir) lt_dlfree(dir);
- if (name) lt_dlfree(name);
- if (canonical) lt_dlfree(canonical);
+ LT_DLFREE (dir);
+ LT_DLFREE (name);
+ LT_DLFREE (canonical);
return handle;
}
char *tmp;
int len;
const char *saved_error = last_error;
-
+
if (!filename)
{
return lt_dlopen (filename);
}
/* try "filename.la" */
- tmp = (char*) lt_dlmalloc (len+4);
+ tmp = LT_DLMALLOC (char, len+4);
if (!tmp)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
if (handle)
{
last_error = saved_error;
- lt_dlfree (tmp);
+ LT_DLFREE (tmp);
return handle;
}
/* try "filename.EXT" */
if (strlen(shlib_ext) > 3)
{
- lt_dlfree (tmp);
- tmp = (char*) lt_dlmalloc (len + strlen (shlib_ext) + 1);
+ LT_DLFREE (tmp);
+ tmp = LT_DLMALLOC (char, len + strlen (shlib_ext) + 1);
if (!tmp)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
if (handle)
{
last_error = saved_error;
- lt_dlfree (tmp);
+ LT_DLFREE (tmp);
return handle;
}
-#endif
+#endif
/* try the normal file name */
handle = lt_dlopen (filename);
{
return handle;
}
-
+
last_error = LT_DLSTRERROR (FILE_NOT_FOUND);
- lt_dlfree (tmp);
+ LT_DLFREE (tmp);
return 0;
}
lt_dlhandle handle;
{
lt_dlhandle cur, last;
-
+
/* check whether the handle is valid */
last = cur = handles;
while (cur && handle != cur)
{
int error;
lt_user_data data = handle->loader->dlloader_data;
-
+
if (handle != handles)
{
last->next = handle->next;
error = handle->loader->module_close (data, handle->module);
error += unload_deplibs(handle);
- if (handle->info.filename)
- {
- lt_dlfree (handle->info.filename);
- }
-
- if (handle->info.name)
- {
- lt_dlfree (handle->info.name);
- }
+ LT_DLFREE (handle->info.filename);
+ LT_DLFREE (handle->info.name);
- lt_dlfree (handle);
+ LT_DLFREE (handle);
return error;
}
last_error = LT_DLSTRERROR (CLOSE_RESIDENT_MODULE);
return 1;
}
-
+
return 0;
}
}
else
{
- sym = (char*) lt_dlmalloc(lensym + LT_SYMBOL_OVERHEAD + 1);
+ sym = LT_DLMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
}
if (!sym)
if (handle->info.name)
{
const char *saved_error = last_error;
-
+
/* this is a libtool module */
if (handle->loader->sym_prefix)
{
{
if (sym != lsym)
{
- lt_dlfree(sym);
+ LT_DLFREE (sym);
}
return address;
}
address = handle->loader->find_sym (data, handle->module, sym);
if (sym != lsym)
{
- lt_dlfree(sym);
+ LT_DLFREE (sym);
}
return address;
lt_dlerror ()
{
const char *error = last_error;
-
+
last_error = 0;
return error;
}
else
{
size_t len = strlen (user_search_path) + 1 + strlen (search_dir);
- char *new_search_path = (char*) lt_dlmalloc (1+ len);
+ char *new_search_path = LT_DLMALLOC (char, 1+ len);
if (!new_search_path)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
return 1;
}
-
+
sprintf (new_search_path, "%s%c%s", user_search_path,
LT_PATHSEP_CHAR, search_dir);
- lt_dlfree (user_search_path);
- user_search_path = new_search_path;
+ LT_DLMEM_REASSIGN (user_search_path, new_search_path);
}
return 0;
lt_dlsetsearchpath (search_path)
const char *search_path;
{
- if (user_search_path)
- {
- lt_dlfree (user_search_path);
- user_search_path = 0;
- }
+ LT_DLFREE (user_search_path);
if (!search_path || !strlen (search_path))
{
return LT_DLIS_RESIDENT (handle);
}
+
+
+\f
+/* --- MODULE INFORMATION --- */
+
const lt_dlinfo *
lt_dlgetinfo (handle)
lt_dlhandle handle;
return 0;
}
+lt_dlcaller_id
+lt_dlcaller_register ()
+{
+ static unsigned last_caller_id = -1;
+
+ return ++last_caller_id;
+}
+
+#define N_ELEMENTS(a) (sizeof(a) / sizeof(*(a)))
+
+lt_ptr
+lt_dlcaller_set_data (key, handle, data)
+ lt_dlcaller_id key;
+ lt_dlhandle handle;
+ lt_ptr data;
+{
+ int n_elements = 0;
+ lt_ptr stale = (lt_ptr) 0;
+ int i;
+
+ if (handle->caller_data)
+ n_elements = N_ELEMENTS (handle->caller_data);
+
+ for (i = 0; i < n_elements; ++i)
+ {
+ if (handle->caller_data[i].key == key)
+ {
+ stale = handle->caller_data[i].data;
+ break;
+ }
+ }
+
+ /* Ensure that there is enough room in this handle's caller_data
+ array to accept a new element. */
+ if (i == n_elements)
+ {
+ lt_caller_data *temp
+ = LT_DLREALLOC (lt_caller_data, handle->caller_data, 1+ n_elements);
+
+ if (temp == 0)
+ {
+ last_error = LT_DLSTRERROR (NO_MEMORY);
+ return (lt_ptr) 0;
+ }
+ else
+ {
+ handle->caller_data = temp;
+ }
+
+ /* We only need this if we needed to allocate a new caller_data. */
+ handle->caller_data[i].key = key;
+ }
+
+ handle->caller_data[i].data = data;
+
+ return stale;
+}
+
+lt_ptr
+lt_dlcaller_get_data (key, handle)
+ lt_dlcaller_id key;
+ lt_dlhandle handle;
+{
+ lt_ptr result = (lt_ptr) 0;
+ int n_elements = 0;
+
+ if (handle->caller_data)
+ n_elements = N_ELEMENTS (handle->caller_data);
+
+ /* Locate the index of the element with a matching KEY. */
+ {
+ int i;
+ for (i = 0; i < n_elements; ++i)
+ {
+ if (handle->caller_data[i].key == key)
+ {
+ result = handle->caller_data[i].data;
+ break;
+ }
+ }
+ }
+
+ return result;
+}
+
+
+\f
+/* --- USER MODULE LOADER API --- */
+
+
int
lt_dlloader_add (place, dlloader, loader_name)
lt_dlloader *place;
const char *loader_name;
{
lt_dlloader *node = 0, *ptr = 0;
-
+
if ((dlloader == 0) /* diagnose null parameters */
|| (dlloader->module_open == 0)
|| (dlloader->module_close == 0)
}
/* Create a new dlloader node with copies of the user callbacks. */
- node = (lt_dlloader *) lt_dlmalloc (sizeof (lt_dlloader));
+ node = LT_DLMALLOC (lt_dlloader, 1);
if (node == 0)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
node->module_close = dlloader->module_close;
node->find_sym = dlloader->find_sym;
node->dlloader_data = dlloader->dlloader_data;
-
+
if (!loaders)
{
/* If there are no loaders, NODE becomes the list! */
return 1;
}
}
-
+
if (place == loaders)
{
/* PLACE is the first loader in the list. */
place = prev->next;
prev->next = prev->next->next;
}
-
+
if (place->dlloader_exit)
{
result = place->dlloader_exit (place->dlloader_data);
}
- if (place)
- {
- lt_dlfree (place);
- }
+ LT_DLFREE (place);
return result;
}
{
return place ? place->next : loaders;
}
-
+
const char *
lt_dlloader_name (place)
lt_dlloader *place;
}
return place ? place->loader_name : 0;
-}
+}
lt_user_data *
lt_dlloader_data (place)
}
return place ? &(place->dlloader_data) : 0;
-}
+}
lt_dlloader *
lt_dlloader_find (loader_name)
return place;
}
-
int (*func) (lt_dlhandle handle, lt_ptr data),
lt_ptr data));
+/* Associating user data with loaded modules. */
+typedef unsigned lt_dlcaller_id;
+
+extern lt_dlcaller_id lt_dlcaller_register LT_PARAMS((void));
+extern lt_ptr lt_dlcaller_set_data LT_PARAMS((lt_dlcaller_id key,
+ lt_dlhandle handle,
+ lt_ptr data));
+extern lt_ptr lt_dlcaller_get_data LT_PARAMS((lt_dlcaller_id key,
+ lt_dlhandle handle));
\f
AC_CHECK_HEADERS(string.h strings.h, break)
AC_CHECK_FUNCS(strchr index, break)
AC_CHECK_FUNCS(strrchr rindex, break)
+AC_CHECK_FUNCS(memcpy bcopy, break)
AC_CHECK_FUNCS(strcmp)
AC_REQUIRE([AC_LTDL_ENABLE_INSTALL])dnl