libtool-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Coverage for libltdl/slist.c and fallout


From: Ralf Wildenhues
Subject: Coverage for libltdl/slist.c and fallout
Date: Sun, 29 Nov 2009 22:27:09 +0100
User-agent: Mutt/1.5.20 (2009-08-09)

A first step at more libltdl coverage: better coverage for the slist
API.  Notes:

- I did find bugs in slist.c, albeit serious ones only in code not used
elsewhere in libltdl.

- slist_foreach and slist_find are redundant, as they have the same
semantics.

- slist_remove should IMVHO return an SList *, because otherwise there
is no way to avoid a memory leak.  APIs that force memleaks are bad.
(Apart from that, I've never really understood the difference between
boxed and unboxed stuff, basically you have to have a SList header in
order to put something in a list, period.  But I didn't want to mangle
the code beyond bug fixing really.)

- In the end I grew really lazy and added the new test to the old
testsuite: that seemed the easiest way to integrate and catch all the
compilation and include flags from toplevel Makefile.am in order to
build and use a separate slist.o object.  If this is not ok with you,
then please complain loudly.


So I have three patches I would like to commit as part of this.
The first one adds the test and fixes slist.c, the second one is only
stylistic and uses NULL instead of 0 throughout slist.c, and the third
one changes our public APIs lt_dlloader_remove and lt_dlloader_find to
accept `const char *' arguments instead of `char *': that's what fits
the purpose best, and what we document in the manual.  I'm not quite
sure whether the last one constitutes a compatible API change or only
a revision change, so versioning bump is still missing.

Review appreciated.

Thanks,
Ralf

    Test and fix slist.c.
    
    * libltdl/libltdl/slist.h: Include stddef.h, for size_t.
    (slist_remove): Return pointer to SList, not void.
    * libltdl/slist.c: Include stdlib.h, for malloc and free.
    (slist_remove): Adjust prototype as above.
    (slist_sort): Do not loop forever on one-item list.
    * tests/test-slist.c: New file.
    * Makefile.am (COMMON_TESTS): Add tests/test-slist.
    (check_PROGRAMS, tests_test_slist_SOURCES): New variables.

diff --git a/Makefile.am b/Makefile.am
index ecc54f8..a1097c7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -672,6 +672,7 @@ COMMON_TESTS = \
        tests/sh.test \
        tests/suffix.test \
        tests/tagtrace.test \
+       tests/test-slist \
        tests/cdemo-static.test \
        tests/cdemo-static-make.test \
        tests/cdemo-static-exec.test \
@@ -759,6 +760,11 @@ COMMON_TESTS = \
        tests/cdemo-undef-make.test \
        tests/cdemo-undef-exec.test
 
+check_PROGRAMS = tests/test-slist
+tests_test_slist_SOURCES = \
+       tests/test-slist.c \
+       libltdl/slist.c
+
 tests/cdemo-undef-exec.log:    tests/cdemo-undef-make.log
 tests/cdemo-undef-make.log:    tests/cdemo-undef.log
 tests/cdemo-undef.log: @ORDER@ tests/cdemo-shared-exec.log
