mirror of
git://git.savannah.gnu.org/libtool.git
synced 2024-11-21 01:40:57 +08:00
* 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:
parent
c821715109
commit
bd96d1928a
18
ChangeLog
18
ChangeLog
@ -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>
|
||||
|
||||
* libltdl/ltdl.h: formatting change.
|
||||
|
2
NEWS
2
NEWS
@ -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.
|
||||
* 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.
|
||||
|
389
doc/libtool.texi
389
doc/libtool.texi
@ -165,8 +165,9 @@ Using libltdl
|
||||
|
||||
* Libltdl interface:: How to use libltdl in your programs.
|
||||
* Modules for libltdl:: Creating modules that can be @code{dlopen}ed.
|
||||
* Distributing libltdl:: How to distribute libltdl with your package.
|
||||
* 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
|
||||
|
||||
@ -2634,8 +2635,9 @@ distribution terms that you use for the rest of that program.
|
||||
@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
|
||||
@ -2684,16 +2686,6 @@ The following types are defined in @file{ltdl.h}:
|
||||
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}.
|
||||
@ -2863,21 +2855,6 @@ function, return -1 and set an error message for retrieval with
|
||||
@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,
|
||||
@ -2953,143 +2930,121 @@ foo1_la_LDFLAGS = -module
|
||||
...
|
||||
@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}.
|
||||
@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
|
||||
|
||||
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}.
|
||||
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'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.
|
||||
@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
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
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.
|
||||
@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:
|
||||
|
||||
@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
|
||||
|
||||
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
|
||||
@section How to create and register new module loaders
|
||||
@ -3337,6 +3292,144 @@ if (lt_dlseterror (LTDL_ERROR_NO_MEMORY) != 0)
|
||||
@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
|
||||
|
395
libltdl/ltdl.c
395
libltdl/ltdl.c
@ -98,6 +98,20 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
#undef LT_SYMBOL_OVERHEAD
|
||||
#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 --- */
|
||||
|
||||
@ -122,6 +136,7 @@ struct lt_dlhandle_struct {
|
||||
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 */
|
||||
};
|
||||
|
||||
@ -144,11 +159,29 @@ static const char shlib_ext[] = LTDL_SHLIB_EXT;
|
||||
static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/* --- 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
|
||||
|
||||
|
||||
|
||||
/* --- ERROR MESSAGES --- */
|
||||
@ -177,26 +210,20 @@ lt_dladderror (diagnostic)
|
||||
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++;
|
||||
}
|
||||
@ -240,7 +267,7 @@ strdup(str)
|
||||
|
||||
if (str)
|
||||
{
|
||||
tmp = (char*) lt_dlmalloc (1+ strlen (str));
|
||||
tmp = LT_DLMALLOC (char, 1+ strlen (str));
|
||||
if (tmp)
|
||||
{
|
||||
strcpy(tmp, str);
|
||||
@ -330,6 +357,78 @@ strrchr(str, ch)
|
||||
# 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
|
||||
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);
|
||||
@ -611,7 +710,7 @@ sys_wll_open (loader_data, filename)
|
||||
}
|
||||
|
||||
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
|
||||
@ -791,7 +890,7 @@ sys_dld_open (loader_data, filename)
|
||||
if (dld_link (filename) != 0)
|
||||
{
|
||||
last_error = LT_DLSTRERROR (CANNOT_OPEN);
|
||||
lt_dlfree(module);
|
||||
LT_DLFREE (module);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -808,7 +907,7 @@ sys_dld_close (loader_data, module)
|
||||
last_error = LT_DLSTRERROR (CANNOT_CLOSE);
|
||||
return 1;
|
||||
}
|
||||
lt_dlfree (module);
|
||||
LT_DLFREE (module);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -876,7 +975,7 @@ presym_free_symlists ()
|
||||
lt_dlsymlists_t *tmp = lists;
|
||||
|
||||
lists = lists->next;
|
||||
lt_dlfree (tmp);
|
||||
LT_DLFREE (tmp);
|
||||
}
|
||||
preloaded_symbols = 0;
|
||||
|
||||
@ -907,7 +1006,7 @@ presym_add_symlist (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);
|
||||
@ -1135,8 +1234,7 @@ lt_dlexit ()
|
||||
++errors;
|
||||
}
|
||||
|
||||
lt_dlfree (loader);
|
||||
loader = next;
|
||||
LT_DLMEM_REASSIGN (loader, next);
|
||||
}
|
||||
loaders = 0;
|
||||
}
|
||||
@ -1208,10 +1306,7 @@ tryall_dlopen (handle, filename)
|
||||
|
||||
if (!loader)
|
||||
{
|
||||
if (cur->info.filename)
|
||||
{
|
||||
lt_dlfree(cur->info.filename);
|
||||
}
|
||||
LT_DLFREE (cur->info.filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1250,7 +1345,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed)
|
||||
if (installed && libdir)
|
||||
{
|
||||
len = strlen (libdir) + 1 + strlen (dlname);
|
||||
filename = (char*) lt_dlmalloc (1+ len);
|
||||
filename = LT_DLMALLOC (char, 1+ len);
|
||||
|
||||
if (!filename)
|
||||
{
|
||||
@ -1260,7 +1355,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed)
|
||||
|
||||
sprintf (filename, "%s/%s", libdir, dlname);
|
||||
error = (tryall_dlopen (handle, filename) != 0);
|
||||
lt_dlfree (filename);
|
||||
LT_DLFREE (filename);
|
||||
|
||||
if (!error)
|
||||
{
|
||||
@ -1272,7 +1367,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed)
|
||||
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)
|
||||
{
|
||||
@ -1292,7 +1387,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed)
|
||||
strcat(filename, dlname);
|
||||
|
||||
error = tryall_dlopen (handle, filename) != 0;
|
||||
lt_dlfree (filename);
|
||||
LT_DLFREE (filename);
|
||||
if (!error)
|
||||
{
|
||||
return 0;
|
||||
@ -1302,7 +1397,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed)
|
||||
/* 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)
|
||||
{
|
||||
@ -1315,7 +1410,7 @@ find_module (handle, dir, libdir, dlname, old_name, installed)
|
||||
strcat(filename, dlname);
|
||||
|
||||
error = (tryall_dlopen (handle, filename) != 0);
|
||||
lt_dlfree (filename);
|
||||
LT_DLFREE (filename);
|
||||
if (!error)
|
||||
{
|
||||
return 0;
|
||||
@ -1408,13 +1503,9 @@ find_file (basename, search_path, pdir, handle)
|
||||
|
||||
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)
|
||||
{
|
||||
@ -1442,10 +1533,7 @@ find_file (basename, search_path, pdir, handle)
|
||||
FILE *file = fopen (filename, LT_READTEXT_MODE);
|
||||
if (file)
|
||||
{
|
||||
if (*pdir)
|
||||
{
|
||||
lt_dlfree (*pdir);
|
||||
}
|
||||
LT_DLFREE (*pdir);
|
||||
|
||||
filename[lendir] = '\0';
|
||||
*pdir = strdup(filename);
|
||||
@ -1466,8 +1554,8 @@ find_file (basename, search_path, pdir, handle)
|
||||
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;
|
||||
}
|
||||
@ -1537,13 +1625,13 @@ load_deplibs(handle, deplibs)
|
||||
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;
|
||||
@ -1572,8 +1660,7 @@ load_deplibs(handle, deplibs)
|
||||
*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);
|
||||
@ -1625,15 +1712,15 @@ load_deplibs(handle, deplibs)
|
||||
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;
|
||||
@ -1671,14 +1758,11 @@ trim (dest, 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);
|
||||
@ -1704,10 +1788,10 @@ free_vars( dlname, oldname, libdir, deplibs)
|
||||
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;
|
||||
}
|
||||
@ -1724,7 +1808,7 @@ lt_dlopen (filename)
|
||||
/* 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);
|
||||
@ -1734,6 +1818,7 @@ lt_dlopen (filename)
|
||||
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. */
|
||||
@ -1741,7 +1826,7 @@ lt_dlopen (filename)
|
||||
|
||||
if (tryall_dlopen (&newhandle, 0) != 0)
|
||||
{
|
||||
lt_dlfree(handle);
|
||||
LT_DLFREE (handle);
|
||||
return 0;
|
||||
}
|
||||
goto register_handle;
|
||||
@ -1751,10 +1836,7 @@ lt_dlopen (filename)
|
||||
if (!canonical)
|
||||
{
|
||||
last_error = LT_DLSTRERROR (NO_MEMORY);
|
||||
if (handle)
|
||||
{
|
||||
lt_dlfree(handle);
|
||||
}
|
||||
LT_DLFREE (handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1764,7 +1846,7 @@ lt_dlopen (filename)
|
||||
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);
|
||||
@ -1798,7 +1880,7 @@ lt_dlopen (filename)
|
||||
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);
|
||||
@ -1863,7 +1945,7 @@ lt_dlopen (filename)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
line = (char*) lt_dlmalloc (LT_FILENAME_MAX);
|
||||
line = LT_DLMALLOC (char, LT_FILENAME_MAX);
|
||||
if (!line)
|
||||
{
|
||||
fclose (file);
|
||||
@ -1933,8 +2015,7 @@ lt_dlopen (filename)
|
||||
(last_libname = strrchr (dlname, ' ')) != NULL)
|
||||
{
|
||||
last_libname = strdup (last_libname + 1);
|
||||
lt_dlfree (dlname);
|
||||
dlname = last_libname;
|
||||
LT_DLMEM_REASSIGN (dlname, last_libname);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1945,16 +2026,13 @@ lt_dlopen (filename)
|
||||
}
|
||||
|
||||
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);
|
||||
@ -1984,8 +2062,7 @@ lt_dlopen (filename)
|
||||
free_vars (dlname, old_name, libdir, deplibs);
|
||||
if (error)
|
||||
{
|
||||
lt_dlfree (handle);
|
||||
handle = 0;
|
||||
LT_DLFREE (handle);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -1997,7 +2074,7 @@ lt_dlopen (filename)
|
||||
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);
|
||||
@ -2026,18 +2103,13 @@ lt_dlopen (filename)
|
||||
#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)
|
||||
{
|
||||
@ -2051,9 +2123,9 @@ lt_dlopen (filename)
|
||||
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;
|
||||
}
|
||||
@ -2080,7 +2152,7 @@ lt_dlopenext (filename)
|
||||
}
|
||||
|
||||
/* try "filename.la" */
|
||||
tmp = (char*) lt_dlmalloc (len+4);
|
||||
tmp = LT_DLMALLOC (char, len+4);
|
||||
if (!tmp)
|
||||
{
|
||||
last_error = LT_DLSTRERROR (NO_MEMORY);
|
||||
@ -2092,7 +2164,7 @@ lt_dlopenext (filename)
|
||||
if (handle)
|
||||
{
|
||||
last_error = saved_error;
|
||||
lt_dlfree (tmp);
|
||||
LT_DLFREE (tmp);
|
||||
return handle;
|
||||
}
|
||||
|
||||
@ -2100,8 +2172,8 @@ lt_dlopenext (filename)
|
||||
/* 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);
|
||||
@ -2119,7 +2191,7 @@ lt_dlopenext (filename)
|
||||
if (handle)
|
||||
{
|
||||
last_error = saved_error;
|
||||
lt_dlfree (tmp);
|
||||
LT_DLFREE (tmp);
|
||||
return handle;
|
||||
}
|
||||
#endif
|
||||
@ -2132,7 +2204,7 @@ lt_dlopenext (filename)
|
||||
}
|
||||
|
||||
last_error = LT_DLSTRERROR (FILE_NOT_FOUND);
|
||||
lt_dlfree (tmp);
|
||||
LT_DLFREE (tmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2179,17 +2251,10 @@ lt_dlclose (handle)
|
||||
error = handle->loader->module_close (data, handle->module);
|
||||
error += unload_deplibs(handle);
|
||||
|
||||
if (handle->info.filename)
|
||||
{
|
||||
lt_dlfree (handle->info.filename);
|
||||
}
|
||||
LT_DLFREE (handle->info.filename);
|
||||
LT_DLFREE (handle->info.name);
|
||||
|
||||
if (handle->info.name)
|
||||
{
|
||||
lt_dlfree (handle->info.name);
|
||||
}
|
||||
|
||||
lt_dlfree (handle);
|
||||
LT_DLFREE (handle);
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -2243,7 +2308,7 @@ lt_dlsym (handle, symbol)
|
||||
}
|
||||
else
|
||||
{
|
||||
sym = (char*) lt_dlmalloc(lensym + LT_SYMBOL_OVERHEAD + 1);
|
||||
sym = LT_DLMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
|
||||
}
|
||||
|
||||
if (!sym)
|
||||
@ -2277,7 +2342,7 @@ lt_dlsym (handle, symbol)
|
||||
{
|
||||
if (sym != lsym)
|
||||
{
|
||||
lt_dlfree(sym);
|
||||
LT_DLFREE (sym);
|
||||
}
|
||||
return address;
|
||||
}
|
||||
@ -2298,7 +2363,7 @@ lt_dlsym (handle, symbol)
|
||||
address = handle->loader->find_sym (data, handle->module, sym);
|
||||
if (sym != lsym)
|
||||
{
|
||||
lt_dlfree(sym);
|
||||
LT_DLFREE (sym);
|
||||
}
|
||||
|
||||
return address;
|
||||
@ -2334,7 +2399,7 @@ lt_dladdsearchdir (search_dir)
|
||||
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)
|
||||
{
|
||||
@ -2345,8 +2410,7 @@ lt_dladdsearchdir (search_dir)
|
||||
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;
|
||||
@ -2356,11 +2420,7 @@ int
|
||||
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))
|
||||
{
|
||||
@ -2410,6 +2470,11 @@ lt_dlisresident (handle)
|
||||
return LT_DLIS_RESIDENT (handle);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* --- MODULE INFORMATION --- */
|
||||
|
||||
const lt_dlinfo *
|
||||
lt_dlgetinfo (handle)
|
||||
lt_dlhandle handle;
|
||||
@ -2444,6 +2509,96 @@ lt_dlforeach (func, data)
|
||||
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
|
||||
lt_dlloader_add (place, dlloader, loader_name)
|
||||
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. */
|
||||
node = (lt_dlloader *) lt_dlmalloc (sizeof (lt_dlloader));
|
||||
node = LT_DLMALLOC (lt_dlloader, 1);
|
||||
if (node == 0)
|
||||
{
|
||||
last_error = LT_DLSTRERROR (NO_MEMORY);
|
||||
@ -2571,10 +2726,7 @@ lt_dlloader_remove (loader_name)
|
||||
result = place->dlloader_exit (place->dlloader_data);
|
||||
}
|
||||
|
||||
if (place)
|
||||
{
|
||||
lt_dlfree (place);
|
||||
}
|
||||
LT_DLFREE (place);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -2626,4 +2778,3 @@ lt_dlloader_find (loader_name)
|
||||
|
||||
return place;
|
||||
}
|
||||
|
||||
|
@ -208,6 +208,15 @@ extern int lt_dlforeach LT_PARAMS((
|
||||
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));
|
||||
|
||||
|
||||
|
||||
|
1
ltdl.m4
1
ltdl.m4
@ -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_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
|
||||
|
Loading…
Reference in New Issue
Block a user