Browse Source

Add gnulib and Flex generated files

This will lesson the dependencies for those who wish to build the
program.
Andrew Young 8 years ago
parent
commit
1dbd66de05

+ 0 - 21
gnulib/lib/.gitignore

@@ -1,21 +0,0 @@
-/Makefile.am
-/diffseq.h
-/gl_array_list.c
-/gl_array_list.h
-/gl_list.c
-/gl_list.h
-/minmax.h
-/size_max.h
-/stdbool.in.h
-/xsize.h
-/gl_anyhash_list1.h
-/gl_anyhash_list2.h
-/gl_oset.c
-/gl_oset.h
-/gl_rbtree_oset.c
-/gl_rbtree_oset.h
-/gl_rbtreehash_list.c
-/gl_rbtreehash_list.h
-/stdint.in.h
-/gl_rbtree_list.c
-/gl_rbtree_list.h

+ 191 - 0
gnulib/lib/Makefile.am

@@ -0,0 +1,191 @@
+## DO NOT EDIT! GENERATED AUTOMATICALLY!
+## Process this file with automake to produce Makefile.in.
+# Copyright (C) 2002-2012 Free Software Foundation, Inc.
+#
+# This file 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 file 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 file.  If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License,
+# this file may be distributed as part of a program that
+# contains a configuration script generated by Autoconf, under
+# the same distribution terms as the rest of that program.
+#
+# Generated by gnulib-tool.
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gnulib/lib --m4-base=m4 --doc-base=gnulib/doc --tests-base=gnulib/tests --aux-dir=config --no-conditional-dependencies --no-libtool --macro-prefix=gl array-list diffseq minmax rb_list rbtree-list rbtreehash-list
+
+AUTOMAKE_OPTIONS = 1.5 gnits
+
+SUBDIRS =
+noinst_HEADERS =
+noinst_LIBRARIES =
+noinst_LTLIBRARIES =
+EXTRA_DIST =
+BUILT_SOURCES =
+SUFFIXES =
+MOSTLYCLEANFILES = core *.stackdump
+MOSTLYCLEANDIRS =
+CLEANFILES =
+DISTCLEANFILES =
+MAINTAINERCLEANFILES =
+
+AM_CPPFLAGS =
+AM_CFLAGS =
+
+noinst_LIBRARIES += libgnu.a
+
+libgnu_a_SOURCES =
+libgnu_a_LIBADD = $(gl_LIBOBJS)
+libgnu_a_DEPENDENCIES = $(gl_LIBOBJS)
+EXTRA_libgnu_a_SOURCES =
+
+## begin gnulib module array-list
+
+libgnu_a_SOURCES += gl_array_list.h gl_array_list.c
+
+## end   gnulib module array-list
+
+## begin gnulib module diffseq
+
+libgnu_a_SOURCES += diffseq.h
+
+## end   gnulib module diffseq
+
+## begin gnulib module list
+
+libgnu_a_SOURCES += gl_list.h gl_list.c
+
+## end   gnulib module list
+
+## begin gnulib module minmax
+
+libgnu_a_SOURCES += minmax.h
+
+## end   gnulib module minmax
+
+## begin gnulib module oset
+
+libgnu_a_SOURCES += gl_oset.h gl_oset.c
+
+## end   gnulib module oset
+
+## begin gnulib module rbtree-list
+
+libgnu_a_SOURCES += gl_rbtree_list.h gl_rbtree_list.c gl_anyrbtree_list1.h gl_anyrbtree_list2.h gl_anytree_list1.h gl_anytree_list2.h
+
+## end   gnulib module rbtree-list
+
+## begin gnulib module rbtree-oset
+
+libgnu_a_SOURCES += gl_rbtree_oset.h gl_rbtree_oset.c gl_anytree_oset.h
+
+## end   gnulib module rbtree-oset
+
+## begin gnulib module rbtreehash-list
+
+libgnu_a_SOURCES += gl_rbtreehash_list.h gl_rbtreehash_list.c 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_anytreehash_list1.h gl_anytreehash_list2.h
+
+## end   gnulib module rbtreehash-list
+
+## begin gnulib module size_max
+
+libgnu_a_SOURCES += size_max.h
+
+## end   gnulib module size_max
+
+## begin gnulib module stdbool
+
+BUILT_SOURCES += $(STDBOOL_H)
+
+# We need the following in order to create <stdbool.h> when the system
+# doesn't have one that works.
+if GL_GENERATE_STDBOOL_H
+stdbool.h: stdbool.in.h $(top_builddir)/config.status
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+else
+stdbool.h: $(top_builddir)/config.status
+	rm -f $@
+endif
+MOSTLYCLEANFILES += stdbool.h stdbool.h-t
+
+EXTRA_DIST += stdbool.in.h
+
+## end   gnulib module stdbool
+
+## begin gnulib module stdint
+
+BUILT_SOURCES += $(STDINT_H)
+
+# We need the following in order to create <stdint.h> when the system
+# doesn't have one that works with the given compiler.
+if GL_GENERATE_STDINT_H
+stdint.h: stdint.in.h $(top_builddir)/config.status
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's/@''HAVE_STDINT_H''@/$(HAVE_STDINT_H)/g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_STDINT_H''@|$(NEXT_STDINT_H)|g' \
+	      -e 's/@''HAVE_SYS_TYPES_H''@/$(HAVE_SYS_TYPES_H)/g' \
+	      -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \
+	      -e 's/@''HAVE_SYS_INTTYPES_H''@/$(HAVE_SYS_INTTYPES_H)/g' \
+	      -e 's/@''HAVE_SYS_BITYPES_H''@/$(HAVE_SYS_BITYPES_H)/g' \
+	      -e 's/@''HAVE_WCHAR_H''@/$(HAVE_WCHAR_H)/g' \
+	      -e 's/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \
+	      -e 's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/g' \
+	      -e 's/@''APPLE_UNIVERSAL_BUILD''@/$(APPLE_UNIVERSAL_BUILD)/g' \
+	      -e 's/@''BITSIZEOF_PTRDIFF_T''@/$(BITSIZEOF_PTRDIFF_T)/g' \
+	      -e 's/@''PTRDIFF_T_SUFFIX''@/$(PTRDIFF_T_SUFFIX)/g' \
+	      -e 's/@''BITSIZEOF_SIG_ATOMIC_T''@/$(BITSIZEOF_SIG_ATOMIC_T)/g' \
+	      -e 's/@''HAVE_SIGNED_SIG_ATOMIC_T''@/$(HAVE_SIGNED_SIG_ATOMIC_T)/g' \
+	      -e 's/@''SIG_ATOMIC_T_SUFFIX''@/$(SIG_ATOMIC_T_SUFFIX)/g' \
+	      -e 's/@''BITSIZEOF_SIZE_T''@/$(BITSIZEOF_SIZE_T)/g' \
+	      -e 's/@''SIZE_T_SUFFIX''@/$(SIZE_T_SUFFIX)/g' \
+	      -e 's/@''BITSIZEOF_WCHAR_T''@/$(BITSIZEOF_WCHAR_T)/g' \
+	      -e 's/@''HAVE_SIGNED_WCHAR_T''@/$(HAVE_SIGNED_WCHAR_T)/g' \
+	      -e 's/@''WCHAR_T_SUFFIX''@/$(WCHAR_T_SUFFIX)/g' \
+	      -e 's/@''BITSIZEOF_WINT_T''@/$(BITSIZEOF_WINT_T)/g' \
+	      -e 's/@''HAVE_SIGNED_WINT_T''@/$(HAVE_SIGNED_WINT_T)/g' \
+	      -e 's/@''WINT_T_SUFFIX''@/$(WINT_T_SUFFIX)/g' \
+	      < $(srcdir)/stdint.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+else
+stdint.h: $(top_builddir)/config.status
+	rm -f $@
+endif
+MOSTLYCLEANFILES += stdint.h stdint.h-t
+
+EXTRA_DIST += stdint.in.h
+
+## end   gnulib module stdint
+
+## begin gnulib module xsize
+
+libgnu_a_SOURCES += xsize.h
+
+## end   gnulib module xsize
+
+
+mostlyclean-local: mostlyclean-generic
+	@for dir in '' $(MOSTLYCLEANDIRS); do \
+	  if test -n "$$dir" && test -d $$dir; then \
+	    echo "rmdir $$dir"; rmdir $$dir; \
+	  fi; \
+	done; \
+	:

+ 523 - 0
gnulib/lib/diffseq.h

