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