* libltdl/slist.c, libltdl/slist.h: Merge in changes from latest

upstream.  Mostly comments, formal item boxing, a sort function,
and const madness reduction.
(slist_new): Removed.
(slist_box, slist_unbox, slist_sort): New.
(SListCompare, SListCallback): Swapped!
(slist_remove, slist_find): Change order of parameters for
orthogonality with slist_foreach.  Changed all callers.
* libltdl/lt_dlloader.c (loader_cmp): Renamed to...
(loader_callback): ...this.  Return boxed item.
(lt_dlloader_remove): Adjust to new loader_callback semantics;
unbox each removed item before returning.
Remove unused variable.
Remove const from name parameter, since the slist API cannot
guarantee userdata const-ancy for its callback functions.
(lt_dlloader_find): Adjust to new loader_callback semantics; need
to return the contents of the boxed item.
Remove const from name parameter, since the slist API cannot
guarantee userdata const-ancy for its callback functions.
* libltdl/lt_dlloader.h (lt_dlloader_find, lt_dlloader_remove):
Adjust to new constless footprint.
* libltdl/ltdl.c (ltdl_exit): The global `loaders' list is changed
variable `loader' is invalidated.  Since some loaders may be
resident modules that cannot be unloaded (though we have none
yet), we must save each `next' address before calling
`lt_dlloader_remove'.
* NEWS: Updated.
* THANKS: Added Ralf.
This commit is contained in:
Gary V. Vaughan 2004-09-02 12:55:32 +00:00
parent 1748adcc65
commit cae83b341b
8 changed files with 327 additions and 116 deletions

View File