@@ -0,0 +1,523 @@
+/* Analyze differences between two vectors.
+
+   Copyright (C) 1988-1989, 1992-1995, 2001-2004, 2006-2012 Free Software
+   Foundation, Inc.
+
+   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/>.  */
+
+
+/* The basic idea is to consider two vectors as similar if, when
+   transforming the first vector into the second vector through a
+   sequence of edits (inserts and deletes of one element each),
+   this sequence is short - or equivalently, if the ordered list
+   of elements that are untouched by these edits is long.  For a
+   good introduction to the subject, read about the "Levenshtein
+   distance" in Wikipedia.
+
+   The basic algorithm is described in:
+   "An O(ND) Difference Algorithm and its Variations", Eugene Myers,
+   Algorithmica Vol. 1 No. 2, 1986, pp. 251-266;
+   see especially section 4.2, which describes the variation used below.
+
+   The basic algorithm was independently discovered as described in:
+   "Algorithms for Approximate String Matching", E. Ukkonen,
+   Information and Control Vol. 64, 1985, pp. 100-118.
+
+   Unless the 'find_minimal' flag is set, this code uses the TOO_EXPENSIVE
+   heuristic, by Paul Eggert, to limit the cost to O(N**1.5 log N)
+   at the price of producing suboptimal output for large inputs with
+   many differences.  */
+
+/* Before including this file, you need to define:
+     ELEMENT                 The element type of the vectors being compared.
+     EQUAL                   A two-argument macro that tests two elements for
+                             equality.
+     OFFSET                  A signed integer type sufficient to hold the
+                             difference between two indices. Usually
+                             something like ssize_t.
+     EXTRA_CONTEXT_FIELDS    Declarations of fields for 'struct context'.
+     NOTE_DELETE(ctxt, xoff) Record the removal of the object xvec[xoff].
+     NOTE_INSERT(ctxt, yoff) Record the insertion of the object yvec[yoff].
+     EARLY_ABORT(ctxt)       (Optional) A boolean expression that triggers an
+                             early abort of the computation.
+     USE_HEURISTIC           (Optional) Define if you want to support the
+                             heuristic for large vectors.
+   It is also possible to use this file with abstract arrays.  In this case,
+   xvec and yvec are not represented in memory.  They only exist conceptually.
+   In this case, the list of defines above is amended as follows:
+     ELEMENT                 Undefined.
+     EQUAL                   Undefined.
+     XVECREF_YVECREF_EQUAL(ctxt, xoff, yoff)
+                             A three-argument macro: References xvec[xoff] and
+                             yvec[yoff] and tests these elements for equality.
+   Before including this file, you also need to include:
+     #include <limits.h>
+     #include <stdbool.h>
+     #include "minmax.h"
+ */
+
+/* Maximum value of type OFFSET.  */
+#define OFFSET_MAX \
+  ((((OFFSET)1 << (sizeof (OFFSET) * CHAR_BIT - 2)) - 1) * 2 + 1)
+
+/* Default to no early abort.  */
+#ifndef EARLY_ABORT
+# define EARLY_ABORT(ctxt) false
+#endif
+
+/* Use this to suppress gcc's "...may be used before initialized" warnings.
+   Beware: The Code argument must not contain commas.  */
+#ifndef IF_LINT
+# ifdef lint
+#  define IF_LINT(Code) Code
+# else
+#  define IF_LINT(Code) /* empty */
+# endif
+#endif
+
+/* As above, but when Code must contain one comma. */
+#ifndef IF_LINT2
+# ifdef lint
+#  define IF_LINT2(Code1, Code2) Code1, Code2
+# else
+#  define IF_LINT2(Code1, Code2) /* empty */
+# endif
+#endif
+
+/*
+ * Context of comparison operation.
+ */
+struct context
+{
+  #ifdef ELEMENT
+  /* Vectors being compared.  */
+  ELEMENT const *xvec;
+  ELEMENT const *yvec;
+  #endif
+
+  /* Extra fields.  */
+  EXTRA_CONTEXT_FIELDS
+
+  /* Vector, indexed by diagonal, containing 1 + the X coordinate of the point
+     furthest along the given diagonal in the forward search of the edit
+     matrix.  */
+  OFFSET *fdiag;
+
+  /* Vector, indexed by diagonal, containing the X coordinate of the point
+     furthest along the given diagonal in the backward search of the edit
+     matrix.  */
+  OFFSET *bdiag;
+
+  #ifdef USE_HEURISTIC
+  /* This corresponds to the diff -H flag.  With this heuristic, for
+     vectors with a constant small density of changes, the algorithm is
+     linear in the vectors size.  */
+  bool heuristic;
+  #endif
+
+  /* Edit scripts longer than this are too expensive to compute.  */
+  OFFSET too_expensive;
+
+  /* Snakes bigger than this are considered "big".  */
+  #define SNAKE_LIMIT 20
+};
+
+struct partition
+{
+  /* Midpoints of this partition.  */
+  OFFSET xmid;
+  OFFSET ymid;
+
+  /* True if low half will be analyzed minimally.  */
+  bool lo_minimal;
+
+  /* Likewise for high half.  */
+  bool hi_minimal;
+};
+
+
+/* Find the midpoint of the shortest edit script for a specified portion
+   of the two vectors.
+
+   Scan from the beginnings of the vectors, and simultaneously from the ends,
+   doing a breadth-first search through the space of edit-sequence.
+   When the two searches meet, we have found the midpoint of the shortest
+   edit sequence.
+
+   If FIND_MINIMAL is true, find the minimal edit script regardless of
+   expense.  Otherwise, if the search is too expensive, use heuristics to
+   stop the search and report a suboptimal answer.
+
+   Set PART->(xmid,ymid) to the midpoint (XMID,YMID).  The diagonal number
+   XMID - YMID equals the number of inserted elements minus the number
+   of deleted elements (counting only elements before the midpoint).
+
+   Set PART->lo_minimal to true iff the minimal edit script for the
+   left half of the partition is known; similarly for PART->hi_minimal.
+
+   This function assumes that the first elements of the specified portions
+   of the two vectors do not match, and likewise that the last elements do not
+   match.  The caller must trim matching elements from the beginning and end
+   of the portions it is going to specify.
+
+   If we return the "wrong" partitions, the worst this can do is cause
+   suboptimal diff output.  It cannot cause incorrect diff output.  */
+
+static void
+diag (OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim, bool find_minimal,
+      struct partition *part, struct context *ctxt)
+{
+  OFFSET *const fd = ctxt->fdiag;       /* Give the compiler a chance. */
+  OFFSET *const bd = ctxt->bdiag;       /* Additional help for the compiler. */
+#ifdef ELEMENT
+  ELEMENT const *const xv = ctxt->xvec; /* Still more help for the compiler. */
+  ELEMENT const *const yv = ctxt->yvec; /* And more and more . . . */
+  #define XREF_YREF_EQUAL(x,y)  EQUAL (xv[x], yv[y])
+#else
+  #define XREF_YREF_EQUAL(x,y)  XVECREF_YVECREF_EQUAL (ctxt, x, y)
+#endif
+  const OFFSET dmin = xoff - ylim;      /* Minimum valid diagonal. */
+  const OFFSET dmax = xlim - yoff;      /* Maximum valid diagonal. */
+  const OFFSET fmid = xoff - yoff;      /* Center diagonal of top-down search. */
+  const OFFSET bmid = xlim - ylim;      /* Center diagonal of bottom-up search. */
+  OFFSET fmin = fmid;
+  OFFSET fmax = fmid;           /* Limits of top-down search. */
+  OFFSET bmin = bmid;
+  OFFSET bmax = bmid;           /* Limits of bottom-up search. */
+  OFFSET c;                     /* Cost. */
+  bool odd = (fmid - bmid) & 1; /* True if southeast corner is on an odd
+                                   diagonal with respect to the northwest. */
+
+  fd[fmid] = xoff;
+  bd[bmid] = xlim;
+
+  for (c = 1;; ++c)
+    {
+      OFFSET d;                 /* Active diagonal. */
+      bool big_snake = false;
+
+      /* Extend the top-down search by an edit step in each diagonal. */
+      if (fmin > dmin)
+        fd[--fmin - 1] = -1;
+      else
+        ++fmin;
+      if (fmax < dmax)
+        fd[++fmax + 1] = -1;
+      else
+        --fmax;
+      for (d = fmax; d >= fmin; d -= 2)
+        {
+          OFFSET x;
+          OFFSET y;
+          OFFSET tlo = fd[d - 1];
+          OFFSET thi = fd[d + 1];
+          OFFSET x0 = tlo < thi ? thi : tlo + 1;
+
+          for (x = x0, y = x0 - d;
+               x < xlim && y < ylim && XREF_YREF_EQUAL (x, y);
+               x++, y++)
+            continue;
+          if (x - x0 > SNAKE_LIMIT)
+            big_snake = true;
+          fd[d] = x;
+          if (odd && bmin <= d && d <= bmax && bd[d] <= x)
+            {
+              part->xmid = x;
+              part->ymid = y;
+              part->lo_minimal = part->hi_minimal = true;
+              return;
+            }
+        }
+
+      /* Similarly extend the bottom-up search.  */
+      if (bmin > dmin)
+        bd[--bmin - 1] = OFFSET_MAX;
+      else
+        ++bmin;
+      if (bmax < dmax)
+        bd[++bmax + 1] = OFFSET_MAX;
+      else
+        --bmax;
+      for (d = bmax; d >= bmin; d -= 2)
+        {
+          OFFSET x;
+          OFFSET y;
+          OFFSET tlo = bd[d - 1];
+          OFFSET thi = bd[d + 1];
+          OFFSET x0 = tlo < thi ? tlo : thi - 1;
+
+          for (x = x0, y = x0 - d;
+               xoff < x && yoff < y && XREF_YREF_EQUAL (x - 1, y - 1);
+               x--, y--)
+            continue;
+          if (x0 - x > SNAKE_LIMIT)
+            big_snake = true;
+          bd[d] = x;
+          if (!odd && fmin <= d && d <= fmax && x <= fd[d])
+            {
+              part->xmid = x;
+              part->ymid = y;
+              part->lo_minimal = part->hi_minimal = true;
+              return;
+            }
+        }
+
+      if (find_minimal)
+        continue;
+
+#ifdef USE_HEURISTIC
+      /* Heuristic: check occasionally for a diagonal that has made lots
+         of progress compared with the edit distance.  If we have any
+         such, find the one that has made the most progress and return it
+         as if it had succeeded.
+
+         With this heuristic, for vectors with a constant small density
+         of changes, the algorithm is linear in the vector size.  */
+
+      if (200 < c && big_snake && ctxt->heuristic)
+        {
+          {
+            OFFSET best = 0;
+
+            for (d = fmax; d >= fmin; d -= 2)
+              {
+                OFFSET dd = d - fmid;
+                OFFSET x = fd[d];
+                OFFSET y = x - d;
+                OFFSET v = (x - xoff) * 2 - dd;
+
+                if (v > 12 * (c + (dd < 0 ? -dd : dd)))
+                  {
+                    if (v > best
+                        && xoff + SNAKE_LIMIT <= x && x < xlim
+                        && yoff + SNAKE_LIMIT <= y && y < ylim)
+                      {
+                        /* We have a good enough best diagonal; now insist
+                           that it end with a significant snake.  */
+                        int k;
+
+                        for (k = 1; XREF_YREF_EQUAL (x - k, y - k); k++)
+                          if (k == SNAKE_LIMIT)
+                            {
+                              best = v;
+                              part->xmid = x;
+                              part->ymid = y;
+                              break;
+                            }
+                      }
+                  }
+              }
+            if (best > 0)
+              {
+                part->lo_minimal = true;
+                part->hi_minimal = false;
+                return;
+              }
+          }
+
+          {
+            OFFSET best = 0;
+
+            for (d = bmax; d >= bmin; d -= 2)
+              {
+                OFFSET dd = d - bmid;
+                OFFSET x = bd[d];
+                OFFSET y = x - d;
+                OFFSET v = (xlim - x) * 2 + dd;
+
+                if (v > 12 * (c + (dd < 0 ? -dd : dd)))
+                  {
+                    if (v > best
+                        && xoff < x && x <= xlim - SNAKE_LIMIT
+                        && yoff < y && y <= ylim - SNAKE_LIMIT)
+                      {
+                        /* We have a good enough best diagonal; now insist
+                           that it end with a significant snake.  */
+                        int k;
+
+                        for (k = 0; XREF_YREF_EQUAL (x + k, y + k); k++)
+                          if (k == SNAKE_LIMIT - 1)
+                            {
+                              best = v;
+                              part->xmid = x;
+                              part->ymid = y;
+                              break;
+                            }
+                      }
+                  }
+              }
+            if (best > 0)
+              {
+                part->lo_minimal = false;
+                part->hi_minimal = true;
+                return;
+              }
+          }
+        }
+#endif /* USE_HEURISTIC */
+
+      /* Heuristic: if we've gone well beyond the call of duty, give up
+         and report halfway between our best results so far.  */
+      if (c >= ctxt->too_expensive)
+        {
+          OFFSET fxybest;
+          OFFSET fxbest IF_LINT (= 0);
+          OFFSET bxybest;
+          OFFSET bxbest IF_LINT (= 0);
+
+          /* Find forward diagonal that maximizes X + Y.  */
+          fxybest = -1;
+          for (d = fmax; d >= fmin; d -= 2)
+            {
+              OFFSET x = MIN (fd[d], xlim);
+              OFFSET y = x - d;
+              if (ylim < y)
+                {
+                  x = ylim + d;
+                  y = ylim;
+                }
+              if (fxybest < x + y)
+                {
+                  fxybest = x + y;
+                  fxbest = x;
+                }
+            }
+
+          /* Find backward diagonal that minimizes X + Y.  */
+          bxybest = OFFSET_MAX;
+          for (d = bmax; d >= bmin; d -= 2)
+            {
+              OFFSET x = MAX (xoff, bd[d]);
+              OFFSET y = x - d;
+              if (y < yoff)
+                {
+                  x = yoff + d;
+                  y = yoff;
+                }
+              if (x + y < bxybest)
+                {
+                  bxybest = x + y;
+                  bxbest = x;
+                }
+            }
+
+          /* Use the better of the two diagonals.  */
+          if ((xlim + ylim) - bxybest < fxybest - (xoff + yoff))
+            {
+              part->xmid = fxbest;
+              part->ymid = fxybest - fxbest;
+              part->lo_minimal = true;
+              part->hi_minimal = false;
+            }
+          else
+            {
+              part->xmid = bxbest;
+              part->ymid = bxybest - bxbest;
+              part->lo_minimal = false;
+              part->hi_minimal = true;
+            }
+          return;
+        }
+    }
+  #undef XREF_YREF_EQUAL
+}
+
+
+/* Compare in detail contiguous subsequences of the two vectors
+   which are known, as a whole, to match each other.
+
+   The subsequence of vector 0 is [XOFF, XLIM) and likewise for vector 1.
+
+   Note that XLIM, YLIM are exclusive bounds.  All indices into the vectors
+   are origin-0.
+
+   If FIND_MINIMAL, find a minimal difference no matter how
+   expensive it is.
+
+   The results are recorded by invoking NOTE_DELETE and NOTE_INSERT.
+
+   Return false if terminated normally, or true if terminated through early
+   abort.  */
+
+static bool
+compareseq (OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim,
+            bool find_minimal, struct context *ctxt)
+{
+#ifdef ELEMENT
+  ELEMENT const *xv = ctxt->xvec; /* Help the compiler.  */
+  ELEMENT const *yv = ctxt->yvec;
+  #define XREF_YREF_EQUAL(x,y)  EQUAL (xv[x], yv[y])
+#else
+  #define XREF_YREF_EQUAL(x,y)  XVECREF_YVECREF_EQUAL (ctxt, x, y)
+#endif
+
+  /* Slide down the bottom initial diagonal.  */
+  while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xoff, yoff))
+    {
+      xoff++;
+      yoff++;
+    }
+
+  /* Slide up the top initial diagonal. */
+  while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xlim - 1, ylim - 1))
+    {
+      xlim--;
+      ylim--;
+    }
+
+  /* Handle simple cases. */
+  if (xoff == xlim)
+    while (yoff < ylim)
+      {
+        NOTE_INSERT (ctxt, yoff);
+        if (EARLY_ABORT (ctxt))
+          return true;
+        yoff++;
+      }
+  else if (yoff == ylim)
+    while (xoff < xlim)
+      {
+        NOTE_DELETE (ctxt, xoff);
+        if (EARLY_ABORT (ctxt))
+          return true;
+        xoff++;
+      }
+  else
+    {
+      struct partition part IF_LINT2 (= { .xmid = 0, .ymid = 0 });
+
+      /* Find a point of correspondence in the middle of the vectors.  */
+      diag (xoff, xlim, yoff, ylim, find_minimal, &part, ctxt);
+
+      /* Use the partitions to split this problem into subproblems.  */
+      if (compareseq (xoff, part.xmid, yoff, part.ymid, part.lo_minimal, ctxt))
+        return true;
+      if (compareseq (part.xmid, xlim, part.ymid, ylim, part.hi_minimal, ctxt))
+        return true;
+    }
+
+  return false;
+  #undef XREF_YREF_EQUAL
+}
+
+#undef ELEMENT
+#undef EQUAL
+#undef OFFSET
+#undef EXTRA_CONTEXT_FIELDS
+#undef NOTE_DELETE
+#undef NOTE_INSERT
+#undef EARLY_ABORT
+#undef USE_HEURISTIC
+#undef XVECREF_YVECREF_EQUAL
+#undef OFFSET_MAX

