? cxxdemo ? patches ? libltdl/ltdl-beos.c ? libltdl/ltdl-dl.c ? libltdl/ltdl-dld.c ? libltdl/ltdl-preload.c ? libltdl/ltdl-shl.c ? libltdl/ltdl-windows.c Index: ChangeLog =================================================================== RCS file: /home/cvs/libtool/ChangeLog,v retrieving revision 1.850 diff -u -p -r1.850 ChangeLog --- ChangeLog 2001/01/04 22:06:10 1.850 +++ ChangeLog 2001/01/05 01:55:24 @@ -1,3 +1,22 @@ +2001-01-05 Gary V. Vaughan + + * 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, lt_dlcaller_remove_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, lt_dlcaller_remove_data): Prototyped. + (LT_ERROR_KEYED_DATA_EXISTS): New error status. + 2001-01-04 Gary V. Vaughan * libltdl/ltdl.h: formatting change. Index: NEWS =================================================================== RCS file: /home/cvs/libtool/NEWS,v retrieving revision 1.83 diff -u -p -r1.83 NEWS --- NEWS 2000/12/14 01:51:59 1.83 +++ NEWS 2001/01/05 01:55:26 @@ -13,6 +13,8 @@ New in 1.3d: 2000-??-??; CVS version 1.3 * 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, lt_dlcaller_remove_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. Index: ltdl.m4 =================================================================== RCS file: /home/cvs/libtool/ltdl.m4,v retrieving revision 1.15 diff -u -p -r1.15 ltdl.m4 --- ltdl.m4 2000/12/01 19:13:20 1.15 +++ ltdl.m4 2001/01/05 01:55:26 @@ -39,6 +39,7 @@ AC_CHECK_HEADERS(malloc.h memory.h stdli 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 Index: doc/libtool.texi =================================================================== RCS file: /home/cvs/libtool/doc/libtool.texi,v retrieving revision 1.112 diff -u -p -r1.112 libtool.texi --- doc/libtool.texi 2000/12/23 16:30:43 1.112 +++ doc/libtool.texi 2001/01/05 01:55:47 @@ -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,11 +2635,12 @@ distribution terms that you use for the @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 address@hidden Libltdl interface address@hidden Libltdl interface @section How to use libltdl in your programs @noindent @@ -2684,16 +2686,6 @@ The following types are defined in @file Every lt_dlopened module has a handle associated with it. @end deftp address@hidden {Type} {struct} lt_dlinfo @{ @w{char address@hidden;} @w{char address@hidden;} @w{int @var{ref_count};} @} address@hidden 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. address@hidden 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 mes @code{lt_dlerror}. @end deftypefun address@hidden {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. address@hidden deftypefun - address@hidden int lt_dlforeach (int (address@hidden)(lt_dlhandle @var{handle}, lt_ptr @var{data}), lt_ptr @var{data}) -For each loaded module call the function @var{func}. The argument address@hidden 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, address@hidden will stop calling @var{func} and immediately return 1. -Otherwise 0 is returned. address@hidden 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,107 @@ foo1_la_LDFLAGS = -module ... @end example address@hidden Distributing libltdl address@hidden 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. address@hidden User defined module data address@hidden 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 address@hidden 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 address@hidden 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}, address@hidden @samp{AC_PROG_LIBTOOL}. address@hidden {Type} {struct} lt_dlinfo @{ @w{char address@hidden;} @w{char address@hidden;} @w{int @var{ref_count};} @} address@hidden 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 address@hidden is its module name (e.g. @code{"libfoo"} for address@hidden"dir/libfoo.la"}), otherwise it is set to @code{NULL}. The address@hidden attribute is a reference counter that describes how +often the same module is currently loaded. address@hidden deftypefn -In order to select the installable version of libltdl, you should add a -call of the macro @samp{AC_LIBLTDL_INSTALLABLE} to your address@hidden @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 @address@hidden@}/libltdl}. address@hidden {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. address@hidden deftypefun -Whatever macro you use, it is up to you to ensure that your address@hidden will configure libltdl, using address@hidden, 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 address@hidden, to the preprocessor flag that you should use to compile -with programs that include @file{ltdl.h}. It is up to you to use address@hidden to ensure that this variable will be available in address@hidden, 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 address@hidden followed by the directory that contains libltdl, both starting -with @address@hidden@}/} or @address@hidden@}/}, respectively. address@hidden int lt_dlforeach (@w{int (address@hidden) (lt_dlhandle @var{handle}, lt_ptr @var{data})}, @w{lt_ptr @var{data}}) +For each loaded module call the function @var{func}. The argument address@hidden 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, address@hidden will stop calling @var{func} and immediately return 1. +Otherwise 0 is returned. address@hidden deftypefun -If you request an installed version of libltdl and one is address@hidden if libltdl is installed, address@hidden 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 @address@hidden@}/}, -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 address@hidden 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. address@hidden {Type} lt_dlcaller_id +The opaque type used to hold individual data set keys. address@hidden deftp -You should probably also add @samp{AC_LIBTOOL_DLOPEN} to your address@hidden @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. address@hidden lt_dlcaller_id lt_dlcaller_register (void) +Use this to obtain a unique key to store and retrieve individual sets of +per module data. address@hidden 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. address@hidden int 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 address@hidden for later retrieval. This function returns the number of +errors encountered in trying to associate the data. A diagnostic for +the last error (if any) is available from @code{lt_dlerror()}. address@hidden deftypefun -The following example shows you how to embed the convenience libltdl in -your package. In order to use the installable variant just replace address@hidden with @samp{AC_LIBLTDL_INSTALLABLE}. We -assume that libltdl was embedded using @samp{libtoolize --ltdl}. address@hidden lt_ptr lt_dlcaller_remove_data (@w{lt_dlcaller_id @var{key}}, @w{lt_dlhandle @var{handle}}) +Remove any data currently associated with @var{key} and @var{handle}. +Only the association is removed, the data itself is returned so that it +can be @code{free}d appropriately by the caller. A @code{NULL} return +value indicates that no matching data is stored. address@hidden deftypefun -configure.in: address@hidden -... -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) -... address@hidden example address@hidden 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 address@hidden, or else @code{NULL} if there is none. address@hidden deftypefun -Makefile.am: +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 -... -SUBDIRS = libltdl +int +my_dlcaller_callback (lt_dlhandle handle, lt_ptr key_ptr) address@hidden + struct my_module_data *my_data; -INCLUDES = $(INCLTDL) + my_data = lt_dlcaller_get_data (handle, (lt_dlcaller_id) *key_ptr); -myprog_LDFLAGS = -export-dynamic -# The quotes around -dlopen below fool automake <= 1.4 into accepting it -myprog_LDADD = $(LIBLTDL) "-dlopen" self "-dlopen" foo1.la -myprog_DEPENDENCIES = $(LIBLTDL) foo1.la -... + return process (my_data); address@hidden + +int +my_dlcaller_foreach (lt_dlcaller_id key) address@hidden + lt_dlforeach (my_dlcaller_callback, (lt_ptr) &key); address@hidden @end example + @node Module loaders for libltdl @section How to create and register new module loaders @@ -3336,6 +3277,144 @@ if (lt_dlseterror (LTDL_ERROR_NO_MEMORY) perror (lt_dlerror ()); @end example @end deftypefun + address@hidden Distributing libltdl address@hidden 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 address@hidden 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 address@hidden 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}, address@hidden @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 address@hidden @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 @address@hidden@}/libltdl}. + +Whatever macro you use, it is up to you to ensure that your address@hidden will configure libltdl, using address@hidden, 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 address@hidden, to the preprocessor flag that you should use to compile +with programs that include @file{ltdl.h}. It is up to you to use address@hidden to ensure that this variable will be available in address@hidden, 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 address@hidden followed by the directory that contains libltdl, both starting +with @address@hidden@}/} or @address@hidden@}/}, respectively. + +If you request an installed version of libltdl and one is address@hidden if libltdl is installed, address@hidden 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 @address@hidden@}/}, +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 address@hidden @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 address@hidden with @samp{AC_LIBLTDL_INSTALLABLE}. We +assume that libltdl was embedded using @samp{libtoolize --ltdl}. + +configure.in: address@hidden +... +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) +... address@hidden example + +Makefile.am: address@hidden +... +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 +... address@hidden example @node Other languages @chapter Using libtool with other languages Index: libltdl/ltdl.c =================================================================== RCS file: /home/cvs/libtool/libltdl/ltdl.c,v retrieving revision 1.119 diff -u -p -r1.119 ltdl.c --- libltdl/ltdl.c 2000/12/20 23:50:09 1.119 +++ libltdl/ltdl.c 2001/01/05 01:55:53 @@ -98,7 +98,21 @@ Foundation, Inc., 59 Temple Place, Suite #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,12 +159,30 @@ static const char shlib_ext[] = LTDL_SH 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), 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++; } @@ -210,7 +237,7 @@ lt_dlseterror (index) last_error = LT_DLSTRERROR (INVALID_ERRORCODE); return 1; } - + if (index < LT_ERROR_MAX) { last_error = lt_dlerror_strings[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); @@ -267,18 +294,18 @@ strcmp (str1, str2) return -1; if (str2 == 0) return 1; - + for (;*str1 && *str2; ++str1, ++str2) { if (*str1 != *str2) break; } - + return (int)(*str1 - *str2); } #endif - + #if ! HAVE_STRCHR # if HAVE_INDEX @@ -330,8 +357,75 @@ 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 , + ``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, give up. */ + 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; + } +} + + + /* --- DLOPEN() INTERFACE LOADER --- */ @@ -424,12 +518,12 @@ sys_dl_sym (loader_data, module, symbol) const char *symbol; { lt_ptr address = dlsym (module, symbol); - + if (!address) { last_error = DLERROR (SYMBOL_NOT_FOUND); } - + return address; } @@ -466,7 +560,7 @@ static struct lt_user_dlloader sys_dl = * * Optionally: * BIND_FIRST - Place the library at the head of the symbol search - * order. + * order. * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all * unsatisfied symbols as fatal. This flag allows * binding of unsatisfied code symbols to be deferred @@ -479,7 +573,7 @@ static struct lt_user_dlloader sys_dl = * when the library is loaded, nor on a future call to * shl_unload(). * BIND_VERBOSE - Print verbose messages concerning possible - * unsatisfied symbols. + * unsatisfied symbols. * * hp9000s700/hp9000s800: * BIND_RESTRICTED - Restrict symbols visible by the library to those @@ -600,7 +694,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,8 +705,8 @@ 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 will search the loaded libraries for a match and return @@ -668,7 +762,7 @@ sys_wll_sym (loader_data, module, symbol const char *symbol; { lt_ptr address = GetProcAddress (module, symbol); - + if (!address) { last_error = LT_DLSTRERROR (SYMBOL_NOT_FOUND); @@ -701,19 +795,19 @@ sys_bedl_open (loader_data, filename) const char *filename; { image_id image = 0; - + if (filename) { image = load_add_on (filename); } else { - image_info info; - int32 cookie = 0; + image_info info; + int32 cookie = 0; if (get_next_image_info (0, &cookie, &info) == B_OK) image = load_add_on (info.name); } - + if (image <= 0) { last_error = LT_DLSTRERROR (CANNOT_OPEN); @@ -745,7 +839,7 @@ sys_bedl_sym (loader_data, module, symbo { lt_ptr address = 0; image_id image = (image_id) module; - + if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK) { last_error = LT_DLSTRERROR (SYMBOL_NOT_FOUND); @@ -787,11 +881,11 @@ sys_dld_open (loader_data, filename) last_error = LT_DLSTRERROR (NO_MEMORY); return 0; } - + if (dld_link (filename) != 0) { last_error = LT_DLSTRERROR (CANNOT_OPEN); - lt_dlfree(module); + LT_DLFREE (module); return 0; } @@ -808,7 +902,7 @@ sys_dld_close (loader_data, module) last_error = LT_DLSTRERROR (CANNOT_CLOSE); return 1; } - lt_dlfree (module); + LT_DLFREE (module); return 0; } @@ -825,7 +919,7 @@ sys_dld_sym (loader_data, module, symbol { last_error = LT_DLSTRERROR (SYMBOL_NOT_FOUND); } - + return address; } @@ -862,7 +956,7 @@ presym_init (loader_data) { return lt_dlpreload (default_preloaded_symbols); } - + return 0; } @@ -870,13 +964,13 @@ static int presym_free_symlists () { lt_dlsymlists_t *lists = preloaded_symbols; - + while (lists) { lt_dlsymlists_t *tmp = lists; - + lists = lists->next; - lt_dlfree (tmp); + LT_DLFREE (tmp); } preloaded_symbols = 0; @@ -897,7 +991,7 @@ presym_add_symlist (preloaded) { lt_dlsymlists_t *tmp; lt_dlsymlists_t *lists = preloaded_symbols; - + while (lists) { if (lists->syms == preloaded) @@ -907,7 +1001,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); @@ -941,7 +1035,7 @@ presym_open (loader_data, filename) while (lists) { const lt_dlsymlist *syms = lists->syms; - + while (syms->name) { if (!syms->address && strcmp(syms->name, filename) == 0) @@ -984,7 +1078,7 @@ presym_sym (loader_data, module, symbol) { return syms->address; } - + ++syms; } @@ -1020,10 +1114,10 @@ lt_dlinit () { handles = 0; user_search_path = 0; /* empty search path */ - + #if HAVE_LIBDL && !defined(__CYGWIN__) errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen"); -#endif +#endif #if HAVE_SHL_LOAD errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen"); #endif @@ -1053,7 +1147,7 @@ lt_dlinit () last_error = 0; } } - + return errors; } @@ -1089,13 +1183,13 @@ lt_dlexit () /* shut down libltdl */ lt_dlloader *loader = loaders; int errors = 0; - + if (!initialized) { last_error = LT_DLSTRERROR (SHUTDOWN); return 1; } - + /* shut down only at last call. */ if (--initialized == 0) { @@ -1124,7 +1218,7 @@ lt_dlexit () } } } - + /* close all loaders */ while (loader) { @@ -1135,8 +1229,7 @@ lt_dlexit () ++errors; } - lt_dlfree (loader); - loader = next; + LT_DLMEM_REASSIGN (loader, next); } loaders = 0; } @@ -1152,7 +1245,7 @@ tryall_dlopen (handle, filename) lt_dlhandle cur = handles; lt_dlloader *loader = loaders; const char *saved_error = last_error; - + /* check whether the module was already opened */ while (cur) { @@ -1177,7 +1270,7 @@ tryall_dlopen (handle, filename) *handle = cur; return 0; } - + cur = *handle; if (filename) { @@ -1208,10 +1301,7 @@ tryall_dlopen (handle, filename) if (!loader) { - if (cur->info.filename) - { - lt_dlfree(cur->info.filename); - } + LT_DLFREE (cur->info.filename); return 1; } @@ -1233,7 +1323,7 @@ find_module (handle, dir, libdir, dlname int error; char *filename; - /* try to open the old library first; if it was dlpreopened, + /* try to open the old library first; if it was dlpreopened, we want the preopened version of it, even if a dlopenable module is available */ if (old_name && tryall_dlopen(handle, old_name) == 0) @@ -1245,12 +1335,12 @@ find_module (handle, dir, libdir, dlname if (dlname) { size_t len; - + /* try to open the installed module */ if (installed && libdir) { len = strlen (libdir) + 1 + strlen (dlname); - filename = (char*) lt_dlmalloc (1+ len); + filename = LT_DLMALLOC (char, 1+ len); if (!filename) { @@ -1260,7 +1350,7 @@ find_module (handle, dir, libdir, dlname sprintf (filename, "%s/%s", libdir, dlname); error = (tryall_dlopen (handle, filename) != 0); - lt_dlfree (filename); + LT_DLFREE (filename); if (!error) { @@ -1272,7 +1362,7 @@ find_module (handle, dir, libdir, dlname 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 +1382,7 @@ find_module (handle, dir, libdir, dlname strcat(filename, dlname); error = tryall_dlopen (handle, filename) != 0; - lt_dlfree (filename); + LT_DLFREE (filename); if (!error) { return 0; @@ -1302,7 +1392,7 @@ find_module (handle, dir, libdir, dlname /* 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 +1405,7 @@ find_module (handle, dir, libdir, dlname strcat(filename, dlname); error = (tryall_dlopen (handle, filename) != 0); - lt_dlfree (filename); + LT_DLFREE (filename); if (!error) { return 0; @@ -1331,7 +1421,7 @@ canonicalize_path (path) const char *path; { char *canonical = 0; - + if (path && *path) { char *ptr = strdup (path); @@ -1365,7 +1455,7 @@ find_file (basename, search_path, pdir, int lenbase = strlen (basename); char *canonical = 0; char *next = 0; - + if (!search_path || !*search_path) { last_error = LT_DLSTRERROR (FILE_NOT_FOUND); @@ -1408,13 +1498,9 @@ find_file (basename, search_path, pdir, 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 +1528,7 @@ find_file (basename, search_path, pdir, FILE *file = fopen (filename, LT_READTEXT_MODE); if (file) { - if (*pdir) - { - lt_dlfree (*pdir); - } + LT_DLFREE (*pdir); filename[lendir] = '\0'; *pdir = strdup(filename); @@ -1462,12 +1545,12 @@ find_file (basename, search_path, pdir, } } } - + 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 +1620,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 +1655,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); @@ -1614,7 +1696,7 @@ load_deplibs(handle, deplibs) goto cleanup_names; } - handles[i] = handle; + handles[i] = handle; } handle->depcount = depcount; @@ -1625,15 +1707,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; @@ -1645,7 +1727,7 @@ unload_deplibs(handle) { int i; int errors = 0; - + if (handle->depcount) { for (i = 0; i < handle->depcount; ++i) @@ -1665,20 +1747,17 @@ trim (dest, str) char **dest; const char *str; { - /* remove the leading and trailing "'" from str + /* remove the leading and trailing "'" from str and store the result in dest */ const char *end = strrchr (str, '\''); int len = strlen (str); char *tmp; - if (*dest) - { - lt_dlfree(*dest); - } - + LT_DLFREE (*dest); + if (len > 3 && str[0] == '\'') { - tmp = (char*) lt_dlmalloc(end - str); + tmp = LT_DLMALLOC (char, end - str); if (!tmp) { last_error = LT_DLSTRERROR (NO_MEMORY); @@ -1693,7 +1772,7 @@ trim (dest, str) { *dest = 0; } - + return 0; } @@ -1704,10 +1783,10 @@ free_vars( dlname, oldname, libdir, depl 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; } @@ -1720,11 +1799,11 @@ lt_dlopen (filename) const char *ext; const char *saved_error = last_error; char *canonical = 0, *basename = 0, *dir = 0, *name = 0; - + /* dlopen self? */ if (!filename) { - handle = (lt_dlhandle) lt_dlmalloc (sizeof (struct lt_dlhandle_struct)); + handle = (lt_dlhandle) LT_DLMALLOC (struct lt_dlhandle_struct, 1); if (!handle) { last_error = LT_DLSTRERROR (NO_MEMORY); @@ -1734,6 +1813,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 +1821,7 @@ lt_dlopen (filename) if (tryall_dlopen (&newhandle, 0) != 0) { - lt_dlfree(handle); + LT_DLFREE (handle); return 0; } goto register_handle; @@ -1751,10 +1831,7 @@ lt_dlopen (filename) if (!canonical) { last_error = LT_DLSTRERROR (NO_MEMORY); - if (handle) - { - lt_dlfree(handle); - } + LT_DLFREE (handle); return 0; } @@ -1764,7 +1841,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); @@ -1795,10 +1872,10 @@ lt_dlopen (filename) /* if we can't find the installed flag, it is probably an installed libtool archive, produced with an old version of libtool */ - int installed = 1; + int installed = 1; /* extract the module name from the file name */ - name = (char*) lt_dlmalloc(ext - basename + 1); + name = LT_DLMALLOC (char, ext - basename + 1); if (!name) { last_error = LT_DLSTRERROR (NO_MEMORY); @@ -1833,7 +1910,7 @@ lt_dlopen (filename) file = (FILE*) find_file(basename, getenv("LTDL_LIBRARY_PATH"), &dir, 0); } - + #ifdef LTDL_SHLIBPATH_VAR if (!file) { @@ -1856,14 +1933,14 @@ lt_dlopen (filename) { last_error = LT_DLSTRERROR (FILE_NOT_FOUND); } - + if (!file) { handle = 0; goto cleanup; } - line = (char*) lt_dlmalloc (LT_FILENAME_MAX); + line = LT_DLMALLOC (char, LT_FILENAME_MAX); if (!line) { fclose (file); @@ -1891,7 +1968,7 @@ lt_dlopen (filename) { error = trim (&dlname, &line[sizeof (STR_DLNAME) - 1]); } - + #undef STR_OLD_LIBRARY #define STR_OLD_LIBRARY "old_library=" else if (strncmp (line, STR_OLD_LIBRARY, @@ -1933,8 +2010,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 +2021,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 +2057,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 +2069,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 +2098,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 +2118,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; } @@ -2066,7 +2133,7 @@ lt_dlopenext (filename) char *tmp; int len; const char *saved_error = last_error; - + if (!filename) { return lt_dlopen (filename); @@ -2080,7 +2147,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 +2159,7 @@ lt_dlopenext (filename) if (handle) { last_error = saved_error; - lt_dlfree (tmp); + LT_DLFREE (tmp); return handle; } @@ -2100,8 +2167,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,10 +2186,10 @@ lt_dlopenext (filename) if (handle) { last_error = saved_error; - lt_dlfree (tmp); + LT_DLFREE (tmp); return handle; } -#endif +#endif /* try the normal file name */ handle = lt_dlopen (filename); @@ -2130,9 +2197,9 @@ lt_dlopenext (filename) { return handle; } - + last_error = LT_DLSTRERROR (FILE_NOT_FOUND); - lt_dlfree (tmp); + LT_DLFREE (tmp); return 0; } @@ -2141,7 +2208,7 @@ lt_dlclose (handle) lt_dlhandle handle; { lt_dlhandle cur, last; - + /* check whether the handle is valid */ last = cur = handles; while (cur && handle != cur) @@ -2166,7 +2233,7 @@ lt_dlclose (handle) { int error; lt_user_data data = handle->loader->dlloader_data; - + if (handle != handles) { last->next = handle->next; @@ -2179,17 +2246,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; } @@ -2199,7 +2259,7 @@ lt_dlclose (handle) last_error = LT_DLSTRERROR (CLOSE_RESIDENT_MODULE); return 1; } - + return 0; } @@ -2243,7 +2303,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) @@ -2256,7 +2316,7 @@ lt_dlsym (handle, symbol) if (handle->info.name) { const char *saved_error = last_error; - + /* this is a libtool module */ if (handle->loader->sym_prefix) { @@ -2277,7 +2337,7 @@ lt_dlsym (handle, symbol) { if (sym != lsym) { - lt_dlfree(sym); + LT_DLFREE (sym); } return address; } @@ -2298,7 +2358,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; @@ -2308,7 +2368,7 @@ const char * lt_dlerror () { const char *error = last_error; - + last_error = 0; return error; } @@ -2334,19 +2394,18 @@ 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) { last_error = LT_DLSTRERROR (NO_MEMORY); return 1; } - + sprintf (new_search_path, "%s%c%s", user_search_path, LT_PATHSEP_CHAR, search_dir); - lt_dlfree (user_search_path); - user_search_path = new_search_path; + LT_DLMEM_REASSIGN (user_search_path, new_search_path); } return 0; @@ -2356,11 +2415,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 +2465,11 @@ lt_dlisresident (handle) return LT_DLIS_RESIDENT (handle); } + + + +/* --- MODULE INFORMATION --- */ + const lt_dlinfo * lt_dlgetinfo (handle) lt_dlhandle handle; @@ -2444,6 +2504,132 @@ 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))) + +int +lt_dlcaller_set_data (key, handle, data) + lt_dlcaller_id key; + lt_dlhandle handle; + lt_ptr data; +{ + int n_elements = 0; + + if (handle->caller) + n_elements = N_ELEMENTS (handle->caller_data); + + /* Don't let the caller leak keyed data references. */ + { + int i; + for (i = 0; i < n_elements; ++i) + { + if (handle->caller_data[i].key == key) + { + last_error = LT_DLSTRERROR (CALLER_DATA_EXISTS); + return 1; + } + } + } + + /* Ensure that there is enough room in this handle's caller_data + array to accept a new element. */ + { + 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 1; + } + else + { + handle->caller_data = temp; + } + } + + handle->caller_data[n_elements].key = key; + handle->caller_data[n_elements].data = data; + + return 0; +} + +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) + 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; +} + +lt_ptr +lt_dlcaller_remove_data (key, handle) + lt_dlcaller_id key; + lt_dlhandle handle; +{ + lt_ptr result = (lt_ptr) 0; + int n_elements = 0; + + if (handle->caller) + 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; + } + } + + /* Don't forget that our memcpy implementation may not handle overlaps, + so this has to be done by hand. */ + while (1+ i < n_elements) + { + handle->caller_data[i].key = handle->caller_data[1+ i].key; + handle->caller_data[i].data = handle->caller_data[1+ i].data; + ++i; + } + } + + return result; +} + + + + +/* --- USER MODULE LOADER API --- */ + + int lt_dlloader_add (place, dlloader, loader_name) lt_dlloader *place; @@ -2451,7 +2637,7 @@ lt_dlloader_add (place, dlloader, loader const char *loader_name; { lt_dlloader *node = 0, *ptr = 0; - + if ((dlloader == 0) /* diagnose null parameters */ || (dlloader->module_open == 0) || (dlloader->module_close == 0) @@ -2462,7 +2648,7 @@ lt_dlloader_add (place, dlloader, loader } /* 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); @@ -2476,7 +2662,7 @@ lt_dlloader_add (place, dlloader, loader node->module_close = dlloader->module_close; node->find_sym = dlloader->find_sym; node->dlloader_data = dlloader->dlloader_data; - + if (!loaders) { /* If there are no loaders, NODE becomes the list! */ @@ -2544,7 +2730,7 @@ lt_dlloader_remove (loader_name) return 1; } } - + if (place == loaders) { /* PLACE is the first loader in the list. */ @@ -2565,16 +2751,13 @@ lt_dlloader_remove (loader_name) place = prev->next; prev->next = prev->next->next; } - + if (place->dlloader_exit) { result = place->dlloader_exit (place->dlloader_data); } - if (place) - { - lt_dlfree (place); - } + LT_DLFREE (place); return result; } @@ -2585,7 +2768,7 @@ lt_dlloader_next (place) { return place ? place->next : loaders; } - + const char * lt_dlloader_name (place) lt_dlloader *place; @@ -2596,7 +2779,7 @@ lt_dlloader_name (place) } return place ? place->loader_name : 0; -} +} lt_user_data * lt_dlloader_data (place) @@ -2608,7 +2791,7 @@ lt_dlloader_data (place) } return place ? &(place->dlloader_data) : 0; -} +} lt_dlloader * lt_dlloader_find (loader_name) @@ -2626,4 +2809,3 @@ lt_dlloader_find (loader_name) return place; } - Index: libltdl/ltdl.h =================================================================== RCS file: /home/cvs/libtool/libltdl/ltdl.h,v retrieving revision 1.50 diff -u -p -r1.50 ltdl.h --- libltdl/ltdl.h 2001/01/04 22:06:11 1.50 +++ libltdl/ltdl.h 2001/01/05 01:55:53 @@ -208,8 +208,19 @@ 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 int 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_caller_id key, + lt_dlhandle handle)); +extern lt_ptr lt_dlcaller_remove_data LT_PARAMS((lt_caller_id key, + lt_dlhandle handle)); + /* --- USER MODULE LOADER API --- */ @@ -274,7 +285,8 @@ extern int lt_dlloader_remove LT_PARAM LT_ERROR(BUFFER_OVERFLOW, "internal buffer overflow") \ LT_ERROR(INVALID_ERRORCODE, "invalid errorcode") \ LT_ERROR(SHUTDOWN, "library already shutdown") \ - LT_ERROR(CLOSE_RESIDENT_MODULE, "can't close resident module") + LT_ERROR(CLOSE_RESIDENT_MODULE, "can't close resident module") \ + LT_ERROR(CALLER_DATA_EXISTS, "keyed caller data is already set") /* Enumerate the symbolic error names. */ enum {