changeset 12444:29d240cb21b2

Move the malloc checking from module 'oset' to new module 'xoset'.
author Bruno Haible <bruno@clisp.org>
date Sun, 13 Dec 2009 20:27:44 +0100
parents 3a97f22a64eb
children a8c91b846640
files ChangeLog NEWS lib/gl_anytree_oset.h lib/gl_anytreehash_list1.h lib/gl_array_oset.c lib/gl_avltree_oset.c lib/gl_oset.c lib/gl_oset.h lib/gl_rbtree_oset.c lib/gl_xoset.c lib/gl_xoset.h modules/array-oset modules/avltree-oset modules/avltree-oset-tests modules/rbtree-oset modules/rbtree-oset-tests modules/xoset tests/test-array_oset.c tests/test-avltree_oset.c tests/test-rbtree_oset.c
diffstat 20 files changed, 357 insertions(+), 101 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,60 @@
+2009-12-13  Bruno Haible  <bruno@clisp.org>
+
+	Move the malloc checking from module 'oset' to new module 'xoset'.
+	* modules/xoset: New file.
+	* lib/gl_xoset.h: New file.
+	* lib/gl_xoset.c: New file.
+	* lib/gl_oset.h (gl_oset_create_empty, gl_oset_add): Disable
+	declarations.
+	(gl_oset_nx_create_empty, gl_oset_nx_add): New declarations.
+	(struct gl_oset_implementation): Rename and change methods accordingly.
+	(gl_oset_nx_create_empty): Renamed from gl_oset_create_empty.
+	(gl_oset_nx_add): Renamed from gl_oset_add. Change return type to
+	'int'. Mark as __warn_unused_result__.
+	* lib/gl_oset.c (gl_oset_nx_create_empty): Renamed from
+	gl_oset_create_empty.
+	(gl_oset_nx_add): Renamed from gl_oset_add. Change return type to
+	'int'.
+	* lib/gl_array_oset.c: Don't include xalloc.h.
+	(gl_array_nx_create_empty): Renamed from gl_array_create_empty. Use
+	malloc, not xmalloc.
+	(grow): Change return type to 'int'. Don't call xalloc_die.
+	(gl_array_nx_add_at): Renamed from gl_array_add_at. Change return type
+	to 'int'.
+	(gl_array_nx_add): Renamed from gl_array_add. Change return type to
+	'int'.
+	(gl_array_oset_implementation): Update.
+	* lib/gl_anytree_oset.h (gl_tree_nx_create_empty): Renamed from
+	gl_tree_create_empty.
+	(gl_tree_nx_add): Renamed from gl_tree_add. Change return type to
+	'int'.
+	* lib/gl_avltree_oset.c: Don't include xalloc.h.
+	(gl_tree_nx_add_first): Renamed from gl_tree_add_first. Use malloc, not
+	xmalloc.
+	(gl_tree_nx_add_before): Renamed from gl_tree_add_before. Use malloc,
+	not xmalloc.
+	(gl_tree_nx_add_after): Renamed from gl_tree_add_after. Use malloc, not
+	xmalloc.
+	(gl_avltree_oset_implementation): Update.
+	* lib/gl_rbtree_oset.c: Don't include xalloc.h.
+	(gl_tree_nx_add_first): Renamed from gl_tree_add_first. Use malloc, not
+	xmalloc.
+	(gl_tree_nx_add_before): Renamed from gl_tree_add_before. Use malloc,
+	not xmalloc.
+	(gl_tree_nx_add_after): Renamed from gl_tree_add_after. Use malloc, not
+	xmalloc.
+	(gl_rbtree_oset_implementation): Update.
+	* modules/array-oset (Depends-on): Remove xalloc.
+	* modules/avltree-oset (Depends-on): Likewise.
+	* modules/rbtree-oset (Depends-on): Likewise.
+	* tests/test-array_oset.c: Use gl_oset_nx_* functions where possible.
+	* tests/test-avltree_oset.c: Likewise.
+	* tests/test-rbtree_oset.c: Likewise.
+	* lib/gl_anytreehash_list1.h (add_to_bucket): Likewise.
+	* modules/avltree-oset-tests (Makefile.am): Don't link with @LIBINTL@.
+	* modules/rbtree-oset-tests (Makefile.am): Likewise.
+	* NEWS: Mention the change.
+
 2009-12-05  Alfred M. Szmidt  <ams@gnu.org>
 
 	maint.mk: allow a project to override release-prep commands
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,11 @@
 
 Date        Modules         Changes
 