+ 27 - 0
gnulib/lib/gl_anyhash_list1.h

@@ -0,0 +1,27 @@
+/* Sequential list data type implemented by a hash table with another list.
+   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_linkedhash_list.c, gl_avltreehash_list.c, gl_rbtreehash_list.c.  */
+
+/* Hash table entry.  */
+struct gl_hash_entry
+{
+  struct gl_hash_entry *hash_next;  /* chain of entries in same bucket */
+  size_t hashcode;                  /* cache of values' common hash code */
+};
+typedef struct gl_hash_entry * gl_hash_entry_t;

+ 138 - 0
gnulib/lib/gl_anyhash_list2.h

@@ -0,0 +1,138 @@
+/* Sequential list data type implemented by a hash table with another list.
+   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_linkedhash_list.c, gl_avltreehash_list.c, gl_rbtreehash_list.c.  */
+
+/* Array of primes, approximately in steps of factor 1.2.
+   This table was computed by executing the Common Lisp expression
+     (dotimes (i 244) (format t "nextprime(~D)~%" (ceiling (expt 1.2d0 i))))
+   and feeding the result to PARI/gp.  */
+static const size_t primes[] =
+  {
+    11, 13, 17, 19, 23, 29, 37, 41, 47, 59, 67, 83, 97, 127, 139, 167, 199,
+    239, 293, 347, 419, 499, 593, 709, 853, 1021, 1229, 1471, 1777, 2129, 2543,
+    3049, 3659, 4391, 5273, 6323, 7589, 9103, 10937, 13109, 15727, 18899,
+    22651, 27179, 32609, 39133, 46957, 56359, 67619, 81157, 97369, 116849,
+    140221, 168253, 201907, 242309, 290761, 348889, 418667, 502409, 602887,
+    723467, 868151, 1041779, 1250141, 1500181, 1800191, 2160233, 2592277,
+    3110741, 3732887, 4479463, 5375371, 6450413, 7740517, 9288589, 11146307,
+    13375573, 16050689, 19260817, 23112977, 27735583, 33282701, 39939233,
+    47927081, 57512503, 69014987, 82818011, 99381577, 119257891, 143109469,
+    171731387, 206077643, 247293161, 296751781, 356102141, 427322587,
+    512787097, 615344489, 738413383, 886096061, 1063315271, 1275978331,
+    1531174013, 1837408799, 2204890543UL, 2645868653UL, 3175042391UL,
+    3810050851UL,
+#if SIZE_MAX > 4294967295UL
+    4572061027UL, 5486473229UL, 6583767889UL, 7900521449UL, 9480625733UL,
+    11376750877UL, 13652101063UL, 16382521261UL, 19659025513UL, 23590830631UL,
+    28308996763UL, 33970796089UL, 40764955463UL, 48917946377UL, 58701535657UL,
+    70441842749UL, 84530211301UL, 101436253561UL, 121723504277UL,
+    146068205131UL, 175281846149UL, 210338215379UL, 252405858521UL,
+    302887030151UL, 363464436191UL, 436157323417UL, 523388788231UL,
+    628066545713UL, 753679854847UL, 904415825857UL, 1085298991109UL,
+    1302358789181UL, 1562830547009UL, 1875396656429UL, 2250475987709UL,
+    2700571185239UL, 3240685422287UL, 3888822506759UL, 4666587008147UL,
+    5599904409713UL, 6719885291641UL, 8063862349969UL, 9676634819959UL,
+    11611961783951UL, 13934354140769UL, 16721224968907UL, 20065469962669UL,
+    24078563955191UL, 28894276746229UL, 34673132095507UL, 41607758514593UL,
+    49929310217531UL, 59915172260971UL, 71898206713183UL, 86277848055823UL,
+    103533417666967UL, 124240101200359UL, 149088121440451UL, 178905745728529UL,
+    214686894874223UL, 257624273849081UL, 309149128618903UL, 370978954342639UL,
+    445174745211143UL, 534209694253381UL, 641051633104063UL, 769261959724877UL,
+    923114351670013UL, 1107737222003791UL, 1329284666404567UL,
+    1595141599685509UL, 1914169919622551UL, 2297003903547091UL,
+    2756404684256459UL, 3307685621107757UL, 3969222745329323UL,
+    4763067294395177UL, 5715680753274209UL, 6858816903929113UL,
+    8230580284714831UL, 9876696341657791UL, 11852035609989371UL,
+    14222442731987227UL, 17066931278384657UL, 20480317534061597UL,
+    24576381040873903UL, 29491657249048679UL, 35389988698858471UL,
+    42467986438630267UL, 50961583726356109UL, 61153900471627387UL,
+    73384680565952851UL, 88061616679143347UL, 105673940014972061UL,
+    126808728017966413UL, 152170473621559703UL, 182604568345871671UL,
+    219125482015045997UL, 262950578418055169UL, 315540694101666193UL,
+    378648832921999397UL, 454378599506399233UL, 545254319407679131UL,
+    654305183289214771UL, 785166219947057701UL, 942199463936469157UL,
+    1130639356723763129UL, 1356767228068515623UL, 1628120673682218619UL,
+    1953744808418662409UL, 2344493770102394881UL, 2813392524122873857UL,
+    3376071028947448339UL, 4051285234736937517UL, 4861542281684325481UL,
+    5833850738021191727UL, 7000620885625427969UL, 8400745062750513217UL,
+    10080894075300616261UL, 12097072890360739951UL, 14516487468432885797UL,
+    17419784962119465179UL,
+#endif
+    SIZE_MAX /* sentinel, to ensure the search terminates */
+  };
+
+/* Return a suitable prime >= ESTIMATE.  */
+static size_t
+next_prime (size_t estimate)
+{
+  size_t i;
+
+  for (i = 0; i < sizeof (primes) / sizeof (primes[0]); i++)
+    if (primes[i] >= estimate)
+      return primes[i];
+  return SIZE_MAX; /* not a prime, but better than nothing */
+}
+
+/* Resize the hash table with a new estimated size.  */
+static void
+hash_resize (gl_list_t list, size_t estimate)
+{
+  size_t new_size = next_prime (estimate);
+
+  if (new_size > list->table_size)
+    {
+      gl_hash_entry_t *old_table = list->table;
+      /* Allocate the new table.  */
+      gl_hash_entry_t *new_table;
+      size_t i;
+
+      if (size_overflow_p (xtimes (new_size, sizeof (gl_hash_entry_t))))
+        goto fail;
+      new_table =
+        (gl_hash_entry_t *) calloc (new_size, sizeof (gl_hash_entry_t));
+      if (new_table == NULL)
+        goto fail;
+
+      /* Iterate through the entries of the old table.  */
+      for (i = list->table_size; i > 0; )
+        {
+          gl_hash_entry_t node = old_table[--i];
+
+          while (node != NULL)
+            {
+              gl_hash_entry_t next = node->hash_next;
+              /* Add the entry to the new table.  */
+              size_t bucket = node->hashcode % new_size;
+              node->hash_next = new_table[bucket];
+              new_table[bucket] = node;
+
+              node = next;
+            }
+        }
+
+      list->table = new_table;
+      list->table_size = new_size;
+      free (old_table);
+    }
+  return;
+
+ fail:
+  /* Just continue without resizing the table.  */
+  return;
+}

+ 680 - 0
gnulib/lib/gl_array_list.c

