Annotation of tme/libltdl/ltdl.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.