+2009-12-13  oset            The module does not define functions any more that
+                            call xalloc_die() in out-of-memory situations.
+                            Use module 'xoset' and include file "gl_xoset.h"
+                            instead.
+
 2009-12-10  *               Most source code files have been converted to
                             indentation by spaces (rather than tabs). Patches
                             of gnulib source code needs to be updated.
--- a/lib/gl_anytree_oset.h
+++ b/lib/gl_anytree_oset.h
@@ -1,5 +1,5 @@
 /* Ordered set data type implemented by a binary tree.
-   Copyright (C) 2006-2007 Free Software Foundation, Inc.
+   Copyright (C) 2006-2007, 2009 Free Software Foundation, Inc.
    Written by Bruno Haible <bruno@clisp.org>, 2006.
 
    This program is free software: you can redistribute it and/or modify
@@ -28,11 +28,15 @@
 typedef iterstack_item_t iterstack_t[MAXHEIGHT];
 
 static gl_oset_t
-gl_tree_create_empty (gl_oset_implementation_t implementation,
-                      gl_setelement_compar_fn compar_fn,
-                      gl_setelement_dispose_fn dispose_fn)
+gl_tree_nx_create_empty (gl_oset_implementation_t implementation,
+                         gl_setelement_compar_fn compar_fn,
+                         gl_setelement_dispose_fn dispose_fn)
 {
-  struct gl_oset_impl *set = XMALLOC (struct gl_oset_impl);
+  struct gl_oset_impl *set =
+    (struct gl_oset_impl *) malloc (sizeof (struct gl_oset_impl));
+
+  if (set == NULL)
+    return NULL;
 
   set->base.vtable = implementation;
   set->base.compar_fn = compar_fn;
@@ -132,15 +136,16 @@
   return NULL;
 }
 
-static bool
-gl_tree_add (gl_oset_t set, const void *elt)
+static int
+gl_tree_nx_add (gl_oset_t set, const void *elt)
 {
   gl_setelement_compar_fn compar;
   gl_oset_node_t node = set->root;
 
   if (node == NULL)
     {
-      gl_tree_add_first (set, elt);
+      if (gl_tree_nx_add_first (set, elt) == NULL)
+        return -1;
       return true;
     }
 
@@ -157,7 +162,8 @@
         {
           if (node->right == NULL)
             {
-              gl_tree_add_after (set, node, elt);
+              if (gl_tree_nx_add_after (set, node, elt) == NULL)
+                return -1;
               return true;
             }
           node = node->right;
@@ -166,7 +172,8 @@
         {
           if (node->left == NULL)
             {
-              gl_tree_add_before (set, node, elt);
+              if (gl_tree_nx_add_before (set, node, elt) == NULL)
+                return -1;
               return true;
             }
           node = node->left;
--- a/lib/gl_anytreehash_list1.h
+++ b/lib/gl_anytreehash_list1.h
@@ -1,5 +1,5 @@
 /* Sequential list data type implemented by a hash table with a binary tree.
-   Copyright (C) 2006-2007 Free Software Foundation, Inc.
+   Copyright (C) 2006-2007, 2009 Free Software Foundation, Inc.
    Written by Bruno Haible <bruno@clisp.org>, 2006.
 
    This program is free software: you can redistribute it and/or modify
@@ -101,8 +101,8 @@
 
 /* Add a node to the hash table structure.
    If duplicates are allowed, this function performs in average time
-   O((log n)^2): gl_oset_add may need to add an element to an ordered set of
-   size O(n), needing O(log n) comparison function calls.  The comparison
+   O((log n)^2): gl_oset_nx_add may need to add an element to an ordered set
+   of size O(n), needing O(log n) comparison function calls.  The comparison
    function is compare_by_position, which is O(log n) worst-case.
    If duplicates are forbidden, this function is O(1).  */
 static void
@@ -134,7 +134,8 @@
                     {
                       /* Found already multiple nodes with the same value.
                          Add the new_node to it.  */
-                      gl_oset_add (nodes, new_node);
+                      if (gl_oset_nx_add (nodes, new_node) < 0)
+                        xalloc_die ();
                       return;
                     }
                 }
@@ -150,11 +151,15 @@
                       struct gl_multiple_nodes *multi_entry;
 
                       nodes =
-                        gl_oset_create_empty (OSET_TREE_FLAVOR,
-                                              compare_by_position, NULL);
+                        gl_oset_nx_create_empty (OSET_TREE_FLAVOR,
+                                                 compare_by_position, NULL);
+                      if (nodes == NULL)
+                        xalloc_die ();
 