@@ -0,0 +1,680 @@
+/* Sequential list data type implemented by an array.
+   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/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "gl_array_list.h"
+
+#include <stdlib.h>
+/* Get memcpy.  */
+#include <string.h>
+
+/* Checked size_t computations.  */
+#include "xsize.h"
+
+#ifndef uintptr_t
+# define uintptr_t unsigned long
+#endif
+
+/* -------------------------- gl_list_t Data Type -------------------------- */
+
+/* Concrete gl_list_impl type, valid for this file only.  */
+struct gl_list_impl
+{
+  struct gl_list_impl_base base;
+  /* An array of ALLOCATED elements, of which the first COUNT are used.
+     0 <= COUNT <= ALLOCATED.  */
+  const void **elements;
+  size_t count;
+  size_t allocated;
+};
+
+/* struct gl_list_node_impl doesn't exist here.  The pointers are actually
+   indices + 1.  */
+#define INDEX_TO_NODE(index) (gl_list_node_t)(uintptr_t)(size_t)((index) + 1)
+#define NODE_TO_INDEX(node) ((uintptr_t)(node) - 1)
+
+static gl_list_t
+gl_array_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;
+  list->elements = NULL;
+  list->count = 0;
+  list->allocated = 0;
+
+  return list;
+}
+
+static gl_list_t
+gl_array_nx_create (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,
+                    size_t count, const void **contents)
+{
+  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 (count > 0)
+    {
+      if (size_overflow_p (xtimes (count, sizeof (const void *))))
+        goto fail;
+      list->elements = (const void **) malloc (count * sizeof (const void *));
+      if (list->elements == NULL)
+        goto fail;
+      memcpy (list->elements, contents, count * sizeof (const void *));
+    }
+  else
+    list->elements = NULL;
+  list->count = count;
+  list->allocated = count;
+
+  return list;
+
+ fail:
+  free (list);
+  return NULL;
+}
+
+static size_t
+gl_array_size (gl_list_t list)
+{
+  return list->count;
+}
+
+static const void *
+gl_array_node_value (gl_list_t list, gl_list_node_t node)
+{
+  uintptr_t index = NODE_TO_INDEX (node);
+  if (!(index < list->count))
+    /* Invalid argument.  */
+    abort ();
+  return list->elements[index];
+}
+
+static int
+gl_array_node_nx_set_value (gl_list_t list, gl_list_node_t node,
+                            const void *elt)
+{
+  uintptr_t index = NODE_TO_INDEX (node);
+  if (!(index < list->count))
+    /* Invalid argument.  */
+    abort ();
+  list->elements[index] = elt;
+  return 0;
+}
+
+static gl_list_node_t
+gl_array_next_node (gl_list_t list, gl_list_node_t node)
+{
+  uintptr_t index = NODE_TO_INDEX (node);
+  if (!(index < list->count))
+    /* Invalid argument.  */
+    abort ();
+  index++;
+  if (index < list->count)
+    return INDEX_TO_NODE (index);
+  else
+    return NULL;
+}
+
+static gl_list_node_t
+gl_array_previous_node (gl_list_t list, gl_list_node_t node)
+{
+  uintptr_t index = NODE_TO_INDEX (node);
+  if (!(index < list->count))
+    /* Invalid argument.  */
+    abort ();
+  if (index > 0)
+    return INDEX_TO_NODE (index - 1);
+  else
+    return NULL;
+}
+
+static const void *
+gl_array_get_at (gl_list_t list, size_t position)
+{
+  size_t count = list->count;
+
+  if (!(position < count))
+    /* Invalid argument.  */
+    abort ();
+  return list->elements[position];
+}
+
+static gl_list_node_t
+gl_array_nx_set_at (gl_list_t list, size_t position, const void *elt)
+{
+  size_t count = list->count;
+
+  if (!(position < count))
+    /* Invalid argument.  */
+    abort ();
+  list->elements[position] = elt;
+  return INDEX_TO_NODE (position);
+}
+
+static size_t
+gl_array_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index,
+                          const void *elt)
+{
+  size_t count = list->count;
+
+  if (!(start_index <= end_index && end_index <= count))
+    /* Invalid arguments.  */
+    abort ();
+
+  if (start_index < end_index)
+    {
+      gl_listelement_equals_fn equals = list->base.equals_fn;
+      if (equals != NULL)
+        {
+          size_t i;
+
+          for (i = start_index;;)
+            {
+              if (equals (elt, list->elements[i]))
+                return i;
+              i++;
+              if (i == end_index)
+                break;
+            }
+        }
+      else
+        {
+          size_t i;
+
+          for (i = start_index;;)
+            {
+              if (elt == list->elements[i])
+                return i;
+              i++;
+              if (i == end_index)
+                break;
+            }
+        }
+    }
+  return (size_t)(-1);
+}
+
+static gl_list_node_t
+gl_array_search_from_to (gl_list_t list, size_t start_index, size_t end_index,
+                         const void *elt)
+{
+  size_t index = gl_array_indexof_from_to (list, start_index, end_index, elt);
+  return INDEX_TO_NODE (index);
+}
+
+/* Ensure that list->allocated > list->count.
+   Return 0 upon success, -1 upon out-of-memory.  */
+static int
+grow (gl_list_t list)
+{
+  size_t new_allocated;
+  size_t memory_size;
+  const void **memory;
+
+  new_allocated = xtimes (list->allocated, 2);
+  new_allocated = xsum (new_allocated, 1);
+  memory_size = xtimes (new_allocated, sizeof (const void *));
+  if (size_overflow_p (memory_size))
+    /* Overflow, would lead to out of memory.  */
+    return -1;
+  memory = (const void **) realloc (list->elements, memory_size);
+  if (memory == NULL)
+    /* Out of memory.  */
+    return -1;
+  list->elements = memory;
+  list->allocated = new_allocated;
+  return 0;
+}
+
+static gl_list_node_t
+gl_array_nx_add_first (gl_list_t list, const void *elt)
+{
+  size_t count = list->count;
+  const void **elements;
+  size_t i;
+
+  if (count == list->allocated)
+    if (grow (list) < 0)
+      return NULL;
+  elements = list->elements;
+  for (i = count; i > 0; i--)
+    elements[i] = elements[i - 1];
+  elements[0] = elt;
+  list->count = count + 1;
+  return INDEX_TO_NODE (0);
+}
+
+static gl_list_node_t
+gl_array_nx_add_last (gl_list_t list, const void *elt)
+{
+  size_t count = list->count;
+
+  if (count == list->allocated)
+    if (grow (list) < 0)
+      return NULL;
+  list->elements[count] = elt;
+  list->count = count + 1;
+  return INDEX_TO_NODE (count);
+}
+
+static gl_list_node_t
+gl_array_nx_add_before (gl_list_t list, gl_list_node_t node, const void *elt)
+{
+  size_t count = list->count;
+  uintptr_t index = NODE_TO_INDEX (node);
+  size_t position;
+  const void **elements;
+  size_t i;
+
+  if (!(index < count))
+    /* Invalid argument.  */
+    abort ();
+  position = index;
+  if (count == list->allocated)
+    if (grow (list) < 0)
+      return NULL;
+  elements = list->elements;
+  for (i = count; i > position; i--)
+    elements[i] = elements[i - 1];
+  elements[position] = elt;
+  list->count = count + 1;
+  return INDEX_TO_NODE (position);
+}
+
+static gl_list_node_t
+gl_array_nx_add_after (gl_list_t list, gl_list_node_t node, const void *elt)
+{
+  size_t count = list->count;
+  uintptr_t index = NODE_TO_INDEX (node);
+  size_t position;
+  const void **elements;
+  size_t i;
+
+  if (!(index < count))
+    /* Invalid argument.  */
+    abort ();
+  position = index + 1;
+  if (count == list->allocated)
+    if (grow (list) < 0)
+      return NULL;
+  elements = list->elements;
+  for (i = count; i > position; i--)
+    elements[i] = elements[i - 1];
+  elements[position] = elt;
+  list->count = count + 1;
+  return INDEX_TO_NODE (position);
+}
+
+static gl_list_node_t
+gl_array_nx_add_at (gl_list_t list, size_t position, const void *elt)
+{
+  size_t count = list->count;
+  const void **elements;
+  size_t i;
+
+  if (!(position <= count))
+    /* Invalid argument.  */
+    abort ();
+  if (count == list->allocated)
+    if (grow (list) < 0)
+      return NULL;
+  elements = list->elements;
+  for (i = count; i > position; i--)
+    elements[i] = elements[i - 1];
+  elements[position] = elt;
+  list->count = count + 1;
+  return INDEX_TO_NODE (position);
+}
+
+static bool
+gl_array_remove_node (gl_list_t list, gl_list_node_t node)
+{
+  size_t count = list->count;
+  uintptr_t index = NODE_TO_INDEX (node);
+  size_t position;
+  const void **elements;
+  size_t i;
+
+  if (!(index < count))
+    /* Invalid argument.  */
+    abort ();
+  position = index;
+  elements = list->elements;
+  if (list->base.dispose_fn != NULL)
+    list->base.dispose_fn (elements[position]);
+  for (i = position + 1; i < count; i++)
+    elements[i - 1] = elements[i];
+  list->count = count - 1;
+  return true;
+}
+
+static bool
+gl_array_remove_at (gl_list_t list, size_t position)
+{
+  size_t count = list->count;
+  const void **elements;
+  size_t i;
+
+  if (!(position < count))
+    /* Invalid argument.  */
+    abort ();
+  elements = list->elements;
+  if (list->base.dispose_fn != NULL)
+    list->base.dispose_fn (elements[position]);
+  for (i = position + 1; i < count; i++)
+    elements[i - 1] = elements[i];
+  list->count = count - 1;
+  return true;
+}
+
+static bool
+gl_array_remove (gl_list_t list, const void *elt)
+{
+  size_t position = gl_array_indexof_from_to (list, 0, list->count, elt);
+  if (position == (size_t)(-1))
+    return false;
+  else
+    return gl_array_remove_at (list, position);
+}
+
+static void
+gl_array_list_free (gl_list_t list)
+{
+  if (list->elements != NULL)
+    {
+      if (list->base.dispose_fn != NULL)
+        {
+          size_t count = list->count;
+
+          if (count > 0)
+            {
+              gl_listelement_dispose_fn dispose = list->base.dispose_fn;
+              const void **elements = list->elements;
+
+              do
+                dispose (*elements++);
+              while (--count > 0);
+            }
+        }
+      free (list->elements);
+    }
+  free (list);
+}
+
+/* --------------------- gl_list_iterator_t Data Type --------------------- */
+
+static gl_list_iterator_t
+gl_array_iterator (gl_list_t list)
+{
+  gl_list_iterator_t result;
+
+  result.vtable = list->base.vtable;
+  result.list = list;
+  result.count = list->count;
+  result.p = list->elements + 0;
+  result.q = list->elements + list->count;
+#ifdef lint
+  result.i = 0;
+  result.j = 0;
+#endif
+
+  return result;
+}
+
+static gl_list_iterator_t
+gl_array_iterator_from_to (gl_list_t list, size_t start_index, size_t end_index)
+{
+  gl_list_iterator_t result;
+
+  if (!(start_index <= end_index && end_index <= list->count))
+    /* Invalid arguments.  */
+    abort ();
+  result.vtable = list->base.vtable;
+  result.list = list;
+  result.count = list->count;
+  result.p = list->elements + start_index;
+  result.q = list->elements + end_index;
+#ifdef lint
+  result.i = 0;
+  result.j = 0;
+#endif
+
+  return result;
+}
+
+static bool
+gl_array_iterator_next (gl_list_iterator_t *iterator,
+                        const void **eltp, gl_list_node_t *nodep)
+{
+  gl_list_t list = iterator->list;
+  if (iterator->count != list->count)
+    {
+      if (iterator->count != list->count + 1)
+        /* Concurrent modifications were done on the list.  */
+        abort ();
+      /* The last returned element was removed.  */
+      iterator->count--;
+      iterator->p = (const void **) iterator->p - 1;
+      iterator->q = (const void **) iterator->q - 1;
+    }
+  if (iterator->p < iterator->q)
+    {
+      const void **p = (const void **) iterator->p;
+      *eltp = *p;
+      if (nodep != NULL)
+        *nodep = INDEX_TO_NODE (p - list->elements);
+      iterator->p = p + 1;
+      return true;
+    }
+  else
+    return false;
+}
+
+static void
+gl_array_iterator_free (gl_list_iterator_t *iterator)
+{
+}
+
+/* ---------------------- Sorted gl_list_t Data Type ---------------------- */
+
+static size_t
+gl_array_sortedlist_indexof_from_to (gl_list_t list,
+                                     gl_listelement_compar_fn compar,
+                                     size_t low, size_t high,
+                                     const void *elt)
+{
+  if (!(low <= high && high <= list->count))
+    /* Invalid arguments.  */
+    abort ();
+  if (low < high)
+    {
+      /* At each loop iteration, low < high; for indices < low the values
+         are smaller than ELT; for indices >= high the values are greater
+         than ELT.  So, if the element occurs in the list, it is at
+         low <= position < high.  */
+      do
+        {
+          size_t mid = low + (high - low) / 2; /* low <= mid < high */
+          int cmp = compar (list->elements[mid], elt);
+
+          if (cmp < 0)
+            low = mid + 1;
+          else if (cmp > 0)
+            high = mid;
+          else /* cmp == 0 */
+            {
+              /* We have an element equal to ELT at index MID.  But we need
+                 the minimal such index.  */
+              high = mid;
+              /* At each loop iteration, low <= high and
+                   compar (list->elements[high], elt) == 0,
+                 and we know that the first occurrence of the element is at
+                 low <= position <= high.  */
+              while (low < high)
+                {
+                  size_t mid2 = low + (high - low) / 2; /* low <= mid2 < high */
+                  int cmp2 = compar (list->elements[mid2], elt);
+
+                  if (cmp2 < 0)
+                    low = mid2 + 1;
+                  else if (cmp2 > 0)
+                    /* The list was not sorted.  */
+                    abort ();
+                  else /* cmp2 == 0 */
+                    {
+                      if (mid2 == low)
+                        break;
+                      high = mid2 - 1;
+                    }
+                }
+              return low;
+            }
+        }
+      while (low < high);
+      /* Here low == high.  */
+    }
+  return (size_t)(-1);
+}
+
+static size_t
+gl_array_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar,
+                             const void *elt)
+{
+  return gl_array_sortedlist_indexof_from_to (list, compar, 0, list->count,
+                                              elt);
+}
+
+static gl_list_node_t
+gl_array_sortedlist_search_from_to (gl_list_t list,
+                                    gl_listelement_compar_fn compar,
+                                    size_t low, size_t high,
+                                    const void *elt)
+{
+  size_t index =
+    gl_array_sortedlist_indexof_from_to (list, compar, low, high, elt);
+  return INDEX_TO_NODE (index);
+}
+
+static gl_list_node_t
+gl_array_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar,
+                            const void *elt)
+{
+  size_t index =
+    gl_array_sortedlist_indexof_from_to (list, compar, 0, list->count, elt);
+  return INDEX_TO_NODE (index);
+}
+
+static gl_list_node_t
+gl_array_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar,
+                            const void *elt)
+{
+  size_t count = list->count;
+  size_t low = 0;
+  size_t high = count;
+
+  /* At each loop iteration, low <= high; for indices < low the values are
+     smaller than ELT; for indices >= high the values are greater than ELT.  */
+  while (low < high)
+    {
+      size_t mid = low + (high - low) / 2; /* low <= mid < high */
+      int cmp = compar (list->elements[mid], elt);
+
+      if (cmp < 0)
+        low = mid + 1;
+      else if (cmp > 0)
+        high = mid;
+      else /* cmp == 0 */
+        {
+          low = mid;
+          break;
+        }
+    }
+  return gl_array_nx_add_at (list, low, elt);
+}
+
+static bool
+gl_array_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar,
+                            const void *elt)
+{
+  size_t index = gl_array_sortedlist_indexof (list, compar, elt);
+  if (index == (size_t)(-1))
+    return false;
+  else
+    return gl_array_remove_at (list, index);
+}
+
+
+const struct gl_list_implementation gl_array_list_implementation =
+  {
+    gl_array_nx_create_empty,
+    gl_array_nx_create,
+    gl_array_size,
+    gl_array_node_value,
+    gl_array_node_nx_set_value,
+    gl_array_next_node,
+    gl_array_previous_node,
+    gl_array_get_at,
+    gl_array_nx_set_at,
+    gl_array_search_from_to,
+    gl_array_indexof_from_to,
+    gl_array_nx_add_first,
+    gl_array_nx_add_last,
+    gl_array_nx_add_before,
+    gl_array_nx_add_after,
+    gl_array_nx_add_at,
+    gl_array_remove_node,
+    gl_array_remove_at,
+    gl_array_remove,
+    gl_array_list_free,
+    gl_array_iterator,
+    gl_array_iterator_from_to,
+    gl_array_iterator_next,
+    gl_array_iterator_free,
+    gl_array_sortedlist_search,
+    gl_array_sortedlist_search_from_to,
+    gl_array_sortedlist_indexof,
+    gl_array_sortedlist_indexof_from_to,
+    gl_array_sortedlist_nx_add,
+    gl_array_sortedlist_remove
+  };

