Annotation of gforth/libltdl/lt_dlloader.c, revision 1.1

1.1     ! anton       1: /* lt_dlloader.c -- dynamic library loader interface
        !             2: 
        !             3:    Copyright (C) 2004, 2007 Free Software Foundation, Inc.
        !             4:    Written by Gary V. Vaughan, 2004
        !             5: 
        !             6:    NOTE: The canonical source of this file is maintained with the
        !             7:    GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
        !             8: 
        !             9: GNU Libltdl is free software; you can redistribute it and/or
        !            10: modify it under the terms of the GNU Lesser General Public
        !            11: License as published by the Free Software Foundation; either
        !            12: version 2 of the License, or (at your option) any later version.
        !            13: 
        !            14: As a special exception to the GNU Lesser General Public License,
        !            15: if you distribute this file as part of a program or library that
        !            16: is built using GNU Libtool, you may include this file under the
        !            17: same distribution terms that you use for the rest of that program.
        !            18: 
        !            19: GNU Libltdl is distributed in the hope that it will be useful,
        !            20: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            21: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            22: GNU Lesser General Public License for more details.
        !            23: 
        !            24: You should have received a copy of the GNU Lesser General Public
        !            25: License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
        !            26: copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
        !            27: or obtained by writing to the Free Software Foundation, Inc.,
        !            28: 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
        !            29: */
        !            30: 
        !            31: #include "lt__private.h"
        !            32: #include "lt_dlloader.h"
        !            33: 
        !            34: #define RETURN_SUCCESS 0
        !            35: #define RETURN_FAILURE 1
        !            36: 
        !            37: static void *  loader_callback (SList *item, void *userdata);
        !            38: 
        !            39: /* A list of all the dlloaders we know about, each stored as a boxed
        !            40:    SList item:  */
        !            41: static SList    *loaders               = 0;
        !            42: 
        !            43: 
        !            44: /* Return NULL, unless the loader in this ITEM has a matching name,
        !            45:    in which case we return the matching item so that its address is
        !            46:    passed back out (for possible freeing) by slist_remove.  */
        !            47: static void *
        !            48: loader_callback (SList *item, void *userdata)
        !            49: {
        !            50:   const lt_dlvtable *vtable = (const lt_dlvtable *) item->userdata;
        !            51:   const char *     name    = (const char *) userdata;
        !            52: 
        !            53:   assert (vtable);
        !            54: 
        !            55:   return streq (vtable->name, name) ? (void *) item : NULL;
        !            56: }
        !            57: 
        !            58: 
        !            59: /* Hook VTABLE into our global LOADERS list according to its own
        !            60:    PRIORITY field value.  */
        !            61: int
        !            62: lt_dlloader_add (const lt_dlvtable *vtable)
        !            63: {
        !            64:   SList *item;
        !            65: 
        !            66:   if ((vtable == 0)    /* diagnose invalid vtable fields */
        !            67:       || (vtable->module_open == 0)
        !            68:       || (vtable->module_close == 0)
        !            69:       || (vtable->find_sym == 0)
        !            70:       || ((vtable->priority != LT_DLLOADER_PREPEND) &&
        !            71:          (vtable->priority != LT_DLLOADER_APPEND)))
        !            72:     {
        !            73:       LT__SETERROR (INVALID_LOADER);
        !            74:       return RETURN_FAILURE;
        !            75:     }
        !            76: 
        !            77:   item = slist_box (vtable);
        !            78:   if (!item)
        !            79:     {
        !            80:       (*lt__alloc_die) ();
        !            81: 
        !            82:       /* Let the caller know something went wrong if lt__alloc_die
        !            83:         doesn't abort.  */
        !            84:       return RETURN_FAILURE;
        !            85:     }
        !            86: 
        !            87:   if (vtable->priority == LT_DLLOADER_PREPEND)
        !            88:     {
        !            89:       loaders = slist_cons (item, loaders);
        !            90:     }
        !            91:   else
        !            92:     {
        !            93:       assert (vtable->priority == LT_DLLOADER_APPEND);
        !            94:       loaders = slist_concat (loaders, item);
        !            95:     }
        !            96: 
        !            97:   return RETURN_SUCCESS;
        !            98: }
        !            99: 
        !           100: #ifdef LT_DEBUG_LOADERS
        !           101: static void *
        !           102: loader_dump_callback (SList *item, void *userdata)
        !           103: {
        !           104:   const lt_dlvtable *vtable = (const lt_dlvtable *) item->userdata;
        !           105:   fprintf (stderr, ", %s", (vtable && vtable->name) ? vtable->name : "(null)");
        !           106:   return 0;
        !           107: }
        !           108: 
        !           109: void
        !           110: lt_dlloader_dump (void)
        !           111: {
        !           112:   fprintf (stderr, "loaders: ");
        !           113:   if (!loaders)
        !           114:     {
        !           115:       fprintf (stderr, "(empty)");
        !           116:     }
        !           117:   else
        !           118:     {
        !           119:       const lt_dlvtable *head = (const lt_dlvtable *) loaders->userdata;
        !           120:       fprintf (stderr, "%s", (head && head->name) ? head->name : "(null)");
        !           121:       if (slist_tail (loaders))
        !           122:        slist_foreach (slist_tail (loaders), loader_dump_callback, NULL);
        !           123:     }
        !           124:   fprintf (stderr, "\n");
        !           125: }
        !           126: #endif
        !           127: 
        !           128: /* An iterator for the global loader list: if LOADER is NULL, then
        !           129:    return the first element, otherwise the following element.  */
        !           130: lt_dlloader
        !           131: lt_dlloader_next (lt_dlloader loader)
        !           132: {
        !           133:   SList *item = (SList *) loader;
        !           134:   return (lt_dlloader) (item ? item->next : loaders);
        !           135: }
        !           136: 
        !           137: 
        !           138: /* Non-destructive unboxing of a loader.  */
        !           139: const lt_dlvtable *
        !           140: lt_dlloader_get        (lt_dlloader loader)
        !           141: {
        !           142:   return (const lt_dlvtable *) (loader ? ((SList *) loader)->userdata : NULL);
        !           143: }
        !           144: 
        !           145: 
        !           146: /* Return the contents of the first item in the global loader list
        !           147:    with a matching NAME after removing it from that list.  If there
        !           148:    was no match, return NULL; if there is an error, return NULL and
        !           149:    set an error for lt_dlerror; do not set an error if only resident
        !           150:    modules need this loader; in either case, the loader list is not
        !           151:    changed if NULL is returned.  */
        !           152: lt_dlvtable *
        !           153: lt_dlloader_remove (char *name)
        !           154: {
        !           155:   const lt_dlvtable *  vtable  = lt_dlloader_find (name);
        !           156:   static const char    id_string[] = "lt_dlloader_remove";
        !           157:   lt_dlinterface_id    iface;
        !           158:   lt_dlhandle          handle = 0;
        !           159:   int                  in_use = 0;
        !           160:   int                  in_use_by_resident = 0;
        !           161: 
        !           162:   if (!vtable)
        !           163:     {
        !           164:       LT__SETERROR (INVALID_LOADER);
        !           165:       return 0;
        !           166:     }
        !           167: 
        !           168:   /* Fail if there are any open modules which use this loader.  */
        !           169:   iface = lt_dlinterface_register (id_string, NULL);
        !           170:   while ((handle = lt_dlhandle_iterate (iface, handle)))
        !           171:     {
        !           172:       lt__handle *cur = (lt__handle *) handle;
        !           173:       if (cur->vtable == vtable)
        !           174:        {
        !           175:          in_use = 1;
        !           176:          if (lt_dlisresident (handle))
        !           177:            in_use_by_resident = 1;
        !           178:        }
        !           179:     }
        !           180:   lt_dlinterface_free (iface);
        !           181:   if (in_use)
        !           182:     {
        !           183:       if (!in_use_by_resident)
        !           184:        LT__SETERROR (REMOVE_LOADER);
        !           185:       return 0;
        !           186:     }
        !           187: 
        !           188:   /* Call the loader finalisation function.  */
        !           189:   if (vtable && vtable->dlloader_exit)
        !           190:     {
        !           191:       if ((*vtable->dlloader_exit) (vtable->dlloader_data) != 0)
        !           192:        {
        !           193:          /* If there is an exit function, and it returns non-zero
        !           194:             then it must set an error, and we will not remove it
        !           195:             from the list.  */
        !           196:          return 0;
        !           197:        }
        !           198:     }
        !           199: 
        !           200:   /* If we got this far, remove the loader from our global list.  */
        !           201:   return (lt_dlvtable *)
        !           202:       slist_unbox ((SList *) slist_remove (&loaders, loader_callback, name));
        !           203: }
        !           204: 
        !           205: 
        !           206: const lt_dlvtable *
        !           207: lt_dlloader_find (char *name)
        !           208: {
        !           209:   return lt_dlloader_get (slist_find (loaders, loader_callback, name));
        !           210: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>