libtool/libltdl/slist.c
Gary V. Vaughan 5451db06bd Split lt_dlloader management into a separate file, and factor
`loaders' list management into a new SList ADT.  In the process,
the API for writing loaders is a little cleaner, so all the
existing loaders were tweaked to take advantage of that:

* libltdl/slist.h, libltdl/slist.c: New files implementing a
generic singly linked list container ADT.  The ADT is purely
internal, and none of its API's are visible from an installed
libltdl.
* libltdl/lt_dlloader.h (lt_dlloader): Removed next field again
:-) Renamed to lt_dlvtable for API.  Changed all callers.
(lt_dlloader_get): New function to turn an lt_dlloader into its
associated lt_dlvtable.
(lt_dlloader_add): Removed unused data parameter.  The caller
data belongs to (and is set by) the loader itself, not the
loader's client.  Changed all callers.
(lt_dlloader_name, lt_dlloader_data): Removed.  Use
lt_dlloader_get instead!
* libltdl/lt__private.h: Include slist.h.
(lt__alloc_die_callback): Add missing LT_SCOPE to declaration.
(lt_dlhandle_struct): Use lt_dlvtable instead of opaque
lt_dlloader.
* libltdl/ltdl.c (lt_dlexit): Rewritten for the new loader API.
(loaders, lt_dlloader_add, lt_dlloader_remove, lt_dlloader_next,
lt_dlloader_find): Moved from here...
* libltdl/lt_dlloader.c ((loaders, lt_dlloader_add,
lt_dlloader_remove, lt_dlloader_next, lt_dlloader_find): ...to
here.  And rewritten in terms of new SList interface.
* libltdl/ltdl.c (lt_dlexit, tryall_dlopen): Rewritten in terms of
new lt_dlloader interface.
* libltdl/Makefile.am (libdlloader_la_SOURCES): Add slist.h and
slist.c.  Move lt_dlloader.h from here...
(pkginclude_HEADERS): ...to here.
(libltdl_la_SOURCES): Add lt_dlloader.c and lt_dlloader.h.
2004-07-15 12:33:20 +00:00

207 lines
4.1 KiB
C

/* slist.h -- generalised singly linked lists
Copyright (C) 2000, 2004 Free Software Foundation, Inc.
Originally 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.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
As a special exception to the GNU Lesser General Public License,
if you distribute this file as part of a program or library that
is built using GNU libtool, you may include it under the same
distribution terms that you use for the rest of that program.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
*/
#include <assert.h>
#include "slist.h"
SList *
slist_new (const void *userdata)
{
SList *node = malloc (sizeof *node);
node->next = 0;
node->userdata = userdata;
return node;
}
SList *
slist_delete (SList *head, void (*delete) (void *data))
{
assert (delete);
while (head)
{
SList *next = head->next;
(*delete) (head);
head = next;
}
return 0;
}
/* Call Find repeatedly with MATCH and each element 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.
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. */
void *
slist_remove (SList **phead, const void *match, SListCompare *find)
{
SList *stale = 0;
void *result = 0;
assert (find);
if (!phead || !*phead)
return 0;
/* Does the head of the passed list match? */
result = (*find) (*phead, match);
if (result)
{
stale = *phead;
*phead = stale->next;
}
/* what about the rest of the elements? */
else
{
SList *head;
for (head = *phead; head->next; head = head->next)
{
result = (*find) (head->next, match);
if (result)
{
stale = head->next;
head->next = stale->next;
}
}
}
return result;
}
SList *
slist_concat (SList *head, SList *tail)
{
if (!head)
{
return tail;
}
while (head->next)
head = head->next;
head->next = tail;
return head;
}
SList *
slist_cons (SList *head, SList *tail)
{
if (!head)
{
return tail;
}
head->next = tail;
return head;
}
SList *
slist_tail (SList *head)
{
return head ? head->next : 0;
}
SList *
slist_nth (SList *head, size_t n)
{
for (;n > 1 && head; n--)
head = head->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;
}
size_t
slist_length (SList *head)
{
size_t n;
for (n = 0; head; ++n)
head = head->next;
return n;
}
SList *
slist_reverse (SList *head)
{
SList *result = 0;
SList *next;
while (head)
{
next = head->next;
head->next = result;
result = head;
head = next;
}
return result;
}
int
slist_foreach (SList *head, SListCallback *foreach, const void *userdata)
{
assert (foreach);
for (; head; head = head->next)
if ((*foreach) (head, userdata) < 0)
return -1;
return 0;
}