+ 34 - 0
gnulib/lib/gl_array_list.h

@@ -0,0 +1,34 @@
+/* Sequential list data type implemented by an array.
+   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/>.  */
+
+#ifndef _GL_ARRAY_LIST_H
+#define _GL_ARRAY_LIST_H
+
+#include "gl_list.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const struct gl_list_implementation gl_array_list_implementation;
+#define GL_ARRAY_LIST &gl_array_list_implementation
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GL_ARRAY_LIST_H */

+ 283 - 0
gnulib/lib/gl_list.c

@@ -0,0 +1,283 @@
+/* Abstract sequential list data type.
+   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/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "gl_list.h"
+
+#if !HAVE_INLINE
+
+/* Define all functions of this file as inline accesses to the
+   struct gl_list_implementation.
+   Use #define to avoid a warning because of extern vs. static.  */
+
+gl_list_t
+gl_list_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)
+{
+  return implementation->nx_create_empty (implementation, equals_fn,
+                                          hashcode_fn, dispose_fn,
+                                          allow_duplicates);
+}
+
+gl_list_t
+gl_list_nx_create (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,
+                   size_t count, const void **contents)
+{
+  return implementation->nx_create (implementation, equals_fn, hashcode_fn,
+                                    dispose_fn, allow_duplicates, count,
+                                    contents);
+}
+
+size_t
+gl_list_size (gl_list_t list)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->size (list);
+}
+
+const void *
+gl_list_node_value (gl_list_t list, gl_list_node_t node)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->node_value (list, node);
+}
+
+int
+gl_list_node_nx_set_value (gl_list_t list, gl_list_node_t node,
+                           const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->node_nx_set_value (list, node, elt);
+}
+
+gl_list_node_t
+gl_list_next_node (gl_list_t list, gl_list_node_t node)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->next_node (list, node);
+}
+
+gl_list_node_t
+gl_list_previous_node (gl_list_t list, gl_list_node_t node)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->previous_node (list, node);
+}
+
+const void *
+gl_list_get_at (gl_list_t list, size_t position)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->get_at (list, position);
+}
+
+gl_list_node_t
+gl_list_nx_set_at (gl_list_t list, size_t position, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->nx_set_at (list, position, elt);
+}
+
+gl_list_node_t
+gl_list_search (gl_list_t list, const void *elt)
+{
+  size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list);
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->search_from_to (list, 0, size, elt);
+}
+
+gl_list_node_t
+gl_list_search_from (gl_list_t list, size_t start_index, const void *elt)
+{
+  size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list);
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->search_from_to (list, start_index, size, elt);
+}
+
+gl_list_node_t
+gl_list_search_from_to (gl_list_t list, size_t start_index, size_t end_index, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->search_from_to (list, start_index, end_index, elt);
+}
+
+size_t
+gl_list_indexof (gl_list_t list, const void *elt)
+{
+  size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list);
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->indexof_from_to (list, 0, size, elt);
+}
+
+size_t
+gl_list_indexof_from (gl_list_t list, size_t start_index, const void *elt)
+{
+  size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list);
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->indexof_from_to (list, start_index, size, elt);
+}
+
+size_t
+gl_list_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->indexof_from_to (list, start_index, end_index, elt);
+}
+
+gl_list_node_t
+gl_list_nx_add_first (gl_list_t list, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->nx_add_first (list, elt);
+}
+
+gl_list_node_t
+gl_list_nx_add_last (gl_list_t list, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->nx_add_last (list, elt);
+}
+
+gl_list_node_t
+gl_list_nx_add_before (gl_list_t list, gl_list_node_t node, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->nx_add_before (list, node, elt);
+}
+
+gl_list_node_t
+gl_list_nx_add_after (gl_list_t list, gl_list_node_t node, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->nx_add_after (list, node, elt);
+}
+
+gl_list_node_t
+gl_list_nx_add_at (gl_list_t list, size_t position, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->nx_add_at (list, position, elt);
+}
+
+bool
+gl_list_remove_node (gl_list_t list, gl_list_node_t node)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->remove_node (list, node);
+}
+
+bool
+gl_list_remove_at (gl_list_t list, size_t position)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->remove_at (list, position);
+}
+
+bool
+gl_list_remove (gl_list_t list, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->remove_elt (list, elt);
+}
+
+void
+gl_list_free (gl_list_t list)
+{
+  ((const struct gl_list_impl_base *) list)->vtable->list_free (list);
+}
+
+gl_list_iterator_t
+gl_list_iterator (gl_list_t list)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->iterator (list);
+}
+
+gl_list_iterator_t
+gl_list_iterator_from_to (gl_list_t list, size_t start_index, size_t end_index)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->iterator_from_to (list, start_index, end_index);
+}
+
+bool
+gl_list_iterator_next (gl_list_iterator_t *iterator,
+                       const void **eltp, gl_list_node_t *nodep)
+{
+  return iterator->vtable->iterator_next (iterator, eltp, nodep);
+}
+
+void
+gl_list_iterator_free (gl_list_iterator_t *iterator)
+{
+  iterator->vtable->iterator_free (iterator);
+}
+
+gl_list_node_t
+gl_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->sortedlist_search (list, compar, elt);
+}
+
+gl_list_node_t
+gl_sortedlist_search_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t start_index, size_t end_index, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->sortedlist_search_from_to (list, compar, start_index, end_index,
+                                      elt);
+}
+
+size_t
+gl_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->sortedlist_indexof (list, compar, elt);
+}
+
+size_t
+gl_sortedlist_indexof_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t start_index, size_t end_index, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->sortedlist_indexof_from_to (list, compar, start_index, end_index,
+                                       elt);
+}
+
+gl_list_node_t
+gl_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->sortedlist_nx_add (list, compar, elt);
+}
+
+bool
+gl_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->sortedlist_remove (list, compar, elt);
+}
+
+#endif

+ 844 - 0
gnulib/lib/gl_list.h