diff --git a/libltdl/libltdl/slist.h b/libltdl/libltdl/slist.h
index e4b7ead..4d56509 100644
--- a/libltdl/libltdl/slist.h
+++ b/libltdl/libltdl/slist.h
@@ -1,6 +1,6 @@
 /* slist.h -- generalised singly linked lists
 
-   Copyright (C) 2000, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2004, 2009 Free Software Foundation, Inc.
    Written by Gary V. Vaughan, 2000
 
    NOTE: The canonical source of this file is maintained with the
@@ -48,6 +48,8 @@ or obtained by writing to the Free Software Foundation, Inc.,
 #  define LT_SCOPE
 #endif
 
+#include <stddef.h>
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -65,7 +67,7 @@ LT_SCOPE SList *slist_concat  (SList *head, SList *tail);
 LT_SCOPE SList *slist_cons     (SList *item, SList *slist);
 
 LT_SCOPE SList *slist_delete   (SList *slist, void (*delete_fct) (void *item));
-LT_SCOPE void *        slist_remove    (SList **phead, SListCallback *find,
+LT_SCOPE SList *slist_remove   (SList **phead, SListCallback *find,
                                 void *matchdata);
 LT_SCOPE SList *slist_reverse  (SList *slist);
 LT_SCOPE SList *slist_sort     (SList *slist, SListCompare *compare,
diff --git a/libltdl/slist.c b/libltdl/slist.c
index c99f399..25906a4 100644
--- a/libltdl/slist.c
+++ b/libltdl/slist.c
@@ -1,6 +1,6 @@
 /* slist.c -- generalised singly linked lists
 
-   Copyright (C) 2000, 2004, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2004, 2007, 2008, 2009 Free Software Foundation, Inc.
    Written by Gary V. Vaughan, 2000
 
    NOTE: The canonical source of this file is maintained with the
@@ -32,6 +32,7 @@ or obtained by writing to the Free Software Foundation, Inc.,
 
 #include "slist.h"
 #include <stddef.h>
+#include <stdlib.h>
 
 static SList * slist_sort_merge    (SList *left, SList *right,
                                     SListCompare *compare, void *userdata);
@@ -73,7 +74,7 @@ slist_delete (SList *head, void (*delete_fct) (void *item))
            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 *
 slist_remove (SList **phead, SListCallback *find, void *matchdata)
 {
   SList *stale = 0;
@@ -107,7 +108,7 @@ slist_remove (SList **phead, SListCallback *find, void 
*matchdata)
        }
     }
 
-  return result;
+  return (SList *) result;
 }
 
 /* Call FIND repeatedly with each element of SLIST and MATCHDATA, until
@@ -314,6 +315,9 @@ slist_sort (SList *slist, SListCompare *compare, void 
*userdata)
   left = slist;
   right = slist->next;
 
+  if (!right)
+    return left;
+
   /* 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))
diff --git a/tests/test-slist.c b/tests/test-slist.c
new file mode 100644
index 0000000..40279a4
--- /dev/null
+++ b/tests/test-slist.c
@@ -0,0 +1,130 @@
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdio.h>
+#include "slist.h"
+
+void *find_string (SList *item, void *data)
+{
+  if (data != NULL && !strcmp ((const char *) item->userdata, (const char 
*)data))
+    return item;
+  else
+    return NULL;
+}
+
+void boxed_delete (void *item)
+{
+  free (slist_unbox ((SList *) item));
+}
+
+void *print_item (SList *item, void *userdata)
+{
+  userdata = userdata; /* unused */
+  printf ("%s\n", (const char*)item->userdata);
+  return NULL;
+}
+
+int list_compare (const SList *item1, const SList *item2, void *userdata)
+{
+  userdata = userdata;
+  return strcmp ((const char *) item1->userdata, (const char 
*)item2->userdata);
+}
+
+int main ()
+{
+  int i;
+  SList *empty_list = NULL, *list = NULL, *item, *list_save;
+  char *data = NULL;
+
+  /* slist_cons */
+  list = slist_cons (NULL, NULL);
+
+  for (i=0; i < 10; ++i) {
+    data = (char *) malloc (42);
+    assert (data);
+    sprintf (data, "foo%d", i);
+    list = slist_cons (slist_box (data), list);
+  }
+  list_save = list;
+  list = slist_cons (NULL, list);
+  assert (list == list_save);
+
+
+  /* slist_find */
+  assert (slist_find (NULL, find_string, (void *) "whatever") == NULL);
+  assert (slist_find (empty_list, find_string, (void *) "whatever") == NULL);
+  assert (slist_find (list, find_string, (void *) "foo10") == NULL);
+  item = (SList *) slist_find (list, find_string, (void *) "foo1");
+  assert (item != NULL);
+  assert (!strcmp ((const char *) item->userdata, "foo1"));
+
+  item = slist_nth (list, 10);
+  assert (item != NULL && !strcmp ((const char *) item->userdata, "foo0"));
+
+  puts ("list as inserted:");
+  slist_foreach (list, print_item, NULL);
+  puts ("reversed list:");
+  list = slist_reverse (list);
+  slist_foreach (list, print_item, NULL);
+
+  item = slist_nth (list, 1);
+  assert (item != NULL && !strcmp ((const char *) item->userdata, "foo0"));
+
+  assert (10 == slist_length (list));
+
+  /* slist_tail is the second item, not the last one */
+  item = slist_tail (list);
+  assert (item != NULL && !strcmp ((const char *) item->userdata, "foo1"));
+
+  assert (slist_tail (slist_nth (list, 10)) == NULL);
+
+  /* slist_sort and implicitly, slist_sort_merge */
+  assert (slist_sort (NULL, list_compare, NULL) == NULL);
+  list = slist_sort (list, list_compare, NULL);
+  puts ("list after no-op sort:");
+  slist_foreach (list, print_item, NULL);
+
+  list = slist_reverse (list);
+  puts ("reversed list:");
+  slist_foreach (list, print_item, NULL);
+  puts ("sorting reversed list:");
+  list = slist_sort (list, list_compare, NULL);
+  slist_foreach (list, print_item, NULL);
+
+  /* slist_remove */
+  assert (slist_remove (NULL, find_string, NULL) == NULL);
+  assert (slist_remove (&empty_list, find_string, NULL) == NULL);
+
+  list_save = list;
+  assert (slist_remove (&list, find_string, NULL) == NULL);
+  assert (list_save == list);
+
+  /* remove entries: middle, last, first, not present */
+  /* slist_reverse above has left us with increasing order */
+  list_save = list;
+  item = slist_remove (&list, find_string, (void *) "foo5");
+  assert (list_save == list);
+  assert (item != NULL && !strcmp (data = (char *) slist_unbox (item), 
"foo5"));
+  free (data);
+
+  list_save = list;
+  item = slist_remove (&list, find_string, (void *) "foo9");
+  assert (list_save == list);
+  assert (item != NULL && !strcmp (data = (char *) slist_unbox (item), 
"foo9"));
+  free (data);
+
+  list_save = list;
+  item = slist_remove (&list, find_string, (void *) "foo0");
+  assert (list_save != list);
+  assert (item != NULL && !strcmp (data = (char *) slist_unbox (item), 
"foo0"));
+  free (data);
+
+  list_save = list;
+  item = slist_remove (&list, find_string, (void *) "foo5");
+  assert (list_save == list);
+  assert (item == NULL);
+
+  assert (slist_delete (list, boxed_delete) == NULL);
+  return 0;
+}




    Use NULL instead of 0 in slist.c.
    
    * libltdl/slist.c (slist_delete, slist_remove, slist_find)
    (slist_reverse, slist_foreach, slist_sort, slist_box)
    (slist_unbox): Use NULL for pointers throughout.

