448bc67cd34ec0e4db9cdd5ad6a7f2bf8f1f2cb5
[fw/sdcc] / sim / ucsim / libltdl / ltdl.c
1 /* ltdl.c -- system independent dlopen wrapper
2    Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
3    Originally by Thomas Tanner <tanner@ffii.org>
4    This file is part of GNU Libtool.
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 As a special exception to the GNU Lesser General Public License,
12 if you distribute this file as part of a program or library that
13 is built using GNU libtool, you may include it under the same
14 distribution terms that you use for the rest of that program.
15
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 Lesser General Public License for more details.
20
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 02111-1307  USA
25
26 */
27
28 #if HAVE_CONFIG_H
29 #  include <config.h>
30 #endif
31
32 #if HAVE_UNISTD_H
33 #  include <unistd.h>
34 #endif
35
36 #if HAVE_STDIO_H
37 #  include <stdio.h>
38 #endif
39
40 #if HAVE_STDLIB_H
41 #  include <stdlib.h>
42 #endif
43
44 #if HAVE_STRING_H
45 #  include <string.h>
46 #else
47 #  if HAVE_STRINGS_H
48 #    include <strings.h>
49 #  endif
50 #endif
51
52 #if HAVE_CTYPE_H
53 #  include <ctype.h>
54 #endif
55
56 #if HAVE_MALLOC_H
57 #  include <malloc.h>
58 #endif
59
60 #if HAVE_MEMORY_H
61 #  include <memory.h>
62 #endif
63
64 #if HAVE_ERRNO_H
65 #  include <errno.h>
66 #endif
67
68 #if HAVE_DIRENT_H
69 #  include <dirent.h>
70 #  define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
71 #else
72 #  define dirent direct
73 #  define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
74 #  if HAVE_SYS_NDIR_H
75 #    include <sys/ndir.h>
76 #  endif
77 #  if HAVE_SYS_DIR_H
78 #    include <sys/dir.h>
79 #  endif
80 #  if HAVE_NDIR_H
81 #    include <ndir.h>
82 #  endif
83 #endif
84
85 #if HAVE_ARGZ_H
86 #  include <argz.h>
87 #endif
88
89 #if HAVE_ASSERT_H
90 #  include <assert.h>
91 #else
92 #  define assert(arg)   ((void) 0)
93 #endif
94
95 #include "ltdl.h"
96
97 #if WITH_DMALLOC
98 #  include <dmalloc.h>
99 #endif
100
101
102
103 \f
104 /* --- WINDOWS SUPPORT --- */
105
106
107 #ifdef DLL_EXPORT
108 #  define LT_GLOBAL_DATA        __declspec(dllexport)
109 #else
110 #  define LT_GLOBAL_DATA
111 #endif
112
113 /* fopen() mode flags for reading a text file */
114 #undef  LT_READTEXT_MODE
115 #ifdef __WINDOWS__
116 #  define LT_READTEXT_MODE "rt"
117 #else
118 #  define LT_READTEXT_MODE "r"
119 #endif
120
121
122
123 \f
124 /* --- MANIFEST CONSTANTS --- */
125
126
127 /* Standard libltdl search path environment variable name  */
128 #undef  LTDL_SEARCHPATH_VAR
129 #define LTDL_SEARCHPATH_VAR     "LTDL_LIBRARY_PATH"
130
131 /* Standard libtool archive file extension.  */
132 #undef  LTDL_ARCHIVE_EXT
133 #define LTDL_ARCHIVE_EXT        ".la"
134
135 /* max. filename length */
136 #ifndef LT_FILENAME_MAX
137 #  define LT_FILENAME_MAX       1024
138 #endif
139
140 /* This is the maximum symbol size that won't require malloc/free */
141 #undef  LT_SYMBOL_LENGTH
142 #define LT_SYMBOL_LENGTH        128
143
144 /* This accounts for the _LTX_ separator */
145 #undef  LT_SYMBOL_OVERHEAD
146 #define LT_SYMBOL_OVERHEAD      5
147
148
149
150 \f
151 /* --- MEMORY HANDLING --- */
152
153
154 /* These are the functions used internally.  In addition to making
155    use of the associated function pointers above, they also perform
156    error handling.  */
157 static char   *lt_estrdup       LT_PARAMS((const char *str));
158 static lt_ptr lt_emalloc        LT_PARAMS((size_t size));
159 static lt_ptr lt_erealloc       LT_PARAMS((lt_ptr addr, size_t size));
160
161 static lt_ptr rpl_realloc       LT_PARAMS((lt_ptr ptr, size_t size));
162
163 /* These are the pointers that can be changed by the caller:  */
164 LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc)    LT_PARAMS((size_t size))
165                         = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
166 LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc)   LT_PARAMS((lt_ptr ptr, size_t size))
167                         = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
168 LT_GLOBAL_DATA void   (*lt_dlfree)      LT_PARAMS((lt_ptr ptr))
169                         = (void (*) LT_PARAMS((lt_ptr))) free;
170
171 /* The following macros reduce the amount of typing needed to cast
172    assigned memory.  */
173 #if WITH_DMALLOC
174
175 #define LT_DLMALLOC(tp, n)      ((tp *) xmalloc ((n) * sizeof(tp)))
176 #define LT_DLREALLOC(tp, p, n)  ((tp *) xrealloc ((p), (n) * sizeof(tp)))
177 #define LT_DLFREE(p)                                            \
178         LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
179
180 #define LT_EMALLOC(tp, n)       ((tp *) xmalloc ((n) * sizeof(tp)))
181 #define LT_EREALLOC(tp, p, n)   ((tp *) xrealloc ((p), (n) * sizeof(tp)))
182
183 #else
184
185 #define LT_DLMALLOC(tp, n)      ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
186 #define LT_DLREALLOC(tp, p, n)  ((tp *) rpl_realloc ((p), (n) * sizeof(tp)))
187 #define LT_DLFREE(p)                                            \
188         LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
189
190 #define LT_EMALLOC(tp, n)       ((tp *) lt_emalloc ((n) * sizeof(tp)))
191 #define LT_EREALLOC(tp, p, n)   ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
192
193 #endif
194
195 #define LT_DLMEM_REASSIGN(p, q)                 LT_STMT_START { \
196         if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; }   \
197                                                 } LT_STMT_END
198
199 \f
200 /* --- REPLACEMENT FUNCTIONS --- */
201
202
203 #undef strdup
204 #define strdup rpl_strdup
205
206 static char *strdup LT_PARAMS((const char *str));
207
208 static char *
209 strdup(str)
210      const char *str;
211 {
212   char *tmp = 0;
213
214   if (str)
215     {
216       tmp = LT_DLMALLOC (char, 1+ strlen (str));
217       if (tmp)
218         {
219           strcpy(tmp, str);
220         }
221     }
222
223   return tmp;
224 }
225
226
227 #if ! HAVE_STRCMP
228
229 #undef strcmp
230 #define strcmp rpl_strcmp
231
232 static int strcmp LT_PARAMS((const char *str1, const char *str2));
233
234 static int
235 strcmp (str1, str2)
236      const char *str1;
237      const char *str2;
238 {
239   if (str1 == str2)
240     return 0;
241   if (str1 == 0)
242     return -1;
243   if (str2 == 0)
244     return 1;
245
246   for (;*str1 && *str2; ++str1, ++str2)
247     {
248       if (*str1 != *str2)
249         break;
250     }
251
252   return (int)(*str1 - *str2);
253 }
254 #endif
255
256
257 #if ! HAVE_STRCHR
258
259 #  if HAVE_INDEX
260 #    define strchr index
261 #  else
262 #    define strchr rpl_strchr
263
264 static const char *strchr LT_PARAMS((const char *str, int ch));
265
266 static const char*
267 strchr(str, ch)
268      const char *str;
269      int ch;
270 {
271   const char *p;
272
273   for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
274     /*NOWORK*/;
275
276   return (*p == (char)ch) ? p : 0;
277 }
278
279 #  endif
280 #endif /* !HAVE_STRCHR */
281
282
283 #if ! HAVE_STRRCHR
284
285 #  if HAVE_RINDEX
286 #    define strrchr rindex
287 #  else
288 #    define strrchr rpl_strrchr
289
290 static const char *strrchr LT_PARAMS((const char *str, int ch));
291
292 static const char*
293 strrchr(str, ch)
294      const char *str;
295      int ch;
296 {
297   const char *p, *q = 0;
298
299   for (p = str; *p != LT_EOS_CHAR; ++p)
300     {
301       if (*p == (char) ch)
302         {
303           q = p;
304         }
305     }
306
307   return q;
308 }
309
310 # endif
311 #endif
312
313 /* NOTE:  Neither bcopy nor the memcpy implementation below can
314           reliably handle copying in overlapping areas of memory.  Use
315           memmove (for which there is a fallback implmentation below)
316           if you need that behaviour.  */
317 #if ! HAVE_MEMCPY
318
319 #  if HAVE_BCOPY
320 #    define memcpy(dest, src, size)     bcopy (src, dest, size)
321 #  else
322 #    define memcpy rpl_memcpy
323
324 static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
325
326 static lt_ptr
327 memcpy (dest, src, size)
328      lt_ptr dest;
329      const lt_ptr src;
330      size_t size;
331 {
332   size_t i = 0;
333
334   for (i = 0; i < size; ++i)
335     {
336       dest[i] = src[i];
337     }
338
339   return dest;
340 }
341
342 #  endif /* !HAVE_BCOPY */
343 #endif   /* !HAVE_MEMCPY */
344
345 #if ! HAVE_MEMMOVE
346 #  define memmove rpl_memmove
347
348 static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
349
350 static lt_ptr
351 memmove (dest, src, size)
352      lt_ptr dest;
353      const lt_ptr src;
354      size_t size;
355 {
356   size_t i;
357
358   if (dest < src)
359     for (i = 0; i < size; ++i)
360       {
361         dest[i] = src[i];
362       }
363   else if (dest > src)
364     for (i = size -1; i >= 0; --i)
365       {
366         dest[i] = src[i];
367       }
368
369   return dest;
370 }
371
372 #endif /* !HAVE_MEMMOVE */
373
374
375 /* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
376     ``realloc is not entirely portable''
377    In any case we want to use the allocator supplied by the user without
378    burdening them with an lt_dlrealloc function pointer to maintain.
379    Instead implement our own version (with known boundary conditions)
380    using lt_dlmalloc and lt_dlfree. */
381
382 #undef realloc
383 #define realloc rpl_realloc
384
385 static lt_ptr
386 realloc (ptr, size)
387      lt_ptr ptr;
388      size_t size;
389 {
390   if (size == 0)
391     {
392       /* For zero or less bytes, free the original memory */
393       if (ptr != 0)
394         {
395           lt_dlfree (ptr);
396         }
397
398       return (lt_ptr) 0;
399     }
400   else if (ptr == 0)
401     {
402       /* Allow reallocation of a NULL pointer.  */
403       return lt_dlmalloc (size);
404     }
405   else
406     {
407       /* Allocate a new block, copy and free the old block.  */
408       lt_ptr mem = lt_dlmalloc (size);
409
410       if (mem)
411         {
412           memcpy (mem, ptr, size);
413           lt_dlfree (ptr);
414         }
415
416       /* Note that the contents of PTR are not damaged if there is
417          insufficient memory to realloc.  */
418       return mem;
419     }
420 }
421
422
423 #if ! HAVE_ARGZ_APPEND
424 #  define argz_append rpl_argz_append
425
426 static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
427                                         const char *buf, size_t buf_len));
428
429 static error_t
430 argz_append (pargz, pargz_len, buf, buf_len)
431      char **pargz;
432      size_t *pargz_len;
433      const char *buf;
434      size_t buf_len;
435 {
436   size_t argz_len;
437   char  *argz;
438
439   assert (pargz);
440   assert (pargz_len);
441   assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
442
443   /* If nothing needs to be appended, no more work is required.  */
444   if (buf_len == 0)
445     return 0;
446
447   /* Ensure there is enough room to append BUF_LEN.  */
448   argz_len = *pargz_len + buf_len;
449   argz = LT_DLREALLOC (char, *pargz, argz_len);
450   if (!argz)
451     return ENOMEM;
452
453   /* Copy characters from BUF after terminating '\0' in ARGZ.  */
454   memcpy (argz + *pargz_len, buf, buf_len);
455
456   /* Assign new values.  */
457   *pargz = argz;
458   *pargz_len = argz_len;
459
460   return 0;
461 }
462 #endif /* !HAVE_ARGZ_APPEND */
463
464
465 #if ! HAVE_ARGZ_CREATE_SEP
466 #  define argz_create_sep rpl_argz_create_sep
467
468 static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
469                                             char **pargz, size_t *pargz_len));
470
471 static error_t
472 argz_create_sep (str, delim, pargz, pargz_len)
473      const char *str;
474      int delim;
475      char **pargz;
476      size_t *pargz_len;
477 {
478   size_t argz_len;
479   char *argz = 0;
480
481   assert (str);
482   assert (pargz);
483   assert (pargz_len);
484
485   /* Make a copy of STR, but replacing each occurence of
486      DELIM with '\0'.  */
487   argz_len = 1+ LT_STRLEN (str);
488   if (argz_len)
489     {
490       const char *p;
491       char *q;
492
493       argz = LT_DLMALLOC (char, argz_len);
494       if (!argz)
495         return ENOMEM;
496
497       for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
498         {
499           if (*p == delim)
500             {
501               /* Ignore leading delimiters, and fold consecutive
502                  delimiters in STR into a single '\0' in ARGZ.  */
503               if ((q > argz) && (q[-1] != LT_EOS_CHAR))
504                 *q++ = LT_EOS_CHAR;
505               else
506                 --argz_len;
507             }
508           else
509             *q++ = *p;
510         }
511       /* Copy terminating LT_EOS_CHAR.  */
512       *q = *p;
513     }
514
515   /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory.  */
516   if (!argz_len)
517     LT_DLFREE (argz);
518
519   /* Assign new values.  */
520   *pargz = argz;
521   *pargz_len = argz_len;
522
523   return 0;
524 }
525 #endif /* !HAVE_ARGZ_CREATE_SEP */
526
527
528 #if ! HAVE_ARGZ_INSERT
529 #  define argz_insert rpl_argz_insert
530
531 static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
532                                         char *before, const char *entry));
533
534 static error_t
535 argz_insert (pargz, pargz_len, before, entry)
536      char **pargz;
537      size_t *pargz_len;
538      char *before;
539      const char *entry;
540 {
541   assert (pargz);
542   assert (pargz_len);
543   assert (entry && *entry);
544
545   /* Either PARGZ/PARGZ_LEN is empty and BEFORE is NULL,
546      or BEFORE points into an address within the ARGZ vector.  */
547   assert ((!*pargz && !*pargz_len && !before)
548           || ((*pargz <= before) && (before < (*pargz + *pargz_len))));
549
550   /* No BEFORE address indicates ENTRY should be inserted after the
551      current last element.  */
552   if (!before)
553     return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry));
554
555   /* This probably indicates a programmer error, but to preserve
556      semantics, scan back to the start of an entry if BEFORE points
557      into the middle of it.  */
558   while ((before >= *pargz) && (before[-1] != LT_EOS_CHAR))
559     --before;
560
561   {
562     size_t entry_len    = 1+ LT_STRLEN (entry);
563     size_t argz_len     = *pargz_len + entry_len;
564     size_t offset       = before - *pargz;
565     char   *argz        = LT_DLREALLOC (char, *pargz, argz_len);
566
567     if (!argz)
568       return ENOMEM;
569
570     /* Make BEFORE point to the equivalent offset in ARGZ that it
571        used to have in *PARGZ incase realloc() moved the block.  */
572     before = argz + offset;
573
574     /* Move the ARGZ entries starting at BEFORE up into the new
575        space at the end -- making room to copy ENTRY into the
576        resulting gap.  */
577     memmove (before + entry_len, before, *pargz_len - offset);
578     memcpy  (before, entry, entry_len);
579
580     /* Assign new values.  */
581     *pargz = argz;
582     *pargz_len = argz_len;
583   }
584
585   return 0;
586 }
587 #endif /* !HAVE_ARGZ_INSERT */
588
589
590 #if ! HAVE_ARGZ_NEXT
591 #  define argz_next rpl_argz_next
592
593 static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
594                                     const char *entry));
595
596 static char *
597 argz_next (argz, argz_len, entry)
598      char *argz;
599      size_t argz_len;
600      const char *entry;
601 {
602   assert ((argz && argz_len) || (!argz && !argz_len));
603
604   if (entry)
605     {
606       /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
607          within the ARGZ vector.  */
608       assert ((!argz && !argz_len)
609               || ((argz <= entry) && (entry < (argz + argz_len))));
610
611       /* Move to the char immediately after the terminating
612          '\0' of ENTRY.  */
613       entry = 1+ strchr (entry, LT_EOS_CHAR);
614
615       /* Return either the new ENTRY, or else NULL if ARGZ is
616          exhausted.  */
617       return (entry >= argz + argz_len) ? 0 : (char *) entry;
618     }
619   else
620     {
621       /* This should probably be flagged as a programmer error,
622          since starting an argz_next loop with the iterator set
623          to ARGZ is safer.  To preserve semantics, handle the NULL
624          case by returning the start of ARGZ (if any).  */
625       if (argz_len > 0)
626         return argz;
627       else
628         return 0;
629     }
630 }
631 #endif /* !HAVE_ARGZ_NEXT */
632
633
634
635 #if ! HAVE_ARGZ_STRINGIFY
636 #  define argz_stringify rpl_argz_stringify
637
638 static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
639                                        int sep));
640
641 static void
642 argz_stringify (argz, argz_len, sep)
643      char *argz;
644      size_t argz_len;
645      int sep;
646 {
647   assert ((argz && argz_len) || (!argz && !argz_len));
648
649   if (sep)
650     {
651       --argz_len;               /* don't stringify the terminating EOS */
652       while (--argz_len > 0)
653         {
654           if (argz[argz_len] == LT_EOS_CHAR)
655             argz[argz_len] = sep;
656         }
657     }
658 }
659 #endif /* !HAVE_ARGZ_STRINGIFY */
660
661
662
663 \f
664 /* --- TYPE DEFINITIONS -- */
665
666
667 /* This type is used for the array of caller data sets in each handler. */
668 typedef struct {
669   lt_dlcaller_id        key;
670   lt_ptr                data;
671 } lt_caller_data;
672
673
674
675 \f
676 /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
677
678
679 /* Extract the diagnostic strings from the error table macro in the same
680    order as the enumerated indices in ltdl.h. */
681
682 static const char *lt_dlerror_strings[] =
683   {
684 #define LT_ERROR(name, diagnostic)      (diagnostic),
685     lt_dlerror_table
686 #undef LT_ERROR
687
688     0
689   };
690
691 /* This structure is used for the list of registered loaders. */
692 struct lt_dlloader {
693   struct lt_dlloader   *next;
694   const char           *loader_name;    /* identifying name for each loader */
695   const char           *sym_prefix;     /* prefix for symbols */
696   lt_module_open       *module_open;
697   lt_module_close      *module_close;
698   lt_find_sym          *find_sym;
699   lt_dlloader_exit     *dlloader_exit;
700   lt_user_data          dlloader_data;
701 };
702
703 struct lt_dlhandle_struct {
704   struct lt_dlhandle_struct   *next;
705   lt_dlloader          *loader;         /* dlopening interface */
706   lt_dlinfo             info;
707   int                   depcount;       /* number of dependencies */
708   lt_dlhandle          *deplibs;        /* dependencies */
709   lt_module             module;         /* system module handle */
710   lt_ptr                system;         /* system specific data */
711   lt_caller_data       *caller_data;    /* per caller associated data */
712   int                   flags;          /* various boolean stats */
713 };
714
715 /* Various boolean flags can be stored in the flags field of an
716    lt_dlhandle_struct... */
717 #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
718 #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
719
720 #define LT_DLRESIDENT_FLAG          (0x01 << 0)
721 /* ...add more flags here... */
722
723 #define LT_DLIS_RESIDENT(handle)    LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
724
725
726 #define LT_DLSTRERROR(name)     lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
727
728 static  const char      objdir[]                = LTDL_OBJDIR;
729 static  const char      archive_ext[]           = LTDL_ARCHIVE_EXT;
730 #ifdef  LTDL_SHLIB_EXT
731 static  const char      shlib_ext[]             = LTDL_SHLIB_EXT;
732 #endif
733 #ifdef  LTDL_SYSSEARCHPATH
734 static  const char      sys_search_path[]       = LTDL_SYSSEARCHPATH;
735 #endif
736
737
738
739 \f
740 /* --- MUTEX LOCKING --- */
741
742
743 /* Macros to make it easier to run the lock functions only if they have
744    been registered.  The reason for the complicated lock macro is to
745    ensure that the stored error message from the last error is not
746    accidentally erased if the current function doesn't generate an
747    error of its own.  */
748 #define LT_DLMUTEX_LOCK()                       LT_STMT_START { \
749         if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)();    \
750                                                 } LT_STMT_END
751 #define LT_DLMUTEX_UNLOCK()                     LT_STMT_START { \
752         if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
753                                                 } LT_STMT_END
754 #define LT_DLMUTEX_SETERROR(errormsg)           LT_STMT_START { \
755         if (lt_dlmutex_seterror_func)                           \
756                 (*lt_dlmutex_seterror_func) (errormsg);         \
757         else    lt_dllast_error = (errormsg);   } LT_STMT_END
758 #define LT_DLMUTEX_GETERROR(errormsg)           LT_STMT_START { \
759         if (lt_dlmutex_seterror_func)                           \
760                 (errormsg) = (*lt_dlmutex_geterror_func) ();    \
761         else    (errormsg) = lt_dllast_error;   } LT_STMT_END
762
763 /* The mutex functions stored here are global, and are necessarily the
764    same for all threads that wish to share access to libltdl.  */
765 static  lt_dlmutex_lock     *lt_dlmutex_lock_func     = 0;
766 static  lt_dlmutex_unlock   *lt_dlmutex_unlock_func   = 0;
767 static  lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
768 static  lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
769 static  const char          *lt_dllast_error          = 0;
770
771
772 /* Either set or reset the mutex functions.  Either all the arguments must
773    be valid functions, or else all can be NULL to turn off locking entirely.
774    The registered functions should be manipulating a static global lock
775    from the lock() and unlock() callbacks, which needs to be reentrant.  */
776 int
777 lt_dlmutex_register (lock, unlock, seterror, geterror)
778      lt_dlmutex_lock *lock;
779      lt_dlmutex_unlock *unlock;
780      lt_dlmutex_seterror *seterror;
781      lt_dlmutex_geterror *geterror;
782 {
783   lt_dlmutex_unlock *old_unlock = unlock;
784   int                errors     = 0;
785
786   /* Lock using the old lock() callback, if any.  */
787   LT_DLMUTEX_LOCK ();
788
789   if ((lock && unlock && seterror && geterror)
790       || !(lock || unlock || seterror || geterror))
791     {
792       lt_dlmutex_lock_func     = lock;
793       lt_dlmutex_unlock_func   = unlock;
794       lt_dlmutex_geterror_func = geterror;
795     }
796   else
797     {
798       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
799       ++errors;
800     }
801
802   /* Use the old unlock() callback we saved earlier, if any.  Otherwise
803      record any errors using internal storage.  */
804   if (old_unlock)
805     (*old_unlock) ();
806
807   /* Return the number of errors encountered during the execution of
808      this function.  */
809   return errors;
810 }
811
812
813
814 \f
815 /* --- ERROR HANDLING --- */
816
817
818 static  const char    **user_error_strings      = 0;
819 static  int             errorcount              = LT_ERROR_MAX;
820
821 int
822 lt_dladderror (diagnostic)
823      const char *diagnostic;
824 {
825   int           errindex = 0;
826   int           result   = -1;
827   const char  **temp     = (const char **) 0;
828
829   assert (diagnostic);
830
831   LT_DLMUTEX_LOCK ();
832
833   errindex = errorcount - LT_ERROR_MAX;
834   temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex);
835   if (temp)
836     {
837       user_error_strings                = temp;
838       user_error_strings[errindex]      = diagnostic;
839       result                            = errorcount++;
840     }
841
842   LT_DLMUTEX_UNLOCK ();
843
844   return result;
845 }
846
847 int
848 lt_dlseterror (errindex)
849      int errindex;
850 {
851   int           errors   = 0;
852
853   LT_DLMUTEX_LOCK ();
854
855   if (errindex >= errorcount || errindex < 0)
856     {
857       /* Ack!  Error setting the error message! */
858       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
859       ++errors;
860     }
861   else if (errindex < LT_ERROR_MAX)
862     {
863       /* No error setting the error message! */
864       LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
865     }
866   else
867     {
868       /* No error setting the error message! */
869       LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
870     }
871
872   LT_DLMUTEX_UNLOCK ();
873
874   return errors;
875 }
876
877 static lt_ptr
878 lt_emalloc (size)
879      size_t size;
880 {
881   lt_ptr mem = lt_dlmalloc (size);
882   if (size && !mem)
883     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
884   return mem;
885 }
886
887 static lt_ptr
888 lt_erealloc (addr, size)
889      lt_ptr addr;
890      size_t size;
891 {
892   lt_ptr mem = realloc (addr, size);
893   if (size && !mem)
894     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
895   return mem;
896 }
897
898 static char *
899 lt_estrdup (str)
900      const char *str;
901 {
902   char *copy = strdup (str);
903   if (LT_STRLEN (str) && !copy)
904     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
905   return copy;
906 }
907
908
909
910 \f
911 /* --- DLOPEN() INTERFACE LOADER --- */
912
913
914 /* The Cygwin dlopen implementation prints a spurious error message to
915    stderr if its call to LoadLibrary() fails for any reason.  We can
916    mitigate this by not using the Cygwin implementation, and falling
917    back to our own LoadLibrary() wrapper. */
918 #if HAVE_LIBDL && !defined(__CYGWIN__)
919
920 /* dynamic linking with dlopen/dlsym */
921
922 #if HAVE_DLFCN_H
923 #  include <dlfcn.h>
924 #endif
925
926 #if HAVE_SYS_DL_H
927 #  include <sys/dl.h>
928 #endif
929
930 #ifdef RTLD_GLOBAL
931 #  define LT_GLOBAL             RTLD_GLOBAL
932 #else
933 #  ifdef DL_GLOBAL
934 #    define LT_GLOBAL           DL_GLOBAL
935 #  endif
936 #endif /* !RTLD_GLOBAL */
937 #ifndef LT_GLOBAL
938 #  define LT_GLOBAL             0
939 #endif /* !LT_GLOBAL */
940
941 /* We may have to define LT_LAZY_OR_NOW in the command line if we
942    find out it does not work in some platform. */
943 #ifndef LT_LAZY_OR_NOW
944 #  ifdef RTLD_LAZY
945 #    define LT_LAZY_OR_NOW      RTLD_LAZY
946 #  else
947 #    ifdef DL_LAZY
948 #      define LT_LAZY_OR_NOW    DL_LAZY
949 #    endif
950 #  endif /* !RTLD_LAZY */
951 #endif
952 #ifndef LT_LAZY_OR_NOW
953 #  ifdef RTLD_NOW
954 #    define LT_LAZY_OR_NOW      RTLD_NOW
955 #  else
956 #    ifdef DL_NOW
957 #      define LT_LAZY_OR_NOW    DL_NOW
958 #    endif
959 #  endif /* !RTLD_NOW */
960 #endif
961 #ifndef LT_LAZY_OR_NOW
962 #  define LT_LAZY_OR_NOW        0
963 #endif /* !LT_LAZY_OR_NOW */
964
965 #if HAVE_DLERROR
966 #  define DLERROR(arg)  dlerror ()
967 #else
968 #  define DLERROR(arg)  LT_DLSTRERROR (arg)
969 #endif
970
971 static lt_module
972 sys_dl_open (loader_data, filename)
973      lt_user_data loader_data;
974      const char *filename;
975 {
976   lt_module   module   = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
977
978   if (!module)
979     {
980       LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
981     }
982
983   return module;
984 }
985
986 static int
987 sys_dl_close (loader_data, module)
988      lt_user_data loader_data;
989      lt_module module;
990 {
991   int errors = 0;
992
993   if (dlclose (module) != 0)
994     {
995       LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
996       ++errors;
997     }
998
999   return errors;
1000 }
1001
1002 static lt_ptr
1003 sys_dl_sym (loader_data, module, symbol)
1004      lt_user_data loader_data;
1005      lt_module module;
1006      const char *symbol;
1007 {
1008   lt_ptr address = dlsym (module, symbol);
1009
1010   if (!address)
1011     {
1012       LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
1013     }
1014
1015   return address;
1016 }
1017
1018 static struct lt_user_dlloader sys_dl =
1019   {
1020 #  ifdef NEED_USCORE
1021     "_",
1022 #  else
1023     0,
1024 #  endif
1025     sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
1026
1027
1028 #endif /* HAVE_LIBDL */
1029
1030
1031 \f
1032 /* --- SHL_LOAD() INTERFACE LOADER --- */
1033
1034 #if HAVE_SHL_LOAD
1035
1036 /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
1037
1038 #ifdef HAVE_DL_H
1039 #  include <dl.h>
1040 #endif
1041
1042 /* some flags are missing on some systems, so we provide
1043  * harmless defaults.
1044  *
1045  * Mandatory:
1046  * BIND_IMMEDIATE  - Resolve symbol references when the library is loaded.
1047  * BIND_DEFERRED   - Delay code symbol resolution until actual reference.
1048  *
1049  * Optionally:
1050  * BIND_FIRST      - Place the library at the head of the symbol search
1051  *                   order.
1052  * BIND_NONFATAL   - The default BIND_IMMEDIATE behavior is to treat all
1053  *                   unsatisfied symbols as fatal.  This flag allows
1054  *                   binding of unsatisfied code symbols to be deferred
1055  *                   until use.
1056  *                   [Perl: For certain libraries, like DCE, deferred
1057  *                   binding often causes run time problems. Adding
1058  *                   BIND_NONFATAL to BIND_IMMEDIATE still allows
1059  *                   unresolved references in situations like this.]
1060  * BIND_NOSTART    - Do not call the initializer for the shared library
1061  *                   when the library is loaded, nor on a future call to
1062  *                   shl_unload().
1063  * BIND_VERBOSE    - Print verbose messages concerning possible
1064  *                   unsatisfied symbols.
1065  *
1066  * hp9000s700/hp9000s800:
1067  * BIND_RESTRICTED - Restrict symbols visible by the library to those
1068  *                   present at library load time.
1069  * DYNAMIC_PATH    - Allow the loader to dynamically search for the
1070  *                   library specified by the path argument.
1071  */
1072
1073 #ifndef DYNAMIC_PATH
1074 #  define DYNAMIC_PATH          0
1075 #endif
1076 #ifndef BIND_RESTRICTED
1077 #  define BIND_RESTRICTED       0
1078 #endif
1079
1080 #define LT_BIND_FLAGS   (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
1081
1082 static lt_module
1083 sys_shl_open (loader_data, filename)
1084      lt_user_data loader_data;
1085      const char *filename;
1086 {
1087   static shl_t self = (shl_t) 0;
1088   lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
1089
1090   /* Since searching for a symbol against a NULL module handle will also
1091      look in everything else that was already loaded and exported with
1092      the -E compiler flag, we always cache a handle saved before any
1093      modules are loaded.  */
1094   if (!self)
1095     {
1096       lt_ptr address;
1097       shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
1098     }
1099
1100   if (!filename)
1101     {
1102       module = self;
1103     }
1104   else
1105     {
1106       module = shl_load (filename, LT_BIND_FLAGS, 0L);
1107
1108       if (!module)
1109         {
1110           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1111         }
1112     }
1113
1114   return module;
1115 }
1116
1117 static int
1118 sys_shl_close (loader_data, module)
1119      lt_user_data loader_data;
1120      lt_module module;
1121 {
1122   int errors = 0;
1123
1124   if (module && (shl_unload ((shl_t) (module)) != 0))
1125     {
1126       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1127       ++errors;
1128     }
1129
1130   return errors;
1131 }
1132
1133 static lt_ptr
1134 sys_shl_sym (loader_data, module, symbol)
1135      lt_user_data loader_data;
1136      lt_module module;
1137      const char *symbol;
1138 {
1139   lt_ptr address = 0;
1140
1141   /* sys_shl_open should never return a NULL module handle */
1142   if (module == (lt_module) 0)
1143   {
1144     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
1145   }
1146   else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
1147     {
1148       if (!address)
1149         {
1150           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1151         }
1152     }
1153
1154   return address;
1155 }
1156
1157 static struct lt_user_dlloader sys_shl = {
1158   0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
1159 };
1160
1161 #endif /* HAVE_SHL_LOAD */
1162
1163
1164
1165 \f
1166 /* --- LOADLIBRARY() INTERFACE LOADER --- */
1167
1168 #ifdef __WINDOWS__
1169
1170 /* dynamic linking for Win32 */
1171
1172 #include <windows.h>
1173
1174 /* Forward declaration; required to implement handle search below. */
1175 static lt_dlhandle handles;
1176
1177 static lt_module
1178 sys_wll_open (loader_data, filename)
1179      lt_user_data loader_data;
1180      const char *filename;
1181 {
1182   lt_dlhandle   cur;
1183   lt_module     module     = 0;
1184   const char   *errormsg   = 0;
1185   char         *searchname = 0;
1186   char         *ext;
1187   char          self_name_buf[MAX_PATH];
1188
1189   if (!filename)
1190     {
1191       /* Get the name of main module */
1192       *self_name_buf = 0;
1193       GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
1194       filename = ext = self_name_buf;
1195     }
1196   else
1197     {
1198       ext = strrchr (filename, '.');
1199     }
1200
1201   if (ext)
1202     {
1203       /* FILENAME already has an extension. */
1204       searchname = lt_estrdup (filename);
1205     }
1206   else
1207     {
1208       /* Append a `.' to stop Windows from adding an
1209          implicit `.dll' extension. */
1210       searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
1211       if (searchname)
1212         sprintf (searchname, "%s.", filename);
1213     }
1214   if (!searchname)
1215     return 0;
1216
1217 #if __CYGWIN__
1218   {
1219     char wpath[MAX_PATH];
1220     cygwin_conv_to_full_win32_path(searchname, wpath);
1221     module = LoadLibrary(wpath);
1222   }
1223 #else
1224   module = LoadLibrary (searchname);
1225 #endif
1226   LT_DLFREE (searchname);
1227
1228   /* libltdl expects this function to fail if it is unable
1229      to physically load the library.  Sadly, LoadLibrary
1230      will search the loaded libraries for a match and return
1231      one of them if the path search load fails.
1232
1233      We check whether LoadLibrary is returning a handle to
1234      an already loaded module, and simulate failure if we
1235      find one. */
1236   LT_DLMUTEX_LOCK ();
1237   cur = handles;
1238   while (cur)
1239     {
1240       if (!cur->module)
1241         {
1242           cur = 0;
1243           break;
1244         }
1245
1246       if (cur->module == module)
1247         {
1248           break;
1249         }
1250
1251       cur = cur->next;
1252   }
1253   LT_DLMUTEX_UNLOCK ();
1254
1255   if (cur || !module)
1256     {
1257       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1258       module = 0;
1259     }
1260
1261   return module;
1262 }
1263
1264 static int
1265 sys_wll_close (loader_data, module)
1266      lt_user_data loader_data;
1267      lt_module module;
1268 {
1269   int         errors   = 0;
1270
1271   if (FreeLibrary(module) == 0)
1272     {
1273       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1274       ++errors;
1275     }
1276
1277   return errors;
1278 }
1279
1280 static lt_ptr
1281 sys_wll_sym (loader_data, module, symbol)
1282      lt_user_data loader_data;
1283      lt_module module;
1284      const char *symbol;
1285 {
1286   lt_ptr      address  = GetProcAddress (module, symbol);
1287
1288   if (!address)
1289     {
1290       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1291     }
1292
1293   return address;
1294 }
1295
1296 static struct lt_user_dlloader sys_wll = {
1297   0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
1298 };
1299
1300 #endif /* __WINDOWS__ */
1301
1302
1303
1304 \f
1305 /* --- LOAD_ADD_ON() INTERFACE LOADER --- */
1306
1307
1308 #ifdef __BEOS__
1309
1310 /* dynamic linking for BeOS */
1311
1312 #include <kernel/image.h>
1313
1314 static lt_module
1315 sys_bedl_open (loader_data, filename)
1316      lt_user_data loader_data;
1317      const char *filename;
1318 {
1319   image_id image = 0;
1320
1321   if (filename)
1322     {
1323       image = load_add_on (filename);
1324     }
1325   else
1326     {
1327       image_info info;
1328       int32 cookie = 0;
1329       if (get_next_image_info (0, &cookie, &info) == B_OK)
1330         image = load_add_on (info.name);
1331     }
1332
1333   if (image <= 0)
1334     {
1335       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1336       image = 0;
1337     }
1338
1339   return (lt_module) image;
1340 }
1341
1342 static int
1343 sys_bedl_close (loader_data, module)
1344      lt_user_data loader_data;
1345      lt_module module;
1346 {
1347   int errors = 0;
1348
1349   if (unload_add_on ((image_id) module) != B_OK)
1350     {
1351       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1352       ++errors;
1353     }
1354
1355   return errors;
1356 }
1357
1358 static lt_ptr
1359 sys_bedl_sym (loader_data, module, symbol)
1360      lt_user_data loader_data;
1361      lt_module module;
1362      const char *symbol;
1363 {
1364   lt_ptr address = 0;
1365   image_id image = (image_id) module;
1366
1367   if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
1368     {
1369       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1370       address = 0;
1371     }
1372
1373   return address;
1374 }
1375
1376 static struct lt_user_dlloader sys_bedl = {
1377   0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
1378 };
1379
1380 #endif /* __BEOS__ */
1381
1382
1383
1384 \f
1385 /* --- DLD_LINK() INTERFACE LOADER --- */
1386
1387
1388 #if HAVE_DLD
1389
1390 /* dynamic linking with dld */
1391
1392 #if HAVE_DLD_H
1393 #include <dld.h>
1394 #endif
1395
1396 static lt_module
1397 sys_dld_open (loader_data, filename)
1398      lt_user_data loader_data;
1399      const char *filename;
1400 {
1401   lt_module module = strdup (filename);
1402
1403   if (dld_link (filename) != 0)
1404     {
1405       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1406       LT_DLFREE (module);
1407       module = 0;
1408     }
1409
1410   return module;
1411 }
1412
1413 static int
1414 sys_dld_close (loader_data, module)
1415      lt_user_data loader_data;
1416      lt_module module;
1417 {
1418   int errors = 0;
1419
1420   if (dld_unlink_by_file ((char*)(module), 1) != 0)
1421     {
1422       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1423       ++errors;
1424     }
1425   else
1426     {
1427       LT_DLFREE (module);
1428     }
1429
1430   return errors;
1431 }
1432
1433 static lt_ptr
1434 sys_dld_sym (loader_data, module, symbol)
1435      lt_user_data loader_data;
1436      lt_module module;
1437      const char *symbol;
1438 {
1439   lt_ptr address = dld_get_func (symbol);
1440
1441   if (!address)
1442     {
1443       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1444     }
1445
1446   return address;
1447 }
1448
1449 static struct lt_user_dlloader sys_dld = {
1450   0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
1451 };
1452
1453 #endif /* HAVE_DLD */
1454
1455
1456
1457 \f
1458 /* --- DLPREOPEN() INTERFACE LOADER --- */
1459
1460
1461 /* emulate dynamic linking using preloaded_symbols */
1462
1463 typedef struct lt_dlsymlists_t
1464 {
1465   struct lt_dlsymlists_t       *next;
1466   const lt_dlsymlist           *syms;
1467 } lt_dlsymlists_t;
1468
1469 static  const lt_dlsymlist     *default_preloaded_symbols       = 0;
1470 static  lt_dlsymlists_t        *preloaded_symbols               = 0;
1471
1472 static int
1473 presym_init (loader_data)
1474      lt_user_data loader_data;
1475 {
1476   int errors = 0;
1477
1478   LT_DLMUTEX_LOCK ();
1479
1480   preloaded_symbols = 0;
1481   if (default_preloaded_symbols)
1482     {
1483       errors = lt_dlpreload (default_preloaded_symbols);
1484     }
1485
1486   LT_DLMUTEX_UNLOCK ();
1487
1488   return errors;
1489 }
1490
1491 static int
1492 presym_free_symlists ()
1493 {
1494   lt_dlsymlists_t *lists;
1495
1496   LT_DLMUTEX_LOCK ();
1497
1498   lists = preloaded_symbols;
1499   while (lists)
1500     {
1501       lt_dlsymlists_t   *tmp = lists;
1502
1503       lists = lists->next;
1504       LT_DLFREE (tmp);
1505     }
1506   preloaded_symbols = 0;
1507
1508   LT_DLMUTEX_UNLOCK ();
1509
1510   return 0;
1511 }
1512
1513 static int
1514 presym_exit (loader_data)
1515      lt_user_data loader_data;
1516 {
1517   presym_free_symlists ();
1518   return 0;
1519 }
1520
1521 static int
1522 presym_add_symlist (preloaded)
1523      const lt_dlsymlist *preloaded;
1524 {
1525   lt_dlsymlists_t *tmp;
1526   lt_dlsymlists_t *lists;
1527   int              errors   = 0;
1528
1529   LT_DLMUTEX_LOCK ();
1530
1531   lists = preloaded_symbols;
1532   while (lists)
1533     {
1534       if (lists->syms == preloaded)
1535         {
1536           goto done;
1537         }
1538       lists = lists->next;
1539     }
1540
1541   tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
1542   if (tmp)
1543     {
1544       memset (tmp, 0, sizeof(lt_dlsymlists_t));
1545       tmp->syms = preloaded;
1546       tmp->next = preloaded_symbols;
1547       preloaded_symbols = tmp;
1548     }
1549   else
1550     {
1551       ++errors;
1552     }
1553
1554  done:
1555   LT_DLMUTEX_UNLOCK ();
1556   return errors;
1557 }
1558
1559 static lt_module
1560 presym_open (loader_data, filename)
1561      lt_user_data loader_data;
1562      const char *filename;
1563 {
1564   lt_dlsymlists_t *lists;
1565   lt_module        module = (lt_module) 0;
1566
1567   LT_DLMUTEX_LOCK ();
1568   lists = preloaded_symbols;
1569
1570   if (!lists)
1571     {
1572       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
1573       goto done;
1574     }
1575
1576   /* Can't use NULL as the reflective symbol header, as NULL is
1577      used to mark the end of the entire symbol list.  Self-dlpreopened
1578      symbols follow this magic number, chosen to be an unlikely
1579      clash with a real module name.  */
1580   if (!filename)
1581     {
1582       filename = "@PROGRAM@";
1583     }
1584
1585   while (lists)
1586     {
1587       const lt_dlsymlist *syms = lists->syms;
1588
1589       while (syms->name)
1590         {
1591           if (!syms->address && strcmp(syms->name, filename) == 0)
1592             {
1593               module = (lt_module) syms;
1594               goto done;
1595             }
1596           ++syms;
1597         }
1598
1599       lists = lists->next;
1600     }
1601
1602   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
1603
1604  done:
1605   LT_DLMUTEX_UNLOCK ();
1606   return module;
1607 }
1608
1609 static int
1610 presym_close (loader_data, module)
1611      lt_user_data loader_data;
1612      lt_module module;
1613 {
1614   /* Just to silence gcc -Wall */
1615   module = 0;
1616   return 0;
1617 }
1618
1619 static lt_ptr
1620 presym_sym (loader_data, module, symbol)
1621      lt_user_data loader_data;
1622      lt_module module;
1623      const char *symbol;
1624 {
1625   lt_dlsymlist *syms = (lt_dlsymlist*) module;
1626
1627   ++syms;
1628   while (syms->address)
1629     {
1630       if (strcmp(syms->name, symbol) == 0)
1631         {
1632           return syms->address;
1633         }
1634
1635     ++syms;
1636   }
1637
1638   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1639
1640   return 0;
1641 }
1642
1643 static struct lt_user_dlloader presym = {
1644   0, presym_open, presym_close, presym_sym, presym_exit, 0
1645 };
1646
1647
1648
1649
1650 \f
1651 /* --- DYNAMIC MODULE LOADING --- */
1652
1653
1654 /* The type of a function used at each iteration of  foreach_dirinpath().  */
1655 typedef int     foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
1656                                                  lt_ptr data2));
1657
1658 static  int     foreach_dirinpath     LT_PARAMS((const char *search_path,
1659                                                  const char *base_name,
1660                                                  foreach_callback_func *func,
1661                                                  lt_ptr data1, lt_ptr data2));
1662
1663 static  int     find_file_callback    LT_PARAMS((char *filename, lt_ptr data,
1664                                                  lt_ptr ignored));
1665 static  int     find_handle_callback  LT_PARAMS((char *filename, lt_ptr data,
1666                                                  lt_ptr ignored));
1667 static  int     foreachfile_callback  LT_PARAMS((char *filename, lt_ptr data1,
1668                                                  lt_ptr data2));
1669
1670
1671 static  int     canonicalize_path     LT_PARAMS((const char *path,
1672                                                  char **pcanonical));
1673 static  int     argzize_path          LT_PARAMS((const char *path,
1674                                                  char **pargz,
1675                                                  size_t *pargz_len));
1676 static  FILE   *find_file             LT_PARAMS((const char *search_path,
1677                                                  const char *base_name,
1678                                                  char **pdir));
1679 static  lt_dlhandle *find_handle      LT_PARAMS((const char *search_path,
1680                                                  const char *base_name,
1681                                                  lt_dlhandle *handle));
1682 static  int     find_module           LT_PARAMS((lt_dlhandle *handle,
1683                                                  const char *dir,
1684                                                  const char *libdir,
1685                                                  const char *dlname,
1686                                                  const char *old_name,
1687                                                  int installed));
1688 static  int     free_vars             LT_PARAMS((char *dlname, char *oldname,
1689                                                  char *libdir, char *deplibs));
1690 static  int     load_deplibs          LT_PARAMS((lt_dlhandle handle,
1691                                                  char *deplibs));
1692 static  int     trim                  LT_PARAMS((char **dest,
1693                                                  const char *str));
1694 static  int     try_dlopen            LT_PARAMS((lt_dlhandle *handle,
1695                                                  const char *filename));
1696 static  int     tryall_dlopen         LT_PARAMS((lt_dlhandle *handle,
1697                                                  const char *filename));
1698 static  int     unload_deplibs        LT_PARAMS((lt_dlhandle handle));
1699 static  int     lt_argz_insert        LT_PARAMS((char **pargz,
1700                                                  size_t *pargz_len,
1701                                                  char *before,
1702                                                  const char *entry));
1703 static  int     lt_argz_insertinorder LT_PARAMS((char **pargz,
1704                                                  size_t *pargz_len,
1705                                                  const char *entry));
1706 static  int     lt_argz_insertdir     LT_PARAMS((char **pargz,
1707                                                  size_t *pargz_len,
1708                                                  const char *dirnam,
1709                                                  struct dirent *dp));
1710 static  int     lt_dlpath_insertdir   LT_PARAMS((char **ppath,
1711                                                  char *before,
1712                                                  const char *dir));
1713 static  int     list_files_by_dir     LT_PARAMS((const char *dirnam,
1714                                                  char **pargz,
1715                                                  size_t *pargz_len));
1716 static  int     file_not_found        LT_PARAMS((void));
1717
1718 static  char           *user_search_path= 0;
1719 static  lt_dlloader    *loaders         = 0;
1720 static  lt_dlhandle     handles         = 0;
1721 static  int             initialized     = 0;
1722
1723 /* Initialize libltdl. */
1724 int
1725 lt_dlinit ()
1726 {
1727   int         errors   = 0;
1728
1729   LT_DLMUTEX_LOCK ();
1730
1731   /* Initialize only at first call. */
1732   if (++initialized == 1)
1733     {
1734       handles = 0;
1735       user_search_path = 0; /* empty search path */
1736
1737 #if HAVE_LIBDL && !defined(__CYGWIN__)
1738       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
1739 #endif
1740 #if HAVE_SHL_LOAD
1741       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
1742 #endif
1743 #ifdef __WINDOWS__
1744       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
1745 #endif
1746 #ifdef __BEOS__
1747       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
1748 #endif
1749 #if HAVE_DLD
1750       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
1751 #endif
1752       errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
1753
1754       if (presym_init (presym.dlloader_data))
1755         {
1756           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
1757           ++errors;
1758         }
1759       else if (errors != 0)
1760         {
1761           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
1762           ++errors;
1763         }
1764     }
1765
1766   LT_DLMUTEX_UNLOCK ();
1767
1768   return errors;
1769 }
1770
1771 int
1772 lt_dlpreload (preloaded)
1773      const lt_dlsymlist *preloaded;
1774 {
1775   int errors = 0;
1776
1777   if (preloaded)
1778     {
1779       errors = presym_add_symlist (preloaded);
1780     }
1781   else
1782     {
1783       presym_free_symlists();
1784
1785       LT_DLMUTEX_LOCK ();
1786       if (default_preloaded_symbols)
1787         {
1788           errors = lt_dlpreload (default_preloaded_symbols);
1789         }
1790       LT_DLMUTEX_UNLOCK ();
1791     }
1792
1793   return errors;
1794 }
1795
1796 int
1797 lt_dlpreload_default (preloaded)
1798      const lt_dlsymlist *preloaded;
1799 {
1800   LT_DLMUTEX_LOCK ();
1801   default_preloaded_symbols = preloaded;
1802   LT_DLMUTEX_UNLOCK ();
1803   return 0;
1804 }
1805
1806 int
1807 lt_dlexit ()
1808 {
1809   /* shut down libltdl */
1810   lt_dlloader *loader;
1811   int          errors   = 0;
1812
1813   LT_DLMUTEX_LOCK ();
1814   loader = loaders;
1815
1816   if (!initialized)
1817     {
1818       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
1819       ++errors;
1820       goto done;
1821     }
1822
1823   /* shut down only at last call. */
1824   if (--initialized == 0)
1825     {
1826       int       level;
1827
1828       while (handles && LT_DLIS_RESIDENT (handles))
1829         {
1830           handles = handles->next;
1831         }
1832
1833       /* close all modules */
1834       for (level = 1; handles; ++level)
1835         {
1836           lt_dlhandle cur = handles;
1837           int saw_nonresident = 0;
1838
1839           while (cur)
1840             {
1841               lt_dlhandle tmp = cur;
1842               cur = cur->next;
1843               if (!LT_DLIS_RESIDENT (tmp))
1844                 saw_nonresident = 1;
1845               if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
1846                 {
1847                   if (lt_dlclose (tmp))
1848                     {
1849                       ++errors;
1850                     }
1851                 }
1852             }
1853           /* done if only resident modules are left */
1854           if (!saw_nonresident)
1855             break;
1856         }
1857
1858       /* close all loaders */
1859       while (loader)
1860         {
1861           lt_dlloader *next = loader->next;
1862           lt_user_data data = loader->dlloader_data;
1863           if (loader->dlloader_exit && loader->dlloader_exit (data))
1864             {
1865               ++errors;
1866             }
1867
1868           LT_DLMEM_REASSIGN (loader, next);
1869         }
1870       loaders = 0;
1871     }
1872
1873  done:
1874   LT_DLMUTEX_UNLOCK ();
1875   return errors;
1876 }
1877
1878 static int
1879 tryall_dlopen (handle, filename)
1880      lt_dlhandle *handle;
1881      const char *filename;
1882 {
1883   lt_dlhandle    cur;
1884   lt_dlloader   *loader;
1885   const char    *saved_error;
1886   int            errors         = 0;
1887
1888   LT_DLMUTEX_GETERROR (saved_error);
1889   LT_DLMUTEX_LOCK ();
1890
1891   cur    = handles;
1892   loader = loaders;
1893
1894   /* check whether the module was already opened */
1895   while (cur)
1896     {
1897       /* try to dlopen the program itself? */
1898       if (!cur->info.filename && !filename)
1899         {
1900           break;
1901         }
1902
1903       if (cur->info.filename && filename
1904           && strcmp (cur->info.filename, filename) == 0)
1905         {
1906           break;
1907         }
1908
1909       cur = cur->next;
1910     }
1911
1912   if (cur)
1913     {
1914       ++cur->info.ref_count;
1915       *handle = cur;
1916       goto done;
1917     }
1918
1919   cur = *handle;
1920   if (filename)
1921     {
1922       cur->info.filename = lt_estrdup (filename);
1923       if (!cur->info.filename)
1924         {
1925           ++errors;
1926           goto done;
1927         }
1928     }
1929   else
1930     {
1931       cur->info.filename = 0;
1932     }
1933
1934   while (loader)
1935     {
1936       lt_user_data data = loader->dlloader_data;
1937
1938       cur->module = loader->module_open (data, filename);
1939
1940       if (cur->module != 0)
1941         {
1942           break;
1943         }
1944       loader = loader->next;
1945     }
1946
1947   if (!loader)
1948     {
1949       LT_DLFREE (cur->info.filename);
1950       ++errors;
1951       goto done;
1952     }
1953
1954   cur->loader   = loader;
1955   LT_DLMUTEX_SETERROR (saved_error);
1956
1957  done:
1958   LT_DLMUTEX_UNLOCK ();
1959
1960   return errors;
1961 }
1962
1963 static int
1964 tryall_dlopen_module (handle, prefix, dirname, dlname)
1965      lt_dlhandle *handle;
1966      const char *prefix;
1967      const char *dirname;
1968      const char *dlname;
1969 {
1970   int      error        = 0;
1971   char     *filename    = 0;
1972   size_t   filename_len = 0;
1973   size_t   dirname_len  = LT_STRLEN (dirname);
1974
1975   assert (handle);
1976   assert (dirname);
1977   assert (dlname);
1978 #ifdef LT_DIRSEP_CHAR
1979   /* Only canonicalized names (i.e. with DIRSEP chars already converted)
1980      should make it into this function:  */
1981   assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
1982 #endif
1983
1984   if (dirname[dirname_len -1] == '/')
1985     --dirname_len;
1986   filename_len = dirname_len + 1 + LT_STRLEN (dlname);
1987
1988   /* Allocate memory, and combine DIRNAME and MODULENAME into it.
1989      The PREFIX (if any) is handled below.  */
1990   filename  = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
1991   if (!filename)
1992     return 1;
1993
1994   sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
1995
1996   /* Now that we have combined DIRNAME and MODULENAME, if there is
1997      also a PREFIX to contend with, simply recurse with the arguments
1998      shuffled.  Otherwise, attempt to open FILENAME as a module.  */
1999   if (prefix)
2000     {
2001       error += tryall_dlopen_module (handle,
2002                                      (const char *) 0, prefix, filename);
2003     }
2004   else if (tryall_dlopen (handle, filename) != 0)
2005     {
2006       ++error;
2007     }
2008
2009   LT_DLFREE (filename);
2010   return error;
2011 }
2012
2013 static int
2014 find_module (handle, dir, libdir, dlname, old_name, installed)
2015      lt_dlhandle *handle;
2016      const char *dir;
2017      const char *libdir;
2018      const char *dlname;
2019      const char *old_name;
2020      int installed;
2021 {
2022   /* Try to open the old library first; if it was dlpreopened,
2023      we want the preopened version of it, even if a dlopenable
2024      module is available.  */
2025   if (old_name && tryall_dlopen (handle, old_name) == 0)
2026     {
2027       return 0;
2028     }
2029
2030   /* Try to open the dynamic library.  */
2031   if (dlname)
2032     {
2033       /* try to open the installed module */
2034       if (installed && libdir)
2035         {
2036           if (tryall_dlopen_module (handle,
2037                                     (const char *) 0, libdir, dlname) == 0)
2038             return 0;
2039         }
2040
2041       /* try to open the not-installed module */
2042       if (!installed)
2043         {
2044           if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
2045             return 0;
2046         }
2047
2048       /* maybe it was moved to another directory */
2049       {
2050           if (tryall_dlopen_module (handle,
2051                                     (const char *) 0, dir, dlname) == 0)
2052             return 0;
2053       }
2054     }
2055
2056   return 1;
2057 }
2058
2059
2060 static int
2061 canonicalize_path (path, pcanonical)
2062      const char *path;
2063      char **pcanonical;
2064 {
2065   char *canonical = 0;
2066
2067   assert (path && *path);
2068   assert (pcanonical);
2069
2070   canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
2071   if (!canonical)
2072     return 1;
2073
2074   {
2075     size_t dest = 0;
2076     size_t src;
2077     for (src = 0; path[src] != LT_EOS_CHAR; ++src)
2078       {
2079         /* Path separators are not copied to the beginning or end of
2080            the destination, or if another separator would follow
2081            immediately.  */
2082         if (path[src] == LT_PATHSEP_CHAR)
2083           {
2084             if ((dest == 0)
2085                 || (path[1+ src] == LT_PATHSEP_CHAR)
2086                 || (path[1+ src] == LT_EOS_CHAR))
2087               continue;
2088           }
2089
2090         /* Anything other than a directory separator is copied verbatim.  */
2091         if ((path[src] != '/')
2092 #ifdef LT_DIRSEP_CHAR
2093             && (path[src] != LT_DIRSEP_CHAR)
2094 #endif
2095             )
2096           {
2097             canonical[dest++] = path[src];
2098           }
2099         /* Directory separators are converted and copied only if they are
2100            not at the end of a path -- i.e. before a path separator or
2101            NULL terminator.  */
2102         else if ((path[1+ src] != LT_PATHSEP_CHAR)
2103                  && (path[1+ src] != LT_EOS_CHAR)
2104 #ifdef LT_DIRSEP_CHAR
2105                  && (path[1+ src] != LT_DIRSEP_CHAR)
2106 #endif
2107                  && (path[1+ src] != '/'))
2108           {
2109             canonical[dest++] = '/';
2110           }
2111       }
2112
2113     /* Add an end-of-string marker at the end.  */
2114     canonical[dest] = LT_EOS_CHAR;
2115   }
2116
2117   /* Assign new value.  */
2118   *pcanonical = canonical;
2119
2120   return 0;
2121 }
2122
2123 static int
2124 argzize_path (path, pargz, pargz_len)
2125      const char *path;
2126      char **pargz;
2127      size_t *pargz_len;
2128 {
2129   error_t error;
2130
2131   assert (path);
2132   assert (pargz);
2133   assert (pargz_len);
2134
2135   if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
2136     {
2137       switch (error)
2138         {
2139         case ENOMEM:
2140           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
2141           break;
2142         default:
2143           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
2144           break;
2145         }
2146
2147       return 1;
2148     }
2149
2150   return 0;
2151 }
2152
2153 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
2154    of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
2155    non-zero or all elements are exhausted.  If BASE_NAME is non-NULL,
2156    it is appended to each SEARCH_PATH element before FUNC is called.  */
2157 static int
2158 foreach_dirinpath (search_path, base_name, func, data1, data2)
2159      const char *search_path;
2160      const char *base_name;
2161      foreach_callback_func *func;
2162      lt_ptr data1;
2163      lt_ptr data2;
2164 {
2165   int    result         = 0;
2166   int    filenamesize   = 0;
2167   size_t lenbase        = LT_STRLEN (base_name);
2168   size_t argz_len       = 0;
2169   char *argz            = 0;
2170   char *filename        = 0;
2171   char *canonical       = 0;
2172
2173   LT_DLMUTEX_LOCK ();
2174
2175   if (!search_path || !*search_path)
2176     {
2177       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2178       goto cleanup;
2179     }
2180
2181   if (canonicalize_path (search_path, &canonical) != 0)
2182     goto cleanup;
2183
2184   if (argzize_path (canonical, &argz, &argz_len) != 0)
2185     goto cleanup;
2186
2187   {
2188     char *dir_name = 0;
2189     while ((dir_name = argz_next (argz, argz_len, dir_name)))
2190       {
2191         size_t lendir = LT_STRLEN (dir_name);
2192
2193         if (lendir +1 +lenbase >= filenamesize)
2194         {
2195           LT_DLFREE (filename);
2196           filenamesize  = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
2197           filename      = LT_EMALLOC (char, filenamesize);
2198           if (!filename)
2199             goto cleanup;
2200         }
2201
2202         strncpy (filename, dir_name, lendir);
2203         if (base_name && *base_name)
2204           {
2205             if (filename[lendir -1] != '/')
2206               filename[lendir++] = '/';
2207             strcpy (filename +lendir, base_name);
2208           }
2209
2210         if ((result = (*func) (filename, data1, data2)))
2211           {
2212             break;
2213           }
2214       }
2215   }
2216
2217  cleanup:
2218   LT_DLFREE (argz);
2219   LT_DLFREE (canonical);
2220   LT_DLFREE (filename);
2221
2222   LT_DLMUTEX_UNLOCK ();
2223
2224   return result;
2225 }
2226
2227 /* If FILEPATH can be opened, store the name of the directory component
2228    in DATA1, and the opened FILE* structure address in DATA2.  Otherwise
2229    DATA1 is unchanged, but DATA2 is set to a pointer to NULL.  */
2230 static int
2231 find_file_callback (filename, data1, data2)
2232      char *filename;
2233      lt_ptr data1;
2234      lt_ptr data2;
2235 {
2236   char       **pdir     = (char **) data1;
2237   FILE       **pfile    = (FILE **) data2;
2238   int        is_done    = 0;
2239
2240   assert (filename && *filename);
2241   assert (pdir);
2242   assert (pfile);
2243
2244   if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
2245     {
2246       char *dirend = strrchr (filename, '/');
2247
2248       if (dirend > filename)
2249         *dirend   = LT_EOS_CHAR;
2250
2251       LT_DLFREE (*pdir);
2252       *pdir   = lt_estrdup (filename);
2253       is_done = (*pdir == 0) ? -1 : 1;
2254     }
2255
2256   return is_done;
2257 }
2258
2259 static FILE *
2260 find_file (search_path, base_name, pdir)
2261      const char *search_path;
2262      const char *base_name;
2263      char **pdir;
2264 {
2265   FILE *file = 0;
2266
2267   foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
2268
2269   return file;
2270 }
2271
2272 static int
2273 find_handle_callback (filename, data, ignored)
2274      char *filename;
2275      lt_ptr data;
2276      lt_ptr ignored;
2277 {
2278   lt_dlhandle  *handle  = (lt_dlhandle *) data;
2279   int           found   = access (filename, R_OK);
2280
2281   /* Bail out if file cannot be read...  */
2282   if (!found)
2283     return 0;
2284
2285   /* Try to dlopen the file, but do not continue searching in any
2286      case.  */
2287   if (tryall_dlopen (handle, filename) != 0)
2288     *handle = 0;
2289
2290   return 1;
2291 }
2292
2293 /* If HANDLE was found return it, otherwise return 0.  If HANDLE was
2294    found but could not be opened, *HANDLE will be set to 0.  */
2295 static lt_dlhandle *
2296 find_handle (search_path, base_name, handle)
2297      const char *search_path;
2298      const char *base_name;
2299      lt_dlhandle *handle;
2300 {
2301   if (!search_path)
2302     return 0;
2303
2304   if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
2305                           handle, 0))
2306     return 0;
2307
2308   return handle;
2309 }
2310
2311 static int
2312 load_deplibs (handle, deplibs)
2313      lt_dlhandle handle;
2314      char *deplibs;
2315 {
2316 #if LTDL_DLOPEN_DEPLIBS
2317   char  *p, *save_search_path = 0;
2318   int   depcount = 0;
2319   int   i;
2320   char  **names = 0;
2321 #endif
2322   int   errors = 0;
2323
2324   handle->depcount = 0;
2325
2326 #if LTDL_DLOPEN_DEPLIBS
2327   if (!deplibs)
2328     {
2329       return errors;
2330     }
2331   ++errors;
2332
2333   LT_DLMUTEX_LOCK ();
2334   if (user_search_path)
2335     {
2336       save_search_path = lt_estrdup (user_search_path);
2337       if (!save_search_path)
2338         goto cleanup;
2339     }
2340
2341   /* extract search paths and count deplibs */
2342   p = deplibs;
2343   while (*p)
2344     {
2345       if (!isspace ((int) *p))
2346         {
2347           char *end = p+1;
2348           while (*end && !isspace((int) *end))
2349             {
2350               ++end;
2351             }
2352
2353           if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
2354             {
2355               char save = *end;
2356               *end = 0; /* set a temporary string terminator */
2357               if (lt_dladdsearchdir(p+2))
2358                 {
2359                   goto cleanup;
2360                 }
2361               *end = save;
2362             }
2363           else
2364             {
2365               ++depcount;
2366             }
2367
2368           p = end;
2369         }
2370       else
2371         {
2372           ++p;
2373         }
2374     }
2375
2376   /* restore the old search path */
2377   LT_DLFREE (user_search_path);
2378   user_search_path = save_search_path;
2379
2380   LT_DLMUTEX_UNLOCK ();
2381
2382   if (!depcount)
2383     {
2384       errors = 0;
2385       goto cleanup;
2386     }
2387
2388   names = LT_EMALLOC (char *, depcount * sizeof (char*));
2389   if (!names)
2390     goto cleanup;
2391
2392   /* now only extract the actual deplibs */
2393   depcount = 0;
2394   p = deplibs;
2395   while (*p)
2396     {
2397       if (isspace ((int) *p))
2398         {
2399           ++p;
2400         }
2401       else
2402         {
2403           char *end = p+1;
2404           while (*end && !isspace ((int) *end))
2405             {
2406               ++end;
2407             }
2408
2409           if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
2410             {
2411               char *name;
2412               char save = *end;
2413               *end = 0; /* set a temporary string terminator */
2414               if (strncmp(p, "-l", 2) == 0)
2415                 {
2416                   size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
2417                   name = LT_EMALLOC (char, 1+ name_len);
2418                   if (name)
2419                     sprintf (name, "lib%s", p+2);
2420                 }
2421               else
2422                 name = lt_estrdup(p);
2423
2424               if (!name)
2425                 goto cleanup_names;
2426
2427               names[depcount++] = name;
2428               *end = save;
2429             }
2430           p = end;
2431         }
2432     }
2433
2434   /* load the deplibs (in reverse order)
2435      At this stage, don't worry if the deplibs do not load correctly,
2436      they may already be statically linked into the loading application
2437      for instance.  There will be a more enlightening error message
2438      later on if the loaded module cannot resolve all of its symbols.  */
2439   if (depcount)
2440     {
2441       int       j = 0;
2442
2443       handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
2444       if (!handle->deplibs)
2445         goto cleanup;
2446
2447       for (i = 0; i < depcount; ++i)
2448         {
2449           handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
2450           if (handle->deplibs[j])
2451             {
2452               ++j;
2453             }
2454         }
2455
2456       handle->depcount  = j;    /* Number of successfully loaded deplibs */
2457       errors            = 0;
2458     }
2459
2460  cleanup_names:
2461   for (i = 0; i < depcount; ++i)
2462     {
2463       LT_DLFREE (names[i]);
2464     }
2465
2466  cleanup:
2467   LT_DLFREE (names);
2468 #endif
2469
2470   return errors;
2471 }
2472
2473 static int
2474 unload_deplibs (handle)
2475      lt_dlhandle handle;
2476 {
2477   int i;
2478   int errors = 0;
2479
2480   if (handle->depcount)
2481     {
2482       for (i = 0; i < handle->depcount; ++i)
2483         {
2484           if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
2485             {
2486               errors += lt_dlclose (handle->deplibs[i]);
2487             }
2488         }
2489     }
2490
2491   return errors;
2492 }
2493
2494 static int
2495 trim (dest, str)
2496      char **dest;
2497      const char *str;
2498 {
2499   /* remove the leading and trailing "'" from str
2500      and store the result in dest */
2501   const char *end   = strrchr (str, '\'');
2502   size_t len        = LT_STRLEN (str);
2503   char *tmp;
2504
2505   LT_DLFREE (*dest);
2506
2507   if (len > 3 && str[0] == '\'')
2508     {
2509       tmp = LT_EMALLOC (char, end - str);
2510       if (!tmp)
2511         return 1;
2512
2513       strncpy(tmp, &str[1], (end - str) - 1);
2514       tmp[len-3] = LT_EOS_CHAR;
2515       *dest = tmp;
2516     }
2517   else
2518     {
2519       *dest = 0;
2520     }
2521
2522   return 0;
2523 }
2524
2525 static int
2526 free_vars (dlname, oldname, libdir, deplibs)
2527      char *dlname;
2528      char *oldname;
2529      char *libdir;
2530      char *deplibs;
2531 {
2532   LT_DLFREE (dlname);
2533   LT_DLFREE (oldname);
2534   LT_DLFREE (libdir);
2535   LT_DLFREE (deplibs);
2536
2537   return 0;
2538 }
2539
2540 static int
2541 try_dlopen (phandle, filename)
2542      lt_dlhandle *phandle;
2543      const char *filename;
2544 {
2545   const char *  ext             = 0;
2546   const char *  saved_error     = 0;
2547   char *        canonical       = 0;
2548   char *        base_name       = 0;
2549   char *        dir             = 0;
2550   char *        name            = 0;
2551   int           errors          = 0;
2552   lt_dlhandle   newhandle;
2553
2554   assert (phandle);
2555   assert (*phandle == 0);
2556
2557   LT_DLMUTEX_GETERROR (saved_error);
2558
2559   /* dlopen self? */
2560   if (!filename)
2561     {
2562       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
2563       if (*phandle == 0)
2564         return 1;
2565
2566       memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
2567       newhandle = *phandle;
2568
2569       /* lt_dlclose()ing yourself is very bad!  Disallow it.  */
2570       LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
2571
2572       if (tryall_dlopen (&newhandle, 0) != 0)
2573         {
2574           LT_DLFREE (*phandle);
2575           return 1;
2576         }
2577
2578       goto register_handle;
2579     }
2580
2581   assert (filename && *filename);
2582
2583   /* Doing this immediately allows internal functions to safely
2584      assume only canonicalized paths are passed.  */
2585   if (canonicalize_path (filename, &canonical) != 0)
2586     {
2587       ++errors;
2588       goto cleanup;
2589     }
2590
2591   /* If the canonical module name is a path (relative or absolute)
2592      then split it into a directory part and a name part.  */
2593   base_name = strrchr (canonical, '/');
2594   if (base_name)
2595     {
2596       size_t dirlen = (1+ base_name) - canonical;
2597
2598       dir = LT_EMALLOC (char, 1+ dirlen);
2599       if (!dir)
2600         {
2601           ++errors;
2602           goto cleanup;
2603         }
2604
2605       strncpy (dir, canonical, dirlen);
2606       dir[dirlen] = LT_EOS_CHAR;
2607
2608       ++base_name;
2609     }
2610   else
2611     LT_DLMEM_REASSIGN (base_name, canonical);
2612
2613   assert (base_name && *base_name);
2614
2615   /* Check whether we are opening a libtool module (.la extension).  */
2616   ext = strrchr (base_name, '.');
2617   if (ext && strcmp (ext, archive_ext) == 0)
2618     {
2619       /* this seems to be a libtool module */
2620       FILE *    file     = 0;
2621       char *    dlname   = 0;
2622       char *    old_name = 0;
2623       char *    libdir   = 0;
2624       char *    deplibs  = 0;
2625       char *    line     = 0;
2626       size_t    line_len;
2627
2628       /* if we can't find the installed flag, it is probably an
2629          installed libtool archive, produced with an old version
2630          of libtool */
2631       int       installed = 1;
2632
2633       /* extract the module name from the file name */
2634       name = LT_EMALLOC (char, ext - base_name + 1);
2635       if (!name)
2636         {
2637           ++errors;
2638           goto cleanup;
2639         }
2640
2641       /* canonicalize the module name */
2642       {
2643         size_t i;
2644         for (i = 0; i < ext - base_name; ++i)
2645           {
2646             if (isalnum ((int)(base_name[i])))
2647               {
2648                 name[i] = base_name[i];
2649               }
2650             else
2651               {
2652                 name[i] = '_';
2653               }
2654           }
2655         name[ext - base_name] = LT_EOS_CHAR;
2656       }
2657
2658       /* Now try to open the .la file.  If there is no directory name
2659          component, try to find it first in user_search_path and then other
2660          prescribed paths.  Otherwise (or in any case if the module was not
2661          yet found) try opening just the module name as passed.  */
2662       if (!dir)
2663         {
2664           const char *search_path;
2665
2666           LT_DLMUTEX_LOCK ();
2667           search_path = user_search_path;
2668           if (search_path)
2669             file = find_file (user_search_path, base_name, &dir);
2670           LT_DLMUTEX_UNLOCK ();
2671
2672           if (!file)
2673             {
2674               search_path = getenv (LTDL_SEARCHPATH_VAR);
2675               if (search_path)
2676                 file = find_file (search_path, base_name, &dir);
2677             }
2678
2679 #ifdef LTDL_SHLIBPATH_VAR
2680           if (!file)
2681             {
2682               search_path = getenv (LTDL_SHLIBPATH_VAR);
2683               if (search_path)
2684                 file = find_file (search_path, base_name, &dir);
2685             }
2686 #endif
2687 #ifdef LTDL_SYSSEARCHPATH
2688           if (!file && sys_search_path)
2689             {
2690               file = find_file (sys_search_path, base_name, &dir);
2691             }
2692 #endif
2693         }
2694       if (!file)
2695         {
2696           file = fopen (filename, LT_READTEXT_MODE);
2697         }
2698
2699       /* If we didn't find the file by now, it really isn't there.  Set
2700          the status flag, and bail out.  */
2701       if (!file)
2702         {
2703           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2704           ++errors;
2705           goto cleanup;
2706         }
2707
2708       line_len = LT_FILENAME_MAX;
2709       line = LT_EMALLOC (char, line_len);
2710       if (!line)
2711         {
2712           fclose (file);
2713           ++errors;
2714           goto cleanup;
2715         }
2716
2717       /* read the .la file */
2718       while (!feof (file))
2719         {
2720           if (!fgets (line, (int) line_len, file))
2721             {
2722               break;
2723             }
2724
2725           /* Handle the case where we occasionally need to read a line
2726              that is longer than the initial buffer size.  */
2727           while (line[LT_STRLEN(line) -1] != '\n')
2728             {
2729               line = LT_DLREALLOC (char, line, line_len *2);
2730               if (!fgets (&line[line_len -1], (int) line_len +1, file))
2731                 {
2732                   break;
2733                 }
2734               line_len *= 2;
2735             }
2736
2737           if (line[0] == '\n' || line[0] == '#')
2738             {
2739               continue;
2740             }
2741
2742 #undef  STR_DLNAME
2743 #define STR_DLNAME      "dlname="
2744           if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
2745             {
2746               errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
2747             }
2748
2749 #undef  STR_OLD_LIBRARY
2750 #define STR_OLD_LIBRARY "old_library="
2751           else if (strncmp (line, STR_OLD_LIBRARY,
2752                             sizeof (STR_OLD_LIBRARY) - 1) == 0)
2753             {
2754               errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
2755             }
2756 #undef  STR_LIBDIR
2757 #define STR_LIBDIR      "libdir="
2758           else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
2759             {
2760               errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
2761             }
2762
2763 #undef  STR_DL_DEPLIBS
2764 #define STR_DL_DEPLIBS  "dependency_libs="
2765           else if (strncmp (line, STR_DL_DEPLIBS,
2766                             sizeof (STR_DL_DEPLIBS) - 1) == 0)
2767             {
2768               errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
2769             }
2770           else if (strcmp (line, "installed=yes\n") == 0)
2771             {
2772               installed = 1;
2773             }
2774           else if (strcmp (line, "installed=no\n") == 0)
2775             {
2776               installed = 0;
2777             }
2778
2779 #undef  STR_LIBRARY_NAMES
2780 #define STR_LIBRARY_NAMES "library_names="
2781           else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
2782                                         sizeof (STR_LIBRARY_NAMES) - 1) == 0)
2783             {
2784               char *last_libname;
2785               errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
2786               if (!errors
2787                   && dlname
2788                   && (last_libname = strrchr (dlname, ' ')) != 0)
2789                 {
2790                   last_libname = lt_estrdup (last_libname + 1);
2791                   if (!last_libname)
2792                     {
2793                       ++errors;
2794                       goto cleanup;
2795                     }
2796                   LT_DLMEM_REASSIGN (dlname, last_libname);
2797                 }
2798             }
2799
2800           if (errors)
2801             break;
2802         }
2803
2804       fclose (file);
2805       LT_DLFREE (line);
2806
2807       /* allocate the handle */
2808       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
2809       if (*phandle == 0)
2810         ++errors;
2811
2812       if (errors)
2813         {
2814           free_vars (dlname, old_name, libdir, deplibs);
2815           LT_DLFREE (*phandle);
2816           goto cleanup;
2817         }
2818
2819       assert (*phandle);
2820
2821       memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
2822       if (load_deplibs (*phandle, deplibs) == 0)
2823         {
2824           newhandle = *phandle;
2825           /* find_module may replace newhandle */
2826           if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
2827             {
2828               unload_deplibs (*phandle);
2829               ++errors;
2830             }
2831         }
2832       else
2833         {
2834           ++errors;
2835         }
2836
2837       free_vars (dlname, old_name, libdir, deplibs);
2838       if (errors)
2839         {
2840           LT_DLFREE (*phandle);
2841           goto cleanup;
2842         }
2843
2844       if (*phandle != newhandle)
2845         {
2846           unload_deplibs (*phandle);
2847         }
2848     }
2849   else
2850     {
2851       /* not a libtool module */
2852       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
2853       if (*phandle == 0)
2854         {
2855           ++errors;
2856           goto cleanup;
2857         }
2858
2859       memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
2860       newhandle = *phandle;
2861
2862       /* If the module has no directory name component, try to find it
2863          first in user_search_path and then other prescribed paths.
2864          Otherwise (or in any case if the module was not yet found) try
2865          opening just the module name as passed.  */
2866       if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
2867                    && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
2868                                     &newhandle)
2869 #ifdef LTDL_SHLIBPATH_VAR
2870                    && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
2871                                     &newhandle)
2872 #endif
2873 #ifdef LTDL_SYSSEARCHPATH
2874                    && !find_handle (sys_search_path, base_name, &newhandle)
2875 #endif
2876                    )))
2877         {
2878           tryall_dlopen (&newhandle, filename);
2879         }
2880
2881       if (!newhandle)
2882         {
2883           LT_DLFREE (*phandle);
2884           ++errors;
2885           goto cleanup;
2886         }
2887     }
2888
2889  register_handle:
2890   LT_DLMEM_REASSIGN (*phandle, newhandle);
2891
2892   if ((*phandle)->info.ref_count == 0)
2893     {
2894       (*phandle)->info.ref_count        = 1;
2895       LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
2896
2897       LT_DLMUTEX_LOCK ();
2898       (*phandle)->next          = handles;
2899       handles                   = *phandle;
2900       LT_DLMUTEX_UNLOCK ();
2901     }
2902
2903   LT_DLMUTEX_SETERROR (saved_error);
2904
2905  cleanup:
2906   LT_DLFREE (dir);
2907   LT_DLFREE (name);
2908   LT_DLFREE (canonical);
2909
2910   return errors;
2911 }
2912
2913 lt_dlhandle
2914 lt_dlopen (filename)
2915      const char *filename;
2916 {
2917   lt_dlhandle handle = 0;
2918
2919   /* Just incase we missed a code path in try_dlopen() that reports
2920      an error, but forgets to reset handle... */
2921   if (try_dlopen (&handle, filename) != 0)
2922     return 0;
2923
2924   return handle;
2925 }
2926
2927 /* If the last error messge store was `FILE_NOT_FOUND', then return
2928    non-zero.  */
2929 static int
2930 file_not_found ()
2931 {
2932   const char *error = 0;
2933
2934   LT_DLMUTEX_GETERROR (error);
2935   if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
2936     return 1;
2937
2938   return 0;
2939 }
2940
2941 /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
2942    open the FILENAME as passed.  Otherwise try appending ARCHIVE_EXT,
2943    and if a file is still not found try again with SHLIB_EXT appended
2944    instead.  */
2945 lt_dlhandle
2946 lt_dlopenext (filename)
2947      const char *filename;
2948 {
2949   lt_dlhandle   handle          = 0;
2950   char *        tmp             = 0;
2951   char *        ext             = 0;
2952   size_t        len;
2953   int           errors          = 0;
2954
2955   if (!filename)
2956     {
2957       return lt_dlopen (filename);
2958     }
2959
2960   assert (filename);
2961
2962   len = LT_STRLEN (filename);
2963   ext = strrchr (filename, '.');
2964
2965   /* If FILENAME already bears a suitable extension, there is no need
2966      to try appending additional extensions.  */
2967   if (ext && ((strcmp (ext, archive_ext) == 0)
2968 #ifdef LTDL_SHLIB_EXT
2969               || (strcmp (ext, shlib_ext) == 0)
2970 #endif
2971       ))
2972     {
2973       return lt_dlopen (filename);
2974     }
2975
2976   /* First try appending ARCHIVE_EXT.  */
2977   tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
2978   if (!tmp)
2979     return 0;
2980
2981   strcpy (tmp, filename);
2982   strcat (tmp, archive_ext);
2983   errors = try_dlopen (&handle, tmp);
2984
2985   /* If we found FILENAME, stop searching -- whether we were able to
2986      load the file as a module or not.  If the file exists but loading
2987      failed, it is better to return an error message here than to
2988      report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
2989      in the module search path.  */
2990   if (handle || ((errors > 0) && file_not_found ()))
2991     {
2992       LT_DLFREE (tmp);
2993       return handle;
2994     }
2995
2996 #ifdef LTDL_SHLIB_EXT
2997   /* Try appending SHLIB_EXT.   */
2998   if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
2999     {
3000       LT_DLFREE (tmp);
3001       tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
3002       if (!tmp)
3003         return 0;
3004
3005       strcpy (tmp, filename);
3006     }
3007   else
3008     {
3009       tmp[len] = LT_EOS_CHAR;
3010     }
3011
3012   strcat(tmp, shlib_ext);
3013   errors = try_dlopen (&handle, tmp);
3014
3015   /* As before, if the file was found but loading failed, return now
3016      with the current error message.  */
3017   if (handle || ((errors > 0) && file_not_found ()))
3018     {
3019       LT_DLFREE (tmp);
3020       return handle;
3021     }
3022 #endif
3023
3024   /* Still here?  Then we really did fail to locate any of the file
3025      names we tried.  */
3026   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3027   LT_DLFREE (tmp);
3028   return 0;
3029 }
3030
3031
3032 static int
3033 lt_argz_insert (pargz, pargz_len, before, entry)
3034      char **pargz;
3035      size_t *pargz_len;
3036      char *before;
3037      const char *entry;
3038 {
3039   error_t error;
3040
3041   if ((error = argz_insert (pargz, pargz_len, before, entry)))
3042     {
3043       switch (error)
3044         {
3045         case ENOMEM:
3046           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
3047           break;
3048         default:
3049           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
3050           break;
3051         }
3052       return 1;
3053     }
3054
3055   return 0;
3056 }
3057
3058 static int
3059 lt_argz_insertinorder (pargz, pargz_len, entry)
3060      char **pargz;
3061      size_t *pargz_len;
3062      const char *entry;
3063 {
3064   char *before = 0;
3065
3066   assert (pargz);
3067   assert (pargz_len);
3068   assert (entry && *entry);
3069
3070   if (*pargz)
3071     while ((before = argz_next (*pargz, *pargz_len, before)))
3072       {
3073         int cmp = strcmp (entry, before);
3074
3075         if (cmp < 0)  break;
3076         if (cmp == 0) return 0; /* No duplicates! */
3077       }
3078
3079   return lt_argz_insert (pargz, pargz_len, before, entry);
3080 }
3081
3082 static int
3083 lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
3084      char **pargz;
3085      size_t *pargz_len;
3086      const char *dirnam;
3087      struct dirent *dp;
3088 {
3089   char   *buf       = 0;
3090   size_t buf_len    = 0;
3091   char   *end       = 0;
3092   size_t end_offset = 0;
3093   size_t dir_len    = 0;
3094   int    errors     = 0;
3095
3096   assert (pargz);
3097   assert (pargz_len);
3098   assert (dp);
3099
3100   dir_len = LT_STRLEN (dirnam);
3101   end     = dp->d_name + LT_D_NAMLEN(dp);
3102
3103   /* Ignore version numbers.  */
3104   {
3105     char *p;
3106     for (p = end; p -1 > dp->d_name; --p)
3107       if (strchr (".0123456789", p[-1]) == 0)
3108         break;
3109
3110     if (*p == '.')
3111       end = p;
3112   }
3113
3114   /* Ignore filename extension.  */
3115   {
3116     char *p;
3117     for (p = end -1; p > dp->d_name; --p)
3118       if (*p == '.')
3119         {
3120           end = p;
3121           break;
3122         }
3123   }
3124
3125   /* Prepend the directory name.  */
3126   end_offset    = end - dp->d_name;
3127   buf_len       = dir_len + 1+ end_offset;
3128   buf           = LT_EMALLOC (char, 1+ buf_len);
3129   if (!buf)
3130     return ++errors;
3131
3132   assert (buf);
3133
3134   strcpy  (buf, dirnam);
3135   strcat  (buf, "/");
3136   strncat (buf, dp->d_name, end_offset);
3137   buf[buf_len] = LT_EOS_CHAR;
3138
3139   /* Try to insert (in order) into ARGZ/ARGZ_LEN.  */
3140   if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
3141     ++errors;
3142
3143   LT_DLFREE (buf);
3144
3145   return errors;
3146 }
3147
3148 static int
3149 list_files_by_dir (dirnam, pargz, pargz_len)
3150      const char *dirnam;
3151      char **pargz;
3152      size_t *pargz_len;
3153 {
3154   DIR   *dirp     = 0;
3155   int    errors   = 0;
3156
3157   assert (dirnam && *dirnam);
3158   assert (pargz);
3159   assert (pargz_len);
3160   assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
3161
3162   dirp = opendir (dirnam);
3163   if (dirp)
3164     {
3165       struct dirent *dp = 0;
3166
3167       while ((dp = readdir (dirp)))
3168         if (dp->d_name[0] != '.')
3169           if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
3170             {
3171               ++errors;
3172               break;
3173             }
3174
3175       closedir (dirp);
3176     }
3177   else
3178     ++errors;
3179
3180   return errors;
3181 }
3182
3183
3184 /* If there are any files in DIRNAME, call the function passed in
3185    DATA1 (with the name of each file and DATA2 as arguments).  */
3186 static int
3187 foreachfile_callback (dirname, data1, data2)
3188      char *dirname;
3189      lt_ptr data1;
3190      lt_ptr data2;
3191 {
3192   int (*func) LT_PARAMS((const char *filename, lt_ptr data))
3193         = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;
3194
3195   int     is_done  = 0;
3196   char   *argz     = 0;
3197   size_t  argz_len = 0;
3198
3199   if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
3200     goto cleanup;
3201   if (!argz)
3202     goto cleanup;
3203
3204   {
3205     char *filename = 0;
3206     while ((filename = argz_next (argz, argz_len, filename)))
3207       if ((is_done = (*func) (filename, data2)))
3208         break;
3209   }
3210
3211  cleanup:
3212   LT_DLFREE (argz);
3213
3214   return is_done;
3215 }
3216
3217
3218 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
3219    with DATA.  The filenames passed to FUNC would be suitable for
3220    passing to lt_dlopenext.  The extensions are stripped so that
3221    individual modules do not generate several entries (e.g. libfoo.la,
3222    libfoo.so, libfoo.so.1, libfoo.so.1.0.0).  If SEARCH_PATH is NULL,
3223    then the same directories that lt_dlopen would search are examined.  */
3224 int
3225 lt_dlforeachfile (search_path, func, data)
3226      const char *search_path;
3227      int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
3228      lt_ptr data;
3229 {
3230   int is_done = 0;
3231
3232   if (search_path)
3233     {
3234       /* If a specific path was passed, search only the directories
3235          listed in it.  */
3236       is_done = foreach_dirinpath (search_path, 0,
3237                                    foreachfile_callback, func, data);
3238     }
3239   else
3240     {
3241       /* Otherwise search the default paths.  */
3242       is_done = foreach_dirinpath (user_search_path, 0,
3243                                    foreachfile_callback, func, data);
3244       if (!is_done)
3245         {
3246           is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
3247                                        foreachfile_callback, func, data);
3248         }
3249
3250 #ifdef LTDL_SHLIBPATH_VAR
3251       if (!is_done)
3252         {
3253           is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
3254                                        foreachfile_callback, func, data);
3255         }
3256 #endif
3257 #ifdef LTDL_SYSSEARCHPATH
3258       if (!is_done)
3259         {
3260           is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
3261                                        foreachfile_callback, func, data);
3262         }
3263 #endif
3264     }
3265
3266   return is_done;
3267 }
3268
3269 int
3270 lt_dlclose (handle)
3271      lt_dlhandle handle;
3272 {
3273   lt_dlhandle cur, last;
3274   int errors = 0;
3275
3276   LT_DLMUTEX_LOCK ();
3277
3278   /* check whether the handle is valid */
3279   last = cur = handles;
3280   while (cur && handle != cur)
3281     {
3282       last = cur;
3283       cur = cur->next;
3284     }
3285
3286   if (!cur)
3287     {
3288       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3289       ++errors;
3290       goto done;
3291     }
3292
3293   handle->info.ref_count--;
3294
3295   /* Note that even with resident modules, we must track the ref_count
3296      correctly incase the user decides to reset the residency flag
3297      later (even though the API makes no provision for that at the
3298      moment).  */
3299   if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
3300     {
3301       lt_user_data data = handle->loader->dlloader_data;
3302
3303       if (handle != handles)
3304         {
3305           last->next = handle->next;
3306         }
3307       else
3308         {
3309           handles = handle->next;
3310         }
3311
3312       errors += handle->loader->module_close (data, handle->module);
3313       errors += unload_deplibs(handle);
3314
3315       /* It is up to the callers to free the data itself.  */
3316       LT_DLFREE (handle->caller_data);
3317
3318       LT_DLFREE (handle->info.filename);
3319       LT_DLFREE (handle->info.name);
3320       LT_DLFREE (handle);
3321
3322       goto done;
3323     }
3324
3325   if (LT_DLIS_RESIDENT (handle))
3326     {
3327       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
3328       ++errors;
3329     }
3330
3331  done:
3332   LT_DLMUTEX_UNLOCK ();
3333
3334   return errors;
3335 }
3336
3337 lt_ptr
3338 lt_dlsym (handle, symbol)
3339      lt_dlhandle handle;
3340      const char *symbol;
3341 {
3342   size_t lensym;
3343   char  lsym[LT_SYMBOL_LENGTH];
3344   char  *sym;
3345   lt_ptr address;
3346   lt_user_data data;
3347
3348   if (!handle)
3349     {
3350       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3351       return 0;
3352     }
3353
3354   if (!symbol)
3355     {
3356       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
3357       return 0;
3358     }
3359
3360   lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
3361                                         + LT_STRLEN (handle->info.name);
3362
3363   if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
3364     {
3365       sym = lsym;
3366     }
3367   else
3368     {
3369       sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
3370       if (!sym)
3371         {
3372           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
3373           return 0;
3374         }
3375     }
3376
3377   data = handle->loader->dlloader_data;
3378   if (handle->info.name)
3379     {
3380       const char *saved_error;
3381
3382       LT_DLMUTEX_GETERROR (saved_error);
3383
3384       /* this is a libtool module */
3385       if (handle->loader->sym_prefix)
3386         {
3387           strcpy(sym, handle->loader->sym_prefix);
3388           strcat(sym, handle->info.name);
3389         }
3390       else
3391         {
3392           strcpy(sym, handle->info.name);
3393         }
3394
3395       strcat(sym, "_LTX_");
3396       strcat(sym, symbol);
3397
3398       /* try "modulename_LTX_symbol" */
3399       address = handle->loader->find_sym (data, handle->module, sym);
3400       if (address)
3401         {
3402           if (sym != lsym)
3403             {
3404               LT_DLFREE (sym);
3405             }
3406           return address;
3407         }
3408       LT_DLMUTEX_SETERROR (saved_error);
3409     }
3410
3411   /* otherwise try "symbol" */
3412   if (handle->loader->sym_prefix)
3413     {
3414       strcpy(sym, handle->loader->sym_prefix);
3415       strcat(sym, symbol);
3416     }
3417   else
3418     {
3419       strcpy(sym, symbol);
3420     }
3421
3422   address = handle->loader->find_sym (data, handle->module, sym);
3423   if (sym != lsym)
3424     {
3425       LT_DLFREE (sym);
3426     }
3427
3428   return address;
3429 }
3430
3431 const char *
3432 lt_dlerror ()
3433 {
3434   const char *error;
3435
3436   LT_DLMUTEX_GETERROR (error);
3437   LT_DLMUTEX_SETERROR (0);
3438
3439   return error ? error : LT_DLSTRERROR (UNKNOWN);
3440 }
3441
3442 static int
3443 lt_dlpath_insertdir (ppath, before, dir)
3444      char **ppath;
3445      char *before;
3446      const char *dir;
3447 {
3448   int    errors         = 0;
3449   char  *canonical      = 0;
3450   char  *argz           = 0;
3451   size_t argz_len       = 0;
3452
3453   assert (ppath);
3454   assert (dir && *dir);
3455
3456   if (canonicalize_path (dir, &canonical) != 0)
3457     {
3458       ++errors;
3459       goto cleanup;
3460     }
3461
3462   assert (canonical && *canonical);
3463
3464   /* If *PPATH is empty, set it to DIR.  */
3465   if (*ppath == 0)
3466     {
3467       assert (!before);         /* BEFORE cannot be set without PPATH.  */
3468       assert (dir);             /* Without DIR, don't call this function!  */
3469
3470       *ppath = lt_estrdup (dir);
3471       if (*ppath == 0)
3472         ++errors;
3473
3474       return errors;
3475     }
3476
3477   assert (ppath && *ppath);
3478
3479   if (argzize_path (*ppath, &argz, &argz_len) != 0)
3480     {
3481       ++errors;
3482       goto cleanup;
3483     }
3484
3485   /* Convert BEFORE into an equivalent offset into ARGZ.  This only works
3486      if *PPATH is already canonicalized, and hence does not change length
3487      with respect to ARGZ.  We canonicalize each entry as it is added to
3488      the search path, and don't call this function with (uncanonicalized)
3489      user paths, so this is a fair assumption.  */
3490   if (before)
3491     {
3492       assert (*ppath <= before);
3493       assert (before - *ppath <= strlen (*ppath));
3494
3495       before = before - *ppath + argz;
3496     }
3497
3498   if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
3499     {
3500       ++errors;
3501       goto cleanup;
3502     }
3503
3504   argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
3505   LT_DLMEM_REASSIGN (*ppath,  argz);
3506
3507  cleanup:
3508   LT_DLFREE (canonical);
3509   LT_DLFREE (argz);
3510
3511   return errors;
3512 }
3513
3514 int
3515 lt_dladdsearchdir (search_dir)
3516      const char *search_dir;
3517 {
3518   int errors = 0;
3519
3520   if (search_dir && *search_dir)
3521     {
3522       LT_DLMUTEX_LOCK ();
3523       if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
3524         ++errors;
3525       LT_DLMUTEX_UNLOCK ();
3526     }
3527
3528   return errors;
3529 }
3530
3531 int
3532 lt_dlinsertsearchdir (before, search_dir)
3533      const char *before;
3534      const char *search_dir;
3535 {
3536   int errors = 0;
3537
3538   if (before)
3539     {
3540       LT_DLMUTEX_LOCK ();
3541       if ((before < user_search_path)
3542           || (before >= user_search_path + LT_STRLEN (user_search_path)))
3543         {
3544           LT_DLMUTEX_UNLOCK ();
3545           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
3546           return 1;
3547         }
3548       LT_DLMUTEX_UNLOCK ();
3549     }
3550
3551   if (search_dir && *search_dir)
3552     {
3553       LT_DLMUTEX_LOCK ();
3554       if (lt_dlpath_insertdir (&user_search_path,
3555                                (char *) before, search_dir) != 0)
3556         {
3557           ++errors;
3558         }
3559       LT_DLMUTEX_UNLOCK ();
3560     }
3561
3562   return errors;
3563 }
3564
3565 int
3566 lt_dlsetsearchpath (search_path)
3567      const char *search_path;
3568 {
3569   int   errors      = 0;
3570
3571   LT_DLMUTEX_LOCK ();
3572   LT_DLFREE (user_search_path);
3573   LT_DLMUTEX_UNLOCK ();
3574
3575   if (!search_path || !LT_STRLEN (search_path))
3576     {
3577       return errors;
3578     }
3579
3580   LT_DLMUTEX_LOCK ();
3581   if (canonicalize_path (search_path, &user_search_path) != 0)
3582     ++errors;
3583   LT_DLMUTEX_UNLOCK ();
3584
3585   return errors;
3586 }
3587
3588 const char *
3589 lt_dlgetsearchpath ()
3590 {
3591   const char *saved_path;
3592
3593   LT_DLMUTEX_LOCK ();
3594   saved_path = user_search_path;
3595   LT_DLMUTEX_UNLOCK ();
3596
3597   return saved_path;
3598 }
3599
3600 int
3601 lt_dlmakeresident (handle)
3602      lt_dlhandle handle;
3603 {
3604   int errors = 0;
3605
3606   if (!handle)
3607     {
3608       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3609       ++errors;
3610     }
3611   else
3612     {
3613       LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
3614     }
3615
3616   return errors;
3617 }
3618
3619 int
3620 lt_dlisresident (handle)
3621      lt_dlhandle handle;
3622 {
3623   if (!handle)
3624     {
3625       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3626       return -1;
3627     }
3628
3629   return LT_DLIS_RESIDENT (handle);
3630 }
3631
3632
3633
3634 \f
3635 /* --- MODULE INFORMATION --- */
3636
3637 const lt_dlinfo *
3638 lt_dlgetinfo (handle)
3639      lt_dlhandle handle;
3640 {
3641   if (!handle)
3642     {
3643       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3644       return 0;
3645     }
3646
3647   return &(handle->info);
3648 }
3649
3650 lt_dlhandle
3651 lt_dlhandle_next (place)
3652      lt_dlhandle place;
3653 {
3654   return place ? place->next : handles;
3655 }
3656
3657 int
3658 lt_dlforeach (func, data)
3659      int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
3660      lt_ptr data;
3661 {
3662   int errors = 0;
3663   lt_dlhandle cur;
3664
3665   LT_DLMUTEX_LOCK ();
3666
3667   cur = handles;
3668   while (cur)
3669     {
3670       lt_dlhandle tmp = cur;
3671
3672       cur = cur->next;
3673       if ((*func) (tmp, data))
3674         {
3675           ++errors;
3676           break;
3677         }
3678     }
3679
3680   LT_DLMUTEX_UNLOCK ();
3681
3682   return errors;
3683 }
3684
3685 lt_dlcaller_id
3686 lt_dlcaller_register ()
3687 {
3688   static lt_dlcaller_id last_caller_id = 0;
3689   int result;
3690
3691   LT_DLMUTEX_LOCK ();
3692   result = ++last_caller_id;
3693   LT_DLMUTEX_UNLOCK ();
3694
3695   return result;
3696 }
3697
3698 lt_ptr
3699 lt_dlcaller_set_data (key, handle, data)
3700      lt_dlcaller_id key;
3701      lt_dlhandle handle;
3702      lt_ptr data;
3703 {
3704   int n_elements = 0;
3705   lt_ptr stale = (lt_ptr) 0;
3706   int i;
3707
3708   /* This needs to be locked so that the caller data can be updated
3709      simultaneously by different threads.  */
3710   LT_DLMUTEX_LOCK ();
3711
3712   if (handle->caller_data)
3713     while (handle->caller_data[n_elements].key)
3714       ++n_elements;
3715
3716   for (i = 0; i < n_elements; ++i)
3717     {
3718       if (handle->caller_data[i].key == key)
3719         {
3720           stale = handle->caller_data[i].data;
3721           break;
3722         }
3723     }
3724
3725   /* Ensure that there is enough room in this handle's caller_data
3726      array to accept a new element (and an empty end marker).  */
3727   if (i == n_elements)
3728     {
3729       lt_caller_data *temp
3730         = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
3731
3732       if (!temp)
3733         {
3734           stale = 0;
3735           goto done;
3736         }
3737
3738       handle->caller_data = temp;
3739
3740       /* We only need this if we needed to allocate a new caller_data.  */
3741       handle->caller_data[i].key  = key;
3742       handle->caller_data[1+ i].key = 0;
3743     }
3744
3745   handle->caller_data[i].data = data;
3746
3747  done:
3748   LT_DLMUTEX_UNLOCK ();
3749
3750   return stale;
3751 }
3752
3753 lt_ptr
3754 lt_dlcaller_get_data  (key, handle)
3755      lt_dlcaller_id key;
3756      lt_dlhandle handle;
3757 {
3758   lt_ptr result = (lt_ptr) 0;
3759
3760   /* This needs to be locked so that the caller data isn't updated by
3761      another thread part way through this function.  */
3762   LT_DLMUTEX_LOCK ();
3763
3764   /* Locate the index of the element with a matching KEY.  */
3765   {
3766     int i;
3767     for (i = 0; handle->caller_data[i].key; ++i)
3768       {
3769         if (handle->caller_data[i].key == key)
3770           {
3771             result = handle->caller_data[i].data;
3772             break;
3773           }
3774       }
3775   }
3776
3777   LT_DLMUTEX_UNLOCK ();
3778
3779   return result;
3780 }
3781
3782
3783 \f
3784 /* --- USER MODULE LOADER API --- */
3785
3786
3787 int
3788 lt_dlloader_add (place, dlloader, loader_name)
3789      lt_dlloader *place;
3790      const struct lt_user_dlloader *dlloader;
3791      const char *loader_name;
3792 {
3793   int errors = 0;
3794   lt_dlloader *node = 0, *ptr = 0;
3795
3796   if ((dlloader == 0)   /* diagnose null parameters */
3797       || (dlloader->module_open == 0)
3798       || (dlloader->module_close == 0)
3799       || (dlloader->find_sym == 0))
3800     {
3801       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
3802       return 1;
3803     }
3804
3805   /* Create a new dlloader node with copies of the user callbacks.  */
3806   node = LT_EMALLOC (lt_dlloader, 1);
3807   if (!node)
3808     return 1;
3809
3810   node->next            = 0;
3811   node->loader_name     = loader_name;
3812   node->sym_prefix      = dlloader->sym_prefix;
3813   node->dlloader_exit   = dlloader->dlloader_exit;
3814   node->module_open     = dlloader->module_open;
3815   node->module_close    = dlloader->module_close;
3816   node->find_sym        = dlloader->find_sym;
3817   node->dlloader_data   = dlloader->dlloader_data;
3818
3819   LT_DLMUTEX_LOCK ();
3820   if (!loaders)
3821     {
3822       /* If there are no loaders, NODE becomes the list! */
3823       loaders = node;
3824     }
3825   else if (!place)
3826     {
3827       /* If PLACE is not set, add NODE to the end of the
3828          LOADERS list. */
3829       for (ptr = loaders; ptr->next; ptr = ptr->next)
3830         {
3831           /*NOWORK*/;
3832         }
3833
3834       ptr->next = node;
3835     }
3836   else if (loaders == place)
3837     {
3838       /* If PLACE is the first loader, NODE goes first. */
3839       node->next = place;
3840       loaders = node;
3841     }
3842   else
3843     {
3844       /* Find the node immediately preceding PLACE. */
3845       for (ptr = loaders; ptr->next != place; ptr = ptr->next)
3846         {
3847           /*NOWORK*/;
3848         }
3849
3850       if (ptr->next != place)
3851         {
3852           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
3853           ++errors;
3854         }
3855       else
3856         {
3857           /* Insert NODE between PTR and PLACE. */
3858           node->next = place;
3859           ptr->next  = node;
3860         }
3861     }
3862
3863   LT_DLMUTEX_UNLOCK ();
3864
3865   return errors;
3866 }
3867
3868 int
3869 lt_dlloader_remove (loader_name)
3870      const char *loader_name;
3871 {
3872   lt_dlloader *place = lt_dlloader_find (loader_name);
3873   lt_dlhandle handle;
3874   int errors = 0;
3875
3876   if (!place)
3877     {
3878       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
3879       return 1;
3880     }
3881
3882   LT_DLMUTEX_LOCK ();
3883
3884   /* Fail if there are any open modules which use this loader. */
3885   for  (handle = handles; handle; handle = handle->next)
3886     {
3887       if (handle->loader == place)
3888         {
3889           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
3890           ++errors;
3891           goto done;
3892         }
3893     }
3894
3895   if (place == loaders)
3896     {
3897       /* PLACE is the first loader in the list. */
3898       loaders = loaders->next;
3899     }
3900   else
3901     {
3902       /* Find the loader before the one being removed. */
3903       lt_dlloader *prev;
3904       for (prev = loaders; prev->next; prev = prev->next)
3905         {
3906           if (!strcmp (prev->next->loader_name, loader_name))
3907             {
3908               break;
3909             }
3910         }
3911
3912       place = prev->next;
3913       prev->next = prev->next->next;
3914     }
3915
3916   if (place->dlloader_exit)
3917     {
3918       errors = place->dlloader_exit (place->dlloader_data);
3919     }
3920
3921   LT_DLFREE (place);
3922
3923  done:
3924   LT_DLMUTEX_UNLOCK ();
3925
3926   return errors;
3927 }
3928
3929 lt_dlloader *
3930 lt_dlloader_next (place)
3931      lt_dlloader *place;
3932 {
3933   lt_dlloader *next;
3934
3935   LT_DLMUTEX_LOCK ();
3936   next = place ? place->next : loaders;
3937   LT_DLMUTEX_UNLOCK ();
3938
3939   return next;
3940 }
3941
3942 const char *
3943 lt_dlloader_name (place)
3944      lt_dlloader *place;
3945 {
3946   const char *name = 0;
3947
3948   if (place)
3949     {
3950       LT_DLMUTEX_LOCK ();
3951       name = place ? place->loader_name : 0;
3952       LT_DLMUTEX_UNLOCK ();
3953     }
3954   else
3955     {
3956       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
3957     }
3958
3959   return name;
3960 }
3961
3962 lt_user_data *
3963 lt_dlloader_data (place)
3964      lt_dlloader *place;
3965 {
3966   lt_user_data *data = 0;
3967
3968   if (place)
3969     {
3970       LT_DLMUTEX_LOCK ();
3971       data = place ? &(place->dlloader_data) : 0;
3972       LT_DLMUTEX_UNLOCK ();
3973     }
3974   else
3975     {
3976       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
3977     }
3978
3979   return data;
3980 }
3981
3982 lt_dlloader *
3983 lt_dlloader_find (loader_name)
3984      const char *loader_name;
3985 {
3986   lt_dlloader *place = 0;
3987
3988   LT_DLMUTEX_LOCK ();
3989   for (place = loaders; place; place = place->next)
3990     {
3991       if (strcmp (place->loader_name, loader_name) == 0)
3992         {
3993           break;
3994         }
3995     }
3996   LT_DLMUTEX_UNLOCK ();
3997
3998   return place;
3999 }