@@ -0,0 +1,844 @@
+/* Abstract sequential list data type.
+   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/>.  */
+
+#ifndef _GL_LIST_H
+#define _GL_LIST_H
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* gl_list is an abstract list data type.  It can contain any number of
+   objects ('void *' or 'const void *' pointers) in any given order.
+   Duplicates are allowed, but can optionally be forbidden.
+
+   There are several implementations of this list datatype, optimized for
+   different operations or for memory.  You can start using the simplest list
+   implementation, GL_ARRAY_LIST, and switch to a different implementation
+   later, when you realize which operations are performed the most frequently.
+   The API of the different implementations is exactly the same; when
+   switching to a different implementation, you only have to change the
+   gl_list_create call.
+
+   The implementations are:
+     GL_ARRAY_LIST        a growable array
+     GL_CARRAY_LIST       a growable circular array
+     GL_LINKED_LIST       a linked list
+     GL_AVLTREE_LIST      a binary tree (AVL tree)
+     GL_RBTREE_LIST       a binary tree (red-black tree)
+     GL_LINKEDHASH_LIST   a hash table with a linked list
+     GL_AVLTREEHASH_LIST  a hash table with a binary tree (AVL tree)
+     GL_RBTREEHASH_LIST   a hash table with a binary tree (red-black tree)
+
+   The memory consumption is asymptotically the same: O(1) for every object
+   in the list.  When looking more closely at the average memory consumed
+   for an object, GL_ARRAY_LIST is the most compact representation, and
+   GL_LINKEDHASH_LIST and GL_TREEHASH_LIST need more memory.
+
+   The guaranteed average performance of the operations is, for a list of
+   n elements:
+
+   Operation                  ARRAY    LINKED    TREE    LINKEDHASH   TREEHASH
+                              CARRAY                   with|without with|without
+                                                         duplicates  duplicates
+
+   gl_list_size                O(1)     O(1)     O(1)      O(1)         O(1)
+   gl_list_node_value          O(1)     O(1)     O(1)      O(1)         O(1)
+   gl_list_node_set_value      O(1)     O(1)     O(1)      O(1)    O((log n)²)/O(1)
+   gl_list_next_node           O(1)     O(1)   O(log n)    O(1)       O(log n)
+   gl_list_previous_node       O(1)     O(1)   O(log n)    O(1)       O(log n)
+   gl_list_get_at              O(1)     O(n)   O(log n)    O(n)       O(log n)
+   gl_list_set_at              O(1)     O(n)   O(log n)    O(n)    O((log n)²)/O(log n)
+   gl_list_search              O(n)     O(n)     O(n)    O(n)/O(1)    O(log n)/O(1)
+   gl_list_search_from         O(n)     O(n)     O(n)    O(n)/O(1) O((log n)²)/O(log n)
+   gl_list_search_from_to      O(n)     O(n)     O(n)    O(n)/O(1) O((log n)²)/O(log n)
+   gl_list_indexof             O(n)     O(n)     O(n)      O(n)       O(log n)
+   gl_list_indexof_from        O(n)     O(n)     O(n)      O(n)    O((log n)²)/O(log n)
+   gl_list_indexof_from_to     O(n)     O(n)     O(n)      O(n)    O((log n)²)/O(log n)
+   gl_list_add_first         O(n)/O(1)  O(1)   O(log n)    O(1)    O((log n)²)/O(log n)
+   gl_list_add_last            O(1)     O(1)   O(log n)    O(1)    O((log n)²)/O(log n)
+   gl_list_add_before          O(n)     O(1)   O(log n)    O(1)    O((log n)²)/O(log n)
+   gl_list_add_after           O(n)     O(1)   O(log n)    O(1)    O((log n)²)/O(log n)
+   gl_list_add_at              O(n)     O(n)   O(log n)    O(n)    O((log n)²)/O(log n)
+   gl_list_remove_node         O(n)     O(1)   O(log n)  O(n)/O(1) O((log n)²)/O(log n)
+   gl_list_remove_at           O(n)     O(n)   O(log n)    O(n)    O((log n)²)/O(log n)
+   gl_list_remove              O(n)     O(n)     O(n)    O(n)/O(1) O((log n)²)/O(log n)
+   gl_list_iterator            O(1)     O(1)   O(log n)    O(1)       O(log n)
+   gl_list_iterator_from_to    O(1)     O(n)   O(log n)    O(n)       O(log n)
+   gl_list_iterator_next       O(1)     O(1)   O(log n)    O(1)       O(log n)
+   gl_sortedlist_search      O(log n)   O(n)   O(log n)    O(n)       O(log n)
+   gl_sortedlist_search_from O(log n)   O(n)   O(log n)    O(n)       O(log n)
+   gl_sortedlist_indexof     O(log n)   O(n)   O(log n)    O(n)       O(log n)
+   gl_sortedlist_indexof_fro O(log n)   O(n)   O(log n)    O(n)       O(log n)
+   gl_sortedlist_add           O(n)     O(n)   O(log n)    O(n)    O((log n)²)/O(log n)
+   gl_sortedlist_remove        O(n)     O(n)   O(log n)    O(n)    O((log n)²)/O(log n)
+ */
+
+/* -------------------------- gl_list_t Data Type -------------------------- */
+
+/* Type of function used to compare two elements.
+   NULL denotes pointer comparison.  */
+typedef bool (*gl_listelement_equals_fn) (const void *elt1, const void *elt2);
+
+/* Type of function used to compute a hash code.
+   NULL denotes a function that depends only on the pointer itself.  */
+typedef size_t (*gl_listelement_hashcode_fn) (const void *elt);
+
+/* Type of function used to dispose an element once it's removed from a list.
+   NULL denotes a no-op.  */
+typedef void (*gl_listelement_dispose_fn) (const void *elt);
+
+struct gl_list_impl;
+/* Type representing an entire list.  */
+typedef struct gl_list_impl * gl_list_t;
+
+struct gl_list_node_impl;
+/* Type representing the position of an element in the list, in a way that
+   is more adapted to the list implementation than a plain index.
+   Note: It is invalidated by insertions and removals!  */
+typedef struct gl_list_node_impl * gl_list_node_t;
+
+struct gl_list_implementation;
+/* Type representing a list datatype implementation.  */
+typedef const struct gl_list_implementation * gl_list_implementation_t;
+
+/* Create an empty list.
+   IMPLEMENTATION is one of GL_ARRAY_LIST, GL_CARRAY_LIST, GL_LINKED_LIST,
+   GL_AVLTREE_LIST, GL_RBTREE_LIST, GL_LINKEDHASH_LIST, GL_AVLTREEHASH_LIST,
+   GL_RBTREEHASH_LIST.
+   EQUALS_FN is an element comparison function or NULL.
+   HASHCODE_FN is an element hash code function or NULL.
+   DISPOSE_FN is an element disposal function or NULL.
+   ALLOW_DUPLICATES is false if duplicate elements shall not be allowed in
+   the list. The implementation may verify this at runtime.  */
+#if 0 /* declared in gl_xlist.h */
+extern gl_list_t gl_list_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);
+#endif
+/* Likewise.  Return NULL upon out-of-memory.  */
+extern gl_list_t gl_list_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);
+
+/* Create a list with given contents.
+   IMPLEMENTATION is one of GL_ARRAY_LIST, GL_CARRAY_LIST, GL_LINKED_LIST,
+   GL_AVLTREE_LIST, GL_RBTREE_LIST, GL_LINKEDHASH_LIST, GL_AVLTREEHASH_LIST,
+   GL_RBTREEHASH_LIST.
+   EQUALS_FN is an element comparison function or NULL.
+   HASHCODE_FN is an element hash code function or NULL.
+   DISPOSE_FN is an element disposal function or NULL.
+   ALLOW_DUPLICATES is false if duplicate elements shall not be allowed in
+   the list. The implementation may verify this at runtime.
+   COUNT is the number of initial elements.
+   CONTENTS[0..COUNT-1] is the initial contents.  */
+#if 0 /* declared in gl_xlist.h */
+extern gl_list_t gl_list_create (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,
+                                 size_t count, const void **contents);
+#endif
+/* Likewise.  Return NULL upon out-of-memory.  */
+extern gl_list_t gl_list_nx_create (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,
+                                    size_t count, const void **contents);
+
+/* Return the current number of elements in a list.  */
+extern size_t gl_list_size (gl_list_t list);
+
+/* Return the element value represented by a list node.  */
+extern const void * gl_list_node_value (gl_list_t list, gl_list_node_t node);
+
+/* Replace the element value represented by a list node.  */
+#if 0 /* declared in gl_xlist.h */
+extern void gl_list_node_set_value (gl_list_t list, gl_list_node_t node,
+                                    const void *elt);
+#endif
+/* Likewise.  Return 0 upon success, -1 upon out-of-memory.  */
+extern int gl_list_node_nx_set_value (gl_list_t list, gl_list_node_t node,
+                                      const void *elt)
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+  __attribute__ ((__warn_unused_result__))
+#endif
+  ;
+
+/* Return the node immediately after the given node in the list, or NULL
+   if the given node is the last (rightmost) one in the list.  */
+extern gl_list_node_t gl_list_next_node (gl_list_t list, gl_list_node_t node);
+
+/* Return the node immediately before the given node in the list, or NULL
+   if the given node is the first (leftmost) one in the list.  */
+extern gl_list_node_t gl_list_previous_node (gl_list_t list, gl_list_node_t node);
+
+/* Return the element at a given position in the list.
+   POSITION must be >= 0 and < gl_list_size (list).  */
+extern const void * gl_list_get_at (gl_list_t list, size_t position);
+
+/* Replace the element at a given position in the list.
+   POSITION must be >= 0 and < gl_list_size (list).
+   Return its node.  */
+#if 0 /* declared in gl_xlist.h */
+extern gl_list_node_t gl_list_set_at (gl_list_t list, size_t position,
+                                      const void *elt);
+#endif
+/* Likewise.  Return NULL upon out-of-memory.  */
+extern gl_list_node_t gl_list_nx_set_at (gl_list_t list, size_t position,
+                                         const void *elt)
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+  __attribute__ ((__warn_unused_result__))
+#endif
+  ;
+
+/* Search whether an element is already in the list.
+   Return its node if found, or NULL if not present in the list.  */
+extern gl_list_node_t gl_list_search (gl_list_t list, const void *elt);
+
+/* Search whether an element is already in the list,
+   at a position >= START_INDEX.
+   Return its node if found, or NULL if not present in the list.  */
+extern gl_list_node_t gl_list_search_from (gl_list_t list, size_t start_index,
+                                           const void *elt);
+
+/* Search whether an element is already in the list,
+   at a position >= START_INDEX and < END_INDEX.
+   Return its node if found, or NULL if not present in the list.  */
+extern gl_list_node_t gl_list_search_from_to (gl_list_t list,
+                                              size_t start_index,
+                                              size_t end_index,
+                                              const void *elt);
+
+/* Search whether an element is already in the list.
+   Return its position if found, or (size_t)(-1) if not present in the list.  */
+extern size_t gl_list_indexof (gl_list_t list, const void *elt);
+
+/* Search whether an element is already in the list,
+   at a position >= START_INDEX.
+   Return its position if found, or (size_t)(-1) if not present in the list.  */
+extern size_t gl_list_indexof_from (gl_list_t list, size_t start_index,
+                                    const void *elt);
+
+/* Search whether an element is already in the list,
+   at a position >= START_INDEX and < END_INDEX.
+   Return its position if found, or (size_t)(-1) if not present in the list.  */
+extern size_t gl_list_indexof_from_to (gl_list_t list,
+                                       size_t start_index, size_t end_index,
+                                       const void *elt);
+
+/* Add an element as the first element of the list.
+   Return its node.  */
+#if 0 /* declared in gl_xlist.h */
+extern gl_list_node_t gl_list_add_first (gl_list_t list, const void *elt);
+#endif
+/* Likewise.  Return NULL upon out-of-memory.  */
+extern gl_list_node_t gl_list_nx_add_first (gl_list_t list, const void *elt)
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+  __attribute__ ((__warn_unused_result__))
+#endif
+  ;
+
+/* Add an element as the last element of the list.
+   Return its node.  */
+#if 0 /* declared in gl_xlist.h */
+extern gl_list_node_t gl_list_add_last (gl_list_t list, const void *elt);
+#endif
+/* Likewise.  Return NULL upon out-of-memory.  */
+extern gl_list_node_t gl_list_nx_add_last (gl_list_t list, const void *elt)
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+  __attribute__ ((__warn_unused_result__))
+#endif
+  ;
+
+/* Add an element before a given element node of the list.
+   Return its node.  */
+#if 0 /* declared in gl_xlist.h */
+extern gl_list_node_t gl_list_add_before (gl_list_t list, gl_list_node_t node,
+                                          const void *elt);
+#endif
+/* Likewise.  Return NULL upon out-of-memory.  */
+extern gl_list_node_t gl_list_nx_add_before (gl_list_t list,
+                                             gl_list_node_t node,
+                                             const void *elt)
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+  __attribute__ ((__warn_unused_result__))
+#endif
+  ;
+
+/* Add an element after a given element node of the list.
+   Return its node.  */
+#if 0 /* declared in gl_xlist.h */
+extern gl_list_node_t gl_list_add_after (gl_list_t list, gl_list_node_t node,
+                                         const void *elt);
+#endif
+/* Likewise.  Return NULL upon out-of-memory.  */
+extern gl_list_node_t gl_list_nx_add_after (gl_list_t list, gl_list_node_t node,
+                                            const void *elt)
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+  __attribute__ ((__warn_unused_result__))
+#endif
+  ;
+
+/* Add an element at a given position in the list.
+   POSITION must be >= 0 and <= gl_list_size (list).  */
+#if 0 /* declared in gl_xlist.h */
+extern gl_list_node_t gl_list_add_at (gl_list_t list, size_t position,
+                                      const void *elt);
+#endif
+/* Likewise.  Return NULL upon out-of-memory.  */
+extern gl_list_node_t gl_list_nx_add_at (gl_list_t list, size_t position,
+                                         const void *elt)
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+  __attribute__ ((__warn_unused_result__))
+#endif
+  ;
+
+/* Remove an element from the list.
+   Return true.  */
+extern bool gl_list_remove_node (gl_list_t list, gl_list_node_t node);
+
+/* Remove an element at a given position from the list.
+   POSITION must be >= 0 and < gl_list_size (list).
+   Return true.  */
+extern bool gl_list_remove_at (gl_list_t list, size_t position);
+
+/* Search and remove an element from the list.
+   Return true if it was found and removed.  */
+extern bool gl_list_remove (gl_list_t list, const void *elt);
+
+/* Free an entire list.
+   (But this call does not free the elements of the list.)  */
+extern void gl_list_free (gl_list_t list);
+
+/* --------------------- gl_list_iterator_t Data Type --------------------- */
+
+/* Functions for iterating through a list.  */
+
+/* Type of an iterator that traverses a list.
+   This is a fixed-size struct, so that creation of an iterator doesn't need
+   memory allocation on the heap.  */
+typedef struct
+{
+  /* For fast dispatch of gl_list_iterator_next.  */
+  const struct gl_list_implementation *vtable;
+  /* For detecting whether the last returned element was removed.  */
+  gl_list_t list;
+  size_t count;
+  /* Other, implementation-private fields.  */
+  void *p; void *q;
+  size_t i; size_t j;
+} gl_list_iterator_t;
+
+/* Create an iterator traversing a list.
+   The list contents must not be modified while the iterator is in use,
+   except for replacing or removing the last returned element.  */
+extern gl_list_iterator_t gl_list_iterator (gl_list_t list);
+
+/* Create an iterator traversing the element with indices i,
+   start_index <= i < end_index, of a list.
+   The list contents must not be modified while the iterator is in use,
+   except for replacing or removing the last returned element.  */
+extern gl_list_iterator_t gl_list_iterator_from_to (gl_list_t list,
+                                                    size_t start_index,
+                                                    size_t end_index);
+
+/* If there is a next element, store the next element in *ELTP, store its
+   node in *NODEP if NODEP is non-NULL, advance the iterator and return true.
+   Otherwise, return false.  */
+extern bool gl_list_iterator_next (gl_list_iterator_t *iterator,
+                                   const void **eltp, gl_list_node_t *nodep);
+
+/* Free an iterator.  */
+extern void gl_list_iterator_free (gl_list_iterator_t *iterator);
+
+/* ---------------------- Sorted gl_list_t Data Type ---------------------- */
+
+/* The following functions are for lists without duplicates where the
+   order is given by a sort criterion.  */
+
+/* Type of function used to compare two elements.  Same as for qsort().
+   NULL denotes pointer comparison.  */
+typedef int (*gl_listelement_compar_fn) (const void *elt1, const void *elt2);
+
+/* Search whether an element is already in the list.
+   The list is assumed to be sorted with COMPAR.
+   Return its node if found, or NULL if not present in the list.
+   If the list contains several copies of ELT, the node of the leftmost one is
+   returned.  */
+extern gl_list_node_t gl_sortedlist_search (gl_list_t list,
+                                            gl_listelement_compar_fn compar,
+                                            const void *elt);
+
+/* Search whether an element is already in the list.
+   The list is assumed to be sorted with COMPAR.
+   Only list elements with indices >= START_INDEX and < END_INDEX are
+   considered; the implementation uses these bounds to minimize the number
+   of COMPAR invocations.
+   Return its node if found, or NULL if not present in the list.
+   If the list contains several copies of ELT, the node of the leftmost one is
+   returned.  */
+extern gl_list_node_t gl_sortedlist_search_from_to (gl_list_t list,
+                                                    gl_listelement_compar_fn compar,
+                                                    size_t start_index,
+                                                    size_t end_index,
+                                                    const void *elt);
+
+/* Search whether an element is already in the list.
+   The list is assumed to be sorted with COMPAR.
+   Return its position if found, or (size_t)(-1) if not present in the list.
+   If the list contains several copies of ELT, the position of the leftmost one
+   is returned.  */
+extern size_t gl_sortedlist_indexof (gl_list_t list,
+                                     gl_listelement_compar_fn compar,
+                                     const void *elt);
+
+/* Search whether an element is already in the list.
+   The list is assumed to be sorted with COMPAR.
+   Only list elements with indices >= START_INDEX and < END_INDEX are
+   considered; the implementation uses these bounds to minimize the number
+   of COMPAR invocations.
+   Return its position if found, or (size_t)(-1) if not present in the list.
+   If the list contains several copies of ELT, the position of the leftmost one
+   is returned.  */
+extern size_t gl_sortedlist_indexof_from_to (gl_list_t list,
+                                             gl_listelement_compar_fn compar,
+                                             size_t start_index,
+                                             size_t end_index,
+                                             const void *elt);
+
+/* Add an element at the appropriate position in the list.
+   The list is assumed to be sorted with COMPAR.
+   Return its node.  */
+#if 0 /* declared in gl_xlist.h */
+extern gl_list_node_t gl_sortedlist_add (gl_list_t list,
+                                         gl_listelement_compar_fn compar,
+                                         const void *elt);
+#endif
+/* Likewise.  Return NULL upon out-of-memory.  */
+extern gl_list_node_t gl_sortedlist_nx_add (gl_list_t list,
+                                            gl_listelement_compar_fn compar,
+                                            const void *elt)
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+  __attribute__ ((__warn_unused_result__))
+#endif
+  ;
+
+/* Search and remove an element from the list.
+   The list is assumed to be sorted with COMPAR.
+   Return true if it was found and removed.
+   If the list contains several copies of ELT, only the leftmost one is
+   removed.  */
+extern bool gl_sortedlist_remove (gl_list_t list,
+                                  gl_listelement_compar_fn compar,
+                                  const void *elt);
+
+/* ------------------------ Implementation Details ------------------------ */
+
+struct gl_list_implementation
+{
+  /* gl_list_t functions.  */
+  gl_list_t (*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);
+  gl_list_t (*nx_create) (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,
+                          size_t count, const void **contents);
+  size_t (*size) (gl_list_t list);
+  const void * (*node_value) (gl_list_t list, gl_list_node_t node);
+  int (*node_nx_set_value) (gl_list_t list, gl_list_node_t node,
+                            const void *elt);
+  gl_list_node_t (*next_node) (gl_list_t list, gl_list_node_t node);
+  gl_list_node_t (*previous_node) (gl_list_t list, gl_list_node_t node);
+  const void * (*get_at) (gl_list_t list, size_t position);
+  gl_list_node_t (*nx_set_at) (gl_list_t list, size_t position,
+                               const void *elt);
+  gl_list_node_t (*search_from_to) (gl_list_t list, size_t start_index,
+                                    size_t end_index, const void *elt);
+  size_t (*indexof_from_to) (gl_list_t list, size_t start_index,
+                             size_t end_index, const void *elt);
+  gl_list_node_t (*nx_add_first) (gl_list_t list, const void *elt);
+  gl_list_node_t (*nx_add_last) (gl_list_t list, const void *elt);
+  gl_list_node_t (*nx_add_before) (gl_list_t list, gl_list_node_t node,
+                                   const void *elt);
+  gl_list_node_t (*nx_add_after) (gl_list_t list, gl_list_node_t node,
+                                  const void *elt);
+  gl_list_node_t (*nx_add_at) (gl_list_t list, size_t position,
+                               const void *elt);
+  bool (*remove_node) (gl_list_t list, gl_list_node_t node);
+  bool (*remove_at) (gl_list_t list, size_t position);
+  bool (*remove_elt) (gl_list_t list, const void *elt);
+  void (*list_free) (gl_list_t list);
+  /* gl_list_iterator_t functions.  */
+  gl_list_iterator_t (*iterator) (gl_list_t list);
+  gl_list_iterator_t (*iterator_from_to) (gl_list_t list,
+                                          size_t start_index,
+                                          size_t end_index);
+  bool (*iterator_next) (gl_list_iterator_t *iterator,
+                         const void **eltp, gl_list_node_t *nodep);
+  void (*iterator_free) (gl_list_iterator_t *iterator);
+  /* Sorted gl_list_t functions.  */
+  gl_list_node_t (*sortedlist_search) (gl_list_t list,
+                                       gl_listelement_compar_fn compar,
+                                       const void *elt);
+  gl_list_node_t (*sortedlist_search_from_to) (gl_list_t list,
+                                               gl_listelement_compar_fn compar,
+                                               size_t start_index,
+                                               size_t end_index,
+                                               const void *elt);
+  size_t (*sortedlist_indexof) (gl_list_t list,
+                                gl_listelement_compar_fn compar,
+                                const void *elt);
+  size_t (*sortedlist_indexof_from_to) (gl_list_t list,
+                                        gl_listelement_compar_fn compar,
+                                        size_t start_index, size_t end_index,
+                                        const void *elt);
+  gl_list_node_t (*sortedlist_nx_add) (gl_list_t list,
+                                       gl_listelement_compar_fn compar,
+                                    const void *elt);
+  bool (*sortedlist_remove) (gl_list_t list,
+                             gl_listelement_compar_fn compar,
+                             const void *elt);
+};
+
+struct gl_list_impl_base
+{
+  const struct gl_list_implementation *vtable;
+  gl_listelement_equals_fn equals_fn;
+  gl_listelement_hashcode_fn hashcode_fn;
+  gl_listelement_dispose_fn dispose_fn;
+  bool allow_duplicates;
+};
+
+#if HAVE_INLINE
+
+/* Define all functions of this file as inline accesses to the
+   struct gl_list_implementation.
+   Use #define to avoid a warning because of extern vs. static.  */
+
+# define gl_list_nx_create_empty gl_list_nx_create_empty_inline
+static inline gl_list_t
+gl_list_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)
+{
+  return implementation->nx_create_empty (implementation, equals_fn,
+                                          hashcode_fn, dispose_fn,
+                                          allow_duplicates);
+}
+
+# define gl_list_nx_create gl_list_nx_create_inline
+static inline gl_list_t
+gl_list_nx_create (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,
+                   size_t count, const void **contents)
+{
+  return implementation->nx_create (implementation, equals_fn, hashcode_fn,
+                                    dispose_fn, allow_duplicates, count,
+                                    contents);
+}
+
+# define gl_list_size gl_list_size_inline
+static inline size_t
+gl_list_size (gl_list_t list)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->size (list);
+}
+
+# define gl_list_node_value gl_list_node_value_inline
+static inline const void *
+gl_list_node_value (gl_list_t list, gl_list_node_t node)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->node_value (list, node);
+}
+
+# define gl_list_node_nx_set_value gl_list_node_nx_set_value_inline
+static inline int
+gl_list_node_nx_set_value (gl_list_t list, gl_list_node_t node,
+                           const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->node_nx_set_value (list, node, elt);
+}
+
+# define gl_list_next_node gl_list_next_node_inline
+static inline gl_list_node_t
+gl_list_next_node (gl_list_t list, gl_list_node_t node)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->next_node (list, node);
+}
+
+# define gl_list_previous_node gl_list_previous_node_inline
+static inline gl_list_node_t
+gl_list_previous_node (gl_list_t list, gl_list_node_t node)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->previous_node (list, node);
+}
+
+# define gl_list_get_at gl_list_get_at_inline
+static inline const void *
+gl_list_get_at (gl_list_t list, size_t position)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->get_at (list, position);
+}
+
+# define gl_list_nx_set_at gl_list_nx_set_at_inline
+static inline gl_list_node_t
+gl_list_nx_set_at (gl_list_t list, size_t position, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->nx_set_at (list, position, elt);
+}
+
+# define gl_list_search gl_list_search_inline
+static inline gl_list_node_t
+gl_list_search (gl_list_t list, const void *elt)
+{
+  size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list);
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->search_from_to (list, 0, size, elt);
+}
+
+# define gl_list_search_from gl_list_search_from_inline
+static inline gl_list_node_t
+gl_list_search_from (gl_list_t list, size_t start_index, const void *elt)
+{
+  size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list);
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->search_from_to (list, start_index, size, elt);
+}
+
+# define gl_list_search_from_to gl_list_search_from_to_inline
+static inline gl_list_node_t
+gl_list_search_from_to (gl_list_t list, size_t start_index, size_t end_index,
+                        const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->search_from_to (list, start_index, end_index, elt);
+}
+
+# define gl_list_indexof gl_list_indexof_inline
+static inline size_t
+gl_list_indexof (gl_list_t list, const void *elt)
+{
+  size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list);
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->indexof_from_to (list, 0, size, elt);
+}
+
+# define gl_list_indexof_from gl_list_indexof_from_inline
+static inline size_t
+gl_list_indexof_from (gl_list_t list, size_t start_index, const void *elt)
+{
+  size_t size = ((const struct gl_list_impl_base *) list)->vtable->size (list);
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->indexof_from_to (list, start_index, size, elt);
+}
+
+# define gl_list_indexof_from_to gl_list_indexof_from_to_inline
+static inline size_t
+gl_list_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index,
+                         const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->indexof_from_to (list, start_index, end_index, elt);
+}
+
+# define gl_list_nx_add_first gl_list_nx_add_first_inline
+static inline gl_list_node_t
+gl_list_nx_add_first (gl_list_t list, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->nx_add_first (list, elt);
+}
+
+# define gl_list_nx_add_last gl_list_nx_add_last_inline
+static inline gl_list_node_t
+gl_list_nx_add_last (gl_list_t list, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->nx_add_last (list, elt);
+}
+
+# define gl_list_nx_add_before gl_list_nx_add_before_inline
+static inline gl_list_node_t
+gl_list_nx_add_before (gl_list_t list, gl_list_node_t node, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->nx_add_before (list, node, elt);
+}
+
+# define gl_list_nx_add_after gl_list_nx_add_after_inline
+static inline gl_list_node_t
+gl_list_nx_add_after (gl_list_t list, gl_list_node_t node, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->nx_add_after (list, node, elt);
+}
+
+# define gl_list_nx_add_at gl_list_nx_add_at_inline
+static inline gl_list_node_t
+gl_list_nx_add_at (gl_list_t list, size_t position, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->nx_add_at (list, position, elt);
+}
+
+# define gl_list_remove_node gl_list_remove_node_inline
+static inline bool
+gl_list_remove_node (gl_list_t list, gl_list_node_t node)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->remove_node (list, node);
+}
+
+# define gl_list_remove_at gl_list_remove_at_inline
+static inline bool
+gl_list_remove_at (gl_list_t list, size_t position)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->remove_at (list, position);
+}
+
+# define gl_list_remove gl_list_remove_inline
+static inline bool
+gl_list_remove (gl_list_t list, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->remove_elt (list, elt);
+}
+
+# define gl_list_free gl_list_free_inline
+static inline void
+gl_list_free (gl_list_t list)
+{
+  ((const struct gl_list_impl_base *) list)->vtable->list_free (list);
+}
+
+# define gl_list_iterator gl_list_iterator_inline
+static inline gl_list_iterator_t
+gl_list_iterator (gl_list_t list)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->iterator (list);
+}
+
+# define gl_list_iterator_from_to gl_list_iterator_from_to_inline
+static inline gl_list_iterator_t
+gl_list_iterator_from_to (gl_list_t list, size_t start_index, size_t end_index)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->iterator_from_to (list, start_index, end_index);
+}
+
+# define gl_list_iterator_next gl_list_iterator_next_inline
+static inline bool
+gl_list_iterator_next (gl_list_iterator_t *iterator,
+                       const void **eltp, gl_list_node_t *nodep)
+{
+  return iterator->vtable->iterator_next (iterator, eltp, nodep);
+}
+
+# define gl_list_iterator_free gl_list_iterator_free_inline
+static inline void
+gl_list_iterator_free (gl_list_iterator_t *iterator)
+{
+  iterator->vtable->iterator_free (iterator);
+}
+
+# define gl_sortedlist_search gl_sortedlist_search_inline
+static inline gl_list_node_t
+gl_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->sortedlist_search (list, compar, elt);
+}
+
+# define gl_sortedlist_search_from_to gl_sortedlist_search_from_to_inline
+static inline gl_list_node_t
+gl_sortedlist_search_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t start_index, size_t end_index, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->sortedlist_search_from_to (list, compar, start_index, end_index,
+                                      elt);
+}
+
+# define gl_sortedlist_indexof gl_sortedlist_indexof_inline
+static inline size_t
+gl_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->sortedlist_indexof (list, compar, elt);
+}
+
+# define gl_sortedlist_indexof_from_to gl_sortedlist_indexof_from_to_inline
+static inline size_t
+gl_sortedlist_indexof_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t start_index, size_t end_index, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->sortedlist_indexof_from_to (list, compar, start_index, end_index,
+                                       elt);
+}
+
+# define gl_sortedlist_nx_add gl_sortedlist_nx_add_inline
+static inline gl_list_node_t
+gl_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->sortedlist_nx_add (list, compar, elt);
+}
+
+# define gl_sortedlist_remove gl_sortedlist_remove_inline
+static inline bool
+gl_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar, const void *elt)
+{
+  return ((const struct gl_list_impl_base *) list)->vtable
+         ->sortedlist_remove (list, compar, elt);
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GL_LIST_H */

+ 96 - 0
gnulib/lib/gl_oset.c

@@ -0,0 +1,96 @@
+/* Abstract ordered set data type.
+   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/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "gl_oset.h"
+
+#if !HAVE_INLINE
+
+/* Define all functions of this file as inline accesses to the
+   struct gl_list_implementation.
+   Use #define to avoid a warning because of extern vs. static.  */
+
+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 implementation->nx_create_empty (implementation, compar_fn,
+                                          dispose_fn);
+}
+
+size_t
+gl_oset_size (gl_oset_t set)
+{
+  return ((const struct gl_oset_impl_base *) set)->vtable->size (set);
+}
+
+bool
+gl_oset_search (gl_oset_t set, const void *elt)
+{
+  return ((const struct gl_oset_impl_base *) set)->vtable->search (set, elt);
+}
+
+bool
+gl_oset_search_atleast (gl_oset_t set,
+                        gl_setelement_threshold_fn threshold_fn,
+                        const void *threshold, const void **eltp)
+{
+  return ((const struct gl_oset_impl_base *) set)->vtable
+         ->search_atleast (set, threshold_fn, threshold, eltp);
+}
+
+int
+gl_oset_nx_add (gl_oset_t set, const void *elt)
+{
+  return ((const struct gl_oset_impl_base *) set)->vtable->nx_add (set, elt);
+}
+
+bool
+gl_oset_remove (gl_oset_t set, const void *elt)
+{
+  return ((const struct gl_oset_impl_base *) set)->vtable
+         ->remove_elt (set, elt);
+}
+
+void
+gl_oset_free (gl_oset_t set)
+{
+  ((const struct gl_oset_impl_base *) set)->vtable->oset_free (set);
+}
+
+gl_oset_iterator_t
+gl_oset_iterator (gl_oset_t set)
+{
+  return ((const struct gl_oset_impl_base *) set)->vtable->iterator (set);
+}
+
+bool
+gl_oset_iterator_next (gl_oset_iterator_t *iterator, const void **eltp)
+{
+  return iterator->vtable->iterator_next (iterator, eltp);
+}
+
+void
+gl_oset_iterator_free (gl_oset_iterator_t *iterator)
+{
+  iterator->vtable->iterator_free (iterator);
+}
+
+#endif