@ -1,3 +1,36 @@
2004-09-02 Gary V. Vaughan <gary@gnu.org>,
Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
* libltdl/slist.c, libltdl/slist.h: Merge in changes from latest
upstream. Mostly comments, formal item boxing, a sort function,
and const madness reduction.
(slist_new): Removed.
(slist_box, slist_unbox, slist_sort): New.
(SListCompare, SListCallback): Swapped!
(slist_remove, slist_find): Change order of parameters for
orthogonality with slist_foreach. Changed all callers.
* libltdl/lt_dlloader.c (loader_cmp): Renamed to...
(loader_callback): ...this. Return boxed item.
(lt_dlloader_remove): Adjust to new loader_callback semantics;
unbox each removed item before returning.
Remove unused variable.
Remove const from name parameter, since the slist API cannot
guarantee userdata const-ancy for its callback functions.
(lt_dlloader_find): Adjust to new loader_callback semantics; need
to return the contents of the boxed item.
Remove const from name parameter, since the slist API cannot
guarantee userdata const-ancy for its callback functions.
* libltdl/lt_dlloader.h (lt_dlloader_find, lt_dlloader_remove):
Adjust to new constless footprint.
* libltdl/ltdl.c (ltdl_exit): The global `loaders' list is changed
by `lt_dlloader_remove' while cleaning up, so the address in local
variable `loader' is invalidated. Since some loaders may be
resident modules that cannot be unloaded (though we have none
yet), we must save each `next' address before calling
`lt_dlloader_remove'.
* NEWS: Updated.
* THANKS: Added Ralf.
2004-09-01 Gary V. Vaughan <gary@gnu.org>
* libltdl/lt_dlloader.c (lt_dlloader_add): Handle malloc failure

8
NEWS
View File

@ -1,7 +1,13 @@
NEWS - list of user-visible changes between releases of GNU Libtool
New in 1.9d: 2004-??-??; CVS version 1.9c, Libtool team:
* Return type of lt_dlloader_remove is no longer `const'.
* Return type, and name parameter of lt_dlloader_remove are no longer
`const'.
* Name parameter of lt_dlloader_find is no longer 'const'.
* The API for the slist ADT has been updated: slist_new has been replaced
by slist_box; slist_unbox and slist_sort are new; the footprint of
slist_remove and slist_fnid have changed; SListCallback and SListCompare
types have been exchanged. See libltdl/slist.c for documentation.
* libltdl is C89 compatible again. lt_dlsymbol type removed, and lt_dlsymlist
structure changed to avoid using C99 flexible arrays.

1
THANKS
View File

@ -43,6 +43,7 @@ Peter Eisentraut peter_e@gmx.net
Benjamin Reed ranger@befunk.com
Pavel Roskin pavel_roskin@geocities.com
Rainer Orth ro@TechFak.Uni-Bielefeld.DE
Ralf Wildenhues Ralf.Wildenhues@gmx.de
Ralph Schleicher rs@nunatak.allgaeu.org
Robert Collins robert.collins@itdomain.com.au
Sebastian Wilhelmi wilhelmi@ira.uka.de

View File

@ -33,24 +33,25 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
#define RETURN_SUCCESS 0
#define RETURN_FAILURE 1
static void * loader_cmp (const SList *node, const void *userdata);
static void * loader_callback (SList *item, void *userdata);
/* A list of all the dlloaders we know about, each stored in the
USERDATA field of an SList node: */
/* A list of all the dlloaders we know about, each stored as a boxed
SList item: */
static SList *loaders = 0;
/* Return NULL, unless the loader in this NODE has a matching name,
in which case we return the vtable from matching node so that its
address is passed back out (for possible freeing) by slist_remove. */
/* Return NULL, unless the loader in this ITEM has a matching name,
in which case we return the matching item so that its address is
passed back out (for possible freeing) by slist_remove. */
static void *
loader_cmp (const SList *node, const void *userdata)
loader_callback (SList *item, void *userdata)
{
const lt_dlvtable *vtable = node->userdata;
const lt_dlvtable *vtable = item->userdata;
const char * name = userdata;
assert (vtable);
return streq (vtable->name, name) ? (void *) vtable : 0;
return streq (vtable->name, name) ? (void *) item : 0;
}
@ -59,7 +60,7 @@ loader_cmp (const SList *node, const void *userdata)
int
lt_dlloader_add (const lt_dlvtable *vtable)
{
SList *list;
SList *item;
if ((vtable == 0) /* diagnose invalid vtable fields */
|| (vtable->module_open == 0)
@ -72,8 +73,8 @@ lt_dlloader_add (const lt_dlvtable *vtable)
return RETURN_FAILURE;
}
list = slist_new (vtable);
if (!list)
item = slist_box (vtable);
if (!item)
{
(*lt__alloc_die) ();
@ -84,12 +85,12 @@ lt_dlloader_add (const lt_dlvtable *vtable)
if (vtable->priority == LT_DLLOADER_PREPEND)
{
loaders = slist_cons (list, loaders);
loaders = slist_cons (item, loaders);
}
else
{
assert (vtable->priority == LT_DLLOADER_APPEND);
loaders = slist_concat (loaders, list);
loaders = slist_concat (loaders, item);
}
return RETURN_SUCCESS;
@ -101,28 +102,29 @@ lt_dlloader_add (const lt_dlvtable *vtable)
lt_dlloader
lt_dlloader_next (lt_dlloader loader)
{
SList *node = (SList *) loader;
return (lt_dlloader) (node ? node->next : loaders);
SList *item = (SList *) loader;
return (lt_dlloader) (item ? item->next : loaders);
}
/* Non-destructive unboxing of a loader. */
const lt_dlvtable *
lt_dlloader_get (lt_dlloader loader)
{
return ((SList *) loader)->userdata;
return loader ? ((SList *) loader)->userdata : 0;
}
/* Return the contents of the first item in the global loader list
with a matching NAME after removing it from that list. If there
was no match, return NULL; if there is an error, return NULL and
set an error for lt_dlerror; in either case the loader list is
not changed. */
set an error for lt_dlerror; in either case, the loader list is
not changed if NULL is returned. */
lt_dlvtable *
lt_dlloader_remove (const char *name)
lt_dlloader_remove (char *name)
{
const lt_dlvtable * vtable = lt_dlloader_find (name);
lt__handle * handle = 0;
int errors = 0;
if (!vtable)
{
@ -153,12 +155,12 @@ lt_dlloader_remove (const char *name)
}
/* If we got this far, remove the loader from our global list. */
return slist_remove (&loaders, name, loader_cmp);
return slist_unbox (slist_remove (&loaders, loader_callback, name));
}
const lt_dlvtable *
lt_dlloader_find (const char *name)
lt_dlloader_find (char *name)
{
return slist_find (loaders, name, loader_cmp);
return lt_dlloader_get (slist_find (loaders, loader_callback, name));
}

View File

@ -70,8 +70,8 @@ typedef struct {
LT_SCOPE int lt_dlloader_add (const lt_dlvtable *vtable);
LT_SCOPE lt_dlloader lt_dlloader_next (const lt_dlloader loader);
LT_SCOPE lt_dlvtable * lt_dlloader_remove (const char *name);
LT_SCOPE const lt_dlvtable *lt_dlloader_find (const char *name);
LT_SCOPE lt_dlvtable * lt_dlloader_remove (char *name);
LT_SCOPE const lt_dlvtable *lt_dlloader_find (char *name);
LT_SCOPE const lt_dlvtable *lt_dlloader_get (lt_dlloader loader);

View File

@ -278,8 +278,9 @@ lt_dlexit (void)
}
/* close all loaders */
while ((loader = lt_dlloader_next (loader)))
for (loader = lt_dlloader_next (NULL); loader;)
{
lt_dlloader *next = lt_dlloader_next (loader);
lt_dlvtable *vtable = (lt_dlvtable *) lt_dlloader_get (loader);
if ((vtable = lt_dlloader_remove (vtable->name)))
@ -290,6 +291,8 @@ lt_dlexit (void)
{
++errors;
}
loader = next;
}
}

View File

@ -1,6 +1,6 @@
/* slist.h -- generalised singly linked lists
Copyright (C) 2000, 2004 Free Software Foundation, Inc.
Originally by Gary V. Vaughan <gary@gnu.org>
Written by Gary V. Vaughan <gary@gnu.org>
NOTE: The canonical source of this file is maintained with the
GNU Libtool package. Report bugs to bug-libtool@gnu.org.
@ -31,23 +31,24 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
#include "slist.h"
static SList * slist_sort_merge (SList *left, SList *right,
SListCompare *compare, void *userdata);
/* Call DELETE repeatedly on each element of HEAD.
CAVEAT: If you call this when HEAD is the start of a list of boxed
items, you must remember that each item passed back to your
DELETE function will be a boxed item must be slist_unbox()ed
before operating on its contents.
e.g. void boxed_delete (void *item) { item_free (slist_unbox (item)); }
...
slist = slist_delete (slist, boxed_delete);
...
*/
SList *
slist_new (const void *userdata)
{
SList *node = malloc (sizeof *node);
if (node)
{
node->next = 0;
node->userdata = userdata;
}
return node;
}
SList *
slist_delete (SList *head, void (*delete) (void *data))
slist_delete (SList *head, void (*delete) (void *item))
{
assert (delete);
@ -61,16 +62,17 @@ slist_delete (SList *head, void (*delete) (void *data))
return 0;
}
/* Call Find repeatedly with MATCH and each element of *PHEAD, until
/* Call FIND repeatedly with MATCHDATA and each item of *PHEAD, until
FIND returns non-NULL, or the list is exhausted. If a match is found
the matching element is removed from *PHEAD, and the value returned
by the matching call to FIND is returned.
the matching item is destructively removed from *PHEAD, and the value
returned by the matching call to FIND is returned.
To avoid memory leaks, unless you already have the address of the
stale element, you should probably return that from FIND if it makes
a successful match. */
CAVEAT: To avoid memory leaks, unless you already have the address of
the stale item, you should probably return that from FIND if
it makes a successful match. Don't forget to slist_unbox()
every item in a boxed list before operating on its contents. */
void *
slist_remove (SList **phead, const void *match, SListCompare *find)
slist_remove (SList **phead, SListCallback *find, void *matchdata)
{
SList *stale = 0;
void *result = 0;
@ -81,7 +83,7 @@ slist_remove (SList **phead, const void *match, SListCompare *find)
return 0;
/* Does the head of the passed list match? */
result = (*find) (*phead, match);
result = (*find) (*phead, matchdata);
if (result)
{
stale = *phead;
@ -93,7 +95,7 @@ slist_remove (SList **phead, const void *match, SListCompare *find)
SList *head;
for (head = *phead; head->next; head = head->next)
{
result = (*find) (head->next, match);
result = (*find) (head->next, matchdata);
if (result)
{
stale = head->next;
@ -105,6 +107,33 @@ slist_remove (SList **phead, const void *match, SListCompare *find)
return result;
}
/* Call FIND repeatedly with each element of SLIST and MATCHDATA, until
FIND returns non-NULL, or the list is exhausted. If a match is found
the value returned by the matching call to FIND is returned. */
void *
slist_find (SList *slist, SListCallback *find, void *matchdata)
{
void *result = 0;
assert (find);
for (; slist; slist = slist->next)
{
result = (*find) (slist, matchdata);
if (result)
break;
}
return result;
}
/* Return a single list, composed by destructively concatenating the
items in HEAD and TAIL. The values of HEAD and TAIL are undefined
after calling this function.
CAVEAT: Don't mix boxed and unboxed items in a single list.
e.g. slist1 = slist_concat (slist1, slist2); */
SList *
slist_concat (SList *head, SList *tail)
{
@ -121,89 +150,218 @@ slist_concat (SList *head, SList *tail)
return head;
}
/* Return a single list, composed by destructively appending all of
the items in SLIST to ITEM. The values of ITEM and SLIST are undefined
after calling this function.
CAVEAT: Don't mix boxed and unboxed items in a single list.
e.g. slist1 = slist_cons (slist_box (data), slist1); */
SList *
slist_cons (SList *head, SList *tail)
slist_cons (SList *item, SList *slist)
{
if (!head)
if (!item)
{
return tail;
return slist;
}
head->next = tail;
return head;
item->next = slist;
return item;
}
/* Return a list starting at the second item of SLIST. */
SList *
slist_tail (SList *head)
slist_tail (SList *slist)
{
return head ? head->next : 0;
return slist ? slist->next : 0;
}
/* Return a list starting at the Nth item of SLIST. If SLIST is less
than N items long, NULL is returned. Just to be confusing, list items
are counted from 1, to get the 2nd element of slist:
e.g. shared_list = slist_nth (slist, 2); */
SList *
slist_nth (SList *head, size_t n)
slist_nth (SList *slist, size_t n)
{
for (;n > 1 && head; n--)
head = head->next;
for (;n > 1 && slist; n--)
slist = slist->next;
return head;
}
/* Call FIND repeatedly with SEARCH and each element of HEAD, until
FIND returns non-NULL, or the list is exhausted. If a match is found
the value returned by the matching call to FIND is returned. */
void *
slist_find (SList *head, const void *match, SListCompare *find)
{
void *result = 0;
assert (find);
for (; head; head = head->next)
{
result = (*find) (head, match);
if (result)
break;
}
return result;
return slist;
}
/* Return the number of items in SLIST. We start counting from 1, so
the length of a list with no items is 0, and so on. */
size_t
slist_length (SList *head)
slist_length (SList *slist)
{
size_t n;
for (n = 0; head; ++n)
head = head->next;
for (n = 0; slist; ++n)
slist = slist->next;
return n;
}
/* Destructively reverse the order of items in SLIST. The value of SLIST
is undefined after calling this function.
CAVEAT: You must stare the result of this function, or you might not
be able to get all the items except the first one back again.
e.g. slist = slist_reverse (slist); */
SList *
slist_reverse (SList *head)
slist_reverse (SList *slist)
{
SList *result = 0;
SList *next;
while (head)
while (slist)
{
next = head->next;
head->next = result;
result = head;
head = next;
next = slist->next;
slist->next = result;
result = slist;
slist = next;
}
return result;
}
int
slist_foreach (SList *head, SListCallback *foreach, const void *userdata)
/* Call FOREACH once for each item in SLIST, passing both the item and
USERDATA on each call. */
void *
slist_foreach (SList *slist, SListCallback *foreach, void *userdata)
{
void *result = 0;
assert (foreach);
for (; head; head = head->next)
if ((*foreach) (head, userdata) < 0)
return -1;
while (slist)
{
SList *next = slist->next;
void *result = (*foreach) (slist, userdata);
return 0;
if (result)
break;
slist = next;
}
return result;
}
/* Destructively merge the items of two ordered lists LEFT and RIGHT,
returning a single sorted list containing the items of both -- Part of
the quicksort algorithm. The values of LEFT and RIGHT are undefined
after calling this function.
At each iteration, add another item to the merged list by taking the
lowest valued item from the head of either LEFT or RIGHT, determined
by passing those items and USERDATA to COMPARE. COMPARE should return
less than 0 if the head of LEFT has the lower value, greater than 0 if
the head of RIGHT has the lower value, otherwise 0. */
static SList *
slist_sort_merge (SList *left, SList *right, SListCompare *compare,
void *userdata)
{
SList merged, *insert;
insert = &merged;
while (left && right)
{
if ((*compare) (left, right, userdata) <= 0)
{
insert = insert->next = left;
left = left->next;
}
else
{
insert = insert->next = right;
right = right->next;
}
}
insert->next = left ? left : right;
return merged.next;
}
/* Perform a destructive quicksort on the items in SLIST, by repeatedly
calling COMPARE with a pair of items from SLIST along with USERDATA
at every iteration. COMPARE is a function as defined above for
slist_sort_merge(). The value of SLIST is undefined after calling
this function.
e.g. slist = slist_sort (slist, compare, 0); */
SList *
slist_sort (SList *slist, SListCompare *compare, void *userdata)
{
SList *left, *right;
if (!slist)
return slist;
/* Be sure that LEFT and RIGHT never contain the same item. */
left = slist;
right = slist->next;
/* Skip two items with RIGHT and one with SLIST, until RIGHT falls off
the end. SLIST must be about half way along. */
while (right && (right = right->next))
{
if (!right || !(right = right->next))
break;
slist = slist->next;
}
right = slist->next;
slist->next = 0;
/* Sort LEFT and RIGHT, then merge the two. */
return slist_sort_merge (slist_sort (left, compare, userdata),
slist_sort (right, compare, userdata),
compare, userdata);
}
/* Aside from using the functions above to manage chained structures of
any type that has a NEXT pointer as its first field, SLISTs can
be comprised of boxed items. The boxes are chained together in
that case, so there is no need for a NEXT field in the item proper.
Some care must be taken to slist_box and slist_unbox each item in
a boxed list at the appropriate points to avoid leaking the memory
used for the boxes. It us usually a very bad idea to mix boxed and
non-boxed items in a single list. */
/* Return a `boxed' freshly mallocated 1 element list containing
USERDATA. */
SList *
slist_box (const void *userdata)
{
SList *item = malloc (sizeof *item);
if (item)
{
item->next = 0;
item->userdata = userdata;
}
return item;
}
/* Return the contents of a `boxed' ITEM, recycling the box itself. */
void *
slist_unbox (SList *item)
{
void *userdata = 0;
if (item)
{
/* Strip the const, because responsibility for this memory
passes to the caller on return. */
userdata = (void *) item->userdata;
free (item);
}
return userdata;
}