-                      gl_oset_add (nodes, node);
-                      gl_oset_add (nodes, new_node);
+                      if (gl_oset_nx_add (nodes, node) < 0)
+                        xalloc_die ();
+                      if (gl_oset_nx_add (nodes, new_node) < 0)
+                        xalloc_die ();
 
                       multi_entry = XMALLOC (struct gl_multiple_nodes);
                       multi_entry->h.hash_next = entry->hash_next;
--- a/lib/gl_array_oset.c
+++ b/lib/gl_array_oset.c
@@ -1,5 +1,5 @@
 /* Ordered set data type implemented by an array.
-   Copyright (C) 2006-2007 Free Software Foundation, Inc.
+   Copyright (C) 2006-2007, 2009 Free Software Foundation, Inc.
    Written by Bruno Haible <bruno@clisp.org>, 2006.
 
    This program is free software: you can redistribute it and/or modify
@@ -22,8 +22,6 @@
 
 #include <stdlib.h>
 
-#include "xalloc.h"
-
 /* Checked size_t computations.  */
 #include "xsize.h"
 
@@ -41,11 +39,15 @@
 };
 
 static gl_oset_t
-gl_array_create_empty (gl_oset_implementation_t implementation,
-                       gl_setelement_compar_fn compar_fn,
-                       gl_setelement_dispose_fn dispose_fn)
+gl_array_nx_create_empty (gl_oset_implementation_t implementation,
+                          gl_setelement_compar_fn compar_fn,
+                          gl_setelement_dispose_fn dispose_fn)
 {
-  struct gl_oset_impl *set = XMALLOC (struct gl_oset_impl);
+  struct gl_oset_impl *set =
+    (struct gl_oset_impl *) malloc (sizeof (struct gl_oset_impl));
+
+  if (set == NULL)
+    return NULL;
 
   set->base.vtable = implementation;
   set->base.compar_fn = compar_fn;
@@ -155,8 +157,9 @@
   return false;
 }
 
-/* Ensure that set->allocated > set->count.  */
-static void
+/* Ensure that set->allocated > set->count.
+   Return 0 upon success, -1 upon out-of-memory.  */
+static int
 grow (gl_oset_t set)
 {
   size_t new_allocated;
@@ -168,31 +171,35 @@
   memory_size = xtimes (new_allocated, sizeof (const void *));
   if (size_overflow_p (memory_size))
     /* Overflow, would lead to out of memory.  */
-    xalloc_die ();
-  memory = (const void **) xrealloc (set->elements, memory_size);
+    return -1;
+  memory = (const void **) realloc (set->elements, memory_size);
   if (memory == NULL)
     /* Out of memory.  */
-    xalloc_die ();
+    return -1;
   set->elements = memory;
   set->allocated = new_allocated;
+  return 0;
 }
 
 /* Add the given element ELT at the given position,
-   0 <= position <= gl_oset_size (set).  */
-static inline void
-gl_array_add_at (gl_oset_t set, size_t position, const void *elt)
+   0 <= position <= gl_oset_size (set).
+   Return 1 upon success, -1 upon out-of-memory.  */
+static inline int
+gl_array_nx_add_at (gl_oset_t set, size_t position, const void *elt)
 {
   size_t count = set->count;
   const void **elements;
   size_t i;
 
   if (count == set->allocated)
-    grow (set);
+    if (grow (set) < 0)
+      return -1;
   elements = set->elements;
   for (i = count; i > position; i--)
     elements[i] = elements[i - 1];
   elements[position] = elt;
   set->count = count + 1;
+  return 1;
 }
 
 /* Remove the element at the given position,
@@ -212,8 +219,8 @@
   set->count = count - 1;
 }
 
-static bool
-gl_array_add (gl_oset_t set, const void *elt)
+static int
+gl_array_nx_add (gl_oset_t set, const void *elt)
 {
   size_t count = set->count;
   size_t low = 0;
@@ -244,8 +251,7 @@
         }
       while (low < high);
     }
-  gl_array_add_at (set, low, elt);
-  return true;
+  return gl_array_nx_add_at (set, low, elt);
 }
 
 static bool
@@ -338,11 +344,11 @@
 
 const struct gl_oset_implementation gl_array_oset_implementation =
   {
-    gl_array_create_empty,
+    gl_array_nx_create_empty,
     gl_array_size,
     gl_array_search,
     gl_array_search_atleast,
-    gl_array_add,
+    gl_array_nx_add,
     gl_array_remove,
     gl_array_free,
     gl_array_iterator,
--- a/lib/gl_avltree_oset.c
+++ b/lib/gl_avltree_oset.c
@@ -1,5 +1,5 @@
 /* Ordered set data type implemented by a binary tree.
-   Copyright (C) 2006-2007 Free Software Foundation, Inc.
+   Copyright (C) 2006-2007, 2009 Free Software Foundation, Inc.
    Written by Bruno Haible <bruno@clisp.org>, 2006.
 
    This program is free software: you can redistribute it and/or modify
@@ -22,8 +22,6 @@
 
 #include <stdlib.h>
 
-#include "xalloc.h"
-
 /* An AVL tree is a binary tree where
    1. The height of each node is calculated as
         heightof(node) = 1 + max (heightof(node.left), heightof(node.right)).
@@ -306,10 +304,14 @@
 }
 
 static gl_oset_node_t
-gl_tree_add_first (gl_oset_t set, const void *elt)
+gl_tree_nx_add_first (gl_oset_t set, const void *elt)
 {
   /* Create new node.  */
