Browse Source

Add private versions of gl_anytree to project

* Taken from gnulib
* include small bugfix in bl_anyrbtree
Andrew Young 8 years ago
parent
commit
76c363bc4f

+ 0 - 7
gnulib/lib/.gitignore

@@ -10,13 +10,6 @@
 /xsize.h
 /gl_anyhash_list1.h
 /gl_anyhash_list2.h
-/gl_anyrbtree_list1.h
-/gl_anyrbtree_list2.h
-/gl_anytree_list1.h
-/gl_anytree_list2.h
-/gl_anytree_oset.h
-/gl_anytreehash_list1.h
-/gl_anytreehash_list2.h
 /gl_oset.c
 /gl_oset.h
 /gl_rbtree_oset.c

+ 76 - 0
gnulib/lib/gl_anyrbtree_list1.h

@@ -0,0 +1,76 @@
+/* Sequential list data type implemented by a binary tree.
+   Copyright (C) 2006, 2009-2012 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2006.
+
+   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/>.  */
+
+/* Common code of gl_rbtree_list.c and gl_rbtreehash_list.c.  */
+
+/* A red-black tree is a binary tree where every node is colored black or
+   red such that
+   1. The root is black.
+   2. No red node has a red parent.
+      Or equivalently: No red node has a red child.
+   3. All paths from the root down to any NULL endpoint contain the same
+      number of black nodes.
+   Let's call this the "black-height" bh of the tree.  It follows that every
+   such path contains exactly bh black and between 0 and bh red nodes.  (The
+   extreme cases are a path containing only black nodes, and a path colored
+   alternately black-red-black-red-...-black-red.)  The height of the tree
+   therefore is >= bh, <= 2*bh.
+ */
+
+/* -------------------------- gl_list_t Data Type -------------------------- */
+
+/* Color of a node.  */
+typedef enum color { BLACK, RED } color_t;
+
+/* Concrete list node implementation, valid for this file only.  */
+struct gl_list_node_impl
+{
+#if WITH_HASHTABLE
+  struct gl_hash_entry h;           /* hash table entry fields; must be first */
+#endif
+  struct gl_list_node_impl *left;   /* left branch, or NULL */
+  struct gl_list_node_impl *right;  /* right branch, or NULL */
+  /* Parent pointer, or NULL. The parent pointer is not needed for most
+     operations.  It is needed so that a gl_list_node_t can be returned
+     without memory allocation, on which the functions gl_list_remove_node,
+     gl_list_add_before, gl_list_add_after can be implemented.  */
+  struct gl_list_node_impl *parent;
+  color_t color;                    /* node's color */
+  size_t branch_size;               /* number of nodes in this branch,
+                                       = branchsize(left)+branchsize(right)+1 */
+  const void *value;
+};
+
+/* Concrete gl_list_impl type, valid for this file only.  */
+struct gl_list_impl
+{
+  struct gl_list_impl_base base;
+#if WITH_HASHTABLE
+  /* A hash table: managed as an array of collision lists.  */
+  struct gl_hash_entry **table;
+  size_t table_size;
+#endif
+  struct gl_list_node_impl *root;   /* root node or NULL */
+};
+
+/* A red-black tree of height h has a black-height bh >= ceil(h/2) and
+   therefore at least 2^ceil(h/2) - 1 elements.  So, h <= 116 (because a tree
+   of height h >= 117 would have at least 2^59 - 1 elements, and because even
+   on 64-bit machines,
+     sizeof (gl_list_node_impl) * (2^59 - 1) > 2^64
+   this would exceed the address space of the machine.  */
+#define MAXHEIGHT 116

File diff suppressed because it is too large
+ 1028 - 0
gnulib/lib/gl_anyrbtree_list2.h


+ 41 - 0
gnulib/lib/gl_anytree_list1.h

@@ -0,0 +1,41 @@
+/* Sequential list data type implemented by a binary tree.
+   Copyright (C) 2006, 2009-2012 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2006.
+
+   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/>.  */
+
+/* Common code of gl_avltree_list.c, gl_rbtree_list.c,
+                  gl_avltreehash_list.c, gl_rbtreehash_list.c.  */
+
+/* An item on the stack used for iterating across the elements.  */
+typedef struct
+{
+  gl_list_node_t node;
+  size_t rightp;
+} iterstack_item_t;
+
+/* A stack used for iterating across the elements.  */
+typedef iterstack_item_t iterstack_t[MAXHEIGHT];
+
+/* Free a non-empty subtree recursively.
+   This function is recursive and therefore not very fast.  */
+static void
+free_subtree (gl_list_node_t node)
+{
+  if (node->left != NULL)
+    free_subtree (node->left);
+  if (node->right != NULL)
+    free_subtree (node->right);
+  free (node);
+}

+ 941 - 0
gnulib/lib/gl_anytree_list2.h

