* 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.
This commit is contained in:
Gary V. Vaughan 2001-01-05 09:33:39 +00:00
parent c821715109
commit bd96d1928a
6 changed files with 606 additions and 332 deletions

View File

@ -1,3 +1,21 @@
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> 2001-01-04 Gary V. Vaughan <gvv@techie.com>
* libltdl/ltdl.h: formatting change. * libltdl/ltdl.h: formatting change.

2
NEWS
View File

@ -13,6 +13,8 @@ New in 1.3d: 2000-??-??; CVS version 1.3c, Libtool team:
* Libtool now allows you to link shared libraries against static code. * Libtool now allows you to link shared libraries against static code.
* New functions in libltdl: * New functions in libltdl:
lt_dlgetinfo, lt_dlforeach provide access to module specific data in handles. 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_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_dlloader_remove can be used for adding new types of module loaders.
lt_dladderror, lt_dlseterror integrate user module loaders with lt_dlerror. lt_dladderror, lt_dlseterror integrate user module loaders with lt_dlerror.

View File

@ -165,8 +165,9 @@ Using libltdl
* Libltdl interface:: How to use libltdl in your programs. * Libltdl interface:: How to use libltdl in your programs.
* Modules for libltdl:: Creating modules that can be @code{dlopen}ed. * 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. * Module loaders for libltdl:: Creating user defined module loaders.
* Distributing libltdl:: How to distribute libltdl with your package.
Using libtool with other languages Using libtool with other languages
@ -2634,8 +2635,9 @@ distribution terms that you use for the rest of that program.
@menu @menu
* Libltdl interface:: How to use libltdl in your programs. * Libltdl interface:: How to use libltdl in your programs.
* Modules for libltdl:: Creating modules that can be @code{dlopen}ed. * 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. * Module loaders for libltdl:: Creating user defined module loaders.
* Distributing libltdl:: How to distribute libltdl with your package.
@end menu @end menu
@node Libltdl interface @node Libltdl interface
@ -2684,16 +2686,6 @@ The following types are defined in @file{ltdl.h}:
Every lt_dlopened module has a handle associated with it. Every lt_dlopened module has a handle associated with it.
@end deftp @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 @deftp {Type} lt_dlsymlist
@code{lt_dlsymlist} is a symbol list for dlpreopened modules. @code{lt_dlsymlist} is a symbol list for dlpreopened modules.
This structure is described in @pxref{Dlpreopening}. This structure is described in @pxref{Dlpreopening}.
@ -2863,21 +2855,6 @@ function, return -1 and set an error message for retrieval with
@code{lt_dlerror}. @code{lt_dlerror}.
@end deftypefun @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 @deftypevar {lt_ptr (*) (size_t @var{size})} lt_dlmalloc
@deftypevarx {void (*) (lt_ptr @var{ptr})} lt_dlfree @deftypevarx {void (*) (lt_ptr @var{ptr})} lt_dlfree
These variables are set to @code{malloc} and @code{free}, by default, These variables are set to @code{malloc} and @code{free}, by default,
@ -2953,143 +2930,121 @@ foo1_la_LDFLAGS = -module
... ...
@end example @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 @node User defined module data
include libltdl in the distribution of your package, for the convenience @section Data associated with loaded modules
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 Some of the internal information about each loaded module that is
the source files, @file{ltdl.c} and @file{ltdl.h}, to a source directory maintained by libltdl is available to the user, in the form of this
withing your package and to build and link them along with the rest of structure:
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 @deftypefn {Type} {struct} lt_dlinfo @{ @w{char *@var{filename};} @w{char *@var{name};} @w{int @var{ref_count};} @}
the fact that you use libltdl will not be apparent to the user, and it @code{lt_dlinfo} is used to store information about a module.
will not overwrite a pre-installed version of libltdl a user might have. The @var{filename} attribute is a null-terminated character string of
On the other hand, if you want to upgrade libltdl for any reason the real module file name. If the module is a libtool module then
(e.g. a bugfix) you'll have to recompile your package instead of just @var{name} is its module name (e.g. @code{"libfoo"} for
replacing an installed version of libltdl. @code{"dir/libfoo.la"}), otherwise it is set to @code{NULL}. The
However, if your programs or libraries are linked with other libraries @var{ref_count} attribute is a reference counter that describes how
that use such a pre-installed version of libltdl, you may get linker often the same module is currently loaded.
errors or run-time crashes. Another problem is that you cannot link the @end deftypefn
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 The following function will return a pointer to libltdl's internal copy
call of the macro @samp{AC_LIBLTDL_INSTALLABLE} to your of this structure for the given @var{handle}:
@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 @deftypefun {const lt_dlinfo *} lt_dlgetinfo (@w{lt_dlhandle @var{handle}})
the @code{libtoolize} command line. It will copy the libltdl sources Return a pointer to a struct that contains some information about
to a subdirectory @samp{libltdl} in your package. the module @var{handle}. The contents of the struct must not be modified.
Both macros accept an optional argument to specify the location Return @code{NULL} on failure.
of the @samp{libltdl} directory. By the default both macros assume that it @end deftypefun
is @samp{$@{top_srcdir@}/libltdl}.
Whatever macro you use, it is up to you to ensure that your Furthermore, in order to save you from having to keep a list of the
@file{configure.in} will configure libltdl, using handles of all the modules you have loaded, this function will supply
@samp{AC_CONFIG_SUBDIRS}, and that your @file{Makefile}s will start the @var{handle} for each loaded module to a given callback:
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 @deftypefun int lt_dlforeach (@w{int (*@var{func}) (lt_dlhandle @var{handle}, lt_ptr @var{data})}, @w{lt_ptr @var{data}})
pathname for the convenience version of libltdl and @var{INCLTDL} will be For each loaded module call the function @var{func}. The argument
@samp{-I} followed by the directory that contains libltdl, both starting @var{handle} is the handle of one of the loaded modules, @var{data} is
with @samp{$@{top_builddir@}/} or @samp{$@{top_srcdir@}/}, respectively. 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
If you request an installed version of libltdl and one is Of course, you would still need to maintain your own list of loaded
found@footnote{Even if libltdl is installed, module handles to parallel the list maintained by libltdl if there are
@samp{AC_LIBLTDL_INSTALLABLE} may fail to detect it, if libltdl depends any other data that you need to associate with each handle for the
on symbols provided by libraries other than the C library. In this purposes of your application. However, if you use the following
case, it will needlessly build and install libltdl.}, @var{LIBLTDL} will @sc{api} calls to associate your application data with individual module
be set to @samp{-lltdl} and @var{INCLTDL} will be empty (which is just a handles as they are loaded there is actually no need to do that. You
blind assumption that @file{ltdl.h} is somewhere in the include path if must first obtain a unique caller id from libltdl which you subsequently
libltdl is in the library path). If an installable version of libltdl use to retrieve the data you stored earlier. This allows for different
must be built, its pathname, starting with @samp{$@{top_builddir@}/}, libraries that each wish to store their own data against loaded modules
will be stored in @var{LIBLTDL}, and @var{INCLTDL} will be set just like to do so without interfering with one another's data.
in the case of convenience library.
So, when you want to link a program with libltdl, be it a convenience, @deftp {Type} lt_dlcaller_id
installed or installable library, just compile with @samp{$(INCLTDL)} The opaque type used to hold individual data set keys.
and link it with @samp{$(LIBLTDL)}, using libtool. @end deftp
You should probably also add @samp{AC_LIBTOOL_DLOPEN} to your @deftypefun lt_dlcaller_id lt_dlcaller_register (void)
@file{configure.in} @emph{before} @samp{AC_PROG_LIBTOOL}, otherwise Use this to obtain a unique key to store and retrieve individual sets of
libtool will assume no dlopening mechanism is supported, and revert to per module data.
dlpreopening, which is probably not what you want. @end deftypefun
Avoid using the @code{-static} or @code{-all-static} switches when @deftypefun lt_ptr lt_dlcaller_set_data (@w{lt_dlcaller_id @var{key}}, @w{lt_dlhandle @var{handle}}, @w{lt_ptr @var{data}})
linking programs with libltdl. This will not work on all platforms, Set @var{data} as the set of data uniquely associated with @var{key} and
because the dlopening functions may not be available for static linking. @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 For example, to correctly remove some associated data:
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 @example
... lt_ptr stale = lt_dlcaller_set_data (key, handle, 0);
dnl Enable building of the convenience library if (stale == NULL)
dnl and set LIBLTDL accordingly @{
AC_LIBLTDL_CONVENIENCE char *error_msg = lt_dlerror ();
dnl Substitute INCLTDL and LIBLTDL in the Makefiles
AC_SUBST(INCLTDL) if (error_msg != NULL)
AC_SUBST(LIBLTDL) @{
dnl Check for dlopen support my_error_handler (error_msg);
AC_LIBTOOL_DLOPEN return STATUS_FAILED;
dnl Configure libtool @}
AC_PROG_LIBTOOL @}
dnl Configure libltdl else
AC_CONFIG_SUBDIRS(libltdl) @{
... 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:
@example
int
my_dlcaller_callback (lt_dlhandle handle, lt_ptr key_ptr)
@{
struct my_module_data *my_data;
my_data = lt_dlcaller_get_data (handle, (lt_dlcaller_id) *key_ptr);
return process (my_data);
@}
int
my_dlcaller_foreach (lt_dlcaller_id key)
@{
lt_dlforeach (my_dlcaller_callback, (lt_ptr) &key);
@}
@end example @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 Module loaders for libltdl @node Module loaders for libltdl
@section How to create and register new module loaders @section How to create and register new module loaders
@ -3337,6 +3292,144 @@ if (lt_dlseterror (LTDL_ERROR_NO_MEMORY) != 0)
@end example @end example
@end deftypefun @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 @node Other languages
@chapter Using libtool with other languages @chapter Using libtool with other languages
@cindex C, not using @cindex C, not using

View File

@ -98,6 +98,20 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
#undef LT_SYMBOL_OVERHEAD #undef LT_SYMBOL_OVERHEAD
#define LT_SYMBOL_OVERHEAD 5 #define LT_SYMBOL_OVERHEAD 5
/* --- 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;
/* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */ /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
@ -122,6 +136,7 @@ struct lt_dlhandle_struct {
lt_dlhandle *deplibs; /* dependencies */ lt_dlhandle *deplibs; /* dependencies */
lt_module module; /* system module handle */ lt_module module; /* system module handle */
lt_ptr system; /* system specific data */ lt_ptr system; /* system specific data */
lt_caller_data *caller_data; /* per caller associated data */
int flags; /* various boolean stats */ int flags; /* various boolean stats */
}; };
@ -144,11 +159,29 @@ static const char shlib_ext[] = LTDL_SHLIB_EXT;
static const char sys_search_path[] = LTDL_SYSSEARCHPATH; static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
#endif #endif
/* --- MEMORY HANDLING --- */
LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size)) LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size))
= (lt_ptr (*) LT_PARAMS((size_t))) malloc; = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr)) LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr))
= (void (*) LT_PARAMS((lt_ptr))) free; = (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
/* --- ERROR MESSAGES --- */ /* --- ERROR MESSAGES --- */
@ -177,26 +210,20 @@ lt_dladderror (diagnostic)
const char *diagnostic; const char *diagnostic;
{ {
int index = errorcode - LT_ERROR_MAX; int index = errorcode - LT_ERROR_MAX;
const char **temp = 0; const char **temp = 0;
/* realloc is not entirely portable, so simulate it using temp = LT_DLREALLOC (const char *, user_error_strings, 1 + index);
lt_dlmalloc and lt_dlfree. */
temp = (const char **) lt_dlmalloc ((1+index) * sizeof (const char*));
if (temp == 0) if (temp == 0)
{ {
last_error = LT_DLSTRERROR (NO_MEMORY); last_error = LT_DLSTRERROR (NO_MEMORY);
return -1; return -1;
} }
else
/* Build the new vector in the memory addressed by temp. */
temp[index] = diagnostic;
while (--index >= 0)
{ {
temp[index] = user_error_strings[index]; user_error_strings = temp;
} }
lt_dlfree (user_error_strings); user_error_strings[index] = diagnostic;
user_error_strings = temp;
return errorcode++; return errorcode++;
} }
@ -240,7 +267,7 @@ strdup(str)
if (str) if (str)
{ {
tmp = (char*) lt_dlmalloc (1+ strlen (str)); tmp = LT_DLMALLOC (char, 1+ strlen (str));
if (tmp) if (tmp)
{ {
strcpy(tmp, str); strcpy(tmp, str);
@ -330,6 +357,78 @@ strrchr(str, ch)
# endif # endif
#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;
}
}
@ -600,7 +699,7 @@ sys_wll_open (loader_data, filename)
{ {
/* Append a `.' to stop Windows from adding an /* Append a `.' to stop Windows from adding an
implicit `.dll' extension. */ implicit `.dll' extension. */
searchname = (char*) lt_dlmalloc (2+ strlen (filename)); searchname = LT_DLMALLOC (char, 2+ strlen (filename));
if (!searchname) if (!searchname)
{ {
last_error = LT_DLSTRERROR (NO_MEMORY); last_error = LT_DLSTRERROR (NO_MEMORY);
@ -611,7 +710,7 @@ sys_wll_open (loader_data, filename)
} }
module = LoadLibrary (searchname); module = LoadLibrary (searchname);
lt_dlfree (searchname); LT_DLFREE (searchname);
/* libltdl expects this function to fail if it is unable /* libltdl expects this function to fail if it is unable
to physically load the library. Sadly, LoadLibrary to physically load the library. Sadly, LoadLibrary
@ -791,7 +890,7 @@ sys_dld_open (loader_data, filename)
if (dld_link (filename) != 0) if (dld_link (filename) != 0)
{ {
last_error = LT_DLSTRERROR (CANNOT_OPEN); last_error = LT_DLSTRERROR (CANNOT_OPEN);
lt_dlfree(module); LT_DLFREE (module);
return 0; return 0;
} }
@ -808,7 +907,7 @@ sys_dld_close (loader_data, module)
last_error = LT_DLSTRERROR (CANNOT_CLOSE); last_error = LT_DLSTRERROR (CANNOT_CLOSE);
return 1; return 1;
} }
lt_dlfree (module); LT_DLFREE (module);
return 0; return 0;
} }
@ -876,7 +975,7 @@ presym_free_symlists ()
lt_dlsymlists_t *tmp = lists; lt_dlsymlists_t *tmp = lists;
lists = lists->next; lists = lists->next;
lt_dlfree (tmp); LT_DLFREE (tmp);
} }
preloaded_symbols = 0; preloaded_symbols = 0;
@ -907,7 +1006,7 @@ presym_add_symlist (preloaded)
lists = lists->next; lists = lists->next;
} }
tmp = (lt_dlsymlists_t*) lt_dlmalloc (sizeof (lt_dlsymlists_t)); tmp = LT_DLMALLOC (lt_dlsymlists_t, 1);
if (!tmp) if (!tmp)
{ {
last_error = LT_DLSTRERROR (NO_MEMORY); last_error = LT_DLSTRERROR (NO_MEMORY);
@ -1135,8 +1234,7 @@ lt_dlexit ()
++errors; ++errors;
} }
lt_dlfree (loader); LT_DLMEM_REASSIGN (loader, next);
loader = next;
} }
loaders = 0; loaders = 0;
} }
@ -1208,10 +1306,7 @@ tryall_dlopen (handle, filename)
if (!loader) if (!loader)
{ {
if (cur->info.filename) LT_DLFREE (cur->info.filename);
{
lt_dlfree(cur->info.filename);
}
return 1; return 1;
} }
@ -1250,7 +1345,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed)
if (installed && libdir) if (installed && libdir)
{ {
len = strlen (libdir) + 1 + strlen (dlname); len = strlen (libdir) + 1 + strlen (dlname);
filename = (char*) lt_dlmalloc (1+ len); filename = LT_DLMALLOC (char, 1+ len);
if (!filename) if (!filename)
{ {
@ -1260,7 +1355,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed)
sprintf (filename, "%s/%s", libdir, dlname); sprintf (filename, "%s/%s", libdir, dlname);
error = (tryall_dlopen (handle, filename) != 0); error = (tryall_dlopen (handle, filename) != 0);
lt_dlfree (filename); LT_DLFREE (filename);
if (!error) if (!error)
{ {
@ -1272,7 +1367,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed)
if (!installed) if (!installed)
{ {
len = (dir ? strlen (dir) : 0) + strlen (objdir) + strlen (dlname); len = (dir ? strlen (dir) : 0) + strlen (objdir) + strlen (dlname);
filename = (char*) lt_dlmalloc(1+ len); filename = LT_DLMALLOC (char, 1+ len);
if (!filename) if (!filename)
{ {
@ -1292,7 +1387,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed)
strcat(filename, dlname); strcat(filename, dlname);
error = tryall_dlopen (handle, filename) != 0; error = tryall_dlopen (handle, filename) != 0;
lt_dlfree (filename); LT_DLFREE (filename);
if (!error) if (!error)
{ {
return 0; return 0;
@ -1302,7 +1397,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed)
/* maybe it was moved to another directory */ /* maybe it was moved to another directory */
{ {
len = (dir ? strlen (dir) : 0) + strlen (dlname); len = (dir ? strlen (dir) : 0) + strlen (dlname);
filename = (char*) lt_dlmalloc (1+ len); filename = LT_DLMALLOC (char, 1+ len);
if (dir) if (dir)
{ {
@ -1315,7 +1410,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed)
strcat(filename, dlname); strcat(filename, dlname);
error = (tryall_dlopen (handle, filename) != 0); error = (tryall_dlopen (handle, filename) != 0);
lt_dlfree (filename); LT_DLFREE (filename);
if (!error) if (!error)
{ {
return 0; return 0;
@ -1408,13 +1503,9 @@ find_file (basename, search_path, pdir, handle)
if (lendir + 1 + lenbase >= filenamesize) if (lendir + 1 + lenbase >= filenamesize)
{ {
if (filename) LT_DLFREE (filename);
{
lt_dlfree (filename);
}
filenamesize = lendir + 1 + lenbase + 1; filenamesize = lendir + 1 + lenbase + 1;
filename = (char*) lt_dlmalloc(filenamesize); filename = LT_DLMALLOC (char, filenamesize);
if (!filename) if (!filename)
{ {
@ -1442,10 +1533,7 @@ find_file (basename, search_path, pdir, handle)
FILE *file = fopen (filename, LT_READTEXT_MODE); FILE *file = fopen (filename, LT_READTEXT_MODE);
if (file) if (file)
{ {
if (*pdir) LT_DLFREE (*pdir);
{
lt_dlfree (*pdir);
}
filename[lendir] = '\0'; filename[lendir] = '\0';
*pdir = strdup(filename); *pdir = strdup(filename);
@ -1466,8 +1554,8 @@ find_file (basename, search_path, pdir, handle)
last_error = LT_DLSTRERROR (FILE_NOT_FOUND); last_error = LT_DLSTRERROR (FILE_NOT_FOUND);
cleanup: cleanup:
if (filename) lt_dlfree (filename); LT_DLFREE (filename);
if (canonical) lt_dlfree (canonical); LT_DLFREE (canonical);
return result; return result;
} }
@ -1537,13 +1625,13 @@ load_deplibs(handle, deplibs)
goto cleanup; goto cleanup;
} }
names = (char**) lt_dlmalloc (depcount * sizeof (char*)); names = LT_DLMALLOC (char *, depcount * sizeof (char*));
if (!names) if (!names)
{ {
goto cleanup; goto cleanup;
} }
handles = (lt_dlhandle*) lt_dlmalloc (depcount * sizeof (lt_dlhandle*)); handles = (lt_dlhandle*) LT_DLMALLOC (lt_dlhandle *, depcount);
if (!handles) if (!handles)
{ {
goto cleanup; goto cleanup;
@ -1572,8 +1660,7 @@ load_deplibs(handle, deplibs)
*end = 0; /* set a temporary string terminator */ *end = 0; /* set a temporary string terminator */
if (strncmp(p, "-l", 2) == 0) if (strncmp(p, "-l", 2) == 0)
{ {
name = lt_dlmalloc(3+ /* "lib" */ name = LT_DLMALLOC (char, 3+ /* "lib" */ strlen (p+2) + 1);
strlen(p+2)+1);
if (name) if (name)
{ {
sprintf (name, "lib%s", p+2); sprintf (name, "lib%s", p+2);
@ -1625,15 +1712,15 @@ load_deplibs(handle, deplibs)
cleanup_names: cleanup_names:
for (i = 0; i < depcount; ++i) for (i = 0; i < depcount; ++i)
{ {
lt_dlfree(names[i]); LT_DLFREE (names[i]);
} }
cleanup: cleanup:
if (names) lt_dlfree(names); LT_DLFREE (names);
if (handles) lt_dlfree(handles); LT_DLFREE (handles);
/* restore the old search path */ /* 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; user_search_path = save_search_path;
return ret; return ret;
@ -1671,14 +1758,11 @@ trim (dest, str)
int len = strlen (str); int len = strlen (str);
char *tmp; char *tmp;
if (*dest) LT_DLFREE (*dest);
{
lt_dlfree(*dest);
}
if (len > 3 && str[0] == '\'') if (len > 3 && str[0] == '\'')
{ {
tmp = (char*) lt_dlmalloc(end - str); tmp = LT_DLMALLOC (char, end - str);
if (!tmp) if (!tmp)
{ {
last_error = LT_DLSTRERROR (NO_MEMORY); last_error = LT_DLSTRERROR (NO_MEMORY);
@ -1704,10 +1788,10 @@ free_vars( dlname, oldname, libdir, deplibs)
char *libdir; char *libdir;
char *deplibs; char *deplibs;
{ {
if (dlname) lt_dlfree(dlname); LT_DLFREE (dlname);
if (oldname) lt_dlfree(oldname); LT_DLFREE (oldname);
if (libdir) lt_dlfree(libdir); LT_DLFREE (libdir);
if (deplibs) lt_dlfree(deplibs); LT_DLFREE (deplibs);
return 0; return 0;
} }
@ -1724,7 +1808,7 @@ lt_dlopen (filename)
/* dlopen self? */ /* dlopen self? */
if (!filename) if (!filename)
{ {
handle = (lt_dlhandle) lt_dlmalloc (sizeof (struct lt_dlhandle_struct)); handle = (lt_dlhandle) LT_DLMALLOC (struct lt_dlhandle_struct, 1);
if (!handle) if (!handle)
{ {
last_error = LT_DLSTRERROR (NO_MEMORY); last_error = LT_DLSTRERROR (NO_MEMORY);
@ -1734,6 +1818,7 @@ lt_dlopen (filename)
handle->info.ref_count = 0; handle->info.ref_count = 0;
handle->depcount = 0; handle->depcount = 0;
handle->deplibs = 0; handle->deplibs = 0;
handle->caller_data = 0;
newhandle = handle; newhandle = handle;
/* lt_dlclose()ing yourself is very bad! Disallow it. */ /* lt_dlclose()ing yourself is very bad! Disallow it. */
@ -1741,7 +1826,7 @@ lt_dlopen (filename)
if (tryall_dlopen (&newhandle, 0) != 0) if (tryall_dlopen (&newhandle, 0) != 0)
{ {
lt_dlfree(handle); LT_DLFREE (handle);
return 0; return 0;
} }
goto register_handle; goto register_handle;
@ -1751,10 +1836,7 @@ lt_dlopen (filename)
if (!canonical) if (!canonical)
{ {
last_error = LT_DLSTRERROR (NO_MEMORY); last_error = LT_DLSTRERROR (NO_MEMORY);
if (handle) LT_DLFREE (handle);
{
lt_dlfree(handle);
}
return 0; return 0;
} }
@ -1764,7 +1846,7 @@ lt_dlopen (filename)
if (basename) if (basename)
{ {
++basename; ++basename;
dir = (char*) lt_dlmalloc (basename - canonical + 1); dir = LT_DLMALLOC (char, basename - canonical + 1);
if (!dir) if (!dir)
{ {
last_error = LT_DLSTRERROR (NO_MEMORY); last_error = LT_DLSTRERROR (NO_MEMORY);
@ -1798,7 +1880,7 @@ lt_dlopen (filename)
int installed = 1; int installed = 1;
/* extract the module name from the file name */ /* extract the module name from the file name */
name = (char*) lt_dlmalloc(ext - basename + 1); name = LT_DLMALLOC (char, ext - basename + 1);
if (!name) if (!name)
{ {
last_error = LT_DLSTRERROR (NO_MEMORY); last_error = LT_DLSTRERROR (NO_MEMORY);
@ -1863,7 +1945,7 @@ lt_dlopen (filename)
goto cleanup; goto cleanup;
} }
line = (char*) lt_dlmalloc (LT_FILENAME_MAX); line = LT_DLMALLOC (char, LT_FILENAME_MAX);
if (!line) if (!line)
{ {
fclose (file); fclose (file);
@ -1933,8 +2015,7 @@ lt_dlopen (filename)
(last_libname = strrchr (dlname, ' ')) != NULL) (last_libname = strrchr (dlname, ' ')) != NULL)
{ {
last_libname = strdup (last_libname + 1); last_libname = strdup (last_libname + 1);
lt_dlfree (dlname); LT_DLMEM_REASSIGN (dlname, last_libname);
dlname = last_libname;
} }
} }
@ -1945,16 +2026,13 @@ lt_dlopen (filename)
} }
fclose (file); fclose (file);
lt_dlfree (line); LT_DLFREE (line);
/* allocate the handle */ /* 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 || error)
{ {
if (handle) LT_DLFREE (handle);
{
lt_dlfree(handle);
}
if (!error) if (!error)
{ {
last_error = LT_DLSTRERROR (NO_MEMORY); last_error = LT_DLSTRERROR (NO_MEMORY);
@ -1984,8 +2062,7 @@ lt_dlopen (filename)
free_vars (dlname, old_name, libdir, deplibs); free_vars (dlname, old_name, libdir, deplibs);
if (error) if (error)
{ {
lt_dlfree (handle); LT_DLFREE (handle);
handle = 0;
goto cleanup; goto cleanup;
} }
@ -1997,7 +2074,7 @@ lt_dlopen (filename)
else else
{ {
/* not a libtool module */ /* 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) if (!handle)
{ {
last_error = LT_DLSTRERROR (NO_MEMORY); last_error = LT_DLSTRERROR (NO_MEMORY);
@ -2026,18 +2103,13 @@ lt_dlopen (filename)
#endif #endif
)) && tryall_dlopen (&newhandle, filename)) )) && tryall_dlopen (&newhandle, filename))
{ {
lt_dlfree (handle); LT_DLFREE (handle);
handle = 0;
goto cleanup; goto cleanup;
} }
} }
register_handle: register_handle:
if (newhandle != handle) LT_DLMEM_REASSIGN (handle, newhandle);
{
lt_dlfree(handle);
handle = newhandle;
}
if (handle->info.ref_count == 0) if (handle->info.ref_count == 0)
{ {
@ -2051,9 +2123,9 @@ lt_dlopen (filename)
last_error = saved_error; last_error = saved_error;
cleanup: cleanup:
if (dir) lt_dlfree(dir); LT_DLFREE (dir);
if (name) lt_dlfree(name); LT_DLFREE (name);
if (canonical) lt_dlfree(canonical); LT_DLFREE (canonical);
return handle; return handle;
} }
@ -2080,7 +2152,7 @@ lt_dlopenext (filename)
} }
/* try "filename.la" */ /* try "filename.la" */
tmp = (char*) lt_dlmalloc (len+4); tmp = LT_DLMALLOC (char, len+4);
if (!tmp) if (!tmp)
{ {
last_error = LT_DLSTRERROR (NO_MEMORY); last_error = LT_DLSTRERROR (NO_MEMORY);
@ -2092,7 +2164,7 @@ lt_dlopenext (filename)
if (handle) if (handle)
{ {
last_error = saved_error; last_error = saved_error;
lt_dlfree (tmp); LT_DLFREE (tmp);
return handle; return handle;
} }
@ -2100,8 +2172,8 @@ lt_dlopenext (filename)
/* try "filename.EXT" */ /* try "filename.EXT" */
if (strlen(shlib_ext) > 3) if (strlen(shlib_ext) > 3)
{ {
lt_dlfree (tmp); LT_DLFREE (tmp);
tmp = (char*) lt_dlmalloc (len + strlen (shlib_ext) + 1); tmp = LT_DLMALLOC (char, len + strlen (shlib_ext) + 1);
if (!tmp) if (!tmp)
{ {
last_error = LT_DLSTRERROR (NO_MEMORY); last_error = LT_DLSTRERROR (NO_MEMORY);
@ -2119,7 +2191,7 @@ lt_dlopenext (filename)
if (handle) if (handle)
{ {
last_error = saved_error; last_error = saved_error;
lt_dlfree (tmp); LT_DLFREE (tmp);
return handle; return handle;
} }
#endif #endif
@ -2132,7 +2204,7 @@ lt_dlopenext (filename)
} }
last_error = LT_DLSTRERROR (FILE_NOT_FOUND); last_error = LT_DLSTRERROR (FILE_NOT_FOUND);
lt_dlfree (tmp); LT_DLFREE (tmp);
return 0; return 0;
} }
@ -2179,17 +2251,10 @@ lt_dlclose (handle)
error = handle->loader->module_close (data, handle->module); error = handle->loader->module_close (data, handle->module);
error += unload_deplibs(handle); error += unload_deplibs(handle);
if (handle->info.filename) LT_DLFREE (handle->info.filename);
{ LT_DLFREE (handle->info.name);
lt_dlfree (handle->info.filename);
}
if (handle->info.name) LT_DLFREE (handle);
{
lt_dlfree (handle->info.name);
}
lt_dlfree (handle);
return error; return error;
} }
@ -2243,7 +2308,7 @@ lt_dlsym (handle, symbol)
} }
else else
{ {
sym = (char*) lt_dlmalloc(lensym + LT_SYMBOL_OVERHEAD + 1); sym = LT_DLMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
} }
if (!sym) if (!sym)
@ -2277,7 +2342,7 @@ lt_dlsym (handle, symbol)
{ {
if (sym != lsym) if (sym != lsym)
{ {
lt_dlfree(sym); LT_DLFREE (sym);
} }
return address; return address;
} }
@ -2298,7 +2363,7 @@ lt_dlsym (handle, symbol)
address = handle->loader->find_sym (data, handle->module, sym); address = handle->loader->find_sym (data, handle->module, sym);
if (sym != lsym) if (sym != lsym)
{ {
lt_dlfree(sym); LT_DLFREE (sym);
} }
return address; return address;
@ -2334,7 +2399,7 @@ lt_dladdsearchdir (search_dir)
else else
{ {
size_t len = strlen (user_search_path) + 1 + strlen (search_dir); 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) if (!new_search_path)
{ {
@ -2345,8 +2410,7 @@ lt_dladdsearchdir (search_dir)
sprintf (new_search_path, "%s%c%s", user_search_path, sprintf (new_search_path, "%s%c%s", user_search_path,
LT_PATHSEP_CHAR, search_dir); LT_PATHSEP_CHAR, search_dir);
lt_dlfree (user_search_path); LT_DLMEM_REASSIGN (user_search_path, new_search_path);
user_search_path = new_search_path;
} }
return 0; return 0;
@ -2356,11 +2420,7 @@ int
lt_dlsetsearchpath (search_path) lt_dlsetsearchpath (search_path)
const char *search_path; const char *search_path;
{ {
if (user_search_path) LT_DLFREE (user_search_path);
{
lt_dlfree (user_search_path);
user_search_path = 0;
}
if (!search_path || !strlen (search_path)) if (!search_path || !strlen (search_path))
{ {
@ -2410,6 +2470,11 @@ lt_dlisresident (handle)
return LT_DLIS_RESIDENT (handle); return LT_DLIS_RESIDENT (handle);
} }
/* --- MODULE INFORMATION --- */
const lt_dlinfo * const lt_dlinfo *
lt_dlgetinfo (handle) lt_dlgetinfo (handle)
lt_dlhandle handle; lt_dlhandle handle;
@ -2444,6 +2509,96 @@ lt_dlforeach (func, data)
return 0; 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;
}
/* --- USER MODULE LOADER API --- */
int int
lt_dlloader_add (place, dlloader, loader_name) lt_dlloader_add (place, dlloader, loader_name)
lt_dlloader *place; lt_dlloader *place;
@ -2462,7 +2617,7 @@ lt_dlloader_add (place, dlloader, loader_name)
} }
/* Create a new dlloader node with copies of the user callbacks. */ /* 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) if (node == 0)
{ {
last_error = LT_DLSTRERROR (NO_MEMORY); last_error = LT_DLSTRERROR (NO_MEMORY);
@ -2571,10 +2726,7 @@ lt_dlloader_remove (loader_name)
result = place->dlloader_exit (place->dlloader_data); result = place->dlloader_exit (place->dlloader_data);
} }
if (place) LT_DLFREE (place);
{
lt_dlfree (place);
}
return result; return result;
} }
@ -2626,4 +2778,3 @@ lt_dlloader_find (loader_name)
return place; return place;
} }

View File

@ -208,6 +208,15 @@ extern int lt_dlforeach LT_PARAMS((
int (*func) (lt_dlhandle handle, lt_ptr data), int (*func) (lt_dlhandle handle, lt_ptr data),
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));

View File

@ -39,6 +39,7 @@ AC_CHECK_HEADERS(malloc.h memory.h stdlib.h stdio.h ctype.h dl.h dld.h)
AC_CHECK_HEADERS(string.h strings.h, break) AC_CHECK_HEADERS(string.h strings.h, break)
AC_CHECK_FUNCS(strchr index, break) AC_CHECK_FUNCS(strchr index, break)
AC_CHECK_FUNCS(strrchr rindex, break) AC_CHECK_FUNCS(strrchr rindex, break)
AC_CHECK_FUNCS(memcpy bcopy, break)
AC_CHECK_FUNCS(strcmp) AC_CHECK_FUNCS(strcmp)
AC_REQUIRE([AC_LTDL_ENABLE_INSTALL])dnl AC_REQUIRE([AC_LTDL_ENABLE_INSTALL])dnl