-  gl_oset_node_t new_node = XMALLOC (struct gl_oset_node_impl);
+  gl_oset_node_t new_node =
+    (struct gl_oset_node_impl *) malloc (sizeof (struct gl_oset_node_impl));
+
+  if (new_node == NULL)
+    return NULL;
 
   new_node->left = NULL;
   new_node->right = NULL;
@@ -343,12 +345,16 @@
 }
 
 static gl_oset_node_t
-gl_tree_add_before (gl_oset_t set, gl_oset_node_t node, const void *elt)
+gl_tree_nx_add_before (gl_oset_t set, gl_oset_node_t node, const void *elt)
 {
   /* Create new node.  */
-  gl_oset_node_t new_node = XMALLOC (struct gl_oset_node_impl);
+  gl_oset_node_t new_node =
+    (struct gl_oset_node_impl *) malloc (sizeof (struct gl_oset_node_impl));
   bool height_inc;
 
+  if (new_node == NULL)
+    return NULL;
+
   new_node->left = NULL;
   new_node->right = NULL;
   new_node->balance = 0;
@@ -380,12 +386,16 @@
 }
 
 static gl_oset_node_t
-gl_tree_add_after (gl_oset_t set, gl_oset_node_t node, const void *elt)
+gl_tree_nx_add_after (gl_oset_t set, gl_oset_node_t node, const void *elt)
 {
   /* Create new node.  */
-  gl_oset_node_t new_node = XMALLOC (struct gl_oset_node_impl);
+  gl_oset_node_t new_node =
+    (struct gl_oset_node_impl *) malloc (sizeof (struct gl_oset_node_impl));
   bool height_inc;
 
+  if (new_node == NULL)
+    return NULL;
+
   new_node->left = NULL;
   new_node->right = NULL;
   new_node->balance = 0;
@@ -560,11 +570,11 @@
 
 const struct gl_oset_implementation gl_avltree_oset_implementation =
   {
-    gl_tree_create_empty,
+    gl_tree_nx_create_empty,
     gl_tree_size,
     gl_tree_search,
     gl_tree_search_atleast,
-    gl_tree_add,
+    gl_tree_nx_add,
     gl_tree_remove,
     gl_tree_oset_free,
     gl_tree_iterator,
--- a/lib/gl_oset.c
+++ b/lib/gl_oset.c
@@ -27,11 +27,12 @@
    Use #define to avoid a warning because of extern vs. static.  */
 
 gl_oset_t
-gl_oset_create_empty (gl_oset_implementation_t implementation,
-                      gl_setelement_compar_fn compar_fn,
-                      gl_setelement_dispose_fn dispose_fn)
+gl_oset_nx_create_empty (gl_oset_implementation_t implementation,
+                         gl_setelement_compar_fn compar_fn,
+                         gl_setelement_dispose_fn dispose_fn)
 {
-  return implementation->create_empty (implementation, compar_fn, dispose_fn);
+  return implementation->nx_create_empty (implementation, compar_fn,
+                                          dispose_fn);
 }
 
 size_t
@@ -55,10 +56,10 @@
          ->search_atleast (set, threshold_fn, threshold, eltp);
 }
 
-bool
-gl_oset_add (gl_oset_t set, const void *elt)
+int
+gl_oset_nx_add (gl_oset_t set, const void *elt)
 {
-  return ((const struct gl_oset_impl_base *) set)->vtable->add (set, elt);
+  return ((const struct gl_oset_impl_base *) set)->vtable->nx_add (set, elt);
 }
 
 bool
--- a/lib/gl_oset.h
+++ b/lib/gl_oset.h
@@ -89,9 +89,15 @@
    IMPLEMENTATION is one of GL_ARRAY_OSET, GL_AVLTREE_OSET, GL_RBTREE_OSET.
    COMPAR_FN is an element comparison function or NULL.
    DISPOSE_FN is an element disposal function or NULL.  */
+#if 0 /* declared in gl_xoset.h */
 extern gl_oset_t gl_oset_create_empty (gl_oset_implementation_t implementation,
                                        gl_setelement_compar_fn compar_fn,
                                        gl_setelement_dispose_fn dispose_fn);
+#endif
+/* Likewise.  Return NULL upon out-of-memory.  */
+extern gl_oset_t gl_oset_nx_create_empty (gl_oset_implementation_t implementation,
+                                          gl_setelement_compar_fn compar_fn,
+                                          gl_setelement_dispose_fn dispose_fn);
 
 /* Return the current number of elements in an ordered set.  */
 extern size_t gl_oset_size (gl_oset_t set);
@@ -111,8 +117,16 @@
                                     const void **eltp);
 
 /* Add an element to an ordered set.
-   Return true if it was not already in the set and added.  */
+   Return true if it was not already in the set and added, false otherwise.  */
+#if 0 /* declared in gl_xoset.h */
 extern bool gl_oset_add (gl_oset_t set, const void *elt);
