summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am44
-rw-r--r--lib/Makefile.in717
-rw-r--r--lib/buildcmd.c515
-rw-r--r--lib/buildcmd.h131
-rw-r--r--lib/extendbuf.c105
-rw-r--r--lib/extendbuf.h27
-rw-r--r--lib/forcefindlib.c50
-rw-r--r--lib/gnulib-version.c2
-rw-r--r--lib/gnulib-version.h21
-rw-r--r--lib/gnulib-version.sh50
-rw-r--r--lib/listfile.c395
-rw-r--r--lib/listfile.h28
-rw-r--r--lib/modetype.h95
-rw-r--r--lib/nextelem.c110
-rw-r--r--lib/nextelem.h28
-rw-r--r--lib/printquoted.c87
-rw-r--r--lib/printquoted.h35
-rw-r--r--lib/qmark.c239
-rw-r--r--lib/regexprops.c505
-rw-r--r--lib/regextype.c158
-rw-r--r--lib/regextype.h28
-rw-r--r--lib/savedirinfo.c387
-rw-r--r--lib/savedirinfo.h73
-rw-r--r--lib/wait.h41
-rw-r--r--lib/waitpid.c81
25 files changed, 3952 insertions, 0 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644
index 0000000..3f6b1fe
--- /dev/null
+++ b/lib/Makefile.am
@@ -0,0 +1,44 @@
+## Process this file with automake to produce Makefile.in.
+
+AUTOMAKE_OPTIONS = 1.5 gnits
+# no-dependencies
+
+noinst_LIBRARIES = libfind.a
+
+if CROSS_COMPILING
+# The regexprops program needs to be a native executable, so we
+# can't build it with a cross-compiler.
+else
+noinst_PROGRAMS = regexprops
+regexprops_SOURCES = regexprops.c regextype.c
+endif
+
+libfind_a_SOURCES = gnulib-version.c
+EXTRA_DIST = modetype.h wait.h extendbuf.h savedirinfo.h buildcmd.h \
+ gnulib-version.h gnulib-version.sh gnulib-version.c
+BUILT_SOURCES = gnulib-version.c
+SUFFIXES =
+MOSTLYCLEANFILES =
+CLEANFILES =
+DISTCLEANFILES =
+MAINTAINERCLEANFILES =
+IMPORT_GNULIB_CONFIG = $(top_srcdir)/import-gnulib.config
+
+INCLUDES = -I../gnulib/lib -I$(top_srcdir)/gnulib/lib
+LDADD = ../gnulib/lib/libgnulib.a @INTLLIBS@
+
+libfind_a_SOURCES += modetype.h nextelem.h printquoted.h listfile.h regextype.h
+libfind_a_SOURCES += listfile.c nextelem.c extendbuf.c buildcmd.c savedirinfo.c forcefindlib.c qmark.c printquoted.c regextype.c
+
+EXTRA_DIST += waitpid.c forcefindlib.c
+
+
+libfind_a_LIBADD = @FINDLIBOBJS@
+libfind_a_DEPENDENCIES = @FINDLIBOBJS@
+# libfind_la_LIBADD = @LTFINDLIBOBJS@
+
+# libfind_a_OBJECTS += @FINDLIBOBJS@
+# libfind_la_OBJECTS += @LTFINDLIBOBJS@
+
+$(srcdir)/gnulib-version.c: $(srcdir)/gnulib-version.sh $(IMPORT_GNULIB_CONFIG)
+ sh $(srcdir)/gnulib-version.sh $(top_srcdir) $(srcdir) $(IMPORT_GNULIB_CONFIG) \ No newline at end of file
diff --git a/lib/Makefile.in b/lib/Makefile.in
new file mode 100644
index 0000000..5a1f252
--- /dev/null
+++ b/lib/Makefile.in
@@ -0,0 +1,717 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006 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@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+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@
+@CROSS_COMPILING_FALSE@noinst_PROGRAMS = regexprops$(EXEEXT)
+subdir = lib
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/gnulib/m4/absolute-header.m4 \
+ $(top_srcdir)/gnulib/m4/alloca.m4 \
+ $(top_srcdir)/gnulib/m4/argmatch.m4 \
+ $(top_srcdir)/gnulib/m4/canonicalize.m4 \
+ $(top_srcdir)/gnulib/m4/chdir-long.m4 \
+ $(top_srcdir)/gnulib/m4/chown.m4 \
+ $(top_srcdir)/gnulib/m4/close-stream.m4 \
+ $(top_srcdir)/gnulib/m4/closeout.m4 \
+ $(top_srcdir)/gnulib/m4/codeset.m4 \
+ $(top_srcdir)/gnulib/m4/cycle-check.m4 \
+ $(top_srcdir)/gnulib/m4/d-ino.m4 \
+ $(top_srcdir)/gnulib/m4/dirfd.m4 \
+ $(top_srcdir)/gnulib/m4/dirname.m4 \
+ $(top_srcdir)/gnulib/m4/dos.m4 \
+ $(top_srcdir)/gnulib/m4/double-slash-root.m4 \
+ $(top_srcdir)/gnulib/m4/error.m4 \
+ $(top_srcdir)/gnulib/m4/exitfail.m4 \
+ $(top_srcdir)/gnulib/m4/extensions.m4 \
+ $(top_srcdir)/gnulib/m4/fcntl-safer.m4 \
+ $(top_srcdir)/gnulib/m4/fcntl_h.m4 \
+ $(top_srcdir)/gnulib/m4/fileblocks.m4 \
+ $(top_srcdir)/gnulib/m4/filemode.m4 \
+ $(top_srcdir)/gnulib/m4/filenamecat.m4 \
+ $(top_srcdir)/gnulib/m4/flexmember.m4 \
+ $(top_srcdir)/gnulib/m4/fnmatch.m4 \
+ $(top_srcdir)/gnulib/m4/fpending.m4 \
+ $(top_srcdir)/gnulib/m4/fstypename.m4 \
+ $(top_srcdir)/gnulib/m4/getcwd-abort-bug.m4 \
+ $(top_srcdir)/gnulib/m4/getcwd-path-max.m4 \
+ $(top_srcdir)/gnulib/m4/getcwd.m4 \
+ $(top_srcdir)/gnulib/m4/getdelim.m4 \
+ $(top_srcdir)/gnulib/m4/getline.m4 \
+ $(top_srcdir)/gnulib/m4/getopt.m4 \
+ $(top_srcdir)/gnulib/m4/gettext.m4 \
+ $(top_srcdir)/gnulib/m4/glibc21.m4 \
+ $(top_srcdir)/gnulib/m4/gnulib-common.m4 \
+ $(top_srcdir)/gnulib/m4/gnulib-comp.m4 \
+ $(top_srcdir)/gnulib/m4/human.m4 \
+ $(top_srcdir)/gnulib/m4/iconv.m4 \
+ $(top_srcdir)/gnulib/m4/idcache.m4 \
+ $(top_srcdir)/gnulib/m4/inline.m4 \
+ $(top_srcdir)/gnulib/m4/inttypes-pri.m4 \
+ $(top_srcdir)/gnulib/m4/inttypes.m4 \
+ $(top_srcdir)/gnulib/m4/lchown.m4 \
+ $(top_srcdir)/gnulib/m4/lib-ld.m4 \
+ $(top_srcdir)/gnulib/m4/lib-link.m4 \
+ $(top_srcdir)/gnulib/m4/lib-prefix.m4 \
+ $(top_srcdir)/gnulib/m4/localcharset.m4 \
+ $(top_srcdir)/gnulib/m4/longlong.m4 \
+ $(top_srcdir)/gnulib/m4/ls-mntd-fs.m4 \
+ $(top_srcdir)/gnulib/m4/lstat.m4 \
+ $(top_srcdir)/gnulib/m4/mbrtowc.m4 \
+ $(top_srcdir)/gnulib/m4/mbstate_t.m4 \
+ $(top_srcdir)/gnulib/m4/memcmp.m4 \
+ $(top_srcdir)/gnulib/m4/mempcpy.m4 \
+ $(top_srcdir)/gnulib/m4/memrchr.m4 \
+ $(top_srcdir)/gnulib/m4/memset.m4 \
+ $(top_srcdir)/gnulib/m4/mktime.m4 \
+ $(top_srcdir)/gnulib/m4/modechange.m4 \
+ $(top_srcdir)/gnulib/m4/mountlist.m4 \
+ $(top_srcdir)/gnulib/m4/nls.m4 \
+ $(top_srcdir)/gnulib/m4/onceonly_2_57.m4 \
+ $(top_srcdir)/gnulib/m4/openat.m4 \
+ $(top_srcdir)/gnulib/m4/pathmax.m4 \
+ $(top_srcdir)/gnulib/m4/po.m4 \
+ $(top_srcdir)/gnulib/m4/progtest.m4 \
+ $(top_srcdir)/gnulib/m4/quote.m4 \
+ $(top_srcdir)/gnulib/m4/quotearg.m4 \
+ $(top_srcdir)/gnulib/m4/readlink.m4 \
+ $(top_srcdir)/gnulib/m4/regex.m4 \
+ $(top_srcdir)/gnulib/m4/rpmatch.m4 \
+ $(top_srcdir)/gnulib/m4/save-cwd.m4 \
+ $(top_srcdir)/gnulib/m4/savedir.m4 \
+ $(top_srcdir)/gnulib/m4/ssize_t.m4 \
+ $(top_srcdir)/gnulib/m4/st_dm_mode.m4 \
+ $(top_srcdir)/gnulib/m4/stdbool.m4 \
+ $(top_srcdir)/gnulib/m4/stdint.m4 \
+ $(top_srcdir)/gnulib/m4/stdio-safer.m4 \
+ $(top_srcdir)/gnulib/m4/stdlib_h.m4 \
+ $(top_srcdir)/gnulib/m4/stpcpy.m4 \
+ $(top_srcdir)/gnulib/m4/strdup.m4 \
+ $(top_srcdir)/gnulib/m4/strftime.m4 \
+ $(top_srcdir)/gnulib/m4/string_h.m4 \
+ $(top_srcdir)/gnulib/m4/strndup.m4 \
+ $(top_srcdir)/gnulib/m4/strnlen.m4 \
+ $(top_srcdir)/gnulib/m4/strtoimax.m4 \
+ $(top_srcdir)/gnulib/m4/strtol.m4 \
+ $(top_srcdir)/gnulib/m4/strtoll.m4 \
+ $(top_srcdir)/gnulib/m4/strtoul.m4 \
+ $(top_srcdir)/gnulib/m4/strtoull.m4 \
+ $(top_srcdir)/gnulib/m4/strtoumax.m4 \
+ $(top_srcdir)/gnulib/m4/sys_stat_h.m4 \
+ $(top_srcdir)/gnulib/m4/time_h.m4 \
+ $(top_srcdir)/gnulib/m4/time_r.m4 \
+ $(top_srcdir)/gnulib/m4/tm_gmtoff.m4 \
+ $(top_srcdir)/gnulib/m4/ulonglong.m4 \
+ $(top_srcdir)/gnulib/m4/unistd-safer.m4 \
+ $(top_srcdir)/gnulib/m4/unistd_h.m4 \
+ $(top_srcdir)/gnulib/m4/wchar.m4 \
+ $(top_srcdir)/gnulib/m4/wchar_t.m4 \
+ $(top_srcdir)/gnulib/m4/wctype.m4 \
+ $(top_srcdir)/gnulib/m4/wint_t.m4 \
+ $(top_srcdir)/gnulib/m4/xalloc.m4 \
+ $(top_srcdir)/gnulib/m4/xgetcwd.m4 \
+ $(top_srcdir)/gnulib/m4/xreadlink.m4 \
+ $(top_srcdir)/gnulib/m4/xstrndup.m4 \
+ $(top_srcdir)/gnulib/m4/xstrtol.m4 \
+ $(top_srcdir)/gnulib/m4/yesno.m4 $(top_srcdir)/m4/findlib.m4 \
+ $(top_srcdir)/m4/mkinstalldirs.m4 $(top_srcdir)/m4/nullsort.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+libfind_a_AR = $(AR) $(ARFLAGS)
+am_libfind_a_OBJECTS = gnulib-version.$(OBJEXT) listfile.$(OBJEXT) \
+ nextelem.$(OBJEXT) extendbuf.$(OBJEXT) buildcmd.$(OBJEXT) \
+ savedirinfo.$(OBJEXT) forcefindlib.$(OBJEXT) qmark.$(OBJEXT) \
+ printquoted.$(OBJEXT) regextype.$(OBJEXT)
+libfind_a_OBJECTS = $(am_libfind_a_OBJECTS)
+PROGRAMS = $(noinst_PROGRAMS)
+am__regexprops_SOURCES_DIST = regexprops.c regextype.c
+@CROSS_COMPILING_FALSE@am_regexprops_OBJECTS = regexprops.$(OBJEXT) \
+@CROSS_COMPILING_FALSE@ regextype.$(OBJEXT)
+regexprops_OBJECTS = $(am_regexprops_OBJECTS)
+regexprops_LDADD = $(LDADD)
+regexprops_DEPENDENCIES = ../gnulib/lib/libgnulib.a
+DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/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 = $(libfind_a_SOURCES) $(regexprops_SOURCES)
+DIST_SOURCES = $(libfind_a_SOURCES) $(am__regexprops_SOURCES_DIST)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ABSOLUTE_FCNTL_H = @ABSOLUTE_FCNTL_H@
+ABSOLUTE_INTTYPES_H = @ABSOLUTE_INTTYPES_H@
+ABSOLUTE_STDINT_H = @ABSOLUTE_STDINT_H@
+ABSOLUTE_STDLIB_H = @ABSOLUTE_STDLIB_H@
+ABSOLUTE_STRING_H = @ABSOLUTE_STRING_H@
+ABSOLUTE_SYS_STAT_H = @ABSOLUTE_SYS_STAT_H@
+ABSOLUTE_TIME_H = @ABSOLUTE_TIME_H@
+ABSOLUTE_UNISTD_H = @ABSOLUTE_UNISTD_H@
+ABSOLUTE_WCHAR_H = @ABSOLUTE_WCHAR_H@
+ABSOLUTE_WCTYPE_H = @ABSOLUTE_WCTYPE_H@
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+ALLOCA_H = @ALLOCA_H@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@
+BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@
+BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@
+BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@
+BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FCNTL_H = @FCNTL_H@
+FINDLIBOBJS = @FINDLIBOBJS@
+FNMATCH_H = @FNMATCH_H@
+GETOPT_H = @GETOPT_H@
+GLIBC21 = @GLIBC21@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNULIB_CHOWN = @GNULIB_CHOWN@
+GNULIB_DUP2 = @GNULIB_DUP2@
+GNULIB_FCHDIR = @GNULIB_FCHDIR@
+GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@
+GNULIB_GETCWD = @GNULIB_GETCWD@
+GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@
+GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@
+GNULIB_IMAXABS = @GNULIB_IMAXABS@
+GNULIB_IMAXDIV = @GNULIB_IMAXDIV@
+GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@
+GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@
+GNULIB_MBSCHR = @GNULIB_MBSCHR@
+GNULIB_MBSCSPN = @GNULIB_MBSCSPN@
+GNULIB_MBSLEN = @GNULIB_MBSLEN@
+GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@
+GNULIB_MBSPBRK = @GNULIB_MBSPBRK@
+GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@
+GNULIB_MBSRCHR = @GNULIB_MBSRCHR@
+GNULIB_MBSSEP = @GNULIB_MBSSEP@
+GNULIB_MBSSPN = @GNULIB_MBSSPN@
+GNULIB_MBSSTR = @GNULIB_MBSSTR@
+GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@
+GNULIB_MEMMEM = @GNULIB_MEMMEM@
+GNULIB_MEMPCPY = @GNULIB_MEMPCPY@
+GNULIB_MEMRCHR = @GNULIB_MEMRCHR@
+GNULIB_MKDTEMP = @GNULIB_MKDTEMP@
+GNULIB_MKSTEMP = @GNULIB_MKSTEMP@
+GNULIB_READLINK = @GNULIB_READLINK@
+GNULIB_STPCPY = @GNULIB_STPCPY@
+GNULIB_STPNCPY = @GNULIB_STPNCPY@
+GNULIB_STRCASESTR = @GNULIB_STRCASESTR@
+GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@
+GNULIB_STRDUP = @GNULIB_STRDUP@
+GNULIB_STRNDUP = @GNULIB_STRNDUP@
+GNULIB_STRNLEN = @GNULIB_STRNLEN@
+GNULIB_STRPBRK = @GNULIB_STRPBRK@
+GNULIB_STRSEP = @GNULIB_STRSEP@
+GNULIB_STRTOIMAX = @GNULIB_STRTOIMAX@
+GNULIB_STRTOK_R = @GNULIB_STRTOK_R@
+GNULIB_STRTOUMAX = @GNULIB_STRTOUMAX@
+GREP = @GREP@
+HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@
+HAVE_DECL_IMAXABS = @HAVE_DECL_IMAXABS@
+HAVE_DECL_IMAXDIV = @HAVE_DECL_IMAXDIV@
+HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@
+HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@
+HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@
+HAVE_DECL_STRNCASECMP = @HAVE_DECL_STRNCASECMP@
+HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@
+HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@
+HAVE_DECL_STRTOIMAX = @HAVE_DECL_STRTOIMAX@
+HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@
+HAVE_DECL_STRTOUMAX = @HAVE_DECL_STRTOUMAX@
+HAVE_DUP2 = @HAVE_DUP2@
+HAVE_FTRUNCATE = @HAVE_FTRUNCATE@
+HAVE_GETSUBOPT = @HAVE_GETSUBOPT@
+HAVE_INTTYPES_H = @HAVE_INTTYPES_H@
+HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@
+HAVE_MEMPCPY = @HAVE_MEMPCPY@
+HAVE_MKDTEMP = @HAVE_MKDTEMP@
+HAVE_READLINK = @HAVE_READLINK@
+HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@
+HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@
+HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@
+HAVE_STDINT_H = @HAVE_STDINT_H@
+HAVE_STPCPY = @HAVE_STPCPY@
+HAVE_STPNCPY = @HAVE_STPNCPY@
+HAVE_STRCASECMP = @HAVE_STRCASECMP@
+HAVE_STRCASESTR = @HAVE_STRCASESTR@
+HAVE_STRCHRNUL = @HAVE_STRCHRNUL@
+HAVE_STRNDUP = @HAVE_STRNDUP@
+HAVE_STRPBRK = @HAVE_STRPBRK@
+HAVE_STRSEP = @HAVE_STRSEP@
+HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@
+HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@
+HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@
+HAVE_UNISTD_H = @HAVE_UNISTD_H@
+HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@
+HAVE_WCTYPE_H = @HAVE_WCTYPE_H@
+HAVE_WINT_T = @HAVE_WINT_T@
+HAVE__BOOL = @HAVE__BOOL@
+INCLUDES = -I../gnulib/lib -I$(top_srcdir)/gnulib/lib
+INSTALL = @INSTALL@
+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@
+INTTYPES_H = @INTTYPES_H@
+LDFLAGS = @LDFLAGS@
+LIBGNULIB_LIBDEPS = @LIBGNULIB_LIBDEPS@
+LIBGNULIB_LTLIBDEPS = @LIBGNULIB_LTLIBDEPS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+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@
+PRIPTR_PREFIX = @PRIPTR_PREFIX@
+PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@
+PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@
+RANLIB = @RANLIB@
+REPLACE_CHOWN = @REPLACE_CHOWN@
+REPLACE_FCHDIR = @REPLACE_FCHDIR@
+REPLACE_GETCWD = @REPLACE_GETCWD@
+REPLACE_LOCALTIME_R = @REPLACE_LOCALTIME_R@
+REPLACE_MKSTEMP = @REPLACE_MKSTEMP@
+REPLACE_NANOSLEEP = @REPLACE_NANOSLEEP@
+REPLACE_STRPTIME = @REPLACE_STRPTIME@
+REPLACE_TIMEGM = @REPLACE_TIMEGM@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@
+SIZE_T_SUFFIX = @SIZE_T_SUFFIX@
+SORT = @SORT@
+SORT_SUPPORTS_Z = @SORT_SUPPORTS_Z@
+STDBOOL_H = @STDBOOL_H@
+STDINT_H = @STDINT_H@
+STRIP = @STRIP@
+SYS_STAT_H = @SYS_STAT_H@
+SYS_TIME_H_DEFINES_STRUCT_TIMESPEC = @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@
+TIME_H_DEFINES_STRUCT_TIMESPEC = @TIME_H_DEFINES_STRUCT_TIMESPEC@
+U = @U@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WCHAR_H = @WCHAR_H@
+WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@
+WCTYPE_H = @WCTYPE_H@
+WINT_T_SUFFIX = @WINT_T_SUFFIX@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+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@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gl_LIBOBJS = @gl_LIBOBJS@
+gl_LTLIBOBJS = @gl_LTLIBOBJS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = 1.5 gnits
+# no-dependencies
+noinst_LIBRARIES = libfind.a
+@CROSS_COMPILING_FALSE@regexprops_SOURCES = regexprops.c regextype.c
+libfind_a_SOURCES = gnulib-version.c modetype.h nextelem.h \
+ printquoted.h listfile.h regextype.h listfile.c nextelem.c \
+ extendbuf.c buildcmd.c savedirinfo.c forcefindlib.c qmark.c \
+ printquoted.c regextype.c
+EXTRA_DIST = modetype.h wait.h extendbuf.h savedirinfo.h buildcmd.h \
+ gnulib-version.h gnulib-version.sh gnulib-version.c waitpid.c \
+ forcefindlib.c
+BUILT_SOURCES = gnulib-version.c
+SUFFIXES =
+MOSTLYCLEANFILES =
+CLEANFILES =
+DISTCLEANFILES =
+MAINTAINERCLEANFILES =
+IMPORT_GNULIB_CONFIG = $(top_srcdir)/import-gnulib.config
+LDADD = ../gnulib/lib/libgnulib.a @INTLLIBS@
+libfind_a_LIBADD = @FINDLIBOBJS@
+libfind_a_DEPENDENCIES = @FINDLIBOBJS@
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(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) --gnits lib/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnits 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
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libfind.a: $(libfind_a_OBJECTS) $(libfind_a_DEPENDENCIES)
+ -rm -f libfind.a
+ $(libfind_a_AR) libfind.a $(libfind_a_OBJECTS) $(libfind_a_LIBADD)
+ $(RANLIB) libfind.a
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+regexprops$(EXEEXT): $(regexprops_OBJECTS) $(regexprops_DEPENDENCIES)
+ @rm -f regexprops$(EXEEXT)
+ $(LINK) $(regexprops_OBJECTS) $(regexprops_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buildcmd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extendbuf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/forcefindlib.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnulib-version.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/listfile.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nextelem.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/printquoted.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qmark.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regexprops.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regextype.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/savedirinfo.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@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@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@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) '$<'`
+
+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)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ 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) $(PROGRAMS)
+installdirs:
+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:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+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)
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(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-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(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:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-noinstLIBRARIES clean-noinstPROGRAMS 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-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am 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
+
+# libfind_la_LIBADD = @LTFINDLIBOBJS@
+
+# libfind_a_OBJECTS += @FINDLIBOBJS@
+# libfind_la_OBJECTS += @LTFINDLIBOBJS@
+
+$(srcdir)/gnulib-version.c: $(srcdir)/gnulib-version.sh $(IMPORT_GNULIB_CONFIG)
+ sh $(srcdir)/gnulib-version.sh $(top_srcdir) $(srcdir) $(IMPORT_GNULIB_CONFIG)
+# 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/buildcmd.c b/lib/buildcmd.c
new file mode 100644
index 0000000..efe1fbf
--- /dev/null
+++ b/lib/buildcmd.c
@@ -0,0 +1,515 @@
+/* buildcmd.c -- build command lines from a list of arguments.
+ Copyright (C) 1990, 91, 92, 93, 94, 2000, 2003, 2005, 2006, 2007 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 <config.h>
+
+# ifndef PARAMS
+# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
+# define PARAMS(Args) Args
+# else
+# define PARAMS(Args) ()
+# endif
+# endif
+
+#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
+#include <string.h>
+#endif
+
+
+#if DO_MULTIBYTE
+# if HAVE_MBRLEN
+# include <wchar.h>
+# else
+ /* Simulate mbrlen with mblen as best we can. */
+# define mbstate_t int
+# define mbrlen(s, n, ps) mblen (s, n)
+# endif
+#endif
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+#if ENABLE_NLS
+# include <libintl.h>
+# define _(Text) gettext (Text)
+#else
+# define _(Text) Text
+#define textdomain(Domain)
+#define bindtextdomain(Package, Directory)
+#endif
+#ifdef gettext_noop
+# define N_(String) gettext_noop (String)
+#else
+/* See locate.c for explanation as to why not use (String) */
+# define N_(String) String
+#endif
+
+#ifndef _POSIX_SOURCE
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+/* The presence of unistd.h is assumed by gnulib these days, so we
+ * might as well assume it too.
+ */
+/* for sysconf() */
+#include <unistd.h>
+
+#include <assert.h>
+
+/* COMPAT: SYSV version defaults size (and has a max value of) to 470.
+ We try to make it as large as possible. */
+#if !defined(ARG_MAX) && defined(_SC_ARG_MAX)
+#define ARG_MAX sysconf (_SC_ARG_MAX)
+#endif
+#ifndef ARG_MAX
+#define ARG_MAX NCARGS
+#endif
+
+
+
+#include <xalloc.h>
+#include <error.h>
+
+#include "buildcmd.h"
+
+
+extern char **environ;
+
+
+static char *mbstrstr PARAMS ((const char *haystack, const char *needle));
+
+/* Replace all instances of `replace_pat' in ARG with `linebuf',
+ and add the resulting string to the list of arguments for the command
+ to execute.
+ ARGLEN is the length of ARG, not including the null.
+ LBLEN is the length of LINEBUF, not including the null.
+ PFXLEN is the length of PREFIX. Substitution is not performed on
+ the prefix. The prefix is used if the argument contains replace_pat.
+
+ COMPAT: insertions on the SYSV version are limited to 255 chars per line,
+ and a max of 5 occurrences of replace_pat in the initial-arguments.
+ Those restrictions do not exist here. */
+
+void
+bc_do_insert (const struct buildcmd_control *ctl,
+ struct buildcmd_state *state,
+ char *arg, size_t arglen,
+ const char *prefix, size_t pfxlen,
+ const char *linebuf, size_t lblen,
+ int initial_args)
+{
+ /* Temporary copy of each arg with the replace pattern replaced by the
+ real arg. */
+ static char *insertbuf;
+ char *p;
+ size_t bytes_left = ctl->arg_max - 1; /* Bytes left on the command line. */
+ int need_prefix;
+
+ /* XXX: on systems lacking an upper limit for exec args, ctl->arg_max
+ * may have been set to LONG_MAX (see bc_get_arg_max()). Hence
+ * this xmalloc call may be a bad idea, especially since we are
+ * adding 1 to it...
+ */
+ if (!insertbuf)
+ insertbuf = (char *) xmalloc (ctl->arg_max + 1);
+ p = insertbuf;
+
+ do
+ {
+ size_t len; /* Length in ARG before `replace_pat'. */
+ char *s = mbstrstr (arg, ctl->replace_pat);
+ if (s)
+ {
+ len = s - arg;
+ }
+ else
+ {
+ len = arglen;
+ }
+
+ if (bytes_left <= len)
+ break;
+ else
+ bytes_left -= len;
+
+ strncpy (p, arg, len);
+ p += len;
+ arg += len;
+ arglen -= len;
+
+ if (s)
+ {
+ if (bytes_left <= (lblen + pfxlen))
+ break;
+ else
+ bytes_left -= (lblen + pfxlen);
+
+ if (prefix)
+ {
+ strcpy (p, prefix);
+ p += pfxlen;
+ }
+ strcpy (p, linebuf);
+ p += lblen;
+
+ arg += ctl->rplen;
+ arglen -= ctl->rplen;
+ }
+ }
+ while (*arg);
+ if (*arg)
+ error (1, 0, _("command too long"));
+ *p++ = '\0';
+
+ bc_push_arg (ctl, state,
+ insertbuf, p - insertbuf,
+ NULL, 0,
+ initial_args);
+}
+
+static
+void do_exec(const struct buildcmd_control *ctl,
+ struct buildcmd_state *state)
+{
+ (ctl->exec_callback)(ctl, state);
+}
+
+
+/* Return nonzero if there would not be enough room for an additional
+ * argument. We check the total number of arguments only, not the space
+ * occupied by those arguments.
+ *
+ * If we return zero, there still may not be enough room for the next
+ * argument, depending on its length.
+ */
+static int
+bc_argc_limit_reached(int initial_args,
+ const struct buildcmd_control *ctl,
+ struct buildcmd_state *state)
+{
+ /* Check to see if we about to exceed a limit set by xargs' -n option */
+ if (!initial_args && ctl->args_per_exec &&
+ ( (state->cmd_argc - ctl->initial_argc) == ctl->args_per_exec))
+ return 1;
+
+ /* We deliberately use an equality test here rather than >= in order
+ * to force a software failure if the code is modified in such a way
+ * that it fails to call this function for every new argument.
+ */
+ return state->cmd_argc == ctl->max_arg_count;
+}
+
+
+/* Add ARG to the end of the list of arguments `cmd_argv' to pass
+ to the command.
+ LEN is the length of ARG, including the terminating null.
+ If this brings the list up to its maximum size, execute the command. */
+
+void
+bc_push_arg (const struct buildcmd_control *ctl,
+ struct buildcmd_state *state,
+ const char *arg, size_t len,
+ const char *prefix, size_t pfxlen,
+ int initial_args)
+{
+ if (!initial_args)
+ state->todo = 1;
+
+ if (arg)
+ {
+ if (state->cmd_argv_chars + len > ctl->arg_max)
+ {
+ if (initial_args || state->cmd_argc == ctl->initial_argc)
+ error (1, 0, _("can not fit single argument within argument list size limit"));
+ /* option -i (replace_pat) implies -x (exit_if_size_exceeded) */
+ if (ctl->replace_pat
+ || (ctl->exit_if_size_exceeded &&
+ (ctl->lines_per_exec || ctl->args_per_exec)))
+ error (1, 0, _("argument list too long"));
+ do_exec (ctl, state);
+ }
+
+ if (bc_argc_limit_reached(initial_args, ctl, state))
+ do_exec (ctl, state);
+ }
+
+ if (state->cmd_argc >= state->cmd_argv_alloc)
+ {
+ if (!state->cmd_argv)
+ {
+ state->cmd_argv_alloc = 64;
+ state->cmd_argv = (char **) xmalloc (sizeof (char *) * state->cmd_argv_alloc);
+ }
+ else
+ {
+ state->cmd_argv_alloc *= 2;
+ state->cmd_argv = (char **) xrealloc (state->cmd_argv,
+ sizeof (char *) * state->cmd_argv_alloc);
+ }
+ }
+
+ if (!arg)
+ state->cmd_argv[state->cmd_argc++] = NULL;
+ else
+ {
+ state->cmd_argv[state->cmd_argc++] = state->argbuf + state->cmd_argv_chars;
+ if (prefix)
+ {
+ strcpy (state->argbuf + state->cmd_argv_chars, prefix);
+ state->cmd_argv_chars += pfxlen;
+ }
+
+ strcpy (state->argbuf + state->cmd_argv_chars, arg);
+ state->cmd_argv_chars += len;
+
+ /* If we have now collected enough arguments,
+ * do the exec immediately. This must be
+ * conditional on arg!=NULL, since do_exec()
+ * actually calls bc_push_arg(ctl, state, NULL, 0, false).
+ */
+ if (bc_argc_limit_reached(initial_args, ctl, state))
+ do_exec (ctl, state);
+ }
+
+ /* If this is an initial argument, set the high-water mark. */
+ if (initial_args)
+ {
+ state->cmd_initial_argv_chars = state->cmd_argv_chars;
+ }
+}
+
+
+/* Finds the first occurrence of the substring NEEDLE in the string
+ HAYSTACK. Both strings can be multibyte strings. */
+
+static char *
+mbstrstr (const char *haystack, const char *needle)
+{
+#if DO_MULTIBYTE
+ if (MB_CUR_MAX > 1)
+ {
+ size_t hlen = strlen (haystack);
+ size_t nlen = strlen (needle);
+ mbstate_t mbstate;
+ size_t step;
+
+ memset (&mbstate, 0, sizeof (mbstate_t));
+ while (hlen >= nlen)
+ {
+ if (memcmp (haystack, needle, nlen) == 0)
+ return (char *) haystack;
+ step = mbrlen (haystack, hlen, &mbstate);
+ if (step <= 0)
+ break;
+ haystack += step;
+ hlen -= step;
+ }
+ return NULL;
+ }
+#endif
+ return strstr (haystack, needle);
+}
+
+static size_t
+get_line_max(void)
+{
+ long val;
+#ifdef _SC_LINE_MAX
+ val = sysconf(_SC_LINE_MAX);
+#else
+ val = -1;
+#endif
+
+ if (val > 0)
+ return val;
+
+ /* either _SC_LINE_MAX was not available or
+ * there is no particular limit.
+ */
+#ifdef LINE_MAX
+ val = LINE_MAX;
+#endif
+
+ if (val > 0)
+ return val;
+
+ return 2048L; /* a reasonable guess. */
+}
+
+
+size_t
+bc_get_arg_max(void)
+{
+ long val;
+
+ /* We may resort to using LONG_MAX, so check it fits. */
+ /* XXX: better to do a compile-time check */
+ assert( (~(size_t)0) >= LONG_MAX);
+
+#ifdef _SC_ARG_MAX
+ val = sysconf(_SC_ARG_MAX);
+#else
+ val = -1;
+#endif
+
+ if (val > 0)
+ return val;
+
+ /* either _SC_ARG_MAX was not available or
+ * there is no particular limit.
+ */
+#ifdef ARG_MAX
+ val = ARG_MAX;
+#endif
+
+ if (val > 0)
+ return val;
+
+ /* The value returned by this function bounds the
+ * value applied as the ceiling for the -s option.
+ * Hence it the system won't tell us what its limit
+ * is, we allow the user to specify more or less
+ * whatever value they like.
+ */
+ return LONG_MAX;
+}
+
+
+static int cb_exec_noop(const struct buildcmd_control *ctl,
+ struct buildcmd_state *state)
+{
+ /* does nothing. */
+ (void) ctl;
+ (void) state;
+
+ return 0;
+}
+
+
+/* Return how much of ARG_MAX is used by the environment. */
+size_t
+bc_size_of_environment (void)
+{
+ size_t len = 0u;
+ char **envp = environ;
+
+ while (*envp)
+ len += strlen (*envp++) + 1;
+
+ return len;
+}
+
+
+enum BC_INIT_STATUS
+bc_init_controlinfo(struct buildcmd_control *ctl)
+{
+ size_t size_of_environment = bc_size_of_environment();
+ size_t arg_max;
+
+ ctl->posix_arg_size_min = get_line_max();
+ arg_max = bc_get_arg_max();
+
+ /* POSIX.2 requires subtracting 2048. */
+ assert(arg_max > 2048u); /* XXX: this is an external condition, should not check it with assert. */
+ ctl->posix_arg_size_max = (arg_max - 2048);
+
+ ctl->exit_if_size_exceeded = 0;
+
+ /* Take the size of the environment into account. */
+ if (size_of_environment > ctl->posix_arg_size_max)
+ {
+ return BC_INIT_ENV_TOO_BIG;
+ }
+ else
+ {
+ ctl->posix_arg_size_max - size_of_environment;
+ }
+
+ /* need to subtract 2 on the following line - for Linux/PPC */
+ ctl->max_arg_count = (ctl->posix_arg_size_max / sizeof(char*)) - 2u;
+ assert(ctl->max_arg_count > 0);
+ ctl->rplen = 0u;
+ ctl->replace_pat = NULL;
+ ctl->initial_argc = 0;
+ ctl->exec_callback = cb_exec_noop;
+ ctl->lines_per_exec = 0;
+ ctl->args_per_exec = 0;
+
+ /* Set the initial value of arg_max to the largest value we can
+ * tolerate.
+ */
+ ctl->arg_max = ctl->posix_arg_size_max;
+
+ return BC_INIT_OK;
+}
+
+void
+bc_use_sensible_arg_max(struct buildcmd_control *ctl)
+{
+ size_t env_size = bc_size_of_environment();
+ const size_t arg_size = (128u * 1024u) + env_size;
+
+ /* Check against the upper and lower limits. */
+ if (arg_size > ctl->posix_arg_size_max)
+ ctl->arg_max = ctl->posix_arg_size_max - env_size;
+ else if (arg_size < ctl->posix_arg_size_min)
+ ctl->arg_max = ctl->posix_arg_size_min;
+ else
+ ctl->arg_max = arg_size;
+}
+
+
+
+
+void
+bc_init_state(const struct buildcmd_control *ctl,
+ struct buildcmd_state *state,
+ void *context)
+{
+ state->cmd_argc = 0;
+ state->cmd_argv_chars = 0;
+ state->cmd_argv = NULL;
+ state->cmd_argv_alloc = 0;
+
+ /* XXX: the following memory allocation is inadvisable on systems
+ * with no ARG_MAX, because ctl->arg_max may actually be close to
+ * LONG_MAX. Adding one to it is safe though because earlier we
+ * subtracted 2048.
+ */
+ assert(ctl->arg_max <= (LONG_MAX - 2048L));
+ state->argbuf = (char *) xmalloc (ctl->arg_max + 1u);
+
+ state->cmd_argv_chars = state->cmd_initial_argv_chars = 0;
+ state->todo = 0;
+ state->usercontext = context;
+}
+
+void
+bc_clear_args(const struct buildcmd_control *ctl,
+ struct buildcmd_state *state)
+{
+ state->cmd_argc = ctl->initial_argc;
+ state->cmd_argv_chars = state->cmd_initial_argv_chars;
+ state->todo = 0;
+}
+
diff --git a/lib/buildcmd.h b/lib/buildcmd.h
new file mode 100644
index 0000000..b8fa896
--- /dev/null
+++ b/lib/buildcmd.h
@@ -0,0 +1,131 @@
+/* buildcmd.h -- build command lines from a stream of arguments
+ 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 James Youngman.
+ */
+#ifndef INC_BUILDCMD_H
+#define INC_BUILDCMD_H 1
+
+struct buildcmd_state
+{
+ /* Number of valid elements in `cmd_argv'. */
+ int cmd_argc; /* 0 */
+
+ /* The list of args being built. */
+ char **cmd_argv; /* NULL */
+
+ /* Number of elements allocated for `cmd_argv'. */
+ int cmd_argv_alloc;
+
+ /* Storage for elements of `cmd_argv'. */
+ char *argbuf;
+
+ /* Number of chars being used in `cmd_argv'. */
+ size_t cmd_argv_chars;
+
+ /* Number of chars being used in `cmd_argv' for the initial args.. */
+ size_t cmd_initial_argv_chars;
+
+ /* User context information. */
+ void *usercontext;
+
+ /* to-do flag. */
+ int todo;
+};
+
+struct buildcmd_control
+{
+ /* If true, exit if lines_per_exec or args_per_exec is exceeded. */
+ int exit_if_size_exceeded; /* false */
+
+ /* POSIX limits on the argument length. */
+ size_t posix_arg_size_max;
+ size_t posix_arg_size_min;
+
+ /* The maximum number of characters that can be used per command line. */
+ size_t arg_max;
+
+ /* max_arg_count: the maximum number of arguments that can be used.
+ *
+ * Many systems include the size of the pointers in ARG_MAX.
+ * Linux on PPC fails if we just subtract 1 here.
+ *
+ * However, not all systems define ARG_MAX. Our bc_get_arg_max()
+ * function returns a useful value even if ARG_MAX is not defined.
+ * However, sometimes, max_arg_count is LONG_MAX!
+ */
+ long max_arg_count;
+
+
+ /* The length of `replace_pat'. */
+ size_t rplen;
+
+ /* If nonzero, then instead of putting the args from stdin at
+ the end of the command argument list, they are each stuck into the
+ initial args, replacing each occurrence of the `replace_pat' in the
+ initial args. */
+ char *replace_pat;
+
+ /* Number of initial arguments given on the command line. */
+ int initial_argc; /* 0 */
+
+ /* exec callback. */
+ int (*exec_callback)(const struct buildcmd_control *, struct buildcmd_state *);
+
+ /* If nonzero, the maximum number of nonblank lines from stdin to use
+ per command line. */
+ long lines_per_exec; /* 0 */
+
+ /* The maximum number of arguments to use per command line. */
+ long args_per_exec;
+};
+
+enum BC_INIT_STATUS
+ {
+ BC_INIT_OK = 0,
+ BC_INIT_ENV_TOO_BIG
+ };
+
+extern size_t bc_size_of_environment (void);
+
+
+extern void bc_do_insert (const struct buildcmd_control *ctl,
+ struct buildcmd_state *state,
+ char *arg, size_t arglen,
+ const char *prefix, size_t pfxlen,
+ const char *linebuf, size_t lblen,
+ int initial_args);
+
+extern void bc_push_arg (const struct buildcmd_control *ctl,
+ struct buildcmd_state *state,
+ const char *arg, size_t len,
+ const char *prefix, size_t pfxlen,
+ int initial_args);
+
+extern void bc_init_state(const struct buildcmd_control *ctl,
+ struct buildcmd_state *state,
+ void *usercontext);
+extern enum BC_INIT_STATUS bc_init_controlinfo(struct buildcmd_control *ctl);
+extern size_t bc_get_arg_max(void);
+extern void bc_use_sensible_arg_max(struct buildcmd_control *ctl);
+extern void bc_clear_args(const struct buildcmd_control *ctl,
+ struct buildcmd_state *state);
+
+
+#endif
diff --git a/lib/extendbuf.c b/lib/extendbuf.c
new file mode 100644
index 0000000..b1a322f
--- /dev/null
+++ b/lib/extendbuf.c
@@ -0,0 +1,105 @@
+/* extendbuf.c -- manage a dynamically-allocated buffer
+
+ Copyright 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 James Yougnman <jay@gnu.org>. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "xalloc.h"
+#include "extendbuf.h"
+
+
+/* We initially use a small default size to ensure that this code
+ * gets exercised.
+ */
+#ifndef SIZE_DEFAULT
+# define SIZE_DEFAULT 16
+#endif
+
+static size_t
+decide_size(size_t current, size_t wanted)
+{
+ size_t newsize;
+
+ if (0 == current)
+ newsize = SIZE_DEFAULT;
+ else
+ newsize = current;
+
+ while (newsize < wanted)
+ {
+ if (2 * newsize < newsize)
+ xalloc_die ();
+ newsize *= 2;
+ }
+ return newsize;
+}
+
+
+void *
+extendbuf(void* existing, size_t wanted, size_t *allocated)
+{
+ int saved_errno;
+ size_t newsize;
+ void *result; /* leave uninitialised to allow static code checkers to identify bugs */
+
+ saved_errno = errno;
+
+ assert(wanted > 0u);
+ newsize = decide_size(*allocated, wanted);
+
+ if ( (*allocated) == 0 )
+ {
+ /* Sanity check: If there is no existing allocation size, there
+ * must be no existing allocated buffer.
+ */
+ assert(NULL == existing);
+
+ (*allocated) = newsize;
+ result = xmalloc(newsize);
+ }
+ else
+ {
+ if (newsize != (*allocated) )
+ {
+ (*allocated) = newsize;
+ result = xrealloc (existing, newsize);
+
+ }
+ else
+ {
+ result = existing;
+ }
+ }
+
+ if (result)
+ {
+ /* xmalloc() or xrealloc() may have changed errno, but in the
+ success case we want to preserve the previous value.
+ */
+ errno = saved_errno;
+ }
+ return result;
+}
diff --git a/lib/extendbuf.h b/lib/extendbuf.h
new file mode 100644
index 0000000..987152e
--- /dev/null
+++ b/lib/extendbuf.h
@@ -0,0 +1,27 @@
+/* extendbuf.h -- Manage a dynamically-alloicated buffer
+
+ 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 INC_EXTENDBUF_H
+#define INC_EXTENDBUF_H 1
+
+void *extendbuf(void* existing, size_t wanted, size_t *allocated);
+
+
+#endif
diff --git a/lib/forcefindlib.c b/lib/forcefindlib.c
new file mode 100644
index 0000000..6ee12c1
--- /dev/null
+++ b/lib/forcefindlib.c
@@ -0,0 +1,50 @@
+/* Ensures that the FINDLIB_REPLACE_FUNCS macro in configure.in works
+ Copyright (C) 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 James Youngman. */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+extern void forcefindlib(void); /* prevent GCC warning... */
+
+
+
+/* forcefindlib
+ *
+ * This function exists only to be pulled into libfind.a by the
+ * FINDLIB_REPLACE_FUNCS macro in configure.in. We already have
+ * AC_REPLACE_FUNCS, but that adds to LIBOBJS, and that's a gnulib thing
+ * in the case of findutils. Hence we have out own library of replacement
+ * functions which aren't in gnulib (or aren't in it any more). An example
+ * of this is waitpid(). I develop on a system that doesn't
+ * lack waitpid, for example. Therefore FINDLIB_REPLACE_FUNCS(waitpid)
+ * never puts waitpid.o into FINDLIBOBJS. Hence, to ensure that these
+ * macros are tested every time, we use FINDLIB_REPLACE_FUNCS on a function
+ * that never exists anywhere, so always needs to be pulled in. That function
+ * is forcefindlib().
+ */
+void
+forcefindlib(void)
+{
+ /* does nothing, exists only to ensure that FINDLIB_REPLACE_FUNCS works. */
+}
diff --git a/lib/gnulib-version.c b/lib/gnulib-version.c
new file mode 100644
index 0000000..708eec1
--- /dev/null
+++ b/lib/gnulib-version.c
@@ -0,0 +1,2 @@
+/* This file is automatically generated by import-gnulib.sh and simply records which version of gnulib we used. */
+const char * const gnulib_version = "2007-02-24";
diff --git a/lib/gnulib-version.h b/lib/gnulib-version.h
new file mode 100644
index 0000000..eadd5be
--- /dev/null
+++ b/lib/gnulib-version.h
@@ -0,0 +1,21 @@
+/* gnulib-version.h
+ Copyright (C) 2007 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 const char * const gnulib_version;
+
diff --git a/lib/gnulib-version.sh b/lib/gnulib-version.sh
new file mode 100644
index 0000000..b9494b9
--- /dev/null
+++ b/lib/gnulib-version.sh
@@ -0,0 +1,50 @@
+#! /bin/sh
+#
+# gnulib-version.sh -- creates gnulib-version.c (from ../import-gnulib.config)
+# Copyright (C) 2007 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.
+#
+
+topsrcdir="$1"
+srcdir="$2"
+configfile="$3"
+
+outfile="${srcdir}"/gnulib-version.c
+
+source $configfile
+
+if [ -z "$gnulib_version" ]
+then
+ echo "Error: There should be a gnulib_version setting in $configfile, but there is not." >&2
+ exit 1
+fi
+
+
+cat > "${outfile}".new <<EOF
+/* This file is automatically generated by $0 and simply records which version of gnulib we used. */
+const char * const gnulib_version = "$gnulib_version";
+EOF
+
+if test -f "$outfile" ; then
+ if diff "${outfile}".new "${outfile}" > /dev/null
+ then
+ # nothing to do
+ rm "${outfile}".new
+ exit 0
+ fi
+fi
+mv "${outfile}".new "${outfile}"
diff --git a/lib/listfile.c b/lib/listfile.c
new file mode 100644
index 0000000..d60f465
--- /dev/null
+++ b/lib/listfile.c
@@ -0,0 +1,395 @@
+/* listfile.c -- display a long listing of a file
+ Copyright (C) 1991, 1993, 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.
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef __GNUC__
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ # pragma alloca
+# else
+# ifdef _WIN32
+# include <malloc.h>
+# include <io.h>
+# else
+# ifndef alloca
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <pwd.h>
+#include <grp.h>
+#include <time.h>
+#include <errno.h>
+#include "human.h"
+#include "xalloc.h"
+#include "pathmax.h"
+#include "error.h"
+#include "filemode.h"
+
+#include "listfile.h"
+
+#if HAVE_STRING_H || STDC_HEADERS
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+
+/* The presence of unistd.h is assumed by gnulib these days, so we
+ * might as well assume it too.
+ */
+#include <unistd.h> /* for readlink() */
+
+
+#if STDC_HEADERS
+# include <stdlib.h>
+#else
+char *getenv ();
+extern int errno;
+#endif
+
+/* Since major is a function on SVR4, we can't use `ifndef major'. */
+#ifdef MAJOR_IN_MKDEV
+#include <sys/mkdev.h>
+#define HAVE_MAJOR
+#endif
+#ifdef MAJOR_IN_SYSMACROS
+#include <sys/sysmacros.h>
+#define HAVE_MAJOR
+#endif
+
+#ifdef STAT_MACROS_BROKEN
+#undef S_ISCHR
+#undef S_ISBLK
+#undef S_ISLNK
+#endif
+
+#ifndef S_ISCHR
+#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#endif
+#ifndef S_ISBLK
+#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+#endif
+#if defined(S_IFLNK) && !defined(S_ISLNK)
+#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#endif
+
+/* Get or fake the disk device blocksize.
+ Usually defined by sys/param.h (if at all). */
+#ifndef DEV_BSIZE
+# ifdef BSIZE
+# define DEV_BSIZE BSIZE
+# else /* !BSIZE */
+# define DEV_BSIZE 4096
+# endif /* !BSIZE */
+#endif /* !DEV_BSIZE */
+
+/* Extract or fake data from a `struct stat'.
+ ST_BLKSIZE: Preferred I/O blocksize for the file, in bytes.
+ ST_NBLOCKS: Number of blocks in the file, including indirect blocks.
+ ST_NBLOCKSIZE: Size of blocks used when calculating ST_NBLOCKS. */
+#ifndef HAVE_STRUCT_STAT_ST_BLOCKS
+# define ST_BLKSIZE(statbuf) DEV_BSIZE
+# if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE. */
+# define ST_NBLOCKS(statbuf) \
+ (S_ISREG ((statbuf).st_mode) \
+ || S_ISDIR ((statbuf).st_mode) \
+ ? (statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0) : 0)
+# else /* !_POSIX_SOURCE && BSIZE */
+# define ST_NBLOCKS(statbuf) \
+ (S_ISREG ((statbuf).st_mode) \
+ || S_ISDIR ((statbuf).st_mode) \
+ ? st_blocks ((statbuf).st_size) : 0)
+# endif /* !_POSIX_SOURCE && BSIZE */
+#else /* HAVE_STRUCT_STAT_ST_BLOCKS */
+/* Some systems, like Sequents, return st_blksize of 0 on pipes. */
+# define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \
+ ? (statbuf).st_blksize : DEV_BSIZE)
+# if defined(hpux) || defined(__hpux__) || defined(__hpux)
+/* HP-UX counts st_blocks in 1024-byte units.
+ This loses when mixing HP-UX and BSD filesystems with NFS. */
+# define ST_NBLOCKSIZE 1024
+# else /* !hpux */
+# if defined(_AIX) && defined(_I386)
+/* AIX PS/2 counts st_blocks in 4K units. */
+# define ST_NBLOCKSIZE (4 * 1024)
+# else /* not AIX PS/2 */
+# if defined(_CRAY)
+# define ST_NBLOCKS(statbuf) \
+ (S_ISREG ((statbuf).st_mode) \
+ || S_ISDIR ((statbuf).st_mode) \
+ ? (statbuf).st_blocks * ST_BLKSIZE(statbuf)/ST_NBLOCKSIZE : 0)
+# endif /* _CRAY */
+# endif /* not AIX PS/2 */
+# endif /* !hpux */
+#endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
+
+#ifndef ST_NBLOCKS
+# define ST_NBLOCKS(statbuf) \
+ (S_ISREG ((statbuf).st_mode) \
+ || S_ISDIR ((statbuf).st_mode) \
+ ? (statbuf).st_blocks : 0)
+#endif
+
+#ifndef ST_NBLOCKSIZE
+# define ST_NBLOCKSIZE 512
+#endif
+
+#ifndef _POSIX_VERSION
+struct passwd *getpwuid ();
+struct group *getgrgid ();
+#endif
+
+#ifdef major /* Might be defined in sys/types.h. */
+#define HAVE_MAJOR
+#endif
+#ifndef HAVE_MAJOR
+#define major(dev) (((dev) >> 8) & 0xff)
+#define minor(dev) ((dev) & 0xff)
+#endif
+#undef HAVE_MAJOR
+
+
+char * get_link_name (char *name, char *relname);
+static void print_name_with_quoting (register char *p, FILE *stream);
+
+extern char * getgroup (gid_t gid);
+extern char * getuser (uid_t uid);
+
+
+/* NAME is the name to print.
+ RELNAME is the path to access it from the current directory.
+ STATP is the results of stat or lstat on it.
+ Use CURRENT_TIME to decide whether to print yyyy or hh:mm.
+ Use OUTPUT_BLOCK_SIZE to determine how to print file block counts
+ and sizes.
+ STREAM is the stdio stream to print on. */
+
+void
+list_file (char *name,
+ char *relname,
+ struct stat *statp,
+ time_t current_time,
+ int output_block_size,
+ FILE *stream)
+{
+ char modebuf[11];
+ struct tm const *when_local;
+ char const *user_name;
+ char const *group_name;
+ char hbuf[LONGEST_HUMAN_READABLE + 1];
+
+#if HAVE_ST_DM_MODE
+ /* Cray DMF: look at the file's migrated, not real, status */
+ strmode (statp->st_dm_mode, modebuf);
+#else
+ strmode (statp->st_mode, modebuf);
+#endif
+ modebuf[10] = '\0';
+
+ fprintf (stream, "%6s ",
+ human_readable ((uintmax_t) statp->st_ino, hbuf,
+ human_ceiling,
+ 1, 1));
+
+ fprintf (stream, "%4s ",
+ human_readable ((uintmax_t) ST_NBLOCKS (*statp), hbuf,
+ human_ceiling,
+ ST_NBLOCKSIZE, output_block_size));
+
+
+ /* The space between the mode and the number of links is the POSIX
+ "optional alternate access method flag". */
+ fprintf (stream, "%s %3lu ", modebuf, (unsigned long) statp->st_nlink);
+
+ user_name = getuser (statp->st_uid);
+ if (user_name)
+ fprintf (stream, "%-8s ", user_name);
+ else
+ fprintf (stream, "%-8lu ", (unsigned long) statp->st_uid);
+
+ group_name = getgroup (statp->st_gid);
+ if (group_name)
+ fprintf (stream, "%-8s ", group_name);
+ else
+ fprintf (stream, "%-8lu ", (unsigned long) statp->st_gid);
+
+ if (S_ISCHR (statp->st_mode) || S_ISBLK (statp->st_mode))
+#ifdef HAVE_ST_RDEV
+ fprintf (stream, "%3lu, %3lu ",
+ (unsigned long) major (statp->st_rdev),
+ (unsigned long) minor (statp->st_rdev));
+#else
+ fprintf (stream, " ");
+#endif
+ else
+ fprintf (stream, "%8s ",
+ human_readable ((uintmax_t) statp->st_size, hbuf,
+ human_ceiling,
+ 1,
+ output_block_size < 0 ? output_block_size : 1));
+
+ if ((when_local = localtime (&statp->st_mtime)))
+ {
+ char init_bigbuf[256];
+ char *buf = init_bigbuf;
+ size_t bufsize = sizeof init_bigbuf;
+
+ /* Use strftime rather than ctime, because the former can produce
+ locale-dependent names for the month (%b).
+
+ Output the year if the file is fairly old or in the future.
+ POSIX says the cutoff is 6 months old;
+ approximate this by 6*30 days.
+ Allow a 1 hour slop factor for what is considered "the future",
+ to allow for NFS server/client clock disagreement. */
+ char const *fmt =
+ ((current_time - 6 * 30 * 24 * 60 * 60 <= statp->st_mtime
+ && statp->st_mtime <= current_time + 60 * 60)
+ ? "%b %e %H:%M"
+ : "%b %e %Y");
+
+ while (!strftime (buf, bufsize, fmt, when_local))
+ buf = (char *) alloca (bufsize *= 2);
+
+ fprintf (stream, "%s ", buf);
+ }
+ else
+ {
+ /* The time cannot be represented as a local time;
+ print it as a huge integer number of seconds. */
+ int width = 12;
+
+ if (statp->st_mtime < 0)
+ {
+ char const *num = human_readable (- (uintmax_t) statp->st_mtime,
+ hbuf, human_ceiling, 1, 1);
+ int sign_width = width - strlen (num);
+ fprintf (stream, "%*s%s ",
+ sign_width < 0 ? 0 : sign_width, "-", num);
+ }
+ else
+ fprintf (stream, "%*s ", width,
+ human_readable ((uintmax_t) statp->st_mtime, hbuf,
+ human_ceiling,
+ 1, 1));
+ }
+
+ print_name_with_quoting (name, stream);
+
+#ifdef S_ISLNK
+ if (S_ISLNK (statp->st_mode))
+ {
+ char *linkname = get_link_name (name, relname);
+
+ if (linkname)
+ {
+ fputs (" -> ", stream);
+ print_name_with_quoting (linkname, stream);
+ free (linkname);
+ }
+ }
+#endif
+ putc ('\n', stream);
+}
+
+static void
+print_name_with_quoting (register char *p, FILE *stream)
+{
+ register unsigned char c;
+
+ while ((c = *p++) != '\0')
+ {
+ switch (c)
+ {
+ case '\\':
+ fprintf (stream, "\\\\");
+ break;
+
+ case '\n':
+ fprintf (stream, "\\n");
+ break;
+
+ case '\b':
+ fprintf (stream, "\\b");
+ break;
+
+ case '\r':
+ fprintf (stream, "\\r");
+ break;
+
+ case '\t':
+ fprintf (stream, "\\t");
+ break;
+
+ case '\f':
+ fprintf (stream, "\\f");
+ break;
+
+ case ' ':
+ fprintf (stream, "\\ ");
+ break;
+
+ case '"':
+ fprintf (stream, "\\\"");
+ break;
+
+ default:
+ if (c > 040 && c < 0177)
+ putc (c, stream);
+ else
+ fprintf (stream, "\\%03o", (unsigned int) c);
+ }
+ }
+}
+
+#ifdef S_ISLNK
+char *
+get_link_name (char *name, char *relname)
+{
+ register char *linkname;
+ register int linklen;
+
+ /* st_size is wrong for symlinks on AIX, and on
+ mount points with some automounters.
+ So allocate a pessimistic PATH_MAX + 1 bytes. */
+#define LINK_BUF PATH_MAX
+ linkname = (char *) xmalloc (LINK_BUF + 1);
+ linklen = readlink (relname, linkname, LINK_BUF);
+ if (linklen < 0)
+ {
+ error (0, errno, "%s", name);
+ free (linkname);
+ return 0;
+ }
+ linkname[linklen] = '\0';
+ return linkname;
+}
+#endif
diff --git a/lib/listfile.h b/lib/listfile.h
new file mode 100644
index 0000000..64d86c5
--- /dev/null
+++ b/lib/listfile.h
@@ -0,0 +1,28 @@
+/* listfile.h -- display a long listing of a file
+ Copyright (C) 1991, 1993, 2000 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 !defined LISTFILE_H
+# define LISTFILE_H
+
+void list_file (char *name, char *relname, struct stat *statp, time_t current_time, int output_block_size, FILE *stream);
+
+
+
+#endif
diff --git a/lib/modetype.h b/lib/modetype.h
new file mode 100644
index 0000000..fb0fc78
--- /dev/null
+++ b/lib/modetype.h
@@ -0,0 +1,95 @@
+/* modetype.h -- file type bits definitions for POSIX systems
+ Requires sys/types.h sys/stat.h.
+ Copyright (C) 1990, 2001, 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.
+*/
+
+/* POSIX.1 doesn't mention the S_IFMT bits; instead, it uses S_IStype
+ test macros. To make storing file types more convenient, define
+ them; the values don't need to correspond to what the kernel uses,
+ because of the way we use them. */
+#ifndef INC_MODETYPE_H
+#define INC_MODETYPE_H 1
+
+#ifndef S_IFMT /* Doesn't have traditional Unix macros. */
+#define S_IFBLK 1
+#define S_IFCHR 2
+#define S_IFDIR 4
+#define S_IFREG 8
+#ifdef S_ISLNK
+#define S_IFLNK 16
+#endif
+#ifdef S_ISFIFO
+#define S_IFIFO 32
+#endif
+#ifdef S_ISSOCK
+#define S_IFSOCK 64
+#endif
+#ifdef S_ISDOOR
+#define S_IFDOOR 128
+#endif
+#endif /* !S_IFMT */
+
+#ifdef STAT_MACROS_BROKEN
+#undef S_ISBLK
+#undef S_ISCHR
+#undef S_ISDIR
+#undef S_ISREG
+#undef S_ISFIFO
+#undef S_ISLNK
+#undef S_ISSOCK
+#undef S_ISDOOR
+#undef S_ISMPB
+#undef S_ISMPC
+#undef S_ISNWK
+#endif
+
+/* Do the reverse: define the POSIX.1 macros for traditional Unix systems
+ that don't have them. */
+#if !defined(S_ISBLK) && defined(S_IFBLK)
+#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+#endif
+#if !defined(S_ISCHR) && defined(S_IFCHR)
+#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#endif
+#if !defined(S_ISDIR) && defined(S_IFDIR)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+#if !defined(S_ISREG) && defined(S_IFREG)
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+#if !defined(S_ISFIFO) && defined(S_IFIFO)
+#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+#endif
+#if !defined(S_ISLNK) && defined(S_IFLNK)
+#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#endif
+#if !defined(S_ISSOCK) && defined(S_IFSOCK)
+#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+#endif
+#if !defined(S_ISDOOR) && defined(S_IFDOOR)
+#define S_ISDOOR(m) (((m) & S_IFMT) == S_IFDOOR)
+#endif
+#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
+#define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
+#define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
+#endif
+#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
+#define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
+#endif
+
+#endif
diff --git a/lib/nextelem.c b/lib/nextelem.c
new file mode 100644
index 0000000..951b634
--- /dev/null
+++ b/lib/nextelem.c
@@ -0,0 +1,110 @@
+/* Return the next element of a path.
+ Copyright (C) 1992, 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@gnu.org>,
+ inspired by John P. Rouillard <rouilj@cs.umb.edu>. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
+#include <string.h>
+#else
+#include <strings.h>
+#ifndef strchr
+#define strchr index
+#endif
+#endif
+#if defined(STDC_HEADERS)
+#include <stdlib.h>
+#endif
+
+#include "nextelem.h"
+
+
+/* Return the next element of a colon-separated path.
+ A null entry in the path is equivalent to "." (the current directory).
+
+ If NEW_PATH is non-NULL, set the path and return NULL.
+ If NEW_PATH is NULL, return the next item in the string, or
+ return NULL if there are no more elements. */
+
+char *
+next_element (const char *new_path, int curdir_ok)
+{
+ static char *path = NULL; /* Freshly allocated copy of NEW_PATH. */
+ static char *end; /* Start of next element to return. */
+ static int final_colon; /* If zero, path didn't end with a colon. */
+ char *start; /* Start of path element to return. */
+
+ if (new_path)
+ {
+ if (path)
+ free (path);
+ end = path = strdup (new_path);
+ final_colon = 0;
+ return NULL;
+ }
+
+ if (*end == '\0')
+ {
+ if (final_colon)
+ {
+ final_colon = 0;
+ return curdir_ok ? "." : "";
+ }
+ return NULL;
+ }
+
+ start = end;
+ final_colon = 1; /* Maybe there will be one. */
+
+ end = strchr (start, ':');
+ if (end == start)
+ {
+ /* An empty path element. */
+ *end++ = '\0';
+ return curdir_ok ? "." : "";
+ }
+ else if (end == NULL)
+ {
+ /* The last path element. */
+ end = strchr (start, '\0');
+ final_colon = 0;
+ }
+ else
+ *end++ = '\0';
+
+ return start;
+}
+
+#ifdef TEST
+int
+main ()
+{
+ char *p;
+
+ next_element (getenv ("PATH"));
+ while (p = next_element (NULL))
+ puts (p);
+ exit (0);
+}
+#endif /* TEST */
diff --git a/lib/nextelem.h b/lib/nextelem.h
new file mode 100644
index 0000000..afd36fd
--- /dev/null
+++ b/lib/nextelem.h
@@ -0,0 +1,28 @@
+/* Return the next element of a path.
+ Copyright (C) 1992, 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@gnu.org>,
+ inspired by John P. Rouillard <rouilj@cs.umb.edu>. */
+
+#ifndef INC_NEXTELEM_H
+#define INC_NEXTELEM_H 1
+
+char *next_element (const char *path, int curdir_ok);
+
+#endif
diff --git a/lib/printquoted.c b/lib/printquoted.c
new file mode 100644
index 0000000..a054825
--- /dev/null
+++ b/lib/printquoted.c
@@ -0,0 +1,87 @@
+/* printquoted.c -- print a specified string with any necessary quoting.
+
+ Copyright (C) 1990, 1991, 1992, 1993, 1994, 2000,
+ 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 <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* Get mbstate_t, mbrtowc(), mbsinit(), wcwidth(). */
+#if HAVE_WCHAR_H
+# include <wchar.h>
+#endif
+
+
+
+#include "xalloc.h"
+#include "printquoted.h"
+
+
+/*
+ * Print S according to the format FORMAT, but if the destination is a tty,
+ * convert any potentially-dangerous characters. The logic in this function
+ * was taken from ls.c in coreutils (at Sun Jun 5 20:42:51 2005 UTC).
+ */
+void
+print_quoted (FILE *fp,
+ const struct quoting_options *qopts,
+ bool dest_is_tty,
+ const char *format,
+ const char *s)
+{
+ if (dest_is_tty)
+ {
+ char smallbuf[BUFSIZ];
+ size_t len = quotearg_buffer (smallbuf, sizeof smallbuf, s, -1, qopts);
+ char *buf;
+ if (len < sizeof smallbuf)
+ buf = smallbuf;
+ else
+ {
+ /* The original coreutils code uses alloca(), but I don't
+ * want to take on the anguish of introducing alloca() to
+ * 'find'.
+ */
+ buf = xmalloc (len + 1);
+ quotearg_buffer (buf, len + 1, s, -1, qopts);
+ }
+
+ /* Replace any remaining funny characters with '?'. */
+ len = qmark_chars(buf, len);
+
+ fprintf(fp, format, buf); /* Print the quoted version */
+ if (buf != smallbuf)
+ {
+ free(buf);
+ buf = NULL;
+ }
+ }
+ else
+ {
+ /* no need to quote things. */
+ fprintf(fp, format, s);
+ }
+
+}
+
diff --git a/lib/printquoted.h b/lib/printquoted.h
new file mode 100644
index 0000000..7381aa0
--- /dev/null
+++ b/lib/printquoted.h
@@ -0,0 +1,35 @@
+/* Print a string, appropriately quoted.
+
+ Copyright 1997, 1999, 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.
+ */
+
+#if !defined PRINTQUOTED_H
+# define PRINTQUOTED_H
+
+#include "quote.h"
+#include "quotearg.h"
+
+
+#include <stdbool.h>
+#include <stdio.h>
+
+
+size_t qmark_chars(char *buf, size_t len);
+void print_quoted (FILE *fp, const struct quoting_options *qopts, bool dest_is_tty, const char *format, const char *s);
+
+
+#endif
diff --git a/lib/qmark.c b/lib/qmark.c
new file mode 100644
index 0000000..dbc9dcb
--- /dev/null
+++ b/lib/qmark.c
@@ -0,0 +1,239 @@
+/* pred.c -- execute the expression tree.
+ Copyright (C) 1990, 1991, 1992, 1993, 1994, 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+# include <stddef.h>
+# include <stdlib.h>
+#include <ctype.h>
+
+#if HAVE_STRING_H || STDC_HEADERS
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+
+/* Get mbstate_t, mbrtowc(), mbsinit(), wcwidth(). */
+#if HAVE_WCHAR_H
+# include <wchar.h>
+#endif
+
+#include "printquoted.h"
+
+
+/*
+ This comment, IN_CTYPE_DOMAIN and ISPRINT were borrowed from
+ coreutils at Sun Jun 5 21:17:40 2005 UTC.
+
+ Jim Meyering writes:
+
+ "... Some ctype macros are valid only for character codes that
+ isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when
+ using /bin/cc or gcc but without giving an ansi option). So, all
+ ctype uses should be through macros like ISPRINT... If
+ STDC_HEADERS is defined, then autoconf has verified that the ctype
+ macros don't need to be guarded with references to isascii. ...
+ Defining isascii to 1 should let any compiler worth its salt
+ eliminate the && through constant folding."
+
+ Bruno Haible adds:
+
+ "... Furthermore, isupper(c) etc. have an undefined result if c is
+ outside the range -1 <= c <= 255. One is tempted to write isupper(c)
+ with c being of type `char', but this is wrong if c is an 8-bit
+ character >= 128 which gets sign-extended to a negative value.
+ The macro ISUPPER protects against this as well." */
+
+
+
+
+/* ISPRINT is defined in <sys/euc.h> on at least Solaris2.6 systems. */
+#undef ISPRINT
+#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
+
+#if STDC_HEADERS || (!defined (isascii) && !HAVE_ISASCII)
+# define IN_CTYPE_DOMAIN(c) 1
+#else
+# define IN_CTYPE_DOMAIN(c) isascii(c)
+#endif
+
+
+
+
+
+/* Convert a possibly-signed character to an unsigned character. This is
+ * a bit safer than casting to unsigned char, since it catches some type
+ * errors that the cast doesn't.
+ *
+ * This code taken from coreutils' system.h header at
+ * Sun Jun 5 21:05:21 2005 UTC.
+ */
+static inline unsigned char to_uchar (char ch)
+{
+ return ch;
+}
+
+
+
+static size_t
+unibyte_qmark_chars(char *buf, size_t len)
+{
+ char *p = buf;
+ char const *plimit = buf + len;
+
+ while (p < plimit)
+ {
+ if (! ISPRINT (to_uchar (*p)))
+ *p = '?';
+ p++;
+ }
+ return len;
+}
+
+
+#if HAVE_MBRTOWC
+static size_t
+multibyte_qmark_chars(char *buf, size_t len)
+{
+ if (MB_CUR_MAX <= 1)
+ {
+ return unibyte_qmark_chars(buf, len);
+ }
+ else
+ {
+ char const *p = buf;
+ char const *plimit = buf + len;
+ char *q = buf;
+
+ 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. */
+ *q++ = *p++;
+ break;
+ default:
+ /* If we have a multibyte sequence, copy it until we
+ reach its end, replacing each non-printable multibyte
+ character with a single question mark. */
+ {
+ 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. Skip one input byte, and
+ put a question mark. */
+ p++;
+ *q++ = '?';
+ break;
+ }
+
+ if (bytes == (size_t) -2)
+ {
+ /* An incomplete multibyte character
+ at the end. Replace it entirely with
+ a question mark. */
+ p = plimit;
+ *q++ = '?';
+ break;
+ }
+
+ if (bytes == 0)
+ /* A null wide character was encountered. */
+ bytes = 1;
+
+ w = wcwidth (wc);
+ if (w >= 0)
+ {
+ /* A printable multibyte character.
+ Keep it. */
+ for (; bytes > 0; --bytes)
+ *q++ = *p++;
+ }
+ else
+ {
+ /* An unprintable multibyte character.
+ Replace it entirely with a question
+ mark. */
+ p += bytes;
+ *q++ = '?';
+ }
+ }
+ while (! mbsinit (&mbstate));
+ }
+ break;
+ }
+
+ /* The buffer may have shrunk. */
+ len = q - buf;
+ return len;
+ }
+}
+#endif
+
+
+/* Scan BUF, replacing any dangerous-looking characters with question
+ * marks. This code is taken from the ls.c file in coreutils as at
+ * Sun Jun 5 20:51:54 2005 UTC.
+ *
+ * This function may shrink the buffer. Either way, the new length
+ * is returned.
+ */
+size_t
+qmark_chars(char *buf, size_t len)
+{
+#if HAVE_MBRTOWC
+ return multibyte_qmark_chars(buf, len);
+#else
+ return unibyte_qmark_chars(buf, len);
+#endif
+}
+
diff --git a/lib/regexprops.c b/lib/regexprops.c
new file mode 100644
index 0000000..74f49b1
--- /dev/null
+++ b/lib/regexprops.c
@@ -0,0 +1,505 @@
+/* regexprops.c -- document the properties of the regular expressions
+ understood by gnulib.
+
+ Copyright 2005, 2007 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 James Youngman, <jay@gnu.org>. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "regex.h"
+#include "regextype.h"
+
+
+/* Name this program was run with. */
+char *program_name;
+
+static void output(const char *s, int escape)
+{
+ fputs(s, stdout);
+}
+
+
+static void newline(void)
+{
+ output("\n", 0);
+}
+
+static void content(const char *s)
+{
+ output(s, 1);
+}
+
+static void literal(const char *s)
+{
+ output(s, 0);
+}
+
+static void directive(const char *s)
+{
+ output(s, 0);
+}
+
+static void enum_item(const char *s)
+{
+ newline();
+ directive("@item ");
+ literal(s);
+ newline();
+}
+static void table_item(const char *s)
+{
+ directive("@item");
+ newline();
+ content(s);
+ newline();
+}
+
+static void code(const char *s)
+{
+ directive("@code{");
+ content(s);
+ directive("}");
+}
+
+static void begin_subsection(const char *name,
+ const char *next,
+ const char *prev,
+ const char *up)
+{
+ newline();
+
+ directive("@node ");
+ content(name);
+ content(" regular expression syntax");
+ newline();
+
+ directive("@subsection ");
+ output("@samp{", 0);
+ content(name);
+ output("}", 0);
+ content(" regular expression syntax");
+ newline();
+}
+
+static void begintable_asis()
+{
+ newline();
+ directive("@table @asis");
+ newline();
+}
+
+static void begintable_markup(char const *markup)
+{
+ newline();
+ directive("@table ");
+ literal(markup);
+ newline();
+}
+
+static void endtable()
+{
+ newline();
+ directive("@end table");
+ newline();
+}
+
+static void beginenum()
+{
+ newline();
+ directive("@enumerate");
+ newline();
+}
+
+static void endenum()
+{
+ newline();
+ directive("@end enumerate");
+ newline();
+}
+
+static void newpara()
+{
+ content("\n\n");
+}
+
+
+static int describe_regex_syntax(int options)
+{
+ newpara();
+ content("The character @samp{.} matches any single character");
+ if ( (options & RE_DOT_NEWLINE) == 0 )
+ {
+ content(" except newline");
+ }
+ if (options & RE_DOT_NOT_NULL)
+ {
+ if ( (options & RE_DOT_NEWLINE) == 0 )
+ content(" and");
+ else
+ content(" except");
+
+ content(" the null character");
+ }
+ content(". ");
+ newpara();
+
+ if (!(options & RE_LIMITED_OPS))
+ {
+ begintable_markup("@samp");
+ if (options & RE_BK_PLUS_QM)
+ {
+ enum_item("\\+");
+ content("indicates that the regular expression should match one"
+ " or more occurrences of the previous atom or regexp. ");
+ enum_item("\\?");
+ content("indicates that the regular expression should match zero"
+ " or one occurrence of the previous atom or regexp. ");
+ enum_item("+ and ? ");
+ content("match themselves. ");
+ }
+ else
+ {
+ enum_item("+");
+ content("indicates that the regular expression should match one"
+ " or more occurrences of the previous atom or regexp. ");
+ enum_item("?");
+ content("indicates that the regular expression should match zero"
+ " or one occurrence of the previous atom or regexp. ");
+ enum_item("\\+");
+ literal("matches a @samp{+}");
+ enum_item("\\?");
+ literal("matches a @samp{?}. ");
+ }
+ endtable();
+ }
+
+ newpara();
+
+ content("Bracket expressions are used to match ranges of characters. ");
+ literal("Bracket expressions where the range is backward, for example @samp{[z-a]}, are ");
+ if (options & RE_NO_EMPTY_RANGES)
+ content("invalid");
+ else
+ content("ignored");
+ content(". ");
+
+ if (options & RE_BACKSLASH_ESCAPE_IN_LISTS)
+ literal("Within square brackets, @samp{\\} can be used to quote "
+ "the following character. ");
+ else
+ literal("Within square brackets, @samp{\\} is taken literally. ");
+
+ if (options & RE_CHAR_CLASSES)
+ content("Character classes are supported; for example "
+ "@samp{[[:digit:]]} will match a single decimal digit. ");
+ else
+ literal("Character classes are not supported, so for example "
+ "you would need to use @samp{[0-9]} "
+ "instead of @samp{[[:digit:]]}. ");
+
+ if (options & RE_HAT_LISTS_NOT_NEWLINE)
+ {
+ literal("Non-matching lists @samp{[^@dots{}]} do not ever match newline. ");
+ }
+ newpara();
+ if (options & RE_NO_GNU_OPS)
+ {
+ content("GNU extensions are not supported and so "
+ "@samp{\\w}, @samp{\\W}, @samp{\\<}, @samp{\\>}, @samp{\\b}, @samp{\\B}, @samp{\\`}, and @samp{\\'} "
+ "match "
+ "@samp{w}, @samp{W}, @samp{<}, @samp{>}, @samp{b}, @samp{B}, @samp{`}, and @samp{'} respectively. ");
+ }
+ else
+ {
+ content("GNU extensions are supported:");
+ beginenum();
+ enum_item("@samp{\\w} matches a character within a word");
+ enum_item("@samp{\\W} matches a character which is not within a word");
+ enum_item("@samp{\\<} matches the beginning of a word");
+ enum_item("@samp{\\>} matches the end of a word");
+ enum_item("@samp{\\b} matches a word boundary");
+ enum_item("@samp{\\B} matches characters which are not a word boundary");
+ enum_item("@samp{\\`} matches the beginning of the whole input");
+ enum_item("@samp{\\'} matches the end of the whole input");
+ endenum();
+ }
+
+ newpara();
+
+
+ if (options & RE_NO_BK_PARENS)
+ {
+ literal("Grouping is performed with parentheses @samp{()}. ");
+
+ if (options & RE_UNMATCHED_RIGHT_PAREN_ORD)
+ literal("An unmatched @samp{)} matches just itself. ");
+ }
+ else
+ {
+ literal("Grouping is performed with backslashes followed by parentheses @samp{\\(}, @samp{\\)}. ");
+ }
+
+ if (options & RE_NO_BK_REFS)
+ {
+ content("A backslash followed by a digit matches that digit. ");
+ }
+ else
+ {
+ literal("A backslash followed by a digit acts as a back-reference and matches the same thing as the previous grouped expression indicated by that number. For example @samp{\\2} matches the second group expression. The order of group expressions is determined by the position of their opening parenthesis ");
+ if (options & RE_NO_BK_PARENS)
+ literal("@samp{(}");
+ else
+ literal("@samp{\\(}");
+ content(". ");
+ }
+
+
+ newpara();
+ if (!(options & RE_LIMITED_OPS))
+ {
+ if (options & RE_NO_BK_VBAR)
+ literal("The alternation operator is @samp{|}. ");
+ else
+ literal("The alternation operator is @samp{\\|}. ");
+ }
+ newpara();
+
+ if (options & RE_CONTEXT_INDEP_ANCHORS)
+ {
+ literal("The characters @samp{^} and @samp{$} always represent the beginning and end of a string respectively, except within square brackets. Within brackets, @samp{^} can be used to invert the membership of the character class being specified. ");
+ }
+ else
+ {
+ literal("The character @samp{^} only represents the beginning of a string when it appears:");
+ beginenum();
+ enum_item("\nAt the beginning of a regular expression");
+ enum_item("After an open-group, signified by ");
+ if (options & RE_NO_BK_PARENS)
+ {
+ literal("@samp{(}");
+ }
+ else
+ {
+ literal("@samp{\\(}");
+ }
+ newline();
+ if (!(options & RE_LIMITED_OPS))
+ {
+ if (options & RE_NEWLINE_ALT)
+ enum_item("After a newline");
+
+ if (options & RE_NO_BK_VBAR )
+ enum_item("After the alternation operator @samp{|}");
+ else
+ enum_item("After the alternation operator @samp{\\|}");
+ }
+ endenum();
+
+ newpara();
+ literal("The character @samp{$} only represents the end of a string when it appears:");
+ beginenum();
+ enum_item("At the end of a regular expression");
+ enum_item("Before a close-group, signified by ");
+ if (options & RE_NO_BK_PARENS)
+ {
+ literal("@samp{)}");
+ }
+ else
+ {
+ literal("@samp{\\)}");
+ }
+ if (!(options & RE_LIMITED_OPS))
+ {
+ if (options & RE_NEWLINE_ALT)
+ enum_item("Before a newline");
+
+ if (options & RE_NO_BK_VBAR)
+ enum_item("Before the alternation operator @samp{|}");
+ else
+ enum_item("Before the alternation operator @samp{\\|}");
+ }
+ endenum();
+ }
+ newpara();
+ if (!(options & RE_LIMITED_OPS) )
+ {
+ if ((options & RE_CONTEXT_INDEP_OPS)
+ && !(options & RE_CONTEXT_INVALID_OPS))
+ {
+ literal("The characters @samp{*}, @samp{+} and @samp{?} are special anywhere in a regular expression. ");
+ }
+ else
+ {
+ if (options & RE_BK_PLUS_QM)
+ literal("@samp{\\*}, @samp{\\+} and @samp{\\?} ");
+ else
+ literal("@samp{*}, @samp{+} and @samp{?} ");
+
+ if (options & RE_CONTEXT_INVALID_OPS)
+ {
+ content("are special at any point in a regular expression except the following places, where they are not allowed:");
+ }
+ else
+ {
+ content("are special at any point in a regular expression except:");
+ }
+
+ beginenum();
+ enum_item("At the beginning of a regular expression");
+ enum_item("After an open-group, signified by ");
+ if (options & RE_NO_BK_PARENS)
+ {
+ literal("@samp{(}");
+ }
+ else
+ {
+ literal("@samp{\\(}");
+ }
+ if (!(options & RE_LIMITED_OPS))
+ {
+ if (options & RE_NEWLINE_ALT)
+ enum_item("After a newline");
+
+ if (options & RE_NO_BK_VBAR)
+ enum_item("After the alternation operator @samp{|}");
+ else
+ enum_item("After the alternation operator @samp{\\|}");
+ }
+ endenum();
+ }
+ }
+
+
+ newpara();
+ if (options & RE_INTERVALS)
+ {
+ if (options & RE_NO_BK_BRACES)
+ {
+ literal("Intervals are specified by @samp{@{} and @samp{@}}. ");
+ if (options & RE_INVALID_INTERVAL_ORD)
+ {
+ literal("Invalid intervals are treated as literals, for example @samp{a@{1} is treated as @samp{a\\@{1}");
+ }
+ else
+ {
+ literal("Invalid intervals such as @samp{a@{1z} are not accepted. ");
+ }
+ }
+ else
+ {
+ literal("Intervals are specified by @samp{\\@{} and @samp{\\@}}. ");
+ if (options & RE_INVALID_INTERVAL_ORD)
+ {
+ literal("Invalid intervals are treated as literals, for example @samp{a\\@{1} is treated as @samp{a@{1}");
+ }
+ else
+ {
+ literal("Invalid intervals such as @samp{a\\@{1z} are not accepted. ");
+ }
+ }
+
+ }
+
+ newpara();
+ if (options & RE_NO_POSIX_BACKTRACKING)
+ {
+ content("Matching succeeds as soon as the whole pattern is matched, meaning that the result may not be the longest possible match. ");
+ }
+ else
+ {
+ content("The longest possible match is returned; this applies to the regular expression as a whole and (subject to this constraint) to subexpressions within groups. ");
+ }
+ newpara();
+}
+
+
+
+static int menu()
+{
+ int i, options;
+ const char *name;
+
+ output("@menu\n", 0);
+ for (i=0;
+ options = get_regex_type_flags(i),
+ name=get_regex_type_name(i);
+ ++i)
+ {
+ output("* ", 0);
+ output(name, 0);
+ content(" regular expression syntax");
+ output("::", 0);
+ newline();
+ }
+ output("@end menu\n", 0);
+}
+
+
+static int describe_all(const char *up)
+{
+ const char *name, *next, *previous;
+ int options;
+ int i, parent;
+
+ menu();
+
+ previous = "";
+
+ for (i=0;
+ options = get_regex_type_flags(i),
+ name=get_regex_type_name(i);
+ ++i)
+ {
+ next = get_regex_type_name(i+1);
+ if (NULL == next)
+ next = "";
+ begin_subsection(name, next, previous, up);
+ parent = get_regex_type_synonym(i);
+ if (parent >= 0)
+ {
+ content("This is a synonym for ");
+ content(get_regex_type_name(parent));
+ content(".");
+ }
+ else
+ {
+ describe_regex_syntax(options);
+ }
+ previous = name;
+ }
+}
+
+
+
+int main (int argc, char *argv[])
+{
+ const char *up = "";
+ program_name = argv[0];
+
+ if (argc > 1)
+ up = argv[1];
+
+ describe_all(up);
+ return 0;
+}
diff --git a/lib/regextype.c b/lib/regextype.c
new file mode 100644
index 0000000..9aaa6c6
--- /dev/null
+++ b/lib/regextype.c
@@ -0,0 +1,158 @@
+
+/* regextype.c -- Decode the name of a regular expression syntax into am
+ option name.
+
+ Copyright 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 James Youngman, <jay@gnu.org>. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+#include "regextype.h"
+#include "regex.h"
+#include "quote.h"
+#include "quotearg.h"
+#include "xalloc.h"
+#include "error.h"
+
+
+#if ENABLE_NLS
+# include <libintl.h>
+# define _(Text) gettext (Text)
+#else
+# define _(Text) Text
+#endif
+#ifdef gettext_noop
+# define N_(String) gettext_noop (String)
+#else
+/* See locate.c for explanation as to why not use (String) */
+# define N_(String) String
+#endif
+
+
+
+struct tagRegexTypeMap
+{
+ char *name;
+ int option_val;
+};
+
+struct tagRegexTypeMap regex_map[] =
+ {
+#ifdef FINDUTILS
+ { "findutils-default", RE_SYNTAX_EMACS|RE_DOT_NEWLINE },
+#endif
+ { "awk", RE_SYNTAX_AWK },
+ { "egrep", RE_SYNTAX_EGREP },
+#ifndef FINDUTILS
+ { "ed", RE_SYNTAX_ED },
+#endif
+ { "emacs", RE_SYNTAX_EMACS },
+ { "gnu-awk", RE_SYNTAX_GNU_AWK },
+ { "grep", RE_SYNTAX_GREP },
+ { "posix-awk", RE_SYNTAX_POSIX_AWK },
+ { "posix-basic", RE_SYNTAX_POSIX_BASIC },
+ { "posix-egrep", RE_SYNTAX_POSIX_EGREP },
+ { "posix-extended", RE_SYNTAX_POSIX_EXTENDED },
+#ifndef FINDUTILS
+ { "posix-minimal-basic", RE_SYNTAX_POSIX_MINIMAL_BASIC },
+ { "sed", RE_SYNTAX_SED },
+ /* ,{ "posix-common", _RE_SYNTAX_POSIX_COMMON } */
+#endif
+ };
+enum { N_REGEX_MAP_ENTRIES = sizeof(regex_map)/sizeof(regex_map[0]) };
+
+int
+get_regex_type(const char *s)
+{
+ unsigned i;
+ size_t msglen;
+ char *buf, *p;
+
+ msglen = 0u;
+ for (i=0u; i<N_REGEX_MAP_ENTRIES; ++i)
+ {
+ if (0 == strcmp(regex_map[i].name, s))
+ return regex_map[i].option_val;
+ else
+ msglen += strlen(quote(regex_map[i].name)) + 2u;
+ }
+
+ /* We didn't find a match for the type of regular expression that the
+ * user indicated they wanted. Tell them what the options are.
+ */
+ p = buf = xmalloc(1u + msglen);
+ for (i=0u; i<N_REGEX_MAP_ENTRIES; ++i)
+ {
+ if (i > 0u)
+ {
+ strcpy(p, ", ");
+ p += 2;
+ }
+ p += sprintf(p, "%s", quote(regex_map[i].name));
+ }
+
+ error(1, 0, _("Unknown regular expression type %s; valid types are %s."),
+ quote(s),
+ buf);
+ /*NOTREACHED*/
+ return -1;
+}
+
+
+const char *
+get_regex_type_name(int ix)
+{
+ if (ix < N_REGEX_MAP_ENTRIES)
+ return regex_map[ix].name;
+ else
+ return NULL;
+}
+
+int
+get_regex_type_flags(int ix)
+{
+ if (ix < N_REGEX_MAP_ENTRIES)
+ return regex_map[ix].option_val;
+ else
+ return -1;
+}
+
+
+int get_regex_type_synonym(int ix)
+{
+ unsigned i;
+ int flags;
+
+ if (ix >= N_REGEX_MAP_ENTRIES)
+ return -1;
+
+ flags = regex_map[ix].option_val;
+ for (i=0u; i<ix; ++i)
+ {
+ if (flags == regex_map[i].option_val)
+ {
+ return i;
+ }
+ }
+ return -1;
+}
diff --git a/lib/regextype.h b/lib/regextype.h
new file mode 100644
index 0000000..e28815f
--- /dev/null
+++ b/lib/regextype.h
@@ -0,0 +1,28 @@
+/* regextype.h -- Decode the name of a regular expression syntax into am
+ option name.
+
+ Copyright 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 James Youngman <jay@gnu.org>.
+ */
+
+int get_regex_type(const char *s);
+
+
+const char * get_regex_type_name(int ix);
+int get_regex_type_flags(int ix);
+int get_regex_type_synonym(int ix);
diff --git a/lib/savedirinfo.c b/lib/savedirinfo.c
new file mode 100644
index 0000000..92d0639
--- /dev/null
+++ b/lib/savedirinfo.c
@@ -0,0 +1,387 @@
+/* savedirinfo.c -- Save the list of files in a directory, with additional information.
+
+ Copyright 1990, 1997, 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. */
+
+/* Written by James Youngman, <jay@gnu.org>. */
+/* Derived from savedir.c, written by David MacKenzie <djm@gnu.org>. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+/* The presence of unistd.h is assumed by gnulib these days, so we
+ * might as well assume it too.
+ */
+#include <unistd.h>
+
+#include <errno.h>
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+#else
+# define dirent direct
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif
+
+#ifdef CLOSEDIR_VOID
+/* Fake a return value. */
+# define CLOSEDIR(d) (closedir (d), 0)
+#else
+# define CLOSEDIR(d) closedir (d)
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xalloc.h"
+#include "extendbuf.h"
+#include "savedirinfo.h"
+
+/* In order to use struct dirent.d_type, it has to be enabled on the
+ * configure command line, and we have to have a d_type member in
+ * 'struct dirent'.
+ */
+#if !defined(USE_STRUCT_DIRENT_D_TYPE)
+/* Not enabled, hence pretend it is absent. */
+#undef HAVE_STRUCT_DIRENT_D_TYPE
+#endif
+#if !defined(HAVE_STRUCT_DIRENT_D_TYPE)
+/* Not present, so cannot use it. */
+#undef USE_STRUCT_DIRENT_D_TYPE
+#endif
+
+
+#if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE)
+/* Convert the value of struct dirent.d_type into a value for
+ * struct stat.st_mode (at least the file type bits), or zero
+ * if the type is DT_UNKNOWN or is a value we don't know about.
+ */
+static mode_t
+type_to_mode(unsigned type)
+{
+ switch (type)
+ {
+#ifdef DT_FIFO
+ case DT_FIFO: return S_IFIFO;
+#endif
+#ifdef DT_CHR
+ case DT_CHR: return S_IFCHR;
+#endif
+#ifdef DT_DIR
+ case DT_DIR: return S_IFDIR;
+#endif
+#ifdef DT_BLK
+ case DT_BLK: return S_IFBLK;
+#endif
+#ifdef DT_REG
+ case DT_REG: return S_IFREG;
+#endif
+#ifdef DT_LNK
+ case DT_LNK: return S_IFLNK;
+#endif
+#ifdef DT_SOCK
+ case DT_SOCK: return S_IFSOCK;
+#endif
+ default:
+ return 0; /* Unknown. */
+ }
+}
+
+#endif
+
+struct new_savedir_direntry_internal
+{
+ int flags; /* from SaveDirDataFlags */
+ mode_t type_info;
+ size_t buffer_offset;
+};
+
+
+
+static int
+savedir_cmp(const void *p1, const void *p2)
+{
+ const struct savedir_direntry *de1, *de2;
+ de1 = p1;
+ de2 = p2;
+ return strcmp(de1->name, de2->name); /* POSIX order, not locale order. */
+}
+
+
+static struct savedir_direntry*
+convertentries(const struct savedir_dirinfo *info,
+ struct new_savedir_direntry_internal *internal)
+{
+ char *p = info->buffer;
+ struct savedir_direntry *result;
+ int n =info->size;
+ int i;
+
+
+ result = xmalloc(sizeof(*result) * info->size);
+
+ for (i=0; i<n; ++i)
+ {
+ result[i].flags = internal[i].flags;
+ result[i].type_info = internal[i].type_info;
+ result[i].name = &p[internal[i].buffer_offset];
+ }
+ return result;
+}
+
+
+struct savedir_dirinfo *
+xsavedir(const char *dir, int flags)
+{
+ DIR *dirp;
+ struct dirent *dp;
+ struct savedir_dirinfo *result = NULL;
+ struct new_savedir_direntry_internal *internal;
+
+ size_t namebuf_allocated = 0u, namebuf_used = 0u;
+ size_t entrybuf_allocated = 0u;
+ int save_errno;
+
+ dirp = opendir (dir);
+ if (dirp == NULL)
+ return NULL;
+
+ errno = 0;
+ result = xmalloc(sizeof(*result));
+ result->buffer = NULL;
+ result->size = 0u;
+ result->entries = NULL;
+ internal = NULL;
+
+ while ((dp = readdir (dirp)) != NULL)
+ {
+ /* Skip "", ".", and "..". "" is returned by at least one buggy
+ implementation: Solaris 2.4 readdir on NFS file systems. */
+ char const *entry = dp->d_name;
+ if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0')
+ {
+ /* Remember the name. */
+ size_t entry_size = strlen (entry) + 1;
+ result->buffer = extendbuf(result->buffer, namebuf_used+entry_size, &namebuf_allocated);
+ memcpy ((result->buffer) + namebuf_used, entry, entry_size);
+
+ /* Remember the other stuff. */
+ internal = extendbuf(internal, (1+result->size)*sizeof(*internal), &entrybuf_allocated);
+ internal[result->size].flags = 0;
+
+#if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE)
+ internal[result->size].type_info = type_to_mode(dp->d_type);
+ if (dp->d_type != DT_UNKNOWN)
+ internal[result->size].flags |= SavedirHaveFileType;
+#else
+ internal[result->size].type_info = 0;
+#endif
+ internal[result->size].buffer_offset = namebuf_used;
+
+ /* Prepare for the next iteration */
+ ++(result->size);
+ namebuf_used += entry_size;
+ }
+ }
+
+ result->buffer = extendbuf(result->buffer, namebuf_used+1, &namebuf_allocated);
+ result->buffer[namebuf_used] = '\0';
+
+ /* convert the result to its externally-usable form. */
+ result->entries = convertentries(result, internal);
+ free(internal);
+ internal = NULL;
+
+
+ if (flags & SavedirSort)
+ {
+ qsort(result->entries,
+ result->size, sizeof(*result->entries),
+ savedir_cmp);
+ }
+
+
+ save_errno = errno;
+ if (CLOSEDIR (dirp) != 0)
+ save_errno = errno;
+ if (save_errno != 0)
+ {
+ free (result->buffer);
+ free (result);
+ errno = save_errno;
+ return NULL;
+ }
+
+ return result;
+}
+
+void free_dirinfo(struct savedir_dirinfo *p)
+{
+ free(p->entries);
+ p->entries = NULL;
+ free(p->buffer);
+ p->buffer = NULL;
+ free(p);
+}
+
+
+
+static char *
+new_savedirinfo (const char *dir, struct savedir_extrainfo **extra)
+{
+ struct savedir_dirinfo *p = xsavedir(dir, SavedirSort);
+ char *buf, *s;
+ size_t bufbytes = 0;
+ int i;
+
+ if (p)
+ {
+ struct savedir_extrainfo *pex = xmalloc(p->size * sizeof(*extra));
+ for (i=0; i<p->size; ++i)
+ {
+ bufbytes += strlen(p->entries[i].name);
+ ++bufbytes; /* the \0 */
+
+ pex[i].type_info = p->entries[i].type_info;
+ }
+
+ s = buf = xmalloc(bufbytes+1);
+ for (i=0; i<p->size; ++i)
+ {
+ size_t len = strlen(p->entries[i].name);
+ memcpy(s, p->entries[i].name, len);
+ s += len;
+ *s = 0; /* Place a NUL */
+ ++s; /* Skip the NUL. */
+ }
+ *s = 0; /* final (doubled) terminating NUL */
+
+ if (extra)
+ *extra = pex;
+ else
+ free (pex);
+ return buf;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+
+#if 0
+/* Return a freshly allocated string containing the filenames
+ in directory DIR, separated by '\0' characters;
+ the end is marked by two '\0' characters in a row.
+ Return NULL (setting errno) if DIR cannot be opened, read, or closed. */
+
+static char *
+old_savedirinfo (const char *dir, struct savedir_extrainfo **extra)
+{
+ DIR *dirp;
+ struct dirent *dp;
+ char *name_space;
+ size_t namebuf_allocated = 0u, namebuf_used = 0u;
+#if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE)
+ size_t extra_allocated = 0u, extra_used = 0u;
+ struct savedir_extrainfo *info = NULL;
+#endif
+ int save_errno;
+
+ if (extra)
+ *extra = NULL;
+
+ dirp = opendir (dir);
+ if (dirp == NULL)
+ return NULL;
+
+ errno = 0;
+ name_space = NULL;
+ while ((dp = readdir (dirp)) != NULL)
+ {
+ /* Skip "", ".", and "..". "" is returned by at least one buggy
+ implementation: Solaris 2.4 readdir on NFS file systems. */
+ char const *entry = dp->d_name;
+ if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0')
+ {
+ /* Remember the name. */
+ size_t entry_size = strlen (entry) + 1;
+ name_space = extendbuf(name_space, namebuf_used+entry_size, &namebuf_allocated);
+ memcpy (name_space + namebuf_used, entry, entry_size);
+ namebuf_used += entry_size;
+
+
+#if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE)
+ /* Remember the type. */
+ if (extra)
+ {
+ info = extendbuf(info,
+ (extra_used+1) * sizeof(struct savedir_dirinfo),
+ &extra_allocated);
+ info[extra_used].type_info = type_to_mode(dp->d_type);
+ ++extra_used;
+ }
+#endif
+ }
+ }
+
+ name_space = extendbuf(name_space, namebuf_used+1, &namebuf_allocated);
+ name_space[namebuf_used] = '\0';
+
+ save_errno = errno;
+ if (CLOSEDIR (dirp) != 0)
+ save_errno = errno;
+ if (save_errno != 0)
+ {
+ free (name_space);
+ errno = save_errno;
+ return NULL;
+ }
+
+#if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE)
+ if (extra && info)
+ *extra = info;
+#endif
+
+ return name_space;
+}
+#endif
+
+
+char *
+savedirinfo (const char *dir, struct savedir_extrainfo **extra)
+{
+ return new_savedirinfo(dir, extra);
+}
diff --git a/lib/savedirinfo.h b/lib/savedirinfo.h
new file mode 100644
index 0000000..365f144
--- /dev/null
+++ b/lib/savedirinfo.h
@@ -0,0 +1,73 @@
+/* Save the list of files in a directory, with additional information.
+
+ Copyright 1997, 1999, 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 James Youngman <jay@gnu.org>.
+ * Based on savedir.h by David MacKenzie <djm@gnu.org>.
+ */
+
+#if !defined SAVEDIRINFO_H_
+# define SAVEDIRINFO_H_
+
+
+typedef enum tagSaveDirControlFlags
+ {
+ SavedirSort = 1
+ }
+SaveDirControlFlags;
+
+
+typedef enum tagSaveDirDataFlags
+ {
+ SavedirHaveFileType = 1
+ }
+SaveDirDataFlags;
+
+
+/* We keep the name and the type in a structure together
+ * to allow us to sort them together.
+ */
+struct savedir_direntry
+{
+ int flags; /* from SaveDirDataFlags */
+ char *name; /* the name of the directory entry */
+ mode_t type_info; /* the type (or zero if unknown) */
+};
+
+struct savedir_dirinfo
+{
+ char *buffer; /* The names are stored here. */
+ size_t size; /* The total number of results. */
+ struct savedir_direntry *entries; /* The results themselves */
+};
+
+
+struct savedir_extrainfo
+{
+ mode_t type_info;
+};
+
+/* savedirinfo() is the old interface. */
+char *savedirinfo (const char *dir, struct savedir_extrainfo **extra);
+
+/* savedir() is the 'new' interface, but the function has the same name
+ * as the function from findutils 4.1.7 and 4.1.20.
+ */
+struct savedir_dirinfo * xsavedir(const char *dir, int flags);
+void free_dirinfo(struct savedir_dirinfo *p);
+
+#endif
diff --git a/lib/wait.h b/lib/wait.h
new file mode 100644
index 0000000..a7b0803
--- /dev/null
+++ b/lib/wait.h
@@ -0,0 +1,41 @@
+/* wait.h -- POSIX macros for evaluating exit statuses
+ Copyright (C) 1990 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 <sys/types.h> /* For pid_t. */
+#if HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+#ifndef WIFSTOPPED
+#define WIFSTOPPED(w) (((w) & 0xff) == 0x7f)
+#endif
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(w) (((w) & 0xff) != 0x7f && ((w) & 0xff) != 0)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(w) (((w) & 0xff) == 0)
+#endif
+
+#ifndef WSTOPSIG
+#define WSTOPSIG(w) (((w) >> 8) & 0xff)
+#endif
+#ifndef WTERMSIG
+#define WTERMSIG(w) ((w) & 0x7f)
+#endif
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(w) (((w) >> 8) & 0xff)
+#endif
diff --git a/lib/waitpid.c b/lib/waitpid.c
new file mode 100644
index 0000000..b7984c0
--- /dev/null
+++ b/lib/waitpid.c
@@ -0,0 +1,81 @@
+/* Emulate waitpid on systems that just have wait.
+ Copyright 1994, 1995, 1998, 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; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+
+#if defined _MSC_VER || defined __MINGW32__
+/* Native Woe32 API. */
+#include <process.h>
+#else
+/* Unix API. */
+#include "wait.h"
+#endif
+
+#define WAITPID_CHILDREN 8
+static pid_t waited_pid[WAITPID_CHILDREN];
+static int waited_status[WAITPID_CHILDREN];
+
+pid_t
+waitpid (pid_t pid, int *stat_loc, int options)
+{
+ int i;
+ pid_t p;
+
+ if (!options && (pid == -1 || 0 < pid))
+ {
+ /* If we have already waited for this child, return it immediately. */
+ for (i = 0; i < WAITPID_CHILDREN; i++)
+ {
+ p = waited_pid[i];
+ if (p && (p == pid || pid == -1))
+ {
+ waited_pid[i] = 0;
+ goto success;
+ }
+ }
+
+ /* The child has not returned yet; wait for it, accumulating status. */
+ for (i = 0; i < WAITPID_CHILDREN; i++)
+ if (! waited_pid[i])
+ {
+ p = wait (&waited_status[i]);
+ if (p < 0)
+ return p;
+ if (p == pid || pid == -1)
+ goto success;
+ waited_pid[i] = p;
+ }
+ }
+
+ /* We cannot emulate this wait call, e.g. because of too many children. */
+ errno = EINVAL;
+ return -1;
+
+success:
+ if (stat_loc)
+ *stat_loc = waited_status[i];
+ return p;
+}