@@ -0,0 +1,941 @@
+/* Sequential list data type implemented by a binary tree.
+   Copyright (C) 2006-2012 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2006.
+
+   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/>.  */
+
+/* Common code of gl_avltree_list.c, gl_rbtree_list.c,
+                  gl_avltreehash_list.c, gl_rbtreehash_list.c.  */
+
+static gl_list_t
+gl_tree_nx_create_empty (gl_list_implementation_t implementation,
+                         gl_listelement_equals_fn equals_fn,
+                         gl_listelement_hashcode_fn hashcode_fn,
+                         gl_listelement_dispose_fn dispose_fn,
+                         bool allow_duplicates)
+{
+  struct gl_list_impl *list = (struct gl_list_impl *) malloc (sizeof (struct gl_list_impl));
+
+  if (list == NULL)
+    return NULL;
+
+  list->base.vtable = implementation;
+  list->base.equals_fn = equals_fn;
+  list->base.hashcode_fn = hashcode_fn;
+  list->base.dispose_fn = dispose_fn;
+  list->base.allow_duplicates = allow_duplicates;
+#if WITH_HASHTABLE
+  list->table_size = 11;
+  list->table =
+    (gl_hash_entry_t *) calloc (list->table_size, sizeof (gl_hash_entry_t));
+  if (list->table == NULL)
+    goto fail;
+#endif
+  list->root = NULL;
+
+  return list;
+
+#if WITH_HASHTABLE
+ fail:
+  free (list);
+  return NULL;
+#endif
+}
+
+static size_t
+gl_tree_size (gl_list_t list)
+{
+  return (list->root != NULL ? list->root->branch_size : 0);
+}
+
+static const void *
+gl_tree_node_value (gl_list_t list, gl_list_node_t node)
+{
+  return node->value;
+}
+
+static int
+gl_tree_node_nx_set_value (gl_list_t list, gl_list_node_t node, const void *elt)
+{
+#if WITH_HASHTABLE
+  if (elt != node->value)
+    {
+      size_t new_hashcode =
+        (list->base.hashcode_fn != NULL
+         ? list->base.hashcode_fn (elt)
+         : (size_t)(uintptr_t) elt);
+
+      if (new_hashcode != node->h.hashcode)
+        {
+          remove_from_bucket (list, node);
+          node->value = elt;
+          node->h.hashcode = new_hashcode;
+          if (add_to_bucket (list, node) < 0)
+            {
+              /* Out of memory.  We removed node from a bucket but cannot add
+                 it to another bucket.  In order to avoid inconsistencies, we
+                 must remove node entirely from the list.  */
+              gl_tree_remove_node_from_tree (list, node);
+              free (node);
+              return -1;
+            }
+        }
+      else
+        node->value = elt;
+    }
+#else
+  node->value = elt;
+#endif
+  return 0;
+}
+
+static gl_list_node_t
+gl_tree_next_node (gl_list_t list, gl_list_node_t node)
+{
+  if (node->right != NULL)
+    {
+      node = node->right;
+      while (node->left != NULL)
+        node = node->left;
+    }
+  else
+    {
+      while (node->parent != NULL && node->parent->right == node)
+        node = node->parent;
+      node = node->parent;
+    }
+  return node;
+}
+
+static gl_list_node_t
+gl_tree_previous_node (gl_list_t list, gl_list_node_t node)
+{
+  if (node->left != NULL)
+    {
+      node = node->left;
+      while (node->right != NULL)
+        node = node->right;
+    }
+  else
+    {
+      while (node->parent != NULL && node->parent->left == node)
+        node = node->parent;
+      node = node->parent;
+    }
+  return node;
+}
+
+/* Return the node at the given position < gl_tree_size (list).  */
+static inline gl_list_node_t
+node_at (gl_list_node_t root, size_t position)
+{
+  /* Here we know that root != NULL.  */
+  gl_list_node_t node = root;
+
+  for (;;)
+    {
+      if (node->left != NULL)
+        {
+          if (position < node->left->branch_size)
+            {
+              node = node->left;
+              continue;
+            }
+          position -= node->left->branch_size;
+        }
+      if (position == 0)
+        break;
+      position--;
+      node = node->right;
+    }
+  return node;
+}
+
+static const void *
+gl_tree_get_at (gl_list_t list, size_t position)
+{
+  gl_list_node_t node = list->root;
+
+  if (!(node != NULL && position < node->branch_size))
+    /* Invalid argument.  */
+    abort ();
+  node = node_at (node, position);
+  return node->value;
+}
+
+static gl_list_node_t
+gl_tree_nx_set_at (gl_list_t list, size_t position, const void *elt)
+{
+  gl_list_node_t node = list->root;
+
+  if (!(node != NULL && position < node->branch_size))
+    /* Invalid argument.  */
+    abort ();
+  node = node_at (node, position);
+#if WITH_HASHTABLE
+  if (elt != node->value)
+    {
+      size_t new_hashcode =
+        (list->base.hashcode_fn != NULL
+         ? list->base.hashcode_fn (elt)
+         : (size_t)(uintptr_t) elt);
+
+      if (new_hashcode != node->h.hashcode)
+        {
+          remove_from_bucket (list, node);
+          node->value = elt;
+          node->h.hashcode = new_hashcode;
+          if (add_to_bucket (list, node) < 0)
+            {
+              /* Out of memory.  We removed node from a bucket but cannot add
+                 it to another bucket.  In order to avoid inconsistencies, we
+                 must remove node entirely from the list.  */
+              gl_tree_remove_node_from_tree (list, node);
+              free (node);
+              return NULL;
+            }
+        }
+      else
+        node->value = elt;
+    }
+#else
+  node->value = elt;
+#endif
+  return node;
+}
+
+#if !WITH_HASHTABLE
+
+static gl_list_node_t
+gl_tree_search_from_to (gl_list_t list, size_t start_index, size_t end_index,
+                        const void *elt)
+{
+  if (!(start_index <= end_index
+        && end_index <= (list->root != NULL ? list->root->branch_size : 0)))
+    /* Invalid arguments.  */
+    abort ();
+  {
+    gl_listelement_equals_fn equals = list->base.equals_fn;
+    /* Iterate across all elements.  */
+    gl_list_node_t node = list->root;
+    iterstack_t stack;
+    iterstack_item_t *stack_ptr = &stack[0];
+    size_t index = 0;
+
+    if (start_index == 0)
+      {
+        /* Consider all elements.  */
+        for (;;)
+          {
+            /* Descend on left branch.  */
+            for (;;)
+              {
+                if (node == NULL)
+                  break;
+                stack_ptr->node = node;
+                stack_ptr->rightp = 0;
+                node = node->left;
+                stack_ptr++;
+              }
+            /* Climb up again.  */
+            for (;;)
+              {
+                if (stack_ptr == &stack[0])
+                  return NULL;
+                stack_ptr--;
+                if (!stack_ptr->rightp)
+                  break;
+              }
+            node = stack_ptr->node;
+            /* Test against current element.  */
+            if (equals != NULL ? equals (elt, node->value) : elt == node->value)
+              return node;
+            index++;
+            if (index >= end_index)
+              return NULL;
+            /* Descend on right branch.  */
+            stack_ptr->rightp = 1;
+            node = node->right;
+            stack_ptr++;
+          }
+      }
+    else
+      {
+        /* Consider only elements at indices >= start_index.
+           In this case, rightp contains the difference between the start_index
+           for the parent node and the one for the child node (0 when the child
+           node is the parent's left child, > 0 when the child is the parent's
+           right child).  */
+        for (;;)
+          {
+            /* Descend on left branch.  */
+            for (;;)
+              {
+                if (node == NULL)
+                  break;
+                if (node->branch_size <= start_index)
+                  break;
+                stack_ptr->node = node;
+                stack_ptr->rightp = 0;
+                node = node->left;
+                stack_ptr++;
+              }
+            /* Climb up again.  */
+            for (;;)
+              {
+                if (stack_ptr == &stack[0])
+                  return NULL;
+                stack_ptr--;
+                if (!stack_ptr->rightp)
+                  break;
+                start_index += stack_ptr->rightp;
+              }
+            node = stack_ptr->node;
+            {
+              size_t left_branch_size1 =
+                (node->left != NULL ? node->left->branch_size : 0) + 1;
+              if (start_index < left_branch_size1)
+                {
+                  /* Test against current element.  */
+                  if (equals != NULL ? equals (elt, node->value) : elt == node->value)
+                    return node;
+                  /* Now that we have considered all indices < left_branch_size1,
+                     we can increment start_index.  */
+                  start_index = left_branch_size1;
+                }
+              index++;
+              if (index >= end_index)
+                return NULL;
+              /* Descend on right branch.  */
+              start_index -= left_branch_size1;
+              stack_ptr->rightp = left_branch_size1;
+            }
+            node = node->right;
+            stack_ptr++;
+          }
+      }
+  }
+}
+
+static size_t
+gl_tree_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index,
+                         const void *elt)
+{
+  if (!(start_index <= end_index
+        && end_index <= (list->root != NULL ? list->root->branch_size : 0)))
+    /* Invalid arguments.  */
+    abort ();
+  {
+    gl_listelement_equals_fn equals = list->base.equals_fn;
+    /* Iterate across all elements.  */
+    gl_list_node_t node = list->root;
+    iterstack_t stack;
+    iterstack_item_t *stack_ptr = &stack[0];
+    size_t index = 0;
+
+    if (start_index == 0)
+      {
+        /* Consider all elements.  */
+        for (;;)
+          {
+            /* Descend on left branch.  */
+            for (;;)
+              {
+                if (node == NULL)
+                  break;
+                stack_ptr->node = node;
+                stack_ptr->rightp = 0;
+                node = node->left;
+                stack_ptr++;
+              }
+            /* Climb up again.  */
+            for (;;)
+              {
+                if (stack_ptr == &stack[0])
+                  return (size_t)(-1);
+                stack_ptr--;
+                if (!stack_ptr->rightp)
+                  break;
+              }
+            node = stack_ptr->node;
+            /* Test against current element.  */
+            if (equals != NULL ? equals (elt, node->value) : elt == node->value)
+              return index;
+            index++;
+            if (index >= end_index)
+              return (size_t)(-1);
+            /* Descend on right branch.  */
+            stack_ptr->rightp = 1;
+            node = node->right;
+            stack_ptr++;
+          }
+      }
+    else
+      {
+        /* Consider only elements at indices >= start_index.
+           In this case, rightp contains the difference between the start_index
+           for the parent node and the one for the child node (0 when the child
+           node is the parent's left child, > 0 when the child is the parent's
+           right child).  */
+        for (;;)
+          {
+            /* Descend on left branch.  */
+            for (;;)
+              {
+                if (node == NULL)
+                  break;
+                if (node->branch_size <= start_index)
+                  break;
+                stack_ptr->node = node;
+                stack_ptr->rightp = 0;
+                node = node->left;
+                stack_ptr++;
+              }
+            /* Climb up again.  */
+            for (;;)
+              {
+                if (stack_ptr == &stack[0])
+                  return (size_t)(-1);
+                stack_ptr--;
+                if (!stack_ptr->rightp)
+                  break;
+                start_index += stack_ptr->rightp;
+              }
+            node = stack_ptr->node;
+            {
+              size_t left_branch_size1 =
+                (node->left != NULL ? node->left->branch_size : 0) + 1;
+              if (start_index < left_branch_size1)
+                {
+                  /* Test against current element.  */
+                  if (equals != NULL ? equals (elt, node->value) : elt == node->value)
+                    return index;
+                  /* Now that we have considered all indices < left_branch_size1,
+                     we can increment start_index.  */
+                  start_index = left_branch_size1;
+                }
+              index++;
+              if (index >= end_index)
+                return (size_t)(-1);
+              /* Descend on right branch.  */
+              start_index -= left_branch_size1;
+              stack_ptr->rightp = left_branch_size1;
+            }
+            node = node->right;
+            stack_ptr++;
+          }
+      }
+  }
+}
+
+#endif
+
+static gl_list_node_t
+gl_tree_nx_add_at (gl_list_t list, size_t position, const void *elt)
+{
+  size_t count = (list->root != NULL ? list->root->branch_size : 0);
+
+  if (!(position <= count))
+    /* Invalid argument.  */
+    abort ();
+  if (position == count)
+    return gl_tree_nx_add_last (list, elt);
+  else
+    return gl_tree_nx_add_before (list, node_at (list->root, position), elt);
+}
+
+static bool
+gl_tree_remove_node (gl_list_t list, gl_list_node_t node)
+{
+#if WITH_HASHTABLE
+  /* Remove node from the hash table.
+     Note that this is only possible _before_ the node is removed from the
+     tree structure, because remove_from_bucket() uses node_position().  */
+  remove_from_bucket (list, node);
+#endif
+
+  gl_tree_remove_node_from_tree (list, node);
+
+  if (list->base.dispose_fn != NULL)
+    list->base.dispose_fn (node->value);
+  free (node);
+  return true;
+}
+
+static bool
+gl_tree_remove_at (gl_list_t list, size_t position)
+{
+  gl_list_node_t node = list->root;
+
+  if (!(node != NULL && position < node->branch_size))
+    /* Invalid argument.  */
+    abort ();
+  node = node_at (node, position);
+  return gl_tree_remove_node (list, node);
+}
+
+static bool
+gl_tree_remove (gl_list_t list, const void *elt)
+{
+  if (list->root != NULL)
+    {
+      gl_list_node_t node =
+        gl_tree_search_from_to (list, 0, list->root->branch_size, elt);
+
+      if (node != NULL)
+        return gl_tree_remove_node (list, node);
+    }
+  return false;
+}
+
+#if !WITH_HASHTABLE
+
+static void
+gl_tree_list_free (gl_list_t list)
+{
+  /* Iterate across all elements in post-order.  */
+  gl_list_node_t node = list->root;
+  iterstack_t stack;
+  iterstack_item_t *stack_ptr = &stack[0];
+
+  for (;;)
+    {
+      /* Descend on left branch.  */
+      for (;;)
+        {
+          if (node == NULL)
+            break;
+          stack_ptr->node = node;
+          stack_ptr->rightp = false;
+          node = node->left;
+          stack_ptr++;
+        }
+      /* Climb up again.  */
+      for (;;)
+        {
+          if (stack_ptr == &stack[0])
+            goto done_iterate;
+          stack_ptr--;
+          node = stack_ptr->node;
+          if (!stack_ptr->rightp)
+            break;
+          /* Free the current node.  */
+          if (list->base.dispose_fn != NULL)
+            list->base.dispose_fn (node->value);
+          free (node);
+        }
+      /* Descend on right branch.  */
+      stack_ptr->rightp = true;
+      node = node->right;
+      stack_ptr++;
+    }
+ done_iterate:
+  free (list);
+}
+
+#endif
+
+/* --------------------- gl_list_iterator_t Data Type --------------------- */
+
+static gl_list_iterator_t
+gl_tree_iterator (gl_list_t list)
+{
+  gl_list_iterator_t result;
+  gl_list_node_t node;
+
+  result.vtable = list->base.vtable;
+  result.list = list;
+  /* Start node is the leftmost node.  */
+  node = list->root;
+  if (node != NULL)
+    while (node->left != NULL)
+      node = node->left;
+  result.p = node;
+  /* End point is past the rightmost node.  */
+  result.q = NULL;
+#ifdef lint
+  result.i = 0;
+  result.j = 0;
+  result.count = 0;
+#endif
+
+  return result;
+}
+
+static gl_list_iterator_t
+gl_tree_iterator_from_to (gl_list_t list, size_t start_index, size_t end_index)
+{
+  size_t count = (list->root != NULL ? list->root->branch_size : 0);
+  gl_list_iterator_t result;
+
+  if (!(start_index <= end_index && end_index <= count))
+    /* Invalid arguments.  */
+    abort ();
+  result.vtable = list->base.vtable;
+  result.list = list;
+  /* Start node is the node at position start_index.  */
+  result.p = (start_index < count ? node_at (list->root, start_index) : NULL);
+  /* End point is the node at position end_index.  */
+  result.q = (end_index < count ? node_at (list->root, end_index) : NULL);
+#ifdef lint
+  result.i = 0;
+  result.j = 0;
+  result.count = 0;
+#endif
+
+  return result;
+}
+
+static bool
+gl_tree_iterator_next (gl_list_iterator_t *iterator,
+                       const void **eltp, gl_list_node_t *nodep)
+{
+  if (iterator->p != iterator->q)
+    {
+      gl_list_node_t node = (gl_list_node_t) iterator->p;
+      *eltp = node->value;
+      if (nodep != NULL)
+        *nodep = node;
+      /* Advance to the next node.  */
+      if (node->right != NULL)
+        {
+          node = node->right;
+          while (node->left != NULL)
+            node = node->left;
+        }
+      else
+        {
+          while (node->parent != NULL && node->parent->right == node)
+            node = node->parent;
+          node = node->parent;
+        }
+      iterator->p = node;
+      return true;
+    }
+  else
+    return false;
+}
+
+static void
+gl_tree_iterator_free (gl_list_iterator_t *iterator)
+{
+}
+
+/* ---------------------- Sorted gl_list_t Data Type ---------------------- */
+
+static gl_list_node_t
+gl_tree_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar,
+                           const void *elt)
+{
+  gl_list_node_t node;
+
+  for (node = list->root; node != NULL; )
+    {
+      int cmp = compar (node->value, elt);
+
+      if (cmp < 0)
+        node = node->right;
+      else if (cmp > 0)
+        node = node->left;
+      else /* cmp == 0 */
+        {
+          /* We have an element equal to ELT.  But we need the leftmost such
+             element.  */
+          gl_list_node_t found = node;
+          node = node->left;
+          for (; node != NULL; )
+            {
+              int cmp2 = compar (node->value, elt);
+
+              if (cmp2 < 0)
+                node = node->right;
+              else if (cmp2 > 0)
+                /* The list was not sorted.  */
+                abort ();
+              else /* cmp2 == 0 */
+                {
+                  found = node;
+                  node = node->left;
+                }
+            }
+          return found;
+        }
+    }
+  return NULL;
+}
+
+static gl_list_node_t
+gl_tree_sortedlist_search_from_to (gl_list_t list,
+                                   gl_listelement_compar_fn compar,
+                                   size_t low, size_t high,
+                                   const void *elt)
+{
+  gl_list_node_t node;
+
+  if (!(low <= high
+        && high <= (list->root != NULL ? list->root->branch_size : 0)))
+    /* Invalid arguments.  */
+    abort ();
+
+  for (node = list->root; node != NULL; )
+    {
+      size_t left_branch_size =
+        (node->left != NULL ? node->left->branch_size : 0);
+
+      if (low > left_branch_size)
+        {
+          low -= left_branch_size + 1;
+          high -= left_branch_size + 1;
+          node = node->right;
+        }
+      else if (high <= left_branch_size)
+        node = node->left;
+      else
+        {
+          /* Here low <= left_branch_size < high.  */
+          int cmp = compar (node->value, elt);
+
+          if (cmp < 0)
+            {
+              low = 0;
+              high -= left_branch_size + 1;
+              node = node->right;
+            }
+          else if (cmp > 0)
+            node = node->left;
+          else /* cmp == 0 */
+            {
+              /* We have an element equal to ELT.  But we need the leftmost
+                 such element.  */
+              gl_list_node_t found = node;
+              node = node->left;
+              for (; node != NULL; )
+                {
+                  size_t left_branch_size2 =
+                    (node->left != NULL ? node->left->branch_size : 0);
+
+                  if (low > left_branch_size2)
+                    {
+                      low -= left_branch_size2 + 1;
+                      node = node->right;
+                    }
+                  else
+                    {
+                      /* Here low <= left_branch_size2.  */
+                      int cmp2 = compar (node->value, elt);
+
+                      if (cmp2 < 0)
+                        {
+                          low = 0;
+                          node = node->right;
+                        }
+                      else if (cmp2 > 0)
+                        /* The list was not sorted.  */
+                        abort ();
+                      else /* cmp2 == 0 */
+                        {
+                          found = node;
+                          node = node->left;
+                        }
+                    }
+                }
+              return found;
+            }
+        }
+    }
+  return NULL;
+}
+
+static size_t
+gl_tree_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar,
+                            const void *elt)
+{
+  gl_list_node_t node;
+  size_t position;
+
+  for (node = list->root, position = 0; node != NULL; )
+    {
+      int cmp = compar (node->value, elt);
+
+      if (cmp < 0)
+        {
+          if (node->left != NULL)
+            position += node->left->branch_size;
+          position++;
+          node = node->right;
+        }
+      else if (cmp > 0)
+        node = node->left;
+      else /* cmp == 0 */
+        {
+          /* We have an element equal to ELT.  But we need the leftmost such
+             element.  */
+          size_t found_position =
+            position + (node->left != NULL ? node->left->branch_size : 0);
+          node = node->left;
+          for (; node != NULL; )
+            {
+              int cmp2 = compar (node->value, elt);
+
+              if (cmp2 < 0)
+                {
+                  if (node->left != NULL)
+                    position += node->left->branch_size;
+                  position++;
+                  node = node->right;
+                }
+              else if (cmp2 > 0)
+                /* The list was not sorted.  */
+                abort ();
+              else /* cmp2 == 0 */
+                {
+                  found_position =
+                    position
+                    + (node->left != NULL ? node->left->branch_size : 0);
+                  node = node->left;
+                }
+            }
+          return found_position;
+        }
+    }
+  return (size_t)(-1);
+}
+
+static size_t
+gl_tree_sortedlist_indexof_from_to (gl_list_t list,
+                                    gl_listelement_compar_fn compar,
+                                    size_t low, size_t high,
+                                    const void *elt)
+{
+  gl_list_node_t node;
+  size_t position;
+  size_t start = low;
+
+  if (!(low <= high
+        && high <= (list->root != NULL ? list->root->branch_size : 0)))
+    /* Invalid arguments.  */
+    abort ();
+
+  for (node = list->root, position = 0; node != NULL; )
+    {
+      size_t left_branch_size =
+        (node->left != NULL ? node->left->branch_size : 0);
+
+      if (low > left_branch_size)
+        {
+          low -= left_branch_size + 1;
+          high -= left_branch_size + 1;
+          position += left_branch_size + 1;
+          node = node->right;
+        }
+      else if (high <= left_branch_size)
+        node = node->left;
+      else
+        {
+          /* Here low <= left_branch_size < high.  */
+          int cmp = compar (node->value, elt);
+
+          if (cmp < 0)
+            {
+              low = 0;
+              high -= left_branch_size + 1;
+              position += left_branch_size + 1;
+              node = node->right;
+            }
+          else if (cmp > 0)
+            node = node->left;
+          else /* cmp == 0 */
+            {
+              /* We have an element equal to ELT.  But we need the leftmost
+                 such element.  */
+              size_t found_position =
+                position + (node->left != NULL ? node->left->branch_size : 0);
+              node = node->left;
+              for (; node != NULL; )
+                {
+                  size_t left_branch_size2 =
+                    (node->left != NULL ? node->left->branch_size : 0);
+
+                  if (low > left_branch_size2)
+                    {
+                      low -= left_branch_size2 + 1;
+                      node = node->right;
+                    }
+                  else
+                    {
+                      /* Here low <= left_branch_size2.  */
+                      int cmp2 = compar (node->value, elt);
+
+                      if (cmp2 < 0)
+                        {
+                          position += left_branch_size2 + 1;
+                          node = node->right;
+                        }
+                      else if (cmp2 > 0)
+                        /* The list was not sorted.  */
+                        abort ();
+                      else /* cmp2 == 0 */
+                        {
+                          found_position = position + left_branch_size2;
+                          node = node->left;
+                        }
+                    }
+                }
+              return (start > found_position) ? start : found_position;
+            }
+        }
+    }
+  return (size_t)(-1);
+}
+
+static gl_list_node_t
+gl_tree_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar,
+                           const void *elt)
+{
+  gl_list_node_t node = list->root;
+
+  if (node == NULL)
+    return gl_tree_nx_add_first (list, elt);
+
+  for (;;)
+    {
+      int cmp = compar (node->value, elt);
+
+      if (cmp < 0)
+        {
+          if (node->right == NULL)
+            return gl_tree_nx_add_after (list, node, elt);
+          node = node->right;
+        }
+      else if (cmp > 0)
+        {
+          if (node->left == NULL)
+            return gl_tree_nx_add_before (list, node, elt);
+          node = node->left;
+        }
+      else /* cmp == 0 */
+        return gl_tree_nx_add_before (list, node, elt);
+    }
+}
+
+static bool
+gl_tree_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar,
+                           const void *elt)
+{
+  gl_list_node_t node = gl_tree_sortedlist_search (list, compar, elt);
+  if (node != NULL)
+    return gl_tree_remove_node (list, node);
+  else
+    return false;
+}