View File

@ -1,6 +1,6 @@
/* slist.h -- generalised singly linked lists
Copyright (C) 2000, 2004 Free Software Foundation, Inc.
Originally by Gary V. Vaughan <gary@gnu.org>
Written by Gary V. Vaughan <gary@gnu.org>
NOTE: The canonical source of this file is maintained with the
GNU Libtool package. Report bugs to bug-libtool@gnu.org.
@ -47,26 +47,34 @@ LT_BEGIN_C_DECLS
typedef struct slist {
struct slist *next; /* chain forward pointer*/
const void * userdata; /* incase you want to use raw `SList's */
const void *userdata; /* for boxed `SList' item */
} SList;
typedef void * SListCompare (const SList *node, const void *userdata);
typedef int SListCallback (const SList *node, const void *userdata);
typedef void * SListCallback (SList *item, void *userdata);
typedef int SListCompare (const SList *item1, const SList *item2,
void *userdata);
LT_SCOPE SList *slist_new (const void *userdata);
LT_SCOPE SList *slist_delete (SList *head, void (*delete) (void *data));
LT_SCOPE void * slist_remove (SList **phead, const void *match,
SListCompare *find);
LT_SCOPE SList *slist_concat (SList *head, SList *tail);
LT_SCOPE SList *slist_cons (SList *head, SList *tail);
LT_SCOPE SList *slist_tail (SList *head);
LT_SCOPE SList *slist_nth (SList *head, size_t n);
LT_SCOPE void * slist_find (SList *head, const void *match,
SListCompare *find);
LT_SCOPE size_t slist_length (SList *head);
LT_SCOPE SList *slist_reverse (SList *head);
LT_SCOPE int slist_foreach (SList *head, SListCallback *foreach,
const void *userdata);
LT_SCOPE SList *slist_cons (SList *item, SList *slist);
LT_SCOPE SList *slist_delete (SList *slist, void (*delete) (void *item));
LT_SCOPE void * slist_remove (SList **phead, SListCallback *find,
void *matchdata);
LT_SCOPE SList *slist_reverse (SList *slist);
LT_SCOPE SList *slist_sort (SList *slist, SListCompare *compare,
void *userdata);
LT_SCOPE SList *slist_tail (SList *slist);
LT_SCOPE SList *slist_nth (SList *slist, size_t n);
LT_SCOPE void * slist_find (SList *slist, SListCallback *find,
void *matchdata);
LT_SCOPE size_t slist_length (SList *slist);
LT_SCOPE void * slist_foreach (SList *slist, SListCallback *foreach,
void *userdata);
LT_SCOPE SList *slist_box (const void *userdata);
LT_SCOPE void * slist_unbox (SList *item);
LT_END_C_DECLS