auto import from //depot/cupcake/@135843
diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644
index 0000000..25490d3
--- /dev/null
+++ b/lib/Makefile
@@ -0,0 +1,623 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# lib/Makefile.  Generated from Makefile.in by configure.
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+srcdir = .
+top_srcdir = ..
+
+pkgdatadir = $(datadir)/bison
+pkglibdir = $(libdir)/bison
+pkgincludedir = $(includedir)/bison
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = /usr/bin/install -c
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = x86_64-unknown-linux-gnu
+host_triplet = x86_64-unknown-linux-gnu
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+	$(srcdir)/gnulib.mk dirname.c dirname.h dup-safer.c error.c \
+	error.h exitfail.c exitfail.h fd-safer.c fopen-safer.c \
+	getopt.c getopt1.c hard-locale.c hard-locale.h hash.c hash.h \
+	malloc.c obstack.c obstack.h pipe-safer.c quote.c quote.h \
+	quotearg.c quotearg.h stdio--.h stdio-safer.h stpcpy.c \
+	strdup.c strdup.h strerror.c strndup.c strndup.h strnlen.c \
+	strnlen.h strtol.c strtoul.c strverscmp.c strverscmp.h \
+	unistd--.h unistd-safer.h unlocked-io.h xalloc.h xmalloc.c
+subdir = lib
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/bison-i18n.m4 \
+	$(top_srcdir)/m4/c-working.m4 $(top_srcdir)/m4/cxx.m4 \
+	$(top_srcdir)/m4/dirname.m4 $(top_srcdir)/m4/dmalloc.m4 \
+	$(top_srcdir)/m4/dos.m4 $(top_srcdir)/m4/error.m4 \
+	$(top_srcdir)/m4/exitfail.m4 $(top_srcdir)/m4/extensions.m4 \
+	$(top_srcdir)/m4/getopt.m4 $(top_srcdir)/m4/gettext_gl.m4 \
+	$(top_srcdir)/m4/gnulib.m4 $(top_srcdir)/m4/hard-locale.m4 \
+	$(top_srcdir)/m4/hash.m4 $(top_srcdir)/m4/iconv.m4 \
+	$(top_srcdir)/m4/inttypes_h_gl.m4 \
+	$(top_srcdir)/m4/lib-ld_gl.m4 $(top_srcdir)/m4/lib-link.m4 \
+	$(top_srcdir)/m4/lib-prefix_gl.m4 $(top_srcdir)/m4/m4.m4 \
+	$(top_srcdir)/m4/mbrtowc.m4 $(top_srcdir)/m4/mbstate_t.m4 \
+	$(top_srcdir)/m4/mbswidth.m4 $(top_srcdir)/m4/nls.m4 \
+	$(top_srcdir)/m4/obstack.m4 $(top_srcdir)/m4/onceonly.m4 \
+	$(top_srcdir)/m4/po_gl.m4 $(top_srcdir)/m4/progtest.m4 \
+	$(top_srcdir)/m4/quote.m4 $(top_srcdir)/m4/quotearg.m4 \
+	$(top_srcdir)/m4/stdbool.m4 $(top_srcdir)/m4/stdint_h_gl.m4 \
+	$(top_srcdir)/m4/stdio-safer.m4 $(top_srcdir)/m4/stpcpy.m4 \
+	$(top_srcdir)/m4/strdup.m4 $(top_srcdir)/m4/strerror.m4 \
+	$(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/strnlen.m4 \
+	$(top_srcdir)/m4/strtol.m4 $(top_srcdir)/m4/strtoul.m4 \
+	$(top_srcdir)/m4/strverscmp.m4 $(top_srcdir)/m4/subpipe.m4 \
+	$(top_srcdir)/m4/timevar.m4 $(top_srcdir)/m4/uintmax_t_gl.m4 \
+	$(top_srcdir)/m4/ulonglong_gl.m4 \
+	$(top_srcdir)/m4/unistd-safer.m4 $(top_srcdir)/m4/unistd_h.m4 \
+	$(top_srcdir)/m4/unlocked-io.m4 $(top_srcdir)/m4/warning.m4 \
+	$(top_srcdir)/m4/xalloc.m4 $(top_srcdir)/m4/xstrndup.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)"
+libLIBRARIES_INSTALL = $(INSTALL_DATA)
+LIBRARIES = $(lib_LIBRARIES) $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+libbison_a_AR = $(AR) $(ARFLAGS)
+am__DEPENDENCIES_1 =  dirname$U.o exitfail$U.o hard-locale$U.o hash$U.o quote$U.o quotearg$U.o fopen-safer$U.o dup-safer$U.o fd-safer$U.o pipe-safer$U.o xmalloc$U.o
+am__objects_1 = abitset.$(OBJEXT) bitset.$(OBJEXT) \
+	bitset_stats.$(OBJEXT) bitsetv.$(OBJEXT) ebitset.$(OBJEXT) \
+	lbitset.$(OBJEXT) vbitset.$(OBJEXT)
+am__objects_2 = bitsetv-print.$(OBJEXT)
+am__objects_3 = timevar.$(OBJEXT)
+am__objects_4 = get-errno.$(OBJEXT) subpipe.$(OBJEXT) $(am__objects_1) \
+	$(am__objects_2) $(am__objects_3) argmatch.$(OBJEXT) \
+	basename.$(OBJEXT) stripslash.$(OBJEXT) mbswidth.$(OBJEXT) \
+	xalloc-die.$(OBJEXT) xstrndup.$(OBJEXT)
+am_libbison_a_OBJECTS = $(am__objects_4)
+libbison_a_OBJECTS = $(am_libbison_a_OBJECTS)
+liby_a_AR = $(AR) $(ARFLAGS)
+liby_a_LIBADD =
+am_liby_a_OBJECTS = main.$(OBJEXT) yyerror.$(OBJEXT)
+liby_a_OBJECTS = $(am_liby_a_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libbison_a_SOURCES) $(liby_a_SOURCES)
+DIST_SOURCES = $(libbison_a_SOURCES) $(liby_a_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = ${SHELL} /usr/local/google/workspace/WebKit/tools/bison-2.3/build-aux/missing --run aclocal-1.9
+AMDEP_FALSE = #
+AMDEP_TRUE = 
+AMTAR = ${SHELL} /usr/local/google/workspace/WebKit/tools/bison-2.3/build-aux/missing --run tar
+AUTOCONF = ${SHELL} /usr/local/google/workspace/WebKit/tools/bison-2.3/build-aux/missing --run autoconf
+AUTOHEADER = ${SHELL} /usr/local/google/workspace/WebKit/tools/bison-2.3/build-aux/missing --run autoheader
+AUTOM4TE = ${SHELL} /usr/local/google/workspace/WebKit/tools/bison-2.3/build-aux/missing --run autom4te
+AUTOMAKE = ${SHELL} /usr/local/google/workspace/WebKit/tools/bison-2.3/build-aux/missing --run automake-1.9
+AWK = gawk
+BISON_CXX_WORKS = :
+BISON_CXX_WORKS_FALSE = #
+BISON_CXX_WORKS_TRUE = 
+BISON_LOCALEDIR = /usr/share/locale
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2
+CPP = gcc -E
+CPPFLAGS = 
+CXX = g++
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O2
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+ECHO_C = 
+ECHO_N = -n
+ECHO_T = 
+EGREP = grep -E
+EXEEXT = 
+GCC = yes
+GETOPT_H = 
+GMSGFMT = /usr/bin/msgfmt
+HAVE__BOOL = 1
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s
+INTLLIBS = 
+INTL_MACOSX_LIBS = 
+LDFLAGS = 
+LEX = flex
+LEXLIB = -lfl
+LEX_OUTPUT_ROOT = lex.yy
+LIBICONV = -liconv
+LIBINTL = 
+LIBOBJS =  dirname$U.o exitfail$U.o hard-locale$U.o hash$U.o quote$U.o quotearg$U.o fopen-safer$U.o dup-safer$U.o fd-safer$U.o pipe-safer$U.o xmalloc$U.o
+LIBS = 
+LTLIBICONV = -liconv
+LTLIBINTL = 
+LTLIBOBJS =  dirname$U.lo exitfail$U.lo hard-locale$U.lo hash$U.lo quote$U.lo quotearg$U.lo fopen-safer$U.lo dup-safer$U.lo fd-safer$U.lo pipe-safer$U.lo xmalloc$U.lo
+M4 = /usr/bin/m4
+MAKEINFO = ${SHELL} /usr/local/google/workspace/WebKit/tools/bison-2.3/build-aux/missing --run makeinfo
+MKINSTALLDIRS = $(top_builddir)/build-aux/mkinstalldirs
+MSGFMT = /usr/bin/msgfmt
+MSGMERGE = /usr/bin/msgmerge
+O0CFLAGS = -g 
+O0CXXFLAGS = -g 
+OBJEXT = o
+PACKAGE = bison
+PACKAGE_BUGREPORT = bug-bison@gnu.org
+PACKAGE_NAME = GNU Bison
+PACKAGE_STRING = GNU Bison 2.3
+PACKAGE_TARNAME = bison
+PACKAGE_VERSION = 2.3
+PATH_SEPARATOR = :
+POSUB = po
+RANLIB = ranlib
+SET_MAKE = 
+SHELL = /bin/sh
+STDBOOL_H = 
+STRIP = 
+UNISTD_H = 
+USE_NLS = yes
+VALGRIND = 
+VERSION = 2.3
+WARNING_CFLAGS = 
+WARNING_CXXFLAGS = 
+WERROR_CFLAGS = 
+XGETTEXT = /usr/bin/xgettext
+YACC = bison -y
+YACC_LIBRARY = liby.a
+YACC_SCRIPT = yacc
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+ac_ct_RANLIB = ranlib
+ac_ct_STRIP = 
+aclocaldir = ${datadir}/aclocal
+am__fastdepCC_FALSE = #
+am__fastdepCC_TRUE = 
+am__fastdepCXX_FALSE = #
+am__fastdepCXX_TRUE = 
+am__include = include
+am__leading_dot = .
+am__quote = 
+am__tar = ${AMTAR} chof - "$$tardir"
+am__untar = ${AMTAR} xf -
+bindir = ${exec_prefix}/bin
+build = x86_64-unknown-linux-gnu
+build_alias = 
+build_cpu = x86_64
+build_os = linux-gnu
+build_vendor = unknown
+datadir = ${prefix}/share
+exec_prefix = ${prefix}
+host = x86_64-unknown-linux-gnu
+host_alias = 
+host_cpu = x86_64
+host_os = linux-gnu
+host_vendor = unknown
+includedir = ${prefix}/include
+infodir = ${prefix}/info
+install_sh = /usr/local/google/workspace/WebKit/tools/bison-2.3/build-aux/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localstatedir = ${prefix}/var
+mandir = ${prefix}/man
+mkdir_p = mkdir -p --
+oldincludedir = /usr/include
+prefix = /home/phanna/src/bison
+program_transform_name = s,x,x,
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+sysconfdir = ${prefix}/etc
+target_alias = 
+AM_CFLAGS = $(WARNING_CFLAGS)
+BUILT_SOURCES = $(GETOPT_H) $(STDBOOL_H) $(UNISTD_H)
+EXTRA_DIST = getopt_.h getopt_int.h stdbool_.h
+MOSTLYCLEANFILES = getopt.h getopt.h-t stdbool.h stdbool.h-t unistd.h
+lib_LIBRARIES = $(YACC_LIBRARY)
+EXTRA_LIBRARIES = liby.a
+noinst_LIBRARIES = libbison.a
+liby_a_SOURCES = main.c yyerror.c
+libbison_a_SOURCES = $(lib_SOURCES)
+
+# This file is generated automatically by "bootstrap".
+
+# This is for those projects which use "gettextize --intl" to put a source-code
+# copy of libintl into their package. In such projects, every Makefile.am needs
+# -I$(top_builddir)/intl, so that <libintl.h> can be found in this directory.
+# For the Makefile.ams in other directories it is the maintainer's
+# responsibility; for the one from gnulib we do it here.
+# This option has no effect when the user disables NLS (because then the intl
+# directory contains no libintl.h file) or when the project does not use
+# "gettextize --intl".
+# (commented out by bootstrap) AM_CPPFLAGS += -I$(top_builddir)/intl
+lib_SOURCES = get-errno.h get-errno.c subpipe.h subpipe.c \
+	$(bitsets_sources) $(additional_bitsets_sources) \
+	$(timevars_sources) argmatch.h argmatch.c basename.c \
+	stripslash.c exit.h gettext.h mbswidth.h mbswidth.c stpcpy.h \
+	verify.h xalloc-die.c xstrndup.h xstrndup.c
+
+# Implementation of bitsets
+bitsets_sources = \
+  abitset.c abitset.h bbitset.h bitset.c bitset.h bitset_stats.c	\
+  bitset_stats.h bitsetv.c bitsetv.h ebitset.c ebitset.h lbitset.c	\
+  lbitset.h libiberty.h vbitset.c vbitset.h
+
+
+# Additional bitset operations.
+additional_bitsets_sources = \
+	bitsetv-print.h bitsetv-print.c
+
+
+# timevars, stolen from GCC.
+timevars_sources = \
+	timevar.h timevar.c timevar.def
+
+libbison_a_LIBADD = $(LIBOBJS) $(ALLOCA)
+libbison_a_DEPENDENCIES = $(libbison_a_LIBADD)
+all: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am $(srcdir)/gnulib.mk $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  lib/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  lib/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLIBRARIES: $(lib_LIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
+	@list='$(lib_LIBRARIES)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    f=$(am__strip_dir) \
+	    echo " $(libLIBRARIES_INSTALL) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+	    $(libLIBRARIES_INSTALL) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+	  else :; fi; \
+	done
+	@$(POST_INSTALL)
+	@list='$(lib_LIBRARIES)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    p=$(am__strip_dir) \
+	    echo " $(RANLIB) '$(DESTDIR)$(libdir)/$$p'"; \
+	    $(RANLIB) "$(DESTDIR)$(libdir)/$$p"; \
+	  else :; fi; \
+	done
+
+uninstall-libLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(lib_LIBRARIES)'; for p in $$list; do \
+	  p=$(am__strip_dir) \
+	  echo " rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+	  rm -f "$(DESTDIR)$(libdir)/$$p"; \
+	done
+
+clean-libLIBRARIES:
+	-test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES)
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libbison.a: $(libbison_a_OBJECTS) $(libbison_a_DEPENDENCIES) 
+	-rm -f libbison.a
+	$(libbison_a_AR) libbison.a $(libbison_a_OBJECTS) $(libbison_a_LIBADD)
+	$(RANLIB) libbison.a
+liby.a: $(liby_a_OBJECTS) $(liby_a_DEPENDENCIES) 
+	-rm -f liby.a
+	$(liby_a_AR) liby.a $(liby_a_OBJECTS) $(liby_a_LIBADD)
+	$(RANLIB) liby.a
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+include $(DEPDIR)/dirname.Po
+include $(DEPDIR)/dup-safer.Po
+include $(DEPDIR)/error.Po
+include $(DEPDIR)/exitfail.Po
+include $(DEPDIR)/fd-safer.Po
+include $(DEPDIR)/fopen-safer.Po
+include $(DEPDIR)/getopt.Po
+include $(DEPDIR)/getopt1.Po
+include $(DEPDIR)/hard-locale.Po
+include $(DEPDIR)/hash.Po
+include $(DEPDIR)/malloc.Po
+include $(DEPDIR)/obstack.Po
+include $(DEPDIR)/pipe-safer.Po
+include $(DEPDIR)/quote.Po
+include $(DEPDIR)/quotearg.Po
+include $(DEPDIR)/stpcpy.Po
+include $(DEPDIR)/strdup.Po
+include $(DEPDIR)/strerror.Po
+include $(DEPDIR)/strndup.Po
+include $(DEPDIR)/strnlen.Po
+include $(DEPDIR)/strtol.Po
+include $(DEPDIR)/strtoul.Po
+include $(DEPDIR)/strverscmp.Po
+include $(DEPDIR)/xmalloc.Po
+include ./$(DEPDIR)/abitset.Po
+include ./$(DEPDIR)/argmatch.Po
+include ./$(DEPDIR)/basename.Po
+include ./$(DEPDIR)/bitset.Po
+include ./$(DEPDIR)/bitset_stats.Po
+include ./$(DEPDIR)/bitsetv-print.Po
+include ./$(DEPDIR)/bitsetv.Po
+include ./$(DEPDIR)/ebitset.Po
+include ./$(DEPDIR)/get-errno.Po
+include ./$(DEPDIR)/lbitset.Po
+include ./$(DEPDIR)/main.Po
+include ./$(DEPDIR)/mbswidth.Po
+include ./$(DEPDIR)/stripslash.Po
+include ./$(DEPDIR)/subpipe.Po
+include ./$(DEPDIR)/timevar.Po
+include ./$(DEPDIR)/vbitset.Po
+include ./$(DEPDIR)/xalloc-die.Po
+include ./$(DEPDIR)/xstrndup.Po
+include ./$(DEPDIR)/yyerror.Po
+
+.c.o:
+	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+#	source='$<' object='$@' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(COMPILE) -c $<
+
+.c.obj:
+	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+#	source='$<' object='$@' libtool=no \
+#	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LIBRARIES)
+installdirs:
+	for dir in "$(DESTDIR)$(libdir)"; do \
+	  test -z "$$dir" || $(mkdir_p) "$$dir"; \
+	done
+install: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libLIBRARIES clean-noinstLIBRARIES \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf $(DEPDIR) ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-libLIBRARIES
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf $(DEPDIR) ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-libLIBRARIES
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libLIBRARIES clean-noinstLIBRARIES ctags distclean \
+	distclean-compile distclean-generic distclean-tags distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-exec install-exec-am \
+	install-info install-info-am install-libLIBRARIES install-man \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+	tags uninstall uninstall-am uninstall-info-am \
+	uninstall-libLIBRARIES
+
+
+# We need the following in order to create <getopt.h> when the system
+# doesn't have one that works with the given compiler.
+getopt.h: getopt_.h
+	cp $(srcdir)/getopt_.h $@-t
+	mv $@-t $@
+
+# We need the following in order to create <stdbool.h> when the system
+# doesn't have one that works.
+stdbool.h: stdbool_.h
+	sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool_.h > $@-t
+	mv $@-t $@
+
+# We need the following in order to create an empty placeholder for
+# <unistd.h> when the system doesn't have one.
+unistd.h:
+	echo '/* Empty placeholder for $@.  */' >$@
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644
index 0000000..f4d783e
--- /dev/null
+++ b/lib/Makefile.am
@@ -0,0 +1,53 @@
+## Copyright (C) 2001, 2002, 2003, 2004 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 2 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, write to the Free Software
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301  USA
+
+AM_CFLAGS = $(WARNING_CFLAGS)
+
+BUILT_SOURCES =
+EXTRA_DIST =
+MOSTLYCLEANFILES =
+
+lib_LIBRARIES = $(YACC_LIBRARY)
+EXTRA_LIBRARIES = liby.a
+noinst_LIBRARIES = libbison.a
+
+liby_a_SOURCES = main.c yyerror.c
+
+libbison_a_SOURCES = $(lib_SOURCES)
+lib_SOURCES = \
+  get-errno.h get-errno.c \
+  subpipe.h subpipe.c \
+  $(bitsets_sources) $(additional_bitsets_sources) $(timevars_sources)
+
+# Implementation of bitsets
+bitsets_sources = \
+  abitset.c abitset.h bbitset.h bitset.c bitset.h bitset_stats.c	\
+  bitset_stats.h bitsetv.c bitsetv.h ebitset.c ebitset.h lbitset.c	\
+  lbitset.h libiberty.h vbitset.c vbitset.h
+
+# Additional bitset operations.
+additional_bitsets_sources = \
+	bitsetv-print.h bitsetv-print.c
+
+# timevars, stolen from GCC.
+timevars_sources = \
+	timevar.h timevar.c timevar.def
+
+libbison_a_LIBADD = $(LIBOBJS) $(ALLOCA)
+libbison_a_DEPENDENCIES = $(libbison_a_LIBADD)
+
+include gnulib.mk
diff --git a/lib/Makefile.in b/lib/Makefile.in
new file mode 100644
index 0000000..d3613e9
--- /dev/null
+++ b/lib/Makefile.in
@@ -0,0 +1,623 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+	$(srcdir)/gnulib.mk dirname.c dirname.h dup-safer.c error.c \
+	error.h exitfail.c exitfail.h fd-safer.c fopen-safer.c \
+	getopt.c getopt1.c hard-locale.c hard-locale.h hash.c hash.h \
+	malloc.c obstack.c obstack.h pipe-safer.c quote.c quote.h \
+	quotearg.c quotearg.h stdio--.h stdio-safer.h stpcpy.c \
+	strdup.c strdup.h strerror.c strndup.c strndup.h strnlen.c \
+	strnlen.h strtol.c strtoul.c strverscmp.c strverscmp.h \
+	unistd--.h unistd-safer.h unlocked-io.h xalloc.h xmalloc.c
+subdir = lib
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/bison-i18n.m4 \
+	$(top_srcdir)/m4/c-working.m4 $(top_srcdir)/m4/cxx.m4 \
+	$(top_srcdir)/m4/dirname.m4 $(top_srcdir)/m4/dmalloc.m4 \
+	$(top_srcdir)/m4/dos.m4 $(top_srcdir)/m4/error.m4 \
+	$(top_srcdir)/m4/exitfail.m4 $(top_srcdir)/m4/extensions.m4 \
+	$(top_srcdir)/m4/getopt.m4 $(top_srcdir)/m4/gettext_gl.m4 \
+	$(top_srcdir)/m4/gnulib.m4 $(top_srcdir)/m4/hard-locale.m4 \
+	$(top_srcdir)/m4/hash.m4 $(top_srcdir)/m4/iconv.m4 \
+	$(top_srcdir)/m4/inttypes_h_gl.m4 \
+	$(top_srcdir)/m4/lib-ld_gl.m4 $(top_srcdir)/m4/lib-link.m4 \
+	$(top_srcdir)/m4/lib-prefix_gl.m4 $(top_srcdir)/m4/m4.m4 \
+	$(top_srcdir)/m4/mbrtowc.m4 $(top_srcdir)/m4/mbstate_t.m4 \
+	$(top_srcdir)/m4/mbswidth.m4 $(top_srcdir)/m4/nls.m4 \
+	$(top_srcdir)/m4/obstack.m4 $(top_srcdir)/m4/onceonly.m4 \
+	$(top_srcdir)/m4/po_gl.m4 $(top_srcdir)/m4/progtest.m4 \
+	$(top_srcdir)/m4/quote.m4 $(top_srcdir)/m4/quotearg.m4 \
+	$(top_srcdir)/m4/stdbool.m4 $(top_srcdir)/m4/stdint_h_gl.m4 \
+	$(top_srcdir)/m4/stdio-safer.m4 $(top_srcdir)/m4/stpcpy.m4 \
+	$(top_srcdir)/m4/strdup.m4 $(top_srcdir)/m4/strerror.m4 \
+	$(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/strnlen.m4 \
+	$(top_srcdir)/m4/strtol.m4 $(top_srcdir)/m4/strtoul.m4 \
+	$(top_srcdir)/m4/strverscmp.m4 $(top_srcdir)/m4/subpipe.m4 \
+	$(top_srcdir)/m4/timevar.m4 $(top_srcdir)/m4/uintmax_t_gl.m4 \
+	$(top_srcdir)/m4/ulonglong_gl.m4 \
+	$(top_srcdir)/m4/unistd-safer.m4 $(top_srcdir)/m4/unistd_h.m4 \
+	$(top_srcdir)/m4/unlocked-io.m4 $(top_srcdir)/m4/warning.m4 \
+	$(top_srcdir)/m4/xalloc.m4 $(top_srcdir)/m4/xstrndup.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)"
+libLIBRARIES_INSTALL = $(INSTALL_DATA)
+LIBRARIES = $(lib_LIBRARIES) $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+libbison_a_AR = $(AR) $(ARFLAGS)
+am__DEPENDENCIES_1 = @LIBOBJS@
+am__objects_1 = abitset.$(OBJEXT) bitset.$(OBJEXT) \
+	bitset_stats.$(OBJEXT) bitsetv.$(OBJEXT) ebitset.$(OBJEXT) \
+	lbitset.$(OBJEXT) vbitset.$(OBJEXT)
+am__objects_2 = bitsetv-print.$(OBJEXT)
+am__objects_3 = timevar.$(OBJEXT)
+am__objects_4 = get-errno.$(OBJEXT) subpipe.$(OBJEXT) $(am__objects_1) \
+	$(am__objects_2) $(am__objects_3) argmatch.$(OBJEXT) \
+	basename.$(OBJEXT) stripslash.$(OBJEXT) mbswidth.$(OBJEXT) \
+	xalloc-die.$(OBJEXT) xstrndup.$(OBJEXT)
+am_libbison_a_OBJECTS = $(am__objects_4)
+libbison_a_OBJECTS = $(am_libbison_a_OBJECTS)
+liby_a_AR = $(AR) $(ARFLAGS)
+liby_a_LIBADD =
+am_liby_a_OBJECTS = main.$(OBJEXT) yyerror.$(OBJEXT)
+liby_a_OBJECTS = $(am_liby_a_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libbison_a_SOURCES) $(liby_a_SOURCES)
+DIST_SOURCES = $(libbison_a_SOURCES) $(liby_a_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOM4TE = @AUTOM4TE@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BISON_CXX_WORKS = @BISON_CXX_WORKS@
+BISON_CXX_WORKS_FALSE = @BISON_CXX_WORKS_FALSE@
+BISON_CXX_WORKS_TRUE = @BISON_CXX_WORKS_TRUE@
+BISON_LOCALEDIR = @BISON_LOCALEDIR@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GCC = @GCC@
+GETOPT_H = @GETOPT_H@
+GMSGFMT = @GMSGFMT@
+HAVE__BOOL = @HAVE__BOOL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+M4 = @M4@
+MAKEINFO = @MAKEINFO@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGMERGE = @MSGMERGE@
+O0CFLAGS = @O0CFLAGS@
+O0CXXFLAGS = @O0CXXFLAGS@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STDBOOL_H = @STDBOOL_H@
+STRIP = @STRIP@
+UNISTD_H = @UNISTD_H@
+USE_NLS = @USE_NLS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARNING_CFLAGS = @WARNING_CFLAGS@
+WARNING_CXXFLAGS = @WARNING_CXXFLAGS@
+WERROR_CFLAGS = @WERROR_CFLAGS@
+XGETTEXT = @XGETTEXT@
+YACC = @YACC@
+YACC_LIBRARY = @YACC_LIBRARY@
+YACC_SCRIPT = @YACC_SCRIPT@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+aclocaldir = @aclocaldir@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+AM_CFLAGS = $(WARNING_CFLAGS)
+BUILT_SOURCES = $(GETOPT_H) $(STDBOOL_H) $(UNISTD_H)
+EXTRA_DIST = getopt_.h getopt_int.h stdbool_.h
+MOSTLYCLEANFILES = getopt.h getopt.h-t stdbool.h stdbool.h-t unistd.h
+lib_LIBRARIES = $(YACC_LIBRARY)
+EXTRA_LIBRARIES = liby.a
+noinst_LIBRARIES = libbison.a
+liby_a_SOURCES = main.c yyerror.c
+libbison_a_SOURCES = $(lib_SOURCES)
+
+# This file is generated automatically by "bootstrap".
+
+# This is for those projects which use "gettextize --intl" to put a source-code
+# copy of libintl into their package. In such projects, every Makefile.am needs
+# -I$(top_builddir)/intl, so that <libintl.h> can be found in this directory.
+# For the Makefile.ams in other directories it is the maintainer's
+# responsibility; for the one from gnulib we do it here.
+# This option has no effect when the user disables NLS (because then the intl
+# directory contains no libintl.h file) or when the project does not use
+# "gettextize --intl".
+# (commented out by bootstrap) AM_CPPFLAGS += -I$(top_builddir)/intl
+lib_SOURCES = get-errno.h get-errno.c subpipe.h subpipe.c \
+	$(bitsets_sources) $(additional_bitsets_sources) \
+	$(timevars_sources) argmatch.h argmatch.c basename.c \
+	stripslash.c exit.h gettext.h mbswidth.h mbswidth.c stpcpy.h \
+	verify.h xalloc-die.c xstrndup.h xstrndup.c
+
+# Implementation of bitsets
+bitsets_sources = \
+  abitset.c abitset.h bbitset.h bitset.c bitset.h bitset_stats.c	\
+  bitset_stats.h bitsetv.c bitsetv.h ebitset.c ebitset.h lbitset.c	\
+  lbitset.h libiberty.h vbitset.c vbitset.h
+
+
+# Additional bitset operations.
+additional_bitsets_sources = \
+	bitsetv-print.h bitsetv-print.c
+
+
+# timevars, stolen from GCC.
+timevars_sources = \
+	timevar.h timevar.c timevar.def
+
+libbison_a_LIBADD = $(LIBOBJS) $(ALLOCA)
+libbison_a_DEPENDENCIES = $(libbison_a_LIBADD)
+all: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am $(srcdir)/gnulib.mk $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  lib/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  lib/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLIBRARIES: $(lib_LIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
+	@list='$(lib_LIBRARIES)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    f=$(am__strip_dir) \
+	    echo " $(libLIBRARIES_INSTALL) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+	    $(libLIBRARIES_INSTALL) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+	  else :; fi; \
+	done
+	@$(POST_INSTALL)
+	@list='$(lib_LIBRARIES)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    p=$(am__strip_dir) \
+	    echo " $(RANLIB) '$(DESTDIR)$(libdir)/$$p'"; \
+	    $(RANLIB) "$(DESTDIR)$(libdir)/$$p"; \
+	  else :; fi; \
+	done
+
+uninstall-libLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(lib_LIBRARIES)'; for p in $$list; do \
+	  p=$(am__strip_dir) \
+	  echo " rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+	  rm -f "$(DESTDIR)$(libdir)/$$p"; \
+	done
+
+clean-libLIBRARIES:
+	-test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES)
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libbison.a: $(libbison_a_OBJECTS) $(libbison_a_DEPENDENCIES) 
+	-rm -f libbison.a
+	$(libbison_a_AR) libbison.a $(libbison_a_OBJECTS) $(libbison_a_LIBADD)
+	$(RANLIB) libbison.a
+liby.a: $(liby_a_OBJECTS) $(liby_a_DEPENDENCIES) 
+	-rm -f liby.a
+	$(liby_a_AR) liby.a $(liby_a_OBJECTS) $(liby_a_LIBADD)
+	$(RANLIB) liby.a
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/dirname.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/dup-safer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/error.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/exitfail.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/fd-safer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/fopen-safer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/getopt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/getopt1.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/hard-locale.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/hash.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/malloc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/obstack.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pipe-safer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/quote.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/quotearg.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/stpcpy.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strdup.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strerror.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strndup.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strnlen.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strtol.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strtoul.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strverscmp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/xmalloc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/abitset.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argmatch.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basename.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bitset.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bitset_stats.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bitsetv-print.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bitsetv.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ebitset.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/get-errno.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lbitset.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbswidth.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stripslash.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subpipe.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timevar.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vbitset.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xalloc-die.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xstrndup.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yyerror.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LIBRARIES)
+installdirs:
+	for dir in "$(DESTDIR)$(libdir)"; do \
+	  test -z "$$dir" || $(mkdir_p) "$$dir"; \
+	done
+install: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libLIBRARIES clean-noinstLIBRARIES \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf $(DEPDIR) ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-libLIBRARIES
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf $(DEPDIR) ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-libLIBRARIES
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libLIBRARIES clean-noinstLIBRARIES ctags distclean \
+	distclean-compile distclean-generic distclean-tags distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-exec install-exec-am \
+	install-info install-info-am install-libLIBRARIES install-man \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+	tags uninstall uninstall-am uninstall-info-am \
+	uninstall-libLIBRARIES
+
+
+# We need the following in order to create <getopt.h> when the system
+# doesn't have one that works with the given compiler.
+getopt.h: getopt_.h
+	cp $(srcdir)/getopt_.h $@-t
+	mv $@-t $@
+
+# We need the following in order to create <stdbool.h> when the system
+# doesn't have one that works.
+stdbool.h: stdbool_.h
+	sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool_.h > $@-t
+	mv $@-t $@
+
+# We need the following in order to create an empty placeholder for
+# <unistd.h> when the system doesn't have one.
+unistd.h:
+	echo '/* Empty placeholder for $@.  */' >$@
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lib/abitset.c b/lib/abitset.c
new file mode 100644
index 0000000..17c0a4a
--- /dev/null
+++ b/lib/abitset.c
@@ -0,0 +1,828 @@
+/* Array bitsets.
+   Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc.
+   Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
+
+   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 2 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "abitset.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* This file implements fixed size bitsets stored as an array
+   of words.  Any unused bits in the last word must be zero.  */
+
+#define ABITSET_N_WORDS(N) (((N) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS)
+#define ABITSET_WORDS(X) ((X)->a.words)
+
+
+static bitset_bindex
+abitset_resize (bitset src, bitset_bindex size)
+{
+    /* These bitsets have a fixed size.  */
+    if (BITSET_SIZE_ (src) != size)
+      abort ();
+
+    return size;
+}
+
+/* Find list of up to NUM bits set in BSET starting from and including
+ *NEXT and store in array LIST.  Return with actual number of bits
+ found and with *NEXT indicating where search stopped.  */
+static bitset_bindex
+abitset_small_list (bitset src, bitset_bindex *list,
+		    bitset_bindex num, bitset_bindex *next)
+{
+  bitset_bindex bitno;
+  bitset_bindex count;
+  bitset_windex size;
+  bitset_word word;
+
+  word = ABITSET_WORDS (src)[0];
+
+  /* Short circuit common case.  */
+  if (!word)
+    return 0;
+
+  size = BITSET_SIZE_ (src);
+  bitno = *next;
+  if (bitno >= size)
+    return 0;
+
+  word >>= bitno;
+
+  /* If num is 1, we could speed things up with a binary search
+     of the word of interest.  */
+
+  if (num >= BITSET_WORD_BITS)
+    {
+      for (count = 0; word; bitno++)
+	{
+	  if (word & 1)
+	    list[count++] = bitno;
+	  word >>= 1;
+	}
+    }
+  else
+    {
+      for (count = 0; word; bitno++)
+	{
+	  if (word & 1)
+	    {
+	      list[count++] = bitno;
+	      if (count >= num)
+		{
+		  bitno++;
+		  break;
+		}
+	    }
+	  word >>= 1;
+	}
+    }
+
+  *next = bitno;
+  return count;
+}
+
+
+/* Set bit BITNO in bitset DST.  */
+static void
+abitset_set (bitset dst ATTRIBUTE_UNUSED, bitset_bindex bitno ATTRIBUTE_UNUSED)
+{
+  /* This should never occur for abitsets since we should always hit
+     the cache.  It is likely someone is trying to access outside the
+     bounds of the bitset.  */
+  abort ();
+}
+
+
+/* Reset bit BITNO in bitset DST.  */
+static void
+abitset_reset (bitset dst ATTRIBUTE_UNUSED,
+	       bitset_bindex bitno ATTRIBUTE_UNUSED)
+{
+  /* This should never occur for abitsets since we should always hit
+     the cache.  It is likely someone is trying to access outside the
+     bounds of the bitset.  Since the bit is zero anyway, let it pass.  */
+}
+
+
+/* Test bit BITNO in bitset SRC.  */
+static bool
+abitset_test (bitset src ATTRIBUTE_UNUSED,
+	      bitset_bindex bitno ATTRIBUTE_UNUSED)
+{
+  /* This should never occur for abitsets since we should always
+     hit the cache.  */
+  return false;
+}
+
+
+/* Find list of up to NUM bits set in BSET in reverse order, starting
+   from and including NEXT and store in array LIST.  Return with
+   actual number of bits found and with *NEXT indicating where search
+   stopped.  */
+static bitset_bindex
+abitset_list_reverse (bitset src, bitset_bindex *list,
+		      bitset_bindex num, bitset_bindex *next)
+{
+  bitset_bindex bitno;
+  bitset_bindex rbitno;
+  bitset_bindex count;
+  bitset_windex windex;
+  unsigned int bitcnt;
+  bitset_bindex bitoff;
+  bitset_word *srcp = ABITSET_WORDS (src);
+  bitset_bindex n_bits = BITSET_SIZE_ (src);
+
+  rbitno = *next;
+
+  /* If num is 1, we could speed things up with a binary search
+     of the word of interest.  */
+
+  if (rbitno >= n_bits)
+    return 0;
+
+  count = 0;
+
+  bitno = n_bits - (rbitno + 1);
+
+  windex = bitno / BITSET_WORD_BITS;
+  bitcnt = bitno % BITSET_WORD_BITS;
+  bitoff = windex * BITSET_WORD_BITS;
+
+  do
+    {
+      bitset_word word;
+
+      word = srcp[windex] << (BITSET_WORD_BITS - 1 - bitcnt);
+      for (; word; bitcnt--)
+	{
+	  if (word & BITSET_MSB)
+	    {
+	      list[count++] = bitoff + bitcnt;
+	      if (count >= num)
+		{
+		  *next = n_bits - (bitoff + bitcnt);
+		  return count;
+		}
+	    }
+	  word <<= 1;
+	}
+      bitoff -= BITSET_WORD_BITS;
+      bitcnt = BITSET_WORD_BITS - 1;
+    }
+  while (windex--);
+
+  *next = n_bits - (bitoff + 1);
+  return count;
+}
+
+
+/* Find list of up to NUM bits set in BSET starting from and including
+ *NEXT and store in array LIST.  Return with actual number of bits
+ found and with *NEXT indicating where search stopped.  */
+static bitset_bindex
+abitset_list (bitset src, bitset_bindex *list,
+	      bitset_bindex num, bitset_bindex *next)
+{
+  bitset_bindex bitno;
+  bitset_bindex count;
+  bitset_windex windex;
+  bitset_bindex bitoff;
+  bitset_windex size = src->b.csize;
+  bitset_word *srcp = ABITSET_WORDS (src);
+  bitset_word word;
+
+  bitno = *next;
+
+  count = 0;
+  if (!bitno)
+    {
+      /* Many bitsets are zero, so make this common case fast.  */
+      for (windex = 0; windex < size && !srcp[windex]; windex++)
+	continue;
+      if (windex >= size)
+	return 0;
+
+      /* If num is 1, we could speed things up with a binary search
+	 of the current word.  */
+
+      bitoff = windex * BITSET_WORD_BITS;
+    }
+  else
+    {
+      if (bitno >= BITSET_SIZE_ (src))
+	return 0;
+
+      windex = bitno / BITSET_WORD_BITS;
+      bitno = bitno % BITSET_WORD_BITS;
+
+      if (bitno)
+	{
+	  /* Handle the case where we start within a word.
+	     Most often, this is executed with large bitsets
+	     with many set bits where we filled the array
+	     on the previous call to this function.  */
+
+	  bitoff = windex * BITSET_WORD_BITS;
+	  word = srcp[windex] >> bitno;
+	  for (bitno = bitoff + bitno; word; bitno++)
+	    {
+	      if (word & 1)
+		{
+		  list[count++] = bitno;
+		  if (count >= num)
+		    {
+		      *next = bitno + 1;
+		      return count;
+		    }
+		}
+	      word >>= 1;
+	    }
+	  windex++;
+	}
+      bitoff = windex * BITSET_WORD_BITS;
+    }
+
+  for (; windex < size; windex++, bitoff += BITSET_WORD_BITS)
+    {
+      if (!(word = srcp[windex]))
+	continue;
+
+      if ((count + BITSET_WORD_BITS) < num)
+	{
+	  for (bitno = bitoff; word; bitno++)
+	    {
+	      if (word & 1)
+		list[count++] = bitno;
+	      word >>= 1;
+	    }
+	}
+      else
+	{
+	  for (bitno = bitoff; word; bitno++)
+	    {
+	      if (word & 1)
+		{
+		  list[count++] = bitno;
+		  if (count >= num)
+		    {
+		      *next = bitno + 1;
+		      return count;
+		    }
+		}
+	      word >>= 1;
+	    }
+	}
+    }
+
+  *next = bitoff;
+  return count;
+}
+
+
+/* Ensure that any unused bits within the last word are clear.  */
+static inline void
+abitset_unused_clear (bitset dst)
+{
+  unsigned int last_bit;
+
+  last_bit = BITSET_SIZE_ (dst) % BITSET_WORD_BITS;
+  if (last_bit)
+    ABITSET_WORDS (dst)[dst->b.csize - 1] &=
+      ((bitset_word) 1 << last_bit) - 1;
+}
+
+
+static void
+abitset_ones (bitset dst)
+{
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  size_t bytes;
+
+  bytes = sizeof (bitset_word) * dst->b.csize;
+
+  memset (dstp, -1, bytes);
+  abitset_unused_clear (dst);
+}
+
+
+static void
+abitset_zero (bitset dst)
+{
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  size_t bytes;
+
+  bytes = sizeof (bitset_word) * dst->b.csize;
+
+  memset (dstp, 0, bytes);
+}
+
+
+static bool
+abitset_empty_p (bitset dst)
+{
+  bitset_windex i;
+  bitset_word *dstp = ABITSET_WORDS (dst);
+
+  for (i = 0; i < dst->b.csize; i++)
+    if (dstp[i])
+      return false;
+
+  return true;
+}
+
+
+static void
+abitset_copy1 (bitset dst, bitset src)
+{
+  bitset_word *srcp = ABITSET_WORDS (src);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  if (srcp == dstp)
+      return;
+  memcpy (dstp, srcp, sizeof (bitset_word) * size);
+}
+
+
+static void
+abitset_not (bitset dst, bitset src)
+{
+  bitset_windex i;
+  bitset_word *srcp = ABITSET_WORDS (src);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++)
+      *dstp++ = ~(*srcp++);
+  abitset_unused_clear (dst);
+}
+
+
+static bool
+abitset_equal_p (bitset dst, bitset src)
+{
+  bitset_windex i;
+  bitset_word *srcp = ABITSET_WORDS (src);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++)
+      if (*srcp++ != *dstp++)
+	  return false;
+  return true;
+}
+
+
+static bool
+abitset_subset_p (bitset dst, bitset src)
+{
+  bitset_windex i;
+  bitset_word *srcp = ABITSET_WORDS (src);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++, dstp++, srcp++)
+      if (*dstp != (*srcp | *dstp))
+	  return false;
+  return true;
+}
+
+
+static bool
+abitset_disjoint_p (bitset dst, bitset src)
+{
+  bitset_windex i;
+  bitset_word *srcp = ABITSET_WORDS (src);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++)
+      if (*srcp++ & *dstp++)
+	  return false;
+
+  return true;
+}
+
+
+static void
+abitset_and (bitset dst, bitset src1, bitset src2)
+{
+  bitset_windex i;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++)
+      *dstp++ = *src1p++ & *src2p++;
+}
+
+
+static bool
+abitset_and_cmp (bitset dst, bitset src1, bitset src2)
+{
+  bitset_windex i;
+  bool changed = false;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++, dstp++)
+    {
+      bitset_word tmp = *src1p++ & *src2p++;
+
+      if (*dstp != tmp)
+	{
+	  changed = true;
+	  *dstp = tmp;
+	}
+    }
+  return changed;
+}
+
+
+static void
+abitset_andn (bitset dst, bitset src1, bitset src2)
+{
+  bitset_windex i;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++)
+      *dstp++ = *src1p++ & ~(*src2p++);
+}
+
+
+static bool
+abitset_andn_cmp (bitset dst, bitset src1, bitset src2)
+{
+  bitset_windex i;
+  bool changed = false;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++, dstp++)
+    {
+      bitset_word tmp = *src1p++ & ~(*src2p++);
+
+      if (*dstp != tmp)
+	{
+	  changed = true;
+	  *dstp = tmp;
+	}
+    }
+  return changed;
+}
+
+
+static void
+abitset_or (bitset dst, bitset src1, bitset src2)
+{
+  bitset_windex i;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++)
+      *dstp++ = *src1p++ | *src2p++;
+}
+
+
+static bool
+abitset_or_cmp (bitset dst, bitset src1, bitset src2)
+{
+  bitset_windex i;
+  bool changed = false;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++, dstp++)
+    {
+      bitset_word tmp = *src1p++ | *src2p++;
+
+      if (*dstp != tmp)
+	{
+	  changed = true;
+	  *dstp = tmp;
+	}
+    }
+  return changed;
+}
+
+
+static void
+abitset_xor (bitset dst, bitset src1, bitset src2)
+{
+  bitset_windex i;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++)
+      *dstp++ = *src1p++ ^ *src2p++;
+}
+
+
+static bool
+abitset_xor_cmp (bitset dst, bitset src1, bitset src2)
+{
+  bitset_windex i;
+  bool changed = false;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++, dstp++)
+    {
+      bitset_word tmp = *src1p++ ^ *src2p++;
+
+      if (*dstp != tmp)
+	{
+	  changed = true;
+	  *dstp = tmp;
+	}
+    }
+  return changed;
+}
+
+
+static void
+abitset_and_or (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  bitset_windex i;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *src3p = ABITSET_WORDS (src3);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++)
+      *dstp++ = (*src1p++ & *src2p++) | *src3p++;
+}
+
+
+static bool
+abitset_and_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  bitset_windex i;
+  bool changed = false;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *src3p = ABITSET_WORDS (src3);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++, dstp++)
+    {
+      bitset_word tmp = (*src1p++ & *src2p++) | *src3p++;
+
+      if (*dstp != tmp)
+	{
+	  changed = true;
+	  *dstp = tmp;
+	}
+    }
+  return changed;
+}
+
+
+static void
+abitset_andn_or (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  bitset_windex i;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *src3p = ABITSET_WORDS (src3);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++)
+      *dstp++ = (*src1p++ & ~(*src2p++)) | *src3p++;
+}
+
+
+static bool
+abitset_andn_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  bitset_windex i;
+  bool changed = false;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *src3p = ABITSET_WORDS (src3);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++, dstp++)
+    {
+      bitset_word tmp = (*src1p++ & ~(*src2p++)) | *src3p++;
+
+      if (*dstp != tmp)
+	{
+	  changed = true;
+	  *dstp = tmp;
+	}
+    }
+  return changed;
+}
+
+
+static void
+abitset_or_and (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  bitset_windex i;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *src3p = ABITSET_WORDS (src3);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++)
+      *dstp++ = (*src1p++ | *src2p++) & *src3p++;
+}
+
+
+static bool
+abitset_or_and_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  bitset_windex i;
+  bool changed = false;
+  bitset_word *src1p = ABITSET_WORDS (src1);
+  bitset_word *src2p = ABITSET_WORDS (src2);
+  bitset_word *src3p = ABITSET_WORDS (src3);
+  bitset_word *dstp = ABITSET_WORDS (dst);
+  bitset_windex size = dst->b.csize;
+
+  for (i = 0; i < size; i++, dstp++)
+    {
+      bitset_word tmp = (*src1p++ | *src2p++) & *src3p++;
+
+      if (*dstp != tmp)
+	{
+	  changed = true;
+	  *dstp = tmp;
+	}
+    }
+  return changed;
+}
+
+
+static void
+abitset_copy (bitset dst, bitset src)
+{
+  if (BITSET_COMPATIBLE_ (dst, src))
+      abitset_copy1 (dst, src);
+  else
+      bitset_copy_ (dst, src);
+}
+
+
+/* Vector of operations for single word bitsets.  */
+struct bitset_vtable abitset_small_vtable = {
+  abitset_set,
+  abitset_reset,
+  bitset_toggle_,
+  abitset_test,
+  abitset_resize,
+  bitset_size_,
+  bitset_count_,
+  abitset_empty_p,
+  abitset_ones,
+  abitset_zero,
+  abitset_copy,
+  abitset_disjoint_p,
+  abitset_equal_p,
+  abitset_not,
+  abitset_subset_p,
+  abitset_and,
+  abitset_and_cmp,
+  abitset_andn,
+  abitset_andn_cmp,
+  abitset_or,
+  abitset_or_cmp,
+  abitset_xor,
+  abitset_xor_cmp,
+  abitset_and_or,
+  abitset_and_or_cmp,
+  abitset_andn_or,
+  abitset_andn_or_cmp,
+  abitset_or_and,
+  abitset_or_and_cmp,
+  abitset_small_list,
+  abitset_list_reverse,
+  NULL,
+  BITSET_ARRAY
+};
+
+
+/* Vector of operations for multiple word bitsets.  */
+struct bitset_vtable abitset_vtable = {
+  abitset_set,
+  abitset_reset,
+  bitset_toggle_,
+  abitset_test,
+  abitset_resize,
+  bitset_size_,
+  bitset_count_,
+  abitset_empty_p,
+  abitset_ones,
+  abitset_zero,
+  abitset_copy,
+  abitset_disjoint_p,
+  abitset_equal_p,
+  abitset_not,
+  abitset_subset_p,
+  abitset_and,
+  abitset_and_cmp,
+  abitset_andn,
+  abitset_andn_cmp,
+  abitset_or,
+  abitset_or_cmp,
+  abitset_xor,
+  abitset_xor_cmp,
+  abitset_and_or,
+  abitset_and_or_cmp,
+  abitset_andn_or,
+  abitset_andn_or_cmp,
+  abitset_or_and,
+  abitset_or_and_cmp,
+  abitset_list,
+  abitset_list_reverse,
+  NULL,
+  BITSET_ARRAY
+};
+
+
+size_t
+abitset_bytes (bitset_bindex n_bits)
+{
+  bitset_windex size;
+  size_t bytes;
+  size_t header_size = offsetof (union bitset_union, a.words);
+  struct bitset_align_struct { char a; union bitset_union b; };
+  size_t bitset_alignment = offsetof (struct bitset_align_struct, b);
+
+  size = ABITSET_N_WORDS (n_bits);
+  bytes = header_size + size * sizeof (bitset_word);
+
+  /* Align the size properly for a vector of abitset objects.  */
+  if (header_size % bitset_alignment != 0
+      || sizeof (bitset_word) % bitset_alignment != 0)
+    {
+      bytes += bitset_alignment - 1;
+      bytes -= bytes % bitset_alignment;
+    }
+
+  return bytes;
+}
+
+
+bitset
+abitset_init (bitset bset, bitset_bindex n_bits)
+{
+  bitset_windex size;
+
+  size = ABITSET_N_WORDS (n_bits);
+  BITSET_NBITS_ (bset) = n_bits;
+
+  /* Use optimized routines if bitset fits within a single word.
+     There is probably little merit if using caching since
+     the small bitset will always fit in the cache.  */
+  if (size == 1)
+    bset->b.vtable = &abitset_small_vtable;
+  else
+    bset->b.vtable = &abitset_vtable;
+
+  bset->b.cindex = 0;
+  bset->b.csize = size;
+  bset->b.cdata = ABITSET_WORDS (bset);
+  return bset;
+}
diff --git a/lib/abitset.h b/lib/abitset.h
new file mode 100644
index 0000000..a22c919
--- /dev/null
+++ b/lib/abitset.h
@@ -0,0 +1,28 @@
+/* Functions to support abitsets.
+   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+   Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
+
+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 2 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, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _ABITSET_H
+#define _ABITSET_H
+
+#include "bitset.h"
+
+extern size_t abitset_bytes (bitset_bindex);
+
+extern bitset abitset_init (bitset, bitset_bindex);
+
+#endif
diff --git a/lib/argmatch.c b/lib/argmatch.c
new file mode 100644
index 0000000..36d5845
--- /dev/null
+++ b/lib/argmatch.c
@@ -0,0 +1,281 @@
+/* argmatch.c -- find a match for a string in an array
+
+   Copyright (C) 1990, 1998, 1999, 2001, 2002, 2003, 2004, 2005 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by David MacKenzie <djm@ai.mit.edu>
+   Modified by Akim Demaille <demaille@inf.enst.fr> */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification.  */
+#include "argmatch.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+#include "error.h"
+#include "exit.h"
+#include "quotearg.h"
+#include "quote.h"
+
+#if USE_UNLOCKED_IO
+# include "unlocked-io.h"
+#endif
+
+/* When reporting an invalid argument, show nonprinting characters
+   by using the quoting style ARGMATCH_QUOTING_STYLE.  Do not use
+   literal_quoting_style.  */
+#ifndef ARGMATCH_QUOTING_STYLE
+# define ARGMATCH_QUOTING_STYLE locale_quoting_style
+#endif
+
+/* Non failing version of argmatch call this function after failing. */
+#ifndef ARGMATCH_DIE
+# include "exitfail.h"
+# define ARGMATCH_DIE exit (exit_failure)
+#endif
+
+#ifdef ARGMATCH_DIE_DECL
+ARGMATCH_DIE_DECL;
+#endif
+
+static void
+__argmatch_die (void)
+{
+  ARGMATCH_DIE;
+}
+
+/* Used by XARGMATCH and XARGCASEMATCH.  See description in argmatch.h.
+   Default to __argmatch_die, but allow caller to change this at run-time. */
+argmatch_exit_fn argmatch_die = __argmatch_die;
+
+
+/* If ARG is an unambiguous match for an element of the
+   NULL-terminated array ARGLIST, return the index in ARGLIST
+   of the matched element, else -1 if it does not match any element
+   or -2 if it is ambiguous (is a prefix of more than one element).
+
+   If VALLIST is none null, use it to resolve ambiguities limited to
+   synonyms, i.e., for
+     "yes", "yop" -> 0
+     "no", "nope" -> 1
+   "y" is a valid argument, for `0', and "n" for `1'.  */
+
+ptrdiff_t
+argmatch (const char *arg, const char *const *arglist,
+	  const char *vallist, size_t valsize)
+{
+  size_t i;			/* Temporary index in ARGLIST.  */
+  size_t arglen;		/* Length of ARG.  */
+  ptrdiff_t matchind = -1;	/* Index of first nonexact match.  */
+  bool ambiguous = false;	/* If true, multiple nonexact match(es).  */
+
+  arglen = strlen (arg);
+
+  /* Test all elements for either exact match or abbreviated matches.  */
+  for (i = 0; arglist[i]; i++)
+    {
+      if (!strncmp (arglist[i], arg, arglen))
+	{
+	  if (strlen (arglist[i]) == arglen)
+	    /* Exact match found.  */
+	    return i;
+	  else if (matchind == -1)
+	    /* First nonexact match found.  */
+	    matchind = i;
+	  else
+	    {
+	      /* Second nonexact match found.  */
+	      if (vallist == NULL
+		  || memcmp (vallist + valsize * matchind,
+			     vallist + valsize * i, valsize))
+		{
+		  /* There is a real ambiguity, or we could not
+		     disambiguate. */
+		  ambiguous = true;
+		}
+	    }
+	}
+    }
+  if (ambiguous)
+    return -2;
+  else
+    return matchind;
+}
+
+/* Error reporting for argmatch.
+   CONTEXT is a description of the type of entity that was being matched.
+   VALUE is the invalid value that was given.
+   PROBLEM is the return value from argmatch.  */
+
+void
+argmatch_invalid (const char *context, const char *value, ptrdiff_t problem)
+{
+  char const *format = (problem == -1
+			? _("invalid argument %s for %s")
+			: _("ambiguous argument %s for %s"));
+
+  error (0, 0, format, quotearg_n_style (0, ARGMATCH_QUOTING_STYLE, value),
+	 quote_n (1, context));
+}
+
+/* List the valid arguments for argmatch.
+   ARGLIST is the same as in argmatch.
+   VALLIST is a pointer to an array of values.
+   VALSIZE is the size of the elements of VALLIST */
+void
+argmatch_valid (const char *const *arglist,
+		const char *vallist, size_t valsize)
+{
+  size_t i;
+  const char *last_val = NULL;
+
+  /* We try to put synonyms on the same line.  The assumption is that
+     synonyms follow each other */
+  fprintf (stderr, _("Valid arguments are:"));
+  for (i = 0; arglist[i]; i++)
+    if ((i == 0)
+	|| memcmp (last_val, vallist + valsize * i, valsize))
+      {
+	fprintf (stderr, "\n  - `%s'", arglist[i]);
+	last_val = vallist + valsize * i;
+      }
+    else
+      {
+	fprintf (stderr, ", `%s'", arglist[i]);
+      }
+  putc ('\n', stderr);
+}
+
+/* Never failing versions of the previous functions.
+
+   CONTEXT is the context for which argmatch is called (e.g.,
+   "--version-control", or "$VERSION_CONTROL" etc.).  Upon failure,
+   calls the (supposed never to return) function EXIT_FN. */
+
+ptrdiff_t
+__xargmatch_internal (const char *context,
+		      const char *arg, const char *const *arglist,
+		      const char *vallist, size_t valsize,
+		      argmatch_exit_fn exit_fn)
+{
+  ptrdiff_t res = argmatch (arg, arglist, vallist, valsize);
+  if (res >= 0)
+    /* Success. */
+    return res;
+
+  /* We failed.  Explain why. */
+  argmatch_invalid (context, arg, res);
+  argmatch_valid (arglist, vallist, valsize);
+  (*exit_fn) ();
+
+  return -1; /* To please the compilers. */
+}
+
+/* Look for VALUE in VALLIST, an array of objects of size VALSIZE and
+   return the first corresponding argument in ARGLIST */
+const char *
+argmatch_to_argument (const char *value,
+		      const char *const *arglist,
+		      const char *vallist, size_t valsize)
+{
+  size_t i;
+
+  for (i = 0; arglist[i]; i++)
+    if (!memcmp (value, vallist + valsize * i, valsize))
+      return arglist[i];
+  return NULL;
+}
+
+#ifdef TEST
+/*
+ * Based on "getversion.c" by David MacKenzie <djm@gnu.ai.mit.edu>
+ */
+char *program_name;
+
+/* When to make backup files.  */
+enum backup_type
+{
+  /* Never make backups.  */
+  no_backups,
+
+  /* Make simple backups of every file.  */
+  simple_backups,
+
+  /* Make numbered backups of files that already have numbered backups,
+     and simple backups of the others.  */
+  numbered_existing_backups,
+
+  /* Make numbered backups of every file.  */
+  numbered_backups
+};
+
+/* Two tables describing arguments (keys) and their corresponding
+   values */
+static const char *const backup_args[] =
+{
+  "no", "none", "off",
+  "simple", "never",
+  "existing", "nil",
+  "numbered", "t",
+  0
+};
+
+static const enum backup_type backup_vals[] =
+{
+  no_backups, no_backups, no_backups,
+  simple_backups, simple_backups,
+  numbered_existing_backups, numbered_existing_backups,
+  numbered_backups, numbered_backups
+};
+
+int
+main (int argc, const char *const *argv)
+{
+  const char *cp;
+  enum backup_type backup_type = no_backups;
+
+  program_name = (char *) argv[0];
+
+  if (argc > 2)
+    {
+      fprintf (stderr, "Usage: %s [VERSION_CONTROL]\n", program_name);
+      exit (1);
+    }
+
+  if ((cp = getenv ("VERSION_CONTROL")))
+    backup_type = XARGMATCH ("$VERSION_CONTROL", cp,
+			     backup_args, backup_vals);
+
+  if (argc == 2)
+    backup_type = XARGMATCH (program_name, argv[1],
+			     backup_args, backup_vals);
+
+  printf ("The version control is `%s'\n",
+	  ARGMATCH_TO_ARGUMENT (backup_type, backup_args, backup_vals));
+
+  return 0;
+}
+#endif
diff --git a/lib/argmatch.h b/lib/argmatch.h
new file mode 100644
index 0000000..f2dfe59
--- /dev/null
+++ b/lib/argmatch.h
@@ -0,0 +1,103 @@
+/* argmatch.h -- definitions and prototypes for argmatch.c
+
+   Copyright (C) 1990, 1998, 1999, 2001, 2002, 2004, 2005 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by David MacKenzie <djm@ai.mit.edu>
+   Modified by Akim Demaille <demaille@inf.enst.fr> */
+
+#ifndef ARGMATCH_H_
+# define ARGMATCH_H_ 1
+
+# include <stddef.h>
+
+# include "verify.h"
+
+# define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array))
+
+/* Assert there are as many real arguments as there are values
+   (argument list ends with a NULL guard).  */
+
+# define ARGMATCH_VERIFY(Arglist, Vallist) \
+    verify (ARRAY_CARDINALITY (Arglist) == ARRAY_CARDINALITY (Vallist) + 1)
+
+/* Return the index of the element of ARGLIST (NULL terminated) that
+   matches with ARG.  If VALLIST is not NULL, then use it to resolve
+   false ambiguities (i.e., different matches of ARG but corresponding
+   to the same values in VALLIST).  */
+
+ptrdiff_t argmatch (char const *arg, char const *const *arglist,
+		    char const *vallist, size_t valsize);
+
+# define ARGMATCH(Arg, Arglist, Vallist) \
+  argmatch (Arg, Arglist, (char const *) (Vallist), sizeof *(Vallist))
+
+/* xargmatch calls this function when it fails.  This function should not
+   return.  By default, this is a function that calls ARGMATCH_DIE which
+   in turn defaults to `exit (exit_failure)'.  */
+typedef void (*argmatch_exit_fn) (void);
+extern argmatch_exit_fn argmatch_die;
+
+/* Report on stderr why argmatch failed.  Report correct values. */
+
+void argmatch_invalid (char const *context, char const *value,
+		       ptrdiff_t problem);
+
+/* Left for compatibility with the old name invalid_arg */
+
+# define invalid_arg(Context, Value, Problem) \
+  argmatch_invalid (Context, Value, Problem)
+
+
+
+/* Report on stderr the list of possible arguments.  */
+
+void argmatch_valid (char const *const *arglist,
+		     char const *vallist, size_t valsize);
+
+# define ARGMATCH_VALID(Arglist, Vallist) \
+  argmatch_valid (Arglist, (char const *) (Vallist), sizeof *(Vallist))
+
+
+
+/* Same as argmatch, but upon failure, reports a explanation on the
+   failure, and exits using the function EXIT_FN. */
+
+ptrdiff_t __xargmatch_internal (char const *context,
+				char const *arg, char const *const *arglist,
+				char const *vallist, size_t valsize,
+				argmatch_exit_fn exit_fn);
+
+/* Programmer friendly interface to __xargmatch_internal. */
+
+# define XARGMATCH(Context, Arg, Arglist, Vallist)		\
+  ((Vallist) [__xargmatch_internal (Context, Arg, Arglist,	\
+				    (char const *) (Vallist),	\
+				    sizeof *(Vallist),		\
+				    argmatch_die)])
+
+/* Convert a value into a corresponding argument. */
+
+char const *argmatch_to_argument (char const *value,
+				  char const *const *arglist,
+				  char const *vallist, size_t valsize);
+
+# define ARGMATCH_TO_ARGUMENT(Value, Arglist, Vallist)			\
+  argmatch_to_argument (Value, Arglist,					\
+			(char const *) (Vallist), sizeof *(Vallist))
+
+#endif /* ARGMATCH_H_ */
diff --git a/lib/basename.c b/lib/basename.c
new file mode 100644
index 0000000..5cc97cd
--- /dev/null
+++ b/lib/basename.c
@@ -0,0 +1,79 @@
+/* basename.c -- return the last element in a file name
+
+   Copyright (C) 1990, 1998, 1999, 2000, 2001, 2003, 2004, 2005 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "dirname.h"
+#include <string.h>
+
+/* In general, we can't use the builtin `basename' function if available,
+   since it has different meanings in different environments.
+   In some environments the builtin `basename' modifies its argument.
+
+   Return the address of the last file name component of NAME.  If
+   NAME has no file name components because it is all slashes, return
+   NAME if it is empty, the address of its last slash otherwise.  */
+
+char *
+base_name (char const *name)
+{
+  char const *base = name + FILE_SYSTEM_PREFIX_LEN (name);
+  char const *p;
+
+  for (p = base; *p; p++)
+    {
+      if (ISSLASH (*p))
+	{
+	  /* Treat multiple adjacent slashes like a single slash.  */
+	  do p++;
+	  while (ISSLASH (*p));
+
+	  /* If the file name ends in slash, use the trailing slash as
+	     the basename if no non-slashes have been found.  */
+	  if (! *p)
+	    {
+	      if (ISSLASH (*base))
+		base = p - 1;
+	      break;
+	    }
+
+	  /* *P is a non-slash preceded by a slash.  */
+	  base = p;
+	}
+    }
+
+  return (char *) base;
+}
+
+/* Return the length of of the basename NAME.  Typically NAME is the
+   value returned by base_name.  Act like strlen (NAME), except omit
+   redundant trailing slashes.  */
+
+size_t
+base_len (char const *name)
+{
+  size_t len;
+
+  for (len = strlen (name);  1 < len && ISSLASH (name[len - 1]);  len--)
+    continue;
+
+  return len;
+}
diff --git a/lib/bbitset.h b/lib/bbitset.h
new file mode 100644
index 0000000..956fc5c
--- /dev/null
+++ b/lib/bbitset.h
@@ -0,0 +1,302 @@
+/* Base bitset stuff.
+   Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+   Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
+
+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 2 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, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _BBITSET_H
+#define _BBITSET_H
+
+#include "libiberty.h"
+
+#include <stdbool.h>
+#include <limits.h>
+#include <stddef.h>
+
+/* Currently we support five flavours of bitsets:
+   BITSET_ARRAY:  Array of bits (fixed size, fast for dense bitsets).
+                  Memory for bit array and bitset structure allocated
+                  contiguously.
+   BITSET_LIST:   Linked list of arrays of bits (variable size, least storage
+		  for large very sparse sets).
+   BITSET_TABLE:  Expandable table of pointers to arrays of bits
+		  (variable size, less storage for large sparse sets).
+                  Faster than BITSET_LIST for random access.
+   BITSET_VARRAY: Variable array of bits (variable size, fast for
+                  dense bitsets).
+   BITSET_STATS:  Wrapper bitset for internal use only.  Used for gathering
+                  statistics and/or better run-time checking.
+*/
+enum bitset_type {BITSET_ARRAY, BITSET_LIST, BITSET_TABLE, BITSET_VARRAY,
+		  BITSET_TYPE_NUM, BITSET_STATS};
+#define BITSET_TYPE_NAMES {"abitset", "lbitset", "ebitset", "vbitset"}
+
+extern const char * const bitset_type_names[];
+
+enum bitset_alloc_type {BITSET_MALLOC, BITSET_OBALLOC};
+
+/* Data type used to store a word of bits.  */
+typedef unsigned long int bitset_word;
+#define BITSET_WORD_BITS ((unsigned int) (CHAR_BIT * sizeof (bitset_word)))
+
+/* Bit index.  In theory we might need a type wider than size_t, but
+   in practice we lose at most a factor of CHAR_BIT by going with
+   size_t, and that is good enough.  If this type is changed to be
+   wider than size_t, the code needs to be modified to check for
+   overflow when converting bit counts to byte or word counts.
+   The bit and word index types must be unsigned.  */
+typedef size_t bitset_bindex;
+
+/* Word index.  */
+typedef size_t bitset_windex;
+
+/* Maximum values for commonly-used unsigned types.  BITSET_SIZE_MAX
+   always equals SIZE_MAX, but some older systems lack SIZE_MAX.  */
+#define BITSET_BINDEX_MAX ((bitset_bindex) -1)
+
+/* Limit max word index to the maximum value of a signed integer
+   to simplify cache disabling.  */
+#define BITSET_WINDEX_MAX (((bitset_windex) -1) >> 1)
+#define BITSET_SIZE_MAX ((size_t) -1)
+
+#define BITSET_MSB ((bitset_word) 1 << (BITSET_WORD_BITS - 1))
+
+#define BITSET_LIST_SIZE 1024
+
+enum bitset_ops {BITSET_OP_ZERO, BITSET_OP_ONES,
+		 BITSET_OP_COPY, BITSET_OP_NOT,
+		 BITSET_OP_EMPTY_P, BITSET_OP_EQUAL_P,
+		 BITSET_OP_SUBSET_P, BITSET_OP_DISJOINT_P,
+		 BITSET_OP_AND, BITSET_OP_OR, BITSET_OP_XOR, BITSET_OP_ANDN,
+		 BITSET_OP_OR_AND, BITSET_OP_AND_OR, BITSET_OP_ANDN_OR};
+
+struct bbitset_struct
+{
+  const struct bitset_vtable *vtable;
+  bitset_windex cindex;		/* Cache word index.  */
+  bitset_windex csize;		/* Cache size in words.  */
+  bitset_word *cdata;		/* Cache data pointer.  */
+  bitset_bindex n_bits;		/* Number of bits.  */
+  /* Perhaps we could sacrifice another word to indicate
+     that the bitset is known to be zero, that a bit has been set
+     in the cache, and that a bit has been cleared in the cache.
+     This would speed up some of the searches but slightly slow down
+     bit set/reset operations of cached bits.  */
+};
+
+
+typedef union bitset_union *bitset;
+
+
+/* Private accessor macros to bitset structure.  */
+#define BITSET_VTABLE_(SRC) (SRC)->b.vtable
+#define BITSET_CINDEX_(SRC) (SRC)->b.cindex
+#define BITSET_CDATA_(SRC) (SRC)->b.cdata
+#define BITSET_CSIZE_(SRC) (SRC)->b.csize
+#define BITSET_NBITS_(SRC) (SRC)->b.n_bits
+
+
+/* The contents of this structure should be considered private.  */
+struct bitset_vtable
+{
+  void (*set) (bitset, bitset_bindex);
+  void (*reset) (bitset, bitset_bindex);
+  bool (*toggle) (bitset, bitset_bindex);
+  bool (*test) (bitset, bitset_bindex);
+  bitset_bindex (*resize) (bitset, bitset_bindex);
+  bitset_bindex (*size) (bitset);
+  bitset_bindex (*count) (bitset);
+
+  bool (*empty_p) (bitset);
+  void (*ones) (bitset);
+  void (*zero) (bitset);
+
+  void (*copy) (bitset, bitset);
+  bool (*disjoint_p) (bitset, bitset);
+  bool (*equal_p) (bitset, bitset);
+  void (*not_) (bitset, bitset);
+  bool (*subset_p) (bitset, bitset);
+
+  void (*and_) (bitset, bitset, bitset);
+  bool (*and_cmp) (bitset, bitset, bitset);
+  void (*andn) (bitset, bitset, bitset);
+  bool (*andn_cmp) (bitset, bitset, bitset);
+  void (*or_) (bitset, bitset, bitset);
+  bool (*or_cmp) (bitset, bitset, bitset);
+  void (*xor_) (bitset, bitset, bitset);
+  bool (*xor_cmp) (bitset, bitset, bitset);
+
+  void (*and_or) (bitset, bitset, bitset, bitset);
+  bool (*and_or_cmp) (bitset, bitset, bitset, bitset);
+  void (*andn_or) (bitset, bitset, bitset, bitset);
+  bool (*andn_or_cmp) (bitset, bitset, bitset, bitset);
+  void (*or_and) (bitset, bitset, bitset, bitset);
+  bool (*or_and_cmp) (bitset, bitset, bitset, bitset);
+
+  bitset_bindex (*list) (bitset, bitset_bindex *, bitset_bindex,
+			 bitset_bindex *);
+  bitset_bindex (*list_reverse) (bitset, bitset_bindex *, bitset_bindex,
+				 bitset_bindex *);
+  void (*free) (bitset);
+  enum bitset_type type;
+};
+
+#define BITSET_COMPATIBLE_(BSET1, BSET2) \
+((BSET1)->b.vtable == (BSET2)->b.vtable)
+
+#define BITSET_CHECK2_(DST, SRC) \
+if (!BITSET_COMPATIBLE_ (DST, SRC)) abort ();
+
+#define BITSET_CHECK3_(DST, SRC1, SRC2) \
+if (!BITSET_COMPATIBLE_ (DST, SRC1) \
+    || !BITSET_COMPATIBLE_ (DST, SRC2)) abort ();
+
+#define BITSET_CHECK4_(DST, SRC1, SRC2, SRC3) \
+if (!BITSET_COMPATIBLE_ (DST, SRC1) || !BITSET_COMPATIBLE_ (DST, SRC2) \
+    || !BITSET_COMPATIBLE_ (DST, SRC3)) abort ();
+
+
+/* Redefine number of bits in bitset DST.  */
+#define BITSET_RESIZE_(DST, SIZE) (DST)->b.vtable->resize (DST, SIZE)
+
+/* Return size in bits of bitset SRC.  */
+#define BITSET_SIZE_(SRC) (SRC)->b.vtable->size (SRC)
+
+/* Return number of bits set in bitset SRC.  */
+#define BITSET_COUNT_(SRC) (SRC)->b.vtable->count (SRC)
+
+/* Return type of bitset SRC.  */
+#define BITSET_TYPE_(DST) (DST)->b.vtable->type
+
+/* Set bit BITNO in bitset DST.  */
+#define BITSET_SET_(DST, BITNO) (DST)->b.vtable->set (DST, BITNO)
+
+/* Reset bit BITNO in bitset DST.  */
+#define BITSET_RESET_(DST, BITNO) (DST)->b.vtable->reset (DST, BITNO)
+
+/* Toggle bit BITNO in bitset DST.  */
+#define BITSET_TOGGLE_(DST, BITNO) (DST)->b.vtable->toggle (DST, BITNO)
+
+/* Return non-zero if bit BITNO in bitset SRC is set.  */
+#define BITSET_TEST_(SRC, BITNO) (SRC)->b.vtable->test (SRC, BITNO)
+
+/* Free bitset SRC.  */
+#define BITSET_FREE_(SRC)\
+ ((SRC)->b.vtable->free ? (SRC)->b.vtable->free (SRC) :(void)0)
+
+
+/* Return SRC == 0.  */
+#define BITSET_EMPTY_P_(SRC) (SRC)->b.vtable->empty_p (SRC)
+
+/* DST = ~0.  */
+#define BITSET_ONES_(DST) (DST)->b.vtable->ones (DST)
+
+/* DST = 0.  */
+#define BITSET_ZERO_(DST) (DST)->b.vtable->zero (DST)
+
+
+
+/* DST = SRC.  */
+#define BITSET_COPY_(DST, SRC) (SRC)->b.vtable->copy (DST, SRC)
+
+/* Return DST & SRC == 0.  */
+#define BITSET_DISJOINT_P_(DST, SRC) (SRC)->b.vtable->disjoint_p (DST, SRC)
+
+/* Return DST == SRC.  */
+#define BITSET_EQUAL_P_(DST, SRC) (SRC)->b.vtable->equal_p (DST, SRC)
+
+/* DST = ~SRC.  */
+#define BITSET_NOT_(DST, SRC) (SRC)->b.vtable->not_ (DST, SRC)
+
+/* Return DST == DST | SRC.  */
+#define BITSET_SUBSET_P_(DST, SRC) (SRC)->b.vtable->subset_p (DST, SRC)
+
+
+/* DST = SRC1 & SRC2.  */
+#define BITSET_AND_(DST, SRC1, SRC2) (SRC1)->b.vtable->and_ (DST, SRC1, SRC2)
+#define BITSET_AND_CMP_(DST, SRC1, SRC2) (SRC1)->b.vtable->and_cmp (DST, SRC1, SRC2)
+
+/* DST = SRC1 & ~SRC2.  */
+#define BITSET_ANDN_(DST, SRC1, SRC2) (SRC1)->b.vtable->andn (DST, SRC1, SRC2)
+#define BITSET_ANDN_CMP_(DST, SRC1, SRC2) (SRC1)->b.vtable->andn_cmp (DST, SRC1, SRC2)
+
+/* DST = SRC1 | SRC2.  */
+#define BITSET_OR_(DST, SRC1, SRC2) (SRC1)->b.vtable->or_ (DST, SRC1, SRC2)
+#define BITSET_OR_CMP_(DST, SRC1, SRC2) (SRC1)->b.vtable->or_cmp (DST, SRC1, SRC2)
+
+/* DST = SRC1 ^ SRC2.  */
+#define BITSET_XOR_(DST, SRC1, SRC2) (SRC1)->b.vtable->xor_ (DST, SRC1, SRC2)
+#define BITSET_XOR_CMP_(DST, SRC1, SRC2) (SRC1)->b.vtable->xor_cmp (DST, SRC1, SRC2)
+
+
+
+/* DST = (SRC1 & SRC2) | SRC3.  Return non-zero if
+   DST != (SRC1 & SRC2) | SRC3.  */
+#define BITSET_AND_OR_(DST, SRC1, SRC2, SRC3) \
+ (SRC1)->b.vtable->and_or (DST, SRC1, SRC2, SRC3)
+#define BITSET_AND_OR_CMP_(DST, SRC1, SRC2, SRC3) \
+ (SRC1)->b.vtable->and_or_cmp (DST, SRC1, SRC2, SRC3)
+
+/* DST = (SRC1 & ~SRC2) | SRC3.  Return non-zero if
+   DST != (SRC1 & ~SRC2) | SRC3.  */
+#define BITSET_ANDN_OR_(DST, SRC1, SRC2, SRC3) \
+ (SRC1)->b.vtable->andn_or (DST, SRC1, SRC2, SRC3)
+#define BITSET_ANDN_OR_CMP_(DST, SRC1, SRC2, SRC3) \
+ (SRC1)->b.vtable->andn_or_cmp (DST, SRC1, SRC2, SRC3)
+
+/* DST = (SRC1 | SRC2) & SRC3.  Return non-zero if
+   DST != (SRC1 | SRC2) & SRC3.  */
+#define BITSET_OR_AND_(DST, SRC1, SRC2, SRC3) \
+ (SRC1)->b.vtable->or_and (DST, SRC1, SRC2, SRC3)
+#define BITSET_OR_AND_CMP_(DST, SRC1, SRC2, SRC3) \
+ (SRC1)->b.vtable->or_and_cmp (DST, SRC1, SRC2, SRC3)
+
+
+/* Find list of up to NUM bits set in BSET starting from and including
+   *NEXT.  Return with actual number of bits found and with *NEXT
+   indicating where search stopped.  */
+#define BITSET_LIST_(BSET, LIST, NUM, NEXT) \
+ (BSET)->b.vtable->list (BSET, LIST, NUM, NEXT)
+
+/* Find reverse list of up to NUM bits set in BSET starting from and
+   including NEXT.  Return with actual number of bits found and with
+   *NEXT indicating where search stopped.  */
+#define BITSET_LIST_REVERSE_(BSET, LIST, NUM, NEXT) \
+ (BSET)->b.vtable->list_reverse (BSET, LIST, NUM, NEXT)
+
+
+/* Private functions for bitset implementations.  */
+
+extern bool bitset_toggle_ (bitset, bitset_bindex);
+
+extern bitset_bindex bitset_count_ (bitset);
+
+extern bitset_bindex bitset_size_ (bitset);
+
+extern bool bitset_copy_ (bitset, bitset);
+
+extern void bitset_and_or_ (bitset, bitset, bitset, bitset);
+
+extern bool bitset_and_or_cmp_ (bitset, bitset, bitset, bitset);
+
+extern void bitset_andn_or_ (bitset, bitset, bitset, bitset);
+
+extern bool bitset_andn_or_cmp_ (bitset, bitset, bitset, bitset);
+
+extern void bitset_or_and_ (bitset, bitset, bitset, bitset);
+
+extern bool bitset_or_and_cmp_ (bitset, bitset, bitset, bitset);
+
+#endif /* _BBITSET_H  */
diff --git a/lib/bitset.c b/lib/bitset.c
new file mode 100644
index 0000000..2924567
--- /dev/null
+++ b/lib/bitset.c
@@ -0,0 +1,505 @@
+/* General bitsets.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
+
+   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 2 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include "bitset.h"
+#include "abitset.h"
+#include "lbitset.h"
+#include "ebitset.h"
+#include "vbitset.h"
+#include "bitset_stats.h"
+#include "obstack.h"
+
+const char * const bitset_type_names[] = BITSET_TYPE_NAMES;
+
+
+/* Return number of bytes required to create a N_BIT bitset
+   of TYPE.  The bitset may grow to require more bytes than this.  */
+size_t
+bitset_bytes (enum bitset_type type, bitset_bindex n_bits)
+{
+  size_t bytes;
+
+  if (bitset_stats_enabled)
+    return bitset_stats_bytes ();
+
+  switch (type)
+    {
+    default:
+      abort ();
+
+    case BITSET_ARRAY:
+      bytes = abitset_bytes (n_bits);
+      break;
+
+    case BITSET_LIST:
+      bytes = lbitset_bytes (n_bits);
+      break;
+
+    case BITSET_TABLE:
+      bytes = ebitset_bytes (n_bits);
+      break;
+
+    case BITSET_VARRAY:
+      bytes = vbitset_bytes (n_bits);
+      break;
+    }
+
+  return bytes;
+}
+
+
+/* Initialise bitset BSET of TYPE for N_BITS.  */
+bitset
+bitset_init (bitset bset, bitset_bindex n_bits, enum bitset_type type)
+{
+  if (bitset_stats_enabled)
+    return bitset_stats_init (bset, n_bits, type);
+
+  switch (type)
+    {
+    default:
+      abort ();
+
+    case BITSET_ARRAY:
+      return abitset_init (bset, n_bits);
+
+    case BITSET_LIST:
+      return lbitset_init (bset, n_bits);
+
+    case BITSET_TABLE:
+      return ebitset_init (bset, n_bits);
+
+    case BITSET_VARRAY:
+      return vbitset_init (bset, n_bits);
+    }
+}
+
+
+/* Select a bitset type for a set of N_BITS and with attribute hints
+   specified by ATTR.  For variable size bitsets, N_BITS is only a
+   hint and may be zero.  */
+enum bitset_type
+bitset_type_choose (bitset_bindex n_bits ATTRIBUTE_UNUSED, unsigned int attr)
+{
+  /* Check attributes.  */
+  if (attr & BITSET_FIXED && attr & BITSET_VARIABLE)
+    abort ();
+  if (attr & BITSET_SPARSE && attr & BITSET_DENSE)
+    abort ();
+
+  /* Choose the type of bitset.  Note that sometimes we will be asked
+  for a zero length fixed size bitset.  */
+
+
+  /* If no attributes selected, choose a good compromise.  */
+  if (!attr)
+    return BITSET_VARRAY;
+
+  if (attr & BITSET_SPARSE)
+    return BITSET_LIST;
+
+  if (attr & BITSET_FIXED)
+    return BITSET_ARRAY;
+
+  if (attr & BITSET_GREEDY)
+    return BITSET_TABLE;
+
+  return BITSET_VARRAY;
+}
+
+
+/* Create a bitset of N_BITS of type TYPE.  */
+bitset
+bitset_alloc (bitset_bindex n_bits, enum bitset_type type)
+{
+  size_t bytes;
+  bitset bset;
+
+  bytes = bitset_bytes (type, n_bits);
+
+  bset = xcalloc (1, bytes);
+
+  /* The cache is disabled until some elements are allocated.  If we
+     have variable length arrays, then we may need to allocate a dummy
+     element.  */
+
+  return bitset_init (bset, n_bits, type);
+}
+
+
+/* Create a bitset of N_BITS of type TYPE.  */
+bitset
+bitset_obstack_alloc (struct obstack *bobstack,
+		      bitset_bindex n_bits, enum bitset_type type)
+{
+  size_t bytes;
+  bitset bset;
+
+  bytes = bitset_bytes (type, n_bits);
+
+  bset = obstack_alloc (bobstack, bytes);
+  memset (bset, 0, bytes);
+
+  return bitset_init (bset, n_bits, type);
+}
+
+
+/* Create a bitset of N_BITS and with attribute hints specified by
+   ATTR.  */
+bitset
+bitset_create (bitset_bindex n_bits, unsigned int attr)
+{
+  enum bitset_type type;
+
+  type = bitset_type_choose (n_bits, attr);
+
+  return bitset_alloc (n_bits, type);
+}
+
+
+/* Free bitset BSET.  */
+void
+bitset_free (bitset bset)
+{
+  BITSET_FREE_ (bset);
+  free (bset);
+}
+
+
+/* Free bitset BSET allocated on obstack.  */
+void
+bitset_obstack_free (bitset bset)
+{
+  BITSET_FREE_ (bset);
+}
+
+
+/* Return bitset type.  */
+enum bitset_type
+bitset_type_get (bitset bset)
+{
+   enum bitset_type type;
+
+   type = BITSET_TYPE_ (bset);
+   if (type != BITSET_STATS)
+      return type;
+
+   return bitset_stats_type_get (bset);
+}
+
+
+/* Return name of bitset type.  */
+const char *
+bitset_type_name_get (bitset bset)
+{
+  enum bitset_type type;
+
+  type = bitset_type_get (bset);
+
+  return bitset_type_names[type];
+}
+
+
+/* Find next bit set in SRC starting from and including BITNO.
+   Return BITSET_BINDEX_MAX if SRC empty.  */
+bitset_bindex
+bitset_next (bitset src, bitset_bindex bitno)
+{
+  bitset_bindex val;
+  bitset_bindex next = bitno;
+
+  if (!bitset_list (src, &val, 1, &next))
+    return BITSET_BINDEX_MAX;
+  return val;
+}
+
+
+/* Return true if both bitsets are of the same type and size.  */
+extern bool
+bitset_compatible_p (bitset bset1, bitset bset2)
+{
+    return BITSET_COMPATIBLE_ (bset1, bset2);
+}
+
+
+/* Find previous bit set in SRC starting from and including BITNO.
+   Return BITSET_BINDEX_MAX if SRC empty.  */
+bitset_bindex
+bitset_prev (bitset src, bitset_bindex bitno)
+{
+  bitset_bindex val;
+  bitset_bindex next = bitno;
+
+  if (!bitset_list_reverse (src, &val, 1, &next))
+    return BITSET_BINDEX_MAX;
+  return val;
+}
+
+
+/* Find first set bit.   */
+bitset_bindex
+bitset_first (bitset src)
+{
+  return bitset_next (src, 0);
+}
+
+
+/* Find last set bit.   */
+bitset_bindex
+bitset_last (bitset src)
+{
+  return bitset_prev (src, 0);
+}
+
+
+/* Is BITNO in SRC the only set bit?  */
+bool
+bitset_only_set_p (bitset src, bitset_bindex bitno)
+{
+  bitset_bindex val[2];
+  bitset_bindex next = 0;
+
+  if (bitset_list (src, val, 2, &next) != 1)
+    return false;
+  return val[0] == bitno;
+}
+
+
+/* Print contents of bitset BSET to FILE.   */
+static void
+bitset_print (FILE *file, bitset bset, bool verbose)
+{
+  unsigned int pos;
+  bitset_bindex i;
+  bitset_iterator iter;
+
+  if (verbose)
+    fprintf (file, "n_bits = %lu, set = {",
+	     (unsigned long int) bitset_size (bset));
+
+  pos = 30;
+  BITSET_FOR_EACH (iter, bset, i, 0)
+  {
+    if (pos > 70)
+      {
+	fprintf (file, "\n");
+	pos = 0;
+      }
+
+    fprintf (file, "%lu ", (unsigned long int) i);
+    pos += 1 + (i >= 10) + (i >= 100);
+  };
+
+  if (verbose)
+    fprintf (file, "}\n");
+}
+
+
+/* Dump bitset BSET to FILE.  */
+void
+bitset_dump (FILE *file, bitset bset)
+{
+  bitset_print (file, bset, false);
+}
+
+
+/* Release memory associated with bitsets.  */
+void
+bitset_release_memory (void)
+{
+  lbitset_release_memory ();
+  ebitset_release_memory ();
+}
+
+
+/* Toggle bit BITNO in bitset BSET and the new value of the bit.  */
+bool
+bitset_toggle_ (bitset bset, bitset_bindex bitno)
+{
+  /* This routine is for completeness.  It could be optimized if
+     required.  */
+  if (bitset_test (bset, bitno))
+    {
+      bitset_reset (bset, bitno);
+      return false;
+    }
+  else
+    {
+      bitset_set (bset, bitno);
+      return true;
+    }
+}
+
+
+/* Return number of bits in bitset SRC.  */
+bitset_bindex
+bitset_size_ (bitset src)
+{
+    return BITSET_NBITS_ (src);
+}
+
+
+/* Return number of bits set in bitset SRC.  */
+bitset_bindex
+bitset_count_ (bitset src)
+{
+  bitset_bindex list[BITSET_LIST_SIZE];
+  bitset_bindex next;
+  bitset_bindex num;
+  bitset_bindex count;
+
+  /* This could be greatly sped up by adding a count method for each
+     bitset implementation that uses a direct technique (based on
+     masks) for counting the number of bits set in a word.  */
+
+  next = 0;
+  for (count = 0; (num = bitset_list (src, list, BITSET_LIST_SIZE, &next));
+       count += num)
+    continue;
+
+  return count;
+}
+
+
+/* DST = SRC.  Return true if DST != SRC.
+   This is a fallback for the case where SRC and DST are different
+   bitset types.  */
+bool
+bitset_copy_ (bitset dst, bitset src)
+{
+  bitset_bindex i;
+  bitset_iterator iter;
+
+  /* Convert bitset types.  We assume that the DST bitset
+     is large enough to hold the SRC bitset.  */
+  bitset_zero (dst);
+  BITSET_FOR_EACH (iter, src, i, 0)
+  {
+     bitset_set (dst, i);
+  };
+
+  return true;
+}
+
+
+/* This is a fallback for implementations that do not support
+   four operand operations.  */
+static inline bool
+bitset_op4_cmp (bitset dst, bitset src1, bitset src2, bitset src3,
+		enum bitset_ops op)
+{
+  bool changed = false;
+  bool stats_enabled_save;
+  bitset tmp;
+
+  /* Create temporary bitset.  */
+  stats_enabled_save = bitset_stats_enabled;
+  bitset_stats_enabled = false;
+  tmp = bitset_alloc (0, bitset_type_get (dst));
+  bitset_stats_enabled = stats_enabled_save;
+
+  switch (op)
+    {
+    default:
+      abort ();
+
+    case BITSET_OP_OR_AND:
+      bitset_or (tmp, src1, src2);
+      changed = bitset_and_cmp (dst, src3, tmp);
+      break;
+
+    case BITSET_OP_AND_OR:
+      bitset_and (tmp, src1, src2);
+      changed = bitset_or_cmp (dst, src3, tmp);
+      break;
+
+    case BITSET_OP_ANDN_OR:
+      bitset_andn (tmp, src1, src2);
+      changed = bitset_or_cmp (dst, src3, tmp);
+      break;
+    }
+
+  bitset_free (tmp);
+  return changed;
+}
+
+
+/* DST = (SRC1 & SRC2) | SRC3.  */
+void
+bitset_and_or_ (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  bitset_and_or_cmp_ (dst, src1, src2, src3);
+}
+
+
+/* DST = (SRC1 & SRC2) | SRC3.  Return non-zero if
+   DST != (SRC1 & SRC2) | SRC3.  */
+bool
+bitset_and_or_cmp_ (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  return bitset_op4_cmp (dst, src1, src2, src3, BITSET_OP_AND_OR);
+}
+
+
+/* DST = (SRC1 & ~SRC2) | SRC3.  */
+void
+bitset_andn_or_ (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  bitset_andn_or_cmp_ (dst, src1, src2, src3);
+}
+
+
+/* DST = (SRC1 & ~SRC2) | SRC3.  Return non-zero if
+   DST != (SRC1 & ~SRC2) | SRC3.  */
+bool
+bitset_andn_or_cmp_ (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  return bitset_op4_cmp (dst, src1, src2, src3, BITSET_OP_ANDN_OR);
+}
+
+
+/* DST = (SRC1 | SRC2) & SRC3.  */
+void
+bitset_or_and_ (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  bitset_or_and_cmp_ (dst, src1, src2, src3);
+}
+
+
+/* DST = (SRC1 | SRC2) & SRC3.  Return non-zero if
+   DST != (SRC1 | SRC2) & SRC3.  */
+bool
+bitset_or_and_cmp_ (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  return bitset_op4_cmp (dst, src1, src2, src3, BITSET_OP_OR_AND);
+}
+
+
+/* Function to be called from debugger to print bitset.  */
+void
+debug_bitset (bitset bset)
+{
+  if (bset)
+    bitset_print (stderr, bset, true);
+}
diff --git a/lib/bitset.h b/lib/bitset.h
new file mode 100644
index 0000000..45c8818
--- /dev/null
+++ b/lib/bitset.h
@@ -0,0 +1,392 @@
+/* Generic bitsets.
+   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
+
+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 2 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, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _BITSET_H
+#define _BITSET_H
+
+/* This file is the public interface to the bitset abstract data type.
+   Only use the functions and macros defined in this file.  */
+
+#include "bbitset.h"
+#include "obstack.h"
+#include <stdio.h>
+
+#if USE_UNLOCKED_IO
+# include "unlocked-io.h"
+#endif
+
+/* Attributes used to select a bitset implementation.  */
+enum bitset_attr {BITSET_FIXED = 1,    /* Bitset size fixed.  */
+		  BITSET_VARIABLE = 2, /* Bitset size variable.  */
+		  BITSET_DENSE = 4,    /* Bitset dense.  */
+		  BITSET_SPARSE = 8,   /* Bitset sparse.  */
+		  BITSET_FRUGAL = 16,  /* Prefer most compact.  */
+		  BITSET_GREEDY = 32}; /* Prefer fastest at memory expense.  */
+
+typedef unsigned int bitset_attrs;
+
+/* The contents of the union should be considered to be private.
+   While I would like to make this union opaque, it needs to be
+   visible for the inline bit set/test functions, and for delegation
+   to the proper implementation.  */
+union bitset_union
+{
+  /* This must be the first member of every other structure that is a
+     member of this union.  */
+  struct bbitset_struct b;	        /* Base bitset data.  */
+
+  struct abitset_struct
+  {
+    struct bbitset_struct b;
+    bitset_word words[1];		/* The array of bits.  */
+  } a;
+
+  struct ebitset_struct
+  {
+    struct bbitset_struct b;
+    bitset_windex size;			/* Number of elements.  */
+    struct ebitset_elt_struct **elts;	/* Expanding array of ptrs to elts.  */
+  } e;
+
+  struct lbitset_struct
+  {
+    struct bbitset_struct b;
+    struct lbitset_elt_struct *head;	/* First element in linked list.  */
+    struct lbitset_elt_struct *tail;	/* Last element in linked list.  */
+  } l;
+
+  struct bitset_stats_struct
+  {
+    struct bbitset_struct b;
+    bitset bset;
+  } s;
+
+  struct vbitset_struct
+  {
+    struct bbitset_struct b;
+    bitset_windex size;			/* Allocated size of array.  */
+  } v;
+
+};
+
+
+/* The contents of this structure should be considered private.
+   It is used for iterating over set bits.  */
+typedef struct
+{
+  bitset_bindex list[BITSET_LIST_SIZE];
+  bitset_bindex next;
+  bitset_bindex num;
+  bitset_bindex i;
+} bitset_iterator;
+
+
+/* Return bytes required for bitset of desired type and size.  */
+extern size_t bitset_bytes (enum bitset_type, bitset_bindex);
+
+/* Initialise a bitset with desired type and size.  */
+extern bitset bitset_init (bitset, bitset_bindex, enum bitset_type);
+
+/* Select an implementation type based on the desired bitset size
+   and attributes.  */
+extern enum bitset_type bitset_type_choose (bitset_bindex, bitset_attrs);
+
+/* Create a bitset of desired type and size.  The bitset is zeroed.  */
+extern bitset bitset_alloc (bitset_bindex, enum bitset_type);
+
+/* Free bitset.  */
+extern void bitset_free (bitset);
+
+/* Create a bitset of desired type and size using an obstack.  The
+   bitset is zeroed.  */
+extern bitset bitset_obstack_alloc (struct obstack *bobstack,
+				    bitset_bindex, enum bitset_type);
+
+/* Free bitset allocated on obstack.  */
+extern void bitset_obstack_free (bitset);
+
+/* Create a bitset of desired size and attributes.  The bitset is zeroed.  */
+extern bitset bitset_create (bitset_bindex, bitset_attrs);
+
+/* Return bitset type.  */
+extern enum bitset_type bitset_type_get (bitset);
+
+/* Return bitset type name.  */
+extern const char *bitset_type_name_get (bitset);
+
+
+/* Set bit BITNO in bitset BSET.  */
+static inline void
+bitset_set (bitset bset, bitset_bindex bitno)
+{
+  bitset_windex windex = bitno / BITSET_WORD_BITS;
+  bitset_windex offset = windex - bset->b.cindex;
+
+  if (offset < bset->b.csize)
+    bset->b.cdata[offset] |= ((bitset_word) 1 << (bitno % BITSET_WORD_BITS));
+  else
+    BITSET_SET_ (bset, bitno);
+}
+
+
+/* Reset bit BITNO in bitset BSET.  */
+static inline void
+bitset_reset (bitset bset, bitset_bindex bitno)
+{
+  bitset_windex windex = bitno / BITSET_WORD_BITS;
+  bitset_windex offset = windex - bset->b.cindex;
+
+  if (offset < bset->b.csize)
+    bset->b.cdata[offset] &= ~((bitset_word) 1 << (bitno % BITSET_WORD_BITS));
+  else
+    BITSET_RESET_ (bset, bitno);
+}
+
+
+/* Test bit BITNO in bitset BSET.  */
+static inline bool
+bitset_test (bitset bset, bitset_bindex bitno)
+{
+  bitset_windex windex = bitno / BITSET_WORD_BITS;
+  bitset_windex offset = windex - bset->b.cindex;
+
+  if (offset < bset->b.csize)
+    return (bset->b.cdata[offset] >> (bitno % BITSET_WORD_BITS)) & 1;
+  else
+    return BITSET_TEST_ (bset, bitno);
+}
+
+
+/* Toggle bit BITNO in bitset BSET and return non-zero if now set.  */
+#define bitset_toggle(bset, bitno) BITSET_TOGGLE_ (bset, bitno)
+
+/* Return size in bits of bitset SRC.  */
+#define bitset_size(SRC) BITSET_SIZE_ (SRC)
+
+/* Change size of bitset.  */
+extern void bitset_resize (bitset, bitset_bindex);
+
+/* Return number of bits set in bitset SRC.  */
+#define bitset_count(SRC) BITSET_COUNT_ (SRC)
+
+
+/* Return SRC == 0.  */
+#define bitset_empty_p(SRC) BITSET_EMPTY_P_ (SRC)
+
+/* DST = ~0.  */
+#define bitset_ones(DST) BITSET_ONES_ (DST)
+
+/* DST = 0.  */
+#define bitset_zero(DST) BITSET_ZERO_ (DST)
+
+
+
+/* DST = SRC.  */
+#define bitset_copy(DST, SRC) BITSET_COPY_ (DST, SRC)
+
+/* Return DST & SRC == 0.  */
+#define bitset_disjoint_p(DST, SRC) BITSET_DISJOINT_P_ (DST, SRC)
+
+/* Return DST == SRC.  */
+#define bitset_equal_p(DST, SRC) BITSET_EQUAL_P_ (DST, SRC)
+
+/* DST = ~SRC.  */
+#define bitset_not(DST, SRC) BITSET_NOT_ (DST, SRC)
+
+/* Return DST == DST | SRC.  */
+#define bitset_subset_p(DST, SRC) BITSET_SUBSET_P_ (DST, SRC)
+
+
+
+/* DST = SRC1 & SRC2.  */
+#define bitset_and(DST, SRC1, SRC2) BITSET_AND_ (DST, SRC1, SRC2)
+
+/* DST = SRC1 & SRC2.  Return non-zero if DST != SRC1 & SRC2.  */
+#define bitset_and_cmp(DST, SRC1, SRC2) BITSET_AND_CMP_ (DST, SRC1, SRC2)
+
+/* DST = SRC1 & ~SRC2.  */
+#define bitset_andn(DST, SRC1, SRC2) BITSET_ANDN_ (DST, SRC1, SRC2)
+
+/* DST = SRC1 & ~SRC2.  Return non-zero if DST != SRC1 & ~SRC2.  */
+#define bitset_andn_cmp(DST, SRC1, SRC2) BITSET_ANDN_CMP_ (DST, SRC1, SRC2)
+
+/* DST = SRC1 | SRC2.  */
+#define bitset_or(DST, SRC1, SRC2) BITSET_OR_ (DST, SRC1, SRC2)
+
+/* DST = SRC1 | SRC2.  Return non-zero if DST != SRC1 | SRC2.  */
+#define bitset_or_cmp(DST, SRC1, SRC2) BITSET_OR_CMP_ (DST, SRC1, SRC2)
+
+/* DST = SRC1 ^ SRC2.  */
+#define bitset_xor(DST, SRC1, SRC2) BITSET_XOR_ (DST, SRC1, SRC2)
+
+/* DST = SRC1 ^ SRC2.  Return non-zero if DST != SRC1 ^ SRC2.  */
+#define bitset_xor_cmp(DST, SRC1, SRC2) BITSET_XOR_CMP_ (DST, SRC1, SRC2)
+
+
+
+/* DST = (SRC1 & SRC2) | SRC3.  */
+#define bitset_and_or(DST, SRC1, SRC2, SRC3) \
+ BITSET_AND_OR_ (DST, SRC1, SRC2, SRC3)
+
+/* DST = (SRC1 & SRC2) | SRC3.  Return non-zero if
+   DST != (SRC1 & SRC2) | SRC3.  */
+#define bitset_and_or_cmp(DST, SRC1, SRC2, SRC3) \
+ BITSET_AND_OR_CMP_ (DST, SRC1, SRC2, SRC3)
+
+/* DST = (SRC1 & ~SRC2) | SRC3.  */
+#define bitset_andn_or(DST, SRC1, SRC2, SRC3) \
+ BITSET_ANDN_OR_ (DST, SRC1, SRC2, SRC3)
+
+/* DST = (SRC1 & ~SRC2) | SRC3.  Return non-zero if
+   DST != (SRC1 & ~SRC2) | SRC3.  */
+#define bitset_andn_or_cmp(DST, SRC1, SRC2, SRC3) \
+ BITSET_ANDN_OR_CMP_ (DST, SRC1, SRC2, SRC3)
+
+/* DST = (SRC1 | SRC2) & SRC3.  */
+#define bitset_or_and(DST, SRC1, SRC2, SRC3)\
+ BITSET_OR_AND_ (DST, SRC1, SRC2, SRC3)
+
+/* DST = (SRC1 | SRC2) & SRC3.  Return non-zero if
+   DST != (SRC1 | SRC2) & SRC3.  */
+#define bitset_or_and_cmp(DST, SRC1, SRC2, SRC3)\
+ BITSET_OR_AND_CMP_ (DST, SRC1, SRC2, SRC3)
+
+/* Find list of up to NUM bits set in BSET starting from and including
+   *NEXT.  Return with actual number of bits found and with *NEXT
+   indicating where search stopped.  */
+#define bitset_list(BSET, LIST, NUM, NEXT) \
+ BITSET_LIST_ (BSET, LIST, NUM, NEXT)
+
+/* Find reverse list of up to NUM bits set in BSET starting from and
+   including NEXT.  Return with actual number of bits found and with
+   *NEXT indicating where search stopped.  */
+#define bitset_list_reverse(BSET, LIST, NUM, NEXT) \
+ BITSET_LIST_REVERSE_ (BSET, LIST, NUM, NEXT)
+
+/* Return true if both bitsets are of the same type and size.  */
+extern bool bitset_compatible_p (bitset bset1, bitset bset2);
+
+/* Find next set bit from the given bit index.  */
+extern bitset_bindex bitset_next (bitset, bitset_bindex);
+
+/* Find previous set bit from the given bit index.  */
+extern bitset_bindex bitset_prev (bitset, bitset_bindex);
+
+/* Find first set bit.  */
+extern bitset_bindex bitset_first (bitset);
+
+/* Find last set bit.  */
+extern bitset_bindex bitset_last (bitset);
+
+/* Return nonzero if this is the only set bit.  */
+extern bool bitset_only_set_p (bitset, bitset_bindex);
+
+/* Dump bitset.  */
+extern void bitset_dump (FILE *, bitset);
+
+/* Loop over all elements of BSET, starting with MIN, setting INDEX
+   to the index of each set bit.  For example, the following will print
+   the bits set in a bitset:
+
+   bitset_bindex i;
+   bitset_iterator iter;
+
+   BITSET_FOR_EACH (iter, src, i, 0)
+   {
+      printf ("%lu ", (unsigned long int) i);
+   };
+*/
+#define BITSET_FOR_EACH(ITER, BSET, INDEX, MIN)				      \
+  for (ITER.next = (MIN), ITER.num = BITSET_LIST_SIZE;			      \
+       (ITER.num == BITSET_LIST_SIZE)					      \
+       && (ITER.num = bitset_list (BSET, ITER.list,			      \
+				   BITSET_LIST_SIZE, &ITER.next));)	      \
+    for (ITER.i = 0;							      \
+	 ITER.i < ITER.num && ((INDEX) = ITER.list[ITER.i], 1);		      \
+	 ITER.i++)
+
+
+/* Loop over all elements of BSET, in reverse order starting with
+   MIN, setting INDEX to the index of each set bit.  For example, the
+   following will print the bits set in a bitset in reverse order:
+
+   bitset_bindex i;
+   bitset_iterator iter;
+
+   BITSET_FOR_EACH_REVERSE (iter, src, i, 0)
+   {
+      printf ("%lu ", (unsigned long int) i);
+   };
+*/
+#define BITSET_FOR_EACH_REVERSE(ITER, BSET, INDEX, MIN)			      \
+  for (ITER.next = (MIN), ITER.num = BITSET_LIST_SIZE;			      \
+       (ITER.num == BITSET_LIST_SIZE)					      \
+       && (ITER.num = bitset_list_reverse (BSET, ITER.list,		      \
+					   BITSET_LIST_SIZE, &ITER.next));)   \
+    for (ITER.i = 0;							      \
+	 ITER.i < ITER.num && ((INDEX) = ITER.list[ITER.i], 1);		      \
+	 ITER.i++)
+
+
+/* Define set operations in terms of logical operations.  */
+
+#define bitset_diff(DST, SRC1, SRC2) bitset_andn (DST, SRC1, SRC2)
+#define bitset_diff_cmp(DST, SRC1, SRC2) bitset_andn_cmp (DST, SRC1, SRC2)
+
+#define bitset_intersection(DST, SRC1, SRC2) bitset_and (DST, SRC1, SRC2)
+#define bitset_intersection_cmp(DST, SRC1, SRC2) bitset_and_cmp (DST, SRC1, SRC2)
+
+#define bitset_union(DST, SRC1, SRC2) bitset_or (DST, SRC1, SRC2)
+#define bitset_union_cmp(DST, SRC1, SRC2) bitset_or_cmp (DST, SRC1, SRC2)
+
+/* Symmetrical difference.  */
+#define bitset_symdiff(DST, SRC1, SRC2) bitset_xor (DST, SRC1, SRC2)
+#define bitset_symdiff_cmp(DST, SRC1, SRC2) bitset_xor_cmp (DST, SRC1, SRC2)
+
+/* Union of difference.  */
+#define bitset_diff_union(DST, SRC1, SRC2, SRC3) \
+  bitset_andn_or (DST, SRC1, SRC2, SRC3)
+#define bitset_diff_union_cmp(DST, SRC1, SRC2, SRC3) \
+  bitset_andn_or_cmp (DST, SRC1, SRC2, SRC3)
+
+
+/* Release any memory tied up with bitsets.  */
+extern void bitset_release_memory (void);
+
+/* Enable bitset stats gathering.  */
+extern void bitset_stats_enable (void);
+
+/* Disable bitset stats gathering.  */
+extern void bitset_stats_disable (void);
+
+/* Read bitset stats file of accummulated stats.  */
+void bitset_stats_read (const char *file_name);
+
+/* Write bitset stats file of accummulated stats.  */
+void bitset_stats_write (const char *file_name);
+
+/* Dump bitset stats.  */
+extern void bitset_stats_dump (FILE *);
+
+/* Function to debug bitset from debugger.  */
+extern void debug_bitset (bitset);
+
+/* Function to debug bitset stats from debugger.  */
+extern void debug_bitset_stats (void);
+
+#endif /* _BITSET_H  */
diff --git a/lib/bitset_stats.c b/lib/bitset_stats.c
new file mode 100644
index 0000000..7b7fb34
--- /dev/null
+++ b/lib/bitset_stats.c
@@ -0,0 +1,730 @@
+/* Bitset statistics.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
+
+   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 2 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* This file is a wrapper bitset implementation for the other bitset
+   implementations.  It provides bitset compatibility checking and
+   statistics gathering without having to instrument the bitset
+   implementations.  When statistics gathering is enabled, the bitset
+   operations get vectored through here and we then call the appropriate
+   routines.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "bbitset.h"
+#include "abitset.h"
+#include "ebitset.h"
+#include "lbitset.h"
+#include "vbitset.h"
+#include "bitset_stats.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "gettext.h"
+#define _(Msgid)  gettext (Msgid)
+
+/* Configuration macros.  */
+#define BITSET_STATS_FILE "bitset.dat"
+#define BITSET_LOG_COUNT_BINS 10
+#define BITSET_LOG_SIZE_BINS  16
+#define BITSET_DENSITY_BINS  20
+
+
+/* Accessor macros.  */
+#define BITSET_STATS_ALLOCS_INC(TYPE)			\
+    bitset_stats_info->types[(TYPE)].allocs++
+#define BITSET_STATS_FREES_INC(BSET)			\
+    bitset_stats_info->types[BITSET_TYPE_ (BSET)].frees++
+#define BITSET_STATS_SETS_INC(BSET)			\
+    bitset_stats_info->types[BITSET_TYPE_ (BSET)].sets++
+#define BITSET_STATS_CACHE_SETS_INC(BSET)		\
+    bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_sets++
+#define BITSET_STATS_RESETS_INC(BSET)			\
+    bitset_stats_info->types[BITSET_TYPE_ (BSET)].resets++
+#define BITSET_STATS_CACHE_RESETS_INC(BSET)		\
+    bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_resets++
+#define BITSET_STATS_TESTS_INC(BSET)			\
+    bitset_stats_info->types[BITSET_TYPE_ (BSET)].tests++
+#define BITSET_STATS_CACHE_TESTS_INC(BSET)		\
+    bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_tests++
+#define BITSET_STATS_LISTS_INC(BSET)			\
+    bitset_stats_info->types[BITSET_TYPE_ (BSET)].lists++
+#define BITSET_STATS_LIST_COUNTS_INC(BSET, I)		\
+    bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_counts[(I)]++
+#define BITSET_STATS_LIST_SIZES_INC(BSET, I)		\
+    bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_sizes[(I)]++
+#define BITSET_STATS_LIST_DENSITY_INC(BSET, I)		\
+    bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_density[(I)]++
+
+
+struct bitset_type_info_struct
+{
+  unsigned int allocs;
+  unsigned int frees;
+  unsigned int lists;
+  unsigned int sets;
+  unsigned int cache_sets;
+  unsigned int resets;
+  unsigned int cache_resets;
+  unsigned int tests;
+  unsigned int cache_tests;
+  unsigned int list_counts[BITSET_LOG_COUNT_BINS];
+  unsigned int list_sizes[BITSET_LOG_SIZE_BINS];
+  unsigned int list_density[BITSET_DENSITY_BINS];
+};
+
+struct bitset_stats_info_struct
+{
+  unsigned int runs;
+  struct bitset_type_info_struct types[BITSET_TYPE_NUM];
+};
+
+
+struct bitset_stats_info_struct bitset_stats_info_data;
+struct bitset_stats_info_struct *bitset_stats_info;
+bool bitset_stats_enabled = false;
+
+
+/* Print a percentage histogram with message MSG to FILE.  */
+static void
+bitset_percent_histogram_print (FILE *file, const char *name, const char *msg,
+				unsigned int n_bins, unsigned int *bins)
+{
+  unsigned int i;
+  unsigned int total;
+
+  total = 0;
+  for (i = 0; i < n_bins; i++)
+    total += bins[i];
+
+  if (!total)
+    return;
+
+  fprintf (file, "%s %s", name, msg);
+  for (i = 0; i < n_bins; i++)
+    fprintf (file, "%.0f-%.0f%%\t%8u (%5.1f%%)\n",
+	     i * 100.0 / n_bins,
+	     (i + 1) * 100.0 / n_bins, bins[i],
+	     (100.0 * bins[i]) / total);
+}
+
+
+/* Print a log histogram with message MSG to FILE.  */
+static void
+bitset_log_histogram_print (FILE *file, const char *name, const char *msg,
+			    unsigned int n_bins, unsigned int *bins)
+{
+  unsigned int i;
+  unsigned int total;
+  unsigned int max_width;
+
+  total = 0;
+  for (i = 0; i < n_bins; i++)
+    total += bins[i];
+
+  if (!total)
+    return;
+
+  /* Determine number of useful bins.  */
+  for (i = n_bins; i > 3 && ! bins[i - 1]; i--)
+     continue;
+  n_bins = i;
+
+  /* 2 * ceil (log10 (2) * (N - 1)) + 1.  */
+  max_width = 2 * (unsigned int) (0.30103 * (n_bins - 1) + 0.9999) + 1;
+
+  fprintf (file, "%s %s", name, msg);
+  for (i = 0; i < 2; i++)
+    fprintf (file, "%*d\t%8u (%5.1f%%)\n",
+	     max_width, i, bins[i], 100.0 * bins[i] / total);
+
+  for (; i < n_bins; i++)
+    fprintf (file, "%*lu-%lu\t%8u (%5.1f%%)\n",
+	     max_width - ((unsigned int) (0.30103 * (i) + 0.9999) + 1),
+	     1UL << (i - 1),
+	     (1UL << i) - 1,
+	     bins[i],
+	     (100.0 * bins[i]) / total);
+}
+
+
+/* Print bitset statistics to FILE.  */
+static void
+bitset_stats_print_1 (FILE *file, const char *name,
+		      struct bitset_type_info_struct *stats)
+{
+  if (!stats)
+    return;
+
+  fprintf (file, "%s:\n", name);
+  fprintf (file, _("%u bitset_allocs, %u freed (%.2f%%).\n"),
+	   stats->allocs, stats->frees,
+	   stats->allocs ? 100.0 * stats->frees / stats->allocs : 0);
+  fprintf (file, _("%u bitset_sets, %u cached (%.2f%%)\n"),
+	   stats->sets, stats->cache_sets,
+	   stats->sets ? 100.0 * stats->cache_sets / stats->sets : 0);
+  fprintf (file, _("%u bitset_resets, %u cached (%.2f%%)\n"),
+	   stats->resets, stats->cache_resets,
+	   stats->resets ? 100.0 * stats->cache_resets / stats->resets : 0);
+  fprintf (file, _("%u bitset_tests, %u cached (%.2f%%)\n"),
+	   stats->tests, stats->cache_tests,
+	   stats->tests ? 100.0 * stats->cache_tests / stats->tests : 0);
+
+  fprintf (file, _("%u bitset_lists\n"), stats->lists);
+
+  bitset_log_histogram_print (file, name, _("count log histogram\n"),
+			      BITSET_LOG_COUNT_BINS, stats->list_counts);
+
+  bitset_log_histogram_print (file, name, _("size log histogram\n"),
+			      BITSET_LOG_SIZE_BINS, stats->list_sizes);
+
+  bitset_percent_histogram_print (file, name, _("density histogram\n"),
+				  BITSET_DENSITY_BINS, stats->list_density);
+}
+
+
+/* Print all bitset statistics to FILE.  */
+static void
+bitset_stats_print (FILE *file, bool verbose ATTRIBUTE_UNUSED)
+{
+  int i;
+
+  if (!bitset_stats_info)
+    return;
+
+  fprintf (file, _("Bitset statistics:\n\n"));
+
+  if (bitset_stats_info->runs > 1)
+    fprintf (file, _("Accumulated runs = %u\n"), bitset_stats_info->runs);
+
+  for (i = 0; i < BITSET_TYPE_NUM; i++)
+    bitset_stats_print_1 (file, bitset_type_names[i],
+			  &bitset_stats_info->types[i]);
+}
+
+
+/* Initialise bitset statistics logging.  */
+void
+bitset_stats_enable (void)
+{
+  if (!bitset_stats_info)
+    bitset_stats_info = &bitset_stats_info_data;
+  bitset_stats_enabled = true;
+}
+
+
+void
+bitset_stats_disable (void)
+{
+  bitset_stats_enabled = false;
+}
+
+
+/* Read bitset statistics file.  */
+void
+bitset_stats_read (const char *file_name)
+{
+  FILE *file;
+
+  if (!bitset_stats_info)
+    return;
+
+  if (!file_name)
+    file_name = BITSET_STATS_FILE;
+
+  file = fopen (file_name, "r");
+  if (file)
+    {
+      if (fread (&bitset_stats_info_data, sizeof (bitset_stats_info_data),
+		 1, file) != 1)
+	{
+	  if (ferror (file))
+	    perror (_("Could not read stats file."));
+	  else
+	    fprintf (stderr, _("Bad stats file size.\n"));
+	}
+      if (fclose (file) != 0)
+	perror (_("Could not read stats file."));
+    }
+  bitset_stats_info_data.runs++;
+}
+
+
+/* Write bitset statistics file.  */
+void
+bitset_stats_write (const char *file_name)
+{
+  FILE *file;
+
+  if (!bitset_stats_info)
+    return;
+
+  if (!file_name)
+    file_name = BITSET_STATS_FILE;
+
+  file = fopen (file_name, "w");
+  if (file)
+    {
+      if (fwrite (&bitset_stats_info_data, sizeof (bitset_stats_info_data),
+		  1, file) != 1)
+	perror (_("Could not write stats file."));
+      if (fclose (file) != 0)
+	perror (_("Could not write stats file."));
+    }
+  else
+    perror (_("Could not open stats file for writing."));
+}
+
+
+/* Dump bitset statistics to FILE.  */
+void
+bitset_stats_dump (FILE *file)
+{
+  bitset_stats_print (file, false);
+}
+
+
+/* Function to be called from debugger to print bitset stats.  */
+void
+debug_bitset_stats (void)
+{
+  bitset_stats_print (stderr, true);
+}
+
+
+static void
+bitset_stats_set (bitset dst, bitset_bindex bitno)
+{
+  bitset bset = dst->s.bset;
+  bitset_windex wordno = bitno / BITSET_WORD_BITS;
+  bitset_windex offset = wordno - bset->b.cindex;
+
+  BITSET_STATS_SETS_INC (bset);
+
+  if (offset < bset->b.csize)
+    {
+      bset->b.cdata[offset] |= (bitset_word) 1 << (bitno % BITSET_WORD_BITS);
+      BITSET_STATS_CACHE_SETS_INC (bset);
+    }
+  else
+    BITSET_SET_ (bset, bitno);
+}
+
+
+static void
+bitset_stats_reset (bitset dst, bitset_bindex bitno)
+{
+  bitset bset = dst->s.bset;
+  bitset_windex wordno = bitno / BITSET_WORD_BITS;
+  bitset_windex offset = wordno - bset->b.cindex;
+
+  BITSET_STATS_RESETS_INC (bset);
+
+  if (offset < bset->b.csize)
+    {
+      bset->b.cdata[offset] &=
+	~((bitset_word) 1 << (bitno % BITSET_WORD_BITS));
+      BITSET_STATS_CACHE_RESETS_INC (bset);
+    }
+  else
+    BITSET_RESET_ (bset, bitno);
+}
+
+
+static bool
+bitset_stats_toggle (bitset src, bitset_bindex bitno)
+{
+    return BITSET_TOGGLE_ (src->s.bset, bitno);
+}
+
+
+static bool
+bitset_stats_test (bitset src, bitset_bindex bitno)
+{
+  bitset bset = src->s.bset;
+  bitset_windex wordno = bitno / BITSET_WORD_BITS;
+  bitset_windex offset = wordno - bset->b.cindex;
+
+  BITSET_STATS_TESTS_INC (bset);
+
+  if (offset < bset->b.csize)
+    {
+      BITSET_STATS_CACHE_TESTS_INC (bset);
+      return (bset->b.cdata[offset] >> (bitno % BITSET_WORD_BITS)) & 1;
+    }
+  else
+    return BITSET_TEST_ (bset, bitno);
+}
+
+
+static bitset_bindex
+bitset_stats_resize (bitset src, bitset_bindex size)
+{
+    return BITSET_RESIZE_ (src->s.bset, size);
+}
+
+
+static bitset_bindex
+bitset_stats_size (bitset src)
+{
+  return BITSET_SIZE_ (src->s.bset);
+}
+
+
+static bitset_bindex
+bitset_stats_count (bitset src)
+{
+  return BITSET_COUNT_ (src->s.bset);
+}
+
+
+static bool
+bitset_stats_empty_p (bitset dst)
+{
+  return BITSET_EMPTY_P_ (dst->s.bset);
+}
+
+
+static void
+bitset_stats_ones (bitset dst)
+{
+  BITSET_ONES_ (dst->s.bset);
+}
+
+
+static void
+bitset_stats_zero (bitset dst)
+{
+  BITSET_ZERO_ (dst->s.bset);
+}
+
+
+static void
+bitset_stats_copy (bitset dst, bitset src)
+{
+  BITSET_CHECK2_ (dst, src);
+  BITSET_COPY_ (dst->s.bset, src->s.bset);
+}
+
+
+static bool
+bitset_stats_disjoint_p (bitset dst, bitset src)
+{
+  BITSET_CHECK2_ (dst, src);
+  return BITSET_DISJOINT_P_ (dst->s.bset, src->s.bset);
+}
+
+
+static bool
+bitset_stats_equal_p (bitset dst, bitset src)
+{
+  BITSET_CHECK2_ (dst, src);
+  return BITSET_EQUAL_P_ (dst->s.bset, src->s.bset);
+}
+
+
+static void
+bitset_stats_not (bitset dst, bitset src)
+{
+  BITSET_CHECK2_ (dst, src);
+  BITSET_NOT_ (dst->s.bset, src->s.bset);
+}
+
+
+static bool
+bitset_stats_subset_p (bitset dst, bitset src)
+{
+  BITSET_CHECK2_ (dst, src);
+  return BITSET_SUBSET_P_ (dst->s.bset, src->s.bset);
+}
+
+
+static void
+bitset_stats_and (bitset dst, bitset src1, bitset src2)
+{
+  BITSET_CHECK3_ (dst, src1, src2);
+  BITSET_AND_ (dst->s.bset, src1->s.bset, src2->s.bset);
+}
+
+
+static bool
+bitset_stats_and_cmp (bitset dst, bitset src1, bitset src2)
+{
+  BITSET_CHECK3_ (dst, src1, src2);
+  return BITSET_AND_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset);
+}
+
+
+static void
+bitset_stats_andn (bitset dst, bitset src1, bitset src2)
+{
+  BITSET_CHECK3_ (dst, src1, src2);
+  BITSET_ANDN_ (dst->s.bset, src1->s.bset, src2->s.bset);
+}
+
+
+static bool
+bitset_stats_andn_cmp (bitset dst, bitset src1, bitset src2)
+{
+  BITSET_CHECK3_ (dst, src1, src2);
+  return BITSET_ANDN_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset);
+}
+
+
+static void
+bitset_stats_or (bitset dst, bitset src1, bitset src2)
+{
+  BITSET_CHECK3_ (dst, src1, src2);
+  BITSET_OR_ (dst->s.bset, src1->s.bset, src2->s.bset);
+}
+
+
+static bool
+bitset_stats_or_cmp (bitset dst, bitset src1, bitset src2)
+{
+  BITSET_CHECK3_ (dst, src1, src2);
+  return BITSET_OR_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset);
+}
+
+
+static void
+bitset_stats_xor (bitset dst, bitset src1, bitset src2)
+{
+  BITSET_CHECK3_ (dst, src1, src2);
+  BITSET_XOR_ (dst->s.bset, src1->s.bset, src2->s.bset);
+}
+
+
+static bool
+bitset_stats_xor_cmp (bitset dst, bitset src1, bitset src2)
+{
+  BITSET_CHECK3_ (dst, src1, src2);
+  return BITSET_XOR_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset);
+}
+
+
+static void
+bitset_stats_and_or (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  BITSET_CHECK4_ (dst, src1, src2, src3);
+  BITSET_AND_OR_ (dst->s.bset, src1->s.bset, src2->s.bset, src3->s.bset);
+}
+
+
+static bool
+bitset_stats_and_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  BITSET_CHECK4_ (dst, src1, src2, src3);
+  return BITSET_AND_OR_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset, src3->s.bset);
+}
+
+
+static void
+bitset_stats_andn_or (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  BITSET_CHECK4_ (dst, src1, src2, src3);
+  BITSET_ANDN_OR_ (dst->s.bset, src1->s.bset, src2->s.bset, src3->s.bset);
+}
+
+
+static bool
+bitset_stats_andn_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  BITSET_CHECK4_ (dst, src1, src2, src3);
+  return BITSET_ANDN_OR_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset, src3->s.bset);
+}
+
+
+static void
+bitset_stats_or_and (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  BITSET_CHECK4_ (dst, src1, src2, src3);
+  BITSET_OR_AND_ (dst->s.bset, src1->s.bset, src2->s.bset, src3->s.bset);
+}
+
+
+static bool
+bitset_stats_or_and_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  BITSET_CHECK4_ (dst, src1, src2, src3);
+  return BITSET_OR_AND_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset, src3->s.bset);
+}
+
+
+static bitset_bindex
+bitset_stats_list (bitset bset, bitset_bindex *list,
+		   bitset_bindex num, bitset_bindex *next)
+{
+  bitset_bindex count;
+  bitset_bindex tmp;
+  bitset_bindex size;
+  bitset_bindex i;
+  enum bitset_type type;
+
+  count = BITSET_LIST_ (bset->s.bset, list, num, next);
+
+  type = BITSET_TYPE_ (bset->s.bset);
+  BITSET_STATS_LISTS_INC (bset->s.bset);
+
+  /* Log histogram of number of set bits.  */
+  for (i = 0, tmp = count; tmp; tmp >>= 1, i++)
+     continue;
+  if (i >= BITSET_LOG_COUNT_BINS)
+     i = BITSET_LOG_COUNT_BINS - 1;
+  BITSET_STATS_LIST_COUNTS_INC (bset->s.bset, i);
+
+  /* Log histogram of number of bits in set.  */
+  size = BITSET_SIZE_ (bset->s.bset);
+  for (i = 0, tmp = size; tmp; tmp >>= 1, i++)
+     continue;
+  if (i >= BITSET_LOG_SIZE_BINS)
+     i = BITSET_LOG_SIZE_BINS - 1;
+  BITSET_STATS_LIST_SIZES_INC (bset->s.bset, i);
+
+  /* Histogram of fraction of bits set.  */
+  i = size ? (count * BITSET_DENSITY_BINS) / size : 0;
+  if (i >= BITSET_DENSITY_BINS)
+     i = BITSET_DENSITY_BINS - 1;
+  BITSET_STATS_LIST_DENSITY_INC (bset->s.bset, i);
+  return count;
+}
+
+
+static bitset_bindex
+bitset_stats_list_reverse (bitset bset, bitset_bindex *list,
+			   bitset_bindex num, bitset_bindex *next)
+{
+  return BITSET_LIST_REVERSE_ (bset->s.bset, list, num, next);
+}
+
+
+static void
+bitset_stats_free (bitset bset)
+{
+  BITSET_STATS_FREES_INC (bset->s.bset);
+  BITSET_FREE_ (bset->s.bset);
+}
+
+
+struct bitset_vtable bitset_stats_vtable = {
+  bitset_stats_set,
+  bitset_stats_reset,
+  bitset_stats_toggle,
+  bitset_stats_test,
+  bitset_stats_resize,
+  bitset_stats_size,
+  bitset_stats_count,
+  bitset_stats_empty_p,
+  bitset_stats_ones,
+  bitset_stats_zero,
+  bitset_stats_copy,
+  bitset_stats_disjoint_p,
+  bitset_stats_equal_p,
+  bitset_stats_not,
+  bitset_stats_subset_p,
+  bitset_stats_and,
+  bitset_stats_and_cmp,
+  bitset_stats_andn,
+  bitset_stats_andn_cmp,
+  bitset_stats_or,
+  bitset_stats_or_cmp,
+  bitset_stats_xor,
+  bitset_stats_xor_cmp,
+  bitset_stats_and_or,
+  bitset_stats_and_or_cmp,
+  bitset_stats_andn_or,
+  bitset_stats_andn_or_cmp,
+  bitset_stats_or_and,
+  bitset_stats_or_and_cmp,
+  bitset_stats_list,
+  bitset_stats_list_reverse,
+  bitset_stats_free,
+  BITSET_STATS
+};
+
+
+/* Return enclosed bitset type.  */
+enum bitset_type
+bitset_stats_type_get (bitset bset)
+{
+   return BITSET_TYPE_ (bset->s.bset);
+}
+
+
+size_t
+bitset_stats_bytes (void)
+{
+  return sizeof (struct bitset_stats_struct);
+}
+
+
+bitset
+bitset_stats_init (bitset bset, bitset_bindex n_bits, enum bitset_type type)
+{
+  size_t bytes;
+  bitset sbset;
+
+  bset->b.vtable = &bitset_stats_vtable;
+
+  /* Disable cache.  */
+  bset->b.cindex = 0;
+  bset->b.csize = 0;
+  bset->b.cdata = 0;
+
+  BITSET_NBITS_ (bset) = n_bits;
+
+  /* Set up the actual bitset implementation that
+     we are a wrapper over.  */
+  switch (type)
+    {
+    default:
+      abort ();
+
+    case BITSET_ARRAY:
+      bytes = abitset_bytes (n_bits);
+      sbset = xcalloc (1, bytes);
+      abitset_init (sbset, n_bits);
+      break;
+
+    case BITSET_LIST:
+      bytes = lbitset_bytes (n_bits);
+      sbset = xcalloc (1, bytes);
+      lbitset_init (sbset, n_bits);
+      break;
+
+    case BITSET_TABLE:
+      bytes = ebitset_bytes (n_bits);
+      sbset = xcalloc (1, bytes);
+      ebitset_init (sbset, n_bits);
+      break;
+
+    case BITSET_VARRAY:
+      bytes = vbitset_bytes (n_bits);
+      sbset = xcalloc (1, bytes);
+      vbitset_init (sbset, n_bits);
+      break;
+    }
+
+  bset->s.bset = sbset;
+
+  BITSET_STATS_ALLOCS_INC (type);
+
+  return bset;
+}
diff --git a/lib/bitset_stats.h b/lib/bitset_stats.h
new file mode 100644
index 0000000..6378c5c
--- /dev/null
+++ b/lib/bitset_stats.h
@@ -0,0 +1,32 @@
+/* Functions to support bitset statistics.
+   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
+
+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 2 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, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _BITSET_STATS_H
+#define _BITSET_STATS_H
+
+#include "bbitset.h"
+
+extern bool bitset_stats_enabled;
+
+extern enum bitset_type bitset_stats_type_get (bitset);
+
+extern size_t bitset_stats_bytes (void);
+
+extern bitset bitset_stats_init (bitset, bitset_bindex, enum bitset_type);
+
+#endif
diff --git a/lib/bitsetv-print.c b/lib/bitsetv-print.c
new file mode 100644
index 0000000..0083871
--- /dev/null
+++ b/lib/bitsetv-print.c
@@ -0,0 +1,71 @@
+/* Bitset vectors.
+   Copyright (C) 2001, 2002, 2004, 2006 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 2 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include "bitsetv-print.h"
+
+/*--------------------------------------------------------.
+| Display the MATRIX array of SIZE bitsets of size SIZE.  |
+`--------------------------------------------------------*/
+
+void
+bitsetv_matrix_dump (FILE * out, const char *title, bitsetv bset)
+{
+  bitset_bindex i, j;
+  bitset_bindex hsize = bitset_size (bset[0]);
+
+  /* Title. */
+  fprintf (out, "%s BEGIN\n", title);
+
+  /* Column numbers. */
+  fputs ("   ", out);
+  for (i = 0; i < hsize; ++i)
+    putc (i / 10 ? '0' + i / 10 : ' ', out);
+  putc ('\n', out);
+  fputs ("   ", out);
+  for (i = 0; i < hsize; ++i)
+    fprintf (out, "%d", (int) (i % 10));
+  putc ('\n', out);
+
+  /* Bar. */
+  fputs ("  .", out);
+  for (i = 0; i < hsize; ++i)
+    putc ('-', out);
+  fputs (".\n", out);
+
+  /* Contents. */
+  for (i = 0; bset[i]; ++i)
+    {
+      fprintf (out, "%2lu|", (unsigned long int) i);
+      for (j = 0; j < hsize; ++j)
+	fputs (bitset_test (bset[i], j) ? "1" : " ", out);
+      fputs ("|\n", out);
+    }
+
+  /* Bar. */
+  fputs ("  `", out);
+  for (i = 0; i < hsize; ++i)
+    putc ('-', out);
+  fputs ("'\n", out);
+
+  /* End title. */
+  fprintf (out, "%s END\n\n", title);
+}
diff --git a/lib/bitsetv-print.h b/lib/bitsetv-print.h
new file mode 100644
index 0000000..e54be68
--- /dev/null
+++ b/lib/bitsetv-print.h
@@ -0,0 +1,27 @@
+/* Bitset vectors.
+   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+   Contributed by Akim Demaille (akim@freefriends.org).
+
+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 2 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, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _BITSETV_PRINT_H
+#define _BITSETV_PRINT_H
+
+#include "bitsetv.h"
+
+/* Dump vector of bitsets as a matrix.  */
+extern void bitsetv_matrix_dump (FILE *, const char *, bitsetv);
+
+#endif  /* _BITSETV_H  */
diff --git a/lib/bitsetv.c b/lib/bitsetv.c
new file mode 100644
index 0000000..ae79853
--- /dev/null
+++ b/lib/bitsetv.c
@@ -0,0 +1,169 @@
+/* Bitset vectors.
+   Copyright (C) 2001, 2002, 2004, 2005, 2006 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 2 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include "bitsetv.h"
+
+
+/* Create a vector of N_VECS bitsets, each of N_BITS, and of
+   type TYPE.  */
+bitset *
+bitsetv_alloc (bitset_bindex n_vecs, bitset_bindex n_bits,
+	       enum bitset_type type)
+{
+  size_t vector_bytes;
+  size_t bytes;
+  bitset *bsetv;
+  bitset_bindex i;
+
+  /* Determine number of bytes for each set.  */
+  bytes = bitset_bytes (type, n_bits);
+
+  /* If size calculation overflows, memory is exhausted.  */
+  if (BITSET_SIZE_MAX / (sizeof (bitset) + bytes) <= n_vecs)
+    xalloc_die ();
+
+  /* Allocate vector table at head of bitset array.  */
+  vector_bytes = (n_vecs + 1) * sizeof (bitset) + bytes - 1;
+  vector_bytes -= vector_bytes % bytes;
+  bsetv = xcalloc (1, vector_bytes + bytes * n_vecs);
+
+  for (i = 0; i < n_vecs; i++)
+    {
+      bsetv[i] = (bitset) (void *) ((char *) bsetv + vector_bytes + i * bytes);
+
+      bitset_init (bsetv[i], n_bits, type);
+    }
+
+  /* Null terminate table.  */
+  bsetv[i] = 0;
+  return bsetv;
+}
+
+
+/* Create a vector of N_VECS bitsets, each of N_BITS, and with
+   attribute hints specified by ATTR.  */
+bitset *
+bitsetv_create (bitset_bindex n_vecs, bitset_bindex n_bits, unsigned int attr)
+{
+  enum bitset_type type;
+
+  type = bitset_type_choose (n_bits, attr);
+  return bitsetv_alloc (n_vecs, n_bits, type);
+}
+
+
+/* Free bitset vector BSETV.  */
+void
+bitsetv_free (bitsetv bsetv)
+{
+  bitset_bindex i;
+
+  for (i = 0; bsetv[i]; i++)
+      BITSET_FREE_ (bsetv[i]);
+  free (bsetv);
+}
+
+
+/* Zero a vector of bitsets.  */
+void
+bitsetv_zero (bitsetv bsetv)
+{
+  bitset_bindex i;
+
+  for (i = 0; bsetv[i]; i++)
+    bitset_zero (bsetv[i]);
+}
+
+
+/* Set a vector of bitsets to ones.  */
+void
+bitsetv_ones (bitsetv bsetv)
+{
+  bitset_bindex i;
+
+  for (i = 0; bsetv[i]; i++)
+    bitset_ones (bsetv[i]);
+}
+
+
+/* Given a vector BSETV of N bitsets of size N, modify its contents to
+   be the transitive closure of what was given.  */
+void
+bitsetv_transitive_closure (bitsetv bsetv)
+{
+  bitset_bindex i;
+  bitset_bindex j;
+
+  for (i = 0; bsetv[i]; i++)
+    for (j = 0; bsetv[j]; j++)
+      if (bitset_test (bsetv[j], i))
+	bitset_or (bsetv[j], bsetv[j], bsetv[i]);
+}
+
+
+/* Given a vector BSETV of N bitsets of size N, modify its contents to
+   be the reflexive transitive closure of what was given.  This is
+   the same as transitive closure but with all bits on the diagonal
+   of the bit matrix set.  */
+void
+bitsetv_reflexive_transitive_closure (bitsetv bsetv)
+{
+  bitset_bindex i;
+
+  bitsetv_transitive_closure (bsetv);
+  for (i = 0; bsetv[i]; i++)
+    bitset_set (bsetv[i], i);
+}
+
+
+/* Dump the contents of a bitset vector BSETV with N_VECS elements to
+   FILE.  */
+void
+bitsetv_dump (FILE *file, char const *title, char const *subtitle,
+	      bitsetv bsetv)
+{
+  bitset_windex i;
+
+  fprintf (file, "%s\n", title);
+  for (i = 0; bsetv[i]; i++)
+    {
+      fprintf (file, "%s %lu\n", subtitle, (unsigned long int) i);
+      bitset_dump (file, bsetv[i]);
+    }
+
+  fprintf (file, "\n");
+}
+
+
+void
+debug_bitsetv (bitsetv bsetv)
+{
+  bitset_windex i;
+
+  for (i = 0; bsetv[i]; i++)
+    {
+      fprintf (stderr, "%lu: ", (unsigned long int) i);
+      debug_bitset (bsetv[i]);
+    }
+
+  fprintf (stderr, "\n");
+}
diff --git a/lib/bitsetv.h b/lib/bitsetv.h
new file mode 100644
index 0000000..652f9e3
--- /dev/null
+++ b/lib/bitsetv.h
@@ -0,0 +1,59 @@
+/* Bitset vectors.
+   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+   Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
+
+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 2 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, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _BITSETV_H
+#define _BITSETV_H
+
+#include "bitset.h"
+
+typedef bitset * bitsetv;
+
+/* Create a vector of N_VECS bitsets, each of N_BITS, and of
+   type TYPE.  */
+extern bitsetv bitsetv_alloc (bitset_bindex, bitset_bindex, enum bitset_type);
+
+/* Create a vector of N_VECS bitsets, each of N_BITS, and with
+   attribute hints specified by ATTR.  */
+extern bitsetv bitsetv_create (bitset_bindex, bitset_bindex, unsigned int);
+
+/* Free vector of bitsets.  */
+extern void bitsetv_free (bitsetv);
+
+/* Zero vector of bitsets.  */
+extern void bitsetv_zero (bitsetv);
+
+/* Set vector of bitsets.  */
+extern void bitsetv_ones (bitsetv);
+
+/* Given a vector BSETV of N bitsets of size N, modify its contents to
+   be the transitive closure of what was given.  */
+extern void bitsetv_transitive_closure (bitsetv);
+
+/* Given a vector BSETV of N bitsets of size N, modify its contents to
+   be the reflexive transitive closure of what was given.  This is
+   the same as transitive closure but with all bits on the diagonal
+   of the bit matrix set.  */
+extern void bitsetv_reflexive_transitive_closure (bitsetv);
+
+/* Dump vector of bitsets.  */
+extern void bitsetv_dump (FILE *, const char *, const char *, bitsetv);
+
+/* Function to debug vector of bitsets from debugger.  */
+extern void debug_bitsetv (bitsetv);
+
+#endif  /* _BITSETV_H  */
diff --git a/lib/dirname.c b/lib/dirname.c
new file mode 100644
index 0000000..e2b9d64
--- /dev/null
+++ b/lib/dirname.c
@@ -0,0 +1,121 @@
+/* dirname.c -- return all but the last element in a file name
+
+   Copyright (C) 1990, 1998, 2000, 2001, 2003, 2004, 2005 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "dirname.h"
+
+#include <string.h>
+#include "xalloc.h"
+
+/* Return the length of `dirname (FILE)', or zero if FILE is
+   in the working directory.  Works properly even if
+   there are trailing slashes (by effectively ignoring them).  */
+size_t
+dir_len (char const *file)
+{
+  size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file);
+  size_t length;
+
+  /* Strip the basename and any redundant slashes before it.  */
+  for (length = base_name (file) - file;  prefix_length < length;  length--)
+    if (! ISSLASH (file[length - 1]))
+      return length;
+
+  /* But don't strip the only slash from "/".  */
+  return prefix_length + ISSLASH (file[prefix_length]);
+}
+
+/* Return the leading directories part of FILE,
+   allocated with xmalloc.
+   Works properly even if there are trailing slashes
+   (by effectively ignoring them).  */
+
+char *
+dir_name (char const *file)
+{
+  size_t length = dir_len (file);
+  bool append_dot = (length == FILE_SYSTEM_PREFIX_LEN (file));
+  char *dir = xmalloc (length + append_dot + 1);
+  memcpy (dir, file, length);
+  if (append_dot)
+    dir[length++] = '.';
+  dir[length] = 0;
+  return dir;
+}
+
+#ifdef TEST_DIRNAME
+/*
+
+Run the test like this (expect no output):
+  gcc -DHAVE_CONFIG_H -DTEST_DIRNAME -I.. -O -Wall \
+     basename.c dirname.c xmalloc.c error.c
+  sed -n '/^BEGIN-DATA$/,/^END-DATA$/p' dirname.c|grep -v DATA|./a.out
+
+If it's been built on a DOS or Windows platforms, run another test like
+this (again, expect no output):
+  sed -n '/^BEGIN-DOS-DATA$/,/^END-DOS-DATA$/p' dirname.c|grep -v DATA|./a.out
+
+BEGIN-DATA
+foo//// .
+bar/foo//// bar
+foo/ .
+/ /
+. .
+a .
+END-DATA
+
+BEGIN-DOS-DATA
+c:///// c:/
+c:/ c:/
+c:/. c:/
+c:foo c:.
+c:foo/bar c:foo
+END-DOS-DATA
+
+*/
+
+# define MAX_BUFF_LEN 1024
+# include <stdio.h>
+
+char *program_name;
+
+int
+main (int argc, char *argv[])
+{
+  char buff[MAX_BUFF_LEN + 1];
+
+  program_name = argv[0];
+
+  buff[MAX_BUFF_LEN] = 0;
+  while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
+    {
+      char file[MAX_BUFF_LEN];
+      char expected_result[MAX_BUFF_LEN];
+      char const *result;
+      sscanf (buff, "%s %s", file, expected_result);
+      result = dir_name (file);
+      if (strcmp (result, expected_result))
+	printf ("%s: got %s, expected %s\n", file, result, expected_result);
+    }
+  return 0;
+}
+#endif
diff --git a/lib/dirname.h b/lib/dirname.h
new file mode 100644
index 0000000..1688ae8
--- /dev/null
+++ b/lib/dirname.h
@@ -0,0 +1,47 @@
+/*  Take file names apart into directory and base names.
+
+    Copyright (C) 1998, 2001, 2003, 2004, 2005 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 2, 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, write to the Free Software Foundation,
+    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef DIRNAME_H_
+# define DIRNAME_H_ 1
+
+# include <stdbool.h>
+# include <stddef.h>
+
+# ifndef DIRECTORY_SEPARATOR
+#  define DIRECTORY_SEPARATOR '/'
+# endif
+
+# ifndef ISSLASH
+#  define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
+# endif
+
+# ifndef FILE_SYSTEM_PREFIX_LEN
+#  define FILE_SYSTEM_PREFIX_LEN(File_name) 0
+# endif
+
+# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
+# define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
+
+char *base_name (char const *file);
+char *dir_name (char const *file);
+size_t base_len (char const *file);
+size_t dir_len (char const *file);
+
+bool strip_trailing_slashes (char *file);
+
+#endif /* not DIRNAME_H_ */
diff --git a/lib/dup-safer.c b/lib/dup-safer.c
new file mode 100644
index 0000000..8cbee70
--- /dev/null
+++ b/lib/dup-safer.c
@@ -0,0 +1,46 @@
+/* Invoke dup, but avoid some glitches.
+   Copyright (C) 2001, 2004, 2005 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Paul Eggert.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "unistd-safer.h"
+
+#include <fcntl.h>
+
+#include <unistd.h>
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+
+/* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or
+   STDERR_FILENO.  */
+
+int
+dup_safer (int fd)
+{
+#ifdef F_DUPFD
+  return fcntl (fd, F_DUPFD, STDERR_FILENO + 1);
+#else
+  /* fd_safer calls us back, but eventually the recursion unwinds and
+     does the right thing.  */
+  return fd_safer (dup (fd));
+#endif
+}
diff --git a/lib/ebitset.c b/lib/ebitset.c
new file mode 100644
index 0000000..cedf0e2
--- /dev/null
+++ b/lib/ebitset.c
@@ -0,0 +1,1366 @@
+/* Functions to support expandable bitsets.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
+
+   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 2 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "ebitset.h"
+#include "obstack.h"
+#include <stdlib.h>
+#include <string.h>
+
+/* This file implements expandable bitsets.  These bitsets can be of
+   arbitrary length and are more efficient than arrays of bits for
+   large sparse sets.
+
+   Empty elements are represented by a NULL pointer in the table of
+   element pointers.  An alternative is to point to a special zero
+   element.  Similarly, we could represent an all 1's element with
+   another special ones element pointer.
+
+   Bitsets are commonly empty so we need to ensure that this special
+   case is fast.  A zero bitset is indicated when cdata is 0.  This is
+   conservative since cdata may be non zero and the bitset may still
+   be zero.
+
+   The bitset cache can be disabled either by setting cindex to
+   BITSET_WINDEX_MAX or by setting csize to 0.  Here
+   we use the former approach since cindex needs to be updated whenever
+   cdata is changed.
+*/
+
+
+/* Number of words to use for each element.  */
+#define EBITSET_ELT_WORDS 2
+
+/* Number of bits stored in each element.  */
+#define EBITSET_ELT_BITS \
+  ((unsigned int) (EBITSET_ELT_WORDS * BITSET_WORD_BITS))
+
+/* Ebitset element.  We use an array of bits.  */
+typedef struct ebitset_elt_struct
+{
+  union
+  {
+    bitset_word words[EBITSET_ELT_WORDS];	/* Bits that are set.  */
+    struct ebitset_elt_struct *next;
+  }
+  u;
+}
+ebitset_elt;
+
+
+typedef ebitset_elt *ebitset_elts;
+
+
+/* Number of elements to initially allocate.  */
+
+#ifndef EBITSET_INITIAL_SIZE
+#define EBITSET_INITIAL_SIZE 2
+#endif
+
+
+enum ebitset_find_mode
+  { EBITSET_FIND, EBITSET_CREATE, EBITSET_SUBST };
+
+static ebitset_elt ebitset_zero_elts[1]; /* Elements of all zero bits.  */
+
+/* Obstack to allocate bitset elements from.  */
+static struct obstack ebitset_obstack;
+static bool ebitset_obstack_init = false;
+static ebitset_elt *ebitset_free_list;	/* Free list of bitset elements.  */
+
+#define EBITSET_N_ELTS(N) (((N) + EBITSET_ELT_BITS - 1) / EBITSET_ELT_BITS)
+#define EBITSET_ELTS(BSET) ((BSET)->e.elts)
+#define EBITSET_SIZE(BSET) EBITSET_N_ELTS (BITSET_NBITS_ (BSET))
+#define EBITSET_ASIZE(BSET) ((BSET)->e.size)
+
+#define EBITSET_NEXT(ELT) ((ELT)->u.next)
+#define EBITSET_WORDS(ELT) ((ELT)->u.words)
+
+/* Disable bitset cache and mark BSET as being zero.  */
+#define EBITSET_ZERO_SET(BSET) ((BSET)->b.cindex = BITSET_WINDEX_MAX, \
+	(BSET)->b.cdata = 0)
+
+#define EBITSET_CACHE_DISABLE(BSET)  ((BSET)->b.cindex = BITSET_WINDEX_MAX)
+
+/* Disable bitset cache and mark BSET as being possibly non-zero.  */
+#define EBITSET_NONZERO_SET(BSET) \
+ (EBITSET_CACHE_DISABLE (BSET), (BSET)->b.cdata = (bitset_word *)~0)
+
+/* A conservative estimate of whether the bitset is zero.
+   This is non-zero only if we know for sure that the bitset is zero.  */
+#define EBITSET_ZERO_P(BSET) ((BSET)->b.cdata == 0)
+
+/* Enable cache to point to element with table index EINDEX.
+   The element must exist.  */
+#define EBITSET_CACHE_SET(BSET, EINDEX) \
+ ((BSET)->b.cindex = (EINDEX) * EBITSET_ELT_WORDS, \
+  (BSET)->b.cdata = EBITSET_WORDS (EBITSET_ELTS (BSET) [EINDEX]))
+
+#undef min
+#undef max
+#define min(a, b) ((a) > (b) ? (b) : (a))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+static bitset_bindex
+ebitset_resize (bitset src, bitset_bindex n_bits)
+{
+  bitset_windex oldsize;
+  bitset_windex newsize;
+
+  if (n_bits == BITSET_NBITS_ (src))
+    return n_bits;
+
+  oldsize = EBITSET_SIZE (src);
+  newsize = EBITSET_N_ELTS (n_bits);
+
+  if (oldsize < newsize)
+    {
+      bitset_windex size;
+
+      /* The bitset needs to grow.  If we already have enough memory
+	 allocated, then just zero what we need.  */
+      if (newsize > EBITSET_ASIZE (src))
+	{
+	  /* We need to allocate more memory.  When oldsize is
+	     non-zero this means that we are changing the size, so
+	     grow the bitset 25% larger than requested to reduce
+	     number of reallocations.  */
+
+	  if (oldsize == 0)
+	    size = newsize;
+	  else
+	    size = newsize + newsize / 4;
+
+	  EBITSET_ELTS (src)
+	    = realloc (EBITSET_ELTS (src), size * sizeof (ebitset_elt *));
+	  EBITSET_ASIZE (src) = size;
+	}
+
+      memset (EBITSET_ELTS (src) + oldsize, 0,
+	      (newsize - oldsize) * sizeof (ebitset_elt *));
+    }
+  else
+    {
+      /* The bitset needs to shrink.  There's no point deallocating
+	 the memory unless it is shrinking by a reasonable amount.  */
+      if ((oldsize - newsize) >= oldsize / 2)
+	{
+	  EBITSET_ELTS (src)
+	    = realloc (EBITSET_ELTS (src), newsize * sizeof (ebitset_elt *));
+	  EBITSET_ASIZE (src) = newsize;
+	}
+
+      /* Need to prune any excess bits.  FIXME.  */
+    }
+
+  BITSET_NBITS_ (src) = n_bits;
+  return n_bits;
+}
+
+
+/* Allocate a ebitset element.  The bits are not cleared.  */
+static inline ebitset_elt *
+ebitset_elt_alloc (void)
+{
+  ebitset_elt *elt;
+
+  if (ebitset_free_list != 0)
+    {
+      elt = ebitset_free_list;
+      ebitset_free_list = EBITSET_NEXT (elt);
+    }
+  else
+    {
+      if (!ebitset_obstack_init)
+	{
+	  ebitset_obstack_init = true;
+
+	  /* Let particular systems override the size of a chunk.  */
+
+#ifndef OBSTACK_CHUNK_SIZE
+#define OBSTACK_CHUNK_SIZE 0
+#endif
+
+	  /* Let them override the alloc and free routines too.  */
+
+#ifndef OBSTACK_CHUNK_ALLOC
+#define OBSTACK_CHUNK_ALLOC xmalloc
+#endif
+
+#ifndef OBSTACK_CHUNK_FREE
+#define OBSTACK_CHUNK_FREE free
+#endif
+
+#if ! defined __GNUC__ || __GNUC__ < 2
+#define __alignof__(type) 0
+#endif
+
+	  obstack_specify_allocation (&ebitset_obstack, OBSTACK_CHUNK_SIZE,
+				      __alignof__ (ebitset_elt),
+				      OBSTACK_CHUNK_ALLOC,
+				      OBSTACK_CHUNK_FREE);
+	}
+
+      /* Perhaps we should add a number of new elements to the free
+	 list.  */
+      elt = (ebitset_elt *) obstack_alloc (&ebitset_obstack,
+					   sizeof (ebitset_elt));
+    }
+
+  return elt;
+}
+
+
+/* Allocate a ebitset element.  The bits are cleared.  */
+static inline ebitset_elt *
+ebitset_elt_calloc (void)
+{
+  ebitset_elt *elt;
+
+  elt = ebitset_elt_alloc ();
+  memset (EBITSET_WORDS (elt), 0, sizeof (EBITSET_WORDS (elt)));
+  return elt;
+}
+
+
+static inline void
+ebitset_elt_free (ebitset_elt *elt)
+{
+  EBITSET_NEXT (elt) = ebitset_free_list;
+  ebitset_free_list = elt;
+}
+
+
+/* Remove element with index EINDEX from bitset BSET.  */
+static inline void
+ebitset_elt_remove (bitset bset, bitset_windex eindex)
+{
+  ebitset_elts *elts;
+  ebitset_elt *elt;
+
+  elts = EBITSET_ELTS (bset);
+
+  elt = elts[eindex];
+
+  elts[eindex] = 0;
+  ebitset_elt_free (elt);
+}
+
+
+/* Add ELT into elts at index EINDEX of bitset BSET.  */
+static inline void
+ebitset_elt_add (bitset bset, ebitset_elt *elt, bitset_windex eindex)
+{
+  ebitset_elts *elts;
+
+  elts = EBITSET_ELTS (bset);
+  /* Assume that the elts entry not allocated.  */
+  elts[eindex] = elt;
+}
+
+
+/* Are all bits in an element zero?  */
+static inline bool
+ebitset_elt_zero_p (ebitset_elt *elt)
+{
+  int i;
+
+  for (i = 0; i < EBITSET_ELT_WORDS; i++)
+    if (EBITSET_WORDS (elt)[i])
+      return false;
+
+  return true;
+}
+
+
+static ebitset_elt *
+ebitset_elt_find (bitset bset, bitset_bindex bindex,
+		  enum ebitset_find_mode mode)
+{
+  ebitset_elt *elt;
+  bitset_windex size;
+  bitset_windex eindex;
+  ebitset_elts *elts;
+
+  eindex = bindex / EBITSET_ELT_BITS;
+
+  elts = EBITSET_ELTS (bset);
+  size = EBITSET_SIZE (bset);
+
+  if (eindex < size)
+    {
+      if ((elt = elts[eindex]))
+	{
+	  if (EBITSET_WORDS (elt) == bset->b.cdata)
+	    return elt;
+
+	  EBITSET_CACHE_SET (bset, eindex);
+	  return elt;
+	}
+    }
+
+  /* The element could not be found.  */
+
+  switch (mode)
+    {
+    default:
+      abort ();
+
+    case EBITSET_FIND:
+      return 0;
+
+    case EBITSET_CREATE:
+      if (eindex >= size)
+	ebitset_resize (bset, bindex);
+
+      /* Create a new element.  */
+      elt = ebitset_elt_calloc ();
+      ebitset_elt_add (bset, elt, eindex);
+      EBITSET_CACHE_SET (bset, eindex);
+      return elt;
+
+    case EBITSET_SUBST:
+      return &ebitset_zero_elts[0];
+    }
+}
+
+
+/* Weed out the zero elements from the elts.  */
+static inline bitset_windex
+ebitset_weed (bitset bset)
+{
+  ebitset_elts *elts;
+  bitset_windex j;
+  bitset_windex count;
+
+  if (EBITSET_ZERO_P (bset))
+    return 0;
+
+  elts = EBITSET_ELTS (bset);
+  count = 0;
+  for (j = 0; j < EBITSET_SIZE (bset); j++)
+    {
+      ebitset_elt *elt = elts[j];
+
+      if (elt)
+	{
+	  if (ebitset_elt_zero_p (elt))
+	    {
+	      ebitset_elt_remove (bset, j);
+	      count++;
+	    }
+	}
+      else
+	count++;
+    }
+
+  count = j - count;
+  if (!count)
+    {
+      /* All the bits are zero.  We could shrink the elts.
+	 For now just mark BSET as known to be zero.  */
+      EBITSET_ZERO_SET (bset);
+    }
+  else
+    EBITSET_NONZERO_SET (bset);
+
+  return count;
+}
+
+
+/* Set all bits in the bitset to zero.  */
+static inline void
+ebitset_zero (bitset bset)
+{
+  ebitset_elts *elts;
+  bitset_windex j;
+
+  if (EBITSET_ZERO_P (bset))
+    return;
+
+  elts = EBITSET_ELTS (bset);
+  for (j = 0; j < EBITSET_SIZE (bset); j++)
+    {
+      ebitset_elt *elt = elts[j];
+
+      if (elt)
+	ebitset_elt_remove (bset, j);
+    }
+
+  /* All the bits are zero.  We could shrink the elts.
+     For now just mark BSET as known to be zero.  */
+  EBITSET_ZERO_SET (bset);
+}
+
+
+static inline bool
+ebitset_equal_p (bitset dst, bitset src)
+{
+  ebitset_elts *selts;
+  ebitset_elts *delts;
+  bitset_windex j;
+
+  if (src == dst)
+    return true;
+
+  ebitset_weed (dst);
+  ebitset_weed (src);
+
+  if (EBITSET_SIZE (src) != EBITSET_SIZE (dst))
+    return false;
+
+  selts = EBITSET_ELTS (src);
+  delts = EBITSET_ELTS (dst);
+
+  for (j = 0; j < EBITSET_SIZE (src); j++)
+    {
+      unsigned int i;
+      ebitset_elt *selt = selts[j];
+      ebitset_elt *delt = delts[j];
+
+      if (!selt && !delt)
+	continue;
+      if ((selt && !delt) || (!selt && delt))
+	return false;
+
+      for (i = 0; i < EBITSET_ELT_WORDS; i++)
+	if (EBITSET_WORDS (selt)[i] != EBITSET_WORDS (delt)[i])
+	  return false;
+    }
+  return true;
+}
+
+
+/* Copy bits from bitset SRC to bitset DST.  */
+static inline void
+ebitset_copy_ (bitset dst, bitset src)
+{
+  ebitset_elts *selts;
+  ebitset_elts *delts;
+  bitset_windex j;
+
+  if (src == dst)
+    return;
+
+  ebitset_zero (dst);
+
+  if (BITSET_NBITS_ (dst) != BITSET_NBITS_ (src))
+    ebitset_resize (dst, BITSET_NBITS_ (src));
+
+  selts = EBITSET_ELTS (src);
+  delts = EBITSET_ELTS (dst);
+  for (j = 0; j < EBITSET_SIZE (src); j++)
+    {
+      ebitset_elt *selt = selts[j];
+
+      if (selt)
+	{
+	  ebitset_elt *tmp;
+
+	  tmp = ebitset_elt_alloc ();
+	  delts[j] = tmp;
+	  memcpy (EBITSET_WORDS (tmp), EBITSET_WORDS (selt),
+		  sizeof (EBITSET_WORDS (selt)));
+	}
+    }
+  EBITSET_NONZERO_SET (dst);
+}
+
+
+/* Copy bits from bitset SRC to bitset DST.  Return true if
+   bitsets different.  */
+static inline bool
+ebitset_copy_cmp (bitset dst, bitset src)
+{
+  if (src == dst)
+    return false;
+
+  if (EBITSET_ZERO_P (dst))
+    {
+      ebitset_copy_ (dst, src);
+      return !EBITSET_ZERO_P (src);
+    }
+
+  if (ebitset_equal_p (dst, src))
+    return false;
+
+  ebitset_copy_ (dst, src);
+  return true;
+}
+
+
+/* Set bit BITNO in bitset DST.  */
+static void
+ebitset_set (bitset dst, bitset_bindex bitno)
+{
+  bitset_windex windex = bitno / BITSET_WORD_BITS;
+
+  ebitset_elt_find (dst, bitno, EBITSET_CREATE);
+
+  dst->b.cdata[windex - dst->b.cindex] |=
+    (bitset_word) 1 << (bitno % BITSET_WORD_BITS);
+}
+
+
+/* Reset bit BITNO in bitset DST.  */
+static void
+ebitset_reset (bitset dst, bitset_bindex bitno)
+{
+  bitset_windex windex = bitno / BITSET_WORD_BITS;
+
+  if (!ebitset_elt_find (dst, bitno, EBITSET_FIND))
+    return;
+
+  dst->b.cdata[windex - dst->b.cindex] &=
+    ~((bitset_word) 1 << (bitno % BITSET_WORD_BITS));
+
+  /* If all the data is zero, perhaps we should remove it now...
+     However, there is a good chance that the element will be needed
+     again soon.  */
+}
+
+
+/* Test bit BITNO in bitset SRC.  */
+static bool
+ebitset_test (bitset src, bitset_bindex bitno)
+{
+  bitset_windex windex = bitno / BITSET_WORD_BITS;
+
+  return (ebitset_elt_find (src, bitno, EBITSET_FIND)
+	  && ((src->b.cdata[windex - src->b.cindex]
+	       >> (bitno % BITSET_WORD_BITS))
+	      & 1));
+}
+
+
+static void
+ebitset_free (bitset bset)
+{
+  ebitset_zero (bset);
+  free (EBITSET_ELTS (bset));
+}
+
+
+/* Find list of up to NUM bits set in BSET starting from and including
+ *NEXT and store in array LIST.  Return with actual number of bits
+ found and with *NEXT indicating where search stopped.  */
+static bitset_bindex
+ebitset_list_reverse (bitset bset, bitset_bindex *list,
+		      bitset_bindex num, bitset_bindex *next)
+{
+  bitset_bindex n_bits;
+  bitset_bindex bitno;
+  bitset_bindex rbitno;
+  unsigned int bcount;
+  bitset_bindex boffset;
+  bitset_windex windex;
+  bitset_windex eindex;
+  bitset_windex woffset;
+  bitset_bindex count;
+  bitset_windex size;
+  ebitset_elts *elts;
+
+  if (EBITSET_ZERO_P (bset))
+    return 0;
+
+  size = EBITSET_SIZE (bset);
+  n_bits = size * EBITSET_ELT_BITS;
+  rbitno = *next;
+
+  if (rbitno >= n_bits)
+    return 0;
+
+  elts = EBITSET_ELTS (bset);
+
+  bitno = n_bits - (rbitno + 1);
+
+  windex = bitno / BITSET_WORD_BITS;
+  eindex = bitno / EBITSET_ELT_BITS;
+  woffset = windex - eindex * EBITSET_ELT_WORDS;
+
+  /* If num is 1, we could speed things up with a binary search
+     of the word of interest.  */
+
+  count = 0;
+  bcount = bitno % BITSET_WORD_BITS;
+  boffset = windex * BITSET_WORD_BITS;
+
+  do
+    {
+      ebitset_elt *elt;
+      bitset_word *srcp;
+
+      elt = elts[eindex];
+      if (elt)
+	{
+	  srcp = EBITSET_WORDS (elt);
+
+	  do
+	    {
+	      bitset_word word;
+
+	      word = srcp[woffset] << (BITSET_WORD_BITS - 1 - bcount);
+
+	      for (; word; bcount--)
+		{
+		  if (word & BITSET_MSB)
+		    {
+		      list[count++] = boffset + bcount;
+		      if (count >= num)
+			{
+			  *next = n_bits - (boffset + bcount);
+			  return count;
+			}
+		    }
+		  word <<= 1;
+		}
+	      boffset -= BITSET_WORD_BITS;
+	      bcount = BITSET_WORD_BITS - 1;
+	    }
+	  while (woffset--);
+	}
+
+      woffset = EBITSET_ELT_WORDS - 1;
+      boffset = eindex * EBITSET_ELT_BITS - BITSET_WORD_BITS;
+    }
+  while (eindex--);
+
+  *next = n_bits - (boffset + 1);
+  return count;
+}
+
+
+/* Find list of up to NUM bits set in BSET starting from and including
+ *NEXT and store in array LIST.  Return with actual number of bits
+ found and with *NEXT indicating where search stopped.  */
+static bitset_bindex
+ebitset_list (bitset bset, bitset_bindex *list,
+	      bitset_bindex num, bitset_bindex *next)
+{
+  bitset_bindex bitno;
+  bitset_windex windex;
+  bitset_windex eindex;
+  bitset_bindex count;
+  bitset_windex size;
+  ebitset_elt *elt;
+  bitset_word word;
+  ebitset_elts *elts;
+
+  if (EBITSET_ZERO_P (bset))
+    return 0;
+
+  bitno = *next;
+  count = 0;
+
+  elts = EBITSET_ELTS (bset);
+  size = EBITSET_SIZE (bset);
+  eindex = bitno / EBITSET_ELT_BITS;
+
+  if (bitno % EBITSET_ELT_BITS)
+    {
+      /* We need to start within an element.  This is not very common.  */
+
+      elt = elts[eindex];
+      if (elt)
+	{
+	  bitset_windex woffset;
+	  bitset_word *srcp = EBITSET_WORDS (elt);
+
+	  windex = bitno / BITSET_WORD_BITS;
+	  woffset = eindex * EBITSET_ELT_WORDS;
+
+	  for (; (windex - woffset) < EBITSET_ELT_WORDS; windex++)
+	    {
+	      word = srcp[windex - woffset] >> (bitno % BITSET_WORD_BITS);
+
+	      for (; word; bitno++)
+		{
+		  if (word & 1)
+		    {
+		      list[count++] = bitno;
+		      if (count >= num)
+			{
+			  *next = bitno + 1;
+			  return count;
+			}
+		    }
+		  word >>= 1;
+		}
+	      bitno = (windex + 1) * BITSET_WORD_BITS;
+	    }
+	}
+
+      /* Skip to next element.  */
+      eindex++;
+    }
+
+  /* If num is 1, we could speed things up with a binary search
+     of the word of interest.  */
+
+  for (; eindex < size; eindex++)
+    {
+      int i;
+      bitset_word *srcp;
+
+      elt = elts[eindex];
+      if (!elt)
+	continue;
+
+      srcp = EBITSET_WORDS (elt);
+      windex = eindex * EBITSET_ELT_WORDS;
+
+      if ((count + EBITSET_ELT_BITS) < num)
+	{
+	  /* The coast is clear, plant boot!  */
+
+#if EBITSET_ELT_WORDS == 2
+	  word = srcp[0];
+	  if (word)
+	    {
+	      if (!(word & 0xffff))
+		{
+		  word >>= 16;
+		  bitno += 16;
+		}
+	      if (!(word & 0xff))
+		{
+		  word >>= 8;
+		  bitno += 8;
+		}
+	      for (; word; bitno++)
+		{
+		  if (word & 1)
+		    list[count++] = bitno;
+		  word >>= 1;
+		}
+	    }
+	  windex++;
+	  bitno = windex * BITSET_WORD_BITS;
+
+	  word = srcp[1];
+	  if (word)
+	    {
+	      if (!(word & 0xffff))
+		{
+		  word >>= 16;
+		  bitno += 16;
+		}
+	      for (; word; bitno++)
+		{
+		  if (word & 1)
+		    list[count++] = bitno;
+		  word >>= 1;
+		}
+	    }
+	  windex++;
+	  bitno = windex * BITSET_WORD_BITS;
+#else
+	  for (i = 0; i < EBITSET_ELT_WORDS; i++, windex++)
+	    {
+	      bitno = windex * BITSET_WORD_BITS;
+
+	      word = srcp[i];
+	      if (word)
+		{
+		  if (!(word & 0xffff))
+		    {
+		      word >>= 16;
+		      bitno += 16;
+		    }
+		  if (!(word & 0xff))
+		    {
+		      word >>= 8;
+		      bitno += 8;
+		    }
+		  for (; word; bitno++)
+		    {
+		      if (word & 1)
+			list[count++] = bitno;
+		      word >>= 1;
+		    }
+		}
+	    }
+#endif
+	}
+      else
+	{
+	  /* Tread more carefully since we need to check
+	     if array overflows.  */
+
+	  for (i = 0; i < EBITSET_ELT_WORDS; i++, windex++)
+	    {
+	      bitno = windex * BITSET_WORD_BITS;
+
+	      for (word = srcp[i]; word; bitno++)
+		{
+		  if (word & 1)
+		    {
+		      list[count++] = bitno;
+		      if (count >= num)
+			{
+			  *next = bitno + 1;
+			  return count;
+			}
+		    }
+		  word >>= 1;
+		}
+	    }
+	}
+    }
+
+  *next = bitno;
+  return count;
+}
+
+
+/* Ensure that any unused bits within the last element are clear.  */
+static inline void
+ebitset_unused_clear (bitset dst)
+{
+  unsigned int last_bit;
+  bitset_bindex n_bits;
+
+  n_bits = BITSET_NBITS_ (dst);
+  last_bit = n_bits % EBITSET_ELT_BITS;
+
+  if (last_bit)
+    {
+      bitset_windex eindex;
+      ebitset_elts *elts;
+      ebitset_elt *elt;
+
+      elts = EBITSET_ELTS (dst);
+
+      eindex = n_bits / EBITSET_ELT_BITS;
+
+      elt = elts[eindex];
+      if (elt)
+	{
+	  bitset_windex windex;
+	  bitset_windex woffset;
+	  bitset_word *srcp = EBITSET_WORDS (elt);
+
+	  windex = n_bits / BITSET_WORD_BITS;
+	  woffset = eindex * EBITSET_ELT_WORDS;
+
+	  srcp[windex - woffset] &= ((bitset_word) 1 << last_bit) - 1;
+	  windex++;
+	  for (; (windex - woffset) < EBITSET_ELT_WORDS; windex++)
+	    srcp[windex - woffset] = 0;
+	}
+    }
+}
+
+
+static void
+ebitset_ones (bitset dst)
+{
+  bitset_windex j;
+  ebitset_elt *elt;
+
+  for (j = 0; j < EBITSET_SIZE (dst); j++)
+    {
+      /* Create new elements if they cannot be found.  Perhaps
+	 we should just add pointers to a ones element?  */
+      elt =
+	ebitset_elt_find (dst, j * EBITSET_ELT_BITS, EBITSET_CREATE);
+      memset (EBITSET_WORDS (elt), -1, sizeof (EBITSET_WORDS (elt)));
+    }
+  EBITSET_NONZERO_SET (dst);
+  ebitset_unused_clear (dst);
+}
+
+
+static bool
+ebitset_empty_p (bitset dst)
+{
+  ebitset_elts *elts;
+  bitset_windex j;
+
+  if (EBITSET_ZERO_P (dst))
+    return 1;
+
+  elts = EBITSET_ELTS (dst);
+  for (j = 0; j < EBITSET_SIZE (dst); j++)
+    {
+      ebitset_elt *elt = elts[j];
+
+      if (elt)
+	{
+	  if (!ebitset_elt_zero_p (elt))
+	    return 0;
+	  /* Do some weeding as we go.  */
+	  ebitset_elt_remove (dst, j);
+	}
+    }
+
+  /* All the bits are zero.  We could shrink the elts.
+     For now just mark DST as known to be zero.  */
+  EBITSET_ZERO_SET (dst);
+  return 1;
+}
+
+
+static void
+ebitset_not (bitset dst, bitset src)
+{
+  unsigned int i;
+  ebitset_elt *selt;
+  ebitset_elt *delt;
+  bitset_windex j;
+
+  ebitset_resize (dst, BITSET_NBITS_ (src));
+
+  for (j = 0; j < EBITSET_SIZE (src); j++)
+    {
+      /* Create new elements for dst if they cannot be found
+	 or substitute zero elements if src elements not found.  */
+      selt =
+	ebitset_elt_find (dst, j * EBITSET_ELT_BITS, EBITSET_SUBST);
+      delt =
+	ebitset_elt_find (dst, j * EBITSET_ELT_BITS, EBITSET_CREATE);
+
+      for (i = 0; i < EBITSET_ELT_WORDS; i++)
+	EBITSET_WORDS (delt)[i] = ~EBITSET_WORDS (selt)[i];
+    }
+  EBITSET_NONZERO_SET (dst);
+  ebitset_unused_clear (dst);
+}
+
+
+/* Is DST == DST | SRC?  */
+static bool
+ebitset_subset_p (bitset dst, bitset src)
+{
+  bitset_windex j;
+  ebitset_elts *selts;
+  ebitset_elts *delts;
+  bitset_windex ssize;
+  bitset_windex dsize;
+
+  selts = EBITSET_ELTS (src);
+  delts = EBITSET_ELTS (dst);
+
+  ssize = EBITSET_SIZE (src);
+  dsize = EBITSET_SIZE (dst);
+
+  for (j = 0; j < ssize; j++)
+    {
+      unsigned int i;
+      ebitset_elt *selt;
+      ebitset_elt *delt;
+
+      selt = j < ssize ? selts[j] : 0;
+      delt = j < dsize ? delts[j] : 0;
+
+      if (!selt && !delt)
+	continue;
+
+      if (!selt)
+	selt = &ebitset_zero_elts[0];
+      if (!delt)
+	delt = &ebitset_zero_elts[0];
+
+      for (i = 0; i < EBITSET_ELT_WORDS; i++)
+	if (EBITSET_WORDS (delt)[i]
+	    != (EBITSET_WORDS (selt)[i] | EBITSET_WORDS (delt)[i]))
+	  return false;
+    }
+  return true;
+}
+
+
+/* Is DST & SRC == 0?  */
+static bool
+ebitset_disjoint_p (bitset dst, bitset src)
+{
+  bitset_windex j;
+  ebitset_elts *selts;
+  ebitset_elts *delts;
+  bitset_windex ssize;
+  bitset_windex dsize;
+
+  selts = EBITSET_ELTS (src);
+  delts = EBITSET_ELTS (dst);
+
+  ssize = EBITSET_SIZE (src);
+  dsize = EBITSET_SIZE (dst);
+
+  for (j = 0; j < ssize; j++)
+    {
+      unsigned int i;
+      ebitset_elt *selt;
+      ebitset_elt *delt;
+
+      selt = j < ssize ? selts[j] : 0;
+      delt = j < dsize ? delts[j] : 0;
+
+      if (!selt || !delt)
+	continue;
+
+      for (i = 0; i < EBITSET_ELT_WORDS; i++)
+	if ((EBITSET_WORDS (selt)[i] & EBITSET_WORDS (delt)[i]))
+	  return false;
+    }
+  return true;
+}
+
+
+
+static bool
+ebitset_op3_cmp (bitset dst, bitset src1, bitset src2, enum bitset_ops op)
+{
+  bitset_windex ssize1;
+  bitset_windex ssize2;
+  bitset_windex dsize;
+  bitset_windex size;
+  ebitset_elts *selts1;
+  ebitset_elts *selts2;
+  ebitset_elts *delts;
+  bitset_word *srcp1;
+  bitset_word *srcp2;
+  bitset_word *dstp;
+  bool changed = false;
+  unsigned int i;
+  bitset_windex j;
+
+  ebitset_resize (dst, max (BITSET_NBITS_ (src1), BITSET_NBITS_ (src2)));
+
+  ssize1 = EBITSET_SIZE (src1);
+  ssize2 = EBITSET_SIZE (src2);
+  dsize = EBITSET_SIZE (dst);
+  size = ssize1;
+  if (size < ssize2)
+    size = ssize2;
+
+  selts1 = EBITSET_ELTS (src1);
+  selts2 = EBITSET_ELTS (src2);
+  delts = EBITSET_ELTS (dst);
+
+  for (j = 0; j < size; j++)
+    {
+      ebitset_elt *selt1;
+      ebitset_elt *selt2;
+      ebitset_elt *delt;
+
+      selt1 = j < ssize1 ? selts1[j] : 0;
+      selt2 = j < ssize2 ? selts2[j] : 0;
+      delt = j < dsize ? delts[j] : 0;
+
+      if (!selt1 && !selt2)
+	{
+	  if (delt)
+	    {
+	      changed = true;
+	      ebitset_elt_remove (dst, j);
+	    }
+	  continue;
+	}
+
+      if (!selt1)
+	selt1 = &ebitset_zero_elts[0];
+      if (!selt2)
+	selt2 = &ebitset_zero_elts[0];
+      if (!delt)
+	delt = ebitset_elt_calloc ();
+      else
+	delts[j] = 0;
+
+      srcp1 = EBITSET_WORDS (selt1);
+      srcp2 = EBITSET_WORDS (selt2);
+      dstp = EBITSET_WORDS (delt);
+      switch (op)
+	{
+	default:
+	  abort ();
+
+	case BITSET_OP_OR:
+	  for (i = 0; i < EBITSET_ELT_WORDS; i++, dstp++)
+	    {
+	      bitset_word tmp = *srcp1++ | *srcp2++;
+
+	      if (*dstp != tmp)
+		{
+		  changed = true;
+		  *dstp = tmp;
+		}
+	    }
+	  break;
+
+	case BITSET_OP_AND:
+	  for (i = 0; i < EBITSET_ELT_WORDS; i++, dstp++)
+	    {
+	      bitset_word tmp = *srcp1++ & *srcp2++;
+
+	      if (*dstp != tmp)
+		{
+		  changed = true;
+		  *dstp = tmp;
+		}
+	    }
+	  break;
+
+	case BITSET_OP_XOR:
+	  for (i = 0; i < EBITSET_ELT_WORDS; i++, dstp++)
+	    {
+	      bitset_word tmp = *srcp1++ ^ *srcp2++;
+
+	      if (*dstp != tmp)
+		{
+		  changed = true;
+		  *dstp = tmp;
+		}
+	    }
+	  break;
+
+	case BITSET_OP_ANDN:
+	  for (i = 0; i < EBITSET_ELT_WORDS; i++, dstp++)
+	    {
+	      bitset_word tmp = *srcp1++ & ~(*srcp2++);
+
+	      if (*dstp != tmp)
+		{
+		  changed = true;
+		  *dstp = tmp;
+		}
+	    }
+	  break;
+	}
+
+      if (!ebitset_elt_zero_p (delt))
+	{
+	  ebitset_elt_add (dst, delt, j);
+	}
+      else
+	{
+	  ebitset_elt_free (delt);
+	}
+    }
+
+  /* If we have elements of DST left over, free them all.  */
+  for (; j < dsize; j++)
+    {
+      ebitset_elt *delt;
+
+      changed = true;
+
+      delt = delts[j];
+
+      if (delt)
+	ebitset_elt_remove (dst, j);
+    }
+
+  EBITSET_NONZERO_SET (dst);
+  return changed;
+}
+
+
+static bool
+ebitset_and_cmp (bitset dst, bitset src1, bitset src2)
+{
+  bool changed;
+
+  if (EBITSET_ZERO_P (src2))
+    {
+      ebitset_weed (dst);
+      changed = EBITSET_ZERO_P (dst);
+      ebitset_zero (dst);
+      return changed;
+    }
+  else if (EBITSET_ZERO_P (src1))
+    {
+      ebitset_weed (dst);
+      changed = EBITSET_ZERO_P (dst);
+      ebitset_zero (dst);
+      return changed;
+    }
+  return ebitset_op3_cmp (dst, src1, src2, BITSET_OP_AND);
+}
+
+
+static void
+ebitset_and (bitset dst, bitset src1, bitset src2)
+{
+  ebitset_and_cmp (dst, src1, src2);
+}
+
+
+static bool
+ebitset_andn_cmp (bitset dst, bitset src1, bitset src2)
+{
+  bool changed;
+
+  if (EBITSET_ZERO_P (src2))
+    {
+      return ebitset_copy_cmp (dst, src1);
+    }
+  else if (EBITSET_ZERO_P (src1))
+    {
+      ebitset_weed (dst);
+      changed = EBITSET_ZERO_P (dst);
+      ebitset_zero (dst);
+      return changed;
+    }
+  return ebitset_op3_cmp (dst, src1, src2, BITSET_OP_ANDN);
+}
+
+
+static void
+ebitset_andn (bitset dst, bitset src1, bitset src2)
+{
+  ebitset_andn_cmp (dst, src1, src2);
+}
+
+
+static bool
+ebitset_or_cmp (bitset dst, bitset src1, bitset src2)
+{
+  if (EBITSET_ZERO_P (src2))
+    {
+      return ebitset_copy_cmp (dst, src1);
+    }
+  else if (EBITSET_ZERO_P (src1))
+    {
+      return ebitset_copy_cmp (dst, src2);
+    }
+  return ebitset_op3_cmp (dst, src1, src2, BITSET_OP_OR);
+}
+
+
+static void
+ebitset_or (bitset dst, bitset src1, bitset src2)
+{
+  ebitset_or_cmp (dst, src1, src2);
+}
+
+
+static bool
+ebitset_xor_cmp (bitset dst, bitset src1, bitset src2)
+{
+  if (EBITSET_ZERO_P (src2))
+    {
+      return ebitset_copy_cmp (dst, src1);
+    }
+  else if (EBITSET_ZERO_P (src1))
+    {
+      return ebitset_copy_cmp (dst, src2);
+    }
+  return ebitset_op3_cmp (dst, src1, src2, BITSET_OP_XOR);
+}
+
+
+static void
+ebitset_xor (bitset dst, bitset src1, bitset src2)
+{
+  ebitset_xor_cmp (dst, src1, src2);
+}
+
+
+static void
+ebitset_copy (bitset dst, bitset src)
+{
+  if (BITSET_COMPATIBLE_ (dst, src))
+      ebitset_copy_ (dst, src);
+  else
+      bitset_copy_ (dst, src);
+}
+
+
+/* Vector of operations for linked-list bitsets.  */
+struct bitset_vtable ebitset_vtable = {
+  ebitset_set,
+  ebitset_reset,
+  bitset_toggle_,
+  ebitset_test,
+  ebitset_resize,
+  bitset_size_,
+  bitset_count_,
+  ebitset_empty_p,
+  ebitset_ones,
+  ebitset_zero,
+  ebitset_copy,
+  ebitset_disjoint_p,
+  ebitset_equal_p,
+  ebitset_not,
+  ebitset_subset_p,
+  ebitset_and,
+  ebitset_and_cmp,
+  ebitset_andn,
+  ebitset_andn_cmp,
+  ebitset_or,
+  ebitset_or_cmp,
+  ebitset_xor,
+  ebitset_xor_cmp,
+  bitset_and_or_,
+  bitset_and_or_cmp_,
+  bitset_andn_or_,
+  bitset_andn_or_cmp_,
+  bitset_or_and_,
+  bitset_or_and_cmp_,
+  ebitset_list,
+  ebitset_list_reverse,
+  ebitset_free,
+  BITSET_TABLE
+};
+
+
+/* Return size of initial structure.  */
+size_t
+ebitset_bytes (bitset_bindex n_bits ATTRIBUTE_UNUSED)
+{
+  return sizeof (struct ebitset_struct);
+}
+
+
+/* Initialize a bitset.  */
+
+bitset
+ebitset_init (bitset bset, bitset_bindex n_bits)
+{
+  bitset_windex size;
+
+  bset->b.vtable = &ebitset_vtable;
+
+  bset->b.csize = EBITSET_ELT_WORDS;
+
+  EBITSET_ZERO_SET (bset);
+
+  size = n_bits ? (n_bits + EBITSET_ELT_BITS - 1) / EBITSET_ELT_BITS
+    : EBITSET_INITIAL_SIZE;
+
+  EBITSET_ASIZE (bset) = 0;
+  EBITSET_ELTS (bset) = 0;
+  ebitset_resize (bset, n_bits);
+
+  return bset;
+}
+
+
+void
+ebitset_release_memory (void)
+{
+  ebitset_free_list = 0;
+  if (ebitset_obstack_init)
+    {
+      ebitset_obstack_init = false;
+      obstack_free (&ebitset_obstack, NULL);
+    }
+}
diff --git a/lib/ebitset.h b/lib/ebitset.h
new file mode 100644
index 0000000..dc60273
--- /dev/null
+++ b/lib/ebitset.h
@@ -0,0 +1,30 @@
+/* Functions to support ebitsets.
+   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+   Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
+
+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 2 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, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _EBITSET_H
+#define _EBITSET_H
+
+#include "bitset.h"
+
+extern size_t ebitset_bytes (bitset_bindex);
+
+extern bitset ebitset_init (bitset, bitset_bindex);
+
+extern void ebitset_release_memory (void);
+
+#endif
diff --git a/lib/error.c b/lib/error.c
new file mode 100644
index 0000000..45698be
--- /dev/null
+++ b/lib/error.c
@@ -0,0 +1,304 @@
+/* Error handler for noninteractive utilities
+   Copyright (C) 1990-1998, 2000-2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by David MacKenzie <djm@gnu.ai.mit.edu>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "error.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if !_LIBC && ENABLE_NLS
+# include "gettext.h"
+#endif
+
+#ifdef _LIBC
+# include <wchar.h>
+# define mbsrtowcs __mbsrtowcs
+#endif
+
+#if USE_UNLOCKED_IO
+# include "unlocked-io.h"
+#endif
+
+#ifndef _
+# define _(String) String
+#endif
+
+/* If NULL, error will flush stdout, then print on stderr the program
+   name, a colon and a space.  Otherwise, error will call this
+   function without parameters instead.  */
+void (*error_print_progname) (void);
+
+/* This variable is incremented each time `error' is called.  */
+unsigned int error_message_count;
+
+#ifdef _LIBC
+/* In the GNU C library, there is a predefined variable for this.  */
+
+# define program_name program_invocation_name
+# include <errno.h>
+# include <libio/libioP.h>
+
+/* In GNU libc we want do not want to use the common name `error' directly.
+   Instead make it a weak alias.  */
+extern void __error (int status, int errnum, const char *message, ...)
+     __attribute__ ((__format__ (__printf__, 3, 4)));
+extern void __error_at_line (int status, int errnum, const char *file_name,
+			     unsigned int line_number, const char *message,
+			     ...)
+     __attribute__ ((__format__ (__printf__, 5, 6)));;
+# define error __error
+# define error_at_line __error_at_line
+
+# include <libio/iolibio.h>
+# define fflush(s) INTUSE(_IO_fflush) (s)
+# undef putc
+# define putc(c, fp) INTUSE(_IO_putc) (c, fp)
+
+# include <bits/libc-lock.h>
+
+#else /* not _LIBC */
+
+# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
+#  ifndef HAVE_DECL_STRERROR_R
+"this configure-time declaration test was not run"
+#  endif
+char *strerror_r ();
+# endif
+
+# ifndef SIZE_MAX
+#  define SIZE_MAX ((size_t) -1)
+# endif
+
+/* The calling program should define program_name and set it to the
+   name of the executing program.  */
+extern char *program_name;
+
+# if HAVE_STRERROR_R || defined strerror_r
+#  define __strerror_r strerror_r
+# endif
+#endif	/* not _LIBC */
+
+static void
+print_errno_message (int errnum)
+{
+  char const *s = NULL;
+
+#if defined HAVE_STRERROR_R || _LIBC
+  char errbuf[1024];
+# if STRERROR_R_CHAR_P || _LIBC
+  s = __strerror_r (errnum, errbuf, sizeof errbuf);
+# else
+  if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
+    s = errbuf;
+# endif
+#endif
+
+#if !_LIBC
+  if (! s && ! (s = strerror (errnum)))
+    s = _("Unknown system error");
+#endif
+
+#if _LIBC
+  if (_IO_fwide (stderr, 0) > 0)
+    {
+      __fwprintf (stderr, L": %s", s);
+      return;
+    }
+#endif
+
+  fprintf (stderr, ": %s", s);
+}
+
+static void
+error_tail (int status, int errnum, const char *message, va_list args)
+{
+#if _LIBC
+  if (_IO_fwide (stderr, 0) > 0)
+    {
+# define ALLOCA_LIMIT 2000
+      size_t len = strlen (message) + 1;
+      const wchar_t *wmessage = L"out of memory";
+      wchar_t *wbuf = (len < ALLOCA_LIMIT
+		       ? alloca (len * sizeof *wbuf)
+		       : len <= SIZE_MAX / sizeof *wbuf
+		       ? malloc (len * sizeof *wbuf)
+		       : NULL);
+
+      if (wbuf)
+	{
+	  size_t res;
+	  mbstate_t st;
+	  const char *tmp = message;
+	  memset (&st, '\0', sizeof (st));
+	  res = mbsrtowcs (wbuf, &tmp, len, &st);
+	  wmessage = res == (size_t) -1 ? L"???" : wbuf;
+	}
+
+      __vfwprintf (stderr, wmessage, args);
+      if (! (len < ALLOCA_LIMIT))
+	free (wbuf);
+    }
+  else
+#endif
+    vfprintf (stderr, message, args);
+  va_end (args);
+
+  ++error_message_count;
+  if (errnum)
+    print_errno_message (errnum);
+#if _LIBC
+  if (_IO_fwide (stderr, 0) > 0)
+    putwc (L'\n', stderr);
+  else
+#endif
+    putc ('\n', stderr);
+  fflush (stderr);
+  if (status)
+    exit (status);
+}
+
+
+/* Print the program name and error message MESSAGE, which is a printf-style
+   format string with optional args.
+   If ERRNUM is nonzero, print its corresponding system error message.
+   Exit with status STATUS if it is nonzero.  */
+void
+error (int status, int errnum, const char *message, ...)
+{
+  va_list args;
+
+#if defined _LIBC && defined __libc_ptf_call
+  /* We do not want this call to be cut short by a thread
+     cancellation.  Therefore disable cancellation for now.  */
+  int state = PTHREAD_CANCEL_ENABLE;
+  __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
+		   0);
+#endif
+
+  fflush (stdout);
+#ifdef _LIBC
+  _IO_flockfile (stderr);
+#endif
+  if (error_print_progname)
+    (*error_print_progname) ();
+  else
+    {
+#if _LIBC
+      if (_IO_fwide (stderr, 0) > 0)
+	__fwprintf (stderr, L"%s: ", program_name);
+      else
+#endif
+	fprintf (stderr, "%s: ", program_name);
+    }
+
+  va_start (args, message);
+  error_tail (status, errnum, message, args);
+
+#ifdef _LIBC
+  _IO_funlockfile (stderr);
+# ifdef __libc_ptf_call
+  __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
+# endif
+#endif
+}
+
+/* Sometimes we want to have at most one error per line.  This
+   variable controls whether this mode is selected or not.  */
+int error_one_per_line;
+
+void
+error_at_line (int status, int errnum, const char *file_name,
+	       unsigned int line_number, const char *message, ...)
+{
+  va_list args;
+
+  if (error_one_per_line)
+    {
+      static const char *old_file_name;
+      static unsigned int old_line_number;
+
+      if (old_line_number == line_number
+	  && (file_name == old_file_name
+	      || strcmp (old_file_name, file_name) == 0))
+	/* Simply return and print nothing.  */
+	return;
+
+      old_file_name = file_name;
+      old_line_number = line_number;
+    }
+
+#if defined _LIBC && defined __libc_ptf_call
+  /* We do not want this call to be cut short by a thread
+     cancellation.  Therefore disable cancellation for now.  */
+  int state = PTHREAD_CANCEL_ENABLE;
+  __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
+		   0);
+#endif
+
+  fflush (stdout);
+#ifdef _LIBC
+  _IO_flockfile (stderr);
+#endif
+  if (error_print_progname)
+    (*error_print_progname) ();
+  else
+    {
+#if _LIBC
+      if (_IO_fwide (stderr, 0) > 0)
+	__fwprintf (stderr, L"%s: ", program_name);
+      else
+#endif
+	fprintf (stderr, "%s:", program_name);
+    }
+
+  if (file_name != NULL)
+    {
+#if _LIBC
+      if (_IO_fwide (stderr, 0) > 0)
+	__fwprintf (stderr, L"%s:%d: ", file_name, line_number);
+      else
+#endif
+	fprintf (stderr, "%s:%d: ", file_name, line_number);
+    }
+
+  va_start (args, message);
+  error_tail (status, errnum, message, args);
+
+#ifdef _LIBC
+  _IO_funlockfile (stderr);
+# ifdef __libc_ptf_call
+  __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
+# endif
+#endif
+}
+
+#ifdef _LIBC
+/* Make the weak alias.  */
+# undef error
+# undef error_at_line
+weak_alias (__error, error)
+weak_alias (__error_at_line, error_at_line)
+#endif
diff --git a/lib/error.h b/lib/error.h
new file mode 100644
index 0000000..e5220a2
--- /dev/null
+++ b/lib/error.h
@@ -0,0 +1,66 @@
+/* Declaration for error-reporting function
+   Copyright (C) 1995, 1996, 1997, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _ERROR_H
+#define _ERROR_H 1
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later.  */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
+#  define __attribute__(Spec) /* empty */
+# endif
+/* The __-protected variants of `format' and `printf' attributes
+   are accepted by gcc versions 2.6.4 (effectively 2.7) and later.  */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+#  define __format__ format
+#  define __printf__ printf
+# endif
+#endif
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/* Print a message with `fprintf (stderr, FORMAT, ...)';
+   if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
+   If STATUS is nonzero, terminate the program with `exit (STATUS)'.  */
+
+extern void error (int __status, int __errnum, const char *__format, ...)
+     __attribute__ ((__format__ (__printf__, 3, 4)));
+
+extern void error_at_line (int __status, int __errnum, const char *__fname,
+			   unsigned int __lineno, const char *__format, ...)
+     __attribute__ ((__format__ (__printf__, 5, 6)));
+
+/* If NULL, error will flush stdout, then print on stderr the program
+   name, a colon and a space.  Otherwise, error will call this
+   function without parameters instead.  */
+extern void (*error_print_progname) (void);
+
+/* This variable is incremented each time `error' is called.  */
+extern unsigned int error_message_count;
+
+/* Sometimes we want to have at most one error per line.  This
+   variable controls whether this mode is selected or not.  */
+extern int error_one_per_line;
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* error.h */
diff --git a/lib/exit.h b/lib/exit.h
new file mode 100644
index 0000000..9dbfb7c
--- /dev/null
+++ b/lib/exit.h
@@ -0,0 +1,32 @@
+/* exit() function.
+   Copyright (C) 1995, 2001 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _EXIT_H
+#define _EXIT_H
+
+/* Get exit() declaration.  */
+#include <stdlib.h>
+
+/* Some systems do not define EXIT_*, even with STDC_HEADERS.  */
+#ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+# define EXIT_FAILURE 1
+#endif
+
+#endif /* _EXIT_H */
diff --git a/lib/exitfail.c b/lib/exitfail.c
new file mode 100644
index 0000000..27d38c3
--- /dev/null
+++ b/lib/exitfail.c
@@ -0,0 +1,27 @@
+/* Failure exit status
+
+   Copyright (C) 2002, 2003 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 2, 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; see the file COPYING.
+   If not, write to the Free Software Foundation,
+   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "exitfail.h"
+#include "exit.h"
+
+int volatile exit_failure = EXIT_FAILURE;
diff --git a/lib/exitfail.h b/lib/exitfail.h
new file mode 100644
index 0000000..e46cf9c
--- /dev/null
+++ b/lib/exitfail.h
@@ -0,0 +1,20 @@
+/* Failure exit status
+
+   Copyright (C) 2002 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 2, 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; see the file COPYING.
+   If not, write to the Free Software Foundation,
+   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+extern int volatile exit_failure;
diff --git a/lib/fd-safer.c b/lib/fd-safer.c
new file mode 100644
index 0000000..5933bcb
--- /dev/null
+++ b/lib/fd-safer.c
@@ -0,0 +1,59 @@
+/* Return a safer copy of a file descriptor.
+
+   Copyright (C) 2005 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Paul Eggert.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "unistd-safer.h"
+
+#include <errno.h>
+
+#include <unistd.h>
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+
+/* Return FD, unless FD would be a copy of standard input, output, or
+   error; in that case, return a duplicate of FD, closing FD.  On
+   failure to duplicate, close FD, set errno, and return -1.  Preserve
+   errno if FD is negative, so that the caller can always inspect
+   errno when the returned value is negative.
+
+   This function is usefully wrapped around functions that return file
+   descriptors, e.g., fd_safer (open ("file", O_RDONLY)).  */
+
+int
+fd_safer (int fd)
+{
+  if (STDIN_FILENO <= fd && fd <= STDERR_FILENO)
+    {
+      int f = dup_safer (fd);
+      int e = errno;
+      close (fd);
+      errno = e;
+      fd = f;
+    }
+
+  return fd;
+}
diff --git a/lib/fopen-safer.c b/lib/fopen-safer.c
new file mode 100644
index 0000000..4f2ffa1
--- /dev/null
+++ b/lib/fopen-safer.c
@@ -0,0 +1,69 @@
+/* Invoke fopen, but avoid some glitches.
+   Copyright (C) 2001, 2004, 2005 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Paul Eggert.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "stdio-safer.h"
+
+#include <errno.h>
+#include <unistd.h>
+#include "unistd-safer.h"
+
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+
+/* Like fopen, but do not return stdin, stdout, or stderr.  */
+
+FILE *
+fopen_safer (char const *file, char const *mode)
+{
+  FILE *fp = fopen (file, mode);
+
+  if (fp)
+    {
+      int fd = fileno (fp);
+
+      if (0 <= fd && fd <= STDERR_FILENO)
+	{
+	  int f = dup_safer (fd);
+
+	  if (f < 0)
+	    {
+	      int e = errno;
+	      fclose (fp);
+	      errno = e;
+	      return NULL;
+	    }
+
+	  if (fclose (fp) != 0
+	      || ! (fp = fdopen (f, mode)))
+	    {
+	      int e = errno;
+	      close (f);
+	      errno = e;
+	      return NULL;
+	    }
+	}
+    }
+
+  return fp;
+}
diff --git a/lib/get-errno.c b/lib/get-errno.c
new file mode 100644
index 0000000..8e8ef58
--- /dev/null
+++ b/lib/get-errno.c
@@ -0,0 +1,45 @@
+/* get-errno.c - get and set errno.
+
+   Copyright (C) 2002, 2006 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Paul Eggert.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+
+#include "get-errno.h"
+
+/* Get and set errno.  A source file that needs to set or get errno,
+   but doesn't need to test for specific errno values, can use these
+   functions to avoid namespace pollution.  For example, a file that
+   defines EQUAL should not include <errno.h>, since <errno.h> might
+   define EQUAL; such a file can include <get-errno.h> instead.  */
+
+int
+get_errno (void)
+{
+  return errno;
+}
+
+void
+set_errno (int e)
+{
+  errno = e;
+}
diff --git a/lib/get-errno.h b/lib/get-errno.h
new file mode 100644
index 0000000..d39a8dd
--- /dev/null
+++ b/lib/get-errno.h
@@ -0,0 +1,20 @@
+/* get-errno.h - get and set errno.
+
+   Copyright (C) 2002 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+extern int get_errno (void);
+extern void set_errno (int);
diff --git a/lib/getopt.c b/lib/getopt.c
new file mode 100644
index 0000000..83bd6db
--- /dev/null
+++ b/lib/getopt.c
@@ -0,0 +1,1191 @@
+/* Getopt for GNU.
+   NOTE: getopt is now part of the C library, so if you don't know what
+   "Keep this file name-space clean" means, talk to drepper@gnu.org
+   before changing it!
+   Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004,2006
+	Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "getopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef VMS
+# include <unixlib.h>
+#endif
+
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "gettext.h"
+# define _(msgid) gettext (msgid)
+#endif
+
+#if defined _LIBC && defined USE_IN_LIBIO
+# include <wchar.h>
+#endif
+
+#ifndef attribute_hidden
+# define attribute_hidden
+#endif
+
+/* Unlike standard Unix `getopt', functions like `getopt_long'
+   let the user intersperse the options with the other arguments.
+
+   As `getopt_long' works, it permutes the elements of ARGV so that,
+   when it is done, all the options precede everything else.  Thus
+   all application programs are extended to handle flexible argument order.
+
+   Using `getopt' or setting the environment variable POSIXLY_CORRECT
+   disables permutation.
+   Then the application's behavior is completely standard.
+
+   GNU application programs can use a third alternative mode in which
+   they can distinguish the relative order of options and other arguments.  */
+
+#include "getopt_int.h"
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns -1, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+/* 1003.2 says this must be 1 before any call.  */
+int optind = 1;
+
+/* Callers store zero here to inhibit the error message
+   for unrecognized options.  */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+   This must be initialized on some systems to avoid linking in the
+   system's own getopt implementation.  */
+
+int optopt = '?';
+
+/* Keep a global copy of all internal members of getopt_data.  */
+
+static struct _getopt_data getopt_data;
+
+
+#if defined HAVE_DECL_GETENV && !HAVE_DECL_GETENV
+extern char *getenv ();
+#endif
+
+#ifdef _LIBC
+/* Stored original parameters.
+   XXX This is no good solution.  We should rather copy the args so
+   that we can compare them later.  But we must not use malloc(3).  */
+extern int __libc_argc;
+extern char **__libc_argv;
+
+/* Bash 2.0 gives us an environment variable containing flags
+   indicating ARGV elements that should not be considered arguments.  */
+
+# ifdef USE_NONOPTION_FLAGS
+/* Defined in getopt_init.c  */
+extern char *__getopt_nonoption_flags;
+# endif
+
+# ifdef USE_NONOPTION_FLAGS
+#  define SWAP_FLAGS(ch1, ch2) \
+  if (d->__nonoption_flags_len > 0)					      \
+    {									      \
+      char __tmp = __getopt_nonoption_flags[ch1];			      \
+      __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2];	      \
+      __getopt_nonoption_flags[ch2] = __tmp;				      \
+    }
+# else
+#  define SWAP_FLAGS(ch1, ch2)
+# endif
+#else	/* !_LIBC */
+# define SWAP_FLAGS(ch1, ch2)
+#endif	/* _LIBC */
+
+/* Exchange two adjacent subsequences of ARGV.
+   One subsequence is elements [first_nonopt,last_nonopt)
+   which contains all the non-options that have been skipped so far.
+   The other is elements [last_nonopt,optind), which contains all
+   the options processed since those non-options were skipped.
+
+   `first_nonopt' and `last_nonopt' are relocated so that they describe
+   the new indices of the non-options in ARGV after they are moved.  */
+
+static void
+exchange (char **argv, struct _getopt_data *d)
+{
+  int bottom = d->__first_nonopt;
+  int middle = d->__last_nonopt;
+  int top = d->optind;
+  char *tem;
+
+  /* Exchange the shorter segment with the far end of the longer segment.
+     That puts the shorter segment into the right place.
+     It leaves the longer segment in the right place overall,
+     but it consists of two parts that need to be swapped next.  */
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+  /* First make sure the handling of the `__getopt_nonoption_flags'
+     string can work normally.  Our top argument must be in the range
+     of the string.  */
+  if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len)
+    {
+      /* We must extend the array.  The user plays games with us and
+	 presents new arguments.  */
+      char *new_str = malloc (top + 1);
+      if (new_str == NULL)
+	d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0;
+      else
+	{
+	  memset (__mempcpy (new_str, __getopt_nonoption_flags,
+			     d->__nonoption_flags_max_len),
+		  '\0', top + 1 - d->__nonoption_flags_max_len);
+	  d->__nonoption_flags_max_len = top + 1;
+	  __getopt_nonoption_flags = new_str;
+	}
+    }
+#endif
+
+  while (top > middle && middle > bottom)
+    {
+      if (top - middle > middle - bottom)
+	{
+	  /* Bottom segment is the short one.  */
+	  int len = middle - bottom;
+	  register int i;
+
+	  /* Swap it with the top part of the top segment.  */
+	  for (i = 0; i < len; i++)
+	    {
+	      tem = argv[bottom + i];
+	      argv[bottom + i] = argv[top - (middle - bottom) + i];
+	      argv[top - (middle - bottom) + i] = tem;
+	      SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
+	    }
+	  /* Exclude the moved bottom segment from further swapping.  */
+	  top -= len;
+	}
+      else
+	{
+	  /* Top segment is the short one.  */
+	  int len = top - middle;
+	  register int i;
+
+	  /* Swap it with the bottom part of the bottom segment.  */
+	  for (i = 0; i < len; i++)
+	    {
+	      tem = argv[bottom + i];
+	      argv[bottom + i] = argv[middle + i];
+	      argv[middle + i] = tem;
+	      SWAP_FLAGS (bottom + i, middle + i);
+	    }
+	  /* Exclude the moved top segment from further swapping.  */
+	  bottom += len;
+	}
+    }
+
+  /* Update records for the slots the non-options now occupy.  */
+
+  d->__first_nonopt += (d->optind - d->__last_nonopt);
+  d->__last_nonopt = d->optind;
+}
+
+/* Initialize the internal data when the first call is made.  */
+
+static const char *
+_getopt_initialize (int argc, char **argv, const char *optstring,
+		    int posixly_correct, struct _getopt_data *d)
+{
+  /* Start processing options with ARGV-element 1 (since ARGV-element 0
+     is the program name); the sequence of previously skipped
+     non-option ARGV-elements is empty.  */
+
+  d->__first_nonopt = d->__last_nonopt = d->optind;
+
+  d->__nextchar = NULL;
+
+  d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT");
+
+  /* Determine how to handle the ordering of options and nonoptions.  */
+
+  if (optstring[0] == '-')
+    {
+      d->__ordering = RETURN_IN_ORDER;
+      ++optstring;
+    }
+  else if (optstring[0] == '+')
+    {
+      d->__ordering = REQUIRE_ORDER;
+      ++optstring;
+    }
+  else if (d->__posixly_correct)
+    d->__ordering = REQUIRE_ORDER;
+  else
+    d->__ordering = PERMUTE;
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+  if (!d->__posixly_correct
+      && argc == __libc_argc && argv == __libc_argv)
+    {
+      if (d->__nonoption_flags_max_len == 0)
+	{
+	  if (__getopt_nonoption_flags == NULL
+	      || __getopt_nonoption_flags[0] == '\0')
+	    d->__nonoption_flags_max_len = -1;
+	  else
+	    {
+	      const char *orig_str = __getopt_nonoption_flags;
+	      int len = d->__nonoption_flags_max_len = strlen (orig_str);
+	      if (d->__nonoption_flags_max_len < argc)
+		d->__nonoption_flags_max_len = argc;
+	      __getopt_nonoption_flags =
+		(char *) malloc (d->__nonoption_flags_max_len);
+	      if (__getopt_nonoption_flags == NULL)
+		d->__nonoption_flags_max_len = -1;
+	      else
+		memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
+			'\0', d->__nonoption_flags_max_len - len);
+	    }
+	}
+      d->__nonoption_flags_len = d->__nonoption_flags_max_len;
+    }
+  else
+    d->__nonoption_flags_len = 0;
+#endif
+
+  return optstring;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+   given in OPTSTRING.
+
+   If an element of ARGV starts with '-', and is not exactly "-" or "--",
+   then it is an option element.  The characters of this element
+   (aside from the initial '-') are option characters.  If `getopt'
+   is called repeatedly, it returns successively each of the option characters
+   from each of the option elements.
+
+   If `getopt' finds another option character, it returns that character,
+   updating `optind' and `nextchar' so that the next call to `getopt' can
+   resume the scan with the following option character or ARGV-element.
+
+   If there are no more option characters, `getopt' returns -1.
+   Then `optind' is the index in ARGV of the first ARGV-element
+   that is not an option.  (The ARGV-elements have been permuted
+   so that those that are not options now come last.)
+
+   OPTSTRING is a string containing the legitimate option characters.
+   If an option character is seen that is not listed in OPTSTRING,
+   return '?' after printing an error message.  If you set `opterr' to
+   zero, the error message is suppressed but we still return '?'.
+
+   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+   so the following text in the same ARGV-element, or the text of the following
+   ARGV-element, is returned in `optarg'.  Two colons mean an option that
+   wants an optional arg; if there is text in the current ARGV-element,
+   it is returned in `optarg', otherwise `optarg' is set to zero.
+
+   If OPTSTRING starts with `-' or `+', it requests different methods of
+   handling the non-option ARGV-elements.
+   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+   Long-named options begin with `--' instead of `-'.
+   Their names may be abbreviated as long as the abbreviation is unique
+   or is an exact match for some defined option.  If they have an
+   argument, it follows the option name in the same ARGV-element, separated
+   from the option name by a `=', or else the in next ARGV-element.
+   When `getopt' finds a long-named option, it returns 0 if that option's
+   `flag' field is nonzero, the value of the option's `val' field
+   if the `flag' field is zero.
+
+   LONGOPTS is a vector of `struct option' terminated by an
+   element containing a name which is zero.
+
+   LONGIND returns the index in LONGOPT of the long-named option found.
+   It is only valid when a long-named option has been found by the most
+   recent call.
+
+   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+   long-named options.
+
+   If POSIXLY_CORRECT is nonzero, behave as if the POSIXLY_CORRECT
+   environment variable were set.  */
+
+int
+_getopt_internal_r (int argc, char **argv, const char *optstring,
+		    const struct option *longopts, int *longind,
+		    int long_only, int posixly_correct, struct _getopt_data *d)
+{
+  int print_errors = d->opterr;
+  if (optstring[0] == ':')
+    print_errors = 0;
+
+  if (argc < 1)
+    return -1;
+
+  d->optarg = NULL;
+
+  if (d->optind == 0 || !d->__initialized)
+    {
+      if (d->optind == 0)
+	d->optind = 1;	/* Don't scan ARGV[0], the program name.  */
+      optstring = _getopt_initialize (argc, argv, optstring,
+				      posixly_correct, d);
+      d->__initialized = 1;
+    }
+
+  /* Test whether ARGV[optind] points to a non-option argument.
+     Either it does not have option syntax, or there is an environment flag
+     from the shell indicating it is not an option.  The later information
+     is only used when the used in the GNU libc.  */
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \
+		      || (d->optind < d->__nonoption_flags_len		      \
+			  && __getopt_nonoption_flags[d->optind] == '1'))
+#else
+# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')
+#endif
+
+  if (d->__nextchar == NULL || *d->__nextchar == '\0')
+    {
+      /* Advance to the next ARGV-element.  */
+
+      /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+	 moved back by the user (who may also have changed the arguments).  */
+      if (d->__last_nonopt > d->optind)
+	d->__last_nonopt = d->optind;
+      if (d->__first_nonopt > d->optind)
+	d->__first_nonopt = d->optind;
+
+      if (d->__ordering == PERMUTE)
+	{
+	  /* If we have just processed some options following some non-options,
+	     exchange them so that the options come first.  */
+
+	  if (d->__first_nonopt != d->__last_nonopt
+	      && d->__last_nonopt != d->optind)
+	    exchange ((char **) argv, d);
+	  else if (d->__last_nonopt != d->optind)
+	    d->__first_nonopt = d->optind;
+
+	  /* Skip any additional non-options
+	     and extend the range of non-options previously skipped.  */
+
+	  while (d->optind < argc && NONOPTION_P)
+	    d->optind++;
+	  d->__last_nonopt = d->optind;
+	}
+
+      /* The special ARGV-element `--' means premature end of options.
+	 Skip it like a null option,
+	 then exchange with previous non-options as if it were an option,
+	 then skip everything else like a non-option.  */
+
+      if (d->optind != argc && !strcmp (argv[d->optind], "--"))
+	{
+	  d->optind++;
+
+	  if (d->__first_nonopt != d->__last_nonopt
+	      && d->__last_nonopt != d->optind)
+	    exchange ((char **) argv, d);
+	  else if (d->__first_nonopt == d->__last_nonopt)
+	    d->__first_nonopt = d->optind;
+	  d->__last_nonopt = argc;
+
+	  d->optind = argc;
+	}
+
+      /* If we have done all the ARGV-elements, stop the scan
+	 and back over any non-options that we skipped and permuted.  */
+
+      if (d->optind == argc)
+	{
+	  /* Set the next-arg-index to point at the non-options
+	     that we previously skipped, so the caller will digest them.  */
+	  if (d->__first_nonopt != d->__last_nonopt)
+	    d->optind = d->__first_nonopt;
+	  return -1;
+	}
+
+      /* If we have come to a non-option and did not permute it,
+	 either stop the scan or describe it to the caller and pass it by.  */
+
+      if (NONOPTION_P)
+	{
+	  if (d->__ordering == REQUIRE_ORDER)
+	    return -1;
+	  d->optarg = argv[d->optind++];
+	  return 1;
+	}
+
+      /* We have found another option-ARGV-element.
+	 Skip the initial punctuation.  */
+
+      d->__nextchar = (argv[d->optind] + 1
+		  + (longopts != NULL && argv[d->optind][1] == '-'));
+    }
+
+  /* Decode the current option-ARGV-element.  */
+
+  /* Check whether the ARGV-element is a long option.
+
+     If long_only and the ARGV-element has the form "-f", where f is
+     a valid short option, don't consider it an abbreviated form of
+     a long option that starts with f.  Otherwise there would be no
+     way to give the -f short option.
+
+     On the other hand, if there's a long option "fubar" and
+     the ARGV-element is "-fu", do consider that an abbreviation of
+     the long option, just like "--fu", and not "-f" with arg "u".
+
+     This distinction seems to be the most useful approach.  */
+
+  if (longopts != NULL
+      && (argv[d->optind][1] == '-'
+	  || (long_only && (argv[d->optind][2]
+			    || !strchr (optstring, argv[d->optind][1])))))
+    {
+      char *nameend;
+      const struct option *p;
+      const struct option *pfound = NULL;
+      int exact = 0;
+      int ambig = 0;
+      int indfound = -1;
+      int option_index;
+
+      for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
+	/* Do nothing.  */ ;
+
+      /* Test all long options for either exact match
+	 or abbreviated matches.  */
+      for (p = longopts, option_index = 0; p->name; p++, option_index++)
+	if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
+	  {
+	    if ((unsigned int) (nameend - d->__nextchar)
+		== (unsigned int) strlen (p->name))
+	      {
+		/* Exact match found.  */
+		pfound = p;
+		indfound = option_index;
+		exact = 1;
+		break;
+	      }
+	    else if (pfound == NULL)
+	      {
+		/* First nonexact match found.  */
+		pfound = p;
+		indfound = option_index;
+	      }
+	    else if (long_only
+		     || pfound->has_arg != p->has_arg
+		     || pfound->flag != p->flag
+		     || pfound->val != p->val)
+	      /* Second or later nonexact match found.  */
+	      ambig = 1;
+	  }
+
+      if (ambig && !exact)
+	{
+	  if (print_errors)
+	    {
+#if defined _LIBC && defined USE_IN_LIBIO
+	      char *buf;
+
+	      if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"),
+			      argv[0], argv[d->optind]) >= 0)
+		{
+		  _IO_flockfile (stderr);
+
+		  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+		  ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+		  __fxprintf (NULL, "%s", buf);
+
+		  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+		  _IO_funlockfile (stderr);
+
+		  free (buf);
+		}
+#else
+	      fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
+		       argv[0], argv[d->optind]);
+#endif
+	    }
+	  d->__nextchar += strlen (d->__nextchar);
+	  d->optind++;
+	  d->optopt = 0;
+	  return '?';
+	}
+
+      if (pfound != NULL)
+	{
+	  option_index = indfound;
+	  d->optind++;
+	  if (*nameend)
+	    {
+	      /* Don't test has_arg with >, because some C compilers don't
+		 allow it to be used on enums.  */
+	      if (pfound->has_arg)
+		d->optarg = nameend + 1;
+	      else
+		{
+		  if (print_errors)
+		    {
+#if defined _LIBC && defined USE_IN_LIBIO
+		      char *buf;
+		      int n;
+#endif
+
+		      if (argv[d->optind - 1][1] == '-')
+			{
+			  /* --option */
+#if defined _LIBC && defined USE_IN_LIBIO
+			  n = __asprintf (&buf, _("\
+%s: option `--%s' doesn't allow an argument\n"),
+					  argv[0], pfound->name);
+#else
+			  fprintf (stderr, _("\
+%s: option `--%s' doesn't allow an argument\n"),
+				   argv[0], pfound->name);
+#endif
+			}
+		      else
+			{
+			  /* +option or -option */
+#if defined _LIBC && defined USE_IN_LIBIO
+			  n = __asprintf (&buf, _("\
+%s: option `%c%s' doesn't allow an argument\n"),
+					  argv[0], argv[d->optind - 1][0],
+					  pfound->name);
+#else
+			  fprintf (stderr, _("\
+%s: option `%c%s' doesn't allow an argument\n"),
+				   argv[0], argv[d->optind - 1][0],
+				   pfound->name);
+#endif
+			}
+
+#if defined _LIBC && defined USE_IN_LIBIO
+		      if (n >= 0)
+			{
+			  _IO_flockfile (stderr);
+
+			  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+			  ((_IO_FILE *) stderr)->_flags2
+			    |= _IO_FLAGS2_NOTCANCEL;
+
+			  __fxprintf (NULL, "%s", buf);
+
+			  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+			  _IO_funlockfile (stderr);
+
+			  free (buf);
+			}
+#endif
+		    }
+
+		  d->__nextchar += strlen (d->__nextchar);
+
+		  d->optopt = pfound->val;
+		  return '?';
+		}
+	    }
+	  else if (pfound->has_arg == 1)
+	    {
+	      if (d->optind < argc)
+		d->optarg = argv[d->optind++];
+	      else
+		{
+		  if (print_errors)
+		    {
+#if defined _LIBC && defined USE_IN_LIBIO
+		      char *buf;
+
+		      if (__asprintf (&buf, _("\
+%s: option `%s' requires an argument\n"),
+				      argv[0], argv[d->optind - 1]) >= 0)
+			{
+			  _IO_flockfile (stderr);
+
+			  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+			  ((_IO_FILE *) stderr)->_flags2
+			    |= _IO_FLAGS2_NOTCANCEL;
+
+			  __fxprintf (NULL, "%s", buf);
+
+			  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+			  _IO_funlockfile (stderr);
+
+			  free (buf);
+			}
+#else
+		      fprintf (stderr,
+			       _("%s: option `%s' requires an argument\n"),
+			       argv[0], argv[d->optind - 1]);
+#endif
+		    }
+		  d->__nextchar += strlen (d->__nextchar);
+		  d->optopt = pfound->val;
+		  return optstring[0] == ':' ? ':' : '?';
+		}
+	    }
+	  d->__nextchar += strlen (d->__nextchar);
+	  if (longind != NULL)
+	    *longind = option_index;
+	  if (pfound->flag)
+	    {
+	      *(pfound->flag) = pfound->val;
+	      return 0;
+	    }
+	  return pfound->val;
+	}
+
+      /* Can't find it as a long option.  If this is not getopt_long_only,
+	 or the option starts with '--' or is not a valid short
+	 option, then it's an error.
+	 Otherwise interpret it as a short option.  */
+      if (!long_only || argv[d->optind][1] == '-'
+	  || strchr (optstring, *d->__nextchar) == NULL)
+	{
+	  if (print_errors)
+	    {
+#if defined _LIBC && defined USE_IN_LIBIO
+	      char *buf;
+	      int n;
+#endif
+
+	      if (argv[d->optind][1] == '-')
+		{
+		  /* --option */
+#if defined _LIBC && defined USE_IN_LIBIO
+		  n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"),
+				  argv[0], d->__nextchar);
+#else
+		  fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
+			   argv[0], d->__nextchar);
+#endif
+		}
+	      else
+		{
+		  /* +option or -option */
+#if defined _LIBC && defined USE_IN_LIBIO
+		  n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"),
+				  argv[0], argv[d->optind][0], d->__nextchar);
+#else
+		  fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
+			   argv[0], argv[d->optind][0], d->__nextchar);
+#endif
+		}
+
+#if defined _LIBC && defined USE_IN_LIBIO
+	      if (n >= 0)
+		{
+		  _IO_flockfile (stderr);
+
+		  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+		  ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+		  __fxprintf (NULL, "%s", buf);
+
+		  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+		  _IO_funlockfile (stderr);
+
+		  free (buf);
+		}
+#endif
+	    }
+	  d->__nextchar = (char *) "";
+	  d->optind++;
+	  d->optopt = 0;
+	  return '?';
+	}
+    }
+
+  /* Look at and handle the next short option-character.  */
+
+  {
+    char c = *d->__nextchar++;
+    char *temp = strchr (optstring, c);
+
+    /* Increment `optind' when we start to process its last character.  */
+    if (*d->__nextchar == '\0')
+      ++d->optind;
+
+    if (temp == NULL || c == ':')
+      {
+	if (print_errors)
+	  {
+#if defined _LIBC && defined USE_IN_LIBIO
+	      char *buf;
+	      int n;
+#endif
+
+	    if (d->__posixly_correct)
+	      {
+		/* 1003.2 specifies the format of this message.  */
+#if defined _LIBC && defined USE_IN_LIBIO
+		n = __asprintf (&buf, _("%s: illegal option -- %c\n"),
+				argv[0], c);
+#else
+		fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c);
+#endif
+	      }
+	    else
+	      {
+#if defined _LIBC && defined USE_IN_LIBIO
+		n = __asprintf (&buf, _("%s: invalid option -- %c\n"),
+				argv[0], c);
+#else
+		fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c);
+#endif
+	      }
+
+#if defined _LIBC && defined USE_IN_LIBIO
+	    if (n >= 0)
+	      {
+		_IO_flockfile (stderr);
+
+		int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+		((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+		__fxprintf (NULL, "%s", buf);
+
+		((_IO_FILE *) stderr)->_flags2 = old_flags2;
+		_IO_funlockfile (stderr);
+
+		free (buf);
+	      }
+#endif
+	  }
+	d->optopt = c;
+	return '?';
+      }
+    /* Convenience. Treat POSIX -W foo same as long option --foo */
+    if (temp[0] == 'W' && temp[1] == ';')
+      {
+	char *nameend;
+	const struct option *p;
+	const struct option *pfound = NULL;
+	int exact = 0;
+	int ambig = 0;
+	int indfound = 0;
+	int option_index;
+
+	/* This is an option that requires an argument.  */
+	if (*d->__nextchar != '\0')
+	  {
+	    d->optarg = d->__nextchar;
+	    /* If we end this ARGV-element by taking the rest as an arg,
+	       we must advance to the next element now.  */
+	    d->optind++;
+	  }
+	else if (d->optind == argc)
+	  {
+	    if (print_errors)
+	      {
+		/* 1003.2 specifies the format of this message.  */
+#if defined _LIBC && defined USE_IN_LIBIO
+		char *buf;
+
+		if (__asprintf (&buf,
+				_("%s: option requires an argument -- %c\n"),
+				argv[0], c) >= 0)
+		  {
+		    _IO_flockfile (stderr);
+
+		    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+		    ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+		    __fxprintf (NULL, "%s", buf);
+
+		    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+		    _IO_funlockfile (stderr);
+
+		    free (buf);
+		  }
+#else
+		fprintf (stderr, _("%s: option requires an argument -- %c\n"),
+			 argv[0], c);
+#endif
+	      }
+	    d->optopt = c;
+	    if (optstring[0] == ':')
+	      c = ':';
+	    else
+	      c = '?';
+	    return c;
+	  }
+	else
+	  /* We already incremented `d->optind' once;
+	     increment it again when taking next ARGV-elt as argument.  */
+	  d->optarg = argv[d->optind++];
+
+	/* optarg is now the argument, see if it's in the
+	   table of longopts.  */
+
+	for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '=';
+	     nameend++)
+	  /* Do nothing.  */ ;
+
+	/* Test all long options for either exact match
+	   or abbreviated matches.  */
+	for (p = longopts, option_index = 0; p->name; p++, option_index++)
+	  if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
+	    {
+	      if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name))
+		{
+		  /* Exact match found.  */
+		  pfound = p;
+		  indfound = option_index;
+		  exact = 1;
+		  break;
+		}
+	      else if (pfound == NULL)
+		{
+		  /* First nonexact match found.  */
+		  pfound = p;
+		  indfound = option_index;
+		}
+	      else
+		/* Second or later nonexact match found.  */
+		ambig = 1;
+	    }
+	if (ambig && !exact)
+	  {
+	    if (print_errors)
+	      {
+#if defined _LIBC && defined USE_IN_LIBIO
+		char *buf;
+
+		if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"),
+				argv[0], argv[d->optind]) >= 0)
+		  {
+		    _IO_flockfile (stderr);
+
+		    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+		    ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+		    __fxprintf (NULL, "%s", buf);
+
+		    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+		    _IO_funlockfile (stderr);
+
+		    free (buf);
+		  }
+#else
+		fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
+			 argv[0], argv[d->optind]);
+#endif
+	      }
+	    d->__nextchar += strlen (d->__nextchar);
+	    d->optind++;
+	    return '?';
+	  }
+	if (pfound != NULL)
+	  {
+	    option_index = indfound;
+	    if (*nameend)
+	      {
+		/* Don't test has_arg with >, because some C compilers don't
+		   allow it to be used on enums.  */
+		if (pfound->has_arg)
+		  d->optarg = nameend + 1;
+		else
+		  {
+		    if (print_errors)
+		      {
+#if defined _LIBC && defined USE_IN_LIBIO
+			char *buf;
+
+			if (__asprintf (&buf, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+					argv[0], pfound->name) >= 0)
+			  {
+			    _IO_flockfile (stderr);
+
+			    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+			    ((_IO_FILE *) stderr)->_flags2
+			      |= _IO_FLAGS2_NOTCANCEL;
+
+			    __fxprintf (NULL, "%s", buf);
+
+			    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+			    _IO_funlockfile (stderr);
+
+			    free (buf);
+			  }
+#else
+			fprintf (stderr, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+				 argv[0], pfound->name);
+#endif
+		      }
+
+		    d->__nextchar += strlen (d->__nextchar);
+		    return '?';
+		  }
+	      }
+	    else if (pfound->has_arg == 1)
+	      {
+		if (d->optind < argc)
+		  d->optarg = argv[d->optind++];
+		else
+		  {
+		    if (print_errors)
+		      {
+#if defined _LIBC && defined USE_IN_LIBIO
+			char *buf;
+
+			if (__asprintf (&buf, _("\
+%s: option `%s' requires an argument\n"),
+					argv[0], argv[d->optind - 1]) >= 0)
+			  {
+			    _IO_flockfile (stderr);
+
+			    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+			    ((_IO_FILE *) stderr)->_flags2
+			      |= _IO_FLAGS2_NOTCANCEL;
+
+			    __fxprintf (NULL, "%s", buf);
+
+			    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+			    _IO_funlockfile (stderr);
+
+			    free (buf);
+			  }
+#else
+			fprintf (stderr,
+				 _("%s: option `%s' requires an argument\n"),
+				 argv[0], argv[d->optind - 1]);
+#endif
+		      }
+		    d->__nextchar += strlen (d->__nextchar);
+		    return optstring[0] == ':' ? ':' : '?';
+		  }
+	      }
+	    d->__nextchar += strlen (d->__nextchar);
+	    if (longind != NULL)
+	      *longind = option_index;
+	    if (pfound->flag)
+	      {
+		*(pfound->flag) = pfound->val;
+		return 0;
+	      }
+	    return pfound->val;
+	  }
+	  d->__nextchar = NULL;
+	  return 'W';	/* Let the application handle it.   */
+      }
+    if (temp[1] == ':')
+      {
+	if (temp[2] == ':')
+	  {
+	    /* This is an option that accepts an argument optionally.  */
+	    if (*d->__nextchar != '\0')
+	      {
+		d->optarg = d->__nextchar;
+		d->optind++;
+	      }
+	    else
+	      d->optarg = NULL;
+	    d->__nextchar = NULL;
+	  }
+	else
+	  {
+	    /* This is an option that requires an argument.  */
+	    if (*d->__nextchar != '\0')
+	      {
+		d->optarg = d->__nextchar;
+		/* If we end this ARGV-element by taking the rest as an arg,
+		   we must advance to the next element now.  */
+		d->optind++;
+	      }
+	    else if (d->optind == argc)
+	      {
+		if (print_errors)
+		  {
+		    /* 1003.2 specifies the format of this message.  */
+#if defined _LIBC && defined USE_IN_LIBIO
+		    char *buf;
+
+		    if (__asprintf (&buf, _("\
+%s: option requires an argument -- %c\n"),
+				    argv[0], c) >= 0)
+		      {
+			_IO_flockfile (stderr);
+
+			int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+			((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+			__fxprintf (NULL, "%s", buf);
+
+			((_IO_FILE *) stderr)->_flags2 = old_flags2;
+			_IO_funlockfile (stderr);
+
+			free (buf);
+		      }
+#else
+		    fprintf (stderr,
+			     _("%s: option requires an argument -- %c\n"),
+			     argv[0], c);
+#endif
+		  }
+		d->optopt = c;
+		if (optstring[0] == ':')
+		  c = ':';
+		else
+		  c = '?';
+	      }
+	    else
+	      /* We already incremented `optind' once;
+		 increment it again when taking next ARGV-elt as argument.  */
+	      d->optarg = argv[d->optind++];
+	    d->__nextchar = NULL;
+	  }
+      }
+    return c;
+  }
+}
+
+int
+_getopt_internal (int argc, char **argv, const char *optstring,
+		  const struct option *longopts, int *longind,
+		  int long_only, int posixly_correct)
+{
+  int result;
+
+  getopt_data.optind = optind;
+  getopt_data.opterr = opterr;
+
+  result = _getopt_internal_r (argc, argv, optstring, longopts, longind,
+			       long_only, posixly_correct, &getopt_data);
+
+  optind = getopt_data.optind;
+  optarg = getopt_data.optarg;
+  optopt = getopt_data.optopt;
+
+  return result;
+}
+
+/* glibc gets a LSB-compliant getopt.
+   Standalone applications get a POSIX-compliant getopt.  */
+#if _LIBC
+enum { POSIXLY_CORRECT = 0 };
+#else
+enum { POSIXLY_CORRECT = 1 };
+#endif
+
+int
+getopt (int argc, char *const *argv, const char *optstring)
+{
+  return _getopt_internal (argc, (char **) argv, optstring, NULL, NULL, 0,
+			   POSIXLY_CORRECT);
+}
+
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+   the above definition of `getopt'.  */
+
+int
+main (int argc, char **argv)
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+
+      c = getopt (argc, argv, "abc:d:0123456789");
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
diff --git a/lib/getopt1.c b/lib/getopt1.c
new file mode 100644
index 0000000..25d7926
--- /dev/null
+++ b/lib/getopt1.c
@@ -0,0 +1,174 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+   Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004
+     Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# include <getopt.h>
+#else
+# include "getopt.h"
+#endif
+#include "getopt_int.h"
+
+#include <stdio.h>
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#endif
+
+#ifndef	NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (int argc, char *__getopt_argv_const *argv, const char *options,
+	     const struct option *long_options, int *opt_index)
+{
+  return _getopt_internal (argc, (char **) argv, options, long_options,
+			   opt_index, 0, 0);
+}
+
+int
+_getopt_long_r (int argc, char **argv, const char *options,
+		const struct option *long_options, int *opt_index,
+		struct _getopt_data *d)
+{
+  return _getopt_internal_r (argc, argv, options, long_options, opt_index,
+			     0, 0, d);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+   If an option that starts with '-' (not '--') doesn't match a long option,
+   but does match a short option, it is parsed as a short option
+   instead.  */
+
+int
+getopt_long_only (int argc, char *__getopt_argv_const *argv,
+		  const char *options,
+		  const struct option *long_options, int *opt_index)
+{
+  return _getopt_internal (argc, (char **) argv, options, long_options,
+			   opt_index, 1, 0);
+}
+
+int
+_getopt_long_only_r (int argc, char **argv, const char *options,
+		     const struct option *long_options, int *opt_index,
+		     struct _getopt_data *d)
+{
+  return _getopt_internal_r (argc, argv, options, long_options, opt_index,
+			     1, 0, d);
+}
+
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+      int option_index = 0;
+      static struct option long_options[] =
+      {
+	{"add", 1, 0, 0},
+	{"append", 0, 0, 0},
+	{"delete", 1, 0, 0},
+	{"verbose", 0, 0, 0},
+	{"create", 0, 0, 0},
+	{"file", 1, 0, 0},
+	{0, 0, 0, 0}
+      };
+
+      c = getopt_long (argc, argv, "abc:d:0123456789",
+		       long_options, &option_index);
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 0:
+	  printf ("option %s", long_options[option_index].name);
+	  if (optarg)
+	    printf (" with arg %s", optarg);
+	  printf ("\n");
+	  break;
+
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case 'd':
+	  printf ("option d with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
diff --git a/lib/getopt_.h b/lib/getopt_.h
new file mode 100644
index 0000000..3c406e5
--- /dev/null
+++ b/lib/getopt_.h
@@ -0,0 +1,225 @@
+/* Declarations for getopt.
+   Copyright (C) 1989-1994,1996-1999,2001,2003,2004,2005
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _GETOPT_H
+
+#ifndef __need_getopt
+# define _GETOPT_H 1
+#endif
+
+/* Standalone applications should #define __GETOPT_PREFIX to an
+   identifier that prefixes the external functions and variables
+   defined in this header.  When this happens, include the
+   headers that might declare getopt so that they will not cause
+   confusion if included after this file.  Then systematically rename
+   identifiers so that they do not collide with the system functions
+   and variables.  Renaming avoids problems with some compilers and
+   linkers.  */
+#if defined __GETOPT_PREFIX && !defined __need_getopt
+# include <stdlib.h>
+# include <stdio.h>
+# include <unistd.h>
+# undef __need_getopt
+# undef getopt
+# undef getopt_long
+# undef getopt_long_only
+# undef optarg
+# undef opterr
+# undef optind
+# undef optopt
+# define __GETOPT_CONCAT(x, y) x ## y
+# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y)
+# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y)
+# define getopt __GETOPT_ID (getopt)
+# define getopt_long __GETOPT_ID (getopt_long)
+# define getopt_long_only __GETOPT_ID (getopt_long_only)
+# define optarg __GETOPT_ID (optarg)
+# define opterr __GETOPT_ID (opterr)
+# define optind __GETOPT_ID (optind)
+# define optopt __GETOPT_ID (optopt)
+#endif
+
+/* Standalone applications get correct prototypes for getopt_long and
+   getopt_long_only; they declare "char **argv".  libc uses prototypes
+   with "char *const *argv" that are incorrect because getopt_long and
+   getopt_long_only can permute argv; this is required for backward
+   compatibility (e.g., for LSB 2.0.1).
+
+   This used to be `#if defined __GETOPT_PREFIX && !defined __need_getopt',
+   but it caused redefinition warnings if both unistd.h and getopt.h were
+   included, since unistd.h includes getopt.h having previously defined
+   __need_getopt.
+
+   The only place where __getopt_argv_const is used is in definitions
+   of getopt_long and getopt_long_only below, but these are visible
+   only if __need_getopt is not defined, so it is quite safe to rewrite
+   the conditional as follows:
+*/
+#if !defined __need_getopt
+# if defined __GETOPT_PREFIX
+#  define __getopt_argv_const /* empty */
+# else
+#  define __getopt_argv_const const
+# endif
+#endif
+
+/* If __GNU_LIBRARY__ is not already defined, either we are being used
+   standalone, or this is the first header included in the source file.
+   If we are being used with glibc, we need to include <features.h>, but
+   that does not exist if we are standalone.  So: if __GNU_LIBRARY__ is
+   not defined, include <ctype.h>, which will pull in <features.h> for us
+   if it's from glibc.  (Why ctype.h?  It's guaranteed to exist and it
+   doesn't flood the namespace with stuff the way some other headers do.)  */
+#if !defined __GNU_LIBRARY__
+# include <ctype.h>
+#endif
+
+#ifndef __THROW
+# ifndef __GNUC_PREREQ
+#  define __GNUC_PREREQ(maj, min) (0)
+# endif
+# if defined __cplusplus && __GNUC_PREREQ (2,8)
+#  define __THROW	throw ()
+# else
+#  define __THROW
+# endif
+#endif
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns -1, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+   for unrecognized options.  */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized.  */
+
+extern int optopt;
+
+#ifndef __need_getopt
+/* Describe the long-named options requested by the application.
+   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+   of `struct option' terminated by an element containing a name which is
+   zero.
+
+   The field `has_arg' is:
+   no_argument		(or 0) if the option does not take an argument,
+   required_argument	(or 1) if the option requires an argument,
+   optional_argument	(or 2) if the option takes an optional argument.
+
+   If the field `flag' is not NULL, it points to a variable that is set
+   to the value given in the field `val' when the option is found, but
+   left unchanged if the option is not found.
+
+   To have a long-named option do something other than set an `int' to
+   a compiled-in constant, such as set a value from `optarg', set the
+   option's `flag' field to zero and its `val' field to a nonzero
+   value (the equivalent single-letter option character, if there is
+   one).  For long options that have a zero `flag' field, `getopt'
+   returns the contents of the `val' field.  */
+
+struct option
+{
+  const char *name;
+  /* has_arg can't be an enum because some compilers complain about
+     type mismatches in all the code that assumes it is an int.  */
+  int has_arg;
+  int *flag;
+  int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'.  */
+
+# define no_argument		0
+# define required_argument	1
+# define optional_argument	2
+#endif	/* need getopt */
+
+
+/* Get definitions and prototypes for functions to process the
+   arguments in ARGV (ARGC of them, minus the program name) for
+   options given in OPTS.
+
+   Return the option character from OPTS just read.  Return -1 when
+   there are no more options.  For unrecognized options, or options
+   missing arguments, `optopt' is set to the option letter, and '?' is
+   returned.
+
+   The OPTS string is a list of characters which are recognized option
+   letters, optionally followed by colons, specifying that that letter
+   takes an argument, to be placed in `optarg'.
+
+   If a letter in OPTS is followed by two colons, its argument is
+   optional.  This behavior is specific to the GNU `getopt'.
+
+   The argument `--' causes premature termination of argument
+   scanning, explicitly telling `getopt' that there are no more
+   options.
+
+   If OPTS begins with `--', then non-option arguments are treated as
+   arguments to the option '\0'.  This behavior is specific to the GNU
+   `getopt'.  */
+
+extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
+       __THROW;
+
+#ifndef __need_getopt
+extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv,
+			const char *__shortopts,
+		        const struct option *__longopts, int *__longind)
+       __THROW;
+extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv,
+			     const char *__shortopts,
+		             const struct option *__longopts, int *__longind)
+       __THROW;
+
+#endif
+
+#ifdef	__cplusplus
+}
+#endif
+
+/* Make sure we later can get all the definitions and declarations.  */
+#undef __need_getopt
+
+#endif /* getopt.h */
diff --git a/lib/getopt_int.h b/lib/getopt_int.h
new file mode 100644
index 0000000..401579f
--- /dev/null
+++ b/lib/getopt_int.h
@@ -0,0 +1,131 @@
+/* Internal declarations for getopt.
+   Copyright (C) 1989-1994,1996-1999,2001,2003,2004
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _GETOPT_INT_H
+#define _GETOPT_INT_H	1
+
+extern int _getopt_internal (int ___argc, char **___argv,
+			     const char *__shortopts,
+		             const struct option *__longopts, int *__longind,
+			     int __long_only, int __posixly_correct);
+
+
+/* Reentrant versions which can handle parsing multiple argument
+   vectors at the same time.  */
+
+/* Data type for reentrant functions.  */
+struct _getopt_data
+{
+  /* These have exactly the same meaning as the corresponding global
+     variables, except that they are used for the reentrant
+     versions of getopt.  */
+  int optind;
+  int opterr;
+  int optopt;
+  char *optarg;
+
+  /* Internal members.  */
+
+  /* True if the internal members have been initialized.  */
+  int __initialized;
+
+  /* The next char to be scanned in the option-element
+     in which the last option character we returned was found.
+     This allows us to pick up the scan where we left off.
+
+     If this is zero, or a null string, it means resume the scan
+     by advancing to the next ARGV-element.  */
+  char *__nextchar;
+
+  /* Describe how to deal with options that follow non-option ARGV-elements.
+
+     If the caller did not specify anything,
+     the default is REQUIRE_ORDER if the environment variable
+     POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+     REQUIRE_ORDER means don't recognize them as options;
+     stop option processing when the first non-option is seen.
+     This is what Unix does.
+     This mode of operation is selected by either setting the environment
+     variable POSIXLY_CORRECT, or using `+' as the first character
+     of the list of option characters, or by calling getopt.
+
+     PERMUTE is the default.  We permute the contents of ARGV as we
+     scan, so that eventually all the non-options are at the end.
+     This allows options to be given in any order, even with programs
+     that were not written to expect this.
+
+     RETURN_IN_ORDER is an option available to programs that were
+     written to expect options and other ARGV-elements in any order
+     and that care about the ordering of the two.  We describe each
+     non-option ARGV-element as if it were the argument of an option
+     with character code 1.  Using `-' as the first character of the
+     list of option characters selects this mode of operation.
+
+     The special argument `--' forces an end of option-scanning regardless
+     of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
+     `--' can cause `getopt' to return -1 with `optind' != ARGC.  */
+
+  enum
+    {
+      REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+    } __ordering;
+
+  /* If the POSIXLY_CORRECT environment variable is set
+     or getopt was called.  */
+  int __posixly_correct;
+
+
+  /* Handle permutation of arguments.  */
+
+  /* Describe the part of ARGV that contains non-options that have
+     been skipped.  `first_nonopt' is the index in ARGV of the first
+     of them; `last_nonopt' is the index after the last of them.  */
+
+  int __first_nonopt;
+  int __last_nonopt;
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+  int __nonoption_flags_max_len;
+  int __nonoption_flags_len;
+# endif
+};
+
+/* The initializer is necessary to set OPTIND and OPTERR to their
+   default values and to clear the initialization flag.  */
+#define _GETOPT_DATA_INITIALIZER	{ 1, 1 }
+
+extern int _getopt_internal_r (int ___argc, char **___argv,
+			       const char *__shortopts,
+			       const struct option *__longopts, int *__longind,
+			       int __long_only, int __posixly_correct,
+			       struct _getopt_data *__data);
+
+extern int _getopt_long_r (int ___argc, char **___argv,
+			   const char *__shortopts,
+			   const struct option *__longopts, int *__longind,
+			   struct _getopt_data *__data);
+
+extern int _getopt_long_only_r (int ___argc, char **___argv,
+				const char *__shortopts,
+				const struct option *__longopts,
+				int *__longind,
+				struct _getopt_data *__data);
+
+#endif /* getopt_int.h */
diff --git a/lib/gettext.h b/lib/gettext.h
new file mode 100644
index 0000000..285cb31
--- /dev/null
+++ b/lib/gettext.h
@@ -0,0 +1,78 @@
+/* Convenience header for conditional use of GNU <libintl.h>.
+   Copyright (C) 1995-1998, 2000-2002, 2004 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _LIBGETTEXT_H
+#define _LIBGETTEXT_H 1
+
+/* NLS can be disabled through the configure --disable-nls option.  */
+#if ENABLE_NLS
+
+/* Get declarations of GNU message catalog functions.  */
+# include <libintl.h>
+
+#else
+
+/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
+   chokes if dcgettext is defined as a macro.  So include it now, to make
+   later inclusions of <locale.h> a NOP.  We don't include <libintl.h>
+   as well because people using "gettext.h" will not include <libintl.h>,
+   and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
+   is OK.  */
+#if defined(__sun)
+# include <locale.h>
+#endif
+
+/* Many header files from the libstdc++ coming with g++ 3.3 or newer include
+   <libintl.h>, which chokes if dcgettext is defined as a macro.  So include
+   it now, to make later inclusions of <libintl.h> a NOP.  */
+#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
+# include <cstdlib>
+# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H
+#  include <libintl.h>
+# endif
+#endif
+
+/* Disabled NLS.
+   The casts to 'const char *' serve the purpose of producing warnings
+   for invalid uses of the value returned from these functions.
+   On pre-ANSI systems without 'const', the config.h file is supposed to
+   contain "#define const".  */
+# define gettext(Msgid) ((const char *) (Msgid))
+# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
+# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
+# define ngettext(Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dngettext(Domainname, Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
+
+#endif
+
+/* A pseudo function call that serves as a marker for the automated
+   extraction of messages, but does not call gettext().  The run-time
+   translation is done at a different place in the code.
+   The argument, String, should be a literal string.  Concatenated strings
+   and other string expressions won't work.
+   The macro's expansion is not parenthesized, so that it is suitable as
+   initializer for static 'char[]' or 'const char[]' variables.  */
+#define gettext_noop(String) String
+
+#endif /* _LIBGETTEXT_H */
diff --git a/lib/gnulib.mk b/lib/gnulib.mk
new file mode 100644
index 0000000..3e7b28d
--- /dev/null
+++ b/lib/gnulib.mk
@@ -0,0 +1,78 @@
+# This file is generated automatically by "bootstrap".
+lib_SOURCES += argmatch.h argmatch.c
+
+lib_SOURCES += basename.c stripslash.c
+
+
+lib_SOURCES += exit.h
+
+
+
+BUILT_SOURCES += $(GETOPT_H)
+EXTRA_DIST += getopt_.h getopt_int.h
+
+# We need the following in order to create <getopt.h> when the system
+# doesn't have one that works with the given compiler.
+getopt.h: getopt_.h
+	cp $(srcdir)/getopt_.h $@-t
+	mv $@-t $@
+MOSTLYCLEANFILES += getopt.h getopt.h-t
+
+# This is for those projects which use "gettextize --intl" to put a source-code
+# copy of libintl into their package. In such projects, every Makefile.am needs
+# -I$(top_builddir)/intl, so that <libintl.h> can be found in this directory.
+# For the Makefile.ams in other directories it is the maintainer's
+# responsibility; for the one from gnulib we do it here.
+# This option has no effect when the user disables NLS (because then the intl
+# directory contains no libintl.h file) or when the project does not use
+# "gettextize --intl".
+# (commented out by bootstrap) AM_CPPFLAGS += -I$(top_builddir)/intl
+
+lib_SOURCES += gettext.h
+
+
+
+
+
+lib_SOURCES += mbswidth.h mbswidth.c
+
+
+
+
+BUILT_SOURCES += $(STDBOOL_H)
+EXTRA_DIST += stdbool_.h
+
+# We need the following in order to create <stdbool.h> when the system
+# doesn't have one that works.
+stdbool.h: stdbool_.h
+	sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool_.h > $@-t
+	mv $@-t $@
+MOSTLYCLEANFILES += stdbool.h stdbool.h-t
+
+
+lib_SOURCES += stpcpy.h
+
+
+
+
+
+
+
+
+BUILT_SOURCES += $(UNISTD_H)
+
+# We need the following in order to create an empty placeholder for
+# <unistd.h> when the system doesn't have one.
+unistd.h:
+	echo '/* Empty placeholder for $@.  */' >$@
+MOSTLYCLEANFILES += unistd.h
+
+
+
+lib_SOURCES += verify.h
+
+
+lib_SOURCES += xalloc-die.c
+
+lib_SOURCES += xstrndup.h xstrndup.c
+
diff --git a/lib/hard-locale.c b/lib/hard-locale.c
new file mode 100644
index 0000000..98530fc
--- /dev/null
+++ b/lib/hard-locale.c
@@ -0,0 +1,75 @@
+/* hard-locale.c -- Determine whether a locale is hard.
+
+   Copyright (C) 1997, 1998, 1999, 2002, 2003, 2004 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "hard-locale.h"
+
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "strdup.h"
+
+#ifdef __GLIBC__
+# define GLIBC_VERSION __GLIBC__
+#else
+# define GLIBC_VERSION 0
+#endif
+
+/* Return true if the current CATEGORY locale is hard, i.e. if you
+   can't get away with assuming traditional C or POSIX behavior.  */
+bool
+hard_locale (int category)
+{
+  bool hard = true;
+  char const *p = setlocale (category, NULL);
+
+  if (p)
+    {
+      if (2 <= GLIBC_VERSION)
+	{
+	  if (strcmp (p, "C") == 0 || strcmp (p, "POSIX") == 0)
+	    hard = false;
+	}
+      else
+	{
+	  char *locale = strdup (p);
+	  if (locale)
+	    {
+	      /* Temporarily set the locale to the "C" and "POSIX" locales
+		 to find their names, so that we can determine whether one
+		 or the other is the caller's locale.  */
+	      if (((p = setlocale (category, "C"))
+		   && strcmp (p, locale) == 0)
+		  || ((p = setlocale (category, "POSIX"))
+		      && strcmp (p, locale) == 0))
+		hard = false;
+
+	      /* Restore the caller's locale.  */
+	      setlocale (category, locale);
+	      free (locale);
+	    }
+	}
+    }
+
+  return hard;
+}
diff --git a/lib/hard-locale.h b/lib/hard-locale.h
new file mode 100644
index 0000000..c5cedc0
--- /dev/null
+++ b/lib/hard-locale.h
@@ -0,0 +1,26 @@
+/* Determine whether a locale is hard.
+
+   Copyright (C) 1999, 2003, 2004 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef HARD_LOCALE_H_
+# define HARD_LOCALE_H_ 1
+
+# include <stdbool.h>
+
+bool hard_locale (int);
+
+#endif /* HARD_LOCALE_H_ */
diff --git a/lib/hash.c b/lib/hash.c
new file mode 100644
index 0000000..f85bd51
--- /dev/null
+++ b/lib/hash.c
@@ -0,0 +1,1050 @@
+/* hash - hashing table processing.
+
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free
+   Software Foundation, Inc.
+
+   Written by Jim Meyering, 1992.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* A generic hash table package.  */
+
+/* Define USE_OBSTACK to 1 if you want the allocator to use obstacks instead
+   of malloc.  If you change USE_OBSTACK, you have to recompile!  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "hash.h"
+#include "xalloc.h"
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if USE_OBSTACK
+# include "obstack.h"
+# ifndef obstack_chunk_alloc
+#  define obstack_chunk_alloc malloc
+# endif
+# ifndef obstack_chunk_free
+#  define obstack_chunk_free free
+# endif
+#endif
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+struct hash_table
+  {
+    /* The array of buckets starts at BUCKET and extends to BUCKET_LIMIT-1,
+       for a possibility of N_BUCKETS.  Among those, N_BUCKETS_USED buckets
+       are not empty, there are N_ENTRIES active entries in the table.  */
+    struct hash_entry *bucket;
+    struct hash_entry const *bucket_limit;
+    size_t n_buckets;
+    size_t n_buckets_used;
+    size_t n_entries;
+
+    /* Tuning arguments, kept in a physicaly separate structure.  */
+    const Hash_tuning *tuning;
+
+    /* Three functions are given to `hash_initialize', see the documentation
+       block for this function.  In a word, HASHER randomizes a user entry
+       into a number up from 0 up to some maximum minus 1; COMPARATOR returns
+       true if two user entries compare equally; and DATA_FREER is the cleanup
+       function for a user entry.  */
+    Hash_hasher hasher;
+    Hash_comparator comparator;
+    Hash_data_freer data_freer;
+
+    /* A linked list of freed struct hash_entry structs.  */
+    struct hash_entry *free_entry_list;
+
+#if USE_OBSTACK
+    /* Whenever obstacks are used, it is possible to allocate all overflowed
+       entries into a single stack, so they all can be freed in a single
+       operation.  It is not clear if the speedup is worth the trouble.  */
+    struct obstack entry_stack;
+#endif
+  };
+
+/* A hash table contains many internal entries, each holding a pointer to
+   some user provided data (also called a user entry).  An entry indistinctly
+   refers to both the internal entry and its associated user entry.  A user
+   entry contents may be hashed by a randomization function (the hashing
+   function, or just `hasher' for short) into a number (or `slot') between 0
+   and the current table size.  At each slot position in the hash table,
+   starts a linked chain of entries for which the user data all hash to this
+   slot.  A bucket is the collection of all entries hashing to the same slot.
+
+   A good `hasher' function will distribute entries rather evenly in buckets.
+   In the ideal case, the length of each bucket is roughly the number of
+   entries divided by the table size.  Finding the slot for a data is usually
+   done in constant time by the `hasher', and the later finding of a precise
+   entry is linear in time with the size of the bucket.  Consequently, a
+   larger hash table size (that is, a larger number of buckets) is prone to
+   yielding shorter chains, *given* the `hasher' function behaves properly.
+
+   Long buckets slow down the lookup algorithm.  One might use big hash table
+   sizes in hope to reduce the average length of buckets, but this might
+   become inordinate, as unused slots in the hash table take some space.  The
+   best bet is to make sure you are using a good `hasher' function (beware
+   that those are not that easy to write! :-), and to use a table size
+   larger than the actual number of entries.  */
+
+/* If an insertion makes the ratio of nonempty buckets to table size larger
+   than the growth threshold (a number between 0.0 and 1.0), then increase
+   the table size by multiplying by the growth factor (a number greater than
+   1.0).  The growth threshold defaults to 0.8, and the growth factor
+   defaults to 1.414, meaning that the table will have doubled its size
+   every second time 80% of the buckets get used.  */
+#define DEFAULT_GROWTH_THRESHOLD 0.8
+#define DEFAULT_GROWTH_FACTOR 1.414
+
+/* If a deletion empties a bucket and causes the ratio of used buckets to
+   table size to become smaller than the shrink threshold (a number between
+   0.0 and 1.0), then shrink the table by multiplying by the shrink factor (a
+   number greater than the shrink threshold but smaller than 1.0).  The shrink
+   threshold and factor default to 0.0 and 1.0, meaning that the table never
+   shrinks.  */
+#define DEFAULT_SHRINK_THRESHOLD 0.0
+#define DEFAULT_SHRINK_FACTOR 1.0
+
+/* Use this to initialize or reset a TUNING structure to
+   some sensible values. */
+static const Hash_tuning default_tuning =
+  {
+    DEFAULT_SHRINK_THRESHOLD,
+    DEFAULT_SHRINK_FACTOR,
+    DEFAULT_GROWTH_THRESHOLD,
+    DEFAULT_GROWTH_FACTOR,
+    false
+  };
+
+/* Information and lookup.  */
+
+/* The following few functions provide information about the overall hash
+   table organization: the number of entries, number of buckets and maximum
+   length of buckets.  */
+
+/* Return the number of buckets in the hash table.  The table size, the total
+   number of buckets (used plus unused), or the maximum number of slots, are
+   the same quantity.  */
+
+size_t
+hash_get_n_buckets (const Hash_table *table)
+{
+  return table->n_buckets;
+}
+
+/* Return the number of slots in use (non-empty buckets).  */
+
+size_t
+hash_get_n_buckets_used (const Hash_table *table)
+{
+  return table->n_buckets_used;
+}
+
+/* Return the number of active entries.  */
+
+size_t
+hash_get_n_entries (const Hash_table *table)
+{
+  return table->n_entries;
+}
+
+/* Return the length of the longest chain (bucket).  */
+
+size_t
+hash_get_max_bucket_length (const Hash_table *table)
+{
+  struct hash_entry const *bucket;
+  size_t max_bucket_length = 0;
+
+  for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+    {
+      if (bucket->data)
+	{
+	  struct hash_entry const *cursor = bucket;
+	  size_t bucket_length = 1;
+
+	  while (cursor = cursor->next, cursor)
+	    bucket_length++;
+
+	  if (bucket_length > max_bucket_length)
+	    max_bucket_length = bucket_length;
+	}
+    }
+
+  return max_bucket_length;
+}
+
+/* Do a mild validation of a hash table, by traversing it and checking two
+   statistics.  */
+
+bool
+hash_table_ok (const Hash_table *table)
+{
+  struct hash_entry const *bucket;
+  size_t n_buckets_used = 0;
+  size_t n_entries = 0;
+
+  for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+    {
+      if (bucket->data)
+	{
+	  struct hash_entry const *cursor = bucket;
+
+	  /* Count bucket head.  */
+	  n_buckets_used++;
+	  n_entries++;
+
+	  /* Count bucket overflow.  */
+	  while (cursor = cursor->next, cursor)
+	    n_entries++;
+	}
+    }
+
+  if (n_buckets_used == table->n_buckets_used && n_entries == table->n_entries)
+    return true;
+
+  return false;
+}
+
+void
+hash_print_statistics (const Hash_table *table, FILE *stream)
+{
+  size_t n_entries = hash_get_n_entries (table);
+  size_t n_buckets = hash_get_n_buckets (table);
+  size_t n_buckets_used = hash_get_n_buckets_used (table);
+  size_t max_bucket_length = hash_get_max_bucket_length (table);
+
+  fprintf (stream, "# entries:         %lu\n", (unsigned long int) n_entries);
+  fprintf (stream, "# buckets:         %lu\n", (unsigned long int) n_buckets);
+  fprintf (stream, "# buckets used:    %lu (%.2f%%)\n",
+	   (unsigned long int) n_buckets_used,
+	   (100.0 * n_buckets_used) / n_buckets);
+  fprintf (stream, "max bucket length: %lu\n",
+	   (unsigned long int) max_bucket_length);
+}
+
+/* If ENTRY matches an entry already in the hash table, return the
+   entry from the table.  Otherwise, return NULL.  */
+
+void *
+hash_lookup (const Hash_table *table, const void *entry)
+{
+  struct hash_entry const *bucket
+    = table->bucket + table->hasher (entry, table->n_buckets);
+  struct hash_entry const *cursor;
+
+  if (! (bucket < table->bucket_limit))
+    abort ();
+
+  if (bucket->data == NULL)
+    return NULL;
+
+  for (cursor = bucket; cursor; cursor = cursor->next)
+    if (table->comparator (entry, cursor->data))
+      return cursor->data;
+
+  return NULL;
+}
+
+/* Walking.  */
+
+/* The functions in this page traverse the hash table and process the
+   contained entries.  For the traversal to work properly, the hash table
+   should not be resized nor modified while any particular entry is being
+   processed.  In particular, entries should not be added or removed.  */
+
+/* Return the first data in the table, or NULL if the table is empty.  */
+
+void *
+hash_get_first (const Hash_table *table)
+{
+  struct hash_entry const *bucket;
+
+  if (table->n_entries == 0)
+    return NULL;
+
+  for (bucket = table->bucket; ; bucket++)
+    if (! (bucket < table->bucket_limit))
+      abort ();
+    else if (bucket->data)
+      return bucket->data;
+}
+
+/* Return the user data for the entry following ENTRY, where ENTRY has been
+   returned by a previous call to either `hash_get_first' or `hash_get_next'.
+   Return NULL if there are no more entries.  */
+
+void *
+hash_get_next (const Hash_table *table, const void *entry)
+{
+  struct hash_entry const *bucket
+    = table->bucket + table->hasher (entry, table->n_buckets);
+  struct hash_entry const *cursor;
+
+  if (! (bucket < table->bucket_limit))
+    abort ();
+
+  /* Find next entry in the same bucket.  */
+  for (cursor = bucket; cursor; cursor = cursor->next)
+    if (cursor->data == entry && cursor->next)
+      return cursor->next->data;
+
+  /* Find first entry in any subsequent bucket.  */
+  while (++bucket < table->bucket_limit)
+    if (bucket->data)
+      return bucket->data;
+
+  /* None found.  */
+  return NULL;
+}
+
+/* Fill BUFFER with pointers to active user entries in the hash table, then
+   return the number of pointers copied.  Do not copy more than BUFFER_SIZE
+   pointers.  */
+
+size_t
+hash_get_entries (const Hash_table *table, void **buffer,
+		  size_t buffer_size)
+{
+  size_t counter = 0;
+  struct hash_entry const *bucket;
+  struct hash_entry const *cursor;
+
+  for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+    {
+      if (bucket->data)
+	{
+	  for (cursor = bucket; cursor; cursor = cursor->next)
+	    {
+	      if (counter >= buffer_size)
+		return counter;
+	      buffer[counter++] = cursor->data;
+	    }
+	}
+    }
+
+  return counter;
+}
+
+/* Call a PROCESSOR function for each entry of a hash table, and return the
+   number of entries for which the processor function returned success.  A
+   pointer to some PROCESSOR_DATA which will be made available to each call to
+   the processor function.  The PROCESSOR accepts two arguments: the first is
+   the user entry being walked into, the second is the value of PROCESSOR_DATA
+   as received.  The walking continue for as long as the PROCESSOR function
+   returns nonzero.  When it returns zero, the walking is interrupted.  */
+
+size_t
+hash_do_for_each (const Hash_table *table, Hash_processor processor,
+		  void *processor_data)
+{
+  size_t counter = 0;
+  struct hash_entry const *bucket;
+  struct hash_entry const *cursor;
+
+  for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+    {
+      if (bucket->data)
+	{
+	  for (cursor = bucket; cursor; cursor = cursor->next)
+	    {
+	      if (!(*processor) (cursor->data, processor_data))
+		return counter;
+	      counter++;
+	    }
+	}
+    }
+
+  return counter;
+}
+
+/* Allocation and clean-up.  */
+
+/* Return a hash index for a NUL-terminated STRING between 0 and N_BUCKETS-1.
+   This is a convenience routine for constructing other hashing functions.  */
+
+#if USE_DIFF_HASH
+
+/* About hashings, Paul Eggert writes to me (FP), on 1994-01-01: "Please see
+   B. J. McKenzie, R. Harries & T. Bell, Selecting a hashing algorithm,
+   Software--practice & experience 20, 2 (Feb 1990), 209-224.  Good hash
+   algorithms tend to be domain-specific, so what's good for [diffutils'] io.c
+   may not be good for your application."  */
+
+size_t
+hash_string (const char *string, size_t n_buckets)
+{
+# define ROTATE_LEFT(Value, Shift) \
+  ((Value) << (Shift) | (Value) >> ((sizeof (size_t) * CHAR_BIT) - (Shift)))
+# define HASH_ONE_CHAR(Value, Byte) \
+  ((Byte) + ROTATE_LEFT (Value, 7))
+
+  size_t value = 0;
+  unsigned char ch;
+
+  for (; (ch = *string); string++)
+    value = HASH_ONE_CHAR (value, ch);
+  return value % n_buckets;
+
+# undef ROTATE_LEFT
+# undef HASH_ONE_CHAR
+}
+
+#else /* not USE_DIFF_HASH */
+
+/* This one comes from `recode', and performs a bit better than the above as
+   per a few experiments.  It is inspired from a hashing routine found in the
+   very old Cyber `snoop', itself written in typical Greg Mansfield style.
+   (By the way, what happened to this excellent man?  Is he still alive?)  */
+
+size_t
+hash_string (const char *string, size_t n_buckets)
+{
+  size_t value = 0;
+  unsigned char ch;
+
+  for (; (ch = *string); string++)
+    value = (value * 31 + ch) % n_buckets;
+  return value;
+}
+
+#endif /* not USE_DIFF_HASH */
+
+/* Return true if CANDIDATE is a prime number.  CANDIDATE should be an odd
+   number at least equal to 11.  */
+
+static bool
+is_prime (size_t candidate)
+{
+  size_t divisor = 3;
+  size_t square = divisor * divisor;
+
+  while (square < candidate && (candidate % divisor))
+    {
+      divisor++;
+      square += 4 * divisor;
+      divisor++;
+    }
+
+  return (candidate % divisor ? true : false);
+}
+
+/* Round a given CANDIDATE number up to the nearest prime, and return that
+   prime.  Primes lower than 10 are merely skipped.  */
+
+static size_t
+next_prime (size_t candidate)
+{
+  /* Skip small primes.  */
+  if (candidate < 10)
+    candidate = 10;
+
+  /* Make it definitely odd.  */
+  candidate |= 1;
+
+  while (!is_prime (candidate))
+    candidate += 2;
+
+  return candidate;
+}
+
+void
+hash_reset_tuning (Hash_tuning *tuning)
+{
+  *tuning = default_tuning;
+}
+
+/* For the given hash TABLE, check the user supplied tuning structure for
+   reasonable values, and return true if there is no gross error with it.
+   Otherwise, definitively reset the TUNING field to some acceptable default
+   in the hash table (that is, the user loses the right of further modifying
+   tuning arguments), and return false.  */
+
+static bool
+check_tuning (Hash_table *table)
+{
+  const Hash_tuning *tuning = table->tuning;
+
+  /* Be a bit stricter than mathematics would require, so that
+     rounding errors in size calculations do not cause allocations to
+     fail to grow or shrink as they should.  The smallest allocation
+     is 11 (due to next_prime's algorithm), so an epsilon of 0.1
+     should be good enough.  */
+  float epsilon = 0.1f;
+
+  if (epsilon < tuning->growth_threshold
+      && tuning->growth_threshold < 1 - epsilon
+      && 1 + epsilon < tuning->growth_factor
+      && 0 <= tuning->shrink_threshold
+      && tuning->shrink_threshold + epsilon < tuning->shrink_factor
+      && tuning->shrink_factor <= 1
+      && tuning->shrink_threshold + epsilon < tuning->growth_threshold)
+    return true;
+
+  table->tuning = &default_tuning;
+  return false;
+}
+
+/* Allocate and return a new hash table, or NULL upon failure.  The initial
+   number of buckets is automatically selected so as to _guarantee_ that you
+   may insert at least CANDIDATE different user entries before any growth of
+   the hash table size occurs.  So, if have a reasonably tight a-priori upper
+   bound on the number of entries you intend to insert in the hash table, you
+   may save some table memory and insertion time, by specifying it here.  If
+   the IS_N_BUCKETS field of the TUNING structure is true, the CANDIDATE
+   argument has its meaning changed to the wanted number of buckets.
+
+   TUNING points to a structure of user-supplied values, in case some fine
+   tuning is wanted over the default behavior of the hasher.  If TUNING is
+   NULL, the default tuning parameters are used instead.
+
+   The user-supplied HASHER function should be provided.  It accepts two
+   arguments ENTRY and TABLE_SIZE.  It computes, by hashing ENTRY contents, a
+   slot number for that entry which should be in the range 0..TABLE_SIZE-1.
+   This slot number is then returned.
+
+   The user-supplied COMPARATOR function should be provided.  It accepts two
+   arguments pointing to user data, it then returns true for a pair of entries
+   that compare equal, or false otherwise.  This function is internally called
+   on entries which are already known to hash to the same bucket index.
+
+   The user-supplied DATA_FREER function, when not NULL, may be later called
+   with the user data as an argument, just before the entry containing the
+   data gets freed.  This happens from within `hash_free' or `hash_clear'.
+   You should specify this function only if you want these functions to free
+   all of your `data' data.  This is typically the case when your data is
+   simply an auxiliary struct that you have malloc'd to aggregate several
+   values.  */
+
+Hash_table *
+hash_initialize (size_t candidate, const Hash_tuning *tuning,
+		 Hash_hasher hasher, Hash_comparator comparator,
+		 Hash_data_freer data_freer)
+{
+  Hash_table *table;
+
+  if (hasher == NULL || comparator == NULL)
+    return NULL;
+
+  table = malloc (sizeof *table);
+  if (table == NULL)
+    return NULL;
+
+  if (!tuning)
+    tuning = &default_tuning;
+  table->tuning = tuning;
+  if (!check_tuning (table))
+    {
+      /* Fail if the tuning options are invalid.  This is the only occasion
+	 when the user gets some feedback about it.  Once the table is created,
+	 if the user provides invalid tuning options, we silently revert to
+	 using the defaults, and ignore further request to change the tuning
+	 options.  */
+      goto fail;
+    }
+
+  if (!tuning->is_n_buckets)
+    {
+      float new_candidate = candidate / tuning->growth_threshold;
+      if (SIZE_MAX <= new_candidate)
+	goto fail;
+      candidate = new_candidate;
+    }
+
+  if (xalloc_oversized (candidate, sizeof *table->bucket))
+    goto fail;
+  table->n_buckets = next_prime (candidate);
+  if (xalloc_oversized (table->n_buckets, sizeof *table->bucket))
+    goto fail;
+
+  table->bucket = calloc (table->n_buckets, sizeof *table->bucket);
+  table->bucket_limit = table->bucket + table->n_buckets;
+  table->n_buckets_used = 0;
+  table->n_entries = 0;
+
+  table->hasher = hasher;
+  table->comparator = comparator;
+  table->data_freer = data_freer;
+
+  table->free_entry_list = NULL;
+#if USE_OBSTACK
+  obstack_init (&table->entry_stack);
+#endif
+  return table;
+
+ fail:
+  free (table);
+  return NULL;
+}
+
+/* Make all buckets empty, placing any chained entries on the free list.
+   Apply the user-specified function data_freer (if any) to the datas of any
+   affected entries.  */
+
+void
+hash_clear (Hash_table *table)
+{
+  struct hash_entry *bucket;
+
+  for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+    {
+      if (bucket->data)
+	{
+	  struct hash_entry *cursor;
+	  struct hash_entry *next;
+
+	  /* Free the bucket overflow.  */
+	  for (cursor = bucket->next; cursor; cursor = next)
+	    {
+	      if (table->data_freer)
+		(*table->data_freer) (cursor->data);
+	      cursor->data = NULL;
+
+	      next = cursor->next;
+	      /* Relinking is done one entry at a time, as it is to be expected
+		 that overflows are either rare or short.  */
+	      cursor->next = table->free_entry_list;
+	      table->free_entry_list = cursor;
+	    }
+
+	  /* Free the bucket head.  */
+	  if (table->data_freer)
+	    (*table->data_freer) (bucket->data);
+	  bucket->data = NULL;
+	  bucket->next = NULL;
+	}
+    }
+
+  table->n_buckets_used = 0;
+  table->n_entries = 0;
+}
+
+/* Reclaim all storage associated with a hash table.  If a data_freer
+   function has been supplied by the user when the hash table was created,
+   this function applies it to the data of each entry before freeing that
+   entry.  */
+
+void
+hash_free (Hash_table *table)
+{
+  struct hash_entry *bucket;
+  struct hash_entry *cursor;
+  struct hash_entry *next;
+
+  /* Call the user data_freer function.  */
+  if (table->data_freer && table->n_entries)
+    {
+      for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+	{
+	  if (bucket->data)
+	    {
+	      for (cursor = bucket; cursor; cursor = cursor->next)
+		{
+		  (*table->data_freer) (cursor->data);
+		}
+	    }
+	}
+    }
+
+#if USE_OBSTACK
+
+  obstack_free (&table->entry_stack, NULL);
+
+#else
+
+  /* Free all bucket overflowed entries.  */
+  for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+    {
+      for (cursor = bucket->next; cursor; cursor = next)
+	{
+	  next = cursor->next;
+	  free (cursor);
+	}
+    }
+
+  /* Also reclaim the internal list of previously freed entries.  */
+  for (cursor = table->free_entry_list; cursor; cursor = next)
+    {
+      next = cursor->next;
+      free (cursor);
+    }
+
+#endif
+
+  /* Free the remainder of the hash table structure.  */
+  free (table->bucket);
+  free (table);
+}
+
+/* Insertion and deletion.  */
+
+/* Get a new hash entry for a bucket overflow, possibly by reclying a
+   previously freed one.  If this is not possible, allocate a new one.  */
+
+static struct hash_entry *
+allocate_entry (Hash_table *table)
+{
+  struct hash_entry *new;
+
+  if (table->free_entry_list)
+    {
+      new = table->free_entry_list;
+      table->free_entry_list = new->next;
+    }
+  else
+    {
+#if USE_OBSTACK
+      new = obstack_alloc (&table->entry_stack, sizeof *new);
+#else
+      new = malloc (sizeof *new);
+#endif
+    }
+
+  return new;
+}
+
+/* Free a hash entry which was part of some bucket overflow,
+   saving it for later recycling.  */
+
+static void
+free_entry (Hash_table *table, struct hash_entry *entry)
+{
+  entry->data = NULL;
+  entry->next = table->free_entry_list;
+  table->free_entry_list = entry;
+}
+
+/* This private function is used to help with insertion and deletion.  When
+   ENTRY matches an entry in the table, return a pointer to the corresponding
+   user data and set *BUCKET_HEAD to the head of the selected bucket.
+   Otherwise, return NULL.  When DELETE is true and ENTRY matches an entry in
+   the table, unlink the matching entry.  */
+
+static void *
+hash_find_entry (Hash_table *table, const void *entry,
+		 struct hash_entry **bucket_head, bool delete)
+{
+  struct hash_entry *bucket
+    = table->bucket + table->hasher (entry, table->n_buckets);
+  struct hash_entry *cursor;
+
+  if (! (bucket < table->bucket_limit))
+    abort ();
+
+  *bucket_head = bucket;
+
+  /* Test for empty bucket.  */
+  if (bucket->data == NULL)
+    return NULL;
+
+  /* See if the entry is the first in the bucket.  */
+  if ((*table->comparator) (entry, bucket->data))
+    {
+      void *data = bucket->data;
+
+      if (delete)
+	{
+	  if (bucket->next)
+	    {
+	      struct hash_entry *next = bucket->next;
+
+	      /* Bump the first overflow entry into the bucket head, then save
+		 the previous first overflow entry for later recycling.  */
+	      *bucket = *next;
+	      free_entry (table, next);
+	    }
+	  else
+	    {
+	      bucket->data = NULL;
+	    }
+	}
+
+      return data;
+    }
+
+  /* Scan the bucket overflow.  */
+  for (cursor = bucket; cursor->next; cursor = cursor->next)
+    {
+      if ((*table->comparator) (entry, cursor->next->data))
+	{
+	  void *data = cursor->next->data;
+
+	  if (delete)
+	    {
+	      struct hash_entry *next = cursor->next;
+
+	      /* Unlink the entry to delete, then save the freed entry for later
+		 recycling.  */
+	      cursor->next = next->next;
+	      free_entry (table, next);
+	    }
+
+	  return data;
+	}
+    }
+
+  /* No entry found.  */
+  return NULL;
+}
+
+/* For an already existing hash table, change the number of buckets through
+   specifying CANDIDATE.  The contents of the hash table are preserved.  The
+   new number of buckets is automatically selected so as to _guarantee_ that
+   the table may receive at least CANDIDATE different user entries, including
+   those already in the table, before any other growth of the hash table size
+   occurs.  If TUNING->IS_N_BUCKETS is true, then CANDIDATE specifies the
+   exact number of buckets desired.  */
+
+bool
+hash_rehash (Hash_table *table, size_t candidate)
+{
+  Hash_table *new_table;
+  struct hash_entry *bucket;
+  struct hash_entry *cursor;
+  struct hash_entry *next;
+
+  new_table = hash_initialize (candidate, table->tuning, table->hasher,
+			       table->comparator, table->data_freer);
+  if (new_table == NULL)
+    return false;
+
+  /* Merely reuse the extra old space into the new table.  */
+#if USE_OBSTACK
+  obstack_free (&new_table->entry_stack, NULL);
+  new_table->entry_stack = table->entry_stack;
+#endif
+  new_table->free_entry_list = table->free_entry_list;
+
+  for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+    if (bucket->data)
+      for (cursor = bucket; cursor; cursor = next)
+	{
+	  void *data = cursor->data;
+	  struct hash_entry *new_bucket
+	    = (new_table->bucket
+	       + new_table->hasher (data, new_table->n_buckets));
+
+	  if (! (new_bucket < new_table->bucket_limit))
+	    abort ();
+
+	  next = cursor->next;
+
+	  if (new_bucket->data)
+	    {
+	      if (cursor == bucket)
+		{
+		  /* Allocate or recycle an entry, when moving from a bucket
+		     header into a bucket overflow.  */
+		  struct hash_entry *new_entry = allocate_entry (new_table);
+
+		  if (new_entry == NULL)
+		    return false;
+
+		  new_entry->data = data;
+		  new_entry->next = new_bucket->next;
+		  new_bucket->next = new_entry;
+		}
+	      else
+		{
+		  /* Merely relink an existing entry, when moving from a
+		     bucket overflow into a bucket overflow.  */
+		  cursor->next = new_bucket->next;
+		  new_bucket->next = cursor;
+		}
+	    }
+	  else
+	    {
+	      /* Free an existing entry, when moving from a bucket
+		 overflow into a bucket header.  Also take care of the
+		 simple case of moving from a bucket header into a bucket
+		 header.  */
+	      new_bucket->data = data;
+	      new_table->n_buckets_used++;
+	      if (cursor != bucket)
+		free_entry (new_table, cursor);
+	    }
+	}
+
+  free (table->bucket);
+  table->bucket = new_table->bucket;
+  table->bucket_limit = new_table->bucket_limit;
+  table->n_buckets = new_table->n_buckets;
+  table->n_buckets_used = new_table->n_buckets_used;
+  table->free_entry_list = new_table->free_entry_list;
+  /* table->n_entries already holds its value.  */
+#if USE_OBSTACK
+  table->entry_stack = new_table->entry_stack;
+#endif
+  free (new_table);
+
+  return true;
+}
+
+/* If ENTRY matches an entry already in the hash table, return the pointer
+   to the entry from the table.  Otherwise, insert ENTRY and return ENTRY.
+   Return NULL if the storage required for insertion cannot be allocated.  */
+
+void *
+hash_insert (Hash_table *table, const void *entry)
+{
+  void *data;
+  struct hash_entry *bucket;
+
+  /* The caller cannot insert a NULL entry.  */
+  if (! entry)
+    abort ();
+
+  /* If there's a matching entry already in the table, return that.  */
+  if ((data = hash_find_entry (table, entry, &bucket, false)) != NULL)
+    return data;
+
+  /* ENTRY is not matched, it should be inserted.  */
+
+  if (bucket->data)
+    {
+      struct hash_entry *new_entry = allocate_entry (table);
+
+      if (new_entry == NULL)
+	return NULL;
+
+      /* Add ENTRY in the overflow of the bucket.  */
+
+      new_entry->data = (void *) entry;
+      new_entry->next = bucket->next;
+      bucket->next = new_entry;
+      table->n_entries++;
+      return (void *) entry;
+    }
+
+  /* Add ENTRY right in the bucket head.  */
+
+  bucket->data = (void *) entry;
+  table->n_entries++;
+  table->n_buckets_used++;
+
+  /* If the growth threshold of the buckets in use has been reached, increase
+     the table size and rehash.  There's no point in checking the number of
+     entries:  if the hashing function is ill-conditioned, rehashing is not
+     likely to improve it.  */
+
+  if (table->n_buckets_used
+      > table->tuning->growth_threshold * table->n_buckets)
+    {
+      /* Check more fully, before starting real work.  If tuning arguments
+	 became invalid, the second check will rely on proper defaults.  */
+      check_tuning (table);
+      if (table->n_buckets_used
+	  > table->tuning->growth_threshold * table->n_buckets)
+	{
+	  const Hash_tuning *tuning = table->tuning;
+	  float candidate =
+	    (tuning->is_n_buckets
+	     ? (table->n_buckets * tuning->growth_factor)
+	     : (table->n_buckets * tuning->growth_factor
+		* tuning->growth_threshold));
+
+	  if (SIZE_MAX <= candidate)
+	    return NULL;
+
+	  /* If the rehash fails, arrange to return NULL.  */
+	  if (!hash_rehash (table, candidate))
+	    entry = NULL;
+	}
+    }
+
+  return (void *) entry;
+}
+
+/* If ENTRY is already in the table, remove it and return the just-deleted
+   data (the user may want to deallocate its storage).  If ENTRY is not in the
+   table, don't modify the table and return NULL.  */
+
+void *
+hash_delete (Hash_table *table, const void *entry)
+{
+  void *data;
+  struct hash_entry *bucket;
+
+  data = hash_find_entry (table, entry, &bucket, true);
+  if (!data)
+    return NULL;
+
+  table->n_entries--;
+  if (!bucket->data)
+    {
+      table->n_buckets_used--;
+
+      /* If the shrink threshold of the buckets in use has been reached,
+	 rehash into a smaller table.  */
+
+      if (table->n_buckets_used
+	  < table->tuning->shrink_threshold * table->n_buckets)
+	{
+	  /* Check more fully, before starting real work.  If tuning arguments
+	     became invalid, the second check will rely on proper defaults.  */
+	  check_tuning (table);
+	  if (table->n_buckets_used
+	      < table->tuning->shrink_threshold * table->n_buckets)
+	    {
+	      const Hash_tuning *tuning = table->tuning;
+	      size_t candidate =
+		(tuning->is_n_buckets
+		 ? table->n_buckets * tuning->shrink_factor
+		 : (table->n_buckets * tuning->shrink_factor
+		    * tuning->growth_threshold));
+
+	      hash_rehash (table, candidate);
+	    }
+	}
+    }
+
+  return data;
+}
+
+/* Testing.  */
+
+#if TESTING
+
+void
+hash_print (const Hash_table *table)
+{
+  struct hash_entry const *bucket;
+
+  for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+    {
+      struct hash_entry *cursor;
+
+      if (bucket)
+	printf ("%lu:\n", (unsigned long int) (bucket - table->bucket));
+
+      for (cursor = bucket; cursor; cursor = cursor->next)
+	{
+	  char const *s = cursor->data;
+	  /* FIXME */
+	  if (s)
+	    printf ("  %s\n", s);
+	}
+    }
+}
+
+#endif /* TESTING */
diff --git a/lib/hash.h b/lib/hash.h
new file mode 100644
index 0000000..ab63a86
--- /dev/null
+++ b/lib/hash.h
@@ -0,0 +1,88 @@
+/* hash - hashing table processing.
+   Copyright (C) 1998, 1999, 2001, 2003 Free Software Foundation, Inc.
+   Written by Jim Meyering <meyering@ascend.com>, 1998.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* A generic hash table package.  */
+
+/* Make sure USE_OBSTACK is defined to 1 if you want the allocator to use
+   obstacks instead of malloc, and recompile `hash.c' with same setting.  */
+
+#ifndef HASH_H_
+# define HASH_H_
+
+# include <stdio.h>
+# include <stdbool.h>
+
+typedef size_t (*Hash_hasher) (const void *, size_t);
+typedef bool (*Hash_comparator) (const void *, const void *);
+typedef void (*Hash_data_freer) (void *);
+typedef bool (*Hash_processor) (void *, void *);
+
+struct hash_entry
+  {
+    void *data;
+    struct hash_entry *next;
+  };
+
+struct hash_tuning
+  {
+    /* This structure is mainly used for `hash_initialize', see the block
+       documentation of `hash_reset_tuning' for more complete comments.  */
+
+    float shrink_threshold;	/* ratio of used buckets to trigger a shrink */
+    float shrink_factor;	/* ratio of new smaller size to original size */
+    float growth_threshold;	/* ratio of used buckets to trigger a growth */
+    float growth_factor;	/* ratio of new bigger size to original size */
+    bool is_n_buckets;		/* if CANDIDATE really means table size */
+  };
+
+typedef struct hash_tuning Hash_tuning;
+
+struct hash_table;
+
+typedef struct hash_table Hash_table;
+
+/* Information and lookup.  */
+size_t hash_get_n_buckets (const Hash_table *);
+size_t hash_get_n_buckets_used (const Hash_table *);
+size_t hash_get_n_entries (const Hash_table *);
+size_t hash_get_max_bucket_length (const Hash_table *);
+bool hash_table_ok (const Hash_table *);
+void hash_print_statistics (const Hash_table *, FILE *);
+void *hash_lookup (const Hash_table *, const void *);
+
+/* Walking.  */
+void *hash_get_first (const Hash_table *);
+void *hash_get_next (const Hash_table *, const void *);
+size_t hash_get_entries (const Hash_table *, void **, size_t);
+size_t hash_do_for_each (const Hash_table *, Hash_processor, void *);
+
+/* Allocation and clean-up.  */
+size_t hash_string (const char *, size_t);
+void hash_reset_tuning (Hash_tuning *);
+Hash_table *hash_initialize (size_t, const Hash_tuning *,
+			     Hash_hasher, Hash_comparator,
+			     Hash_data_freer);
+void hash_clear (Hash_table *);
+void hash_free (Hash_table *);
+
+/* Insertion and deletion.  */
+bool hash_rehash (Hash_table *, size_t);
+void *hash_insert (Hash_table *, const void *);
+void *hash_delete (Hash_table *, const void *);
+
+#endif
diff --git a/lib/lbitset.c b/lib/lbitset.c
new file mode 100644
index 0000000..7d47a05
--- /dev/null
+++ b/lib/lbitset.c
@@ -0,0 +1,1405 @@
+/* Functions to support link list bitsets.
+   Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+   Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
+
+   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 2 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "lbitset.h"
+#include "obstack.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/* This file implements linked-list bitsets.  These bitsets can be of
+   arbitrary length and are more efficient than arrays of bits for
+   large sparse sets.
+
+   Usually if all the bits in an element are zero we remove the element
+   from the list.  However, a side effect of the bit caching is that we
+   do not always notice when an element becomes zero.  Hence the
+   lbitset_weed function which removes zero elements.  */
+
+
+/* Number of words to use for each element.  The larger the value the
+   greater the size of the cache and the shorter the time to find a given bit
+   but the more memory wasted for sparse bitsets and the longer the time
+   to search for set bits.
+
+   The routines that dominate timing profiles are lbitset_elt_find
+   and lbitset_elt_link, especially when accessing the bits randomly.  */
+
+#define LBITSET_ELT_WORDS 2
+
+typedef bitset_word lbitset_word;
+
+#define LBITSET_WORD_BITS BITSET_WORD_BITS
+
+/* Number of bits stored in each element.  */
+#define LBITSET_ELT_BITS \
+  ((unsigned int) (LBITSET_ELT_WORDS * LBITSET_WORD_BITS))
+
+/* Lbitset element.   We use an array of bits for each element.
+   These are linked together in a doubly-linked list.  */
+typedef struct lbitset_elt_struct
+{
+  struct lbitset_elt_struct *next;	/* Next element.  */
+  struct lbitset_elt_struct *prev;	/* Previous element.  */
+  bitset_windex index;	/* bitno / BITSET_WORD_BITS.  */
+  bitset_word words[LBITSET_ELT_WORDS];	/* Bits that are set.  */
+}
+lbitset_elt;
+
+
+enum lbitset_find_mode
+  { LBITSET_FIND, LBITSET_CREATE, LBITSET_SUBST };
+
+static lbitset_elt lbitset_zero_elts[3]; /* Elements of all zero bits.  */
+
+/* Obstack to allocate bitset elements from.  */
+static struct obstack lbitset_obstack;
+static bool lbitset_obstack_init = false;
+static lbitset_elt *lbitset_free_list;	/* Free list of bitset elements.  */
+
+extern void debug_lbitset (bitset);
+
+#define LBITSET_CURRENT1(X) \
+  ((lbitset_elt *) (void *) ((char *) (X) - offsetof (lbitset_elt, words)))
+
+#define LBITSET_CURRENT(X) LBITSET_CURRENT1((X)->b.cdata)
+
+#define LBITSET_HEAD(X) ((X)->l.head)
+#define LBITSET_TAIL(X) ((X)->l.tail)
+
+/* Allocate a lbitset element.  The bits are not cleared.  */
+static inline lbitset_elt *
+lbitset_elt_alloc (void)
+{
+  lbitset_elt *elt;
+
+  if (lbitset_free_list != 0)
+    {
+      elt = lbitset_free_list;
+      lbitset_free_list = elt->next;
+    }
+  else
+    {
+      if (!lbitset_obstack_init)
+	{
+	  lbitset_obstack_init = true;
+
+	  /* Let particular systems override the size of a chunk.  */
+
+#ifndef OBSTACK_CHUNK_SIZE
+#define OBSTACK_CHUNK_SIZE 0
+#endif
+
+	  /* Let them override the alloc and free routines too.  */
+
+#ifndef OBSTACK_CHUNK_ALLOC
+#define OBSTACK_CHUNK_ALLOC xmalloc
+#endif
+
+#ifndef OBSTACK_CHUNK_FREE
+#define OBSTACK_CHUNK_FREE free
+#endif
+
+#if ! defined __GNUC__ || __GNUC__ < 2
+#define __alignof__(type) 0
+#endif
+
+	  obstack_specify_allocation (&lbitset_obstack, OBSTACK_CHUNK_SIZE,
+				      __alignof__ (lbitset_elt),
+				      OBSTACK_CHUNK_ALLOC,
+				      OBSTACK_CHUNK_FREE);
+	}
+
+      /* Perhaps we should add a number of new elements to the free
+	 list.  */
+      elt = (lbitset_elt *) obstack_alloc (&lbitset_obstack,
+					   sizeof (lbitset_elt));
+    }
+
+  return elt;
+}
+
+
+/* Allocate a lbitset element.  The bits are cleared.  */
+static inline lbitset_elt *
+lbitset_elt_calloc (void)
+{
+  lbitset_elt *elt;
+
+  elt = lbitset_elt_alloc ();
+  memset (elt->words, 0, sizeof (elt->words));
+  return elt;
+}
+
+
+static inline void
+lbitset_elt_free (lbitset_elt *elt)
+{
+  elt->next = lbitset_free_list;
+  lbitset_free_list = elt;
+}
+
+
+/* Unlink element ELT from bitset BSET.  */
+static inline void
+lbitset_elt_unlink (bitset bset, lbitset_elt *elt)
+{
+  lbitset_elt *next = elt->next;
+  lbitset_elt *prev = elt->prev;
+
+  if (prev)
+    prev->next = next;
+
+  if (next)
+    next->prev = prev;
+
+  if (LBITSET_HEAD (bset) == elt)
+    LBITSET_HEAD (bset) = next;
+  if (LBITSET_TAIL (bset) == elt)
+    LBITSET_TAIL (bset) = prev;
+
+  /* Update cache pointer.  Since the first thing we try is to insert
+     before current, make current the next entry in preference to the
+     previous.  */
+  if (LBITSET_CURRENT (bset) == elt)
+    {
+      if (next)
+	{
+	  bset->b.cdata = next->words;
+	  bset->b.cindex = next->index;
+	}
+      else if (prev)
+	{
+	  bset->b.cdata = prev->words;
+	  bset->b.cindex = prev->index;
+	}
+      else
+	{
+	  bset->b.csize = 0;
+	  bset->b.cdata = 0;
+	}
+    }
+
+  lbitset_elt_free (elt);
+}
+
+
+/* Cut the chain of bitset BSET before element ELT and free the
+   elements.  */
+static inline void
+lbitset_prune (bitset bset, lbitset_elt *elt)
+{
+  lbitset_elt *next;
+
+  if (!elt)
+    return;
+
+  if (elt->prev)
+    {
+      LBITSET_TAIL (bset) = elt->prev;
+      bset->b.cdata = elt->prev->words;
+      bset->b.cindex = elt->prev->index;
+      elt->prev->next = 0;
+    }
+  else
+    {
+      LBITSET_HEAD (bset) = 0;
+      LBITSET_TAIL (bset) = 0;
+      bset->b.cdata = 0;
+      bset->b.csize = 0;
+    }
+
+  for (; elt; elt = next)
+    {
+      next = elt->next;
+      lbitset_elt_free (elt);
+    }
+}
+
+
+/* Are all bits in an element zero?  */
+static inline bool
+lbitset_elt_zero_p (lbitset_elt *elt)
+{
+  int i;
+
+  for (i = 0; i < LBITSET_ELT_WORDS; i++)
+    if (elt->words[i])
+      return false;
+
+  return true;
+}
+
+
+/* Link the bitset element into the current bitset linked list.  */
+static inline void
+lbitset_elt_link (bitset bset, lbitset_elt *elt)
+{
+  bitset_windex windex = elt->index;
+  lbitset_elt *ptr;
+  lbitset_elt *current;
+
+  if (bset->b.csize)
+    current = LBITSET_CURRENT (bset);
+  else
+    current = LBITSET_HEAD (bset);
+
+  /* If this is the first and only element, add it in.  */
+  if (LBITSET_HEAD (bset) == 0)
+    {
+      elt->next = elt->prev = 0;
+      LBITSET_HEAD (bset) = elt;
+      LBITSET_TAIL (bset) = elt;
+    }
+
+  /* If this index is less than that of the current element, it goes
+     somewhere before the current element.  */
+  else if (windex < bset->b.cindex)
+    {
+      for (ptr = current;
+	   ptr->prev && ptr->prev->index > windex; ptr = ptr->prev)
+	continue;
+
+      if (ptr->prev)
+	ptr->prev->next = elt;
+      else
+	LBITSET_HEAD (bset) = elt;
+
+      elt->prev = ptr->prev;
+      elt->next = ptr;
+      ptr->prev = elt;
+    }
+
+  /* Otherwise, it must go somewhere after the current element.  */
+  else
+    {
+      for (ptr = current;
+	   ptr->next && ptr->next->index < windex; ptr = ptr->next)
+	continue;
+
+      if (ptr->next)
+	ptr->next->prev = elt;
+      else
+	LBITSET_TAIL (bset) = elt;
+
+      elt->next = ptr->next;
+      elt->prev = ptr;
+      ptr->next = elt;
+    }
+
+  /* Set up so this is the first element searched.  */
+  bset->b.cindex = windex;
+  bset->b.csize = LBITSET_ELT_WORDS;
+  bset->b.cdata = elt->words;
+}
+
+
+static lbitset_elt *
+lbitset_elt_find (bitset bset, bitset_windex windex,
+		  enum lbitset_find_mode mode)
+{
+  lbitset_elt *elt;
+  lbitset_elt *current;
+
+  if (bset->b.csize)
+    {
+      current = LBITSET_CURRENT (bset);
+      /* Check if element is the cached element.  */
+      if ((windex - bset->b.cindex) < bset->b.csize)
+	return current;
+    }
+  else
+    {
+      current = LBITSET_HEAD (bset);
+    }
+
+  if (current)
+    {
+      if (windex < bset->b.cindex)
+	{
+	  for (elt = current;
+	       elt->prev && elt->index > windex; elt = elt->prev)
+	    continue;
+	}
+      else
+	{
+	  for (elt = current;
+	       elt->next && (elt->index + LBITSET_ELT_WORDS - 1) < windex;
+	       elt = elt->next)
+	    continue;
+	}
+
+      /* ELT is the nearest to the one we want.  If it's not the one
+	 we want, the one we want does not exist.  */
+      if (elt && (windex - elt->index) < LBITSET_ELT_WORDS)
+	{
+	  bset->b.cindex = elt->index;
+	  bset->b.csize = LBITSET_ELT_WORDS;
+	  bset->b.cdata = elt->words;
+	  return elt;
+	}
+    }
+
+  switch (mode)
+    {
+    default:
+      abort ();
+
+    case LBITSET_FIND:
+      return 0;
+
+    case LBITSET_CREATE:
+      windex -= windex % LBITSET_ELT_WORDS;
+
+      elt = lbitset_elt_calloc ();
+      elt->index = windex;
+      lbitset_elt_link (bset, elt);
+      return elt;
+
+    case LBITSET_SUBST:
+      return &lbitset_zero_elts[0];
+    }
+}
+
+
+/* Weed out the zero elements from the list.  */
+static inline void
+lbitset_weed (bitset bset)
+{
+  lbitset_elt *elt;
+  lbitset_elt *next;
+
+  for (elt = LBITSET_HEAD (bset); elt; elt = next)
+    {
+      next = elt->next;
+      if (lbitset_elt_zero_p (elt))
+	lbitset_elt_unlink (bset, elt);
+    }
+}
+
+
+/* Set all bits in the bitset to zero.  */
+static void
+lbitset_zero (bitset bset)
+{
+  lbitset_elt *head;
+
+  head = LBITSET_HEAD (bset);
+  if (!head)
+    return;
+
+  /* Clear a bitset by freeing the linked list at the head element.  */
+  lbitset_prune (bset, head);
+}
+
+
+/* Is DST == SRC?  */
+static inline bool
+lbitset_equal_p (bitset dst, bitset src)
+{
+  lbitset_elt *selt;
+  lbitset_elt *delt;
+  int j;
+
+  if (src == dst)
+    return true;
+
+  lbitset_weed (src);
+  lbitset_weed (dst);
+  for (selt = LBITSET_HEAD (src), delt = LBITSET_HEAD (dst);
+       selt && delt; selt = selt->next, delt = delt->next)
+    {
+      if (selt->index != delt->index)
+	return false;
+
+      for (j = 0; j < LBITSET_ELT_WORDS; j++)
+	if (delt->words[j] != selt->words[j])
+	  return false;
+    }
+  return !selt && !delt;
+}
+
+
+/* Copy bits from bitset SRC to bitset DST.  */
+static inline void
+lbitset_copy (bitset dst, bitset src)
+{
+  lbitset_elt *elt;
+  lbitset_elt *head;
+  lbitset_elt *prev;
+  lbitset_elt *tmp;
+
+  if (src == dst)
+    return;
+
+  lbitset_zero (dst);
+
+  head = LBITSET_HEAD (src);
+  if (!head)
+    return;
+
+  prev = 0;
+  for (elt = head; elt; elt = elt->next)
+    {
+      tmp = lbitset_elt_alloc ();
+      tmp->index = elt->index;
+      tmp->prev = prev;
+      tmp->next = 0;
+      if (prev)
+	prev->next = tmp;
+      else
+	LBITSET_HEAD (dst) = tmp;
+      prev = tmp;
+
+      memcpy (tmp->words, elt->words, sizeof (elt->words));
+    }
+  LBITSET_TAIL (dst) = tmp;
+
+  dst->b.csize = LBITSET_ELT_WORDS;
+  dst->b.cdata = LBITSET_HEAD (dst)->words;
+  dst->b.cindex = LBITSET_HEAD (dst)->index;
+}
+
+
+/* Copy bits from bitset SRC to bitset DST.  Return true if
+   bitsets different.  */
+static inline bool
+lbitset_copy_cmp (bitset dst, bitset src)
+{
+  if (src == dst)
+    return false;
+
+  if (!LBITSET_HEAD (dst))
+    {
+      lbitset_copy (dst, src);
+      return LBITSET_HEAD (src) != 0;
+    }
+
+  if (lbitset_equal_p (dst, src))
+    return false;
+
+  lbitset_copy (dst, src);
+  return true;
+}
+
+
+static bitset_bindex
+lbitset_resize (bitset src, bitset_bindex size)
+{
+    BITSET_NBITS_ (src) = size;
+
+    /* Need to prune any excess bits.  FIXME.  */
+    return size;
+}
+
+/* Set bit BITNO in bitset DST.  */
+static void
+lbitset_set (bitset dst, bitset_bindex bitno)
+{
+  bitset_windex windex = bitno / BITSET_WORD_BITS;
+
+  lbitset_elt_find (dst, windex, LBITSET_CREATE);
+
+  dst->b.cdata[windex - dst->b.cindex] |=
+    (bitset_word) 1 << (bitno % BITSET_WORD_BITS);
+}
+
+
+/* Reset bit BITNO in bitset DST.  */
+static void
+lbitset_reset (bitset dst, bitset_bindex bitno)
+{
+  bitset_windex windex = bitno / BITSET_WORD_BITS;
+
+  if (!lbitset_elt_find (dst, windex, LBITSET_FIND))
+    return;
+
+  dst->b.cdata[windex - dst->b.cindex] &=
+    ~((bitset_word) 1 << (bitno % BITSET_WORD_BITS));
+
+  /* If all the data is zero, perhaps we should unlink it now...  */
+}
+
+
+/* Test bit BITNO in bitset SRC.  */
+static bool
+lbitset_test (bitset src, bitset_bindex bitno)
+{
+  bitset_windex windex = bitno / BITSET_WORD_BITS;
+
+  return (lbitset_elt_find (src, windex, LBITSET_FIND)
+	  && ((src->b.cdata[windex - src->b.cindex]
+	       >> (bitno % BITSET_WORD_BITS))
+	      & 1));
+}
+
+
+static void
+lbitset_free (bitset bset)
+{
+  lbitset_zero (bset);
+}
+
+
+/* Find list of up to NUM bits set in BSET starting from and including
+ *NEXT and store in array LIST.  Return with actual number of bits
+ found and with *NEXT indicating where search stopped.  */
+static bitset_bindex
+lbitset_list_reverse (bitset bset, bitset_bindex *list,
+		      bitset_bindex num, bitset_bindex *next)
+{
+  bitset_bindex rbitno;
+  bitset_bindex bitno;
+  unsigned int bcount;
+  bitset_bindex boffset;
+  bitset_windex windex;
+  bitset_bindex count;
+  lbitset_elt *elt;
+  bitset_word word;
+  bitset_bindex n_bits;
+
+  elt = LBITSET_TAIL (bset);
+  if (!elt)
+    return 0;
+
+  n_bits = (elt->index + LBITSET_ELT_WORDS) * BITSET_WORD_BITS;
+  rbitno = *next;
+
+  if (rbitno >= n_bits)
+    return 0;
+
+  bitno = n_bits - (rbitno + 1);
+
+  windex = bitno / BITSET_WORD_BITS;
+
+  /* Skip back to starting element.  */
+  for (; elt && elt->index > windex; elt = elt->prev)
+    continue;
+
+  if (!elt)
+    return 0;
+
+  if (windex >= elt->index + LBITSET_ELT_WORDS)
+    {
+      /* We are trying to start in no-mans land so start
+	 at end of current elt.  */
+      bcount = BITSET_WORD_BITS - 1;
+      windex = elt->index + LBITSET_ELT_WORDS - 1;
+    }
+  else
+    {
+      bcount = bitno % BITSET_WORD_BITS;
+    }
+
+  count = 0;
+  boffset = windex * BITSET_WORD_BITS;
+
+  /* If num is 1, we could speed things up with a binary search
+     of the word of interest.  */
+
+  while (elt)
+    {
+      bitset_word *srcp = elt->words;
+
+      for (; (windex - elt->index) < LBITSET_ELT_WORDS;
+	   windex--, boffset -= BITSET_WORD_BITS,
+	     bcount = BITSET_WORD_BITS - 1)
+	{
+	  word =
+	    srcp[windex - elt->index] << (BITSET_WORD_BITS - 1 - bcount);
+
+	  for (; word; bcount--)
+	    {
+	      if (word & BITSET_MSB)
+		{
+		  list[count++] = boffset + bcount;
+		  if (count >= num)
+		    {
+		      *next = n_bits - (boffset + bcount);
+		      return count;
+		    }
+		}
+	      word <<= 1;
+	    }
+	}
+
+      elt = elt->prev;
+      if (elt)
+	{
+	  windex = elt->index + LBITSET_ELT_WORDS - 1;
+	  boffset = windex * BITSET_WORD_BITS;
+	}
+    }
+
+  *next = n_bits - (boffset + 1);
+  return count;
+}
+
+
+/* Find list of up to NUM bits set in BSET starting from and including
+ *NEXT and store in array LIST.  Return with actual number of bits
+ found and with *NEXT indicating where search stopped.  */
+static bitset_bindex
+lbitset_list (bitset bset, bitset_bindex *list,
+	      bitset_bindex num, bitset_bindex *next)
+{
+  bitset_bindex bitno;
+  bitset_windex windex;
+  bitset_bindex count;
+  lbitset_elt *elt;
+  lbitset_elt *head;
+  bitset_word word;
+
+  head = LBITSET_HEAD (bset);
+  if (!head)
+    return 0;
+
+  bitno = *next;
+  count = 0;
+
+  if (!bitno)
+    {
+      /* This is the most common case.  */
+
+      /* Start with the first element.  */
+      elt = head;
+      windex = elt->index;
+      bitno = windex * BITSET_WORD_BITS;
+    }
+  else
+    {
+      windex = bitno / BITSET_WORD_BITS;
+
+      /* Skip to starting element.  */
+      for (elt = head;
+	   elt && (elt->index + LBITSET_ELT_WORDS - 1) < windex;
+	   elt = elt->next)
+	continue;
+
+      if (!elt)
+	return 0;
+
+      if (windex < elt->index)
+	{
+	  windex = elt->index;
+	  bitno = windex * BITSET_WORD_BITS;
+	}
+      else
+	{
+	  bitset_word *srcp = elt->words;
+
+	  /* We are starting within an element.  */
+
+	  for (; (windex - elt->index) < LBITSET_ELT_WORDS; windex++)
+	    {
+	      word = srcp[windex - elt->index] >> (bitno % BITSET_WORD_BITS);
+
+	      for (; word; bitno++)
+		{
+		  if (word & 1)
+		    {
+		      list[count++] = bitno;
+		      if (count >= num)
+			{
+			  *next = bitno + 1;
+			  return count;
+			}
+		    }
+		  word >>= 1;
+		}
+	      bitno = (windex + 1) * BITSET_WORD_BITS;
+	    }
+
+	  elt = elt->next;
+	  if (elt)
+	    {
+	      windex = elt->index;
+	      bitno = windex * BITSET_WORD_BITS;
+	    }
+	}
+    }
+
+
+  /* If num is 1, we could speed things up with a binary search
+     of the word of interest.  */
+
+  while (elt)
+    {
+      int i;
+      bitset_word *srcp = elt->words;
+
+      if ((count + LBITSET_ELT_BITS) < num)
+	{
+	  /* The coast is clear, plant boot!  */
+
+#if LBITSET_ELT_WORDS == 2
+	  word = srcp[0];
+	  if (word)
+	    {
+	      if (!(word & 0xffff))
+		{
+		  word >>= 16;
+		  bitno += 16;
+		}
+	      if (!(word & 0xff))
+		{
+		  word >>= 8;
+		  bitno += 8;
+		}
+	      for (; word; bitno++)
+		{
+		  if (word & 1)
+		    list[count++] = bitno;
+		  word >>= 1;
+		}
+	    }
+	  windex++;
+	  bitno = windex * BITSET_WORD_BITS;
+
+	  word = srcp[1];
+	  if (word)
+	    {
+	      if (!(word & 0xffff))
+		{
+		  word >>= 16;
+		  bitno += 16;
+		}
+	      for (; word; bitno++)
+		{
+		  if (word & 1)
+		    list[count++] = bitno;
+		  word >>= 1;
+		}
+	    }
+	  windex++;
+	  bitno = windex * BITSET_WORD_BITS;
+#else
+	  for (i = 0; i < LBITSET_ELT_WORDS; i++)
+	    {
+	      word = srcp[i];
+	      if (word)
+		{
+		  if (!(word & 0xffff))
+		    {
+		      word >>= 16;
+		      bitno += 16;
+		    }
+		  if (!(word & 0xff))
+		    {
+		      word >>= 8;
+		      bitno += 8;
+		    }
+		  for (; word; bitno++)
+		    {
+		      if (word & 1)
+			list[count++] = bitno;
+		      word >>= 1;
+		    }
+		}
+	      windex++;
+	      bitno = windex * BITSET_WORD_BITS;
+	    }
+#endif
+	}
+      else
+	{
+	  /* Tread more carefully since we need to check
+	     if array overflows.  */
+
+	  for (i = 0; i < LBITSET_ELT_WORDS; i++)
+	    {
+	      for (word = srcp[i]; word; bitno++)
+		{
+		  if (word & 1)
+		    {
+		      list[count++] = bitno;
+		      if (count >= num)
+			{
+			  *next = bitno + 1;
+			  return count;
+			}
+		    }
+		  word >>= 1;
+		}
+	      windex++;
+	      bitno = windex * BITSET_WORD_BITS;
+	    }
+	}
+
+      elt = elt->next;
+      if (elt)
+	{
+	  windex = elt->index;
+	  bitno = windex * BITSET_WORD_BITS;
+	}
+    }
+
+  *next = bitno;
+  return count;
+}
+
+
+static bool
+lbitset_empty_p (bitset dst)
+{
+  lbitset_elt *elt;
+  lbitset_elt *next;
+
+  for (elt = LBITSET_HEAD (dst); elt; elt = next)
+    {
+      next = elt->next;
+      if (!lbitset_elt_zero_p (elt))
+	return 0;
+      /* Weed as we go.  */
+      lbitset_elt_unlink (dst, elt);
+    }
+
+  return 1;
+}
+
+
+/* Ensure that any unused bits within the last element are clear.  */
+static inline void
+lbitset_unused_clear (bitset dst)
+{
+  unsigned int last_bit;
+  bitset_bindex n_bits;
+
+  n_bits = BITSET_SIZE_ (dst);
+  last_bit = n_bits % LBITSET_ELT_BITS;
+
+  if (last_bit)
+    {
+      lbitset_elt *elt;
+      bitset_windex windex;
+      bitset_word *srcp;
+
+      elt = LBITSET_TAIL (dst);
+      srcp = elt->words;
+      windex = n_bits / BITSET_WORD_BITS;
+
+      srcp[windex - elt->index] &= ((bitset_word) 1 << last_bit) - 1;
+      windex++;
+
+      for (; (windex - elt->index) < LBITSET_ELT_WORDS; windex++)
+	srcp[windex - elt->index] = 0;
+    }
+}
+
+
+static void
+lbitset_ones (bitset dst)
+{
+  bitset_windex i;
+  bitset_windex windex;
+  lbitset_elt *elt;
+
+  /* This is a decidedly unfriendly operation for a linked list
+      bitset!  It makes a sparse bitset become dense.  An alternative
+      is to have a flag that indicates that the bitset stores the
+      complement of what it indicates.  */
+
+  windex = (BITSET_SIZE_ (dst) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS;
+
+  for (i = 0; i < windex; i += LBITSET_ELT_WORDS)
+    {
+      /* Create new elements if they cannot be found.  */
+      elt = lbitset_elt_find (dst, i, LBITSET_CREATE);
+      memset (elt->words, -1, sizeof (elt->words));
+    }
+
+  lbitset_unused_clear (dst);
+}
+
+
+static void
+lbitset_not (bitset dst, bitset src)
+{
+  lbitset_elt *elt;
+  lbitset_elt *selt;
+  lbitset_elt *delt;
+  bitset_windex i;
+  unsigned int j;
+  bitset_windex windex;
+
+  /* This is another unfriendly operation for a linked list
+     bitset!  */
+  elt = LBITSET_TAIL (dst);
+
+  windex = (BITSET_SIZE_ (dst) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS;
+
+  for (i = 0; i < windex; i += LBITSET_ELT_WORDS)
+    {
+      /* Create new elements for dst if they cannot be found
+	 or substitute zero elements if src elements not found.  */
+      selt = lbitset_elt_find (src, i, LBITSET_SUBST);
+      delt = lbitset_elt_find (dst, i, LBITSET_CREATE);
+
+      for (j = 0; j < LBITSET_ELT_WORDS; j++)
+	delt->words[j] = ~selt->words[j];
+    }
+  lbitset_unused_clear (dst);
+  lbitset_weed (dst);
+  return;
+}
+
+
+/* Is DST == DST | SRC?  */
+static bool
+lbitset_subset_p (bitset dst, bitset src)
+{
+  lbitset_elt *selt;
+  lbitset_elt *delt;
+  unsigned int j;
+
+  for (selt = LBITSET_HEAD (src), delt = LBITSET_HEAD (dst);
+       selt || delt; selt = selt->next, delt = delt->next)
+    {
+      if (!selt)
+	selt = &lbitset_zero_elts[0];
+      else if (!delt)
+	delt = &lbitset_zero_elts[0];
+      else if (selt->index != delt->index)
+	{
+	  if (selt->index < delt->index)
+	    {
+	      lbitset_zero_elts[2].next = delt;
+	      delt = &lbitset_zero_elts[2];
+	    }
+	  else
+	    {
+	      lbitset_zero_elts[1].next = selt;
+	      selt = &lbitset_zero_elts[1];
+	    }
+	}
+
+      for (j = 0; j < LBITSET_ELT_WORDS; j++)
+	if (delt->words[j] != (selt->words[j] | delt->words[j]))
+	  return false;
+    }
+  return true;
+}
+
+
+/* Is DST & SRC == 0?  */
+static bool
+lbitset_disjoint_p (bitset dst, bitset src)
+{
+  lbitset_elt *selt;
+  lbitset_elt *delt;
+  unsigned int j;
+
+  for (selt = LBITSET_HEAD (src), delt = LBITSET_HEAD (dst);
+       selt && delt; selt = selt->next, delt = delt->next)
+    {
+      if (selt->index != delt->index)
+	{
+	  if (selt->index < delt->index)
+	    {
+	      lbitset_zero_elts[2].next = delt;
+	      delt = &lbitset_zero_elts[2];
+	    }
+	  else
+	    {
+	      lbitset_zero_elts[1].next = selt;
+	      selt = &lbitset_zero_elts[1];
+	    }
+	  /* Since the elements are different, there is no
+	     intersection of these elements.  */
+	  continue;
+	}
+
+      for (j = 0; j < LBITSET_ELT_WORDS; j++)
+	if (selt->words[j] & delt->words[j])
+	  return false;
+    }
+  return true;
+}
+
+
+static bool
+lbitset_op3_cmp (bitset dst, bitset src1, bitset src2, enum bitset_ops op)
+{
+  lbitset_elt *selt1 = LBITSET_HEAD (src1);
+  lbitset_elt *selt2 = LBITSET_HEAD (src2);
+  lbitset_elt *delt = LBITSET_HEAD (dst);
+  bitset_windex windex1;
+  bitset_windex windex2;
+  bitset_windex windex;
+  lbitset_elt *stmp1;
+  lbitset_elt *stmp2;
+  lbitset_elt *dtmp;
+  bitset_word *srcp1;
+  bitset_word *srcp2;
+  bitset_word *dstp;
+  bool changed = false;
+  unsigned int i;
+
+  LBITSET_HEAD (dst) = 0;
+  dst->b.csize = 0;
+
+  windex1 = (selt1) ? selt1->index : BITSET_WINDEX_MAX;
+  windex2 = (selt2) ? selt2->index : BITSET_WINDEX_MAX;
+
+  while (selt1 || selt2)
+    {
+      /* Figure out whether we need to substitute zero elements for
+	 missing links.  */
+      if (windex1 == windex2)
+	{
+	  windex = windex1;
+	  stmp1 = selt1;
+	  stmp2 = selt2;
+	  selt1 = selt1->next;
+	  windex1 = (selt1) ? selt1->index : BITSET_WINDEX_MAX;
+	  selt2 = selt2->next;
+	  windex2 = (selt2) ? selt2->index : BITSET_WINDEX_MAX;
+	}
+      else if (windex1 < windex2)
+	{
+	  windex = windex1;
+	  stmp1 = selt1;
+	  stmp2 = &lbitset_zero_elts[0];
+	  selt1 = selt1->next;
+	  windex1 = (selt1) ? selt1->index : BITSET_WINDEX_MAX;
+	}
+      else
+	{
+	  windex = windex2;
+	  stmp1 = &lbitset_zero_elts[0];
+	  stmp2 = selt2;
+	  selt2 = selt2->next;
+	  windex2 = (selt2) ? selt2->index : BITSET_WINDEX_MAX;
+	}
+
+      /* Find the appropriate element from DST.  Begin by discarding
+	 elements that we've skipped.  */
+      while (delt && delt->index < windex)
+	{
+	  changed = true;
+	  dtmp = delt;
+	  delt = delt->next;
+	  lbitset_elt_free (dtmp);
+	}
+      if (delt && delt->index == windex)
+	{
+	  dtmp = delt;
+	  delt = delt->next;
+	}
+      else
+	dtmp = lbitset_elt_calloc ();
+
+      /* Do the operation, and if any bits are set, link it into the
+	 linked list.  */
+      srcp1 = stmp1->words;
+      srcp2 = stmp2->words;
+      dstp = dtmp->words;
+      switch (op)
+	{
+	default:
+	  abort ();
+
+	case BITSET_OP_OR:
+	  for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++)
+	    {
+	      bitset_word tmp = *srcp1++ | *srcp2++;
+
+	      if (*dstp != tmp)
+		{
+		  changed = true;
+		  *dstp = tmp;
+		}
+	    }
+	  break;
+
+	case BITSET_OP_AND:
+	  for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++)
+	    {
+	      bitset_word tmp = *srcp1++ & *srcp2++;
+
+	      if (*dstp != tmp)
+		{
+		  changed = true;
+		  *dstp = tmp;
+		}
+	    }
+	  break;
+
+	case BITSET_OP_XOR:
+	  for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++)
+	    {
+	      bitset_word tmp = *srcp1++ ^ *srcp2++;
+
+	      if (*dstp != tmp)
+		{
+		  changed = true;
+		  *dstp = tmp;
+		}
+	    }
+	  break;
+
+	case BITSET_OP_ANDN:
+	  for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++)
+	    {
+	      bitset_word tmp = *srcp1++ & ~(*srcp2++);
+
+	      if (*dstp != tmp)
+		{
+		  changed = true;
+		  *dstp = tmp;
+		}
+	    }
+	  break;
+	}
+
+      if (!lbitset_elt_zero_p (dtmp))
+	{
+	  dtmp->index = windex;
+	  /* Perhaps this could be optimised...  */
+	  lbitset_elt_link (dst, dtmp);
+	}
+      else
+	{
+	  lbitset_elt_free (dtmp);
+	}
+    }
+
+  /* If we have elements of DST left over, free them all.  */
+  if (delt)
+    {
+      changed = true;
+      lbitset_prune (dst, delt);
+    }
+
+  return changed;
+}
+
+
+static bool
+lbitset_and_cmp (bitset dst, bitset src1, bitset src2)
+{
+  lbitset_elt *selt1 = LBITSET_HEAD (src1);
+  lbitset_elt *selt2 = LBITSET_HEAD (src2);
+  bool changed;
+
+  if (!selt2)
+    {
+      lbitset_weed (dst);
+      changed = !LBITSET_HEAD (dst);
+      lbitset_zero (dst);
+      return changed;
+    }
+  else if (!selt1)
+    {
+      lbitset_weed (dst);
+      changed = !LBITSET_HEAD (dst);
+      lbitset_zero (dst);
+      return changed;
+    }
+  return lbitset_op3_cmp (dst, src1, src2, BITSET_OP_AND);
+}
+
+
+static void
+lbitset_and (bitset dst, bitset src1, bitset src2)
+{
+  lbitset_and_cmp (dst, src1, src2);
+}
+
+
+static bool
+lbitset_andn_cmp (bitset dst, bitset src1, bitset src2)
+{
+  lbitset_elt *selt1 = LBITSET_HEAD (src1);
+  lbitset_elt *selt2 = LBITSET_HEAD (src2);
+  bool changed;
+
+  if (!selt2)
+    {
+      return lbitset_copy_cmp (dst, src1);
+    }
+  else if (!selt1)
+    {
+      lbitset_weed (dst);
+      changed = !LBITSET_HEAD (dst);
+      lbitset_zero (dst);
+      return changed;
+    }
+  return lbitset_op3_cmp (dst, src1, src2, BITSET_OP_ANDN);
+}
+
+
+static void
+lbitset_andn (bitset dst, bitset src1, bitset src2)
+{
+  lbitset_andn_cmp (dst, src1, src2);
+}
+
+
+static bool
+lbitset_or_cmp (bitset dst, bitset src1, bitset src2)
+{
+  lbitset_elt *selt1 = LBITSET_HEAD (src1);
+  lbitset_elt *selt2 = LBITSET_HEAD (src2);
+
+  if (!selt2)
+    {
+      return lbitset_copy_cmp (dst, src1);
+    }
+  else if (!selt1)
+    {
+      return lbitset_copy_cmp (dst, src2);
+    }
+  return lbitset_op3_cmp (dst, src1, src2, BITSET_OP_OR);
+}
+
+
+static void
+lbitset_or (bitset dst, bitset src1, bitset src2)
+{
+  lbitset_or_cmp (dst, src1, src2);
+}
+
+
+static bool
+lbitset_xor_cmp (bitset dst, bitset src1, bitset src2)
+{
+  lbitset_elt *selt1 = LBITSET_HEAD (src1);
+  lbitset_elt *selt2 = LBITSET_HEAD (src2);
+
+  if (!selt2)
+    {
+      return lbitset_copy_cmp (dst, src1);
+    }
+  else if (!selt1)
+    {
+      return lbitset_copy_cmp (dst, src2);
+    }
+  return lbitset_op3_cmp (dst, src1, src2, BITSET_OP_XOR);
+}
+
+
+static void
+lbitset_xor (bitset dst, bitset src1, bitset src2)
+{
+  lbitset_xor_cmp (dst, src1, src2);
+}
+
+
+
+/* Vector of operations for linked-list bitsets.  */
+struct bitset_vtable lbitset_vtable = {
+  lbitset_set,
+  lbitset_reset,
+  bitset_toggle_,
+  lbitset_test,
+  lbitset_resize,
+  bitset_size_,
+  bitset_count_,
+  lbitset_empty_p,
+  lbitset_ones,
+  lbitset_zero,
+  lbitset_copy,
+  lbitset_disjoint_p,
+  lbitset_equal_p,
+  lbitset_not,
+  lbitset_subset_p,
+  lbitset_and,
+  lbitset_and_cmp,
+  lbitset_andn,
+  lbitset_andn_cmp,
+  lbitset_or,
+  lbitset_or_cmp,
+  lbitset_xor,
+  lbitset_xor_cmp,
+  bitset_and_or_,
+  bitset_and_or_cmp_,
+  bitset_andn_or_,
+  bitset_andn_or_cmp_,
+  bitset_or_and_,
+  bitset_or_and_cmp_,
+  lbitset_list,
+  lbitset_list_reverse,
+  lbitset_free,
+  BITSET_LIST
+};
+
+
+/* Return size of initial structure.  */
+size_t
+lbitset_bytes (bitset_bindex n_bits ATTRIBUTE_UNUSED)
+{
+  return sizeof (struct lbitset_struct);
+}
+
+
+/* Initialize a bitset.  */
+bitset
+lbitset_init (bitset bset, bitset_bindex n_bits ATTRIBUTE_UNUSED)
+{
+  BITSET_NBITS_ (bset) = n_bits;
+  bset->b.vtable = &lbitset_vtable;
+  return bset;
+}
+
+
+void
+lbitset_release_memory (void)
+{
+  lbitset_free_list = 0;
+  if (lbitset_obstack_init)
+    {
+      lbitset_obstack_init = false;
+      obstack_free (&lbitset_obstack, NULL);
+    }
+}
+
+
+/* Function to be called from debugger to debug lbitset.  */
+void
+debug_lbitset (bitset bset)
+{
+  lbitset_elt *elt;
+  unsigned int i;
+
+  if (!bset)
+    return;
+
+  for (elt = LBITSET_HEAD (bset); elt; elt = elt->next)
+    {
+      fprintf (stderr, "Elt %lu\n", (unsigned long int) elt->index);
+      for (i = 0; i < LBITSET_ELT_WORDS; i++)
+	{
+	  unsigned int j;
+	  bitset_word word;
+
+	  word = elt->words[i];
+
+	  fprintf (stderr, "  Word %u:", i);
+	  for (j = 0; j < LBITSET_WORD_BITS; j++)
+	    if ((word & ((bitset_word) 1 << j)))
+	      fprintf (stderr, " %u", j);
+	  fprintf (stderr, "\n");
+	}
+    }
+}
diff --git a/lib/lbitset.h b/lib/lbitset.h
new file mode 100644
index 0000000..aaad834
--- /dev/null
+++ b/lib/lbitset.h
@@ -0,0 +1,30 @@
+/* Functions to support lbitsets.
+   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+   Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
+
+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 2 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, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _LBITSET_H
+#define _LBITSET_H
+
+#include "bitset.h"
+
+extern size_t lbitset_bytes (bitset_bindex);
+
+extern bitset lbitset_init (bitset, bitset_bindex);
+
+extern void lbitset_release_memory (void);
+
+#endif
diff --git a/lib/libiberty.h b/lib/libiberty.h
new file mode 100644
index 0000000..e8629e4
--- /dev/null
+++ b/lib/libiberty.h
@@ -0,0 +1,36 @@
+/* Fake libiberty.h for Bison.
+   Copyright (C) 2002, 2003, 2004 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+
+/* Bison depends on libiberty's implementation of bitsets, which
+   requires a `libiberty.h' file.  This file provides the minimum
+   services.  */
+
+#ifndef BISON_LIBIBERTY_H_
+# define BISON_LIBIBERTY_H_ 1
+
+# ifndef __attribute__
+#  if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
+#   define __attribute__(x)
+#  endif
+# endif
+
+# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+
+# include "xalloc.h"
+
+#endif /* ! BISON_LIBIBERTY_H_ */
diff --git a/lib/main.c b/lib/main.c
new file mode 100644
index 0000000..98dedf9
--- /dev/null
+++ b/lib/main.c
@@ -0,0 +1,38 @@
+/* Yacc library main function.
+
+   Copyright (C) 2002 Free Software Foundation, Inc.
+
+   This file is part of Bison, the GNU Compiler Compiler.
+
+   Bison 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 2, or (at your option)
+   any later version.
+
+   Bison 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 Bison; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+#include <config.h>
+
+#if HAVE_LOCALE_H
+# include <locale.h>
+#endif
+#if ! HAVE_SETLOCALE
+# define setlocale(Category, Locale)
+#endif
+
+int yyparse (void);
+
+int
+main (void)
+{
+  setlocale (LC_ALL, "");
+  return yyparse ();
+}
diff --git a/lib/malloc.c b/lib/malloc.c
new file mode 100644
index 0000000..58fa611
--- /dev/null
+++ b/lib/malloc.c
@@ -0,0 +1,36 @@
+/* malloc() function that is glibc compatible.
+   Copyright (C) 1997, 1998 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* written by Jim Meyering */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#undef malloc
+
+#include <stdlib.h>
+
+/* Allocate an N-byte block of memory from the heap.
+   If N is zero, allocate a 1-byte block.  */
+
+void *
+rpl_malloc (size_t n)
+{
+  if (n == 0)
+    n = 1;
+  return malloc (n);
+}
diff --git a/lib/mbswidth.c b/lib/mbswidth.c
new file mode 100644
index 0000000..c9e78d6
--- /dev/null
+++ b/lib/mbswidth.c
@@ -0,0 +1,221 @@
+/* Determine the number of screen columns needed for a string.
+   Copyright (C) 2000-2005 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Bruno Haible <haible@clisp.cons.org>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification.  */
+#include "mbswidth.h"
+
+/* Get MB_CUR_MAX.  */
+#include <stdlib.h>
+
+#include <string.h>
+
+/* Get isprint().  */
+#include <ctype.h>
+
+/* Get mbstate_t, mbrtowc(), mbsinit(), wcwidth().  */
+#if HAVE_WCHAR_H
+/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
+   <wchar.h>.
+   BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before
+   <wchar.h>.  */
+# include <stdio.h>
+# include <time.h>
+# include <wchar.h>
+#endif
+
+/* Get iswprint(), iswcntrl().  */
+#if HAVE_WCTYPE_H
+# include <wctype.h>
+#endif
+#if !defined iswprint && !HAVE_ISWPRINT
+# define iswprint(wc) 1
+#endif
+#if !defined iswcntrl && !HAVE_ISWCNTRL
+# define iswcntrl(wc) 0
+#endif
+
+#ifndef mbsinit
+# if !HAVE_MBSINIT
+#  define mbsinit(ps) 1
+# endif
+#endif
+
+#ifndef HAVE_DECL_WCWIDTH
+"this configure-time declaration test was not run"
+#endif
+#if !HAVE_DECL_WCWIDTH
+int wcwidth ();
+#endif
+
+#ifndef wcwidth
+# if !HAVE_WCWIDTH
+/* wcwidth doesn't exist, so assume all printable characters have
+   width 1.  */
+#  define wcwidth(wc) ((wc) == 0 ? 0 : iswprint (wc) ? 1 : -1)
+# endif
+#endif
+
+/* Get ISPRINT.  */
+#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
+# define IN_CTYPE_DOMAIN(c) 1
+#else
+# define IN_CTYPE_DOMAIN(c) isascii(c)
+#endif
+/* Undefine to protect against the definition in wctype.h of Solaris 2.6.   */
+#undef ISPRINT
+#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
+#undef ISCNTRL
+#define ISCNTRL(c) (IN_CTYPE_DOMAIN (c) && iscntrl (c))
+
+/* Returns the number of columns needed to represent the multibyte
+   character string pointed to by STRING.  If a non-printable character
+   occurs, and MBSW_REJECT_UNPRINTABLE is specified, -1 is returned.
+   With flags = MBSW_REJECT_INVALID | MBSW_REJECT_UNPRINTABLE, this is
+   the multibyte analogue of the wcswidth function.
+   If STRING is not of length < INT_MAX / 2, integer overflow can occur.  */
+int
+mbswidth (const char *string, int flags)
+{
+  return mbsnwidth (string, strlen (string), flags);
+}
+
+/* Returns the number of columns needed to represent the multibyte
+   character string pointed to by STRING of length NBYTES.  If a
+   non-printable character occurs, and MBSW_REJECT_UNPRINTABLE is
+   specified, -1 is returned.
+   If NBYTES is not < INT_MAX / 2, integer overflow can occur.  */
+int
+mbsnwidth (const char *string, size_t nbytes, int flags)
+{
+  const char *p = string;
+  const char *plimit = p + nbytes;
+  int width;
+
+  width = 0;
+#if HAVE_MBRTOWC
+  if (MB_CUR_MAX > 1)
+    {
+      while (p < plimit)
+	switch (*p)
+	  {
+	    case ' ': case '!': case '"': case '#': case '%':
+	    case '&': case '\'': case '(': case ')': case '*':
+	    case '+': case ',': case '-': case '.': case '/':
+	    case '0': case '1': case '2': case '3': case '4':
+	    case '5': case '6': case '7': case '8': case '9':
+	    case ':': case ';': case '<': case '=': case '>':
+	    case '?':
+	    case 'A': case 'B': case 'C': case 'D': case 'E':
+	    case 'F': case 'G': case 'H': case 'I': case 'J':
+	    case 'K': case 'L': case 'M': case 'N': case 'O':
+	    case 'P': case 'Q': case 'R': case 'S': case 'T':
+	    case 'U': case 'V': case 'W': case 'X': case 'Y':
+	    case 'Z':
+	    case '[': case '\\': case ']': case '^': case '_':
+	    case 'a': case 'b': case 'c': case 'd': case 'e':
+	    case 'f': case 'g': case 'h': case 'i': case 'j':
+	    case 'k': case 'l': case 'm': case 'n': case 'o':
+	    case 'p': case 'q': case 'r': case 's': case 't':
+	    case 'u': case 'v': case 'w': case 'x': case 'y':
+	    case 'z': case '{': case '|': case '}': case '~':
+	      /* These characters are printable ASCII characters.  */
+	      p++;
+	      width++;
+	      break;
+	    default:
+	      /* If we have a multibyte sequence, scan it up to its end.  */
+	      {
+		mbstate_t mbstate;
+		memset (&mbstate, 0, sizeof mbstate);
+		do
+		  {
+		    wchar_t wc;
+		    size_t bytes;
+		    int w;
+
+		    bytes = mbrtowc (&wc, p, plimit - p, &mbstate);
+
+		    if (bytes == (size_t) -1)
+		      /* An invalid multibyte sequence was encountered.  */
+		      {
+			if (!(flags & MBSW_REJECT_INVALID))
+			  {
+			    p++;
+			    width++;
+			    break;
+			  }
+			else
+			  return -1;
+		      }
+
+		    if (bytes == (size_t) -2)
+		      /* An incomplete multibyte character at the end.  */
+		      {
+			if (!(flags & MBSW_REJECT_INVALID))
+			  {
+			    p = plimit;
+			    width++;
+			    break;
+			  }
+			else
+			  return -1;
+		      }
+
+		    if (bytes == 0)
+		      /* A null wide character was encountered.  */
+		      bytes = 1;
+
+		    w = wcwidth (wc);
+		    if (w >= 0)
+		      /* A printable multibyte character.  */
+		      width += w;
+		    else
+		      /* An unprintable multibyte character.  */
+		      if (!(flags & MBSW_REJECT_UNPRINTABLE))
+			width += (iswcntrl (wc) ? 0 : 1);
+		      else
+			return -1;
+
+		    p += bytes;
+		  }
+		while (! mbsinit (&mbstate));
+	      }
+	      break;
+	  }
+      return width;
+    }
+#endif
+
+  while (p < plimit)
+    {
+      unsigned char c = (unsigned char) *p++;
+
+      if (ISPRINT (c))
+	width++;
+      else if (!(flags & MBSW_REJECT_UNPRINTABLE))
+	width += (ISCNTRL (c) ? 0 : 1);
+      else
+	return -1;
+    }
+  return width;
+}
diff --git a/lib/mbswidth.h b/lib/mbswidth.h
new file mode 100644
index 0000000..1935e0a
--- /dev/null
+++ b/lib/mbswidth.h
@@ -0,0 +1,61 @@
+/* Determine the number of screen columns needed for a string.
+   Copyright (C) 2000-2004 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <stddef.h>
+
+/* Avoid a clash of our mbswidth() with a function of the same name defined
+   in UnixWare 7.1.1 <wchar.h>.  We need this #include before the #define
+   below.
+   However, we don't want to #include <wchar.h> on all platforms because
+   - Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
+     <wchar.h>.
+   - BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before
+     <wchar.h>.  */
+#if HAVE_DECL_MBSWIDTH_IN_WCHAR_H
+# include <wchar.h>
+#endif
+
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+
+/* Optional flags to influence mbswidth/mbsnwidth behavior.  */
+
+/* If this bit is set, return -1 upon finding an invalid or incomplete
+   character.  Otherwise, assume invalid characters have width 1.  */
+#define MBSW_REJECT_INVALID 1
+
+/* If this bit is set, return -1 upon finding a non-printable character.
+   Otherwise, assume unprintable characters have width 0 if they are
+   control characters and 1 otherwise.  */
+#define MBSW_REJECT_UNPRINTABLE	2
+
+
+/* Returns the number of screen columns needed for STRING.  */
+#define mbswidth gnu_mbswidth  /* avoid clash with UnixWare 7.1.1 function */
+extern int mbswidth (const char *string, int flags);
+
+/* Returns the number of screen columns needed for the NBYTES bytes
+   starting at BUF.  */
+extern int mbsnwidth (const char *buf, size_t nbytes, int flags);
+
+
+#ifdef	__cplusplus
+}
+#endif
diff --git a/lib/obstack.c b/lib/obstack.c
new file mode 100644
index 0000000..6df0611
--- /dev/null
+++ b/lib/obstack.c
@@ -0,0 +1,440 @@
+/* obstack.c - subroutines used implicitly by object stack macros
+
+   Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997,
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# include <obstack.h>
+# include <shlib-compat.h>
+#else
+# include "obstack.h"
+#endif
+
+/* NOTE BEFORE MODIFYING THIS FILE: This version number must be
+   incremented whenever callers compiled using an old obstack.h can no
+   longer properly call the functions in this obstack.c.  */
+#define OBSTACK_INTERFACE_VERSION 1
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself, and the installed library
+   supports the same library interface we do.  This code is part of the GNU
+   C Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object
+   files, it is simpler to just do this in the source for each such file.  */
+
+#include <stdio.h>		/* Random thing to get __GNU_LIBRARY__.  */
+#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
+# include <gnu-versions.h>
+# if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
+#  define ELIDE_CODE
+# endif
+#endif
+
+#include <stddef.h>
+
+#ifndef ELIDE_CODE
+
+
+# if HAVE_INTTYPES_H
+#  include <inttypes.h>
+# endif
+# if HAVE_STDINT_H || defined _LIBC
+#  include <stdint.h>
+# endif
+
+/* Determine default alignment.  */
+union fooround
+{
+  uintmax_t i;
+  long double d;
+  void *p;
+};
+struct fooalign
+{
+  char c;
+  union fooround u;
+};
+/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
+   But in fact it might be less smart and round addresses to as much as
+   DEFAULT_ROUNDING.  So we prepare for it to do that.  */
+enum
+  {
+    DEFAULT_ALIGNMENT = offsetof (struct fooalign, u),
+    DEFAULT_ROUNDING = sizeof (union fooround)
+  };
+
+/* When we copy a long block of data, this is the unit to do it with.
+   On some machines, copying successive ints does not work;
+   in such a case, redefine COPYING_UNIT to `long' (if that works)
+   or `char' as a last resort.  */
+# ifndef COPYING_UNIT
+#  define COPYING_UNIT int
+# endif
+
+
+/* The functions allocating more room by calling `obstack_chunk_alloc'
+   jump to the handler pointed to by `obstack_alloc_failed_handler'.
+   This can be set to a user defined function which should either
+   abort gracefully or use longjump - but shouldn't return.  This
+   variable by default points to the internal function
+   `print_and_abort'.  */
+static void print_and_abort (void);
+void (*obstack_alloc_failed_handler) (void) = print_and_abort;
+
+/* Exit value used when `print_and_abort' is used.  */
+# include <stdlib.h>
+# ifdef _LIBC
+int obstack_exit_failure = EXIT_FAILURE;
+# else
+#  include "exitfail.h"
+#  define obstack_exit_failure exit_failure
+# endif
+
+# ifdef _LIBC
+#  if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
+/* A looong time ago (before 1994, anyway; we're not sure) this global variable
+   was used by non-GNU-C macros to avoid multiple evaluation.  The GNU C
+   library still exports it because somebody might use it.  */
+struct obstack *_obstack_compat;
+compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
+#  endif
+# endif
+
+/* Define a macro that either calls functions with the traditional malloc/free
+   calling interface, or calls functions with the mmalloc/mfree interface
+   (that adds an extra first argument), based on the state of use_extra_arg.
+   For free, do not use ?:, since some compilers, like the MIPS compilers,
+   do not allow (expr) ? void : void.  */
+
+# define CALL_CHUNKFUN(h, size) \
+  (((h) -> use_extra_arg) \
+   ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
+   : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
+
+# define CALL_FREEFUN(h, old_chunk) \
+  do { \
+    if ((h) -> use_extra_arg) \
+      (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
+    else \
+      (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
+  } while (0)
+
+
+/* Initialize an obstack H for use.  Specify chunk size SIZE (0 means default).
+   Objects start on multiples of ALIGNMENT (0 means use default).
+   CHUNKFUN is the function to use to allocate chunks,
+   and FREEFUN the function to free them.
+
+   Return nonzero if successful, calls obstack_alloc_failed_handler if
+   allocation fails.  */
+
+int
+_obstack_begin (struct obstack *h,
+		int size, int alignment,
+		void *(*chunkfun) (long),
+		void (*freefun) (void *))
+{
+  register struct _obstack_chunk *chunk; /* points to new chunk */
+
+  if (alignment == 0)
+    alignment = DEFAULT_ALIGNMENT;
+  if (size == 0)
+    /* Default size is what GNU malloc can fit in a 4096-byte block.  */
+    {
+      /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
+	 Use the values for range checking, because if range checking is off,
+	 the extra bytes won't be missed terribly, but if range checking is on
+	 and we used a larger request, a whole extra 4096 bytes would be
+	 allocated.
+
+	 These number are irrelevant to the new GNU malloc.  I suspect it is
+	 less sensitive to the size of the request.  */
+      int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+		    + 4 + DEFAULT_ROUNDING - 1)
+		   & ~(DEFAULT_ROUNDING - 1));
+      size = 4096 - extra;
+    }
+
+  h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
+  h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+  h->chunk_size = size;
+  h->alignment_mask = alignment - 1;
+  h->use_extra_arg = 0;
+
+  chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
+  if (!chunk)
+    (*obstack_alloc_failed_handler) ();
+  h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
+					       alignment - 1);
+  h->chunk_limit = chunk->limit
+    = (char *) chunk + h->chunk_size;
+  chunk->prev = 0;
+  /* The initial chunk now contains no empty object.  */
+  h->maybe_empty_object = 0;
+  h->alloc_failed = 0;
+  return 1;
+}
+
+int
+_obstack_begin_1 (struct obstack *h, int size, int alignment,
+		  void *(*chunkfun) (void *, long),
+		  void (*freefun) (void *, void *),
+		  void *arg)
+{
+  register struct _obstack_chunk *chunk; /* points to new chunk */
+
+  if (alignment == 0)
+    alignment = DEFAULT_ALIGNMENT;
+  if (size == 0)
+    /* Default size is what GNU malloc can fit in a 4096-byte block.  */
+    {
+      /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
+	 Use the values for range checking, because if range checking is off,
+	 the extra bytes won't be missed terribly, but if range checking is on
+	 and we used a larger request, a whole extra 4096 bytes would be
+	 allocated.
+
+	 These number are irrelevant to the new GNU malloc.  I suspect it is
+	 less sensitive to the size of the request.  */
+      int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+		    + 4 + DEFAULT_ROUNDING - 1)
+		   & ~(DEFAULT_ROUNDING - 1));
+      size = 4096 - extra;
+    }
+
+  h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
+  h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+  h->chunk_size = size;
+  h->alignment_mask = alignment - 1;
+  h->extra_arg = arg;
+  h->use_extra_arg = 1;
+
+  chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
+  if (!chunk)
+    (*obstack_alloc_failed_handler) ();
+  h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
+					       alignment - 1);
+  h->chunk_limit = chunk->limit
+    = (char *) chunk + h->chunk_size;
+  chunk->prev = 0;
+  /* The initial chunk now contains no empty object.  */
+  h->maybe_empty_object = 0;
+  h->alloc_failed = 0;
+  return 1;
+}
+
+/* Allocate a new current chunk for the obstack *H
+   on the assumption that LENGTH bytes need to be added
+   to the current object, or a new object of length LENGTH allocated.
+   Copies any partial object from the end of the old chunk
+   to the beginning of the new one.  */
+
+void
+_obstack_newchunk (struct obstack *h, int length)
+{
+  register struct _obstack_chunk *old_chunk = h->chunk;
+  register struct _obstack_chunk *new_chunk;
+  register long	new_size;
+  register long obj_size = h->next_free - h->object_base;
+  register long i;
+  long already;
+  char *object_base;
+
+  /* Compute size for new chunk.  */
+  new_size = (obj_size + length) + (obj_size >> 3) + h->alignment_mask + 100;
+  if (new_size < h->chunk_size)
+    new_size = h->chunk_size;
+
+  /* Allocate and initialize the new chunk.  */
+  new_chunk = CALL_CHUNKFUN (h, new_size);
+  if (!new_chunk)
+    (*obstack_alloc_failed_handler) ();
+  h->chunk = new_chunk;
+  new_chunk->prev = old_chunk;
+  new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
+
+  /* Compute an aligned object_base in the new chunk */
+  object_base =
+    __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask);
+
+  /* Move the existing object to the new chunk.
+     Word at a time is fast and is safe if the object
+     is sufficiently aligned.  */
+  if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
+    {
+      for (i = obj_size / sizeof (COPYING_UNIT) - 1;
+	   i >= 0; i--)
+	((COPYING_UNIT *)object_base)[i]
+	  = ((COPYING_UNIT *)h->object_base)[i];
+      /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
+	 but that can cross a page boundary on a machine
+	 which does not do strict alignment for COPYING_UNITS.  */
+      already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
+    }
+  else
+    already = 0;
+  /* Copy remaining bytes one by one.  */
+  for (i = already; i < obj_size; i++)
+    object_base[i] = h->object_base[i];
+
+  /* If the object just copied was the only data in OLD_CHUNK,
+     free that chunk and remove it from the chain.
+     But not if that chunk might contain an empty object.  */
+  if (! h->maybe_empty_object
+      && (h->object_base
+	  == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,
+			  h->alignment_mask)))
+    {
+      new_chunk->prev = old_chunk->prev;
+      CALL_FREEFUN (h, old_chunk);
+    }
+
+  h->object_base = object_base;
+  h->next_free = h->object_base + obj_size;
+  /* The new chunk certainly contains no empty object yet.  */
+  h->maybe_empty_object = 0;
+}
+# ifdef _LIBC
+libc_hidden_def (_obstack_newchunk)
+# endif
+
+/* Return nonzero if object OBJ has been allocated from obstack H.
+   This is here for debugging.
+   If you use it in a program, you are probably losing.  */
+
+/* Suppress -Wmissing-prototypes warning.  We don't want to declare this in
+   obstack.h because it is just for debugging.  */
+int _obstack_allocated_p (struct obstack *h, void *obj);
+
+int
+_obstack_allocated_p (struct obstack *h, void *obj)
+{
+  register struct _obstack_chunk *lp;	/* below addr of any objects in this chunk */
+  register struct _obstack_chunk *plp;	/* point to previous chunk if any */
+
+  lp = (h)->chunk;
+  /* We use >= rather than > since the object cannot be exactly at
+     the beginning of the chunk but might be an empty object exactly
+     at the end of an adjacent chunk.  */
+  while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
+    {
+      plp = lp->prev;
+      lp = plp;
+    }
+  return lp != 0;
+}
+
+/* Free objects in obstack H, including OBJ and everything allocate
+   more recently than OBJ.  If OBJ is zero, free everything in H.  */
+
+# undef obstack_free
+
+void
+obstack_free (struct obstack *h, void *obj)
+{
+  register struct _obstack_chunk *lp;	/* below addr of any objects in this chunk */
+  register struct _obstack_chunk *plp;	/* point to previous chunk if any */
+
+  lp = h->chunk;
+  /* We use >= because there cannot be an object at the beginning of a chunk.
+     But there can be an empty object at that address
+     at the end of another chunk.  */
+  while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
+    {
+      plp = lp->prev;
+      CALL_FREEFUN (h, lp);
+      lp = plp;
+      /* If we switch chunks, we can't tell whether the new current
+	 chunk contains an empty object, so assume that it may.  */
+      h->maybe_empty_object = 1;
+    }
+  if (lp)
+    {
+      h->object_base = h->next_free = (char *) (obj);
+      h->chunk_limit = lp->limit;
+      h->chunk = lp;
+    }
+  else if (obj != 0)
+    /* obj is not in any of the chunks! */
+    abort ();
+}
+
+# ifdef _LIBC
+/* Older versions of libc used a function _obstack_free intended to be
+   called by non-GCC compilers.  */
+strong_alias (obstack_free, _obstack_free)
+# endif
+
+int
+_obstack_memory_used (struct obstack *h)
+{
+  register struct _obstack_chunk* lp;
+  register int nbytes = 0;
+
+  for (lp = h->chunk; lp != 0; lp = lp->prev)
+    {
+      nbytes += lp->limit - (char *) lp;
+    }
+  return nbytes;
+}
+
+/* Define the error handler.  */
+# ifdef _LIBC
+#  include <libintl.h>
+# else
+#  include "gettext.h"
+# endif
+# ifndef _
+#  define _(msgid) gettext (msgid)
+# endif
+
+# ifdef _LIBC
+#  include <libio/iolibio.h>
+# endif
+
+# ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later.  */
+#  if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
+#   define __attribute__(Spec) /* empty */
+#  endif
+# endif
+
+static void
+__attribute__ ((noreturn))
+print_and_abort (void)
+{
+  /* Don't change any of these strings.  Yes, it would be possible to add
+     the newline to the string and use fputs or so.  But this must not
+     happen because the "memory exhausted" message appears in other places
+     like this and the translation should be reused instead of creating
+     a very similar string which requires a separate translation.  */
+# ifdef _LIBC
+  (void) __fxprintf (NULL, "%s\n", _("memory exhausted"));
+# else
+  fprintf (stderr, "%s\n", _("memory exhausted"));
+# endif
+  exit (obstack_exit_failure);
+}
+
+#endif	/* !ELIDE_CODE */
diff --git a/lib/obstack.h b/lib/obstack.h
new file mode 100644
index 0000000..95dd438
--- /dev/null
+++ b/lib/obstack.h
@@ -0,0 +1,508 @@
+/* obstack.h - object stack macros
+   Copyright (C) 1988-1994,1996-1999,2003,2004,2005
+	Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Summary:
+
+All the apparent functions defined here are macros. The idea
+is that you would use these pre-tested macros to solve a
+very specific set of problems, and they would run fast.
+Caution: no side-effects in arguments please!! They may be
+evaluated MANY times!!
+
+These macros operate a stack of objects.  Each object starts life
+small, and may grow to maturity.  (Consider building a word syllable
+by syllable.)  An object can move while it is growing.  Once it has
+been "finished" it never changes address again.  So the "top of the
+stack" is typically an immature growing object, while the rest of the
+stack is of mature, fixed size and fixed address objects.
+
+These routines grab large chunks of memory, using a function you
+supply, called `obstack_chunk_alloc'.  On occasion, they free chunks,
+by calling `obstack_chunk_free'.  You must define them and declare
+them before using any obstack macros.
+
+Each independent stack is represented by a `struct obstack'.
+Each of the obstack macros expects a pointer to such a structure
+as the first argument.
+
+One motivation for this package is the problem of growing char strings
+in symbol tables.  Unless you are "fascist pig with a read-only mind"
+--Gosper's immortal quote from HAKMEM item 154, out of context--you
+would not like to put any arbitrary upper limit on the length of your
+symbols.
+
+In practice this often means you will build many short symbols and a
+few long symbols.  At the time you are reading a symbol you don't know
+how long it is.  One traditional method is to read a symbol into a
+buffer, realloc()ating the buffer every time you try to read a symbol
+that is longer than the buffer.  This is beaut, but you still will
+want to copy the symbol from the buffer to a more permanent
+symbol-table entry say about half the time.
+
+With obstacks, you can work differently.  Use one obstack for all symbol
+names.  As you read a symbol, grow the name in the obstack gradually.
+When the name is complete, finalize it.  Then, if the symbol exists already,
+free the newly read name.
+
+The way we do this is to take a large chunk, allocating memory from
+low addresses.  When you want to build a symbol in the chunk you just
+add chars above the current "high water mark" in the chunk.  When you
+have finished adding chars, because you got to the end of the symbol,
+you know how long the chars are, and you can create a new object.
+Mostly the chars will not burst over the highest address of the chunk,
+because you would typically expect a chunk to be (say) 100 times as
+long as an average object.
+
+In case that isn't clear, when we have enough chars to make up
+the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
+so we just point to it where it lies.  No moving of chars is
+needed and this is the second win: potentially long strings need
+never be explicitly shuffled. Once an object is formed, it does not
+change its address during its lifetime.
+
+When the chars burst over a chunk boundary, we allocate a larger
+chunk, and then copy the partly formed object from the end of the old
+chunk to the beginning of the new larger chunk.  We then carry on
+accreting characters to the end of the object as we normally would.
+
+A special macro is provided to add a single char at a time to a
+growing object.  This allows the use of register variables, which
+break the ordinary 'growth' macro.
+
+Summary:
+	We allocate large chunks.
+	We carve out one object at a time from the current chunk.
+	Once carved, an object never moves.
+	We are free to append data of any size to the currently
+	  growing object.
+	Exactly one object is growing in an obstack at any one time.
+	You can run one obstack per control block.
+	You may have as many control blocks as you dare.
+	Because of the way we do it, you can `unwind' an obstack
+	  back to a previous state. (You may remove objects much
+	  as you would with a stack.)
+*/
+
+
+/* Don't do the contents of this file more than once.  */
+
+#ifndef _OBSTACK_H
+#define _OBSTACK_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* We need the type of a pointer subtraction.  If __PTRDIFF_TYPE__ is
+   defined, as with GNU C, use that; that way we don't pollute the
+   namespace with <stddef.h>'s symbols.  Otherwise, include <stddef.h>
+   and use ptrdiff_t.  */
+
+#ifdef __PTRDIFF_TYPE__
+# define PTR_INT_TYPE __PTRDIFF_TYPE__
+#else
+# include <stddef.h>
+# define PTR_INT_TYPE ptrdiff_t
+#endif
+
+/* If B is the base of an object addressed by P, return the result of
+   aligning P to the next multiple of A + 1.  B and P must be of type
+   char *.  A + 1 must be a power of 2.  */
+
+#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A)))
+
+/* Similiar to _BPTR_ALIGN (B, P, A), except optimize the common case
+   where pointers can be converted to integers, aligned as integers,
+   and converted back again.  If PTR_INT_TYPE is narrower than a
+   pointer (e.g., the AS/400), play it safe and compute the alignment
+   relative to B.  Otherwise, use the faster strategy of computing the
+   alignment relative to 0.  */
+
+#define __PTR_ALIGN(B, P, A)						    \
+  __BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \
+		P, A)
+
+#include <string.h>
+
+struct _obstack_chunk		/* Lives at front of each chunk. */
+{
+  char  *limit;			/* 1 past end of this chunk */
+  struct _obstack_chunk *prev;	/* address of prior chunk or NULL */
+  char	contents[4];		/* objects begin here */
+};
+
+struct obstack		/* control current object in current chunk */
+{
+  long	chunk_size;		/* preferred size to allocate chunks in */
+  struct _obstack_chunk *chunk;	/* address of current struct obstack_chunk */
+  char	*object_base;		/* address of object we are building */
+  char	*next_free;		/* where to add next char to current object */
+  char	*chunk_limit;		/* address of char after current chunk */
+  union
+  {
+    PTR_INT_TYPE tempint;
+    void *tempptr;
+  } temp;			/* Temporary for some macros.  */
+  int   alignment_mask;		/* Mask of alignment for each object. */
+  /* These prototypes vary based on `use_extra_arg', and we use
+     casts to the prototypeless function type in all assignments,
+     but having prototypes here quiets -Wstrict-prototypes.  */
+  struct _obstack_chunk *(*chunkfun) (void *, long);
+  void (*freefun) (void *, struct _obstack_chunk *);
+  void *extra_arg;		/* first arg for chunk alloc/dealloc funcs */
+  unsigned use_extra_arg:1;	/* chunk alloc/dealloc funcs take extra arg */
+  unsigned maybe_empty_object:1;/* There is a possibility that the current
+				   chunk contains a zero-length object.  This
+				   prevents freeing the chunk if we allocate
+				   a bigger chunk to replace it. */
+  unsigned alloc_failed:1;	/* No longer used, as we now call the failed
+				   handler on error, but retained for binary
+				   compatibility.  */
+};
+
+/* Declare the external functions we use; they are in obstack.c.  */
+
+extern void _obstack_newchunk (struct obstack *, int);
+extern int _obstack_begin (struct obstack *, int, int,
+			    void *(*) (long), void (*) (void *));
+extern int _obstack_begin_1 (struct obstack *, int, int,
+			     void *(*) (void *, long),
+			     void (*) (void *, void *), void *);
+extern int _obstack_memory_used (struct obstack *);
+
+void obstack_free (struct obstack *obstack, void *block);
+
+
+/* Error handler called when `obstack_chunk_alloc' failed to allocate
+   more memory.  This can be set to a user defined function which
+   should either abort gracefully or use longjump - but shouldn't
+   return.  The default action is to print a message and abort.  */
+extern void (*obstack_alloc_failed_handler) (void);
+
+/* Exit value used when `print_and_abort' is used.  */
+extern int obstack_exit_failure;
+
+/* Pointer to beginning of object being allocated or to be allocated next.
+   Note that this might not be the final address of the object
+   because a new chunk might be needed to hold the final size.  */
+
+#define obstack_base(h) ((void *) (h)->object_base)
+
+/* Size for allocating ordinary chunks.  */
+
+#define obstack_chunk_size(h) ((h)->chunk_size)
+
+/* Pointer to next byte not yet allocated in current chunk.  */
+
+#define obstack_next_free(h)	((h)->next_free)
+
+/* Mask specifying low bits that should be clear in address of an object.  */
+
+#define obstack_alignment_mask(h) ((h)->alignment_mask)
+
+/* To prevent prototype warnings provide complete argument list.  */
+#define obstack_init(h)						\
+  _obstack_begin ((h), 0, 0,					\
+		  (void *(*) (long)) obstack_chunk_alloc,	\
+		  (void (*) (void *)) obstack_chunk_free)
+
+#define obstack_begin(h, size)					\
+  _obstack_begin ((h), (size), 0,				\
+		  (void *(*) (long)) obstack_chunk_alloc,	\
+		  (void (*) (void *)) obstack_chunk_free)
+
+#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun)  \
+  _obstack_begin ((h), (size), (alignment),				   \
+		  (void *(*) (long)) (chunkfun),			   \
+		  (void (*) (void *)) (freefun))
+
+#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
+  _obstack_begin_1 ((h), (size), (alignment),				\
+		    (void *(*) (void *, long)) (chunkfun),		\
+		    (void (*) (void *, void *)) (freefun), (arg))
+
+#define obstack_chunkfun(h, newchunkfun) \
+  ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun))
+
+#define obstack_freefun(h, newfreefun) \
+  ((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun))
+
+#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = (achar))
+
+#define obstack_blank_fast(h,n) ((h)->next_free += (n))
+
+#define obstack_memory_used(h) _obstack_memory_used (h)
+
+#if defined __GNUC__ && defined __STDC__ && __STDC__
+/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and
+   does not implement __extension__.  But that compiler doesn't define
+   __GNUC_MINOR__.  */
+# if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__)
+#  define __extension__
+# endif
+
+/* For GNU C, if not -traditional,
+   we can define these macros to compute all args only once
+   without using a global variable.
+   Also, we can avoid using the `temp' slot, to make faster code.  */
+
+# define obstack_object_size(OBSTACK)					\
+  __extension__								\
+  ({ struct obstack const *__o = (OBSTACK);				\
+     (unsigned) (__o->next_free - __o->object_base); })
+
+# define obstack_room(OBSTACK)						\
+  __extension__								\
+  ({ struct obstack const *__o = (OBSTACK);				\
+     (unsigned) (__o->chunk_limit - __o->next_free); })
+
+# define obstack_make_room(OBSTACK,length)				\
+__extension__								\
+({ struct obstack *__o = (OBSTACK);					\
+   int __len = (length);						\
+   if (__o->chunk_limit - __o->next_free < __len)			\
+     _obstack_newchunk (__o, __len);					\
+   (void) 0; })
+
+# define obstack_empty_p(OBSTACK)					\
+  __extension__								\
+  ({ struct obstack const *__o = (OBSTACK);				\
+     (__o->chunk->prev == 0						\
+      && __o->next_free == __PTR_ALIGN ((char *) __o->chunk,		\
+					__o->chunk->contents,		\
+					__o->alignment_mask)); })
+
+# define obstack_grow(OBSTACK,where,length)				\
+__extension__								\
+({ struct obstack *__o = (OBSTACK);					\
+   int __len = (length);						\
+   if (__o->next_free + __len > __o->chunk_limit)			\
+     _obstack_newchunk (__o, __len);					\
+   memcpy (__o->next_free, where, __len);				\
+   __o->next_free += __len;						\
+   (void) 0; })
+
+# define obstack_grow0(OBSTACK,where,length)				\
+__extension__								\
+({ struct obstack *__o = (OBSTACK);					\
+   int __len = (length);						\
+   if (__o->next_free + __len + 1 > __o->chunk_limit)			\
+     _obstack_newchunk (__o, __len + 1);				\
+   memcpy (__o->next_free, where, __len);				\
+   __o->next_free += __len;						\
+   *(__o->next_free)++ = 0;						\
+   (void) 0; })
+
+# define obstack_1grow(OBSTACK,datum)					\
+__extension__								\
+({ struct obstack *__o = (OBSTACK);					\
+   if (__o->next_free + 1 > __o->chunk_limit)				\
+     _obstack_newchunk (__o, 1);					\
+   obstack_1grow_fast (__o, datum);					\
+   (void) 0; })
+
+/* These assume that the obstack alignment is good enough for pointers
+   or ints, and that the data added so far to the current object
+   shares that much alignment.  */
+
+# define obstack_ptr_grow(OBSTACK,datum)				\
+__extension__								\
+({ struct obstack *__o = (OBSTACK);					\
+   if (__o->next_free + sizeof (void *) > __o->chunk_limit)		\
+     _obstack_newchunk (__o, sizeof (void *));				\
+   obstack_ptr_grow_fast (__o, datum); })				\
+
+# define obstack_int_grow(OBSTACK,datum)				\
+__extension__								\
+({ struct obstack *__o = (OBSTACK);					\
+   if (__o->next_free + sizeof (int) > __o->chunk_limit)		\
+     _obstack_newchunk (__o, sizeof (int));				\
+   obstack_int_grow_fast (__o, datum); })
+
+# define obstack_ptr_grow_fast(OBSTACK,aptr)				\
+__extension__								\
+({ struct obstack *__o1 = (OBSTACK);					\
+   *(const void **) __o1->next_free = (aptr);				\
+   __o1->next_free += sizeof (const void *);				\
+   (void) 0; })
+
+# define obstack_int_grow_fast(OBSTACK,aint)				\
+__extension__								\
+({ struct obstack *__o1 = (OBSTACK);					\
+   *(int *) __o1->next_free = (aint);					\
+   __o1->next_free += sizeof (int);					\
+   (void) 0; })
+
+# define obstack_blank(OBSTACK,length)					\
+__extension__								\
+({ struct obstack *__o = (OBSTACK);					\
+   int __len = (length);						\
+   if (__o->chunk_limit - __o->next_free < __len)			\
+     _obstack_newchunk (__o, __len);					\
+   obstack_blank_fast (__o, __len);					\
+   (void) 0; })
+
+# define obstack_alloc(OBSTACK,length)					\
+__extension__								\
+({ struct obstack *__h = (OBSTACK);					\
+   obstack_blank (__h, (length));					\
+   obstack_finish (__h); })
+
+# define obstack_copy(OBSTACK,where,length)				\
+__extension__								\
+({ struct obstack *__h = (OBSTACK);					\
+   obstack_grow (__h, (where), (length));				\
+   obstack_finish (__h); })
+
+# define obstack_copy0(OBSTACK,where,length)				\
+__extension__								\
+({ struct obstack *__h = (OBSTACK);					\
+   obstack_grow0 (__h, (where), (length));				\
+   obstack_finish (__h); })
+
+/* The local variable is named __o1 to avoid a name conflict
+   when obstack_blank is called.  */
+# define obstack_finish(OBSTACK)					\
+__extension__								\
+({ struct obstack *__o1 = (OBSTACK);					\
+   void *__value = (void *) __o1->object_base;				\
+   if (__o1->next_free == __value)					\
+     __o1->maybe_empty_object = 1;					\
+   __o1->next_free							\
+     = __PTR_ALIGN (__o1->object_base, __o1->next_free,			\
+		    __o1->alignment_mask);				\
+   if (__o1->next_free - (char *)__o1->chunk				\
+       > __o1->chunk_limit - (char *)__o1->chunk)			\
+     __o1->next_free = __o1->chunk_limit;				\
+   __o1->object_base = __o1->next_free;					\
+   __value; })
+
+# define obstack_free(OBSTACK, OBJ)					\
+__extension__								\
+({ struct obstack *__o = (OBSTACK);					\
+   void *__obj = (OBJ);							\
+   if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit)  \
+     __o->next_free = __o->object_base = (char *)__obj;			\
+   else (obstack_free) (__o, __obj); })
+
+#else /* not __GNUC__ or not __STDC__ */
+
+# define obstack_object_size(h) \
+ (unsigned) ((h)->next_free - (h)->object_base)
+
+# define obstack_room(h)		\
+ (unsigned) ((h)->chunk_limit - (h)->next_free)
+
+# define obstack_empty_p(h) \
+ ((h)->chunk->prev == 0							\
+  && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk,		\
+				    (h)->chunk->contents,		\
+				    (h)->alignment_mask))
+
+/* Note that the call to _obstack_newchunk is enclosed in (..., 0)
+   so that we can avoid having void expressions
+   in the arms of the conditional expression.
+   Casting the third operand to void was tried before,
+   but some compilers won't accept it.  */
+
+# define obstack_make_room(h,length)					\
+( (h)->temp.tempint = (length),						\
+  (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit)		\
+   ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0))
+
+# define obstack_grow(h,where,length)					\
+( (h)->temp.tempint = (length),						\
+  (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit)		\
+   ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0),		\
+  memcpy ((h)->next_free, where, (h)->temp.tempint),			\
+  (h)->next_free += (h)->temp.tempint)
+
+# define obstack_grow0(h,where,length)					\
+( (h)->temp.tempint = (length),						\
+  (((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit)		\
+   ? (_obstack_newchunk ((h), (h)->temp.tempint + 1), 0) : 0),		\
+  memcpy ((h)->next_free, where, (h)->temp.tempint),			\
+  (h)->next_free += (h)->temp.tempint,					\
+  *((h)->next_free)++ = 0)
+
+# define obstack_1grow(h,datum)						\
+( (((h)->next_free + 1 > (h)->chunk_limit)				\
+   ? (_obstack_newchunk ((h), 1), 0) : 0),				\
+  obstack_1grow_fast (h, datum))
+
+# define obstack_ptr_grow(h,datum)					\
+( (((h)->next_free + sizeof (char *) > (h)->chunk_limit)		\
+   ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0),		\
+  obstack_ptr_grow_fast (h, datum))
+
+# define obstack_int_grow(h,datum)					\
+( (((h)->next_free + sizeof (int) > (h)->chunk_limit)			\
+   ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0),			\
+  obstack_int_grow_fast (h, datum))
+
+# define obstack_ptr_grow_fast(h,aptr)					\
+  (((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr))
+
+# define obstack_int_grow_fast(h,aint)					\
+  (((int *) ((h)->next_free += sizeof (int)))[-1] = (aint))
+
+# define obstack_blank(h,length)					\
+( (h)->temp.tempint = (length),						\
+  (((h)->chunk_limit - (h)->next_free < (h)->temp.tempint)		\
+   ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0),		\
+  obstack_blank_fast (h, (h)->temp.tempint))
+
+# define obstack_alloc(h,length)					\
+ (obstack_blank ((h), (length)), obstack_finish ((h)))
+
+# define obstack_copy(h,where,length)					\
+ (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
+
+# define obstack_copy0(h,where,length)					\
+ (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
+
+# define obstack_finish(h)						\
+( ((h)->next_free == (h)->object_base					\
+   ? (((h)->maybe_empty_object = 1), 0)					\
+   : 0),								\
+  (h)->temp.tempptr = (h)->object_base,					\
+  (h)->next_free							\
+    = __PTR_ALIGN ((h)->object_base, (h)->next_free,			\
+		   (h)->alignment_mask),				\
+  (((h)->next_free - (char *) (h)->chunk				\
+    > (h)->chunk_limit - (char *) (h)->chunk)				\
+   ? ((h)->next_free = (h)->chunk_limit) : 0),				\
+  (h)->object_base = (h)->next_free,					\
+  (h)->temp.tempptr)
+
+# define obstack_free(h,obj)						\
+( (h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk,		\
+  ((((h)->temp.tempint > 0						\
+    && (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk))	\
+   ? (int) ((h)->next_free = (h)->object_base				\
+	    = (h)->temp.tempint + (char *) (h)->chunk)			\
+   : (((obstack_free) ((h), (h)->temp.tempint + (char *) (h)->chunk), 0), 0)))
+
+#endif /* not __GNUC__ or not __STDC__ */
+
+#ifdef __cplusplus
+}	/* C++ */
+#endif
+
+#endif /* obstack.h */
diff --git a/lib/pipe-safer.c b/lib/pipe-safer.c
new file mode 100644
index 0000000..fb02d72
--- /dev/null
+++ b/lib/pipe-safer.c
@@ -0,0 +1,50 @@
+/* Invoke pipe, but avoid some glitches.
+   Copyright (C) 2005 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Jim Meyering.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "unistd-safer.h"
+
+#include <unistd.h>
+
+/* Like pipe, but ensure that neither of the file descriptors is
+   STDIN_FILENO, STDOUT_FILENO, or STDERR_FILENO.  */
+
+int
+pipe_safer (int fd[2])
+{
+  int fail = pipe (fd);
+  if (fail)
+    return fail;
+
+  {
+    int i;
+    for (i = 0; i < 2; i++)
+      {
+	int f = fd_safer (fd[i]);
+	if (f < 0)
+	  return -1;
+	fd[i] = f;
+      }
+  }
+
+  return 0;
+}
diff --git a/lib/quote.c b/lib/quote.c
new file mode 100644
index 0000000..16cc939
--- /dev/null
+++ b/lib/quote.c
@@ -0,0 +1,41 @@
+/* quote.c - quote arguments for output
+   Copyright (C) 1998, 1999, 2000, 2001, 2003 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Paul Eggert <eggert@twinsun.com> */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "quotearg.h"
+#include "quote.h"
+
+/* Return an unambiguous printable representation of NAME,
+   allocated in slot N, suitable for diagnostics.  */
+char const *
+quote_n (int n, char const *name)
+{
+  return quotearg_n_style (n, locale_quoting_style, name);
+}
+
+/* Return an unambiguous printable representation of NAME,
+   suitable for diagnostics.  */
+char const *
+quote (char const *name)
+{
+  return quote_n (0, name);
+}
diff --git a/lib/quote.h b/lib/quote.h
new file mode 100644
index 0000000..5400ead
--- /dev/null
+++ b/lib/quote.h
@@ -0,0 +1,22 @@
+/* quote.h - prototypes for quote.c
+
+   Copyright (C) 1998, 1999, 2000, 2001, 2003 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+
+char const *quote_n (int n, char const *name);
+char const *quote (char const *name);
diff --git a/lib/quotearg.c b/lib/quotearg.c
new file mode 100644
index 0000000..113239f
--- /dev/null
+++ b/lib/quotearg.c
@@ -0,0 +1,690 @@
+/* quotearg.c - quote arguments for output
+
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Paul Eggert <eggert@twinsun.com> */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "quotearg.h"
+
+#include "xalloc.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+#if HAVE_WCHAR_H
+
+/* BSD/OS 4.1 wchar.h requires FILE and struct tm to be declared.  */
+# include <stdio.h>
+# include <time.h>
+
+# include <wchar.h>
+#endif
+
+#if !HAVE_MBRTOWC
+/* Disable multibyte processing entirely.  Since MB_CUR_MAX is 1, the
+   other macros are defined only for documentation and to satisfy C
+   syntax.  */
+# undef MB_CUR_MAX
+# define MB_CUR_MAX 1
+# define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0)
+# define iswprint(wc) isprint ((unsigned char) (wc))
+# undef HAVE_MBSINIT
+#endif
+
+#if !defined mbsinit && !HAVE_MBSINIT
+# define mbsinit(ps) 1
+#endif
+
+#ifndef iswprint
+# if HAVE_WCTYPE_H
+#  include <wctype.h>
+# endif
+# if !defined iswprint && !HAVE_ISWPRINT
+#  define iswprint(wc) 1
+# endif
+#endif
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+#define INT_BITS (sizeof (int) * CHAR_BIT)
+
+struct quoting_options
+{
+  /* Basic quoting style.  */
+  enum quoting_style style;
+
+  /* Quote the characters indicated by this bit vector even if the
+     quoting style would not normally require them to be quoted.  */
+  unsigned int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
+};
+
+/* Names of quoting styles.  */
+char const *const quoting_style_args[] =
+{
+  "literal",
+  "shell",
+  "shell-always",
+  "c",
+  "escape",
+  "locale",
+  "clocale",
+  0
+};
+
+/* Correspondences to quoting style names.  */
+enum quoting_style const quoting_style_vals[] =
+{
+  literal_quoting_style,
+  shell_quoting_style,
+  shell_always_quoting_style,
+  c_quoting_style,
+  escape_quoting_style,
+  locale_quoting_style,
+  clocale_quoting_style
+};
+
+/* The default quoting options.  */
+static struct quoting_options default_quoting_options;
+
+/* Allocate a new set of quoting options, with contents initially identical
+   to O if O is not null, or to the default if O is null.
+   It is the caller's responsibility to free the result.  */
+struct quoting_options *
+clone_quoting_options (struct quoting_options *o)
+{
+  int e = errno;
+  struct quoting_options *p = xmalloc (sizeof *p);
+  *p = *(o ? o : &default_quoting_options);
+  errno = e;
+  return p;
+}
+
+/* Get the value of O's quoting style.  If O is null, use the default.  */
+enum quoting_style
+get_quoting_style (struct quoting_options *o)
+{
+  return (o ? o : &default_quoting_options)->style;
+}
+
+/* In O (or in the default if O is null),
+   set the value of the quoting style to S.  */
+void
+set_quoting_style (struct quoting_options *o, enum quoting_style s)
+{
+  (o ? o : &default_quoting_options)->style = s;
+}
+
+/* In O (or in the default if O is null),
+   set the value of the quoting options for character C to I.
+   Return the old value.  Currently, the only values defined for I are
+   0 (the default) and 1 (which means to quote the character even if
+   it would not otherwise be quoted).  */
+int
+set_char_quoting (struct quoting_options *o, char c, int i)
+{
+  unsigned char uc = c;
+  unsigned int *p =
+    (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
+  int shift = uc % INT_BITS;
+  int r = (*p >> shift) & 1;
+  *p ^= ((i & 1) ^ r) << shift;
+  return r;
+}
+
+/* MSGID approximates a quotation mark.  Return its translation if it
+   has one; otherwise, return either it or "\"", depending on S.  */
+static char const *
+gettext_quote (char const *msgid, enum quoting_style s)
+{
+  char const *translation = _(msgid);
+  if (translation == msgid && s == clocale_quoting_style)
+    translation = "\"";
+  return translation;
+}
+
+/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
+   argument ARG (of size ARGSIZE), using QUOTING_STYLE and the
+   non-quoting-style part of O to control quoting.
+   Terminate the output with a null character, and return the written
+   size of the output, not counting the terminating null.
+   If BUFFERSIZE is too small to store the output string, return the
+   value that would have been returned had BUFFERSIZE been large enough.
+   If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE.
+
+   This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
+   ARGSIZE, O), except it uses QUOTING_STYLE instead of the quoting
+   style specified by O, and O may not be null.  */
+
+static size_t
+quotearg_buffer_restyled (char *buffer, size_t buffersize,
+			  char const *arg, size_t argsize,
+			  enum quoting_style quoting_style,
+			  struct quoting_options const *o)
+{
+  size_t i;
+  size_t len = 0;
+  char const *quote_string = 0;
+  size_t quote_string_len = 0;
+  bool backslash_escapes = false;
+  bool unibyte_locale = MB_CUR_MAX == 1;
+
+#define STORE(c) \
+    do \
+      { \
+	if (len < buffersize) \
+	  buffer[len] = (c); \
+	len++; \
+      } \
+    while (0)
+
+  switch (quoting_style)
+    {
+    case c_quoting_style:
+      STORE ('"');
+      backslash_escapes = true;
+      quote_string = "\"";
+      quote_string_len = 1;
+      break;
+
+    case escape_quoting_style:
+      backslash_escapes = true;
+      break;
+
+    case locale_quoting_style:
+    case clocale_quoting_style:
+      {
+	/* TRANSLATORS:
+	   Get translations for open and closing quotation marks.
+
+	   The message catalog should translate "`" to a left
+	   quotation mark suitable for the locale, and similarly for
+	   "'".  If the catalog has no translation,
+	   locale_quoting_style quotes `like this', and
+	   clocale_quoting_style quotes "like this".
+
+	   For example, an American English Unicode locale should
+	   translate "`" to U+201C (LEFT DOUBLE QUOTATION MARK), and
+	   should translate "'" to U+201D (RIGHT DOUBLE QUOTATION
+	   MARK).  A British English Unicode locale should instead
+	   translate these to U+2018 (LEFT SINGLE QUOTATION MARK) and
+	   U+2019 (RIGHT SINGLE QUOTATION MARK), respectively.
+
+	   If you don't know what to put here, please see
+	   <http://en.wikipedia.org/wiki/Quotation_mark#Glyphs>
+	   and use glyphs suitable for your language.  */
+
+	char const *left = gettext_quote (N_("`"), quoting_style);
+	char const *right = gettext_quote (N_("'"), quoting_style);
+	for (quote_string = left; *quote_string; quote_string++)
+	  STORE (*quote_string);
+	backslash_escapes = true;
+	quote_string = right;
+	quote_string_len = strlen (quote_string);
+      }
+      break;
+
+    case shell_always_quoting_style:
+      STORE ('\'');
+      quote_string = "'";
+      quote_string_len = 1;
+      break;
+
+    default:
+      break;
+    }
+
+  for (i = 0;  ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize);  i++)
+    {
+      unsigned char c;
+      unsigned char esc;
+
+      if (backslash_escapes
+	  && quote_string_len
+	  && i + quote_string_len <= argsize
+	  && memcmp (arg + i, quote_string, quote_string_len) == 0)
+	STORE ('\\');
+
+      c = arg[i];
+      switch (c)
+	{
+	case '\0':
+	  if (backslash_escapes)
+	    {
+	      STORE ('\\');
+	      STORE ('0');
+	      STORE ('0');
+	      c = '0';
+	    }
+	  break;
+
+	case '?':
+	  switch (quoting_style)
+	    {
+	    case shell_quoting_style:
+	      goto use_shell_always_quoting_style;
+
+	    case c_quoting_style:
+	      if (i + 2 < argsize && arg[i + 1] == '?')
+		switch (arg[i + 2])
+		  {
+		  case '!': case '\'':
+		  case '(': case ')': case '-': case '/':
+		  case '<': case '=': case '>':
+		    /* Escape the second '?' in what would otherwise be
+		       a trigraph.  */
+		    c = arg[i + 2];
+		    i += 2;
+		    STORE ('?');
+		    STORE ('\\');
+		    STORE ('?');
+		    break;
+
+		  default:
+		    break;
+		  }
+	      break;
+
+	    default:
+	      break;
+	    }
+	  break;
+
+	case '\a': esc = 'a'; goto c_escape;
+	case '\b': esc = 'b'; goto c_escape;
+	case '\f': esc = 'f'; goto c_escape;
+	case '\n': esc = 'n'; goto c_and_shell_escape;
+	case '\r': esc = 'r'; goto c_and_shell_escape;
+	case '\t': esc = 't'; goto c_and_shell_escape;
+	case '\v': esc = 'v'; goto c_escape;
+	case '\\': esc = c; goto c_and_shell_escape;
+
+	c_and_shell_escape:
+	  if (quoting_style == shell_quoting_style)
+	    goto use_shell_always_quoting_style;
+	c_escape:
+	  if (backslash_escapes)
+	    {
+	      c = esc;
+	      goto store_escape;
+	    }
+	  break;
+
+	case '{': case '}': /* sometimes special if isolated */
+	  if (! (argsize == SIZE_MAX ? arg[1] == '\0' : argsize == 1))
+	    break;
+	  /* Fall through.  */
+	case '#': case '~':
+	  if (i != 0)
+	    break;
+	  /* Fall through.  */
+	case ' ':
+	case '!': /* special in bash */
+	case '"': case '$': case '&':
+	case '(': case ')': case '*': case ';':
+	case '<':
+	case '=': /* sometimes special in 0th or (with "set -k") later args */
+	case '>': case '[':
+	case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
+	case '`': case '|':
+	  /* A shell special character.  In theory, '$' and '`' could
+	     be the first bytes of multibyte characters, which means
+	     we should check them with mbrtowc, but in practice this
+	     doesn't happen so it's not worth worrying about.  */
+	  if (quoting_style == shell_quoting_style)
+	    goto use_shell_always_quoting_style;
+	  break;
+
+	case '\'':
+	  switch (quoting_style)
+	    {
+	    case shell_quoting_style:
+	      goto use_shell_always_quoting_style;
+
+	    case shell_always_quoting_style:
+	      STORE ('\'');
+	      STORE ('\\');
+	      STORE ('\'');
+	      break;
+
+	    default:
+	      break;
+	    }
+	  break;
+
+	case '%': case '+': case ',': case '-': case '.': case '/':
+	case '0': case '1': case '2': case '3': case '4': case '5':
+	case '6': case '7': case '8': case '9': case ':':
+	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+	case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+	case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+	case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+	case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
+	case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
+	case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
+	case 'o': case 'p': case 'q': case 'r': case 's': case 't':
+	case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
+	  /* These characters don't cause problems, no matter what the
+	     quoting style is.  They cannot start multibyte sequences.  */
+	  break;
+
+	default:
+	  /* If we have a multibyte sequence, copy it until we reach
+	     its end, find an error, or come back to the initial shift
+	     state.  For C-like styles, if the sequence has
+	     unprintable characters, escape the whole sequence, since
+	     we can't easily escape single characters within it.  */
+	  {
+	    /* Length of multibyte sequence found so far.  */
+	    size_t m;
+
+	    bool printable;
+
+	    if (unibyte_locale)
+	      {
+		m = 1;
+		printable = isprint (c) != 0;
+	      }
+	    else
+	      {
+		mbstate_t mbstate;
+		memset (&mbstate, 0, sizeof mbstate);
+
+		m = 0;
+		printable = true;
+		if (argsize == SIZE_MAX)
+		  argsize = strlen (arg);
+
+		do
+		  {
+		    wchar_t w;
+		    size_t bytes = mbrtowc (&w, &arg[i + m],
+					    argsize - (i + m), &mbstate);
+		    if (bytes == 0)
+		      break;
+		    else if (bytes == (size_t) -1)
+		      {
+			printable = false;
+			break;
+		      }
+		    else if (bytes == (size_t) -2)
+		      {
+			printable = false;
+			while (i + m < argsize && arg[i + m])
+			  m++;
+			break;
+		      }
+		    else
+		      {
+			/* Work around a bug with older shells that "see" a '\'
+			   that is really the 2nd byte of a multibyte character.
+			   In practice the problem is limited to ASCII
+			   chars >= '@' that are shell special chars.  */
+			if ('[' == 0x5b && quoting_style == shell_quoting_style)
+			  {
+			    size_t j;
+			    for (j = 1; j < bytes; j++)
+			      switch (arg[i + m + j])
+				{
+				case '[': case '\\': case '^':
+				case '`': case '|':
+				  goto use_shell_always_quoting_style;
+
+				default:
+				  break;
+				}
+			  }
+
+			if (! iswprint (w))
+			  printable = false;
+			m += bytes;
+		      }
+		  }
+		while (! mbsinit (&mbstate));
+	      }
+
+	    if (1 < m || (backslash_escapes && ! printable))
+	      {
+		/* Output a multibyte sequence, or an escaped
+		   unprintable unibyte character.  */
+		size_t ilim = i + m;
+
+		for (;;)
+		  {
+		    if (backslash_escapes && ! printable)
+		      {
+			STORE ('\\');
+			STORE ('0' + (c >> 6));
+			STORE ('0' + ((c >> 3) & 7));
+			c = '0' + (c & 7);
+		      }
+		    if (ilim <= i + 1)
+		      break;
+		    STORE (c);
+		    c = arg[++i];
+		  }
+
+		goto store_c;
+	      }
+	  }
+	}
+
+      if (! (backslash_escapes
+	     && o->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
+	goto store_c;
+
+    store_escape:
+      STORE ('\\');
+
+    store_c:
+      STORE (c);
+    }
+
+  if (i == 0 && quoting_style == shell_quoting_style)
+    goto use_shell_always_quoting_style;
+
+  if (quote_string)
+    for (; *quote_string; quote_string++)
+      STORE (*quote_string);
+
+  if (len < buffersize)
+    buffer[len] = '\0';
+  return len;
+
+ use_shell_always_quoting_style:
+  return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
+				   shell_always_quoting_style, o);
+}
+
+/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
+   argument ARG (of size ARGSIZE), using O to control quoting.
+   If O is null, use the default.
+   Terminate the output with a null character, and return the written
+   size of the output, not counting the terminating null.
+   If BUFFERSIZE is too small to store the output string, return the
+   value that would have been returned had BUFFERSIZE been large enough.
+   If ARGSIZE is SIZE_MAX, use the string length of the argument for
+   ARGSIZE.  */
+size_t
+quotearg_buffer (char *buffer, size_t buffersize,
+		 char const *arg, size_t argsize,
+		 struct quoting_options const *o)
+{
+  struct quoting_options const *p = o ? o : &default_quoting_options;
+  int e = errno;
+  size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
+				       p->style, p);
+  errno = e;
+  return r;
+}
+
+/* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly
+   allocated storage containing the quoted string.  */
+char *
+quotearg_alloc (char const *arg, size_t argsize,
+		struct quoting_options const *o)
+{
+  int e = errno;
+  size_t bufsize = quotearg_buffer (0, 0, arg, argsize, o) + 1;
+  char *buf = xmalloc (bufsize);
+  quotearg_buffer (buf, bufsize, arg, argsize, o);
+  errno = e;
+  return buf;
+}
+
+/* Use storage slot N to return a quoted version of argument ARG.
+   ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a
+   null-terminated string.
+   OPTIONS specifies the quoting options.
+   The returned value points to static storage that can be
+   reused by the next call to this function with the same value of N.
+   N must be nonnegative.  N is deliberately declared with type "int"
+   to allow for future extensions (using negative values).  */
+static char *
+quotearg_n_options (int n, char const *arg, size_t argsize,
+		    struct quoting_options const *options)
+{
+  int e = errno;
+
+  /* Preallocate a slot 0 buffer, so that the caller can always quote
+     one small component of a "memory exhausted" message in slot 0.  */
+  static char slot0[256];
+  static unsigned int nslots = 1;
+  unsigned int n0 = n;
+  struct slotvec
+    {
+      size_t size;
+      char *val;
+    };
+  static struct slotvec slotvec0 = {sizeof slot0, slot0};
+  static struct slotvec *slotvec = &slotvec0;
+
+  if (n < 0)
+    abort ();
+
+  if (nslots <= n0)
+    {
+      /* FIXME: technically, the type of n1 should be `unsigned int',
+	 but that evokes an unsuppressible warning from gcc-4.0.1 and
+	 older.  If gcc ever provides an option to suppress that warning,
+	 revert to the original type, so that the test in xalloc_oversized
+	 is once again performed only at compile time.  */
+      size_t n1 = n0 + 1;
+
+      if (xalloc_oversized (n1, sizeof *slotvec))
+	xalloc_die ();
+
+      if (slotvec == &slotvec0)
+	{
+	  slotvec = xmalloc (sizeof *slotvec);
+	  *slotvec = slotvec0;
+	}
+      slotvec = xrealloc (slotvec, n1 * sizeof *slotvec);
+      memset (slotvec + nslots, 0, (n1 - nslots) * sizeof *slotvec);
+      nslots = n1;
+    }
+
+  {
+    size_t size = slotvec[n].size;
+    char *val = slotvec[n].val;
+    size_t qsize = quotearg_buffer (val, size, arg, argsize, options);
+
+    if (size <= qsize)
+      {
+	slotvec[n].size = size = qsize + 1;
+	if (val != slot0)
+	  free (val);
+	slotvec[n].val = val = xmalloc (size);
+	quotearg_buffer (val, size, arg, argsize, options);
+      }
+
+    errno = e;
+    return val;
+  }
+}
+
+char *
+quotearg_n (int n, char const *arg)
+{
+  return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options);
+}
+
+char *
+quotearg (char const *arg)
+{
+  return quotearg_n (0, arg);
+}
+
+/* Return quoting options for STYLE, with no extra quoting.  */
+static struct quoting_options
+quoting_options_from_style (enum quoting_style style)
+{
+  struct quoting_options o;
+  o.style = style;
+  memset (o.quote_these_too, 0, sizeof o.quote_these_too);
+  return o;
+}
+
+char *
+quotearg_n_style (int n, enum quoting_style s, char const *arg)
+{
+  struct quoting_options const o = quoting_options_from_style (s);
+  return quotearg_n_options (n, arg, SIZE_MAX, &o);
+}
+
+char *
+quotearg_n_style_mem (int n, enum quoting_style s,
+		      char const *arg, size_t argsize)
+{
+  struct quoting_options const o = quoting_options_from_style (s);
+  return quotearg_n_options (n, arg, argsize, &o);
+}
+
+char *
+quotearg_style (enum quoting_style s, char const *arg)
+{
+  return quotearg_n_style (0, s, arg);
+}
+
+char *
+quotearg_char (char const *arg, char ch)
+{
+  struct quoting_options options;
+  options = default_quoting_options;
+  set_char_quoting (&options, ch, 1);
+  return quotearg_n_options (0, arg, SIZE_MAX, &options);
+}
+
+char *
+quotearg_colon (char const *arg)
+{
+  return quotearg_char (arg, ':');
+}
diff --git a/lib/quotearg.h b/lib/quotearg.h
new file mode 100644
index 0000000..24f26f7
--- /dev/null
+++ b/lib/quotearg.h
@@ -0,0 +1,137 @@
+/* quotearg.h - quote arguments for output
+
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Paul Eggert <eggert@twinsun.com> */
+
+#ifndef QUOTEARG_H_
+# define QUOTEARG_H_ 1
+
+# include <stddef.h>
+
+/* Basic quoting styles.  */
+enum quoting_style
+  {
+    /* Output names as-is (ls --quoting-style=literal).  */
+    literal_quoting_style,
+
+    /* Quote names for the shell if they contain shell metacharacters
+       or would cause ambiguous output (ls --quoting-style=shell).  */
+    shell_quoting_style,
+
+    /* Quote names for the shell, even if they would normally not
+       require quoting (ls --quoting-style=shell-always).  */
+    shell_always_quoting_style,
+
+    /* Quote names as for a C language string (ls --quoting-style=c).  */
+    c_quoting_style,
+
+    /* Like c_quoting_style except omit the surrounding double-quote
+       characters (ls --quoting-style=escape).  */
+    escape_quoting_style,
+
+    /* Like clocale_quoting_style, but quote `like this' instead of
+       "like this" in the default C locale (ls --quoting-style=locale).  */
+    locale_quoting_style,
+
+    /* Like c_quoting_style except use quotation marks appropriate for
+       the locale (ls --quoting-style=clocale).  */
+    clocale_quoting_style
+  };
+
+/* For now, --quoting-style=literal is the default, but this may change.  */
+# ifndef DEFAULT_QUOTING_STYLE
+#  define DEFAULT_QUOTING_STYLE literal_quoting_style
+# endif
+
+/* Names of quoting styles and their corresponding values.  */
+extern char const *const quoting_style_args[];
+extern enum quoting_style const quoting_style_vals[];
+
+struct quoting_options;
+
+/* The functions listed below set and use a hidden variable
+   that contains the default quoting style options.  */
+
+/* Allocate a new set of quoting options, with contents initially identical
+   to O if O is not null, or to the default if O is null.
+   It is the caller's responsibility to free the result.  */
+struct quoting_options *clone_quoting_options (struct quoting_options *o);
+
+/* Get the value of O's quoting style.  If O is null, use the default.  */
+enum quoting_style get_quoting_style (struct quoting_options *o);
+
+/* In O (or in the default if O is null),
+   set the value of the quoting style to S.  */
+void set_quoting_style (struct quoting_options *o, enum quoting_style s);
+
+/* In O (or in the default if O is null),
+   set the value of the quoting options for character C to I.
+   Return the old value.  Currently, the only values defined for I are
+   0 (the default) and 1 (which means to quote the character even if
+   it would not otherwise be quoted).  */
+int set_char_quoting (struct quoting_options *o, char c, int i);
+
+/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
+   argument ARG (of size ARGSIZE), using O to control quoting.
+   If O is null, use the default.
+   Terminate the output with a null character, and return the written
+   size of the output, not counting the terminating null.
+   If BUFFERSIZE is too small to store the output string, return the
+   value that would have been returned had BUFFERSIZE been large enough.
+   If ARGSIZE is -1, use the string length of the argument for ARGSIZE.  */
+size_t quotearg_buffer (char *buffer, size_t buffersize,
+			char const *arg, size_t argsize,
+			struct quoting_options const *o);
+
+/* Like quotearg_buffer, except return the result in a newly allocated
+   buffer.  It is the caller's responsibility to free the result.  */
+char *quotearg_alloc (char const *arg, size_t argsize,
+		      struct quoting_options const *o);
+
+/* Use storage slot N to return a quoted version of the string ARG.
+   Use the default quoting options.
+   The returned value points to static storage that can be
+   reused by the next call to this function with the same value of N.
+   N must be nonnegative.  */
+char *quotearg_n (int n, char const *arg);
+
+/* Equivalent to quotearg_n (0, ARG).  */
+char *quotearg (char const *arg);
+
+/* Use style S and storage slot N to return a quoted version of the string ARG.
+   This is like quotearg_n (N, ARG), except that it uses S with no other
+   options to specify the quoting method.  */
+char *quotearg_n_style (int n, enum quoting_style s, char const *arg);
+
+/* Use style S and storage slot N to return a quoted version of the
+   argument ARG of size ARGSIZE.  This is like quotearg_n_style
+   (N, S, ARG), except it can quote null bytes.  */
+char *quotearg_n_style_mem (int n, enum quoting_style s,
+			    char const *arg, size_t argsize);
+
+/* Equivalent to quotearg_n_style (0, S, ARG).  */
+char *quotearg_style (enum quoting_style s, char const *arg);
+
+/* Like quotearg (ARG), except also quote any instances of CH.  */
+char *quotearg_char (char const *arg, char ch);
+
+/* Equivalent to quotearg_char (ARG, ':').  */
+char *quotearg_colon (char const *arg);
+
+#endif /* !QUOTEARG_H_ */
diff --git a/lib/stdbool_.h b/lib/stdbool_.h
new file mode 100644
index 0000000..efa80ba
--- /dev/null
+++ b/lib/stdbool_.h
@@ -0,0 +1,115 @@
+/* Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+   Written by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _STDBOOL_H
+#define _STDBOOL_H
+
+/* ISO C 99 <stdbool.h> for platforms that lack it.  */
+
+/* Usage suggestions:
+
+   Programs that use <stdbool.h> should be aware of some limitations
+   and standards compliance issues.
+
+   Standards compliance:
+
+       - <stdbool.h> must be #included before 'bool', 'false', 'true'
+         can be used.
+
+       - You cannot assume that sizeof (bool) == 1.
+
+       - Programs should not undefine the macros bool, true, and false,
+         as C99 lists that as an "obsolescent feature".
+
+   Limitations of this substitute, when used in a C89 environment:
+
+       - <stdbool.h> must be #included before the '_Bool' type can be used.
+
+       - You cannot assume that _Bool is a typedef; it might be a macro.
+
+       - In C99, casts and automatic conversions to '_Bool' or 'bool' are
+         performed in such a way that every nonzero value gets converted
+         to 'true', and zero gets converted to 'false'.  This doesn't work
+         with this substitute.  With this substitute, only the values 0 and 1
+         give the expected result when converted to _Bool' or 'bool'.
+
+   Also, it is suggested that programs use 'bool' rather than '_Bool';
+   this isn't required, but 'bool' is more common.  */
+
+
+/* 7.16. Boolean type and values */
+
+/* BeOS <sys/socket.h> already #defines false 0, true 1.  We use the same
+   definitions below, but temporarily we have to #undef them.  */
+#ifdef __BEOS__
+# include <OS.h> /* defines bool but not _Bool */
+# undef false
+# undef true
+#endif
+
+/* For the sake of symbolic names in gdb, we define true and false as
+   enum constants, not only as macros.
+   It is tempting to write
+      typedef enum { false = 0, true = 1 } _Bool;
+   so that gdb prints values of type 'bool' symbolically. But if we do
+   this, values of type '_Bool' may promote to 'int' or 'unsigned int'
+   (see ISO C 99 6.7.2.2.(4)); however, '_Bool' must promote to 'int'
+   (see ISO C 99 6.3.1.1.(2)).  So we add a negative value to the
+   enum; this ensures that '_Bool' promotes to 'int'.  */
+#if defined __cplusplus || defined __BEOS__
+  /* A compiler known to have 'bool'.  */
+  /* If the compiler already has both 'bool' and '_Bool', we can assume they
+     are the same types.  */
+# if !@HAVE__BOOL@
+typedef bool _Bool;
+# endif
+#else
+# if !defined __GNUC__
+   /* If @HAVE__BOOL@:
+        Some HP-UX cc and AIX IBM C compiler versions have compiler bugs when
+        the built-in _Bool type is used.  See
+          http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
+          http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
+          http://lists.gnu.org/archive/html/bug-coreutils/2005-10/msg00086.html
+        Similar bugs are likely with other compilers as well; this file
+        wouldn't be used if <stdbool.h> was working.
+        So we override the _Bool type.
+      If !@HAVE__BOOL@:
+        Need to define _Bool ourselves. As 'signed char' or as an enum type?
+        Use of a typedef, with SunPRO C, leads to a stupid
+          "warning: _Bool is a keyword in ISO C99".
+        Use of an enum type, with IRIX cc, leads to a stupid
+          "warning(1185): enumerated type mixed with another type".
+        The only benefit of the enum type, debuggability, is not important
+        with these compilers.  So use 'signed char' and no typedef.  */
+#  define _Bool signed char
+enum { false = 0, true = 1 };
+# else
+   /* With this compiler, trust the _Bool type if the compiler has it.  */
+#  if !@HAVE__BOOL@
+typedef enum { _Bool_must_promote_to_int = -1, false = 0, true = 1 } _Bool;
+#  endif
+# endif
+#endif
+#define bool _Bool
+
+/* The other macros must be usable in preprocessor directives.  */
+#define false 0
+#define true 1
+#define __bool_true_false_are_defined 1
+
+#endif /* _STDBOOL_H */
diff --git a/lib/stdio--.h b/lib/stdio--.h
new file mode 100644
index 0000000..b2765fd
--- /dev/null
+++ b/lib/stdio--.h
@@ -0,0 +1,25 @@
+/* Like stdio.h, but redefine some names to avoid glitches.
+
+   Copyright (C) 2005 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Paul Eggert.  */
+
+#include <stdio.h>
+#include "stdio-safer.h"
+
+#undef fopen
+#define fopen fopen_safer
diff --git a/lib/stdio-safer.h b/lib/stdio-safer.h
new file mode 100644
index 0000000..0b9a9ab
--- /dev/null
+++ b/lib/stdio-safer.h
@@ -0,0 +1,23 @@
+/* Invoke stdio functions, but avoid some glitches.
+
+   Copyright (C) 2001, 2003 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Paul Eggert.  */
+
+#include <stdio.h>
+
+FILE *fopen_safer (char const *, char const *);
diff --git a/lib/stpcpy.c b/lib/stpcpy.c
new file mode 100644
index 0000000..acda21a
--- /dev/null
+++ b/lib/stpcpy.c
@@ -0,0 +1,50 @@
+/* stpcpy.c -- copy a string and return pointer to end of new string
+   Copyright (C) 1992, 1995, 1997, 1998 Free Software Foundation, Inc.
+
+   NOTE: The canonical source of this file is maintained with the GNU C Library.
+   Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+   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 2, 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, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#undef __stpcpy
+#undef stpcpy
+
+#ifndef weak_alias
+# define __stpcpy stpcpy
+#endif
+
+/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST.  */
+char *
+__stpcpy (char *dest, const char *src)
+{
+  register char *d = dest;
+  register const char *s = src;
+
+  do
+    *d++ = *s;
+  while (*s++ != '\0');
+
+  return d - 1;
+}
+#ifdef weak_alias
+weak_alias (__stpcpy, stpcpy)
+#endif
diff --git a/lib/stpcpy.h b/lib/stpcpy.h
new file mode 100644
index 0000000..53c4ce0
--- /dev/null
+++ b/lib/stpcpy.h
@@ -0,0 +1,41 @@
+/* String copying.
+   Copyright (C) 1995, 2001, 2003 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _STPCPY_H
+#define _STPCPY_H
+
+#if HAVE_STPCPY
+
+/* Get stpcpy() declaration.  */
+#include <string.h>
+
+#else
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Copy SRC to DST, returning the address of the terminating '\0' in DST.  */
+extern char *stpcpy (char *dst, const char *src);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#endif /* _STPCPY_H */
diff --git a/lib/strdup.c b/lib/strdup.c
new file mode 100644
index 0000000..d6d0116
--- /dev/null
+++ b/lib/strdup.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 1991, 1996, 1997, 1998, 2002, 2003, 2004 Free Software
+   Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef _LIBC
+/* Get specification.  */
+# include "strdup.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#undef __strdup
+#undef strdup
+
+#ifndef weak_alias
+# define __strdup strdup
+#endif
+
+/* Duplicate S, returning an identical malloc'd string.  */
+char *
+__strdup (const char *s)
+{
+  size_t len = strlen (s) + 1;
+  void *new = malloc (len);
+
+  if (new == NULL)
+    return NULL;
+
+  return (char *) memcpy (new, s, len);
+}
+#ifdef libc_hidden_def
+libc_hidden_def (__strdup)
+#endif
+#ifdef weak_alias
+weak_alias (__strdup, strdup)
+#endif
diff --git a/lib/strdup.h b/lib/strdup.h
new file mode 100644
index 0000000..a0d5fb9
--- /dev/null
+++ b/lib/strdup.h
@@ -0,0 +1,29 @@
+/* strdup.h -- duplicate a string
+   Copyright (C) 2004 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef STRDUP_H_
+#define STRDUP_H_
+
+/* Get strdup declaration, if available.  */
+#include <string.h>
+
+#if defined HAVE_DECL_STRDUP && !HAVE_DECL_STRDUP && !defined strdup
+/* Duplicate S, returning an identical malloc'd string.  */
+extern char *strdup (const char *s);
+#endif
+
+#endif /* STRDUP_H_ */
diff --git a/lib/strerror.c b/lib/strerror.c
new file mode 100644
index 0000000..623821d
--- /dev/null
+++ b/lib/strerror.c
@@ -0,0 +1,49 @@
+/* strerror.c --- ANSI C compatible system error routine
+
+   Copyright (C) 1986, 1988, 1989, 1991, 2002, 2003 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <limits.h>
+
+/* Don't include <stdio.h>, since it may or may not declare
+   sys_errlist and its declarations may collide with ours.  Just
+   declare the stuff that we need directly.  Standard hosted C89
+   implementations define strerror and they don't need this strerror
+   function, so take some liberties with the standard to cater to
+   ancient or limited freestanding implementations.  */
+int sprintf (char *, char const *, ...);
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+char *
+strerror (int n)
+{
+  static char const fmt[] = "Unknown error (%d)";
+  static char mesg[sizeof fmt + sizeof n * CHAR_BIT / 3];
+
+  if (n < 0 || n >= sys_nerr)
+    {
+      sprintf (mesg, fmt, n);
+      return mesg;
+    }
+  else
+    return sys_errlist[n];
+}
diff --git a/lib/stripslash.c b/lib/stripslash.c
new file mode 100644
index 0000000..9b55da4
--- /dev/null
+++ b/lib/stripslash.c
@@ -0,0 +1,40 @@
+/* stripslash.c -- remove redundant trailing slashes from a file name
+
+   Copyright (C) 1990, 2001, 2003, 2004, 2005 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "dirname.h"
+
+/* Remove trailing slashes from FILE.
+   Return true if a trailing slash was removed.
+   This is useful when using file name completion from a shell that
+   adds a "/" after directory names (such as tcsh and bash), because
+   the Unix rename and rmdir system calls return an "Invalid argument" error
+   when given a file that ends in "/" (except for the root directory).  */
+
+bool
+strip_trailing_slashes (char *file)
+{
+  char *base = base_name (file);
+  char *base_lim = base + base_len (base);
+  bool had_slash = (*base_lim != '\0');
+  *base_lim = '\0';
+  return had_slash;
+}
diff --git a/lib/strndup.c b/lib/strndup.c
new file mode 100644
index 0000000..2626373
--- /dev/null
+++ b/lib/strndup.c
@@ -0,0 +1,66 @@
+/* Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2005, 2006 Free
+   Software Foundation, Inc.
+
+   NOTE: The canonical source of this file is maintained with the GNU C Library.
+   Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#if !_LIBC
+# include "strndup.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#if !_LIBC
+# include "strnlen.h"
+# ifndef __strnlen
+#  define __strnlen strnlen
+# endif
+#endif
+
+#undef __strndup
+#if _LIBC
+# undef strndup
+#endif
+
+#ifndef weak_alias
+# define __strndup strndup
+#endif
+
+char *
+__strndup (s, n)
+     const char *s;
+     size_t n;
+{
+  size_t len = __strnlen (s, n);
+  char *new = malloc (len + 1);
+
+  if (new == NULL)
+    return NULL;
+
+  new[len] = '\0';
+  return memcpy (new, s, len);
+}
+#ifdef libc_hidden_def
+libc_hidden_def (__strndup)
+#endif
+#ifdef weak_alias
+weak_alias (__strndup, strndup)
+#endif
diff --git a/lib/strndup.h b/lib/strndup.h
new file mode 100644
index 0000000..8eae493
--- /dev/null
+++ b/lib/strndup.h
@@ -0,0 +1,30 @@
+/* Duplicate a size-bounded string.
+   Copyright (C) 2003 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#if HAVE_STRNDUP
+
+/* Get strndup() declaration.  */
+#include <string.h>
+
+#else
+
+#include <stddef.h>
+
+/* Return a newly allocated copy of at most N bytes of STRING.  */
+extern char *strndup (const char *string, size_t n);
+
+#endif
diff --git a/lib/strnlen.c b/lib/strnlen.c
new file mode 100644
index 0000000..09ba788
--- /dev/null
+++ b/lib/strnlen.c
@@ -0,0 +1,33 @@
+/* Find the length of STRING, but scan at most MAXLEN characters.
+   Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+   Written by Simon Josefsson.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "strnlen.h"
+
+/* Find the length of STRING, but scan at most MAXLEN characters.
+   If no '\0' terminator is found in that many characters, return MAXLEN.  */
+
+size_t
+strnlen (const char *string, size_t maxlen)
+{
+  const char *end = memchr (string, '\0', maxlen);
+  return end ? (size_t) (end - string) : maxlen;
+}
diff --git a/lib/strnlen.h b/lib/strnlen.h
new file mode 100644
index 0000000..ba74dba
--- /dev/null
+++ b/lib/strnlen.h
@@ -0,0 +1,32 @@
+/* Find the length of STRING, but scan at most MAXLEN characters.
+   Copyright (C) 2005 Free Software Foundation, Inc.
+   Written by Simon Josefsson.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef STRNLEN_H
+#define STRNLEN_H
+
+/* Get strnlen declaration, if available.  */
+#include <string.h>
+
+#if defined HAVE_DECL_STRNLEN && !HAVE_DECL_STRNLEN
+/* Find the length (number of bytes) of STRING, but scan at most
+   MAXLEN bytes.  If no '\0' terminator is found in that many bytes,
+   return MAXLEN.  */
+extern size_t strnlen(const char *string, size_t maxlen);
+#endif
+
+#endif /* STRNLEN_H */
diff --git a/lib/strtol.c b/lib/strtol.c
new file mode 100644
index 0000000..9bfbe3c
--- /dev/null
+++ b/lib/strtol.c
@@ -0,0 +1,447 @@
+/* Convert string representation of a number into an integer value.
+
+   Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2003, 2005
+   Free Software Foundation, Inc.
+
+   NOTE: The canonical source of this file is maintained with the GNU C
+   Library.  Bugs can be reported to bug-glibc@gnu.org.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# define USE_NUMBER_GROUPING
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+#ifndef __set_errno
+# define __set_errno(Val) errno = (Val)
+#endif
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef USE_NUMBER_GROUPING
+# include "../locale/localeinfo.h"
+#endif
+
+/* Nonzero if we are defining `strtoul' or `strtoull', operating on
+   unsigned integers.  */
+#ifndef UNSIGNED
+# define UNSIGNED 0
+# define INT LONG int
+#else
+# define INT unsigned LONG int
+#endif
+
+/* Determine the name.  */
+#ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# if UNSIGNED
+#  ifdef USE_WIDE_CHAR
+#   ifdef QUAD
+#    define strtol __wcstoull_l
+#   else
+#    define strtol __wcstoul_l
+#   endif
+#  else
+#   ifdef QUAD
+#    define strtol __strtoull_l
+#   else
+#    define strtol __strtoul_l
+#   endif
+#  endif
+# else
+#  ifdef USE_WIDE_CHAR
+#   ifdef QUAD
+#    define strtol __wcstoll_l
+#   else
+#    define strtol __wcstol_l
+#   endif
+#  else
+#   ifdef QUAD
+#    define strtol __strtoll_l
+#   else
+#    define strtol __strtol_l
+#   endif
+#  endif
+# endif
+#else
+# if UNSIGNED
+#  ifdef USE_WIDE_CHAR
+#   ifdef QUAD
+#    define strtol wcstoull
+#   else
+#    define strtol wcstoul
+#   endif
+#  else
+#   ifdef QUAD
+#    define strtol strtoull
+#   else
+#    define strtol strtoul
+#   endif
+#  endif
+# else
+#  ifdef USE_WIDE_CHAR
+#   ifdef QUAD
+#    define strtol wcstoll
+#   else
+#    define strtol wcstol
+#   endif
+#  else
+#   ifdef QUAD
+#    define strtol strtoll
+#   endif
+#  endif
+# endif
+#endif
+
+/* If QUAD is defined, we are defining `strtoll' or `strtoull',
+   operating on `long long int's.  */
+#ifdef QUAD
+# define LONG long long
+# define STRTOL_LONG_MIN LONG_LONG_MIN
+# define STRTOL_LONG_MAX LONG_LONG_MAX
+# define STRTOL_ULONG_MAX ULONG_LONG_MAX
+
+/* The extra casts in the following macros work around compiler bugs,
+   e.g., in Cray C 5.0.3.0.  */
+
+/* True if negative values of the signed integer type T use two's
+   complement, ones' complement, or signed magnitude representation,
+   respectively.  Much GNU code assumes two's complement, but some
+   people like to be portable to all possible C hosts.  */
+# define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
+# define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0)
+# define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1)
+
+/* True if the arithmetic type T is signed.  */
+# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+
+/* The maximum and minimum values for the integer type T.  These
+   macros have undefined behavior if T is signed and has padding bits.
+   If this is a problem for you, please let us know how to fix it for
+   your host.  */
+# define TYPE_MINIMUM(t) \
+   ((t) (! TYPE_SIGNED (t) \
+	 ? (t) 0 \
+	 : TYPE_SIGNED_MAGNITUDE (t) \
+	 ? ~ (t) 0 \
+	 : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))
+# define TYPE_MAXIMUM(t) \
+   ((t) (! TYPE_SIGNED (t) \
+	 ? (t) -1 \
+	 : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
+
+# ifndef ULONG_LONG_MAX
+#  define ULONG_LONG_MAX TYPE_MAXIMUM (unsigned long long)
+# endif
+# ifndef LONG_LONG_MAX
+#  define LONG_LONG_MAX TYPE_MAXIMUM (long long int)
+# endif
+# ifndef LONG_LONG_MIN
+#  define LONG_LONG_MIN TYPE_MINIMUM (long long int)
+# endif
+
+# if __GNUC__ == 2 && __GNUC_MINOR__ < 7
+   /* Work around gcc bug with using this constant.  */
+   static const unsigned long long int maxquad = ULONG_LONG_MAX;
+#  undef STRTOL_ULONG_MAX
+#  define STRTOL_ULONG_MAX maxquad
+# endif
+#else
+# define LONG long
+# define STRTOL_LONG_MIN LONG_MIN
+# define STRTOL_LONG_MAX LONG_MAX
+# define STRTOL_ULONG_MAX ULONG_MAX
+#endif
+
+
+/* We use this code also for the extended locale handling where the
+   function gets as an additional argument the locale which has to be
+   used.  To access the values we have to redefine the _NL_CURRENT
+   macro.  */
+#ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# undef _NL_CURRENT
+# define _NL_CURRENT(category, item) \
+  (current->values[_NL_ITEM_INDEX (item)].string)
+# define LOCALE_PARAM , loc
+# define LOCALE_PARAM_PROTO , __locale_t loc
+#else
+# define LOCALE_PARAM
+# define LOCALE_PARAM_PROTO
+#endif
+
+#if defined _LIBC || defined HAVE_WCHAR_H
+# include <wchar.h>
+#endif
+
+#ifdef USE_WIDE_CHAR
+# include <wctype.h>
+# define L_(Ch) L##Ch
+# define UCHAR_TYPE wint_t
+# define STRING_TYPE wchar_t
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+#  define ISSPACE(Ch) __iswspace_l ((Ch), loc)
+#  define ISALPHA(Ch) __iswalpha_l ((Ch), loc)
+#  define TOUPPER(Ch) __towupper_l ((Ch), loc)
+# else
+#  define ISSPACE(Ch) iswspace (Ch)
+#  define ISALPHA(Ch) iswalpha (Ch)
+#  define TOUPPER(Ch) towupper (Ch)
+# endif
+#else
+# if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
+#  define IN_CTYPE_DOMAIN(c) 1
+# else
+#  define IN_CTYPE_DOMAIN(c) isascii(c)
+# endif
+# define L_(Ch) Ch
+# define UCHAR_TYPE unsigned char
+# define STRING_TYPE char
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+#  define ISSPACE(Ch) __isspace_l ((Ch), loc)
+#  define ISALPHA(Ch) __isalpha_l ((Ch), loc)
+#  define TOUPPER(Ch) __toupper_l ((Ch), loc)
+# else
+#  define ISSPACE(Ch) (IN_CTYPE_DOMAIN (Ch) && isspace (Ch))
+#  define ISALPHA(Ch) (IN_CTYPE_DOMAIN (Ch) && isalpha (Ch))
+#  define TOUPPER(Ch) (IN_CTYPE_DOMAIN (Ch) ? toupper (Ch) : (Ch))
+# endif
+#endif
+
+#define INTERNAL(X) INTERNAL1(X)
+#define INTERNAL1(X) __##X##_internal
+#define WEAKNAME(X) WEAKNAME1(X)
+
+#ifdef USE_NUMBER_GROUPING
+/* This file defines a function to check for correct grouping.  */
+# include "grouping.h"
+#endif
+
+
+
+/* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
+   If BASE is 0 the base is determined by the presence of a leading
+   zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
+   If BASE is < 2 or > 36, it is reset to 10.
+   If ENDPTR is not NULL, a pointer to the character after the last
+   one converted is stored in *ENDPTR.  */
+
+INT
+INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
+		   int base, int group LOCALE_PARAM_PROTO)
+{
+  int negative;
+  register unsigned LONG int cutoff;
+  register unsigned int cutlim;
+  register unsigned LONG int i;
+  register const STRING_TYPE *s;
+  register UCHAR_TYPE c;
+  const STRING_TYPE *save, *end;
+  int overflow;
+
+#ifdef USE_NUMBER_GROUPING
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+  struct locale_data *current = loc->__locales[LC_NUMERIC];
+# endif
+  /* The thousands character of the current locale.  */
+  wchar_t thousands = L'\0';
+  /* The numeric grouping specification of the current locale,
+     in the format described in <locale.h>.  */
+  const char *grouping;
+
+  if (group)
+    {
+      grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
+      if (*grouping <= 0 || *grouping == CHAR_MAX)
+	grouping = NULL;
+      else
+	{
+	  /* Figure out the thousands separator character.  */
+# if defined _LIBC || defined _HAVE_BTOWC
+	  thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP));
+	  if (thousands == WEOF)
+	    thousands = L'\0';
+# endif
+	  if (thousands == L'\0')
+	    grouping = NULL;
+	}
+    }
+  else
+    grouping = NULL;
+#endif
+
+  if (base < 0 || base == 1 || base > 36)
+    {
+      __set_errno (EINVAL);
+      return 0;
+    }
+
+  save = s = nptr;
+
+  /* Skip white space.  */
+  while (ISSPACE (*s))
+    ++s;
+  if (*s == L_('\0'))
+    goto noconv;
+
+  /* Check for a sign.  */
+  if (*s == L_('-'))
+    {
+      negative = 1;
+      ++s;
+    }
+  else if (*s == L_('+'))
+    {
+      negative = 0;
+      ++s;
+    }
+  else
+    negative = 0;
+
+  /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
+  if (*s == L_('0'))
+    {
+      if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X'))
+	{
+	  s += 2;
+	  base = 16;
+	}
+      else if (base == 0)
+	base = 8;
+    }
+  else if (base == 0)
+    base = 10;
+
+  /* Save the pointer so we can check later if anything happened.  */
+  save = s;
+
+#ifdef USE_NUMBER_GROUPING
+  if (group)
+    {
+      /* Find the end of the digit string and check its grouping.  */
+      end = s;
+      for (c = *end; c != L_('\0'); c = *++end)
+	if ((wchar_t) c != thousands
+	    && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9'))
+	    && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base))
+	  break;
+      if (*s == thousands)
+	end = s;
+      else
+	end = correctly_grouped_prefix (s, end, thousands, grouping);
+    }
+  else
+#endif
+    end = NULL;
+
+  cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base;
+  cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base;
+
+  overflow = 0;
+  i = 0;
+  for (c = *s; c != L_('\0'); c = *++s)
+    {
+      if (s == end)
+	break;
+      if (c >= L_('0') && c <= L_('9'))
+	c -= L_('0');
+      else if (ISALPHA (c))
+	c = TOUPPER (c) - L_('A') + 10;
+      else
+	break;
+      if ((int) c >= base)
+	break;
+      /* Check for overflow.  */
+      if (i > cutoff || (i == cutoff && c > cutlim))
+	overflow = 1;
+      else
+	{
+	  i *= (unsigned LONG int) base;
+	  i += c;
+	}
+    }
+
+  /* Check if anything actually happened.  */
+  if (s == save)
+    goto noconv;
+
+  /* Store in ENDPTR the address of one character
+     past the last character we converted.  */
+  if (endptr != NULL)
+    *endptr = (STRING_TYPE *) s;
+
+#if !UNSIGNED
+  /* Check for a value that is within the range of
+     `unsigned LONG int', but outside the range of `LONG int'.  */
+  if (overflow == 0
+      && i > (negative
+	      ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1
+	      : (unsigned LONG int) STRTOL_LONG_MAX))
+    overflow = 1;
+#endif
+
+  if (overflow)
+    {
+      __set_errno (ERANGE);
+#if UNSIGNED
+      return STRTOL_ULONG_MAX;
+#else
+      return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;
+#endif
+    }
+
+  /* Return the result of the appropriate sign.  */
+  return negative ? -i : i;
+
+noconv:
+  /* We must handle a special case here: the base is 0 or 16 and the
+     first two characters are '0' and 'x', but the rest are no
+     hexadecimal digits.  This is no error case.  We return 0 and
+     ENDPTR points to the `x`.  */
+  if (endptr != NULL)
+    {
+      if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
+	  && save[-2] == L_('0'))
+	*endptr = (STRING_TYPE *) &save[-1];
+      else
+	/*  There was no number to convert.  */
+	*endptr = (STRING_TYPE *) nptr;
+    }
+
+  return 0L;
+}
+
+/* External user entry point.  */
+
+
+INT
+#ifdef weak_function
+weak_function
+#endif
+strtol (const STRING_TYPE *nptr, STRING_TYPE **endptr,
+	int base LOCALE_PARAM_PROTO)
+{
+  return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM);
+}
diff --git a/lib/strtoul.c b/lib/strtoul.c
new file mode 100644
index 0000000..79ceed2
--- /dev/null
+++ b/lib/strtoul.c
@@ -0,0 +1,20 @@
+/* Copyright (C) 1991, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#define	UNSIGNED	1
+
+#include "strtol.c"
diff --git a/lib/strverscmp.c b/lib/strverscmp.c
new file mode 100644
index 0000000..6276bca
--- /dev/null
+++ b/lib/strverscmp.c
@@ -0,0 +1,131 @@
+/* Compare strings while treating digits characters numerically.
+   Copyright (C) 1997, 2000, 2002, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jean-François Bignolles <bignolle@ecoledoc.ibp.fr>, 1997.
+
+   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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <ctype.h>
+
+/* states: S_N: normal, S_I: comparing integral part, S_F: comparing
+           fractional parts, S_Z: idem but with leading Zeroes only */
+#define S_N    0x0
+#define S_I    0x4
+#define S_F    0x8
+#define S_Z    0xC
+
+/* result_type: CMP: return diff; LEN: compare using len_diff/diff */
+#define CMP    2
+#define LEN    3
+
+
+/* ISDIGIT differs from isdigit, as follows:
+   - Its arg may be any int or unsigned int; it need not be an unsigned char.
+   - It's guaranteed to evaluate its argument exactly once.
+   - It's typically faster.
+   POSIX says that only '0' through '9' are digits.  Prefer ISDIGIT to
+   ISDIGIT_LOCALE unless it's important to use the locale's definition
+   of `digit' even when the host does not conform to POSIX.  */
+#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
+
+#undef __strverscmp
+#undef strverscmp
+
+#ifndef weak_alias
+# define __strverscmp strverscmp
+#endif
+
+/* Compare S1 and S2 as strings holding indices/version numbers,
+   returning less than, equal to or greater than zero if S1 is less than,
+   equal to or greater than S2 (for more info, see the texinfo doc).
+*/
+
+int
+__strverscmp (const char *s1, const char *s2)
+{
+  const unsigned char *p1 = (const unsigned char *) s1;
+  const unsigned char *p2 = (const unsigned char *) s2;
+  unsigned char c1, c2;
+  int state;
+  int diff;
+
+  /* Symbol(s)    0       [1-9]   others  (padding)
+     Transition   (10) 0  (01) d  (00) x  (11) -   */
+  static const unsigned int next_state[] =
+  {
+      /* state    x    d    0    - */
+      /* S_N */  S_N, S_I, S_Z, S_N,
+      /* S_I */  S_N, S_I, S_I, S_I,
+      /* S_F */  S_N, S_F, S_F, S_F,
+      /* S_Z */  S_N, S_F, S_Z, S_Z
+  };
+
+  static const int result_type[] =
+  {
+      /* state   x/x  x/d  x/0  x/-  d/x  d/d  d/0  d/-
+                 0/x  0/d  0/0  0/-  -/x  -/d  -/0  -/- */
+
+      /* S_N */  CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
+                 CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+      /* S_I */  CMP, -1,  -1,  CMP,  1,  LEN, LEN, CMP,
+                  1,  LEN, LEN, CMP, CMP, CMP, CMP, CMP,
+      /* S_F */  CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
+                 CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+      /* S_Z */  CMP,  1,   1,  CMP, -1,  CMP, CMP, CMP,
+                 -1,  CMP, CMP, CMP
+  };
+
+  if (p1 == p2)
+    return 0;
+
+  c1 = *p1++;
+  c2 = *p2++;
+  /* Hint: '0' is a digit too.  */
+  state = S_N | ((c1 == '0') + (ISDIGIT (c1) != 0));
+
+  while ((diff = c1 - c2) == 0 && c1 != '\0')
+    {
+      state = next_state[state];
+      c1 = *p1++;
+      c2 = *p2++;
+      state |= (c1 == '0') + (ISDIGIT (c1) != 0);
+    }
+
+  state = result_type[state << 2 | ((c2 == '0') + (ISDIGIT (c2) != 0))];
+
+  switch (state)
+    {
+    case CMP:
+      return diff;
+
+    case LEN:
+      while (ISDIGIT (*p1++))
+	if (!ISDIGIT (*p2++))
+	  return 1;
+
+      return ISDIGIT (*p2) ? -1 : diff;
+
+    default:
+      return state;
+    }
+}
+#ifdef weak_alias
+weak_alias (__strverscmp, strverscmp)
+#endif
diff --git a/lib/strverscmp.h b/lib/strverscmp.h
new file mode 100644
index 0000000..7edeac5
--- /dev/null
+++ b/lib/strverscmp.h
@@ -0,0 +1,24 @@
+/* Compare strings while treating digits characters numerically.
+
+   Copyright (C) 1997, 2003 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef STRVERSCMP_H_
+# define STRVERSCMP_H_
+
+int strverscmp (const char *, const char *);
+
+#endif /* not STRVERSCMP_H_ */
diff --git a/lib/subpipe.c b/lib/subpipe.c
new file mode 100644
index 0000000..646aa8e
--- /dev/null
+++ b/lib/subpipe.c
@@ -0,0 +1,186 @@
+/* Subprocesses with pipes.
+
+   Copyright (C) 2002, 2004, 2005, 2006 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Paul Eggert <eggert@twinsun.com>
+   and Florian Krohm <florian@edamail.fishkill.ibm.com>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "subpipe.h"
+
+#include <errno.h>
+
+#include <signal.h>
+#if ! defined SIGCHLD && defined SIGCLD
+# define SIGCHLD SIGCLD
+#endif
+
+#include <stdlib.h>
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+#if ! HAVE_DUP2 && ! defined dup2
+# include <fcntl.h>
+# define dup2(f, t) (close (t), fcntl (f, F_DUPFD, t))
+#endif
+
+#if HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+
+#if HAVE_VFORK_H
+# include <vfork.h>
+#endif
+#if ! HAVE_WORKING_VFORK
+# define vfork fork
+#endif
+
+#include "error.h"
+#include "unistd-safer.h"
+
+#include "gettext.h"
+#define _(Msgid)  gettext (Msgid)
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later.  */
+# if ! defined __GNUC__ || __GNUC__ < 2 || \
+(__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
+#  define __attribute__(Spec) /* empty */
+# endif
+#endif
+
+#ifndef ATTRIBUTE_UNUSED
+# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif
+
+
+/* Initialize this module.  */
+
+void
+init_subpipe (void)
+{
+#ifdef SIGCHLD
+  /* System V fork+wait does not work if SIGCHLD is ignored.  */
+  signal (SIGCHLD, SIG_DFL);
+#endif
+}
+
+
+/* Create a subprocess that is run as a filter.  ARGV is the
+   NULL-terminated argument vector for the subprocess.  Store read and
+   write file descriptors for communication with the subprocess into
+   FD[0] and FD[1]: input meant for the process can be written into
+   FD[0], and output from the process can be read from FD[1].  Return
+   the subprocess id.
+
+   To avoid deadlock, the invoker must not let incoming data pile up
+   in FD[1] while writing data to FD[0].  */
+
+pid_t
+create_subpipe (char const * const *argv, int fd[2])
+{
+  int pipe_fd[2];
+  int child_fd[2];
+  pid_t pid;
+
+  if (pipe (child_fd) != 0
+      || (child_fd[0] = fd_safer (child_fd[0])) < 0
+      || (fd[0] = fd_safer (child_fd[1])) < 0
+      || pipe (pipe_fd) != 0
+      || (fd[1] = fd_safer (pipe_fd[0])) < 0
+      || (child_fd[1] = fd_safer (pipe_fd[1])) < 0)
+    error (EXIT_FAILURE, errno,
+	   "pipe");
+
+  pid = vfork ();
+  if (pid < 0)
+    error (EXIT_FAILURE, errno,
+	   "fork");
+
+  if (! pid)
+    {
+      /* Child.  */
+      close (fd[0]);
+      close (fd[1]);
+      dup2 (child_fd[0], STDIN_FILENO);
+      close (child_fd[0]);
+      dup2 (child_fd[1], STDOUT_FILENO);
+      close (child_fd[1]);
+
+      /* The cast to (char **) rather than (char * const *) is needed
+	 for portability to older hosts with a nonstandard prototype
+	 for execvp.  */
+      execvp (argv[0], (char **) argv);
+
+      _exit (errno == ENOENT ? 127 : 126);
+    }
+
+  /* Parent.  */
+  close (child_fd[0]);
+  close (child_fd[1]);
+  return pid;
+}
+
+
+/* Wait for the subprocess to exit.  */
+
+void
+reap_subpipe (pid_t pid, char const *program)
+{
+#if HAVE_WAITPID || defined waitpid
+  int wstatus;
+  if (waitpid (pid, &wstatus, 0) < 0)
+    error (EXIT_FAILURE, errno,
+	   "waitpid");
+  else
+    {
+      int status = WIFEXITED (wstatus) ? WEXITSTATUS (wstatus) : -1;
+      if (status)
+	error (EXIT_FAILURE, 0,
+	       _(status == 126
+		 ? "subsidiary program `%s' could not be invoked"
+		 : status == 127
+		 ? "subsidiary program `%s' not found"
+		 : status < 0
+		 ? "subsidiary program `%s' failed"
+		 : "subsidiary program `%s' failed (exit status %d)"),
+	       program, status);
+    }
+#endif
+}
+
+void
+end_of_output_subpipe (pid_t pid ATTRIBUTE_UNUSED,
+		       int fd[2] ATTRIBUTE_UNUSED)
+{
+}
diff --git a/lib/subpipe.h b/lib/subpipe.h
new file mode 100644
index 0000000..1083d32
--- /dev/null
+++ b/lib/subpipe.h
@@ -0,0 +1,28 @@
+/* Subprocesses with pipes.
+   Copyright (C) 2002, 2004, 2005 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 2 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Paul Eggert <eggert@twinsun.com>
+   and Florian Krohm <florian@edamail.fishkill.ibm.com>.  */
+
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+void init_subpipe (void);
+pid_t create_subpipe (char const * const *, int[2]);
+void end_of_output_subpipe (pid_t, int[2]);
+void reap_subpipe (pid_t, char const *);
diff --git a/lib/timevar.c b/lib/timevar.c
new file mode 100644
index 0000000..d9b533c
--- /dev/null
+++ b/lib/timevar.c
@@ -0,0 +1,565 @@
+/* Timing variables for measuring compiler performance.
+   Copyright (C) 2000, 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
+   Contributed by Alex Samuel <samuel@codesourcery.com>
+
+   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 2 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if IN_GCC
+
+#include "system.h"
+#include "intl.h"
+#include "rtl.h"
+
+#else
+
+/* This source file is taken from the GCC source code, with slight
+   modifications that are under control of the IN_GCC preprocessor
+   variable.  The !IN_GCC part of this file is specific to Bison.  */
+
+# include "../src/system.h"
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# endif
+int timevar_report = 0;
+
+#endif
+
+
+#ifdef HAVE_SYS_TIMES_H
+# include <sys/times.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#ifndef HAVE_CLOCK_T
+typedef int clock_t;
+#endif
+
+#ifndef HAVE_STRUCT_TMS
+struct tms
+{
+  clock_t tms_utime;
+  clock_t tms_stime;
+  clock_t tms_cutime;
+  clock_t tms_cstime;
+};
+#endif
+
+#if defined HAVE_DECL_GETRUSAGE && !HAVE_DECL_GETRUSAGE
+extern int getrusage (int, struct rusage *);
+#endif
+#if defined HAVE_DECL_TIMES && !HAVE_DECL_TIMES
+extern clock_t times (struct tms *);
+#endif
+#if defined HAVE_DECL_CLOCK && !HAVE_DECL_CLOCK
+extern clock_t clock (void);
+#endif
+
+#ifndef RUSAGE_SELF
+# define RUSAGE_SELF 0
+#endif
+
+/* Calculation of scale factor to convert ticks to microseconds.
+   We mustn't use CLOCKS_PER_SEC except with clock().  */
+#if HAVE_SYSCONF && defined _SC_CLK_TCK
+# define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
+#else
+# ifdef CLK_TCK
+#  define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
+# else
+#  ifdef HZ
+#   define TICKS_PER_SECOND HZ  /* traditional UNIX */
+#  else
+#   define TICKS_PER_SECOND 100 /* often the correct value */
+#  endif
+# endif
+#endif
+
+/* Prefer times to getrusage to clock (each gives successively less
+   information).  */
+#ifdef HAVE_TIMES
+# define USE_TIMES
+# define HAVE_USER_TIME
+# define HAVE_SYS_TIME
+# define HAVE_WALL_TIME
+#else
+#ifdef HAVE_GETRUSAGE
+# define USE_GETRUSAGE
+# define HAVE_USER_TIME
+# define HAVE_SYS_TIME
+#else
+#ifdef HAVE_CLOCK
+# define USE_CLOCK
+# define HAVE_USER_TIME
+#endif
+#endif
+#endif
+
+/* libc is very likely to have snuck a call to sysconf() into one of
+   the underlying constants, and that can be very slow, so we have to
+   precompute them.  Whose wonderful idea was it to make all those
+   _constants_ variable at run time, anyway?  */
+#ifdef USE_TIMES
+static float ticks_to_msec;
+#define TICKS_TO_MSEC (1.0 / TICKS_PER_SECOND)
+#endif
+
+#ifdef USE_CLOCK
+static float clocks_to_msec;
+#define CLOCKS_TO_MSEC (1.0 / CLOCKS_PER_SEC)
+#endif
+
+#if IN_GCC
+#include "flags.h"
+#endif
+#include "timevar.h"
+
+/* See timevar.h for an explanation of timing variables.  */
+
+/* This macro evaluates to nonzero if timing variables are enabled.  */
+#define TIMEVAR_ENABLE (timevar_report)
+
+/* A timing variable.  */
+
+struct timevar_def
+{
+  /* Elapsed time for this variable.  */
+  struct timevar_time_def elapsed;
+
+  /* If this variable is timed independently of the timing stack,
+     using timevar_start, this contains the start time.  */
+  struct timevar_time_def start_time;
+
+  /* The name of this timing variable.  */
+  const char *name;
+
+  /* Non-zero if this timing variable is running as a standalone
+     timer.  */
+  unsigned standalone : 1;
+
+  /* Non-zero if this timing variable was ever started or pushed onto
+     the timing stack.  */
+  unsigned used : 1;
+};
+
+/* An element on the timing stack.  Elapsed time is attributed to the
+   topmost timing variable on the stack.  */
+
+struct timevar_stack_def
+{
+  /* The timing variable at this stack level.  */
+  struct timevar_def *timevar;
+
+  /* The next lower timing variable context in the stack.  */
+  struct timevar_stack_def *next;
+};
+
+/* Declared timing variables.  Constructed from the contents of
+   timevar.def.  */
+static struct timevar_def timevars[TIMEVAR_LAST];
+
+/* The top of the timing stack.  */
+static struct timevar_stack_def *stack;
+
+/* A list of unused (i.e. allocated and subsequently popped)
+   timevar_stack_def instances.  */
+static struct timevar_stack_def *unused_stack_instances;
+
+/* The time at which the topmost element on the timing stack was
+   pushed.  Time elapsed since then is attributed to the topmost
+   element.  */
+static struct timevar_time_def start_time;
+
+static void get_time (struct timevar_time_def *);
+static void timevar_accumulate (struct timevar_time_def *,
+				struct timevar_time_def *,
+				struct timevar_time_def *);
+
+/* Fill the current times into TIME.  The definition of this function
+   also defines any or all of the HAVE_USER_TIME, HAVE_SYS_TIME, and
+   HAVE_WALL_TIME macros.  */
+
+static void
+get_time (now)
+     struct timevar_time_def *now;
+{
+  now->user = 0;
+  now->sys  = 0;
+  now->wall = 0;
+
+  if (!TIMEVAR_ENABLE)
+    return;
+
+  {
+#ifdef USE_TIMES
+    struct tms tms;
+    now->wall = times (&tms)  * ticks_to_msec;
+#if IN_GCC
+    now->user = tms.tms_utime * ticks_to_msec;
+    now->sys  = tms.tms_stime * ticks_to_msec;
+#else
+    now->user = (tms.tms_utime + tms.tms_cutime) * ticks_to_msec;
+    now->sys  = (tms.tms_stime + tms.tms_cstime) * ticks_to_msec;
+#endif
+#endif
+#ifdef USE_GETRUSAGE
+    struct rusage rusage;
+#if IN_GCC
+    getrusage (RUSAGE_SELF, &rusage);
+#else
+    getrusage (RUSAGE_CHILDREN, &rusage);
+#endif
+    now->user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec * 1e-6;
+    now->sys  = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec * 1e-6;
+#endif
+#ifdef USE_CLOCK
+    now->user = clock () * clocks_to_msec;
+#endif
+  }
+}
+
+/* Add the difference between STOP and START to TIMER.  */
+
+static void
+timevar_accumulate (timer, start, stop)
+     struct timevar_time_def *timer;
+     struct timevar_time_def *start;
+     struct timevar_time_def *stop;
+{
+  timer->user += stop->user - start->user;
+  timer->sys += stop->sys - start->sys;
+  timer->wall += stop->wall - start->wall;
+}
+
+/* Initialize timing variables.  */
+
+void
+init_timevar ()
+{
+  if (!TIMEVAR_ENABLE)
+    return;
+
+  /* Zero all elapsed times.  */
+  memset ((void *) timevars, 0, sizeof (timevars));
+
+  /* Initialize the names of timing variables.  */
+#define DEFTIMEVAR(identifier__, name__) \
+  timevars[identifier__].name = name__;
+#include "timevar.def"
+#undef DEFTIMEVAR
+
+#ifdef USE_TIMES
+  ticks_to_msec = TICKS_TO_MSEC;
+#endif
+#ifdef USE_CLOCK
+  clocks_to_msec = CLOCKS_TO_MSEC;
+#endif
+}
+
+/* Push TIMEVAR onto the timing stack.  No further elapsed time is
+   attributed to the previous topmost timing variable on the stack;
+   subsequent elapsed time is attributed to TIMEVAR, until it is
+   popped or another element is pushed on top.
+
+   TIMEVAR cannot be running as a standalone timer.  */
+
+void
+timevar_push (timevar)
+     timevar_id_t timevar;
+{
+  struct timevar_def *tv = &timevars[timevar];
+  struct timevar_stack_def *context;
+  struct timevar_time_def now;
+
+  if (!TIMEVAR_ENABLE)
+    return;
+
+  /* Mark this timing variable as used.  */
+  tv->used = 1;
+
+  /* Can't push a standalone timer.  */
+  if (tv->standalone)
+    abort ();
+
+  /* What time is it?  */
+  get_time (&now);
+
+  /* If the stack isn't empty, attribute the current elapsed time to
+     the old topmost element.  */
+  if (stack)
+    timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
+
+  /* Reset the start time; from now on, time is attributed to
+     TIMEVAR.  */
+  start_time = now;
+
+  /* See if we have a previously-allocated stack instance.  If so,
+     take it off the list.  If not, malloc a new one.  */
+  if (unused_stack_instances != NULL)
+    {
+      context = unused_stack_instances;
+      unused_stack_instances = unused_stack_instances->next;
+    }
+  else
+    context = (struct timevar_stack_def *)
+      xmalloc (sizeof (struct timevar_stack_def));
+
+  /* Fill it in and put it on the stack.  */
+  context->timevar = tv;
+  context->next = stack;
+  stack = context;
+}
+
+/* Pop the topmost timing variable element off the timing stack.  The
+   popped variable must be TIMEVAR.  Elapsed time since the that
+   element was pushed on, or since it was last exposed on top of the
+   stack when the element above it was popped off, is credited to that
+   timing variable.  */
+
+void
+timevar_pop (timevar)
+     timevar_id_t timevar;
+{
+  struct timevar_time_def now;
+  struct timevar_stack_def *popped = stack;
+
+  if (!TIMEVAR_ENABLE)
+    return;
+
+  if (&timevars[timevar] != stack->timevar)
+    abort ();
+
+  /* What time is it?  */
+  get_time (&now);
+
+  /* Attribute the elapsed time to the element we're popping.  */
+  timevar_accumulate (&popped->timevar->elapsed, &start_time, &now);
+
+  /* Reset the start time; from now on, time is attributed to the
+     element just exposed on the stack.  */
+  start_time = now;
+
+  /* Take the item off the stack.  */
+  stack = stack->next;
+
+  /* Don't delete the stack element; instead, add it to the list of
+     unused elements for later use.  */
+  popped->next = unused_stack_instances;
+  unused_stack_instances = popped;
+}
+
+/* Start timing TIMEVAR independently of the timing stack.  Elapsed
+   time until timevar_stop is called for the same timing variable is
+   attributed to TIMEVAR.  */
+
+void
+timevar_start (timevar)
+     timevar_id_t timevar;
+{
+  struct timevar_def *tv = &timevars[timevar];
+
+  if (!TIMEVAR_ENABLE)
+    return;
+
+  /* Mark this timing variable as used.  */
+  tv->used = 1;
+
+  /* Don't allow the same timing variable to be started more than
+     once.  */
+  if (tv->standalone)
+    abort ();
+  tv->standalone = 1;
+
+  get_time (&tv->start_time);
+}
+
+/* Stop timing TIMEVAR.  Time elapsed since timevar_start was called
+   is attributed to it.  */
+
+void
+timevar_stop (timevar)
+     timevar_id_t timevar;
+{
+  struct timevar_def *tv = &timevars[timevar];
+  struct timevar_time_def now;
+
+  if (!TIMEVAR_ENABLE)
+    return;
+
+  /* TIMEVAR must have been started via timevar_start.  */
+  if (!tv->standalone)
+    abort ();
+
+  get_time (&now);
+  timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
+}
+
+/* Fill the elapsed time for TIMEVAR into ELAPSED.  Returns
+   update-to-date information even if TIMEVAR is currently running.  */
+
+void
+timevar_get (timevar, elapsed)
+     timevar_id_t timevar;
+     struct timevar_time_def *elapsed;
+{
+  struct timevar_def *tv = &timevars[timevar];
+  struct timevar_time_def now;
+
+  *elapsed = tv->elapsed;
+
+  /* Is TIMEVAR currently running as a standalone timer?  */
+  if (tv->standalone)
+    {
+      get_time (&now);
+      timevar_accumulate (elapsed, &tv->start_time, &now);
+    }
+  /* Or is TIMEVAR at the top of the timer stack?  */
+  else if (stack->timevar == tv)
+    {
+      get_time (&now);
+      timevar_accumulate (elapsed, &start_time, &now);
+    }
+}
+
+/* Summarize timing variables to FP.  The timing variable TV_TOTAL has
+   a special meaning -- it's considered to be the total elapsed time,
+   for normalizing the others, and is displayed last.  */
+
+void
+timevar_print (fp)
+     FILE *fp;
+{
+  /* Only print stuff if we have some sort of time information.  */
+#if defined HAVE_USER_TIME || defined HAVE_SYS_TIME || defined HAVE_WALL_TIME
+  unsigned int /* timevar_id_t */ id;
+  struct timevar_time_def *total = &timevars[TV_TOTAL].elapsed;
+  struct timevar_time_def now;
+
+  if (!TIMEVAR_ENABLE)
+    return;
+
+  /* Update timing information in case we're calling this from GDB.  */
+
+  if (fp == 0)
+    fp = stderr;
+
+  /* What time is it?  */
+  get_time (&now);
+
+  /* If the stack isn't empty, attribute the current elapsed time to
+     the old topmost element.  */
+  if (stack)
+    timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
+
+  /* Reset the start time; from now on, time is attributed to
+     TIMEVAR.  */
+  start_time = now;
+
+  fputs (_("\nExecution times (seconds)\n"), fp);
+  for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
+    {
+      struct timevar_def *tv = &timevars[(timevar_id_t) id];
+      const float tiny = 5e-3;
+
+      /* Don't print the total execution time here; that goes at the
+	 end.  */
+      if ((timevar_id_t) id == TV_TOTAL)
+	continue;
+
+      /* Don't print timing variables that were never used.  */
+      if (!tv->used)
+	continue;
+
+      /* Don't print timing variables if we're going to get a row of
+	 zeroes.  */
+      if (tv->elapsed.user < tiny
+	  && tv->elapsed.sys < tiny
+	  && tv->elapsed.wall < tiny)
+	continue;
+
+      /* The timing variable name.  */
+      fprintf (fp, " %-22s:", tv->name);
+
+#ifdef HAVE_USER_TIME
+      /* Print user-mode time for this process.  */
+      fprintf (fp, "%7.2f (%2.0f%%) usr",
+	       tv->elapsed.user,
+	       (total->user == 0 ? 0 : tv->elapsed.user / total->user) * 100);
+#endif /* HAVE_USER_TIME */
+
+#ifdef HAVE_SYS_TIME
+      /* Print system-mode time for this process.  */
+      fprintf (fp, "%7.2f (%2.0f%%) sys",
+	       tv->elapsed.sys,
+	       (total->sys == 0 ? 0 : tv->elapsed.sys / total->sys) * 100);
+#endif /* HAVE_SYS_TIME */
+
+#ifdef HAVE_WALL_TIME
+      /* Print wall clock time elapsed.  */
+      fprintf (fp, "%7.2f (%2.0f%%) wall",
+	       tv->elapsed.wall,
+	       (total->wall == 0 ? 0 : tv->elapsed.wall / total->wall) * 100);
+#endif /* HAVE_WALL_TIME */
+
+      putc ('\n', fp);
+    }
+
+  /* Print total time.  */
+  fputs (_(" TOTAL                 :"), fp);
+#ifdef HAVE_USER_TIME
+  fprintf (fp, "%7.2f          ", total->user);
+#endif
+#ifdef HAVE_SYS_TIME
+  fprintf (fp, "%7.2f          ", total->sys);
+#endif
+#ifdef HAVE_WALL_TIME
+  fprintf (fp, "%7.2f\n", total->wall);
+#endif
+
+#endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
+	  || defined (HAVE_WALL_TIME) */
+}
+
+/* Returns time (user + system) used so far by the compiler process,
+   in microseconds.  */
+
+long
+get_run_time ()
+{
+  struct timevar_time_def total_elapsed;
+  timevar_get (TV_TOTAL, &total_elapsed);
+  return total_elapsed.user + total_elapsed.sys;
+}
+
+/* Prints a message to stderr stating that time elapsed in STR is
+   TOTAL (given in microseconds).  */
+
+void
+print_time (str, total)
+     const char *str;
+     long total;
+{
+  long all_time = get_run_time ();
+  fprintf (stderr,
+	   _("time in %s: %ld.%06ld (%ld%%)\n"),
+	   str, total / 1000000, total % 1000000,
+	   all_time == 0 ? 0
+	   : (long) (((100.0 * (double) total) / (double) all_time) + .5));
+}
diff --git a/lib/timevar.def b/lib/timevar.def
new file mode 100644
index 0000000..04ac392
--- /dev/null
+++ b/lib/timevar.def
@@ -0,0 +1,56 @@
+/* This file contains the definitions for timing variables used to -*- C -*-
+   measure run-time performance of the compiler.
+   Copyright (C) 2002 Free Software Foundation, Inc.
+   Contributed by Akim Demaille <akim@freefriends.org>.
+
+   This file is part of Bison, the GNU Compiler Compiler.
+
+   Bison 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 2, or (at your option)
+   any later version.
+
+   Bison 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 Bison; see the file COPYING.  If not, write to
+   the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* This file contains timing variable definitions, used by timevar.h
+   and timevar.c.
+
+   Syntax:
+
+     DEFTIMEVAR (id, name)
+
+   where ID is the enumeral value used to identify the timing
+   variable, and NAME is a character string describing its purpose.  */
+
+/* The total execution time.  */
+DEFTIMEVAR (TV_TOTAL                 , "total time")
+
+/* Time spent in the reader.  */
+DEFTIMEVAR (TV_READER                , "reader")
+DEFTIMEVAR (TV_SCANNING              , "scanner")
+DEFTIMEVAR (TV_PARSING               , "parser")
+
+/* Time spent handling the grammar.  */
+DEFTIMEVAR (TV_REDUCE                , "reducing the grammar")
+DEFTIMEVAR (TV_SETS                  , "computing the sets")
+DEFTIMEVAR (TV_LR0                   , "LR(0)")
+DEFTIMEVAR (TV_LALR                  , "LALR(1)")
+DEFTIMEVAR (TV_CONFLICTS             , "conflicts")
+
+/* Time spent outputing results.  */
+DEFTIMEVAR (TV_REPORT                , "outputing report")
+DEFTIMEVAR (TV_GRAPH                 , "outputing graph")
+DEFTIMEVAR (TV_ACTIONS               , "parser action tables")
+DEFTIMEVAR (TV_PARSER                , "outputing parser")
+DEFTIMEVAR (TV_M4                    , "running m4")
+
+/* Time spent by freeing the memory :).  */
+DEFTIMEVAR (TV_FREE                  , "freeing")
diff --git a/lib/timevar.h b/lib/timevar.h
new file mode 100644
index 0000000..bbeb402
--- /dev/null
+++ b/lib/timevar.h
@@ -0,0 +1,90 @@
+/* Timing variables for measuring compiler performance.
+   Copyright (C) 2000, 2002, 2004 Free Software Foundation, Inc.
+   Contributed by Alex Samuel <samuel@codesourcery.com>
+
+   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 2 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef GCC_TIMEVAR_H
+#define GCC_TIMEVAR_H
+
+/* Timing variables are used to measure elapsed time in various
+   portions of the compiler.  Each measures elapsed user, system, and
+   wall-clock time, as appropriate to and supported by the host
+   system.
+
+   Timing variables are defined using the DEFTIMEVAR macro in
+   timevar.def.  Each has an enumeral identifier, used when referring
+   to the timing variable in code, and a character string name.
+
+   Timing variables can be used in two ways:
+
+     - On the timing stack, using timevar_push and timevar_pop.
+       Timing variables may be pushed onto the stack; elapsed time is
+       attributed to the topmost timing variable on the stack.  When
+       another variable is pushed on, the previous topmost variable is
+       `paused' until the pushed variable is popped back off.
+
+     - As a standalone timer, using timevar_start and timevar_stop.
+       All time elapsed between the two calls is attributed to the
+       variable.
+*/
+
+/* This structure stores the various varieties of time that can be
+   measured.  Times are stored in seconds.  The time may be an
+   absolute time or a time difference; in the former case, the time
+   base is undefined, except that the difference between two times
+   produces a valid time difference.  */
+
+struct timevar_time_def
+{
+  /* User time in this process.  */
+  float user;
+
+  /* System time (if applicable for this host platform) in this
+     process.  */
+  float sys;
+
+  /* Wall clock time.  */
+  float wall;
+};
+
+/* An enumeration of timing variable identifiers.  Constructed from
+   the contents of timevar.def.  */
+
+#define DEFTIMEVAR(identifier__, name__) \
+    identifier__,
+typedef enum
+{
+#include "timevar.def"
+  TIMEVAR_LAST
+}
+timevar_id_t;
+#undef DEFTIMEVAR
+
+extern void init_timevar (void);
+extern void timevar_push (timevar_id_t);
+extern void timevar_pop (timevar_id_t);
+extern void timevar_start (timevar_id_t);
+extern void timevar_stop (timevar_id_t);
+extern void timevar_get (timevar_id_t, struct timevar_time_def *);
+extern void timevar_print (FILE *);
+
+/* Provided for backward compatibility.  */
+extern long get_run_time (void);
+extern void print_time (const char *, long);
+
+extern int timevar_report;
+
+#endif /* ! GCC_TIMEVAR_H */
diff --git a/lib/unistd--.h b/lib/unistd--.h
new file mode 100644
index 0000000..1fe6ce8
--- /dev/null
+++ b/lib/unistd--.h
@@ -0,0 +1,28 @@
+/* Like unistd.h, but redefine some names to avoid glitches.
+
+   Copyright (C) 2005 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Paul Eggert.  */
+
+#include <unistd.h>
+#include "unistd-safer.h"
+
+#undef dup
+#define dup dup_safer
+
+#undef pipe
+#define pipe pipe_safer
diff --git a/lib/unistd-safer.h b/lib/unistd-safer.h
new file mode 100644
index 0000000..f95999d
--- /dev/null
+++ b/lib/unistd-safer.h
@@ -0,0 +1,23 @@
+/* Invoke unistd-like functions, but avoid some glitches.
+
+   Copyright (C) 2001, 2003, 2005 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Paul Eggert.  */
+
+int dup_safer (int);
+int fd_safer (int);
+int pipe_safer (int[2]);
diff --git a/lib/unlocked-io.h b/lib/unlocked-io.h
new file mode 100644
index 0000000..d009303
--- /dev/null
+++ b/lib/unlocked-io.h
@@ -0,0 +1,137 @@
+/* Prefer faster, non-thread-safe stdio functions if available.
+
+   Copyright (C) 2001, 2002, 2003, 2004 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Jim Meyering.  */
+
+#ifndef UNLOCKED_IO_H
+# define UNLOCKED_IO_H 1
+
+/* These are wrappers for functions/macros from the GNU C library, and
+   from other C libraries supporting POSIX's optional thread-safe functions.
+
+   The standard I/O functions are thread-safe.  These *_unlocked ones are
+   more efficient but not thread-safe.  That they're not thread-safe is
+   fine since all of the applications in this package are single threaded.
+
+   Also, some code that is shared with the GNU C library may invoke
+   the *_unlocked functions directly.  On hosts that lack those
+   functions, invoke the non-thread-safe versions instead.  */
+
+# include <stdio.h>
+
+# if HAVE_DECL_CLEARERR_UNLOCKED
+#  undef clearerr
+#  define clearerr(x) clearerr_unlocked (x)
+# else
+#  define clearerr_unlocked(x) clearerr (x)
+# endif
+
+# if HAVE_DECL_FEOF_UNLOCKED
+#  undef feof
+#  define feof(x) feof_unlocked (x)
+# else
+#  define feof_unlocked(x) feof (x)
+# endif
+
+# if HAVE_DECL_FERROR_UNLOCKED
+#  undef ferror
+#  define ferror(x) ferror_unlocked (x)
+# else
+#  define ferror_unlocked(x) ferror (x)
+# endif
+
+# if HAVE_DECL_FFLUSH_UNLOCKED
+#  undef fflush
+#  define fflush(x) fflush_unlocked (x)
+# else
+#  define fflush_unlocked(x) fflush (x)
+# endif
+
+# if HAVE_DECL_FGETS_UNLOCKED
+#  undef fgets
+#  define fgets(x,y,z) fgets_unlocked (x,y,z)
+# else
+#  define fgets_unlocked(x,y,z) fgets (x,y,z)
+# endif
+
+# if HAVE_DECL_FPUTC_UNLOCKED
+#  undef fputc
+#  define fputc(x,y) fputc_unlocked (x,y)
+# else
+#  define fputc_unlocked(x,y) fputc (x,y)
+# endif
+
+# if HAVE_DECL_FPUTS_UNLOCKED
+#  undef fputs
+#  define fputs(x,y) fputs_unlocked (x,y)
+# else
+#  define fputs_unlocked(x,y) fputs (x,y)
+# endif
+
+# if HAVE_DECL_FREAD_UNLOCKED
+#  undef fread
+#  define fread(w,x,y,z) fread_unlocked (w,x,y,z)
+# else
+#  define fread_unlocked(w,x,y,z) fread (w,x,y,z)
+# endif
+
+# if HAVE_DECL_FWRITE_UNLOCKED
+#  undef fwrite
+#  define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z)
+# else
+#  define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
+# endif
+
+# if HAVE_DECL_GETC_UNLOCKED
+#  undef getc
+#  define getc(x) getc_unlocked (x)
+# else
+#  define getc_unlocked(x) getc (x)
+# endif
+
+# if HAVE_DECL_GETCHAR_UNLOCKED
+#  undef getchar
+#  define getchar() getchar_unlocked ()
+# else
+#  define getchar_unlocked() getchar ()
+# endif
+
+# if HAVE_DECL_PUTC_UNLOCKED
+#  undef putc
+#  define putc(x,y) putc_unlocked (x,y)
+# else
+#  define putc_unlocked(x,y) putc (x,y)
+# endif
+
+# if HAVE_DECL_PUTCHAR_UNLOCKED
+#  undef putchar
+#  define putchar(x) putchar_unlocked (x)
+# else
+#  define putchar_unlocked(x) putchar (x)
+# endif
+
+# undef flockfile
+# define flockfile(x) ((void) 0)
+
+# undef ftrylockfile
+# define ftrylockfile(x) 0
+
+# undef funlockfile
+# define funlockfile(x) ((void) 0)
+
+#endif /* UNLOCKED_IO_H */
diff --git a/lib/vbitset.c b/lib/vbitset.c
new file mode 100644
index 0000000..d0fe30f
--- /dev/null
+++ b/lib/vbitset.c
@@ -0,0 +1,1140 @@
+/* Variable array bitsets.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
+
+   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 2 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "vbitset.h"
+#include <stdlib.h>
+#include <string.h>
+
+/* This file implements variable size bitsets stored as a variable
+   length array of words.  Any unused bits in the last word must be
+   zero.
+
+   Note that binary or ternary operations assume that each bitset operand
+   has the same size.
+*/
+
+static void vbitset_unused_clear (bitset);
+
+static void vbitset_set (bitset, bitset_bindex);
+static void vbitset_reset (bitset, bitset_bindex);
+static bool vbitset_test (bitset, bitset_bindex);
+static bitset_bindex vbitset_list (bitset, bitset_bindex *,
+				   bitset_bindex, bitset_bindex *);
+static bitset_bindex vbitset_list_reverse (bitset, bitset_bindex *,
+					   bitset_bindex, bitset_bindex *);
+
+#define VBITSET_N_WORDS(N) (((N) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS)
+#define VBITSET_WORDS(X) ((X)->b.cdata)
+#define VBITSET_SIZE(X) ((X)->b.csize)
+#define VBITSET_ASIZE(X) ((X)->v.size)
+
+#undef min
+#undef max
+#define min(a, b) ((a) > (b) ? (b) : (a))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+static bitset_bindex
+vbitset_resize (bitset src, bitset_bindex n_bits)
+{
+  bitset_windex oldsize;
+  bitset_windex newsize;
+
+  if (n_bits == BITSET_NBITS_ (src))
+    return n_bits;
+
+  oldsize = VBITSET_SIZE (src);
+  newsize = VBITSET_N_WORDS (n_bits);
+
+  if (oldsize < newsize)
+    {
+      bitset_windex size;
+
+      /* The bitset needs to grow.  If we already have enough memory
+	 allocated, then just zero what we need.  */
+      if (newsize > VBITSET_ASIZE (src))
+	{
+	  /* We need to allocate more memory.  When oldsize is
+	     non-zero this means that we are changing the size, so
+	     grow the bitset 25% larger than requested to reduce
+	     number of reallocations.  */
+
+	  if (oldsize == 0)
+	    size = newsize;
+	  else
+	    size = newsize + newsize / 4;
+
+	  VBITSET_WORDS (src)
+	    = realloc (VBITSET_WORDS (src), size * sizeof (bitset_word));
+	  VBITSET_ASIZE (src) = size;
+	}
+
+      memset (VBITSET_WORDS (src) + oldsize, 0,
+	      (newsize - oldsize) * sizeof (bitset_word));
+      VBITSET_SIZE (src) = newsize;
+    }
+  else
+    {
+      /* The bitset needs to shrink.  There's no point deallocating
+	 the memory unless it is shrinking by a reasonable amount.  */
+      if ((oldsize - newsize) >= oldsize / 2)
+	{
+	  VBITSET_WORDS (src)
+	    = realloc (VBITSET_WORDS (src), newsize * sizeof (bitset_word));
+	  VBITSET_ASIZE (src) = newsize;
+	}
+
+      /* Need to prune any excess bits.  FIXME.  */
+
+      VBITSET_SIZE (src) = newsize;
+    }
+
+  BITSET_NBITS_ (src) = n_bits;
+  return n_bits;
+}
+
+
+/* Set bit BITNO in bitset DST.  */
+static void
+vbitset_set (dst, bitno)
+     bitset dst;
+     bitset_bindex bitno;
+{
+  bitset_windex windex = bitno / BITSET_WORD_BITS;
+
+  /* Perhaps we should abort.  The user should explicitly call
+     bitset_resize since this will not catch the case when we set a
+     bit larger than the current size but smaller than the allocated
+     size.  */
+  vbitset_resize (dst, bitno);
+
+  dst->b.cdata[windex - dst->b.cindex] |=
+    (bitset_word) 1 << (bitno % BITSET_WORD_BITS);
+}
+
+
+/* Reset bit BITNO in bitset DST.  */
+static void
+vbitset_reset (dst, bitno)
+     bitset dst ATTRIBUTE_UNUSED;
+     bitset_bindex bitno ATTRIBUTE_UNUSED;
+{
+  /* We must be accessing outside the cache so the bit is
+     zero anyway.  */
+}
+
+
+/* Test bit BITNO in bitset SRC.  */
+static bool
+vbitset_test (src, bitno)
+     bitset src ATTRIBUTE_UNUSED;
+     bitset_bindex bitno ATTRIBUTE_UNUSED;
+{
+  /* We must be accessing outside the cache so the bit is
+     zero anyway.  */
+  return 0;
+}
+
+
+/* Find list of up to NUM bits set in BSET in reverse order, starting
+   from and including NEXT and store in array LIST.  Return with
+   actual number of bits found and with *NEXT indicating where search
+   stopped.  */
+static bitset_bindex
+vbitset_list_reverse (src, list, num, next)
+     bitset src;
+     bitset_bindex *list;
+     bitset_bindex num;
+     bitset_bindex *next;
+{
+  bitset_bindex bitno;
+  bitset_bindex rbitno;
+  bitset_bindex count;
+  bitset_windex windex;
+  unsigned int bitcnt;
+  bitset_bindex bitoff;
+  bitset_word *srcp = VBITSET_WORDS (src);
+  bitset_bindex n_bits = BITSET_SIZE_ (src);
+
+  rbitno = *next;
+
+  /* If num is 1, we could speed things up with a binary search
+     of the word of interest.  */
+
+  if (rbitno >= n_bits)
+    return 0;
+
+  count = 0;
+
+  bitno = n_bits - (rbitno + 1);
+
+  windex = bitno / BITSET_WORD_BITS;
+  bitcnt = bitno % BITSET_WORD_BITS;
+  bitoff = windex * BITSET_WORD_BITS;
+
+  do
+    {
+      bitset_word word;
+
+      word = srcp[windex] << (BITSET_WORD_BITS - 1 - bitcnt);
+      for (; word; bitcnt--)
+	{
+	  if (word & BITSET_MSB)
+	    {
+	      list[count++] = bitoff + bitcnt;
+	      if (count >= num)
+		{
+		  *next = n_bits - (bitoff + bitcnt);
+		  return count;
+		}
+	    }
+	  word <<= 1;
+	}
+      bitoff -= BITSET_WORD_BITS;
+      bitcnt = BITSET_WORD_BITS - 1;
+    }
+  while (windex--);
+
+  *next = n_bits - (bitoff + 1);
+  return count;
+}
+
+
+/* Find list of up to NUM bits set in BSET starting from and including
+ *NEXT and store in array LIST.  Return with actual number of bits
+ found and with *NEXT indicating where search stopped.  */
+static bitset_bindex
+vbitset_list (src, list, num, next)
+     bitset src;
+     bitset_bindex *list;
+     bitset_bindex num;
+     bitset_bindex *next;
+{
+  bitset_bindex bitno;
+  bitset_bindex count;
+  bitset_windex windex;
+  bitset_bindex bitoff;
+  bitset_windex size = VBITSET_SIZE (src);
+  bitset_word *srcp = VBITSET_WORDS (src);
+  bitset_word word;
+
+  bitno = *next;
+
+  count = 0;
+  if (!bitno)
+    {
+      /* Many bitsets are zero, so make this common case fast.  */
+      for (windex = 0; windex < size && !srcp[windex]; windex++)
+	continue;
+      if (windex >= size)
+	return 0;
+
+      /* If num is 1, we could speed things up with a binary search
+	 of the current word.  */
+
+      bitoff = windex * BITSET_WORD_BITS;
+    }
+  else
+    {
+      if (bitno >= BITSET_SIZE_ (src))
+	return 0;
+
+      windex = bitno / BITSET_WORD_BITS;
+      bitno = bitno % BITSET_WORD_BITS;
+
+      if (bitno)
+	{
+	  /* Handle the case where we start within a word.
+	     Most often, this is executed with large bitsets
+	     with many set bits where we filled the array
+	     on the previous call to this function.  */
+
+	  bitoff = windex * BITSET_WORD_BITS;
+	  word = srcp[windex] >> bitno;
+	  for (bitno = bitoff + bitno; word; bitno++)
+	    {
+	      if (word & 1)
+		{
+		  list[count++] = bitno;
+		  if (count >= num)
+		    {
+		      *next = bitno + 1;
+		      return count;
+		    }
+		}
+	      word >>= 1;
+	    }
+	  windex++;
+	}
+      bitoff = windex * BITSET_WORD_BITS;
+    }
+
+  for (; windex < size; windex++, bitoff += BITSET_WORD_BITS)
+    {
+      if (!(word = srcp[windex]))
+	continue;
+
+      if ((count + BITSET_WORD_BITS) < num)
+	{
+	  for (bitno = bitoff; word; bitno++)
+	    {
+	      if (word & 1)
+		list[count++] = bitno;
+	      word >>= 1;
+	    }
+	}
+      else
+	{
+	  for (bitno = bitoff; word; bitno++)
+	    {
+	      if (word & 1)
+		{
+		  list[count++] = bitno;
+		  if (count >= num)
+		    {
+		      *next = bitno + 1;
+		      return count;
+		    }
+		}
+	      word >>= 1;
+	    }
+	}
+    }
+
+  *next = bitoff;
+  return count;
+}
+
+
+/* Ensure that any unused bits within the last word are clear.  */
+static inline void
+vbitset_unused_clear (dst)
+     bitset dst;
+{
+  unsigned int last_bit;
+
+  last_bit = BITSET_SIZE_ (dst) % BITSET_WORD_BITS;
+  if (last_bit)
+    VBITSET_WORDS (dst)[VBITSET_SIZE (dst) - 1] &=
+      ((bitset_word) 1 << last_bit) - 1;
+}
+
+
+static void
+vbitset_ones (bitset dst)
+{
+  bitset_word *dstp = VBITSET_WORDS (dst);
+  unsigned int bytes;
+
+  bytes = sizeof (bitset_word) * VBITSET_SIZE (dst);
+
+  memset (dstp, -1, bytes);
+  vbitset_unused_clear (dst);
+}
+
+
+static void
+vbitset_zero (bitset dst)
+{
+  bitset_word *dstp = VBITSET_WORDS (dst);
+  unsigned int bytes;
+
+  bytes = sizeof (bitset_word) * VBITSET_SIZE (dst);
+
+  memset (dstp, 0, bytes);
+}
+
+
+static bool
+vbitset_empty_p (bitset dst)
+{
+  unsigned int i;
+  bitset_word *dstp = VBITSET_WORDS (dst);
+
+  for (i = 0; i < VBITSET_SIZE (dst); i++)
+    if (dstp[i])
+      return 0;
+
+  return 1;
+}
+
+
+static void
+vbitset_copy1 (bitset dst, bitset src)
+{
+  bitset_word *srcp;
+  bitset_word *dstp;
+  bitset_windex ssize;
+  bitset_windex dsize;
+
+  if (src == dst)
+      return;
+
+  vbitset_resize (dst, BITSET_SIZE_ (src));
+
+  srcp = VBITSET_WORDS (src);
+  dstp = VBITSET_WORDS (dst);
+  ssize = VBITSET_SIZE (src);
+  dsize = VBITSET_SIZE (dst);
+
+  memcpy (dstp, srcp, sizeof (bitset_word) * ssize);
+
+  memset (dstp + sizeof (bitset_word) * ssize, 0,
+	  sizeof (bitset_word) * (dsize - ssize));
+}
+
+
+static void
+vbitset_not (bitset dst, bitset src)
+{
+  unsigned int i;
+  bitset_word *srcp;
+  bitset_word *dstp;
+  bitset_windex ssize;
+  bitset_windex dsize;
+
+  vbitset_resize (dst, BITSET_SIZE_ (src));
+
+  srcp = VBITSET_WORDS (src);
+  dstp = VBITSET_WORDS (dst);
+  ssize = VBITSET_SIZE (src);
+  dsize = VBITSET_SIZE (dst);
+
+  for (i = 0; i < ssize; i++)
+      *dstp++ = ~(*srcp++);
+
+  vbitset_unused_clear (dst);
+  memset (dstp + sizeof (bitset_word) * ssize, 0,
+	  sizeof (bitset_word) * (dsize - ssize));
+}
+
+
+static bool
+vbitset_equal_p (bitset dst, bitset src)
+{
+  unsigned int i;
+  bitset_word *srcp = VBITSET_WORDS (src);
+  bitset_word *dstp = VBITSET_WORDS (dst);
+  bitset_windex ssize = VBITSET_SIZE (src);
+  bitset_windex dsize = VBITSET_SIZE (dst);
+
+  for (i = 0; i < min (ssize, dsize); i++)
+      if (*srcp++ != *dstp++)
+	  return 0;
+
+  if (ssize > dsize)
+    {
+      for (; i < ssize; i++)
+	if (*srcp++)
+	  return 0;
+    }
+  else
+    {
+      for (; i < dsize; i++)
+	if (*dstp++)
+	  return 0;
+    }
+
+  return 1;
+}
+
+
+static bool
+vbitset_subset_p (bitset dst, bitset src)
+{
+  unsigned int i;
+  bitset_word *srcp = VBITSET_WORDS (src);
+  bitset_word *dstp = VBITSET_WORDS (dst);
+  bitset_windex ssize = VBITSET_SIZE (src);
+  bitset_windex dsize = VBITSET_SIZE (dst);
+
+  for (i = 0; i < min (ssize, dsize); i++, dstp++, srcp++)
+      if (*dstp != (*srcp | *dstp))
+	  return 0;
+
+  if (ssize > dsize)
+    {
+      for (; i < ssize; i++)
+	if (*srcp++)
+	  return 0;
+    }
+
+  return 1;
+}
+
+
+static bool
+vbitset_disjoint_p (bitset dst, bitset src)
+{
+  unsigned int i;
+  bitset_word *srcp = VBITSET_WORDS (src);
+  bitset_word *dstp = VBITSET_WORDS (dst);
+  bitset_windex ssize = VBITSET_SIZE (src);
+  bitset_windex dsize = VBITSET_SIZE (dst);
+
+  for (i = 0; i < min (ssize, dsize); i++)
+      if (*srcp++ & *dstp++)
+	  return 0;
+
+  return 1;
+}
+
+
+static void
+vbitset_and (bitset dst, bitset src1, bitset src2)
+{
+  unsigned int i;
+  bitset_word *src1p;
+  bitset_word *src2p;
+  bitset_word *dstp;
+  bitset_windex ssize1;
+  bitset_windex ssize2;
+  bitset_windex dsize;
+
+  vbitset_resize (dst, max (BITSET_SIZE_ (src1), BITSET_SIZE_ (src2)));
+
+  dsize = VBITSET_SIZE (dst);
+  ssize1 = VBITSET_SIZE (src1);
+  ssize2 = VBITSET_SIZE (src2);
+  dstp = VBITSET_WORDS (dst);
+  src1p = VBITSET_WORDS (src1);
+  src2p = VBITSET_WORDS (src2);
+
+  for (i = 0; i < min (ssize1, ssize2); i++)
+      *dstp++ = *src1p++ & *src2p++;
+
+  memset (dstp, 0, sizeof (bitset_word) * (dsize - min (ssize1, ssize2)));
+}
+
+
+static bool
+vbitset_and_cmp (bitset dst, bitset src1, bitset src2)
+{
+  unsigned int i;
+  int changed = 0;
+  bitset_word *src1p;
+  bitset_word *src2p;
+  bitset_word *dstp;
+  bitset_windex ssize1;
+  bitset_windex ssize2;
+  bitset_windex dsize;
+
+  vbitset_resize (dst, max (BITSET_SIZE_ (src1), BITSET_SIZE_ (src2)));
+
+  dsize = VBITSET_SIZE (dst);
+  ssize1 = VBITSET_SIZE (src1);
+  ssize2 = VBITSET_SIZE (src2);
+  dstp = VBITSET_WORDS (dst);
+  src1p = VBITSET_WORDS (src1);
+  src2p = VBITSET_WORDS (src2);
+
+  for (i = 0; i < min (ssize1, ssize2); i++, dstp++)
+    {
+      bitset_word tmp = *src1p++ & *src2p++;
+
+      if (*dstp != tmp)
+	{
+	  changed = 1;
+	  *dstp = tmp;
+	}
+    }
+
+  if (ssize2 > ssize1)
+    {
+      src1p = src2p;
+      ssize1 = ssize2;
+    }
+
+  for (; i < ssize1; i++, dstp++)
+    {
+      if (*dstp != 0)
+	{
+	  changed = 1;
+	  *dstp = 0;
+	}
+    }
+
+  memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
+
+  return changed;
+}
+
+
+static void
+vbitset_andn (bitset dst, bitset src1, bitset src2)
+{
+  unsigned int i;
+  bitset_word *src1p;
+  bitset_word *src2p;
+  bitset_word *dstp;
+  bitset_windex ssize1;
+  bitset_windex ssize2;
+  bitset_windex dsize;
+
+  vbitset_resize (dst, max (BITSET_SIZE_ (src1), BITSET_SIZE_ (src2)));
+
+  dsize = VBITSET_SIZE (dst);
+  ssize1 = VBITSET_SIZE (src1);
+  ssize2 = VBITSET_SIZE (src2);
+  dstp = VBITSET_WORDS (dst);
+  src1p = VBITSET_WORDS (src1);
+  src2p = VBITSET_WORDS (src2);
+
+  for (i = 0; i < min (ssize1, ssize2); i++)
+      *dstp++ = *src1p++ & ~(*src2p++);
+
+  if (ssize2 > ssize1)
+    {
+      for (; i < ssize2; i++)
+	*dstp++ = 0;
+
+      memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize2));
+    }
+  else
+    {
+      for (; i < ssize1; i++)
+	*dstp++ = *src1p++;
+
+      memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
+    }
+}
+
+
+static bool
+vbitset_andn_cmp (bitset dst, bitset src1, bitset src2)
+{
+  unsigned int i;
+  int changed = 0;
+  bitset_word *src1p;
+  bitset_word *src2p;
+  bitset_word *dstp;
+  bitset_windex ssize1;
+  bitset_windex ssize2;
+  bitset_windex dsize;
+
+  vbitset_resize (dst, max (BITSET_SIZE_ (src1), BITSET_SIZE_ (src2)));
+
+  dsize = VBITSET_SIZE (dst);
+  ssize1 = VBITSET_SIZE (src1);
+  ssize2 = VBITSET_SIZE (src2);
+  dstp = VBITSET_WORDS (dst);
+  src1p = VBITSET_WORDS (src1);
+  src2p = VBITSET_WORDS (src2);
+
+  for (i = 0; i < min (ssize1, ssize2); i++, dstp++)
+    {
+      bitset_word tmp = *src1p++ & ~(*src2p++);
+
+      if (*dstp != tmp)
+	{
+	  changed = 1;
+	  *dstp = tmp;
+	}
+    }
+
+  if (ssize2 > ssize1)
+    {
+      for (; i < ssize2; i++, dstp++)
+	{
+	  if (*dstp != 0)
+	    {
+	      changed = 1;
+	      *dstp = 0;
+	    }
+	}
+
+      memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize2));
+    }
+  else
+    {
+      for (; i < ssize1; i++, dstp++)
+	{
+	  bitset_word tmp = *src1p++;
+
+	  if (*dstp != tmp)
+	    {
+	      changed = 1;
+	      *dstp = tmp;
+	    }
+	}
+
+      memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
+    }
+
+  return changed;
+}
+
+
+static void
+vbitset_or (bitset dst, bitset src1, bitset src2)
+{
+  unsigned int i;
+  bitset_word *src1p;
+  bitset_word *src2p;
+  bitset_word *dstp;
+  bitset_windex ssize1;
+  bitset_windex ssize2;
+  bitset_windex dsize;
+
+  vbitset_resize (dst, max (BITSET_SIZE_ (src1), BITSET_SIZE_ (src2)));
+
+  dsize = VBITSET_SIZE (dst);
+  ssize1 = VBITSET_SIZE (src1);
+  ssize2 = VBITSET_SIZE (src2);
+  dstp = VBITSET_WORDS (dst);
+  src1p = VBITSET_WORDS (src1);
+  src2p = VBITSET_WORDS (src2);
+
+  for (i = 0; i < min (ssize1, ssize2); i++)
+      *dstp++ = *src1p++ | *src2p++;
+
+  if (ssize2 > ssize1)
+    {
+      src1p = src2p;
+      ssize1 = ssize2;
+    }
+
+  for (; i < ssize1; i++)
+    *dstp++ = *src1p++;
+
+  memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
+}
+
+
+static bool
+vbitset_or_cmp (bitset dst, bitset src1, bitset src2)
+{
+  unsigned int i;
+  int changed = 0;
+  bitset_word *src1p;
+  bitset_word *src2p;
+  bitset_word *dstp;
+  bitset_windex ssize1;
+  bitset_windex ssize2;
+  bitset_windex dsize;
+
+  vbitset_resize (dst, max (BITSET_SIZE_ (src1), BITSET_SIZE_ (src2)));
+
+  dsize = VBITSET_SIZE (dst);
+  ssize1 = VBITSET_SIZE (src1);
+  ssize2 = VBITSET_SIZE (src2);
+  dstp = VBITSET_WORDS (dst);
+  src1p = VBITSET_WORDS (src1);
+  src2p = VBITSET_WORDS (src2);
+
+  for (i = 0; i < min (ssize1, ssize2); i++, dstp++)
+    {
+      bitset_word tmp = *src1p++ | *src2p++;
+
+      if (*dstp != tmp)
+	{
+	  changed = 1;
+	  *dstp = tmp;
+	}
+    }
+
+  if (ssize2 > ssize1)
+    {
+      src1p = src2p;
+      ssize1 = ssize2;
+    }
+
+  for (; i < ssize1; i++, dstp++)
+    {
+      bitset_word tmp = *src1p++;
+
+      if (*dstp != tmp)
+	{
+	  changed = 1;
+	  *dstp = tmp;
+	}
+    }
+
+  memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
+
+  return changed;
+}
+
+
+static void
+vbitset_xor (bitset dst, bitset src1, bitset src2)
+{
+  unsigned int i;
+  bitset_word *src1p;
+  bitset_word *src2p;
+  bitset_word *dstp;
+  bitset_windex ssize1;
+  bitset_windex ssize2;
+  bitset_windex dsize;
+
+  vbitset_resize (dst, max (BITSET_SIZE_ (src1), BITSET_SIZE_ (src2)));
+
+  dsize = VBITSET_SIZE (dst);
+  ssize1 = VBITSET_SIZE (src1);
+  ssize2 = VBITSET_SIZE (src2);
+  dstp = VBITSET_WORDS (dst);
+  src1p = VBITSET_WORDS (src1);
+  src2p = VBITSET_WORDS (src2);
+
+  for (i = 0; i < min (ssize1, ssize2); i++)
+      *dstp++ = *src1p++ ^ *src2p++;
+
+  if (ssize2 > ssize1)
+    {
+      src1p = src2p;
+      ssize1 = ssize2;
+    }
+
+  for (; i < ssize1; i++)
+    *dstp++ = *src1p++;
+
+  memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
+}
+
+
+static bool
+vbitset_xor_cmp (bitset dst, bitset src1, bitset src2)
+{
+  unsigned int i;
+  int changed = 0;
+  bitset_word *src1p;
+  bitset_word *src2p;
+  bitset_word *dstp;
+  bitset_windex ssize1;
+  bitset_windex ssize2;
+  bitset_windex dsize;
+
+  vbitset_resize (dst, max (BITSET_SIZE_ (src1), BITSET_SIZE_ (src2)));
+
+  dsize = VBITSET_SIZE (dst);
+  ssize1 = VBITSET_SIZE (src1);
+  ssize2 = VBITSET_SIZE (src2);
+  dstp = VBITSET_WORDS (dst);
+  src1p = VBITSET_WORDS (src1);
+  src2p = VBITSET_WORDS (src2);
+
+  for (i = 0; i < min (ssize1, ssize2); i++, dstp++)
+    {
+      bitset_word tmp = *src1p++ ^ *src2p++;
+
+      if (*dstp != tmp)
+	{
+	  changed = 1;
+	  *dstp = tmp;
+	}
+    }
+
+  if (ssize2 > ssize1)
+    {
+      src1p = src2p;
+      ssize1 = ssize2;
+    }
+
+  for (; i < ssize1; i++, dstp++)
+    {
+      bitset_word tmp = *src1p++;
+
+      if (*dstp != tmp)
+	{
+	  changed = 1;
+	  *dstp = tmp;
+	}
+    }
+
+  memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
+
+  return changed;
+}
+
+
+/* FIXME, these operations need fixing for different size
+   bitsets.  */
+
+static void
+vbitset_and_or (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  unsigned int i;
+  bitset_word *src1p;
+  bitset_word *src2p;
+  bitset_word *src3p;
+  bitset_word *dstp;
+  bitset_windex size;
+
+  if (BITSET_NBITS_ (src1) != BITSET_NBITS_ (src2)
+      || BITSET_NBITS_ (src1) != BITSET_NBITS_ (src3))
+    {
+      bitset_and_or_ (dst, src1, src2, src3);
+      return;
+    }
+
+  vbitset_resize (dst, BITSET_NBITS_ (src1));
+
+  src1p = VBITSET_WORDS (src1);
+  src2p = VBITSET_WORDS (src2);
+  src3p = VBITSET_WORDS (src3);
+  dstp = VBITSET_WORDS (dst);
+  size = VBITSET_SIZE (dst);
+
+  for (i = 0; i < size; i++)
+      *dstp++ = (*src1p++ & *src2p++) | *src3p++;
+}
+
+
+static bool
+vbitset_and_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  unsigned int i;
+  int changed = 0;
+  bitset_word *src1p;
+  bitset_word *src2p;
+  bitset_word *src3p;
+  bitset_word *dstp;
+  bitset_windex size;
+
+  if (BITSET_NBITS_ (src1) != BITSET_NBITS_ (src2)
+      || BITSET_NBITS_ (src1) != BITSET_NBITS_ (src3))
+    return bitset_and_or_cmp_ (dst, src1, src2, src3);
+
+  vbitset_resize (dst, BITSET_NBITS_ (src1));
+
+  src1p = VBITSET_WORDS (src1);
+  src2p = VBITSET_WORDS (src2);
+  src3p = VBITSET_WORDS (src3);
+  dstp = VBITSET_WORDS (dst);
+  size = VBITSET_SIZE (dst);
+
+  for (i = 0; i < size; i++, dstp++)
+    {
+      bitset_word tmp = (*src1p++ & *src2p++) | *src3p++;
+
+      if (*dstp != tmp)
+	{
+	  changed = 1;
+	  *dstp = tmp;
+	}
+    }
+  return changed;
+}
+
+
+static void
+vbitset_andn_or (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  unsigned int i;
+  bitset_word *src1p;
+  bitset_word *src2p;
+  bitset_word *src3p;
+  bitset_word *dstp;
+  bitset_windex size;
+
+  if (BITSET_NBITS_ (src1) != BITSET_NBITS_ (src2)
+      || BITSET_NBITS_ (src1) != BITSET_NBITS_ (src3))
+    {
+      bitset_andn_or_ (dst, src1, src2, src3);
+      return;
+    }
+
+  vbitset_resize (dst, BITSET_NBITS_ (src1));
+
+  src1p = VBITSET_WORDS (src1);
+  src2p = VBITSET_WORDS (src2);
+  src3p = VBITSET_WORDS (src3);
+  dstp = VBITSET_WORDS (dst);
+  size = VBITSET_SIZE (dst);
+
+  for (i = 0; i < size; i++)
+      *dstp++ = (*src1p++ & ~(*src2p++)) | *src3p++;
+}
+
+
+static bool
+vbitset_andn_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  unsigned int i;
+  int changed = 0;
+  bitset_word *src1p;
+  bitset_word *src2p;
+  bitset_word *src3p;
+  bitset_word *dstp;
+  bitset_windex size;
+
+  if (BITSET_NBITS_ (src1) != BITSET_NBITS_ (src2)
+      || BITSET_NBITS_ (src1) != BITSET_NBITS_ (src3))
+    return bitset_andn_or_cmp_ (dst, src1, src2, src3);
+
+  vbitset_resize (dst, BITSET_NBITS_ (src1));
+
+  src1p = VBITSET_WORDS (src1);
+  src2p = VBITSET_WORDS (src2);
+  src3p = VBITSET_WORDS (src3);
+  dstp = VBITSET_WORDS (dst);
+  size = VBITSET_SIZE (dst);
+
+  for (i = 0; i < size; i++, dstp++)
+    {
+      bitset_word tmp = (*src1p++ & ~(*src2p++)) | *src3p++;
+
+      if (*dstp != tmp)
+	{
+	  changed = 1;
+	  *dstp = tmp;
+	}
+    }
+  return changed;
+}
+
+
+static void
+vbitset_or_and (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  unsigned int i;
+  bitset_word *src1p;
+  bitset_word *src2p;
+  bitset_word *src3p;
+  bitset_word *dstp;
+  bitset_windex size;
+
+  if (BITSET_NBITS_ (src1) != BITSET_NBITS_ (src2)
+      || BITSET_NBITS_ (src1) != BITSET_NBITS_ (src3))
+    {
+      bitset_or_and_ (dst, src1, src2, src3);
+      return;
+    }
+
+  vbitset_resize (dst, BITSET_NBITS_ (src1));
+
+  src1p = VBITSET_WORDS (src1);
+  src2p = VBITSET_WORDS (src2);
+  src3p = VBITSET_WORDS (src3);
+  dstp = VBITSET_WORDS (dst);
+  size = VBITSET_SIZE (dst);
+
+  for (i = 0; i < size; i++)
+      *dstp++ = (*src1p++ | *src2p++) & *src3p++;
+}
+
+
+static bool
+vbitset_or_and_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
+{
+  unsigned int i;
+  int changed = 0;
+  bitset_word *src1p;
+  bitset_word *src2p;
+  bitset_word *src3p;
+  bitset_word *dstp;
+  bitset_windex size;
+
+  if (BITSET_NBITS_ (src1) != BITSET_NBITS_ (src2)
+      || BITSET_NBITS_ (src1) != BITSET_NBITS_ (src3))
+    return bitset_or_and_cmp_ (dst, src1, src2, src3);
+
+  vbitset_resize (dst, BITSET_NBITS_ (src1));
+
+  src1p = VBITSET_WORDS (src1);
+  src2p = VBITSET_WORDS (src2);
+  src3p = VBITSET_WORDS (src3);
+  dstp = VBITSET_WORDS (dst);
+  size = VBITSET_SIZE (dst);
+
+  for (i = 0; i < size; i++, dstp++)
+    {
+      bitset_word tmp = (*src1p++ | *src2p++) & *src3p++;
+
+      if (*dstp != tmp)
+	{
+	  changed = 1;
+	  *dstp = tmp;
+	}
+    }
+  return changed;
+}
+
+
+static void
+vbitset_copy (bitset dst, bitset src)
+{
+  if (BITSET_COMPATIBLE_ (dst, src))
+      vbitset_copy1 (dst, src);
+  else
+      bitset_copy_ (dst, src);
+}
+
+
+/* Vector of operations for multiple word bitsets.  */
+struct bitset_vtable vbitset_vtable = {
+  vbitset_set,
+  vbitset_reset,
+  bitset_toggle_,
+  vbitset_test,
+  vbitset_resize,
+  bitset_size_,
+  bitset_count_,
+  vbitset_empty_p,
+  vbitset_ones,
+  vbitset_zero,
+  vbitset_copy,
+  vbitset_disjoint_p,
+  vbitset_equal_p,
+  vbitset_not,
+  vbitset_subset_p,
+  vbitset_and,
+  vbitset_and_cmp,
+  vbitset_andn,
+  vbitset_andn_cmp,
+  vbitset_or,
+  vbitset_or_cmp,
+  vbitset_xor,
+  vbitset_xor_cmp,
+  vbitset_and_or,
+  vbitset_and_or_cmp,
+  vbitset_andn_or,
+  vbitset_andn_or_cmp,
+  vbitset_or_and,
+  vbitset_or_and_cmp,
+  vbitset_list,
+  vbitset_list_reverse,
+  NULL,
+  BITSET_VARRAY
+};
+
+
+size_t
+vbitset_bytes (n_bits)
+     bitset_bindex n_bits ATTRIBUTE_UNUSED;
+{
+  return sizeof (struct vbitset_struct);
+}
+
+
+bitset
+vbitset_init (bset, n_bits)
+     bitset bset;
+     bitset_bindex n_bits;
+{
+  bset->b.vtable = &vbitset_vtable;
+
+  bset->b.cindex = 0;
+
+  VBITSET_SIZE (bset) = 0;
+  vbitset_resize (bset, n_bits);
+  return bset;
+}
diff --git a/lib/vbitset.h b/lib/vbitset.h
new file mode 100644
index 0000000..bab011c
--- /dev/null
+++ b/lib/vbitset.h
@@ -0,0 +1,28 @@
+/* Functions to support vbitsets.
+   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+   Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
+
+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 2 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, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _VBITSET_H
+#define _VBITSET_H
+
+#include "bitset.h"
+
+extern size_t vbitset_bytes (bitset_bindex);
+
+extern bitset vbitset_init (bitset, bitset_bindex);
+
+#endif
diff --git a/lib/verify.h b/lib/verify.h
new file mode 100644
index 0000000..d603b17
--- /dev/null
+++ b/lib/verify.h
@@ -0,0 +1,141 @@
+/* Compile-time assert-like macros.
+
+   Copyright (C) 2005, 2006 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Paul Eggert, Bruno Haible, and Jim Meyering.  */
+
+#ifndef VERIFY_H
+# define VERIFY_H 1
+
+/* Each of these macros verifies that its argument R is nonzero.  To
+   be portable, R should be an integer constant expression.  Unlike
+   assert (R), there is no run-time overhead.
+
+   There are two macros, since no single macro can be used in all
+   contexts in C.  verify_true (R) is for scalar contexts, including
+   integer constant expression contexts.  verify (R) is for declaration
+   contexts, e.g., the top level.
+
+   Symbols ending in "__" are private to this header.
+
+   The code below uses several ideas.
+
+   * The first step is ((R) ? 1 : -1).  Given an expression R, of
+     integral or boolean or floating-point type, this yields an
+     expression of integral type, whose value is later verified to be
+     constant and nonnegative.
+
+   * Next this expression W is wrapped in a type
+     struct verify_type__ { unsigned int verify_error_if_negative_size__: W; }.
+     If W is negative, this yields a compile-time error.  No compiler can
+     deal with a bit-field of negative size.
+
+     One might think that an array size check would have the same
+     effect, that is, that the type struct { unsigned int dummy[W]; }
+     would work as well.  However, inside a function, some compilers
+     (such as C++ compilers and GNU C) allow local parameters and
+     variables inside array size expressions.  With these compilers,
+     an array size check would not properly diagnose this misuse of
+     the verify macro:
+
+       void function (int n) { verify (n < 0); }
+
+   * For the verify macro, the struct verify_type__ will need to
+     somehow be embedded into a declaration.  To be portable, this
+     declaration must declare an object, a constant, a function, or a
+     typedef name.  If the declared entity uses the type directly,
+     such as in
+
+       struct dummy {...};
+       typedef struct {...} dummy;
+       extern struct {...} *dummy;
+       extern void dummy (struct {...} *);
+       extern struct {...} *dummy (void);
+
+     two uses of the verify macro would yield colliding declarations
+     if the entity names are not disambiguated.  A workaround is to
+     attach the current line number to the entity name:
+
+       #define GL_CONCAT0(x, y) x##y
+       #define GL_CONCAT(x, y) GL_CONCAT0 (x, y)
+       extern struct {...} * GL_CONCAT(dummy,__LINE__);
+
+     But this has the problem that two invocations of verify from
+     within the same macro would collide, since the __LINE__ value
+     would be the same for both invocations.
+
+     A solution is to use the sizeof operator.  It yields a number,
+     getting rid of the identity of the type.  Declarations like
+
+       extern int dummy [sizeof (struct {...})];
+       extern void dummy (int [sizeof (struct {...})]);
+       extern int (*dummy (void)) [sizeof (struct {...})];
+
+     can be repeated.
+
+   * Should the implementation use a named struct or an unnamed struct?
+     Which of the following alternatives can be used?
+
+       extern int dummy [sizeof (struct {...})];
+       extern int dummy [sizeof (struct verify_type__ {...})];
+       extern void dummy (int [sizeof (struct {...})]);
+       extern void dummy (int [sizeof (struct verify_type__ {...})]);
+       extern int (*dummy (void)) [sizeof (struct {...})];
+       extern int (*dummy (void)) [sizeof (struct verify_type__ {...})];
+
+     In the second and sixth case, the struct type is exported to the
+     outer scope; two such declarations therefore collide.  GCC warns
+     about the first, third, and fourth cases.  So the only remaining
+     possibility is the fifth case:
+
+       extern int (*dummy (void)) [sizeof (struct {...})];
+
+   * This implementation exploits the fact that GCC does not warn about
+     the last declaration mentioned above.  If a future version of GCC
+     introduces a warning for this, the problem could be worked around
+     by using code specialized to GCC, e.g.,:
+
+       #if 4 <= __GNUC__
+       # define verify(R) \
+	   extern int (* verify_function__ (void)) \
+		      [__builtin_constant_p (R) && (R) ? 1 : -1]
+       #endif
+
+   * In C++, any struct definition inside sizeof is invalid.
+     Use a template type to work around the problem.  */
+
+
+/* Verify requirement R at compile-time, as an integer constant expression.
+   Return 1.  */
+
+# ifdef __cplusplus
+template <int w>
+  struct verify_type__ { unsigned int verify_error_if_negative_size__: w; };
+#  define verify_true(R) \
+     (!!sizeof (verify_type__<(R) ? 1 : -1>))
+# else
+#  define verify_true(R) \
+     (!!sizeof \
+      (struct { unsigned int verify_error_if_negative_size__: (R) ? 1 : -1; }))
+# endif
+
+/* Verify requirement R at compile-time, as a declaration without a
+   trailing ';'.  */
+
+# define verify(R) extern int (* verify_function__ (void)) [verify_true (R)]
+
+#endif
diff --git a/lib/xalloc-die.c b/lib/xalloc-die.c
new file mode 100644
index 0000000..9b4a76c
--- /dev/null
+++ b/lib/xalloc-die.c
@@ -0,0 +1,44 @@
+/* Report a memory allocation failure and exit.
+
+   Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2006 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "xalloc.h"
+
+#include <stdlib.h>
+
+#include "error.h"
+#include "exitfail.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+void
+xalloc_die (void)
+{
+  error (exit_failure, 0, "%s", _("memory exhausted"));
+
+  /* The `noreturn' cannot be given to error, since it may return if
+     its first argument is 0.  To help compilers understand the
+     xalloc_die does not return, call abort.  Also, the abort is a
+     safety feature if exit_failure is 0 (which shouldn't happen).  */
+  abort ();
+}
diff --git a/lib/xalloc.h b/lib/xalloc.h
new file mode 100644
index 0000000..f80977e
--- /dev/null
+++ b/lib/xalloc.h
@@ -0,0 +1,79 @@
+/* xalloc.h -- malloc with out-of-memory checking
+
+   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2003, 2004 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef XALLOC_H_
+# define XALLOC_H_
+
+# include <stddef.h>
+
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+
+# ifndef __attribute__
+#  if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
+#   define __attribute__(x)
+#  endif
+# endif
+
+# ifndef ATTRIBUTE_NORETURN
+#  define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
+# endif
+
+/* This function is always triggered when memory is exhausted.
+   It must be defined by the application, either explicitly
+   or by using gnulib's xalloc-die module.  This is the
+   function to call when one wants the program to die because of a
+   memory allocation failure.  */
+extern void xalloc_die (void) ATTRIBUTE_NORETURN;
+
+void *xmalloc (size_t s);
+void *xnmalloc (size_t n, size_t s);
+void *xzalloc (size_t s);
+void *xcalloc (size_t n, size_t s);
+void *xrealloc (void *p, size_t s);
+void *xnrealloc (void *p, size_t n, size_t s);
+void *x2realloc (void *p, size_t *pn);
+void *x2nrealloc (void *p, size_t *pn, size_t s);
+void *xmemdup (void const *p, size_t s);
+char *xstrdup (char const *str);
+
+/* Return 1 if an array of N objects, each of size S, cannot exist due
+   to size arithmetic overflow.  S must be positive and N must be
+   nonnegative.  This is a macro, not an inline function, so that it
+   works correctly even when SIZE_MAX < N.
+
+   By gnulib convention, SIZE_MAX represents overflow in size
+   calculations, so the conservative dividend to use here is
+   SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
+   However, malloc (SIZE_MAX) fails on all known hosts where
+   sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
+   exactly-SIZE_MAX allocations on such hosts; this avoids a test and
+   branch when S is known to be 1.  */
+# define xalloc_oversized(n, s) \
+    ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
+
+# ifdef __cplusplus
+}
+# endif
+
+
+#endif /* !XALLOC_H_ */
diff --git a/lib/xmalloc.c b/lib/xmalloc.c
new file mode 100644
index 0000000..687633c
--- /dev/null
+++ b/lib/xmalloc.c
@@ -0,0 +1,241 @@
+/* xmalloc.c -- malloc with out of memory checking
+
+   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2002, 2003, 2004, 2005 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "xalloc.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+/* 1 if calloc is known to be compatible with GNU calloc.  This
+   matters if we are not also using the calloc module, which defines
+   HAVE_CALLOC and supports the GNU API even on non-GNU platforms.  */
+#if defined HAVE_CALLOC || defined __GLIBC__
+enum { HAVE_GNU_CALLOC = 1 };
+#else
+enum { HAVE_GNU_CALLOC = 0 };
+#endif
+
+/* Allocate an array of N objects, each with S bytes of memory,
+   dynamically, with error checking.  S must be nonzero.  */
+
+static inline void *
+xnmalloc_inline (size_t n, size_t s)
+{
+  void *p;
+  if (xalloc_oversized (n, s) || (! (p = malloc (n * s)) && n != 0))
+    xalloc_die ();
+  return p;
+}
+
+void *
+xnmalloc (size_t n, size_t s)
+{
+  return xnmalloc_inline (n, s);
+}
+
+/* Allocate N bytes of memory dynamically, with error checking.  */
+
+void *
+xmalloc (size_t n)
+{
+  return xnmalloc_inline (n, 1);
+}
+
+/* Change the size of an allocated block of memory P to an array of N
+   objects each of S bytes, with error checking.  S must be nonzero.  */
+
+static inline void *
+xnrealloc_inline (void *p, size_t n, size_t s)
+{
+  if (xalloc_oversized (n, s) || (! (p = realloc (p, n * s)) && n != 0))
+    xalloc_die ();
+  return p;
+}
+
+void *
+xnrealloc (void *p, size_t n, size_t s)
+{
+  return xnrealloc_inline (p, n, s);
+}
+
+/* Change the size of an allocated block of memory P to N bytes,
+   with error checking.  */
+
+void *
+xrealloc (void *p, size_t n)
+{
+  return xnrealloc_inline (p, n, 1);
+}
+
+
+/* If P is null, allocate a block of at least *PN such objects;
+   otherwise, reallocate P so that it contains more than *PN objects
+   each of S bytes.  *PN must be nonzero unless P is null, and S must
+   be nonzero.  Set *PN to the new number of objects, and return the
+   pointer to the new block.  *PN is never set to zero, and the
+   returned pointer is never null.
+
+   Repeated reallocations are guaranteed to make progress, either by
+   allocating an initial block with a nonzero size, or by allocating a
+   larger block.
+
+   In the following implementation, nonzero sizes are doubled so that
+   repeated reallocations have O(N log N) overall cost rather than
+   O(N**2) cost, but the specification for this function does not
+   guarantee that sizes are doubled.
+
+   Here is an example of use:
+
+     int *p = NULL;
+     size_t used = 0;
+     size_t allocated = 0;
+
+     void
+     append_int (int value)
+       {
+	 if (used == allocated)
+	   p = x2nrealloc (p, &allocated, sizeof *p);
+	 p[used++] = value;
+       }
+
+   This causes x2nrealloc to allocate a block of some nonzero size the
+   first time it is called.
+
+   To have finer-grained control over the initial size, set *PN to a
+   nonzero value before calling this function with P == NULL.  For
+   example:
+
+     int *p = NULL;
+     size_t used = 0;
+     size_t allocated = 0;
+     size_t allocated1 = 1000;
+
+     void
+     append_int (int value)
+       {
+	 if (used == allocated)
+	   {
+	     p = x2nrealloc (p, &allocated1, sizeof *p);
+	     allocated = allocated1;
+	   }
+	 p[used++] = value;
+       }
+
+   */
+
+static inline void *
+x2nrealloc_inline (void *p, size_t *pn, size_t s)
+{
+  size_t n = *pn;
+
+  if (! p)
+    {
+      if (! n)
+	{
+	  /* The approximate size to use for initial small allocation
+	     requests, when the invoking code specifies an old size of
+	     zero.  64 bytes is the largest "small" request for the
+	     GNU C library malloc.  */
+	  enum { DEFAULT_MXFAST = 64 };
+
+	  n = DEFAULT_MXFAST / s;
+	  n += !n;
+	}
+    }
+  else
+    {
+      if (SIZE_MAX / 2 / s < n)
+	xalloc_die ();
+      n *= 2;
+    }
+
+  *pn = n;
+  return xrealloc (p, n * s);
+}
+
+void *
+x2nrealloc (void *p, size_t *pn, size_t s)
+{
+  return x2nrealloc_inline (p, pn, s);
+}
+
+/* If P is null, allocate a block of at least *PN bytes; otherwise,
+   reallocate P so that it contains more than *PN bytes.  *PN must be
+   nonzero unless P is null.  Set *PN to the new block's size, and
+   return the pointer to the new block.  *PN is never set to zero, and
+   the returned pointer is never null.  */
+
+void *
+x2realloc (void *p, size_t *pn)
+{
+  return x2nrealloc_inline (p, pn, 1);
+}
+
+/* Allocate S bytes of zeroed memory dynamically, with error checking.
+   There's no need for xnzalloc (N, S), since it would be equivalent
+   to xcalloc (N, S).  */
+
+void *
+xzalloc (size_t s)
+{
+  return memset (xmalloc (s), 0, s);
+}
+
+/* Allocate zeroed memory for N elements of S bytes, with error
+   checking.  S must be nonzero.  */
+
+void *
+xcalloc (size_t n, size_t s)
+{
+  void *p;
+  /* Test for overflow, since some calloc implementations don't have
+     proper overflow checks.  But omit overflow and size-zero tests if
+     HAVE_GNU_CALLOC, since GNU calloc catches overflow and never
+     returns NULL if successful.  */
+  if ((! HAVE_GNU_CALLOC && xalloc_oversized (n, s))
+      || (! (p = calloc (n, s)) && (HAVE_GNU_CALLOC || n != 0)))
+    xalloc_die ();
+  return p;
+}
+
+/* Clone an object P of size S, with error checking.  There's no need
+   for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any
+   need for an arithmetic overflow check.  */
+
+void *
+xmemdup (void const *p, size_t s)
+{
+  return memcpy (xmalloc (s), p, s);
+}
+
+/* Clone STRING.  */
+
+char *
+xstrdup (char const *string)
+{
+  return xmemdup (string, strlen (string) + 1);
+}
diff --git a/lib/xstrndup.c b/lib/xstrndup.c
new file mode 100644
index 0000000..a62d4bd
--- /dev/null
+++ b/lib/xstrndup.c
@@ -0,0 +1,39 @@
+/* Duplicate a bounded initial segment of a string, with out-of-memory
+   checking.
+   Copyright (C) 2003 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification.  */
+#include "xstrndup.h"
+
+#include "strndup.h"
+#include "xalloc.h"
+
+/* Return a newly allocated copy of at most N bytes of STRING.
+   In other words, return a copy of the initial segment of length N of
+   STRING.  */
+char *
+xstrndup (const char *string, size_t n)
+{
+  char *s = strndup (string, n);
+  if (! s)
+    xalloc_die ();
+  return s;
+}
diff --git a/lib/xstrndup.h b/lib/xstrndup.h
new file mode 100644
index 0000000..88354cf
--- /dev/null
+++ b/lib/xstrndup.h
@@ -0,0 +1,24 @@
+/* Duplicate a bounded initial segment of a string, with out-of-memory
+   checking.
+   Copyright (C) 2003 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <stddef.h>
+
+/* Return a newly allocated copy of at most N bytes of STRING.
+   In other words, return a copy of the initial segment of length N of
+   STRING.  */
+extern char *xstrndup (const char *string, size_t n);
diff --git a/lib/yyerror.c b/lib/yyerror.c
new file mode 100644
index 0000000..b4ce4ba
--- /dev/null
+++ b/lib/yyerror.c
@@ -0,0 +1,30 @@
+/* Yacc library error-printing function.
+
+   Copyright (C) 2002 Free Software Foundation, Inc.
+
+   This file is part of Bison, the GNU Compiler Compiler.
+
+   Bison 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 2, or (at your option)
+   any later version.
+
+   Bison 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 Bison; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+#include <stdio.h>
+
+int yyerror (char const *);
+
+int
+yyerror (char const *message)
+{
+  return fprintf (stderr, "%s\n", message);
+}