+ 297 - 0
gnulib/lib/gl_anytree_oset.h

@@ -0,0 +1,297 @@
+/* Ordered set data type implemented by a binary tree.
+   Copyright (C) 2006-2007, 2009-2012 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2006.
+
+   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/>.  */
+
+/* Common code of gl_avltree_oset.c and gl_rbtree_oset.c.  */
+
+/* An item on the stack used for iterating across the elements.  */
+typedef struct
+{
+  gl_oset_node_t node;
+  bool rightp;
+} iterstack_item_t;
+
+/* A stack used for iterating across the elements.  */
+typedef iterstack_item_t iterstack_t[MAXHEIGHT];
+
+static gl_oset_t
+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 =
+    (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;
+  set->base.dispose_fn = dispose_fn;
+  set->root = NULL;
+  set->count = 0;
+
+  return set;
+}
+
+static size_t
+gl_tree_size (gl_oset_t set)
+{
+  return set->count;
+}
+
+static bool
+gl_tree_search (gl_oset_t set, const void *elt)
+{
+  gl_setelement_compar_fn compar = set->base.compar_fn;
+  gl_oset_node_t node;
+
+  for (node = set->root; node != NULL; )
+    {
+      int cmp = (compar != NULL
+                 ? compar (node->value, elt)
+                 : (node->value > elt ? 1 :
+                    node->value < elt ? -1 : 0));
+
+      if (cmp < 0)
+        node = node->right;
+      else if (cmp > 0)
+        node = node->left;
+      else /* cmp == 0 */
+        /* We have an element equal to ELT.  */
+        return true;
+    }
+  return false;
+}
+
+static bool
+gl_tree_search_atleast (gl_oset_t set,
+                        gl_setelement_threshold_fn threshold_fn,
+                        const void *threshold,
+                        const void **eltp)
+{
+  gl_oset_node_t node;
+
+  for (node = set->root; node != NULL; )
+    {
+      if (! threshold_fn (node->value, threshold))
+        node = node->right;
+      else
+        {
+          /* We have an element >= VALUE.  But we need the leftmost such
+             element.  */
+          gl_oset_node_t found = node;
+          node = node->left;
+          for (; node != NULL; )
+            {
+              if (! threshold_fn (node->value, threshold))
+                node = node->right;
+              else
+                {
+                  found = node;
+                  node = node->left;
+                }
+            }
+          *eltp = found->value;
+          return true;
+        }
+    }
+  return false;
+}
+
+static gl_oset_node_t
+gl_tree_search_node (gl_oset_t set, const void *elt)
+{
+  gl_setelement_compar_fn compar = set->base.compar_fn;
+  gl_oset_node_t node;
+
+  for (node = set->root; node != NULL; )
+    {
+      int cmp = (compar != NULL
+                 ? compar (node->value, elt)
+                 : (node->value > elt ? 1 :
+                    node->value < elt ? -1 : 0));
+
+      if (cmp < 0)
+        node = node->right;
+      else if (cmp > 0)
+        node = node->left;
+      else /* cmp == 0 */
+        /* We have an element equal to ELT.  */
+        return node;
+    }
+  return NULL;
+}
+
+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)
+    {
+      if (gl_tree_nx_add_first (set, elt) == NULL)
+        return -1;
+      return true;
+    }
+
+  compar = set->base.compar_fn;
+
+  for (;;)
+    {
+      int cmp = (compar != NULL
+                 ? compar (node->value, elt)
+                 : (node->value > elt ? 1 :
+                    node->value < elt ? -1 : 0));
+
+      if (cmp < 0)
+        {
+          if (node->right == NULL)
+            {
+              if (gl_tree_nx_add_after (set, node, elt) == NULL)
+                return -1;
+              return true;
+            }
+          node = node->right;
+        }
+      else if (cmp > 0)
+        {
+          if (node->left == NULL)
+            {
+              if (gl_tree_nx_add_before (set, node, elt) == NULL)
+                return -1;
+              return true;
+            }
+          node = node->left;
+        }
+      else /* cmp == 0 */
+        return false;
+    }
+}
+
+static bool
+gl_tree_remove (gl_oset_t set, const void *elt)
+{
+  gl_oset_node_t node = gl_tree_search_node (set, elt);
+
+  if (node != NULL)
+    return gl_tree_remove_node (set, node);
+  else
+    return false;
+}
+
+static void
+gl_tree_oset_free (gl_oset_t set)
+{
+  /* Iterate across all elements in post-order.  */
+  gl_oset_node_t node = set->root;
+  iterstack_t stack;
+  iterstack_item_t *stack_ptr = &stack[0];
+
+  for (;;)
+    {
+      /* Descend on left branch.  */
+      for (;;)
+        {
+          if (node == NULL)
+            break;
+          stack_ptr->node = node;
+          stack_ptr->rightp = false;
+          node = node->left;
+          stack_ptr++;
+        }
+      /* Climb up again.  */
+      for (;;)
+        {
+          if (stack_ptr == &stack[0])
+            goto done_iterate;
+          stack_ptr--;
+          node = stack_ptr->node;
+          if (!stack_ptr->rightp)
+            break;
+          /* Free the current node.  */
+          if (set->base.dispose_fn != NULL)
+            set->base.dispose_fn (node->value);
+          free (node);
+        }
+      /* Descend on right branch.  */
+      stack_ptr->rightp = true;
+      node = node->right;
+      stack_ptr++;
+    }
+ done_iterate:
+  free (set);
+}
+
+/* --------------------- gl_oset_iterator_t Data Type --------------------- */
+
+static gl_oset_iterator_t
+gl_tree_iterator (gl_oset_t set)
+{
+  gl_oset_iterator_t result;
+  gl_oset_node_t node;
+
+  result.vtable = set->base.vtable;
+  result.set = set;
+  /* Start node is the leftmost node.  */
+  node = set->root;
+  if (node != NULL)
+    while (node->left != NULL)
+      node = node->left;
+  result.p = node;
+  /* End point is past the rightmost node.  */
+  result.q = NULL;
+#ifdef lint
+  result.i = 0;
+  result.j = 0;
+  result.count = 0;
+#endif
+
+  return result;
+}
+
+static bool
+gl_tree_iterator_next (gl_oset_iterator_t *iterator, const void **eltp)
+{
+  if (iterator->p != iterator->q)
+    {
+      gl_oset_node_t node = (gl_oset_node_t) iterator->p;
+      *eltp = node->value;
+      /* Advance to the next node.  */
+      if (node->right != NULL)
+        {
+          node = node->right;
+          while (node->left != NULL)
+            node = node->left;
+        }
+      else
+        {
+          while (node->parent != NULL && node->parent->right == node)
+            node = node->parent;
+          node = node->parent;
+        }
+      iterator->p = node;
+      return true;
+    }
+  else
+    return false;
+}
+
+static void
+gl_tree_iterator_free (gl_oset_iterator_t *iterator)
+{
+}

+ 358 - 0
gnulib/lib/gl_anytreehash_list1.h

@@ -0,0 +1,358 @@
+/* Sequential list data type implemented by a hash table with a binary tree.
+   Copyright (C) 2006-2007, 2009-2012 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2006.
+
+   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/>.  */
+
+/* Common code of gl_avltreehash_list.c and gl_rbtreehash_list.c.  */
+
+/* Hash table entry representing the same value at more than one position.  */
+struct gl_multiple_nodes
+{
+  struct gl_hash_entry h;           /* hash table entry fields; must be first */
+  void *magic;                      /* used to distinguish from single node */
+  gl_oset_t nodes;                  /* set of nodes, sorted by position */
+};
+/* A value that cannot occur at the corresponding field (->left) in
+   gl_list_node_impl.  */
+#define MULTIPLE_NODES_MAGIC  (void *) -1
+
+/* Resize the hash table if needed, after list->count was incremented.  */
+static inline void
+hash_resize_after_add (gl_list_t list)
+{
+  size_t count = (list->root != 0 ? list->root->branch_size : 0);
+  size_t estimate = xsum (count, count / 2); /* 1.5 * count */
+  if (estimate > list->table_size)
+    hash_resize (list, estimate);
+}
+
+/* Return the position of the given node in the tree.  */
+static size_t
+node_position (gl_list_node_t node)
+{
+  size_t position = 0;
+
+  if (node->left != NULL)
+    position += node->left->branch_size;
+  for (;;)
+    {
+      gl_list_node_t parent = node->parent;
+
+      if (parent == NULL)
+        return position;
+      /* position is now relative to the subtree of node.  */
+      if (parent->right == node)
+        {
+          position += 1;
+          if (parent->left != NULL)
+            position += parent->left->branch_size;
+        }
+      /* position is now relative to the subtree of parent.  */
+      node = parent;
+    }
+}
+
+/* Compares two nodes by their position in the tree.  */
+static int
+compare_by_position (const void *x1, const void *x2)
+{
+  gl_list_node_t node1 = (gl_list_node_t) x1;
+  gl_list_node_t node2 = (gl_list_node_t) x2;
+  size_t position1 = node_position (node1);
+  size_t position2 = node_position (node2);
+
+  return (position1 > position2 ? 1 :
+          position1 < position2 ? -1 : 0);
+}
+
+/* Compares a node's position in the tree with a given threshold.  */
+static bool
+compare_position_threshold (const void *x, const void *threshold)
+{
+  gl_list_node_t node = (gl_list_node_t) x;
+  size_t position = node_position (node);
+  return (position >= (uintptr_t)threshold);
+}
+
+/* Return the first element of a non-empty ordered set of nodes.  */
+static inline gl_list_node_t
+gl_oset_first (gl_oset_t set)
+{
+  gl_oset_iterator_t iter = gl_oset_iterator (set);
+  const void *first;
+
+  if (!gl_oset_iterator_next (&iter, &first))
+    abort ();
+  gl_oset_iterator_free (&iter);
+  return (gl_list_node_t) first;
+}
+
+/* Add a node to the hash table structure.
+   If duplicates are allowed, this function performs in average time
+   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).
+   Return 0 upon success, -1 upon out-of-memory.  */
+static int
+add_to_bucket (gl_list_t list, gl_list_node_t new_node)
+{
+  size_t bucket = new_node->h.hashcode % list->table_size;
+
+  /* If no duplicates are allowed, multiple nodes are not needed.  */
+  if (list->base.allow_duplicates)
+    {
+      size_t hashcode = new_node->h.hashcode;
+      const void *value = new_node->value;
+      gl_listelement_equals_fn equals = list->base.equals_fn;
+      gl_hash_entry_t *entryp;
+
+      for (entryp = &list->table[bucket]; *entryp != NULL; entryp = &(*entryp)->hash_next)
+        {
+          gl_hash_entry_t entry = *entryp;
+
+          if (entry->hashcode == hashcode)
+            {
+              if (((struct gl_multiple_nodes *) entry)->magic == MULTIPLE_NODES_MAGIC)
+                {
+                  /* An entry representing multiple nodes.  */
+                  gl_oset_t nodes = ((struct gl_multiple_nodes *) entry)->nodes;
+                  /* Only the first node is interesting.  */
+                  gl_list_node_t node = gl_oset_first (nodes);
+                  if (equals != NULL ? equals (value, node->value) : value == node->value)
+                    {
+                      /* Found already multiple nodes with the same value.
+                         Add the new_node to it.  */
+                      return gl_oset_nx_add (nodes, new_node);
+                    }
+                }
+              else
+                {
+                  /* An entry representing a single node.  */
+                  gl_list_node_t node = (struct gl_list_node_impl *) entry;
+                  if (equals != NULL ? equals (value, node->value) : value == node->value)
+                    {
+                      /* Found already a node with the same value.  Turn it
+                         into an ordered set, and add new_node to it.  */
+                      gl_oset_t nodes;
+                      struct gl_multiple_nodes *multi_entry;
+
+                      nodes =
+                        gl_oset_nx_create_empty (OSET_TREE_FLAVOR,
+                                                 compare_by_position, NULL);
+                      if (nodes == NULL)
+                        return -1;
+
+                      if (gl_oset_nx_add (nodes, node) < 0)
+                        goto fail;
+                      if (gl_oset_nx_add (nodes, new_node) < 0)
+                        goto fail;
+
+                      multi_entry =
+                       (struct gl_multiple_nodes *) malloc (sizeof (struct gl_multiple_nodes));
+                      if (multi_entry == NULL)
+                        goto fail;
+                      multi_entry->h.hash_next = entry->hash_next;
+                      multi_entry->h.hashcode = entry->hashcode;
+                      multi_entry->magic = MULTIPLE_NODES_MAGIC;
+                      multi_entry->nodes = nodes;
+                      *entryp = &multi_entry->h;
+                      return 0;
+
+                    fail:
+                      gl_oset_free (nodes);
+                      return -1;
+                    }
+                }
+            }
+        }
+    }
+  /* If no duplicates are allowed, multiple nodes are not needed.  */
+  new_node->h.hash_next = list->table[bucket];
+  list->table[bucket] = &new_node->h;
+  return 0;
+}
+/* Tell GCC that the likely return value is 0.  */
+#if __GNUC__ >= 3
+# define add_to_bucket(list,node) \
+    __builtin_expect ((add_to_bucket) (list, node), 0)
+#endif
+
+/* Remove a node from the hash table structure.
+   If duplicates are allowed, this function performs in average time
+   O((log n)^2): gl_oset_remove may need to remove an element from 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) on average.  */
+static void
+remove_from_bucket (gl_list_t list, gl_list_node_t old_node)
+{
+  size_t bucket = old_node->h.hashcode % list->table_size;
+
+  if (list->base.allow_duplicates)
+    {
+      size_t hashcode = old_node->h.hashcode;
+      const void *value = old_node->value;
+      gl_listelement_equals_fn equals = list->base.equals_fn;
+      gl_hash_entry_t *entryp;
+
+      for (entryp = &list->table[bucket]; ; entryp = &(*entryp)->hash_next)
+        {
+          gl_hash_entry_t entry = *entryp;
+
+          if (entry == &old_node->h)
+            {
+              /* Found old_node as a single node in the bucket.  Remove it.  */
+              *entryp = old_node->h.hash_next;
+              break;
+            }
+          if (entry == NULL)
+            /* node is not in the right bucket.  Did the hash codes
+               change inadvertently?  */
+            abort ();
+          if (((struct gl_multiple_nodes *) entry)->magic == MULTIPLE_NODES_MAGIC
+              && entry->hashcode == hashcode)
+            {
+              /* An entry representing multiple nodes.  */
+              gl_oset_t nodes = ((struct gl_multiple_nodes *) entry)->nodes;
+              /* Only the first node is interesting.  */
+              gl_list_node_t node = gl_oset_first (nodes);
+              if (equals != NULL ? equals (value, node->value) : value == node->value)
+                {
+                  /* Found multiple nodes with the same value.
+                     old_node must be one of them.  Remove it.  */
+                  if (!gl_oset_remove (nodes, old_node))
+                    abort ();
+                  if (gl_oset_size (nodes) == 1)
+                    {
+                      /* Replace a one-element set with a single node.  */
+                      node = gl_oset_first (nodes);
+                      node->h.hash_next = entry->hash_next;
+                      *entryp = &node->h;
+                      gl_oset_free (nodes);
+                      free (entry);
+                    }
+                  break;
+                }
+            }
+        }
+    }
+  else
+    {
+      /* If no duplicates are allowed, multiple nodes are not needed.  */
+      gl_hash_entry_t *entryp;
+
+      for (entryp = &list->table[bucket]; ; entryp = &(*entryp)->hash_next)
+        {
+          if (*entryp == &old_node->h)
+            {
+              *entryp = old_node->h.hash_next;
+              break;
+            }
+          if (*entryp == NULL)
+            /* node is not in the right bucket.  Did the hash codes
+               change inadvertently?  */
+            abort ();
+        }
+    }
+}
+
+/* Build up the hash table during initialization: Store all the nodes of
+   list->root in the hash table.
+   Return 0 upon success, -1 upon out-of-memory.  */
+static inline int
+add_nodes_to_buckets (gl_list_t list)
+{
+  /* Iterate across all nodes.  */
+  gl_list_node_t node = list->root;
+  iterstack_t stack;
+  iterstack_item_t *stack_ptr = &stack[0];
+
+  for (;;)
+    {
+      /* Descend on left branch.  */
+      for (;;)
+        {
+          if (node == NULL)
+            break;
+          stack_ptr->node = node;
+          stack_ptr->rightp = false;
+          node = node->left;
+          stack_ptr++;
+        }
+      /* Climb up again.  */
+      for (;;)
+        {
+          if (stack_ptr == &stack[0])
+            goto done;
+          stack_ptr--;
+          if (!stack_ptr->rightp)
+            break;
+        }
+      node = stack_ptr->node;
+      /* Add the current node to the hash table.  */
+      node->h.hashcode =
+        (list->base.hashcode_fn != NULL
+         ? list->base.hashcode_fn (node->value)
+         : (size_t)(uintptr_t) node->value);
+      if (add_to_bucket (list, node) < 0)
+        goto fail;
+      /* Descend on right branch.  */
+      stack_ptr->rightp = true;
+      node = node->right;
+      stack_ptr++;
+    }
+ done:
+  return 0;
+
+ fail:
+  /* Undo everything.  */
+  for (;;)
+    {
+      /* Descend on left branch.  */
+      stack_ptr->rightp = false;
+      node = node->left;
+      stack_ptr++;
+      /* Descend on right branch.  */
+      for (;;)
+        {
+          if (node == NULL)
+            break;
+          stack_ptr->node = node;
+          stack_ptr->rightp = true;
+          node = node->right;
+          stack_ptr++;
+        }
+      /* Climb up again.  */
+      for (;;)
+        {
+          if (stack_ptr == &stack[0])
+            goto fail_done;
+          stack_ptr--;
+          if (stack_ptr->rightp)
+            break;
+        }
+      node = stack_ptr->node;
+      /* Remove the current node from the hash table.  */
+      remove_from_bucket (list, node);
+    }
+ fail_done:
+  return -1;
+}
+/* Tell GCC that the likely return value is 0.  */
+#if __GNUC__ >= 3
+# define add_nodes_to_buckets(list) \
+    __builtin_expect ((add_nodes_to_buckets) (list), 0)
+#endif