+ 289 - 0
gnulib/lib/gl_oset.h

@@ -0,0 +1,289 @@
+/* Abstract ordered set data type.
+   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/>.  */
+
+#ifndef _GL_OSET_H
+#define _GL_OSET_H
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* gl_oset is an abstract ordered set data type.  It can contain any number
+   of objects ('void *' or 'const void *' pointers) in the order of a given
+   comparator function.  Duplicates (in the sense of the comparator) are
+   forbidden.
+
+   There are several implementations of this ordered set datatype, optimized
+   for different operations or for memory.  You can start using the simplest
+   ordered set implementation, GL_ARRAY_OSET, and switch to a different
+   implementation later, when you realize which operations are performed
+   the most frequently.  The API of the different implementations is exactly
+   the same; when switching to a different implementation, you only have to
+   change the gl_oset_create call.
+
+   The implementations are:
+     GL_ARRAY_OSET        a growable array
+     GL_AVLTREE_OSET      a binary tree (AVL tree)
+     GL_RBTREE_OSET       a binary tree (red-black tree)
+
+   The memory consumption is asymptotically the same: O(1) for every object
+   in the set.  When looking more closely at the average memory consumed
+   for an object, GL_ARRAY_OSET is the most compact representation, and
+   GL_AVLTREE_OSET, GL_RBTREE_OSET need more memory.
+
+   The guaranteed average performance of the operations is, for a set of
+   n elements:
+
+   Operation                  ARRAY     TREE
+
+   gl_oset_size                O(1)     O(1)
+   gl_oset_add                 O(n)   O(log n)
+   gl_oset_remove              O(n)   O(log n)
+   gl_oset_search            O(log n) O(log n)
+   gl_oset_search_atleast    O(log n) O(log n)
+   gl_oset_iterator            O(1)   O(log n)
+   gl_oset_iterator_next       O(1)   O(log n)
+ */
+
+/* -------------------------- gl_oset_t Data Type -------------------------- */