]> git.ipfire.org Git - thirdparty/libtool.git/commitdiff
* libltdl/slist.c, libltdl/slist.h: Merge in changes from latest
authorGary V. Vaughan <gary@gnu.org>
Thu, 2 Sep 2004 12:55:32 +0000 (12:55 +0000)
committerGary V. Vaughan <gary@gnu.org>
Thu, 2 Sep 2004 12:55:32 +0000 (12:55 +0000)
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.

ChangeLog
NEWS
THANKS
libltdl/lt_dlloader.c
libltdl/lt_dlloader.h
libltdl/ltdl.c
libltdl/slist.c
libltdl/slist.h

index 91e5b0d7b94371538d7889f94d896bf013d75673..4c4c3a8b6972c85c5f0d1e3917b4b562c68e6477 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/NEWS b/NEWS
index 272475a1c29fe52c52d35aad005fece67fcb0833..435a4a444c8a0f694949214bb083b25bd6092d75 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -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.
 \f
diff --git a/THANKS b/THANKS
index 7675394edb034e8f417a44e2049f6a36b3c0e9b9..4b83df981e359a60a2b08cece70a18e9b93be70d 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -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
index 1700cc019652bf00813f1a22f9481146e3ab8359..6dff74ba4f03ffd6203e09951926695b2d742b71 100644 (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));
 }
index 6bf66b7cf0e73b252334f54a8a8bc5f2525d9efe..9ed117ffcf9552785475a610801ceb5dcea4d941 100644 (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);
 
 
index 27273595cb8dac4b03aa797d0cf6944eacfb2893..4e95b120977ed4979fe04afb522b13d408260f3d 100644 (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;
        }
     }
 
index e24b092daed8cd6c112c458ae3723ba586b18121..06ccf346f8be79cb2f651462ec677ba17433d2d4 100644 (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);
 
-SList *
-slist_new (const void *userdata)
-{
-  SList *node = malloc (sizeof *node);
 
-  if (node)
-    {
-      node->next     = 0;
-      node->userdata = userdata;
-    }
+/* Call DELETE repeatedly on each element of HEAD.
 
-  return node;
-}
+   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_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;
+  return slist;
 }
 
-/* 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. */
+/* 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 *slist)
+{
+  size_t n;
+
+  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 *slist)
+{
+  SList *result = 0;
+  SList *next;
+
+  while (slist)
+    {
+      next             = slist->next;
+      slist->next      = result;
+      result           = slist;
+      slist            = next;
+    }
+
+  return result;
+}
+
+/* Call FOREACH once for each item in SLIST, passing both the item and
+   USERDATA on each call. */
 void *
-slist_find (SList *head, const void *match, SListCompare *find)
+slist_foreach (SList *slist, SListCallback *foreach, void *userdata)
 {
   void *result = 0;
 
-  assert (find);
+  assert (foreach);
 
-  for (; head; head = head->next)
+  while (slist)
     {
-      result = (*find) (head, match);
+      SList *next = slist->next;
+      void *result = (*foreach) (slist, userdata);
+
       if (result)
        break;
+
+      slist = next;
     }
 
   return result;
 }
 
-size_t
-slist_length (SList *head)
+/* 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)
 {
-  size_t n;
+  SList merged, *insert;
 
-  for (n = 0; head; ++n)
-    head = head->next;
+  insert = &merged;
 
-  return n;
+  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_reverse (SList *head)
+slist_sort (SList *slist, SListCompare *compare, void *userdata)
 {
-  SList *result = 0;
-  SList *next;
+  SList *left, *right;
 
-  while (head)
+  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))
     {
-      next             = head->next;
-      head->next       = result;
-      result           = head;
-      head             = next;
+      if (!right || !(right = right->next))
+       break;
+      slist = slist->next;
     }
+  right = slist->next;
+  slist->next = 0;
 
-  return result;
+  /* Sort LEFT and RIGHT, then merge the two.  */
+  return slist_sort_merge (slist_sort (left, compare, userdata),
+                          slist_sort (right, compare, userdata),
+                          compare, userdata);
 }
 
-int
-slist_foreach (SList *head, SListCallback *foreach, const void *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)
 {
-  assert (foreach);
+  SList *item = malloc (sizeof *item);
 
-  for (; head; head = head->next)
-    if ((*foreach) (head, userdata) < 0)
-      return -1;
+  if (item)
+    {
+      item->next     = 0;
+      item->userdata = userdata;
+    }
 
-  return 0;
+  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;
 }
index 737a25ddea2a6855905a4c133f7c500267d19bfb..422a2e2b56db9c93b09788d49357b184c66586d1 100644 (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