+#endif
+/* Likewise.  Return -1 upon out-of-memory.  */
+extern int gl_oset_nx_add (gl_oset_t set, const void *elt)
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+  __attribute__ ((__warn_unused_result__))
+#endif
+  ;
 
 /* Remove an element from an ordered set.
    Return true if it was found and removed.  */
@@ -159,15 +173,15 @@
 struct gl_oset_implementation
 {
   /* gl_oset_t functions.  */
-  gl_oset_t (*create_empty) (gl_oset_implementation_t implementation,
-                             gl_setelement_compar_fn compar_fn,
-                             gl_setelement_dispose_fn dispose_fn);
+  gl_oset_t (*nx_create_empty) (gl_oset_implementation_t implementation,
+                                gl_setelement_compar_fn compar_fn,
+                                gl_setelement_dispose_fn dispose_fn);
   size_t (*size) (gl_oset_t set);
   bool (*search) (gl_oset_t set, const void *elt);
   bool (*search_atleast) (gl_oset_t set,
                           gl_setelement_threshold_fn threshold_fn,
                           const void *threshold, const void **eltp);
-  bool (*add) (gl_oset_t set, const void *elt);
+  int (*nx_add) (gl_oset_t set, const void *elt);
   bool (*remove_elt) (gl_oset_t set, const void *elt);
   void (*oset_free) (gl_oset_t set);
   /* gl_oset_iterator_t functions.  */
@@ -189,13 +203,14 @@
    struct gl_oset_implementation.
    Use #define to avoid a warning because of extern vs. static.  */
 
-# define gl_oset_create_empty gl_oset_create_empty_inline
+# define gl_oset_nx_create_empty gl_oset_nx_create_empty_inline
 static inline gl_oset_t
-gl_oset_create_empty (gl_oset_implementation_t implementation,
-                      gl_setelement_compar_fn compar_fn,
-                      gl_setelement_dispose_fn dispose_fn)
+gl_oset_nx_create_empty (gl_oset_implementation_t implementation,
+                         gl_setelement_compar_fn compar_fn,
+                         gl_setelement_dispose_fn dispose_fn)
 {
-  return implementation->create_empty (implementation, compar_fn, dispose_fn);
+  return implementation->nx_create_empty (implementation, compar_fn,
+                                          dispose_fn);
 }
 
 # define gl_oset_size gl_oset_size_inline
@@ -222,11 +237,11 @@
          ->search_atleast (set, threshold_fn, threshold, eltp);
 }
 
-# define gl_oset_add gl_oset_add_inline
-static inline bool
-gl_oset_add (gl_oset_t set, const void *elt)
+# define gl_oset_nx_add gl_oset_nx_add_inline
+static inline int
+gl_oset_nx_add (gl_oset_t set, const void *elt)
 {
-  return ((const struct gl_oset_impl_base *) set)->vtable->add (set, elt);
+  return ((const struct gl_oset_impl_base *) set)->vtable->nx_add (set, elt);
 }
 
 # define gl_oset_remove gl_oset_remove_inline