diff --git a/libltdl/slist.c b/libltdl/slist.c
index 25906a4..07a2e10 100644
--- a/libltdl/slist.c
+++ b/libltdl/slist.c
@@ -62,7 +62,7 @@ slist_delete (SList *head, void (*delete_fct) (void *item))
       head = next;
     }
 
-  return 0;
+  return NULL;
 }
 
 /* Call FIND repeatedly with MATCHDATA and each item of *PHEAD, until
@@ -77,13 +77,13 @@ slist_delete (SList *head, void (*delete_fct) (void *item))
 SList *
 slist_remove (SList **phead, SListCallback *find, void *matchdata)
 {
-  SList *stale = 0;
-  void *result = 0;
+  SList *stale = NULL;
+  void *result = NULL;
 
   assert (find);
 
   if (!phead || !*phead)
-    return 0;
+    return NULL;
 
   /* Does the head of the passed list match? */
   result = (*find) (*phead, matchdata);
@@ -117,7 +117,7 @@ slist_remove (SList **phead, SListCallback *find, void 
*matchdata)
 void *
 slist_find (SList *slist, SListCallback *find, void *matchdata)
 {
-  void *result = 0;
+  void *result = NULL;
 
   assert (find);
 
@@ -222,7 +222,7 @@ slist_length (SList *slist)
 SList *
 slist_reverse (SList *slist)
 {
-  SList *result = 0;
+  SList *result = NULL;
   SList *next;
 
   while (slist)
@@ -241,7 +241,7 @@ slist_reverse (SList *slist)
 void *
 slist_foreach (SList *slist, SListCallback *foreach, void *userdata)
 {
-  void *result = 0;
+  void *result = NULL;
 
   assert (foreach);
 
@@ -327,7 +327,7 @@ slist_sort (SList *slist, SListCompare *compare, void 
*userdata)
       slist = slist->next;
     }
   right = slist->next;
-  slist->next = 0;
+  slist->next = NULL;
 
   /* Sort LEFT and RIGHT, then merge the two.  */
   return slist_sort_merge (slist_sort (left, compare, userdata),
@@ -354,7 +354,7 @@ slist_box (const void *userdata)
 
   if (item)
     {
-      item->next     = 0;
+      item->next     = NULL;
       item->userdata = userdata;
     }
 
@@ -365,7 +365,7 @@ slist_box (const void *userdata)
 void *
 slist_unbox (SList *item)
 {
-  void *userdata = 0;
+  void *userdata = NULL;
 
   if (item)
     {



    lt_dlloader_remove and lt_dlloader_find accept const arguments.
    
    * libltdl/lt_dlloader.c (lt_dlloader_remove, lt_dlloader_find):
    Accept `const char *' arguments, as documented.  Cast them to
    `void *' for the slist machinery.
    * libltdl/libltdl/lt_dlloader.h: Adjust prototypes.

diff --git a/libltdl/libltdl/lt_dlloader.h b/libltdl/libltdl/lt_dlloader.h
index ae131fa..589fd0d 100644
--- a/libltdl/libltdl/lt_dlloader.h
+++ b/libltdl/libltdl/lt_dlloader.h
@@ -73,8 +73,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      (char *name);
-LT_SCOPE const lt_dlvtable *lt_dlloader_find   (char *name);
+LT_SCOPE lt_dlvtable * lt_dlloader_remove      (const char *name);
+LT_SCOPE const lt_dlvtable *lt_dlloader_find   (const char *name);
 LT_SCOPE const lt_dlvtable *lt_dlloader_get    (lt_dlloader loader);
 
 
diff --git a/libltdl/lt_dlloader.c b/libltdl/lt_dlloader.c
index 4e66a6c..2c99a22 100644
--- a/libltdl/lt_dlloader.c
+++ b/libltdl/lt_dlloader.c
@@ -150,7 +150,7 @@ lt_dlloader_get     (lt_dlloader loader)
    modules need this loader; in either case, the loader list is not
    changed if NULL is returned.  */
 lt_dlvtable *
-lt_dlloader_remove (char *name)
+lt_dlloader_remove (const char *name)
 {
   const lt_dlvtable *  vtable  = lt_dlloader_find (name);
   static const char    id_string[] = "lt_dlloader_remove";
@@ -199,12 +199,12 @@ lt_dlloader_remove (char *name)
 
   /* If we got this far, remove the loader from our global list.  */
   return (lt_dlvtable *)
-      slist_unbox ((SList *) slist_remove (&loaders, loader_callback, name));
+      slist_unbox ((SList *) slist_remove (&loaders, loader_callback, (void *) 
name));
 }
 
 
 const lt_dlvtable *
-lt_dlloader_find (char *name)
+lt_dlloader_find (const char *name)
 {
-  return lt_dlloader_get (slist_find (loaders, loader_callback, name));
+  return lt_dlloader_get (slist_find (loaders, loader_callback, (void *) 
name));
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]