+ 213 - 0
gnulib/lib/gl_anytreehash_list2.h

@@ -0,0 +1,213 @@
+/* Sequential list data type implemented by a hash table with a binary tree.
+   Copyright (C) 2006-2007, 2009-2012 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2006.
+
+   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/>.  */
+
+/* Common code of gl_avltreehash_list.c and gl_rbtreehash_list.c.  */
+
+static gl_list_node_t
+gl_tree_search_from_to (gl_list_t list, size_t start_index, size_t end_index,
+                        const void *elt)
+{
+  if (!(start_index <= end_index
+        && end_index <= (list->root != NULL ? list->root->branch_size : 0)))
+    /* Invalid arguments.  */
+    abort ();
+  {
+    size_t hashcode =
+      (list->base.hashcode_fn != NULL
+       ? list->base.hashcode_fn (elt)
+       : (size_t)(uintptr_t) elt);
+    size_t bucket = hashcode % list->table_size;
+    gl_listelement_equals_fn equals = list->base.equals_fn;
+    gl_hash_entry_t entry;
+
+    if (list->base.allow_duplicates)
+      {
+        for (entry = list->table[bucket]; entry != NULL; entry = entry->hash_next)
+          if (entry->hashcode == hashcode)
+            {
+              if (((struct gl_multiple_nodes *) entry)->magic == MULTIPLE_NODES_MAGIC)
+                {
+                  /* An entry representing multiple nodes.  */
+                  gl_oset_t nodes = ((struct gl_multiple_nodes *) entry)->nodes;
+                  /* The first node is interesting.  */
+                  gl_list_node_t node = gl_oset_first (nodes);
+                  if (equals != NULL ? equals (elt, node->value) : elt == node->value)
+                    {
+                      /* All nodes in the entry are equal to the given ELT.  */
+                      if (start_index == 0)
+                        {
+                          /* We have to return only the one at the minimal
+                             position, and this is the first one in the ordered
+                             set.  */
+                          if (end_index == list->root->branch_size
+                              || node_position (node) < end_index)
+                            return node;
+                        }
+                      else
+                        {
+                          /* We have to return only the one at the minimal
+                             position >= start_index.  */
+                          const void *elt;
+                          if (gl_oset_search_atleast (nodes,
+                                                      compare_position_threshold,
+                                                      (void *)(uintptr_t)start_index,
+                                                      &elt))
+                            {
+                              node = (gl_list_node_t) elt;
+                              if (end_index == list->root->branch_size
+                                  || node_position (node) < end_index)
+                                return node;
+                            }
+                        }
+                      break;
+                    }
+                }
+              else
+                {
+                  /* An entry representing a single node.  */
+                  gl_list_node_t node = (struct gl_list_node_impl *) entry;
+                  if (equals != NULL ? equals (elt, node->value) : elt == node->value)
+                    {
+                      bool position_in_bounds;
+                      if (start_index == 0 && end_index == list->root->branch_size)
+                        position_in_bounds = true;
+                      else
+                        {
+                          size_t position = node_position (node);
+                          position_in_bounds =
+                            (position >= start_index && position < end_index);
+                        }
+                      if (position_in_bounds)
+                        return node;
+                      break;
+                    }
+                }
+            }
+      }
+    else
+      {
+        /* If no duplicates are allowed, multiple nodes are not needed.  */
+        for (entry = list->table[bucket]; entry != NULL; entry = entry->hash_next)
+          if (entry->hashcode == hashcode)
+            {
+              gl_list_node_t node = (struct gl_list_node_impl *) entry;
+              if (equals != NULL ? equals (elt, node->value) : elt == node->value)
+                {
+                  bool position_in_bounds;
+                  if (start_index == 0 && end_index == list->root->branch_size)
+                    position_in_bounds = true;
+                  else
+                    {
+                      size_t position = node_position (node);
+                      position_in_bounds =
+                        (position >= start_index && position < end_index);
+                    }
+                  if (position_in_bounds)
+                    return node;
+                  break;
+                }
+            }
+      }
+
+    return NULL;
+  }
+}
+
+static size_t
+gl_tree_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index,
+                         const void *elt)
+{
+  gl_list_node_t node =
+    gl_tree_search_from_to (list, start_index, end_index, elt);
+
+  if (node != NULL)
+    return node_position (node);
+  else
+    return (size_t)(-1);
+}
+
+static void
+gl_tree_list_free (gl_list_t list)
+{
+  if (list->base.allow_duplicates)
+    {
+      /* Free the ordered sets in the hash buckets.  */
+      size_t i;
+
+      for (i = list->table_size; i > 0; )
+        {
+          gl_hash_entry_t entry = list->table[--i];
+
+          while (entry != NULL)
+            {
+              gl_hash_entry_t next = entry->hash_next;
+
+              if (((struct gl_multiple_nodes *) entry)->magic == MULTIPLE_NODES_MAGIC)
+                {
+                  gl_oset_t nodes = ((struct gl_multiple_nodes *) entry)->nodes;
+
+                  gl_oset_free (nodes);
+                  free (entry);
+                }
+
+              entry = next;
+            }
+        }
+    }
+
+  /* Iterate across all elements in post-order.  */
+  {
+    gl_list_node_t node = list->root;
+    iterstack_t stack;
+    iterstack_item_t *stack_ptr = &stack[0];
+
+    for (;;)
+      {
+        /* Descend on left branch.  */
+        for (;;)
+          {
+            if (node == NULL)
+              break;
+            stack_ptr->node = node;
+            stack_ptr->rightp = false;
+            node = node->left;
+            stack_ptr++;
+          }
+        /* Climb up again.  */
+        for (;;)
+          {
+            if (stack_ptr == &stack[0])
+              goto done_iterate;
+            stack_ptr--;
+            node = stack_ptr->node;
+            if (!stack_ptr->rightp)
+              break;
+            /* Free the current node.  */
+            if (list->base.dispose_fn != NULL)
+              list->base.dispose_fn (node->value);
+            free (node);
+          }
+        /* Descend on right branch.  */
+        stack_ptr->rightp = true;
+        node = node->right;
+        stack_ptr++;
+      }
+  }
+ done_iterate:
+  free (list->table);
+  free (list);
+}