--- a/lib/gl_rbtree_oset.c
+++ b/lib/gl_rbtree_oset.c
@@ -1,5 +1,5 @@
 /* Ordered set data type implemented by a binary tree.
-   Copyright (C) 2006-2007 Free Software Foundation, Inc.
+   Copyright (C) 2006-2007, 2009 Free Software Foundation, Inc.
    Written by Bruno Haible <bruno@clisp.org>, 2006.
 
    This program is free software: you can redistribute it and/or modify
@@ -22,8 +22,6 @@
 
 #include <stdlib.h>
 
-#include "xalloc.h"
-
 /* A red-black tree is a binary tree where every node is colored black or
    red such that
    1. The root is black.
@@ -538,10 +536,14 @@
 }
 
 static gl_oset_node_t
-gl_tree_add_first (gl_oset_t set, const void *elt)
+gl_tree_nx_add_first (gl_oset_t set, const void *elt)
 {
   /* Create new node.  */
-  gl_oset_node_t new_node = XMALLOC (struct gl_oset_node_impl);
+  gl_oset_node_t new_node =
+    (struct gl_oset_node_impl *) malloc (sizeof (struct gl_oset_node_impl));
+
+  if (new_node == NULL)
+    return NULL;
 
   new_node->left = NULL;
   new_node->right = NULL;
@@ -573,10 +575,14 @@
 }
 
 static gl_oset_node_t
-gl_tree_add_before (gl_oset_t set, gl_oset_node_t node, const void *elt)
+gl_tree_nx_add_before (gl_oset_t set, gl_oset_node_t node, const void *elt)
 {
   /* Create new node.  */
-  gl_oset_node_t new_node = XMALLOC (struct gl_oset_node_impl);
+  gl_oset_node_t new_node =
+    (struct gl_oset_node_impl *) malloc (sizeof (struct gl_oset_node_impl));
+
+  if (new_node == NULL)
+    return NULL;
 
   new_node->left = NULL;
   new_node->right = NULL;
@@ -601,10 +607,14 @@
 }
 
 static gl_oset_node_t
-gl_tree_add_after (gl_oset_t set, gl_oset_node_t node, const void *elt)
+gl_tree_nx_add_after (gl_oset_t set, gl_oset_node_t node, const void *elt)
 {
   /* Create new node.  */
-  gl_oset_node_t new_node = XMALLOC (struct gl_oset_node_impl);
+  gl_oset_node_t new_node =
+    (struct gl_oset_node_impl *) malloc (sizeof (struct gl_oset_node_impl));
+
+  if (new_node == NULL)
+    return NULL;
 
   new_node->left = NULL;
   new_node->right = NULL;
@@ -791,11 +801,11 @@
 
 const struct gl_oset_implementation gl_rbtree_oset_implementation =
   {
-    gl_tree_create_empty,
+    gl_tree_nx_create_empty,
     gl_tree_size,
     gl_tree_search,
     gl_tree_search_atleast,
-    gl_tree_add,
+    gl_tree_nx_add,
     gl_tree_remove,
     gl_tree_oset_free,
     gl_tree_iterator,
new file mode 100644
--- /dev/null
+++ b/lib/gl_xoset.c
@@ -0,0 +1,46 @@
+/* Abstract ordered set data type, with out-of-memory checking.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2009.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "gl_xoset.h"
+
+#if !HAVE_INLINE
+
+gl_oset_t
+gl_oset_create_empty (gl_oset_implementation_t implementation,
+                      gl_setelement_compar_fn compar_fn,
+                      gl_setelement_dispose_fn dispose_fn)
+{
+  gl_oset_t result =
+    gl_oset_nx_create_empty (implementation, compar_fn, dispose_fn);
+  if (result == NULL)
+    xalloc_die ();
+  return result;
+}
+
+bool
+gl_oset_add (gl_oset_t set, const void *elt)
+{
+  int result = gl_oset_nx_add (set, elt);
+  if (result < 0)
+    xalloc_die ();
+  return result;
+}
+
+#endif
new file mode 100644
--- /dev/null
+++ b/lib/gl_xoset.h
@@ -0,0 +1,67 @@
+/* Abstract ordered set data type, with out-of-memory checking.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2009.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _GL_XOSET_H
+#define _GL_XOSET_H
+
+#include "gl_oset.h"
+#include "xalloc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* These functions are thin wrappers around the corresponding functions with
+   _nx_ infix from gl_oset.h.  Upon out-of-memory, they invoke xalloc_die (),
+   instead of returning an error indicator.  */
+extern gl_oset_t gl_oset_create_empty (gl_oset_implementation_t implementation,
+                                       gl_setelement_compar_fn compar_fn,
+                                       gl_setelement_dispose_fn dispose_fn);
+extern bool gl_oset_add (gl_oset_t set, const void *elt);
+
+#if HAVE_INLINE
+
+# define gl_oset_create_empty gl_oset_create_empty_inline
+static inline gl_oset_t
+gl_oset_create_empty (gl_oset_implementation_t implementation,
+                      gl_setelement_compar_fn compar_fn,
+                      gl_setelement_dispose_fn dispose_fn)
+{
+  gl_oset_t result =
+    gl_oset_nx_create_empty (implementation, compar_fn, dispose_fn);
+  if (result == NULL)
+    xalloc_die ();
+  return result;
+}
+
+# define gl_oset_add gl_oset_add_inline
+static inline bool
+gl_oset_add (gl_oset_t set, const void *elt)
+{
+  int result = gl_oset_nx_add (set, elt);
+  if (result < 0)
+    xalloc_die ();
+  return result;
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GL_XOSET_H */
--- a/modules/array-oset
+++ b/modules/array-oset
@@ -7,7 +7,6 @@
 
 Depends-on:
 oset
-xalloc
 xsize
 
 configure.ac:
--- a/modules/avltree-oset
+++ b/modules/avltree-oset
@@ -8,7 +8,6 @@
 
 Depends-on:
 oset
-xalloc
 
 configure.ac:
 
--- a/modules/avltree-oset-tests
+++ b/modules/avltree-oset-tests
@@ -10,4 +10,3 @@
 Makefile.am:
 TESTS += test-avltree_oset
 check_PROGRAMS += test-avltree_oset
-test_avltree_oset_LDADD = $(LDADD) @LIBINTL@
--- a/modules/rbtree-oset
+++ b/modules/rbtree-oset
@@ -8,7 +8,6 @@
 
 Depends-on:
 oset
-xalloc
 
 configure.ac:
 
--- a/modules/rbtree-oset-tests
+++ b/modules/rbtree-oset-tests
@@ -10,4 +10,3 @@
 Makefile.am:
 TESTS += test-rbtree_oset
 check_PROGRAMS += test-rbtree_oset
-test_rbtree_oset_LDADD = $(LDADD) @LIBINTL@
new file mode 100644
--- /dev/null
+++ b/modules/xoset
@@ -0,0 +1,27 @@
+Description:
+Abstract ordered set data type, with out-of-memory checking.
+
+Files:
+lib/gl_xoset.h
+lib/gl_xoset.c
+m4/gl_list.m4
+
+Depends-on:
+inline
+stdbool
+xalloc-die
+
+configure.ac:
+gl_LIST
+
+Makefile.am:
+lib_SOURCES += gl_xoset.h gl_xoset.c
+
+Include:
+"gl_xoset.h"
+
+License:
+GPL
+
+Maintainer:
+Bruno Haible
--- a/tests/test-array_oset.c
+++ b/tests/test-array_oset.c
@@ -1,5 +1,5 @@
 /* Test of ordered set data type implementation.
-   Copyright (C) 2006-2008 Free Software Foundation, Inc.
+   Copyright (C) 2006-2009 Free Software Foundation, Inc.
    Written by Bruno Haible <bruno@clisp.org>, 2007.
 
    This program is free software: you can redistribute it and/or modify
@@ -96,7 +96,8 @@
     unsigned int repeat;
 
     /* Create set1.  */
-    set1 = gl_oset_create_empty (GL_ARRAY_OSET, (gl_setelement_compar_fn) strcmp, NULL);
+    set1 = gl_oset_nx_create_empty (GL_ARRAY_OSET, (gl_setelement_compar_fn) strcmp, NULL);
+    ASSERT (set1 != NULL);
 
     /* Create set2.  */
     set2 = gl_list_create_empty (GL_ARRAY_LIST, NULL, NULL, NULL, false);
@@ -107,7 +108,7 @@
     for (i = 0; i < initial_size; i++)
       {
         const char *obj = RANDOM_OBJECT ();
-        ASSERT (gl_oset_add (set1, obj)
+        ASSERT (gl_oset_nx_add (set1, obj)
                 == (gl_sortedlist_search (set2, (gl_listelement_compar_fn)strcmp, obj) != NULL
                     ? false
                     : (gl_sortedlist_add (set2, (gl_listelement_compar_fn)strcmp, obj), true)));
@@ -129,7 +130,7 @@
           case 1:
             {
               const char *obj = RANDOM_OBJECT ();
-              ASSERT (gl_oset_add (set1, obj)
+              ASSERT (gl_oset_nx_add (set1, obj)
                       == (gl_sortedlist_search (set2, (gl_listelement_compar_fn)strcmp, obj) != NULL
                           ? false
                           : (gl_sortedlist_add (set2, (gl_listelement_compar_fn)strcmp, obj), true)));
--- a/tests/test-avltree_oset.c
+++ b/tests/test-avltree_oset.c
@@ -96,10 +96,12 @@
     unsigned int repeat;
 
     /* Create set1.  */
-    set1 = gl_oset_create_empty (GL_ARRAY_OSET, (gl_setelement_compar_fn) strcmp, NULL);
+    set1 = gl_oset_nx_create_empty (GL_ARRAY_OSET, (gl_setelement_compar_fn) strcmp, NULL);
+    ASSERT (set1 != NULL);
 
     /* Create set2.  */
-    set2 = gl_oset_create_empty (GL_AVLTREE_OSET, (gl_setelement_compar_fn) strcmp, NULL);
+    set2 = gl_oset_nx_create_empty (GL_AVLTREE_OSET, (gl_setelement_compar_fn) strcmp, NULL);
+    ASSERT (set2 != NULL);
 
     check_all (set1, set2);
 
@@ -107,7 +109,7 @@
     for (i = 0; i < initial_size; i++)
       {
         const char *obj = RANDOM_OBJECT ();
-        ASSERT (gl_oset_add (set1, obj) == gl_oset_add (set2, obj));
+        ASSERT (gl_oset_nx_add (set1, obj) == gl_oset_nx_add (set2, obj));
         check_all (set1, set2);
       }
 
@@ -125,7 +127,7 @@
           case 1:
             {
               const char *obj = RANDOM_OBJECT ();
-              ASSERT (gl_oset_add (set1, obj) == gl_oset_add (set2, obj));
+              ASSERT (gl_oset_nx_add (set1, obj) == gl_oset_nx_add (set2, obj));
             }
             break;
           case 2:
--- a/tests/test-rbtree_oset.c
+++ b/tests/test-rbtree_oset.c
@@ -1,5 +1,5 @@
 /* Test of ordered set data type implementation.
-   Copyright (C) 2006-2008 Free Software Foundation, Inc.
+   Copyright (C) 2006-2009 Free Software Foundation, Inc.
    Written by Bruno Haible <bruno@clisp.org>, 2006.
 
    This program is free software: you can redistribute it and/or modify
@@ -96,10 +96,12 @@
     unsigned int repeat;
 
     /* Create set1.  */
-    set1 = gl_oset_create_empty (GL_ARRAY_OSET, (gl_setelement_compar_fn) strcmp, NULL);
+    set1 = gl_oset_nx_create_empty (GL_ARRAY_OSET, (gl_setelement_compar_fn) strcmp, NULL);
+    ASSERT (set1 != NULL);
 
     /* Create set2.  */
-    set2 = gl_oset_create_empty (GL_RBTREE_OSET, (gl_setelement_compar_fn) strcmp, NULL);
+    set2 = gl_oset_nx_create_empty (GL_RBTREE_OSET, (gl_setelement_compar_fn) strcmp, NULL);
+    ASSERT (set2 != NULL);
 
     check_all (set1, set2);
 
@@ -107,7 +109,7 @@
     for (i = 0; i < initial_size; i++)
       {
         const char *obj = RANDOM_OBJECT ();
-        ASSERT (gl_oset_add (set1, obj) == gl_oset_add (set2, obj));
+        ASSERT (gl_oset_nx_add (set1, obj) == gl_oset_nx_add (set2, obj));
         check_all (set1, set2);
       }
 
@@ -125,7 +127,7 @@
           case 1:
             {
               const char *obj = RANDOM_OBJECT ();
-              ASSERT (gl_oset_add (set1, obj) == gl_oset_add (set2, obj));
+              ASSERT (gl_oset_nx_add (set1, obj) == gl_oset_nx_add (set2, obj));
             }
             break;
           case 2: