summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-07-21 17:12:39 +0100
committerAnas Nashif <anas.nashif@intel.com>2012-07-23 10:19:53 +0100
commit3f1932e927ae070261a8d428d5c5f158c2f525ba (patch)
tree286e9acc48a43dd751e4112144eb7d4d6ba62533 /lib
parentf86053dd05b02441d0c27eb68524ae3c1cf0fe81 (diff)
downloadcpio-3f1932e927ae070261a8d428d5c5f158c2f525ba.tar.gz
cpio-3f1932e927ae070261a8d428d5c5f158c2f525ba.tar.bz2
cpio-3f1932e927ae070261a8d428d5c5f158c2f525ba.zip
downgrade to 2.8 (GPLv2)
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am86
-rw-r--r--lib/Makefile.in1342
-rw-r--r--lib/__fpending.c30
-rw-r--r--lib/__fpending.h34
-rw-r--r--lib/alloca.c489
-rw-r--r--lib/alloca_.h54
-rw-r--r--lib/allocsa.c137
-rw-r--r--lib/allocsa.h124
-rw-r--r--lib/allocsa.valgrind7
-rw-r--r--lib/argmatch.c278
-rw-r--r--lib/argmatch.h103
-rw-r--r--lib/argp-ba.c25
-rw-r--r--lib/argp-eexst.c31
-rw-r--r--lib/argp-fmtstream.c435
-rw-r--r--lib/argp-fmtstream.h301
-rw-r--r--lib/argp-fs-xinl.c43
-rw-r--r--lib/argp-help.c1954
-rw-r--r--lib/argp-namefrob.h158
-rw-r--r--lib/argp-parse.c953
-rw-r--r--lib/argp-pin.c28
-rw-r--r--lib/argp-pv.c24
-rw-r--r--lib/argp-pvh.c31
-rw-r--r--lib/argp-xinl.c43
-rw-r--r--lib/argp.h622
-rw-r--r--lib/asnprintf.c35
-rw-r--r--lib/at-func.c86
-rw-r--r--lib/basename.c129
-rw-r--r--lib/canonicalize-lgpl.c353
-rw-r--r--lib/canonicalize.h54
-rw-r--r--lib/chdir-long.c265
-rw-r--r--lib/chdir-long.h35
-rw-r--r--lib/chown.c104
-rw-r--r--lib/close-stream.c76
-rw-r--r--lib/close-stream.h2
-rw-r--r--lib/closeout.c86
-rw-r--r--lib/closeout.h33
-rw-r--r--lib/creat-safer.c32
-rw-r--r--lib/dirent_.h50
-rw-r--r--lib/dirfd.c29
-rw-r--r--lib/dirfd.h29
-rw-r--r--lib/dirname.c85
-rw-r--r--lib/dirname.h70
-rw-r--r--lib/dup-safer.c45
-rw-r--r--lib/dup2.c58
-rw-r--r--lib/error.c693
-rw-r--r--lib/error.h66
-rw-r--r--lib/exitfail.c26
-rw-r--r--lib/exitfail.h20
-rw-r--r--lib/fatal.c27
-rw-r--r--lib/fchdir.c279
-rw-r--r--lib/fchmodat.c50
-rw-r--r--lib/fchown-stub.c16
-rw-r--r--lib/fchownat.c50
-rw-r--r--lib/fcntl--.h28
-rw-r--r--lib/fcntl-safer.h24
-rw-r--r--lib/fcntl_.h125
-rw-r--r--lib/fd-safer.c57
-rw-r--r--lib/fileblocks.c75
-rw-r--r--lib/float+.h148
-rw-r--r--lib/float_.h63
-rw-r--r--lib/fnmatch.c354
-rw-r--r--lib/fnmatch_.h65
-rw-r--r--lib/fnmatch_loop.c1210
-rw-r--r--lib/fstatat.c57
-rw-r--r--lib/full-write.c81
-rw-r--r--lib/full-write.h35
-rw-r--r--lib/getcwd.c428
-rw-r--r--lib/getdate.c3289
-rw-r--r--lib/getdate.h23
-rw-r--r--lib/getdate.y1520
-rw-r--r--lib/getopt.c1191
-rw-r--r--lib/getopt1.c171
-rw-r--r--lib/getopt_.h226
-rw-r--r--lib/getopt_int.h131
-rw-r--r--lib/gettext.h270
-rw-r--r--lib/gettime.c49
-rw-r--r--lib/gettimeofday.c142
-rw-r--r--lib/gnulib.mk1244
-rw-r--r--lib/hash.c1048
-rw-r--r--lib/hash.h88
-rw-r--r--lib/imaxtostr.c3
-rw-r--r--lib/intprops.h78
-rw-r--r--lib/inttostr.c51
-rw-r--r--lib/inttostr.h30
-rw-r--r--lib/inttypes_.h1100
-rw-r--r--lib/lchown.c47
-rw-r--r--lib/lchown.h42
-rw-r--r--lib/lstat.c76
-rw-r--r--lib/lstat.h24
-rw-r--r--lib/malloc.c35
-rw-r--r--lib/mempcpy.c29
-rw-r--r--lib/memrchr.c190
-rw-r--r--lib/mkdirat.c43
-rw-r--r--lib/mktime.c663
-rw-r--r--lib/obstack.c431
-rw-r--r--lib/obstack.h513
-rw-r--r--lib/offtostr.c3
-rw-r--r--lib/open-safer.c50
-rw-r--r--lib/openat-die.c51
-rw-r--r--lib/openat-priv.h55
-rw-r--r--lib/openat-proc.c95
-rw-r--r--lib/openat.c270
-rw-r--r--lib/openat.h127
-rw-r--r--lib/pathmax.h47
-rw-r--r--lib/paxerror.c365
-rw-r--r--lib/paxexit.c (renamed from lib/exit.c)4
-rw-r--r--lib/paxlib.h4
-rw-r--r--lib/paxnames.c (renamed from lib/names.c)51
-rw-r--r--lib/pipe-safer.c57
-rw-r--r--lib/printf-args.c139
-rw-r--r--lib/printf-args.h132
-rw-r--r--lib/printf-parse.c543
-rw-r--r--lib/printf-parse.h74
-rw-r--r--lib/quote.c41
-rw-r--r--lib/quote.h22
-rw-r--r--lib/quotearg.c697
-rw-r--r--lib/quotearg.h140
-rw-r--r--lib/readlink.c50
-rw-r--r--lib/rmt-command.h4
-rw-r--r--lib/rmt.h6
-rw-r--r--lib/rtapelib.c20
-rw-r--r--lib/safe-read.c78
-rw-r--r--lib/safe-read.h35
-rw-r--r--lib/safe-write.c19
-rw-r--r--lib/safe-write.h25
-rw-r--r--lib/same-inode.h26
-rw-r--r--lib/save-cwd.c103
-rw-r--r--lib/save-cwd.h34
-rw-r--r--lib/savedir.c137
-rw-r--r--lib/savedir.h27
-rw-r--r--lib/setenv.c332
-rw-r--r--lib/setenv.h54
-rw-r--r--lib/sleep.c47
-rw-r--r--lib/stdbool_.h118
-rw-r--r--lib/stdint_.h512
-rw-r--r--lib/stdio_.h320
-rw-r--r--lib/stdlib_.h140
-rw-r--r--lib/stpcpy.c49
-rw-r--r--lib/strcasecmp.c63
-rw-r--r--lib/strchrnul.c32
-rw-r--r--lib/strdup.c55
-rw-r--r--lib/strerror.c57
-rw-r--r--lib/string_.h546
-rw-r--r--lib/stripslash.c45
-rw-r--r--lib/strncasecmp.c63
-rw-r--r--lib/strndup.c37
-rw-r--r--lib/strnlen.c31
-rw-r--r--lib/strtol.c436
-rw-r--r--lib/sys_stat_.h284
-rw-r--r--lib/sys_time_.h52
-rw-r--r--lib/sysdep.c190
-rw-r--r--lib/sysdep.h144
-rw-r--r--lib/sysexits_.h72
-rw-r--r--lib/system-ioctl.h4
-rw-r--r--lib/system.h14
-rw-r--r--lib/time_.h125
-rw-r--r--lib/time_r.c47
-rw-r--r--lib/timespec.h37
-rw-r--r--lib/uinttostr.c3
-rw-r--r--lib/umaxtostr.c3
-rw-r--r--lib/unistd--.h28
-rw-r--r--lib/unistd-safer.h23
-rw-r--r--lib/unistd_.h242
-rw-r--r--lib/unlocked-io.h137
-rw-r--r--lib/unsetenv.c92
-rw-r--r--lib/utimens.c189
-rw-r--r--lib/utimens.h3
-rw-r--r--lib/vasnprintf.c3193
-rw-r--r--lib/vasnprintf.h81
-rw-r--r--lib/verify.h141
-rw-r--r--lib/version-etc-fsf.c31
-rw-r--r--lib/version-etc.c173
-rw-r--r--lib/version-etc.h37
-rw-r--r--lib/vsnprintf.c76
-rw-r--r--lib/wchar_.h50
-rw-r--r--lib/wctype_.h165
-rw-r--r--lib/xalloc-die.c42
-rw-r--r--lib/xalloc.h271
-rw-r--r--lib/xgetcwd.c41
-rw-r--r--lib/xgetcwd.h18
-rw-r--r--lib/xmalloc.c123
-rw-r--r--lib/xsize.h108
-rw-r--r--lib/xstrndup.c37
-rw-r--r--lib/xstrndup.h24
184 files changed, 37115 insertions, 1365 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index d9a42a0..7a56237 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,40 +1,48 @@
-# Makefile for GNU tar library. -*- Makefile -*-
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004,
-# 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-noinst_LIBRARIES=libpax.a
-rmt-command.h : Makefile
- $(AM_V_GEN)rm -f $@-t $@
- $(AM_V_at)echo "#ifndef DEFAULT_RMT_COMMAND" >> $@-t
- $(AM_V_at)echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo rmt | sed '$(transform)'`$(EXEEXT)\"" >> $@-t
- $(AM_V_at)echo "#endif" >> $@-t
- $(AM_V_at)mv $@-t $@
-BUILT_SOURCES = rmt-command.h
-CLEANFILES = rmt-command.h rmt-command.h-t
-INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu
-
-noinst_HEADERS = system.h system-ioctl.h rmt.h paxlib.h
-libpax_a_SOURCES = \
- exit.c\
+# Makefile for GNU cpio library.
+
+# 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.
+
+include gnulib.mk
+
+noinst_HEADERS += \
paxlib.h\
- rtapelib.c\
- sysdep.h\
- sysdep.c\
- system.h\
- error.c\
- names.c
+ rmt.h\
+ rmt-command.h\
+ system-ioctl.h\
+ system.h
+
+libcpio_a_SOURCES += \
+ fatal.c\
+ paxerror.c\
+ paxexit.c\
+ paxlib.h\
+ paxnames.c\
+ rtapelib.c
+
+DISTCLEANFILES += rmt-command.h
+rmt-command.h: Makefile
+ echo '#define LOCALEDIR "$(localedir)"' >$@
+ echo "#ifndef DEFAULT_RMT_COMMAND" >> $@
+ echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo \"rmt\" | sed 's,^.*/,,;$(transform)'`$(EXEEXT)\"" >> $@
+ echo "#endif" >> $@
+
+BUILT_SOURCES += rmt-command.h
+CLEANFILES += rmt-command.h
+
+libcpio_a_LIBADD += $(LIBOBJS)
+libcpio_a_DEPENDENCIES += $(LIBOBJS)
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 808b411..be86cc7 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -1,9 +1,8 @@
-# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# Makefile.in generated by automake 1.10a from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
-# Inc.
+# 2003, 2004, 2005, 2006, 2007 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.
@@ -15,24 +14,21 @@
@SET_MAKE@
-# Makefile for GNU tar library. -*- Makefile -*-
+# Makefile for GNU cpio library.
-# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004,
-# 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
+# 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 3 of the License, or
-# (at your option) any later version.
+# Copyright (C) 2004-2007 Free Software Foundation, Inc.
+#
+# This file is free software, distributed under the terms of the GNU
+# General Public License. As a special exception to the GNU General
+# Public License, this file may be distributed as part of a program
+# that contains a configuration script generated by Autoconf, under
+# the same distribution terms as the rest of that program.
+#
+# Generated by gnulib-tool.
+# Reproduce by: gnulib-tool --import --dir=. --local-dir=gl --lib=libcpio --source-base=.#bootmp/lib --m4-base=.#bootmp/m4 --doc-base=.#bootmp/doc --aux-dir=.#bootmp/build-aux --avoid=lock --avoid=size_max --no-libtool --macro-prefix=gl alloca argmatch argp closeout configmake dirname error fileblocks fnmatch-gnu full-write getdate getopt gettext hash inttostr inttypes lchown obstack quote quotearg safe-read savedir stdbool stdint stpcpy strerror strtol unlocked-io utimens version-etc-fsf xalloc xalloc-die
-# 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 St, Fifth Floor, Boston, MA 02110-1301 USA
VPATH = @srcdir@
@@ -54,139 +50,129 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-subdir = lib
DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
- $(srcdir)/Makefile.in
+ $(srcdir)/Makefile.in $(srcdir)/gnulib.mk alloca.c getdate.c
+subdir = lib
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/am/flushleft.m4 \
- $(top_srcdir)/am/pack.m4 $(top_srcdir)/am/sysdep.m4 \
- $(top_srcdir)/m4/00gnulib.m4 $(top_srcdir)/m4/alloca.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \
+ $(top_srcdir)/m4/alloca.m4 $(top_srcdir)/m4/allocsa.m4 \
$(top_srcdir)/m4/argmatch.m4 $(top_srcdir)/m4/argp.m4 \
- $(top_srcdir)/m4/bison.m4 $(top_srcdir)/m4/chdir-long.m4 \
- $(top_srcdir)/m4/chown.m4 $(top_srcdir)/m4/clock_time.m4 \
- $(top_srcdir)/m4/close-stream.m4 $(top_srcdir)/m4/close.m4 \
- $(top_srcdir)/m4/closeout.m4 $(top_srcdir)/m4/codeset.m4 \
- $(top_srcdir)/m4/d-ino.m4 $(top_srcdir)/m4/dirent-safer.m4 \
- $(top_srcdir)/m4/dirent_h.m4 $(top_srcdir)/m4/dirfd.m4 \
+ $(top_srcdir)/m4/bison.m4 \
+ $(top_srcdir)/m4/canonicalize-lgpl.m4 \
+ $(top_srcdir)/m4/chdir-long.m4 $(top_srcdir)/m4/chown.m4 \
+ $(top_srcdir)/m4/clock_time.m4 \
+ $(top_srcdir)/m4/close-stream.m4 $(top_srcdir)/m4/closeout.m4 \
+ $(top_srcdir)/m4/d-ino.m4 $(top_srcdir)/m4/dirfd.m4 \
$(top_srcdir)/m4/dirname.m4 $(top_srcdir)/m4/dos.m4 \
$(top_srcdir)/m4/double-slash-root.m4 $(top_srcdir)/m4/dup2.m4 \
- $(top_srcdir)/m4/eealloc.m4 $(top_srcdir)/m4/environ.m4 \
- $(top_srcdir)/m4/errno_h.m4 $(top_srcdir)/m4/error.m4 \
+ $(top_srcdir)/m4/eealloc.m4 $(top_srcdir)/m4/eoverflow.m4 \
+ $(top_srcdir)/m4/error.m4 $(top_srcdir)/m4/exitfail.m4 \
$(top_srcdir)/m4/extensions.m4 $(top_srcdir)/m4/fchdir.m4 \
- $(top_srcdir)/m4/fclose.m4 $(top_srcdir)/m4/fcntl-o.m4 \
- $(top_srcdir)/m4/fcntl.m4 $(top_srcdir)/m4/fcntl_h.m4 \
- $(top_srcdir)/m4/fdopendir.m4 $(top_srcdir)/m4/fileblocks.m4 \
- $(top_srcdir)/m4/float_h.m4 $(top_srcdir)/m4/fnmatch.m4 \
- $(top_srcdir)/m4/fpending.m4 $(top_srcdir)/m4/fseeko.m4 \
+ $(top_srcdir)/m4/fcntl-safer.m4 $(top_srcdir)/m4/fcntl_h.m4 \
+ $(top_srcdir)/m4/fileblocks.m4 $(top_srcdir)/m4/float_h.m4 \
+ $(top_srcdir)/m4/fnmatch.m4 $(top_srcdir)/m4/fpending.m4 \
$(top_srcdir)/m4/getcwd-abort-bug.m4 \
$(top_srcdir)/m4/getcwd-path-max.m4 $(top_srcdir)/m4/getcwd.m4 \
- $(top_srcdir)/m4/getdate.m4 $(top_srcdir)/m4/getdtablesize.m4 \
- $(top_srcdir)/m4/getopt.m4 $(top_srcdir)/m4/gettext.m4 \
- $(top_srcdir)/m4/gettime.m4 $(top_srcdir)/m4/gettimeofday.m4 \
- $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnulib-common.m4 \
+ $(top_srcdir)/m4/getdate.m4 $(top_srcdir)/m4/getopt.m4 \
+ $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/gettime.m4 \
+ $(top_srcdir)/m4/gettimeofday.m4 \
+ $(top_srcdir)/m4/gnulib-common.m4 \
$(top_srcdir)/m4/gnulib-comp.m4 $(top_srcdir)/m4/hash.m4 \
- $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/include_next.m4 \
- $(top_srcdir)/m4/inline.m4 $(top_srcdir)/m4/intlmacosx.m4 \
+ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/inline.m4 \
$(top_srcdir)/m4/intmax_t.m4 $(top_srcdir)/m4/inttostr.m4 \
$(top_srcdir)/m4/inttypes-pri.m4 $(top_srcdir)/m4/inttypes.m4 \
$(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lchown.m4 \
$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
- $(top_srcdir)/m4/lib-prefix.m4 \
- $(top_srcdir)/m4/localcharset.m4 $(top_srcdir)/m4/locale-fr.m4 \
- $(top_srcdir)/m4/locale-ja.m4 $(top_srcdir)/m4/locale-zh.m4 \
- $(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/lseek.m4 \
- $(top_srcdir)/m4/lstat.m4 $(top_srcdir)/m4/malloc.m4 \
- $(top_srcdir)/m4/malloca.m4 $(top_srcdir)/m4/mbrtowc.m4 \
- $(top_srcdir)/m4/mbsinit.m4 $(top_srcdir)/m4/mbsrtowcs.m4 \
- $(top_srcdir)/m4/mbstate_t.m4 $(top_srcdir)/m4/memchr.m4 \
- $(top_srcdir)/m4/mempcpy.m4 $(top_srcdir)/m4/memrchr.m4 \
- $(top_srcdir)/m4/mkdir.m4 $(top_srcdir)/m4/mktime.m4 \
- $(top_srcdir)/m4/mmap-anon.m4 $(top_srcdir)/m4/mode_t.m4 \
- $(top_srcdir)/m4/multiarch.m4 $(top_srcdir)/m4/nls.m4 \
- $(top_srcdir)/m4/open.m4 $(top_srcdir)/m4/openat.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/longlong.m4 \
+ $(top_srcdir)/m4/lstat.m4 $(top_srcdir)/m4/mbrtowc.m4 \
+ $(top_srcdir)/m4/mbstate_t.m4 $(top_srcdir)/m4/mempcpy.m4 \
+ $(top_srcdir)/m4/memrchr.m4 $(top_srcdir)/m4/mktime.m4 \
+ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/onceonly_2_57.m4 \
+ $(top_srcdir)/m4/openat.m4 $(top_srcdir)/m4/pathmax.m4 \
$(top_srcdir)/m4/paxutils.m4 $(top_srcdir)/m4/po.m4 \
- $(top_srcdir)/m4/printf.m4 $(top_srcdir)/m4/progtest.m4 \
- $(top_srcdir)/m4/quote.m4 $(top_srcdir)/m4/quotearg.m4 \
- $(top_srcdir)/m4/rawmemchr.m4 $(top_srcdir)/m4/realloc.m4 \
- $(top_srcdir)/m4/rmdir.m4 $(top_srcdir)/m4/rmt.m4 \
- $(top_srcdir)/m4/rtapelib.m4 $(top_srcdir)/m4/safe-read.m4 \
- $(top_srcdir)/m4/safe-write.m4 $(top_srcdir)/m4/save-cwd.m4 \
- $(top_srcdir)/m4/savedir.m4 $(top_srcdir)/m4/setenv.m4 \
- $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/sleep.m4 \
- $(top_srcdir)/m4/ssize_t.m4 $(top_srcdir)/m4/stat-time.m4 \
- $(top_srcdir)/m4/stat.m4 $(top_srcdir)/m4/stdarg.m4 \
- $(top_srcdir)/m4/stdbool.m4 $(top_srcdir)/m4/stddef_h.m4 \
+ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/quote.m4 \
+ $(top_srcdir)/m4/quotearg.m4 $(top_srcdir)/m4/readlink.m4 \
+ $(top_srcdir)/m4/rmt.m4 $(top_srcdir)/m4/rtapelib.m4 \
+ $(top_srcdir)/m4/safe-read.m4 $(top_srcdir)/m4/safe-write.m4 \
+ $(top_srcdir)/m4/save-cwd.m4 $(top_srcdir)/m4/savedir.m4 \
+ $(top_srcdir)/m4/setenv.m4 $(top_srcdir)/m4/size_max.m4 \
+ $(top_srcdir)/m4/sleep.m4 $(top_srcdir)/m4/ssize_t.m4 \
+ $(top_srcdir)/m4/stdarg.m4 $(top_srcdir)/m4/stdbool.m4 \
$(top_srcdir)/m4/stdint.m4 $(top_srcdir)/m4/stdint_h.m4 \
$(top_srcdir)/m4/stdio_h.m4 $(top_srcdir)/m4/stdlib_h.m4 \
$(top_srcdir)/m4/stpcpy.m4 $(top_srcdir)/m4/strcase.m4 \
$(top_srcdir)/m4/strchrnul.m4 $(top_srcdir)/m4/strdup.m4 \
$(top_srcdir)/m4/strerror.m4 $(top_srcdir)/m4/string_h.m4 \
- $(top_srcdir)/m4/strings_h.m4 $(top_srcdir)/m4/strndup.m4 \
- $(top_srcdir)/m4/strnlen.m4 $(top_srcdir)/m4/strtol.m4 \
- $(top_srcdir)/m4/sys_stat_h.m4 $(top_srcdir)/m4/sys_time_h.m4 \
- $(top_srcdir)/m4/sysexits.m4 $(top_srcdir)/m4/system.m4 \
- $(top_srcdir)/m4/time_h.m4 $(top_srcdir)/m4/time_r.m4 \
- $(top_srcdir)/m4/timespec.m4 $(top_srcdir)/m4/tm_gmtoff.m4 \
+ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/strnlen.m4 \
+ $(top_srcdir)/m4/strtol.m4 $(top_srcdir)/m4/sys_stat_h.m4 \
+ $(top_srcdir)/m4/sys_time_h.m4 $(top_srcdir)/m4/sysexits.m4 \
+ $(top_srcdir)/m4/system.m4 $(top_srcdir)/m4/time_h.m4 \
+ $(top_srcdir)/m4/time_r.m4 $(top_srcdir)/m4/timespec.m4 \
+ $(top_srcdir)/m4/tm_gmtoff.m4 $(top_srcdir)/m4/ulonglong.m4 \
$(top_srcdir)/m4/unistd-safer.m4 $(top_srcdir)/m4/unistd_h.m4 \
- $(top_srcdir)/m4/unlink.m4 $(top_srcdir)/m4/unlocked-io.m4 \
- $(top_srcdir)/m4/utimbuf.m4 $(top_srcdir)/m4/utimens.m4 \
- $(top_srcdir)/m4/utimes.m4 $(top_srcdir)/m4/vasnprintf.m4 \
- $(top_srcdir)/m4/version-etc.m4 $(top_srcdir)/m4/vsnprintf.m4 \
- $(top_srcdir)/m4/warn-on-use.m4 $(top_srcdir)/m4/wchar_h.m4 \
- $(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wctype_h.m4 \
- $(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/write.m4 \
+ $(top_srcdir)/m4/unlocked-io.m4 $(top_srcdir)/m4/utimbuf.m4 \
+ $(top_srcdir)/m4/utimens.m4 $(top_srcdir)/m4/utimes.m4 \
+ $(top_srcdir)/m4/vasnprintf.m4 $(top_srcdir)/m4/vsnprintf.m4 \
+ $(top_srcdir)/m4/wchar.m4 $(top_srcdir)/m4/wchar_t.m4 \
+ $(top_srcdir)/m4/wctype.m4 $(top_srcdir)/m4/wint_t.m4 \
$(top_srcdir)/m4/xalloc.m4 $(top_srcdir)/m4/xgetcwd.m4 \
$(top_srcdir)/m4/xsize.m4 $(top_srcdir)/m4/xstrndup.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
LIBRARIES = $(noinst_LIBRARIES)
AR = ar
ARFLAGS = cru
-AM_V_AR = $(am__v_AR_$(V))
-am__v_AR_ = $(am__v_AR_$(AM_DEFAULT_VERBOSITY))
-am__v_AR_0 = @echo " AR " $@;
-AM_V_at = $(am__v_at_$(V))
-am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
-am__v_at_0 = @
-libpax_a_AR = $(AR) $(ARFLAGS)
-libpax_a_LIBADD =
-am_libpax_a_OBJECTS = exit.$(OBJEXT) rtapelib.$(OBJEXT) \
- sysdep.$(OBJEXT) error.$(OBJEXT) names.$(OBJEXT)
-libpax_a_OBJECTS = $(am_libpax_a_OBJECTS)
-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+libcpio_a_AR = $(AR) $(ARFLAGS)
+am__DEPENDENCIES_1 =
+am_libcpio_a_OBJECTS = allocsa.$(OBJEXT) argp-ba.$(OBJEXT) \
+ argp-eexst.$(OBJEXT) argp-fmtstream.$(OBJEXT) \
+ argp-fs-xinl.$(OBJEXT) argp-help.$(OBJEXT) \
+ argp-parse.$(OBJEXT) argp-pin.$(OBJEXT) argp-pv.$(OBJEXT) \
+ argp-pvh.$(OBJEXT) argp-xinl.$(OBJEXT) full-write.$(OBJEXT) \
+ getdate.$(OBJEXT) openat-die.$(OBJEXT) version-etc.$(OBJEXT) \
+ version-etc-fsf.$(OBJEXT) xalloc-die.$(OBJEXT) \
+ xstrndup.$(OBJEXT) fatal.$(OBJEXT) paxerror.$(OBJEXT) \
+ paxexit.$(OBJEXT) paxnames.$(OBJEXT) rtapelib.$(OBJEXT)
+libcpio_a_OBJECTS = $(am_libcpio_a_OBJECTS)
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__depfiles_maybe = depfiles
-am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_$(V))
-am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
-am__v_CC_0 = @echo " CC " $@;
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_$(V))
-am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
-am__v_CCLD_0 = @echo " CCLD " $@;
-AM_V_GEN = $(am__v_GEN_$(V))
-am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
-am__v_GEN_0 = @echo " GEN " $@;
-SOURCES = $(libpax_a_SOURCES)
-DIST_SOURCES = $(libpax_a_SOURCES)
+YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS)
+YLWRAP = $(top_srcdir)/build-aux/ylwrap
+SOURCES = $(libcpio_a_SOURCES) $(EXTRA_libcpio_a_SOURCES)
+DIST_SOURCES = $(libcpio_a_SOURCES) $(EXTRA_libcpio_a_SOURCES)
HEADERS = $(noinst_HEADERS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ABSOLUTE_DIRENT_H = @ABSOLUTE_DIRENT_H@
+ABSOLUTE_FCNTL_H = @ABSOLUTE_FCNTL_H@
+ABSOLUTE_FLOAT_H = @ABSOLUTE_FLOAT_H@
+ABSOLUTE_INTTYPES_H = @ABSOLUTE_INTTYPES_H@
+ABSOLUTE_STDINT_H = @ABSOLUTE_STDINT_H@
+ABSOLUTE_STDIO_H = @ABSOLUTE_STDIO_H@
+ABSOLUTE_STDLIB_H = @ABSOLUTE_STDLIB_H@
+ABSOLUTE_STRING_H = @ABSOLUTE_STRING_H@
+ABSOLUTE_SYSEXITS_H = @ABSOLUTE_SYSEXITS_H@
+ABSOLUTE_SYS_STAT_H = @ABSOLUTE_SYS_STAT_H@
+ABSOLUTE_SYS_TIME_H = @ABSOLUTE_SYS_TIME_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@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-APPLE_UNIVERSAL_BUILD = @APPLE_UNIVERSAL_BUILD@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOM4TE = @AUTOM4TE@
@@ -208,291 +194,104 @@ DEFAULT_RMT_COMMAND = @DEFAULT_RMT_COMMAND@
DEFAULT_RMT_DIR = @DEFAULT_RMT_DIR@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
+DIRENT_H = @DIRENT_H@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
-EMULTIHOP_HIDDEN = @EMULTIHOP_HIDDEN@
-EMULTIHOP_VALUE = @EMULTIHOP_VALUE@
-ENOLINK_HIDDEN = @ENOLINK_HIDDEN@
-ENOLINK_VALUE = @ENOLINK_VALUE@
-EOVERFLOW_HIDDEN = @EOVERFLOW_HIDDEN@
-EOVERFLOW_VALUE = @EOVERFLOW_VALUE@
-ERRNO_H = @ERRNO_H@
+EOVERFLOW = @EOVERFLOW@
EXEEXT = @EXEEXT@
+FCNTL_H = @FCNTL_H@
FLOAT_H = @FLOAT_H@
FNMATCH_H = @FNMATCH_H@
GETOPT_H = @GETOPT_H@
-GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
-GLIBC21 = @GLIBC21@
GMSGFMT = @GMSGFMT@
GMSGFMT_015 = @GMSGFMT_015@
-GNULIB_ALPHASORT = @GNULIB_ALPHASORT@
-GNULIB_ATOLL = @GNULIB_ATOLL@
-GNULIB_BTOWC = @GNULIB_BTOWC@
-GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@
-GNULIB_CANONICALIZE_FILE_NAME = @GNULIB_CANONICALIZE_FILE_NAME@
GNULIB_CHOWN = @GNULIB_CHOWN@
-GNULIB_CLOSE = @GNULIB_CLOSE@
-GNULIB_DIRFD = @GNULIB_DIRFD@
-GNULIB_DPRINTF = @GNULIB_DPRINTF@
GNULIB_DUP2 = @GNULIB_DUP2@
-GNULIB_DUP3 = @GNULIB_DUP3@
-GNULIB_ENVIRON = @GNULIB_ENVIRON@
-GNULIB_EUIDACCESS = @GNULIB_EUIDACCESS@
-GNULIB_FACCESSAT = @GNULIB_FACCESSAT@
GNULIB_FCHDIR = @GNULIB_FCHDIR@
-GNULIB_FCHMODAT = @GNULIB_FCHMODAT@
-GNULIB_FCHOWNAT = @GNULIB_FCHOWNAT@
-GNULIB_FCLOSE = @GNULIB_FCLOSE@
-GNULIB_FCNTL = @GNULIB_FCNTL@
-GNULIB_FDOPENDIR = @GNULIB_FDOPENDIR@
GNULIB_FFLUSH = @GNULIB_FFLUSH@
-GNULIB_FOPEN = @GNULIB_FOPEN@
-GNULIB_FPRINTF = @GNULIB_FPRINTF@
GNULIB_FPRINTF_POSIX = @GNULIB_FPRINTF_POSIX@
-GNULIB_FPURGE = @GNULIB_FPURGE@
-GNULIB_FPUTC = @GNULIB_FPUTC@
-GNULIB_FPUTS = @GNULIB_FPUTS@
-GNULIB_FREOPEN = @GNULIB_FREOPEN@
GNULIB_FSEEK = @GNULIB_FSEEK@
GNULIB_FSEEKO = @GNULIB_FSEEKO@
-GNULIB_FSTATAT = @GNULIB_FSTATAT@
-GNULIB_FSYNC = @GNULIB_FSYNC@
GNULIB_FTELL = @GNULIB_FTELL@
GNULIB_FTELLO = @GNULIB_FTELLO@
GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@
-GNULIB_FUTIMENS = @GNULIB_FUTIMENS@
-GNULIB_FWRITE = @GNULIB_FWRITE@
GNULIB_GETCWD = @GNULIB_GETCWD@
-GNULIB_GETDELIM = @GNULIB_GETDELIM@
-GNULIB_GETDOMAINNAME = @GNULIB_GETDOMAINNAME@
-GNULIB_GETDTABLESIZE = @GNULIB_GETDTABLESIZE@
-GNULIB_GETGROUPS = @GNULIB_GETGROUPS@
-GNULIB_GETHOSTNAME = @GNULIB_GETHOSTNAME@
-GNULIB_GETLINE = @GNULIB_GETLINE@
-GNULIB_GETLOADAVG = @GNULIB_GETLOADAVG@
-GNULIB_GETLOGIN = @GNULIB_GETLOGIN@
GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@
-GNULIB_GETPAGESIZE = @GNULIB_GETPAGESIZE@
GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@
-GNULIB_GETTIMEOFDAY = @GNULIB_GETTIMEOFDAY@
-GNULIB_GETUSERSHELL = @GNULIB_GETUSERSHELL@
GNULIB_IMAXABS = @GNULIB_IMAXABS@
GNULIB_IMAXDIV = @GNULIB_IMAXDIV@
-GNULIB_LCHMOD = @GNULIB_LCHMOD@
-GNULIB_LCHOWN = @GNULIB_LCHOWN@
-GNULIB_LINK = @GNULIB_LINK@
-GNULIB_LINKAT = @GNULIB_LINKAT@
GNULIB_LSEEK = @GNULIB_LSEEK@
-GNULIB_LSTAT = @GNULIB_LSTAT@
-GNULIB_MALLOC_POSIX = @GNULIB_MALLOC_POSIX@
-GNULIB_MBRLEN = @GNULIB_MBRLEN@
-GNULIB_MBRTOWC = @GNULIB_MBRTOWC@
GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@
GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@
GNULIB_MBSCHR = @GNULIB_MBSCHR@
GNULIB_MBSCSPN = @GNULIB_MBSCSPN@
-GNULIB_MBSINIT = @GNULIB_MBSINIT@
GNULIB_MBSLEN = @GNULIB_MBSLEN@
GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@
-GNULIB_MBSNLEN = @GNULIB_MBSNLEN@
-GNULIB_MBSNRTOWCS = @GNULIB_MBSNRTOWCS@
GNULIB_MBSPBRK = @GNULIB_MBSPBRK@
GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@
GNULIB_MBSRCHR = @GNULIB_MBSRCHR@
-GNULIB_MBSRTOWCS = @GNULIB_MBSRTOWCS@
GNULIB_MBSSEP = @GNULIB_MBSSEP@
GNULIB_MBSSPN = @GNULIB_MBSSPN@
GNULIB_MBSSTR = @GNULIB_MBSSTR@
GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@
-GNULIB_MEMCHR = @GNULIB_MEMCHR@
GNULIB_MEMMEM = @GNULIB_MEMMEM@
GNULIB_MEMPCPY = @GNULIB_MEMPCPY@
GNULIB_MEMRCHR = @GNULIB_MEMRCHR@
-GNULIB_MKDIRAT = @GNULIB_MKDIRAT@
GNULIB_MKDTEMP = @GNULIB_MKDTEMP@
-GNULIB_MKFIFO = @GNULIB_MKFIFO@
-GNULIB_MKFIFOAT = @GNULIB_MKFIFOAT@
-GNULIB_MKNOD = @GNULIB_MKNOD@
-GNULIB_MKNODAT = @GNULIB_MKNODAT@
-GNULIB_MKOSTEMP = @GNULIB_MKOSTEMP@
-GNULIB_MKOSTEMPS = @GNULIB_MKOSTEMPS@
GNULIB_MKSTEMP = @GNULIB_MKSTEMP@
-GNULIB_MKSTEMPS = @GNULIB_MKSTEMPS@
-GNULIB_MKTIME = @GNULIB_MKTIME@
-GNULIB_NANOSLEEP = @GNULIB_NANOSLEEP@
-GNULIB_OBSTACK_PRINTF = @GNULIB_OBSTACK_PRINTF@
-GNULIB_OBSTACK_PRINTF_POSIX = @GNULIB_OBSTACK_PRINTF_POSIX@
-GNULIB_OPEN = @GNULIB_OPEN@
-GNULIB_OPENAT = @GNULIB_OPENAT@
-GNULIB_PERROR = @GNULIB_PERROR@
-GNULIB_PIPE2 = @GNULIB_PIPE2@
-GNULIB_POPEN = @GNULIB_POPEN@
-GNULIB_PREAD = @GNULIB_PREAD@
-GNULIB_PRINTF = @GNULIB_PRINTF@
GNULIB_PRINTF_POSIX = @GNULIB_PRINTF_POSIX@
-GNULIB_PUTC = @GNULIB_PUTC@
-GNULIB_PUTCHAR = @GNULIB_PUTCHAR@
-GNULIB_PUTENV = @GNULIB_PUTENV@
-GNULIB_PUTS = @GNULIB_PUTS@
-GNULIB_RANDOM_R = @GNULIB_RANDOM_R@
-GNULIB_RAWMEMCHR = @GNULIB_RAWMEMCHR@
GNULIB_READLINK = @GNULIB_READLINK@
-GNULIB_READLINKAT = @GNULIB_READLINKAT@
-GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@
-GNULIB_REALPATH = @GNULIB_REALPATH@
-GNULIB_REMOVE = @GNULIB_REMOVE@
-GNULIB_RENAME = @GNULIB_RENAME@
-GNULIB_RENAMEAT = @GNULIB_RENAMEAT@
-GNULIB_RMDIR = @GNULIB_RMDIR@
-GNULIB_RPMATCH = @GNULIB_RPMATCH@
-GNULIB_SCANDIR = @GNULIB_SCANDIR@
-GNULIB_SETENV = @GNULIB_SETENV@
GNULIB_SLEEP = @GNULIB_SLEEP@
GNULIB_SNPRINTF = @GNULIB_SNPRINTF@
GNULIB_SPRINTF_POSIX = @GNULIB_SPRINTF_POSIX@
-GNULIB_STAT = @GNULIB_STAT@
-GNULIB_STDIO_H_SIGPIPE = @GNULIB_STDIO_H_SIGPIPE@
GNULIB_STPCPY = @GNULIB_STPCPY@
GNULIB_STPNCPY = @GNULIB_STPNCPY@
GNULIB_STRCASESTR = @GNULIB_STRCASESTR@
GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@
GNULIB_STRDUP = @GNULIB_STRDUP@
-GNULIB_STRERROR = @GNULIB_STRERROR@
GNULIB_STRNDUP = @GNULIB_STRNDUP@
GNULIB_STRNLEN = @GNULIB_STRNLEN@
GNULIB_STRPBRK = @GNULIB_STRPBRK@
-GNULIB_STRPTIME = @GNULIB_STRPTIME@
GNULIB_STRSEP = @GNULIB_STRSEP@
-GNULIB_STRSIGNAL = @GNULIB_STRSIGNAL@
-GNULIB_STRSTR = @GNULIB_STRSTR@
-GNULIB_STRTOD = @GNULIB_STRTOD@
GNULIB_STRTOIMAX = @GNULIB_STRTOIMAX@
GNULIB_STRTOK_R = @GNULIB_STRTOK_R@
-GNULIB_STRTOLL = @GNULIB_STRTOLL@
-GNULIB_STRTOULL = @GNULIB_STRTOULL@
GNULIB_STRTOUMAX = @GNULIB_STRTOUMAX@
-GNULIB_STRVERSCMP = @GNULIB_STRVERSCMP@
-GNULIB_SYMLINK = @GNULIB_SYMLINK@
-GNULIB_SYMLINKAT = @GNULIB_SYMLINKAT@
-GNULIB_TIMEGM = @GNULIB_TIMEGM@
-GNULIB_UNISTD_H_GETOPT = @GNULIB_UNISTD_H_GETOPT@
-GNULIB_UNISTD_H_SIGPIPE = @GNULIB_UNISTD_H_SIGPIPE@
-GNULIB_UNLINK = @GNULIB_UNLINK@
-GNULIB_UNLINKAT = @GNULIB_UNLINKAT@
-GNULIB_UNSETENV = @GNULIB_UNSETENV@
-GNULIB_USLEEP = @GNULIB_USLEEP@
-GNULIB_UTIMENSAT = @GNULIB_UTIMENSAT@
GNULIB_VASPRINTF = @GNULIB_VASPRINTF@
-GNULIB_VDPRINTF = @GNULIB_VDPRINTF@
-GNULIB_VFPRINTF = @GNULIB_VFPRINTF@
GNULIB_VFPRINTF_POSIX = @GNULIB_VFPRINTF_POSIX@
-GNULIB_VPRINTF = @GNULIB_VPRINTF@
GNULIB_VPRINTF_POSIX = @GNULIB_VPRINTF_POSIX@
GNULIB_VSNPRINTF = @GNULIB_VSNPRINTF@
GNULIB_VSPRINTF_POSIX = @GNULIB_VSPRINTF_POSIX@
-GNULIB_WCRTOMB = @GNULIB_WCRTOMB@
-GNULIB_WCSNRTOMBS = @GNULIB_WCSNRTOMBS@
-GNULIB_WCSRTOMBS = @GNULIB_WCSRTOMBS@
-GNULIB_WCTOB = @GNULIB_WCTOB@
-GNULIB_WCWIDTH = @GNULIB_WCWIDTH@
-GNULIB_WRITE = @GNULIB_WRITE@
GREP = @GREP@
-HAVE_ALPHASORT = @HAVE_ALPHASORT@
-HAVE_ATOLL = @HAVE_ATOLL@
-HAVE_BTOWC = @HAVE_BTOWC@
-HAVE_CALLOC_POSIX = @HAVE_CALLOC_POSIX@
-HAVE_CANONICALIZE_FILE_NAME = @HAVE_CANONICALIZE_FILE_NAME@
-HAVE_CHOWN = @HAVE_CHOWN@
-HAVE_DECL_DIRFD = @HAVE_DECL_DIRFD@
-HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@
-HAVE_DECL_FPURGE = @HAVE_DECL_FPURGE@
-HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@
-HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@
-HAVE_DECL_GETLOADAVG = @HAVE_DECL_GETLOADAVG@
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_OBSTACK_PRINTF = @HAVE_DECL_OBSTACK_PRINTF@
+HAVE_DECL_MKDIR = @HAVE_DECL_MKDIR@
HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@
HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@
-HAVE_DECL_STRERROR = @HAVE_DECL_STRERROR@
HAVE_DECL_STRNCASECMP = @HAVE_DECL_STRNCASECMP@
HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@
HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@
-HAVE_DECL_STRSIGNAL = @HAVE_DECL_STRSIGNAL@
HAVE_DECL_STRTOIMAX = @HAVE_DECL_STRTOIMAX@
HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@
HAVE_DECL_STRTOUMAX = @HAVE_DECL_STRTOUMAX@
HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@
-HAVE_DECL_WCTOB = @HAVE_DECL_WCTOB@
-HAVE_DECL_WCWIDTH = @HAVE_DECL_WCWIDTH@
-HAVE_DPRINTF = @HAVE_DPRINTF@
HAVE_DUP2 = @HAVE_DUP2@
-HAVE_DUP3 = @HAVE_DUP3@
-HAVE_EUIDACCESS = @HAVE_EUIDACCESS@
-HAVE_FACCESSAT = @HAVE_FACCESSAT@
-HAVE_FCHMODAT = @HAVE_FCHMODAT@
-HAVE_FCHOWNAT = @HAVE_FCHOWNAT@
-HAVE_FCNTL = @HAVE_FCNTL@
-HAVE_FDOPENDIR = @HAVE_FDOPENDIR@
-HAVE_FSTATAT = @HAVE_FSTATAT@
-HAVE_FSYNC = @HAVE_FSYNC@
+HAVE_FSEEKO = @HAVE_FSEEKO@
+HAVE_FTELLO = @HAVE_FTELLO@
HAVE_FTRUNCATE = @HAVE_FTRUNCATE@
-HAVE_FUTIMENS = @HAVE_FUTIMENS@
-HAVE_GETDOMAINNAME = @HAVE_GETDOMAINNAME@
-HAVE_GETDTABLESIZE = @HAVE_GETDTABLESIZE@
-HAVE_GETGROUPS = @HAVE_GETGROUPS@
-HAVE_GETHOSTNAME = @HAVE_GETHOSTNAME@
-HAVE_GETLOGIN = @HAVE_GETLOGIN@
-HAVE_GETOPT_H = @HAVE_GETOPT_H@
-HAVE_GETPAGESIZE = @HAVE_GETPAGESIZE@
HAVE_GETSUBOPT = @HAVE_GETSUBOPT@
-HAVE_GETTIMEOFDAY = @HAVE_GETTIMEOFDAY@
-HAVE_GETUSERSHELL = @HAVE_GETUSERSHELL@
HAVE_INTTYPES_H = @HAVE_INTTYPES_H@
+HAVE_IO_H = @HAVE_IO_H@
HAVE_ISWCNTRL = @HAVE_ISWCNTRL@
-HAVE_LCHMOD = @HAVE_LCHMOD@
-HAVE_LCHOWN = @HAVE_LCHOWN@
-HAVE_LINK = @HAVE_LINK@
-HAVE_LINKAT = @HAVE_LINKAT@
HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@
HAVE_LSTAT = @HAVE_LSTAT@
-HAVE_MALLOC_POSIX = @HAVE_MALLOC_POSIX@
-HAVE_MBRLEN = @HAVE_MBRLEN@
-HAVE_MBRTOWC = @HAVE_MBRTOWC@
-HAVE_MBSINIT = @HAVE_MBSINIT@
-HAVE_MBSLEN = @HAVE_MBSLEN@
-HAVE_MBSNRTOWCS = @HAVE_MBSNRTOWCS@
-HAVE_MBSRTOWCS = @HAVE_MBSRTOWCS@
HAVE_MEMPCPY = @HAVE_MEMPCPY@
-HAVE_MKDIRAT = @HAVE_MKDIRAT@
HAVE_MKDTEMP = @HAVE_MKDTEMP@
-HAVE_MKFIFO = @HAVE_MKFIFO@
-HAVE_MKFIFOAT = @HAVE_MKFIFOAT@
-HAVE_MKNOD = @HAVE_MKNOD@
-HAVE_MKNODAT = @HAVE_MKNODAT@
-HAVE_MKOSTEMP = @HAVE_MKOSTEMP@
-HAVE_MKOSTEMPS = @HAVE_MKOSTEMPS@
-HAVE_MKSTEMPS = @HAVE_MKSTEMPS@
-HAVE_OPENAT = @HAVE_OPENAT@
-HAVE_OS_H = @HAVE_OS_H@
-HAVE_PIPE2 = @HAVE_PIPE2@
-HAVE_PREAD = @HAVE_PREAD@
-HAVE_RANDOM_H = @HAVE_RANDOM_H@
-HAVE_RANDOM_R = @HAVE_RANDOM_R@
-HAVE_RAWMEMCHR = @HAVE_RAWMEMCHR@
HAVE_READLINK = @HAVE_READLINK@
-HAVE_READLINKAT = @HAVE_READLINKAT@
-HAVE_REALLOC_POSIX = @HAVE_REALLOC_POSIX@
-HAVE_REALPATH = @HAVE_REALPATH@
-HAVE_RENAMEAT = @HAVE_RENAMEAT@
-HAVE_RPMATCH = @HAVE_RPMATCH@
-HAVE_SCANDIR = @HAVE_SCANDIR@
-HAVE_SETENV = @HAVE_SETENV@
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@
@@ -503,63 +302,38 @@ 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_STRTOD = @HAVE_STRTOD@
-HAVE_STRTOLL = @HAVE_STRTOLL@
-HAVE_STRTOULL = @HAVE_STRTOULL@
-HAVE_STRUCT_RANDOM_DATA = @HAVE_STRUCT_RANDOM_DATA@
HAVE_STRUCT_TIMEVAL = @HAVE_STRUCT_TIMEVAL@
-HAVE_STRVERSCMP = @HAVE_STRVERSCMP@
-HAVE_SYMLINK = @HAVE_SYMLINK@
-HAVE_SYMLINKAT = @HAVE_SYMLINKAT@
HAVE_SYSEXITS_H = @HAVE_SYSEXITS_H@
HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@
HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@
-HAVE_SYS_LOADAVG_H = @HAVE_SYS_LOADAVG_H@
-HAVE_SYS_PARAM_H = @HAVE_SYS_PARAM_H@
HAVE_SYS_TIME_H = @HAVE_SYS_TIME_H@
HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@
HAVE_UNISTD_H = @HAVE_UNISTD_H@
-HAVE_UNLINKAT = @HAVE_UNLINKAT@
-HAVE_UNSETENV = @HAVE_UNSETENV@
HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@
-HAVE_USLEEP = @HAVE_USLEEP@
-HAVE_UTIMENSAT = @HAVE_UTIMENSAT@
HAVE_VASPRINTF = @HAVE_VASPRINTF@
-HAVE_VDPRINTF = @HAVE_VDPRINTF@
-HAVE_WCHAR_H = @HAVE_WCHAR_H@
-HAVE_WCHAR_T = @HAVE_WCHAR_T@
-HAVE_WCRTOMB = @HAVE_WCRTOMB@
-HAVE_WCSNRTOMBS = @HAVE_WCSNRTOMBS@
-HAVE_WCSRTOMBS = @HAVE_WCSRTOMBS@
HAVE_WCTYPE_H = @HAVE_WCTYPE_H@
HAVE_WINT_T = @HAVE_WINT_T@
HAVE__BOOL = @HAVE__BOOL@
-INCLUDE_NEXT = @INCLUDE_NEXT@
-INCLUDE_NEXT_AS_FIRST_DIRECTIVE = @INCLUDE_NEXT_AS_FIRST_DIRECTIVE@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-INT32_MAX_LT_INTMAX_MAX = @INT32_MAX_LT_INTMAX_MAX@
-INT64_MAX_EQ_LONG_MAX = @INT64_MAX_EQ_LONG_MAX@
INTLLIBS = @INTLLIBS@
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+INTTYPES_H = @INTTYPES_H@
LDFLAGS = @LDFLAGS@
-LIBGNU_LIBDEPS = @LIBGNU_LIBDEPS@
-LIBGNU_LTLIBDEPS = @LIBGNU_LTLIBDEPS@
+LIBCPIO_LIBDEPS = @LIBCPIO_LIBDEPS@
+LIBCPIO_LTLIBDEPS = @LIBCPIO_LTLIBDEPS@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@
LIB_SETSOCKOPT = @LIB_SETSOCKOPT@
-LOCALCHARSET_TESTS_ENVIRONMENT = @LOCALCHARSET_TESTS_ENVIRONMENT@
-LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@
-LOCALE_JA = @LOCALE_JA@
-LOCALE_ZH_CN = @LOCALE_ZH_CN@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
@@ -568,46 +342,6 @@ MKDIR_P = @MKDIR_P@
MSGFMT = @MSGFMT@
MSGFMT_015 = @MSGFMT_015@
MSGMERGE = @MSGMERGE@
-NEXT_AS_FIRST_DIRECTIVE_DIRENT_H = @NEXT_AS_FIRST_DIRECTIVE_DIRENT_H@
-NEXT_AS_FIRST_DIRECTIVE_ERRNO_H = @NEXT_AS_FIRST_DIRECTIVE_ERRNO_H@
-NEXT_AS_FIRST_DIRECTIVE_FCNTL_H = @NEXT_AS_FIRST_DIRECTIVE_FCNTL_H@
-NEXT_AS_FIRST_DIRECTIVE_FLOAT_H = @NEXT_AS_FIRST_DIRECTIVE_FLOAT_H@
-NEXT_AS_FIRST_DIRECTIVE_GETOPT_H = @NEXT_AS_FIRST_DIRECTIVE_GETOPT_H@
-NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H = @NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H@
-NEXT_AS_FIRST_DIRECTIVE_STDARG_H = @NEXT_AS_FIRST_DIRECTIVE_STDARG_H@
-NEXT_AS_FIRST_DIRECTIVE_STDDEF_H = @NEXT_AS_FIRST_DIRECTIVE_STDDEF_H@
-NEXT_AS_FIRST_DIRECTIVE_STDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDINT_H@
-NEXT_AS_FIRST_DIRECTIVE_STDIO_H = @NEXT_AS_FIRST_DIRECTIVE_STDIO_H@
-NEXT_AS_FIRST_DIRECTIVE_STDLIB_H = @NEXT_AS_FIRST_DIRECTIVE_STDLIB_H@
-NEXT_AS_FIRST_DIRECTIVE_STRINGS_H = @NEXT_AS_FIRST_DIRECTIVE_STRINGS_H@
-NEXT_AS_FIRST_DIRECTIVE_STRING_H = @NEXT_AS_FIRST_DIRECTIVE_STRING_H@
-NEXT_AS_FIRST_DIRECTIVE_SYSEXITS_H = @NEXT_AS_FIRST_DIRECTIVE_SYSEXITS_H@
-NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H@
-NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H@
-NEXT_AS_FIRST_DIRECTIVE_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_TIME_H@
-NEXT_AS_FIRST_DIRECTIVE_UNISTD_H = @NEXT_AS_FIRST_DIRECTIVE_UNISTD_H@
-NEXT_AS_FIRST_DIRECTIVE_WCHAR_H = @NEXT_AS_FIRST_DIRECTIVE_WCHAR_H@
-NEXT_AS_FIRST_DIRECTIVE_WCTYPE_H = @NEXT_AS_FIRST_DIRECTIVE_WCTYPE_H@
-NEXT_DIRENT_H = @NEXT_DIRENT_H@
-NEXT_ERRNO_H = @NEXT_ERRNO_H@
-NEXT_FCNTL_H = @NEXT_FCNTL_H@
-NEXT_FLOAT_H = @NEXT_FLOAT_H@
-NEXT_GETOPT_H = @NEXT_GETOPT_H@
-NEXT_INTTYPES_H = @NEXT_INTTYPES_H@
-NEXT_STDARG_H = @NEXT_STDARG_H@
-NEXT_STDDEF_H = @NEXT_STDDEF_H@
-NEXT_STDINT_H = @NEXT_STDINT_H@
-NEXT_STDIO_H = @NEXT_STDIO_H@
-NEXT_STDLIB_H = @NEXT_STDLIB_H@
-NEXT_STRINGS_H = @NEXT_STRINGS_H@
-NEXT_STRING_H = @NEXT_STRING_H@
-NEXT_SYSEXITS_H = @NEXT_SYSEXITS_H@
-NEXT_SYS_STAT_H = @NEXT_SYS_STAT_H@
-NEXT_SYS_TIME_H = @NEXT_SYS_TIME_H@
-NEXT_TIME_H = @NEXT_TIME_H@
-NEXT_UNISTD_H = @NEXT_UNISTD_H@
-NEXT_WCHAR_H = @NEXT_WCHAR_H@
-NEXT_WCTYPE_H = @NEXT_WCTYPE_H@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
@@ -617,138 +351,55 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
POSUB = @POSUB@
-PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@
PRIPTR_PREFIX = @PRIPTR_PREFIX@
PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@
PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@
PU_RMT_PROG = @PU_RMT_PROG@
RANLIB = @RANLIB@
-REPLACE_BTOWC = @REPLACE_BTOWC@
-REPLACE_CANONICALIZE_FILE_NAME = @REPLACE_CANONICALIZE_FILE_NAME@
REPLACE_CHOWN = @REPLACE_CHOWN@
-REPLACE_CLOSE = @REPLACE_CLOSE@
-REPLACE_CLOSEDIR = @REPLACE_CLOSEDIR@
-REPLACE_DPRINTF = @REPLACE_DPRINTF@
-REPLACE_DUP = @REPLACE_DUP@
-REPLACE_DUP2 = @REPLACE_DUP2@
REPLACE_FCHDIR = @REPLACE_FCHDIR@
-REPLACE_FCHOWNAT = @REPLACE_FCHOWNAT@
-REPLACE_FCLOSE = @REPLACE_FCLOSE@
-REPLACE_FCNTL = @REPLACE_FCNTL@
-REPLACE_FDOPENDIR = @REPLACE_FDOPENDIR@
REPLACE_FFLUSH = @REPLACE_FFLUSH@
-REPLACE_FOPEN = @REPLACE_FOPEN@
REPLACE_FPRINTF = @REPLACE_FPRINTF@
-REPLACE_FPURGE = @REPLACE_FPURGE@
-REPLACE_FREOPEN = @REPLACE_FREOPEN@
REPLACE_FSEEK = @REPLACE_FSEEK@
REPLACE_FSEEKO = @REPLACE_FSEEKO@
-REPLACE_FSTAT = @REPLACE_FSTAT@
-REPLACE_FSTATAT = @REPLACE_FSTATAT@
REPLACE_FTELL = @REPLACE_FTELL@
REPLACE_FTELLO = @REPLACE_FTELLO@
-REPLACE_FUTIMENS = @REPLACE_FUTIMENS@
REPLACE_GETCWD = @REPLACE_GETCWD@
-REPLACE_GETDELIM = @REPLACE_GETDELIM@
-REPLACE_GETGROUPS = @REPLACE_GETGROUPS@
-REPLACE_GETLINE = @REPLACE_GETLINE@
-REPLACE_GETPAGESIZE = @REPLACE_GETPAGESIZE@
REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@
-REPLACE_ISWCNTRL = @REPLACE_ISWCNTRL@
-REPLACE_LCHOWN = @REPLACE_LCHOWN@
-REPLACE_LINK = @REPLACE_LINK@
-REPLACE_LINKAT = @REPLACE_LINKAT@
REPLACE_LOCALTIME_R = @REPLACE_LOCALTIME_R@
REPLACE_LSEEK = @REPLACE_LSEEK@
-REPLACE_LSTAT = @REPLACE_LSTAT@
-REPLACE_MBRLEN = @REPLACE_MBRLEN@
-REPLACE_MBRTOWC = @REPLACE_MBRTOWC@
-REPLACE_MBSINIT = @REPLACE_MBSINIT@
-REPLACE_MBSNRTOWCS = @REPLACE_MBSNRTOWCS@
-REPLACE_MBSRTOWCS = @REPLACE_MBSRTOWCS@
-REPLACE_MBSTATE_T = @REPLACE_MBSTATE_T@
-REPLACE_MEMCHR = @REPLACE_MEMCHR@
-REPLACE_MEMMEM = @REPLACE_MEMMEM@
-REPLACE_MKDIR = @REPLACE_MKDIR@
-REPLACE_MKFIFO = @REPLACE_MKFIFO@
-REPLACE_MKNOD = @REPLACE_MKNOD@
REPLACE_MKSTEMP = @REPLACE_MKSTEMP@
-REPLACE_MKTIME = @REPLACE_MKTIME@
REPLACE_NANOSLEEP = @REPLACE_NANOSLEEP@
-REPLACE_NULL = @REPLACE_NULL@
-REPLACE_OBSTACK_PRINTF = @REPLACE_OBSTACK_PRINTF@
-REPLACE_OPEN = @REPLACE_OPEN@
-REPLACE_OPENAT = @REPLACE_OPENAT@
-REPLACE_OPENDIR = @REPLACE_OPENDIR@
-REPLACE_PERROR = @REPLACE_PERROR@
-REPLACE_POPEN = @REPLACE_POPEN@
-REPLACE_PREAD = @REPLACE_PREAD@
REPLACE_PRINTF = @REPLACE_PRINTF@
-REPLACE_PUTENV = @REPLACE_PUTENV@
-REPLACE_READLINK = @REPLACE_READLINK@
-REPLACE_REALPATH = @REPLACE_REALPATH@
-REPLACE_REMOVE = @REPLACE_REMOVE@
-REPLACE_RENAME = @REPLACE_RENAME@
-REPLACE_RENAMEAT = @REPLACE_RENAMEAT@
-REPLACE_RMDIR = @REPLACE_RMDIR@
-REPLACE_SETENV = @REPLACE_SETENV@
-REPLACE_SLEEP = @REPLACE_SLEEP@
REPLACE_SNPRINTF = @REPLACE_SNPRINTF@
REPLACE_SPRINTF = @REPLACE_SPRINTF@
-REPLACE_STAT = @REPLACE_STAT@
-REPLACE_STDIO_WRITE_FUNCS = @REPLACE_STDIO_WRITE_FUNCS@
-REPLACE_STRCASESTR = @REPLACE_STRCASESTR@
-REPLACE_STRDUP = @REPLACE_STRDUP@
-REPLACE_STRERROR = @REPLACE_STRERROR@
-REPLACE_STRNDUP = @REPLACE_STRNDUP@
REPLACE_STRPTIME = @REPLACE_STRPTIME@
-REPLACE_STRSIGNAL = @REPLACE_STRSIGNAL@
-REPLACE_STRSTR = @REPLACE_STRSTR@
-REPLACE_STRTOD = @REPLACE_STRTOD@
-REPLACE_STRTOK_R = @REPLACE_STRTOK_R@
-REPLACE_SYMLINK = @REPLACE_SYMLINK@
REPLACE_TIMEGM = @REPLACE_TIMEGM@
-REPLACE_UNLINK = @REPLACE_UNLINK@
-REPLACE_UNLINKAT = @REPLACE_UNLINKAT@
-REPLACE_UNSETENV = @REPLACE_UNSETENV@
-REPLACE_USLEEP = @REPLACE_USLEEP@
-REPLACE_UTIMENSAT = @REPLACE_UTIMENSAT@
REPLACE_VASPRINTF = @REPLACE_VASPRINTF@
-REPLACE_VDPRINTF = @REPLACE_VDPRINTF@
REPLACE_VFPRINTF = @REPLACE_VFPRINTF@
REPLACE_VPRINTF = @REPLACE_VPRINTF@
REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@
REPLACE_VSPRINTF = @REPLACE_VSPRINTF@
-REPLACE_WCRTOMB = @REPLACE_WCRTOMB@
-REPLACE_WCSNRTOMBS = @REPLACE_WCSNRTOMBS@
-REPLACE_WCSRTOMBS = @REPLACE_WCSRTOMBS@
-REPLACE_WCTOB = @REPLACE_WCTOB@
-REPLACE_WCWIDTH = @REPLACE_WCWIDTH@
-REPLACE_WRITE = @REPLACE_WRITE@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@
SIZE_T_SUFFIX = @SIZE_T_SUFFIX@
-STDARG_H = @STDARG_H@
STDBOOL_H = @STDBOOL_H@
-STDDEF_H = @STDDEF_H@
STDINT_H = @STDINT_H@
STRIP = @STRIP@
SYSEXITS_H = @SYSEXITS_H@
+SYS_STAT_H = @SYS_STAT_H@
+SYS_TIME_H = @SYS_TIME_H@
SYS_TIME_H_DEFINES_STRUCT_TIMESPEC = @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@
TIME_H_DEFINES_STRUCT_TIMESPEC = @TIME_H_DEFINES_STRUCT_TIMESPEC@
-UINT32_MAX_LT_UINTMAX_MAX = @UINT32_MAX_LT_UINTMAX_MAX@
-UINT64_MAX_EQ_ULONG_MAX = @UINT64_MAX_EQ_ULONG_MAX@
-UNDEFINE_STRTOK_R = @UNDEFINE_STRTOK_R@
-UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@
-UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@
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@
-XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
YACC = @YACC@
YFLAGS = @YFLAGS@
abs_builddir = @abs_builddir@
@@ -775,8 +426,6 @@ dvidir = @dvidir@
exec_prefix = @exec_prefix@
gl_LIBOBJS = @gl_LIBOBJS@
gl_LTLIBOBJS = @gl_LTLIBOBJS@
-gltests_LIBOBJS = @gltests_LIBOBJS@
-gltests_LTLIBOBJS = @gltests_LTLIBOBJS@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
@@ -802,41 +451,115 @@ sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-noinst_LIBRARIES = libpax.a
-BUILT_SOURCES = rmt-command.h
-CLEANFILES = rmt-command.h rmt-command.h-t
-INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu
-noinst_HEADERS = system.h system-ioctl.h rmt.h paxlib.h
-libpax_a_SOURCES = \
- exit.c\
- paxlib.h\
- rtapelib.c\
- sysdep.h\
- sysdep.c\
- system.h\
- error.c\
- names.c
-
+AUTOMAKE_OPTIONS = 1.5 gnits
+noinst_HEADERS = paxlib.h rmt.h rmt-command.h system-ioctl.h system.h
+noinst_LIBRARIES = libcpio.a
+noinst_LTLIBRARIES =
+EXTRA_DIST = alloca.c alloca_.h allocsa.valgrind argmatch.c argmatch.h \
+ canonicalize-lgpl.c canonicalize.h chdir-long.c chdir-long.h \
+ chown.c fchown-stub.c close-stream.c close-stream.h closeout.c \
+ closeout.h dirfd.c dirfd.h basename.c dirname.c dirname.h \
+ stripslash.c dup2.c error.c error.h exitfail.c exitfail.h \
+ dirent_.h fchdir.c fcntl_.h creat-safer.c fcntl--.h \
+ fcntl-safer.h open-safer.c fileblocks.c float_.h fnmatch.c \
+ fnmatch_.h fnmatch_loop.c __fpending.c __fpending.h getcwd.c \
+ getdate.c getdate.h getopt.c getopt1.c getopt_.h getopt_int.h \
+ gettime.c gettimeofday.c hash.c hash.h intprops.h imaxtostr.c \
+ inttostr.c inttostr.h offtostr.c uinttostr.c umaxtostr.c \
+ inttypes_.h lchown.c lchown.h lstat.c lstat.h malloc.c \
+ mempcpy.c memrchr.c mktime.c obstack.c obstack.h at-func.c \
+ fchmodat.c fchownat.c fstatat.c mkdirat.c openat-priv.h \
+ openat-proc.c openat.c openat.h pathmax.h quote.c quote.h \
+ quotearg.c quotearg.h readlink.c safe-read.c safe-read.h \
+ safe-write.c safe-write.h same-inode.h save-cwd.c save-cwd.h \
+ savedir.c savedir.h setenv.c setenv.h unsetenv.c sleep.c \
+ stdbool_.h stdint_.h stdio_.h stdlib_.h stpcpy.c strcasecmp.c \
+ strncasecmp.c strchrnul.c strdup.c strerror.c string_.h \
+ strndup.c strnlen.c strtol.c sys_stat_.h sys_time_.h \
+ sysexits_.h time_.h time_r.c timespec.h unistd_.h dup-safer.c \
+ fd-safer.c pipe-safer.c unistd--.h unistd-safer.h \
+ unlocked-io.h utimens.c utimens.h asnprintf.c float+.h \
+ printf-args.c printf-args.h printf-parse.c printf-parse.h \
+ vasnprintf.c vasnprintf.h vsnprintf.c wchar_.h wctype_.h \
+ xalloc.h xmalloc.c xgetcwd.c xgetcwd.h
+BUILT_SOURCES = $(ALLOCA_H) configmake.h $(DIRENT_H) $(FCNTL_H) \
+ $(FLOAT_H) $(FNMATCH_H) getdate.c $(GETOPT_H) $(INTTYPES_H) \
+ $(STDBOOL_H) $(STDINT_H) stdio.h stdlib.h string.h \
+ $(SYS_STAT_H) $(SYS_TIME_H) $(SYSEXITS_H) time.h unistd.h \
+ $(WCHAR_H) $(WCTYPE_H) rmt-command.h
+SUFFIXES =
+MOSTLYCLEANFILES = core *.stackdump alloca.h alloca.h-t dirent.h \
+ dirent.h-t fcntl.h fcntl.h-t float.h float.h-t fnmatch.h \
+ fnmatch.h-t getopt.h getopt.h-t inttypes.h inttypes.h-t \
+ stdbool.h stdbool.h-t stdint.h stdint.h-t stdio.h stdio.h-t \
+ stdlib.h stdlib.h-t string.h string.h-t sys/stat.h \
+ sys/stat.h-t sys/time.h sys/time.h-t sysexits.h sysexits.h-t \
+ time.h time.h-t unistd.h unistd.h-t wchar.h wchar.h-t wctype.h \
+ wctype.h-t
+MOSTLYCLEANDIRS = sys
+CLEANFILES = configmake.h configmake.h-t rmt-command.h
+DISTCLEANFILES = rmt-command.h
+MAINTAINERCLEANFILES = getdate.c
+AM_CPPFLAGS =
+
+# This is for those projects which use "gettextize --intl" to put a source-code
+# copy of libintl into their package. In such projects, every Makefile.am needs
+# -I$(top_builddir)/intl, so that <libintl.h> can be found in this directory.
+# For the Makefile.ams in other directories it is the maintainer's
+# responsibility; for the one from gnulib we do it here.
+# This option has no effect when the user disables NLS (because then the intl
+# directory contains no libintl.h file) or when the project does not use
+# "gettextize --intl".
+#AM_CPPFLAGS += -I$(top_builddir)/intl
+libcpio_a_SOURCES = allocsa.h allocsa.c argp.h argp-ba.c argp-eexst.c \
+ argp-fmtstream.c argp-fmtstream.h argp-fs-xinl.c argp-help.c \
+ argp-namefrob.h argp-parse.c argp-pin.c argp-pv.c argp-pvh.c \
+ argp-xinl.c full-write.h full-write.c getdate.y gettext.h \
+ openat-die.c verify.h version-etc.h version-etc.c \
+ version-etc-fsf.c xalloc-die.c xsize.h xstrndup.h xstrndup.c \
+ fatal.c paxerror.c paxexit.c paxlib.h paxnames.c rtapelib.c
+libcpio_a_LIBADD = $(gl_LIBOBJS) @ALLOCA@ $(LIBOBJS)
+libcpio_a_DEPENDENCIES = $(gl_LIBOBJS) @ALLOCA@ $(LIBOBJS)
+EXTRA_libcpio_a_SOURCES = alloca.c argmatch.c canonicalize-lgpl.c \
+ chdir-long.c chown.c fchown-stub.c close-stream.c closeout.c \
+ dirfd.c basename.c dirname.c stripslash.c dup2.c error.c \
+ exitfail.c fchdir.c creat-safer.c open-safer.c fileblocks.c \
+ fnmatch.c fnmatch_loop.c __fpending.c getcwd.c getopt.c \
+ getopt1.c gettime.c gettimeofday.c hash.c imaxtostr.c \
+ inttostr.c offtostr.c uinttostr.c umaxtostr.c lchown.c lstat.c \
+ malloc.c mempcpy.c memrchr.c mktime.c obstack.c at-func.c \
+ fchmodat.c fchownat.c fstatat.c mkdirat.c openat-proc.c \
+ openat.c quote.c quotearg.c readlink.c safe-read.c \
+ safe-write.c save-cwd.c savedir.c setenv.c unsetenv.c sleep.c \
+ stpcpy.c strcasecmp.c strncasecmp.c strchrnul.c strdup.c \
+ strerror.c strndup.c strnlen.c strtol.c time_r.c dup-safer.c \
+ fd-safer.c pipe-safer.c utimens.c asnprintf.c printf-args.c \
+ printf-parse.c vasnprintf.c vsnprintf.c xmalloc.c xgetcwd.c
+
+# Use this preprocessor expression to decide whether #include_next works.
+# Do not rely on a 'configure'-time test for this, since the expression
+# might appear in an installed header, which is used by some other compiler.
+HAVE_INCLUDE_NEXT = (__GNUC__ || 60000000 <= __DECC_VER)
+LINK_WARNING_H = $(top_srcdir)/build-aux/link-warning.h
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-am
.SUFFIXES:
-.SUFFIXES: .c .o .obj
-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+.SUFFIXES: .c .o .obj .y
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/gnulib.mk $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
- && { if test -f $@; then exit 0; else break; fi; }; \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits lib/Makefile'; \
- $(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnits lib/Makefile
+ 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 \
@@ -854,14 +577,22 @@ $(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
-$(am__aclocal_m4_deps):
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
-libpax.a: $(libpax_a_OBJECTS) $(libpax_a_DEPENDENCIES)
- $(AM_V_at)-rm -f libpax.a
- $(AM_V_AR)$(libpax_a_AR) libpax.a $(libpax_a_OBJECTS) $(libpax_a_LIBADD)
- $(AM_V_at)$(RANLIB) libpax.a
+libcpio.a: $(libcpio_a_OBJECTS) $(libcpio_a_DEPENDENCIES)
+ -rm -f libcpio.a
+ $(libcpio_a_AR) libcpio.a $(libcpio_a_OBJECTS) $(libcpio_a_LIBADD)
+ $(RANLIB) libcpio.a
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -869,76 +600,170 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/alloca.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/__fpending.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloca.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/allocsa.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argmatch.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-ba.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-eexst.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-fmtstream.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-fs-xinl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-help.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-parse.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-pin.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-pv.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-pvh.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-xinl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asnprintf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/at-func.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basename.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/canonicalize-lgpl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chdir-long.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chown.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/close-stream.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/closeout.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/creat-safer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dirfd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dirname.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dup-safer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dup2.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exit.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/names.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exitfail.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fatal.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fchdir.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fchmodat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fchown-stub.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fchownat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fd-safer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileblocks.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fnmatch.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fnmatch_loop.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fstatat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/full-write.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getcwd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getdate.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gettime.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gettimeofday.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imaxtostr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inttostr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lchown.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lstat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mempcpy.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memrchr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkdirat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mktime.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/obstack.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/offtostr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/open-safer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openat-die.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openat-proc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/paxerror.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/paxexit.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/paxnames.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pipe-safer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/printf-args.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/printf-parse.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quote.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quotearg.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readlink.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rtapelib.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysdep.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/safe-read.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/safe-write.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/save-cwd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/savedir.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/setenv.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sleep.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stpcpy.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strcasecmp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strchrnul.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strdup.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strerror.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stripslash.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strncasecmp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strndup.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strnlen.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strtol.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time_r.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uinttostr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/umaxtostr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unsetenv.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utimens.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vasnprintf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version-etc-fsf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version-etc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vsnprintf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xalloc-die.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xgetcwd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmalloc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xstrndup.Po@am__quote@
.c.o:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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) '$<'`
+.y.c:
+ $(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE)
+
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; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
- set x; \
+ 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; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
- shift; \
- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ $(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; \
- if test $$# -gt 0; then \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- "$$@" $$unique; \
- else \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$unique; \
- fi; \
+ $(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; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
- test -z "$(CTAGS_ARGS)$$unique" \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$unique
+ $$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
- && $(am__cd) $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) "$$here"
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
@@ -959,24 +784,20 @@ distdir: $(DISTFILES)
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 "$(distdir)/$$file"; then \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
- fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
- test -f "$(distdir)/$$file" \
- || cp -p $$d/$$file "$(distdir)/$$file" \
+ 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) $(HEADERS)
+all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(HEADERS)
installdirs:
install: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) install-am
@@ -994,24 +815,28 @@ install-strip:
`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 . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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."
+ -rm -f getdate.c
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
clean: clean-am
-clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+clean-am: clean-generic clean-noinstLIBRARIES clean-noinstLTLIBRARIES \
+ mostlyclean-am
distclean: distclean-am
- -rm -rf ./$(DEPDIR)
+ -rm -rf $(DEPDIR) ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@@ -1022,8 +847,6 @@ dvi-am:
html: html-am
-html-am:
-
info: info-am
info-am:
@@ -1032,38 +855,29 @@ install-data-am:
install-dvi: install-dvi-am
-install-dvi-am:
-
install-exec-am:
install-html: install-html-am
-install-html-am:
-
install-info: install-info-am
-install-info-am:
-
install-man:
install-pdf: install-pdf-am
-install-pdf-am:
-
install-ps: install-ps-am
-install-ps-am:
-
installcheck-am:
maintainer-clean: maintainer-clean-am
- -rm -rf ./$(DEPDIR)
+ -rm -rf $(DEPDIR) ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
-mostlyclean-am: mostlyclean-compile mostlyclean-generic
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-local
pdf: pdf-am
@@ -1075,28 +889,434 @@ ps-am:
uninstall-am:
-.MAKE: all check install install-am install-strip
+.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-noinstLIBRARIES ctags distclean distclean-compile \
- distclean-generic distclean-tags distdir dvi dvi-am html \
- html-am info info-am install install-am install-data \
- install-data-am install-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 \
+ clean-noinstLIBRARIES clean-noinstLTLIBRARIES 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
-
-rmt-command.h : Makefile
- $(AM_V_GEN)rm -f $@-t $@
- $(AM_V_at)echo "#ifndef DEFAULT_RMT_COMMAND" >> $@-t
- $(AM_V_at)echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo rmt | sed '$(transform)'`$(EXEEXT)\"" >> $@-t
- $(AM_V_at)echo "#endif" >> $@-t
- $(AM_V_at)mv $@-t $@
-
+ mostlyclean-generic mostlyclean-local pdf pdf-am ps ps-am tags \
+ uninstall uninstall-am
+
+
+# We need the following in order to create <alloca.h> when the system
+# doesn't have one that works with the given compiler.
+alloca.h: alloca_.h
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ cat $(srcdir)/alloca_.h; \
+ } > $@-t
+ mv -f $@-t $@
+
+# Retrieve values of the variables through 'configure' followed by
+# 'make', not directly through 'configure', so that a user who
+# sets some of these variables consistently on the 'make' command
+# line gets correct results.
+#
+# One advantage of this approach, compared to the classical
+# approach of adding -DLIBDIR=\"$(libdir)\" etc. to AM_CPPFLAGS,
+# is that it protects against the use of undefined variables.
+# If, say, $(libdir) is not set in the Makefile, LIBDIR is not
+# defined by this module, and code using LIBDIR gives a
+# compilation error.
+#
+# Another advantage is that 'make' output is shorter.
+#
+# Listed in the same order as the GNU makefile conventions.
+# The Automake-defined pkg* macros are appended, in the order
+# listed in the Automake 1.10a+ documentation.
+configmake.h: Makefile
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ echo '#define PREFIX "$(prefix)"'; \
+ echo '#define EXEC_PREFIX "$(exec_prefix)"'; \
+ echo '#define BINDIR "$(bindir)"'; \
+ echo '#define SBINDIR "$(sbindir)"'; \
+ echo '#define LIBEXECDIR "$(libexecdir)"'; \
+ echo '#define DATAROOTDIR "$(datarootdir)"'; \
+ echo '#define DATADIR "$(datadir)"'; \
+ echo '#define SYSCONFDIR "$(sysconfdir)"'; \
+ echo '#define SHAREDSTATEDIR "$(sharedstatedir)"'; \
+ echo '#define LOCALSTATEDIR "$(localstatedir)"'; \
+ echo '#define INCLUDEDIR "$(includedir)"'; \
+ echo '#define OLDINCLUDEDIR "$(oldincludedir)"'; \
+ echo '#define DOCDIR "$(docdir)"'; \
+ echo '#define INFODIR "$(infodir)"'; \
+ echo '#define HTMLDIR "$(htmldir)"'; \
+ echo '#define DVIDIR "$(dvidir)"'; \
+ echo '#define PDFDIR "$(pdfdir)"'; \
+ echo '#define PSDIR "$(psdir)"'; \
+ echo '#define LIBDIR "$(libdir)"'; \
+ echo '#define LISPDIR "$(lispdir)"'; \
+ echo '#define LOCALEDIR "$(localedir)"'; \
+ echo '#define MANDIR "$(mandir)"'; \
+ echo '#define MANEXT "$(manext)"'; \
+ echo '#define PKGDATADIR "$(pkgdatadir)"'; \
+ echo '#define PKGINCLUDEDIR "$(pkgincludedir)"'; \
+ echo '#define PKGLIBDIR "$(pkglibdir)"'; \
+ echo '#define PKGLIBEXECDIR "$(pkglibexecdir)"'; \
+ } | sed '/""/d' > $@-t
+ mv $@-t $@
+
+# We need the following in order to create <dirent.h> when the system
+# doesn't have one that works with the given compiler.
+dirent.h: dirent_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's|@''ABSOLUTE_DIRENT_H''@|$(ABSOLUTE_DIRENT_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's|@''REPLACE_FCHDIR''@|$(REPLACE_FCHDIR)|g' \
+ < $(srcdir)/dirent_.h; \
+ } > $@-t
+ mv $@-t $@
+
+# We need the following in order to create <fcntl.h> when the system
+# doesn't have one that works with the given compiler.
+fcntl.h: fcntl_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's|@''ABSOLUTE_FCNTL_H''@|$(ABSOLUTE_FCNTL_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ < $(srcdir)/fcntl_.h; \
+ } > $@-t
+ mv $@-t $@
+
+# We need the following in order to create <float.h> when the system
+# doesn't have one that works with the given compiler.
+float.h: float_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+ sed -e 's|@''ABSOLUTE_FLOAT_H''@|$(ABSOLUTE_FLOAT_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ < $(srcdir)/float_.h; \
+ } > $@-t
+ mv $@-t $@
+
+# We need the following in order to create <fnmatch.h> when the system
+# doesn't have one that supports the required API.
+fnmatch.h: fnmatch_.h
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ cat $(srcdir)/fnmatch_.h; \
+ } > $@-t
+ mv -f $@-t $@
+
+# We need the following in order to create <getopt.h> when the system
+# doesn't have one that works with the given compiler.
+getopt.h: getopt_.h
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ cat $(srcdir)/getopt_.h; \
+ } > $@-t
+ mv -f $@-t $@
+
+# We need the following in order to create <inttypes.h> when the system
+# doesn't have one that works with the given compiler.
+inttypes.h: inttypes_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \
+ -e 's|@''ABSOLUTE_INTTYPES_H''@|$(ABSOLUTE_INTTYPES_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's/@''PRI_MACROS_BROKEN''@/$(PRI_MACROS_BROKEN)/g' \
+ -e 's/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \
+ -e 's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/g' \
+ -e 's/@''PRIPTR_PREFIX''@/$(PRIPTR_PREFIX)/g' \
+ -e 's/@''GNULIB_IMAXABS''@/$(GNULIB_IMAXABS)/g' \
+ -e 's/@''GNULIB_IMAXDIV''@/$(GNULIB_IMAXDIV)/g' \
+ -e 's/@''GNULIB_STRTOIMAX''@/$(GNULIB_STRTOIMAX)/g' \
+ -e 's/@''GNULIB_STRTOUMAX''@/$(GNULIB_STRTOUMAX)/g' \
+ -e 's/@''HAVE_DECL_IMAXABS''@/$(HAVE_DECL_IMAXABS)/g' \
+ -e 's/@''HAVE_DECL_IMAXDIV''@/$(HAVE_DECL_IMAXDIV)/g' \
+ -e 's/@''HAVE_DECL_STRTOIMAX''@/$(HAVE_DECL_STRTOIMAX)/g' \
+ -e 's/@''HAVE_DECL_STRTOUMAX''@/$(HAVE_DECL_STRTOUMAX)/g' \
+ -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \
+ < $(srcdir)/inttypes_.h; \
+ } > $@-t
+ mv $@-t $@
+
+# We need the following in order to create <stdbool.h> when the system
+# doesn't have one that works.
+stdbool.h: stdbool_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool_.h; \
+ } > $@-t
+ mv $@-t $@
+
+# We need the following in order to create <stdint.h> when the system
+# doesn't have one that works with the given compiler.
+stdint.h: stdint_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's/@''HAVE_STDINT_H''@/$(HAVE_STDINT_H)/g' \
+ -e 's|@''ABSOLUTE_STDINT_H''@|$(ABSOLUTE_STDINT_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's/@''HAVE_SYS_TYPES_H''@/$(HAVE_SYS_TYPES_H)/g' \
+ -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \
+ -e 's/@''HAVE_SYS_INTTYPES_H''@/$(HAVE_SYS_INTTYPES_H)/g' \
+ -e 's/@''HAVE_SYS_BITYPES_H''@/$(HAVE_SYS_BITYPES_H)/g' \
+ -e 's/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \
+ -e 's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/g' \
+ -e 's/@''BITSIZEOF_PTRDIFF_T''@/$(BITSIZEOF_PTRDIFF_T)/g' \
+ -e 's/@''PTRDIFF_T_SUFFIX''@/$(PTRDIFF_T_SUFFIX)/g' \
+ -e 's/@''BITSIZEOF_SIG_ATOMIC_T''@/$(BITSIZEOF_SIG_ATOMIC_T)/g' \
+ -e 's/@''HAVE_SIGNED_SIG_ATOMIC_T''@/$(HAVE_SIGNED_SIG_ATOMIC_T)/g' \
+ -e 's/@''SIG_ATOMIC_T_SUFFIX''@/$(SIG_ATOMIC_T_SUFFIX)/g' \
+ -e 's/@''BITSIZEOF_SIZE_T''@/$(BITSIZEOF_SIZE_T)/g' \
+ -e 's/@''SIZE_T_SUFFIX''@/$(SIZE_T_SUFFIX)/g' \
+ -e 's/@''BITSIZEOF_WCHAR_T''@/$(BITSIZEOF_WCHAR_T)/g' \
+ -e 's/@''HAVE_SIGNED_WCHAR_T''@/$(HAVE_SIGNED_WCHAR_T)/g' \
+ -e 's/@''WCHAR_T_SUFFIX''@/$(WCHAR_T_SUFFIX)/g' \
+ -e 's/@''BITSIZEOF_WINT_T''@/$(BITSIZEOF_WINT_T)/g' \
+ -e 's/@''HAVE_SIGNED_WINT_T''@/$(HAVE_SIGNED_WINT_T)/g' \
+ -e 's/@''WINT_T_SUFFIX''@/$(WINT_T_SUFFIX)/g' \
+ < $(srcdir)/stdint_.h; \
+ } > $@-t
+ mv $@-t $@
+
+# We need the following in order to create <stdio.h> when the system
+# doesn't have one that works with the given compiler.
+stdio.h: stdio_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+ sed -e 's|@''ABSOLUTE_STDIO_H''@|$(ABSOLUTE_STDIO_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's|@''GNULIB_FPRINTF_POSIX''@|$(GNULIB_FPRINTF_POSIX)|g' \
+ -e 's|@''GNULIB_PRINTF_POSIX''@|$(GNULIB_PRINTF_POSIX)|g' \
+ -e 's|@''GNULIB_SNPRINTF''@|$(GNULIB_SNPRINTF)|g' \
+ -e 's|@''GNULIB_SPRINTF_POSIX''@|$(GNULIB_SPRINTF_POSIX)|g' \
+ -e 's|@''GNULIB_VFPRINTF_POSIX''@|$(GNULIB_VFPRINTF_POSIX)|g' \
+ -e 's|@''GNULIB_VPRINTF_POSIX''@|$(GNULIB_VPRINTF_POSIX)|g' \
+ -e 's|@''GNULIB_VSNPRINTF''@|$(GNULIB_VSNPRINTF)|g' \
+ -e 's|@''GNULIB_VSPRINTF_POSIX''@|$(GNULIB_VSPRINTF_POSIX)|g' \
+ -e 's|@''GNULIB_VASPRINTF''@|$(GNULIB_VASPRINTF)|g' \
+ -e 's|@''GNULIB_FSEEK''@|$(GNULIB_FSEEK)|g' \
+ -e 's|@''GNULIB_FSEEKO''@|$(GNULIB_FSEEKO)|g' \
+ -e 's|@''GNULIB_FTELL''@|$(GNULIB_FTELL)|g' \
+ -e 's|@''GNULIB_FTELLO''@|$(GNULIB_FTELLO)|g' \
+ -e 's|@''GNULIB_FFLUSH''@|$(GNULIB_FFLUSH)|g' \
+ -e 's|@''REPLACE_FPRINTF''@|$(REPLACE_FPRINTF)|g' \
+ -e 's|@''REPLACE_VFPRINTF''@|$(REPLACE_VFPRINTF)|g' \
+ -e 's|@''REPLACE_PRINTF''@|$(REPLACE_PRINTF)|g' \
+ -e 's|@''REPLACE_VPRINTF''@|$(REPLACE_VPRINTF)|g' \
+ -e 's|@''REPLACE_SNPRINTF''@|$(REPLACE_SNPRINTF)|g' \
+ -e 's|@''HAVE_DECL_SNPRINTF''@|$(HAVE_DECL_SNPRINTF)|g' \
+ -e 's|@''REPLACE_VSNPRINTF''@|$(REPLACE_VSNPRINTF)|g' \
+ -e 's|@''HAVE_DECL_VSNPRINTF''@|$(HAVE_DECL_VSNPRINTF)|g' \
+ -e 's|@''REPLACE_SPRINTF''@|$(REPLACE_SPRINTF)|g' \
+ -e 's|@''REPLACE_VSPRINTF''@|$(REPLACE_VSPRINTF)|g' \
+ -e 's|@''HAVE_VASPRINTF''@|$(HAVE_VASPRINTF)|g' \
+ -e 's|@''REPLACE_VASPRINTF''@|$(REPLACE_VASPRINTF)|g' \
+ -e 's|@''REPLACE_FSEEKO''@|$(REPLACE_FSEEKO)|g' \
+ -e 's|@''REPLACE_FSEEK''@|$(REPLACE_FSEEK)|g' \
+ -e 's|@''REPLACE_FTELLO''@|$(REPLACE_FTELLO)|g' \
+ -e 's|@''REPLACE_FTELL''@|$(REPLACE_FTELL)|g' \
+ -e 's|@''REPLACE_FFLUSH''@|$(REPLACE_FFLUSH)|g' \
+ -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \
+ < $(srcdir)/stdio_.h; \
+ } > $@-t
+ mv $@-t $@
+
+# We need the following in order to create <stdlib.h> when the system
+# doesn't have one that works with the given compiler.
+stdlib.h: stdlib_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+ sed -e 's|@''ABSOLUTE_STDLIB_H''@|$(ABSOLUTE_STDLIB_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's|@''GNULIB_GETSUBOPT''@|$(GNULIB_GETSUBOPT)|g' \
+ -e 's|@''GNULIB_MKDTEMP''@|$(GNULIB_MKDTEMP)|g' \
+ -e 's|@''GNULIB_MKSTEMP''@|$(GNULIB_MKSTEMP)|g' \
+ -e 's|@''HAVE_GETSUBOPT''@|$(HAVE_GETSUBOPT)|g' \
+ -e 's|@''HAVE_MKDTEMP''@|$(HAVE_MKDTEMP)|g' \
+ -e 's|@''REPLACE_MKSTEMP''@|$(REPLACE_MKSTEMP)|g' \
+ -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \
+ < $(srcdir)/stdlib_.h; \
+ } > $@-t
+ mv $@-t $@
+
+# We need the following in order to create <string.h> when the system
+# doesn't have one that works with the given compiler.
+string.h: string_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+ sed -e 's|@''ABSOLUTE_STRING_H''@|$(ABSOLUTE_STRING_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's|@''GNULIB_MBSLEN''@|$(GNULIB_MBSLEN)|g' \
+ -e 's|@''GNULIB_MBSCHR''@|$(GNULIB_MBSCHR)|g' \
+ -e 's|@''GNULIB_MBSRCHR''@|$(GNULIB_MBSRCHR)|g' \
+ -e 's|@''GNULIB_MBSSTR''@|$(GNULIB_MBSSTR)|g' \
+ -e 's|@''GNULIB_MBSCASECMP''@|$(GNULIB_MBSCASECMP)|g' \
+ -e 's|@''GNULIB_MBSNCASECMP''@|$(GNULIB_MBSNCASECMP)|g' \
+ -e 's|@''GNULIB_MBSPCASECMP''@|$(GNULIB_MBSPCASECMP)|g' \
+ -e 's|@''GNULIB_MBSCASESTR''@|$(GNULIB_MBSCASESTR)|g' \
+ -e 's|@''GNULIB_MBSCSPN''@|$(GNULIB_MBSCSPN)|g' \
+ -e 's|@''GNULIB_MBSPBRK''@|$(GNULIB_MBSPBRK)|g' \
+ -e 's|@''GNULIB_MBSSPN''@|$(GNULIB_MBSSPN)|g' \
+ -e 's|@''GNULIB_MBSSEP''@|$(GNULIB_MBSSEP)|g' \
+ -e 's|@''GNULIB_MBSTOK_R''@|$(GNULIB_MBSTOK_R)|g' \
+ -e 's|@''GNULIB_MEMMEM''@|$(GNULIB_MEMMEM)|g' \
+ -e 's|@''GNULIB_MEMPCPY''@|$(GNULIB_MEMPCPY)|g' \
+ -e 's|@''GNULIB_MEMRCHR''@|$(GNULIB_MEMRCHR)|g' \
+ -e 's|@''GNULIB_STPCPY''@|$(GNULIB_STPCPY)|g' \
+ -e 's|@''GNULIB_STPNCPY''@|$(GNULIB_STPNCPY)|g' \
+ -e 's|@''GNULIB_STRCHRNUL''@|$(GNULIB_STRCHRNUL)|g' \
+ -e 's|@''GNULIB_STRDUP''@|$(GNULIB_STRDUP)|g' \
+ -e 's|@''GNULIB_STRNDUP''@|$(GNULIB_STRNDUP)|g' \
+ -e 's|@''GNULIB_STRNLEN''@|$(GNULIB_STRNLEN)|g' \
+ -e 's|@''GNULIB_STRPBRK''@|$(GNULIB_STRPBRK)|g' \
+ -e 's|@''GNULIB_STRSEP''@|$(GNULIB_STRSEP)|g' \
+ -e 's|@''GNULIB_STRCASESTR''@|$(GNULIB_STRCASESTR)|g' \
+ -e 's|@''GNULIB_STRTOK_R''@|$(GNULIB_STRTOK_R)|g' \
+ -e 's|@''HAVE_DECL_MEMMEM''@|$(HAVE_DECL_MEMMEM)|g' \
+ -e 's|@''HAVE_MEMPCPY''@|$(HAVE_MEMPCPY)|g' \
+ -e 's|@''HAVE_DECL_MEMRCHR''@|$(HAVE_DECL_MEMRCHR)|g' \
+ -e 's|@''HAVE_STPCPY''@|$(HAVE_STPCPY)|g' \
+ -e 's|@''HAVE_STPNCPY''@|$(HAVE_STPNCPY)|g' \
+ -e 's|@''HAVE_STRCASECMP''@|$(HAVE_STRCASECMP)|g' \
+ -e 's|@''HAVE_DECL_STRNCASECMP''@|$(HAVE_DECL_STRNCASECMP)|g' \
+ -e 's|@''HAVE_STRCHRNUL''@|$(HAVE_STRCHRNUL)|g' \
+ -e 's|@''HAVE_DECL_STRDUP''@|$(HAVE_DECL_STRDUP)|g' \
+ -e 's|@''HAVE_STRNDUP''@|$(HAVE_STRNDUP)|g' \
+ -e 's|@''HAVE_DECL_STRNDUP''@|$(HAVE_DECL_STRNDUP)|g' \
+ -e 's|@''HAVE_DECL_STRNLEN''@|$(HAVE_DECL_STRNLEN)|g' \
+ -e 's|@''HAVE_STRPBRK''@|$(HAVE_STRPBRK)|g' \
+ -e 's|@''HAVE_STRSEP''@|$(HAVE_STRSEP)|g' \
+ -e 's|@''HAVE_STRCASESTR''@|$(HAVE_STRCASESTR)|g' \
+ -e 's|@''HAVE_DECL_STRTOK_R''@|$(HAVE_DECL_STRTOK_R)|g' \
+ -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \
+ < $(srcdir)/string_.h; \
+ } > $@-t
+ mv $@-t $@
+
+# We need the following in order to create <sys/stat.h> when the system
+# has one that is incomplete.
+sys/stat.h: sys_stat_.h
+ @MKDIR_P@ sys
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's|@''ABSOLUTE_SYS_STAT_H''@|$(ABSOLUTE_SYS_STAT_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's|@''HAVE_IO_H''@|$(HAVE_IO_H)|g' \
+ -e 's|@''HAVE_LSTAT''@|$(HAVE_LSTAT)|g' \
+ -e 's|@''HAVE_DECL_MKDIR''@|$(HAVE_DECL_MKDIR)|g' \
+ < $(srcdir)/sys_stat_.h; \
+ } > $@-t
+ mv $@-t $@
+
+# We need the following in order to create <sys/time.h> when the system
+# doesn't have one that works with the given compiler.
+sys/time.h: sys_time_.h
+ @MKDIR_P@ sys
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's/@''HAVE_SYS_TIME_H''@/$(HAVE_SYS_TIME_H)/g' \
+ -e 's|@''ABSOLUTE_SYS_TIME_H''@|$(ABSOLUTE_SYS_TIME_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's/@''REPLACE_GETTIMEOFDAY''@/$(REPLACE_GETTIMEOFDAY)/g' \
+ -e 's/@''HAVE_STRUCT_TIMEVAL''@/$(HAVE_STRUCT_TIMEVAL)/g' \
+ < $(srcdir)/sys_time_.h; \
+ } > $@-t
+ mv $@-t $@
+
+# We need the following in order to create <sysexits.h> when the system
+# doesn't have one that works with the given compiler.
+sysexits.h: sysexits_.h
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's|@''HAVE_SYSEXITS_H''@|$(HAVE_SYSEXITS_H)|g' \
+ -e 's|@''ABSOLUTE_SYSEXITS_H''@|$(ABSOLUTE_SYSEXITS_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ < $(srcdir)/sysexits_.h; \
+ } > $@-t
+ mv -f $@-t $@
+
+# We need the following in order to create <time.h> when the system
+# doesn't have one that works with the given compiler.
+time.h: time_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+ sed -e 's|@ABSOLUTE_TIME_H''@|$(ABSOLUTE_TIME_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's|@REPLACE_LOCALTIME_R''@|$(REPLACE_LOCALTIME_R)|g' \
+ -e 's|@REPLACE_NANOSLEEP''@|$(REPLACE_NANOSLEEP)|g' \
+ -e 's|@REPLACE_STRPTIME''@|$(REPLACE_STRPTIME)|g' \
+ -e 's|@REPLACE_TIMEGM''@|$(REPLACE_TIMEGM)|g' \
+ -e 's|@SYS_TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(SYS_TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \
+ -e 's|@TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \
+ < $(srcdir)/time_.h; \
+ } > $@-t
+ mv $@-t $@
+
+# We need the following in order to create an empty placeholder for
+# <unistd.h> when the system doesn't have one.
+unistd.h: unistd_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's|@''HAVE_UNISTD_H''@|$(HAVE_UNISTD_H)|g' \
+ -e 's|@''ABSOLUTE_UNISTD_H''@|$(ABSOLUTE_UNISTD_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's|@''GNULIB_CHOWN''@|$(GNULIB_CHOWN)|g' \
+ -e 's|@''GNULIB_DUP2''@|$(GNULIB_DUP2)|g' \
+ -e 's|@''GNULIB_FCHDIR''@|$(GNULIB_FCHDIR)|g' \
+ -e 's|@''GNULIB_FTRUNCATE''@|$(GNULIB_FTRUNCATE)|g' \
+ -e 's|@''GNULIB_GETCWD''@|$(GNULIB_GETCWD)|g' \
+ -e 's|@''GNULIB_GETLOGIN_R''@|$(GNULIB_GETLOGIN_R)|g' \
+ -e 's|@''GNULIB_LSEEK''@|$(GNULIB_LSEEK)|g' \
+ -e 's|@''GNULIB_READLINK''@|$(GNULIB_READLINK)|g' \
+ -e 's|@''GNULIB_SLEEP''@|$(GNULIB_SLEEP)|g' \
+ -e 's|@''HAVE_DUP2''@|$(HAVE_DUP2)|g' \
+ -e 's|@''HAVE_FTRUNCATE''@|$(HAVE_FTRUNCATE)|g' \
+ -e 's|@''HAVE_READLINK''@|$(HAVE_READLINK)|g' \
+ -e 's|@''HAVE_SLEEP''@|$(HAVE_SLEEP)|g' \
+ -e 's|@''HAVE_DECL_GETLOGIN_R''@|$(HAVE_DECL_GETLOGIN_R)|g' \
+ -e 's|@''REPLACE_CHOWN''@|$(REPLACE_CHOWN)|g' \
+ -e 's|@''REPLACE_FCHDIR''@|$(REPLACE_FCHDIR)|g' \
+ -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \
+ -e 's|@''REPLACE_LSEEK''@|$(REPLACE_LSEEK)|g' \
+ < $(srcdir)/unistd_.h; \
+ } > $@-t
+ mv $@-t $@
+
+# We need the following in order to create <wchar.h> when the system
+# version does not work standalone.
+wchar.h: wchar_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's|@''ABSOLUTE_WCHAR_H''@|$(ABSOLUTE_WCHAR_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ < $(srcdir)/wchar_.h; \
+ } > $@-t
+ mv $@-t $@
+
+# We need the following in order to create <wctype.h> when the system
+# doesn't have one that works with the given compiler.
+wctype.h: wctype_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's/@''HAVE_WCTYPE_H''@/$(HAVE_WCTYPE_H)/g' \
+ -e 's|@''ABSOLUTE_WCTYPE_H''@|$(ABSOLUTE_WCTYPE_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's/@''HAVE_ISWCNTRL''@/$(HAVE_ISWCNTRL)/g' \
+ -e 's/@''HAVE_WINT_T''@/$(HAVE_WINT_T)/g' \
+ < $(srcdir)/wctype_.h; \
+ } > $@-t
+ mv $@-t $@
+
+mostlyclean-local: mostlyclean-generic
+ @for dir in '' $(MOSTLYCLEANDIRS); do \
+ if test -n "$$dir" && test -d $$dir; then \
+ echo "rmdir $$dir"; rmdir $$dir; \
+ fi; \
+ done
+rmt-command.h: Makefile
+ echo '#define LOCALEDIR "$(localedir)"' >$@
+ echo "#ifndef DEFAULT_RMT_COMMAND" >> $@
+ echo "# define DEFAULT_RMT_COMMAND \"$(DEFAULT_RMT_DIR)/`echo \"rmt\" | sed 's,^.*/,,;$(transform)'`$(EXEEXT)\"" >> $@
+ echo "#endif" >> $@
# 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/__fpending.c b/lib/__fpending.c
new file mode 100644
index 0000000..221aee6
--- /dev/null
+++ b/lib/__fpending.c
@@ -0,0 +1,30 @@
+/* __fpending.c -- return the number of pending output bytes on a stream
+ Copyright (C) 2000, 2004, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Jim Meyering. */
+
+#include <config.h>
+
+#include "__fpending.h"
+
+/* Return the number of pending (aka buffered, unflushed)
+ bytes on the stream, FP, that is open for writing. */
+size_t
+__fpending (FILE *fp)
+{
+ return PENDING_OUTPUT_N_BYTES;
+}
diff --git a/lib/__fpending.h b/lib/__fpending.h
new file mode 100644
index 0000000..8a8aabc
--- /dev/null
+++ b/lib/__fpending.h
@@ -0,0 +1,34 @@
+/* Declare __fpending.
+
+ Copyright (C) 2000, 2003, 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 Jim Meyering. */
+
+#include <stddef.h>
+#include <stdio.h>
+
+#ifndef HAVE_DECL___FPENDING
+"this configure-time declaration test was not run"
+#endif
+
+#if HAVE_DECL___FPENDING
+# if HAVE_STDIO_EXT_H
+# include <stdio_ext.h>
+# endif
+#else
+size_t __fpending (FILE *);
+#endif
diff --git a/lib/alloca.c b/lib/alloca.c
new file mode 100644
index 0000000..3a1f4e2
--- /dev/null
+++ b/lib/alloca.c
@@ -0,0 +1,489 @@
+/* alloca.c -- allocate automatically reclaimed memory
+ (Mostly) portable public-domain implementation -- D A Gwyn
+
+ This implementation of the PWB library alloca function,
+ which is used to allocate space off the run-time stack so
+ that it is automatically reclaimed upon procedure exit,
+ was inspired by discussions with J. Q. Johnson of Cornell.
+ J.Otto Tennant <jot@cray.com> contributed the Cray support.
+
+ There are some preprocessor constants that can
+ be defined when compiling for your specific system, for
+ improved efficiency; however, the defaults should be okay.
+
+ The general concept of this implementation is to keep
+ track of all alloca-allocated blocks, and reclaim any
+ that are found to be deeper in the stack than the current
+ invocation. This heuristic does not reclaim storage as
+ soon as it becomes invalid, but it will do so eventually.
+
+ As a special case, alloca(0) reclaims storage without
+ allocating any. It is a good idea to use alloca(0) in
+ your main control loop, etc. to force garbage collection. */
+
+#include <config.h>
+
+#include <alloca.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef emacs
+# include "lisp.h"
+# include "blockinput.h"
+# ifdef EMACS_FREE
+# undef free
+# define free EMACS_FREE
+# endif
+#else
+# define memory_full() abort ()
+#endif
+
+/* If compiling with GCC 2, this file's not needed. */
+#if !defined (__GNUC__) || __GNUC__ < 2
+
+/* If someone has defined alloca as a macro,
+ there must be some other way alloca is supposed to work. */
+# ifndef alloca
+
+# ifdef emacs
+# ifdef static
+/* actually, only want this if static is defined as ""
+ -- this is for usg, in which emacs must undefine static
+ in order to make unexec workable
+ */
+# ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+/* Using #error here is not wise since this file should work for
+ old and obscure compilers. */
+# endif /* STACK_DIRECTION undefined */
+# endif /* static */
+# endif /* emacs */
+
+/* If your stack is a linked list of frames, you have to
+ provide an "address metric" ADDRESS_FUNCTION macro. */
+
+# if defined (CRAY) && defined (CRAY_STACKSEG_END)
+long i00afunc ();
+# define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
+# else
+# define ADDRESS_FUNCTION(arg) &(arg)
+# endif
+
+/* Define STACK_DIRECTION if you know the direction of stack
+ growth for your system; otherwise it will be automatically
+ deduced at run-time.
+
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown */
+
+# ifndef STACK_DIRECTION
+# define STACK_DIRECTION 0 /* Direction unknown. */
+# endif
+
+# if STACK_DIRECTION != 0
+
+# define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
+
+# else /* STACK_DIRECTION == 0; need run-time code. */
+
+static int stack_dir; /* 1 or -1 once known. */
+# define STACK_DIR stack_dir
+
+static void
+find_stack_direction (void)
+{
+ static char *addr = NULL; /* Address of first `dummy', once known. */
+ auto char dummy; /* To get stack address. */
+
+ if (addr == NULL)
+ { /* Initial entry. */
+ addr = ADDRESS_FUNCTION (dummy);
+
+ find_stack_direction (); /* Recurse once. */
+ }
+ else
+ {
+ /* Second entry. */
+ if (ADDRESS_FUNCTION (dummy) > addr)
+ stack_dir = 1; /* Stack grew upward. */
+ else
+ stack_dir = -1; /* Stack grew downward. */
+ }
+}
+
+# endif /* STACK_DIRECTION == 0 */
+
+/* An "alloca header" is used to:
+ (a) chain together all alloca'ed blocks;
+ (b) keep track of stack depth.
+
+ It is very important that sizeof(header) agree with malloc
+ alignment chunk size. The following default should work okay. */
+
+# ifndef ALIGN_SIZE
+# define ALIGN_SIZE sizeof(double)
+# endif
+
+typedef union hdr
+{
+ char align[ALIGN_SIZE]; /* To force sizeof(header). */
+ struct
+ {
+ union hdr *next; /* For chaining headers. */
+ char *deep; /* For stack depth measure. */
+ } h;
+} header;
+
+static header *last_alloca_header = NULL; /* -> last alloca header. */
+
+/* Return a pointer to at least SIZE bytes of storage,
+ which will be automatically reclaimed upon exit from
+ the procedure that called alloca. Originally, this space
+ was supposed to be taken from the current stack frame of the
+ caller, but that method cannot be made to work for some
+ implementations of C, for example under Gould's UTX/32. */
+
+void *
+alloca (size_t size)
+{
+ auto char probe; /* Probes stack depth: */
+ register char *depth = ADDRESS_FUNCTION (probe);
+
+# if STACK_DIRECTION == 0
+ if (STACK_DIR == 0) /* Unknown growth direction. */
+ find_stack_direction ();
+# endif
+
+ /* Reclaim garbage, defined as all alloca'd storage that
+ was allocated from deeper in the stack than currently. */
+
+ {
+ register header *hp; /* Traverses linked list. */
+
+# ifdef emacs
+ BLOCK_INPUT;
+# endif
+
+ for (hp = last_alloca_header; hp != NULL;)
+ if ((STACK_DIR > 0 && hp->h.deep > depth)
+ || (STACK_DIR < 0 && hp->h.deep < depth))
+ {
+ register header *np = hp->h.next;
+
+ free (hp); /* Collect garbage. */
+
+ hp = np; /* -> next header. */
+ }
+ else
+ break; /* Rest are not deeper. */
+
+ last_alloca_header = hp; /* -> last valid storage. */
+
+# ifdef emacs
+ UNBLOCK_INPUT;
+# endif
+ }
+
+ if (size == 0)
+ return NULL; /* No allocation required. */
+
+ /* Allocate combined header + user data storage. */
+
+ {
+ /* Address of header. */
+ register header *new;
+
+ size_t combined_size = sizeof (header) + size;
+ if (combined_size < sizeof (header))
+ memory_full ();
+
+ new = malloc (combined_size);
+
+ if (! new)
+ memory_full ();
+
+ new->h.next = last_alloca_header;
+ new->h.deep = depth;
+
+ last_alloca_header = new;
+
+ /* User storage begins just after header. */
+
+ return (void *) (new + 1);
+ }
+}
+
+# if defined (CRAY) && defined (CRAY_STACKSEG_END)
+
+# ifdef DEBUG_I00AFUNC
+# include <stdio.h>
+# endif
+
+# ifndef CRAY_STACK
+# define CRAY_STACK
+# ifndef CRAY2
+/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
+struct stack_control_header
+ {
+ long shgrow:32; /* Number of times stack has grown. */
+ long shaseg:32; /* Size of increments to stack. */
+ long shhwm:32; /* High water mark of stack. */
+ long shsize:32; /* Current size of stack (all segments). */
+ };
+
+/* The stack segment linkage control information occurs at
+ the high-address end of a stack segment. (The stack
+ grows from low addresses to high addresses.) The initial
+ part of the stack segment linkage control information is
+ 0200 (octal) words. This provides for register storage
+ for the routine which overflows the stack. */
+
+struct stack_segment_linkage
+ {
+ long ss[0200]; /* 0200 overflow words. */
+ long sssize:32; /* Number of words in this segment. */
+ long ssbase:32; /* Offset to stack base. */
+ long:32;
+ long sspseg:32; /* Offset to linkage control of previous
+ segment of stack. */
+ long:32;
+ long sstcpt:32; /* Pointer to task common address block. */
+ long sscsnm; /* Private control structure number for
+ microtasking. */
+ long ssusr1; /* Reserved for user. */
+ long ssusr2; /* Reserved for user. */
+ long sstpid; /* Process ID for pid based multi-tasking. */
+ long ssgvup; /* Pointer to multitasking thread giveup. */
+ long sscray[7]; /* Reserved for Cray Research. */
+ long ssa0;
+ long ssa1;
+ long ssa2;
+ long ssa3;
+ long ssa4;
+ long ssa5;
+ long ssa6;
+ long ssa7;
+ long sss0;
+ long sss1;
+ long sss2;
+ long sss3;
+ long sss4;
+ long sss5;
+ long sss6;
+ long sss7;
+ };
+
+# else /* CRAY2 */
+/* The following structure defines the vector of words
+ returned by the STKSTAT library routine. */
+struct stk_stat
+ {
+ long now; /* Current total stack size. */
+ long maxc; /* Amount of contiguous space which would
+ be required to satisfy the maximum
+ stack demand to date. */
+ long high_water; /* Stack high-water mark. */
+ long overflows; /* Number of stack overflow ($STKOFEN) calls. */
+ long hits; /* Number of internal buffer hits. */
+ long extends; /* Number of block extensions. */
+ long stko_mallocs; /* Block allocations by $STKOFEN. */
+ long underflows; /* Number of stack underflow calls ($STKRETN). */
+ long stko_free; /* Number of deallocations by $STKRETN. */
+ long stkm_free; /* Number of deallocations by $STKMRET. */
+ long segments; /* Current number of stack segments. */
+ long maxs; /* Maximum number of stack segments so far. */
+ long pad_size; /* Stack pad size. */
+ long current_address; /* Current stack segment address. */
+ long current_size; /* Current stack segment size. This
+ number is actually corrupted by STKSTAT to
+ include the fifteen word trailer area. */
+ long initial_address; /* Address of initial segment. */
+ long initial_size; /* Size of initial segment. */
+ };
+
+/* The following structure describes the data structure which trails
+ any stack segment. I think that the description in 'asdef' is
+ out of date. I only describe the parts that I am sure about. */
+
+struct stk_trailer
+ {
+ long this_address; /* Address of this block. */
+ long this_size; /* Size of this block (does not include
+ this trailer). */
+ long unknown2;
+ long unknown3;
+ long link; /* Address of trailer block of previous
+ segment. */
+ long unknown5;
+ long unknown6;
+ long unknown7;
+ long unknown8;
+ long unknown9;
+ long unknown10;
+ long unknown11;
+ long unknown12;
+ long unknown13;
+ long unknown14;
+ };
+
+# endif /* CRAY2 */
+# endif /* not CRAY_STACK */
+
+# ifdef CRAY2
+/* Determine a "stack measure" for an arbitrary ADDRESS.
+ I doubt that "lint" will like this much. */
+
+static long
+i00afunc (long *address)
+{
+ struct stk_stat status;
+ struct stk_trailer *trailer;
+ long *block, size;
+ long result = 0;
+
+ /* We want to iterate through all of the segments. The first
+ step is to get the stack status structure. We could do this
+ more quickly and more directly, perhaps, by referencing the
+ $LM00 common block, but I know that this works. */
+
+ STKSTAT (&status);
+
+ /* Set up the iteration. */
+
+ trailer = (struct stk_trailer *) (status.current_address
+ + status.current_size
+ - 15);
+
+ /* There must be at least one stack segment. Therefore it is
+ a fatal error if "trailer" is null. */
+
+ if (trailer == 0)
+ abort ();
+
+ /* Discard segments that do not contain our argument address. */
+
+ while (trailer != 0)
+ {
+ block = (long *) trailer->this_address;
+ size = trailer->this_size;
+ if (block == 0 || size == 0)
+ abort ();
+ trailer = (struct stk_trailer *) trailer->link;
+ if ((block <= address) && (address < (block + size)))
+ break;
+ }
+
+ /* Set the result to the offset in this segment and add the sizes
+ of all predecessor segments. */
+
+ result = address - block;
+
+ if (trailer == 0)
+ {
+ return result;
+ }
+
+ do
+ {
+ if (trailer->this_size <= 0)
+ abort ();
+ result += trailer->this_size;
+ trailer = (struct stk_trailer *) trailer->link;
+ }
+ while (trailer != 0);
+
+ /* We are done. Note that if you present a bogus address (one
+ not in any segment), you will get a different number back, formed
+ from subtracting the address of the first block. This is probably
+ not what you want. */
+
+ return (result);
+}
+
+# else /* not CRAY2 */
+/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
+ Determine the number of the cell within the stack,
+ given the address of the cell. The purpose of this
+ routine is to linearize, in some sense, stack addresses
+ for alloca. */
+
+static long
+i00afunc (long address)
+{
+ long stkl = 0;
+
+ long size, pseg, this_segment, stack;
+ long result = 0;
+
+ struct stack_segment_linkage *ssptr;
+
+ /* Register B67 contains the address of the end of the
+ current stack segment. If you (as a subprogram) store
+ your registers on the stack and find that you are past
+ the contents of B67, you have overflowed the segment.
+
+ B67 also points to the stack segment linkage control
+ area, which is what we are really interested in. */
+
+ stkl = CRAY_STACKSEG_END ();
+ ssptr = (struct stack_segment_linkage *) stkl;
+
+ /* If one subtracts 'size' from the end of the segment,
+ one has the address of the first word of the segment.
+
+ If this is not the first segment, 'pseg' will be
+ nonzero. */
+
+ pseg = ssptr->sspseg;
+ size = ssptr->sssize;
+
+ this_segment = stkl - size;
+
+ /* It is possible that calling this routine itself caused
+ a stack overflow. Discard stack segments which do not
+ contain the target address. */
+
+ while (!(this_segment <= address && address <= stkl))
+ {
+# ifdef DEBUG_I00AFUNC
+ fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
+# endif
+ if (pseg == 0)
+ break;
+ stkl = stkl - pseg;
+ ssptr = (struct stack_segment_linkage *) stkl;
+ size = ssptr->sssize;
+ pseg = ssptr->sspseg;
+ this_segment = stkl - size;
+ }
+
+ result = address - this_segment;
+
+ /* If you subtract pseg from the current end of the stack,
+ you get the address of the previous stack segment's end.
+ This seems a little convoluted to me, but I'll bet you save
+ a cycle somewhere. */
+
+ while (pseg != 0)
+ {
+# ifdef DEBUG_I00AFUNC
+ fprintf (stderr, "%011o %011o\n", pseg, size);
+# endif
+ stkl = stkl - pseg;
+ ssptr = (struct stack_segment_linkage *) stkl;
+ size = ssptr->sssize;
+ pseg = ssptr->sspseg;
+ result += size;
+ }
+ return (result);
+}
+
+# endif /* not CRAY2 */
+# endif /* CRAY */
+
+# endif /* no alloca */
+#endif /* not GCC version 2 */
diff --git a/lib/alloca_.h b/lib/alloca_.h
new file mode 100644
index 0000000..af274b9
--- /dev/null
+++ b/lib/alloca_.h
@@ -0,0 +1,54 @@
+/* Memory allocation on the stack.
+
+ Copyright (C) 1995, 1999, 2001-2004, 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. */
+
+/* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H
+ means there is a real alloca function. */
+#ifndef _GL_ALLOCA_H
+#define _GL_ALLOCA_H
+
+/* alloca (N) returns a pointer to N bytes of memory
+ allocated on the stack, which will last until the function returns.
+ Use of alloca should be avoided:
+ - inside arguments of function calls - undefined behaviour,
+ - in inline functions - the allocation may actually last until the
+ calling function returns,
+ - for huge N (say, N >= 65536) - you never know how large (or small)
+ the stack is, and when the stack cannot fulfill the memory allocation
+ request, the program just crashes.
+ */
+
+#ifndef alloca
+# ifdef __GNUC__
+# define alloca __builtin_alloca
+# elif defined _AIX
+# define alloca __alloca
+# elif defined _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# include <stddef.h>
+# ifdef __cplusplus
+extern "C"
+# endif
+void *alloca (size_t);
+# endif
+#endif
+
+#endif /* _GL_ALLOCA_H */
diff --git a/lib/allocsa.c b/lib/allocsa.c
new file mode 100644
index 0000000..97652e6
--- /dev/null
+++ b/lib/allocsa.c
@@ -0,0 +1,137 @@
+/* Safe automatic memory allocation.
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2003.
+
+ 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>
+
+/* Specification. */
+#include "allocsa.h"
+
+/* The speed critical point in this file is freesa() applied to an alloca()
+ result: it must be fast, to match the speed of alloca(). The speed of
+ mallocsa() and freesa() in the other case are not critical, because they
+ are only invoked for big memory sizes. */
+
+#if HAVE_ALLOCA
+
+/* Store the mallocsa() results in a hash table. This is needed to reliably
+ distinguish a mallocsa() result and an alloca() result.
+
+ Although it is possible that the same pointer is returned by alloca() and
+ by mallocsa() at different times in the same application, it does not lead
+ to a bug in freesa(), because:
+ - Before a pointer returned by alloca() can point into malloc()ed memory,
+ the function must return, and once this has happened the programmer must
+ not call freesa() on it anyway.
+ - Before a pointer returned by mallocsa() can point into the stack, it
+ must be freed. The only function that can free it is freesa(), and
+ when freesa() frees it, it also removes it from the hash table. */
+
+#define MAGIC_NUMBER 0x1415fb4a
+#define MAGIC_SIZE sizeof (int)
+/* This is how the header info would look like without any alignment
+ considerations. */
+struct preliminary_header { void *next; char room[MAGIC_SIZE]; };
+/* But the header's size must be a multiple of sa_alignment_max. */
+#define HEADER_SIZE \
+ (((sizeof (struct preliminary_header) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max)
+struct header { void *next; char room[HEADER_SIZE - sizeof (struct preliminary_header) + MAGIC_SIZE]; };
+/* Verify that HEADER_SIZE == sizeof (struct header). */
+typedef int verify1[2 * (HEADER_SIZE == sizeof (struct header)) - 1];
+/* We make the hash table quite big, so that during lookups the probability
+ of empty hash buckets is quite high. There is no need to make the hash
+ table resizable, because when the hash table gets filled so much that the
+ lookup becomes slow, it means that the application has memory leaks. */
+#define HASH_TABLE_SIZE 257
+static void * mallocsa_results[HASH_TABLE_SIZE];
+
+#endif
+
+void *
+mallocsa (size_t n)
+{
+#if HAVE_ALLOCA
+ /* Allocate one more word, that serves as an indicator for malloc()ed
+ memory, so that freesa() of an alloca() result is fast. */
+ size_t nplus = n + HEADER_SIZE;
+
+ if (nplus >= n)
+ {
+ char *p = (char *) malloc (nplus);
+
+ if (p != NULL)
+ {
+ size_t slot;
+
+ p += HEADER_SIZE;
+
+ /* Put a magic number into the indicator word. */
+ ((int *) p)[-1] = MAGIC_NUMBER;
+
+ /* Enter p into the hash table. */
+ slot = (unsigned long) p % HASH_TABLE_SIZE;
+ ((struct header *) (p - HEADER_SIZE))->next = mallocsa_results[slot];
+ mallocsa_results[slot] = p;
+
+ return p;
+ }
+ }
+ /* Out of memory. */
+ return NULL;
+#else
+# if !MALLOC_0_IS_NONNULL
+ if (n == 0)
+ n = 1;
+# endif
+ return malloc (n);
+#endif
+}
+
+#if HAVE_ALLOCA
+void
+freesa (void *p)
+{
+ /* mallocsa() may have returned NULL. */
+ if (p != NULL)
+ {
+ /* Attempt to quickly distinguish the mallocsa() result - which has
+ a magic indicator word - and the alloca() result - which has an
+ uninitialized indicator word. It is for this test that sa_increment
+ additional bytes are allocated in the alloca() case. */
+ if (((int *) p)[-1] == MAGIC_NUMBER)
+ {
+ /* Looks like a mallocsa() result. To see whether it really is one,
+ perform a lookup in the hash table. */
+ size_t slot = (unsigned long) p % HASH_TABLE_SIZE;
+ void **chain = &mallocsa_results[slot];
+ for (; *chain != NULL;)
+ {
+ if (*chain == p)
+ {
+ /* Found it. Remove it from the hash table and free it. */
+ char *p_begin = (char *) p - HEADER_SIZE;
+ *chain = ((struct header *) p_begin)->next;
+ free (p_begin);
+ return;
+ }
+ chain = &((struct header *) ((char *) *chain - HEADER_SIZE))->next;
+ }
+ }
+ /* At this point, we know it was not a mallocsa() result. */
+ }
+}
+#endif
diff --git a/lib/allocsa.h b/lib/allocsa.h
new file mode 100644
index 0000000..ffee917
--- /dev/null
+++ b/lib/allocsa.h
@@ -0,0 +1,124 @@
+/* Safe automatic memory allocation.
+ Copyright (C) 2003-2007 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2003.
+
+ 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 _ALLOCSA_H
+#define _ALLOCSA_H
+
+#include <alloca.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* safe_alloca(N) is equivalent to alloca(N) when it is safe to call
+ alloca(N); otherwise it returns NULL. It either returns N bytes of
+ memory allocated on the stack, that lasts until the function returns,
+ or NULL.
+ Use of safe_alloca should be avoided:
+ - inside arguments of function calls - undefined behaviour,
+ - in inline functions - the allocation may actually last until the
+ calling function returns.
+*/
+#if HAVE_ALLOCA
+/* The OS usually guarantees only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ allocate anything larger than 4096 bytes. Also care for the possibility
+ of a few compiler-allocated temporary stack slots.
+ This must be a macro, not an inline function. */
+# define safe_alloca(N) ((N) < 4032 ? alloca (N) : NULL)
+#else
+# define safe_alloca(N) ((void) (N), NULL)
+#endif
+
+/* allocsa(N) is a safe variant of alloca(N). It allocates N bytes of
+ memory allocated on the stack, that must be freed using freesa() before
+ the function returns. Upon failure, it returns NULL. */
+#if HAVE_ALLOCA
+# define allocsa(N) \
+ ((N) < 4032 - sa_increment \
+ ? (void *) ((char *) alloca ((N) + sa_increment) + sa_increment) \
+ : mallocsa (N))
+#else
+# define allocsa(N) \
+ mallocsa (N)
+#endif
+extern void * mallocsa (size_t n);
+
+/* Free a block of memory allocated through allocsa(). */
+#if HAVE_ALLOCA
+extern void freesa (void *p);
+#else
+# define freesa free
+#endif
+
+/* Maybe we should also define a variant
+ nallocsa (size_t n, size_t s) - behaves like allocsa (n * s)
+ If this would be useful in your application. please speak up. */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* ------------------- Auxiliary, non-public definitions ------------------- */
+
+/* Determine the alignment of a type at compile time. */
+#if defined __GNUC__
+# define sa_alignof __alignof__
+#elif defined __cplusplus
+ template <class type> struct sa_alignof_helper { char __slot1; type __slot2; };
+# define sa_alignof(type) offsetof (sa_alignof_helper<type>, __slot2)
+#elif defined __hpux
+ /* Work around a HP-UX 10.20 cc bug with enums constants defined as offsetof
+ values. */
+# define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8)
+#elif defined _AIX
+ /* Work around an AIX 3.2.5 xlc bug with enums constants defined as offsetof
+ values. */
+# define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8)
+#else
+# define sa_alignof(type) offsetof (struct { char __slot1; type __slot2; }, __slot2)
+#endif
+
+enum
+{
+/* The desired alignment of memory allocations is the maximum alignment
+ among all elementary types. */
+ sa_alignment_long = sa_alignof (long),
+ sa_alignment_double = sa_alignof (double),
+#if HAVE_LONG_LONG_INT
+ sa_alignment_longlong = sa_alignof (long long),
+#endif
+ sa_alignment_longdouble = sa_alignof (long double),
+ sa_alignment_max = ((sa_alignment_long - 1) | (sa_alignment_double - 1)
+#if HAVE_LONG_LONG_INT
+ | (sa_alignment_longlong - 1)
+#endif
+ | (sa_alignment_longdouble - 1)
+ ) + 1,
+/* The increment that guarantees room for a magic word must be >= sizeof (int)
+ and a multiple of sa_alignment_max. */
+ sa_increment = ((sizeof (int) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max
+};
+
+#endif /* _ALLOCSA_H */
diff --git a/lib/allocsa.valgrind b/lib/allocsa.valgrind
new file mode 100644
index 0000000..f4c77d6
--- /dev/null
+++ b/lib/allocsa.valgrind
@@ -0,0 +1,7 @@
+# Suppress a valgrind message about use of uninitialized memory in freesa().
+# This use is OK because it provides only a speedup.
+{
+ freesa
+ Memcheck:Cond
+ fun:freesa
+}
diff --git a/lib/argmatch.c b/lib/argmatch.c
new file mode 100644
index 0000000..72d9248
--- /dev/null
+++ b/lib/argmatch.c
@@ -0,0 +1,278 @@
+/* argmatch.c -- find a match for a string in an array
+
+ Copyright (C) 1990, 1998, 1999, 2001, 2002, 2003, 2004, 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. */
+
+/* Written by David MacKenzie <djm@ai.mit.edu>
+ Modified by Akim Demaille <demaille@inf.enst.fr> */
+
+#include <config.h>
+
+/* Specification. */
+#include "argmatch.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+#include "error.h"
+#include "quotearg.h"
+#include "quote.h"
+
+#if USE_UNLOCKED_IO
+# include "unlocked-io.h"
+#endif
+
+/* When reporting an invalid argument, show nonprinting characters
+ by using the quoting style ARGMATCH_QUOTING_STYLE. Do not use
+ literal_quoting_style. */
+#ifndef ARGMATCH_QUOTING_STYLE
+# define ARGMATCH_QUOTING_STYLE locale_quoting_style
+#endif
+
+/* Non failing version of argmatch call this function after failing. */
+#ifndef ARGMATCH_DIE
+# include "exitfail.h"
+# define ARGMATCH_DIE exit (exit_failure)
+#endif
+
+#ifdef ARGMATCH_DIE_DECL
+ARGMATCH_DIE_DECL;
+#endif
+
+static void
+__argmatch_die (void)
+{
+ ARGMATCH_DIE;
+}
+
+/* Used by XARGMATCH and XARGCASEMATCH. See description in argmatch.h.
+ Default to __argmatch_die, but allow caller to change this at run-time. */
+argmatch_exit_fn argmatch_die = __argmatch_die;
+
+
+/* If ARG is an unambiguous match for an element of the
+ NULL-terminated array ARGLIST, return the index in ARGLIST
+ of the matched element, else -1 if it does not match any element
+ or -2 if it is ambiguous (is a prefix of more than one element).
+
+ If VALLIST is none null, use it to resolve ambiguities limited to
+ synonyms, i.e., for
+ "yes", "yop" -> 0
+ "no", "nope" -> 1
+ "y" is a valid argument, for `0', and "n" for `1'. */
+
+ptrdiff_t
+argmatch (const char *arg, const char *const *arglist,
+ const char *vallist, size_t valsize)
+{
+ size_t i; /* Temporary index in ARGLIST. */
+ size_t arglen; /* Length of ARG. */
+ ptrdiff_t matchind = -1; /* Index of first nonexact match. */
+ bool ambiguous = false; /* If true, multiple nonexact match(es). */
+
+ arglen = strlen (arg);
+
+ /* Test all elements for either exact match or abbreviated matches. */
+ for (i = 0; arglist[i]; i++)
+ {
+ if (!strncmp (arglist[i], arg, arglen))
+ {
+ if (strlen (arglist[i]) == arglen)
+ /* Exact match found. */
+ return i;
+ else if (matchind == -1)
+ /* First nonexact match found. */
+ matchind = i;
+ else
+ {
+ /* Second nonexact match found. */
+ if (vallist == NULL
+ || memcmp (vallist + valsize * matchind,
+ vallist + valsize * i, valsize))
+ {
+ /* There is a real ambiguity, or we could not
+ disambiguate. */
+ ambiguous = true;
+ }
+ }
+ }
+ }
+ if (ambiguous)
+ return -2;
+ else
+ return matchind;
+}
+
+/* Error reporting for argmatch.
+ CONTEXT is a description of the type of entity that was being matched.
+ VALUE is the invalid value that was given.
+ PROBLEM is the return value from argmatch. */
+
+void
+argmatch_invalid (const char *context, const char *value, ptrdiff_t problem)
+{
+ char const *format = (problem == -1
+ ? _("invalid argument %s for %s")
+ : _("ambiguous argument %s for %s"));
+
+ error (0, 0, format, quotearg_n_style (0, ARGMATCH_QUOTING_STYLE, value),
+ quote_n (1, context));
+}
+
+/* List the valid arguments for argmatch.
+ ARGLIST is the same as in argmatch.
+ VALLIST is a pointer to an array of values.
+ VALSIZE is the size of the elements of VALLIST */
+void
+argmatch_valid (const char *const *arglist,
+ const char *vallist, size_t valsize)
+{
+ size_t i;
+ const char *last_val = NULL;
+
+ /* We try to put synonyms on the same line. The assumption is that
+ synonyms follow each other */
+ fprintf (stderr, _("Valid arguments are:"));
+ for (i = 0; arglist[i]; i++)
+ if ((i == 0)
+ || memcmp (last_val, vallist + valsize * i, valsize))
+ {
+ fprintf (stderr, "\n - `%s'", arglist[i]);
+ last_val = vallist + valsize * i;
+ }
+ else
+ {
+ fprintf (stderr, ", `%s'", arglist[i]);
+ }
+ putc ('\n', stderr);
+}
+
+/* Never failing versions of the previous functions.
+
+ CONTEXT is the context for which argmatch is called (e.g.,
+ "--version-control", or "$VERSION_CONTROL" etc.). Upon failure,
+ calls the (supposed never to return) function EXIT_FN. */
+
+ptrdiff_t
+__xargmatch_internal (const char *context,
+ const char *arg, const char *const *arglist,
+ const char *vallist, size_t valsize,
+ argmatch_exit_fn exit_fn)
+{
+ ptrdiff_t res = argmatch (arg, arglist, vallist, valsize);
+ if (res >= 0)
+ /* Success. */
+ return res;
+
+ /* We failed. Explain why. */
+ argmatch_invalid (context, arg, res);
+ argmatch_valid (arglist, vallist, valsize);
+ (*exit_fn) ();
+
+ return -1; /* To please the compilers. */
+}
+
+/* Look for VALUE in VALLIST, an array of objects of size VALSIZE and
+ return the first corresponding argument in ARGLIST */
+const char *
+argmatch_to_argument (const char *value,
+ const char *const *arglist,
+ const char *vallist, size_t valsize)
+{
+ size_t i;
+
+ for (i = 0; arglist[i]; i++)
+ if (!memcmp (value, vallist + valsize * i, valsize))
+ return arglist[i];
+ return NULL;
+}
+
+#ifdef TEST
+/*
+ * Based on "getversion.c" by David MacKenzie <djm@gnu.ai.mit.edu>
+ */
+char *program_name;
+
+/* When to make backup files. */
+enum backup_type
+{
+ /* Never make backups. */
+ no_backups,
+
+ /* Make simple backups of every file. */
+ simple_backups,
+
+ /* Make numbered backups of files that already have numbered backups,
+ and simple backups of the others. */
+ numbered_existing_backups,
+
+ /* Make numbered backups of every file. */
+ numbered_backups
+};
+
+/* Two tables describing arguments (keys) and their corresponding
+ values */
+static const char *const backup_args[] =
+{
+ "no", "none", "off",
+ "simple", "never",
+ "existing", "nil",
+ "numbered", "t",
+ 0
+};
+
+static const enum backup_type backup_vals[] =
+{
+ no_backups, no_backups, no_backups,
+ simple_backups, simple_backups,
+ numbered_existing_backups, numbered_existing_backups,
+ numbered_backups, numbered_backups
+};
+
+int
+main (int argc, const char *const *argv)
+{
+ const char *cp;
+ enum backup_type backup_type = no_backups;
+
+ program_name = (char *) argv[0];
+
+ if (argc > 2)
+ {
+ fprintf (stderr, "Usage: %s [VERSION_CONTROL]\n", program_name);
+ exit (1);
+ }
+
+ if ((cp = getenv ("VERSION_CONTROL")))
+ backup_type = XARGMATCH ("$VERSION_CONTROL", cp,
+ backup_args, backup_vals);
+
+ if (argc == 2)
+ backup_type = XARGMATCH (program_name, argv[1],
+ backup_args, backup_vals);
+
+ printf ("The version control is `%s'\n",
+ ARGMATCH_TO_ARGUMENT (backup_type, backup_args, backup_vals));
+
+ return 0;
+}
+#endif
diff --git a/lib/argmatch.h b/lib/argmatch.h
new file mode 100644
index 0000000..f2dfe59
--- /dev/null
+++ b/lib/argmatch.h
@@ -0,0 +1,103 @@
+/* argmatch.h -- definitions and prototypes for argmatch.c
+
+ Copyright (C) 1990, 1998, 1999, 2001, 2002, 2004, 2005 Free Software
+ Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by David MacKenzie <djm@ai.mit.edu>
+ Modified by Akim Demaille <demaille@inf.enst.fr> */
+
+#ifndef ARGMATCH_H_
+# define ARGMATCH_H_ 1
+
+# include <stddef.h>
+
+# include "verify.h"
+
+# define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array))
+
+/* Assert there are as many real arguments as there are values
+ (argument list ends with a NULL guard). */
+
+# define ARGMATCH_VERIFY(Arglist, Vallist) \
+ verify (ARRAY_CARDINALITY (Arglist) == ARRAY_CARDINALITY (Vallist) + 1)
+
+/* Return the index of the element of ARGLIST (NULL terminated) that
+ matches with ARG. If VALLIST is not NULL, then use it to resolve
+ false ambiguities (i.e., different matches of ARG but corresponding
+ to the same values in VALLIST). */
+
+ptrdiff_t argmatch (char const *arg, char const *const *arglist,
+ char const *vallist, size_t valsize);
+
+# define ARGMATCH(Arg, Arglist, Vallist) \
+ argmatch (Arg, Arglist, (char const *) (Vallist), sizeof *(Vallist))
+
+/* xargmatch calls this function when it fails. This function should not
+ return. By default, this is a function that calls ARGMATCH_DIE which
+ in turn defaults to `exit (exit_failure)'. */
+typedef void (*argmatch_exit_fn) (void);
+extern argmatch_exit_fn argmatch_die;
+
+/* Report on stderr why argmatch failed. Report correct values. */
+
+void argmatch_invalid (char const *context, char const *value,
+ ptrdiff_t problem);
+
+/* Left for compatibility with the old name invalid_arg */
+
+# define invalid_arg(Context, Value, Problem) \
+ argmatch_invalid (Context, Value, Problem)
+
+
+
+/* Report on stderr the list of possible arguments. */
+
+void argmatch_valid (char const *const *arglist,
+ char const *vallist, size_t valsize);
+
+# define ARGMATCH_VALID(Arglist, Vallist) \
+ argmatch_valid (Arglist, (char const *) (Vallist), sizeof *(Vallist))
+
+
+
+/* Same as argmatch, but upon failure, reports a explanation on the
+ failure, and exits using the function EXIT_FN. */
+
+ptrdiff_t __xargmatch_internal (char const *context,
+ char const *arg, char const *const *arglist,
+ char const *vallist, size_t valsize,
+ argmatch_exit_fn exit_fn);
+
+/* Programmer friendly interface to __xargmatch_internal. */
+
+# define XARGMATCH(Context, Arg, Arglist, Vallist) \
+ ((Vallist) [__xargmatch_internal (Context, Arg, Arglist, \
+ (char const *) (Vallist), \
+ sizeof *(Vallist), \
+ argmatch_die)])
+
+/* Convert a value into a corresponding argument. */
+
+char const *argmatch_to_argument (char const *value,
+ char const *const *arglist,
+ char const *vallist, size_t valsize);
+
+# define ARGMATCH_TO_ARGUMENT(Value, Arglist, Vallist) \
+ argmatch_to_argument (Value, Arglist, \
+ (char const *) (Vallist), sizeof *(Vallist))
+
+#endif /* ARGMATCH_H_ */
diff --git a/lib/argp-ba.c b/lib/argp-ba.c
new file mode 100644
index 0000000..8bb7309
--- /dev/null
+++ b/lib/argp-ba.c
@@ -0,0 +1,25 @@
+/* Default definition for ARGP_PROGRAM_BUG_ADDRESS.
+ Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* If set by the user program, it should point to string that is the
+ bug-reporting address for the program. It will be printed by argp_help if
+ the ARGP_HELP_BUG_ADDR flag is set (as it is by various standard help
+ messages), embedded in a sentence that says something like `Report bugs to
+ ADDR.'. */
+const char *argp_program_bug_address;
diff --git a/lib/argp-eexst.c b/lib/argp-eexst.c
new file mode 100644
index 0000000..bcab1c0
--- /dev/null
+++ b/lib/argp-eexst.c
@@ -0,0 +1,31 @@
+/* Default definition for ARGP_ERR_EXIT_STATUS
+ Copyright (C) 1997 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sysexits.h>
+
+#include "argp.h"
+
+/* The exit status that argp will use when exiting due to a parsing error.
+ If not defined or set by the user program, this defaults to EX_USAGE from
+ <sysexits.h>. */
+error_t argp_err_exit_status = EX_USAGE;
diff --git a/lib/argp-fmtstream.c b/lib/argp-fmtstream.c
new file mode 100644
index 0000000..0dd9256
--- /dev/null
+++ b/lib/argp-fmtstream.c
@@ -0,0 +1,435 @@
+/* Word-wrapping and line-truncating streams
+ Copyright (C) 1997-1999,2001,2002,2003,2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* This package emulates glibc `line_wrap_stream' semantics for systems that
+ don't have that. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#include "argp-fmtstream.h"
+#include "argp-namefrob.h"
+
+#ifndef ARGP_FMTSTREAM_USE_LINEWRAP
+
+#ifndef isblank
+#define isblank(ch) ((ch)==' ' || (ch)=='\t')
+#endif
+
+#if defined _LIBC && defined USE_IN_LIBIO
+# include <wchar.h>
+# include <libio/libioP.h>
+# define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a)
+#endif
+
+#define INIT_BUF_SIZE 200
+#define PRINTF_SIZE_GUESS 150
+
+/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines
+ written on it with LMARGIN spaces and limits them to RMARGIN columns
+ total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by
+ replacing the whitespace before them with a newline and WMARGIN spaces.
+ Otherwise, chars beyond RMARGIN are simply dropped until a newline.
+ Returns NULL if there was an error. */
+argp_fmtstream_t
+__argp_make_fmtstream (FILE *stream,
+ size_t lmargin, size_t rmargin, ssize_t wmargin)
+{
+ argp_fmtstream_t fs;
+
+ fs = (struct argp_fmtstream *) malloc (sizeof (struct argp_fmtstream));
+ if (fs != NULL)
+ {
+ fs->stream = stream;
+
+ fs->lmargin = lmargin;
+ fs->rmargin = rmargin;
+ fs->wmargin = wmargin;
+ fs->point_col = 0;
+ fs->point_offs = 0;
+
+ fs->buf = (char *) malloc (INIT_BUF_SIZE);
+ if (! fs->buf)
+ {
+ free (fs);
+ fs = 0;
+ }
+ else
+ {
+ fs->p = fs->buf;
+ fs->end = fs->buf + INIT_BUF_SIZE;
+ }
+ }
+
+ return fs;
+}
+#if 0
+/* Not exported. */
+#ifdef weak_alias
+weak_alias (__argp_make_fmtstream, argp_make_fmtstream)
+#endif
+#endif
+
+/* Flush FS to its stream, and free it (but don't close the stream). */
+void
+__argp_fmtstream_free (argp_fmtstream_t fs)
+{
+ __argp_fmtstream_update (fs);
+ if (fs->p > fs->buf)
+ {
+#ifdef USE_IN_LIBIO
+ __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
+#else
+ fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
+#endif
+ }
+ free (fs->buf);
+ free (fs);
+}
+#if 0
+/* Not exported. */
+#ifdef weak_alias
+weak_alias (__argp_fmtstream_free, argp_fmtstream_free)
+#endif
+#endif
+
+/* Process FS's buffer so that line wrapping is done from POINT_OFFS to the
+ end of its buffer. This code is mostly from glibc stdio/linewrap.c. */
+void
+__argp_fmtstream_update (argp_fmtstream_t fs)
+{
+ char *buf, *nl;
+ size_t len;
+
+ /* Scan the buffer for newlines. */
+ buf = fs->buf + fs->point_offs;
+ while (buf < fs->p)
+ {
+ size_t r;
+
+ if (fs->point_col == 0 && fs->lmargin != 0)
+ {
+ /* We are starting a new line. Print spaces to the left margin. */
+ const size_t pad = fs->lmargin;
+ if (fs->p + pad < fs->end)
+ {
+ /* We can fit in them in the buffer by moving the
+ buffer text up and filling in the beginning. */
+ memmove (buf + pad, buf, fs->p - buf);
+ fs->p += pad; /* Compensate for bigger buffer. */
+ memset (buf, ' ', pad); /* Fill in the spaces. */
+ buf += pad; /* Don't bother searching them. */
+ }
+ else
+ {
+ /* No buffer space for spaces. Must flush. */
+ size_t i;
+ for (i = 0; i < pad; i++)
+ {
+#ifdef USE_IN_LIBIO
+ if (_IO_fwide (fs->stream, 0) > 0)
+ putwc_unlocked (L' ', fs->stream);
+ else
+#endif
+ putc_unlocked (' ', fs->stream);
+ }
+ }
+ fs->point_col = pad;
+ }
+
+ len = fs->p - buf;
+ nl = memchr (buf, '\n', len);
+
+ if (fs->point_col < 0)
+ fs->point_col = 0;
+
+ if (!nl)
+ {
+ /* The buffer ends in a partial line. */
+
+ if (fs->point_col + len < fs->rmargin)
+ {
+ /* The remaining buffer text is a partial line and fits
+ within the maximum line width. Advance point for the
+ characters to be written and stop scanning. */
+ fs->point_col += len;
+ break;
+ }
+ else
+ /* Set the end-of-line pointer for the code below to
+ the end of the buffer. */
+ nl = fs->p;
+ }
+ else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin)
+ {
+ /* The buffer contains a full line that fits within the maximum
+ line width. Reset point and scan the next line. */
+ fs->point_col = 0;
+ buf = nl + 1;
+ continue;
+ }
+
+ /* This line is too long. */
+ r = fs->rmargin - 1;
+
+ if (fs->wmargin < 0)
+ {
+ /* Truncate the line by overwriting the excess with the
+ newline and anything after it in the buffer. */
+ if (nl < fs->p)
+ {
+ memmove (buf + (r - fs->point_col), nl, fs->p - nl);
+ fs->p -= buf + (r - fs->point_col) - nl;
+ /* Reset point for the next line and start scanning it. */
+ fs->point_col = 0;
+ buf += r + 1; /* Skip full line plus \n. */
+ }
+ else
+ {
+ /* The buffer ends with a partial line that is beyond the
+ maximum line width. Advance point for the characters
+ written, and discard those past the max from the buffer. */
+ fs->point_col += len;
+ fs->p -= fs->point_col - r;
+ break;
+ }
+ }
+ else
+ {
+ /* Do word wrap. Go to the column just past the maximum line
+ width and scan back for the beginning of the word there.
+ Then insert a line break. */
+
+ char *p, *nextline;
+ int i;
+
+ p = buf + (r + 1 - fs->point_col);
+ while (p >= buf && !isblank (*p))
+ --p;
+ nextline = p + 1; /* This will begin the next line. */
+
+ if (nextline > buf)
+ {
+ /* Swallow separating blanks. */
+ if (p >= buf)
+ do
+ --p;
+ while (p >= buf && isblank (*p));
+ nl = p + 1; /* The newline will replace the first blank. */
+ }
+ else
+ {
+ /* A single word that is greater than the maximum line width.
+ Oh well. Put it on an overlong line by itself. */
+ p = buf + (r + 1 - fs->point_col);
+ /* Find the end of the long word. */
+ if (p < nl)
+ do
+ ++p;
+ while (p < nl && !isblank (*p));
+ if (p == nl)
+ {
+ /* It already ends a line. No fussing required. */
+ fs->point_col = 0;
+ buf = nl + 1;
+ continue;
+ }
+ /* We will move the newline to replace the first blank. */
+ nl = p;
+ /* Swallow separating blanks. */
+ do
+ ++p;
+ while (isblank (*p));
+ /* The next line will start here. */
+ nextline = p;
+ }
+
+ /* Note: There are a bunch of tests below for
+ NEXTLINE == BUF + LEN + 1; this case is where NL happens to fall
+ at the end of the buffer, and NEXTLINE is in fact empty (and so
+ we need not be careful to maintain its contents). */
+
+ if ((nextline == buf + len + 1
+ ? fs->end - nl < fs->wmargin + 1
+ : nextline - (nl + 1) < fs->wmargin)
+ && fs->p > nextline)
+ {
+ /* The margin needs more blanks than we removed. */
+ if (fs->end - fs->p > fs->wmargin + 1)
+ /* Make some space for them. */
+ {
+ size_t mv = fs->p - nextline;
+ memmove (nl + 1 + fs->wmargin, nextline, mv);
+ nextline = nl + 1 + fs->wmargin;
+ len = nextline + mv - buf;
+ *nl++ = '\n';
+ }
+ else
+ /* Output the first line so we can use the space. */
+ {
+#ifdef _LIBC
+ __fxprintf (fs->stream, "%.*s\n",
+ (int) (nl - fs->buf), fs->buf);
+#else
+ if (nl > fs->buf)
+ fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream);
+ putc_unlocked ('\n', fs->stream);
+#endif
+
+ len += buf - fs->buf;
+ nl = buf = fs->buf;
+ }
+ }
+ else
+ /* We can fit the newline and blanks in before
+ the next word. */
+ *nl++ = '\n';
+
+ if (nextline - nl >= fs->wmargin
+ || (nextline == buf + len + 1 && fs->end - nextline >= fs->wmargin))
+ /* Add blanks up to the wrap margin column. */
+ for (i = 0; i < fs->wmargin; ++i)
+ *nl++ = ' ';
+ else
+ for (i = 0; i < fs->wmargin; ++i)
+#ifdef USE_IN_LIBIO
+ if (_IO_fwide (fs->stream, 0) > 0)
+ putwc_unlocked (L' ', fs->stream);
+ else
+#endif
+ putc_unlocked (' ', fs->stream);
+
+ /* Copy the tail of the original buffer into the current buffer
+ position. */
+ if (nl < nextline)
+ memmove (nl, nextline, buf + len - nextline);
+ len -= nextline - buf;
+
+ /* Continue the scan on the remaining lines in the buffer. */
+ buf = nl;
+
+ /* Restore bufp to include all the remaining text. */
+ fs->p = nl + len;
+
+ /* Reset the counter of what has been output this line. If wmargin
+ is 0, we want to avoid the lmargin getting added, so we set
+ point_col to a magic value of -1 in that case. */
+ fs->point_col = fs->wmargin ? fs->wmargin : -1;
+ }
+ }
+
+ /* Remember that we've scanned as far as the end of the buffer. */
+ fs->point_offs = fs->p - fs->buf;
+}
+
+/* Ensure that FS has space for AMOUNT more bytes in its buffer, either by
+ growing the buffer, or by flushing it. True is returned iff we succeed. */
+int
+__argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount)
+{
+ if ((size_t) (fs->end - fs->p) < amount)
+ {
+ ssize_t wrote;
+
+ /* Flush FS's buffer. */
+ __argp_fmtstream_update (fs);
+
+#ifdef _LIBC
+ __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
+ wrote = fs->p - fs->buf;
+#else
+ wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
+#endif
+ if (wrote == fs->p - fs->buf)
+ {
+ fs->p = fs->buf;
+ fs->point_offs = 0;
+ }
+ else
+ {
+ fs->p -= wrote;
+ fs->point_offs -= wrote;
+ memmove (fs->buf, fs->buf + wrote, fs->p - fs->buf);
+ return 0;
+ }
+
+ if ((size_t) (fs->end - fs->buf) < amount)
+ /* Gotta grow the buffer. */
+ {
+ size_t old_size = fs->end - fs->buf;
+ size_t new_size = old_size + amount;
+ char *new_buf;
+
+ if (new_size < old_size || ! (new_buf = realloc (fs->buf, new_size)))
+ {
+ __set_errno (ENOMEM);
+ return 0;
+ }
+
+ fs->buf = new_buf;
+ fs->end = new_buf + new_size;
+ fs->p = fs->buf;
+ }
+ }
+
+ return 1;
+}
+
+ssize_t
+__argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...)
+{
+ int out;
+ size_t avail;
+ size_t size_guess = PRINTF_SIZE_GUESS; /* How much space to reserve. */
+
+ do
+ {
+ va_list args;
+
+ if (! __argp_fmtstream_ensure (fs, size_guess))
+ return -1;
+
+ va_start (args, fmt);
+ avail = fs->end - fs->p;
+ out = __vsnprintf (fs->p, avail, fmt, args);
+ va_end (args);
+ if ((size_t) out >= avail)
+ size_guess = out + 1;
+ }
+ while ((size_t) out >= avail);
+
+ fs->p += out;
+
+ return out;
+}
+#if 0
+/* Not exported. */
+#ifdef weak_alias
+weak_alias (__argp_fmtstream_printf, argp_fmtstream_printf)
+#endif
+#endif
+
+#endif /* !ARGP_FMTSTREAM_USE_LINEWRAP */
diff --git a/lib/argp-fmtstream.h b/lib/argp-fmtstream.h
new file mode 100644
index 0000000..e045a72
--- /dev/null
+++ b/lib/argp-fmtstream.h
@@ -0,0 +1,301 @@
+/* Word-wrapping and line-truncating streams.
+ Copyright (C) 1997, 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* This package emulates glibc `line_wrap_stream' semantics for systems that
+ don't have that. If the system does have it, it is just a wrapper for
+ that. This header file is only used internally while compiling argp, and
+ shouldn't be installed. */
+
+#ifndef _ARGP_FMTSTREAM_H
+#define _ARGP_FMTSTREAM_H
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
+# define __attribute__(Spec) /* empty */
+# endif
+/* The __-protected variants of `format' and `printf' attributes
+ are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) || __STRICT_ANSI__
+# define __format__ format
+# define __printf__ printf
+# endif
+#endif
+
+#if (_LIBC - 0 && !defined (USE_IN_LIBIO)) \
+ || (defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H))
+/* line_wrap_stream is available, so use that. */
+#define ARGP_FMTSTREAM_USE_LINEWRAP
+#endif
+
+#ifdef ARGP_FMTSTREAM_USE_LINEWRAP
+/* Just be a simple wrapper for line_wrap_stream; the semantics are
+ *slightly* different, as line_wrap_stream doesn't actually make a new
+ object, it just modifies the given stream (reversibly) to do
+ line-wrapping. Since we control who uses this code, it doesn't matter. */
+
+#include <linewrap.h>
+
+typedef FILE *argp_fmtstream_t;
+
+#define argp_make_fmtstream line_wrap_stream
+#define __argp_make_fmtstream line_wrap_stream
+#define argp_fmtstream_free line_unwrap_stream
+#define __argp_fmtstream_free line_unwrap_stream
+
+#define __argp_fmtstream_putc(fs,ch) putc(ch,fs)
+#define argp_fmtstream_putc(fs,ch) putc(ch,fs)
+#define __argp_fmtstream_puts(fs,str) fputs(str,fs)
+#define argp_fmtstream_puts(fs,str) fputs(str,fs)
+#define __argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs)
+#define argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs)
+#define __argp_fmtstream_printf fprintf
+#define argp_fmtstream_printf fprintf
+
+#define __argp_fmtstream_lmargin line_wrap_lmargin
+#define argp_fmtstream_lmargin line_wrap_lmargin
+#define __argp_fmtstream_set_lmargin line_wrap_set_lmargin
+#define argp_fmtstream_set_lmargin line_wrap_set_lmargin
+#define __argp_fmtstream_rmargin line_wrap_rmargin
+#define argp_fmtstream_rmargin line_wrap_rmargin
+#define __argp_fmtstream_set_rmargin line_wrap_set_rmargin
+#define argp_fmtstream_set_rmargin line_wrap_set_rmargin
+#define __argp_fmtstream_wmargin line_wrap_wmargin
+#define argp_fmtstream_wmargin line_wrap_wmargin
+#define __argp_fmtstream_set_wmargin line_wrap_set_wmargin
+#define argp_fmtstream_set_wmargin line_wrap_set_wmargin
+#define __argp_fmtstream_point line_wrap_point
+#define argp_fmtstream_point line_wrap_point
+
+#else /* !ARGP_FMTSTREAM_USE_LINEWRAP */
+/* Guess we have to define our own version. */
+
+struct argp_fmtstream
+{
+ FILE *stream; /* The stream we're outputting to. */
+
+ size_t lmargin, rmargin; /* Left and right margins. */
+ ssize_t wmargin; /* Margin to wrap to, or -1 to truncate. */
+
+ /* Point in buffer to which we've processed for wrapping, but not output. */
+ size_t point_offs;
+ /* Output column at POINT_OFFS, or -1 meaning 0 but don't add lmargin. */
+ ssize_t point_col;
+
+ char *buf; /* Output buffer. */
+ char *p; /* Current end of text in BUF. */
+ char *end; /* Absolute end of BUF. */
+};
+
+typedef struct argp_fmtstream *argp_fmtstream_t;
+
+/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines
+ written on it with LMARGIN spaces and limits them to RMARGIN columns
+ total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by
+ replacing the whitespace before them with a newline and WMARGIN spaces.
+ Otherwise, chars beyond RMARGIN are simply dropped until a newline.
+ Returns NULL if there was an error. */
+extern argp_fmtstream_t __argp_make_fmtstream (FILE *__stream,
+ size_t __lmargin,
+ size_t __rmargin,
+ ssize_t __wmargin);
+extern argp_fmtstream_t argp_make_fmtstream (FILE *__stream,
+ size_t __lmargin,
+ size_t __rmargin,
+ ssize_t __wmargin);
+
+/* Flush __FS to its stream, and free it (but don't close the stream). */
+extern void __argp_fmtstream_free (argp_fmtstream_t __fs);
+extern void argp_fmtstream_free (argp_fmtstream_t __fs);
+
+extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs,
+ const char *__fmt, ...)
+ __attribute__ ((__format__ (printf, 2, 3)));
+extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs,
+ const char *__fmt, ...)
+ __attribute__ ((__format__ (printf, 2, 3)));
+
+extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
+extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
+
+extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str);
+extern int argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str);
+
+extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs,
+ const char *__str, size_t __len);
+extern size_t argp_fmtstream_write (argp_fmtstream_t __fs,
+ const char *__str, size_t __len);
+
+/* Access macros for various bits of state. */
+#define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin)
+#define argp_fmtstream_rmargin(__fs) ((__fs)->rmargin)
+#define argp_fmtstream_wmargin(__fs) ((__fs)->wmargin)
+#define __argp_fmtstream_lmargin argp_fmtstream_lmargin
+#define __argp_fmtstream_rmargin argp_fmtstream_rmargin
+#define __argp_fmtstream_wmargin argp_fmtstream_wmargin
+
+/* Set __FS's left margin to LMARGIN and return the old value. */
+extern size_t argp_fmtstream_set_lmargin (argp_fmtstream_t __fs,
+ size_t __lmargin);
+extern size_t __argp_fmtstream_set_lmargin (argp_fmtstream_t __fs,
+ size_t __lmargin);
+
+/* Set __FS's right margin to __RMARGIN and return the old value. */
+extern size_t argp_fmtstream_set_rmargin (argp_fmtstream_t __fs,
+ size_t __rmargin);
+extern size_t __argp_fmtstream_set_rmargin (argp_fmtstream_t __fs,
+ size_t __rmargin);
+
+/* Set __FS's wrap margin to __WMARGIN and return the old value. */
+extern size_t argp_fmtstream_set_wmargin (argp_fmtstream_t __fs,
+ size_t __wmargin);
+extern size_t __argp_fmtstream_set_wmargin (argp_fmtstream_t __fs,
+ size_t __wmargin);
+
+/* Return the column number of the current output point in __FS. */
+extern size_t argp_fmtstream_point (argp_fmtstream_t __fs);
+extern size_t __argp_fmtstream_point (argp_fmtstream_t __fs);
+
+/* Internal routines. */
+extern void _argp_fmtstream_update (argp_fmtstream_t __fs);
+extern void __argp_fmtstream_update (argp_fmtstream_t __fs);
+extern int _argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount);
+extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount);
+
+#ifdef __OPTIMIZE__
+/* Inline versions of above routines. */
+
+#if !_LIBC
+#define __argp_fmtstream_putc argp_fmtstream_putc
+#define __argp_fmtstream_puts argp_fmtstream_puts
+#define __argp_fmtstream_write argp_fmtstream_write
+#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin
+#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin
+#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin
+#define __argp_fmtstream_point argp_fmtstream_point
+#define __argp_fmtstream_update _argp_fmtstream_update
+#define __argp_fmtstream_ensure _argp_fmtstream_ensure
+#endif
+
+#ifndef ARGP_FS_EI
+#define ARGP_FS_EI extern inline
+#endif
+
+ARGP_FS_EI size_t
+__argp_fmtstream_write (argp_fmtstream_t __fs,
+ const char *__str, size_t __len)
+{
+ if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len))
+ {
+ memcpy (__fs->p, __str, __len);
+ __fs->p += __len;
+ return __len;
+ }
+ else
+ return 0;
+}
+
+ARGP_FS_EI int
+__argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str)
+{
+ size_t __len = strlen (__str);
+ if (__len)
+ {
+ size_t __wrote = __argp_fmtstream_write (__fs, __str, __len);
+ return __wrote == __len ? 0 : -1;
+ }
+ else
+ return 0;
+}
+
+ARGP_FS_EI int
+__argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch)
+{
+ if (__fs->p < __fs->end || __argp_fmtstream_ensure (__fs, 1))
+ return *__fs->p++ = __ch;
+ else
+ return EOF;
+}
+
+/* Set __FS's left margin to __LMARGIN and return the old value. */
+ARGP_FS_EI size_t
+__argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin)
+{
+ size_t __old;
+ if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
+ __argp_fmtstream_update (__fs);
+ __old = __fs->lmargin;
+ __fs->lmargin = __lmargin;
+ return __old;
+}
+
+/* Set __FS's right margin to __RMARGIN and return the old value. */
+ARGP_FS_EI size_t
+__argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, size_t __rmargin)
+{
+ size_t __old;
+ if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
+ __argp_fmtstream_update (__fs);
+ __old = __fs->rmargin;
+ __fs->rmargin = __rmargin;
+ return __old;
+}
+
+/* Set FS's wrap margin to __WMARGIN and return the old value. */
+ARGP_FS_EI size_t
+__argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, size_t __wmargin)
+{
+ size_t __old;
+ if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
+ __argp_fmtstream_update (__fs);
+ __old = __fs->wmargin;
+ __fs->wmargin = __wmargin;
+ return __old;
+}
+
+/* Return the column number of the current output point in __FS. */
+ARGP_FS_EI size_t
+__argp_fmtstream_point (argp_fmtstream_t __fs)
+{
+ if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
+ __argp_fmtstream_update (__fs);
+ return __fs->point_col >= 0 ? __fs->point_col : 0;
+}
+
+#if !_LIBC
+#undef __argp_fmtstream_putc
+#undef __argp_fmtstream_puts
+#undef __argp_fmtstream_write
+#undef __argp_fmtstream_set_lmargin
+#undef __argp_fmtstream_set_rmargin
+#undef __argp_fmtstream_set_wmargin
+#undef __argp_fmtstream_point
+#undef __argp_fmtstream_update
+#undef __argp_fmtstream_ensure
+#endif
+
+#endif /* __OPTIMIZE__ */
+
+#endif /* ARGP_FMTSTREAM_USE_LINEWRAP */
+
+#endif /* argp-fmtstream.h */
diff --git a/lib/argp-fs-xinl.c b/lib/argp-fs-xinl.c
new file mode 100644
index 0000000..3b4c917
--- /dev/null
+++ b/lib/argp-fs-xinl.c
@@ -0,0 +1,43 @@
+/* Real definitions for extern inline functions in argp-fmtstream.h
+ Copyright (C) 1997, 2003, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define ARGP_FS_EI
+#undef __OPTIMIZE__
+#define __OPTIMIZE__ 1
+#include "argp-fmtstream.h"
+
+#if 0
+/* Not exported. */
+/* Add weak aliases. */
+#if _LIBC - 0 && !defined (ARGP_FMTSTREAM_USE_LINEWRAP) && defined (weak_alias)
+
+weak_alias (__argp_fmtstream_putc, argp_fmtstream_putc)
+weak_alias (__argp_fmtstream_puts, argp_fmtstream_puts)
+weak_alias (__argp_fmtstream_write, argp_fmtstream_write)
+weak_alias (__argp_fmtstream_set_lmargin, argp_fmtstream_set_lmargin)
+weak_alias (__argp_fmtstream_set_rmargin, argp_fmtstream_set_rmargin)
+weak_alias (__argp_fmtstream_set_wmargin, argp_fmtstream_set_wmargin)
+weak_alias (__argp_fmtstream_point, argp_fmtstream_point)
+
+#endif
+#endif
diff --git a/lib/argp-help.c b/lib/argp-help.c
new file mode 100644
index 0000000..396e733
--- /dev/null
+++ b/lib/argp-help.c
@@ -0,0 +1,1954 @@
+/* Hierarchial argument parsing help output
+ Copyright (C) 1995-2005, 2007 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <alloca.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <limits.h>
+#ifdef USE_IN_LIBIO
+# include <wchar.h>
+#endif
+
+#ifdef _LIBC
+# include <libintl.h>
+# undef dgettext
+# define dgettext(domain, msgid) \
+ INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES)
+#else
+# include "gettext.h"
+#endif
+
+#include "argp.h"
+#include "argp-fmtstream.h"
+#include "argp-namefrob.h"
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+/* User-selectable (using an environment variable) formatting parameters.
+
+ These may be specified in an environment variable called `ARGP_HELP_FMT',
+ with a contents like: VAR1=VAL1,VAR2=VAL2,BOOLVAR2,no-BOOLVAR2
+ Where VALn must be a positive integer. The list of variables is in the
+ UPARAM_NAMES vector, below. */
+
+/* Default parameters. */
+#define DUP_ARGS 0 /* True if option argument can be duplicated. */
+#define DUP_ARGS_NOTE 1 /* True to print a note about duplicate args. */
+#define SHORT_OPT_COL 2 /* column in which short options start */
+#define LONG_OPT_COL 6 /* column in which long options start */
+#define DOC_OPT_COL 2 /* column in which doc options start */
+#define OPT_DOC_COL 29 /* column in which option text starts */
+#define HEADER_COL 1 /* column in which group headers are printed */
+#define USAGE_INDENT 12 /* indentation of wrapped usage lines */
+#define RMARGIN 79 /* right margin used for wrapping */
+
+/* User-selectable (using an environment variable) formatting parameters.
+ They must all be of type `int' for the parsing code to work. */
+struct uparams
+{
+ /* If true, arguments for an option are shown with both short and long
+ options, even when a given option has both, e.g. `-x ARG, --longx=ARG'.
+ If false, then if an option has both, the argument is only shown with
+ the long one, e.g., `-x, --longx=ARG', and a message indicating that
+ this really means both is printed below the options. */
+ int dup_args;
+
+ /* This is true if when DUP_ARGS is false, and some duplicate arguments have
+ been suppressed, an explanatory message should be printed. */
+ int dup_args_note;
+
+ /* Various output columns. */
+ int short_opt_col; /* column in which short options start */
+ int long_opt_col; /* column in which long options start */
+ int doc_opt_col; /* column in which doc options start */
+ int opt_doc_col; /* column in which option text starts */
+ int header_col; /* column in which group headers are printed */
+ int usage_indent; /* indentation of wrapped usage lines */
+ int rmargin; /* right margin used for wrapping */
+
+ int valid; /* True when the values in here are valid. */
+};
+
+/* This is a global variable, as user options are only ever read once. */
+static struct uparams uparams = {
+ DUP_ARGS, DUP_ARGS_NOTE,
+ SHORT_OPT_COL, LONG_OPT_COL, DOC_OPT_COL, OPT_DOC_COL, HEADER_COL,
+ USAGE_INDENT, RMARGIN,
+ 0
+};
+
+/* A particular uparam, and what the user name is. */
+struct uparam_name
+{
+ const char *name; /* User name. */
+ int is_bool; /* Whether it's `boolean'. */
+ size_t uparams_offs; /* Location of the (int) field in UPARAMS. */
+};
+
+/* The name-field mappings we know about. */
+static const struct uparam_name uparam_names[] =
+{
+ { "dup-args", 1, offsetof (struct uparams, dup_args) },
+ { "dup-args-note", 1, offsetof (struct uparams, dup_args_note) },
+ { "short-opt-col", 0, offsetof (struct uparams, short_opt_col) },
+ { "long-opt-col", 0, offsetof (struct uparams, long_opt_col) },
+ { "doc-opt-col", 0, offsetof (struct uparams, doc_opt_col) },
+ { "opt-doc-col", 0, offsetof (struct uparams, opt_doc_col) },
+ { "header-col", 0, offsetof (struct uparams, header_col) },
+ { "usage-indent", 0, offsetof (struct uparams, usage_indent) },
+ { "rmargin", 0, offsetof (struct uparams, rmargin) },
+ { 0 }
+};
+
+static void
+validate_uparams (const struct argp_state *state, struct uparams *upptr)
+{
+ const struct uparam_name *up;
+
+ for (up = uparam_names; up->name; up++)
+ {
+ if (up->is_bool
+ || up->uparams_offs == offsetof (struct uparams, rmargin))
+ continue;
+ if (*(int *)((char *)upptr + up->uparams_offs) >= upptr->rmargin)
+ {
+ __argp_failure (state, 0, 0,
+ dgettext (state->root_argp->argp_domain,
+ "\
+ARGP_HELP_FMT: %s value is less than or equal to %s"),
+ "rmargin", up->name);
+ return;
+ }
+ }
+ uparams = *upptr;
+ uparams.valid = 1;
+}
+
+/* Read user options from the environment, and fill in UPARAMS appropiately. */
+static void
+fill_in_uparams (const struct argp_state *state)
+{
+ const char *var = getenv ("ARGP_HELP_FMT");
+ struct uparams new_params = uparams;
+
+#define SKIPWS(p) do { while (isspace ((unsigned char) *p)) p++; } while (0);
+
+ if (var)
+ {
+ /* Parse var. */
+ while (*var)
+ {
+ SKIPWS (var);
+
+ if (isalpha ((unsigned char) *var))
+ {
+ size_t var_len;
+ const struct uparam_name *un;
+ int unspec = 0, val = 0;
+ const char *arg = var;
+
+ while (isalnum ((unsigned char) *arg) || *arg == '-' || *arg == '_')
+ arg++;
+ var_len = arg - var;
+
+ SKIPWS (arg);
+
+ if (*arg == '\0' || *arg == ',')
+ unspec = 1;
+ else if (*arg == '=')
+ {
+ arg++;
+ SKIPWS (arg);
+ }
+
+ if (unspec)
+ {
+ if (var[0] == 'n' && var[1] == 'o' && var[2] == '-')
+ {
+ val = 0;
+ var += 3;
+ var_len -= 3;
+ }
+ else
+ val = 1;
+ }
+ else if (isdigit ((unsigned char) *arg))
+ {
+ val = atoi (arg);
+ while (isdigit ((unsigned char) *arg))
+ arg++;
+ SKIPWS (arg);
+ }
+
+ for (un = uparam_names; un->name; un++)
+ if (strlen (un->name) == var_len
+ && strncmp (var, un->name, var_len) == 0)
+ {
+ if (unspec && !un->is_bool)
+ __argp_failure (state, 0, 0,
+ dgettext (state->root_argp->argp_domain,
+ "\
+%.*s: ARGP_HELP_FMT parameter requires a value"),
+ (int) var_len, var);
+ else if (val < 0)
+ __argp_failure (state, 0, 0,
+ dgettext (state->root_argp->argp_domain,
+ "\
+%.*s: ARGP_HELP_FMT parameter must be positive"),
+ (int) var_len, var);
+ else
+ *(int *)((char *)&new_params + un->uparams_offs) = val;
+ break;
+ }
+ if (! un->name)
+ __argp_failure (state, 0, 0,
+ dgettext (state->root_argp->argp_domain, "\
+%.*s: Unknown ARGP_HELP_FMT parameter"),
+ (int) var_len, var);
+
+ var = arg;
+ if (*var == ',')
+ var++;
+ }
+ else if (*var)
+ {
+ __argp_failure (state, 0, 0,
+ dgettext (state->root_argp->argp_domain,
+ "Garbage in ARGP_HELP_FMT: %s"), var);
+ break;
+ }
+ }
+ validate_uparams (state, &new_params);
+ }
+}
+
+/* Returns true if OPT hasn't been marked invisible. Visibility only affects
+ whether OPT is displayed or used in sorting, not option shadowing. */
+#define ovisible(opt) (! ((opt)->flags & OPTION_HIDDEN))
+
+/* Returns true if OPT is an alias for an earlier option. */
+#define oalias(opt) ((opt)->flags & OPTION_ALIAS)
+
+/* Returns true if OPT is an documentation-only entry. */
+#define odoc(opt) ((opt)->flags & OPTION_DOC)
+
+/* Returns true if OPT should not be translated */
+#define onotrans(opt) ((opt)->flags & OPTION_NO_TRANS)
+
+/* Returns true if OPT is the end-of-list marker for a list of options. */
+#define oend(opt) __option_is_end (opt)
+
+/* Returns true if OPT has a short option. */
+#define oshort(opt) __option_is_short (opt)
+
+/*
+ The help format for a particular option is like:
+
+ -xARG, -yARG, --long1=ARG, --long2=ARG Documentation...
+
+ Where ARG will be omitted if there's no argument, for this option, or
+ will be surrounded by "[" and "]" appropiately if the argument is
+ optional. The documentation string is word-wrapped appropiately, and if
+ the list of options is long enough, it will be started on a separate line.
+ If there are no short options for a given option, the first long option is
+ indented slighly in a way that's supposed to make most long options appear
+ to be in a separate column.
+
+ For example, the following output (from ps):
+
+ -p PID, --pid=PID List the process PID
+ --pgrp=PGRP List processes in the process group PGRP
+ -P, -x, --no-parent Include processes without parents
+ -Q, --all-fields Don't elide unusable fields (normally if there's
+ some reason ps can't print a field for any
+ process, it's removed from the output entirely)
+ -r, --reverse, --gratuitously-long-reverse-option
+ Reverse the order of any sort
+ --session[=SID] Add the processes from the session SID (which
+ defaults to the sid of the current process)
+
+ Here are some more options:
+ -f ZOT, --foonly=ZOT Glork a foonly
+ -z, --zaza Snit a zar
+
+ -?, --help Give this help list
+ --usage Give a short usage message
+ -V, --version Print program version
+
+ The struct argp_option array for the above could look like:
+
+ {
+ {"pid", 'p', "PID", 0, "List the process PID"},
+ {"pgrp", OPT_PGRP, "PGRP", 0, "List processes in the process group PGRP"},
+ {"no-parent", 'P', 0, 0, "Include processes without parents"},
+ {0, 'x', 0, OPTION_ALIAS},
+ {"all-fields",'Q', 0, 0, "Don't elide unusable fields (normally"
+ " if there's some reason ps can't"
+ " print a field for any process, it's"
+ " removed from the output entirely)" },
+ {"reverse", 'r', 0, 0, "Reverse the order of any sort"},
+ {"gratuitously-long-reverse-option", 0, 0, OPTION_ALIAS},
+ {"session", OPT_SESS, "SID", OPTION_ARG_OPTIONAL,
+ "Add the processes from the session"
+ " SID (which defaults to the sid of"
+ " the current process)" },
+
+ {0,0,0,0, "Here are some more options:"},
+ {"foonly", 'f', "ZOT", 0, "Glork a foonly"},
+ {"zaza", 'z', 0, 0, "Snit a zar"},
+
+ {0}
+ }
+
+ Note that the last three options are automatically supplied by argp_parse,
+ unless you tell it not to with ARGP_NO_HELP.
+
+*/
+
+/* Returns true if CH occurs between BEG and END. */
+static int
+find_char (char ch, char *beg, char *end)
+{
+ while (beg < end)
+ if (*beg == ch)
+ return 1;
+ else
+ beg++;
+ return 0;
+}
+
+struct hol_cluster; /* fwd decl */
+
+struct hol_entry
+{
+ /* First option. */
+ const struct argp_option *opt;
+ /* Number of options (including aliases). */
+ unsigned num;
+
+ /* A pointers into the HOL's short_options field, to the first short option
+ letter for this entry. The order of the characters following this point
+ corresponds to the order of options pointed to by OPT, and there are at
+ most NUM. A short option recorded in a option following OPT is only
+ valid if it occurs in the right place in SHORT_OPTIONS (otherwise it's
+ probably been shadowed by some other entry). */
+ char *short_options;
+
+ /* Entries are sorted by their group first, in the order:
+ 1, 2, ..., n, 0, -m, ..., -2, -1
+ and then alphabetically within each group. The default is 0. */
+ int group;
+
+ /* The cluster of options this entry belongs to, or 0 if none. */
+ struct hol_cluster *cluster;
+
+ /* The argp from which this option came. */
+ const struct argp *argp;
+
+ /* Position in the array */
+ unsigned ord;
+};
+
+/* A cluster of entries to reflect the argp tree structure. */
+struct hol_cluster
+{
+ /* A descriptive header printed before options in this cluster. */
+ const char *header;
+
+ /* Used to order clusters within the same group with the same parent,
+ according to the order in which they occurred in the parent argp's child
+ list. */
+ int index;
+
+ /* How to sort this cluster with respect to options and other clusters at the
+ same depth (clusters always follow options in the same group). */
+ int group;
+
+ /* The cluster to which this cluster belongs, or 0 if it's at the base
+ level. */
+ struct hol_cluster *parent;
+
+ /* The argp from which this cluster is (eventually) derived. */
+ const struct argp *argp;
+
+ /* The distance this cluster is from the root. */
+ int depth;
+
+ /* Clusters in a given hol are kept in a linked list, to make freeing them
+ possible. */
+ struct hol_cluster *next;
+};
+
+/* A list of options for help. */
+struct hol
+{
+ /* An array of hol_entry's. */
+ struct hol_entry *entries;
+ /* The number of entries in this hol. If this field is zero, the others
+ are undefined. */
+ unsigned num_entries;
+
+ /* A string containing all short options in this HOL. Each entry contains
+ pointers into this string, so the order can't be messed with blindly. */
+ char *short_options;
+
+ /* Clusters of entries in this hol. */
+ struct hol_cluster *clusters;
+};
+
+/* Create a struct hol from the options in ARGP. CLUSTER is the
+ hol_cluster in which these entries occur, or 0, if at the root. */
+static struct hol *
+make_hol (const struct argp *argp, struct hol_cluster *cluster)
+{
+ char *so;
+ const struct argp_option *o;
+ const struct argp_option *opts = argp->options;
+ struct hol_entry *entry;
+ unsigned num_short_options = 0;
+ struct hol *hol = malloc (sizeof (struct hol));
+
+ assert (hol);
+
+ hol->num_entries = 0;
+ hol->clusters = 0;
+
+ if (opts)
+ {
+ int cur_group = 0;
+
+ /* The first option must not be an alias. */
+ assert (! oalias (opts));
+
+ /* Calculate the space needed. */
+ for (o = opts; ! oend (o); o++)
+ {
+ if (! oalias (o))
+ hol->num_entries++;
+ if (oshort (o))
+ num_short_options++; /* This is an upper bound. */
+ }
+
+ hol->entries = malloc (sizeof (struct hol_entry) * hol->num_entries);
+ hol->short_options = malloc (num_short_options + 1);
+
+ assert (hol->entries && hol->short_options);
+ if (SIZE_MAX <= UINT_MAX)
+ assert (hol->num_entries <= SIZE_MAX / sizeof (struct hol_entry));
+
+ /* Fill in the entries. */
+ so = hol->short_options;
+ for (o = opts, entry = hol->entries; ! oend (o); entry++)
+ {
+ entry->opt = o;
+ entry->num = 0;
+ entry->short_options = so;
+ entry->group = cur_group =
+ o->group
+ ? o->group
+ : ((!o->name && !o->key)
+ ? cur_group + 1
+ : cur_group);
+ entry->cluster = cluster;
+ entry->argp = argp;
+
+ do
+ {
+ entry->num++;
+ if (oshort (o) && ! find_char (o->key, hol->short_options, so))
+ /* O has a valid short option which hasn't already been used.*/
+ *so++ = o->key;
+ o++;
+ }
+ while (! oend (o) && oalias (o));
+ }
+ *so = '\0'; /* null terminated so we can find the length */
+ }
+
+ return hol;
+}
+
+/* Add a new cluster to HOL, with the given GROUP and HEADER (taken from the
+ associated argp child list entry), INDEX, and PARENT, and return a pointer
+ to it. ARGP is the argp that this cluster results from. */
+static struct hol_cluster *
+hol_add_cluster (struct hol *hol, int group, const char *header, int index,
+ struct hol_cluster *parent, const struct argp *argp)
+{
+ struct hol_cluster *cl = malloc (sizeof (struct hol_cluster));
+ if (cl)
+ {
+ cl->group = group;
+ cl->header = header;
+
+ cl->index = index;
+ cl->parent = parent;
+ cl->argp = argp;
+ cl->depth = parent ? parent->depth + 1 : 0;
+
+ cl->next = hol->clusters;
+ hol->clusters = cl;
+ }
+ return cl;
+}
+
+/* Free HOL and any resources it uses. */
+static void
+hol_free (struct hol *hol)
+{
+ struct hol_cluster *cl = hol->clusters;
+
+ while (cl)
+ {
+ struct hol_cluster *next = cl->next;
+ free (cl);
+ cl = next;
+ }
+
+ if (hol->num_entries > 0)
+ {
+ free (hol->entries);
+ free (hol->short_options);
+ }
+
+ free (hol);
+}
+
+static int
+hol_entry_short_iterate (const struct hol_entry *entry,
+ int (*func)(const struct argp_option *opt,
+ const struct argp_option *real,
+ const char *domain, void *cookie),
+ const char *domain, void *cookie)
+{
+ unsigned nopts;
+ int val = 0;
+ const struct argp_option *opt, *real = entry->opt;
+ char *so = entry->short_options;
+
+ for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--)
+ if (oshort (opt) && *so == opt->key)
+ {
+ if (!oalias (opt))
+ real = opt;
+ if (ovisible (opt))
+ val = (*func)(opt, real, domain, cookie);
+ so++;
+ }
+
+ return val;
+}
+
+static inline int
+__attribute__ ((always_inline))
+hol_entry_long_iterate (const struct hol_entry *entry,
+ int (*func)(const struct argp_option *opt,
+ const struct argp_option *real,
+ const char *domain, void *cookie),
+ const char *domain, void *cookie)
+{
+ unsigned nopts;
+ int val = 0;
+ const struct argp_option *opt, *real = entry->opt;
+
+ for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--)
+ if (opt->name)
+ {
+ if (!oalias (opt))
+ real = opt;
+ if (ovisible (opt))
+ val = (*func)(opt, real, domain, cookie);
+ }
+
+ return val;
+}
+
+/* Iterator that returns true for the first short option. */
+static inline int
+until_short (const struct argp_option *opt, const struct argp_option *real,
+ const char *domain, void *cookie)
+{
+ return oshort (opt) ? opt->key : 0;
+}
+
+/* Returns the first valid short option in ENTRY, or 0 if there is none. */
+static char
+hol_entry_first_short (const struct hol_entry *entry)
+{
+ return hol_entry_short_iterate (entry, until_short,
+ entry->argp->argp_domain, 0);
+}
+
+/* Returns the first valid long option in ENTRY, or 0 if there is none. */
+static const char *
+hol_entry_first_long (const struct hol_entry *entry)
+{
+ const struct argp_option *opt;
+ unsigned num;
+ for (opt = entry->opt, num = entry->num; num > 0; opt++, num--)
+ if (opt->name && ovisible (opt))
+ return opt->name;
+ return 0;
+}
+
+/* Returns the entry in HOL with the long option name NAME, or 0 if there is
+ none. */
+static struct hol_entry *
+hol_find_entry (struct hol *hol, const char *name)
+{
+ struct hol_entry *entry = hol->entries;
+ unsigned num_entries = hol->num_entries;
+
+ while (num_entries-- > 0)
+ {
+ const struct argp_option *opt = entry->opt;
+ unsigned num_opts = entry->num;
+
+ while (num_opts-- > 0)
+ if (opt->name && ovisible (opt) && strcmp (opt->name, name) == 0)
+ return entry;
+ else
+ opt++;
+
+ entry++;
+ }
+
+ return 0;
+}
+
+/* If an entry with the long option NAME occurs in HOL, set it's special
+ sort position to GROUP. */
+static void
+hol_set_group (struct hol *hol, const char *name, int group)
+{
+ struct hol_entry *entry = hol_find_entry (hol, name);
+ if (entry)
+ entry->group = group;
+}
+
+/* Order by group: 0, 1, 2, ..., n, -m, ..., -2, -1.
+ EQ is what to return if GROUP1 and GROUP2 are the same. */
+static int
+group_cmp (int group1, int group2, int eq)
+{
+ if (group1 == group2)
+ return eq;
+ else if ((group1 < 0 && group2 < 0) || (group1 >= 0 && group2 >= 0))
+ return group1 - group2;
+ else
+ return group2 - group1;
+}
+
+/* Compare clusters CL1 & CL2 by the order that they should appear in
+ output. */
+static int
+hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2)
+{
+ /* If one cluster is deeper than the other, use its ancestor at the same
+ level, so that finding the common ancestor is straightforward.
+
+ clN->depth > 0 means that clN->parent != NULL (see hol_add_cluster) */
+ while (cl1->depth > cl2->depth)
+ cl1 = cl1->parent;
+ while (cl2->depth > cl1->depth)
+ cl2 = cl2->parent;
+
+ /* Now reduce both clusters to their ancestors at the point where both have
+ a common parent; these can be directly compared. */
+ while (cl1->parent != cl2->parent)
+ cl1 = cl1->parent, cl2 = cl2->parent;
+
+ return group_cmp (cl1->group, cl2->group, cl2->index - cl1->index);
+}
+
+/* Return the ancestor of CL that's just below the root (i.e., has a parent
+ of 0). */
+static struct hol_cluster *
+hol_cluster_base (struct hol_cluster *cl)
+{
+ while (cl->parent)
+ cl = cl->parent;
+ return cl;
+}
+
+/* Return true if CL1 is a child of CL2. */
+static int
+hol_cluster_is_child (const struct hol_cluster *cl1,
+ const struct hol_cluster *cl2)
+{
+ while (cl1 && cl1 != cl2)
+ cl1 = cl1->parent;
+ return cl1 == cl2;
+}
+
+/* Given the name of a OPTION_DOC option, modifies NAME to start at the tail
+ that should be used for comparisons, and returns true iff it should be
+ treated as a non-option. */
+static int
+canon_doc_option (const char **name)
+{
+ int non_opt;
+
+ if (!*name)
+ non_opt = 1;
+ else
+ {
+ /* Skip initial whitespace. */
+ while (isspace ((unsigned char) **name))
+ (*name)++;
+ /* Decide whether this looks like an option (leading `-') or not. */
+ non_opt = (**name != '-');
+ /* Skip until part of name used for sorting. */
+ while (**name && !isalnum ((unsigned char) **name))
+ (*name)++;
+ }
+ return non_opt;
+}
+
+#define HOL_ENTRY_PTRCMP(a,b) ((a)->ord < (b)->ord ? -1 : 1)
+
+/* Order ENTRY1 & ENTRY2 by the order which they should appear in a help
+ listing. */
+static int
+hol_entry_cmp (const struct hol_entry *entry1,
+ const struct hol_entry *entry2)
+{
+ /* The group numbers by which the entries should be ordered; if either is
+ in a cluster, then this is just the group within the cluster. */
+ int group1 = entry1->group, group2 = entry2->group;
+ int rc;
+
+ if (entry1->cluster != entry2->cluster)
+ {
+ /* The entries are not within the same cluster, so we can't compare them
+ directly, we have to use the appropiate clustering level too. */
+ if (! entry1->cluster)
+ /* ENTRY1 is at the `base level', not in a cluster, so we have to
+ compare it's group number with that of the base cluster in which
+ ENTRY2 resides. Note that if they're in the same group, the
+ clustered option always comes laster. */
+ return group_cmp (group1, hol_cluster_base (entry2->cluster)->group, -1);
+ else if (! entry2->cluster)
+ /* Likewise, but ENTRY2's not in a cluster. */
+ return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1);
+ else
+ /* Both entries are in clusters, we can just compare the clusters. */
+ return (rc = hol_cluster_cmp (entry1->cluster, entry2->cluster)) ?
+ rc : HOL_ENTRY_PTRCMP(entry1, entry2);
+ }
+ else if (group1 == group2)
+ /* The entries are both in the same cluster and group, so compare them
+ alphabetically. */
+ {
+ int short1 = hol_entry_first_short (entry1);
+ int short2 = hol_entry_first_short (entry2);
+ int doc1 = odoc (entry1->opt);
+ int doc2 = odoc (entry2->opt);
+ const char *long1 = hol_entry_first_long (entry1);
+ const char *long2 = hol_entry_first_long (entry2);
+
+ if (doc1)
+ doc1 = canon_doc_option (&long1);
+ if (doc2)
+ doc2 = canon_doc_option (&long2);
+
+ if (doc1 != doc2)
+ /* `documentation' options always follow normal options (or
+ documentation options that *look* like normal options). */
+ return doc1 - doc2;
+ else if (!short1 && !short2 && long1 && long2)
+ /* Only long options. */
+ return (rc = __strcasecmp (long1, long2)) ?
+ rc : HOL_ENTRY_PTRCMP(entry1, entry2);
+ else
+ /* Compare short/short, long/short, short/long, using the first
+ character of long options. Entries without *any* valid
+ options (such as options with OPTION_HIDDEN set) will be put
+ first, but as they're not displayed, it doesn't matter where
+ they are. */
+ {
+ char first1 = short1 ? short1 : long1 ? *long1 : 0;
+ char first2 = short2 ? short2 : long2 ? *long2 : 0;
+#ifdef _tolower
+ int lower_cmp = _tolower (first1) - _tolower (first2);
+#else
+ int lower_cmp = tolower (first1) - tolower (first2);
+#endif
+ /* Compare ignoring case, except when the options are both the
+ same letter, in which case lower-case always comes first. */
+ return lower_cmp ? lower_cmp :
+ (rc = first2 - first1) ?
+ rc : HOL_ENTRY_PTRCMP(entry1, entry2);
+ }
+ }
+ else
+ /* Within the same cluster, but not the same group, so just compare
+ groups. */
+ return group_cmp (group1, group2, HOL_ENTRY_PTRCMP(entry1, entry2));
+}
+
+/* Version of hol_entry_cmp with correct signature for qsort. */
+static int
+hol_entry_qcmp (const void *entry1_v, const void *entry2_v)
+{
+ return hol_entry_cmp (entry1_v, entry2_v);
+}
+
+/* Sort HOL by group and alphabetically by option name (with short options
+ taking precedence over long). Since the sorting is for display purposes
+ only, the shadowing of options isn't effected. */
+static void
+hol_sort (struct hol *hol)
+{
+ if (hol->num_entries > 0)
+ {
+ unsigned i;
+ struct hol_entry *e;
+ for (i = 0, e = hol->entries; i < hol->num_entries; i++, e++)
+ e->ord = i;
+ qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry),
+ hol_entry_qcmp);
+ }
+}
+
+/* Append MORE to HOL, destroying MORE in the process. Options in HOL shadow
+ any in MORE with the same name. */
+static void
+hol_append (struct hol *hol, struct hol *more)
+{
+ struct hol_cluster **cl_end = &hol->clusters;
+
+ /* Steal MORE's cluster list, and add it to the end of HOL's. */
+ while (*cl_end)
+ cl_end = &(*cl_end)->next;
+ *cl_end = more->clusters;
+ more->clusters = 0;
+
+ /* Merge entries. */
+ if (more->num_entries > 0)
+ {
+ if (hol->num_entries == 0)
+ {
+ hol->num_entries = more->num_entries;
+ hol->entries = more->entries;
+ hol->short_options = more->short_options;
+ more->num_entries = 0; /* Mark MORE's fields as invalid. */
+ }
+ else
+ /* Append the entries in MORE to those in HOL, taking care to only add
+ non-shadowed SHORT_OPTIONS values. */
+ {
+ unsigned left;
+ char *so, *more_so;
+ struct hol_entry *e;
+ unsigned num_entries = hol->num_entries + more->num_entries;
+ struct hol_entry *entries =
+ malloc (num_entries * sizeof (struct hol_entry));
+ unsigned hol_so_len = strlen (hol->short_options);
+ char *short_options =
+ malloc (hol_so_len + strlen (more->short_options) + 1);
+
+ assert (entries && short_options);
+ if (SIZE_MAX <= UINT_MAX)
+ assert (num_entries <= SIZE_MAX / sizeof (struct hol_entry));
+
+ __mempcpy (__mempcpy (entries, hol->entries,
+ hol->num_entries * sizeof (struct hol_entry)),
+ more->entries,
+ more->num_entries * sizeof (struct hol_entry));
+
+ __mempcpy (short_options, hol->short_options, hol_so_len);
+
+ /* Fix up the short options pointers from HOL. */
+ for (e = entries, left = hol->num_entries; left > 0; e++, left--)
+ e->short_options += (short_options - hol->short_options);
+
+ /* Now add the short options from MORE, fixing up its entries
+ too. */
+ so = short_options + hol_so_len;
+ more_so = more->short_options;
+ for (left = more->num_entries; left > 0; e++, left--)
+ {
+ int opts_left;
+ const struct argp_option *opt;
+
+ e->short_options = so;
+
+ for (opts_left = e->num, opt = e->opt; opts_left; opt++, opts_left--)
+ {
+ int ch = *more_so;
+ if (oshort (opt) && ch == opt->key)
+ /* The next short option in MORE_SO, CH, is from OPT. */
+ {
+ if (! find_char (ch, short_options,
+ short_options + hol_so_len))
+ /* The short option CH isn't shadowed by HOL's options,
+ so add it to the sum. */
+ *so++ = ch;
+ more_so++;
+ }
+ }
+ }
+
+ *so = '\0';
+
+ free (hol->entries);
+ free (hol->short_options);
+
+ hol->entries = entries;
+ hol->num_entries = num_entries;
+ hol->short_options = short_options;
+ }
+ }
+
+ hol_free (more);
+}
+
+/* Inserts enough spaces to make sure STREAM is at column COL. */
+static void
+indent_to (argp_fmtstream_t stream, unsigned col)
+{
+ int needed = col - __argp_fmtstream_point (stream);
+ while (needed-- > 0)
+ __argp_fmtstream_putc (stream, ' ');
+}
+
+/* Output to STREAM either a space, or a newline if there isn't room for at
+ least ENSURE characters before the right margin. */
+static void
+space (argp_fmtstream_t stream, size_t ensure)
+{
+ if (__argp_fmtstream_point (stream) + ensure
+ >= __argp_fmtstream_rmargin (stream))
+ __argp_fmtstream_putc (stream, '\n');
+ else
+ __argp_fmtstream_putc (stream, ' ');
+}
+
+/* If the option REAL has an argument, we print it in using the printf
+ format REQ_FMT or OPT_FMT depending on whether it's a required or
+ optional argument. */
+static void
+arg (const struct argp_option *real, const char *req_fmt, const char *opt_fmt,
+ const char *domain, argp_fmtstream_t stream)
+{
+ if (real->arg)
+ {
+ if (real->flags & OPTION_ARG_OPTIONAL)
+ __argp_fmtstream_printf (stream, opt_fmt,
+ dgettext (domain, real->arg));
+ else
+ __argp_fmtstream_printf (stream, req_fmt,
+ dgettext (domain, real->arg));
+ }
+}
+
+/* Helper functions for hol_entry_help. */
+
+/* State used during the execution of hol_help. */
+struct hol_help_state
+{
+ /* PREV_ENTRY should contain the previous entry printed, or 0. */
+ struct hol_entry *prev_entry;
+
+ /* If an entry is in a different group from the previous one, and SEP_GROUPS
+ is true, then a blank line will be printed before any output. */
+ int sep_groups;
+
+ /* True if a duplicate option argument was suppressed (only ever set if
+ UPARAMS.dup_args is false). */
+ int suppressed_dup_arg;
+};
+
+/* Some state used while printing a help entry (used to communicate with
+ helper functions). See the doc for hol_entry_help for more info, as most
+ of the fields are copied from its arguments. */
+struct pentry_state
+{
+ const struct hol_entry *entry;
+ argp_fmtstream_t stream;
+ struct hol_help_state *hhstate;
+
+ /* True if nothing's been printed so far. */
+ int first;
+
+ /* If non-zero, the state that was used to print this help. */
+ const struct argp_state *state;
+};
+
+/* If a user doc filter should be applied to DOC, do so. */
+static const char *
+filter_doc (const char *doc, int key, const struct argp *argp,
+ const struct argp_state *state)
+{
+ if (argp->help_filter)
+ /* We must apply a user filter to this output. */
+ {
+ void *input = __argp_input (argp, state);
+ return (*argp->help_filter) (key, doc, input);
+ }
+ else
+ /* No filter. */
+ return doc;
+}
+
+/* Prints STR as a header line, with the margin lines set appropiately, and
+ notes the fact that groups should be separated with a blank line. ARGP is
+ the argp that should dictate any user doc filtering to take place. Note
+ that the previous wrap margin isn't restored, but the left margin is reset
+ to 0. */
+static void
+print_header (const char *str, const struct argp *argp,
+ struct pentry_state *pest)
+{
+ const char *tstr = dgettext (argp->argp_domain, str);
+ const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_HEADER, argp, pest->state);
+
+ if (fstr)
+ {
+ if (*fstr)
+ {
+ if (pest->hhstate->prev_entry)
+ /* Precede with a blank line. */
+ __argp_fmtstream_putc (pest->stream, '\n');
+ indent_to (pest->stream, uparams.header_col);
+ __argp_fmtstream_set_lmargin (pest->stream, uparams.header_col);
+ __argp_fmtstream_set_wmargin (pest->stream, uparams.header_col);
+ __argp_fmtstream_puts (pest->stream, fstr);
+ __argp_fmtstream_set_lmargin (pest->stream, 0);
+ __argp_fmtstream_putc (pest->stream, '\n');
+ }
+
+ pest->hhstate->sep_groups = 1; /* Separate subsequent groups. */
+ }
+
+ if (fstr != tstr)
+ free ((char *) fstr);
+}
+
+/* Inserts a comma if this isn't the first item on the line, and then makes
+ sure we're at least to column COL. If this *is* the first item on a line,
+ prints any pending whitespace/headers that should precede this line. Also
+ clears FIRST. */
+static void
+comma (unsigned col, struct pentry_state *pest)
+{
+ if (pest->first)
+ {
+ const struct hol_entry *pe = pest->hhstate->prev_entry;
+ const struct hol_cluster *cl = pest->entry->cluster;
+
+ if (pest->hhstate->sep_groups && pe && pest->entry->group != pe->group)
+ __argp_fmtstream_putc (pest->stream, '\n');
+
+ if (cl && cl->header && *cl->header
+ && (!pe
+ || (pe->cluster != cl
+ && !hol_cluster_is_child (pe->cluster, cl))))
+ /* If we're changing clusters, then this must be the start of the
+ ENTRY's cluster unless that is an ancestor of the previous one
+ (in which case we had just popped into a sub-cluster for a bit).
+ If so, then print the cluster's header line. */
+ {
+ int old_wm = __argp_fmtstream_wmargin (pest->stream);
+ print_header (cl->header, cl->argp, pest);
+ __argp_fmtstream_set_wmargin (pest->stream, old_wm);
+ }
+
+ pest->first = 0;
+ }
+ else
+ __argp_fmtstream_puts (pest->stream, ", ");
+
+ indent_to (pest->stream, col);
+}
+
+/* Print help for ENTRY to STREAM. */
+static void
+hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
+ argp_fmtstream_t stream, struct hol_help_state *hhstate)
+{
+ unsigned num;
+ const struct argp_option *real = entry->opt, *opt;
+ char *so = entry->short_options;
+ int have_long_opt = 0; /* We have any long options. */
+ /* Saved margins. */
+ int old_lm = __argp_fmtstream_set_lmargin (stream, 0);
+ int old_wm = __argp_fmtstream_wmargin (stream);
+ /* PEST is a state block holding some of our variables that we'd like to
+ share with helper functions. */
+ struct pentry_state pest;
+
+ pest.entry = entry;
+ pest.stream = stream;
+ pest.hhstate = hhstate;
+ pest.first = 1;
+ pest.state = state;
+
+ if (! odoc (real))
+ for (opt = real, num = entry->num; num > 0; opt++, num--)
+ if (opt->name && ovisible (opt))
+ {
+ have_long_opt = 1;
+ break;
+ }
+
+ /* First emit short options. */
+ __argp_fmtstream_set_wmargin (stream, uparams.short_opt_col); /* For truly bizarre cases. */
+ for (opt = real, num = entry->num; num > 0; opt++, num--)
+ if (oshort (opt) && opt->key == *so)
+ /* OPT has a valid (non shadowed) short option. */
+ {
+ if (ovisible (opt))
+ {
+ comma (uparams.short_opt_col, &pest);
+ __argp_fmtstream_putc (stream, '-');
+ __argp_fmtstream_putc (stream, *so);
+ if (!have_long_opt || uparams.dup_args)
+ arg (real, " %s", "[%s]", state->root_argp->argp_domain, stream);
+ else if (real->arg)
+ hhstate->suppressed_dup_arg = 1;
+ }
+ so++;
+ }
+
+ /* Now, long options. */
+ if (odoc (real))
+ /* A `documentation' option. */
+ {
+ __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col);
+ for (opt = real, num = entry->num; num > 0; opt++, num--)
+ if (opt->name && *opt->name && ovisible (opt))
+ {
+ comma (uparams.doc_opt_col, &pest);
+ /* Calling dgettext here isn't quite right, since sorting will
+ have been done on the original; but documentation options
+ should be pretty rare anyway... */
+ __argp_fmtstream_puts (stream,
+ onotrans (opt) ?
+ opt->name :
+ dgettext (state->root_argp->argp_domain,
+ opt->name));
+ }
+ }
+ else
+ /* A real long option. */
+ {
+ int first_long_opt = 1;
+
+ __argp_fmtstream_set_wmargin (stream, uparams.long_opt_col);
+ for (opt = real, num = entry->num; num > 0; opt++, num--)
+ if (opt->name && ovisible (opt))
+ {
+ comma (uparams.long_opt_col, &pest);
+ __argp_fmtstream_printf (stream, "--%s", opt->name);
+ if (first_long_opt || uparams.dup_args)
+ arg (real, "=%s", "[=%s]", state->root_argp->argp_domain,
+ stream);
+ else if (real->arg)
+ hhstate->suppressed_dup_arg = 1;
+ }
+ }
+
+ /* Next, documentation strings. */
+ __argp_fmtstream_set_lmargin (stream, 0);
+
+ if (pest.first)
+ {
+ /* Didn't print any switches, what's up? */
+ if (!oshort (real) && !real->name)
+ /* This is a group header, print it nicely. */
+ print_header (real->doc, entry->argp, &pest);
+ else
+ /* Just a totally shadowed option or null header; print nothing. */
+ goto cleanup; /* Just return, after cleaning up. */
+ }
+ else
+ {
+ const char *tstr = real->doc ? dgettext (state->root_argp->argp_domain,
+ real->doc) : 0;
+ const char *fstr = filter_doc (tstr, real->key, entry->argp, state);
+ if (fstr && *fstr)
+ {
+ unsigned int col = __argp_fmtstream_point (stream);
+
+ __argp_fmtstream_set_lmargin (stream, uparams.opt_doc_col);
+ __argp_fmtstream_set_wmargin (stream, uparams.opt_doc_col);
+
+ if (col > (unsigned int) (uparams.opt_doc_col + 3))
+ __argp_fmtstream_putc (stream, '\n');
+ else if (col >= (unsigned int) uparams.opt_doc_col)
+ __argp_fmtstream_puts (stream, " ");
+ else
+ indent_to (stream, uparams.opt_doc_col);
+
+ __argp_fmtstream_puts (stream, fstr);
+ }
+ if (fstr && fstr != tstr)
+ free ((char *) fstr);
+
+ /* Reset the left margin. */
+ __argp_fmtstream_set_lmargin (stream, 0);
+ __argp_fmtstream_putc (stream, '\n');
+ }
+
+ hhstate->prev_entry = entry;
+
+cleanup:
+ __argp_fmtstream_set_lmargin (stream, old_lm);
+ __argp_fmtstream_set_wmargin (stream, old_wm);
+}
+
+/* Output a long help message about the options in HOL to STREAM. */
+static void
+hol_help (struct hol *hol, const struct argp_state *state,
+ argp_fmtstream_t stream)
+{
+ unsigned num;
+ struct hol_entry *entry;
+ struct hol_help_state hhstate = { 0, 0, 0 };
+
+ for (entry = hol->entries, num = hol->num_entries; num > 0; entry++, num--)
+ hol_entry_help (entry, state, stream, &hhstate);
+
+ if (hhstate.suppressed_dup_arg && uparams.dup_args_note)
+ {
+ const char *tstr = dgettext (state->root_argp->argp_domain, "\
+Mandatory or optional arguments to long options are also mandatory or \
+optional for any corresponding short options.");
+ const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_DUP_ARGS_NOTE,
+ state ? state->root_argp : 0, state);
+ if (fstr && *fstr)
+ {
+ __argp_fmtstream_putc (stream, '\n');
+ __argp_fmtstream_puts (stream, fstr);
+ __argp_fmtstream_putc (stream, '\n');
+ }
+ if (fstr && fstr != tstr)
+ free ((char *) fstr);
+ }
+}
+
+/* Helper functions for hol_usage. */
+
+/* If OPT is a short option without an arg, append its key to the string
+ pointer pointer to by COOKIE, and advance the pointer. */
+static int
+add_argless_short_opt (const struct argp_option *opt,
+ const struct argp_option *real,
+ const char *domain, void *cookie)
+{
+ char **snao_end = cookie;
+ if (!(opt->arg || real->arg)
+ && !((opt->flags | real->flags) & OPTION_NO_USAGE))
+ *(*snao_end)++ = opt->key;
+ return 0;
+}
+
+/* If OPT is a short option with an arg, output a usage entry for it to the
+ stream pointed at by COOKIE. */
+static int
+usage_argful_short_opt (const struct argp_option *opt,
+ const struct argp_option *real,
+ const char *domain, void *cookie)
+{
+ argp_fmtstream_t stream = cookie;
+ const char *arg = opt->arg;
+ int flags = opt->flags | real->flags;
+
+ if (! arg)
+ arg = real->arg;
+
+ if (arg && !(flags & OPTION_NO_USAGE))
+ {
+ arg = dgettext (domain, arg);
+
+ if (flags & OPTION_ARG_OPTIONAL)
+ __argp_fmtstream_printf (stream, " [-%c[%s]]", opt->key, arg);
+ else
+ {
+ /* Manually do line wrapping so that it (probably) won't
+ get wrapped at the embedded space. */
+ space (stream, 6 + strlen (arg));
+ __argp_fmtstream_printf (stream, "[-%c %s]", opt->key, arg);
+ }
+ }
+
+ return 0;
+}
+
+/* Output a usage entry for the long option opt to the stream pointed at by
+ COOKIE. */
+static int
+usage_long_opt (const struct argp_option *opt,
+ const struct argp_option *real,
+ const char *domain, void *cookie)
+{
+ argp_fmtstream_t stream = cookie;
+ const char *arg = opt->arg;
+ int flags = opt->flags | real->flags;
+
+ if (! arg)
+ arg = real->arg;
+
+ if (! (flags & OPTION_NO_USAGE) && !odoc (opt))
+ {
+ if (arg)
+ {
+ arg = dgettext (domain, arg);
+ if (flags & OPTION_ARG_OPTIONAL)
+ __argp_fmtstream_printf (stream, " [--%s[=%s]]", opt->name, arg);
+ else
+ __argp_fmtstream_printf (stream, " [--%s=%s]", opt->name, arg);
+ }
+ else
+ __argp_fmtstream_printf (stream, " [--%s]", opt->name);
+ }
+
+ return 0;
+}
+
+/* Print a short usage description for the arguments in HOL to STREAM. */
+static void
+hol_usage (struct hol *hol, argp_fmtstream_t stream)
+{
+ if (hol->num_entries > 0)
+ {
+ unsigned nentries;
+ struct hol_entry *entry;
+ char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1);
+ char *snao_end = short_no_arg_opts;
+
+ /* First we put a list of short options without arguments. */
+ for (entry = hol->entries, nentries = hol->num_entries
+ ; nentries > 0
+ ; entry++, nentries--)
+ hol_entry_short_iterate (entry, add_argless_short_opt,
+ entry->argp->argp_domain, &snao_end);
+ if (snao_end > short_no_arg_opts)
+ {
+ *snao_end++ = 0;
+ __argp_fmtstream_printf (stream, " [-%s]", short_no_arg_opts);
+ }
+
+ /* Now a list of short options *with* arguments. */
+ for (entry = hol->entries, nentries = hol->num_entries
+ ; nentries > 0
+ ; entry++, nentries--)
+ hol_entry_short_iterate (entry, usage_argful_short_opt,
+ entry->argp->argp_domain, stream);
+
+ /* Finally, a list of long options (whew!). */
+ for (entry = hol->entries, nentries = hol->num_entries
+ ; nentries > 0
+ ; entry++, nentries--)
+ hol_entry_long_iterate (entry, usage_long_opt,
+ entry->argp->argp_domain, stream);
+ }
+}
+
+/* Make a HOL containing all levels of options in ARGP. CLUSTER is the
+ cluster in which ARGP's entries should be clustered, or 0. */
+static struct hol *
+argp_hol (const struct argp *argp, struct hol_cluster *cluster)
+{
+ const struct argp_child *child = argp->children;
+ struct hol *hol = make_hol (argp, cluster);
+ if (child)
+ while (child->argp)
+ {
+ struct hol_cluster *child_cluster =
+ ((child->group || child->header)
+ /* Put CHILD->argp within its own cluster. */
+ ? hol_add_cluster (hol, child->group, child->header,
+ child - argp->children, cluster, argp)
+ /* Just merge it into the parent's cluster. */
+ : cluster);
+ hol_append (hol, argp_hol (child->argp, child_cluster)) ;
+ child++;
+ }
+ return hol;
+}
+
+/* Calculate how many different levels with alternative args strings exist in
+ ARGP. */
+static size_t
+argp_args_levels (const struct argp *argp)
+{
+ size_t levels = 0;
+ const struct argp_child *child = argp->children;
+
+ if (argp->args_doc && strchr (argp->args_doc, '\n'))
+ levels++;
+
+ if (child)
+ while (child->argp)
+ levels += argp_args_levels ((child++)->argp);
+
+ return levels;
+}
+
+/* Print all the non-option args documented in ARGP to STREAM. Any output is
+ preceded by a space. LEVELS is a pointer to a byte vector the length
+ returned by argp_args_levels; it should be initialized to zero, and
+ updated by this routine for the next call if ADVANCE is true. True is
+ returned as long as there are more patterns to output. */
+static int
+argp_args_usage (const struct argp *argp, const struct argp_state *state,
+ char **levels, int advance, argp_fmtstream_t stream)
+{
+ char *our_level = *levels;
+ int multiple = 0;
+ const struct argp_child *child = argp->children;
+ const char *tdoc = dgettext (argp->argp_domain, argp->args_doc), *nl = 0;
+ const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC, argp, state);
+
+ if (fdoc)
+ {
+ const char *cp = fdoc;
+ nl = __strchrnul (cp, '\n');
+ if (*nl != '\0')
+ /* This is a `multi-level' args doc; advance to the correct position
+ as determined by our state in LEVELS, and update LEVELS. */
+ {
+ int i;
+ multiple = 1;
+ for (i = 0; i < *our_level; i++)
+ cp = nl + 1, nl = __strchrnul (cp, '\n');
+ (*levels)++;
+ }
+
+ /* Manually do line wrapping so that it (probably) won't get wrapped at
+ any embedded spaces. */
+ space (stream, 1 + nl - cp);
+
+ __argp_fmtstream_write (stream, cp, nl - cp);
+ }
+ if (fdoc && fdoc != tdoc)
+ free ((char *)fdoc); /* Free user's modified doc string. */
+
+ if (child)
+ while (child->argp)
+ advance = !argp_args_usage ((child++)->argp, state, levels, advance, stream);
+
+ if (advance && multiple)
+ {
+ /* Need to increment our level. */
+ if (*nl)
+ /* There's more we can do here. */
+ {
+ (*our_level)++;
+ advance = 0; /* Our parent shouldn't advance also. */
+ }
+ else if (*our_level > 0)
+ /* We had multiple levels, but used them up; reset to zero. */
+ *our_level = 0;
+ }
+
+ return !advance;
+}
+
+/* Print the documentation for ARGP to STREAM; if POST is false, then
+ everything preceeding a `\v' character in the documentation strings (or
+ the whole string, for those with none) is printed, otherwise, everything
+ following the `\v' character (nothing for strings without). Each separate
+ bit of documentation is separated a blank line, and if PRE_BLANK is true,
+ then the first is as well. If FIRST_ONLY is true, only the first
+ occurrence is output. Returns true if anything was output. */
+static int
+argp_doc (const struct argp *argp, const struct argp_state *state,
+ int post, int pre_blank, int first_only,
+ argp_fmtstream_t stream)
+{
+ const char *text;
+ const char *inp_text;
+ size_t inp_text_len = 0;
+ const char *trans_text;
+ void *input = 0;
+ int anything = 0;
+ const struct argp_child *child = argp->children;
+
+ if (argp->doc)
+ {
+ char *vt = strchr (argp->doc, '\v');
+ if (vt)
+ {
+ if (post)
+ inp_text = vt + 1;
+ else
+ {
+ inp_text_len = vt - argp->doc;
+ inp_text = __strndup (argp->doc, inp_text_len);
+ }
+ }
+ else
+ inp_text = post ? 0 : argp->doc;
+ trans_text = inp_text ? dgettext (argp->argp_domain, inp_text) : NULL;
+ }
+ else
+ trans_text = inp_text = 0;
+
+ if (argp->help_filter)
+ /* We have to filter the doc strings. */
+ {
+ input = __argp_input (argp, state);
+ text =
+ (*argp->help_filter) (post
+ ? ARGP_KEY_HELP_POST_DOC
+ : ARGP_KEY_HELP_PRE_DOC,
+ trans_text, input);
+ }
+ else
+ text = (const char *) trans_text;
+
+ if (text)
+ {
+ if (pre_blank)
+ __argp_fmtstream_putc (stream, '\n');
+
+ __argp_fmtstream_puts (stream, text);
+
+ if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream))
+ __argp_fmtstream_putc (stream, '\n');
+
+ anything = 1;
+ }
+
+ if (text && text != trans_text)
+ free ((char *) text); /* Free TEXT returned from the help filter. */
+
+ if (inp_text && inp_text_len)
+ free ((char *) inp_text); /* We copied INP_TEXT, so free it now. */
+
+ if (post && argp->help_filter)
+ /* Now see if we have to output a ARGP_KEY_HELP_EXTRA text. */
+ {
+ text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input);
+ if (text)
+ {
+ if (anything || pre_blank)
+ __argp_fmtstream_putc (stream, '\n');
+ __argp_fmtstream_puts (stream, text);
+ free ((char *) text);
+ if (__argp_fmtstream_point (stream)
+ > __argp_fmtstream_lmargin (stream))
+ __argp_fmtstream_putc (stream, '\n');
+ anything = 1;
+ }
+ }
+
+ if (child)
+ while (child->argp && !(first_only && anything))
+ anything |=
+ argp_doc ((child++)->argp, state,
+ post, anything || pre_blank, first_only,
+ stream);
+
+ return anything;
+}
+
+/* Output a usage message for ARGP to STREAM. If called from
+ argp_state_help, STATE is the relevent parsing state. FLAGS are from the
+ set ARGP_HELP_*. NAME is what to use wherever a `program name' is
+ needed. */
+static void
+_help (const struct argp *argp, const struct argp_state *state, FILE *stream,
+ unsigned flags, char *name)
+{
+ int anything = 0; /* Whether we've output anything. */
+ struct hol *hol = 0;
+ argp_fmtstream_t fs;
+
+ if (! stream)
+ return;
+
+#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
+ __flockfile (stream);
+#endif
+
+ if (! uparams.valid)
+ fill_in_uparams (state);
+
+ fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0);
+ if (! fs)
+ {
+#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
+ __funlockfile (stream);
+#endif
+ return;
+ }
+
+ if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG))
+ {
+ hol = argp_hol (argp, 0);
+
+ /* If present, these options always come last. */
+ hol_set_group (hol, "help", -1);
+ hol_set_group (hol, "version", -1);
+
+ hol_sort (hol);
+ }
+
+ if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE))
+ /* Print a short `Usage:' message. */
+ {
+ int first_pattern = 1, more_patterns;
+ size_t num_pattern_levels = argp_args_levels (argp);
+ char *pattern_levels = alloca (num_pattern_levels);
+
+ memset (pattern_levels, 0, num_pattern_levels);
+
+ do
+ {
+ int old_lm;
+ int old_wm = __argp_fmtstream_set_wmargin (fs, uparams.usage_indent);
+ char *levels = pattern_levels;
+
+ if (first_pattern)
+ __argp_fmtstream_printf (fs, "%s %s",
+ dgettext (argp->argp_domain, "Usage:"),
+ name);
+ else
+ __argp_fmtstream_printf (fs, "%s %s",
+ dgettext (argp->argp_domain, " or: "),
+ name);
+
+ /* We set the lmargin as well as the wmargin, because hol_usage
+ manually wraps options with newline to avoid annoying breaks. */
+ old_lm = __argp_fmtstream_set_lmargin (fs, uparams.usage_indent);
+
+ if (flags & ARGP_HELP_SHORT_USAGE)
+ /* Just show where the options go. */
+ {
+ if (hol->num_entries > 0)
+ __argp_fmtstream_puts (fs, dgettext (argp->argp_domain,
+ " [OPTION...]"));
+ }
+ else
+ /* Actually print the options. */
+ {
+ hol_usage (hol, fs);
+ flags |= ARGP_HELP_SHORT_USAGE; /* But only do so once. */
+ }
+
+ more_patterns = argp_args_usage (argp, state, &levels, 1, fs);
+
+ __argp_fmtstream_set_wmargin (fs, old_wm);
+ __argp_fmtstream_set_lmargin (fs, old_lm);
+
+ __argp_fmtstream_putc (fs, '\n');
+ anything = 1;
+
+ first_pattern = 0;
+ }
+ while (more_patterns);
+ }
+
+ if (flags & ARGP_HELP_PRE_DOC)
+ anything |= argp_doc (argp, state, 0, 0, 1, fs);
+
+ if (flags & ARGP_HELP_SEE)
+ {
+ __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, "\
+Try `%s --help' or `%s --usage' for more information.\n"),
+ name, name);
+ anything = 1;
+ }
+
+ if (flags & ARGP_HELP_LONG)
+ /* Print a long, detailed help message. */
+ {
+ /* Print info about all the options. */
+ if (hol->num_entries > 0)
+ {
+ if (anything)
+ __argp_fmtstream_putc (fs, '\n');
+ hol_help (hol, state, fs);
+ anything = 1;
+ }
+ }
+
+ if (flags & ARGP_HELP_POST_DOC)
+ /* Print any documentation strings at the end. */
+ anything |= argp_doc (argp, state, 1, anything, 0, fs);
+
+ if ((flags & ARGP_HELP_BUG_ADDR) && argp_program_bug_address)
+ {
+ if (anything)
+ __argp_fmtstream_putc (fs, '\n');
+ __argp_fmtstream_printf (fs, dgettext (argp->argp_domain,
+ "Report bugs to %s.\n"),
+ argp_program_bug_address);
+ anything = 1;
+ }
+
+#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
+ __funlockfile (stream);
+#endif
+
+ if (hol)
+ hol_free (hol);
+
+ __argp_fmtstream_free (fs);
+}
+
+/* Output a usage message for ARGP to STREAM. FLAGS are from the set
+ ARGP_HELP_*. NAME is what to use wherever a `program name' is needed. */
+void __argp_help (const struct argp *argp, FILE *stream,
+ unsigned flags, char *name)
+{
+ struct argp_state state;
+ memset (&state, 0, sizeof state);
+ state.root_argp = argp;
+ _help (argp, &state, stream, flags, name);
+}
+#ifdef weak_alias
+weak_alias (__argp_help, argp_help)
+#endif
+
+#if ! (defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME)
+char *
+__argp_short_program_name (void)
+{
+# if HAVE_DECL_PROGRAM_INVOCATION_NAME
+ return __argp_base_name (program_invocation_name);
+# else
+ /* FIXME: What now? Miles suggests that it is better to use NULL,
+ but currently the value is passed on directly to fputs_unlocked,
+ so that requires more changes. */
+# if __GNUC__
+# warning No reasonable value to return
+# endif /* __GNUC__ */
+ return "";
+# endif
+}
+#endif
+
+/* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are
+ from the set ARGP_HELP_*. */
+void
+__argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags)
+{
+ if ((!state || ! (state->flags & ARGP_NO_ERRS)) && stream)
+ {
+ if (state && (state->flags & ARGP_LONG_ONLY))
+ flags |= ARGP_HELP_LONG_ONLY;
+
+ _help (state ? state->root_argp : 0, state, stream, flags,
+ state ? state->name : __argp_short_program_name ());
+
+ if (!state || ! (state->flags & ARGP_NO_EXIT))
+ {
+ if (flags & ARGP_HELP_EXIT_ERR)
+ exit (argp_err_exit_status);
+ if (flags & ARGP_HELP_EXIT_OK)
+ exit (0);
+ }
+ }
+}
+#ifdef weak_alias
+weak_alias (__argp_state_help, argp_state_help)
+#endif
+
+/* If appropriate, print the printf string FMT and following args, preceded
+ by the program name and `:', to stderr, and followed by a `Try ... --help'
+ message, then exit (1). */
+void
+__argp_error (const struct argp_state *state, const char *fmt, ...)
+{
+ if (!state || !(state->flags & ARGP_NO_ERRS))
+ {
+ FILE *stream = state ? state->err_stream : stderr;
+
+ if (stream)
+ {
+ va_list ap;
+
+#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
+ __flockfile (stream);
+#endif
+
+ va_start (ap, fmt);
+
+#ifdef USE_IN_LIBIO
+ if (_IO_fwide (stream, 0) > 0)
+ {
+ char *buf;
+
+ if (__asprintf (&buf, fmt, ap) < 0)
+ buf = NULL;
+
+ __fwprintf (stream, L"%s: %s\n",
+ state ? state->name : __argp_short_program_name (),
+ buf);
+
+ free (buf);
+ }
+ else
+#endif
+ {
+ fputs_unlocked (state
+ ? state->name : __argp_short_program_name (),
+ stream);
+ putc_unlocked (':', stream);
+ putc_unlocked (' ', stream);
+
+ vfprintf (stream, fmt, ap);
+
+ putc_unlocked ('\n', stream);
+ }
+
+ __argp_state_help (state, stream, ARGP_HELP_STD_ERR);
+
+ va_end (ap);
+
+#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
+ __funlockfile (stream);
+#endif
+ }
+ }
+}
+#ifdef weak_alias
+weak_alias (__argp_error, argp_error)
+#endif
+
+/* Similar to the standard gnu error-reporting function error(), but will
+ respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print
+ to STATE->err_stream. This is useful for argument parsing code that is
+ shared between program startup (when exiting is desired) and runtime
+ option parsing (when typically an error code is returned instead). The
+ difference between this function and argp_error is that the latter is for
+ *parsing errors*, and the former is for other problems that occur during
+ parsing but don't reflect a (syntactic) problem with the input. */
+void
+__argp_failure (const struct argp_state *state, int status, int errnum,
+ const char *fmt, ...)
+{
+ if (!state || !(state->flags & ARGP_NO_ERRS))
+ {
+ FILE *stream = state ? state->err_stream : stderr;
+
+ if (stream)
+ {
+#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
+ __flockfile (stream);
+#endif
+
+#ifdef USE_IN_LIBIO
+ if (_IO_fwide (stream, 0) > 0)
+ __fwprintf (stream, L"%s",
+ state ? state->name : __argp_short_program_name ());
+ else
+#endif
+ fputs_unlocked (state
+ ? state->name : __argp_short_program_name (),
+ stream);
+
+ if (fmt)
+ {
+ va_list ap;
+
+ va_start (ap, fmt);
+#ifdef USE_IN_LIBIO
+ if (_IO_fwide (stream, 0) > 0)
+ {
+ char *buf;
+
+ if (__asprintf (&buf, fmt, ap) < 0)
+ buf = NULL;
+
+ __fwprintf (stream, L": %s", buf);
+
+ free (buf);
+ }
+ else
+#endif
+ {
+ putc_unlocked (':', stream);
+ putc_unlocked (' ', stream);
+
+ vfprintf (stream, fmt, ap);
+ }
+
+ va_end (ap);
+ }
+
+ if (errnum)
+ {
+ char buf[200];
+
+#ifdef USE_IN_LIBIO
+ if (_IO_fwide (stream, 0) > 0)
+ __fwprintf (stream, L": %s",
+ __strerror_r (errnum, buf, sizeof (buf)));
+ else
+#endif
+ {
+ char const *s = NULL;
+ putc_unlocked (':', stream);
+ putc_unlocked (' ', stream);
+#if _LIBC || (HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P)
+ s = __strerror_r (errnum, buf, sizeof buf);
+#elif HAVE_DECL_STRERROR_R
+ if (__strerror_r (errnum, buf, sizeof buf) == 0)
+ s = buf;
+#endif
+#if !_LIBC
+ if (! s && ! (s = strerror (errnum)))
+ s = dgettext (state->root_argp->argp_domain,
+ "Unknown system error");
+#endif
+ fputs (s, stream);
+ }
+ }
+
+#ifdef USE_IN_LIBIO
+ if (_IO_fwide (stream, 0) > 0)
+ putwc_unlocked (L'\n', stream);
+ else
+#endif
+ putc_unlocked ('\n', stream);
+
+#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
+ __funlockfile (stream);
+#endif
+
+ if (status && (!state || !(state->flags & ARGP_NO_EXIT)))
+ exit (status);
+ }
+ }
+}
+#ifdef weak_alias
+weak_alias (__argp_failure, argp_failure)
+#endif
diff --git a/lib/argp-namefrob.h b/lib/argp-namefrob.h
new file mode 100644
index 0000000..6fe99cd
--- /dev/null
+++ b/lib/argp-namefrob.h
@@ -0,0 +1,158 @@
+/* Name frobnication for compiling argp outside of glibc
+ Copyright (C) 1997, 2003, 2007 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#if !_LIBC
+/* This code is written for inclusion in gnu-libc, and uses names in the
+ namespace reserved for libc. If we're not compiling in libc, define those
+ names to be the normal ones instead. */
+
+/* argp-parse functions */
+#undef __argp_parse
+#define __argp_parse argp_parse
+#undef __option_is_end
+#define __option_is_end _option_is_end
+#undef __option_is_short
+#define __option_is_short _option_is_short
+#undef __argp_input
+#define __argp_input _argp_input
+
+/* argp-help functions */
+#undef __argp_help
+#define __argp_help argp_help
+#undef __argp_error
+#define __argp_error argp_error
+#undef __argp_failure
+#define __argp_failure argp_failure
+#undef __argp_state_help
+#define __argp_state_help argp_state_help
+#undef __argp_usage
+#define __argp_usage argp_usage
+
+/* argp-fmtstream functions */
+#undef __argp_make_fmtstream
+#define __argp_make_fmtstream argp_make_fmtstream
+#undef __argp_fmtstream_free
+#define __argp_fmtstream_free argp_fmtstream_free
+#undef __argp_fmtstream_putc
+#define __argp_fmtstream_putc argp_fmtstream_putc
+#undef __argp_fmtstream_puts
+#define __argp_fmtstream_puts argp_fmtstream_puts
+#undef __argp_fmtstream_write
+#define __argp_fmtstream_write argp_fmtstream_write
+#undef __argp_fmtstream_printf
+#define __argp_fmtstream_printf argp_fmtstream_printf
+#undef __argp_fmtstream_set_lmargin
+#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin
+#undef __argp_fmtstream_set_rmargin
+#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin
+#undef __argp_fmtstream_set_wmargin
+#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin
+#undef __argp_fmtstream_point
+#define __argp_fmtstream_point argp_fmtstream_point
+#undef __argp_fmtstream_update
+#define __argp_fmtstream_update _argp_fmtstream_update
+#undef __argp_fmtstream_ensure
+#define __argp_fmtstream_ensure _argp_fmtstream_ensure
+#undef __argp_fmtstream_lmargin
+#define __argp_fmtstream_lmargin argp_fmtstream_lmargin
+#undef __argp_fmtstream_rmargin
+#define __argp_fmtstream_rmargin argp_fmtstream_rmargin
+#undef __argp_fmtstream_wmargin
+#define __argp_fmtstream_wmargin argp_fmtstream_wmargin
+
+/* normal libc functions we call */
+#undef __flockfile
+#define __flockfile flockfile
+#undef __funlockfile
+#define __funlockfile funlockfile
+#undef __mempcpy
+#define __mempcpy mempcpy
+#undef __sleep
+#define __sleep sleep
+#undef __strcasecmp
+#define __strcasecmp strcasecmp
+#undef __strchrnul
+#define __strchrnul strchrnul
+#undef __strerror_r
+#define __strerror_r strerror_r
+#undef __strndup
+#define __strndup strndup
+#undef __vsnprintf
+#define __vsnprintf vsnprintf
+
+#if defined(HAVE_DECL_CLEARERR_UNLOCKED) && !HAVE_DECL_CLEARERR_UNLOCKED
+# define clearerr_unlocked(x) clearerr (x)
+#endif
+#if defined(HAVE_DECL_FEOF_UNLOCKED) && !HAVE_DECL_FEOF_UNLOCKED
+# define feof_unlocked(x) feof (x)
+# endif
+#if defined(HAVE_DECL_FERROR_UNLOCKED) && !HAVE_DECL_FERROR_UNLOCKED
+# define ferror_unlocked(x) ferror (x)
+# endif
+#if defined(HAVE_DECL_FFLUSH_UNLOCKED) && !HAVE_DECL_FFLUSH_UNLOCKED
+# define fflush_unlocked(x) fflush (x)
+# endif
+#if defined(HAVE_DECL_FGETS_UNLOCKED) && !HAVE_DECL_FGETS_UNLOCKED
+# define fgets_unlocked(x,y,z) fgets (x,y,z)
+# endif
+#if defined(HAVE_DECL_FPUTC_UNLOCKED) && !HAVE_DECL_FPUTC_UNLOCKED
+# define fputc_unlocked(x,y) fputc (x,y)
+# endif
+#if defined(HAVE_DECL_FPUTS_UNLOCKED) && !HAVE_DECL_FPUTS_UNLOCKED
+# define fputs_unlocked(x,y) fputs (x,y)
+# endif
+#if defined(HAVE_DECL_FREAD_UNLOCKED) && !HAVE_DECL_FREAD_UNLOCKED
+# define fread_unlocked(w,x,y,z) fread (w,x,y,z)
+# endif
+#if defined(HAVE_DECL_FWRITE_UNLOCKED) && !HAVE_DECL_FWRITE_UNLOCKED
+# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
+# endif
+#if defined(HAVE_DECL_GETC_UNLOCKED) && !HAVE_DECL_GETC_UNLOCKED
+# define getc_unlocked(x) getc (x)
+# endif
+#if defined(HAVE_DECL_GETCHAR_UNLOCKED) && !HAVE_DECL_GETCHAR_UNLOCKED
+# define getchar_unlocked() getchar ()
+# endif
+#if defined(HAVE_DECL_PUTC_UNLOCKED) && !HAVE_DECL_PUTC_UNLOCKED
+# define putc_unlocked(x,y) putc (x,y)
+# endif
+#if defined(HAVE_DECL_PUTCHAR_UNLOCKED) && !HAVE_DECL_PUTCHAR_UNLOCKED
+# define putchar_unlocked(x) putchar (x)
+# endif
+
+#endif /* !_LIBC */
+
+#ifndef __set_errno
+#define __set_errno(e) (errno = (e))
+#endif
+
+#if defined GNULIB_ARGP_DISABLE_DIRNAME
+# define __argp_base_name(arg) arg
+#elif defined GNULIB_ARGP_EXTERN_BASENAME
+extern char *__argp_base_name(const char *arg);
+#else
+# include "dirname.h"
+# define __argp_base_name base_name
+#endif
+
+#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
+# define __argp_short_program_name() (program_invocation_short_name)
+#else
+extern char *__argp_short_program_name (void);
+#endif
diff --git a/lib/argp-parse.c b/lib/argp-parse.c
new file mode 100644
index 0000000..a7de729
--- /dev/null
+++ b/lib/argp-parse.c
@@ -0,0 +1,953 @@
+/* Hierarchial argument parsing, layered over getopt
+ Copyright (C) 1995-2000, 2002, 2003, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <alloca.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <getopt.h>
+#include <getopt_int.h>
+
+#ifdef _LIBC
+# include <libintl.h>
+# undef dgettext
+# define dgettext(domain, msgid) \
+ INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES)
+#else
+# include "gettext.h"
+#endif
+#define N_(msgid) msgid
+
+#include "argp.h"
+#include "argp-namefrob.h"
+
+#define alignof(type) offsetof (struct { char c; type x; }, x)
+#define alignto(n, d) ((((n) + (d) - 1) / (d)) * (d))
+
+/* Getopt return values. */
+#define KEY_END (-1) /* The end of the options. */
+#define KEY_ARG 1 /* A non-option argument. */
+#define KEY_ERR '?' /* An error parsing the options. */
+
+/* The meta-argument used to prevent any further arguments being interpreted
+ as options. */
+#define QUOTE "--"
+
+/* The number of bits we steal in a long-option value for our own use. */
+#define GROUP_BITS CHAR_BIT
+
+/* The number of bits available for the user value. */
+#define USER_BITS ((sizeof ((struct option *)0)->val * CHAR_BIT) - GROUP_BITS)
+#define USER_MASK ((1 << USER_BITS) - 1)
+
+/* EZ alias for ARGP_ERR_UNKNOWN. */
+#define EBADKEY ARGP_ERR_UNKNOWN
+
+/* Default options. */
+
+/* When argp is given the --HANG switch, _ARGP_HANG is set and argp will sleep
+ for one second intervals, decrementing _ARGP_HANG until it's zero. Thus
+ you can force the program to continue by attaching a debugger and setting
+ it to 0 yourself. */
+static volatile int _argp_hang;
+
+#define OPT_PROGNAME -2
+#define OPT_USAGE -3
+#define OPT_HANG -4
+
+static const struct argp_option argp_default_options[] =
+{
+ {"help", '?', 0, 0, N_("give this help list"), -1},
+ {"usage", OPT_USAGE, 0, 0, N_("give a short usage message"), 0},
+ {"program-name",OPT_PROGNAME,N_("NAME"), OPTION_HIDDEN, N_("set the program name"), 0},
+ {"HANG", OPT_HANG, N_("SECS"), OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
+ N_("hang for SECS seconds (default 3600)"), 0},
+ {NULL, 0, 0, 0, NULL, 0}
+};
+
+static error_t
+argp_default_parser (int key, char *arg, struct argp_state *state)
+{
+ switch (key)
+ {
+ case '?':
+ __argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP);
+ break;
+ case OPT_USAGE:
+ __argp_state_help (state, state->out_stream,
+ ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
+ break;
+
+ case OPT_PROGNAME: /* Set the program name. */
+#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_NAME
+ program_invocation_name = arg;
+#endif
+ /* [Note that some systems only have PROGRAM_INVOCATION_SHORT_NAME (aka
+ __PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined
+ to be that, so we have to be a bit careful here.] */
+
+ /* Update what we use for messages. */
+ state->name = __argp_base_name (arg);
+
+#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
+ program_invocation_short_name = state->name;
+#endif
+
+ if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS))
+ == ARGP_PARSE_ARGV0)
+ /* Update what getopt uses too. */
+ state->argv[0] = arg;
+
+ break;
+
+ case OPT_HANG:
+ _argp_hang = atoi (arg ? arg : "3600");
+ while (_argp_hang-- > 0)
+ __sleep (1);
+ break;
+
+ default:
+ return EBADKEY;
+ }
+ return 0;
+}
+
+static const struct argp argp_default_argp =
+ {argp_default_options, &argp_default_parser, NULL, NULL, NULL, NULL, "libc"};
+
+
+static const struct argp_option argp_version_options[] =
+{
+ {"version", 'V', 0, 0, N_("print program version"), -1},
+ {NULL, 0, 0, 0, NULL, 0}
+};
+
+static error_t
+argp_version_parser (int key, char *arg, struct argp_state *state)
+{
+ switch (key)
+ {
+ case 'V':
+ if (argp_program_version_hook)
+ (*argp_program_version_hook) (state->out_stream, state);
+ else if (argp_program_version)
+ fprintf (state->out_stream, "%s\n", argp_program_version);
+ else
+ __argp_error (state, dgettext (state->root_argp->argp_domain,
+ "(PROGRAM ERROR) No version known!?"));
+ if (! (state->flags & ARGP_NO_EXIT))
+ exit (0);
+ break;
+ default:
+ return EBADKEY;
+ }
+ return 0;
+}
+
+static const struct argp argp_version_argp =
+ {argp_version_options, &argp_version_parser, NULL, NULL, NULL, NULL, "libc"};
+
+/* Returns the offset into the getopt long options array LONG_OPTIONS of a
+ long option with called NAME, or -1 if none is found. Passing NULL as
+ NAME will return the number of options. */
+static int
+find_long_option (struct option *long_options, const char *name)
+{
+ struct option *l = long_options;
+ while (l->name != NULL)
+ if (name != NULL && strcmp (l->name, name) == 0)
+ return l - long_options;
+ else
+ l++;
+ if (name == NULL)
+ return l - long_options;
+ else
+ return -1;
+}
+
+
+/* The state of a `group' during parsing. Each group corresponds to a
+ particular argp structure from the tree of such descending from the top
+ level argp passed to argp_parse. */
+struct group
+{
+ /* This group's parsing function. */
+ argp_parser_t parser;
+
+ /* Which argp this group is from. */
+ const struct argp *argp;
+
+ /* Points to the point in SHORT_OPTS corresponding to the end of the short
+ options for this group. We use it to determine from which group a
+ particular short options is from. */
+ char *short_end;
+
+ /* The number of non-option args sucessfully handled by this parser. */
+ unsigned args_processed;
+
+ /* This group's parser's parent's group. */
+ struct group *parent;
+ unsigned parent_index; /* And the our position in the parent. */
+
+ /* These fields are swapped into and out of the state structure when
+ calling this group's parser. */
+ void *input, **child_inputs;
+ void *hook;
+};
+
+/* Call GROUP's parser with KEY and ARG, swapping any group-specific info
+ from STATE before calling, and back into state afterwards. If GROUP has
+ no parser, EBADKEY is returned. */
+static error_t
+group_parse (struct group *group, struct argp_state *state, int key, char *arg)
+{
+ if (group->parser)
+ {
+ error_t err;
+ state->hook = group->hook;
+ state->input = group->input;
+ state->child_inputs = group->child_inputs;
+ state->arg_num = group->args_processed;
+ err = (*group->parser)(key, arg, state);
+ group->hook = state->hook;
+ return err;
+ }
+ else
+ return EBADKEY;
+}
+
+struct parser
+{
+ const struct argp *argp;
+
+ /* SHORT_OPTS is the getopt short options string for the union of all the
+ groups of options. */
+ char *short_opts;
+ /* LONG_OPTS is the array of getop long option structures for the union of
+ all the groups of options. */
+ struct option *long_opts;
+ /* OPT_DATA is the getopt data used for the re-entrant getopt. */
+ struct _getopt_data opt_data;
+
+ /* States of the various parsing groups. */
+ struct group *groups;
+ /* The end of the GROUPS array. */
+ struct group *egroup;
+ /* An vector containing storage for the CHILD_INPUTS field in all groups. */
+ void **child_inputs;
+
+ /* True if we think using getopt is still useful; if false, then
+ remaining arguments are just passed verbatim with ARGP_KEY_ARG. This is
+ cleared whenever getopt returns KEY_END, but may be set again if the user
+ moves the next argument pointer backwards. */
+ int try_getopt;
+
+ /* State block supplied to parsing routines. */
+ struct argp_state state;
+
+ /* Memory used by this parser. */
+ void *storage;
+};
+
+/* The next usable entries in the various parser tables being filled in by
+ convert_options. */
+struct parser_convert_state
+{
+ struct parser *parser;
+ char *short_end;
+ struct option *long_end;
+ void **child_inputs_end;
+};
+
+/* Converts all options in ARGP (which is put in GROUP) and ancestors
+ into getopt options stored in SHORT_OPTS and LONG_OPTS; SHORT_END and
+ CVT->LONG_END are the points at which new options are added. Returns the
+ next unused group entry. CVT holds state used during the conversion. */
+static struct group *
+convert_options (const struct argp *argp,
+ struct group *parent, unsigned parent_index,
+ struct group *group, struct parser_convert_state *cvt)
+{
+ /* REAL is the most recent non-alias value of OPT. */
+ const struct argp_option *real = argp->options;
+ const struct argp_child *children = argp->children;
+
+ if (real || argp->parser)
+ {
+ const struct argp_option *opt;
+
+ if (real)
+ for (opt = real; !__option_is_end (opt); opt++)
+ {
+ if (! (opt->flags & OPTION_ALIAS))
+ /* OPT isn't an alias, so we can use values from it. */
+ real = opt;
+
+ if (! (real->flags & OPTION_DOC))
+ /* A real option (not just documentation). */
+ {
+ if (__option_is_short (opt))
+ /* OPT can be used as a short option. */
+ {
+ *cvt->short_end++ = opt->key;
+ if (real->arg)
+ {
+ *cvt->short_end++ = ':';
+ if (real->flags & OPTION_ARG_OPTIONAL)
+ *cvt->short_end++ = ':';
+ }
+ *cvt->short_end = '\0'; /* keep 0 terminated */
+ }
+
+ if (opt->name
+ && find_long_option (cvt->parser->long_opts, opt->name) < 0)
+ /* OPT can be used as a long option. */
+ {
+ cvt->long_end->name = opt->name;
+ cvt->long_end->has_arg =
+ (real->arg
+ ? (real->flags & OPTION_ARG_OPTIONAL
+ ? optional_argument
+ : required_argument)
+ : no_argument);
+ cvt->long_end->flag = 0;
+ /* we add a disambiguating code to all the user's
+ values (which is removed before we actually call
+ the function to parse the value); this means that
+ the user loses use of the high 8 bits in all his
+ values (the sign of the lower bits is preserved
+ however)... */
+ cvt->long_end->val =
+ ((opt->key | real->key) & USER_MASK)
+ + (((group - cvt->parser->groups) + 1) << USER_BITS);
+
+ /* Keep the LONG_OPTS list terminated. */
+ (++cvt->long_end)->name = NULL;
+ }
+ }
+ }
+
+ group->parser = argp->parser;
+ group->argp = argp;
+ group->short_end = cvt->short_end;
+ group->args_processed = 0;
+ group->parent = parent;
+ group->parent_index = parent_index;
+ group->input = 0;
+ group->hook = 0;
+ group->child_inputs = 0;
+
+ if (children)
+ /* Assign GROUP's CHILD_INPUTS field some space from
+ CVT->child_inputs_end.*/
+ {
+ unsigned num_children = 0;
+ while (children[num_children].argp)
+ num_children++;
+ group->child_inputs = cvt->child_inputs_end;
+ cvt->child_inputs_end += num_children;
+ }
+
+ parent = group++;
+ }
+ else
+ parent = 0;
+
+ if (children)
+ {
+ unsigned index = 0;
+ while (children->argp)
+ group =
+ convert_options (children++->argp, parent, index++, group, cvt);
+ }
+
+ return group;
+}
+
+/* Find the merged set of getopt options, with keys appropiately prefixed. */
+static void
+parser_convert (struct parser *parser, const struct argp *argp, int flags)
+{
+ struct parser_convert_state cvt;
+
+ cvt.parser = parser;
+ cvt.short_end = parser->short_opts;
+ cvt.long_end = parser->long_opts;
+ cvt.child_inputs_end = parser->child_inputs;
+
+ if (flags & ARGP_IN_ORDER)
+ *cvt.short_end++ = '-';
+ else if (flags & ARGP_NO_ARGS)
+ *cvt.short_end++ = '+';
+ *cvt.short_end = '\0';
+
+ cvt.long_end->name = NULL;
+
+ parser->argp = argp;
+
+ if (argp)
+ parser->egroup = convert_options (argp, 0, 0, parser->groups, &cvt);
+ else
+ parser->egroup = parser->groups; /* No parsers at all! */
+}
+
+/* Lengths of various parser fields which we will allocated. */
+struct parser_sizes
+{
+ size_t short_len; /* Getopt short options string. */
+ size_t long_len; /* Getopt long options vector. */
+ size_t num_groups; /* Group structures we allocate. */
+ size_t num_child_inputs; /* Child input slots. */
+};
+
+/* For ARGP, increments the NUM_GROUPS field in SZS by the total number of
+ argp structures descended from it, and the SHORT_LEN & LONG_LEN fields by
+ the maximum lengths of the resulting merged getopt short options string and
+ long-options array, respectively. */
+static void
+calc_sizes (const struct argp *argp, struct parser_sizes *szs)
+{
+ const struct argp_child *child = argp->children;
+ const struct argp_option *opt = argp->options;
+
+ if (opt || argp->parser)
+ {
+ szs->num_groups++;
+ if (opt)
+ {
+ int num_opts = 0;
+ while (!__option_is_end (opt++))
+ num_opts++;
+ szs->short_len += num_opts * 3; /* opt + up to 2 `:'s */
+ szs->long_len += num_opts;
+ }
+ }
+
+ if (child)
+ while (child->argp)
+ {
+ calc_sizes ((child++)->argp, szs);
+ szs->num_child_inputs++;
+ }
+}
+
+/* Initializes PARSER to parse ARGP in a manner described by FLAGS. */
+static error_t
+parser_init (struct parser *parser, const struct argp *argp,
+ int argc, char **argv, int flags, void *input)
+{
+ error_t err = 0;
+ struct group *group;
+ struct parser_sizes szs;
+ struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER;
+ char *storage;
+ size_t glen, gsum;
+ size_t clen, csum;
+ size_t llen, lsum;
+ size_t slen, ssum;
+
+ szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1;
+ szs.long_len = 0;
+ szs.num_groups = 0;
+ szs.num_child_inputs = 0;
+
+ if (argp)
+ calc_sizes (argp, &szs);
+
+ /* Lengths of the various bits of storage used by PARSER. */
+ glen = (szs.num_groups + 1) * sizeof (struct group);
+ clen = szs.num_child_inputs * sizeof (void *);
+ llen = (szs.long_len + 1) * sizeof (struct option);
+ slen = szs.short_len + 1;
+
+ /* Sums of previous lengths, properly aligned. There's no need to
+ align gsum, since struct group is aligned at least as strictly as
+ void * (since it contains a void * member). And there's no need
+ to align lsum, since struct option is aligned at least as
+ strictly as char. */
+ gsum = glen;
+ csum = alignto (gsum + clen, alignof (struct option));
+ lsum = csum + llen;
+ ssum = lsum + slen;
+
+ parser->storage = malloc (ssum);
+ if (! parser->storage)
+ return ENOMEM;
+
+ storage = parser->storage;
+ parser->groups = parser->storage;
+ parser->child_inputs = (void **) (storage + gsum);
+ parser->long_opts = (struct option *) (storage + csum);
+ parser->short_opts = storage + lsum;
+ parser->opt_data = opt_data;
+
+ memset (parser->child_inputs, 0, clen);
+ parser_convert (parser, argp, flags);
+
+ memset (&parser->state, 0, sizeof (struct argp_state));
+ parser->state.root_argp = parser->argp;
+ parser->state.argc = argc;
+ parser->state.argv = argv;
+ parser->state.flags = flags;
+ parser->state.err_stream = stderr;
+ parser->state.out_stream = stdout;
+ parser->state.next = 0; /* Tell getopt to initialize. */
+ parser->state.pstate = parser;
+
+ parser->try_getopt = 1;
+
+ /* Call each parser for the first time, giving it a chance to propagate
+ values to child parsers. */
+ if (parser->groups < parser->egroup)
+ parser->groups->input = input;
+ for (group = parser->groups;
+ group < parser->egroup && (!err || err == EBADKEY);
+ group++)
+ {
+ if (group->parent)
+ /* If a child parser, get the initial input value from the parent. */
+ group->input = group->parent->child_inputs[group->parent_index];
+
+ if (!group->parser
+ && group->argp->children && group->argp->children->argp)
+ /* For the special case where no parsing function is supplied for an
+ argp, propagate its input to its first child, if any (this just
+ makes very simple wrapper argps more convenient). */
+ group->child_inputs[0] = group->input;
+
+ err = group_parse (group, &parser->state, ARGP_KEY_INIT, 0);
+ }
+ if (err == EBADKEY)
+ err = 0; /* Some parser didn't understand. */
+
+ if (err)
+ return err;
+
+ if (parser->state.flags & ARGP_NO_ERRS)
+ {
+ parser->opt_data.opterr = 0;
+ if (parser->state.flags & ARGP_PARSE_ARGV0)
+ /* getopt always skips ARGV[0], so we have to fake it out. As long
+ as OPTERR is 0, then it shouldn't actually try to access it. */
+ parser->state.argv--, parser->state.argc++;
+ }
+ else
+ parser->opt_data.opterr = 1; /* Print error messages. */
+
+ if (parser->state.argv == argv && argv[0])
+ /* There's an argv[0]; use it for messages. */
+ parser->state.name = __argp_base_name (argv[0]);
+ else
+ parser->state.name = __argp_short_program_name ();
+
+ return 0;
+}
+
+/* Free any storage consumed by PARSER (but not PARSER itself). */
+static error_t
+parser_finalize (struct parser *parser,
+ error_t err, int arg_ebadkey, int *end_index)
+{
+ struct group *group;
+
+ if (err == EBADKEY && arg_ebadkey)
+ /* Suppress errors generated by unparsed arguments. */
+ err = 0;
+
+ if (! err)
+ {
+ if (parser->state.next == parser->state.argc)
+ /* We successfully parsed all arguments! Call all the parsers again,
+ just a few more times... */
+ {
+ for (group = parser->groups;
+ group < parser->egroup && (!err || err==EBADKEY);
+ group++)
+ if (group->args_processed == 0)
+ err = group_parse (group, &parser->state, ARGP_KEY_NO_ARGS, 0);
+ for (group = parser->egroup - 1;
+ group >= parser->groups && (!err || err==EBADKEY);
+ group--)
+ err = group_parse (group, &parser->state, ARGP_KEY_END, 0);
+
+ if (err == EBADKEY)
+ err = 0; /* Some parser didn't understand. */
+
+ /* Tell the user that all arguments are parsed. */
+ if (end_index)
+ *end_index = parser->state.next;
+ }
+ else if (end_index)
+ /* Return any remaining arguments to the user. */
+ *end_index = parser->state.next;
+ else
+ /* No way to return the remaining arguments, they must be bogus. */
+ {
+ if (!(parser->state.flags & ARGP_NO_ERRS)
+ && parser->state.err_stream)
+ fprintf (parser->state.err_stream,
+ dgettext (parser->argp->argp_domain,
+ "%s: Too many arguments\n"),
+ parser->state.name);
+ err = EBADKEY;
+ }
+ }
+
+ /* Okay, we're all done, with either an error or success; call the parsers
+ to indicate which one. */
+
+ if (err)
+ {
+ /* Maybe print an error message. */
+ if (err == EBADKEY)
+ /* An appropriate message describing what the error was should have
+ been printed earlier. */
+ __argp_state_help (&parser->state, parser->state.err_stream,
+ ARGP_HELP_STD_ERR);
+
+ /* Since we didn't exit, give each parser an error indication. */
+ for (group = parser->groups; group < parser->egroup; group++)
+ group_parse (group, &parser->state, ARGP_KEY_ERROR, 0);
+ }
+ else
+ /* Notify parsers of success, and propagate back values from parsers. */
+ {
+ /* We pass over the groups in reverse order so that child groups are
+ given a chance to do there processing before passing back a value to
+ the parent. */
+ for (group = parser->egroup - 1
+ ; group >= parser->groups && (!err || err == EBADKEY)
+ ; group--)
+ err = group_parse (group, &parser->state, ARGP_KEY_SUCCESS, 0);
+ if (err == EBADKEY)
+ err = 0; /* Some parser didn't understand. */
+ }
+
+ /* Call parsers once more, to do any final cleanup. Errors are ignored. */
+ for (group = parser->egroup - 1; group >= parser->groups; group--)
+ group_parse (group, &parser->state, ARGP_KEY_FINI, 0);
+
+ if (err == EBADKEY)
+ err = EINVAL;
+
+ free (parser->storage);
+
+ return err;
+}
+
+/* Call the user parsers to parse the non-option argument VAL, at the current
+ position, returning any error. The state NEXT pointer is assumed to have
+ been adjusted (by getopt) to point after this argument; this function will
+ adjust it correctly to reflect however many args actually end up being
+ consumed. */
+static error_t
+parser_parse_arg (struct parser *parser, char *val)
+{
+ /* Save the starting value of NEXT, first adjusting it so that the arg
+ we're parsing is again the front of the arg vector. */
+ int index = --parser->state.next;
+ error_t err = EBADKEY;
+ struct group *group;
+ int key = 0; /* Which of ARGP_KEY_ARG[S] we used. */
+
+ /* Try to parse the argument in each parser. */
+ for (group = parser->groups
+ ; group < parser->egroup && err == EBADKEY
+ ; group++)
+ {
+ parser->state.next++; /* For ARGP_KEY_ARG, consume the arg. */
+ key = ARGP_KEY_ARG;
+ err = group_parse (group, &parser->state, key, val);
+
+ if (err == EBADKEY)
+ /* This parser doesn't like ARGP_KEY_ARG; try ARGP_KEY_ARGS instead. */
+ {
+ parser->state.next--; /* For ARGP_KEY_ARGS, put back the arg. */
+ key = ARGP_KEY_ARGS;
+ err = group_parse (group, &parser->state, key, 0);
+ }
+ }
+
+ if (! err)
+ {
+ if (key == ARGP_KEY_ARGS)
+ /* The default for ARGP_KEY_ARGS is to assume that if NEXT isn't
+ changed by the user, *all* arguments should be considered
+ consumed. */
+ parser->state.next = parser->state.argc;
+
+ if (parser->state.next > index)
+ /* Remember that we successfully processed a non-option
+ argument -- but only if the user hasn't gotten tricky and set
+ the clock back. */
+ (--group)->args_processed += (parser->state.next - index);
+ else
+ /* The user wants to reparse some args, give getopt another try. */
+ parser->try_getopt = 1;
+ }
+
+ return err;
+}
+
+/* Call the user parsers to parse the option OPT, with argument VAL, at the
+ current position, returning any error. */
+static error_t
+parser_parse_opt (struct parser *parser, int opt, char *val)
+{
+ /* The group key encoded in the high bits; 0 for short opts or
+ group_number + 1 for long opts. */
+ int group_key = opt >> USER_BITS;
+ error_t err = EBADKEY;
+
+ if (group_key == 0)
+ /* A short option. By comparing OPT's position in SHORT_OPTS to the
+ various starting positions in each group's SHORT_END field, we can
+ determine which group OPT came from. */
+ {
+ struct group *group;
+ char *short_index = strchr (parser->short_opts, opt);
+
+ if (short_index)
+ for (group = parser->groups; group < parser->egroup; group++)
+ if (group->short_end > short_index)
+ {
+ err = group_parse (group, &parser->state, opt,
+ parser->opt_data.optarg);
+ break;
+ }
+ }
+ else
+ /* A long option. We use shifts instead of masking for extracting
+ the user value in order to preserve the sign. */
+ err =
+ group_parse (&parser->groups[group_key - 1], &parser->state,
+ (opt << GROUP_BITS) >> GROUP_BITS,
+ parser->opt_data.optarg);
+
+ if (err == EBADKEY)
+ /* At least currently, an option not recognized is an error in the
+ parser, because we pre-compute which parser is supposed to deal
+ with each option. */
+ {
+ static const char bad_key_err[] =
+ N_("(PROGRAM ERROR) Option should have been recognized!?");
+ if (group_key == 0)
+ __argp_error (&parser->state, "-%c: %s", opt,
+ dgettext (parser->argp->argp_domain, bad_key_err));
+ else
+ {
+ struct option *long_opt = parser->long_opts;
+ while (long_opt->val != opt && long_opt->name)
+ long_opt++;
+ __argp_error (&parser->state, "--%s: %s",
+ long_opt->name ? long_opt->name : "???",
+ dgettext (parser->argp->argp_domain, bad_key_err));
+ }
+ }
+
+ return err;
+}
+
+/* Parse the next argument in PARSER (as indicated by PARSER->state.next).
+ Any error from the parsers is returned, and *ARGP_EBADKEY indicates
+ whether a value of EBADKEY is due to an unrecognized argument (which is
+ generally not fatal). */
+static error_t
+parser_parse_next (struct parser *parser, int *arg_ebadkey)
+{
+ int opt;
+ error_t err = 0;
+
+ if (parser->state.quoted && parser->state.next < parser->state.quoted)
+ /* The next argument pointer has been moved to before the quoted
+ region, so pretend we never saw the quoting `--', and give getopt
+ another chance. If the user hasn't removed it, getopt will just
+ process it again. */
+ parser->state.quoted = 0;
+
+ if (parser->try_getopt && !parser->state.quoted)
+ /* Give getopt a chance to parse this. */
+ {
+ /* Put it back in OPTIND for getopt. */
+ parser->opt_data.optind = parser->state.next;
+ /* Distinguish KEY_ERR from a real option. */
+ parser->opt_data.optopt = KEY_END;
+ if (parser->state.flags & ARGP_LONG_ONLY)
+ opt = _getopt_long_only_r (parser->state.argc, parser->state.argv,
+ parser->short_opts, parser->long_opts, 0,
+ &parser->opt_data);
+ else
+ opt = _getopt_long_r (parser->state.argc, parser->state.argv,
+ parser->short_opts, parser->long_opts, 0,
+ &parser->opt_data);
+ /* And see what getopt did. */
+ parser->state.next = parser->opt_data.optind;
+
+ if (opt == KEY_END)
+ /* Getopt says there are no more options, so stop using
+ getopt; we'll continue if necessary on our own. */
+ {
+ parser->try_getopt = 0;
+ if (parser->state.next > 1
+ && strcmp (parser->state.argv[parser->state.next - 1], QUOTE)
+ == 0)
+ /* Not only is this the end of the options, but it's a
+ `quoted' region, which may have args that *look* like
+ options, so we definitely shouldn't try to use getopt past
+ here, whatever happens. */
+ parser->state.quoted = parser->state.next;
+ }
+ else if (opt == KEY_ERR && parser->opt_data.optopt != KEY_END)
+ /* KEY_ERR can have the same value as a valid user short
+ option, but in the case of a real error, getopt sets OPTOPT
+ to the offending character, which can never be KEY_END. */
+ {
+ *arg_ebadkey = 0;
+ return EBADKEY;
+ }
+ }
+ else
+ opt = KEY_END;
+
+ if (opt == KEY_END)
+ {
+ /* We're past what getopt considers the options. */
+ if (parser->state.next >= parser->state.argc
+ || (parser->state.flags & ARGP_NO_ARGS))
+ /* Indicate that we're done. */
+ {
+ *arg_ebadkey = 1;
+ return EBADKEY;
+ }
+ else
+ /* A non-option arg; simulate what getopt might have done. */
+ {
+ opt = KEY_ARG;
+ parser->opt_data.optarg = parser->state.argv[parser->state.next++];
+ }
+ }
+
+ if (opt == KEY_ARG)
+ /* A non-option argument; try each parser in turn. */
+ err = parser_parse_arg (parser, parser->opt_data.optarg);
+ else
+ err = parser_parse_opt (parser, opt, parser->opt_data.optarg);
+
+ if (err == EBADKEY)
+ *arg_ebadkey = (opt == KEY_END || opt == KEY_ARG);
+
+ return err;
+}
+
+/* Parse the options strings in ARGC & ARGV according to the argp in ARGP.
+ FLAGS is one of the ARGP_ flags above. If END_INDEX is non-NULL, the
+ index in ARGV of the first unparsed option is returned in it. If an
+ unknown option is present, EINVAL is returned; if some parser routine
+ returned a non-zero value, it is returned; otherwise 0 is returned. */
+error_t
+__argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags,
+ int *end_index, void *input)
+{
+ error_t err;
+ struct parser parser;
+
+ /* If true, then err == EBADKEY is a result of a non-option argument failing
+ to be parsed (which in some cases isn't actually an error). */
+ int arg_ebadkey = 0;
+
+#ifndef _LIBC
+ if (!(flags & ARGP_PARSE_ARGV0))
+ {
+#ifdef HAVE_DECL_PROGRAM_INVOCATION_NAME
+ if (!program_invocation_name)
+ program_invocation_name = argv[0];
+#endif
+#ifdef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
+ if (!program_invocation_short_name)
+ program_invocation_short_name = __argp_base_name (argv[0]);
+#endif
+ }
+#endif
+
+ if (! (flags & ARGP_NO_HELP))
+ /* Add our own options. */
+ {
+ struct argp_child *child = alloca (4 * sizeof (struct argp_child));
+ struct argp *top_argp = alloca (sizeof (struct argp));
+
+ /* TOP_ARGP has no options, it just serves to group the user & default
+ argps. */
+ memset (top_argp, 0, sizeof (*top_argp));
+ top_argp->children = child;
+
+ memset (child, 0, 4 * sizeof (struct argp_child));
+
+ if (argp)
+ (child++)->argp = argp;
+ (child++)->argp = &argp_default_argp;
+ if (argp_program_version || argp_program_version_hook)
+ (child++)->argp = &argp_version_argp;
+ child->argp = 0;
+
+ argp = top_argp;
+ }
+
+ /* Construct a parser for these arguments. */
+ err = parser_init (&parser, argp, argc, argv, flags, input);
+
+ if (! err)
+ /* Parse! */
+ {
+ while (! err)
+ err = parser_parse_next (&parser, &arg_ebadkey);
+ err = parser_finalize (&parser, err, arg_ebadkey, end_index);
+ }
+
+ return err;
+}
+#ifdef weak_alias
+weak_alias (__argp_parse, argp_parse)
+#endif
+
+/* Return the input field for ARGP in the parser corresponding to STATE; used
+ by the help routines. */
+void *
+__argp_input (const struct argp *argp, const struct argp_state *state)
+{
+ if (state)
+ {
+ struct group *group;
+ struct parser *parser = state->pstate;
+
+ for (group = parser->groups; group < parser->egroup; group++)
+ if (group->argp == argp)
+ return group->input;
+ }
+
+ return 0;
+}
+#ifdef weak_alias
+weak_alias (__argp_input, _argp_input)
+#endif
diff --git a/lib/argp-pin.c b/lib/argp-pin.c
new file mode 100644
index 0000000..852c6d6
--- /dev/null
+++ b/lib/argp-pin.c
@@ -0,0 +1,28 @@
+/* Full and short program names for argp module
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME
+char *program_invocation_short_name = 0;
+#endif
+#ifndef HAVE_PROGRAM_INVOCATION_NAME
+char *program_invocation_name = 0;
+#endif
+
diff --git a/lib/argp-pv.c b/lib/argp-pv.c
new file mode 100644
index 0000000..a11298b
--- /dev/null
+++ b/lib/argp-pv.c
@@ -0,0 +1,24 @@
+/* Default definition for ARGP_PROGRAM_VERSION.
+ Copyright (C) 1996, 1997, 1999, 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* If set by the user program to a non-zero value, then a default option
+ --version is added (unless the ARGP_NO_HELP flag is used), which will
+ print this string followed by a newline and exit (unless the
+ ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */
+const char *argp_program_version;
diff --git a/lib/argp-pvh.c b/lib/argp-pvh.c
new file mode 100644
index 0000000..6bf7c49
--- /dev/null
+++ b/lib/argp-pvh.c
@@ -0,0 +1,31 @@
+/* Default definition for ARGP_PROGRAM_VERSION_HOOK.
+ Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "argp.h"
+
+/* If set by the user program to a non-zero value, then a default option
+ --version is added (unless the ARGP_NO_HELP flag is used), which calls
+ this function with a stream to print the version to and a pointer to the
+ current parsing state, and then exits (unless the ARGP_NO_EXIT flag is
+ used). This variable takes precedent over ARGP_PROGRAM_VERSION. */
+void (*argp_program_version_hook) (FILE *stream, struct argp_state *state) = NULL;
diff --git a/lib/argp-xinl.c b/lib/argp-xinl.c
new file mode 100644
index 0000000..a6afb1f
--- /dev/null
+++ b/lib/argp-xinl.c
@@ -0,0 +1,43 @@
+/* Real definitions for extern inline functions in argp.h
+ Copyright (C) 1997, 1998, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if defined _LIBC || defined HAVE_FEATURES_H
+# include <features.h>
+#endif
+
+#ifndef __USE_EXTERN_INLINES
+# define __USE_EXTERN_INLINES 1
+#endif
+#define ARGP_EI
+#undef __OPTIMIZE__
+#define __OPTIMIZE__ 1
+#include "argp.h"
+
+/* Add weak aliases. */
+#if _LIBC - 0 && defined (weak_alias)
+
+weak_alias (__argp_usage, argp_usage)
+weak_alias (__option_is_short, _option_is_short)
+weak_alias (__option_is_end, _option_is_end)
+
+#endif
diff --git a/lib/argp.h b/lib/argp.h
new file mode 100644
index 0000000..1c4e06f
--- /dev/null
+++ b/lib/argp.h
@@ -0,0 +1,622 @@
+/* Hierarchial argument parsing, layered over getopt.
+ Copyright (C) 1995-1999,2003-2007 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Miles Bader <miles@gnu.ai.mit.edu>.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _ARGP_H
+#define _ARGP_H
+
+#include <stdio.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <limits.h>
+
+#define __need_error_t
+#include <errno.h>
+
+#ifndef __THROW
+# define __THROW
+#endif
+#ifndef __NTH
+# define __NTH(fct) fct __THROW
+#endif
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
+# define __attribute__(Spec) /* empty */
+# endif
+/* The __-protected variants of `format' and `printf' attributes
+ are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) || __STRICT_ANSI__
+# define __format__ format
+# define __printf__ printf
+# endif
+#endif
+
+/* GCC 2.95 and later have "__restrict"; C99 compilers have
+ "restrict", and "configure" may have defined "restrict".
+ Other compilers use __restrict, __restrict__, and _Restrict, and
+ 'configure' might #define 'restrict' to those words. */
+#ifndef __restrict
+# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
+# if 199901L <= __STDC_VERSION__
+# define __restrict restrict
+# else
+# define __restrict
+# endif
+# endif
+#endif
+
+#ifndef __error_t_defined
+typedef int error_t;
+# define __error_t_defined
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* A description of a particular option. A pointer to an array of
+ these is passed in the OPTIONS field of an argp structure. Each option
+ entry can correspond to one long option and/or one short option; more
+ names for the same option can be added by following an entry in an option
+ array with options having the OPTION_ALIAS flag set. */
+struct argp_option
+{
+ /* The long option name. For more than one name for the same option, you
+ can use following options with the OPTION_ALIAS flag set. */
+ const char *name;
+
+ /* What key is returned for this option. If > 0 and printable, then it's
+ also accepted as a short option. */
+ int key;
+
+ /* If non-NULL, this is the name of the argument associated with this
+ option, which is required unless the OPTION_ARG_OPTIONAL flag is set. */
+ const char *arg;
+
+ /* OPTION_ flags. */
+ int flags;
+
+ /* The doc string for this option. If both NAME and KEY are 0, This string
+ will be printed outdented from the normal option column, making it
+ useful as a group header (it will be the first thing printed in its
+ group); in this usage, it's conventional to end the string with a `:'.
+
+ Write the initial value as N_("TEXT") if you want xgettext to collect
+ it into a POT file. */
+ const char *doc;
+
+ /* The group this option is in. In a long help message, options are sorted
+ alphabetically within each group, and the groups presented in the order
+ 0, 1, 2, ..., n, -m, ..., -2, -1. Every entry in an options array with
+ if this field 0 will inherit the group number of the previous entry, or
+ zero if it's the first one, unless its a group header (NAME and KEY both
+ 0), in which case, the previous entry + 1 is the default. Automagic
+ options such as --help are put into group -1. */
+ int group;
+};
+
+/* The argument associated with this option is optional. */
+#define OPTION_ARG_OPTIONAL 0x1
+
+/* This option isn't displayed in any help messages. */
+#define OPTION_HIDDEN 0x2
+
+/* This option is an alias for the closest previous non-alias option. This
+ means that it will be displayed in the same help entry, and will inherit
+ fields other than NAME and KEY from the aliased option. */
+#define OPTION_ALIAS 0x4
+
+/* This option isn't actually an option (and so should be ignored by the
+ actual option parser), but rather an arbitrary piece of documentation that
+ should be displayed in much the same manner as the options. If this flag
+ is set, then the option NAME field is displayed unmodified (e.g., no `--'
+ prefix is added) at the left-margin (where a *short* option would normally
+ be displayed), and the documentation string in the normal place. The NAME
+ field will be translated using gettext, unless OPTION_NO_TRANS is set (see
+ below). For purposes of sorting, any leading whitespace and punctuation is
+ ignored, except that if the first non-whitespace character is not `-', this
+ entry is displayed after all options (and OPTION_DOC entries with a leading
+ `-') in the same group. */
+#define OPTION_DOC 0x8
+
+/* This option shouldn't be included in `long' usage messages (but is still
+ included in help messages). This is mainly intended for options that are
+ completely documented in an argp's ARGS_DOC field, in which case including
+ the option in the generic usage list would be redundant. For instance,
+ if ARGS_DOC is "FOO BAR\n-x BLAH", and the `-x' option's purpose is to
+ distinguish these two cases, -x should probably be marked
+ OPTION_NO_USAGE. */
+#define OPTION_NO_USAGE 0x10
+
+/* Valid only in conjunction with OPTION_DOC. This option disables translation
+ of option name. */
+#define OPTION_NO_TRANS 0x20
+
+
+struct argp; /* fwd declare this type */
+struct argp_state; /* " */
+struct argp_child; /* " */
+
+/* The type of a pointer to an argp parsing function. */
+typedef error_t (*argp_parser_t) (int key, char *arg,
+ struct argp_state *state);
+
+/* What to return for unrecognized keys. For special ARGP_KEY_ keys, such
+ returns will simply be ignored. For user keys, this error will be turned
+ into EINVAL (if the call to argp_parse is such that errors are propagated
+ back to the user instead of exiting); returning EINVAL itself would result
+ in an immediate stop to parsing in *all* cases. */
+#define ARGP_ERR_UNKNOWN E2BIG /* Hurd should never need E2BIG. XXX */
+
+/* Special values for the KEY argument to an argument parsing function.
+ ARGP_ERR_UNKNOWN should be returned if they aren't understood.
+
+ The sequence of keys to a parsing function is either (where each
+ uppercased word should be prefixed by `ARGP_KEY_' and opt is a user key):
+
+ INIT opt... NO_ARGS END SUCCESS -- No non-option arguments at all
+ or INIT (opt | ARG)... END SUCCESS -- All non-option args parsed
+ or INIT (opt | ARG)... SUCCESS -- Some non-option arg unrecognized
+
+ The third case is where every parser returned ARGP_KEY_UNKNOWN for an
+ argument, in which case parsing stops at that argument (returning the
+ unparsed arguments to the caller of argp_parse if requested, or stopping
+ with an error message if not).
+
+ If an error occurs (either detected by argp, or because the parsing
+ function returned an error value), then the parser is called with
+ ARGP_KEY_ERROR, and no further calls are made. */
+
+/* This is not an option at all, but rather a command line argument. If a
+ parser receiving this key returns success, the fact is recorded, and the
+ ARGP_KEY_NO_ARGS case won't be used. HOWEVER, if while processing the
+ argument, a parser function decrements the NEXT field of the state it's
+ passed, the option won't be considered processed; this is to allow you to
+ actually modify the argument (perhaps into an option), and have it
+ processed again. */
+#define ARGP_KEY_ARG 0
+/* There are remaining arguments not parsed by any parser, which may be found
+ starting at (STATE->argv + STATE->next). If success is returned, but
+ STATE->next left untouched, it's assumed that all arguments were consume,
+ otherwise, the parser should adjust STATE->next to reflect any arguments
+ consumed. */
+#define ARGP_KEY_ARGS 0x1000006
+/* There are no more command line arguments at all. */
+#define ARGP_KEY_END 0x1000001
+/* Because it's common to want to do some special processing if there aren't
+ any non-option args, user parsers are called with this key if they didn't
+ successfully process any non-option arguments. Called just before
+ ARGP_KEY_END (where more general validity checks on previously parsed
+ arguments can take place). */
+#define ARGP_KEY_NO_ARGS 0x1000002
+/* Passed in before any parsing is done. Afterwards, the values of each
+ element of the CHILD_INPUT field, if any, in the state structure is
+ copied to each child's state to be the initial value of the INPUT field. */
+#define ARGP_KEY_INIT 0x1000003
+/* Use after all other keys, including SUCCESS & END. */
+#define ARGP_KEY_FINI 0x1000007
+/* Passed in when parsing has successfully been completed (even if there are
+ still arguments remaining). */
+#define ARGP_KEY_SUCCESS 0x1000004
+/* Passed in if an error occurs. */
+#define ARGP_KEY_ERROR 0x1000005
+
+/* An argp structure contains a set of options declarations, a function to
+ deal with parsing one, documentation string, a possible vector of child
+ argp's, and perhaps a function to filter help output. When actually
+ parsing options, getopt is called with the union of all the argp
+ structures chained together through their CHILD pointers, with conflicts
+ being resolved in favor of the first occurrence in the chain. */
+struct argp
+{
+ /* An array of argp_option structures, terminated by an entry with both
+ NAME and KEY having a value of 0. */
+ const struct argp_option *options;
+
+ /* What to do with an option from this structure. KEY is the key
+ associated with the option, and ARG is any associated argument (NULL if
+ none was supplied). If KEY isn't understood, ARGP_ERR_UNKNOWN should be
+ returned. If a non-zero, non-ARGP_ERR_UNKNOWN value is returned, then
+ parsing is stopped immediately, and that value is returned from
+ argp_parse(). For special (non-user-supplied) values of KEY, see the
+ ARGP_KEY_ definitions below. */
+ argp_parser_t parser;
+
+ /* A string describing what other arguments are wanted by this program. It
+ is only used by argp_usage to print the `Usage:' message. If it
+ contains newlines, the strings separated by them are considered
+ alternative usage patterns, and printed on separate lines (lines after
+ the first are prefix by ` or: ' instead of `Usage:'). */
+ const char *args_doc;
+
+ /* If non-NULL, a string containing extra text to be printed before and
+ after the options in a long help message (separated by a vertical tab
+ `\v' character).
+ Write the initial value as N_("BEFORE-TEXT") "\v" N_("AFTER-TEXT") if
+ you want xgettext to collect the two pieces of text into a POT file. */
+ const char *doc;
+
+ /* A vector of argp_children structures, terminated by a member with a 0
+ argp field, pointing to child argps should be parsed with this one. Any
+ conflicts are resolved in favor of this argp, or early argps in the
+ CHILDREN list. This field is useful if you use libraries that supply
+ their own argp structure, which you want to use in conjunction with your
+ own. */
+ const struct argp_child *children;
+
+ /* If non-zero, this should be a function to filter the output of help
+ messages. KEY is either a key from an option, in which case TEXT is
+ that option's help text, or a special key from the ARGP_KEY_HELP_
+ defines, below, describing which other help text TEXT is. The function
+ should return either TEXT, if it should be used as-is, a replacement
+ string, which should be malloced, and will be freed by argp, or NULL,
+ meaning `print nothing'. The value for TEXT is *after* any translation
+ has been done, so if any of the replacement text also needs translation,
+ that should be done by the filter function. INPUT is either the input
+ supplied to argp_parse, or NULL, if argp_help was called directly. */
+ char *(*help_filter) (int __key, const char *__text, void *__input);
+
+ /* If non-zero the strings used in the argp library are translated using
+ the domain described by this string. Otherwise the currently installed
+ default domain is used. */
+ const char *argp_domain;
+};
+
+/* Possible KEY arguments to a help filter function. */
+#define ARGP_KEY_HELP_PRE_DOC 0x2000001 /* Help text preceeding options. */
+#define ARGP_KEY_HELP_POST_DOC 0x2000002 /* Help text following options. */
+#define ARGP_KEY_HELP_HEADER 0x2000003 /* Option header string. */
+#define ARGP_KEY_HELP_EXTRA 0x2000004 /* After all other documentation;
+ TEXT is NULL for this key. */
+/* Explanatory note emitted when duplicate option arguments have been
+ suppressed. */
+#define ARGP_KEY_HELP_DUP_ARGS_NOTE 0x2000005
+#define ARGP_KEY_HELP_ARGS_DOC 0x2000006 /* Argument doc string. */
+
+/* When an argp has a non-zero CHILDREN field, it should point to a vector of
+ argp_child structures, each of which describes a subsidiary argp. */
+struct argp_child
+{
+ /* The child parser. */
+ const struct argp *argp;
+
+ /* Flags for this child. */
+ int flags;
+
+ /* If non-zero, an optional header to be printed in help output before the
+ child options. As a side-effect, a non-zero value forces the child
+ options to be grouped together; to achieve this effect without actually
+ printing a header string, use a value of "". */
+ const char *header;
+
+ /* Where to group the child options relative to the other (`consolidated')
+ options in the parent argp; the values are the same as the GROUP field
+ in argp_option structs, but all child-groupings follow parent options at
+ a particular group level. If both this field and HEADER are zero, then
+ they aren't grouped at all, but rather merged with the parent options
+ (merging the child's grouping levels with the parents). */
+ int group;
+};
+
+/* Parsing state. This is provided to parsing functions called by argp,
+ which may examine and, as noted, modify fields. */
+struct argp_state
+{
+ /* The top level ARGP being parsed. */
+ const struct argp *root_argp;
+
+ /* The argument vector being parsed. May be modified. */
+ int argc;
+ char **argv;
+
+ /* The index in ARGV of the next arg that to be parsed. May be modified. */
+ int next;
+
+ /* The flags supplied to argp_parse. May be modified. */
+ unsigned flags;
+
+ /* While calling a parsing function with a key of ARGP_KEY_ARG, this is the
+ number of the current arg, starting at zero, and incremented after each
+ such call returns. At all other times, this is the number of such
+ arguments that have been processed. */
+ unsigned arg_num;
+
+ /* If non-zero, the index in ARGV of the first argument following a special
+ `--' argument (which prevents anything following being interpreted as an
+ option). Only set once argument parsing has proceeded past this point. */
+ int quoted;
+
+ /* An arbitrary pointer passed in from the user. */
+ void *input;
+ /* Values to pass to child parsers. This vector will be the same length as
+ the number of children for the current parser. */
+ void **child_inputs;
+
+ /* For the parser's use. Initialized to 0. */
+ void *hook;
+
+ /* The name used when printing messages. This is initialized to ARGV[0],
+ or PROGRAM_INVOCATION_NAME if that is unavailable. */
+ char *name;
+
+ /* Streams used when argp prints something. */
+ FILE *err_stream; /* For errors; initialized to stderr. */
+ FILE *out_stream; /* For information; initialized to stdout. */
+
+ void *pstate; /* Private, for use by argp. */
+};
+
+/* Flags for argp_parse (note that the defaults are those that are
+ convenient for program command line parsing): */
+
+/* Don't ignore the first element of ARGV. Normally (and always unless
+ ARGP_NO_ERRS is set) the first element of the argument vector is
+ skipped for option parsing purposes, as it corresponds to the program name
+ in a command line. */
+#define ARGP_PARSE_ARGV0 0x01
+
+/* Don't print error messages for unknown options to stderr; unless this flag
+ is set, ARGP_PARSE_ARGV0 is ignored, as ARGV[0] is used as the program
+ name in the error messages. This flag implies ARGP_NO_EXIT (on the
+ assumption that silent exiting upon errors is bad behaviour). */
+#define ARGP_NO_ERRS 0x02
+
+/* Don't parse any non-option args. Normally non-option args are parsed by
+ calling the parse functions with a key of ARGP_KEY_ARG, and the actual arg
+ as the value. Since it's impossible to know which parse function wants to
+ handle it, each one is called in turn, until one returns 0 or an error
+ other than ARGP_ERR_UNKNOWN; if an argument is handled by no one, the
+ argp_parse returns prematurely (but with a return value of 0). If all
+ args have been parsed without error, all parsing functions are called one
+ last time with a key of ARGP_KEY_END. This flag needn't normally be set,
+ as the normal behavior is to stop parsing as soon as some argument can't
+ be handled. */
+#define ARGP_NO_ARGS 0x04
+
+/* Parse options and arguments in the same order they occur on the command
+ line -- normally they're rearranged so that all options come first. */
+#define ARGP_IN_ORDER 0x08
+
+/* Don't provide the standard long option --help, which causes usage and
+ option help information to be output to stdout, and exit (0) called. */
+#define ARGP_NO_HELP 0x10
+
+/* Don't exit on errors (they may still result in error messages). */
+#define ARGP_NO_EXIT 0x20
+
+/* Use the gnu getopt `long-only' rules for parsing arguments. */
+#define ARGP_LONG_ONLY 0x40
+
+/* Turns off any message-printing/exiting options. */
+#define ARGP_SILENT (ARGP_NO_EXIT | ARGP_NO_ERRS | ARGP_NO_HELP)
+
+/* Parse the options strings in ARGC & ARGV according to the options in ARGP.
+ FLAGS is one of the ARGP_ flags above. If ARG_INDEX is non-NULL, the
+ index in ARGV of the first unparsed option is returned in it. If an
+ unknown option is present, ARGP_ERR_UNKNOWN is returned; if some parser
+ routine returned a non-zero value, it is returned; otherwise 0 is
+ returned. This function may also call exit unless the ARGP_NO_HELP flag
+ is set. INPUT is a pointer to a value to be passed in to the parser. */
+extern error_t argp_parse (const struct argp *__restrict __argp,
+ int /*argc*/, char **__restrict /*argv*/,
+ unsigned __flags, int *__restrict __arg_index,
+ void *__restrict __input);
+extern error_t __argp_parse (const struct argp *__restrict __argp,
+ int /*argc*/, char **__restrict /*argv*/,
+ unsigned __flags, int *__restrict __arg_index,
+ void *__restrict __input);
+
+/* Global variables. */
+
+/* GNULIB makes sure both program_invocation_name and
+ program_invocation_short_name are available */
+#ifdef GNULIB_PROGRAM_INVOCATION_NAME
+extern char *program_invocation_name;
+# undef HAVE_DECL_PROGRAM_INVOCATION_NAME
+# define HAVE_DECL_PROGRAM_INVOCATION_NAME 1
+#endif
+
+#ifdef GNULIB_PROGRAM_INVOCATION_SHORT_NAME
+extern char *program_invocation_short_name;
+# undef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
+# define HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME 1
+#endif
+
+/* If defined or set by the user program to a non-zero value, then a default
+ option --version is added (unless the ARGP_NO_HELP flag is used), which
+ will print this string followed by a newline and exit (unless the
+ ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */
+extern const char *argp_program_version;
+
+/* If defined or set by the user program to a non-zero value, then a default
+ option --version is added (unless the ARGP_NO_HELP flag is used), which
+ calls this function with a stream to print the version to and a pointer to
+ the current parsing state, and then exits (unless the ARGP_NO_EXIT flag is
+ used). This variable takes precedent over ARGP_PROGRAM_VERSION. */
+extern void (*argp_program_version_hook) (FILE *__restrict __stream,
+ struct argp_state *__restrict
+ __state);
+
+/* If defined or set by the user program, it should point to string that is
+ the bug-reporting address for the program. It will be printed by
+ argp_help if the ARGP_HELP_BUG_ADDR flag is set (as it is by various
+ standard help messages), embedded in a sentence that says something like
+ `Report bugs to ADDR.'. */
+extern const char *argp_program_bug_address;
+
+/* The exit status that argp will use when exiting due to a parsing error.
+ If not defined or set by the user program, this defaults to EX_USAGE from
+ <sysexits.h>. */
+extern error_t argp_err_exit_status;
+
+/* Flags for argp_help. */
+#define ARGP_HELP_USAGE 0x01 /* a Usage: message. */
+#define ARGP_HELP_SHORT_USAGE 0x02 /* " but don't actually print options. */
+#define ARGP_HELP_SEE 0x04 /* a `Try ... for more help' message. */
+#define ARGP_HELP_LONG 0x08 /* a long help message. */
+#define ARGP_HELP_PRE_DOC 0x10 /* doc string preceding long help. */
+#define ARGP_HELP_POST_DOC 0x20 /* doc string following long help. */
+#define ARGP_HELP_DOC (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC)
+#define ARGP_HELP_BUG_ADDR 0x40 /* bug report address */
+#define ARGP_HELP_LONG_ONLY 0x80 /* modify output appropriately to
+ reflect ARGP_LONG_ONLY mode. */
+
+/* These ARGP_HELP flags are only understood by argp_state_help. */
+#define ARGP_HELP_EXIT_ERR 0x100 /* Call exit(1) instead of returning. */
+#define ARGP_HELP_EXIT_OK 0x200 /* Call exit(0) instead of returning. */
+
+/* The standard thing to do after a program command line parsing error, if an
+ error message has already been printed. */
+#define ARGP_HELP_STD_ERR \
+ (ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
+/* The standard thing to do after a program command line parsing error, if no
+ more specific error message has been printed. */
+#define ARGP_HELP_STD_USAGE \
+ (ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
+/* The standard thing to do in response to a --help option. */
+#define ARGP_HELP_STD_HELP \
+ (ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK \
+ | ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR)
+
+/* Output a usage message for ARGP to STREAM. FLAGS are from the set
+ ARGP_HELP_*. */
+extern void argp_help (const struct argp *__restrict __argp,
+ FILE *__restrict __stream,
+ unsigned __flags, char *__restrict __name);
+extern void __argp_help (const struct argp *__restrict __argp,
+ FILE *__restrict __stream, unsigned __flags,
+ char *__name);
+
+/* The following routines are intended to be called from within an argp
+ parsing routine (thus taking an argp_state structure as the first
+ argument). They may or may not print an error message and exit, depending
+ on the flags in STATE -- in any case, the caller should be prepared for
+ them *not* to exit, and should return an appropiate error after calling
+ them. [argp_usage & argp_error should probably be called argp_state_...,
+ but they're used often enough that they should be short] */
+
+/* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are
+ from the set ARGP_HELP_*. */
+extern void argp_state_help (const struct argp_state *__restrict __state,
+ FILE *__restrict __stream,
+ unsigned int __flags);
+extern void __argp_state_help (const struct argp_state *__restrict __state,
+ FILE *__restrict __stream,
+ unsigned int __flags);
+
+/* Possibly output the standard usage message for ARGP to stderr and exit. */
+extern void argp_usage (const struct argp_state *__state);
+extern void __argp_usage (const struct argp_state *__state);
+
+/* If appropriate, print the printf string FMT and following args, preceded
+ by the program name and `:', to stderr, and followed by a `Try ... --help'
+ message, then exit (1). */
+extern void argp_error (const struct argp_state *__restrict __state,
+ const char *__restrict __fmt, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)));
+extern void __argp_error (const struct argp_state *__restrict __state,
+ const char *__restrict __fmt, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)));
+
+/* Similar to the standard gnu error-reporting function error(), but will
+ respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print
+ to STATE->err_stream. This is useful for argument parsing code that is
+ shared between program startup (when exiting is desired) and runtime
+ option parsing (when typically an error code is returned instead). The
+ difference between this function and argp_error is that the latter is for
+ *parsing errors*, and the former is for other problems that occur during
+ parsing but don't reflect a (syntactic) problem with the input. */
+extern void argp_failure (const struct argp_state *__restrict __state,
+ int __status, int __errnum,
+ const char *__restrict __fmt, ...)
+ __attribute__ ((__format__ (__printf__, 4, 5)));
+extern void __argp_failure (const struct argp_state *__restrict __state,
+ int __status, int __errnum,
+ const char *__restrict __fmt, ...)
+ __attribute__ ((__format__ (__printf__, 4, 5)));
+
+/* Returns true if the option OPT is a valid short option. */
+extern int _option_is_short (const struct argp_option *__opt) __THROW;
+extern int __option_is_short (const struct argp_option *__opt) __THROW;
+
+/* Returns true if the option OPT is in fact the last (unused) entry in an
+ options array. */
+extern int _option_is_end (const struct argp_option *__opt) __THROW;
+extern int __option_is_end (const struct argp_option *__opt) __THROW;
+
+/* Return the input field for ARGP in the parser corresponding to STATE; used
+ by the help routines. */
+extern void *_argp_input (const struct argp *__restrict __argp,
+ const struct argp_state *__restrict __state)
+ __THROW;
+extern void *__argp_input (const struct argp *__restrict __argp,
+ const struct argp_state *__restrict __state)
+ __THROW;
+
+#ifdef __USE_EXTERN_INLINES
+
+# if !_LIBC
+# define __argp_usage argp_usage
+# define __argp_state_help argp_state_help
+# define __option_is_short _option_is_short
+# define __option_is_end _option_is_end
+# endif
+
+# ifndef ARGP_EI
+# define ARGP_EI extern __inline__
+# endif
+
+ARGP_EI void
+__argp_usage (const struct argp_state *__state)
+{
+ __argp_state_help (__state, stderr, ARGP_HELP_STD_USAGE);
+}
+
+ARGP_EI int
+__NTH (__option_is_short (const struct argp_option *__opt))
+{
+ if (__opt->flags & OPTION_DOC)
+ return 0;
+ else
+ {
+ int __key = __opt->key;
+ return __key > 0 && __key <= UCHAR_MAX && isprint (__key);
+ }
+}
+
+ARGP_EI int
+__NTH (__option_is_end (const struct argp_option *__opt))
+{
+ return !__opt->key && !__opt->name && !__opt->doc && !__opt->group;
+}
+
+# if !_LIBC
+# undef __argp_usage
+# undef __argp_state_help
+# undef __option_is_short
+# undef __option_is_end
+# endif
+#endif /* Use extern inlines. */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* argp.h */
diff --git a/lib/asnprintf.c b/lib/asnprintf.c
new file mode 100644
index 0000000..26c3988
--- /dev/null
+++ b/lib/asnprintf.c
@@ -0,0 +1,35 @@
+/* Formatted output to strings.
+ Copyright (C) 1999, 2002, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+/* Specification. */
+#include "vasnprintf.h"
+
+#include <stdarg.h>
+
+char *
+asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
+{
+ va_list args;
+ char *result;
+
+ va_start (args, format);
+ result = vasnprintf (resultbuf, lengthp, format, args);
+ va_end (args);
+ return result;
+}
diff --git a/lib/at-func.c b/lib/at-func.c
new file mode 100644
index 0000000..f98c207
--- /dev/null
+++ b/lib/at-func.c
@@ -0,0 +1,86 @@
+/* Define an at-style functions like fstatat, unlinkat, fchownat, etc.
+ Copyright (C) 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 Jim Meyering */
+
+#define CALL_FUNC(F) \
+ (AT_FUNC_USE_F1_COND \
+ ? AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS) \
+ : AT_FUNC_F2 (F AT_FUNC_POST_FILE_ARGS))
+
+/* Call AT_FUNC_F1 or AT_FUNC_F2 (testing AT_FUNC_USE_F1_COND to
+ determine which) to operate on FILE, which is in the directory
+ open on descriptor FD. If possible, do it without changing the
+ working directory. Otherwise, resort to using save_cwd/fchdir,
+ then AT_FUNC_F?/restore_cwd. If either the save_cwd or the restore_cwd
+ fails, then give a diagnostic and exit nonzero. */
+int
+AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS)
+{
+ struct saved_cwd saved_cwd;
+ int saved_errno;
+ int err;
+
+ if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file))
+ return CALL_FUNC (file);
+
+ {
+ char buf[OPENAT_BUFFER_SIZE];
+ char *proc_file = openat_proc_name (buf, fd, file);
+ if (proc_file)
+ {
+ int proc_result = CALL_FUNC (proc_file);
+ int proc_errno = errno;
+ if (proc_file != buf)
+ free (proc_file);
+ /* If the syscall succeeds, or if it fails with an unexpected
+ errno value, then return right away. Otherwise, fall through
+ and resort to using save_cwd/restore_cwd. */
+ if (0 <= proc_result)
+ return proc_result;
+ if (! EXPECTED_ERRNO (proc_errno))
+ {
+ errno = proc_errno;
+ return proc_result;
+ }
+ }
+ }
+
+ if (save_cwd (&saved_cwd) != 0)
+ openat_save_fail (errno);
+
+ if (fchdir (fd) != 0)
+ {
+ saved_errno = errno;
+ free_cwd (&saved_cwd);
+ errno = saved_errno;
+ return -1;
+ }
+
+ err = CALL_FUNC (file);
+ saved_errno = (err < 0 ? errno : 0);
+
+ if (restore_cwd (&saved_cwd) != 0)
+ openat_restore_fail (errno);
+
+ free_cwd (&saved_cwd);
+
+ if (saved_errno)
+ errno = saved_errno;
+ return err;
+}
+#undef CALL_FUNC
diff --git a/lib/basename.c b/lib/basename.c
new file mode 100644
index 0000000..fbe17ff
--- /dev/null
+++ b/lib/basename.c
@@ -0,0 +1,129 @@
+/* basename.c -- return the last element in a file name
+
+ Copyright (C) 1990, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006 Free
+ Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+#include "dirname.h"
+
+#include <string.h>
+#include "xalloc.h"
+#include "xstrndup.h"
+
+/* Return the address of the last file name component of NAME. If
+ NAME has no relative file name components because it is a file
+ system root, return the empty string. */
+
+char *
+last_component (char const *name)
+{
+ char const *base = name + FILE_SYSTEM_PREFIX_LEN (name);
+ char const *p;
+ bool saw_slash = false;
+
+ while (ISSLASH (*base))
+ base++;
+
+ for (p = base; *p; p++)
+ {
+ if (ISSLASH (*p))
+ saw_slash = true;
+ else if (saw_slash)
+ {
+ base = p;
+ saw_slash = false;
+ }
+ }
+
+ return (char *) base;
+}
+
+
+/* In general, we can't use the builtin `basename' function if available,
+ since it has different meanings in different environments.
+ In some environments the builtin `basename' modifies its argument.
+
+ Return the last file name component of NAME, allocated with
+ xmalloc. On systems with drive letters, a leading "./"
+ distinguishes relative names that would otherwise look like a drive
+ letter. Unlike POSIX basename(), NAME cannot be NULL,
+ base_name("") returns "", and the first trailing slash is not
+ stripped.
+
+ If lstat (NAME) would succeed, then { chdir (dir_name (NAME));
+ lstat (base_name (NAME)); } will access the same file. Likewise,
+ if the sequence { chdir (dir_name (NAME));
+ rename (base_name (NAME), "foo"); } succeeds, you have renamed NAME
+ to "foo" in the same directory NAME was in. */
+
+char *
+base_name (char const *name)
+{
+ char const *base = last_component (name);
+ size_t length;
+
+ /* If there is no last component, then name is a file system root or the
+ empty string. */
+ if (! *base)
+ return xstrndup (name, base_len (name));
+
+ /* Collapse a sequence of trailing slashes into one. */
+ length = base_len (base);
+ if (ISSLASH (base[length]))
+ length++;
+
+ /* On systems with drive letters, `a/b:c' must return `./b:c' rather
+ than `b:c' to avoid confusion with a drive letter. On systems
+ with pure POSIX semantics, this is not an issue. */
+ if (FILE_SYSTEM_PREFIX_LEN (base))
+ {
+ char *p = xmalloc (length + 3);
+ p[0] = '.';
+ p[1] = '/';
+ memcpy (p + 2, base, length);
+ p[length + 2] = '\0';
+ return p;
+ }
+
+ /* Finally, copy the basename. */
+ return xstrndup (base, length);
+}
+
+/* Return the length of the basename NAME. Typically NAME is the
+ value returned by base_name or last_component. Act like strlen
+ (NAME), except omit all trailing slashes. */
+
+size_t
+base_len (char const *name)
+{
+ size_t len;
+ size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
+
+ for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--)
+ continue;
+
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT && len == 1
+ && ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2])
+ return 2;
+
+ if (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && prefix_len
+ && len == prefix_len && ISSLASH (name[prefix_len]))
+ return prefix_len + 1;
+
+ return len;
+}
diff --git a/lib/canonicalize-lgpl.c b/lib/canonicalize-lgpl.c
new file mode 100644
index 0000000..05ced11
--- /dev/null
+++ b/lib/canonicalize-lgpl.c
@@ -0,0 +1,353 @@
+/* Return the canonical absolute name of a given file.
+ Copyright (C) 1996-2003, 2005-2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+/* Avoid a clash of our rpl_realpath() function with the prototype in
+ <stdlib.h> on Solaris 2.5.1. */
+#undef realpath
+
+#if !HAVE_CANONICALIZE_FILE_NAME || defined _LIBC
+
+#include <alloca.h>
+
+/* Specification. */
+#include "canonicalize.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_UNISTD_H || defined _LIBC
+# include <unistd.h>
+#endif
+
+#include <limits.h>
+
+#if HAVE_SYS_PARAM_H || defined _LIBC
+# include <sys/param.h>
+#endif
+#ifndef MAXSYMLINKS
+# define MAXSYMLINKS 20
+#endif
+
+#include <sys/stat.h>
+
+#include <errno.h>
+#ifndef _LIBC
+# define __set_errno(e) errno = (e)
+# ifndef ENAMETOOLONG
+# define ENAMETOOLONG EINVAL
+# endif
+#endif
+
+#ifdef _LIBC
+# include <shlib-compat.h>
+#else
+# define SHLIB_COMPAT(lib, introduced, obsoleted) 0
+# define versioned_symbol(lib, local, symbol, version)
+# define compat_symbol(lib, local, symbol, version)
+# define weak_alias(local, symbol)
+# define __canonicalize_file_name canonicalize_file_name
+# define __realpath rpl_realpath
+# include "pathmax.h"
+# include "allocsa.h"
+# if HAVE_GETCWD
+# ifdef VMS
+ /* We want the directory in Unix syntax, not in VMS syntax. */
+# define __getcwd(buf, max) getcwd (buf, max, 0)
+# else
+# define __getcwd getcwd
+# endif
+# else
+# define __getcwd(buf, max) getwd (buf)
+# endif
+# define __readlink readlink
+ /* On systems without symbolic links, call stat() instead of lstat(). */
+# if !defined S_ISNLK && !HAVE_READLINK
+# define lstat stat
+# endif
+#endif
+
+/* Return the canonical absolute name of file NAME. A canonical name
+ does not contain any `.', `..' components nor any repeated path
+ separators ('/') or symlinks. All path components must exist. If
+ RESOLVED is null, the result is malloc'd; otherwise, if the
+ canonical name is PATH_MAX chars or more, returns null with `errno'
+ set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
+ returns the name in RESOLVED. If the name cannot be resolved and
+ RESOLVED is non-NULL, it contains the path of the first component
+ that cannot be resolved. If the path can be resolved, RESOLVED
+ holds the same value as the value returned. */
+
+char *
+__realpath (const char *name, char *resolved)
+{
+ char *rpath, *dest, *extra_buf = NULL;
+ const char *start, *end, *rpath_limit;
+ long int path_max;
+#if HAVE_READLINK
+ int num_links = 0;
+#endif
+
+ if (name == NULL)
+ {
+ /* As per Single Unix Specification V2 we must return an error if
+ either parameter is a null pointer. We extend this to allow
+ the RESOLVED parameter to be NULL in case the we are expected to
+ allocate the room for the return value. */
+ __set_errno (EINVAL);
+ return NULL;
+ }
+
+ if (name[0] == '\0')
+ {
+ /* As per Single Unix Specification V2 we must return an error if
+ the name argument points to an empty string. */
+ __set_errno (ENOENT);
+ return NULL;
+ }
+
+#ifdef PATH_MAX
+ path_max = PATH_MAX;
+#else
+ path_max = pathconf (name, _PC_PATH_MAX);
+ if (path_max <= 0)
+ path_max = 1024;
+#endif
+
+ if (resolved == NULL)
+ {
+ rpath = malloc (path_max);
+ if (rpath == NULL)
+ return NULL;
+ }
+ else
+ rpath = resolved;
+ rpath_limit = rpath + path_max;
+
+ if (name[0] != '/')
+ {
+ if (!__getcwd (rpath, path_max))
+ {
+ rpath[0] = '\0';
+ goto error;
+ }
+ dest = strchr (rpath, '\0');
+ }
+ else
+ {
+ rpath[0] = '/';
+ dest = rpath + 1;
+ }
+
+ for (start = end = name; *start; start = end)
+ {
+#ifdef _LIBC
+ struct stat64 st;
+#else
+ struct stat st;
+#endif
+
+ /* Skip sequence of multiple path-separators. */
+ while (*start == '/')
+ ++start;
+
+ /* Find end of path component. */
+ for (end = start; *end && *end != '/'; ++end)
+ /* Nothing. */;
+
+ if (end - start == 0)
+ break;
+ else if (end - start == 1 && start[0] == '.')
+ /* nothing */;
+ else if (end - start == 2 && start[0] == '.' && start[1] == '.')
+ {
+ /* Back up to previous component, ignore if at root already. */
+ if (dest > rpath + 1)
+ while ((--dest)[-1] != '/');
+ }
+ else
+ {
+ size_t new_size;
+
+ if (dest[-1] != '/')
+ *dest++ = '/';
+
+ if (dest + (end - start) >= rpath_limit)
+ {
+ ptrdiff_t dest_offset = dest - rpath;
+ char *new_rpath;
+
+ if (resolved)
+ {
+ __set_errno (ENAMETOOLONG);
+ if (dest > rpath + 1)
+ dest--;
+ *dest = '\0';
+ goto error;
+ }
+ new_size = rpath_limit - rpath;
+ if (end - start + 1 > path_max)
+ new_size += end - start + 1;
+ else
+ new_size += path_max;
+ new_rpath = (char *) realloc (rpath, new_size);
+ if (new_rpath == NULL)
+ goto error;
+ rpath = new_rpath;
+ rpath_limit = rpath + new_size;
+
+ dest = rpath + dest_offset;
+ }
+
+#ifdef _LIBC
+ dest = __mempcpy (dest, start, end - start);
+#else
+ memcpy (dest, start, end - start);
+ dest += end - start;
+#endif
+ *dest = '\0';
+
+#ifdef _LIBC
+ if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
+#else
+ if (lstat (rpath, &st) < 0)
+#endif
+ goto error;
+
+#if HAVE_READLINK
+ if (S_ISLNK (st.st_mode))
+ {
+ char *buf;
+ size_t len;
+ int n;
+
+ if (++num_links > MAXSYMLINKS)
+ {
+ __set_errno (ELOOP);
+ goto error;
+ }
+
+ buf = allocsa (path_max);
+ if (!buf)
+ {
+ errno = ENOMEM;
+ goto error;
+ }
+
+ n = __readlink (rpath, buf, path_max);
+ if (n < 0)
+ {
+ int saved_errno = errno;
+ freesa (buf);
+ errno = saved_errno;
+ goto error;
+ }
+ buf[n] = '\0';
+
+ if (!extra_buf)
+ {
+ extra_buf = allocsa (path_max);
+ if (!extra_buf)
+ {
+ freesa (buf);
+ errno = ENOMEM;
+ goto error;
+ }
+ }
+
+ len = strlen (end);
+ if ((long int) (n + len) >= path_max)
+ {
+ freesa (buf);
+ __set_errno (ENAMETOOLONG);
+ goto error;
+ }
+
+ /* Careful here, end may be a pointer into extra_buf... */
+ memmove (&extra_buf[n], end, len + 1);
+ name = end = memcpy (extra_buf, buf, n);
+
+ if (buf[0] == '/')
+ dest = rpath + 1; /* It's an absolute symlink */
+ else
+ /* Back up to previous component, ignore if at root already: */
+ if (dest > rpath + 1)
+ while ((--dest)[-1] != '/');
+ }
+#endif
+ }
+ }
+ if (dest > rpath + 1 && dest[-1] == '/')
+ --dest;
+ *dest = '\0';
+
+ if (extra_buf)
+ freesa (extra_buf);
+
+ return resolved ? memcpy (resolved, rpath, dest - rpath + 1) : rpath;
+
+error:
+ {
+ int saved_errno = errno;
+ if (extra_buf)
+ freesa (extra_buf);
+ if (resolved)
+ strcpy (resolved, rpath);
+ else
+ free (rpath);
+ errno = saved_errno;
+ }
+ return NULL;
+}
+#ifdef _LIBC
+versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
+#endif
+
+
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
+char *
+__old_realpath (const char *name, char *resolved)
+{
+ if (resolved == NULL)
+ {
+ __set_errno (EINVAL);
+ return NULL;
+ }
+
+ return __realpath (name, resolved);
+}
+compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0);
+#endif
+
+
+char *
+__canonicalize_file_name (const char *name)
+{
+ return __realpath (name, NULL);
+}
+weak_alias (__canonicalize_file_name, canonicalize_file_name)
+
+#else
+
+/* This declaration is solely to ensure that after preprocessing
+ this file is never empty. */
+typedef int dummy;
+
+#endif
diff --git a/lib/canonicalize.h b/lib/canonicalize.h
new file mode 100644
index 0000000..5c4d3f1
--- /dev/null
+++ b/lib/canonicalize.h
@@ -0,0 +1,54 @@
+/* Return the canonical absolute name of a given file.
+ Copyright (C) 1996-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; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef CANONICALIZE_H_
+# define CANONICALIZE_H_
+
+# if GNULIB_CANONICALIZE
+enum canonicalize_mode_t
+ {
+ /* All components must exist. */
+ CAN_EXISTING = 0,
+
+ /* All components excluding last one must exist. */
+ CAN_ALL_BUT_LAST = 1,
+
+ /* No requirements on components existence. */
+ CAN_MISSING = 2
+ };
+typedef enum canonicalize_mode_t canonicalize_mode_t;
+
+/* Return a malloc'd string containing the canonical absolute name of
+ the named file. This acts like canonicalize_file_name, except that
+ whether components must exist depends on the canonicalize_mode_t
+ argument. */
+char *canonicalize_filename_mode (const char *, canonicalize_mode_t);
+# endif
+
+# if HAVE_DECL_CANONICALIZE_FILE_NAME
+# include <stdlib.h>
+# else
+/* Return a malloc'd string containing the canonical absolute name of
+ the named file. If any file name component does not exist or is a
+ symlink to a nonexistent file, return NULL. A canonical name does
+ not contain any `.', `..' components nor any repeated file name
+ separators ('/') or symlinks. */
+char *canonicalize_file_name (const char *);
+# endif
+
+#endif /* !CANONICALIZE_H_ */
diff --git a/lib/chdir-long.c b/lib/chdir-long.c
new file mode 100644
index 0000000..3fc7ef2
--- /dev/null
+++ b/lib/chdir-long.c
@@ -0,0 +1,265 @@
+/* provide a chdir function that tries not to fail due to ENAMETOOLONG
+ Copyright (C) 2004, 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. */
+
+/* written by Jim Meyering */
+
+#include <config.h>
+
+#include "chdir-long.h"
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "openat.h"
+
+#ifndef PATH_MAX
+# error "compile this file only if your system defines PATH_MAX"
+#endif
+
+struct cd_buf
+{
+ int fd;
+};
+
+static inline void
+cdb_init (struct cd_buf *cdb)
+{
+ cdb->fd = AT_FDCWD;
+}
+
+static inline int
+cdb_fchdir (struct cd_buf const *cdb)
+{
+ return fchdir (cdb->fd);
+}
+
+static inline void
+cdb_free (struct cd_buf const *cdb)
+{
+ if (0 <= cdb->fd)
+ {
+ bool close_fail = close (cdb->fd);
+ assert (! close_fail);
+ }
+}
+
+/* Given a file descriptor of an open directory (or AT_FDCWD), CDB->fd,
+ try to open the CDB->fd-relative directory, DIR. If the open succeeds,
+ update CDB->fd with the resulting descriptor, close the incoming file
+ descriptor, and return zero. Upon failure, return -1 and set errno. */
+static int
+cdb_advance_fd (struct cd_buf *cdb, char const *dir)
+{
+ int new_fd = openat (cdb->fd, dir,
+ O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK);
+ if (new_fd < 0)
+ return -1;
+
+ cdb_free (cdb);
+ cdb->fd = new_fd;
+
+ return 0;
+}
+
+/* Return a pointer to the first non-slash in S. */
+static inline char *
+find_non_slash (char const *s)
+{
+ size_t n_slash = strspn (s, "/");
+ return (char *) s + n_slash;
+}
+
+/* This is a function much like chdir, but without the PATH_MAX limitation
+ on the length of the directory name. A significant difference is that
+ it must be able to modify (albeit only temporarily) the directory
+ name. It handles an arbitrarily long directory name by operating
+ on manageable portions of the name. On systems without the openat
+ syscall, this means changing the working directory to more and more
+ `distant' points along the long directory name and then restoring
+ the working directory. If any of those attempts to save or restore
+ the working directory fails, this function exits nonzero.
+
+ Note that this function may still fail with errno == ENAMETOOLONG, but
+ only if the specified directory name contains a component that is long
+ enough to provoke such a failure all by itself (e.g. if the component
+ has length PATH_MAX or greater on systems that define PATH_MAX). */
+
+int
+chdir_long (char *dir)
+{
+ int e = chdir (dir);
+ if (e == 0 || errno != ENAMETOOLONG)
+ return e;
+
+ {
+ size_t len = strlen (dir);
+ char *dir_end = dir + len;
+ struct cd_buf cdb;
+ size_t n_leading_slash;
+
+ cdb_init (&cdb);
+
+ /* If DIR is the empty string, then the chdir above
+ must have failed and set errno to ENOENT. */
+ assert (0 < len);
+ assert (PATH_MAX <= len);
+
+ /* Count leading slashes. */
+ n_leading_slash = strspn (dir, "/");
+
+ /* Handle any leading slashes as well as any name that matches
+ the regular expression, m!^//hostname[/]*! . Handling this
+ prefix separately usually results in a single additional
+ cdb_advance_fd call, but it's worthwhile, since it makes the
+ code in the following loop cleaner. */
+ if (n_leading_slash == 2)
+ {
+ int err;
+ /* Find next slash.
+ We already know that dir[2] is neither a slash nor '\0'. */
+ char *slash = memchr (dir + 3, '/', dir_end - (dir + 3));
+ if (slash == NULL)
+ {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ *slash = '\0';
+ err = cdb_advance_fd (&cdb, dir);
+ *slash = '/';
+ if (err != 0)
+ goto Fail;
+ dir = find_non_slash (slash + 1);
+ }
+ else if (n_leading_slash)
+ {
+ if (cdb_advance_fd (&cdb, "/") != 0)
+ goto Fail;
+ dir += n_leading_slash;
+ }
+
+ assert (*dir != '/');
+ assert (dir <= dir_end);
+
+ while (PATH_MAX <= dir_end - dir)
+ {
+ int err;
+ /* Find a slash that is PATH_MAX or fewer bytes away from dir.
+ I.e. see if there is a slash that will give us a name of
+ length PATH_MAX-1 or less. */
+ char *slash = memrchr (dir, '/', PATH_MAX);
+ if (slash == NULL)
+ {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+ *slash = '\0';
+ assert (slash - dir < PATH_MAX);
+ err = cdb_advance_fd (&cdb, dir);
+ *slash = '/';
+ if (err != 0)
+ goto Fail;
+
+ dir = find_non_slash (slash + 1);
+ }
+
+ if (dir < dir_end)
+ {
+ if (cdb_advance_fd (&cdb, dir) != 0)
+ goto Fail;
+ }
+
+ if (cdb_fchdir (&cdb) != 0)
+ goto Fail;
+
+ cdb_free (&cdb);
+ return 0;
+
+ Fail:
+ {
+ int saved_errno = errno;
+ cdb_free (&cdb);
+ errno = saved_errno;
+ return -1;
+ }
+ }
+}
+
+#if TEST_CHDIR
+
+# include <stdio.h>
+# include "closeout.h"
+# include "error.h"
+
+char *program_name;
+
+int
+main (int argc, char *argv[])
+{
+ char *line = NULL;
+ size_t n = 0;
+ int len;
+
+ program_name = argv[0];
+ atexit (close_stdout);
+
+ len = getline (&line, &n, stdin);
+ if (len < 0)
+ {
+ int saved_errno = errno;
+ if (feof (stdin))
+ exit (0);
+
+ error (EXIT_FAILURE, saved_errno,
+ "reading standard input");
+ }
+ else if (len == 0)
+ exit (0);
+
+ if (line[len-1] == '\n')
+ line[len-1] = '\0';
+
+ if (chdir_long (line) != 0)
+ error (EXIT_FAILURE, errno,
+ "chdir_long failed: %s", line);
+
+ if (argc <= 1)
+ {
+ /* Using `pwd' here makes sense only if it is a robust implementation,
+ like the one in coreutils after the 2004-04-19 changes. */
+ char const *cmd = "pwd";
+ execlp (cmd, (char *) NULL);
+ error (EXIT_FAILURE, errno, "%s", cmd);
+ }
+
+ fclose (stdin);
+ fclose (stderr);
+
+ exit (EXIT_SUCCESS);
+}
+#endif
+
+/*
+Local Variables:
+compile-command: "gcc -DTEST_CHDIR=1 -g -O -W -Wall chdir-long.c libcoreutils.a"
+End:
+*/
diff --git a/lib/chdir-long.h b/lib/chdir-long.h
new file mode 100644
index 0000000..4852b40
--- /dev/null
+++ b/lib/chdir-long.h
@@ -0,0 +1,35 @@
+/* provide a chdir function that tries not to fail due to ENAMETOOLONG
+ 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 Jim Meyering. */
+
+#include <unistd.h>
+#include <limits.h>
+
+#ifndef PATH_MAX
+# ifdef MAXPATHLEN
+# define PATH_MAX MAXPATHLEN
+# endif
+#endif
+
+/* On systems without PATH_MAX, presume that chdir accepts
+ arbitrarily long directory names. */
+#ifndef PATH_MAX
+# define chdir_long(Dir) chdir (Dir)
+#else
+int chdir_long (char *dir);
+#endif
diff --git a/lib/chown.c b/lib/chown.c
new file mode 100644
index 0000000..b7786f6
--- /dev/null
+++ b/lib/chown.c
@@ -0,0 +1,104 @@
+/* provide consistent interface to chown for systems that don't interpret
+ an ID of -1 as meaning `don't change the corresponding ID'.
+
+ Copyright (C) 1997, 2004, 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. */
+
+/* written by Jim Meyering */
+
+#include <config.h>
+
+/* Specification. */
+#include <unistd.h>
+
+#include <stdbool.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+/* Below we refer to the system's chown(). */
+#undef chown
+
+/* The results of open() in this file are not used with fchdir,
+ therefore save some unnecessary work in fchdir.c. */
+#undef open
+#undef close
+
+/* Provide a more-closely POSIX-conforming version of chown on
+ systems with one or both of the following problems:
+ - chown doesn't treat an ID of -1 as meaning
+ `don't change the corresponding ID'.
+ - chown doesn't dereference symlinks. */
+
+int
+rpl_chown (const char *file, uid_t uid, gid_t gid)
+{
+#if CHOWN_FAILS_TO_HONOR_ID_OF_NEGATIVE_ONE
+ if (gid == (gid_t) -1 || uid == (uid_t) -1)
+ {
+ struct stat file_stats;
+
+ /* Stat file to get id(s) that should remain unchanged. */
+ if (stat (file, &file_stats))
+ return -1;
+
+ if (gid == (gid_t) -1)
+ gid = file_stats.st_gid;
+
+ if (uid == (uid_t) -1)
+ uid = file_stats.st_uid;
+ }
+#endif
+
+#if CHOWN_MODIFIES_SYMLINK
+ {
+ /* Handle the case in which the system-supplied chown function
+ does *not* follow symlinks. Instead, it changes permissions
+ on the symlink itself. To work around that, we open the
+ file (but this can fail due to lack of read or write permission) and
+ use fchown on the resulting descriptor. */
+ int open_flags = O_NONBLOCK | O_NOCTTY;
+ int fd = open (file, O_RDONLY | open_flags);
+ if (0 <= fd
+ || (errno == EACCES
+ && 0 <= (fd = open (file, O_WRONLY | open_flags))))
+ {
+ int result = fchown (fd, uid, gid);
+ int saved_errno = errno;
+
+ /* POSIX says fchown can fail with errno == EINVAL on sockets,
+ so fall back on chown in that case. */
+ struct stat sb;
+ bool fchown_socket_failure =
+ (result != 0 && saved_errno == EINVAL
+ && fstat (fd, &sb) == 0 && S_ISFIFO (sb.st_mode));
+
+ close (fd);
+
+ if (! fchown_socket_failure)
+ {
+ errno = saved_errno;
+ return result;
+ }
+ }
+ else if (errno != EACCES)
+ return -1;
+ }
+#endif
+
+ return chown (file, uid, gid);
+}
diff --git a/lib/close-stream.c b/lib/close-stream.c
new file mode 100644
index 0000000..72d0d68
--- /dev/null
+++ b/lib/close-stream.c
@@ -0,0 +1,76 @@
+/* Close a stream, with nicer error checking than fclose's.
+
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006 Free
+ Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, 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>
+
+#include "close-stream.h"
+
+#include <errno.h>
+#include <stdbool.h>
+
+#include "__fpending.h"
+
+#if USE_UNLOCKED_IO
+# include "unlocked-io.h"
+#endif
+
+/* Close STREAM. Return 0 if successful, EOF (setting errno)
+ otherwise. A failure might set errno to 0 if the error number
+ cannot be determined.
+
+ If a program writes *anything* to STREAM, that program should close
+ STREAM and make sure that it succeeds before exiting. Otherwise,
+ suppose that you go to the extreme of checking the return status
+ of every function that does an explicit write to STREAM. The last
+ printf can succeed in writing to the internal stream buffer, and yet
+ the fclose(STREAM) could still fail (due e.g., to a disk full error)
+ when it tries to write out that buffered data. Thus, you would be
+ left with an incomplete output file and the offending program would
+ exit successfully. Even calling fflush is not always sufficient,
+ since some file systems (NFS and CODA) buffer written/flushed data
+ until an actual close call.
+
+ Besides, it's wasteful to check the return value from every call
+ that writes to STREAM -- just let the internal stream state record
+ the failure. That's what the ferror test is checking below. */
+
+int
+close_stream (FILE *stream)
+{
+ bool some_pending = (__fpending (stream) != 0);
+ bool prev_fail = (ferror (stream) != 0);
+ bool fclose_fail = (fclose (stream) != 0);
+
+ /* Return an error indication if there was a previous failure or if
+ fclose failed, with one exception: ignore an fclose failure if
+ there was no previous error, no data remains to be flushed, and
+ fclose failed with EBADF. That can happen when a program like cp
+ is invoked like this `cp a b >&-' (i.e., with standard output
+ closed) and doesn't generate any output (hence no previous error
+ and nothing to be flushed). */
+
+ if (prev_fail || (fclose_fail && (some_pending || errno != EBADF)))
+ {
+ if (! fclose_fail)
+ errno = 0;
+ return EOF;
+ }
+
+ return 0;
+}
diff --git a/lib/close-stream.h b/lib/close-stream.h
new file mode 100644
index 0000000..be3d419
--- /dev/null
+++ b/lib/close-stream.h
@@ -0,0 +1,2 @@
+#include <stdio.h>
+int close_stream (FILE *stream);
diff --git a/lib/closeout.c b/lib/closeout.c
new file mode 100644
index 0000000..830f16f
--- /dev/null
+++ b/lib/closeout.c
@@ -0,0 +1,86 @@
+/* Close standard output and standard error, exiting with a diagnostic on error.
+
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006 Free
+ Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, 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>
+
+#include "closeout.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+#include "close-stream.h"
+#include "error.h"
+#include "exitfail.h"
+#include "quotearg.h"
+
+static const char *file_name;
+
+/* Set the file name to be reported in the event an error is detected
+ by close_stdout. */
+void
+close_stdout_set_file_name (const char *file)
+{
+ file_name = file;
+}
+
+/* Close standard output. On error, issue a diagnostic and _exit
+ with status 'exit_failure'.
+
+ Also close standard error. On error, _exit with status 'exit_failure'.
+
+ Since close_stdout is commonly registered via 'atexit', POSIX
+ and the C standard both say that it should not call 'exit',
+ because the behavior is undefined if 'exit' is called more than
+ once. So it calls '_exit' instead of 'exit'. If close_stdout
+ is registered via atexit before other functions are registered,
+ the other functions can act before this _exit is invoked.
+
+ Applications that use close_stdout should flush any streams
+ other than stdout and stderr before exiting, since the call to
+ _exit will bypass other buffer flushing. Applications should
+ be flushing and closing other streams anyway, to check for I/O
+ errors. Also, applications should not use tmpfile, since _exit
+ can bypass the removal of these files.
+
+ It's important to detect such failures and exit nonzero because many
+ tools (most notably `make' and other build-management systems) depend
+ on being able to detect failure in other tools via their exit status. */
+
+void
+close_stdout (void)
+{
+ if (close_stream (stdout) != 0)
+ {
+ char const *write_error = _("write error");
+ if (file_name)
+ error (0, errno, "%s: %s", quotearg_colon (file_name),
+ write_error);
+ else
+ error (0, errno, "%s", write_error);
+
+ _exit (exit_failure);
+ }
+
+ if (close_stream (stderr) != 0)
+ _exit (exit_failure);
+}
diff --git a/lib/closeout.h b/lib/closeout.h
new file mode 100644
index 0000000..8bed23b
--- /dev/null
+++ b/lib/closeout.h
@@ -0,0 +1,33 @@
+/* Close standard output and standard error.
+
+ Copyright (C) 1998, 2000, 2003, 2004, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef CLOSEOUT_H
+# define CLOSEOUT_H 1
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+void close_stdout_set_file_name (const char *file);
+void close_stdout (void);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/lib/creat-safer.c b/lib/creat-safer.c
new file mode 100644
index 0000000..f4a2e59
--- /dev/null
+++ b/lib/creat-safer.c
@@ -0,0 +1,32 @@
+/* Invoke creat, but avoid some glitches.
+
+ 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 Jim Meyering. */
+
+#include <config.h>
+
+#include "fcntl-safer.h"
+
+#include <fcntl.h>
+#include "unistd-safer.h"
+
+int
+creat_safer (char const *file, mode_t mode)
+{
+ return fd_safer (creat (file, mode));
+}
diff --git a/lib/dirent_.h b/lib/dirent_.h
new file mode 100644
index 0000000..94e44fc
--- /dev/null
+++ b/lib/dirent_.h
@@ -0,0 +1,50 @@
+/* Wrapper around <dirent.h>.
+ Copyright (C) 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. */
+
+#ifndef _GL_DIRENT_H
+
+/* The include_next requires a split double-inclusion guard. */
+#if @HAVE_INCLUDE_NEXT@
+# include_next <dirent.h>
+#else
+# include @ABSOLUTE_DIRENT_H@
+#endif
+
+#ifndef _GL_DIRENT_H
+#define _GL_DIRENT_H
+
+
+/* Declare overridden functions. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if @REPLACE_FCHDIR@
+# define opendir rpl_opendir
+extern DIR * opendir (const char *);
+# define closedir rpl_closedir
+extern int closedir (DIR *);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _GL_DIRENT_H */
+#endif /* _GL_DIRENT_H */
diff --git a/lib/dirfd.c b/lib/dirfd.c
new file mode 100644
index 0000000..06cb3c4
--- /dev/null
+++ b/lib/dirfd.c
@@ -0,0 +1,29 @@
+/* dirfd.c -- return the file descriptor associated with an open DIR*
+
+ Copyright (C) 2001, 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 Jim Meyering. */
+
+#include <config.h>
+
+#include "dirfd.h"
+
+int
+dirfd (DIR const *dir_p)
+{
+ return DIR_TO_FD (dir_p);
+}
diff --git a/lib/dirfd.h b/lib/dirfd.h
new file mode 100644
index 0000000..05b7777
--- /dev/null
+++ b/lib/dirfd.h
@@ -0,0 +1,29 @@
+/* Declare dirfd, if necessary.
+ Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Written by Jim Meyering. */
+
+#include <sys/types.h>
+
+#include <dirent.h>
+
+#ifndef HAVE_DECL_DIRFD
+"this configure-time declaration test was not run"
+#endif
+#if !HAVE_DECL_DIRFD && !defined dirfd
+int dirfd (DIR const *);
+#endif
diff --git a/lib/dirname.c b/lib/dirname.c
new file mode 100644
index 0000000..16552c6
--- /dev/null
+++ b/lib/dirname.c
@@ -0,0 +1,85 @@
+/* dirname.c -- return all but the last element in a file name
+
+ Copyright (C) 1990, 1998, 2000, 2001, 2003, 2004, 2005, 2006 Free Software
+ Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+#include "dirname.h"
+
+#include <string.h>
+#include "xalloc.h"
+
+/* Return the length of the prefix of FILE that will be used by
+ dir_name. If FILE is in the working directory, this returns zero
+ even though `dir_name (FILE)' will return ".". Works properly even
+ if there are trailing slashes (by effectively ignoring them). */
+
+size_t
+dir_len (char const *file)
+{
+ size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file);
+ size_t length;
+
+ /* Advance prefix_length beyond important leading slashes. */
+ prefix_length += (prefix_length != 0
+ ? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
+ && ISSLASH (file[prefix_length]))
+ : (ISSLASH (file[0])
+ ? ((DOUBLE_SLASH_IS_DISTINCT_ROOT
+ && ISSLASH (file[1]) && ! ISSLASH (file[2])
+ ? 2 : 1))
+ : 0));
+
+ /* Strip the basename and any redundant slashes before it. */
+ for (length = last_component (file) - file;
+ prefix_length < length; length--)
+ if (! ISSLASH (file[length - 1]))
+ break;
+ return length;
+}
+
+
+/* In general, we can't use the builtin `dirname' function if available,
+ since it has different meanings in different environments.
+ In some environments the builtin `dirname' modifies its argument.
+
+ Return the leading directories part of FILE, allocated with xmalloc.
+ Works properly even if there are trailing slashes (by effectively
+ ignoring them). Unlike POSIX dirname(), FILE cannot be NULL.
+
+ If lstat (FILE) would succeed, then { chdir (dir_name (FILE));
+ lstat (base_name (FILE)); } will access the same file. Likewise,
+ if the sequence { chdir (dir_name (FILE));
+ rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE
+ to "foo" in the same directory FILE was in. */
+
+char *
+dir_name (char const *file)
+{
+ size_t length = dir_len (file);
+ bool append_dot = (length == 0
+ || (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
+ && length == FILE_SYSTEM_PREFIX_LEN (file)
+ && file[2] != '\0' && ! ISSLASH (file[2])));
+ char *dir = xmalloc (length + append_dot + 1);
+ memcpy (dir, file, length);
+ if (append_dot)
+ dir[length++] = '.';
+ dir[length] = '\0';
+ return dir;
+}
diff --git a/lib/dirname.h b/lib/dirname.h
new file mode 100644
index 0000000..91e7ed3
--- /dev/null
+++ b/lib/dirname.h
@@ -0,0 +1,70 @@
+/* Take file names apart into directory and base names.
+
+ Copyright (C) 1998, 2001, 2003-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. */
+
+#ifndef DIRNAME_H_
+# define DIRNAME_H_ 1
+
+# include <stdbool.h>
+# include <stddef.h>
+
+# ifndef DIRECTORY_SEPARATOR
+# define DIRECTORY_SEPARATOR '/'
+# endif
+
+# ifndef ISSLASH
+# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
+# endif
+
+# ifndef FILE_SYSTEM_PREFIX_LEN
+# if FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX
+ /* This internal macro assumes ASCII, but all hosts that support drive
+ letters use ASCII. */
+# define _IS_DRIVE_LETTER(c) (((unsigned int) (c) | ('a' - 'A')) - 'a' \
+ <= 'z' - 'a')
+# define FILE_SYSTEM_PREFIX_LEN(Filename) \
+ (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0)
+# else
+# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
+# endif
+# endif
+
+# ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
+# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
+# endif
+
+# ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
+# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
+# endif
+
+# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
+# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
+# else
+# define IS_ABSOLUTE_FILE_NAME(F) \
+ (ISSLASH ((F)[0]) || 0 < FILE_SYSTEM_PREFIX_LEN (F))
+# endif
+# define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
+
+char *base_name (char const *file);
+char *dir_name (char const *file);
+size_t base_len (char const *file);
+size_t dir_len (char const *file);
+char *last_component (char const *file);
+
+bool strip_trailing_slashes (char *file);
+
+#endif /* not DIRNAME_H_ */
diff --git a/lib/dup-safer.c b/lib/dup-safer.c
new file mode 100644
index 0000000..7b12b61
--- /dev/null
+++ b/lib/dup-safer.c
@@ -0,0 +1,45 @@
+/* Invoke dup, but avoid some glitches.
+
+ Copyright (C) 2001, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert. */
+
+#include <config.h>
+
+#include "unistd-safer.h"
+
+#include <fcntl.h>
+
+#include <unistd.h>
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+
+/* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or
+ STDERR_FILENO. */
+
+int
+dup_safer (int fd)
+{
+#if defined F_DUPFD && !defined FCHDIR_REPLACEMENT
+ return fcntl (fd, F_DUPFD, STDERR_FILENO + 1);
+#else
+ /* fd_safer calls us back, but eventually the recursion unwinds and
+ does the right thing. */
+ return fd_safer (dup (fd));
+#endif
+}
diff --git a/lib/dup2.c b/lib/dup2.c
new file mode 100644
index 0000000..8894481
--- /dev/null
+++ b/lib/dup2.c
@@ -0,0 +1,58 @@
+/* Duplicate an open file descriptor to a specified file descriptor.
+
+ Copyright (C) 1999, 2004, 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. */
+
+/* written by Paul Eggert */
+
+#include <config.h>
+
+/* Specification. */
+#include <unistd.h>
+
+#include <errno.h>
+#include <fcntl.h>
+
+#ifndef F_DUPFD
+static int
+dupfd (int fd, int desired_fd)
+{
+ int duplicated_fd = dup (fd);
+ if (duplicated_fd < 0 || duplicated_fd == desired_fd)
+ return duplicated_fd;
+ else
+ {
+ int r = dupfd (fd, desired_fd);
+ int e = errno;
+ close (duplicated_fd);
+ errno = e;
+ return r;
+ }
+}
+#endif
+
+int
+dup2 (int fd, int desired_fd)
+{
+ if (fd == desired_fd)
+ return fd;
+ close (desired_fd);
+#ifdef F_DUPFD
+ return fcntl (fd, F_DUPFD, desired_fd);
+#else
+ return dupfd (fd, desired_fd);
+#endif
+}
diff --git a/lib/error.c b/lib/error.c
index b4edb68..cf86343 100644
--- a/lib/error.c
+++ b/lib/error.c
@@ -1,365 +1,338 @@
-/* Miscellaneous error functions
+/* Error handler for noninteractive utilities
+ Copyright (C) 1990-1998, 2000-2005, 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
- Copyright (C) 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 free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 3, 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.
+ 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 <system.h>
-#include <paxlib.h>
-#include <quote.h>
-#include <quotearg.h>
-
-/* Decode MODE from its binary form in a stat structure, and encode it
- into a 9-byte string STRING, terminated with a NUL. */
-
-void
-pax_decode_mode (mode_t mode, char *string)
-{
- *string++ = mode & S_IRUSR ? 'r' : '-';
- *string++ = mode & S_IWUSR ? 'w' : '-';
- *string++ = (mode & S_ISUID
- ? (mode & S_IXUSR ? 's' : 'S')
- : (mode & S_IXUSR ? 'x' : '-'));
- *string++ = mode & S_IRGRP ? 'r' : '-';
- *string++ = mode & S_IWGRP ? 'w' : '-';
- *string++ = (mode & S_ISGID
- ? (mode & S_IXGRP ? 's' : 'S')
- : (mode & S_IXGRP ? 'x' : '-'));
- *string++ = mode & S_IROTH ? 'r' : '-';
- *string++ = mode & S_IWOTH ? 'w' : '-';
- *string++ = (mode & S_ISVTX
- ? (mode & S_IXOTH ? 't' : 'T')
- : (mode & S_IXOTH ? 'x' : '-'));
- *string = '\0';
-}
-
-/* Report an error associated with the system call CALL and the
- optional name NAME. */
-void
-call_arg_error (char const *call, char const *name)
-{
- int e = errno;
- /* TRANSLATORS: %s after `Cannot' is a function name, e.g. `Cannot open'.
- Directly translating this to another language will not work, first because
- %s itself is not translated.
- Translate it as `%s: Function %s failed'. */
- ERROR ((0, e, _("%s: Cannot %s"), quotearg_colon (name), call));
-}
-
-/* Report a fatal error associated with the system call CALL and
- the optional file name NAME. */
-void
-call_arg_fatal (char const *call, char const *name)
-{
- int e = errno;
- /* TRANSLATORS: %s after `Cannot' is a function name, e.g. `Cannot open'.
- Directly translating this to another language will not work, first because
- %s itself is not translated.
- Translate it as `%s: Function %s failed'. */
- FATAL_ERROR ((0, e, _("%s: Cannot %s"), quotearg_colon (name), call));
-}
-
-/* Report a warning associated with the system call CALL and
- the optional file name NAME. */
-void
-call_arg_warn (char const *call, char const *name)
-{
- int e = errno;
- /* TRANSLATORS: %s after `Cannot' is a function name, e.g. `Cannot open'.
- Directly translating this to another language will not work, first because
- %s itself is not translated.
- Translate it as `%s: Function %s failed'. */
- WARN ((0, e, _("%s: Warning: Cannot %s"), quotearg_colon (name), call));
-}
-
-void
-chmod_error_details (char const *name, mode_t mode)
-{
- int e = errno;
- char buf[10];
- pax_decode_mode (mode, buf);
- ERROR ((0, e, _("%s: Cannot change mode to %s"),
- quotearg_colon (name), buf));
-}
-
-void
-chown_error_details (char const *name, uid_t uid, gid_t gid)
-{
- int e = errno;
- ERROR ((0, e, _("%s: Cannot change ownership to uid %lu, gid %lu"),
- quotearg_colon (name), (unsigned long) uid, (unsigned long) gid));
-}
-
-void
-close_error (char const *name)
-{
- call_arg_error ("close", name);
-}
-
-void
-close_warn (char const *name)
-{
- call_arg_warn ("close", name);
-}
-
-void
-exec_fatal (char const *name)
-{
- call_arg_fatal ("exec", name);
-}
-
-void
-link_error (char const *target, char const *source)
-{
- int e = errno;
- ERROR ((0, e, _("%s: Cannot hard link to %s"),
- quotearg_colon (source), quote_n (1, target)));
-}
-
-void
-mkdir_error (char const *name)
-{
- call_arg_error ("mkdir", name);
-}
-
-void
-mkfifo_error (char const *name)
-{
- call_arg_error ("mkfifo", name);
-}
-
-void
-mknod_error (char const *name)
-{
- call_arg_error ("mknod", name);
-}
-
-void
-open_error (char const *name)
-{
- call_arg_error ("open", name);
-}
-
-void
-open_fatal (char const *name)
-{
- call_arg_fatal ("open", name);
-}
-
-void
-open_warn (char const *name)
-{
- call_arg_warn ("open", name);
-}
-
-void
-read_error (char const *name)
-{
- call_arg_error ("read", name);
-}
-
-void
-read_error_details (char const *name, off_t offset, size_t size)
-{
- char buf[UINTMAX_STRSIZE_BOUND];
- int e = errno;
- ERROR ((0, e,
- ngettext ("%s: Read error at byte %s, while reading %lu byte",
- "%s: Read error at byte %s, while reading %lu bytes",
- size),
- quotearg_colon (name), STRINGIFY_BIGINT (offset, buf),
- (unsigned long) size));
-}
-
-void
-read_warn_details (char const *name, off_t offset, size_t size)
-{
- char buf[UINTMAX_STRSIZE_BOUND];
- int e = errno;
- WARN ((0, e,
- ngettext ("%s: Warning: Read error at byte %s, while reading %lu byte",
- "%s: Warning: Read error at byte %s, while reading %lu bytes",
- size),
- quotearg_colon (name), STRINGIFY_BIGINT (offset, buf),
- (unsigned long) size));
-}
-
-void
-read_fatal (char const *name)
-{
- call_arg_fatal ("read", name);
-}
-
-void
-read_fatal_details (char const *name, off_t offset, size_t size)
-{
- char buf[UINTMAX_STRSIZE_BOUND];
- int e = errno;
- FATAL_ERROR ((0, e,
- ngettext ("%s: Read error at byte %s, while reading %lu byte",
- "%s: Read error at byte %s, while reading %lu bytes",
- size),
- quotearg_colon (name), STRINGIFY_BIGINT (offset, buf),
- (unsigned long) size));
-}
-
-void
-readlink_error (char const *name)
-{
- call_arg_error ("readlink", name);
-}
-
-void
-readlink_warn (char const *name)
-{
- call_arg_warn ("readlink", name);
-}
-
-void
-rmdir_error (char const *name)
-{
- call_arg_error ("rmdir", name);
-}
-
-void
-savedir_error (char const *name)
-{
- call_arg_error ("savedir", name);
-}
-
-void
-savedir_warn (char const *name)
-{
- call_arg_warn ("savedir", name);
-}
-
-void
-seek_error (char const *name)
-{
- call_arg_error ("seek", name);
-}
-
-void
-seek_error_details (char const *name, off_t offset)
-{
- char buf[UINTMAX_STRSIZE_BOUND];
- int e = errno;
- ERROR ((0, e, _("%s: Cannot seek to %s"),
- quotearg_colon (name),
- STRINGIFY_BIGINT (offset, buf)));
-}
-
-void
-seek_warn (char const *name)
-{
- call_arg_warn ("seek", name);
-}
-
-void
-seek_warn_details (char const *name, off_t offset)
-{
- char buf[UINTMAX_STRSIZE_BOUND];
- int e = errno;
- WARN ((0, e, _("%s: Warning: Cannot seek to %s"),
- quotearg_colon (name),
- STRINGIFY_BIGINT (offset, buf)));
-}
-
-void
-symlink_error (char const *contents, char const *name)
-{
- int e = errno;
- ERROR ((0, e, _("%s: Cannot create symlink to %s"),
- quotearg_colon (name), quote_n (1, contents)));
-}
-
-void
-stat_fatal (char const *name)
-{
- call_arg_fatal ("stat", name);
-}
-
-void
-stat_error (char const *name)
-{
- call_arg_error ("stat", name);
-}
-
-void
-stat_warn (char const *name)
-{
- call_arg_warn ("stat", name);
-}
-
-void
-truncate_error (char const *name)
-{
- call_arg_error ("truncate", name);
-}
-
-void
-truncate_warn (char const *name)
-{
- call_arg_warn ("truncate", name);
-}
-
-void
-unlink_error (char const *name)
-{
- call_arg_error ("unlink", name);
-}
-
-void
-utime_error (char const *name)
-{
- call_arg_error ("utime", name);
-}
-
-void
-waitpid_error (char const *name)
-{
- call_arg_error ("waitpid", name);
-}
-
-void
-write_error (char const *name)
-{
- call_arg_error ("write", name);
-}
-
-void
-write_error_details (char const *name, size_t status, size_t size)
-{
- if (status == 0)
- write_error (name);
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
+
+#if !_LIBC
+# include <config.h>
+#endif
+
+#include "error.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if !_LIBC && ENABLE_NLS
+# include "gettext.h"
+#endif
+
+#ifdef _LIBC
+# include <libintl.h>
+# include <stdbool.h>
+# include <stdint.h>
+# include <wchar.h>
+# define mbsrtowcs __mbsrtowcs
+#endif
+
+#if USE_UNLOCKED_IO
+# include "unlocked-io.h"
+#endif
+
+#ifndef _
+# define _(String) String
+#endif
+
+/* If NULL, error will flush stdout, then print on stderr the program
+ name, a colon and a space. Otherwise, error will call this
+ function without parameters instead. */
+void (*error_print_progname) (void);
+
+/* This variable is incremented each time `error' is called. */
+unsigned int error_message_count;
+
+#ifdef _LIBC
+/* In the GNU C library, there is a predefined variable for this. */
+
+# define program_name program_invocation_name
+# include <errno.h>
+# include <limits.h>
+# include <libio/libioP.h>
+
+/* In GNU libc we want do not want to use the common name `error' directly.
+ Instead make it a weak alias. */
+extern void __error (int status, int errnum, const char *message, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+extern void __error_at_line (int status, int errnum, const char *file_name,
+ unsigned int line_number, const char *message,
+ ...)
+ __attribute__ ((__format__ (__printf__, 5, 6)));;
+# define error __error
+# define error_at_line __error_at_line
+
+# include <libio/iolibio.h>
+# define fflush(s) INTUSE(_IO_fflush) (s)
+# undef putc
+# define putc(c, fp) INTUSE(_IO_putc) (c, fp)
+
+# include <bits/libc-lock.h>
+
+#else /* not _LIBC */
+
+# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
+# ifndef HAVE_DECL_STRERROR_R
+"this configure-time declaration test was not run"
+# endif
+char *strerror_r ();
+# endif
+
+/* The calling program should define program_name and set it to the
+ name of the executing program. */
+extern char *program_name;
+
+# if HAVE_STRERROR_R || defined strerror_r
+# define __strerror_r strerror_r
+# endif /* HAVE_STRERROR_R || defined strerror_r */
+#endif /* not _LIBC */
+
+static void
+print_errno_message (int errnum)
+{
+ char const *s;
+
+#if defined HAVE_STRERROR_R || _LIBC
+ char errbuf[1024];
+# if STRERROR_R_CHAR_P || _LIBC
+ s = __strerror_r (errnum, errbuf, sizeof errbuf);
+# else
+ if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
+ s = errbuf;
else
- ERROR ((0, 0,
- ngettext ("%s: Wrote only %lu of %lu byte",
- "%s: Wrote only %lu of %lu bytes",
- size),
- name, (unsigned long int) status, (unsigned long int) size));
-}
-
-void
-write_fatal (char const *name)
-{
- call_arg_fatal ("write", name);
-}
-
-void
-chdir_fatal (char const *name)
-{
- call_arg_fatal ("chdir", name);
-}
+ s = 0;
+# endif
+#else
+ s = strerror (errnum);
+#endif
+
+#if !_LIBC
+ if (! s)
+ s = _("Unknown system error");
+#endif
+
+#if _LIBC
+ __fxprintf (NULL, ": %s", s);
+#else
+ fprintf (stderr, ": %s", s);
+#endif
+}
+
+static void
+error_tail (int status, int errnum, const char *message, va_list args)
+{
+#if _LIBC
+ if (_IO_fwide (stderr, 0) > 0)
+ {
+# define ALLOCA_LIMIT 2000
+ size_t len = strlen (message) + 1;
+ wchar_t *wmessage = NULL;
+ mbstate_t st;
+ size_t res;
+ const char *tmp;
+ bool use_malloc = false;
+
+ while (1)
+ {
+ if (__libc_use_alloca (len * sizeof (wchar_t)))
+ wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
+ else
+ {
+ if (!use_malloc)
+ wmessage = NULL;
+
+ wchar_t *p = (wchar_t *) realloc (wmessage,
+ len * sizeof (wchar_t));
+ if (p == NULL)
+ {
+ free (wmessage);
+ fputws_unlocked (L"out of memory\n", stderr);
+ return;
+ }
+ wmessage = p;
+ use_malloc = true;
+ }
+
+ memset (&st, '\0', sizeof (st));
+ tmp = message;
+
+ res = mbsrtowcs (wmessage, &tmp, len, &st);
+ if (res != len)
+ break;
+
+ if (__builtin_expect (len >= SIZE_MAX / 2, 0))
+ {
+ /* This really should not happen if everything is fine. */
+ res = (size_t) -1;
+ break;
+ }
+
+ len *= 2;
+ }
+
+ if (res == (size_t) -1)
+ {
+ /* The string cannot be converted. */
+ if (use_malloc)
+ {
+ free (wmessage);
+ use_malloc = false;
+ }
+ wmessage = (wchar_t *) L"???";
+ }
+
+ __vfwprintf (stderr, wmessage, args);
+
+ if (use_malloc)
+ free (wmessage);
+ }
+ else
+#endif
+ vfprintf (stderr, message, args);
+ va_end (args);
+
+ ++error_message_count;
+ if (errnum)
+ print_errno_message (errnum);
+#if _LIBC
+ __fxprintf (NULL, "\n");
+#else
+ putc ('\n', stderr);
+#endif
+ fflush (stderr);
+ if (status)
+ exit (status);
+}
+
+
+/* Print the program name and error message MESSAGE, which is a printf-style
+ format string with optional args.
+ If ERRNUM is nonzero, print its corresponding system error message.
+ Exit with status STATUS if it is nonzero. */
+void
+error (int status, int errnum, const char *message, ...)
+{
+ va_list args;
+
+#if defined _LIBC && defined __libc_ptf_call
+ /* We do not want this call to be cut short by a thread
+ cancellation. Therefore disable cancellation for now. */
+ int state = PTHREAD_CANCEL_ENABLE;
+ __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
+ 0);
+#endif
+
+ fflush (stdout);
+#ifdef _LIBC
+ _IO_flockfile (stderr);
+#endif
+ if (error_print_progname)
+ (*error_print_progname) ();
+ else
+ {
+#if _LIBC
+ __fxprintf (NULL, "%s: ", program_name);
+#else
+ fprintf (stderr, "%s: ", program_name);
+#endif
+ }
+
+ va_start (args, message);
+ error_tail (status, errnum, message, args);
+
+#ifdef _LIBC
+ _IO_funlockfile (stderr);
+# ifdef __libc_ptf_call
+ __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
+# endif
+#endif
+}
+
+/* Sometimes we want to have at most one error per line. This
+ variable controls whether this mode is selected or not. */
+int error_one_per_line;
+
+void
+error_at_line (int status, int errnum, const char *file_name,
+ unsigned int line_number, const char *message, ...)
+{
+ va_list args;
+
+ if (error_one_per_line)
+ {
+ static const char *old_file_name;
+ static unsigned int old_line_number;
+
+ if (old_line_number == line_number
+ && (file_name == old_file_name
+ || strcmp (old_file_name, file_name) == 0))
+ /* Simply return and print nothing. */
+ return;
+
+ old_file_name = file_name;
+ old_line_number = line_number;
+ }
+
+#if defined _LIBC && defined __libc_ptf_call
+ /* We do not want this call to be cut short by a thread
+ cancellation. Therefore disable cancellation for now. */
+ int state = PTHREAD_CANCEL_ENABLE;
+ __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
+ 0);
+#endif
+
+ fflush (stdout);
+#ifdef _LIBC
+ _IO_flockfile (stderr);
+#endif
+ if (error_print_progname)
+ (*error_print_progname) ();
+ else
+ {
+#if _LIBC
+ __fxprintf (NULL, "%s:", program_name);
+#else
+ fprintf (stderr, "%s:", program_name);
+#endif
+ }
+
+#if _LIBC
+ __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ",
+ file_name, line_number);
+#else
+ fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
+ file_name, line_number);
+#endif
+
+ va_start (args, message);
+ error_tail (status, errnum, message, args);
+
+#ifdef _LIBC
+ _IO_funlockfile (stderr);
+# ifdef __libc_ptf_call
+ __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
+# endif
+#endif
+}
+
+#ifdef _LIBC
+/* Make the weak alias. */
+# undef error
+# undef error_at_line
+weak_alias (__error, error)
+weak_alias (__error_at_line, error_at_line)
+#endif
diff --git a/lib/error.h b/lib/error.h
new file mode 100644
index 0000000..5a5f247
--- /dev/null
+++ b/lib/error.h
@@ -0,0 +1,66 @@
+/* Declaration for error-reporting function
+ Copyright (C) 1995, 1996, 1997, 2003, 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _ERROR_H
+#define _ERROR_H 1
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
+# define __attribute__(Spec) /* empty */
+# endif
+/* The __-protected variants of `format' and `printf' attributes
+ are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+# define __format__ format
+# define __printf__ printf
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Print a message with `fprintf (stderr, FORMAT, ...)';
+ if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
+ If STATUS is nonzero, terminate the program with `exit (STATUS)'. */
+
+extern void error (int __status, int __errnum, const char *__format, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+
+extern void error_at_line (int __status, int __errnum, const char *__fname,
+ unsigned int __lineno, const char *__format, ...)
+ __attribute__ ((__format__ (__printf__, 5, 6)));
+
+/* If NULL, error will flush stdout, then print on stderr the program
+ name, a colon and a space. Otherwise, error will call this
+ function without parameters instead. */
+extern void (*error_print_progname) (void);
+
+/* This variable is incremented each time `error' is called. */
+extern unsigned int error_message_count;
+
+/* Sometimes we want to have at most one error per line. This
+ variable controls whether this mode is selected or not. */
+extern int error_one_per_line;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* error.h */
diff --git a/lib/exitfail.c b/lib/exitfail.c
new file mode 100644
index 0000000..373d325
--- /dev/null
+++ b/lib/exitfail.c
@@ -0,0 +1,26 @@
+/* Failure exit status
+
+ Copyright (C) 2002, 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; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+#include "exitfail.h"
+
+#include <stdlib.h>
+
+int volatile exit_failure = EXIT_FAILURE;
diff --git a/lib/exitfail.h b/lib/exitfail.h
new file mode 100644
index 0000000..e46cf9c
--- /dev/null
+++ b/lib/exitfail.h
@@ -0,0 +1,20 @@
+/* Failure exit status
+
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+extern int volatile exit_failure;
diff --git a/lib/fatal.c b/lib/fatal.c
new file mode 100644
index 0000000..bcce42c
--- /dev/null
+++ b/lib/fatal.c
@@ -0,0 +1,27 @@
+/* This file is part of GNU cpio.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA. */
+
+#include <system.h>
+#include <paxlib.h>
+
+void
+fatal_exit ()
+{
+ exit (PAXEXIT_FAILURE);
+}
+
diff --git a/lib/fchdir.c b/lib/fchdir.c
new file mode 100644
index 0000000..e3ec2fc
--- /dev/null
+++ b/lib/fchdir.c
@@ -0,0 +1,279 @@
+/* fchdir replacement.
+ Copyright (C) 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>
+
+/* Specification. */
+#include <unistd.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#include "canonicalize.h"
+#include "dirfd.h"
+
+/* This replacement assumes that a directory is not renamed while opened
+ through a file descriptor. */
+
+/* Array of file descriptors opened. If it points to a directory, it stores
+ info about this directory; otherwise it stores an errno value of ENOTDIR. */
+typedef struct
+{
+ char *name; /* Absolute name of the directory, or NULL. */
+ int saved_errno; /* If name == NULL: The error code describing the failure
+ reason. */
+} dir_info_t;
+static dir_info_t *dirs;
+static size_t dirs_allocated;
+
+/* Try to ensure dirs has enough room for a slot at index fd. */
+static void
+ensure_dirs_slot (size_t fd)
+{
+ if (fd >= dirs_allocated)
+ {
+ size_t new_allocated;
+ dir_info_t *new_dirs;
+ size_t i;
+
+ new_allocated = 2 * dirs_allocated + 1;
+ if (new_allocated <= fd)
+ new_allocated = fd + 1;
+ new_dirs =
+ (dirs != NULL
+ ? (dir_info_t *) realloc (dirs, new_allocated * sizeof (dir_info_t))
+ : (dir_info_t *) malloc (new_allocated * sizeof (dir_info_t)));
+ if (new_dirs != NULL)
+ {
+ for (i = dirs_allocated; i < new_allocated; i++)
+ {
+ new_dirs[i].name = NULL;
+ new_dirs[i].saved_errno = ENOTDIR;
+ }
+ dirs = new_dirs;
+ dirs_allocated = new_allocated;
+ }
+ }
+}
+
+/* Override open() and close(), to keep track of the open file descriptors. */
+
+int
+close (int fd)
+#undef close
+{
+ int retval = close (fd);
+
+ if (retval >= 0 && fd >= 0 && fd < dirs_allocated)
+ {
+ if (dirs[fd].name != NULL)
+ free (dirs[fd].name);
+ dirs[fd].name = NULL;
+ dirs[fd].saved_errno = ENOTDIR;
+ }
+ return retval;
+}
+
+int
+open (const char *filename, int flags, ...)
+#undef open
+{
+ mode_t mode;
+ int fd;
+ struct stat statbuf;
+
+ mode = 0;
+ if (flags & O_CREAT)
+ {
+ va_list arg;
+ va_start (arg, flags);
+
+ /* If mode_t is narrower than int, use the promoted type (int),
+ not mode_t. Use sizeof to guess whether mode_t is narrower;
+ we don't know of any practical counterexamples. */
+ mode = (sizeof (mode_t) < sizeof (int)
+ ? va_arg (arg, int)
+ : va_arg (arg, mode_t));
+
+ va_end (arg);
+ }
+ fd = open (filename, flags, mode);
+ if (fd >= 0)
+ {
+ ensure_dirs_slot (fd);
+ if (fd < dirs_allocated
+ && fstat (fd, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode))
+ {
+ dirs[fd].name = canonicalize_file_name (filename);
+ if (dirs[fd].name == NULL)
+ dirs[fd].saved_errno = errno;
+ }
+ }
+ return fd;
+}
+
+/* Override opendir() and closedir(), to keep track of the open file
+ descriptors. Needed because there is a function dirfd(). */
+
+int
+closedir (DIR *dp)
+#undef closedir
+{
+ int fd = dirfd (dp);
+ int retval = closedir (dp);
+
+ if (retval >= 0 && fd >= 0 && fd < dirs_allocated)
+ {
+ if (dirs[fd].name != NULL)
+ free (dirs[fd].name);
+ dirs[fd].name = NULL;
+ dirs[fd].saved_errno = ENOTDIR;
+ }
+ return retval;
+}
+
+DIR *
+opendir (const char *filename)
+#undef opendir
+{
+ DIR *dp;
+
+ dp = opendir (filename);
+ if (dp != NULL)
+ {
+ int fd = dirfd (dp);
+ if (fd >= 0)
+ {
+ ensure_dirs_slot (fd);
+ if (fd < dirs_allocated)
+ {
+ dirs[fd].name = canonicalize_file_name (filename);
+ if (dirs[fd].name == NULL)
+ dirs[fd].saved_errno = errno;
+ }
+ }
+ }
+ return dp;
+}
+
+/* Override dup() and dup2(), to keep track of open file descriptors. */
+
+int
+dup (int oldfd)
+#undef dup
+{
+ int newfd = dup (oldfd);
+
+ if (oldfd >= 0 && newfd >= 0)
+ {
+ ensure_dirs_slot (newfd);
+ if (newfd < dirs_allocated)
+ {
+ if (oldfd < dirs_allocated)
+ {
+ if (dirs[oldfd].name != NULL)
+ {
+ dirs[newfd].name = strdup (dirs[oldfd].name);
+ if (dirs[newfd].name == NULL)
+ dirs[newfd].saved_errno = ENOMEM;
+ }
+ else
+ {
+ dirs[newfd].name = NULL;
+ dirs[newfd].saved_errno = dirs[oldfd].saved_errno;
+ }
+ }
+ else
+ {
+ dirs[newfd].name = NULL;
+ dirs[newfd].saved_errno = ENOMEM;
+ }
+ }
+ }
+ return newfd;
+}
+
+int
+dup2 (int oldfd, int newfd)
+#undef dup2
+{
+ int retval = dup2 (oldfd, newfd);
+
+ if (retval >= 0 && oldfd >= 0 && newfd >= 0 && newfd != oldfd)
+ {
+ ensure_dirs_slot (newfd);
+ if (newfd < dirs_allocated)
+ {
+ if (oldfd < dirs_allocated)
+ {
+ if (dirs[oldfd].name != NULL)
+ {
+ dirs[newfd].name = strdup (dirs[oldfd].name);
+ if (dirs[newfd].name == NULL)
+ dirs[newfd].saved_errno = ENOMEM;
+ }
+ else
+ {
+ dirs[newfd].name = NULL;
+ dirs[newfd].saved_errno = dirs[oldfd].saved_errno;
+ }
+ }
+ else
+ {
+ dirs[newfd].name = NULL;
+ dirs[newfd].saved_errno = ENOMEM;
+ }
+ }
+ }
+ return retval;
+}
+
+/* Implement fchdir() in terms of chdir(). */
+
+int
+fchdir (int fd)
+{
+ if (fd >= 0)
+ {
+ if (fd < dirs_allocated)
+ {
+ if (dirs[fd].name != NULL)
+ return chdir (dirs[fd].name);
+ else
+ {
+ errno = dirs[fd].saved_errno;
+ return -1;
+ }
+ }
+ else
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+ else
+ {
+ errno = EBADF;
+ return -1;
+ }
+}
diff --git a/lib/fchmodat.c b/lib/fchmodat.c
new file mode 100644
index 0000000..2598b70
--- /dev/null
+++ b/lib/fchmodat.c
@@ -0,0 +1,50 @@
+/* Change the protections of file relative to an open directory.
+ Copyright (C) 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 Jim Meyering */
+
+#include <config.h>
+
+#include "openat.h"
+#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
+#include "save-cwd.h"
+#include "openat-priv.h"
+
+#ifndef HAVE_LCHMOD
+/* Use a different name, to avoid conflicting with any
+ system-supplied declaration. */
+# undef lchmod
+# define lchmod lchmod_rpl
+static int lchmod (char const *f, mode_t m) { errno = ENOSYS; return -1; }
+#endif
+
+/* Solaris 10 has no function like this.
+ Invoke chmod or lchmod on file, FILE, using mode MODE, in the directory
+ open on descriptor FD. If possible, do it without changing the
+ working directory. Otherwise, resort to using save_cwd/fchdir,
+ then mkdir/restore_cwd. If either the save_cwd or the restore_cwd
+ fails, then give a diagnostic and exit nonzero.
+ Note that an attempt to use a FLAG value of AT_SYMLINK_NOFOLLOW
+ on a system without lchmod support causes this function to fail. */
+
+#define AT_FUNC_NAME fchmodat
+#define AT_FUNC_F1 lchmod
+#define AT_FUNC_F2 chmod
+#define AT_FUNC_USE_F1_COND flag == AT_SYMLINK_NOFOLLOW
+#define AT_FUNC_POST_FILE_PARAM_DECLS , mode_t mode, int flag
+#define AT_FUNC_POST_FILE_ARGS , mode
+#include "at-func.c"
diff --git a/lib/fchown-stub.c b/lib/fchown-stub.c
new file mode 100644
index 0000000..6be750b
--- /dev/null
+++ b/lib/fchown-stub.c
@@ -0,0 +1,16 @@
+#include <config.h>
+
+#include <sys/types.h>
+#include <errno.h>
+
+/* A trivial substitute for `fchown'.
+
+ DJGPP 2.03 and earlier (and perhaps later) don't have `fchown',
+ so we pretend no-one has permission for this operation. */
+
+int
+fchown (int fd, uid_t uid, gid_t gid)
+{
+ errno = EPERM;
+ return -1;
+}
diff --git a/lib/fchownat.c b/lib/fchownat.c
new file mode 100644
index 0000000..801c92a
--- /dev/null
+++ b/lib/fchownat.c
@@ -0,0 +1,50 @@
+/* This function serves as replacement for a missing fchownat function,
+ as well as a work around for the fchownat bug in glibc-2.4:
+ <http://lists.ubuntu.com/archives/ubuntu-users/2006-September/093218.html>
+ when the buggy fchownat-with-AT_SYMLINK_NOFOLLOW operates on a symlink, it
+ mistakenly affects the symlink referent, rather than the symlink itself.
+
+ Copyright (C) 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. */
+
+/* written by Jim Meyering */
+
+#include <config.h>
+
+#include "openat.h"
+
+#include <unistd.h>
+
+#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
+#include "lchown.h"
+#include "save-cwd.h"
+#include "openat-priv.h"
+
+/* Replacement for Solaris' function by the same name.
+ Invoke chown or lchown on file, FILE, using OWNER and GROUP, in the
+ directory open on descriptor FD. If FLAG is AT_SYMLINK_NOFOLLOW, then
+ use lchown, otherwise, use chown. If possible, do it without changing
+ the working directory. Otherwise, resort to using save_cwd/fchdir,
+ then mkdir/restore_cwd. If either the save_cwd or the restore_cwd
+ fails, then give a diagnostic and exit nonzero. */
+
+#define AT_FUNC_NAME fchownat
+#define AT_FUNC_F1 lchown
+#define AT_FUNC_F2 chown
+#define AT_FUNC_USE_F1_COND flag == AT_SYMLINK_NOFOLLOW
+#define AT_FUNC_POST_FILE_PARAM_DECLS , uid_t owner, gid_t group, int flag
+#define AT_FUNC_POST_FILE_ARGS , owner, group
+#include "at-func.c"
diff --git a/lib/fcntl--.h b/lib/fcntl--.h
new file mode 100644
index 0000000..51b869e
--- /dev/null
+++ b/lib/fcntl--.h
@@ -0,0 +1,28 @@
+/* Like fcntl.h, but redefine some names to avoid glitches.
+
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert. */
+
+#include <fcntl.h>
+#include "fcntl-safer.h"
+
+#undef open
+#define open open_safer
+
+#undef creat
+#define creat creat_safer
diff --git a/lib/fcntl-safer.h b/lib/fcntl-safer.h
new file mode 100644
index 0000000..cab6aab
--- /dev/null
+++ b/lib/fcntl-safer.h
@@ -0,0 +1,24 @@
+/* Invoke fcntl-like functions, but avoid some glitches.
+
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert. */
+
+#include <sys/types.h>
+
+int open_safer (char const *, int, ...);
+int creat_safer (char const *, mode_t);
diff --git a/lib/fcntl_.h b/lib/fcntl_.h
new file mode 100644
index 0000000..1330cde
--- /dev/null
+++ b/lib/fcntl_.h
@@ -0,0 +1,125 @@
+/* Like <fcntl.h>, but with non-working flags defined to 0.
+
+ Copyright (C) 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. */
+
+/* written by Paul Eggert */
+
+#ifndef _GL_FCNTL_H
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+/* The include_next requires a split double-inclusion guard. */
+#if @HAVE_INCLUDE_NEXT@
+# include_next <fcntl.h>
+#else
+# include @ABSOLUTE_FCNTL_H@
+#endif
+
+#ifndef _GL_FCNTL_H
+#define _GL_FCNTL_H
+
+
+/* Declare overridden functions. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef FCHDIR_REPLACEMENT
+# define open rpl_open
+extern int open (const char *, int, ...);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* Fix up the O_* macros. */
+
+#if !defined O_DIRECT && defined O_DIRECTIO
+/* Tru64 spells it `O_DIRECTIO'. */
+# define O_DIRECT O_DIRECTIO
+#endif
+
+#ifndef O_DIRECT
+# define O_DIRECT 0
+#endif
+
+#ifndef O_DIRECTORY
+# define O_DIRECTORY 0
+#endif
+
+#ifndef O_DSYNC
+# define O_DSYNC 0
+#endif
+
+#ifndef O_NDELAY
+# define O_NDELAY 0
+#endif
+
+#ifndef O_NOATIME
+# define O_NOATIME 0
+#endif
+
+#ifndef O_NONBLOCK
+# define O_NONBLOCK O_NDELAY
+#endif
+
+#ifndef O_NOCTTY
+# define O_NOCTTY 0
+#endif
+
+#ifndef O_NOFOLLOW
+# define O_NOFOLLOW 0
+#endif
+
+#ifndef O_NOLINKS
+# define O_NOLINKS 0
+#endif
+
+#ifndef O_RSYNC
+# define O_RSYNC 0
+#endif
+
+#ifndef O_SYNC
+# define O_SYNC 0
+#endif
+
+/* For systems that distinguish between text and binary I/O.
+ O_BINARY is usually declared in fcntl.h */
+#if !defined O_BINARY && defined _O_BINARY
+ /* For MSC-compatible compilers. */
+# define O_BINARY _O_BINARY
+# define O_TEXT _O_TEXT
+#endif
+
+#ifdef __BEOS__
+ /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */
+# undef O_BINARY
+# undef O_TEXT
+#endif
+
+#ifndef O_BINARY
+# define O_BINARY 0
+# define O_TEXT 0
+#endif
+
+
+#endif /* _GL_FCNTL_H */
+#endif /* _GL_FCNTL_H */
diff --git a/lib/fd-safer.c b/lib/fd-safer.c
new file mode 100644
index 0000000..256bfa4
--- /dev/null
+++ b/lib/fd-safer.c
@@ -0,0 +1,57 @@
+/* Return a safer copy of a file descriptor.
+
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert. */
+
+#include <config.h>
+
+#include "unistd-safer.h"
+
+#include <errno.h>
+
+#include <unistd.h>
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+
+/* Return FD, unless FD would be a copy of standard input, output, or
+ error; in that case, return a duplicate of FD, closing FD. On
+ failure to duplicate, close FD, set errno, and return -1. Preserve
+ errno if FD is negative, so that the caller can always inspect
+ errno when the returned value is negative.
+
+ This function is usefully wrapped around functions that return file
+ descriptors, e.g., fd_safer (open ("file", O_RDONLY)). */
+
+int
+fd_safer (int fd)
+{
+ if (STDIN_FILENO <= fd && fd <= STDERR_FILENO)
+ {
+ int f = dup_safer (fd);
+ int e = errno;
+ close (fd);
+ errno = e;
+ fd = f;
+ }
+
+ return fd;
+}
diff --git a/lib/fileblocks.c b/lib/fileblocks.c
new file mode 100644
index 0000000..4024d1e
--- /dev/null
+++ b/lib/fileblocks.c
@@ -0,0 +1,75 @@
+/* Convert file size to number of blocks on System V-like machines.
+
+ Copyright (C) 1990, 1997, 1998, 1999, 2004, 2005, 2006 Free Software
+ Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Brian L. Matthews, blm@6sceng.UUCP. */
+
+#include <config.h>
+
+#include <sys/types.h>
+
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#if !HAVE_STRUCT_STAT_ST_BLOCKS && !defined _POSIX_SOURCE && defined BSIZE
+
+# include <unistd.h>
+
+# ifndef NINDIR
+
+# if defined __DJGPP__
+typedef long daddr_t; /* for disk address */
+# endif
+
+/* Some SysV's, like Irix, seem to lack this. Hope it's correct. */
+/* Number of inode pointers per indirect block. */
+# define NINDIR (BSIZE / sizeof (daddr_t))
+# endif /* !NINDIR */
+
+/* Number of direct block addresses in an inode. */
+# define NDIR 10
+
+/* Return the number of 512-byte blocks in a file of SIZE bytes. */
+
+off_t
+st_blocks (off_t size)
+{
+ off_t datablks = size / 512 + (size % 512 != 0);
+ off_t indrblks = 0;
+
+ if (datablks > NDIR)
+ {
+ indrblks = (datablks - NDIR - 1) / NINDIR + 1;
+
+ if (datablks > NDIR + NINDIR)
+ {
+ indrblks += (datablks - NDIR - NINDIR - 1) / (NINDIR * NINDIR) + 1;
+
+ if (datablks > NDIR + NINDIR + NINDIR * NINDIR)
+ indrblks++;
+ }
+ }
+
+ return datablks + indrblks;
+}
+#else
+/* This declaration is solely to ensure that after preprocessing
+ this file is never empty. */
+typedef int textutils_fileblocks_unused;
+#endif
diff --git a/lib/float+.h b/lib/float+.h
new file mode 100644
index 0000000..4de25a9
--- /dev/null
+++ b/lib/float+.h
@@ -0,0 +1,148 @@
+/* Supplemental information about the floating-point formats.
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2007.
+
+ 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 _FLOATPLUS_H
+#define _FLOATPLUS_H
+
+#include <float.h>
+#include <limits.h>
+
+/* Number of bits in the mantissa of a floating-point number, including the
+ "hidden bit". */
+#if FLT_RADIX == 2
+# define FLT_MANT_BIT FLT_MANT_DIG
+# define DBL_MANT_BIT DBL_MANT_DIG
+# define LDBL_MANT_BIT LDBL_MANT_DIG
+#elif FLT_RADIX == 4
+# define FLT_MANT_BIT (FLT_MANT_DIG * 2)
+# define DBL_MANT_BIT (DBL_MANT_DIG * 2)
+# define LDBL_MANT_BIT (LDBL_MANT_DIG * 2)
+#elif FLT_RADIX == 16
+# define FLT_MANT_BIT (FLT_MANT_DIG * 4)
+# define DBL_MANT_BIT (DBL_MANT_DIG * 4)
+# define LDBL_MANT_BIT (LDBL_MANT_DIG * 4)
+#endif
+
+/* Bit mask that can be used to mask the exponent, as an unsigned number. */
+#define FLT_EXP_MASK ((FLT_MAX_EXP - FLT_MIN_EXP) | 7)
+#define DBL_EXP_MASK ((DBL_MAX_EXP - DBL_MIN_EXP) | 7)
+#define LDBL_EXP_MASK ((LDBL_MAX_EXP - LDBL_MIN_EXP) | 7)
+
+/* Number of bits used for the exponent of a floating-point number, including
+ the exponent's sign. */
+#define FLT_EXP_BIT \
+ (FLT_EXP_MASK < 0x100 ? 8 : \
+ FLT_EXP_MASK < 0x200 ? 9 : \
+ FLT_EXP_MASK < 0x400 ? 10 : \
+ FLT_EXP_MASK < 0x800 ? 11 : \
+ FLT_EXP_MASK < 0x1000 ? 12 : \
+ FLT_EXP_MASK < 0x2000 ? 13 : \
+ FLT_EXP_MASK < 0x4000 ? 14 : \
+ FLT_EXP_MASK < 0x8000 ? 15 : \
+ FLT_EXP_MASK < 0x10000 ? 16 : \
+ FLT_EXP_MASK < 0x20000 ? 17 : \
+ FLT_EXP_MASK < 0x40000 ? 18 : \
+ FLT_EXP_MASK < 0x80000 ? 19 : \
+ FLT_EXP_MASK < 0x100000 ? 20 : \
+ FLT_EXP_MASK < 0x200000 ? 21 : \
+ FLT_EXP_MASK < 0x400000 ? 22 : \
+ FLT_EXP_MASK < 0x800000 ? 23 : \
+ FLT_EXP_MASK < 0x1000000 ? 24 : \
+ FLT_EXP_MASK < 0x2000000 ? 25 : \
+ FLT_EXP_MASK < 0x4000000 ? 26 : \
+ FLT_EXP_MASK < 0x8000000 ? 27 : \
+ FLT_EXP_MASK < 0x10000000 ? 28 : \
+ FLT_EXP_MASK < 0x20000000 ? 29 : \
+ FLT_EXP_MASK < 0x40000000 ? 30 : \
+ FLT_EXP_MASK <= 0x7fffffff ? 31 : \
+ 32)
+#define DBL_EXP_BIT \
+ (DBL_EXP_MASK < 0x100 ? 8 : \
+ DBL_EXP_MASK < 0x200 ? 9 : \
+ DBL_EXP_MASK < 0x400 ? 10 : \
+ DBL_EXP_MASK < 0x800 ? 11 : \
+ DBL_EXP_MASK < 0x1000 ? 12 : \
+ DBL_EXP_MASK < 0x2000 ? 13 : \
+ DBL_EXP_MASK < 0x4000 ? 14 : \
+ DBL_EXP_MASK < 0x8000 ? 15 : \
+ DBL_EXP_MASK < 0x10000 ? 16 : \
+ DBL_EXP_MASK < 0x20000 ? 17 : \
+ DBL_EXP_MASK < 0x40000 ? 18 : \
+ DBL_EXP_MASK < 0x80000 ? 19 : \
+ DBL_EXP_MASK < 0x100000 ? 20 : \
+ DBL_EXP_MASK < 0x200000 ? 21 : \
+ DBL_EXP_MASK < 0x400000 ? 22 : \
+ DBL_EXP_MASK < 0x800000 ? 23 : \
+ DBL_EXP_MASK < 0x1000000 ? 24 : \
+ DBL_EXP_MASK < 0x2000000 ? 25 : \
+ DBL_EXP_MASK < 0x4000000 ? 26 : \
+ DBL_EXP_MASK < 0x8000000 ? 27 : \
+ DBL_EXP_MASK < 0x10000000 ? 28 : \
+ DBL_EXP_MASK < 0x20000000 ? 29 : \
+ DBL_EXP_MASK < 0x40000000 ? 30 : \
+ DBL_EXP_MASK <= 0x7fffffff ? 31 : \
+ 32)
+#define LDBL_EXP_BIT \
+ (LDBL_EXP_MASK < 0x100 ? 8 : \
+ LDBL_EXP_MASK < 0x200 ? 9 : \
+ LDBL_EXP_MASK < 0x400 ? 10 : \
+ LDBL_EXP_MASK < 0x800 ? 11 : \
+ LDBL_EXP_MASK < 0x1000 ? 12 : \
+ LDBL_EXP_MASK < 0x2000 ? 13 : \
+ LDBL_EXP_MASK < 0x4000 ? 14 : \
+ LDBL_EXP_MASK < 0x8000 ? 15 : \
+ LDBL_EXP_MASK < 0x10000 ? 16 : \
+ LDBL_EXP_MASK < 0x20000 ? 17 : \
+ LDBL_EXP_MASK < 0x40000 ? 18 : \
+ LDBL_EXP_MASK < 0x80000 ? 19 : \
+ LDBL_EXP_MASK < 0x100000 ? 20 : \
+ LDBL_EXP_MASK < 0x200000 ? 21 : \
+ LDBL_EXP_MASK < 0x400000 ? 22 : \
+ LDBL_EXP_MASK < 0x800000 ? 23 : \
+ LDBL_EXP_MASK < 0x1000000 ? 24 : \
+ LDBL_EXP_MASK < 0x2000000 ? 25 : \
+ LDBL_EXP_MASK < 0x4000000 ? 26 : \
+ LDBL_EXP_MASK < 0x8000000 ? 27 : \
+ LDBL_EXP_MASK < 0x10000000 ? 28 : \
+ LDBL_EXP_MASK < 0x20000000 ? 29 : \
+ LDBL_EXP_MASK < 0x40000000 ? 30 : \
+ LDBL_EXP_MASK <= 0x7fffffff ? 31 : \
+ 32)
+
+/* Number of bits used for a floating-point number: the mantissa (not
+ counting the "hidden bit", since it may or may not be explicit), the
+ exponent, and the sign. */
+#define FLT_TOTAL_BIT ((FLT_MANT_BIT - 1) + FLT_EXP_BIT + 1)
+#define DBL_TOTAL_BIT ((DBL_MANT_BIT - 1) + DBL_EXP_BIT + 1)
+#define LDBL_TOTAL_BIT ((LDBL_MANT_BIT - 1) + LDBL_EXP_BIT + 1)
+
+/* Number of bytes used for a floating-point number.
+ This can be smaller than the 'sizeof'. For example, on i386 systems,
+ 'long double' most often have LDBL_MANT_BIT = 64, LDBL_EXP_BIT = 16, hence
+ LDBL_TOTAL_BIT = 80 bits, i.e. 10 bytes of consecutive memory, but
+ sizeof (long double) = 12 or = 16. */
+#define SIZEOF_FLT ((FLT_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT)
+#define SIZEOF_DBL ((DBL_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT)
+#define SIZEOF_LDBL ((LDBL_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT)
+
+/* Verify that SIZEOF_FLT <= sizeof (float) etc. */
+typedef int verify_sizeof_flt[2 * (SIZEOF_FLT <= sizeof (float)) - 1];
+typedef int verify_sizeof_dbl[2 * (SIZEOF_DBL <= sizeof (double)) - 1];
+typedef int verify_sizeof_ldbl[2 * (SIZEOF_LDBL <= sizeof (long double)) - 1];
+
+#endif /* _FLOATPLUS_H */
diff --git a/lib/float_.h b/lib/float_.h
new file mode 100644
index 0000000..d898d85
--- /dev/null
+++ b/lib/float_.h
@@ -0,0 +1,63 @@
+/* A correct <float.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. */
+
+#ifndef _GL_FLOAT_H
+
+/* The include_next requires a split double-inclusion guard. */
+#if @HAVE_INCLUDE_NEXT@
+# include_next <float.h>
+#else
+# include @ABSOLUTE_FLOAT_H@
+#endif
+
+#ifndef _GL_FLOAT_H
+#define _GL_FLOAT_H
+
+/* 'long double' properties. */
+#if defined __i386__ && defined __BEOS__
+/* Number of mantissa units, in base FLT_RADIX. */
+# undef LDBL_MANT_DIG
+# define LDBL_MANT_DIG 64
+/* Number of decimal digits that is sufficient for representing a number. */
+# undef LDBL_DIG
+# define LDBL_DIG 18
+/* x-1 where x is the smallest representable number > 1. */
+# undef LDBL_EPSILON
+# define LDBL_EPSILON 1.0842021724855044340E-19L
+/* Minimum e such that FLT_RADIX^(e-1) is a normalized number. */
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP (-16381)
+/* Maximum e such that FLT_RADIX^(e-1) is a representable finite number. */
+# undef LDBL_MAX_EXP
+# define LDBL_MAX_EXP 16384
+/* Minimum positive normalized number. */
+# undef LDBL_MIN
+# define LDBL_MIN 3.3621031431120935063E-4932L
+/* Maximum representable finite number. */
+# undef LDBL_MAX
+# define LDBL_MAX 1.1897314953572317650E+4932L
+/* Minimum e such that 10^e is in the range of normalized numbers. */
+# undef LDBL_MIN_10_EXP
+# define LDBL_MIN_10_EXP (-4931)
+/* Maximum e such that 10^e is in the range of representable finite numbers. */
+# undef LDBL_MAX_10_EXP
+# define LDBL_MAX_10_EXP 4932
+#endif
+
+#endif /* _GL_FLOAT_H */
+#endif /* _GL_FLOAT_H */
diff --git a/lib/fnmatch.c b/lib/fnmatch.c
new file mode 100644
index 0000000..02dd365
--- /dev/null
+++ b/lib/fnmatch.c
@@ -0,0 +1,354 @@
+/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003,2004,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. */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+/* Enable GNU extensions in fnmatch.h. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#if ! defined __builtin_expect && __GNUC__ < 3
+# define __builtin_expect(expr, expected) (expr)
+#endif
+
+#include <fnmatch.h>
+
+#include <alloca.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define WIDE_CHAR_SUPPORT \
+ (HAVE_WCTYPE_H && HAVE_BTOWC && HAVE_ISWCTYPE \
+ && HAVE_WMEMCHR && (HAVE_WMEMCPY || HAVE_WMEMPCPY))
+
+/* For platform which support the ISO C amendement 1 functionality we
+ support user defined character classes. */
+#if defined _LIBC || WIDE_CHAR_SUPPORT
+# include <wctype.h>
+# include <wchar.h>
+#endif
+
+/* We need some of the locale data (the collation sequence information)
+ but there is no interface to get this information in general. Therefore
+ we support a correct implementation only in glibc. */
+#ifdef _LIBC
+# include "../locale/localeinfo.h"
+# include "../locale/elem-hash.h"
+# include "../locale/coll-lookup.h"
+# include <shlib-compat.h>
+
+# define CONCAT(a,b) __CONCAT(a,b)
+# define mbsrtowcs __mbsrtowcs
+# define fnmatch __fnmatch
+extern int fnmatch (const char *pattern, const char *string, int flags);
+#endif
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set. */
+#define NO_LEADING_PERIOD(flags) \
+ ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD))
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself, and have not detected a bug
+ in the library. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#if defined _LIBC || !defined __GNU_LIBRARY__ || !HAVE_FNMATCH_GNU
+
+
+# if ! (defined isblank || HAVE_DECL_ISBLANK)
+# define isblank(c) ((c) == ' ' || (c) == '\t')
+# endif
+
+# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
+
+# if defined _LIBC || WIDE_CHAR_SUPPORT
+/* The GNU C library provides support for user-defined character classes
+ and the functions from ISO C amendement 1. */
+# ifdef CHARCLASS_NAME_MAX
+# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
+# else
+/* This shouldn't happen but some implementation might still have this
+ problem. Use a reasonable default value. */
+# define CHAR_CLASS_MAX_LENGTH 256
+# endif
+
+# ifdef _LIBC
+# define IS_CHAR_CLASS(string) __wctype (string)
+# else
+# define IS_CHAR_CLASS(string) wctype (string)
+# endif
+
+# ifdef _LIBC
+# define ISWCTYPE(WC, WT) __iswctype (WC, WT)
+# else
+# define ISWCTYPE(WC, WT) iswctype (WC, WT)
+# endif
+
+# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC
+/* In this case we are implementing the multibyte character handling. */
+# define HANDLE_MULTIBYTE 1
+# endif
+
+# else
+# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
+
+# define IS_CHAR_CLASS(string) \
+ (STREQ (string, "alpha") || STREQ (string, "upper") \
+ || STREQ (string, "lower") || STREQ (string, "digit") \
+ || STREQ (string, "alnum") || STREQ (string, "xdigit") \
+ || STREQ (string, "space") || STREQ (string, "print") \
+ || STREQ (string, "punct") || STREQ (string, "graph") \
+ || STREQ (string, "cntrl") || STREQ (string, "blank"))
+# endif
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+/* Global variable. */
+static int posixly_correct;
+
+# ifndef internal_function
+/* Inside GNU libc we mark some function in a special way. In other
+ environments simply ignore the marking. */
+# define internal_function
+# endif
+
+/* Note that this evaluates C many times. */
+# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
+# define CHAR char
+# define UCHAR unsigned char
+# define INT int
+# define FCT internal_fnmatch
+# define EXT ext_match
+# define END end_pattern
+# define L_(CS) CS
+# ifdef _LIBC
+# define BTOWC(C) __btowc (C)
+# else
+# define BTOWC(C) btowc (C)
+# endif
+# define STRLEN(S) strlen (S)
+# define STRCAT(D, S) strcat (D, S)
+# ifdef _LIBC
+# define MEMPCPY(D, S, N) __mempcpy (D, S, N)
+# else
+# if HAVE_MEMPCPY
+# define MEMPCPY(D, S, N) mempcpy (D, S, N)
+# else
+# define MEMPCPY(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N)))
+# endif
+# endif
+# define MEMCHR(S, C, N) memchr (S, C, N)
+# define STRCOLL(S1, S2) strcoll (S1, S2)
+# include "fnmatch_loop.c"
+
+
+# if HANDLE_MULTIBYTE
+# define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c))
+# define CHAR wchar_t
+# define UCHAR wint_t
+# define INT wint_t
+# define FCT internal_fnwmatch
+# define EXT ext_wmatch
+# define END end_wpattern
+# define L_(CS) L##CS
+# define BTOWC(C) (C)
+# ifdef _LIBC
+# define STRLEN(S) __wcslen (S)
+# define STRCAT(D, S) __wcscat (D, S)
+# define MEMPCPY(D, S, N) __wmempcpy (D, S, N)
+# else
+# define STRLEN(S) wcslen (S)
+# define STRCAT(D, S) wcscat (D, S)
+# if HAVE_WMEMPCPY
+# define MEMPCPY(D, S, N) wmempcpy (D, S, N)
+# else
+# define MEMPCPY(D, S, N) (wmemcpy (D, S, N) + (N))
+# endif
+# endif
+# define MEMCHR(S, C, N) wmemchr (S, C, N)
+# define STRCOLL(S1, S2) wcscoll (S1, S2)
+# define WIDE_CHAR_VERSION 1
+
+# undef IS_CHAR_CLASS
+/* We have to convert the wide character string in a multibyte string. But
+ we know that the character class names consist of alphanumeric characters
+ from the portable character set, and since the wide character encoding
+ for a member of the portable character set is the same code point as
+ its single-byte encoding, we can use a simplified method to convert the
+ string to a multibyte character string. */
+static wctype_t
+is_char_class (const wchar_t *wcs)
+{
+ char s[CHAR_CLASS_MAX_LENGTH + 1];
+ char *cp = s;
+
+ do
+ {
+ /* Test for a printable character from the portable character set. */
+# ifdef _LIBC
+ if (*wcs < 0x20 || *wcs > 0x7e
+ || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60)
+ return (wctype_t) 0;
+# else
+ switch (*wcs)
+ {
+ case L' ': case L'!': case L'"': case L'#': case L'%':
+ case L'&': case L'\'': case L'(': case L')': case L'*':
+ case L'+': case L',': case L'-': case L'.': case L'/':
+ case L'0': case L'1': case L'2': case L'3': case L'4':
+ case L'5': case L'6': case L'7': case L'8': case L'9':
+ case L':': case L';': case L'<': case L'=': case L'>':
+ case L'?':
+ case L'A': case L'B': case L'C': case L'D': case L'E':
+ case L'F': case L'G': case L'H': case L'I': case L'J':
+ case L'K': case L'L': case L'M': case L'N': case L'O':
+ case L'P': case L'Q': case L'R': case L'S': case L'T':
+ case L'U': case L'V': case L'W': case L'X': case L'Y':
+ case L'Z':
+ case L'[': case L'\\': case L']': case L'^': case L'_':
+ case L'a': case L'b': case L'c': case L'd': case L'e':
+ case L'f': case L'g': case L'h': case L'i': case L'j':
+ case L'k': case L'l': case L'm': case L'n': case L'o':
+ case L'p': case L'q': case L'r': case L's': case L't':
+ case L'u': case L'v': case L'w': case L'x': case L'y':
+ case L'z': case L'{': case L'|': case L'}': case L'~':
+ break;
+ default:
+ return (wctype_t) 0;
+ }
+# endif
+
+ /* Avoid overrunning the buffer. */
+ if (cp == s + CHAR_CLASS_MAX_LENGTH)
+ return (wctype_t) 0;
+
+ *cp++ = (char) *wcs++;
+ }
+ while (*wcs != L'\0');
+
+ *cp = '\0';
+
+# ifdef _LIBC
+ return __wctype (s);
+# else
+ return wctype (s);
+# endif
+}
+# define IS_CHAR_CLASS(string) is_char_class (string)
+
+# include "fnmatch_loop.c"
+# endif
+
+
+int
+fnmatch (const char *pattern, const char *string, int flags)
+{
+# if HANDLE_MULTIBYTE
+# define ALLOCA_LIMIT 2000
+ if (__builtin_expect (MB_CUR_MAX, 1) != 1)
+ {
+ mbstate_t ps;
+ size_t patsize;
+ size_t strsize;
+ size_t totsize;
+ wchar_t *wpattern;
+ wchar_t *wstring;
+ int res;
+
+ /* Calculate the size needed to convert the strings to
+ wide characters. */
+ memset (&ps, '\0', sizeof (ps));
+ patsize = mbsrtowcs (NULL, &pattern, 0, &ps) + 1;
+ if (__builtin_expect (patsize != 0, 1))
+ {
+ assert (mbsinit (&ps));
+ strsize = mbsrtowcs (NULL, &string, 0, &ps) + 1;
+ if (__builtin_expect (strsize != 0, 1))
+ {
+ assert (mbsinit (&ps));
+ totsize = patsize + strsize;
+ if (__builtin_expect (! (patsize <= totsize
+ && totsize <= SIZE_MAX / sizeof (wchar_t)),
+ 0))
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /* Allocate room for the wide characters. */
+ if (__builtin_expect (totsize < ALLOCA_LIMIT, 1))
+ wpattern = (wchar_t *) alloca (totsize * sizeof (wchar_t));
+ else
+ {
+ wpattern = malloc (totsize * sizeof (wchar_t));
+ if (__builtin_expect (! wpattern, 0))
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+ wstring = wpattern + patsize;
+
+ /* Convert the strings into wide characters. */
+ mbsrtowcs (wpattern, &pattern, patsize, &ps);
+ assert (mbsinit (&ps));
+ mbsrtowcs (wstring, &string, strsize, &ps);
+
+ res = internal_fnwmatch (wpattern, wstring, wstring + strsize - 1,
+ flags & FNM_PERIOD, flags);
+
+ if (__builtin_expect (! (totsize < ALLOCA_LIMIT), 0))
+ free (wpattern);
+ return res;
+ }
+ }
+ }
+
+# endif /* HANDLE_MULTIBYTE */
+
+ return internal_fnmatch (pattern, string, string + strlen (string),
+ flags & FNM_PERIOD, flags);
+}
+
+# ifdef _LIBC
+# undef fnmatch
+versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3);
+# if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3)
+strong_alias (__fnmatch, __fnmatch_old)
+compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0);
+# endif
+libc_hidden_ver (__fnmatch, fnmatch)
+# endif
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
diff --git a/lib/fnmatch_.h b/lib/fnmatch_.h
new file mode 100644
index 0000000..b086b45
--- /dev/null
+++ b/lib/fnmatch_.h
@@ -0,0 +1,65 @@
+/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2001, 2002, 2003,
+ 2005, 2007 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _FNMATCH_H
+#define _FNMATCH_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* We #undef these before defining them because some losing systems
+ (HP-UX A.08.07 for example) define these in <unistd.h>. */
+#undef FNM_PATHNAME
+#undef FNM_NOESCAPE
+#undef FNM_PERIOD
+
+/* Bits set in the FLAGS argument to `fnmatch'. */
+#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
+#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */
+#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */
+
+#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE
+# define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */
+# define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */
+# define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
+# define FNM_EXTMATCH (1 << 5) /* Use ksh-like extended matching. */
+#endif
+
+/* Value returned by `fnmatch' if STRING does not match PATTERN. */
+#define FNM_NOMATCH 1
+
+/* This value is returned if the implementation does not support
+ `fnmatch'. Since this is not the case here it will never be
+ returned but the conformance test suites still require the symbol
+ to be defined. */
+#ifdef _XOPEN_SOURCE
+# define FNM_NOSYS (-1)
+#endif
+
+/* Match NAME against the file name pattern PATTERN,
+ returning zero if it matches, FNM_NOMATCH if not. */
+extern int fnmatch (const char *__pattern, const char *__name,
+ int __flags);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* fnmatch.h */
diff --git a/lib/fnmatch_loop.c b/lib/fnmatch_loop.c
new file mode 100644
index 0000000..d1008c2
--- /dev/null
+++ b/lib/fnmatch_loop.c
@@ -0,0 +1,1210 @@
+/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Match STRING against the file name pattern PATTERN, returning zero if
+ it matches, nonzero if not. */
+static int EXT (INT opt, const CHAR *pattern, const CHAR *string,
+ const CHAR *string_end, bool no_leading_period, int flags)
+ internal_function;
+static const CHAR *END (const CHAR *patternp) internal_function;
+
+static int
+internal_function
+FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end,
+ bool no_leading_period, int flags)
+{
+ register const CHAR *p = pattern, *n = string;
+ register UCHAR c;
+#ifdef _LIBC
+# if WIDE_CHAR_VERSION
+ const char *collseq = (const char *)
+ _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC);
+# else
+ const UCHAR *collseq = (const UCHAR *)
+ _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB);
+# endif
+#endif
+
+ while ((c = *p++) != L_('\0'))
+ {
+ bool new_no_leading_period = false;
+ c = FOLD (c);
+
+ switch (c)
+ {
+ case L_('?'):
+ if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
+ {
+ int res;
+
+ res = EXT (c, p, n, string_end, no_leading_period,
+ flags);
+ if (res != -1)
+ return res;
+ }
+
+ if (n == string_end)
+ return FNM_NOMATCH;
+ else if (*n == L_('/') && (flags & FNM_FILE_NAME))
+ return FNM_NOMATCH;
+ else if (*n == L_('.') && no_leading_period)
+ return FNM_NOMATCH;
+ break;
+
+ case L_('\\'):
+ if (!(flags & FNM_NOESCAPE))
+ {
+ c = *p++;
+ if (c == L_('\0'))
+ /* Trailing \ loses. */
+ return FNM_NOMATCH;
+ c = FOLD (c);
+ }
+ if (n == string_end || FOLD ((UCHAR) *n) != c)
+ return FNM_NOMATCH;
+ break;
+
+ case L_('*'):
+ if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
+ {
+ int res;
+
+ res = EXT (c, p, n, string_end, no_leading_period,
+ flags);
+ if (res != -1)
+ return res;
+ }
+
+ if (n != string_end && *n == L_('.') && no_leading_period)
+ return FNM_NOMATCH;
+
+ for (c = *p++; c == L_('?') || c == L_('*'); c = *p++)
+ {
+ if (*p == L_('(') && (flags & FNM_EXTMATCH) != 0)
+ {
+ const CHAR *endp = END (p);
+ if (endp != p)
+ {
+ /* This is a pattern. Skip over it. */
+ p = endp;
+ continue;
+ }
+ }
+
+ if (c == L_('?'))
+ {
+ /* A ? needs to match one character. */
+ if (n == string_end)
+ /* There isn't another character; no match. */
+ return FNM_NOMATCH;
+ else if (*n == L_('/')
+ && __builtin_expect (flags & FNM_FILE_NAME, 0))
+ /* A slash does not match a wildcard under
+ FNM_FILE_NAME. */
+ return FNM_NOMATCH;
+ else
+ /* One character of the string is consumed in matching
+ this ? wildcard, so *??? won't match if there are
+ less than three characters. */
+ ++n;
+ }
+ }
+
+ if (c == L_('\0'))
+ /* The wildcard(s) is/are the last element of the pattern.
+ If the name is a file name and contains another slash
+ this means it cannot match, unless the FNM_LEADING_DIR
+ flag is set. */
+ {
+ int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH;
+
+ if (flags & FNM_FILE_NAME)
+ {
+ if (flags & FNM_LEADING_DIR)
+ result = 0;
+ else
+ {
+ if (MEMCHR (n, L_('/'), string_end - n) == NULL)
+ result = 0;
+ }
+ }
+
+ return result;
+ }
+ else
+ {
+ const CHAR *endp;
+
+ endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L_('/') : L_('\0'),
+ string_end - n);
+ if (endp == NULL)
+ endp = string_end;
+
+ if (c == L_('[')
+ || (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0
+ && (c == L_('@') || c == L_('+') || c == L_('!'))
+ && *p == L_('(')))
+ {
+ int flags2 = ((flags & FNM_FILE_NAME)
+ ? flags : (flags & ~FNM_PERIOD));
+ bool no_leading_period2 = no_leading_period;
+
+ for (--p; n < endp; ++n, no_leading_period2 = false)
+ if (FCT (p, n, string_end, no_leading_period2, flags2)
+ == 0)
+ return 0;
+ }
+ else if (c == L_('/') && (flags & FNM_FILE_NAME))
+ {
+ while (n < string_end && *n != L_('/'))
+ ++n;
+ if (n < string_end && *n == L_('/')
+ && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags)
+ == 0))
+ return 0;
+ }
+ else
+ {
+ int flags2 = ((flags & FNM_FILE_NAME)
+ ? flags : (flags & ~FNM_PERIOD));
+ int no_leading_period2 = no_leading_period;
+
+ if (c == L_('\\') && !(flags & FNM_NOESCAPE))
+ c = *p;
+ c = FOLD (c);
+ for (--p; n < endp; ++n, no_leading_period2 = false)
+ if (FOLD ((UCHAR) *n) == c
+ && (FCT (p, n, string_end, no_leading_period2, flags2)
+ == 0))
+ return 0;
+ }
+ }
+
+ /* If we come here no match is possible with the wildcard. */
+ return FNM_NOMATCH;
+
+ case L_('['):
+ {
+ /* Nonzero if the sense of the character class is inverted. */
+ register bool not;
+ CHAR cold;
+ UCHAR fn;
+
+ if (posixly_correct == 0)
+ posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
+
+ if (n == string_end)
+ return FNM_NOMATCH;
+
+ if (*n == L_('.') && no_leading_period)
+ return FNM_NOMATCH;
+
+ if (*n == L_('/') && (flags & FNM_FILE_NAME))
+ /* `/' cannot be matched. */
+ return FNM_NOMATCH;
+
+ not = (*p == L_('!') || (posixly_correct < 0 && *p == L_('^')));
+ if (not)
+ ++p;
+
+ fn = FOLD ((UCHAR) *n);
+
+ c = *p++;
+ for (;;)
+ {
+ if (!(flags & FNM_NOESCAPE) && c == L_('\\'))
+ {
+ if (*p == L_('\0'))
+ return FNM_NOMATCH;
+ c = FOLD ((UCHAR) *p);
+ ++p;
+
+ goto normal_bracket;
+ }
+ else if (c == L_('[') && *p == L_(':'))
+ {
+ /* Leave room for the null. */
+ CHAR str[CHAR_CLASS_MAX_LENGTH + 1];
+ size_t c1 = 0;
+#if defined _LIBC || WIDE_CHAR_SUPPORT
+ wctype_t wt;
+#endif
+ const CHAR *startp = p;
+
+ for (;;)
+ {
+ if (c1 == CHAR_CLASS_MAX_LENGTH)
+ /* The name is too long and therefore the pattern
+ is ill-formed. */
+ return FNM_NOMATCH;
+
+ c = *++p;
+ if (c == L_(':') && p[1] == L_(']'))
+ {
+ p += 2;
+ break;
+ }
+ if (c < L_('a') || c >= L_('z'))
+ {
+ /* This cannot possibly be a character class name.
+ Match it as a normal range. */
+ p = startp;
+ c = L_('[');
+ goto normal_bracket;
+ }
+ str[c1++] = c;
+ }
+ str[c1] = L_('\0');
+
+#if defined _LIBC || WIDE_CHAR_SUPPORT
+ wt = IS_CHAR_CLASS (str);
+ if (wt == 0)
+ /* Invalid character class name. */
+ return FNM_NOMATCH;
+
+# if defined _LIBC && ! WIDE_CHAR_VERSION
+ /* The following code is glibc specific but does
+ there a good job in speeding up the code since
+ we can avoid the btowc() call. */
+ if (_ISCTYPE ((UCHAR) *n, wt))
+ goto matched;
+# else
+ if (ISWCTYPE (BTOWC ((UCHAR) *n), wt))
+ goto matched;
+# endif
+#else
+ if ((STREQ (str, L_("alnum")) && isalnum ((UCHAR) *n))
+ || (STREQ (str, L_("alpha")) && isalpha ((UCHAR) *n))
+ || (STREQ (str, L_("blank")) && isblank ((UCHAR) *n))
+ || (STREQ (str, L_("cntrl")) && iscntrl ((UCHAR) *n))
+ || (STREQ (str, L_("digit")) && isdigit ((UCHAR) *n))
+ || (STREQ (str, L_("graph")) && isgraph ((UCHAR) *n))
+ || (STREQ (str, L_("lower")) && islower ((UCHAR) *n))
+ || (STREQ (str, L_("print")) && isprint ((UCHAR) *n))
+ || (STREQ (str, L_("punct")) && ispunct ((UCHAR) *n))
+ || (STREQ (str, L_("space")) && isspace ((UCHAR) *n))
+ || (STREQ (str, L_("upper")) && isupper ((UCHAR) *n))
+ || (STREQ (str, L_("xdigit")) && isxdigit ((UCHAR) *n)))
+ goto matched;
+#endif
+ c = *p++;
+ }
+#ifdef _LIBC
+ else if (c == L_('[') && *p == L_('='))
+ {
+ UCHAR str[1];
+ uint32_t nrules =
+ _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+ const CHAR *startp = p;
+
+ c = *++p;
+ if (c == L_('\0'))
+ {
+ p = startp;
+ c = L_('[');
+ goto normal_bracket;
+ }
+ str[0] = c;
+
+ c = *++p;
+ if (c != L_('=') || p[1] != L_(']'))
+ {
+ p = startp;
+ c = L_('[');
+ goto normal_bracket;
+ }
+ p += 2;
+
+ if (nrules == 0)
+ {
+ if ((UCHAR) *n == str[0])
+ goto matched;
+ }
+ else
+ {
+ const int32_t *table;
+# if WIDE_CHAR_VERSION
+ const int32_t *weights;
+ const int32_t *extra;
+# else
+ const unsigned char *weights;
+ const unsigned char *extra;
+# endif
+ const int32_t *indirect;
+ int32_t idx;
+ const UCHAR *cp = (const UCHAR *) str;
+
+ /* This #include defines a local function! */
+# if WIDE_CHAR_VERSION
+# include <locale/weightwc.h>
+# else
+# include <locale/weight.h>
+# endif
+
+# if WIDE_CHAR_VERSION
+ table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC);
+ weights = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC);
+ extra = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC);
+ indirect = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC);
+# else
+ table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
+ weights = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
+ extra = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
+ indirect = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
+# endif
+
+ idx = findidx (&cp);
+ if (idx != 0)
+ {
+ /* We found a table entry. Now see whether the
+ character we are currently at has the same
+ equivalance class value. */
+ int len = weights[idx];
+ int32_t idx2;
+ const UCHAR *np = (const UCHAR *) n;
+
+ idx2 = findidx (&np);
+ if (idx2 != 0 && len == weights[idx2])
+ {
+ int cnt = 0;
+
+ while (cnt < len
+ && (weights[idx + 1 + cnt]
+ == weights[idx2 + 1 + cnt]))
+ ++cnt;
+
+ if (cnt == len)
+ goto matched;
+ }
+ }
+ }
+
+ c = *p++;
+ }
+#endif
+ else if (c == L_('\0'))
+ /* [ (unterminated) loses. */
+ return FNM_NOMATCH;
+ else
+ {
+ bool is_range = false;
+
+#ifdef _LIBC
+ bool is_seqval = false;
+
+ if (c == L_('[') && *p == L_('.'))
+ {
+ uint32_t nrules =
+ _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
+ const CHAR *startp = p;
+ size_t c1 = 0;
+
+ while (1)
+ {
+ c = *++p;
+ if (c == L_('.') && p[1] == L_(']'))
+ {
+ p += 2;
+ break;
+ }
+ if (c == '\0')
+ return FNM_NOMATCH;
+ ++c1;
+ }
+
+ /* We have to handling the symbols differently in
+ ranges since then the collation sequence is
+ important. */
+ is_range = *p == L_('-') && p[1] != L_('\0');
+
+ if (nrules == 0)
+ {
+ /* There are no names defined in the collation
+ data. Therefore we only accept the trivial
+ names consisting of the character itself. */
+ if (c1 != 1)
+ return FNM_NOMATCH;
+
+ if (!is_range && *n == startp[1])
+ goto matched;
+
+ cold = startp[1];
+ c = *p++;
+ }
+ else
+ {
+ int32_t table_size;
+ const int32_t *symb_table;
+# ifdef WIDE_CHAR_VERSION
+ char str[c1];
+ size_t strcnt;
+# else
+# define str (startp + 1)
+# endif
+ const unsigned char *extra;
+ int32_t idx;
+ int32_t elem;
+ int32_t second;
+ int32_t hash;
+
+# ifdef WIDE_CHAR_VERSION
+ /* We have to convert the name to a single-byte
+ string. This is possible since the names
+ consist of ASCII characters and the internal
+ representation is UCS4. */
+ for (strcnt = 0; strcnt < c1; ++strcnt)
+ str[strcnt] = startp[1 + strcnt];
+# endif
+
+ table_size =
+ _NL_CURRENT_WORD (LC_COLLATE,
+ _NL_COLLATE_SYMB_HASH_SIZEMB);
+ symb_table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_SYMB_TABLEMB);
+ extra = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_SYMB_EXTRAMB);
+
+ /* Locate the character in the hashing table. */
+ hash = elem_hash (str, c1);
+
+ idx = 0;
+ elem = hash % table_size;
+ if (symb_table[2 * elem] != 0)
+ {
+ second = hash % (table_size - 2) + 1;
+
+ do
+ {
+ /* First compare the hashing value. */
+ if (symb_table[2 * elem] == hash
+ && (c1
+ == extra[symb_table[2 * elem + 1]])
+ && memcmp (str,
+ &extra[symb_table[2 * elem
+ + 1]
+ + 1], c1) == 0)
+ {
+ /* Yep, this is the entry. */
+ idx = symb_table[2 * elem + 1];
+ idx += 1 + extra[idx];
+ break;
+ }
+
+ /* Next entry. */
+ elem += second;
+ }
+ while (symb_table[2 * elem] != 0);
+ }
+
+ if (symb_table[2 * elem] != 0)
+ {
+ /* Compare the byte sequence but only if
+ this is not part of a range. */
+# ifdef WIDE_CHAR_VERSION
+ int32_t *wextra;
+
+ idx += 1 + extra[idx];
+ /* Adjust for the alignment. */
+ idx = (idx + 3) & ~3;
+
+ wextra = (int32_t *) &extra[idx + 4];
+# endif
+
+ if (! is_range)
+ {
+# ifdef WIDE_CHAR_VERSION
+ for (c1 = 0;
+ (int32_t) c1 < wextra[idx];
+ ++c1)
+ if (n[c1] != wextra[1 + c1])
+ break;
+
+ if ((int32_t) c1 == wextra[idx])
+ goto matched;
+# else
+ for (c1 = 0; c1 < extra[idx]; ++c1)
+ if (n[c1] != extra[1 + c1])
+ break;
+
+ if (c1 == extra[idx])
+ goto matched;
+# endif
+ }
+
+ /* Get the collation sequence value. */
+ is_seqval = true;
+# ifdef WIDE_CHAR_VERSION
+ cold = wextra[1 + wextra[idx]];
+# else
+ /* Adjust for the alignment. */
+ idx += 1 + extra[idx];
+ idx = (idx + 3) & ~4;
+ cold = *((int32_t *) &extra[idx]);
+# endif
+
+ c = *p++;
+ }
+ else if (c1 == 1)
+ {
+ /* No valid character. Match it as a
+ single byte. */
+ if (!is_range && *n == str[0])
+ goto matched;
+
+ cold = str[0];
+ c = *p++;
+ }
+ else
+ return FNM_NOMATCH;
+ }
+ }
+ else
+# undef str
+#endif
+ {
+ c = FOLD (c);
+ normal_bracket:
+
+ /* We have to handling the symbols differently in
+ ranges since then the collation sequence is
+ important. */
+ is_range = (*p == L_('-') && p[1] != L_('\0')
+ && p[1] != L_(']'));
+
+ if (!is_range && c == fn)
+ goto matched;
+
+#if _LIBC
+ /* This is needed if we goto normal_bracket; from
+ outside of is_seqval's scope. */
+ is_seqval = false;
+#endif
+
+ cold = c;
+ c = *p++;
+ }
+
+ if (c == L_('-') && *p != L_(']'))
+ {
+#if _LIBC
+ /* We have to find the collation sequence
+ value for C. Collation sequence is nothing
+ we can regularly access. The sequence
+ value is defined by the order in which the
+ definitions of the collation values for the
+ various characters appear in the source
+ file. A strange concept, nowhere
+ documented. */
+ uint32_t fcollseq;
+ uint32_t lcollseq;
+ UCHAR cend = *p++;
+
+# ifdef WIDE_CHAR_VERSION
+ /* Search in the `names' array for the characters. */
+ fcollseq = __collseq_table_lookup (collseq, fn);
+ if (fcollseq == ~((uint32_t) 0))
+ /* XXX We don't know anything about the character
+ we are supposed to match. This means we are
+ failing. */
+ goto range_not_matched;
+
+ if (is_seqval)
+ lcollseq = cold;
+ else
+ lcollseq = __collseq_table_lookup (collseq, cold);
+# else
+ fcollseq = collseq[fn];
+ lcollseq = is_seqval ? cold : collseq[(UCHAR) cold];
+# endif
+
+ is_seqval = false;
+ if (cend == L_('[') && *p == L_('.'))
+ {
+ uint32_t nrules =
+ _NL_CURRENT_WORD (LC_COLLATE,
+ _NL_COLLATE_NRULES);
+ const CHAR *startp = p;
+ size_t c1 = 0;
+
+ while (1)
+ {
+ c = *++p;
+ if (c == L_('.') && p[1] == L_(']'))
+ {
+ p += 2;
+ break;
+ }
+ if (c == '\0')
+ return FNM_NOMATCH;
+ ++c1;
+ }
+
+ if (nrules == 0)
+ {
+ /* There are no names defined in the
+ collation data. Therefore we only
+ accept the trivial names consisting
+ of the character itself. */
+ if (c1 != 1)
+ return FNM_NOMATCH;
+
+ cend = startp[1];
+ }
+ else
+ {
+ int32_t table_size;
+ const int32_t *symb_table;
+# ifdef WIDE_CHAR_VERSION
+ char str[c1];
+ size_t strcnt;
+# else
+# define str (startp + 1)
+# endif
+ const unsigned char *extra;
+ int32_t idx;
+ int32_t elem;
+ int32_t second;
+ int32_t hash;
+
+# ifdef WIDE_CHAR_VERSION
+ /* We have to convert the name to a single-byte
+ string. This is possible since the names
+ consist of ASCII characters and the internal
+ representation is UCS4. */
+ for (strcnt = 0; strcnt < c1; ++strcnt)
+ str[strcnt] = startp[1 + strcnt];
+# endif
+
+ table_size =
+ _NL_CURRENT_WORD (LC_COLLATE,
+ _NL_COLLATE_SYMB_HASH_SIZEMB);
+ symb_table = (const int32_t *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_SYMB_TABLEMB);
+ extra = (const unsigned char *)
+ _NL_CURRENT (LC_COLLATE,
+ _NL_COLLATE_SYMB_EXTRAMB);
+
+ /* Locate the character in the hashing
+ table. */
+ hash = elem_hash (str, c1);
+
+ idx = 0;
+ elem = hash % table_size;
+ if (symb_table[2 * elem] != 0)
+ {
+ second = hash % (table_size - 2) + 1;
+
+ do
+ {
+ /* First compare the hashing value. */
+ if (symb_table[2 * elem] == hash
+ && (c1
+ == extra[symb_table[2 * elem + 1]])
+ && memcmp (str,
+ &extra[symb_table[2 * elem + 1]
+ + 1], c1) == 0)
+ {
+ /* Yep, this is the entry. */
+ idx = symb_table[2 * elem + 1];
+ idx += 1 + extra[idx];
+ break;
+ }
+
+ /* Next entry. */
+ elem += second;
+ }
+ while (symb_table[2 * elem] != 0);
+ }
+
+ if (symb_table[2 * elem] != 0)
+ {
+ /* Compare the byte sequence but only if
+ this is not part of a range. */
+# ifdef WIDE_CHAR_VERSION
+ int32_t *wextra;
+
+ idx += 1 + extra[idx];
+ /* Adjust for the alignment. */
+ idx = (idx + 3) & ~4;
+
+ wextra = (int32_t *) &extra[idx + 4];
+# endif
+ /* Get the collation sequence value. */
+ is_seqval = true;
+# ifdef WIDE_CHAR_VERSION
+ cend = wextra[1 + wextra[idx]];
+# else
+ /* Adjust for the alignment. */
+ idx += 1 + extra[idx];
+ idx = (idx + 3) & ~4;
+ cend = *((int32_t *) &extra[idx]);
+# endif
+ }
+ else if (symb_table[2 * elem] != 0 && c1 == 1)
+ {
+ cend = str[0];
+ c = *p++;
+ }
+ else
+ return FNM_NOMATCH;
+ }
+# undef str
+ }
+ else
+ {
+ if (!(flags & FNM_NOESCAPE) && cend == L_('\\'))
+ cend = *p++;
+ if (cend == L_('\0'))
+ return FNM_NOMATCH;
+ cend = FOLD (cend);
+ }
+
+ /* XXX It is not entirely clear to me how to handle
+ characters which are not mentioned in the
+ collation specification. */
+ if (
+# ifdef WIDE_CHAR_VERSION
+ lcollseq == 0xffffffff ||
+# endif
+ lcollseq <= fcollseq)
+ {
+ /* We have to look at the upper bound. */
+ uint32_t hcollseq;
+
+ if (is_seqval)
+ hcollseq = cend;
+ else
+ {
+# ifdef WIDE_CHAR_VERSION
+ hcollseq =
+ __collseq_table_lookup (collseq, cend);
+ if (hcollseq == ~((uint32_t) 0))
+ {
+ /* Hum, no information about the upper
+ bound. The matching succeeds if the
+ lower bound is matched exactly. */
+ if (lcollseq != fcollseq)
+ goto range_not_matched;
+
+ goto matched;
+ }
+# else
+ hcollseq = collseq[cend];
+# endif
+ }
+
+ if (lcollseq <= hcollseq && fcollseq <= hcollseq)
+ goto matched;
+ }
+# ifdef WIDE_CHAR_VERSION
+ range_not_matched:
+# endif
+#else
+ /* We use a boring value comparison of the character
+ values. This is better than comparing using
+ `strcoll' since the latter would have surprising
+ and sometimes fatal consequences. */
+ UCHAR cend = *p++;
+
+ if (!(flags & FNM_NOESCAPE) && cend == L_('\\'))
+ cend = *p++;
+ if (cend == L_('\0'))
+ return FNM_NOMATCH;
+
+ /* It is a range. */
+ if (cold <= fn && fn <= cend)
+ goto matched;
+#endif
+
+ c = *p++;
+ }
+ }
+
+ if (c == L_(']'))
+ break;
+ }
+
+ if (!not)
+ return FNM_NOMATCH;
+ break;
+
+ matched:
+ /* Skip the rest of the [...] that already matched. */
+ do
+ {
+ ignore_next:
+ c = *p++;
+
+ if (c == L_('\0'))
+ /* [... (unterminated) loses. */
+ return FNM_NOMATCH;
+
+ if (!(flags & FNM_NOESCAPE) && c == L_('\\'))
+ {
+ if (*p == L_('\0'))
+ return FNM_NOMATCH;
+ /* XXX 1003.2d11 is unclear if this is right. */
+ ++p;
+ }
+ else if (c == L_('[') && *p == L_(':'))
+ {
+ int c1 = 0;
+ const CHAR *startp = p;
+
+ while (1)
+ {
+ c = *++p;
+ if (++c1 == CHAR_CLASS_MAX_LENGTH)
+ return FNM_NOMATCH;
+
+ if (*p == L_(':') && p[1] == L_(']'))
+ break;
+
+ if (c < L_('a') || c >= L_('z'))
+ {
+ p = startp;
+ goto ignore_next;
+ }
+ }
+ p += 2;
+ c = *p++;
+ }
+ else if (c == L_('[') && *p == L_('='))
+ {
+ c = *++p;
+ if (c == L_('\0'))
+ return FNM_NOMATCH;
+ c = *++p;
+ if (c != L_('=') || p[1] != L_(']'))
+ return FNM_NOMATCH;
+ p += 2;
+ c = *p++;
+ }
+ else if (c == L_('[') && *p == L_('.'))
+ {
+ ++p;
+ while (1)
+ {
+ c = *++p;
+ if (c == '\0')
+ return FNM_NOMATCH;
+
+ if (*p == L_('.') && p[1] == L_(']'))
+ break;
+ }
+ p += 2;
+ c = *p++;
+ }
+ }
+ while (c != L_(']'));
+ if (not)
+ return FNM_NOMATCH;
+ }
+ break;
+
+ case L_('+'):
+ case L_('@'):
+ case L_('!'):
+ if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
+ {
+ int res;
+
+ res = EXT (c, p, n, string_end, no_leading_period, flags);
+ if (res != -1)
+ return res;
+ }
+ goto normal_match;
+
+ case L_('/'):
+ if (NO_LEADING_PERIOD (flags))
+ {
+ if (n == string_end || c != (UCHAR) *n)
+ return FNM_NOMATCH;
+
+ new_no_leading_period = true;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ normal_match:
+ if (n == string_end || c != FOLD ((UCHAR) *n))
+ return FNM_NOMATCH;
+ }
+
+ no_leading_period = new_no_leading_period;
+ ++n;
+ }
+
+ if (n == string_end)
+ return 0;
+
+ if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L_('/'))
+ /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
+ return 0;
+
+ return FNM_NOMATCH;
+}
+
+
+static const CHAR *
+internal_function
+END (const CHAR *pattern)
+{
+ const CHAR *p = pattern;
+
+ while (1)
+ if (*++p == L_('\0'))
+ /* This is an invalid pattern. */
+ return pattern;
+ else if (*p == L_('['))
+ {
+ /* Handle brackets special. */
+ if (posixly_correct == 0)
+ posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
+
+ /* Skip the not sign. We have to recognize it because of a possibly
+ following ']'. */
+ if (*++p == L_('!') || (posixly_correct < 0 && *p == L_('^')))
+ ++p;
+ /* A leading ']' is recognized as such. */
+ if (*p == L_(']'))
+ ++p;
+ /* Skip over all characters of the list. */
+ while (*p != L_(']'))
+ if (*p++ == L_('\0'))
+ /* This is no valid pattern. */
+ return pattern;
+ }
+ else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@')
+ || *p == L_('!')) && p[1] == L_('('))
+ p = END (p + 1);
+ else if (*p == L_(')'))
+ break;
+
+ return p + 1;
+}
+
+
+static int
+internal_function
+EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
+ bool no_leading_period, int flags)
+{
+ const CHAR *startp;
+ size_t level;
+ struct patternlist
+ {
+ struct patternlist *next;
+ CHAR str[1];
+ } *list = NULL;
+ struct patternlist **lastp = &list;
+ size_t pattern_len = STRLEN (pattern);
+ const CHAR *p;
+ const CHAR *rs;
+ enum { ALLOCA_LIMIT = 8000 };
+
+ /* Parse the pattern. Store the individual parts in the list. */
+ level = 0;
+ for (startp = p = pattern + 1; ; ++p)
+ if (*p == L_('\0'))
+ /* This is an invalid pattern. */
+ return -1;
+ else if (*p == L_('['))
+ {
+ /* Handle brackets special. */
+ if (posixly_correct == 0)
+ posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
+
+ /* Skip the not sign. We have to recognize it because of a possibly
+ following ']'. */
+ if (*++p == L_('!') || (posixly_correct < 0 && *p == L_('^')))
+ ++p;
+ /* A leading ']' is recognized as such. */
+ if (*p == L_(']'))
+ ++p;
+ /* Skip over all characters of the list. */
+ while (*p != L_(']'))
+ if (*p++ == L_('\0'))
+ /* This is no valid pattern. */
+ return -1;
+ }
+ else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@')
+ || *p == L_('!')) && p[1] == L_('('))
+ /* Remember the nesting level. */
+ ++level;
+ else if (*p == L_(')'))
+ {
+ if (level-- == 0)
+ {
+ /* This means we found the end of the pattern. */
+#define NEW_PATTERN \
+ struct patternlist *newp; \
+ size_t plen; \
+ size_t plensize; \
+ size_t newpsize; \
+ \
+ plen = (opt == L_('?') || opt == L_('@') \
+ ? pattern_len \
+ : p - startp + 1); \
+ plensize = plen * sizeof (CHAR); \
+ newpsize = offsetof (struct patternlist, str) + plensize; \
+ if ((size_t) -1 / sizeof (CHAR) < plen \
+ || newpsize < offsetof (struct patternlist, str) \
+ || ALLOCA_LIMIT <= newpsize) \
+ return -1; \
+ newp = (struct patternlist *) alloca (newpsize); \
+ *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L_('\0'); \
+ newp->next = NULL; \
+ *lastp = newp; \
+ lastp = &newp->next
+ NEW_PATTERN;
+ break;
+ }
+ }
+ else if (*p == L_('|'))
+ {
+ if (level == 0)
+ {
+ NEW_PATTERN;
+ startp = p + 1;
+ }
+ }
+ assert (list != NULL);
+ assert (p[-1] == L_(')'));
+#undef NEW_PATTERN
+
+ switch (opt)
+ {
+ case L_('*'):
+ if (FCT (p, string, string_end, no_leading_period, flags) == 0)
+ return 0;
+ /* FALLTHROUGH */
+
+ case L_('+'):
+ do
+ {
+ for (rs = string; rs <= string_end; ++rs)
+ /* First match the prefix with the current pattern with the
+ current pattern. */
+ if (FCT (list->str, string, rs, no_leading_period,
+ flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0
+ /* This was successful. Now match the rest with the rest
+ of the pattern. */
+ && (FCT (p, rs, string_end,
+ rs == string
+ ? no_leading_period
+ : rs[-1] == '/' && NO_LEADING_PERIOD (flags),
+ flags & FNM_FILE_NAME
+ ? flags : flags & ~FNM_PERIOD) == 0
+ /* This didn't work. Try the whole pattern. */
+ || (rs != string
+ && FCT (pattern - 1, rs, string_end,
+ rs == string
+ ? no_leading_period
+ : rs[-1] == '/' && NO_LEADING_PERIOD (flags),
+ flags & FNM_FILE_NAME
+ ? flags : flags & ~FNM_PERIOD) == 0)))
+ /* It worked. Signal success. */
+ return 0;
+ }
+ while ((list = list->next) != NULL);
+
+ /* None of the patterns lead to a match. */
+ return FNM_NOMATCH;
+
+ case L_('?'):
+ if (FCT (p, string, string_end, no_leading_period, flags) == 0)
+ return 0;
+ /* FALLTHROUGH */
+
+ case L_('@'):
+ do
+ /* I cannot believe it but `strcat' is actually acceptable
+ here. Match the entire string with the prefix from the
+ pattern list and the rest of the pattern following the
+ pattern list. */
+ if (FCT (STRCAT (list->str, p), string, string_end,
+ no_leading_period,
+ flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0)
+ /* It worked. Signal success. */
+ return 0;
+ while ((list = list->next) != NULL);
+
+ /* None of the patterns lead to a match. */
+ return FNM_NOMATCH;
+
+ case L_('!'):
+ for (rs = string; rs <= string_end; ++rs)
+ {
+ struct patternlist *runp;
+
+ for (runp = list; runp != NULL; runp = runp->next)
+ if (FCT (runp->str, string, rs, no_leading_period,
+ flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0)
+ break;
+
+ /* If none of the patterns matched see whether the rest does. */
+ if (runp == NULL
+ && (FCT (p, rs, string_end,
+ rs == string
+ ? no_leading_period
+ : rs[-1] == '/' && NO_LEADING_PERIOD (flags),
+ flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD)
+ == 0))
+ /* This is successful. */
+ return 0;
+ }
+
+ /* None of the patterns together with the rest of the pattern
+ lead to a match. */
+ return FNM_NOMATCH;
+
+ default:
+ assert (! "Invalid extended matching operator");
+ break;
+ }
+
+ return -1;
+}
+
+
+#undef FOLD
+#undef CHAR
+#undef UCHAR
+#undef INT
+#undef FCT
+#undef EXT
+#undef END
+#undef MEMPCPY
+#undef MEMCHR
+#undef STRCOLL
+#undef STRLEN
+#undef STRCAT
+#undef L_
+#undef BTOWC
diff --git a/lib/fstatat.c b/lib/fstatat.c
new file mode 100644
index 0000000..92a5164
--- /dev/null
+++ b/lib/fstatat.c
@@ -0,0 +1,57 @@
+/* Work around an fstatat bug on Solaris 9.
+
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert and Jim Meyering. */
+
+#include <config.h>
+
+#define COMPILING_FSTATAT 1
+#include "openat.h"
+
+#include <errno.h>
+#include <string.h>
+
+/* fstatat should always follow symbolic links that end in /, but on
+ Solaris 9 it doesn't if AT_SYMLINK_NOFOLLOW is specified. This is
+ the same problem that lstat.c addresses, so solve it in a similar
+ way. */
+
+int
+rpl_fstatat (int fd, char const *file, struct stat *st, int flag)
+{
+ int result = fstatat (fd, file, st, flag);
+
+ if (result == 0 && (flag & AT_SYMLINK_NOFOLLOW) && S_ISLNK (st->st_mode)
+ && file[strlen (file) - 1] == '/')
+ {
+ /* FILE refers to a symbolic link and the name ends with a slash.
+ Get info about the link's referent. */
+ result = fstatat (fd, file, st, flag & ~AT_SYMLINK_NOFOLLOW);
+ if (result == 0 && ! S_ISDIR (st->st_mode))
+ {
+ /* fstatat succeeded and FILE references a non-directory.
+ But it was specified via a name including a trailing
+ slash. Fail with errno set to ENOTDIR to indicate the
+ contradiction. */
+ errno = ENOTDIR;
+ return -1;
+ }
+ }
+
+ return result;
+}
diff --git a/lib/full-write.c b/lib/full-write.c
new file mode 100644
index 0000000..cc16872
--- /dev/null
+++ b/lib/full-write.c
@@ -0,0 +1,81 @@
+/* An interface to read and write that retries (if necessary) until complete.
+
+ Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+ 2004, 2005, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+/* Specification. */
+#ifdef FULL_READ
+# include "full-read.h"
+#else
+# include "full-write.h"
+#endif
+
+#include <errno.h>
+
+#ifdef FULL_READ
+# include "safe-read.h"
+# define safe_rw safe_read
+# define full_rw full_read
+# undef const
+# define const /* empty */
+#else
+# include "safe-write.h"
+# define safe_rw safe_write
+# define full_rw full_write
+#endif
+
+#ifdef FULL_READ
+/* Set errno to zero upon EOF. */
+# define ZERO_BYTE_TRANSFER_ERRNO 0
+#else
+/* Some buggy drivers return 0 when one tries to write beyond
+ a device's end. (Example: Linux 1.2.13 on /dev/fd0.)
+ Set errno to ENOSPC so they get a sensible diagnostic. */
+# define ZERO_BYTE_TRANSFER_ERRNO ENOSPC
+#endif
+
+/* Write(read) COUNT bytes at BUF to(from) descriptor FD, retrying if
+ interrupted or if a partial write(read) occurs. Return the number
+ of bytes transferred.
+ When writing, set errno if fewer than COUNT bytes are written.
+ When reading, if fewer than COUNT bytes are read, you must examine
+ errno to distinguish failure from EOF (errno == 0). */
+size_t
+full_rw (int fd, const void *buf, size_t count)
+{
+ size_t total = 0;
+ const char *ptr = (const char *) buf;
+
+ while (count > 0)
+ {
+ size_t n_rw = safe_rw (fd, ptr, count);
+ if (n_rw == (size_t) -1)
+ break;
+ if (n_rw == 0)
+ {
+ errno = ZERO_BYTE_TRANSFER_ERRNO;
+ break;
+ }
+ total += n_rw;
+ ptr += n_rw;
+ count -= n_rw;
+ }
+
+ return total;
+}
diff --git a/lib/full-write.h b/lib/full-write.h
new file mode 100644
index 0000000..d20d2fe
--- /dev/null
+++ b/lib/full-write.h
@@ -0,0 +1,35 @@
+/* An interface to write() that writes all it is asked to write.
+
+ Copyright (C) 2002-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <stddef.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Write COUNT bytes at BUF to descriptor FD, retrying if interrupted
+ or if partial writes occur. Return the number of bytes successfully
+ written, setting errno if that is less than COUNT. */
+extern size_t full_write (int fd, const void *buf, size_t count);
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/lib/getcwd.c b/lib/getcwd.c
new file mode 100644
index 0000000..23b35de
--- /dev/null
+++ b/lib/getcwd.c
@@ -0,0 +1,428 @@
+/* Copyright (C) 1991,92,93,94,95,96,97,98,99,2004,2005,2006,2007 Free Software
+ Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#if !_LIBC
+# include <config.h>
+# include <unistd.h>
+# include "dirfd.h"
+#endif
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#include <fcntl.h> /* For AT_FDCWD on Solaris 9. */
+
+#ifndef __set_errno
+# define __set_errno(val) (errno = (val))
+#endif
+
+#include <dirent.h>
+#ifndef _D_EXACT_NAMLEN
+# define _D_EXACT_NAMLEN(d) strlen ((d)->d_name)
+#endif
+#ifndef _D_ALLOC_NAMLEN
+# define _D_ALLOC_NAMLEN(d) (_D_EXACT_NAMLEN (d) + 1)
+#endif
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if _LIBC
+# ifndef mempcpy
+# define mempcpy __mempcpy
+# endif
+#endif
+
+#include <limits.h>
+
+/* Work around a bug in Solaris 9 and 10: AT_FDCWD is positive. Its
+ value exceeds INT_MAX, so its use as an int doesn't conform to the
+ C standard, and GCC and Sun C complain in some cases. */
+#if 0 < AT_FDCWD && AT_FDCWD == 0xffd19553
+# undef AT_FDCWD
+# define AT_FDCWD (-3041965)
+#endif
+
+#ifdef ENAMETOOLONG
+# define is_ENAMETOOLONG(x) ((x) == ENAMETOOLONG)
+#else
+# define is_ENAMETOOLONG(x) 0
+#endif
+
+#ifndef MAX
+# define MAX(a, b) ((a) < (b) ? (b) : (a))
+#endif
+#ifndef MIN
+# define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef PATH_MAX
+# ifdef MAXPATHLEN
+# define PATH_MAX MAXPATHLEN
+# else
+# define PATH_MAX 1024
+# endif
+#endif
+
+#if D_INO_IN_DIRENT
+# define MATCHING_INO(dp, ino) ((dp)->d_ino == (ino))
+#else
+# define MATCHING_INO(dp, ino) true
+#endif
+
+#if !_LIBC
+# define __getcwd getcwd
+# define __lstat lstat
+# define __closedir closedir
+# define __opendir opendir
+# define __readdir readdir
+#endif
+
+/* The results of opendir() in this file are not used with dirfd and fchdir,
+ therefore save some unnecessary recursion in fchdir.c. */
+#undef opendir
+#undef closedir
+
+/* Get the name of the current working directory, and put it in SIZE
+ bytes of BUF. Returns NULL if the directory couldn't be determined or
+ SIZE was too small. If successful, returns BUF. In GNU, if BUF is
+ NULL, an array is allocated with `malloc'; the array is SIZE bytes long,
+ unless SIZE == 0, in which case it is as big as necessary. */
+
+char *
+__getcwd (char *buf, size_t size)
+{
+ /* Lengths of big file name components and entire file names, and a
+ deep level of file name nesting. These numbers are not upper
+ bounds; they are merely large values suitable for initial
+ allocations, designed to be large enough for most real-world
+ uses. */
+ enum
+ {
+ BIG_FILE_NAME_COMPONENT_LENGTH = 255,
+ BIG_FILE_NAME_LENGTH = MIN (4095, PATH_MAX - 1),
+ DEEP_NESTING = 100
+ };
+
+#ifdef AT_FDCWD
+ int fd = AT_FDCWD;
+ bool fd_needs_closing = false;
+#else
+ char dots[DEEP_NESTING * sizeof ".." + BIG_FILE_NAME_COMPONENT_LENGTH + 1];
+ char *dotlist = dots;
+ size_t dotsize = sizeof dots;
+ size_t dotlen = 0;
+#endif
+ DIR *dirstream = NULL;
+ dev_t rootdev, thisdev;
+ ino_t rootino, thisino;
+ char *dir;
+ register char *dirp;
+ struct stat st;
+ size_t allocated = size;
+ size_t used;
+
+#if HAVE_PARTLY_WORKING_GETCWD
+ /* The system getcwd works, except it sometimes fails when it
+ shouldn't, setting errno to ERANGE, ENAMETOOLONG, or ENOENT. If
+ AT_FDCWD is not defined, the algorithm below is O(N**2) and this
+ is much slower than the system getcwd (at least on GNU/Linux).
+ So trust the system getcwd's results unless they look
+ suspicious.
+
+ Use the system getcwd even if we have openat support, since the
+ system getcwd works even when a parent is unreadable, while the
+ openat-based approach does not. */
+
+# undef getcwd
+ dir = getcwd (buf, size);
+ if (dir || (errno != ERANGE && !is_ENAMETOOLONG (errno) && errno != ENOENT))
+ return dir;
+#endif
+
+ if (size == 0)
+ {
+ if (buf != NULL)
+ {
+ __set_errno (EINVAL);
+ return NULL;
+ }
+
+ allocated = BIG_FILE_NAME_LENGTH + 1;
+ }
+
+ if (buf == NULL)
+ {
+ dir = malloc (allocated);
+ if (dir == NULL)
+ return NULL;
+ }
+ else
+ dir = buf;
+
+ dirp = dir + allocated;
+ *--dirp = '\0';
+
+ if (__lstat (".", &st) < 0)
+ goto lose;
+ thisdev = st.st_dev;
+ thisino = st.st_ino;
+
+ if (__lstat ("/", &st) < 0)
+ goto lose;
+ rootdev = st.st_dev;
+ rootino = st.st_ino;
+
+ while (!(thisdev == rootdev && thisino == rootino))
+ {
+ struct dirent *d;
+ dev_t dotdev;
+ ino_t dotino;
+ bool mount_point;
+ int parent_status;
+ size_t dirroom;
+ size_t namlen;
+ bool use_d_ino = true;
+
+ /* Look at the parent directory. */
+#ifdef AT_FDCWD
+ fd = openat (fd, "..", O_RDONLY);
+ if (fd < 0)
+ goto lose;
+ fd_needs_closing = true;
+ parent_status = fstat (fd, &st);
+#else
+ dotlist[dotlen++] = '.';
+ dotlist[dotlen++] = '.';
+ dotlist[dotlen] = '\0';
+ parent_status = __lstat (dotlist, &st);
+#endif
+ if (parent_status != 0)
+ goto lose;
+
+ if (dirstream && __closedir (dirstream) != 0)
+ {
+ dirstream = NULL;
+ goto lose;
+ }
+
+ /* Figure out if this directory is a mount point. */
+ dotdev = st.st_dev;
+ dotino = st.st_ino;
+ mount_point = dotdev != thisdev;
+
+ /* Search for the last directory. */
+#ifdef AT_FDCWD
+ dirstream = fdopendir (fd);
+ if (dirstream == NULL)
+ goto lose;
+ /* Reset fd. It may have been closed by fdopendir. */
+ fd = dirfd (dirstream);
+ fd_needs_closing = false;
+#else
+ dirstream = __opendir (dotlist);
+ if (dirstream == NULL)
+ goto lose;
+ dotlist[dotlen++] = '/';
+#endif
+ for (;;)
+ {
+ /* Clear errno to distinguish EOF from error if readdir returns
+ NULL. */
+ __set_errno (0);
+ d = __readdir (dirstream);
+
+ /* When we've iterated through all directory entries without finding
+ one with a matching d_ino, rewind the stream and consider each
+ name again, but this time, using lstat. This is necessary in a
+ chroot on at least one system (glibc-2.3.6 + linux 2.6.12), where
+ .., ../.., ../../.., etc. all had the same device number, yet the
+ d_ino values for entries in / did not match those obtained
+ via lstat. */
+ if (d == NULL && errno == 0 && use_d_ino)
+ {
+ use_d_ino = false;
+ rewinddir (dirstream);
+ d = __readdir (dirstream);
+ }
+
+ if (d == NULL)
+ {
+ if (errno == 0)
+ /* EOF on dirstream, which can mean e.g., that the current
+ directory has been removed. */
+ __set_errno (ENOENT);
+ goto lose;
+ }
+ if (d->d_name[0] == '.' &&
+ (d->d_name[1] == '\0' ||
+ (d->d_name[1] == '.' && d->d_name[2] == '\0')))
+ continue;
+
+ if (use_d_ino)
+ {
+ bool match = (MATCHING_INO (d, thisino) || mount_point);
+ if (! match)
+ continue;
+ }
+
+ {
+ int entry_status;
+#ifdef AT_FDCWD
+ entry_status = fstatat (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW);
+#else
+ /* Compute size needed for this file name, or for the file
+ name ".." in the same directory, whichever is larger.
+ Room for ".." might be needed the next time through
+ the outer loop. */
+ size_t name_alloc = _D_ALLOC_NAMLEN (d);
+ size_t filesize = dotlen + MAX (sizeof "..", name_alloc);
+
+ if (filesize < dotlen)
+ goto memory_exhausted;
+
+ if (dotsize < filesize)
+ {
+ /* My, what a deep directory tree you have, Grandma. */
+ size_t newsize = MAX (filesize, dotsize * 2);
+ size_t i;
+ if (newsize < dotsize)
+ goto memory_exhausted;
+ if (dotlist != dots)
+ free (dotlist);
+ dotlist = malloc (newsize);
+ if (dotlist == NULL)
+ goto lose;
+ dotsize = newsize;
+
+ i = 0;
+ do
+ {
+ dotlist[i++] = '.';
+ dotlist[i++] = '.';
+ dotlist[i++] = '/';
+ }
+ while (i < dotlen);
+ }
+
+ memcpy (dotlist + dotlen, d->d_name, _D_ALLOC_NAMLEN (d));
+ entry_status = __lstat (dotlist, &st);
+#endif
+ /* We don't fail here if we cannot stat() a directory entry.
+ This can happen when (network) file systems fail. If this
+ entry is in fact the one we are looking for we will find
+ out soon as we reach the end of the directory without
+ having found anything. */
+ if (entry_status == 0 && S_ISDIR (st.st_mode)
+ && st.st_dev == thisdev && st.st_ino == thisino)
+ break;
+ }
+ }
+
+ dirroom = dirp - dir;
+ namlen = _D_EXACT_NAMLEN (d);
+
+ if (dirroom <= namlen)
+ {
+ if (size != 0)
+ {
+ __set_errno (ERANGE);
+ goto lose;
+ }
+ else
+ {
+ char *tmp;
+ size_t oldsize = allocated;
+
+ allocated += MAX (allocated, namlen);
+ if (allocated < oldsize
+ || ! (tmp = realloc (dir, allocated)))
+ goto memory_exhausted;
+
+ /* Move current contents up to the end of the buffer.
+ This is guaranteed to be non-overlapping. */
+ dirp = memcpy (tmp + allocated - (oldsize - dirroom),
+ tmp + dirroom,
+ oldsize - dirroom);
+ dir = tmp;
+ }
+ }
+ dirp -= namlen;
+ memcpy (dirp, d->d_name, namlen);
+ *--dirp = '/';
+
+ thisdev = dotdev;
+ thisino = dotino;
+ }
+
+ if (dirstream && __closedir (dirstream) != 0)
+ {
+ dirstream = NULL;
+ goto lose;
+ }
+
+ if (dirp == &dir[allocated - 1])
+ *--dirp = '/';
+
+#ifndef AT_FDCWD
+ if (dotlist != dots)
+ free (dotlist);
+#endif
+
+ used = dir + allocated - dirp;
+ memmove (dir, dirp, used);
+
+ if (size == 0)
+ /* Ensure that the buffer is only as large as necessary. */
+ buf = realloc (dir, used);
+
+ if (buf == NULL)
+ /* Either buf was NULL all along, or `realloc' failed but
+ we still have the original string. */
+ buf = dir;
+
+ return buf;
+
+ memory_exhausted:
+ __set_errno (ENOMEM);
+ lose:
+ {
+ int save = errno;
+ if (dirstream)
+ __closedir (dirstream);
+#ifdef AT_FDCWD
+ if (fd_needs_closing)
+ close (fd);
+#else
+ if (dotlist != dots)
+ free (dotlist);
+#endif
+ if (buf == NULL)
+ free (dir);
+ __set_errno (save);
+ }
+ return NULL;
+}
+
+#ifdef weak_alias
+weak_alias (__getcwd, getcwd)
+#endif
diff --git a/lib/getdate.c b/lib/getdate.c
new file mode 100644
index 0000000..2f59183
--- /dev/null
+++ b/lib/getdate.c
@@ -0,0 +1,3289 @@
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.3"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ tAGO = 258,
+ tDST = 259,
+ tYEAR_UNIT = 260,
+ tMONTH_UNIT = 261,
+ tHOUR_UNIT = 262,
+ tMINUTE_UNIT = 263,
+ tSEC_UNIT = 264,
+ tDAY_UNIT = 265,
+ tDAY = 266,
+ tDAYZONE = 267,
+ tLOCAL_ZONE = 268,
+ tMERIDIAN = 269,
+ tMONTH = 270,
+ tORDINAL = 271,
+ tZONE = 272,
+ tSNUMBER = 273,
+ tUNUMBER = 274,
+ tSDECIMAL_NUMBER = 275,
+ tUDECIMAL_NUMBER = 276
+ };
+#endif
+/* Tokens. */
+#define tAGO 258
+#define tDST 259
+#define tYEAR_UNIT 260
+#define tMONTH_UNIT 261
+#define tHOUR_UNIT 262
+#define tMINUTE_UNIT 263
+#define tSEC_UNIT 264
+#define tDAY_UNIT 265
+#define tDAY 266
+#define tDAYZONE 267
+#define tLOCAL_ZONE 268
+#define tMERIDIAN 269
+#define tMONTH 270
+#define tORDINAL 271
+#define tZONE 272
+#define tSNUMBER 273
+#define tUNUMBER 274
+#define tSDECIMAL_NUMBER 275
+#define tUDECIMAL_NUMBER 276
+
+
+
+
+/* Copy the first part of user declarations. */
+#line 1 "getdate.y"
+
+/* Parse a string into an internal time stamp.
+
+ Copyright (C) 1999, 2000, 2002, 2003, 2004, 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. */
+
+/* Originally written by Steven M. Bellovin <smb@research.att.com> while
+ at the University of North Carolina at Chapel Hill. Later tweaked by
+ a couple of people on Usenet. Completely overhauled by Rich $alz
+ <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990.
+
+ Modified by Paul Eggert <eggert@twinsun.com> in August 1999 to do
+ the right thing about local DST. Also modified by Paul Eggert
+ <eggert@cs.ucla.edu> in February 2004 to support
+ nanosecond-resolution time stamps, and in October 2004 to support
+ TZ strings in dates. */
+
+/* FIXME: Check for arithmetic overflow in all cases, not just
+ some of them. */
+
+#include <config.h>
+
+#include "getdate.h"
+#include "timespec.h"
+
+/* There's no need to extend the stack, so there's no need to involve
+ alloca. */
+#define YYSTACK_USE_ALLOCA 0
+
+/* Tell Bison how much stack space is needed. 20 should be plenty for
+ this grammar, which is not right recursive. Beware setting it too
+ high, since that might cause problems on machines whose
+ implementations have lame stack-overflow checking. */
+#define YYMAXDEPTH 20
+#define YYINITDEPTH YYMAXDEPTH
+
+/* Since the code of getdate.y is not included in the Emacs executable
+ itself, there is no need to #define static in this file. Even if
+ the code were included in the Emacs executable, it probably
+ wouldn't do any harm to #undef it here; this will only cause
+ problems if we try to write to a static variable, which I don't
+ think this code needs to do. */
+#ifdef emacs
+# undef static
+#endif
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "setenv.h"
+#include "xalloc.h"
+
+
+/* ISDIGIT differs from isdigit, as follows:
+ - Its arg may be any int or unsigned int; it need not be an unsigned char
+ or EOF.
+ - It's typically faster.
+ POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to
+ isdigit unless it's important to use the locale's definition
+ of `digit' even when the host does not conform to POSIX. */
+#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
+
+#ifndef __attribute__
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
+# define __attribute__(x)
+# endif
+#endif
+
+#ifndef ATTRIBUTE_UNUSED
+# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif
+
+/* Shift A right by B bits portably, by dividing A by 2**B and
+ truncating towards minus infinity. A and B should be free of side
+ effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
+ INT_BITS is the number of useful bits in an int. GNU code can
+ assume that INT_BITS is at least 32.
+
+ ISO C99 says that A >> B is implementation-defined if A < 0. Some
+ implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
+ right in the usual way when A < 0, so SHR falls back on division if
+ ordinary A >> B doesn't seem to be the usual signed shift. */
+#define SHR(a, b) \
+ (-1 >> 1 == -1 \
+ ? (a) >> (b) \
+ : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
+
+#define EPOCH_YEAR 1970
+#define TM_YEAR_BASE 1900
+
+#define HOUR(x) ((x) * 60)
+
+/* An integer value, and the number of digits in its textual
+ representation. */
+typedef struct
+{
+ bool negative;
+ long int value;
+ size_t digits;
+} textint;
+
+/* An entry in the lexical lookup table. */
+typedef struct
+{
+ char const *name;
+ int type;
+ int value;
+} table;
+
+/* Meridian: am, pm, or 24-hour style. */
+enum { MERam, MERpm, MER24 };
+
+enum { BILLION = 1000000000, LOG10_BILLION = 9 };
+
+/* Relative times. */
+typedef struct
+{
+ /* Relative year, month, day, hour, minutes, seconds, and nanoseconds. */
+ long int year;
+ long int month;
+ long int day;
+ long int hour;
+ long int minutes;
+ long int seconds;
+ long int ns;
+} relative_time;
+
+#if HAVE_COMPOUND_LITERALS
+# define RELATIVE_TIME_0 ((relative_time) { 0, 0, 0, 0, 0, 0, 0 })
+#else
+static relative_time const RELATIVE_TIME_0;
+#endif
+
+/* Information passed to and from the parser. */
+typedef struct
+{
+ /* The input string remaining to be parsed. */
+ const char *input;
+
+ /* N, if this is the Nth Tuesday. */
+ long int day_ordinal;
+
+ /* Day of week; Sunday is 0. */
+ int day_number;
+
+ /* tm_isdst flag for the local zone. */
+ int local_isdst;
+
+ /* Time zone, in minutes east of UTC. */
+ long int time_zone;
+
+ /* Style used for time. */
+ int meridian;
+
+ /* Gregorian year, month, day, hour, minutes, seconds, and nanoseconds. */
+ textint year;
+ long int month;
+ long int day;
+ long int hour;
+ long int minutes;
+ struct timespec seconds; /* includes nanoseconds */
+
+ /* Relative year, month, day, hour, minutes, seconds, and nanoseconds. */
+ relative_time rel;
+
+ /* Presence or counts of nonterminals of various flavors parsed so far. */
+ bool timespec_seen;
+ bool rels_seen;
+ size_t dates_seen;
+ size_t days_seen;
+ size_t local_zones_seen;
+ size_t dsts_seen;
+ size_t times_seen;
+ size_t zones_seen;
+
+ /* Table of local time zone abbrevations, terminated by a null entry. */
+ table local_time_zone_table[3];
+} parser_control;
+
+union YYSTYPE;
+static int yylex (union YYSTYPE *, parser_control *);
+static int yyerror (parser_control const *, char const *);
+static long int time_zone_hhmm (textint, long int);
+
+
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 214 "getdate.y"
+{
+ long int intval;
+ textint textintval;
+ struct timespec timespec;
+ relative_time rel;
+}
+/* Line 193 of yacc.c. */
+#line 348 "getdate.c"
+ YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 216 of yacc.c. */
+#line 361 "getdate.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+ int i;
+#endif
+{
+ return i;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss;
+ YYSTYPE yyvs;
+ };
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
+ Stack = &yyptr->Stack; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 12
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 91
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 26
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 19
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 78
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 96
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 276
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 24, 2, 2, 25, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 23, 2,
+ 2, 2, 2, 2, 22, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint8 yyprhs[] =
+{
+ 0, 0, 3, 5, 7, 10, 11, 14, 16, 18,
+ 20, 22, 24, 26, 28, 31, 36, 42, 49, 57,
+ 59, 62, 64, 67, 71, 73, 76, 78, 81, 84,
+ 87, 91, 97, 101, 105, 109, 112, 117, 120, 124,
+ 127, 129, 132, 135, 137, 140, 143, 145, 148, 151,
+ 153, 156, 159, 161, 164, 167, 169, 172, 175, 178,
+ 181, 183, 185, 188, 191, 194, 197, 200, 203, 205,
+ 207, 209, 211, 213, 215, 217, 218, 221, 222
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
+{
+ 27, 0, -1, 28, -1, 29, -1, 22, 39, -1,
+ -1, 29, 30, -1, 31, -1, 32, -1, 33, -1,
+ 35, -1, 34, -1, 36, -1, 42, -1, 19, 14,
+ -1, 19, 23, 19, 44, -1, 19, 23, 19, 18,
+ 43, -1, 19, 23, 19, 23, 41, 44, -1, 19,
+ 23, 19, 23, 41, 18, 43, -1, 13, -1, 13,
+ 4, -1, 17, -1, 17, 38, -1, 17, 18, 43,
+ -1, 12, -1, 17, 4, -1, 11, -1, 11, 24,
+ -1, 16, 11, -1, 19, 11, -1, 19, 25, 19,
+ -1, 19, 25, 19, 25, 19, -1, 19, 18, 18,
+ -1, 19, 15, 18, -1, 15, 18, 18, -1, 15,
+ 19, -1, 15, 19, 24, 19, -1, 19, 15, -1,
+ 19, 15, 19, -1, 37, 3, -1, 37, -1, 16,
+ 5, -1, 19, 5, -1, 5, -1, 16, 6, -1,
+ 19, 6, -1, 6, -1, 16, 10, -1, 19, 10,
+ -1, 10, -1, 16, 7, -1, 19, 7, -1, 7,
+ -1, 16, 8, -1, 19, 8, -1, 8, -1, 16,
+ 9, -1, 19, 9, -1, 20, 9, -1, 21, 9,
+ -1, 9, -1, 38, -1, 18, 5, -1, 18, 6,
+ -1, 18, 10, -1, 18, 7, -1, 18, 8, -1,
+ 18, 9, -1, 40, -1, 41, -1, 20, -1, 18,
+ -1, 21, -1, 19, -1, 19, -1, -1, 23, 19,
+ -1, -1, 14, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 240, 240, 241, 245, 252, 254, 258, 260, 262,
+ 264, 266, 268, 270, 274, 282, 290, 300, 307, 319,
+ 324, 332, 334, 344, 346, 348, 353, 358, 363, 368,
+ 376, 381, 401, 408, 416, 424, 429, 435, 440, 449,
+ 459, 472, 474, 476, 478, 480, 482, 484, 486, 488,
+ 490, 492, 494, 496, 498, 500, 502, 504, 506, 508,
+ 510, 512, 516, 518, 520, 522, 524, 526, 530, 530,
+ 533, 534, 539, 540, 545, 583, 584, 590, 591
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "tAGO", "tDST", "tYEAR_UNIT",
+ "tMONTH_UNIT", "tHOUR_UNIT", "tMINUTE_UNIT", "tSEC_UNIT", "tDAY_UNIT",
+ "tDAY", "tDAYZONE", "tLOCAL_ZONE", "tMERIDIAN", "tMONTH", "tORDINAL",
+ "tZONE", "tSNUMBER", "tUNUMBER", "tSDECIMAL_NUMBER", "tUDECIMAL_NUMBER",
+ "'@'", "':'", "','", "'/'", "$accept", "spec", "timespec", "items",
+ "item", "time", "local_zone", "zone", "day", "date", "rel", "relunit",
+ "relunit_snumber", "seconds", "signed_seconds", "unsigned_seconds",
+ "number", "o_colon_minutes", "o_merid", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 64, 58, 44, 47
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 26, 27, 27, 28, 29, 29, 30, 30, 30,
+ 30, 30, 30, 30, 31, 31, 31, 31, 31, 32,
+ 32, 33, 33, 33, 33, 33, 34, 34, 34, 34,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 36,
+ 36, 37, 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 38, 38, 38, 38, 38, 38, 39, 39,
+ 40, 40, 41, 41, 42, 43, 43, 44, 44
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 1, 1, 2, 0, 2, 1, 1, 1,
+ 1, 1, 1, 1, 2, 4, 5, 6, 7, 1,
+ 2, 1, 2, 3, 1, 2, 1, 2, 2, 2,
+ 3, 5, 3, 3, 3, 2, 4, 2, 3, 2,
+ 1, 2, 2, 1, 2, 2, 1, 2, 2, 1,
+ 2, 2, 1, 2, 2, 1, 2, 2, 2, 2,
+ 1, 1, 2, 2, 2, 2, 2, 2, 1, 1,
+ 1, 1, 1, 1, 1, 0, 2, 0, 1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 5, 0, 0, 2, 3, 71, 73, 70, 72, 4,
+ 68, 69, 1, 43, 46, 52, 55, 60, 49, 26,
+ 24, 19, 0, 0, 21, 0, 74, 0, 0, 6,
+ 7, 8, 9, 11, 10, 12, 40, 61, 13, 27,
+ 20, 0, 35, 41, 44, 50, 53, 56, 47, 28,
+ 25, 75, 22, 62, 63, 65, 66, 67, 64, 42,
+ 45, 51, 54, 57, 48, 29, 14, 37, 0, 0,
+ 0, 58, 59, 39, 34, 0, 0, 23, 33, 38,
+ 32, 77, 30, 36, 76, 78, 75, 0, 15, 0,
+ 16, 77, 31, 75, 17, 18
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int8 yydefgoto[] =
+{
+ -1, 2, 3, 4, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 9, 10, 11, 38, 77, 88
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -79
+static const yytype_int8 yypact[] =
+{
+ -10, 47, 27, -79, 25, -79, -79, -79, -79, -79,
+ -79, -79, -79, -79, -79, -79, -79, -79, -79, 5,
+ -79, 59, 43, 42, 10, 49, -5, 62, 63, -79,
+ -79, -79, -79, -79, -79, -79, 70, -79, -79, -79,
+ -79, 56, 52, -79, -79, -79, -79, -79, -79, -79,
+ -79, 16, -79, -79, -79, -79, -79, -79, -79, -79,
+ -79, -79, -79, -79, -79, -79, -79, 51, 57, 58,
+ 60, -79, -79, -79, -79, 61, 64, -79, -79, -79,
+ -79, -7, 53, -79, -79, -79, 65, -2, -79, 66,
+ -79, 46, -79, 65, -79, -79
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int8 yypgoto[] =
+{
+ -79, -79, -79, -79, -79, -79, -79, -79, -79, -79,
+ -79, -79, 67, -79, -79, -6, -79, -78, -9
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -1
+static const yytype_uint8 yytable[] =
+{
+ 59, 60, 61, 62, 63, 64, 65, 85, 90, 66,
+ 67, 86, 1, 68, 50, 95, 87, 6, 69, 8,
+ 70, 53, 54, 55, 56, 57, 58, 12, 51, 39,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 76,
+ 22, 23, 24, 25, 26, 27, 28, 43, 44, 45,
+ 46, 47, 48, 49, 53, 54, 55, 56, 57, 58,
+ 85, 41, 42, 40, 93, 5, 6, 7, 8, 78,
+ 79, 71, 72, 73, 74, 80, 75, 81, 89, 82,
+ 83, 91, 94, 84, 0, 92, 0, 0, 76, 0,
+ 0, 52
+};
+
+static const yytype_int8 yycheck[] =
+{
+ 5, 6, 7, 8, 9, 10, 11, 14, 86, 14,
+ 15, 18, 22, 18, 4, 93, 23, 19, 23, 21,
+ 25, 5, 6, 7, 8, 9, 10, 0, 18, 24,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 23,
+ 15, 16, 17, 18, 19, 20, 21, 5, 6, 7,
+ 8, 9, 10, 11, 5, 6, 7, 8, 9, 10,
+ 14, 18, 19, 4, 18, 18, 19, 20, 21, 18,
+ 19, 9, 9, 3, 18, 18, 24, 19, 25, 19,
+ 19, 87, 91, 19, -1, 19, -1, -1, 23, -1,
+ -1, 24
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 22, 27, 28, 29, 18, 19, 20, 21, 39,
+ 40, 41, 0, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 15, 16, 17, 18, 19, 20, 21, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 42, 24,
+ 4, 18, 19, 5, 6, 7, 8, 9, 10, 11,
+ 4, 18, 38, 5, 6, 7, 8, 9, 10, 5,
+ 6, 7, 8, 9, 10, 11, 14, 15, 18, 23,
+ 25, 9, 9, 3, 18, 24, 23, 43, 18, 19,
+ 18, 19, 19, 19, 19, 14, 18, 23, 44, 25,
+ 43, 41, 19, 18, 44, 43
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (pc, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval, pc)
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, pc); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, parser_control *pc)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, pc)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ parser_control *pc;
+#endif
+{
+ if (!yyvaluep)
+ return;
+ YYUSE (pc);
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, parser_control *pc)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, pc)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ parser_control *pc;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, pc);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+#else
+static void
+yy_stack_print (bottom, top)
+ yytype_int16 *bottom;
+ yytype_int16 *top;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; bottom <= top; ++bottom)
+ YYFPRINTF (stderr, " %d", *bottom);
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule, parser_control *pc)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule, pc)
+ YYSTYPE *yyvsp;
+ int yyrule;
+ parser_control *pc;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ fprintf (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , pc);
+ fprintf (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, Rule, pc); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, parser_control *pc)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, pc)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+ parser_control *pc;
+#endif
+{
+ YYUSE (yyvaluep);
+ YYUSE (pc);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes. */
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (parser_control *pc);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (parser_control *pc)
+#else
+int
+yyparse (pc)
+ parser_control *pc;
+#endif
+#endif
+{
+ /* The look-ahead symbol. */
+int yychar;
+
+/* The semantic value of the look-ahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+ int yystate;
+ int yyn;
+ int yyresult;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+ /* Look-ahead token as an internal (translated) token number. */
+ int yytoken = 0;
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+ /* Three stacks and their tools:
+ `yyss': related to states,
+ `yyvs': related to semantic values,
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss = yyssa;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ YYSIZE_T yystacksize = YYINITDEPTH;
+
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss);
+ YYSTACK_RELOCATE (yyvs);
+
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ look-ahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to look-ahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a look-ahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the look-ahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 4:
+#line 246 "getdate.y"
+ {
+ pc->seconds = (yyvsp[(2) - (2)].timespec);
+ pc->timespec_seen = true;
+ }
+ break;
+
+ case 7:
+#line 259 "getdate.y"
+ { pc->times_seen++; }
+ break;
+
+ case 8:
+#line 261 "getdate.y"
+ { pc->local_zones_seen++; }
+ break;
+
+ case 9:
+#line 263 "getdate.y"
+ { pc->zones_seen++; }
+ break;
+
+ case 10:
+#line 265 "getdate.y"
+ { pc->dates_seen++; }
+ break;
+
+ case 11:
+#line 267 "getdate.y"
+ { pc->days_seen++; }
+ break;
+
+ case 12:
+#line 269 "getdate.y"
+ { pc->rels_seen = true; }
+ break;
+
+ case 14:
+#line 275 "getdate.y"
+ {
+ pc->hour = (yyvsp[(1) - (2)].textintval).value;
+ pc->minutes = 0;
+ pc->seconds.tv_sec = 0;
+ pc->seconds.tv_nsec = 0;
+ pc->meridian = (yyvsp[(2) - (2)].intval);
+ }
+ break;
+
+ case 15:
+#line 283 "getdate.y"
+ {
+ pc->hour = (yyvsp[(1) - (4)].textintval).value;
+ pc->minutes = (yyvsp[(3) - (4)].textintval).value;
+ pc->seconds.tv_sec = 0;
+ pc->seconds.tv_nsec = 0;
+ pc->meridian = (yyvsp[(4) - (4)].intval);
+ }
+ break;
+
+ case 16:
+#line 291 "getdate.y"
+ {
+ pc->hour = (yyvsp[(1) - (5)].textintval).value;
+ pc->minutes = (yyvsp[(3) - (5)].textintval).value;
+ pc->seconds.tv_sec = 0;
+ pc->seconds.tv_nsec = 0;
+ pc->meridian = MER24;
+ pc->zones_seen++;
+ pc->time_zone = time_zone_hhmm ((yyvsp[(4) - (5)].textintval), (yyvsp[(5) - (5)].intval));
+ }
+ break;
+
+ case 17:
+#line 301 "getdate.y"
+ {
+ pc->hour = (yyvsp[(1) - (6)].textintval).value;
+ pc->minutes = (yyvsp[(3) - (6)].textintval).value;
+ pc->seconds = (yyvsp[(5) - (6)].timespec);
+ pc->meridian = (yyvsp[(6) - (6)].intval);
+ }
+ break;
+
+ case 18:
+#line 308 "getdate.y"
+ {
+ pc->hour = (yyvsp[(1) - (7)].textintval).value;
+ pc->minutes = (yyvsp[(3) - (7)].textintval).value;
+ pc->seconds = (yyvsp[(5) - (7)].timespec);
+ pc->meridian = MER24;
+ pc->zones_seen++;
+ pc->time_zone = time_zone_hhmm ((yyvsp[(6) - (7)].textintval), (yyvsp[(7) - (7)].intval));
+ }
+ break;
+
+ case 19:
+#line 320 "getdate.y"
+ {
+ pc->local_isdst = (yyvsp[(1) - (1)].intval);
+ pc->dsts_seen += (0 < (yyvsp[(1) - (1)].intval));
+ }
+ break;
+
+ case 20:
+#line 325 "getdate.y"
+ {
+ pc->local_isdst = 1;
+ pc->dsts_seen += (0 < (yyvsp[(1) - (2)].intval)) + 1;
+ }
+ break;
+
+ case 21:
+#line 333 "getdate.y"
+ { pc->time_zone = (yyvsp[(1) - (1)].intval); }
+ break;
+
+ case 22:
+#line 335 "getdate.y"
+ { pc->time_zone = (yyvsp[(1) - (2)].intval);
+ pc->rel.ns += (yyvsp[(2) - (2)].rel).ns;
+ pc->rel.seconds += (yyvsp[(2) - (2)].rel).seconds;
+ pc->rel.minutes += (yyvsp[(2) - (2)].rel).minutes;
+ pc->rel.hour += (yyvsp[(2) - (2)].rel).hour;
+ pc->rel.day += (yyvsp[(2) - (2)].rel).day;
+ pc->rel.month += (yyvsp[(2) - (2)].rel).month;
+ pc->rel.year += (yyvsp[(2) - (2)].rel).year;
+ pc->rels_seen = true; }
+ break;
+
+ case 23:
+#line 345 "getdate.y"
+ { pc->time_zone = (yyvsp[(1) - (3)].intval) + time_zone_hhmm ((yyvsp[(2) - (3)].textintval), (yyvsp[(3) - (3)].intval)); }
+ break;
+
+ case 24:
+#line 347 "getdate.y"
+ { pc->time_zone = (yyvsp[(1) - (1)].intval) + 60; }
+ break;
+
+ case 25:
+#line 349 "getdate.y"
+ { pc->time_zone = (yyvsp[(1) - (2)].intval) + 60; }
+ break;
+
+ case 26:
+#line 354 "getdate.y"
+ {
+ pc->day_ordinal = 1;
+ pc->day_number = (yyvsp[(1) - (1)].intval);
+ }
+ break;
+
+ case 27:
+#line 359 "getdate.y"
+ {
+ pc->day_ordinal = 1;
+ pc->day_number = (yyvsp[(1) - (2)].intval);
+ }
+ break;
+
+ case 28:
+#line 364 "getdate.y"
+ {
+ pc->day_ordinal = (yyvsp[(1) - (2)].intval);
+ pc->day_number = (yyvsp[(2) - (2)].intval);
+ }
+ break;
+
+ case 29:
+#line 369 "getdate.y"
+ {
+ pc->day_ordinal = (yyvsp[(1) - (2)].textintval).value;
+ pc->day_number = (yyvsp[(2) - (2)].intval);
+ }
+ break;
+
+ case 30:
+#line 377 "getdate.y"
+ {
+ pc->month = (yyvsp[(1) - (3)].textintval).value;
+ pc->day = (yyvsp[(3) - (3)].textintval).value;
+ }
+ break;
+
+ case 31:
+#line 382 "getdate.y"
+ {
+ /* Interpret as YYYY/MM/DD if the first value has 4 or more digits,
+ otherwise as MM/DD/YY.
+ The goal in recognizing YYYY/MM/DD is solely to support legacy
+ machine-generated dates like those in an RCS log listing. If
+ you want portability, use the ISO 8601 format. */
+ if (4 <= (yyvsp[(1) - (5)].textintval).digits)
+ {
+ pc->year = (yyvsp[(1) - (5)].textintval);
+ pc->month = (yyvsp[(3) - (5)].textintval).value;
+ pc->day = (yyvsp[(5) - (5)].textintval).value;
+ }
+ else
+ {
+ pc->month = (yyvsp[(1) - (5)].textintval).value;
+ pc->day = (yyvsp[(3) - (5)].textintval).value;
+ pc->year = (yyvsp[(5) - (5)].textintval);
+ }
+ }
+ break;
+
+ case 32:
+#line 402 "getdate.y"
+ {
+ /* ISO 8601 format. YYYY-MM-DD. */
+ pc->year = (yyvsp[(1) - (3)].textintval);
+ pc->month = -(yyvsp[(2) - (3)].textintval).value;
+ pc->day = -(yyvsp[(3) - (3)].textintval).value;
+ }
+ break;
+
+ case 33:
+#line 409 "getdate.y"
+ {
+ /* e.g. 17-JUN-1992. */
+ pc->day = (yyvsp[(1) - (3)].textintval).value;
+ pc->month = (yyvsp[(2) - (3)].intval);
+ pc->year.value = -(yyvsp[(3) - (3)].textintval).value;
+ pc->year.digits = (yyvsp[(3) - (3)].textintval).digits;
+ }
+ break;
+
+ case 34:
+#line 417 "getdate.y"
+ {
+ /* e.g. JUN-17-1992. */
+ pc->month = (yyvsp[(1) - (3)].intval);
+ pc->day = -(yyvsp[(2) - (3)].textintval).value;
+ pc->year.value = -(yyvsp[(3) - (3)].textintval).value;
+ pc->year.digits = (yyvsp[(3) - (3)].textintval).digits;
+ }
+ break;
+
+ case 35:
+#line 425 "getdate.y"
+ {
+ pc->month = (yyvsp[(1) - (2)].intval);
+ pc->day = (yyvsp[(2) - (2)].textintval).value;
+ }
+ break;
+
+ case 36:
+#line 430 "getdate.y"
+ {
+ pc->month = (yyvsp[(1) - (4)].intval);
+ pc->day = (yyvsp[(2) - (4)].textintval).value;
+ pc->year = (yyvsp[(4) - (4)].textintval);
+ }
+ break;
+
+ case 37:
+#line 436 "getdate.y"
+ {
+ pc->day = (yyvsp[(1) - (2)].textintval).value;
+ pc->month = (yyvsp[(2) - (2)].intval);
+ }
+ break;
+
+ case 38:
+#line 441 "getdate.y"
+ {
+ pc->day = (yyvsp[(1) - (3)].textintval).value;
+ pc->month = (yyvsp[(2) - (3)].intval);
+ pc->year = (yyvsp[(3) - (3)].textintval);
+ }
+ break;
+
+ case 39:
+#line 450 "getdate.y"
+ {
+ pc->rel.ns -= (yyvsp[(1) - (2)].rel).ns;
+ pc->rel.seconds -= (yyvsp[(1) - (2)].rel).seconds;
+ pc->rel.minutes -= (yyvsp[(1) - (2)].rel).minutes;
+ pc->rel.hour -= (yyvsp[(1) - (2)].rel).hour;
+ pc->rel.day -= (yyvsp[(1) - (2)].rel).day;
+ pc->rel.month -= (yyvsp[(1) - (2)].rel).month;
+ pc->rel.year -= (yyvsp[(1) - (2)].rel).year;
+ }
+ break;
+
+ case 40:
+#line 460 "getdate.y"
+ {
+ pc->rel.ns += (yyvsp[(1) - (1)].rel).ns;
+ pc->rel.seconds += (yyvsp[(1) - (1)].rel).seconds;
+ pc->rel.minutes += (yyvsp[(1) - (1)].rel).minutes;
+ pc->rel.hour += (yyvsp[(1) - (1)].rel).hour;
+ pc->rel.day += (yyvsp[(1) - (1)].rel).day;
+ pc->rel.month += (yyvsp[(1) - (1)].rel).month;
+ pc->rel.year += (yyvsp[(1) - (1)].rel).year;
+ }
+ break;
+
+ case 41:
+#line 473 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).year = (yyvsp[(1) - (2)].intval); }
+ break;
+
+ case 42:
+#line 475 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).year = (yyvsp[(1) - (2)].textintval).value; }
+ break;
+
+ case 43:
+#line 477 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).year = 1; }
+ break;
+
+ case 44:
+#line 479 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).month = (yyvsp[(1) - (2)].intval); }
+ break;
+
+ case 45:
+#line 481 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).month = (yyvsp[(1) - (2)].textintval).value; }
+ break;
+
+ case 46:
+#line 483 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).month = 1; }
+ break;
+
+ case 47:
+#line 485 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[(1) - (2)].intval) * (yyvsp[(2) - (2)].intval); }
+ break;
+
+ case 48:
+#line 487 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[(1) - (2)].textintval).value * (yyvsp[(2) - (2)].intval); }
+ break;
+
+ case 49:
+#line 489 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[(1) - (1)].intval); }
+ break;
+
+ case 50:
+#line 491 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).hour = (yyvsp[(1) - (2)].intval); }
+ break;
+
+ case 51:
+#line 493 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).hour = (yyvsp[(1) - (2)].textintval).value; }
+ break;
+
+ case 52:
+#line 495 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).hour = 1; }
+ break;
+
+ case 53:
+#line 497 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).minutes = (yyvsp[(1) - (2)].intval); }
+ break;
+
+ case 54:
+#line 499 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).minutes = (yyvsp[(1) - (2)].textintval).value; }
+ break;
+
+ case 55:
+#line 501 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).minutes = 1; }
+ break;
+
+ case 56:
+#line 503 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[(1) - (2)].intval); }
+ break;
+
+ case 57:
+#line 505 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[(1) - (2)].textintval).value; }
+ break;
+
+ case 58:
+#line 507 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[(1) - (2)].timespec).tv_sec; (yyval.rel).ns = (yyvsp[(1) - (2)].timespec).tv_nsec; }
+ break;
+
+ case 59:
+#line 509 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[(1) - (2)].timespec).tv_sec; (yyval.rel).ns = (yyvsp[(1) - (2)].timespec).tv_nsec; }
+ break;
+
+ case 60:
+#line 511 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = 1; }
+ break;
+
+ case 62:
+#line 517 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).year = (yyvsp[(1) - (2)].textintval).value; }
+ break;
+
+ case 63:
+#line 519 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).month = (yyvsp[(1) - (2)].textintval).value; }
+ break;
+
+ case 64:
+#line 521 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[(1) - (2)].textintval).value * (yyvsp[(2) - (2)].intval); }
+ break;
+
+ case 65:
+#line 523 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).hour = (yyvsp[(1) - (2)].textintval).value; }
+ break;
+
+ case 66:
+#line 525 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).minutes = (yyvsp[(1) - (2)].textintval).value; }
+ break;
+
+ case 67:
+#line 527 "getdate.y"
+ { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[(1) - (2)].textintval).value; }
+ break;
+
+ case 71:
+#line 535 "getdate.y"
+ { (yyval.timespec).tv_sec = (yyvsp[(1) - (1)].textintval).value; (yyval.timespec).tv_nsec = 0; }
+ break;
+
+ case 73:
+#line 541 "getdate.y"
+ { (yyval.timespec).tv_sec = (yyvsp[(1) - (1)].textintval).value; (yyval.timespec).tv_nsec = 0; }
+ break;
+
+ case 74:
+#line 546 "getdate.y"
+ {
+ if (pc->dates_seen && ! pc->year.digits
+ && ! pc->rels_seen && (pc->times_seen || 2 < (yyvsp[(1) - (1)].textintval).digits))
+ pc->year = (yyvsp[(1) - (1)].textintval);
+ else
+ {
+ if (4 < (yyvsp[(1) - (1)].textintval).digits)
+ {
+ pc->dates_seen++;
+ pc->day = (yyvsp[(1) - (1)].textintval).value % 100;
+ pc->month = ((yyvsp[(1) - (1)].textintval).value / 100) % 100;
+ pc->year.value = (yyvsp[(1) - (1)].textintval).value / 10000;
+ pc->year.digits = (yyvsp[(1) - (1)].textintval).digits - 4;
+ }
+ else
+ {
+ pc->times_seen++;
+ if ((yyvsp[(1) - (1)].textintval).digits <= 2)
+ {
+ pc->hour = (yyvsp[(1) - (1)].textintval).value;
+ pc->minutes = 0;
+ }
+ else
+ {
+ pc->hour = (yyvsp[(1) - (1)].textintval).value / 100;
+ pc->minutes = (yyvsp[(1) - (1)].textintval).value % 100;
+ }
+ pc->seconds.tv_sec = 0;
+ pc->seconds.tv_nsec = 0;
+ pc->meridian = MER24;
+ }
+ }
+ }
+ break;
+
+ case 75:
+#line 583 "getdate.y"
+ { (yyval.intval) = -1; }
+ break;
+
+ case 76:
+#line 585 "getdate.y"
+ { (yyval.intval) = (yyvsp[(2) - (2)].textintval).value; }
+ break;
+
+ case 77:
+#line 590 "getdate.y"
+ { (yyval.intval) = MER24; }
+ break;
+
+ case 78:
+#line 592 "getdate.y"
+ { (yyval.intval) = (yyvsp[(1) - (1)].intval); }
+ break;
+
+
+/* Line 1267 of yacc.c. */
+#line 2149 "getdate.c"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (pc, YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (pc, yymsg);
+ }
+ else
+ {
+ yyerror (pc, YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse look-ahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, pc);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse look-ahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, pc);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ *++yyvsp = yylval;
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#ifndef yyoverflow
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (pc, YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEOF && yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, pc);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, pc);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+#line 595 "getdate.y"
+
+
+static table const meridian_table[] =
+{
+ { "AM", tMERIDIAN, MERam },
+ { "A.M.", tMERIDIAN, MERam },
+ { "PM", tMERIDIAN, MERpm },
+ { "P.M.", tMERIDIAN, MERpm },
+ { NULL, 0, 0 }
+};
+
+static table const dst_table[] =
+{
+ { "DST", tDST, 0 }
+};
+
+static table const month_and_day_table[] =
+{
+ { "JANUARY", tMONTH, 1 },
+ { "FEBRUARY", tMONTH, 2 },
+ { "MARCH", tMONTH, 3 },
+ { "APRIL", tMONTH, 4 },
+ { "MAY", tMONTH, 5 },
+ { "JUNE", tMONTH, 6 },
+ { "JULY", tMONTH, 7 },
+ { "AUGUST", tMONTH, 8 },
+ { "SEPTEMBER",tMONTH, 9 },
+ { "SEPT", tMONTH, 9 },
+ { "OCTOBER", tMONTH, 10 },
+ { "NOVEMBER", tMONTH, 11 },
+ { "DECEMBER", tMONTH, 12 },
+ { "SUNDAY", tDAY, 0 },
+ { "MONDAY", tDAY, 1 },
+ { "TUESDAY", tDAY, 2 },
+ { "TUES", tDAY, 2 },
+ { "WEDNESDAY",tDAY, 3 },
+ { "WEDNES", tDAY, 3 },
+ { "THURSDAY", tDAY, 4 },
+ { "THUR", tDAY, 4 },
+ { "THURS", tDAY, 4 },
+ { "FRIDAY", tDAY, 5 },
+ { "SATURDAY", tDAY, 6 },
+ { NULL, 0, 0 }
+};
+
+static table const time_units_table[] =
+{
+ { "YEAR", tYEAR_UNIT, 1 },
+ { "MONTH", tMONTH_UNIT, 1 },
+ { "FORTNIGHT",tDAY_UNIT, 14 },
+ { "WEEK", tDAY_UNIT, 7 },
+ { "DAY", tDAY_UNIT, 1 },
+ { "HOUR", tHOUR_UNIT, 1 },
+ { "MINUTE", tMINUTE_UNIT, 1 },
+ { "MIN", tMINUTE_UNIT, 1 },
+ { "SECOND", tSEC_UNIT, 1 },
+ { "SEC", tSEC_UNIT, 1 },
+ { NULL, 0, 0 }
+};
+
+/* Assorted relative-time words. */
+static table const relative_time_table[] =
+{
+ { "TOMORROW", tDAY_UNIT, 1 },
+ { "YESTERDAY",tDAY_UNIT, -1 },
+ { "TODAY", tDAY_UNIT, 0 },
+ { "NOW", tDAY_UNIT, 0 },
+ { "LAST", tORDINAL, -1 },
+ { "THIS", tORDINAL, 0 },
+ { "NEXT", tORDINAL, 1 },
+ { "FIRST", tORDINAL, 1 },
+/*{ "SECOND", tORDINAL, 2 }, */
+ { "THIRD", tORDINAL, 3 },
+ { "FOURTH", tORDINAL, 4 },
+ { "FIFTH", tORDINAL, 5 },
+ { "SIXTH", tORDINAL, 6 },
+ { "SEVENTH", tORDINAL, 7 },
+ { "EIGHTH", tORDINAL, 8 },
+ { "NINTH", tORDINAL, 9 },
+ { "TENTH", tORDINAL, 10 },
+ { "ELEVENTH", tORDINAL, 11 },
+ { "TWELFTH", tORDINAL, 12 },
+ { "AGO", tAGO, 1 },
+ { NULL, 0, 0 }
+};
+
+/* The universal time zone table. These labels can be used even for
+ time stamps that would not otherwise be valid, e.g., GMT time
+ stamps in London during summer. */
+static table const universal_time_zone_table[] =
+{
+ { "GMT", tZONE, HOUR ( 0) }, /* Greenwich Mean */
+ { "UT", tZONE, HOUR ( 0) }, /* Universal (Coordinated) */
+ { "UTC", tZONE, HOUR ( 0) },
+ { NULL, 0, 0 }
+};
+
+/* The time zone table. This table is necessarily incomplete, as time
+ zone abbreviations are ambiguous; e.g. Australians interpret "EST"
+ as Eastern time in Australia, not as US Eastern Standard Time.
+ You cannot rely on getdate to handle arbitrary time zone
+ abbreviations; use numeric abbreviations like `-0500' instead. */
+static table const time_zone_table[] =
+{
+ { "WET", tZONE, HOUR ( 0) }, /* Western European */
+ { "WEST", tDAYZONE, HOUR ( 0) }, /* Western European Summer */
+ { "BST", tDAYZONE, HOUR ( 0) }, /* British Summer */
+ { "ART", tZONE, -HOUR ( 3) }, /* Argentina */
+ { "BRT", tZONE, -HOUR ( 3) }, /* Brazil */
+ { "BRST", tDAYZONE, -HOUR ( 3) }, /* Brazil Summer */
+ { "NST", tZONE, -(HOUR ( 3) + 30) }, /* Newfoundland Standard */
+ { "NDT", tDAYZONE,-(HOUR ( 3) + 30) }, /* Newfoundland Daylight */
+ { "AST", tZONE, -HOUR ( 4) }, /* Atlantic Standard */
+ { "ADT", tDAYZONE, -HOUR ( 4) }, /* Atlantic Daylight */
+ { "CLT", tZONE, -HOUR ( 4) }, /* Chile */
+ { "CLST", tDAYZONE, -HOUR ( 4) }, /* Chile Summer */
+ { "EST", tZONE, -HOUR ( 5) }, /* Eastern Standard */
+ { "EDT", tDAYZONE, -HOUR ( 5) }, /* Eastern Daylight */
+ { "CST", tZONE, -HOUR ( 6) }, /* Central Standard */
+ { "CDT", tDAYZONE, -HOUR ( 6) }, /* Central Daylight */
+ { "MST", tZONE, -HOUR ( 7) }, /* Mountain Standard */
+ { "MDT", tDAYZONE, -HOUR ( 7) }, /* Mountain Daylight */
+ { "PST", tZONE, -HOUR ( 8) }, /* Pacific Standard */
+ { "PDT", tDAYZONE, -HOUR ( 8) }, /* Pacific Daylight */
+ { "AKST", tZONE, -HOUR ( 9) }, /* Alaska Standard */
+ { "AKDT", tDAYZONE, -HOUR ( 9) }, /* Alaska Daylight */
+ { "HST", tZONE, -HOUR (10) }, /* Hawaii Standard */
+ { "HAST", tZONE, -HOUR (10) }, /* Hawaii-Aleutian Standard */
+ { "HADT", tDAYZONE, -HOUR (10) }, /* Hawaii-Aleutian Daylight */
+ { "SST", tZONE, -HOUR (12) }, /* Samoa Standard */
+ { "WAT", tZONE, HOUR ( 1) }, /* West Africa */
+ { "CET", tZONE, HOUR ( 1) }, /* Central European */
+ { "CEST", tDAYZONE, HOUR ( 1) }, /* Central European Summer */
+ { "MET", tZONE, HOUR ( 1) }, /* Middle European */
+ { "MEZ", tZONE, HOUR ( 1) }, /* Middle European */
+ { "MEST", tDAYZONE, HOUR ( 1) }, /* Middle European Summer */
+ { "MESZ", tDAYZONE, HOUR ( 1) }, /* Middle European Summer */
+ { "EET", tZONE, HOUR ( 2) }, /* Eastern European */
+ { "EEST", tDAYZONE, HOUR ( 2) }, /* Eastern European Summer */
+ { "CAT", tZONE, HOUR ( 2) }, /* Central Africa */
+ { "SAST", tZONE, HOUR ( 2) }, /* South Africa Standard */
+ { "EAT", tZONE, HOUR ( 3) }, /* East Africa */
+ { "MSK", tZONE, HOUR ( 3) }, /* Moscow */
+ { "MSD", tDAYZONE, HOUR ( 3) }, /* Moscow Daylight */
+ { "IST", tZONE, (HOUR ( 5) + 30) }, /* India Standard */
+ { "SGT", tZONE, HOUR ( 8) }, /* Singapore */
+ { "KST", tZONE, HOUR ( 9) }, /* Korea Standard */
+ { "JST", tZONE, HOUR ( 9) }, /* Japan Standard */
+ { "GST", tZONE, HOUR (10) }, /* Guam Standard */
+ { "NZST", tZONE, HOUR (12) }, /* New Zealand Standard */
+ { "NZDT", tDAYZONE, HOUR (12) }, /* New Zealand Daylight */
+ { NULL, 0, 0 }
+};
+
+/* Military time zone table. */
+static table const military_table[] =
+{
+ { "A", tZONE, -HOUR ( 1) },
+ { "B", tZONE, -HOUR ( 2) },
+ { "C", tZONE, -HOUR ( 3) },
+ { "D", tZONE, -HOUR ( 4) },
+ { "E", tZONE, -HOUR ( 5) },
+ { "F", tZONE, -HOUR ( 6) },
+ { "G", tZONE, -HOUR ( 7) },
+ { "H", tZONE, -HOUR ( 8) },
+ { "I", tZONE, -HOUR ( 9) },
+ { "K", tZONE, -HOUR (10) },
+ { "L", tZONE, -HOUR (11) },
+ { "M", tZONE, -HOUR (12) },
+ { "N", tZONE, HOUR ( 1) },
+ { "O", tZONE, HOUR ( 2) },
+ { "P", tZONE, HOUR ( 3) },
+ { "Q", tZONE, HOUR ( 4) },
+ { "R", tZONE, HOUR ( 5) },
+ { "S", tZONE, HOUR ( 6) },
+ { "T", tZONE, HOUR ( 7) },
+ { "U", tZONE, HOUR ( 8) },
+ { "V", tZONE, HOUR ( 9) },
+ { "W", tZONE, HOUR (10) },
+ { "X", tZONE, HOUR (11) },
+ { "Y", tZONE, HOUR (12) },
+ { "Z", tZONE, HOUR ( 0) },
+ { NULL, 0, 0 }
+};
+
+
+
+/* Convert a time zone expressed as HH:MM into an integer count of
+ minutes. If MM is negative, then S is of the form HHMM and needs
+ to be picked apart; otherwise, S is of the form HH. */
+
+static long int
+time_zone_hhmm (textint s, long int mm)
+{
+ if (mm < 0)
+ return (s.value / 100) * 60 + s.value % 100;
+ else
+ return s.value * 60 + (s.negative ? -mm : mm);
+}
+
+static int
+to_hour (long int hours, int meridian)
+{
+ switch (meridian)
+ {
+ default: /* Pacify GCC. */
+ case MER24:
+ return 0 <= hours && hours < 24 ? hours : -1;
+ case MERam:
+ return 0 < hours && hours < 12 ? hours : hours == 12 ? 0 : -1;
+ case MERpm:
+ return 0 < hours && hours < 12 ? hours + 12 : hours == 12 ? 12 : -1;
+ }
+}
+
+static long int
+to_year (textint textyear)
+{
+ long int year = textyear.value;
+
+ if (year < 0)
+ year = -year;
+
+ /* XPG4 suggests that years 00-68 map to 2000-2068, and
+ years 69-99 map to 1969-1999. */
+ else if (textyear.digits == 2)
+ year += year < 69 ? 2000 : 1900;
+
+ return year;
+}
+
+static table const *
+lookup_zone (parser_control const *pc, char const *name)
+{
+ table const *tp;
+
+ for (tp = universal_time_zone_table; tp->name; tp++)
+ if (strcmp (name, tp->name) == 0)
+ return tp;
+
+ /* Try local zone abbreviations before those in time_zone_table, as
+ the local ones are more likely to be right. */
+ for (tp = pc->local_time_zone_table; tp->name; tp++)
+ if (strcmp (name, tp->name) == 0)
+ return tp;
+
+ for (tp = time_zone_table; tp->name; tp++)
+ if (strcmp (name, tp->name) == 0)
+ return tp;
+
+ return NULL;
+}
+
+#if ! HAVE_TM_GMTOFF
+/* Yield the difference between *A and *B,
+ measured in seconds, ignoring leap seconds.
+ The body of this function is taken directly from the GNU C Library;
+ see src/strftime.c. */
+static long int
+tm_diff (struct tm const *a, struct tm const *b)
+{
+ /* Compute intervening leap days correctly even if year is negative.
+ Take care to avoid int overflow in leap day calculations. */
+ int a4 = SHR (a->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (a->tm_year & 3);
+ int b4 = SHR (b->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (b->tm_year & 3);
+ int a100 = a4 / 25 - (a4 % 25 < 0);
+ int b100 = b4 / 25 - (b4 % 25 < 0);
+ int a400 = SHR (a100, 2);
+ int b400 = SHR (b100, 2);
+ int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
+ long int ayear = a->tm_year;
+ long int years = ayear - b->tm_year;
+ long int days = (365 * years + intervening_leap_days
+ + (a->tm_yday - b->tm_yday));
+ return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
+ + (a->tm_min - b->tm_min))
+ + (a->tm_sec - b->tm_sec));
+}
+#endif /* ! HAVE_TM_GMTOFF */
+
+static table const *
+lookup_word (parser_control const *pc, char *word)
+{
+ char *p;
+ char *q;
+ size_t wordlen;
+ table const *tp;
+ bool period_found;
+ bool abbrev;
+
+ /* Make it uppercase. */
+ for (p = word; *p; p++)
+ {
+ unsigned char ch = *p;
+ *p = toupper (ch);
+ }
+
+ for (tp = meridian_table; tp->name; tp++)
+ if (strcmp (word, tp->name) == 0)
+ return tp;
+
+ /* See if we have an abbreviation for a month. */
+ wordlen = strlen (word);
+ abbrev = wordlen == 3 || (wordlen == 4 && word[3] == '.');
+
+ for (tp = month_and_day_table; tp->name; tp++)
+ if ((abbrev ? strncmp (word, tp->name, 3) : strcmp (word, tp->name)) == 0)
+ return tp;
+
+ if ((tp = lookup_zone (pc, word)))
+ return tp;
+
+ if (strcmp (word, dst_table[0].name) == 0)
+ return dst_table;
+
+ for (tp = time_units_table; tp->name; tp++)
+ if (strcmp (word, tp->name) == 0)
+ return tp;
+
+ /* Strip off any plural and try the units table again. */
+ if (word[wordlen - 1] == 'S')
+ {
+ word[wordlen - 1] = '\0';
+ for (tp = time_units_table; tp->name; tp++)
+ if (strcmp (word, tp->name) == 0)
+ return tp;
+ word[wordlen - 1] = 'S'; /* For "this" in relative_time_table. */
+ }
+
+ for (tp = relative_time_table; tp->name; tp++)
+ if (strcmp (word, tp->name) == 0)
+ return tp;
+
+ /* Military time zones. */
+ if (wordlen == 1)
+ for (tp = military_table; tp->name; tp++)
+ if (word[0] == tp->name[0])
+ return tp;
+
+ /* Drop out any periods and try the time zone table again. */
+ for (period_found = false, p = q = word; (*p = *q); q++)
+ if (*q == '.')
+ period_found = true;
+ else
+ p++;
+ if (period_found && (tp = lookup_zone (pc, word)))
+ return tp;
+
+ return NULL;
+}
+
+static int
+yylex (YYSTYPE *lvalp, parser_control *pc)
+{
+ unsigned char c;
+ size_t count;
+
+ for (;;)
+ {
+ while (c = *pc->input, isspace (c))
+ pc->input++;
+
+ if (ISDIGIT (c) || c == '-' || c == '+')
+ {
+ char const *p;
+ int sign;
+ unsigned long int value;
+ if (c == '-' || c == '+')
+ {
+ sign = c == '-' ? -1 : 1;
+ while (c = *++pc->input, isspace (c))
+ continue;
+ if (! ISDIGIT (c))
+ /* skip the '-' sign */
+ continue;
+ }
+ else
+ sign = 0;
+ p = pc->input;
+ for (value = 0; ; value *= 10)
+ {
+ unsigned long int value1 = value + (c - '0');
+ if (value1 < value)
+ return '?';
+ value = value1;
+ c = *++p;
+ if (! ISDIGIT (c))
+ break;
+ if (ULONG_MAX / 10 < value)
+ return '?';
+ }
+ if ((c == '.' || c == ',') && ISDIGIT (p[1]))
+ {
+ time_t s;
+ int ns;
+ int digits;
+ unsigned long int value1;
+
+ /* Check for overflow when converting value to time_t. */
+ if (sign < 0)
+ {
+ s = - value;
+ if (0 < s)
+ return '?';
+ value1 = -s;
+ }
+ else
+ {
+ s = value;
+ if (s < 0)
+ return '?';
+ value1 = s;
+ }
+ if (value != value1)
+ return '?';
+
+ /* Accumulate fraction, to ns precision. */
+ p++;
+ ns = *p++ - '0';
+ for (digits = 2; digits <= LOG10_BILLION; digits++)
+ {
+ ns *= 10;
+ if (ISDIGIT (*p))
+ ns += *p++ - '0';
+ }
+
+ /* Skip excess digits, truncating toward -Infinity. */
+ if (sign < 0)
+ for (; ISDIGIT (*p); p++)
+ if (*p != '0')
+ {
+ ns++;
+ break;
+ }
+ while (ISDIGIT (*p))
+ p++;
+
+ /* Adjust to the timespec convention, which is that
+ tv_nsec is always a positive offset even if tv_sec is
+ negative. */
+ if (sign < 0 && ns)
+ {
+ s--;
+ if (! (s < 0))
+ return '?';
+ ns = BILLION - ns;
+ }
+
+ lvalp->timespec.tv_sec = s;
+ lvalp->timespec.tv_nsec = ns;
+ pc->input = p;
+ return sign ? tSDECIMAL_NUMBER : tUDECIMAL_NUMBER;
+ }
+ else
+ {
+ lvalp->textintval.negative = sign < 0;
+ if (sign < 0)
+ {
+ lvalp->textintval.value = - value;
+ if (0 < lvalp->textintval.value)
+ return '?';
+ }
+ else
+ {
+ lvalp->textintval.value = value;
+ if (lvalp->textintval.value < 0)
+ return '?';
+ }
+ lvalp->textintval.digits = p - pc->input;
+ pc->input = p;
+ return sign ? tSNUMBER : tUNUMBER;
+ }
+ }
+
+ if (isalpha (c))
+ {
+ char buff[20];
+ char *p = buff;
+ table const *tp;
+
+ do
+ {
+ if (p < buff + sizeof buff - 1)
+ *p++ = c;
+ c = *++pc->input;
+ }
+ while (isalpha (c) || c == '.');
+
+ *p = '\0';
+ tp = lookup_word (pc, buff);
+ if (! tp)
+ return '?';
+ lvalp->intval = tp->value;
+ return tp->type;
+ }
+
+ if (c != '(')
+ return *pc->input++;
+ count = 0;
+ do
+ {
+ c = *pc->input++;
+ if (c == '\0')
+ return c;
+ if (c == '(')
+ count++;
+ else if (c == ')')
+ count--;
+ }
+ while (count != 0);
+ }
+}
+
+/* Do nothing if the parser reports an error. */
+static int
+yyerror (parser_control const *pc ATTRIBUTE_UNUSED,
+ char const *s ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+/* If *TM0 is the old and *TM1 is the new value of a struct tm after
+ passing it to mktime, return true if it's OK that mktime returned T.
+ It's not OK if *TM0 has out-of-range members. */
+
+static bool
+mktime_ok (struct tm const *tm0, struct tm const *tm1, time_t t)
+{
+ if (t == (time_t) -1)
+ {
+ /* Guard against falsely reporting an error when parsing a time
+ stamp that happens to equal (time_t) -1, on a host that
+ supports such a time stamp. */
+ tm1 = localtime (&t);
+ if (!tm1)
+ return false;
+ }
+
+ return ! ((tm0->tm_sec ^ tm1->tm_sec)
+ | (tm0->tm_min ^ tm1->tm_min)
+ | (tm0->tm_hour ^ tm1->tm_hour)
+ | (tm0->tm_mday ^ tm1->tm_mday)
+ | (tm0->tm_mon ^ tm1->tm_mon)
+ | (tm0->tm_year ^ tm1->tm_year));
+}
+
+/* A reasonable upper bound for the size of ordinary TZ strings.
+ Use heap allocation if TZ's length exceeds this. */
+enum { TZBUFSIZE = 100 };
+
+/* Return a copy of TZ, stored in TZBUF if it fits, and heap-allocated
+ otherwise. */
+static char *
+get_tz (char tzbuf[TZBUFSIZE])
+{
+ char *tz = getenv ("TZ");
+ if (tz)
+ {
+ size_t tzsize = strlen (tz) + 1;
+ tz = (tzsize <= TZBUFSIZE
+ ? memcpy (tzbuf, tz, tzsize)
+ : xmemdup (tz, tzsize));
+ }
+ return tz;
+}
+
+/* Parse a date/time string, storing the resulting time value into *RESULT.
+ The string itself is pointed to by P. Return true if successful.
+ P can be an incomplete or relative time specification; if so, use
+ *NOW as the basis for the returned time. */
+bool
+get_date (struct timespec *result, char const *p, struct timespec const *now)
+{
+ time_t Start;
+ long int Start_ns;
+ struct tm const *tmp;
+ struct tm tm;
+ struct tm tm0;
+ parser_control pc;
+ struct timespec gettime_buffer;
+ unsigned char c;
+ bool tz_was_altered = false;
+ char *tz0 = NULL;
+ char tz0buf[TZBUFSIZE];
+ bool ok = true;
+
+ if (! now)
+ {
+ gettime (&gettime_buffer);
+ now = &gettime_buffer;
+ }
+
+ Start = now->tv_sec;
+ Start_ns = now->tv_nsec;
+
+ tmp = localtime (&now->tv_sec);
+ if (! tmp)
+ return false;
+
+ while (c = *p, isspace (c))
+ p++;
+
+ if (strncmp (p, "TZ=\"", 4) == 0)
+ {
+ char const *tzbase = p + 4;
+ size_t tzsize = 1;
+ char const *s;
+
+ for (s = tzbase; *s; s++, tzsize++)
+ if (*s == '\\')
+ {
+ s++;
+ if (! (*s == '\\' || *s == '"'))
+ break;
+ }
+ else if (*s == '"')
+ {
+ char *z;
+ char *tz1;
+ char tz1buf[TZBUFSIZE];
+ bool large_tz = TZBUFSIZE < tzsize;
+ bool setenv_ok;
+ tz0 = get_tz (tz0buf);
+ z = tz1 = large_tz ? xmalloc (tzsize) : tz1buf;
+ for (s = tzbase; *s != '"'; s++)
+ *z++ = *(s += *s == '\\');
+ *z = '\0';
+ setenv_ok = setenv ("TZ", tz1, 1) == 0;
+ if (large_tz)
+ free (tz1);
+ if (!setenv_ok)
+ goto fail;
+ tz_was_altered = true;
+ p = s + 1;
+ }
+ }
+
+ pc.input = p;
+ pc.year.value = tmp->tm_year;
+ pc.year.value += TM_YEAR_BASE;
+ pc.year.digits = 0;
+ pc.month = tmp->tm_mon + 1;
+ pc.day = tmp->tm_mday;
+ pc.hour = tmp->tm_hour;
+ pc.minutes = tmp->tm_min;
+ pc.seconds.tv_sec = tmp->tm_sec;
+ pc.seconds.tv_nsec = Start_ns;
+ tm.tm_isdst = tmp->tm_isdst;
+
+ pc.meridian = MER24;
+ pc.rel = RELATIVE_TIME_0;
+ pc.timespec_seen = false;
+ pc.rels_seen = false;
+ pc.dates_seen = 0;
+ pc.days_seen = 0;
+ pc.times_seen = 0;
+ pc.local_zones_seen = 0;
+ pc.dsts_seen = 0;
+ pc.zones_seen = 0;
+
+#if HAVE_STRUCT_TM_TM_ZONE
+ pc.local_time_zone_table[0].name = tmp->tm_zone;
+ pc.local_time_zone_table[0].type = tLOCAL_ZONE;
+ pc.local_time_zone_table[0].value = tmp->tm_isdst;
+ pc.local_time_zone_table[1].name = NULL;
+
+ /* Probe the names used in the next three calendar quarters, looking
+ for a tm_isdst different from the one we already have. */
+ {
+ int quarter;
+ for (quarter = 1; quarter <= 3; quarter++)
+ {
+ time_t probe = Start + quarter * (90 * 24 * 60 * 60);
+ struct tm const *probe_tm = localtime (&probe);
+ if (probe_tm && probe_tm->tm_zone
+ && probe_tm->tm_isdst != pc.local_time_zone_table[0].value)
+ {
+ {
+ pc.local_time_zone_table[1].name = probe_tm->tm_zone;
+ pc.local_time_zone_table[1].type = tLOCAL_ZONE;
+ pc.local_time_zone_table[1].value = probe_tm->tm_isdst;
+ pc.local_time_zone_table[2].name = NULL;
+ }
+ break;
+ }
+ }
+ }
+#else
+#if HAVE_TZNAME
+ {
+# ifndef tzname
+ extern char *tzname[];
+# endif
+ int i;
+ for (i = 0; i < 2; i++)
+ {
+ pc.local_time_zone_table[i].name = tzname[i];
+ pc.local_time_zone_table[i].type = tLOCAL_ZONE;
+ pc.local_time_zone_table[i].value = i;
+ }
+ pc.local_time_zone_table[i].name = NULL;
+ }
+#else
+ pc.local_time_zone_table[0].name = NULL;
+#endif
+#endif
+
+ if (pc.local_time_zone_table[0].name && pc.local_time_zone_table[1].name
+ && ! strcmp (pc.local_time_zone_table[0].name,
+ pc.local_time_zone_table[1].name))
+ {
+ /* This locale uses the same abbrevation for standard and
+ daylight times. So if we see that abbreviation, we don't
+ know whether it's daylight time. */
+ pc.local_time_zone_table[0].value = -1;
+ pc.local_time_zone_table[1].name = NULL;
+ }
+
+ if (yyparse (&pc) != 0)
+ goto fail;
+
+ if (pc.timespec_seen)
+ *result = pc.seconds;
+ else
+ {
+ if (1 < (pc.times_seen | pc.dates_seen | pc.days_seen | pc.dsts_seen
+ | (pc.local_zones_seen + pc.zones_seen)))
+ goto fail;
+
+ tm.tm_year = to_year (pc.year) - TM_YEAR_BASE;
+ tm.tm_mon = pc.month - 1;
+ tm.tm_mday = pc.day;
+ if (pc.times_seen || (pc.rels_seen && ! pc.dates_seen && ! pc.days_seen))
+ {
+ tm.tm_hour = to_hour (pc.hour, pc.meridian);
+ if (tm.tm_hour < 0)
+ goto fail;
+ tm.tm_min = pc.minutes;
+ tm.tm_sec = pc.seconds.tv_sec;
+ }
+ else
+ {
+ tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
+ pc.seconds.tv_nsec = 0;
+ }
+
+ /* Let mktime deduce tm_isdst if we have an absolute time stamp. */
+ if (pc.dates_seen | pc.days_seen | pc.times_seen)
+ tm.tm_isdst = -1;
+
+ /* But if the input explicitly specifies local time with or without
+ DST, give mktime that information. */
+ if (pc.local_zones_seen)
+ tm.tm_isdst = pc.local_isdst;
+
+ tm0 = tm;
+
+ Start = mktime (&tm);
+
+ if (! mktime_ok (&tm0, &tm, Start))
+ {
+ if (! pc.zones_seen)
+ goto fail;
+ else
+ {
+ /* Guard against falsely reporting errors near the time_t
+ boundaries when parsing times in other time zones. For
+ example, suppose the input string "1969-12-31 23:00:00 -0100",
+ the current time zone is 8 hours ahead of UTC, and the min
+ time_t value is 1970-01-01 00:00:00 UTC. Then the min
+ localtime value is 1970-01-01 08:00:00, and mktime will
+ therefore fail on 1969-12-31 23:00:00. To work around the
+ problem, set the time zone to 1 hour behind UTC temporarily
+ by setting TZ="XXX1:00" and try mktime again. */
+
+ long int time_zone = pc.time_zone;
+ long int abs_time_zone = time_zone < 0 ? - time_zone : time_zone;
+ long int abs_time_zone_hour = abs_time_zone / 60;
+ int abs_time_zone_min = abs_time_zone % 60;
+ char tz1buf[sizeof "XXX+0:00"
+ + sizeof pc.time_zone * CHAR_BIT / 3];
+ if (!tz_was_altered)
+ tz0 = get_tz (tz0buf);
+ sprintf (tz1buf, "XXX%s%ld:%02d", "-" + (time_zone < 0),
+ abs_time_zone_hour, abs_time_zone_min);
+ if (setenv ("TZ", tz1buf, 1) != 0)
+ goto fail;
+ tz_was_altered = true;
+ tm = tm0;
+ Start = mktime (&tm);
+ if (! mktime_ok (&tm0, &tm, Start))
+ goto fail;
+ }
+ }
+
+ if (pc.days_seen && ! pc.dates_seen)
+ {
+ tm.tm_mday += ((pc.day_number - tm.tm_wday + 7) % 7
+ + 7 * (pc.day_ordinal - (0 < pc.day_ordinal)));
+ tm.tm_isdst = -1;
+ Start = mktime (&tm);
+ if (Start == (time_t) -1)
+ goto fail;
+ }
+
+ if (pc.zones_seen)
+ {
+ long int delta = pc.time_zone * 60;
+ time_t t1;
+#ifdef HAVE_TM_GMTOFF
+ delta -= tm.tm_gmtoff;
+#else
+ time_t t = Start;
+ struct tm const *gmt = gmtime (&t);
+ if (! gmt)
+ goto fail;
+ delta -= tm_diff (&tm, gmt);
+#endif
+ t1 = Start - delta;
+ if ((Start < t1) != (delta < 0))
+ goto fail; /* time_t overflow */
+ Start = t1;
+ }
+
+ /* Add relative date. */
+ if (pc.rel.year | pc.rel.month | pc.rel.day)
+ {
+ int year = tm.tm_year + pc.rel.year;
+ int month = tm.tm_mon + pc.rel.month;
+ int day = tm.tm_mday + pc.rel.day;
+ if (((year < tm.tm_year) ^ (pc.rel.year < 0))
+ | ((month < tm.tm_mon) ^ (pc.rel.month < 0))
+ | ((day < tm.tm_mday) ^ (pc.rel.day < 0)))
+ goto fail;
+ tm.tm_year = year;
+ tm.tm_mon = month;
+ tm.tm_mday = day;
+ tm.tm_hour = tm0.tm_hour;
+ tm.tm_min = tm0.tm_min;
+ tm.tm_sec = tm0.tm_sec;
+ tm.tm_isdst = tm0.tm_isdst;
+ Start = mktime (&tm);
+ if (Start == (time_t) -1)
+ goto fail;
+ }
+
+ /* Add relative hours, minutes, and seconds. On hosts that support
+ leap seconds, ignore the possibility of leap seconds; e.g.,
+ "+ 10 minutes" adds 600 seconds, even if one of them is a
+ leap second. Typically this is not what the user wants, but it's
+ too hard to do it the other way, because the time zone indicator
+ must be applied before relative times, and if mktime is applied
+ again the time zone will be lost. */
+ {
+ long int sum_ns = pc.seconds.tv_nsec + pc.rel.ns;
+ long int normalized_ns = (sum_ns % BILLION + BILLION) % BILLION;
+ time_t t0 = Start;
+ long int d1 = 60 * 60 * pc.rel.hour;
+ time_t t1 = t0 + d1;
+ long int d2 = 60 * pc.rel.minutes;
+ time_t t2 = t1 + d2;
+ long int d3 = pc.rel.seconds;
+ time_t t3 = t2 + d3;
+ long int d4 = (sum_ns - normalized_ns) / BILLION;
+ time_t t4 = t3 + d4;
+
+ if ((d1 / (60 * 60) ^ pc.rel.hour)
+ | (d2 / 60 ^ pc.rel.minutes)
+ | ((t1 < t0) ^ (d1 < 0))
+ | ((t2 < t1) ^ (d2 < 0))
+ | ((t3 < t2) ^ (d3 < 0))
+ | ((t4 < t3) ^ (d4 < 0)))
+ goto fail;
+
+ result->tv_sec = t4;
+ result->tv_nsec = normalized_ns;
+ }
+ }
+
+ goto done;
+
+ fail:
+ ok = false;
+ done:
+ if (tz_was_altered)
+ ok &= (tz0 ? setenv ("TZ", tz0, 1) : unsetenv ("TZ")) == 0;
+ if (tz0 != tz0buf)
+ free (tz0);
+ return ok;
+}
+
+#if TEST
+
+int
+main (int ac, char **av)
+{
+ char buff[BUFSIZ];
+
+ printf ("Enter date, or blank line to exit.\n\t> ");
+ fflush (stdout);
+
+ buff[BUFSIZ - 1] = '\0';
+ while (fgets (buff, BUFSIZ - 1, stdin) && buff[0])
+ {
+ struct timespec d;
+ struct tm const *tm;
+ if (! get_date (&d, buff, NULL))
+ printf ("Bad format - couldn't convert.\n");
+ else if (! (tm = localtime (&d.tv_sec)))
+ {
+ long int sec = d.tv_sec;
+ printf ("localtime (%ld) failed\n", sec);
+ }
+ else
+ {
+ int ns = d.tv_nsec;
+ printf ("%04ld-%02d-%02d %02d:%02d:%02d.%09d\n",
+ tm->tm_year + 1900L, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec, ns);
+ }
+ printf ("\t> ");
+ fflush (stdout);
+ }
+ return 0;
+}
+#endif /* TEST */
+
diff --git a/lib/getdate.h b/lib/getdate.h
new file mode 100644
index 0000000..142231e
--- /dev/null
+++ b/lib/getdate.h
@@ -0,0 +1,23 @@
+/* Parse a string into an internal time stamp.
+
+ Copyright (C) 1995, 1997, 1998, 2003, 2004, 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 <stdbool.h>
+#include <time.h>
+
+bool get_date (struct timespec *, char const *, struct timespec const *);
diff --git a/lib/getdate.y b/lib/getdate.y
new file mode 100644
index 0000000..cbf3ca1
--- /dev/null
+++ b/lib/getdate.y
@@ -0,0 +1,1520 @@
+%{
+/* Parse a string into an internal time stamp.
+
+ Copyright (C) 1999, 2000, 2002, 2003, 2004, 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. */
+
+/* Originally written by Steven M. Bellovin <smb@research.att.com> while
+ at the University of North Carolina at Chapel Hill. Later tweaked by
+ a couple of people on Usenet. Completely overhauled by Rich $alz
+ <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990.
+
+ Modified by Paul Eggert <eggert@twinsun.com> in August 1999 to do
+ the right thing about local DST. Also modified by Paul Eggert
+ <eggert@cs.ucla.edu> in February 2004 to support
+ nanosecond-resolution time stamps, and in October 2004 to support
+ TZ strings in dates. */
+
+/* FIXME: Check for arithmetic overflow in all cases, not just
+ some of them. */
+
+#include <config.h>
+
+#include "getdate.h"
+#include "timespec.h"
+
+/* There's no need to extend the stack, so there's no need to involve
+ alloca. */
+#define YYSTACK_USE_ALLOCA 0
+
+/* Tell Bison how much stack space is needed. 20 should be plenty for
+ this grammar, which is not right recursive. Beware setting it too
+ high, since that might cause problems on machines whose
+ implementations have lame stack-overflow checking. */
+#define YYMAXDEPTH 20
+#define YYINITDEPTH YYMAXDEPTH
+
+/* Since the code of getdate.y is not included in the Emacs executable
+ itself, there is no need to #define static in this file. Even if
+ the code were included in the Emacs executable, it probably
+ wouldn't do any harm to #undef it here; this will only cause
+ problems if we try to write to a static variable, which I don't
+ think this code needs to do. */
+#ifdef emacs
+# undef static
+#endif
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "setenv.h"
+#include "xalloc.h"
+
+
+/* ISDIGIT differs from isdigit, as follows:
+ - Its arg may be any int or unsigned int; it need not be an unsigned char
+ or EOF.
+ - It's typically faster.
+ POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to
+ isdigit unless it's important to use the locale's definition
+ of `digit' even when the host does not conform to POSIX. */
+#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
+
+#ifndef __attribute__
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
+# define __attribute__(x)
+# endif
+#endif
+
+#ifndef ATTRIBUTE_UNUSED
+# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif
+
+/* Shift A right by B bits portably, by dividing A by 2**B and
+ truncating towards minus infinity. A and B should be free of side
+ effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
+ INT_BITS is the number of useful bits in an int. GNU code can
+ assume that INT_BITS is at least 32.
+
+ ISO C99 says that A >> B is implementation-defined if A < 0. Some
+ implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
+ right in the usual way when A < 0, so SHR falls back on division if
+ ordinary A >> B doesn't seem to be the usual signed shift. */
+#define SHR(a, b) \
+ (-1 >> 1 == -1 \
+ ? (a) >> (b) \
+ : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
+
+#define EPOCH_YEAR 1970
+#define TM_YEAR_BASE 1900
+
+#define HOUR(x) ((x) * 60)
+
+/* An integer value, and the number of digits in its textual
+ representation. */
+typedef struct
+{
+ bool negative;
+ long int value;
+ size_t digits;
+} textint;
+
+/* An entry in the lexical lookup table. */
+typedef struct
+{
+ char const *name;
+ int type;
+ int value;
+} table;
+
+/* Meridian: am, pm, or 24-hour style. */
+enum { MERam, MERpm, MER24 };
+
+enum { BILLION = 1000000000, LOG10_BILLION = 9 };
+
+/* Relative times. */
+typedef struct
+{
+ /* Relative year, month, day, hour, minutes, seconds, and nanoseconds. */
+ long int year;
+ long int month;
+ long int day;
+ long int hour;
+ long int minutes;
+ long int seconds;
+ long int ns;
+} relative_time;
+
+#if HAVE_COMPOUND_LITERALS
+# define RELATIVE_TIME_0 ((relative_time) { 0, 0, 0, 0, 0, 0, 0 })
+#else
+static relative_time const RELATIVE_TIME_0;
+#endif
+
+/* Information passed to and from the parser. */
+typedef struct
+{
+ /* The input string remaining to be parsed. */
+ const char *input;
+
+ /* N, if this is the Nth Tuesday. */
+ long int day_ordinal;
+
+ /* Day of week; Sunday is 0. */
+ int day_number;
+
+ /* tm_isdst flag for the local zone. */
+ int local_isdst;
+
+ /* Time zone, in minutes east of UTC. */
+ long int time_zone;
+
+ /* Style used for time. */
+ int meridian;
+
+ /* Gregorian year, month, day, hour, minutes, seconds, and nanoseconds. */
+ textint year;
+ long int month;
+ long int day;
+ long int hour;
+ long int minutes;
+ struct timespec seconds; /* includes nanoseconds */
+
+ /* Relative year, month, day, hour, minutes, seconds, and nanoseconds. */
+ relative_time rel;
+
+ /* Presence or counts of nonterminals of various flavors parsed so far. */
+ bool timespec_seen;
+ bool rels_seen;
+ size_t dates_seen;
+ size_t days_seen;
+ size_t local_zones_seen;
+ size_t dsts_seen;
+ size_t times_seen;
+ size_t zones_seen;
+
+ /* Table of local time zone abbrevations, terminated by a null entry. */
+ table local_time_zone_table[3];
+} parser_control;
+
+union YYSTYPE;
+static int yylex (union YYSTYPE *, parser_control *);
+static int yyerror (parser_control const *, char const *);
+static long int time_zone_hhmm (textint, long int);
+
+%}
+
+/* We want a reentrant parser, even if the TZ manipulation and the calls to
+ localtime and gmtime are not reentrant. */
+%pure-parser
+%parse-param { parser_control *pc }
+%lex-param { parser_control *pc }
+
+/* This grammar has 20 shift/reduce conflicts. */
+%expect 20
+
+%union
+{
+ long int intval;
+ textint textintval;
+ struct timespec timespec;
+ relative_time rel;
+}
+
+%token tAGO tDST
+
+%token tYEAR_UNIT tMONTH_UNIT tHOUR_UNIT tMINUTE_UNIT tSEC_UNIT
+%token <intval> tDAY_UNIT
+
+%token <intval> tDAY tDAYZONE tLOCAL_ZONE tMERIDIAN
+%token <intval> tMONTH tORDINAL tZONE
+
+%token <textintval> tSNUMBER tUNUMBER
+%token <timespec> tSDECIMAL_NUMBER tUDECIMAL_NUMBER
+
+%type <intval> o_colon_minutes o_merid
+%type <timespec> seconds signed_seconds unsigned_seconds
+
+%type <rel> relunit relunit_snumber
+
+%%
+
+spec:
+ timespec
+ | items
+ ;
+
+timespec:
+ '@' seconds
+ {
+ pc->seconds = $2;
+ pc->timespec_seen = true;
+ }
+ ;
+
+items:
+ /* empty */
+ | items item
+ ;
+
+item:
+ time
+ { pc->times_seen++; }
+ | local_zone
+ { pc->local_zones_seen++; }
+ | zone
+ { pc->zones_seen++; }
+ | date
+ { pc->dates_seen++; }
+ | day
+ { pc->days_seen++; }
+ | rel
+ { pc->rels_seen = true; }
+ | number
+ ;
+
+time:
+ tUNUMBER tMERIDIAN
+ {
+ pc->hour = $1.value;
+ pc->minutes = 0;
+ pc->seconds.tv_sec = 0;
+ pc->seconds.tv_nsec = 0;
+ pc->meridian = $2;
+ }
+ | tUNUMBER ':' tUNUMBER o_merid
+ {
+ pc->hour = $1.value;
+ pc->minutes = $3.value;
+ pc->seconds.tv_sec = 0;
+ pc->seconds.tv_nsec = 0;
+ pc->meridian = $4;
+ }
+ | tUNUMBER ':' tUNUMBER tSNUMBER o_colon_minutes
+ {
+ pc->hour = $1.value;
+ pc->minutes = $3.value;
+ pc->seconds.tv_sec = 0;
+ pc->seconds.tv_nsec = 0;
+ pc->meridian = MER24;
+ pc->zones_seen++;
+ pc->time_zone = time_zone_hhmm ($4, $5);
+ }
+ | tUNUMBER ':' tUNUMBER ':' unsigned_seconds o_merid
+ {
+ pc->hour = $1.value;
+ pc->minutes = $3.value;
+ pc->seconds = $5;
+ pc->meridian = $6;
+ }
+ | tUNUMBER ':' tUNUMBER ':' unsigned_seconds tSNUMBER o_colon_minutes
+ {
+ pc->hour = $1.value;
+ pc->minutes = $3.value;
+ pc->seconds = $5;
+ pc->meridian = MER24;
+ pc->zones_seen++;
+ pc->time_zone = time_zone_hhmm ($6, $7);
+ }
+ ;
+
+local_zone:
+ tLOCAL_ZONE
+ {
+ pc->local_isdst = $1;
+ pc->dsts_seen += (0 < $1);
+ }
+ | tLOCAL_ZONE tDST
+ {
+ pc->local_isdst = 1;
+ pc->dsts_seen += (0 < $1) + 1;
+ }
+ ;
+
+zone:
+ tZONE
+ { pc->time_zone = $1; }
+ | tZONE relunit_snumber
+ { pc->time_zone = $1;
+ pc->rel.ns += $2.ns;
+ pc->rel.seconds += $2.seconds;
+ pc->rel.minutes += $2.minutes;
+ pc->rel.hour += $2.hour;
+ pc->rel.day += $2.day;
+ pc->rel.month += $2.month;
+ pc->rel.year += $2.year;
+ pc->rels_seen = true; }
+ | tZONE tSNUMBER o_colon_minutes
+ { pc->time_zone = $1 + time_zone_hhmm ($2, $3); }
+ | tDAYZONE
+ { pc->time_zone = $1 + 60; }
+ | tZONE tDST
+ { pc->time_zone = $1 + 60; }
+ ;
+
+day:
+ tDAY
+ {
+ pc->day_ordinal = 1;
+ pc->day_number = $1;
+ }
+ | tDAY ','
+ {
+ pc->day_ordinal = 1;
+ pc->day_number = $1;
+ }
+ | tORDINAL tDAY
+ {
+ pc->day_ordinal = $1;
+ pc->day_number = $2;
+ }
+ | tUNUMBER tDAY
+ {
+ pc->day_ordinal = $1.value;
+ pc->day_number = $2;
+ }
+ ;
+
+date:
+ tUNUMBER '/' tUNUMBER
+ {
+ pc->month = $1.value;
+ pc->day = $3.value;
+ }
+ | tUNUMBER '/' tUNUMBER '/' tUNUMBER
+ {
+ /* Interpret as YYYY/MM/DD if the first value has 4 or more digits,
+ otherwise as MM/DD/YY.
+ The goal in recognizing YYYY/MM/DD is solely to support legacy
+ machine-generated dates like those in an RCS log listing. If
+ you want portability, use the ISO 8601 format. */
+ if (4 <= $1.digits)
+ {
+ pc->year = $1;
+ pc->month = $3.value;
+ pc->day = $5.value;
+ }
+ else
+ {
+ pc->month = $1.value;
+ pc->day = $3.value;
+ pc->year = $5;
+ }
+ }
+ | tUNUMBER tSNUMBER tSNUMBER
+ {
+ /* ISO 8601 format. YYYY-MM-DD. */
+ pc->year = $1;
+ pc->month = -$2.value;
+ pc->day = -$3.value;
+ }
+ | tUNUMBER tMONTH tSNUMBER
+ {
+ /* e.g. 17-JUN-1992. */
+ pc->day = $1.value;
+ pc->month = $2;
+ pc->year.value = -$3.value;
+ pc->year.digits = $3.digits;
+ }
+ | tMONTH tSNUMBER tSNUMBER
+ {
+ /* e.g. JUN-17-1992. */
+ pc->month = $1;
+ pc->day = -$2.value;
+ pc->year.value = -$3.value;
+ pc->year.digits = $3.digits;
+ }
+ | tMONTH tUNUMBER
+ {
+ pc->month = $1;
+ pc->day = $2.value;
+ }
+ | tMONTH tUNUMBER ',' tUNUMBER
+ {
+ pc->month = $1;
+ pc->day = $2.value;
+ pc->year = $4;
+ }
+ | tUNUMBER tMONTH
+ {
+ pc->day = $1.value;
+ pc->month = $2;
+ }
+ | tUNUMBER tMONTH tUNUMBER
+ {
+ pc->day = $1.value;
+ pc->month = $2;
+ pc->year = $3;
+ }
+ ;
+
+rel:
+ relunit tAGO
+ {
+ pc->rel.ns -= $1.ns;
+ pc->rel.seconds -= $1.seconds;
+ pc->rel.minutes -= $1.minutes;
+ pc->rel.hour -= $1.hour;
+ pc->rel.day -= $1.day;
+ pc->rel.month -= $1.month;
+ pc->rel.year -= $1.year;
+ }
+ | relunit
+ {
+ pc->rel.ns += $1.ns;
+ pc->rel.seconds += $1.seconds;
+ pc->rel.minutes += $1.minutes;
+ pc->rel.hour += $1.hour;
+ pc->rel.day += $1.day;
+ pc->rel.month += $1.month;
+ pc->rel.year += $1.year;
+ }
+ ;
+
+relunit:
+ tORDINAL tYEAR_UNIT
+ { $$ = RELATIVE_TIME_0; $$.year = $1; }
+ | tUNUMBER tYEAR_UNIT
+ { $$ = RELATIVE_TIME_0; $$.year = $1.value; }
+ | tYEAR_UNIT
+ { $$ = RELATIVE_TIME_0; $$.year = 1; }
+ | tORDINAL tMONTH_UNIT
+ { $$ = RELATIVE_TIME_0; $$.month = $1; }
+ | tUNUMBER tMONTH_UNIT
+ { $$ = RELATIVE_TIME_0; $$.month = $1.value; }
+ | tMONTH_UNIT
+ { $$ = RELATIVE_TIME_0; $$.month = 1; }
+ | tORDINAL tDAY_UNIT
+ { $$ = RELATIVE_TIME_0; $$.day = $1 * $2; }
+ | tUNUMBER tDAY_UNIT
+ { $$ = RELATIVE_TIME_0; $$.day = $1.value * $2; }
+ | tDAY_UNIT
+ { $$ = RELATIVE_TIME_0; $$.day = $1; }
+ | tORDINAL tHOUR_UNIT
+ { $$ = RELATIVE_TIME_0; $$.hour = $1; }
+ | tUNUMBER tHOUR_UNIT
+ { $$ = RELATIVE_TIME_0; $$.hour = $1.value; }
+ | tHOUR_UNIT
+ { $$ = RELATIVE_TIME_0; $$.hour = 1; }
+ | tORDINAL tMINUTE_UNIT
+ { $$ = RELATIVE_TIME_0; $$.minutes = $1; }
+ | tUNUMBER tMINUTE_UNIT
+ { $$ = RELATIVE_TIME_0; $$.minutes = $1.value; }
+ | tMINUTE_UNIT
+ { $$ = RELATIVE_TIME_0; $$.minutes = 1; }
+ | tORDINAL tSEC_UNIT
+ { $$ = RELATIVE_TIME_0; $$.seconds = $1; }
+ | tUNUMBER tSEC_UNIT
+ { $$ = RELATIVE_TIME_0; $$.seconds = $1.value; }
+ | tSDECIMAL_NUMBER tSEC_UNIT
+ { $$ = RELATIVE_TIME_0; $$.seconds = $1.tv_sec; $$.ns = $1.tv_nsec; }
+ | tUDECIMAL_NUMBER tSEC_UNIT
+ { $$ = RELATIVE_TIME_0; $$.seconds = $1.tv_sec; $$.ns = $1.tv_nsec; }
+ | tSEC_UNIT
+ { $$ = RELATIVE_TIME_0; $$.seconds = 1; }
+ | relunit_snumber
+ ;
+
+relunit_snumber:
+ tSNUMBER tYEAR_UNIT
+ { $$ = RELATIVE_TIME_0; $$.year = $1.value; }
+ | tSNUMBER tMONTH_UNIT
+ { $$ = RELATIVE_TIME_0; $$.month = $1.value; }
+ | tSNUMBER tDAY_UNIT
+ { $$ = RELATIVE_TIME_0; $$.day = $1.value * $2; }
+ | tSNUMBER tHOUR_UNIT
+ { $$ = RELATIVE_TIME_0; $$.hour = $1.value; }
+ | tSNUMBER tMINUTE_UNIT
+ { $$ = RELATIVE_TIME_0; $$.minutes = $1.value; }
+ | tSNUMBER tSEC_UNIT
+ { $$ = RELATIVE_TIME_0; $$.seconds = $1.value; }
+ ;
+
+seconds: signed_seconds | unsigned_seconds;
+
+signed_seconds:
+ tSDECIMAL_NUMBER
+ | tSNUMBER
+ { $$.tv_sec = $1.value; $$.tv_nsec = 0; }
+ ;
+
+unsigned_seconds:
+ tUDECIMAL_NUMBER
+ | tUNUMBER
+ { $$.tv_sec = $1.value; $$.tv_nsec = 0; }
+ ;
+
+number:
+ tUNUMBER
+ {
+ if (pc->dates_seen && ! pc->year.digits
+ && ! pc->rels_seen && (pc->times_seen || 2 < $1.digits))
+ pc->year = $1;
+ else
+ {
+ if (4 < $1.digits)
+ {
+ pc->dates_seen++;
+ pc->day = $1.value % 100;
+ pc->month = ($1.value / 100) % 100;
+ pc->year.value = $1.value / 10000;
+ pc->year.digits = $1.digits - 4;
+ }
+ else
+ {
+ pc->times_seen++;
+ if ($1.digits <= 2)
+ {
+ pc->hour = $1.value;
+ pc->minutes = 0;
+ }
+ else
+ {
+ pc->hour = $1.value / 100;
+ pc->minutes = $1.value % 100;
+ }
+ pc->seconds.tv_sec = 0;
+ pc->seconds.tv_nsec = 0;
+ pc->meridian = MER24;
+ }
+ }
+ }
+ ;
+
+o_colon_minutes:
+ /* empty */
+ { $$ = -1; }
+ | ':' tUNUMBER
+ { $$ = $2.value; }
+ ;
+
+o_merid:
+ /* empty */
+ { $$ = MER24; }
+ | tMERIDIAN
+ { $$ = $1; }
+ ;
+
+%%
+
+static table const meridian_table[] =
+{
+ { "AM", tMERIDIAN, MERam },
+ { "A.M.", tMERIDIAN, MERam },
+ { "PM", tMERIDIAN, MERpm },
+ { "P.M.", tMERIDIAN, MERpm },
+ { NULL, 0, 0 }
+};
+
+static table const dst_table[] =
+{
+ { "DST", tDST, 0 }
+};
+
+static table const month_and_day_table[] =
+{
+ { "JANUARY", tMONTH, 1 },
+ { "FEBRUARY", tMONTH, 2 },
+ { "MARCH", tMONTH, 3 },
+ { "APRIL", tMONTH, 4 },
+ { "MAY", tMONTH, 5 },
+ { "JUNE", tMONTH, 6 },
+ { "JULY", tMONTH, 7 },
+ { "AUGUST", tMONTH, 8 },
+ { "SEPTEMBER",tMONTH, 9 },
+ { "SEPT", tMONTH, 9 },
+ { "OCTOBER", tMONTH, 10 },
+ { "NOVEMBER", tMONTH, 11 },
+ { "DECEMBER", tMONTH, 12 },
+ { "SUNDAY", tDAY, 0 },
+ { "MONDAY", tDAY, 1 },
+ { "TUESDAY", tDAY, 2 },
+ { "TUES", tDAY, 2 },
+ { "WEDNESDAY",tDAY, 3 },
+ { "WEDNES", tDAY, 3 },
+ { "THURSDAY", tDAY, 4 },
+ { "THUR", tDAY, 4 },
+ { "THURS", tDAY, 4 },
+ { "FRIDAY", tDAY, 5 },
+ { "SATURDAY", tDAY, 6 },
+ { NULL, 0, 0 }
+};
+
+static table const time_units_table[] =
+{
+ { "YEAR", tYEAR_UNIT, 1 },
+ { "MONTH", tMONTH_UNIT, 1 },
+ { "FORTNIGHT",tDAY_UNIT, 14 },
+ { "WEEK", tDAY_UNIT, 7 },
+ { "DAY", tDAY_UNIT, 1 },
+ { "HOUR", tHOUR_UNIT, 1 },
+ { "MINUTE", tMINUTE_UNIT, 1 },
+ { "MIN", tMINUTE_UNIT, 1 },
+ { "SECOND", tSEC_UNIT, 1 },
+ { "SEC", tSEC_UNIT, 1 },
+ { NULL, 0, 0 }
+};
+
+/* Assorted relative-time words. */
+static table const relative_time_table[] =
+{
+ { "TOMORROW", tDAY_UNIT, 1 },
+ { "YESTERDAY",tDAY_UNIT, -1 },
+ { "TODAY", tDAY_UNIT, 0 },
+ { "NOW", tDAY_UNIT, 0 },
+ { "LAST", tORDINAL, -1 },
+ { "THIS", tORDINAL, 0 },
+ { "NEXT", tORDINAL, 1 },
+ { "FIRST", tORDINAL, 1 },
+/*{ "SECOND", tORDINAL, 2 }, */
+ { "THIRD", tORDINAL, 3 },
+ { "FOURTH", tORDINAL, 4 },
+ { "FIFTH", tORDINAL, 5 },
+ { "SIXTH", tORDINAL, 6 },
+ { "SEVENTH", tORDINAL, 7 },
+ { "EIGHTH", tORDINAL, 8 },
+ { "NINTH", tORDINAL, 9 },
+ { "TENTH", tORDINAL, 10 },
+ { "ELEVENTH", tORDINAL, 11 },
+ { "TWELFTH", tORDINAL, 12 },
+ { "AGO", tAGO, 1 },
+ { NULL, 0, 0 }
+};
+
+/* The universal time zone table. These labels can be used even for
+ time stamps that would not otherwise be valid, e.g., GMT time
+ stamps in London during summer. */
+static table const universal_time_zone_table[] =
+{
+ { "GMT", tZONE, HOUR ( 0) }, /* Greenwich Mean */
+ { "UT", tZONE, HOUR ( 0) }, /* Universal (Coordinated) */
+ { "UTC", tZONE, HOUR ( 0) },
+ { NULL, 0, 0 }
+};
+
+/* The time zone table. This table is necessarily incomplete, as time
+ zone abbreviations are ambiguous; e.g. Australians interpret "EST"
+ as Eastern time in Australia, not as US Eastern Standard Time.
+ You cannot rely on getdate to handle arbitrary time zone
+ abbreviations; use numeric abbreviations like `-0500' instead. */
+static table const time_zone_table[] =
+{
+ { "WET", tZONE, HOUR ( 0) }, /* Western European */
+ { "WEST", tDAYZONE, HOUR ( 0) }, /* Western European Summer */
+ { "BST", tDAYZONE, HOUR ( 0) }, /* British Summer */
+ { "ART", tZONE, -HOUR ( 3) }, /* Argentina */
+ { "BRT", tZONE, -HOUR ( 3) }, /* Brazil */
+ { "BRST", tDAYZONE, -HOUR ( 3) }, /* Brazil Summer */
+ { "NST", tZONE, -(HOUR ( 3) + 30) }, /* Newfoundland Standard */
+ { "NDT", tDAYZONE,-(HOUR ( 3) + 30) }, /* Newfoundland Daylight */
+ { "AST", tZONE, -HOUR ( 4) }, /* Atlantic Standard */
+ { "ADT", tDAYZONE, -HOUR ( 4) }, /* Atlantic Daylight */
+ { "CLT", tZONE, -HOUR ( 4) }, /* Chile */
+ { "CLST", tDAYZONE, -HOUR ( 4) }, /* Chile Summer */
+ { "EST", tZONE, -HOUR ( 5) }, /* Eastern Standard */
+ { "EDT", tDAYZONE, -HOUR ( 5) }, /* Eastern Daylight */
+ { "CST", tZONE, -HOUR ( 6) }, /* Central Standard */
+ { "CDT", tDAYZONE, -HOUR ( 6) }, /* Central Daylight */
+ { "MST", tZONE, -HOUR ( 7) }, /* Mountain Standard */
+ { "MDT", tDAYZONE, -HOUR ( 7) }, /* Mountain Daylight */
+ { "PST", tZONE, -HOUR ( 8) }, /* Pacific Standard */
+ { "PDT", tDAYZONE, -HOUR ( 8) }, /* Pacific Daylight */
+ { "AKST", tZONE, -HOUR ( 9) }, /* Alaska Standard */
+ { "AKDT", tDAYZONE, -HOUR ( 9) }, /* Alaska Daylight */
+ { "HST", tZONE, -HOUR (10) }, /* Hawaii Standard */
+ { "HAST", tZONE, -HOUR (10) }, /* Hawaii-Aleutian Standard */
+ { "HADT", tDAYZONE, -HOUR (10) }, /* Hawaii-Aleutian Daylight */
+ { "SST", tZONE, -HOUR (12) }, /* Samoa Standard */
+ { "WAT", tZONE, HOUR ( 1) }, /* West Africa */
+ { "CET", tZONE, HOUR ( 1) }, /* Central European */
+ { "CEST", tDAYZONE, HOUR ( 1) }, /* Central European Summer */
+ { "MET", tZONE, HOUR ( 1) }, /* Middle European */
+ { "MEZ", tZONE, HOUR ( 1) }, /* Middle European */
+ { "MEST", tDAYZONE, HOUR ( 1) }, /* Middle European Summer */
+ { "MESZ", tDAYZONE, HOUR ( 1) }, /* Middle European Summer */
+ { "EET", tZONE, HOUR ( 2) }, /* Eastern European */
+ { "EEST", tDAYZONE, HOUR ( 2) }, /* Eastern European Summer */
+ { "CAT", tZONE, HOUR ( 2) }, /* Central Africa */
+ { "SAST", tZONE, HOUR ( 2) }, /* South Africa Standard */
+ { "EAT", tZONE, HOUR ( 3) }, /* East Africa */
+ { "MSK", tZONE, HOUR ( 3) }, /* Moscow */
+ { "MSD", tDAYZONE, HOUR ( 3) }, /* Moscow Daylight */
+ { "IST", tZONE, (HOUR ( 5) + 30) }, /* India Standard */
+ { "SGT", tZONE, HOUR ( 8) }, /* Singapore */
+ { "KST", tZONE, HOUR ( 9) }, /* Korea Standard */
+ { "JST", tZONE, HOUR ( 9) }, /* Japan Standard */
+ { "GST", tZONE, HOUR (10) }, /* Guam Standard */
+ { "NZST", tZONE, HOUR (12) }, /* New Zealand Standard */
+ { "NZDT", tDAYZONE, HOUR (12) }, /* New Zealand Daylight */
+ { NULL, 0, 0 }
+};
+
+/* Military time zone table. */
+static table const military_table[] =
+{
+ { "A", tZONE, -HOUR ( 1) },
+ { "B", tZONE, -HOUR ( 2) },
+ { "C", tZONE, -HOUR ( 3) },
+ { "D", tZONE, -HOUR ( 4) },
+ { "E", tZONE, -HOUR ( 5) },
+ { "F", tZONE, -HOUR ( 6) },
+ { "G", tZONE, -HOUR ( 7) },
+ { "H", tZONE, -HOUR ( 8) },
+ { "I", tZONE, -HOUR ( 9) },
+ { "K", tZONE, -HOUR (10) },
+ { "L", tZONE, -HOUR (11) },
+ { "M", tZONE, -HOUR (12) },
+ { "N", tZONE, HOUR ( 1) },
+ { "O", tZONE, HOUR ( 2) },
+ { "P", tZONE, HOUR ( 3) },
+ { "Q", tZONE, HOUR ( 4) },
+ { "R", tZONE, HOUR ( 5) },
+ { "S", tZONE, HOUR ( 6) },
+ { "T", tZONE, HOUR ( 7) },
+ { "U", tZONE, HOUR ( 8) },
+ { "V", tZONE, HOUR ( 9) },
+ { "W", tZONE, HOUR (10) },
+ { "X", tZONE, HOUR (11) },
+ { "Y", tZONE, HOUR (12) },
+ { "Z", tZONE, HOUR ( 0) },
+ { NULL, 0, 0 }
+};
+
+
+
+/* Convert a time zone expressed as HH:MM into an integer count of
+ minutes. If MM is negative, then S is of the form HHMM and needs
+ to be picked apart; otherwise, S is of the form HH. */
+
+static long int
+time_zone_hhmm (textint s, long int mm)
+{
+ if (mm < 0)
+ return (s.value / 100) * 60 + s.value % 100;
+ else
+ return s.value * 60 + (s.negative ? -mm : mm);
+}
+
+static int
+to_hour (long int hours, int meridian)
+{
+ switch (meridian)
+ {
+ default: /* Pacify GCC. */
+ case MER24:
+ return 0 <= hours && hours < 24 ? hours : -1;
+ case MERam:
+ return 0 < hours && hours < 12 ? hours : hours == 12 ? 0 : -1;
+ case MERpm:
+ return 0 < hours && hours < 12 ? hours + 12 : hours == 12 ? 12 : -1;
+ }
+}
+
+static long int
+to_year (textint textyear)
+{
+ long int year = textyear.value;
+
+ if (year < 0)
+ year = -year;
+
+ /* XPG4 suggests that years 00-68 map to 2000-2068, and
+ years 69-99 map to 1969-1999. */
+ else if (textyear.digits == 2)
+ year += year < 69 ? 2000 : 1900;
+
+ return year;
+}
+
+static table const *
+lookup_zone (parser_control const *pc, char const *name)
+{
+ table const *tp;
+
+ for (tp = universal_time_zone_table; tp->name; tp++)
+ if (strcmp (name, tp->name) == 0)
+ return tp;
+
+ /* Try local zone abbreviations before those in time_zone_table, as
+ the local ones are more likely to be right. */
+ for (tp = pc->local_time_zone_table; tp->name; tp++)
+ if (strcmp (name, tp->name) == 0)
+ return tp;
+
+ for (tp = time_zone_table; tp->name; tp++)
+ if (strcmp (name, tp->name) == 0)
+ return tp;
+
+ return NULL;
+}
+
+#if ! HAVE_TM_GMTOFF
+/* Yield the difference between *A and *B,
+ measured in seconds, ignoring leap seconds.
+ The body of this function is taken directly from the GNU C Library;
+ see src/strftime.c. */
+static long int
+tm_diff (struct tm const *a, struct tm const *b)
+{
+ /* Compute intervening leap days correctly even if year is negative.
+ Take care to avoid int overflow in leap day calculations. */
+ int a4 = SHR (a->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (a->tm_year & 3);
+ int b4 = SHR (b->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (b->tm_year & 3);
+ int a100 = a4 / 25 - (a4 % 25 < 0);
+ int b100 = b4 / 25 - (b4 % 25 < 0);
+ int a400 = SHR (a100, 2);
+ int b400 = SHR (b100, 2);
+ int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
+ long int ayear = a->tm_year;
+ long int years = ayear - b->tm_year;
+ long int days = (365 * years + intervening_leap_days
+ + (a->tm_yday - b->tm_yday));
+ return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
+ + (a->tm_min - b->tm_min))
+ + (a->tm_sec - b->tm_sec));
+}
+#endif /* ! HAVE_TM_GMTOFF */
+
+static table const *
+lookup_word (parser_control const *pc, char *word)
+{
+ char *p;
+ char *q;
+ size_t wordlen;
+ table const *tp;
+ bool period_found;
+ bool abbrev;
+
+ /* Make it uppercase. */
+ for (p = word; *p; p++)
+ {
+ unsigned char ch = *p;
+ *p = toupper (ch);
+ }
+
+ for (tp = meridian_table; tp->name; tp++)
+ if (strcmp (word, tp->name) == 0)
+ return tp;
+
+ /* See if we have an abbreviation for a month. */
+ wordlen = strlen (word);
+ abbrev = wordlen == 3 || (wordlen == 4 && word[3] == '.');
+
+ for (tp = month_and_day_table; tp->name; tp++)
+ if ((abbrev ? strncmp (word, tp->name, 3) : strcmp (word, tp->name)) == 0)
+ return tp;
+
+ if ((tp = lookup_zone (pc, word)))
+ return tp;
+
+ if (strcmp (word, dst_table[0].name) == 0)
+ return dst_table;
+
+ for (tp = time_units_table; tp->name; tp++)
+ if (strcmp (word, tp->name) == 0)
+ return tp;
+
+ /* Strip off any plural and try the units table again. */
+ if (word[wordlen - 1] == 'S')
+ {
+ word[wordlen - 1] = '\0';
+ for (tp = time_units_table; tp->name; tp++)
+ if (strcmp (word, tp->name) == 0)
+ return tp;
+ word[wordlen - 1] = 'S'; /* For "this" in relative_time_table. */
+ }
+
+ for (tp = relative_time_table; tp->name; tp++)
+ if (strcmp (word, tp->name) == 0)
+ return tp;
+
+ /* Military time zones. */
+ if (wordlen == 1)
+ for (tp = military_table; tp->name; tp++)
+ if (word[0] == tp->name[0])
+ return tp;
+
+ /* Drop out any periods and try the time zone table again. */
+ for (period_found = false, p = q = word; (*p = *q); q++)
+ if (*q == '.')
+ period_found = true;
+ else
+ p++;
+ if (period_found && (tp = lookup_zone (pc, word)))
+ return tp;
+
+ return NULL;
+}
+
+static int
+yylex (YYSTYPE *lvalp, parser_control *pc)
+{
+ unsigned char c;
+ size_t count;
+
+ for (;;)
+ {
+ while (c = *pc->input, isspace (c))
+ pc->input++;
+
+ if (ISDIGIT (c) || c == '-' || c == '+')
+ {
+ char const *p;
+ int sign;
+ unsigned long int value;
+ if (c == '-' || c == '+')
+ {
+ sign = c == '-' ? -1 : 1;
+ while (c = *++pc->input, isspace (c))
+ continue;
+ if (! ISDIGIT (c))
+ /* skip the '-' sign */
+ continue;
+ }
+ else
+ sign = 0;
+ p = pc->input;
+ for (value = 0; ; value *= 10)
+ {
+ unsigned long int value1 = value + (c - '0');
+ if (value1 < value)
+ return '?';
+ value = value1;
+ c = *++p;
+ if (! ISDIGIT (c))
+ break;
+ if (ULONG_MAX / 10 < value)
+ return '?';
+ }
+ if ((c == '.' || c == ',') && ISDIGIT (p[1]))
+ {
+ time_t s;
+ int ns;
+ int digits;
+ unsigned long int value1;
+
+ /* Check for overflow when converting value to time_t. */
+ if (sign < 0)
+ {
+ s = - value;
+ if (0 < s)
+ return '?';
+ value1 = -s;
+ }
+ else
+ {
+ s = value;
+ if (s < 0)
+ return '?';
+ value1 = s;
+ }
+ if (value != value1)
+ return '?';
+
+ /* Accumulate fraction, to ns precision. */
+ p++;
+ ns = *p++ - '0';
+ for (digits = 2; digits <= LOG10_BILLION; digits++)
+ {
+ ns *= 10;
+ if (ISDIGIT (*p))
+ ns += *p++ - '0';
+ }
+
+ /* Skip excess digits, truncating toward -Infinity. */
+ if (sign < 0)
+ for (; ISDIGIT (*p); p++)
+ if (*p != '0')
+ {
+ ns++;
+ break;
+ }
+ while (ISDIGIT (*p))
+ p++;
+
+ /* Adjust to the timespec convention, which is that
+ tv_nsec is always a positive offset even if tv_sec is
+ negative. */
+ if (sign < 0 && ns)
+ {
+ s--;
+ if (! (s < 0))
+ return '?';
+ ns = BILLION - ns;
+ }
+
+ lvalp->timespec.tv_sec = s;
+ lvalp->timespec.tv_nsec = ns;
+ pc->input = p;
+ return sign ? tSDECIMAL_NUMBER : tUDECIMAL_NUMBER;
+ }
+ else
+ {
+ lvalp->textintval.negative = sign < 0;
+ if (sign < 0)
+ {
+ lvalp->textintval.value = - value;
+ if (0 < lvalp->textintval.value)
+ return '?';
+ }
+ else
+ {
+ lvalp->textintval.value = value;
+ if (lvalp->textintval.value < 0)
+ return '?';
+ }
+ lvalp->textintval.digits = p - pc->input;
+ pc->input = p;
+ return sign ? tSNUMBER : tUNUMBER;
+ }
+ }
+
+ if (isalpha (c))
+ {
+ char buff[20];
+ char *p = buff;
+ table const *tp;
+
+ do
+ {
+ if (p < buff + sizeof buff - 1)
+ *p++ = c;
+ c = *++pc->input;
+ }
+ while (isalpha (c) || c == '.');
+
+ *p = '\0';
+ tp = lookup_word (pc, buff);
+ if (! tp)
+ return '?';
+ lvalp->intval = tp->value;
+ return tp->type;
+ }
+
+ if (c != '(')
+ return *pc->input++;
+ count = 0;
+ do
+ {
+ c = *pc->input++;
+ if (c == '\0')
+ return c;
+ if (c == '(')
+ count++;
+ else if (c == ')')
+ count--;
+ }
+ while (count != 0);
+ }
+}
+
+/* Do nothing if the parser reports an error. */
+static int
+yyerror (parser_control const *pc ATTRIBUTE_UNUSED,
+ char const *s ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+/* If *TM0 is the old and *TM1 is the new value of a struct tm after
+ passing it to mktime, return true if it's OK that mktime returned T.
+ It's not OK if *TM0 has out-of-range members. */
+
+static bool
+mktime_ok (struct tm const *tm0, struct tm const *tm1, time_t t)
+{
+ if (t == (time_t) -1)
+ {
+ /* Guard against falsely reporting an error when parsing a time
+ stamp that happens to equal (time_t) -1, on a host that
+ supports such a time stamp. */
+ tm1 = localtime (&t);
+ if (!tm1)
+ return false;
+ }
+
+ return ! ((tm0->tm_sec ^ tm1->tm_sec)
+ | (tm0->tm_min ^ tm1->tm_min)
+ | (tm0->tm_hour ^ tm1->tm_hour)
+ | (tm0->tm_mday ^ tm1->tm_mday)
+ | (tm0->tm_mon ^ tm1->tm_mon)
+ | (tm0->tm_year ^ tm1->tm_year));
+}
+
+/* A reasonable upper bound for the size of ordinary TZ strings.
+ Use heap allocation if TZ's length exceeds this. */
+enum { TZBUFSIZE = 100 };
+
+/* Return a copy of TZ, stored in TZBUF if it fits, and heap-allocated
+ otherwise. */
+static char *
+get_tz (char tzbuf[TZBUFSIZE])
+{
+ char *tz = getenv ("TZ");
+ if (tz)
+ {
+ size_t tzsize = strlen (tz) + 1;
+ tz = (tzsize <= TZBUFSIZE
+ ? memcpy (tzbuf, tz, tzsize)
+ : xmemdup (tz, tzsize));
+ }
+ return tz;
+}
+
+/* Parse a date/time string, storing the resulting time value into *RESULT.
+ The string itself is pointed to by P. Return true if successful.
+ P can be an incomplete or relative time specification; if so, use
+ *NOW as the basis for the returned time. */
+bool
+get_date (struct timespec *result, char const *p, struct timespec const *now)
+{
+ time_t Start;
+ long int Start_ns;
+ struct tm const *tmp;
+ struct tm tm;
+ struct tm tm0;
+ parser_control pc;
+ struct timespec gettime_buffer;
+ unsigned char c;
+ bool tz_was_altered = false;
+ char *tz0 = NULL;
+ char tz0buf[TZBUFSIZE];
+ bool ok = true;
+
+ if (! now)
+ {
+ gettime (&gettime_buffer);
+ now = &gettime_buffer;
+ }
+
+ Start = now->tv_sec;
+ Start_ns = now->tv_nsec;
+
+ tmp = localtime (&now->tv_sec);
+ if (! tmp)
+ return false;
+
+ while (c = *p, isspace (c))
+ p++;
+
+ if (strncmp (p, "TZ=\"", 4) == 0)
+ {
+ char const *tzbase = p + 4;
+ size_t tzsize = 1;
+ char const *s;
+
+ for (s = tzbase; *s; s++, tzsize++)
+ if (*s == '\\')
+ {
+ s++;
+ if (! (*s == '\\' || *s == '"'))
+ break;
+ }
+ else if (*s == '"')
+ {
+ char *z;
+ char *tz1;
+ char tz1buf[TZBUFSIZE];
+ bool large_tz = TZBUFSIZE < tzsize;
+ bool setenv_ok;
+ tz0 = get_tz (tz0buf);
+ z = tz1 = large_tz ? xmalloc (tzsize) : tz1buf;
+ for (s = tzbase; *s != '"'; s++)
+ *z++ = *(s += *s == '\\');
+ *z = '\0';
+ setenv_ok = setenv ("TZ", tz1, 1) == 0;
+ if (large_tz)
+ free (tz1);
+ if (!setenv_ok)
+ goto fail;
+ tz_was_altered = true;
+ p = s + 1;
+ }
+ }
+
+ pc.input = p;
+ pc.year.value = tmp->tm_year;
+ pc.year.value += TM_YEAR_BASE;
+ pc.year.digits = 0;
+ pc.month = tmp->tm_mon + 1;
+ pc.day = tmp->tm_mday;
+ pc.hour = tmp->tm_hour;
+ pc.minutes = tmp->tm_min;
+ pc.seconds.tv_sec = tmp->tm_sec;
+ pc.seconds.tv_nsec = Start_ns;
+ tm.tm_isdst = tmp->tm_isdst;
+
+ pc.meridian = MER24;
+ pc.rel = RELATIVE_TIME_0;
+ pc.timespec_seen = false;
+ pc.rels_seen = false;
+ pc.dates_seen = 0;
+ pc.days_seen = 0;
+ pc.times_seen = 0;
+ pc.local_zones_seen = 0;
+ pc.dsts_seen = 0;
+ pc.zones_seen = 0;
+
+#if HAVE_STRUCT_TM_TM_ZONE
+ pc.local_time_zone_table[0].name = tmp->tm_zone;
+ pc.local_time_zone_table[0].type = tLOCAL_ZONE;
+ pc.local_time_zone_table[0].value = tmp->tm_isdst;
+ pc.local_time_zone_table[1].name = NULL;
+
+ /* Probe the names used in the next three calendar quarters, looking
+ for a tm_isdst different from the one we already have. */
+ {
+ int quarter;
+ for (quarter = 1; quarter <= 3; quarter++)
+ {
+ time_t probe = Start + quarter * (90 * 24 * 60 * 60);
+ struct tm const *probe_tm = localtime (&probe);
+ if (probe_tm && probe_tm->tm_zone
+ && probe_tm->tm_isdst != pc.local_time_zone_table[0].value)
+ {
+ {
+ pc.local_time_zone_table[1].name = probe_tm->tm_zone;
+ pc.local_time_zone_table[1].type = tLOCAL_ZONE;
+ pc.local_time_zone_table[1].value = probe_tm->tm_isdst;
+ pc.local_time_zone_table[2].name = NULL;
+ }
+ break;
+ }
+ }
+ }
+#else
+#if HAVE_TZNAME
+ {
+# ifndef tzname
+ extern char *tzname[];
+# endif
+ int i;
+ for (i = 0; i < 2; i++)
+ {
+ pc.local_time_zone_table[i].name = tzname[i];
+ pc.local_time_zone_table[i].type = tLOCAL_ZONE;
+ pc.local_time_zone_table[i].value = i;
+ }
+ pc.local_time_zone_table[i].name = NULL;
+ }
+#else
+ pc.local_time_zone_table[0].name = NULL;
+#endif
+#endif
+
+ if (pc.local_time_zone_table[0].name && pc.local_time_zone_table[1].name
+ && ! strcmp (pc.local_time_zone_table[0].name,
+ pc.local_time_zone_table[1].name))
+ {
+ /* This locale uses the same abbrevation for standard and
+ daylight times. So if we see that abbreviation, we don't
+ know whether it's daylight time. */
+ pc.local_time_zone_table[0].value = -1;
+ pc.local_time_zone_table[1].name = NULL;
+ }
+
+ if (yyparse (&pc) != 0)
+ goto fail;
+
+ if (pc.timespec_seen)
+ *result = pc.seconds;
+ else
+ {
+ if (1 < (pc.times_seen | pc.dates_seen | pc.days_seen | pc.dsts_seen
+ | (pc.local_zones_seen + pc.zones_seen)))
+ goto fail;
+
+ tm.tm_year = to_year (pc.year) - TM_YEAR_BASE;
+ tm.tm_mon = pc.month - 1;
+ tm.tm_mday = pc.day;
+ if (pc.times_seen || (pc.rels_seen && ! pc.dates_seen && ! pc.days_seen))
+ {
+ tm.tm_hour = to_hour (pc.hour, pc.meridian);
+ if (tm.tm_hour < 0)
+ goto fail;
+ tm.tm_min = pc.minutes;
+ tm.tm_sec = pc.seconds.tv_sec;
+ }
+ else
+ {
+ tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
+ pc.seconds.tv_nsec = 0;
+ }
+
+ /* Let mktime deduce tm_isdst if we have an absolute time stamp. */
+ if (pc.dates_seen | pc.days_seen | pc.times_seen)
+ tm.tm_isdst = -1;
+
+ /* But if the input explicitly specifies local time with or without
+ DST, give mktime that information. */
+ if (pc.local_zones_seen)
+ tm.tm_isdst = pc.local_isdst;
+
+ tm0 = tm;
+
+ Start = mktime (&tm);
+
+ if (! mktime_ok (&tm0, &tm, Start))
+ {
+ if (! pc.zones_seen)
+ goto fail;
+ else
+ {
+ /* Guard against falsely reporting errors near the time_t
+ boundaries when parsing times in other time zones. For
+ example, suppose the input string "1969-12-31 23:00:00 -0100",
+ the current time zone is 8 hours ahead of UTC, and the min
+ time_t value is 1970-01-01 00:00:00 UTC. Then the min
+ localtime value is 1970-01-01 08:00:00, and mktime will
+ therefore fail on 1969-12-31 23:00:00. To work around the
+ problem, set the time zone to 1 hour behind UTC temporarily
+ by setting TZ="XXX1:00" and try mktime again. */
+
+ long int time_zone = pc.time_zone;
+ long int abs_time_zone = time_zone < 0 ? - time_zone : time_zone;
+ long int abs_time_zone_hour = abs_time_zone / 60;
+ int abs_time_zone_min = abs_time_zone % 60;
+ char tz1buf[sizeof "XXX+0:00"
+ + sizeof pc.time_zone * CHAR_BIT / 3];
+ if (!tz_was_altered)
+ tz0 = get_tz (tz0buf);
+ sprintf (tz1buf, "XXX%s%ld:%02d", "-" + (time_zone < 0),
+ abs_time_zone_hour, abs_time_zone_min);
+ if (setenv ("TZ", tz1buf, 1) != 0)
+ goto fail;
+ tz_was_altered = true;
+ tm = tm0;
+ Start = mktime (&tm);
+ if (! mktime_ok (&tm0, &tm, Start))
+ goto fail;
+ }
+ }
+
+ if (pc.days_seen && ! pc.dates_seen)
+ {
+ tm.tm_mday += ((pc.day_number - tm.tm_wday + 7) % 7
+ + 7 * (pc.day_ordinal - (0 < pc.day_ordinal)));
+ tm.tm_isdst = -1;
+ Start = mktime (&tm);
+ if (Start == (time_t) -1)
+ goto fail;
+ }
+
+ if (pc.zones_seen)
+ {
+ long int delta = pc.time_zone * 60;
+ time_t t1;
+#ifdef HAVE_TM_GMTOFF
+ delta -= tm.tm_gmtoff;
+#else
+ time_t t = Start;
+ struct tm const *gmt = gmtime (&t);
+ if (! gmt)
+ goto fail;
+ delta -= tm_diff (&tm, gmt);
+#endif
+ t1 = Start - delta;
+ if ((Start < t1) != (delta < 0))
+ goto fail; /* time_t overflow */
+ Start = t1;
+ }
+
+ /* Add relative date. */
+ if (pc.rel.year | pc.rel.month | pc.rel.day)
+ {
+ int year = tm.tm_year + pc.rel.year;
+ int month = tm.tm_mon + pc.rel.month;
+ int day = tm.tm_mday + pc.rel.day;
+ if (((year < tm.tm_year) ^ (pc.rel.year < 0))
+ | ((month < tm.tm_mon) ^ (pc.rel.month < 0))
+ | ((day < tm.tm_mday) ^ (pc.rel.day < 0)))
+ goto fail;
+ tm.tm_year = year;
+ tm.tm_mon = month;
+ tm.tm_mday = day;
+ tm.tm_hour = tm0.tm_hour;
+ tm.tm_min = tm0.tm_min;
+ tm.tm_sec = tm0.tm_sec;
+ tm.tm_isdst = tm0.tm_isdst;
+ Start = mktime (&tm);
+ if (Start == (time_t) -1)
+ goto fail;
+ }
+
+ /* Add relative hours, minutes, and seconds. On hosts that support
+ leap seconds, ignore the possibility of leap seconds; e.g.,
+ "+ 10 minutes" adds 600 seconds, even if one of them is a
+ leap second. Typically this is not what the user wants, but it's
+ too hard to do it the other way, because the time zone indicator
+ must be applied before relative times, and if mktime is applied
+ again the time zone will be lost. */
+ {
+ long int sum_ns = pc.seconds.tv_nsec + pc.rel.ns;
+ long int normalized_ns = (sum_ns % BILLION + BILLION) % BILLION;
+ time_t t0 = Start;
+ long int d1 = 60 * 60 * pc.rel.hour;
+ time_t t1 = t0 + d1;
+ long int d2 = 60 * pc.rel.minutes;
+ time_t t2 = t1 + d2;
+ long int d3 = pc.rel.seconds;
+ time_t t3 = t2 + d3;
+ long int d4 = (sum_ns - normalized_ns) / BILLION;
+ time_t t4 = t3 + d4;
+
+ if ((d1 / (60 * 60) ^ pc.rel.hour)
+ | (d2 / 60 ^ pc.rel.minutes)
+ | ((t1 < t0) ^ (d1 < 0))
+ | ((t2 < t1) ^ (d2 < 0))
+ | ((t3 < t2) ^ (d3 < 0))
+ | ((t4 < t3) ^ (d4 < 0)))
+ goto fail;
+
+ result->tv_sec = t4;
+ result->tv_nsec = normalized_ns;
+ }
+ }
+
+ goto done;
+
+ fail:
+ ok = false;
+ done:
+ if (tz_was_altered)
+ ok &= (tz0 ? setenv ("TZ", tz0, 1) : unsetenv ("TZ")) == 0;
+ if (tz0 != tz0buf)
+ free (tz0);
+ return ok;
+}
+
+#if TEST
+
+int
+main (int ac, char **av)
+{
+ char buff[BUFSIZ];
+
+ printf ("Enter date, or blank line to exit.\n\t> ");
+ fflush (stdout);
+
+ buff[BUFSIZ - 1] = '\0';
+ while (fgets (buff, BUFSIZ - 1, stdin) && buff[0])
+ {
+ struct timespec d;
+ struct tm const *tm;
+ if (! get_date (&d, buff, NULL))
+ printf ("Bad format - couldn't convert.\n");
+ else if (! (tm = localtime (&d.tv_sec)))
+ {
+ long int sec = d.tv_sec;
+ printf ("localtime (%ld) failed\n", sec);
+ }
+ else
+ {
+ int ns = d.tv_nsec;
+ printf ("%04ld-%02d-%02d %02d:%02d:%02d.%09d\n",
+ tm->tm_year + 1900L, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec, ns);
+ }
+ printf ("\t> ");
+ fflush (stdout);
+ }
+ return 0;
+}
+#endif /* TEST */
diff --git a/lib/getopt.c b/lib/getopt.c
new file mode 100644
index 0000000..3580ad8
--- /dev/null
+++ b/lib/getopt.c
@@ -0,0 +1,1191 @@
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "Keep this file name-space clean" means, talk to drepper@gnu.org
+ before changing it!
+ Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004,2006
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+#include "getopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef __VMS
+# include <unixlib.h>
+#endif
+
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "gettext.h"
+# define _(msgid) gettext (msgid)
+#endif
+
+#if defined _LIBC && defined USE_IN_LIBIO
+# include <wchar.h>
+#endif
+
+#ifndef attribute_hidden
+# define attribute_hidden
+#endif
+
+/* Unlike standard Unix `getopt', functions like `getopt_long'
+ let the user intersperse the options with the other arguments.
+
+ As `getopt_long' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Using `getopt' or setting the environment variable POSIXLY_CORRECT
+ disables permutation.
+ Then the application's behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "getopt_int.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+/* 1003.2 says this must be 1 before any call. */
+int optind = 1;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+ This must be initialized on some systems to avoid linking in the
+ system's own getopt implementation. */
+
+int optopt = '?';
+
+/* Keep a global copy of all internal members of getopt_data. */
+
+static struct _getopt_data getopt_data;
+
+
+#if defined HAVE_DECL_GETENV && !HAVE_DECL_GETENV
+extern char *getenv ();
+#endif
+
+#ifdef _LIBC
+/* Stored original parameters.
+ XXX This is no good solution. We should rather copy the args so
+ that we can compare them later. But we must not use malloc(3). */
+extern int __libc_argc;
+extern char **__libc_argv;
+
+/* Bash 2.0 gives us an environment variable containing flags
+ indicating ARGV elements that should not be considered arguments. */
+
+# ifdef USE_NONOPTION_FLAGS
+/* Defined in getopt_init.c */
+extern char *__getopt_nonoption_flags;
+# endif
+
+# ifdef USE_NONOPTION_FLAGS
+# define SWAP_FLAGS(ch1, ch2) \
+ if (d->__nonoption_flags_len > 0) \
+ { \
+ char __tmp = __getopt_nonoption_flags[ch1]; \
+ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
+ __getopt_nonoption_flags[ch2] = __tmp; \
+ }
+# else
+# define SWAP_FLAGS(ch1, ch2)
+# endif
+#else /* !_LIBC */
+# define SWAP_FLAGS(ch1, ch2)
+#endif /* _LIBC */
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+static void
+exchange (char **argv, struct _getopt_data *d)
+{
+ int bottom = d->__first_nonopt;
+ int middle = d->__last_nonopt;
+ int top = d->optind;
+ char *tem;
+
+ /* Exchange the shorter segment with the far end of the longer segment.
+ That puts the shorter segment into the right place.
+ It leaves the longer segment in the right place overall,
+ but it consists of two parts that need to be swapped next. */
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+ /* First make sure the handling of the `__getopt_nonoption_flags'
+ string can work normally. Our top argument must be in the range
+ of the string. */
+ if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len)
+ {
+ /* We must extend the array. The user plays games with us and
+ presents new arguments. */
+ char *new_str = malloc (top + 1);
+ if (new_str == NULL)
+ d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0;
+ else
+ {
+ memset (__mempcpy (new_str, __getopt_nonoption_flags,
+ d->__nonoption_flags_max_len),
+ '\0', top + 1 - d->__nonoption_flags_max_len);
+ d->__nonoption_flags_max_len = top + 1;
+ __getopt_nonoption_flags = new_str;
+ }
+ }
+#endif
+
+ while (top > middle && middle > bottom)
+ {
+ if (top - middle > middle - bottom)
+ {
+ /* Bottom segment is the short one. */
+ int len = middle - bottom;
+ register int i;
+
+ /* Swap it with the top part of the top segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[top - (middle - bottom) + i];
+ argv[top - (middle - bottom) + i] = tem;
+ SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
+ }
+ /* Exclude the moved bottom segment from further swapping. */
+ top -= len;
+ }
+ else
+ {
+ /* Top segment is the short one. */
+ int len = top - middle;
+ register int i;
+
+ /* Swap it with the bottom part of the bottom segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[middle + i];
+ argv[middle + i] = tem;
+ SWAP_FLAGS (bottom + i, middle + i);
+ }
+ /* Exclude the moved top segment from further swapping. */
+ bottom += len;
+ }
+ }
+
+ /* Update records for the slots the non-options now occupy. */
+
+ d->__first_nonopt += (d->optind - d->__last_nonopt);
+ d->__last_nonopt = d->optind;
+}
+
+/* Initialize the internal data when the first call is made. */
+
+static const char *
+_getopt_initialize (int argc, char **argv, const char *optstring,
+ int posixly_correct, struct _getopt_data *d)
+{
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ d->__first_nonopt = d->__last_nonopt = d->optind;
+
+ d->__nextchar = NULL;
+
+ d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT");
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ d->__ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ d->__ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (d->__posixly_correct)
+ d->__ordering = REQUIRE_ORDER;
+ else
+ d->__ordering = PERMUTE;
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+ if (!d->__posixly_correct
+ && argc == __libc_argc && argv == __libc_argv)
+ {
+ if (d->__nonoption_flags_max_len == 0)
+ {
+ if (__getopt_nonoption_flags == NULL
+ || __getopt_nonoption_flags[0] == '\0')
+ d->__nonoption_flags_max_len = -1;
+ else
+ {
+ const char *orig_str = __getopt_nonoption_flags;
+ int len = d->__nonoption_flags_max_len = strlen (orig_str);
+ if (d->__nonoption_flags_max_len < argc)
+ d->__nonoption_flags_max_len = argc;
+ __getopt_nonoption_flags =
+ (char *) malloc (d->__nonoption_flags_max_len);
+ if (__getopt_nonoption_flags == NULL)
+ d->__nonoption_flags_max_len = -1;
+ else
+ memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
+ '\0', d->__nonoption_flags_max_len - len);
+ }
+ }
+ d->__nonoption_flags_len = d->__nonoption_flags_max_len;
+ }
+ else
+ d->__nonoption_flags_len = 0;
+#endif
+
+ return optstring;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns -1.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options.
+
+ If POSIXLY_CORRECT is nonzero, behave as if the POSIXLY_CORRECT
+ environment variable were set. */
+
+int
+_getopt_internal_r (int argc, char **argv, const char *optstring,
+ const struct option *longopts, int *longind,
+ int long_only, int posixly_correct, struct _getopt_data *d)
+{
+ int print_errors = d->opterr;
+ if (optstring[0] == ':')
+ print_errors = 0;
+
+ if (argc < 1)
+ return -1;
+
+ d->optarg = NULL;
+
+ if (d->optind == 0 || !d->__initialized)
+ {
+ if (d->optind == 0)
+ d->optind = 1; /* Don't scan ARGV[0], the program name. */
+ optstring = _getopt_initialize (argc, argv, optstring,
+ posixly_correct, d);
+ d->__initialized = 1;
+ }
+
+ /* Test whether ARGV[optind] points to a non-option argument.
+ Either it does not have option syntax, or there is an environment flag
+ from the shell indicating it is not an option. The later information
+ is only used when the used in the GNU libc. */
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \
+ || (d->optind < d->__nonoption_flags_len \
+ && __getopt_nonoption_flags[d->optind] == '1'))
+#else
+# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')
+#endif
+
+ if (d->__nextchar == NULL || *d->__nextchar == '\0')
+ {
+ /* Advance to the next ARGV-element. */
+
+ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+ moved back by the user (who may also have changed the arguments). */
+ if (d->__last_nonopt > d->optind)
+ d->__last_nonopt = d->optind;
+ if (d->__first_nonopt > d->optind)
+ d->__first_nonopt = d->optind;
+
+ if (d->__ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (d->__first_nonopt != d->__last_nonopt
+ && d->__last_nonopt != d->optind)
+ exchange ((char **) argv, d);
+ else if (d->__last_nonopt != d->optind)
+ d->__first_nonopt = d->optind;
+
+ /* Skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (d->optind < argc && NONOPTION_P)
+ d->optind++;
+ d->__last_nonopt = d->optind;
+ }
+
+ /* The special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (d->optind != argc && !strcmp (argv[d->optind], "--"))
+ {
+ d->optind++;
+
+ if (d->__first_nonopt != d->__last_nonopt
+ && d->__last_nonopt != d->optind)
+ exchange ((char **) argv, d);
+ else if (d->__first_nonopt == d->__last_nonopt)
+ d->__first_nonopt = d->optind;
+ d->__last_nonopt = argc;
+
+ d->optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (d->optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (d->__first_nonopt != d->__last_nonopt)
+ d->optind = d->__first_nonopt;
+ return -1;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if (NONOPTION_P)
+ {
+ if (d->__ordering == REQUIRE_ORDER)
+ return -1;
+ d->optarg = argv[d->optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Skip the initial punctuation. */
+
+ d->__nextchar = (argv[d->optind] + 1
+ + (longopts != NULL && argv[d->optind][1] == '-'));
+ }
+
+ /* Decode the current option-ARGV-element. */
+
+ /* Check whether the ARGV-element is a long option.
+
+ If long_only and the ARGV-element has the form "-f", where f is
+ a valid short option, don't consider it an abbreviated form of
+ a long option that starts with f. Otherwise there would be no
+ way to give the -f short option.
+
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an abbreviation of
+ the long option, just like "--fu", and not "-f" with arg "u".
+
+ This distinction seems to be the most useful approach. */
+
+ if (longopts != NULL
+ && (argv[d->optind][1] == '-'
+ || (long_only && (argv[d->optind][2]
+ || !strchr (optstring, argv[d->optind][1])))))
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = -1;
+ int option_index;
+
+ for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
+ {
+ if ((unsigned int) (nameend - d->__nextchar)
+ == (unsigned int) strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else if (long_only
+ || pfound->has_arg != p->has_arg
+ || pfound->flag != p->flag
+ || pfound->val != p->val)
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (print_errors)
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"),
+ argv[0], argv[d->optind]) >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+ __fxprintf (NULL, "%s", buf);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
+ argv[0], argv[d->optind]);
+#endif
+ }
+ d->__nextchar += strlen (d->__nextchar);
+ d->optind++;
+ d->optopt = 0;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ d->optind++;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ d->optarg = nameend + 1;
+ else
+ {
+ if (print_errors)
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+ int n;
+#endif
+
+ if (argv[d->optind - 1][1] == '-')
+ {
+ /* --option */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("\
+%s: option `--%s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+#else
+ fprintf (stderr, _("\
+%s: option `--%s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+#endif
+ }
+ else
+ {
+ /* +option or -option */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("\
+%s: option `%c%s' doesn't allow an argument\n"),
+ argv[0], argv[d->optind - 1][0],
+ pfound->name);
+#else
+ fprintf (stderr, _("\
+%s: option `%c%s' doesn't allow an argument\n"),
+ argv[0], argv[d->optind - 1][0],
+ pfound->name);
+#endif
+ }
+
+#if defined _LIBC && defined USE_IN_LIBIO
+ if (n >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2
+ |= _IO_FLAGS2_NOTCANCEL;
+
+ __fxprintf (NULL, "%s", buf);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#endif
+ }
+
+ d->__nextchar += strlen (d->__nextchar);
+
+ d->optopt = pfound->val;
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (d->optind < argc)
+ d->optarg = argv[d->optind++];
+ else
+ {
+ if (print_errors)
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("\
+%s: option `%s' requires an argument\n"),
+ argv[0], argv[d->optind - 1]) >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2
+ |= _IO_FLAGS2_NOTCANCEL;
+
+ __fxprintf (NULL, "%s", buf);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[d->optind - 1]);
+#endif
+ }
+ d->__nextchar += strlen (d->__nextchar);
+ d->optopt = pfound->val;
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ d->__nextchar += strlen (d->__nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[d->optind][1] == '-'
+ || strchr (optstring, *d->__nextchar) == NULL)
+ {
+ if (print_errors)
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+ int n;
+#endif
+
+ if (argv[d->optind][1] == '-')
+ {
+ /* --option */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"),
+ argv[0], d->__nextchar);
+#else
+ fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
+ argv[0], d->__nextchar);
+#endif
+ }
+ else
+ {
+ /* +option or -option */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"),
+ argv[0], argv[d->optind][0], d->__nextchar);
+#else
+ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
+ argv[0], argv[d->optind][0], d->__nextchar);
+#endif
+ }
+
+#if defined _LIBC && defined USE_IN_LIBIO
+ if (n >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+ __fxprintf (NULL, "%s", buf);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#endif
+ }
+ d->__nextchar = (char *) "";
+ d->optind++;
+ d->optopt = 0;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next short option-character. */
+
+ {
+ char c = *d->__nextchar++;
+ char *temp = strchr (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*d->__nextchar == '\0')
+ ++d->optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (print_errors)
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+ int n;
+#endif
+
+ if (d->__posixly_correct)
+ {
+ /* 1003.2 specifies the format of this message. */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("%s: illegal option -- %c\n"),
+ argv[0], c);
+#else
+ fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c);
+#endif
+ }
+ else
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("%s: invalid option -- %c\n"),
+ argv[0], c);
+#else
+ fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c);
+#endif
+ }
+
+#if defined _LIBC && defined USE_IN_LIBIO
+ if (n >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+ __fxprintf (NULL, "%s", buf);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#endif
+ }
+ d->optopt = c;
+ return '?';
+ }
+ /* Convenience. Treat POSIX -W foo same as long option --foo */
+ if (temp[0] == 'W' && temp[1] == ';')
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = 0;
+ int option_index;
+
+ /* This is an option that requires an argument. */
+ if (*d->__nextchar != '\0')
+ {
+ d->optarg = d->__nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ d->optind++;
+ }
+ else if (d->optind == argc)
+ {
+ if (print_errors)
+ {
+ /* 1003.2 specifies the format of this message. */
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf,
+ _("%s: option requires an argument -- %c\n"),
+ argv[0], c) >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+ __fxprintf (NULL, "%s", buf);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr, _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+#endif
+ }
+ d->optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ return c;
+ }
+ else
+ /* We already incremented `d->optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ d->optarg = argv[d->optind++];
+
+ /* optarg is now the argument, see if it's in the
+ table of longopts. */
+
+ for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '=';
+ nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
+ {
+ if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+ if (ambig && !exact)
+ {
+ if (print_errors)
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"),
+ argv[0], argv[d->optind]) >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+ __fxprintf (NULL, "%s", buf);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
+ argv[0], argv[d->optind]);
+#endif
+ }
+ d->__nextchar += strlen (d->__nextchar);
+ d->optind++;
+ return '?';
+ }
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ d->optarg = nameend + 1;
+ else
+ {
+ if (print_errors)
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+ argv[0], pfound->name) >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2
+ |= _IO_FLAGS2_NOTCANCEL;
+
+ __fxprintf (NULL, "%s", buf);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+#endif
+ }
+
+ d->__nextchar += strlen (d->__nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (d->optind < argc)
+ d->optarg = argv[d->optind++];
+ else
+ {
+ if (print_errors)
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("\
+%s: option `%s' requires an argument\n"),
+ argv[0], argv[d->optind - 1]) >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2
+ |= _IO_FLAGS2_NOTCANCEL;
+
+ __fxprintf (NULL, "%s", buf);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[d->optind - 1]);
+#endif
+ }
+ d->__nextchar += strlen (d->__nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ d->__nextchar += strlen (d->__nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+ d->__nextchar = NULL;
+ return 'W'; /* Let the application handle it. */
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*d->__nextchar != '\0')
+ {
+ d->optarg = d->__nextchar;
+ d->optind++;
+ }
+ else
+ d->optarg = NULL;
+ d->__nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*d->__nextchar != '\0')
+ {
+ d->optarg = d->__nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ d->optind++;
+ }
+ else if (d->optind == argc)
+ {
+ if (print_errors)
+ {
+ /* 1003.2 specifies the format of this message. */
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("\
+%s: option requires an argument -- %c\n"),
+ argv[0], c) >= 0)
+ {
+ _IO_flockfile (stderr);
+
+ int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+ ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+ __fxprintf (NULL, "%s", buf);
+
+ ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+ _IO_funlockfile (stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr,
+ _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+#endif
+ }
+ d->optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ d->optarg = argv[d->optind++];
+ d->__nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+_getopt_internal (int argc, char **argv, const char *optstring,
+ const struct option *longopts, int *longind,
+ int long_only, int posixly_correct)
+{
+ int result;
+
+ getopt_data.optind = optind;
+ getopt_data.opterr = opterr;
+
+ result = _getopt_internal_r (argc, argv, optstring, longopts, longind,
+ long_only, posixly_correct, &getopt_data);
+
+ optind = getopt_data.optind;
+ optarg = getopt_data.optarg;
+ optopt = getopt_data.optopt;
+
+ return result;
+}
+
+/* glibc gets a LSB-compliant getopt.
+ Standalone applications get a POSIX-compliant getopt. */
+#if _LIBC
+enum { POSIXLY_CORRECT = 0 };
+#else
+enum { POSIXLY_CORRECT = 1 };
+#endif
+
+int
+getopt (int argc, char *const *argv, const char *optstring)
+{
+ return _getopt_internal (argc, (char **) argv, optstring, NULL, NULL, 0,
+ POSIXLY_CORRECT);
+}
+
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (int argc, char **argv)
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/lib/getopt1.c b/lib/getopt1.c
new file mode 100644
index 0000000..cc0746e
--- /dev/null
+++ b/lib/getopt1.c
@@ -0,0 +1,171 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+ Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004,2006
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef _LIBC
+# include <getopt.h>
+#else
+# include <config.h>
+# include "getopt.h"
+#endif
+#include "getopt_int.h"
+
+#include <stdio.h>
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (int argc, char *__getopt_argv_const *argv, const char *options,
+ const struct option *long_options, int *opt_index)
+{
+ return _getopt_internal (argc, (char **) argv, options, long_options,
+ opt_index, 0, 0);
+}
+
+int
+_getopt_long_r (int argc, char **argv, const char *options,
+ const struct option *long_options, int *opt_index,
+ struct _getopt_data *d)
+{
+ return _getopt_internal_r (argc, argv, options, long_options, opt_index,
+ 0, 0, d);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+ If an option that starts with '-' (not '--') doesn't match a long option,
+ but does match a short option, it is parsed as a short option
+ instead. */
+
+int
+getopt_long_only (int argc, char *__getopt_argv_const *argv,
+ const char *options,
+ const struct option *long_options, int *opt_index)
+{
+ return _getopt_internal (argc, (char **) argv, options, long_options,
+ opt_index, 1, 0);
+}
+
+int
+_getopt_long_only_r (int argc, char **argv, const char *options,
+ const struct option *long_options, int *opt_index,
+ struct _getopt_data *d)
+{
+ return _getopt_internal_r (argc, argv, options, long_options, opt_index,
+ 1, 0, d);
+}
+
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"add", 1, 0, 0},
+ {"append", 0, 0, 0},
+ {"delete", 1, 0, 0},
+ {"verbose", 0, 0, 0},
+ {"create", 0, 0, 0},
+ {"file", 1, 0, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long (argc, argv, "abc:d:0123456789",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case 0:
+ printf ("option %s", long_options[option_index].name);
+ if (optarg)
+ printf (" with arg %s", optarg);
+ printf ("\n");
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case 'd':
+ printf ("option d with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/lib/getopt_.h b/lib/getopt_.h
new file mode 100644
index 0000000..615ef9a
--- /dev/null
+++ b/lib/getopt_.h
@@ -0,0 +1,226 @@
+/* Declarations for getopt.
+ Copyright (C) 1989-1994,1996-1999,2001,2003,2004,2005,2006,2007
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _GETOPT_H
+
+#ifndef __need_getopt
+# define _GETOPT_H 1
+#endif
+
+/* Standalone applications should #define __GETOPT_PREFIX to an
+ identifier that prefixes the external functions and variables
+ defined in this header. When this happens, include the
+ headers that might declare getopt so that they will not cause
+ confusion if included after this file. Then systematically rename
+ identifiers so that they do not collide with the system functions
+ and variables. Renaming avoids problems with some compilers and
+ linkers. */
+#if defined __GETOPT_PREFIX && !defined __need_getopt
+# include <stdlib.h>
+# include <stdio.h>
+# include <unistd.h>
+# undef __need_getopt
+# undef getopt
+# undef getopt_long
+# undef getopt_long_only
+# undef optarg
+# undef opterr
+# undef optind
+# undef optopt
+# define __GETOPT_CONCAT(x, y) x ## y
+# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y)
+# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y)
+# define getopt __GETOPT_ID (getopt)
+# define getopt_long __GETOPT_ID (getopt_long)
+# define getopt_long_only __GETOPT_ID (getopt_long_only)
+# define optarg __GETOPT_ID (optarg)
+# define opterr __GETOPT_ID (opterr)
+# define optind __GETOPT_ID (optind)
+# define optopt __GETOPT_ID (optopt)
+#endif
+
+/* Standalone applications get correct prototypes for getopt_long and
+ getopt_long_only; they declare "char **argv". libc uses prototypes
+ with "char *const *argv" that are incorrect because getopt_long and
+ getopt_long_only can permute argv; this is required for backward
+ compatibility (e.g., for LSB 2.0.1).
+
+ This used to be `#if defined __GETOPT_PREFIX && !defined __need_getopt',
+ but it caused redefinition warnings if both unistd.h and getopt.h were
+ included, since unistd.h includes getopt.h having previously defined
+ __need_getopt.
+
+ The only place where __getopt_argv_const is used is in definitions
+ of getopt_long and getopt_long_only below, but these are visible
+ only if __need_getopt is not defined, so it is quite safe to rewrite
+ the conditional as follows:
+*/
+#if !defined __need_getopt
+# if defined __GETOPT_PREFIX
+# define __getopt_argv_const /* empty */
+# else
+# define __getopt_argv_const const
+# endif
+#endif
+
+/* If __GNU_LIBRARY__ is not already defined, either we are being used
+ standalone, or this is the first header included in the source file.
+ If we are being used with glibc, we need to include <features.h>, but
+ that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
+ not defined, include <ctype.h>, which will pull in <features.h> for us
+ if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
+ doesn't flood the namespace with stuff the way some other headers do.) */
+#if !defined __GNU_LIBRARY__
+# include <ctype.h>
+#endif
+
+#ifndef __THROW
+# ifndef __GNUC_PREREQ
+# define __GNUC_PREREQ(maj, min) (0)
+# endif
+# if defined __cplusplus && __GNUC_PREREQ (2,8)
+# define __THROW throw ()
+# else
+# define __THROW
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized. */
+
+extern int optopt;
+
+#ifndef __need_getopt
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+ const char *name;
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+# define no_argument 0
+# define required_argument 1
+# define optional_argument 2
+#endif /* need getopt */
+
+
+/* Get definitions and prototypes for functions to process the
+ arguments in ARGV (ARGC of them, minus the program name) for
+ options given in OPTS.
+
+ Return the option character from OPTS just read. Return -1 when
+ there are no more options. For unrecognized options, or options
+ missing arguments, `optopt' is set to the option letter, and '?' is
+ returned.
+
+ The OPTS string is a list of characters which are recognized option
+ letters, optionally followed by colons, specifying that that letter
+ takes an argument, to be placed in `optarg'.
+
+ If a letter in OPTS is followed by two colons, its argument is
+ optional. This behavior is specific to the GNU `getopt'.
+
+ The argument `--' causes premature termination of argument
+ scanning, explicitly telling `getopt' that there are no more
+ options.
+
+ If OPTS begins with `-', then non-option arguments are treated as
+ arguments to the option '\1'. This behavior is specific to the GNU
+ `getopt'. If OPTS begins with `+', or POSIXLY_CORRECT is set in
+ the environment, then do not permute arguments. */
+
+extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
+ __THROW;
+
+#ifndef __need_getopt
+extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind)
+ __THROW;
+extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind)
+ __THROW;
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Make sure we later can get all the definitions and declarations. */
+#undef __need_getopt
+
+#endif /* getopt.h */
diff --git a/lib/getopt_int.h b/lib/getopt_int.h
new file mode 100644
index 0000000..401579f
--- /dev/null
+++ b/lib/getopt_int.h
@@ -0,0 +1,131 @@
+/* Internal declarations for getopt.
+ Copyright (C) 1989-1994,1996-1999,2001,2003,2004
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _GETOPT_INT_H
+#define _GETOPT_INT_H 1
+
+extern int _getopt_internal (int ___argc, char **___argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind,
+ int __long_only, int __posixly_correct);
+
+
+/* Reentrant versions which can handle parsing multiple argument
+ vectors at the same time. */
+
+/* Data type for reentrant functions. */
+struct _getopt_data
+{
+ /* These have exactly the same meaning as the corresponding global
+ variables, except that they are used for the reentrant
+ versions of getopt. */
+ int optind;
+ int opterr;
+ int optopt;
+ char *optarg;
+
+ /* Internal members. */
+
+ /* True if the internal members have been initialized. */
+ int __initialized;
+
+ /* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+ char *__nextchar;
+
+ /* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters, or by calling getopt.
+
+ PERMUTE is the default. We permute the contents of ARGV as we
+ scan, so that eventually all the non-options are at the end.
+ This allows options to be given in any order, even with programs
+ that were not written to expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were
+ written to expect options and other ARGV-elements in any order
+ and that care about the ordering of the two. We describe each
+ non-option ARGV-element as if it were the argument of an option
+ with character code 1. Using `-' as the first character of the
+ list of option characters selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return -1 with `optind' != ARGC. */
+
+ enum
+ {
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+ } __ordering;
+
+ /* If the POSIXLY_CORRECT environment variable is set
+ or getopt was called. */
+ int __posixly_correct;
+
+
+ /* Handle permutation of arguments. */
+
+ /* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first
+ of them; `last_nonopt' is the index after the last of them. */
+
+ int __first_nonopt;
+ int __last_nonopt;
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+ int __nonoption_flags_max_len;
+ int __nonoption_flags_len;
+# endif
+};
+
+/* The initializer is necessary to set OPTIND and OPTERR to their
+ default values and to clear the initialization flag. */
+#define _GETOPT_DATA_INITIALIZER { 1, 1 }
+
+extern int _getopt_internal_r (int ___argc, char **___argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind,
+ int __long_only, int __posixly_correct,
+ struct _getopt_data *__data);
+
+extern int _getopt_long_r (int ___argc, char **___argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind,
+ struct _getopt_data *__data);
+
+extern int _getopt_long_only_r (int ___argc, char **___argv,
+ const char *__shortopts,
+ const struct option *__longopts,
+ int *__longind,
+ struct _getopt_data *__data);
+
+#endif /* getopt_int.h */
diff --git a/lib/gettext.h b/lib/gettext.h
new file mode 100644
index 0000000..9d76ec9
--- /dev/null
+++ b/lib/gettext.h
@@ -0,0 +1,270 @@
+/* Convenience header for conditional use of GNU <libintl.h>.
+ Copyright (C) 1995-1998, 2000-2002, 2004-2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _LIBGETTEXT_H
+#define _LIBGETTEXT_H 1
+
+/* NLS can be disabled through the configure --disable-nls option. */
+#if ENABLE_NLS
+
+/* Get declarations of GNU message catalog functions. */
+# include <libintl.h>
+
+/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
+ the gettext() and ngettext() macros. This is an alternative to calling
+ textdomain(), and is useful for libraries. */
+# ifdef DEFAULT_TEXT_DOMAIN
+# undef gettext
+# define gettext(Msgid) \
+ dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
+# undef ngettext
+# define ngettext(Msgid1, Msgid2, N) \
+ dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
+# endif
+
+#else
+
+/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
+ chokes if dcgettext is defined as a macro. So include it now, to make
+ later inclusions of <locale.h> a NOP. We don't include <libintl.h>
+ as well because people using "gettext.h" will not include <libintl.h>,
+ and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
+ is OK. */
+#if defined(__sun)
+# include <locale.h>
+#endif
+
+/* Many header files from the libstdc++ coming with g++ 3.3 or newer include
+ <libintl.h>, which chokes if dcgettext is defined as a macro. So include
+ it now, to make later inclusions of <libintl.h> a NOP. */
+#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
+# include <cstdlib>
+# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H
+# include <libintl.h>
+# endif
+#endif
+
+/* Disabled NLS.
+ The casts to 'const char *' serve the purpose of producing warnings
+ for invalid uses of the value returned from these functions.
+ On pre-ANSI systems without 'const', the config.h file is supposed to
+ contain "#define const". */
+# define gettext(Msgid) ((const char *) (Msgid))
+# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
+# define dcgettext(Domainname, Msgid, Category) \
+ ((void) (Category), dgettext (Domainname, Msgid))
+# define ngettext(Msgid1, Msgid2, N) \
+ ((N) == 1 \
+ ? ((void) (Msgid2), (const char *) (Msgid1)) \
+ : ((void) (Msgid1), (const char *) (Msgid2)))
+# define dngettext(Domainname, Msgid1, Msgid2, N) \
+ ((void) (Domainname), ngettext (Msgid1, Msgid2, N))
+# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+ ((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) \
+ ((void) (Domainname), (const char *) (Dirname))
+# define bind_textdomain_codeset(Domainname, Codeset) \
+ ((void) (Domainname), (const char *) (Codeset))
+
+#endif
+
+/* A pseudo function call that serves as a marker for the automated
+ extraction of messages, but does not call gettext(). The run-time
+ translation is done at a different place in the code.
+ The argument, String, should be a literal string. Concatenated strings
+ and other string expressions won't work.
+ The macro's expansion is not parenthesized, so that it is suitable as
+ initializer for static 'char[]' or 'const char[]' variables. */
+#define gettext_noop(String) String
+
+/* The separator between msgctxt and msgid in a .mo file. */
+#define GETTEXT_CONTEXT_GLUE "\004"
+
+/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
+ MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be
+ short and rarely need to change.
+ The letter 'p' stands for 'particular' or 'special'. */
+#ifdef DEFAULT_TEXT_DOMAIN
+# define pgettext(Msgctxt, Msgid) \
+ pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
+#else
+# define pgettext(Msgctxt, Msgid) \
+ pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
+#endif
+#define dpgettext(Domainname, Msgctxt, Msgid) \
+ pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
+#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
+ pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
+#ifdef DEFAULT_TEXT_DOMAIN
+# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
+ npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
+#else
+# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
+ npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
+#endif
+#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
+ npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
+#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
+ npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static const char *
+pgettext_aux (const char *domain,
+ const char *msg_ctxt_id, const char *msgid,
+ int category)
+{
+ const char *translation = dcgettext (domain, msg_ctxt_id, category);
+ if (translation == msg_ctxt_id)
+ return msgid;
+ else
+ return translation;
+}
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static const char *
+npgettext_aux (const char *domain,
+ const char *msg_ctxt_id, const char *msgid,
+ const char *msgid_plural, unsigned long int n,
+ int category)
+{
+ const char *translation =
+ dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
+ if (translation == msg_ctxt_id || translation == msgid_plural)
+ return (n == 1 ? msgid : msgid_plural);
+ else
+ return translation;
+}
+
+/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID
+ can be arbitrary expressions. But for string literals these macros are
+ less efficient than those above. */
+
+#include <string.h>
+
+#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \
+ (((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \
+ /* || __STDC_VERSION__ >= 199901L */ )
+
+#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+#include <stdlib.h>
+#endif
+
+#define pgettext_expr(Msgctxt, Msgid) \
+ dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
+#define dpgettext_expr(Domainname, Msgctxt, Msgid) \
+ dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static const char *
+dcpgettext_expr (const char *domain,
+ const char *msgctxt, const char *msgid,
+ int category)
+{
+ size_t msgctxt_len = strlen (msgctxt) + 1;
+ size_t msgid_len = strlen (msgid) + 1;
+ const char *translation;
+#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+ char msg_ctxt_id[msgctxt_len + msgid_len];
+#else
+ char buf[1024];
+ char *msg_ctxt_id =
+ (msgctxt_len + msgid_len <= sizeof (buf)
+ ? buf
+ : (char *) malloc (msgctxt_len + msgid_len));
+ if (msg_ctxt_id != NULL)
+#endif
+ {
+ memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
+ msg_ctxt_id[msgctxt_len - 1] = '\004';
+ memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
+ translation = dcgettext (domain, msg_ctxt_id, category);
+#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+ if (msg_ctxt_id != buf)
+ free (msg_ctxt_id);
+#endif
+ if (translation != msg_ctxt_id)
+ return translation;
+ }
+ return msgid;
+}
+
+#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
+ dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
+#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
+ dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static const char *
+dcnpgettext_expr (const char *domain,
+ const char *msgctxt, const char *msgid,
+ const char *msgid_plural, unsigned long int n,
+ int category)
+{
+ size_t msgctxt_len = strlen (msgctxt) + 1;
+ size_t msgid_len = strlen (msgid) + 1;
+ const char *translation;
+#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+ char msg_ctxt_id[msgctxt_len + msgid_len];
+#else
+ char buf[1024];
+ char *msg_ctxt_id =
+ (msgctxt_len + msgid_len <= sizeof (buf)
+ ? buf
+ : (char *) malloc (msgctxt_len + msgid_len));
+ if (msg_ctxt_id != NULL)
+#endif
+ {
+ memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
+ msg_ctxt_id[msgctxt_len - 1] = '\004';
+ memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
+ translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
+#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+ if (msg_ctxt_id != buf)
+ free (msg_ctxt_id);
+#endif
+ if (!(translation == msg_ctxt_id || translation == msgid_plural))
+ return translation;
+ }
+ return (n == 1 ? msgid : msgid_plural);
+}
+
+#endif /* _LIBGETTEXT_H */
diff --git a/lib/gettime.c b/lib/gettime.c
new file mode 100644
index 0000000..86bd325
--- /dev/null
+++ b/lib/gettime.c
@@ -0,0 +1,49 @@
+/* gettime -- get the system clock
+
+ Copyright (C) 2002, 2004, 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. */
+
+/* Written by Paul Eggert. */
+
+#include <config.h>
+
+#include "timespec.h"
+
+#include <sys/time.h>
+
+/* Get the system time into *TS. */
+
+void
+gettime (struct timespec *ts)
+{
+#if HAVE_NANOTIME
+ nanotime (ts);
+#else
+
+# if defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME
+ if (clock_gettime (CLOCK_REALTIME, ts) == 0)
+ return;
+# endif
+
+ {
+ struct timeval tv;
+ gettimeofday (&tv, NULL);
+ ts->tv_sec = tv.tv_sec;
+ ts->tv_nsec = tv.tv_usec * 1000;
+ }
+
+#endif
+}
diff --git a/lib/gettimeofday.c b/lib/gettimeofday.c
new file mode 100644
index 0000000..bd5576c
--- /dev/null
+++ b/lib/gettimeofday.c
@@ -0,0 +1,142 @@
+/* Provide gettimeofday for systems that don't have it or for which it's broken.
+
+ Copyright (C) 2001, 2002, 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. */
+
+/* written by Jim Meyering */
+
+#include <config.h>
+
+/* Specification. */
+#include <sys/time.h>
+
+#include <time.h>
+
+#if HAVE_SYS_TIMEB_H
+# include <sys/timeb.h>
+#endif
+
+#if GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME
+
+/* Work around the bug in some systems whereby gettimeofday clobbers
+ the static buffer that localtime uses for its return value. The
+ gettimeofday function from Mac OS X 10.0.4 (i.e., Darwin 1.3.7) has
+ this problem. The tzset replacement is necessary for at least
+ Solaris 2.5, 2.5.1, and 2.6. */
+
+static struct tm tm_zero_buffer;
+static struct tm *localtime_buffer_addr = &tm_zero_buffer;
+
+/* This is a wrapper for localtime. It is used only on systems for which
+ gettimeofday clobbers the static buffer used for localtime's result.
+
+ On the first call, record the address of the static buffer that
+ localtime uses for its result. */
+
+struct tm *
+localtime (time_t const *timep)
+{
+#undef localtime
+ extern struct tm *localtime (time_t const *);
+ struct tm *tm = localtime (timep);
+
+ if (localtime_buffer_addr == &tm_zero_buffer)
+ localtime_buffer_addr = tm;
+
+ return tm;
+}
+
+/* Same as above, since gmtime and localtime use the same buffer. */
+struct tm *
+gmtime (time_t const *timep)
+{
+#undef gmtime
+ extern struct tm *gmtime (time_t const *);
+ struct tm *tm = gmtime (timep);
+
+ if (localtime_buffer_addr == &tm_zero_buffer)
+ localtime_buffer_addr = tm;
+
+ return tm;
+}
+
+#endif /* GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME */
+
+#if TZSET_CLOBBERS_LOCALTIME
+/* This is a wrapper for tzset, for systems on which tzset may clobber
+ the static buffer used for localtime's result. */
+void
+tzset (void)
+{
+#undef tzset
+ extern void tzset (void);
+
+ /* Save and restore the contents of the buffer used for localtime's
+ result around the call to tzset. */
+ struct tm save = *localtime_buffer_addr;
+ tzset ();
+ *localtime_buffer_addr = save;
+}
+#endif
+
+/* This is a wrapper for gettimeofday. It is used only on systems
+ that lack this function, or whose implementation of this function
+ causes problems. */
+
+int
+rpl_gettimeofday (struct timeval *restrict tv, void *restrict tz)
+{
+#undef gettimeofday
+#if HAVE_GETTIMEOFDAY
+# if GETTIMEOFDAY_CLOBBERS_LOCALTIME
+ /* Save and restore the contents of the buffer used for localtime's
+ result around the call to gettimeofday. */
+ struct tm save = *localtime_buffer_addr;
+# endif
+
+ int result = gettimeofday (tv, tz);
+
+# if GETTIMEOFDAY_CLOBBERS_LOCALTIME
+ *localtime_buffer_addr = save;
+# endif
+
+ return result;
+
+#else
+
+# if HAVE__FTIME
+
+ struct _timeb timebuf;
+ _ftime (&timebuf);
+ tv->tv_sec = timebuf.time;
+ tv->tv_usec = timebuf.millitm * 1000;
+
+# else
+
+# if !defined OK_TO_USE_1S_CLOCK
+# error "Only 1-second nominal clock resolution found. Is that intended?" \
+ "If so, compile with the -DOK_TO_USE_1S_CLOCK option."
+# endif
+ tv->tv_sec = time (NULL);
+ tv->tv_usec = 0;
+
+# endif
+
+ return 0;
+
+#endif
+}
diff --git a/lib/gnulib.mk b/lib/gnulib.mk
new file mode 100644
index 0000000..b69f608
--- /dev/null
+++ b/lib/gnulib.mk
@@ -0,0 +1,1244 @@
+## DO NOT EDIT! GENERATED AUTOMATICALLY!
+## Process this file with automake to produce Makefile.in.
+# Copyright (C) 2004-2007 Free Software Foundation, Inc.
+#
+# This file is free software, distributed under the terms of the GNU
+# General Public License. As a special exception to the GNU General
+# Public License, this file may be distributed as part of a program
+# that contains a configuration script generated by Autoconf, under
+# the same distribution terms as the rest of that program.
+#
+# Generated by gnulib-tool.
+# Reproduce by: gnulib-tool --import --dir=. --local-dir=gl --lib=libcpio --source-base=.#bootmp/lib --m4-base=.#bootmp/m4 --doc-base=.#bootmp/doc --aux-dir=.#bootmp/build-aux --avoid=lock --avoid=size_max --no-libtool --macro-prefix=gl alloca argmatch argp closeout configmake dirname error fileblocks fnmatch-gnu full-write getdate getopt gettext hash inttostr inttypes lchown obstack quote quotearg safe-read savedir stdbool stdint stpcpy strerror strtol unlocked-io utimens version-etc-fsf xalloc xalloc-die
+
+AUTOMAKE_OPTIONS = 1.5 gnits
+
+noinst_HEADERS =
+noinst_LIBRARIES =
+noinst_LTLIBRARIES =
+EXTRA_DIST =
+BUILT_SOURCES =
+SUFFIXES =
+MOSTLYCLEANFILES = core *.stackdump
+MOSTLYCLEANDIRS =
+CLEANFILES =
+DISTCLEANFILES =
+MAINTAINERCLEANFILES =
+
+AM_CPPFLAGS =
+
+noinst_LIBRARIES += libcpio.a
+
+libcpio_a_SOURCES =
+libcpio_a_LIBADD = $(gl_LIBOBJS)
+libcpio_a_DEPENDENCIES = $(gl_LIBOBJS)
+EXTRA_libcpio_a_SOURCES =
+
+## begin gnulib module absolute-header
+
+# Use this preprocessor expression to decide whether #include_next works.
+# Do not rely on a 'configure'-time test for this, since the expression
+# might appear in an installed header, which is used by some other compiler.
+HAVE_INCLUDE_NEXT = (__GNUC__ || 60000000 <= __DECC_VER)
+
+## end gnulib module absolute-header
+
+## begin gnulib module alloca
+
+
+EXTRA_DIST += alloca.c
+
+EXTRA_libcpio_a_SOURCES += alloca.c
+
+libcpio_a_LIBADD += @ALLOCA@
+libcpio_a_DEPENDENCIES += @ALLOCA@
+## end gnulib module alloca
+
+## begin gnulib module alloca-opt
+
+BUILT_SOURCES += $(ALLOCA_H)
+
+# We need the following in order to create <alloca.h> when the system
+# doesn't have one that works with the given compiler.
+alloca.h: alloca_.h
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ cat $(srcdir)/alloca_.h; \
+ } > $@-t
+ mv -f $@-t $@
+MOSTLYCLEANFILES += alloca.h alloca.h-t
+
+EXTRA_DIST += alloca_.h
+
+## end gnulib module alloca-opt
+
+## begin gnulib module allocsa
+
+libcpio_a_SOURCES += allocsa.h allocsa.c
+
+EXTRA_DIST += allocsa.valgrind
+
+## end gnulib module allocsa
+
+## begin gnulib module argmatch
+
+
+EXTRA_DIST += argmatch.c argmatch.h
+
+EXTRA_libcpio_a_SOURCES += argmatch.c
+
+## end gnulib module argmatch
+
+## begin gnulib module argp
+
+libcpio_a_SOURCES += argp.h argp-ba.c argp-eexst.c \
+ argp-fmtstream.c argp-fmtstream.h argp-fs-xinl.c argp-help.c \
+ argp-namefrob.h argp-parse.c argp-pin.c argp-pv.c argp-pvh.c \
+ argp-xinl.c
+
+## end gnulib module argp
+
+## begin gnulib module canonicalize-lgpl
+
+
+EXTRA_DIST += canonicalize-lgpl.c canonicalize.h
+
+EXTRA_libcpio_a_SOURCES += canonicalize-lgpl.c
+
+## end gnulib module canonicalize-lgpl
+
+## begin gnulib module chdir-long
+
+
+EXTRA_DIST += chdir-long.c chdir-long.h
+
+EXTRA_libcpio_a_SOURCES += chdir-long.c
+
+## end gnulib module chdir-long
+
+## begin gnulib module chown
+
+
+EXTRA_DIST += chown.c fchown-stub.c
+
+EXTRA_libcpio_a_SOURCES += chown.c fchown-stub.c
+
+## end gnulib module chown
+
+## begin gnulib module close-stream
+
+
+EXTRA_DIST += close-stream.c close-stream.h
+
+EXTRA_libcpio_a_SOURCES += close-stream.c
+
+## end gnulib module close-stream
+
+## begin gnulib module closeout
+
+
+EXTRA_DIST += closeout.c closeout.h
+
+EXTRA_libcpio_a_SOURCES += closeout.c
+
+## end gnulib module closeout
+
+## begin gnulib module configmake
+
+# Retrieve values of the variables through 'configure' followed by
+# 'make', not directly through 'configure', so that a user who
+# sets some of these variables consistently on the 'make' command
+# line gets correct results.
+#
+# One advantage of this approach, compared to the classical
+# approach of adding -DLIBDIR=\"$(libdir)\" etc. to AM_CPPFLAGS,
+# is that it protects against the use of undefined variables.
+# If, say, $(libdir) is not set in the Makefile, LIBDIR is not
+# defined by this module, and code using LIBDIR gives a
+# compilation error.
+#
+# Another advantage is that 'make' output is shorter.
+#
+# Listed in the same order as the GNU makefile conventions.
+# The Automake-defined pkg* macros are appended, in the order
+# listed in the Automake 1.10a+ documentation.
+configmake.h: Makefile
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ echo '#define PREFIX "$(prefix)"'; \
+ echo '#define EXEC_PREFIX "$(exec_prefix)"'; \
+ echo '#define BINDIR "$(bindir)"'; \
+ echo '#define SBINDIR "$(sbindir)"'; \
+ echo '#define LIBEXECDIR "$(libexecdir)"'; \
+ echo '#define DATAROOTDIR "$(datarootdir)"'; \
+ echo '#define DATADIR "$(datadir)"'; \
+ echo '#define SYSCONFDIR "$(sysconfdir)"'; \
+ echo '#define SHAREDSTATEDIR "$(sharedstatedir)"'; \
+ echo '#define LOCALSTATEDIR "$(localstatedir)"'; \
+ echo '#define INCLUDEDIR "$(includedir)"'; \
+ echo '#define OLDINCLUDEDIR "$(oldincludedir)"'; \
+ echo '#define DOCDIR "$(docdir)"'; \
+ echo '#define INFODIR "$(infodir)"'; \
+ echo '#define HTMLDIR "$(htmldir)"'; \
+ echo '#define DVIDIR "$(dvidir)"'; \
+ echo '#define PDFDIR "$(pdfdir)"'; \
+ echo '#define PSDIR "$(psdir)"'; \
+ echo '#define LIBDIR "$(libdir)"'; \
+ echo '#define LISPDIR "$(lispdir)"'; \
+ echo '#define LOCALEDIR "$(localedir)"'; \
+ echo '#define MANDIR "$(mandir)"'; \
+ echo '#define MANEXT "$(manext)"'; \
+ echo '#define PKGDATADIR "$(pkgdatadir)"'; \
+ echo '#define PKGINCLUDEDIR "$(pkgincludedir)"'; \
+ echo '#define PKGLIBDIR "$(pkglibdir)"'; \
+ echo '#define PKGLIBEXECDIR "$(pkglibexecdir)"'; \
+ } | sed '/""/d' > $@-t
+ mv $@-t $@
+BUILT_SOURCES += configmake.h
+CLEANFILES += configmake.h configmake.h-t
+
+## end gnulib module configmake
+
+## begin gnulib module dirfd
+
+
+EXTRA_DIST += dirfd.c dirfd.h
+
+EXTRA_libcpio_a_SOURCES += dirfd.c
+
+## end gnulib module dirfd
+
+## begin gnulib module dirname
+
+
+EXTRA_DIST += basename.c dirname.c dirname.h stripslash.c
+
+EXTRA_libcpio_a_SOURCES += basename.c dirname.c stripslash.c
+
+## end gnulib module dirname
+
+## begin gnulib module dup2
+
+
+EXTRA_DIST += dup2.c
+
+EXTRA_libcpio_a_SOURCES += dup2.c
+
+## end gnulib module dup2
+
+## begin gnulib module error
+
+
+EXTRA_DIST += error.c error.h
+
+EXTRA_libcpio_a_SOURCES += error.c
+
+## end gnulib module error
+
+## begin gnulib module exitfail
+
+
+EXTRA_DIST += exitfail.c exitfail.h
+
+EXTRA_libcpio_a_SOURCES += exitfail.c
+
+## end gnulib module exitfail
+
+## begin gnulib module fchdir
+
+BUILT_SOURCES += $(DIRENT_H)
+
+# We need the following in order to create <dirent.h> when the system
+# doesn't have one that works with the given compiler.
+dirent.h: dirent_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's|@''ABSOLUTE_DIRENT_H''@|$(ABSOLUTE_DIRENT_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's|@''REPLACE_FCHDIR''@|$(REPLACE_FCHDIR)|g' \
+ < $(srcdir)/dirent_.h; \
+ } > $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += dirent.h dirent.h-t
+
+EXTRA_DIST += dirent_.h fchdir.c
+
+EXTRA_libcpio_a_SOURCES += fchdir.c
+
+## end gnulib module fchdir
+
+## begin gnulib module fcntl
+
+BUILT_SOURCES += $(FCNTL_H)
+
+# We need the following in order to create <fcntl.h> when the system
+# doesn't have one that works with the given compiler.
+fcntl.h: fcntl_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's|@''ABSOLUTE_FCNTL_H''@|$(ABSOLUTE_FCNTL_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ < $(srcdir)/fcntl_.h; \
+ } > $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += fcntl.h fcntl.h-t
+
+EXTRA_DIST += fcntl_.h
+
+## end gnulib module fcntl
+
+## begin gnulib module fcntl-safer
+
+
+EXTRA_DIST += creat-safer.c fcntl--.h fcntl-safer.h open-safer.c
+
+EXTRA_libcpio_a_SOURCES += creat-safer.c open-safer.c
+
+## end gnulib module fcntl-safer
+
+## begin gnulib module fileblocks
+
+
+EXTRA_DIST += fileblocks.c
+
+EXTRA_libcpio_a_SOURCES += fileblocks.c
+
+## end gnulib module fileblocks
+
+## begin gnulib module float
+
+BUILT_SOURCES += $(FLOAT_H)
+
+# We need the following in order to create <float.h> when the system
+# doesn't have one that works with the given compiler.
+float.h: float_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+ sed -e 's|@''ABSOLUTE_FLOAT_H''@|$(ABSOLUTE_FLOAT_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ < $(srcdir)/float_.h; \
+ } > $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += float.h float.h-t
+
+EXTRA_DIST += float_.h
+
+## end gnulib module float
+
+## begin gnulib module fnmatch
+
+BUILT_SOURCES += $(FNMATCH_H)
+
+# We need the following in order to create <fnmatch.h> when the system
+# doesn't have one that supports the required API.
+fnmatch.h: fnmatch_.h
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ cat $(srcdir)/fnmatch_.h; \
+ } > $@-t
+ mv -f $@-t $@
+MOSTLYCLEANFILES += fnmatch.h fnmatch.h-t
+
+EXTRA_DIST += fnmatch.c fnmatch_.h fnmatch_loop.c
+
+EXTRA_libcpio_a_SOURCES += fnmatch.c fnmatch_loop.c
+
+## end gnulib module fnmatch
+
+## begin gnulib module fpending
+
+
+EXTRA_DIST += __fpending.c __fpending.h
+
+EXTRA_libcpio_a_SOURCES += __fpending.c
+
+## end gnulib module fpending
+
+## begin gnulib module full-write
+
+libcpio_a_SOURCES += full-write.h full-write.c
+
+## end gnulib module full-write
+
+## begin gnulib module getcwd
+
+
+EXTRA_DIST += getcwd.c
+
+EXTRA_libcpio_a_SOURCES += getcwd.c
+
+## end gnulib module getcwd
+
+## begin gnulib module getdate
+
+libcpio_a_SOURCES += getdate.y
+BUILT_SOURCES += getdate.c
+MAINTAINERCLEANFILES += getdate.c
+EXTRA_DIST += getdate.c
+
+EXTRA_DIST += getdate.h
+
+## end gnulib module getdate
+
+## begin gnulib module getopt
+
+BUILT_SOURCES += $(GETOPT_H)
+
+# We need the following in order to create <getopt.h> when the system
+# doesn't have one that works with the given compiler.
+getopt.h: getopt_.h
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ cat $(srcdir)/getopt_.h; \
+ } > $@-t
+ mv -f $@-t $@
+MOSTLYCLEANFILES += getopt.h getopt.h-t
+
+EXTRA_DIST += getopt.c getopt1.c getopt_.h getopt_int.h
+
+EXTRA_libcpio_a_SOURCES += getopt.c getopt1.c
+
+## end gnulib module getopt
+
+## begin gnulib module gettext
+
+# This is for those projects which use "gettextize --intl" to put a source-code
+# copy of libintl into their package. In such projects, every Makefile.am needs
+# -I$(top_builddir)/intl, so that <libintl.h> can be found in this directory.
+# For the Makefile.ams in other directories it is the maintainer's
+# responsibility; for the one from gnulib we do it here.
+# This option has no effect when the user disables NLS (because then the intl
+# directory contains no libintl.h file) or when the project does not use
+# "gettextize --intl".
+#AM_CPPFLAGS += -I$(top_builddir)/intl
+
+## end gnulib module gettext
+
+## begin gnulib module gettext-h
+
+libcpio_a_SOURCES += gettext.h
+
+## end gnulib module gettext-h
+
+## begin gnulib module gettime
+
+
+EXTRA_DIST += gettime.c
+
+EXTRA_libcpio_a_SOURCES += gettime.c
+
+## end gnulib module gettime
+
+## begin gnulib module gettimeofday
+
+
+EXTRA_DIST += gettimeofday.c
+
+EXTRA_libcpio_a_SOURCES += gettimeofday.c
+
+## end gnulib module gettimeofday
+
+## begin gnulib module hash
+
+
+EXTRA_DIST += hash.c hash.h
+
+EXTRA_libcpio_a_SOURCES += hash.c
+
+## end gnulib module hash
+
+## begin gnulib module intprops
+
+
+EXTRA_DIST += intprops.h
+
+## end gnulib module intprops
+
+## begin gnulib module inttostr
+
+
+EXTRA_DIST += imaxtostr.c inttostr.c inttostr.h offtostr.c uinttostr.c umaxtostr.c
+
+EXTRA_libcpio_a_SOURCES += imaxtostr.c inttostr.c offtostr.c uinttostr.c umaxtostr.c
+
+## end gnulib module inttostr
+
+## begin gnulib module inttypes
+
+BUILT_SOURCES += $(INTTYPES_H)
+
+# We need the following in order to create <inttypes.h> when the system
+# doesn't have one that works with the given compiler.
+inttypes.h: inttypes_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \
+ -e 's|@''ABSOLUTE_INTTYPES_H''@|$(ABSOLUTE_INTTYPES_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's/@''PRI_MACROS_BROKEN''@/$(PRI_MACROS_BROKEN)/g' \
+ -e 's/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \
+ -e 's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/g' \
+ -e 's/@''PRIPTR_PREFIX''@/$(PRIPTR_PREFIX)/g' \
+ -e 's/@''GNULIB_IMAXABS''@/$(GNULIB_IMAXABS)/g' \
+ -e 's/@''GNULIB_IMAXDIV''@/$(GNULIB_IMAXDIV)/g' \
+ -e 's/@''GNULIB_STRTOIMAX''@/$(GNULIB_STRTOIMAX)/g' \
+ -e 's/@''GNULIB_STRTOUMAX''@/$(GNULIB_STRTOUMAX)/g' \
+ -e 's/@''HAVE_DECL_IMAXABS''@/$(HAVE_DECL_IMAXABS)/g' \
+ -e 's/@''HAVE_DECL_IMAXDIV''@/$(HAVE_DECL_IMAXDIV)/g' \
+ -e 's/@''HAVE_DECL_STRTOIMAX''@/$(HAVE_DECL_STRTOIMAX)/g' \
+ -e 's/@''HAVE_DECL_STRTOUMAX''@/$(HAVE_DECL_STRTOUMAX)/g' \
+ -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \
+ < $(srcdir)/inttypes_.h; \
+ } > $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += inttypes.h inttypes.h-t
+
+EXTRA_DIST += inttypes_.h
+
+## end gnulib module inttypes
+
+## begin gnulib module lchown
+
+
+EXTRA_DIST += lchown.c lchown.h
+
+EXTRA_libcpio_a_SOURCES += lchown.c
+
+## end gnulib module lchown
+
+## begin gnulib module link-warning
+
+LINK_WARNING_H=$(top_srcdir)/build-aux/link-warning.h
+
+## end gnulib module link-warning
+
+## begin gnulib module lstat
+
+
+EXTRA_DIST += lstat.c lstat.h
+
+EXTRA_libcpio_a_SOURCES += lstat.c
+
+## end gnulib module lstat
+
+## begin gnulib module malloc
+
+
+EXTRA_DIST += malloc.c
+
+EXTRA_libcpio_a_SOURCES += malloc.c
+
+## end gnulib module malloc
+
+## begin gnulib module mempcpy
+
+
+EXTRA_DIST += mempcpy.c
+
+EXTRA_libcpio_a_SOURCES += mempcpy.c
+
+## end gnulib module mempcpy
+
+## begin gnulib module memrchr
+
+
+EXTRA_DIST += memrchr.c
+
+EXTRA_libcpio_a_SOURCES += memrchr.c
+
+## end gnulib module memrchr
+
+## begin gnulib module mktime
+
+
+EXTRA_DIST += mktime.c
+
+EXTRA_libcpio_a_SOURCES += mktime.c
+
+## end gnulib module mktime
+
+## begin gnulib module obstack
+
+
+EXTRA_DIST += obstack.c obstack.h
+
+EXTRA_libcpio_a_SOURCES += obstack.c
+
+## end gnulib module obstack
+
+## begin gnulib module openat
+
+
+EXTRA_DIST += at-func.c fchmodat.c fchownat.c fstatat.c mkdirat.c openat-priv.h openat-proc.c openat.c openat.h
+
+EXTRA_libcpio_a_SOURCES += at-func.c fchmodat.c fchownat.c fstatat.c mkdirat.c openat-proc.c openat.c
+
+## end gnulib module openat
+
+## begin gnulib module openat-die
+
+libcpio_a_SOURCES += openat-die.c
+
+## end gnulib module openat-die
+
+## begin gnulib module pathmax
+
+
+EXTRA_DIST += pathmax.h
+
+## end gnulib module pathmax
+
+## begin gnulib module quote
+
+
+EXTRA_DIST += quote.c quote.h
+
+EXTRA_libcpio_a_SOURCES += quote.c
+
+## end gnulib module quote
+
+## begin gnulib module quotearg
+
+
+EXTRA_DIST += quotearg.c quotearg.h
+
+EXTRA_libcpio_a_SOURCES += quotearg.c
+
+## end gnulib module quotearg
+
+## begin gnulib module readlink
+
+
+EXTRA_DIST += readlink.c
+
+EXTRA_libcpio_a_SOURCES += readlink.c
+
+## end gnulib module readlink
+
+## begin gnulib module safe-read
+
+
+EXTRA_DIST += safe-read.c safe-read.h
+
+EXTRA_libcpio_a_SOURCES += safe-read.c
+
+## end gnulib module safe-read
+
+## begin gnulib module safe-write
+
+
+EXTRA_DIST += safe-write.c safe-write.h
+
+EXTRA_libcpio_a_SOURCES += safe-write.c
+
+## end gnulib module safe-write
+
+## begin gnulib module same-inode
+
+
+EXTRA_DIST += same-inode.h
+
+## end gnulib module same-inode
+
+## begin gnulib module save-cwd
+
+
+EXTRA_DIST += save-cwd.c save-cwd.h
+
+EXTRA_libcpio_a_SOURCES += save-cwd.c
+
+## end gnulib module save-cwd
+
+## begin gnulib module savedir
+
+
+EXTRA_DIST += savedir.c savedir.h
+
+EXTRA_libcpio_a_SOURCES += savedir.c
+
+## end gnulib module savedir
+
+## begin gnulib module setenv
+
+
+EXTRA_DIST += setenv.c setenv.h unsetenv.c
+
+EXTRA_libcpio_a_SOURCES += setenv.c unsetenv.c
+
+## end gnulib module setenv
+
+## begin gnulib module sleep
+
+
+EXTRA_DIST += sleep.c
+
+EXTRA_libcpio_a_SOURCES += sleep.c
+
+## end gnulib module sleep
+
+## begin gnulib module stdbool
+
+BUILT_SOURCES += $(STDBOOL_H)
+
+# We need the following in order to create <stdbool.h> when the system
+# doesn't have one that works.
+stdbool.h: stdbool_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool_.h; \
+ } > $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += stdbool.h stdbool.h-t
+
+EXTRA_DIST += stdbool_.h
+
+## end gnulib module stdbool
+
+## begin gnulib module stdint
+
+BUILT_SOURCES += $(STDINT_H)
+
+# We need the following in order to create <stdint.h> when the system
+# doesn't have one that works with the given compiler.
+stdint.h: stdint_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's/@''HAVE_STDINT_H''@/$(HAVE_STDINT_H)/g' \
+ -e 's|@''ABSOLUTE_STDINT_H''@|$(ABSOLUTE_STDINT_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's/@''HAVE_SYS_TYPES_H''@/$(HAVE_SYS_TYPES_H)/g' \
+ -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \
+ -e 's/@''HAVE_SYS_INTTYPES_H''@/$(HAVE_SYS_INTTYPES_H)/g' \
+ -e 's/@''HAVE_SYS_BITYPES_H''@/$(HAVE_SYS_BITYPES_H)/g' \
+ -e 's/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \
+ -e 's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/g' \
+ -e 's/@''BITSIZEOF_PTRDIFF_T''@/$(BITSIZEOF_PTRDIFF_T)/g' \
+ -e 's/@''PTRDIFF_T_SUFFIX''@/$(PTRDIFF_T_SUFFIX)/g' \
+ -e 's/@''BITSIZEOF_SIG_ATOMIC_T''@/$(BITSIZEOF_SIG_ATOMIC_T)/g' \
+ -e 's/@''HAVE_SIGNED_SIG_ATOMIC_T''@/$(HAVE_SIGNED_SIG_ATOMIC_T)/g' \
+ -e 's/@''SIG_ATOMIC_T_SUFFIX''@/$(SIG_ATOMIC_T_SUFFIX)/g' \
+ -e 's/@''BITSIZEOF_SIZE_T''@/$(BITSIZEOF_SIZE_T)/g' \
+ -e 's/@''SIZE_T_SUFFIX''@/$(SIZE_T_SUFFIX)/g' \
+ -e 's/@''BITSIZEOF_WCHAR_T''@/$(BITSIZEOF_WCHAR_T)/g' \
+ -e 's/@''HAVE_SIGNED_WCHAR_T''@/$(HAVE_SIGNED_WCHAR_T)/g' \
+ -e 's/@''WCHAR_T_SUFFIX''@/$(WCHAR_T_SUFFIX)/g' \
+ -e 's/@''BITSIZEOF_WINT_T''@/$(BITSIZEOF_WINT_T)/g' \
+ -e 's/@''HAVE_SIGNED_WINT_T''@/$(HAVE_SIGNED_WINT_T)/g' \
+ -e 's/@''WINT_T_SUFFIX''@/$(WINT_T_SUFFIX)/g' \
+ < $(srcdir)/stdint_.h; \
+ } > $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += stdint.h stdint.h-t
+
+EXTRA_DIST += stdint_.h
+
+## end gnulib module stdint
+
+## begin gnulib module stdio
+
+BUILT_SOURCES += stdio.h
+
+# We need the following in order to create <stdio.h> when the system
+# doesn't have one that works with the given compiler.
+stdio.h: stdio_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+ sed -e 's|@''ABSOLUTE_STDIO_H''@|$(ABSOLUTE_STDIO_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's|@''GNULIB_FPRINTF_POSIX''@|$(GNULIB_FPRINTF_POSIX)|g' \
+ -e 's|@''GNULIB_PRINTF_POSIX''@|$(GNULIB_PRINTF_POSIX)|g' \
+ -e 's|@''GNULIB_SNPRINTF''@|$(GNULIB_SNPRINTF)|g' \
+ -e 's|@''GNULIB_SPRINTF_POSIX''@|$(GNULIB_SPRINTF_POSIX)|g' \
+ -e 's|@''GNULIB_VFPRINTF_POSIX''@|$(GNULIB_VFPRINTF_POSIX)|g' \
+ -e 's|@''GNULIB_VPRINTF_POSIX''@|$(GNULIB_VPRINTF_POSIX)|g' \
+ -e 's|@''GNULIB_VSNPRINTF''@|$(GNULIB_VSNPRINTF)|g' \
+ -e 's|@''GNULIB_VSPRINTF_POSIX''@|$(GNULIB_VSPRINTF_POSIX)|g' \
+ -e 's|@''GNULIB_VASPRINTF''@|$(GNULIB_VASPRINTF)|g' \
+ -e 's|@''GNULIB_FSEEK''@|$(GNULIB_FSEEK)|g' \
+ -e 's|@''GNULIB_FSEEKO''@|$(GNULIB_FSEEKO)|g' \
+ -e 's|@''GNULIB_FTELL''@|$(GNULIB_FTELL)|g' \
+ -e 's|@''GNULIB_FTELLO''@|$(GNULIB_FTELLO)|g' \
+ -e 's|@''GNULIB_FFLUSH''@|$(GNULIB_FFLUSH)|g' \
+ -e 's|@''REPLACE_FPRINTF''@|$(REPLACE_FPRINTF)|g' \
+ -e 's|@''REPLACE_VFPRINTF''@|$(REPLACE_VFPRINTF)|g' \
+ -e 's|@''REPLACE_PRINTF''@|$(REPLACE_PRINTF)|g' \
+ -e 's|@''REPLACE_VPRINTF''@|$(REPLACE_VPRINTF)|g' \
+ -e 's|@''REPLACE_SNPRINTF''@|$(REPLACE_SNPRINTF)|g' \
+ -e 's|@''HAVE_DECL_SNPRINTF''@|$(HAVE_DECL_SNPRINTF)|g' \
+ -e 's|@''REPLACE_VSNPRINTF''@|$(REPLACE_VSNPRINTF)|g' \
+ -e 's|@''HAVE_DECL_VSNPRINTF''@|$(HAVE_DECL_VSNPRINTF)|g' \
+ -e 's|@''REPLACE_SPRINTF''@|$(REPLACE_SPRINTF)|g' \
+ -e 's|@''REPLACE_VSPRINTF''@|$(REPLACE_VSPRINTF)|g' \
+ -e 's|@''HAVE_VASPRINTF''@|$(HAVE_VASPRINTF)|g' \
+ -e 's|@''REPLACE_VASPRINTF''@|$(REPLACE_VASPRINTF)|g' \
+ -e 's|@''REPLACE_FSEEKO''@|$(REPLACE_FSEEKO)|g' \
+ -e 's|@''REPLACE_FSEEK''@|$(REPLACE_FSEEK)|g' \
+ -e 's|@''REPLACE_FTELLO''@|$(REPLACE_FTELLO)|g' \
+ -e 's|@''REPLACE_FTELL''@|$(REPLACE_FTELL)|g' \
+ -e 's|@''REPLACE_FFLUSH''@|$(REPLACE_FFLUSH)|g' \
+ -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \
+ < $(srcdir)/stdio_.h; \
+ } > $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += stdio.h stdio.h-t
+
+EXTRA_DIST += stdio_.h
+
+## end gnulib module stdio
+
+## begin gnulib module stdlib
+
+BUILT_SOURCES += stdlib.h
+
+# We need the following in order to create <stdlib.h> when the system
+# doesn't have one that works with the given compiler.
+stdlib.h: stdlib_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+ sed -e 's|@''ABSOLUTE_STDLIB_H''@|$(ABSOLUTE_STDLIB_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's|@''GNULIB_GETSUBOPT''@|$(GNULIB_GETSUBOPT)|g' \
+ -e 's|@''GNULIB_MKDTEMP''@|$(GNULIB_MKDTEMP)|g' \
+ -e 's|@''GNULIB_MKSTEMP''@|$(GNULIB_MKSTEMP)|g' \
+ -e 's|@''HAVE_GETSUBOPT''@|$(HAVE_GETSUBOPT)|g' \
+ -e 's|@''HAVE_MKDTEMP''@|$(HAVE_MKDTEMP)|g' \
+ -e 's|@''REPLACE_MKSTEMP''@|$(REPLACE_MKSTEMP)|g' \
+ -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \
+ < $(srcdir)/stdlib_.h; \
+ } > $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += stdlib.h stdlib.h-t
+
+EXTRA_DIST += stdlib_.h
+
+## end gnulib module stdlib
+
+## begin gnulib module stpcpy
+
+
+EXTRA_DIST += stpcpy.c
+
+EXTRA_libcpio_a_SOURCES += stpcpy.c
+
+## end gnulib module stpcpy
+
+## begin gnulib module strcase
+
+
+EXTRA_DIST += strcasecmp.c strncasecmp.c
+
+EXTRA_libcpio_a_SOURCES += strcasecmp.c strncasecmp.c
+
+## end gnulib module strcase
+
+## begin gnulib module strchrnul
+
+
+EXTRA_DIST += strchrnul.c
+
+EXTRA_libcpio_a_SOURCES += strchrnul.c
+
+## end gnulib module strchrnul
+
+## begin gnulib module strdup
+
+
+EXTRA_DIST += strdup.c
+
+EXTRA_libcpio_a_SOURCES += strdup.c
+
+## end gnulib module strdup
+
+## begin gnulib module strerror
+
+
+EXTRA_DIST += strerror.c
+
+EXTRA_libcpio_a_SOURCES += strerror.c
+
+## end gnulib module strerror
+
+## begin gnulib module string
+
+BUILT_SOURCES += string.h
+
+# We need the following in order to create <string.h> when the system
+# doesn't have one that works with the given compiler.
+string.h: string_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+ sed -e 's|@''ABSOLUTE_STRING_H''@|$(ABSOLUTE_STRING_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's|@''GNULIB_MBSLEN''@|$(GNULIB_MBSLEN)|g' \
+ -e 's|@''GNULIB_MBSCHR''@|$(GNULIB_MBSCHR)|g' \
+ -e 's|@''GNULIB_MBSRCHR''@|$(GNULIB_MBSRCHR)|g' \
+ -e 's|@''GNULIB_MBSSTR''@|$(GNULIB_MBSSTR)|g' \
+ -e 's|@''GNULIB_MBSCASECMP''@|$(GNULIB_MBSCASECMP)|g' \
+ -e 's|@''GNULIB_MBSNCASECMP''@|$(GNULIB_MBSNCASECMP)|g' \
+ -e 's|@''GNULIB_MBSPCASECMP''@|$(GNULIB_MBSPCASECMP)|g' \
+ -e 's|@''GNULIB_MBSCASESTR''@|$(GNULIB_MBSCASESTR)|g' \
+ -e 's|@''GNULIB_MBSCSPN''@|$(GNULIB_MBSCSPN)|g' \
+ -e 's|@''GNULIB_MBSPBRK''@|$(GNULIB_MBSPBRK)|g' \
+ -e 's|@''GNULIB_MBSSPN''@|$(GNULIB_MBSSPN)|g' \
+ -e 's|@''GNULIB_MBSSEP''@|$(GNULIB_MBSSEP)|g' \
+ -e 's|@''GNULIB_MBSTOK_R''@|$(GNULIB_MBSTOK_R)|g' \
+ -e 's|@''GNULIB_MEMMEM''@|$(GNULIB_MEMMEM)|g' \
+ -e 's|@''GNULIB_MEMPCPY''@|$(GNULIB_MEMPCPY)|g' \
+ -e 's|@''GNULIB_MEMRCHR''@|$(GNULIB_MEMRCHR)|g' \
+ -e 's|@''GNULIB_STPCPY''@|$(GNULIB_STPCPY)|g' \
+ -e 's|@''GNULIB_STPNCPY''@|$(GNULIB_STPNCPY)|g' \
+ -e 's|@''GNULIB_STRCHRNUL''@|$(GNULIB_STRCHRNUL)|g' \
+ -e 's|@''GNULIB_STRDUP''@|$(GNULIB_STRDUP)|g' \
+ -e 's|@''GNULIB_STRNDUP''@|$(GNULIB_STRNDUP)|g' \
+ -e 's|@''GNULIB_STRNLEN''@|$(GNULIB_STRNLEN)|g' \
+ -e 's|@''GNULIB_STRPBRK''@|$(GNULIB_STRPBRK)|g' \
+ -e 's|@''GNULIB_STRSEP''@|$(GNULIB_STRSEP)|g' \
+ -e 's|@''GNULIB_STRCASESTR''@|$(GNULIB_STRCASESTR)|g' \
+ -e 's|@''GNULIB_STRTOK_R''@|$(GNULIB_STRTOK_R)|g' \
+ -e 's|@''HAVE_DECL_MEMMEM''@|$(HAVE_DECL_MEMMEM)|g' \
+ -e 's|@''HAVE_MEMPCPY''@|$(HAVE_MEMPCPY)|g' \
+ -e 's|@''HAVE_DECL_MEMRCHR''@|$(HAVE_DECL_MEMRCHR)|g' \
+ -e 's|@''HAVE_STPCPY''@|$(HAVE_STPCPY)|g' \
+ -e 's|@''HAVE_STPNCPY''@|$(HAVE_STPNCPY)|g' \
+ -e 's|@''HAVE_STRCASECMP''@|$(HAVE_STRCASECMP)|g' \
+ -e 's|@''HAVE_DECL_STRNCASECMP''@|$(HAVE_DECL_STRNCASECMP)|g' \
+ -e 's|@''HAVE_STRCHRNUL''@|$(HAVE_STRCHRNUL)|g' \
+ -e 's|@''HAVE_DECL_STRDUP''@|$(HAVE_DECL_STRDUP)|g' \
+ -e 's|@''HAVE_STRNDUP''@|$(HAVE_STRNDUP)|g' \
+ -e 's|@''HAVE_DECL_STRNDUP''@|$(HAVE_DECL_STRNDUP)|g' \
+ -e 's|@''HAVE_DECL_STRNLEN''@|$(HAVE_DECL_STRNLEN)|g' \
+ -e 's|@''HAVE_STRPBRK''@|$(HAVE_STRPBRK)|g' \
+ -e 's|@''HAVE_STRSEP''@|$(HAVE_STRSEP)|g' \
+ -e 's|@''HAVE_STRCASESTR''@|$(HAVE_STRCASESTR)|g' \
+ -e 's|@''HAVE_DECL_STRTOK_R''@|$(HAVE_DECL_STRTOK_R)|g' \
+ -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \
+ < $(srcdir)/string_.h; \
+ } > $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += string.h string.h-t
+
+EXTRA_DIST += string_.h
+
+## end gnulib module string
+
+## begin gnulib module strndup
+
+
+EXTRA_DIST += strndup.c
+
+EXTRA_libcpio_a_SOURCES += strndup.c
+
+## end gnulib module strndup
+
+## begin gnulib module strnlen
+
+
+EXTRA_DIST += strnlen.c
+
+EXTRA_libcpio_a_SOURCES += strnlen.c
+
+## end gnulib module strnlen
+
+## begin gnulib module strtol
+
+
+EXTRA_DIST += strtol.c
+
+EXTRA_libcpio_a_SOURCES += strtol.c
+
+## end gnulib module strtol
+
+## begin gnulib module sys_stat
+
+BUILT_SOURCES += $(SYS_STAT_H)
+
+# We need the following in order to create <sys/stat.h> when the system
+# has one that is incomplete.
+sys/stat.h: sys_stat_.h
+ @MKDIR_P@ sys
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's|@''ABSOLUTE_SYS_STAT_H''@|$(ABSOLUTE_SYS_STAT_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's|@''HAVE_IO_H''@|$(HAVE_IO_H)|g' \
+ -e 's|@''HAVE_LSTAT''@|$(HAVE_LSTAT)|g' \
+ -e 's|@''HAVE_DECL_MKDIR''@|$(HAVE_DECL_MKDIR)|g' \
+ < $(srcdir)/sys_stat_.h; \
+ } > $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += sys/stat.h sys/stat.h-t
+MOSTLYCLEANDIRS += sys
+
+EXTRA_DIST += sys_stat_.h
+
+## end gnulib module sys_stat
+
+## begin gnulib module sys_time
+
+BUILT_SOURCES += $(SYS_TIME_H)
+
+# We need the following in order to create <sys/time.h> when the system
+# doesn't have one that works with the given compiler.
+sys/time.h: sys_time_.h
+ @MKDIR_P@ sys
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's/@''HAVE_SYS_TIME_H''@/$(HAVE_SYS_TIME_H)/g' \
+ -e 's|@''ABSOLUTE_SYS_TIME_H''@|$(ABSOLUTE_SYS_TIME_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's/@''REPLACE_GETTIMEOFDAY''@/$(REPLACE_GETTIMEOFDAY)/g' \
+ -e 's/@''HAVE_STRUCT_TIMEVAL''@/$(HAVE_STRUCT_TIMEVAL)/g' \
+ < $(srcdir)/sys_time_.h; \
+ } > $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += sys/time.h sys/time.h-t
+
+EXTRA_DIST += sys_time_.h
+
+## end gnulib module sys_time
+
+## begin gnulib module sysexits
+
+BUILT_SOURCES += $(SYSEXITS_H)
+
+# We need the following in order to create <sysexits.h> when the system
+# doesn't have one that works with the given compiler.
+sysexits.h: sysexits_.h
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's|@''HAVE_SYSEXITS_H''@|$(HAVE_SYSEXITS_H)|g' \
+ -e 's|@''ABSOLUTE_SYSEXITS_H''@|$(ABSOLUTE_SYSEXITS_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ < $(srcdir)/sysexits_.h; \
+ } > $@-t
+ mv -f $@-t $@
+MOSTLYCLEANFILES += sysexits.h sysexits.h-t
+
+EXTRA_DIST += sysexits_.h
+
+## end gnulib module sysexits
+
+## begin gnulib module time
+
+BUILT_SOURCES += time.h
+
+# We need the following in order to create <time.h> when the system
+# doesn't have one that works with the given compiler.
+time.h: time_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+ sed -e 's|@ABSOLUTE_TIME_H''@|$(ABSOLUTE_TIME_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's|@REPLACE_LOCALTIME_R''@|$(REPLACE_LOCALTIME_R)|g' \
+ -e 's|@REPLACE_NANOSLEEP''@|$(REPLACE_NANOSLEEP)|g' \
+ -e 's|@REPLACE_STRPTIME''@|$(REPLACE_STRPTIME)|g' \
+ -e 's|@REPLACE_TIMEGM''@|$(REPLACE_TIMEGM)|g' \
+ -e 's|@SYS_TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(SYS_TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \
+ -e 's|@TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \
+ < $(srcdir)/time_.h; \
+ } > $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += time.h time.h-t
+
+EXTRA_DIST += time_.h
+
+## end gnulib module time
+
+## begin gnulib module time_r
+
+
+EXTRA_DIST += time_r.c
+
+EXTRA_libcpio_a_SOURCES += time_r.c
+
+## end gnulib module time_r
+
+## begin gnulib module timespec
+
+
+EXTRA_DIST += timespec.h
+
+## end gnulib module timespec
+
+## begin gnulib module unistd
+
+BUILT_SOURCES += unistd.h
+
+# We need the following in order to create an empty placeholder for
+# <unistd.h> when the system doesn't have one.
+unistd.h: unistd_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's|@''HAVE_UNISTD_H''@|$(HAVE_UNISTD_H)|g' \
+ -e 's|@''ABSOLUTE_UNISTD_H''@|$(ABSOLUTE_UNISTD_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's|@''GNULIB_CHOWN''@|$(GNULIB_CHOWN)|g' \
+ -e 's|@''GNULIB_DUP2''@|$(GNULIB_DUP2)|g' \
+ -e 's|@''GNULIB_FCHDIR''@|$(GNULIB_FCHDIR)|g' \
+ -e 's|@''GNULIB_FTRUNCATE''@|$(GNULIB_FTRUNCATE)|g' \
+ -e 's|@''GNULIB_GETCWD''@|$(GNULIB_GETCWD)|g' \
+ -e 's|@''GNULIB_GETLOGIN_R''@|$(GNULIB_GETLOGIN_R)|g' \
+ -e 's|@''GNULIB_LSEEK''@|$(GNULIB_LSEEK)|g' \
+ -e 's|@''GNULIB_READLINK''@|$(GNULIB_READLINK)|g' \
+ -e 's|@''GNULIB_SLEEP''@|$(GNULIB_SLEEP)|g' \
+ -e 's|@''HAVE_DUP2''@|$(HAVE_DUP2)|g' \
+ -e 's|@''HAVE_FTRUNCATE''@|$(HAVE_FTRUNCATE)|g' \
+ -e 's|@''HAVE_READLINK''@|$(HAVE_READLINK)|g' \
+ -e 's|@''HAVE_SLEEP''@|$(HAVE_SLEEP)|g' \
+ -e 's|@''HAVE_DECL_GETLOGIN_R''@|$(HAVE_DECL_GETLOGIN_R)|g' \
+ -e 's|@''REPLACE_CHOWN''@|$(REPLACE_CHOWN)|g' \
+ -e 's|@''REPLACE_FCHDIR''@|$(REPLACE_FCHDIR)|g' \
+ -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \
+ -e 's|@''REPLACE_LSEEK''@|$(REPLACE_LSEEK)|g' \
+ < $(srcdir)/unistd_.h; \
+ } > $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += unistd.h unistd.h-t
+
+EXTRA_DIST += unistd_.h
+
+## end gnulib module unistd
+
+## begin gnulib module unistd-safer
+
+
+EXTRA_DIST += dup-safer.c fd-safer.c pipe-safer.c unistd--.h unistd-safer.h
+
+EXTRA_libcpio_a_SOURCES += dup-safer.c fd-safer.c pipe-safer.c
+
+## end gnulib module unistd-safer
+
+## begin gnulib module unlocked-io
+
+
+EXTRA_DIST += unlocked-io.h
+
+## end gnulib module unlocked-io
+
+## begin gnulib module utimens
+
+
+EXTRA_DIST += utimens.c utimens.h
+
+EXTRA_libcpio_a_SOURCES += utimens.c
+
+## end gnulib module utimens
+
+## begin gnulib module vasnprintf
+
+
+EXTRA_DIST += asnprintf.c float+.h printf-args.c printf-args.h printf-parse.c printf-parse.h vasnprintf.c vasnprintf.h
+
+EXTRA_libcpio_a_SOURCES += asnprintf.c printf-args.c printf-parse.c vasnprintf.c
+
+## end gnulib module vasnprintf
+
+## begin gnulib module verify
+
+libcpio_a_SOURCES += verify.h
+
+## end gnulib module verify
+
+## begin gnulib module version-etc
+
+libcpio_a_SOURCES += version-etc.h version-etc.c
+
+## end gnulib module version-etc
+
+## begin gnulib module version-etc-fsf
+
+libcpio_a_SOURCES += version-etc-fsf.c
+
+## end gnulib module version-etc-fsf
+
+## begin gnulib module vsnprintf
+
+
+EXTRA_DIST += vsnprintf.c
+
+EXTRA_libcpio_a_SOURCES += vsnprintf.c
+
+## end gnulib module vsnprintf
+
+## begin gnulib module wchar
+
+BUILT_SOURCES += $(WCHAR_H)
+
+# We need the following in order to create <wchar.h> when the system
+# version does not work standalone.
+wchar.h: wchar_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's|@''ABSOLUTE_WCHAR_H''@|$(ABSOLUTE_WCHAR_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ < $(srcdir)/wchar_.h; \
+ } > $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += wchar.h wchar.h-t
+
+EXTRA_DIST += wchar_.h
+
+## end gnulib module wchar
+
+## begin gnulib module wctype
+
+BUILT_SOURCES += $(WCTYPE_H)
+
+# We need the following in order to create <wctype.h> when the system
+# doesn't have one that works with the given compiler.
+wctype.h: wctype_.h
+ rm -f $@-t $@
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's/@''HAVE_WCTYPE_H''@/$(HAVE_WCTYPE_H)/g' \
+ -e 's|@''ABSOLUTE_WCTYPE_H''@|$(ABSOLUTE_WCTYPE_H)|g' \
+ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \
+ -e 's/@''HAVE_ISWCNTRL''@/$(HAVE_ISWCNTRL)/g' \
+ -e 's/@''HAVE_WINT_T''@/$(HAVE_WINT_T)/g' \
+ < $(srcdir)/wctype_.h; \
+ } > $@-t
+ mv $@-t $@
+MOSTLYCLEANFILES += wctype.h wctype.h-t
+
+EXTRA_DIST += wctype_.h
+
+## end gnulib module wctype
+
+## begin gnulib module xalloc
+
+
+EXTRA_DIST += xalloc.h xmalloc.c
+
+EXTRA_libcpio_a_SOURCES += xmalloc.c
+
+## end gnulib module xalloc
+
+## begin gnulib module xalloc-die
+
+libcpio_a_SOURCES += xalloc-die.c
+
+## end gnulib module xalloc-die
+
+## begin gnulib module xgetcwd
+
+
+EXTRA_DIST += xgetcwd.c xgetcwd.h
+
+EXTRA_libcpio_a_SOURCES += xgetcwd.c
+
+## end gnulib module xgetcwd
+
+## begin gnulib module xsize
+
+libcpio_a_SOURCES += xsize.h
+
+## end gnulib module xsize
+
+## begin gnulib module xstrndup
+
+libcpio_a_SOURCES += xstrndup.h xstrndup.c
+
+## end gnulib module xstrndup
+
+
+mostlyclean-local: mostlyclean-generic
+ @for dir in '' $(MOSTLYCLEANDIRS); do \
+ if test -n "$$dir" && test -d $$dir; then \
+ echo "rmdir $$dir"; rmdir $$dir; \
+ fi; \
+ done
diff --git a/lib/hash.c b/lib/hash.c
new file mode 100644
index 0000000..f4ab12f
--- /dev/null
+++ b/lib/hash.c
@@ -0,0 +1,1048 @@
+/* hash - hashing table processing.
+
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006 Free
+ Software Foundation, Inc.
+
+ Written by Jim Meyering, 1992.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* A generic hash table package. */
+
+/* Define USE_OBSTACK to 1 if you want the allocator to use obstacks instead
+ of malloc. If you change USE_OBSTACK, you have to recompile! */
+
+#include <config.h>
+
+#include "hash.h"
+#include "xalloc.h"
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if USE_OBSTACK
+# include "obstack.h"
+# ifndef obstack_chunk_alloc
+# define obstack_chunk_alloc malloc
+# endif
+# ifndef obstack_chunk_free
+# define obstack_chunk_free free
+# endif
+#endif
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+struct hash_table
+ {
+ /* The array of buckets starts at BUCKET and extends to BUCKET_LIMIT-1,
+ for a possibility of N_BUCKETS. Among those, N_BUCKETS_USED buckets
+ are not empty, there are N_ENTRIES active entries in the table. */
+ struct hash_entry *bucket;
+ struct hash_entry const *bucket_limit;
+ size_t n_buckets;
+ size_t n_buckets_used;
+ size_t n_entries;
+
+ /* Tuning arguments, kept in a physicaly separate structure. */
+ const Hash_tuning *tuning;
+
+ /* Three functions are given to `hash_initialize', see the documentation
+ block for this function. In a word, HASHER randomizes a user entry
+ into a number up from 0 up to some maximum minus 1; COMPARATOR returns
+ true if two user entries compare equally; and DATA_FREER is the cleanup
+ function for a user entry. */
+ Hash_hasher hasher;
+ Hash_comparator comparator;
+ Hash_data_freer data_freer;
+
+ /* A linked list of freed struct hash_entry structs. */
+ struct hash_entry *free_entry_list;
+
+#if USE_OBSTACK
+ /* Whenever obstacks are used, it is possible to allocate all overflowed
+ entries into a single stack, so they all can be freed in a single
+ operation. It is not clear if the speedup is worth the trouble. */
+ struct obstack entry_stack;
+#endif
+ };
+
+/* A hash table contains many internal entries, each holding a pointer to
+ some user provided data (also called a user entry). An entry indistinctly
+ refers to both the internal entry and its associated user entry. A user
+ entry contents may be hashed by a randomization function (the hashing
+ function, or just `hasher' for short) into a number (or `slot') between 0
+ and the current table size. At each slot position in the hash table,
+ starts a linked chain of entries for which the user data all hash to this
+ slot. A bucket is the collection of all entries hashing to the same slot.
+
+ A good `hasher' function will distribute entries rather evenly in buckets.
+ In the ideal case, the length of each bucket is roughly the number of
+ entries divided by the table size. Finding the slot for a data is usually
+ done in constant time by the `hasher', and the later finding of a precise
+ entry is linear in time with the size of the bucket. Consequently, a
+ larger hash table size (that is, a larger number of buckets) is prone to
+ yielding shorter chains, *given* the `hasher' function behaves properly.
+
+ Long buckets slow down the lookup algorithm. One might use big hash table
+ sizes in hope to reduce the average length of buckets, but this might
+ become inordinate, as unused slots in the hash table take some space. The
+ best bet is to make sure you are using a good `hasher' function (beware
+ that those are not that easy to write! :-), and to use a table size
+ larger than the actual number of entries. */
+
+/* If an insertion makes the ratio of nonempty buckets to table size larger
+ than the growth threshold (a number between 0.0 and 1.0), then increase
+ the table size by multiplying by the growth factor (a number greater than
+ 1.0). The growth threshold defaults to 0.8, and the growth factor
+ defaults to 1.414, meaning that the table will have doubled its size
+ every second time 80% of the buckets get used. */
+#define DEFAULT_GROWTH_THRESHOLD 0.8
+#define DEFAULT_GROWTH_FACTOR 1.414
+
+/* If a deletion empties a bucket and causes the ratio of used buckets to
+ table size to become smaller than the shrink threshold (a number between
+ 0.0 and 1.0), then shrink the table by multiplying by the shrink factor (a
+ number greater than the shrink threshold but smaller than 1.0). The shrink
+ threshold and factor default to 0.0 and 1.0, meaning that the table never
+ shrinks. */
+#define DEFAULT_SHRINK_THRESHOLD 0.0
+#define DEFAULT_SHRINK_FACTOR 1.0
+
+/* Use this to initialize or reset a TUNING structure to
+ some sensible values. */
+static const Hash_tuning default_tuning =
+ {
+ DEFAULT_SHRINK_THRESHOLD,
+ DEFAULT_SHRINK_FACTOR,
+ DEFAULT_GROWTH_THRESHOLD,
+ DEFAULT_GROWTH_FACTOR,
+ false
+ };
+
+/* Information and lookup. */
+
+/* The following few functions provide information about the overall hash
+ table organization: the number of entries, number of buckets and maximum
+ length of buckets. */
+
+/* Return the number of buckets in the hash table. The table size, the total
+ number of buckets (used plus unused), or the maximum number of slots, are
+ the same quantity. */
+
+size_t
+hash_get_n_buckets (const Hash_table *table)
+{
+ return table->n_buckets;
+}
+
+/* Return the number of slots in use (non-empty buckets). */
+
+size_t
+hash_get_n_buckets_used (const Hash_table *table)
+{
+ return table->n_buckets_used;
+}
+
+/* Return the number of active entries. */
+
+size_t
+hash_get_n_entries (const Hash_table *table)
+{
+ return table->n_entries;
+}
+
+/* Return the length of the longest chain (bucket). */
+
+size_t
+hash_get_max_bucket_length (const Hash_table *table)
+{
+ struct hash_entry const *bucket;
+ size_t max_bucket_length = 0;
+
+ for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+ {
+ if (bucket->data)
+ {
+ struct hash_entry const *cursor = bucket;
+ size_t bucket_length = 1;
+
+ while (cursor = cursor->next, cursor)
+ bucket_length++;
+
+ if (bucket_length > max_bucket_length)
+ max_bucket_length = bucket_length;
+ }
+ }
+
+ return max_bucket_length;
+}
+
+/* Do a mild validation of a hash table, by traversing it and checking two
+ statistics. */
+
+bool
+hash_table_ok (const Hash_table *table)
+{
+ struct hash_entry const *bucket;
+ size_t n_buckets_used = 0;
+ size_t n_entries = 0;
+
+ for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+ {
+ if (bucket->data)
+ {
+ struct hash_entry const *cursor = bucket;
+
+ /* Count bucket head. */
+ n_buckets_used++;
+ n_entries++;
+
+ /* Count bucket overflow. */
+ while (cursor = cursor->next, cursor)
+ n_entries++;
+ }
+ }
+
+ if (n_buckets_used == table->n_buckets_used && n_entries == table->n_entries)
+ return true;
+
+ return false;
+}
+
+void
+hash_print_statistics (const Hash_table *table, FILE *stream)
+{
+ size_t n_entries = hash_get_n_entries (table);
+ size_t n_buckets = hash_get_n_buckets (table);
+ size_t n_buckets_used = hash_get_n_buckets_used (table);
+ size_t max_bucket_length = hash_get_max_bucket_length (table);
+
+ fprintf (stream, "# entries: %lu\n", (unsigned long int) n_entries);
+ fprintf (stream, "# buckets: %lu\n", (unsigned long int) n_buckets);
+ fprintf (stream, "# buckets used: %lu (%.2f%%)\n",
+ (unsigned long int) n_buckets_used,
+ (100.0 * n_buckets_used) / n_buckets);
+ fprintf (stream, "max bucket length: %lu\n",
+ (unsigned long int) max_bucket_length);
+}
+
+/* If ENTRY matches an entry already in the hash table, return the
+ entry from the table. Otherwise, return NULL. */
+
+void *
+hash_lookup (const Hash_table *table, const void *entry)
+{
+ struct hash_entry const *bucket
+ = table->bucket + table->hasher (entry, table->n_buckets);
+ struct hash_entry const *cursor;
+
+ if (! (bucket < table->bucket_limit))
+ abort ();
+
+ if (bucket->data == NULL)
+ return NULL;
+
+ for (cursor = bucket; cursor; cursor = cursor->next)
+ if (table->comparator (entry, cursor->data))
+ return cursor->data;
+
+ return NULL;
+}
+
+/* Walking. */
+
+/* The functions in this page traverse the hash table and process the
+ contained entries. For the traversal to work properly, the hash table
+ should not be resized nor modified while any particular entry is being
+ processed. In particular, entries should not be added or removed. */
+
+/* Return the first data in the table, or NULL if the table is empty. */
+
+void *
+hash_get_first (const Hash_table *table)
+{
+ struct hash_entry const *bucket;
+
+ if (table->n_entries == 0)
+ return NULL;
+
+ for (bucket = table->bucket; ; bucket++)
+ if (! (bucket < table->bucket_limit))
+ abort ();
+ else if (bucket->data)
+ return bucket->data;
+}
+
+/* Return the user data for the entry following ENTRY, where ENTRY has been
+ returned by a previous call to either `hash_get_first' or `hash_get_next'.
+ Return NULL if there are no more entries. */
+
+void *
+hash_get_next (const Hash_table *table, const void *entry)
+{
+ struct hash_entry const *bucket
+ = table->bucket + table->hasher (entry, table->n_buckets);
+ struct hash_entry const *cursor;
+
+ if (! (bucket < table->bucket_limit))
+ abort ();
+
+ /* Find next entry in the same bucket. */
+ for (cursor = bucket; cursor; cursor = cursor->next)
+ if (cursor->data == entry && cursor->next)
+ return cursor->next->data;
+
+ /* Find first entry in any subsequent bucket. */
+ while (++bucket < table->bucket_limit)
+ if (bucket->data)
+ return bucket->data;
+
+ /* None found. */
+ return NULL;
+}
+
+/* Fill BUFFER with pointers to active user entries in the hash table, then
+ return the number of pointers copied. Do not copy more than BUFFER_SIZE
+ pointers. */
+
+size_t
+hash_get_entries (const Hash_table *table, void **buffer,
+ size_t buffer_size)
+{
+ size_t counter = 0;
+ struct hash_entry const *bucket;
+ struct hash_entry const *cursor;
+
+ for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+ {
+ if (bucket->data)
+ {
+ for (cursor = bucket; cursor; cursor = cursor->next)
+ {
+ if (counter >= buffer_size)
+ return counter;
+ buffer[counter++] = cursor->data;
+ }
+ }
+ }
+
+ return counter;
+}
+
+/* Call a PROCESSOR function for each entry of a hash table, and return the
+ number of entries for which the processor function returned success. A
+ pointer to some PROCESSOR_DATA which will be made available to each call to
+ the processor function. The PROCESSOR accepts two arguments: the first is
+ the user entry being walked into, the second is the value of PROCESSOR_DATA
+ as received. The walking continue for as long as the PROCESSOR function
+ returns nonzero. When it returns zero, the walking is interrupted. */
+
+size_t
+hash_do_for_each (const Hash_table *table, Hash_processor processor,
+ void *processor_data)
+{
+ size_t counter = 0;
+ struct hash_entry const *bucket;
+ struct hash_entry const *cursor;
+
+ for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+ {
+ if (bucket->data)
+ {
+ for (cursor = bucket; cursor; cursor = cursor->next)
+ {
+ if (!(*processor) (cursor->data, processor_data))
+ return counter;
+ counter++;
+ }
+ }
+ }
+
+ return counter;
+}
+
+/* Allocation and clean-up. */
+
+/* Return a hash index for a NUL-terminated STRING between 0 and N_BUCKETS-1.
+ This is a convenience routine for constructing other hashing functions. */
+
+#if USE_DIFF_HASH
+
+/* About hashings, Paul Eggert writes to me (FP), on 1994-01-01: "Please see
+ B. J. McKenzie, R. Harries & T. Bell, Selecting a hashing algorithm,
+ Software--practice & experience 20, 2 (Feb 1990), 209-224. Good hash
+ algorithms tend to be domain-specific, so what's good for [diffutils'] io.c
+ may not be good for your application." */
+
+size_t
+hash_string (const char *string, size_t n_buckets)
+{
+# define ROTATE_LEFT(Value, Shift) \
+ ((Value) << (Shift) | (Value) >> ((sizeof (size_t) * CHAR_BIT) - (Shift)))
+# define HASH_ONE_CHAR(Value, Byte) \
+ ((Byte) + ROTATE_LEFT (Value, 7))
+
+ size_t value = 0;
+ unsigned char ch;
+
+ for (; (ch = *string); string++)
+ value = HASH_ONE_CHAR (value, ch);
+ return value % n_buckets;
+
+# undef ROTATE_LEFT
+# undef HASH_ONE_CHAR
+}
+
+#else /* not USE_DIFF_HASH */
+
+/* This one comes from `recode', and performs a bit better than the above as
+ per a few experiments. It is inspired from a hashing routine found in the
+ very old Cyber `snoop', itself written in typical Greg Mansfield style.
+ (By the way, what happened to this excellent man? Is he still alive?) */
+
+size_t
+hash_string (const char *string, size_t n_buckets)
+{
+ size_t value = 0;
+ unsigned char ch;
+
+ for (; (ch = *string); string++)
+ value = (value * 31 + ch) % n_buckets;
+ return value;
+}
+
+#endif /* not USE_DIFF_HASH */
+
+/* Return true if CANDIDATE is a prime number. CANDIDATE should be an odd
+ number at least equal to 11. */
+
+static bool
+is_prime (size_t candidate)
+{
+ size_t divisor = 3;
+ size_t square = divisor * divisor;
+
+ while (square < candidate && (candidate % divisor))
+ {
+ divisor++;
+ square += 4 * divisor;
+ divisor++;
+ }
+
+ return (candidate % divisor ? true : false);
+}
+
+/* Round a given CANDIDATE number up to the nearest prime, and return that
+ prime. Primes lower than 10 are merely skipped. */
+
+static size_t
+next_prime (size_t candidate)
+{
+ /* Skip small primes. */
+ if (candidate < 10)
+ candidate = 10;
+
+ /* Make it definitely odd. */
+ candidate |= 1;
+
+ while (!is_prime (candidate))
+ candidate += 2;
+
+ return candidate;
+}
+
+void
+hash_reset_tuning (Hash_tuning *tuning)
+{
+ *tuning = default_tuning;
+}
+
+/* For the given hash TABLE, check the user supplied tuning structure for
+ reasonable values, and return true if there is no gross error with it.
+ Otherwise, definitively reset the TUNING field to some acceptable default
+ in the hash table (that is, the user loses the right of further modifying
+ tuning arguments), and return false. */
+
+static bool
+check_tuning (Hash_table *table)
+{
+ const Hash_tuning *tuning = table->tuning;
+
+ /* Be a bit stricter than mathematics would require, so that
+ rounding errors in size calculations do not cause allocations to
+ fail to grow or shrink as they should. The smallest allocation
+ is 11 (due to next_prime's algorithm), so an epsilon of 0.1
+ should be good enough. */
+ float epsilon = 0.1f;
+
+ if (epsilon < tuning->growth_threshold
+ && tuning->growth_threshold < 1 - epsilon
+ && 1 + epsilon < tuning->growth_factor
+ && 0 <= tuning->shrink_threshold
+ && tuning->shrink_threshold + epsilon < tuning->shrink_factor
+ && tuning->shrink_factor <= 1
+ && tuning->shrink_threshold + epsilon < tuning->growth_threshold)
+ return true;
+
+ table->tuning = &default_tuning;
+ return false;
+}
+
+/* Allocate and return a new hash table, or NULL upon failure. The initial
+ number of buckets is automatically selected so as to _guarantee_ that you
+ may insert at least CANDIDATE different user entries before any growth of
+ the hash table size occurs. So, if have a reasonably tight a-priori upper
+ bound on the number of entries you intend to insert in the hash table, you
+ may save some table memory and insertion time, by specifying it here. If
+ the IS_N_BUCKETS field of the TUNING structure is true, the CANDIDATE
+ argument has its meaning changed to the wanted number of buckets.
+
+ TUNING points to a structure of user-supplied values, in case some fine
+ tuning is wanted over the default behavior of the hasher. If TUNING is
+ NULL, the default tuning parameters are used instead.
+
+ The user-supplied HASHER function should be provided. It accepts two
+ arguments ENTRY and TABLE_SIZE. It computes, by hashing ENTRY contents, a
+ slot number for that entry which should be in the range 0..TABLE_SIZE-1.
+ This slot number is then returned.
+
+ The user-supplied COMPARATOR function should be provided. It accepts two
+ arguments pointing to user data, it then returns true for a pair of entries
+ that compare equal, or false otherwise. This function is internally called
+ on entries which are already known to hash to the same bucket index.
+
+ The user-supplied DATA_FREER function, when not NULL, may be later called
+ with the user data as an argument, just before the entry containing the
+ data gets freed. This happens from within `hash_free' or `hash_clear'.
+ You should specify this function only if you want these functions to free
+ all of your `data' data. This is typically the case when your data is
+ simply an auxiliary struct that you have malloc'd to aggregate several
+ values. */
+
+Hash_table *
+hash_initialize (size_t candidate, const Hash_tuning *tuning,
+ Hash_hasher hasher, Hash_comparator comparator,
+ Hash_data_freer data_freer)
+{
+ Hash_table *table;
+
+ if (hasher == NULL || comparator == NULL)
+ return NULL;
+
+ table = malloc (sizeof *table);
+ if (table == NULL)
+ return NULL;
+
+ if (!tuning)
+ tuning = &default_tuning;
+ table->tuning = tuning;
+ if (!check_tuning (table))
+ {
+ /* Fail if the tuning options are invalid. This is the only occasion
+ when the user gets some feedback about it. Once the table is created,
+ if the user provides invalid tuning options, we silently revert to
+ using the defaults, and ignore further request to change the tuning
+ options. */
+ goto fail;
+ }
+
+ if (!tuning->is_n_buckets)
+ {
+ float new_candidate = candidate / tuning->growth_threshold;
+ if (SIZE_MAX <= new_candidate)
+ goto fail;
+ candidate = new_candidate;
+ }
+
+ if (xalloc_oversized (candidate, sizeof *table->bucket))
+ goto fail;
+ table->n_buckets = next_prime (candidate);
+ if (xalloc_oversized (table->n_buckets, sizeof *table->bucket))
+ goto fail;
+
+ table->bucket = calloc (table->n_buckets, sizeof *table->bucket);
+ table->bucket_limit = table->bucket + table->n_buckets;
+ table->n_buckets_used = 0;
+ table->n_entries = 0;
+
+ table->hasher = hasher;
+ table->comparator = comparator;
+ table->data_freer = data_freer;
+
+ table->free_entry_list = NULL;
+#if USE_OBSTACK
+ obstack_init (&table->entry_stack);
+#endif
+ return table;
+
+ fail:
+ free (table);
+ return NULL;
+}
+
+/* Make all buckets empty, placing any chained entries on the free list.
+ Apply the user-specified function data_freer (if any) to the datas of any
+ affected entries. */
+
+void
+hash_clear (Hash_table *table)
+{
+ struct hash_entry *bucket;
+
+ for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+ {
+ if (bucket->data)
+ {
+ struct hash_entry *cursor;
+ struct hash_entry *next;
+
+ /* Free the bucket overflow. */
+ for (cursor = bucket->next; cursor; cursor = next)
+ {
+ if (table->data_freer)
+ (*table->data_freer) (cursor->data);
+ cursor->data = NULL;
+
+ next = cursor->next;
+ /* Relinking is done one entry at a time, as it is to be expected
+ that overflows are either rare or short. */
+ cursor->next = table->free_entry_list;
+ table->free_entry_list = cursor;
+ }
+
+ /* Free the bucket head. */
+ if (table->data_freer)
+ (*table->data_freer) (bucket->data);
+ bucket->data = NULL;
+ bucket->next = NULL;
+ }
+ }
+
+ table->n_buckets_used = 0;
+ table->n_entries = 0;
+}
+
+/* Reclaim all storage associated with a hash table. If a data_freer
+ function has been supplied by the user when the hash table was created,
+ this function applies it to the data of each entry before freeing that
+ entry. */
+
+void
+hash_free (Hash_table *table)
+{
+ struct hash_entry *bucket;
+ struct hash_entry *cursor;
+ struct hash_entry *next;
+
+ /* Call the user data_freer function. */
+ if (table->data_freer && table->n_entries)
+ {
+ for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+ {
+ if (bucket->data)
+ {
+ for (cursor = bucket; cursor; cursor = cursor->next)
+ {
+ (*table->data_freer) (cursor->data);
+ }
+ }
+ }
+ }
+
+#if USE_OBSTACK
+
+ obstack_free (&table->entry_stack, NULL);
+
+#else
+
+ /* Free all bucket overflowed entries. */
+ for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+ {
+ for (cursor = bucket->next; cursor; cursor = next)
+ {
+ next = cursor->next;
+ free (cursor);
+ }
+ }
+
+ /* Also reclaim the internal list of previously freed entries. */
+ for (cursor = table->free_entry_list; cursor; cursor = next)
+ {
+ next = cursor->next;
+ free (cursor);
+ }
+
+#endif
+
+ /* Free the remainder of the hash table structure. */
+ free (table->bucket);
+ free (table);
+}
+
+/* Insertion and deletion. */
+
+/* Get a new hash entry for a bucket overflow, possibly by reclying a
+ previously freed one. If this is not possible, allocate a new one. */
+
+static struct hash_entry *
+allocate_entry (Hash_table *table)
+{
+ struct hash_entry *new;
+
+ if (table->free_entry_list)
+ {
+ new = table->free_entry_list;
+ table->free_entry_list = new->next;
+ }
+ else
+ {
+#if USE_OBSTACK
+ new = obstack_alloc (&table->entry_stack, sizeof *new);
+#else
+ new = malloc (sizeof *new);
+#endif
+ }
+
+ return new;
+}
+
+/* Free a hash entry which was part of some bucket overflow,
+ saving it for later recycling. */
+
+static void
+free_entry (Hash_table *table, struct hash_entry *entry)
+{
+ entry->data = NULL;
+ entry->next = table->free_entry_list;
+ table->free_entry_list = entry;
+}
+
+/* This private function is used to help with insertion and deletion. When
+ ENTRY matches an entry in the table, return a pointer to the corresponding
+ user data and set *BUCKET_HEAD to the head of the selected bucket.
+ Otherwise, return NULL. When DELETE is true and ENTRY matches an entry in
+ the table, unlink the matching entry. */
+
+static void *
+hash_find_entry (Hash_table *table, const void *entry,
+ struct hash_entry **bucket_head, bool delete)
+{
+ struct hash_entry *bucket
+ = table->bucket + table->hasher (entry, table->n_buckets);
+ struct hash_entry *cursor;
+
+ if (! (bucket < table->bucket_limit))
+ abort ();
+
+ *bucket_head = bucket;
+
+ /* Test for empty bucket. */
+ if (bucket->data == NULL)
+ return NULL;
+
+ /* See if the entry is the first in the bucket. */
+ if ((*table->comparator) (entry, bucket->data))
+ {
+ void *data = bucket->data;
+
+ if (delete)
+ {
+ if (bucket->next)
+ {
+ struct hash_entry *next = bucket->next;
+
+ /* Bump the first overflow entry into the bucket head, then save
+ the previous first overflow entry for later recycling. */
+ *bucket = *next;
+ free_entry (table, next);
+ }
+ else
+ {
+ bucket->data = NULL;
+ }
+ }
+
+ return data;
+ }
+
+ /* Scan the bucket overflow. */
+ for (cursor = bucket; cursor->next; cursor = cursor->next)
+ {
+ if ((*table->comparator) (entry, cursor->next->data))
+ {
+ void *data = cursor->next->data;
+
+ if (delete)
+ {
+ struct hash_entry *next = cursor->next;
+
+ /* Unlink the entry to delete, then save the freed entry for later
+ recycling. */
+ cursor->next = next->next;
+ free_entry (table, next);
+ }
+
+ return data;
+ }
+ }
+
+ /* No entry found. */
+ return NULL;
+}
+
+/* For an already existing hash table, change the number of buckets through
+ specifying CANDIDATE. The contents of the hash table are preserved. The
+ new number of buckets is automatically selected so as to _guarantee_ that
+ the table may receive at least CANDIDATE different user entries, including
+ those already in the table, before any other growth of the hash table size
+ occurs. If TUNING->IS_N_BUCKETS is true, then CANDIDATE specifies the
+ exact number of buckets desired. */
+
+bool
+hash_rehash (Hash_table *table, size_t candidate)
+{
+ Hash_table *new_table;
+ struct hash_entry *bucket;
+ struct hash_entry *cursor;
+ struct hash_entry *next;
+
+ new_table = hash_initialize (candidate, table->tuning, table->hasher,
+ table->comparator, table->data_freer);
+ if (new_table == NULL)
+ return false;
+
+ /* Merely reuse the extra old space into the new table. */
+#if USE_OBSTACK
+ obstack_free (&new_table->entry_stack, NULL);
+ new_table->entry_stack = table->entry_stack;
+#endif
+ new_table->free_entry_list = table->free_entry_list;
+
+ for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+ if (bucket->data)
+ for (cursor = bucket; cursor; cursor = next)
+ {
+ void *data = cursor->data;
+ struct hash_entry *new_bucket
+ = (new_table->bucket
+ + new_table->hasher (data, new_table->n_buckets));
+
+ if (! (new_bucket < new_table->bucket_limit))
+ abort ();
+
+ next = cursor->next;
+
+ if (new_bucket->data)
+ {
+ if (cursor == bucket)
+ {
+ /* Allocate or recycle an entry, when moving from a bucket
+ header into a bucket overflow. */
+ struct hash_entry *new_entry = allocate_entry (new_table);
+
+ if (new_entry == NULL)
+ return false;
+
+ new_entry->data = data;
+ new_entry->next = new_bucket->next;
+ new_bucket->next = new_entry;
+ }
+ else
+ {
+ /* Merely relink an existing entry, when moving from a
+ bucket overflow into a bucket overflow. */
+ cursor->next = new_bucket->next;
+ new_bucket->next = cursor;
+ }
+ }
+ else
+ {
+ /* Free an existing entry, when moving from a bucket
+ overflow into a bucket header. Also take care of the
+ simple case of moving from a bucket header into a bucket
+ header. */
+ new_bucket->data = data;
+ new_table->n_buckets_used++;
+ if (cursor != bucket)
+ free_entry (new_table, cursor);
+ }
+ }
+
+ free (table->bucket);
+ table->bucket = new_table->bucket;
+ table->bucket_limit = new_table->bucket_limit;
+ table->n_buckets = new_table->n_buckets;
+ table->n_buckets_used = new_table->n_buckets_used;
+ table->free_entry_list = new_table->free_entry_list;
+ /* table->n_entries already holds its value. */
+#if USE_OBSTACK
+ table->entry_stack = new_table->entry_stack;
+#endif
+ free (new_table);
+
+ return true;
+}
+
+/* If ENTRY matches an entry already in the hash table, return the pointer
+ to the entry from the table. Otherwise, insert ENTRY and return ENTRY.
+ Return NULL if the storage required for insertion cannot be allocated. */
+
+void *
+hash_insert (Hash_table *table, const void *entry)
+{
+ void *data;
+ struct hash_entry *bucket;
+
+ /* The caller cannot insert a NULL entry. */
+ if (! entry)
+ abort ();
+
+ /* If there's a matching entry already in the table, return that. */
+ if ((data = hash_find_entry (table, entry, &bucket, false)) != NULL)
+ return data;
+
+ /* ENTRY is not matched, it should be inserted. */
+
+ if (bucket->data)
+ {
+ struct hash_entry *new_entry = allocate_entry (table);
+
+ if (new_entry == NULL)
+ return NULL;
+
+ /* Add ENTRY in the overflow of the bucket. */
+
+ new_entry->data = (void *) entry;
+ new_entry->next = bucket->next;
+ bucket->next = new_entry;
+ table->n_entries++;
+ return (void *) entry;
+ }
+
+ /* Add ENTRY right in the bucket head. */
+
+ bucket->data = (void *) entry;
+ table->n_entries++;
+ table->n_buckets_used++;
+
+ /* If the growth threshold of the buckets in use has been reached, increase
+ the table size and rehash. There's no point in checking the number of
+ entries: if the hashing function is ill-conditioned, rehashing is not
+ likely to improve it. */
+
+ if (table->n_buckets_used
+ > table->tuning->growth_threshold * table->n_buckets)
+ {
+ /* Check more fully, before starting real work. If tuning arguments
+ became invalid, the second check will rely on proper defaults. */
+ check_tuning (table);
+ if (table->n_buckets_used
+ > table->tuning->growth_threshold * table->n_buckets)
+ {
+ const Hash_tuning *tuning = table->tuning;
+ float candidate =
+ (tuning->is_n_buckets
+ ? (table->n_buckets * tuning->growth_factor)
+ : (table->n_buckets * tuning->growth_factor
+ * tuning->growth_threshold));
+
+ if (SIZE_MAX <= candidate)
+ return NULL;
+
+ /* If the rehash fails, arrange to return NULL. */
+ if (!hash_rehash (table, candidate))
+ entry = NULL;
+ }
+ }
+
+ return (void *) entry;
+}
+
+/* If ENTRY is already in the table, remove it and return the just-deleted
+ data (the user may want to deallocate its storage). If ENTRY is not in the
+ table, don't modify the table and return NULL. */
+
+void *
+hash_delete (Hash_table *table, const void *entry)
+{
+ void *data;
+ struct hash_entry *bucket;
+
+ data = hash_find_entry (table, entry, &bucket, true);
+ if (!data)
+ return NULL;
+
+ table->n_entries--;
+ if (!bucket->data)
+ {
+ table->n_buckets_used--;
+
+ /* If the shrink threshold of the buckets in use has been reached,
+ rehash into a smaller table. */
+
+ if (table->n_buckets_used
+ < table->tuning->shrink_threshold * table->n_buckets)
+ {
+ /* Check more fully, before starting real work. If tuning arguments
+ became invalid, the second check will rely on proper defaults. */
+ check_tuning (table);
+ if (table->n_buckets_used
+ < table->tuning->shrink_threshold * table->n_buckets)
+ {
+ const Hash_tuning *tuning = table->tuning;
+ size_t candidate =
+ (tuning->is_n_buckets
+ ? table->n_buckets * tuning->shrink_factor
+ : (table->n_buckets * tuning->shrink_factor
+ * tuning->growth_threshold));
+
+ hash_rehash (table, candidate);
+ }
+ }
+ }
+
+ return data;
+}
+
+/* Testing. */
+
+#if TESTING
+
+void
+hash_print (const Hash_table *table)
+{
+ struct hash_entry const *bucket;
+
+ for (bucket = table->bucket; bucket < table->bucket_limit; bucket++)
+ {
+ struct hash_entry *cursor;
+
+ if (bucket)
+ printf ("%lu:\n", (unsigned long int) (bucket - table->bucket));
+
+ for (cursor = bucket; cursor; cursor = cursor->next)
+ {
+ char const *s = cursor->data;
+ /* FIXME */
+ if (s)
+ printf (" %s\n", s);
+ }
+ }
+}
+
+#endif /* TESTING */
diff --git a/lib/hash.h b/lib/hash.h
new file mode 100644
index 0000000..ab63a86
--- /dev/null
+++ b/lib/hash.h
@@ -0,0 +1,88 @@
+/* hash - hashing table processing.
+ Copyright (C) 1998, 1999, 2001, 2003 Free Software Foundation, Inc.
+ Written by Jim Meyering <meyering@ascend.com>, 1998.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* A generic hash table package. */
+
+/* Make sure USE_OBSTACK is defined to 1 if you want the allocator to use
+ obstacks instead of malloc, and recompile `hash.c' with same setting. */
+
+#ifndef HASH_H_
+# define HASH_H_
+
+# include <stdio.h>
+# include <stdbool.h>
+
+typedef size_t (*Hash_hasher) (const void *, size_t);
+typedef bool (*Hash_comparator) (const void *, const void *);
+typedef void (*Hash_data_freer) (void *);
+typedef bool (*Hash_processor) (void *, void *);
+
+struct hash_entry
+ {
+ void *data;
+ struct hash_entry *next;
+ };
+
+struct hash_tuning
+ {
+ /* This structure is mainly used for `hash_initialize', see the block
+ documentation of `hash_reset_tuning' for more complete comments. */
+
+ float shrink_threshold; /* ratio of used buckets to trigger a shrink */
+ float shrink_factor; /* ratio of new smaller size to original size */
+ float growth_threshold; /* ratio of used buckets to trigger a growth */
+ float growth_factor; /* ratio of new bigger size to original size */
+ bool is_n_buckets; /* if CANDIDATE really means table size */
+ };
+
+typedef struct hash_tuning Hash_tuning;
+
+struct hash_table;
+
+typedef struct hash_table Hash_table;
+
+/* Information and lookup. */
+size_t hash_get_n_buckets (const Hash_table *);
+size_t hash_get_n_buckets_used (const Hash_table *);
+size_t hash_get_n_entries (const Hash_table *);
+size_t hash_get_max_bucket_length (const Hash_table *);
+bool hash_table_ok (const Hash_table *);
+void hash_print_statistics (const Hash_table *, FILE *);
+void *hash_lookup (const Hash_table *, const void *);
+
+/* Walking. */
+void *hash_get_first (const Hash_table *);
+void *hash_get_next (const Hash_table *, const void *);
+size_t hash_get_entries (const Hash_table *, void **, size_t);
+size_t hash_do_for_each (const Hash_table *, Hash_processor, void *);
+
+/* Allocation and clean-up. */
+size_t hash_string (const char *, size_t);
+void hash_reset_tuning (Hash_tuning *);
+Hash_table *hash_initialize (size_t, const Hash_tuning *,
+ Hash_hasher, Hash_comparator,
+ Hash_data_freer);
+void hash_clear (Hash_table *);
+void hash_free (Hash_table *);
+
+/* Insertion and deletion. */
+bool hash_rehash (Hash_table *, size_t);
+void *hash_insert (Hash_table *, const void *);
+void *hash_delete (Hash_table *, const void *);
+
+#endif
diff --git a/lib/imaxtostr.c b/lib/imaxtostr.c
new file mode 100644
index 0000000..5e87ad5
--- /dev/null
+++ b/lib/imaxtostr.c
@@ -0,0 +1,3 @@
+#define inttostr imaxtostr
+#define inttype intmax_t
+#include "inttostr.c"
diff --git a/lib/intprops.h b/lib/intprops.h
new file mode 100644
index 0000000..34f971c
--- /dev/null
+++ b/lib/intprops.h
@@ -0,0 +1,78 @@
+/* intprops.h -- properties of integer types
+
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert. */
+
+#include <limits.h>
+
+/* The extra casts in the following macros work around compiler bugs,
+ e.g., in Cray C 5.0.3.0. */
+
+/* True if the arithmetic type T is an integer type. bool counts as
+ an integer. */
+#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
+
+/* True if negative values of the signed integer type T use two's
+ complement, ones' complement, or signed magnitude representation,
+ respectively. Much GNU code assumes two's complement, but some
+ people like to be portable to all possible C hosts. */
+#define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
+#define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0)
+#define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1)
+
+/* True if the arithmetic type T is signed. */
+#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+
+/* The maximum and minimum values for the integer type T. These
+ macros have undefined behavior if T is signed and has padding bits.
+ If this is a problem for you, please let us know how to fix it for
+ your host. */
+#define TYPE_MINIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) 0 \
+ : TYPE_SIGNED_MAGNITUDE (t) \
+ ? ~ (t) 0 \
+ : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))
+#define TYPE_MAXIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) -1 \
+ : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
+
+/* Return zero if T can be determined to be an unsigned type.
+ Otherwise, return 1.
+ When compiling with GCC, INT_STRLEN_BOUND uses this macro to obtain a
+ tighter bound. Otherwise, it overestimates the true bound by one byte
+ when applied to unsigned types of size 2, 4, 16, ... bytes.
+ The symbol signed_type_or_expr__ is private to this header file. */
+#if __GNUC__ >= 2
+# define signed_type_or_expr__(t) TYPE_SIGNED (__typeof__ (t))
+#else
+# define signed_type_or_expr__(t) 1
+#endif
+
+/* Bound on length of the string representing an integer type or expression T.
+ Subtract 1 for the sign bit if T is signed; log10 (2.0) < 146/485;
+ add 1 for integer division truncation; add 1 more for a minus sign
+ if needed. */
+#define INT_STRLEN_BOUND(t) \
+ ((sizeof (t) * CHAR_BIT - signed_type_or_expr__ (t)) * 146 / 485 \
+ + signed_type_or_expr__ (t) + 1)
+
+/* Bound on buffer size needed to represent an integer type or expression T,
+ including the terminating null. */
+#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1)
diff --git a/lib/inttostr.c b/lib/inttostr.c
new file mode 100644
index 0000000..246d658
--- /dev/null
+++ b/lib/inttostr.c
@@ -0,0 +1,51 @@
+/* inttostr.c -- convert integers to printable strings
+
+ Copyright (C) 2001, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert */
+
+#include <config.h>
+
+#include "inttostr.h"
+
+/* Convert I to a printable string in BUF, which must be at least
+ INT_BUFSIZE_BOUND (INTTYPE) bytes long. Return the address of the
+ printable string, which need not start at BUF. */
+
+char *
+inttostr (inttype i, char *buf)
+{
+ char *p = buf + INT_STRLEN_BOUND (inttype);
+ *p = 0;
+
+ if (i < 0)
+ {
+ do
+ *--p = '0' - i % 10;
+ while ((i /= 10) != 0);
+
+ *--p = '-';
+ }
+ else
+ {
+ do
+ *--p = '0' + i % 10;
+ while ((i /= 10) != 0);
+ }
+
+ return p;
+}
diff --git a/lib/inttostr.h b/lib/inttostr.h
new file mode 100644
index 0000000..31258ca
--- /dev/null
+++ b/lib/inttostr.h
@@ -0,0 +1,30 @@
+/* inttostr.h -- convert integers to printable strings
+
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+ Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "intprops.h"
+
+char *offtostr (off_t, char *);
+char *imaxtostr (intmax_t, char *);
+char *umaxtostr (uintmax_t, char *);
+char *uinttostr (unsigned int, char *);
diff --git a/lib/inttypes_.h b/lib/inttypes_.h
new file mode 100644
index 0000000..6d78325
--- /dev/null
+++ b/lib/inttypes_.h
@@ -0,0 +1,1100 @@
+/* Copyright (C) 2006-2007 Free Software Foundation, Inc.
+ Written by Paul Eggert, Bruno Haible, Derek Price.
+ This file is part of gnulib.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1, 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 Lesser 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. */
+
+/*
+ * ISO C 99 <inttypes.h> for platforms that lack it.
+ * <http://www.opengroup.org/susv3xbd/inttypes.h.html>
+ */
+
+/* Include the original <inttypes.h> if it exists, and if this file
+ has not been included yet or if this file includes gnulib stdint.h
+ which in turn includes this file.
+ The include_next requires a split double-inclusion guard. */
+#if ! defined INTTYPES_H || defined _GL_JUST_INCLUDE_ABSOLUTE_INTTYPES_H
+# if @HAVE_INTTYPES_H@
+# if @HAVE_INCLUDE_NEXT@
+# include_next <inttypes.h>
+# else
+# include @ABSOLUTE_INTTYPES_H@
+# endif
+# endif
+#endif
+
+#if ! defined INTTYPES_H && ! defined _GL_JUST_INCLUDE_ABSOLUTE_INTTYPES_H
+#define INTTYPES_H
+
+/* Include <stdint.h> or the gnulib replacement. */
+#include <stdint.h>
+/* Get CHAR_BIT. */
+#include <limits.h>
+
+#if !(INT_MIN == INT32_MIN && INT_MAX == INT32_MAX)
+# error "This file assumes that 'int' has exactly 32 bits. Please report your platform and compiler to <bug-gnulib@gnu.org>."
+#endif
+
+/* The definition of GL_LINK_WARNING is copied here. */
+
+/* 7.8.1 Macros for format specifiers */
+
+#if ! defined __cplusplus || defined __STDC_FORMAT_MACROS
+
+# if defined _TNS_R_TARGET
+ /* Tandem NonStop R series and compatible platforms released before
+ July 2005 support %Ld but not %lld. */
+# define _LONG_LONG_FORMAT_PREFIX "L"
+# else
+# define _LONG_LONG_FORMAT_PREFIX "ll"
+# endif
+
+# if !defined PRId8 || @PRI_MACROS_BROKEN@
+# undef PRId8
+# ifdef INT8_MAX
+# define PRId8 "d"
+# endif
+# endif
+# if !defined PRIi8 || @PRI_MACROS_BROKEN@
+# undef PRIi8
+# ifdef INT8_MAX
+# define PRIi8 "i"
+# endif
+# endif
+# if !defined PRIo8 || @PRI_MACROS_BROKEN@
+# undef PRIo8
+# ifdef UINT8_MAX
+# define PRIo8 "o"
+# endif
+# endif
+# if !defined PRIu8 || @PRI_MACROS_BROKEN@
+# undef PRIu8
+# ifdef UINT8_MAX
+# define PRIu8 "u"
+# endif
+# endif
+# if !defined PRIx8 || @PRI_MACROS_BROKEN@
+# undef PRIx8
+# ifdef UINT8_MAX
+# define PRIx8 "x"
+# endif
+# endif
+# if !defined PRIX8 || @PRI_MACROS_BROKEN@
+# undef PRIX8
+# ifdef UINT8_MAX
+# define PRIX8 "X"
+# endif
+# endif
+# if !defined PRId16 || @PRI_MACROS_BROKEN@
+# undef PRId16
+# ifdef INT16_MAX
+# define PRId16 "d"
+# endif
+# endif
+# if !defined PRIi16 || @PRI_MACROS_BROKEN@
+# undef PRIi16
+# ifdef INT16_MAX
+# define PRIi16 "i"
+# endif
+# endif
+# if !defined PRIo16 || @PRI_MACROS_BROKEN@
+# undef PRIo16
+# ifdef UINT16_MAX
+# define PRIo16 "o"
+# endif
+# endif
+# if !defined PRIu16 || @PRI_MACROS_BROKEN@
+# undef PRIu16
+# ifdef UINT16_MAX
+# define PRIu16 "u"
+# endif
+# endif
+# if !defined PRIx16 || @PRI_MACROS_BROKEN@
+# undef PRIx16
+# ifdef UINT16_MAX
+# define PRIx16 "x"
+# endif
+# endif
+# if !defined PRIX16 || @PRI_MACROS_BROKEN@
+# undef PRIX16
+# ifdef UINT16_MAX
+# define PRIX16 "X"
+# endif
+# endif
+# if !defined PRId32 || @PRI_MACROS_BROKEN@
+# undef PRId32
+# ifdef INT32_MAX
+# define PRId32 "d"
+# endif
+# endif
+# if !defined PRIi32 || @PRI_MACROS_BROKEN@
+# undef PRIi32
+# ifdef INT32_MAX
+# define PRIi32 "i"
+# endif
+# endif
+# if !defined PRIo32 || @PRI_MACROS_BROKEN@
+# undef PRIo32
+# ifdef UINT32_MAX
+# define PRIo32 "o"
+# endif
+# endif
+# if !defined PRIu32 || @PRI_MACROS_BROKEN@
+# undef PRIu32
+# ifdef UINT32_MAX
+# define PRIu32 "u"
+# endif
+# endif
+# if !defined PRIx32 || @PRI_MACROS_BROKEN@
+# undef PRIx32
+# ifdef UINT32_MAX
+# define PRIx32 "x"
+# endif
+# endif
+# if !defined PRIX32 || @PRI_MACROS_BROKEN@
+# undef PRIX32
+# ifdef UINT32_MAX
+# define PRIX32 "X"
+# endif
+# endif
+# ifdef INT64_MAX
+# if INT64_MAX == LONG_MAX
+# define _PRI64_PREFIX "l"
+# elif defined _MSC_VER || defined __MINGW32__
+# define _PRI64_PREFIX "I64"
+# elif @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1
+# define _PRI64_PREFIX _LONG_LONG_FORMAT_PREFIX
+# endif
+# if !defined PRId64 || @PRI_MACROS_BROKEN@
+# undef PRId64
+# define PRId64 _PRI64_PREFIX "d"
+# endif
+# if !defined PRIi64 || @PRI_MACROS_BROKEN@
+# undef PRIi64
+# define PRIi64 _PRI64_PREFIX "i"
+# endif
+# endif
+# ifdef UINT64_MAX
+# if UINT64_MAX == ULONG_MAX
+# define _PRIu64_PREFIX "l"
+# elif defined _MSC_VER || defined __MINGW32__
+# define _PRIu64_PREFIX "I64"
+# elif @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1
+# define _PRIu64_PREFIX _LONG_LONG_FORMAT_PREFIX
+# endif
+# if !defined PRIo64 || @PRI_MACROS_BROKEN@
+# undef PRIo64
+# define PRIo64 _PRIu64_PREFIX "o"
+# endif
+# if !defined PRIu64 || @PRI_MACROS_BROKEN@
+# undef PRIu64
+# define PRIu64 _PRIu64_PREFIX "u"
+# endif
+# if !defined PRIx64 || @PRI_MACROS_BROKEN@
+# undef PRIx64
+# define PRIx64 _PRIu64_PREFIX "x"
+# endif
+# if !defined PRIX64 || @PRI_MACROS_BROKEN@
+# undef PRIX64
+# define PRIX64 _PRIu64_PREFIX "X"
+# endif
+# endif
+
+# if !defined PRIdLEAST8 || @PRI_MACROS_BROKEN@
+# undef PRIdLEAST8
+# define PRIdLEAST8 "d"
+# endif
+# if !defined PRIiLEAST8 || @PRI_MACROS_BROKEN@
+# undef PRIiLEAST8
+# define PRIiLEAST8 "i"
+# endif
+# if !defined PRIoLEAST8 || @PRI_MACROS_BROKEN@
+# undef PRIoLEAST8
+# define PRIoLEAST8 "o"
+# endif
+# if !defined PRIuLEAST8 || @PRI_MACROS_BROKEN@
+# undef PRIuLEAST8
+# define PRIuLEAST8 "u"
+# endif
+# if !defined PRIxLEAST8 || @PRI_MACROS_BROKEN@
+# undef PRIxLEAST8
+# define PRIxLEAST8 "x"
+# endif
+# if !defined PRIXLEAST8 || @PRI_MACROS_BROKEN@
+# undef PRIXLEAST8
+# define PRIXLEAST8 "X"
+# endif
+# if !defined PRIdLEAST16 || @PRI_MACROS_BROKEN@
+# undef PRIdLEAST16
+# define PRIdLEAST16 "d"
+# endif
+# if !defined PRIiLEAST16 || @PRI_MACROS_BROKEN@
+# undef PRIiLEAST16
+# define PRIiLEAST16 "i"
+# endif
+# if !defined PRIoLEAST16 || @PRI_MACROS_BROKEN@
+# undef PRIoLEAST16
+# define PRIoLEAST16 "o"
+# endif
+# if !defined PRIuLEAST16 || @PRI_MACROS_BROKEN@
+# undef PRIuLEAST16
+# define PRIuLEAST16 "u"
+# endif
+# if !defined PRIxLEAST16 || @PRI_MACROS_BROKEN@
+# undef PRIxLEAST16
+# define PRIxLEAST16 "x"
+# endif
+# if !defined PRIXLEAST16 || @PRI_MACROS_BROKEN@
+# undef PRIXLEAST16
+# define PRIXLEAST16 "X"
+# endif
+# if !defined PRIdLEAST32 || @PRI_MACROS_BROKEN@
+# undef PRIdLEAST32
+# define PRIdLEAST32 "d"
+# endif
+# if !defined PRIiLEAST32 || @PRI_MACROS_BROKEN@
+# undef PRIiLEAST32
+# define PRIiLEAST32 "i"
+# endif
+# if !defined PRIoLEAST32 || @PRI_MACROS_BROKEN@
+# undef PRIoLEAST32
+# define PRIoLEAST32 "o"
+# endif
+# if !defined PRIuLEAST32 || @PRI_MACROS_BROKEN@
+# undef PRIuLEAST32
+# define PRIuLEAST32 "u"
+# endif
+# if !defined PRIxLEAST32 || @PRI_MACROS_BROKEN@
+# undef PRIxLEAST32
+# define PRIxLEAST32 "x"
+# endif
+# if !defined PRIXLEAST32 || @PRI_MACROS_BROKEN@
+# undef PRIXLEAST32
+# define PRIXLEAST32 "X"
+# endif
+# ifdef INT64_MAX
+# if !defined PRIdLEAST64 || @PRI_MACROS_BROKEN@
+# undef PRIdLEAST64
+# define PRIdLEAST64 PRId64
+# endif
+# if !defined PRIiLEAST64 || @PRI_MACROS_BROKEN@
+# undef PRIiLEAST64
+# define PRIiLEAST64 PRIi64
+# endif
+# endif
+# ifdef UINT64_MAX
+# if !defined PRIoLEAST64 || @PRI_MACROS_BROKEN@
+# undef PRIoLEAST64
+# define PRIoLEAST64 PRIo64
+# endif
+# if !defined PRIuLEAST64 || @PRI_MACROS_BROKEN@
+# undef PRIuLEAST64
+# define PRIuLEAST64 PRIu64
+# endif
+# if !defined PRIxLEAST64 || @PRI_MACROS_BROKEN@
+# undef PRIxLEAST64
+# define PRIxLEAST64 PRIx64
+# endif
+# if !defined PRIXLEAST64 || @PRI_MACROS_BROKEN@
+# undef PRIXLEAST64
+# define PRIXLEAST64 PRIX64
+# endif
+# endif
+
+# if !defined PRIdFAST8 || @PRI_MACROS_BROKEN@
+# undef PRIdFAST8
+# if INT_FAST8_MAX > INT32_MAX
+# define PRIdFAST8 PRId64
+# else
+# define PRIdFAST8 "d"
+# endif
+# endif
+# if !defined PRIiFAST8 || @PRI_MACROS_BROKEN@
+# undef PRIiFAST8
+# if INT_FAST8_MAX > INT32_MAX
+# define PRIiFAST8 PRIi64
+# else
+# define PRIiFAST8 "i"
+# endif
+# endif
+# if !defined PRIoFAST8 || @PRI_MACROS_BROKEN@
+# undef PRIoFAST8
+# if UINT_FAST8_MAX > UINT32_MAX
+# define PRIoFAST8 PRIo64
+# else
+# define PRIoFAST8 "o"
+# endif
+# endif
+# if !defined PRIuFAST8 || @PRI_MACROS_BROKEN@
+# undef PRIuFAST8
+# if UINT_FAST8_MAX > UINT32_MAX
+# define PRIuFAST8 PRIu64
+# else
+# define PRIuFAST8 "u"
+# endif
+# endif
+# if !defined PRIxFAST8 || @PRI_MACROS_BROKEN@
+# undef PRIxFAST8
+# if UINT_FAST8_MAX > UINT32_MAX
+# define PRIxFAST8 PRIx64
+# else
+# define PRIxFAST8 "x"
+# endif
+# endif
+# if !defined PRIXFAST8 || @PRI_MACROS_BROKEN@
+# undef PRIXFAST8
+# if UINT_FAST8_MAX > UINT32_MAX
+# define PRIXFAST8 PRIX64
+# else
+# define PRIXFAST8 "X"
+# endif
+# endif
+# if !defined PRIdFAST16 || @PRI_MACROS_BROKEN@
+# undef PRIdFAST16
+# if INT_FAST16_MAX > INT32_MAX
+# define PRIdFAST16 PRId64
+# else
+# define PRIdFAST16 "d"
+# endif
+# endif
+# if !defined PRIiFAST16 || @PRI_MACROS_BROKEN@
+# undef PRIiFAST16
+# if INT_FAST16_MAX > INT32_MAX
+# define PRIiFAST16 PRIi64
+# else
+# define PRIiFAST16 "i"
+# endif
+# endif
+# if !defined PRIoFAST16 || @PRI_MACROS_BROKEN@
+# undef PRIoFAST16
+# if UINT_FAST16_MAX > UINT32_MAX
+# define PRIoFAST16 PRIo64
+# else
+# define PRIoFAST16 "o"
+# endif
+# endif
+# if !defined PRIuFAST16 || @PRI_MACROS_BROKEN@
+# undef PRIuFAST16
+# if UINT_FAST16_MAX > UINT32_MAX
+# define PRIuFAST16 PRIu64
+# else
+# define PRIuFAST16 "u"
+# endif
+# endif
+# if !defined PRIxFAST16 || @PRI_MACROS_BROKEN@
+# undef PRIxFAST16
+# if UINT_FAST16_MAX > UINT32_MAX
+# define PRIxFAST16 PRIx64
+# else
+# define PRIxFAST16 "x"
+# endif
+# endif
+# if !defined PRIXFAST16 || @PRI_MACROS_BROKEN@
+# undef PRIXFAST16
+# if UINT_FAST16_MAX > UINT32_MAX
+# define PRIXFAST16 PRIX64
+# else
+# define PRIXFAST16 "X"
+# endif
+# endif
+# if !defined PRIdFAST32 || @PRI_MACROS_BROKEN@
+# undef PRIdFAST32
+# if INT_FAST32_MAX > INT32_MAX
+# define PRIdFAST32 PRId64
+# else
+# define PRIdFAST32 "d"
+# endif
+# endif
+# if !defined PRIiFAST32 || @PRI_MACROS_BROKEN@
+# undef PRIiFAST32
+# if INT_FAST32_MAX > INT32_MAX
+# define PRIiFAST32 PRIi64
+# else
+# define PRIiFAST32 "i"
+# endif
+# endif
+# if !defined PRIoFAST32 || @PRI_MACROS_BROKEN@
+# undef PRIoFAST32
+# if UINT_FAST32_MAX > UINT32_MAX
+# define PRIoFAST32 PRIo64
+# else
+# define PRIoFAST32 "o"
+# endif
+# endif
+# if !defined PRIuFAST32 || @PRI_MACROS_BROKEN@
+# undef PRIuFAST32
+# if UINT_FAST32_MAX > UINT32_MAX
+# define PRIuFAST32 PRIu64
+# else
+# define PRIuFAST32 "u"
+# endif
+# endif
+# if !defined PRIxFAST32 || @PRI_MACROS_BROKEN@
+# undef PRIxFAST32
+# if UINT_FAST32_MAX > UINT32_MAX
+# define PRIxFAST32 PRIx64
+# else
+# define PRIxFAST32 "x"
+# endif
+# endif
+# if !defined PRIXFAST32 || @PRI_MACROS_BROKEN@
+# undef PRIXFAST32
+# if UINT_FAST32_MAX > UINT32_MAX
+# define PRIXFAST32 PRIX64
+# else
+# define PRIXFAST32 "X"
+# endif
+# endif
+# ifdef INT64_MAX
+# if !defined PRIdFAST64 || @PRI_MACROS_BROKEN@
+# undef PRIdFAST64
+# define PRIdFAST64 PRId64
+# endif
+# if !defined PRIiFAST64 || @PRI_MACROS_BROKEN@
+# undef PRIiFAST64
+# define PRIiFAST64 PRIi64
+# endif
+# endif
+# ifdef UINT64_MAX
+# if !defined PRIoFAST64 || @PRI_MACROS_BROKEN@
+# undef PRIoFAST64
+# define PRIoFAST64 PRIo64
+# endif
+# if !defined PRIuFAST64 || @PRI_MACROS_BROKEN@
+# undef PRIuFAST64
+# define PRIuFAST64 PRIu64
+# endif
+# if !defined PRIxFAST64 || @PRI_MACROS_BROKEN@
+# undef PRIxFAST64
+# define PRIxFAST64 PRIx64
+# endif
+# if !defined PRIXFAST64 || @PRI_MACROS_BROKEN@
+# undef PRIXFAST64
+# define PRIXFAST64 PRIX64
+# endif
+# endif
+
+# if !defined PRIdMAX || @PRI_MACROS_BROKEN@
+# undef PRIdMAX
+# if INTMAX_MAX > INT32_MAX
+# define PRIdMAX PRId64
+# else
+# define PRIdMAX "ld"
+# endif
+# endif
+# if !defined PRIiMAX || @PRI_MACROS_BROKEN@
+# undef PRIiMAX
+# if INTMAX_MAX > INT32_MAX
+# define PRIiMAX PRIi64
+# else
+# define PRIiMAX "li"
+# endif
+# endif
+# if !defined PRIoMAX || @PRI_MACROS_BROKEN@
+# undef PRIoMAX
+# if UINTMAX_MAX > UINT32_MAX
+# define PRIoMAX PRIo64
+# else
+# define PRIoMAX "lo"
+# endif
+# endif
+# if !defined PRIuMAX || @PRI_MACROS_BROKEN@
+# undef PRIuMAX
+# if UINTMAX_MAX > UINT32_MAX
+# define PRIuMAX PRIu64
+# else
+# define PRIuMAX "lu"
+# endif
+# endif
+# if !defined PRIxMAX || @PRI_MACROS_BROKEN@
+# undef PRIxMAX
+# if UINTMAX_MAX > UINT32_MAX
+# define PRIxMAX PRIx64
+# else
+# define PRIxMAX "lx"
+# endif
+# endif
+# if !defined PRIXMAX || @PRI_MACROS_BROKEN@
+# undef PRIXMAX
+# if UINTMAX_MAX > UINT32_MAX
+# define PRIXMAX PRIX64
+# else
+# define PRIXMAX "lX"
+# endif
+# endif
+
+# if !defined PRIdPTR || @PRI_MACROS_BROKEN@
+# undef PRIdPTR
+# ifdef INTPTR_MAX
+# define PRIdPTR @PRIPTR_PREFIX@ "d"
+# endif
+# endif
+# if !defined PRIiPTR || @PRI_MACROS_BROKEN@
+# undef PRIiPTR
+# ifdef INTPTR_MAX
+# define PRIiPTR @PRIPTR_PREFIX@ "i"
+# endif
+# endif
+# if !defined PRIoPTR || @PRI_MACROS_BROKEN@
+# undef PRIoPTR
+# ifdef UINTPTR_MAX
+# define PRIoPTR @PRIPTR_PREFIX@ "o"
+# endif
+# endif
+# if !defined PRIuPTR || @PRI_MACROS_BROKEN@
+# undef PRIuPTR
+# ifdef UINTPTR_MAX
+# define PRIuPTR @PRIPTR_PREFIX@ "u"
+# endif
+# endif
+# if !defined PRIxPTR || @PRI_MACROS_BROKEN@
+# undef PRIxPTR
+# ifdef UINTPTR_MAX
+# define PRIxPTR @PRIPTR_PREFIX@ "x"
+# endif
+# endif
+# if !defined PRIXPTR || @PRI_MACROS_BROKEN@
+# undef PRIXPTR
+# ifdef UINTPTR_MAX
+# define PRIXPTR @PRIPTR_PREFIX@ "X"
+# endif
+# endif
+
+# if !defined SCNd8 || @PRI_MACROS_BROKEN@
+# undef SCNd8
+# ifdef INT8_MAX
+# define SCNd8 "hhd"
+# endif
+# endif
+# if !defined SCNi8 || @PRI_MACROS_BROKEN@
+# undef SCNi8
+# ifdef INT8_MAX
+# define SCNi8 "hhi"
+# endif
+# endif
+# if !defined SCNo8 || @PRI_MACROS_BROKEN@
+# undef SCNo8
+# ifdef UINT8_MAX
+# define SCNo8 "hho"
+# endif
+# endif
+# if !defined SCNu8 || @PRI_MACROS_BROKEN@
+# undef SCNu8
+# ifdef UINT8_MAX
+# define SCNu8 "hhu"
+# endif
+# endif
+# if !defined SCNx8 || @PRI_MACROS_BROKEN@
+# undef SCNx8
+# ifdef UINT8_MAX
+# define SCNx8 "hhx"
+# endif
+# endif
+# if !defined SCNd16 || @PRI_MACROS_BROKEN@
+# undef SCNd16
+# ifdef INT16_MAX
+# define SCNd16 "hd"
+# endif
+# endif
+# if !defined SCNi16 || @PRI_MACROS_BROKEN@
+# undef SCNi16
+# ifdef INT16_MAX
+# define SCNi16 "hi"
+# endif
+# endif
+# if !defined SCNo16 || @PRI_MACROS_BROKEN@
+# undef SCNo16
+# ifdef UINT16_MAX
+# define SCNo16 "ho"
+# endif
+# endif
+# if !defined SCNu16 || @PRI_MACROS_BROKEN@
+# undef SCNu16
+# ifdef UINT16_MAX
+# define SCNu16 "hu"
+# endif
+# endif
+# if !defined SCNx16 || @PRI_MACROS_BROKEN@
+# undef SCNx16
+# ifdef UINT16_MAX
+# define SCNx16 "hx"
+# endif
+# endif
+# if !defined SCNd32 || @PRI_MACROS_BROKEN@
+# undef SCNd32
+# ifdef INT32_MAX
+# define SCNd32 "d"
+# endif
+# endif
+# if !defined SCNi32 || @PRI_MACROS_BROKEN@
+# undef SCNi32
+# ifdef INT32_MAX
+# define SCNi32 "i"
+# endif
+# endif
+# if !defined SCNo32 || @PRI_MACROS_BROKEN@
+# undef SCNo32
+# ifdef UINT32_MAX
+# define SCNo32 "o"
+# endif
+# endif
+# if !defined SCNu32 || @PRI_MACROS_BROKEN@
+# undef SCNu32
+# ifdef UINT32_MAX
+# define SCNu32 "u"
+# endif
+# endif
+# if !defined SCNx32 || @PRI_MACROS_BROKEN@
+# undef SCNx32
+# ifdef UINT32_MAX
+# define SCNx32 "x"
+# endif
+# endif
+# ifdef INT64_MAX
+# if INT64_MAX == LONG_MAX
+# define _SCN64_PREFIX "l"
+# elif defined _MSC_VER || defined __MINGW32__
+# define _SCN64_PREFIX "I64"
+# elif @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1
+# define _SCN64_PREFIX _LONG_LONG_FORMAT_PREFIX
+# endif
+# if !defined SCNd64 || @PRI_MACROS_BROKEN@
+# undef SCNd64
+# define SCNd64 _SCN64_PREFIX "d"
+# endif
+# if !defined SCNi64 || @PRI_MACROS_BROKEN@
+# undef SCNi64
+# define SCNi64 _SCN64_PREFIX "i"
+# endif
+# endif
+# ifdef UINT64_MAX
+# if UINT64_MAX == ULONG_MAX
+# define _SCNu64_PREFIX "l"
+# elif defined _MSC_VER || defined __MINGW32__
+# define _SCNu64_PREFIX "I64"
+# elif @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1
+# define _SCNu64_PREFIX _LONG_LONG_FORMAT_PREFIX
+# endif
+# if !defined SCNo64 || @PRI_MACROS_BROKEN@
+# undef SCNo64
+# define SCNo64 _SCNu64_PREFIX "o"
+# endif
+# if !defined SCNu64 || @PRI_MACROS_BROKEN@
+# undef SCNu64
+# define SCNu64 _SCNu64_PREFIX "u"
+# endif
+# if !defined SCNx64 || @PRI_MACROS_BROKEN@
+# undef SCNx64
+# define SCNx64 _SCNu64_PREFIX "x"
+# endif
+# endif
+
+# if !defined SCNdLEAST8 || @PRI_MACROS_BROKEN@
+# undef SCNdLEAST8
+# define SCNdLEAST8 "hhd"
+# endif
+# if !defined SCNiLEAST8 || @PRI_MACROS_BROKEN@
+# undef SCNiLEAST8
+# define SCNiLEAST8 "hhi"
+# endif
+# if !defined SCNoLEAST8 || @PRI_MACROS_BROKEN@
+# undef SCNoLEAST8
+# define SCNoLEAST8 "hho"
+# endif
+# if !defined SCNuLEAST8 || @PRI_MACROS_BROKEN@
+# undef SCNuLEAST8
+# define SCNuLEAST8 "hhu"
+# endif
+# if !defined SCNxLEAST8 || @PRI_MACROS_BROKEN@
+# undef SCNxLEAST8
+# define SCNxLEAST8 "hhx"
+# endif
+# if !defined SCNdLEAST16 || @PRI_MACROS_BROKEN@
+# undef SCNdLEAST16
+# define SCNdLEAST16 "hd"
+# endif
+# if !defined SCNiLEAST16 || @PRI_MACROS_BROKEN@
+# undef SCNiLEAST16
+# define SCNiLEAST16 "hi"
+# endif
+# if !defined SCNoLEAST16 || @PRI_MACROS_BROKEN@
+# undef SCNoLEAST16
+# define SCNoLEAST16 "ho"
+# endif
+# if !defined SCNuLEAST16 || @PRI_MACROS_BROKEN@
+# undef SCNuLEAST16
+# define SCNuLEAST16 "hu"
+# endif
+# if !defined SCNxLEAST16 || @PRI_MACROS_BROKEN@
+# undef SCNxLEAST16
+# define SCNxLEAST16 "hx"
+# endif
+# if !defined SCNdLEAST32 || @PRI_MACROS_BROKEN@
+# undef SCNdLEAST32
+# define SCNdLEAST32 "d"
+# endif
+# if !defined SCNiLEAST32 || @PRI_MACROS_BROKEN@
+# undef SCNiLEAST32
+# define SCNiLEAST32 "i"
+# endif
+# if !defined SCNoLEAST32 || @PRI_MACROS_BROKEN@
+# undef SCNoLEAST32
+# define SCNoLEAST32 "o"
+# endif
+# if !defined SCNuLEAST32 || @PRI_MACROS_BROKEN@
+# undef SCNuLEAST32
+# define SCNuLEAST32 "u"
+# endif
+# if !defined SCNxLEAST32 || @PRI_MACROS_BROKEN@
+# undef SCNxLEAST32
+# define SCNxLEAST32 "x"
+# endif
+# ifdef INT64_MAX
+# if !defined SCNdLEAST64 || @PRI_MACROS_BROKEN@
+# undef SCNdLEAST64
+# define SCNdLEAST64 SCNd64
+# endif
+# if !defined SCNiLEAST64 || @PRI_MACROS_BROKEN@
+# undef SCNiLEAST64
+# define SCNiLEAST64 SCNi64
+# endif
+# endif
+# ifdef UINT64_MAX
+# if !defined SCNoLEAST64 || @PRI_MACROS_BROKEN@
+# undef SCNoLEAST64
+# define SCNoLEAST64 SCNo64
+# endif
+# if !defined SCNuLEAST64 || @PRI_MACROS_BROKEN@
+# undef SCNuLEAST64
+# define SCNuLEAST64 SCNu64
+# endif
+# if !defined SCNxLEAST64 || @PRI_MACROS_BROKEN@
+# undef SCNxLEAST64
+# define SCNxLEAST64 SCNx64
+# endif
+# endif
+
+# if !defined SCNdFAST8 || @PRI_MACROS_BROKEN@
+# undef SCNdFAST8
+# if INT_FAST8_MAX > INT32_MAX
+# define SCNdFAST8 SCNd64
+# elif INT_FAST8_MAX == 0x7fff
+# define SCNdFAST8 "hd"
+# elif INT_FAST8_MAX == 0x7f
+# define SCNdFAST8 "hhd"
+# else
+# define SCNdFAST8 "d"
+# endif
+# endif
+# if !defined SCNiFAST8 || @PRI_MACROS_BROKEN@
+# undef SCNiFAST8
+# if INT_FAST8_MAX > INT32_MAX
+# define SCNiFAST8 SCNi64
+# elif INT_FAST8_MAX == 0x7fff
+# define SCNiFAST8 "hi"
+# elif INT_FAST8_MAX == 0x7f
+# define SCNiFAST8 "hhi"
+# else
+# define SCNiFAST8 "i"
+# endif
+# endif
+# if !defined SCNoFAST8 || @PRI_MACROS_BROKEN@
+# undef SCNoFAST8
+# if UINT_FAST8_MAX > UINT32_MAX
+# define SCNoFAST8 SCNo64
+# elif UINT_FAST8_MAX == 0xffff
+# define SCNoFAST8 "ho"
+# elif UINT_FAST8_MAX == 0xff
+# define SCNoFAST8 "hho"
+# else
+# define SCNoFAST8 "o"
+# endif
+# endif
+# if !defined SCNuFAST8 || @PRI_MACROS_BROKEN@
+# undef SCNuFAST8
+# if UINT_FAST8_MAX > UINT32_MAX
+# define SCNuFAST8 SCNu64
+# elif UINT_FAST8_MAX == 0xffff
+# define SCNuFAST8 "hu"
+# elif UINT_FAST8_MAX == 0xff
+# define SCNuFAST8 "hhu"
+# else
+# define SCNuFAST8 "u"
+# endif
+# endif
+# if !defined SCNxFAST8 || @PRI_MACROS_BROKEN@
+# undef SCNxFAST8
+# if UINT_FAST8_MAX > UINT32_MAX
+# define SCNxFAST8 SCNx64
+# elif UINT_FAST8_MAX == 0xffff
+# define SCNxFAST8 "hx"
+# elif UINT_FAST8_MAX == 0xff
+# define SCNxFAST8 "hhx"
+# else
+# define SCNxFAST8 "x"
+# endif
+# endif
+# if !defined SCNdFAST16 || @PRI_MACROS_BROKEN@
+# undef SCNdFAST16
+# if INT_FAST16_MAX > INT32_MAX
+# define SCNdFAST16 SCNd64
+# elif INT_FAST16_MAX == 0x7fff
+# define SCNdFAST16 "hd"
+# else
+# define SCNdFAST16 "d"
+# endif
+# endif
+# if !defined SCNiFAST16 || @PRI_MACROS_BROKEN@
+# undef SCNiFAST16
+# if INT_FAST16_MAX > INT32_MAX
+# define SCNiFAST16 SCNi64
+# elif INT_FAST16_MAX == 0x7fff
+# define SCNiFAST16 "hi"
+# else
+# define SCNiFAST16 "i"
+# endif
+# endif
+# if !defined SCNoFAST16 || @PRI_MACROS_BROKEN@
+# undef SCNoFAST16
+# if UINT_FAST16_MAX > UINT32_MAX
+# define SCNoFAST16 SCNo64
+# elif UINT_FAST16_MAX == 0xffff
+# define SCNoFAST16 "ho"
+# else
+# define SCNoFAST16 "o"
+# endif
+# endif
+# if !defined SCNuFAST16 || @PRI_MACROS_BROKEN@
+# undef SCNuFAST16
+# if UINT_FAST16_MAX > UINT32_MAX
+# define SCNuFAST16 SCNu64
+# elif UINT_FAST16_MAX == 0xffff
+# define SCNuFAST16 "hu"
+# else
+# define SCNuFAST16 "u"
+# endif
+# endif
+# if !defined SCNxFAST16 || @PRI_MACROS_BROKEN@
+# undef SCNxFAST16
+# if UINT_FAST16_MAX > UINT32_MAX
+# define SCNxFAST16 SCNx64
+# elif UINT_FAST16_MAX == 0xffff
+# define SCNxFAST16 "hx"
+# else
+# define SCNxFAST16 "x"
+# endif
+# endif
+# if !defined SCNdFAST32 || @PRI_MACROS_BROKEN@
+# undef SCNdFAST32
+# if INT_FAST32_MAX > INT32_MAX
+# define SCNdFAST32 SCNd64
+# else
+# define SCNdFAST32 "d"
+# endif
+# endif
+# if !defined SCNiFAST32 || @PRI_MACROS_BROKEN@
+# undef SCNiFAST32
+# if INT_FAST32_MAX > INT32_MAX
+# define SCNiFAST32 SCNi64
+# else
+# define SCNiFAST32 "i"
+# endif
+# endif
+# if !defined SCNoFAST32 || @PRI_MACROS_BROKEN@
+# undef SCNoFAST32
+# if UINT_FAST32_MAX > UINT32_MAX
+# define SCNoFAST32 SCNo64
+# else
+# define SCNoFAST32 "o"
+# endif
+# endif
+# if !defined SCNuFAST32 || @PRI_MACROS_BROKEN@
+# undef SCNuFAST32
+# if UINT_FAST32_MAX > UINT32_MAX
+# define SCNuFAST32 SCNu64
+# else
+# define SCNuFAST32 "u"
+# endif
+# endif
+# if !defined SCNxFAST32 || @PRI_MACROS_BROKEN@
+# undef SCNxFAST32
+# if UINT_FAST32_MAX > UINT32_MAX
+# define SCNxFAST32 SCNx64
+# else
+# define SCNxFAST32 "x"
+# endif
+# endif
+# ifdef INT64_MAX
+# if !defined SCNdFAST64 || @PRI_MACROS_BROKEN@
+# undef SCNdFAST64
+# define SCNdFAST64 SCNd64
+# endif
+# if !defined SCNiFAST64 || @PRI_MACROS_BROKEN@
+# undef SCNiFAST64
+# define SCNiFAST64 SCNi64
+# endif
+# endif
+# ifdef UINT64_MAX
+# if !defined SCNoFAST64 || @PRI_MACROS_BROKEN@
+# undef SCNoFAST64
+# define SCNoFAST64 SCNo64
+# endif
+# if !defined SCNuFAST64 || @PRI_MACROS_BROKEN@
+# undef SCNuFAST64
+# define SCNuFAST64 SCNu64
+# endif
+# if !defined SCNxFAST64 || @PRI_MACROS_BROKEN@
+# undef SCNxFAST64
+# define SCNxFAST64 SCNx64
+# endif
+# endif
+
+# if !defined SCNdMAX || @PRI_MACROS_BROKEN@
+# undef SCNdMAX
+# if INTMAX_MAX > INT32_MAX
+# define SCNdMAX SCNd64
+# else
+# define SCNdMAX "ld"
+# endif
+# endif
+# if !defined SCNiMAX || @PRI_MACROS_BROKEN@
+# undef SCNiMAX
+# if INTMAX_MAX > INT32_MAX
+# define SCNiMAX SCNi64
+# else
+# define SCNiMAX "li"
+# endif
+# endif
+# if !defined SCNoMAX || @PRI_MACROS_BROKEN@
+# undef SCNoMAX
+# if UINTMAX_MAX > UINT32_MAX
+# define SCNoMAX SCNo64
+# else
+# define SCNoMAX "lo"
+# endif
+# endif
+# if !defined SCNuMAX || @PRI_MACROS_BROKEN@
+# undef SCNuMAX
+# if UINTMAX_MAX > UINT32_MAX
+# define SCNuMAX SCNu64
+# else
+# define SCNuMAX "lu"
+# endif
+# endif
+# if !defined SCNxMAX || @PRI_MACROS_BROKEN@
+# undef SCNxMAX
+# if UINTMAX_MAX > UINT32_MAX
+# define SCNxMAX SCNx64
+# else
+# define SCNxMAX "lx"
+# endif
+# endif
+
+# if !defined SCNdPTR || @PRI_MACROS_BROKEN@
+# undef SCNdPTR
+# ifdef INTPTR_MAX
+# define SCNdPTR @PRIPTR_PREFIX@ "d"
+# endif
+# endif
+# if !defined SCNiPTR || @PRI_MACROS_BROKEN@
+# undef SCNiPTR
+# ifdef INTPTR_MAX
+# define SCNiPTR @PRIPTR_PREFIX@ "i"
+# endif
+# endif
+# if !defined SCNoPTR || @PRI_MACROS_BROKEN@
+# undef SCNoPTR
+# ifdef UINTPTR_MAX
+# define SCNoPTR @PRIPTR_PREFIX@ "o"
+# endif
+# endif
+# if !defined SCNuPTR || @PRI_MACROS_BROKEN@
+# undef SCNuPTR
+# ifdef UINTPTR_MAX
+# define SCNuPTR @PRIPTR_PREFIX@ "u"
+# endif
+# endif
+# if !defined SCNxPTR || @PRI_MACROS_BROKEN@
+# undef SCNxPTR
+# ifdef UINTPTR_MAX
+# define SCNxPTR @PRIPTR_PREFIX@ "x"
+# endif
+# endif
+
+#endif
+
+/* 7.8.2 Functions for greatest-width integer types */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if @GNULIB_IMAXABS@
+# if !@HAVE_DECL_IMAXABS@
+extern intmax_t imaxabs (intmax_t);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef imaxabs
+# define imaxabs(a) \
+ (GL_LINK_WARNING ("imaxabs is unportable - " \
+ "use gnulib module imaxabs for portability"), \
+ imaxabs (a))
+#endif
+
+#if @GNULIB_IMAXDIV@
+# if !@HAVE_DECL_IMAXDIV@
+typedef struct { intmax_t quot; intmax_t rem; } imaxdiv_t;
+extern imaxdiv_t imaxdiv (intmax_t, intmax_t);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef imaxdiv
+# define imaxdiv(a,b) \
+ (GL_LINK_WARNING ("imaxdiv is unportable - " \
+ "use gnulib module imaxdiv for portability"), \
+ imaxdiv (a, b))
+#endif
+
+#if @GNULIB_STRTOIMAX@
+# if !@HAVE_DECL_STRTOIMAX@
+extern intmax_t strtoimax (const char *, char **, int);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef strtoimax
+# define strtoimax(p,e,b) \
+ (GL_LINK_WARNING ("strtoimax is unportable - " \
+ "use gnulib module strtoimax for portability"), \
+ strtoimax (p, e, b))
+#endif
+
+#if @GNULIB_STRTOUMAX@
+# if !@HAVE_DECL_STRTOUMAX@
+extern uintmax_t strtoumax (const char *, char **, int);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef strtoumax
+# define strtoumax(p,e,b) \
+ (GL_LINK_WARNING ("strtoumax is unportable - " \
+ "use gnulib module strtoumax for portability"), \
+ strtoumax (p, e, b))
+#endif
+
+/* Don't bother defining or declaring wcstoimax and wcstoumax, since
+ wide-character functions like this are hardly ever useful. */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* INTTYPES_H */
diff --git a/lib/lchown.c b/lib/lchown.c
new file mode 100644
index 0000000..fa0826e
--- /dev/null
+++ b/lib/lchown.c
@@ -0,0 +1,47 @@
+/* Provide a stub lchown function for systems that lack it.
+
+ Copyright (C) 1998, 1999, 2002, 2004, 2006 Free Software
+ Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* written by Jim Meyering */
+
+#include <config.h>
+
+#include "lchown.h"
+
+#include <sys/stat.h>
+
+/* Work just like chown, except when FILE is a symbolic link.
+ In that case, set errno to EOPNOTSUPP and return -1.
+ But if autoconf tests determined that chown modifies
+ symlinks, then just call chown. */
+
+int
+lchown (const char *file, uid_t uid, gid_t gid)
+{
+#if ! CHOWN_MODIFIES_SYMLINK
+ struct stat stats;
+
+ if (lstat (file, &stats) == 0 && S_ISLNK (stats.st_mode))
+ {
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+#endif
+
+ return chown (file, uid, gid);
+}
diff --git a/lib/lchown.h b/lib/lchown.h
new file mode 100644
index 0000000..6816d1f
--- /dev/null
+++ b/lib/lchown.h
@@ -0,0 +1,42 @@
+/* Declare a replacement for lchown on hosts that lack it.
+
+ Copyright (C) 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 Jim Meyering. */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#if HAVE_DECL_LCHOWN
+# if ! HAVE_LCHOWN
+# undef lchown
+# define lchown rpl_chown
+# endif
+#else
+int lchown (char const *, uid_t, gid_t);
+#endif
+
+/* Some systems don't have EOPNOTSUPP. */
+#ifndef EOPNOTSUPP
+# ifdef ENOTSUP
+# define EOPNOTSUPP ENOTSUP
+# else
+/* Some systems don't have ENOTSUP either. */
+# define EOPNOTSUPP EINVAL
+# endif
+#endif
diff --git a/lib/lstat.c b/lib/lstat.c
new file mode 100644
index 0000000..77dd228
--- /dev/null
+++ b/lib/lstat.c
@@ -0,0 +1,76 @@
+/* Work around a bug of lstat on some systems
+
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free
+ Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* written by Jim Meyering */
+
+#include <config.h>
+
+/* The specification of these functions is in sys_stat.h. But we cannot
+ include this include file here, because on some systems, a
+ "#define lstat lstat64" is being used, and sys_stat.h deletes this
+ definition. */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+
+/* lstat works differently on Linux and Solaris systems. POSIX (see
+ `pathname resolution' in the glossary) requires that programs like
+ `ls' take into consideration the fact that FILE has a trailing slash
+ when FILE is a symbolic link. On Linux and Solaris 10 systems, the
+ lstat function already has the desired semantics (in treating
+ `lstat ("symlink/", sbuf)' just like `lstat ("symlink/.", sbuf)',
+ but on Solaris 9 and earlier it does not.
+
+ If FILE has a trailing slash and specifies a symbolic link,
+ then use stat() to get more info on the referent of FILE.
+ If the referent is a non-directory, then set errno to ENOTDIR
+ and return -1. Otherwise, return stat's result. */
+
+int
+rpl_lstat (const char *file, struct stat *sbuf)
+{
+ size_t len;
+ int lstat_result = lstat (file, sbuf);
+
+ if (lstat_result != 0 || !S_ISLNK (sbuf->st_mode))
+ return lstat_result;
+
+ len = strlen (file);
+ if (len == 0 || file[len - 1] != '/')
+ return 0;
+
+ /* FILE refers to a symbolic link and the name ends with a slash.
+ Call stat() to get info about the link's referent. */
+
+ /* If stat fails, then we do the same. */
+ if (stat (file, sbuf) != 0)
+ return -1;
+
+ /* If FILE references a directory, return 0. */
+ if (S_ISDIR (sbuf->st_mode))
+ return 0;
+
+ /* Here, we know stat succeeded and FILE references a non-directory.
+ But it was specified via a name including a trailing slash.
+ Fail with errno set to ENOTDIR to indicate the contradiction. */
+ errno = ENOTDIR;
+ return -1;
+}
diff --git a/lib/lstat.h b/lib/lstat.h
new file mode 100644
index 0000000..6a83fbf
--- /dev/null
+++ b/lib/lstat.h
@@ -0,0 +1,24 @@
+/* Retrieving information about files.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <sys/stat.h>
+
+#if !LSTAT_FOLLOWS_SLASHED_SYMLINK
+extern int rpl_lstat (const char *name, struct stat *buf);
+# undef lstat
+# define lstat rpl_lstat
+#endif
diff --git a/lib/malloc.c b/lib/malloc.c
new file mode 100644
index 0000000..d4dae3e
--- /dev/null
+++ b/lib/malloc.c
@@ -0,0 +1,35 @@
+/* malloc() function that is glibc compatible.
+
+ Copyright (C) 1997, 1998, 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 Jim Meyering */
+
+#include <config.h>
+#undef malloc
+
+#include <stdlib.h>
+
+/* Allocate an N-byte block of memory from the heap.
+ If N is zero, allocate a 1-byte block. */
+
+void *
+rpl_malloc (size_t n)
+{
+ if (n == 0)
+ n = 1;
+ return malloc (n);
+}
diff --git a/lib/mempcpy.c b/lib/mempcpy.c
new file mode 100644
index 0000000..1c702c7
--- /dev/null
+++ b/lib/mempcpy.c
@@ -0,0 +1,29 @@
+/* Copy memory area and return pointer after last written byte.
+ Copyright (C) 2003, 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>
+
+/* Specification. */
+#include <string.h>
+
+/* Copy N bytes of SRC to DEST, return pointer to bytes after the
+ last written byte. */
+void *
+mempcpy (void *dest, const void *src, size_t n)
+{
+ return (char *) memcpy (dest, src, n) + n;
+}
diff --git a/lib/memrchr.c b/lib/memrchr.c
new file mode 100644
index 0000000..29fd531
--- /dev/null
+++ b/lib/memrchr.c
@@ -0,0 +1,190 @@
+/* memrchr -- find the last occurrence of a byte in a memory block
+
+ Copyright (C) 1991, 1993, 1996, 1997, 1999, 2000, 2003, 2004, 2005,
+ 2006, 2007 Free Software Foundation, Inc.
+
+ Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
+ with help from Dan Sahlin (dan@sics.se) and
+ commentary by Jim Blandy (jimb@ai.mit.edu);
+ adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
+ and implemented by Roland McGrath (roland@ai.mit.edu).
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#if defined _LIBC
+# include <memcopy.h>
+#else
+# include <config.h>
+# define reg_char char
+#endif
+
+#include <string.h>
+#include <limits.h>
+
+#undef __memrchr
+#undef memrchr
+
+#ifndef weak_alias
+# define __memrchr memrchr
+#endif
+
+/* Search no more than N bytes of S for C. */
+void *
+__memrchr (void const *s, int c_in, size_t n)
+{
+ const unsigned char *char_ptr;
+ const unsigned long int *longword_ptr;
+ unsigned long int longword, magic_bits, charmask;
+ unsigned reg_char c;
+ int i;
+
+ c = (unsigned char) c_in;
+
+ /* Handle the last few characters by reading one character at a time.
+ Do this until CHAR_PTR is aligned on a longword boundary. */
+ for (char_ptr = (const unsigned char *) s + n;
+ n > 0 && (size_t) char_ptr % sizeof longword != 0;
+ --n)
+ if (*--char_ptr == c)
+ return (void *) char_ptr;
+
+ /* All these elucidatory comments refer to 4-byte longwords,
+ but the theory applies equally well to any size longwords. */
+
+ longword_ptr = (const unsigned long int *) char_ptr;
+
+ /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits
+ the "holes." Note that there is a hole just to the left of
+ each byte, with an extra at the end:
+
+ bits: 01111110 11111110 11111110 11111111
+ bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
+
+ The 1-bits make sure that carries propagate to the next 0-bit.
+ The 0-bits provide holes for carries to fall into. */
+
+ /* Set MAGIC_BITS to be this pattern of 1 and 0 bits.
+ Set CHARMASK to be a longword, each of whose bytes is C. */
+
+ magic_bits = 0xfefefefe;
+ charmask = c | (c << 8);
+ charmask |= charmask << 16;
+#if 0xffffffffU < ULONG_MAX
+ magic_bits |= magic_bits << 32;
+ charmask |= charmask << 32;
+ if (8 < sizeof longword)
+ for (i = 64; i < sizeof longword * 8; i *= 2)
+ {
+ magic_bits |= magic_bits << i;
+ charmask |= charmask << i;
+ }
+#endif
+ magic_bits = (ULONG_MAX >> 1) & (magic_bits | 1);
+
+ /* Instead of the traditional loop which tests each character,
+ we will test a longword at a time. The tricky part is testing
+ if *any of the four* bytes in the longword in question are zero. */
+ while (n >= sizeof longword)
+ {
+ /* We tentatively exit the loop if adding MAGIC_BITS to
+ LONGWORD fails to change any of the hole bits of LONGWORD.
+
+ 1) Is this safe? Will it catch all the zero bytes?
+ Suppose there is a byte with all zeros. Any carry bits
+ propagating from its left will fall into the hole at its
+ least significant bit and stop. Since there will be no
+ carry from its most significant bit, the LSB of the
+ byte to the left will be unchanged, and the zero will be
+ detected.
+
+ 2) Is this worthwhile? Will it ignore everything except
+ zero bytes? Suppose every byte of LONGWORD has a bit set
+ somewhere. There will be a carry into bit 8. If bit 8
+ is set, this will carry into bit 16. If bit 8 is clear,
+ one of bits 9-15 must be set, so there will be a carry
+ into bit 16. Similarly, there will be a carry into bit
+ 24. If one of bits 24-30 is set, there will be a carry
+ into bit 31, so all of the hole bits will be changed.
+
+ The one misfire occurs when bits 24-30 are clear and bit
+ 31 is set; in this case, the hole at bit 31 is not
+ changed. If we had access to the processor carry flag,
+ we could close this loophole by putting the fourth hole
+ at bit 32!
+
+ So it ignores everything except 128's, when they're aligned
+ properly.
+
+ 3) But wait! Aren't we looking for C, not zero?
+ Good point. So what we do is XOR LONGWORD with a longword,
+ each of whose bytes is C. This turns each byte that is C
+ into a zero. */
+
+ longword = *--longword_ptr ^ charmask;
+
+ /* Add MAGIC_BITS to LONGWORD. */
+ if ((((longword + magic_bits)
+
+ /* Set those bits that were unchanged by the addition. */
+ ^ ~longword)
+
+ /* Look at only the hole bits. If any of the hole bits
+ are unchanged, most likely one of the bytes was a
+ zero. */
+ & ~magic_bits) != 0)
+ {
+ /* Which of the bytes was C? If none of them were, it was
+ a misfire; continue the search. */
+
+ const unsigned char *cp = (const unsigned char *) longword_ptr;
+
+ if (8 < sizeof longword)
+ for (i = sizeof longword - 1; 8 <= i; i--)
+ if (cp[i] == c)
+ return (void *) &cp[i];
+ if (7 < sizeof longword && cp[7] == c)
+ return (void *) &cp[7];
+ if (6 < sizeof longword && cp[6] == c)
+ return (void *) &cp[6];
+ if (5 < sizeof longword && cp[5] == c)
+ return (void *) &cp[5];
+ if (4 < sizeof longword && cp[4] == c)
+ return (void *) &cp[4];
+ if (cp[3] == c)
+ return (void *) &cp[3];
+ if (cp[2] == c)
+ return (void *) &cp[2];
+ if (cp[1] == c)
+ return (void *) &cp[1];
+ if (cp[0] == c)
+ return (void *) cp;
+ }
+
+ n -= sizeof longword;
+ }
+
+ char_ptr = (const unsigned char *) longword_ptr;
+
+ while (n-- > 0)
+ {
+ if (*--char_ptr == c)
+ return (void *) char_ptr;
+ }
+
+ return 0;
+}
+#ifdef weak_alias
+weak_alias (__memrchr, memrchr)
+#endif
diff --git a/lib/mkdirat.c b/lib/mkdirat.c
new file mode 100644
index 0000000..da0b262
--- /dev/null
+++ b/lib/mkdirat.c
@@ -0,0 +1,43 @@
+/* fd-relative mkdir
+ 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 Jim Meyering */
+
+#include <config.h>
+
+#include "openat.h"
+
+#include <unistd.h>
+
+#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
+#include "save-cwd.h"
+#include "openat-priv.h"
+
+/* Solaris 10 has no function like this.
+ Create a subdirectory, FILE, with mode MODE, in the directory
+ open on descriptor FD. If possible, do it without changing the
+ working directory. Otherwise, resort to using save_cwd/fchdir,
+ then mkdir/restore_cwd. If either the save_cwd or the restore_cwd
+ fails, then give a diagnostic and exit nonzero. */
+
+#define AT_FUNC_NAME mkdirat
+#define AT_FUNC_F1 mkdir
+#define AT_FUNC_F2 mkdir
+#define AT_FUNC_USE_F1_COND 1
+#define AT_FUNC_POST_FILE_PARAM_DECLS , mode_t mode
+#define AT_FUNC_POST_FILE_ARGS , mode
+#include "at-func.c"
diff --git a/lib/mktime.c b/lib/mktime.c
new file mode 100644
index 0000000..a91fb20
--- /dev/null
+++ b/lib/mktime.c
@@ -0,0 +1,663 @@
+/* Convert a `struct tm' to a time_t value.
+ Copyright (C) 1993-1999, 2002-2005, 2006, 2007 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Paul Eggert <eggert@twinsun.com>.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Define this to have a standalone program to test this implementation of
+ mktime. */
+/* #define DEBUG 1 */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+/* Assume that leap seconds are possible, unless told otherwise.
+ If the host has a `zic' command with a `-L leapsecondfilename' option,
+ then it supports leap seconds; otherwise it probably doesn't. */
+#ifndef LEAP_SECONDS_POSSIBLE
+# define LEAP_SECONDS_POSSIBLE 1
+#endif
+
+#include <time.h>
+
+#include <limits.h>
+
+#include <string.h> /* For the real memcpy prototype. */
+
+#if DEBUG
+# include <stdio.h>
+# include <stdlib.h>
+/* Make it work even if the system's libc has its own mktime routine. */
+# define mktime my_mktime
+#endif /* DEBUG */
+
+/* Shift A right by B bits portably, by dividing A by 2**B and
+ truncating towards minus infinity. A and B should be free of side
+ effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
+ INT_BITS is the number of useful bits in an int. GNU code can
+ assume that INT_BITS is at least 32.
+
+ ISO C99 says that A >> B is implementation-defined if A < 0. Some
+ implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
+ right in the usual way when A < 0, so SHR falls back on division if
+ ordinary A >> B doesn't seem to be the usual signed shift. */
+#define SHR(a, b) \
+ (-1 >> 1 == -1 \
+ ? (a) >> (b) \
+ : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
+
+/* The extra casts in the following macros work around compiler bugs,
+ e.g., in Cray C 5.0.3.0. */
+
+/* True if the arithmetic type T is an integer type. bool counts as
+ an integer. */
+#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
+
+/* True if negative values of the signed integer type T use two's
+ complement, ones' complement, or signed magnitude representation,
+ respectively. Much GNU code assumes two's complement, but some
+ people like to be portable to all possible C hosts. */
+#define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
+#define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0)
+#define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1)
+
+/* True if the arithmetic type T is signed. */
+#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+
+/* The maximum and minimum values for the integer type T. These
+ macros have undefined behavior if T is signed and has padding bits.
+ If this is a problem for you, please let us know how to fix it for
+ your host. */
+#define TYPE_MINIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) 0 \
+ : TYPE_SIGNED_MAGNITUDE (t) \
+ ? ~ (t) 0 \
+ : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))
+#define TYPE_MAXIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) -1 \
+ : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
+
+#ifndef TIME_T_MIN
+# define TIME_T_MIN TYPE_MINIMUM (time_t)
+#endif
+#ifndef TIME_T_MAX
+# define TIME_T_MAX TYPE_MAXIMUM (time_t)
+#endif
+#define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1)
+
+/* Verify a requirement at compile-time (unlike assert, which is runtime). */
+#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
+
+verify (time_t_is_integer, TYPE_IS_INTEGER (time_t));
+verify (twos_complement_arithmetic, TYPE_TWOS_COMPLEMENT (int));
+/* The code also assumes that signed integer overflow silently wraps
+ around, but this assumption can't be stated without causing a
+ diagnostic on some hosts. */
+
+#define EPOCH_YEAR 1970
+#define TM_YEAR_BASE 1900
+verify (base_year_is_a_multiple_of_100, TM_YEAR_BASE % 100 == 0);
+
+/* Return 1 if YEAR + TM_YEAR_BASE is a leap year. */
+static inline int
+leapyear (long int year)
+{
+ /* Don't add YEAR to TM_YEAR_BASE, as that might overflow.
+ Also, work even if YEAR is negative. */
+ return
+ ((year & 3) == 0
+ && (year % 100 != 0
+ || ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3)));
+}
+
+/* How many days come before each month (0-12). */
+#ifndef _LIBC
+static
+#endif
+const unsigned short int __mon_yday[2][13] =
+ {
+ /* Normal years. */
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+ /* Leap years. */
+ { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+ };
+
+
+#ifndef _LIBC
+/* Portable standalone applications should supply a <time.h> that
+ declares a POSIX-compliant localtime_r, for the benefit of older
+ implementations that lack localtime_r or have a nonstandard one.
+ See the gnulib time_r module for one way to implement this. */
+# undef __localtime_r
+# define __localtime_r localtime_r
+# define __mktime_internal mktime_internal
+#endif
+
+/* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) -
+ (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks
+ were not adjusted between the time stamps.
+
+ The YEAR values uses the same numbering as TP->tm_year. Values
+ need not be in the usual range. However, YEAR1 must not be less
+ than 2 * INT_MIN or greater than 2 * INT_MAX.
+
+ The result may overflow. It is the caller's responsibility to
+ detect overflow. */
+
+static inline time_t
+ydhms_diff (long int year1, long int yday1, int hour1, int min1, int sec1,
+ int year0, int yday0, int hour0, int min0, int sec0)
+{
+ verify (C99_integer_division, -1 / 2 == 0);
+ verify (long_int_year_and_yday_are_wide_enough,
+ INT_MAX <= LONG_MAX / 2 || TIME_T_MAX <= UINT_MAX);
+
+ /* Compute intervening leap days correctly even if year is negative.
+ Take care to avoid integer overflow here. */
+ int a4 = SHR (year1, 2) + SHR (TM_YEAR_BASE, 2) - ! (year1 & 3);
+ int b4 = SHR (year0, 2) + SHR (TM_YEAR_BASE, 2) - ! (year0 & 3);
+ int a100 = a4 / 25 - (a4 % 25 < 0);
+ int b100 = b4 / 25 - (b4 % 25 < 0);
+ int a400 = SHR (a100, 2);
+ int b400 = SHR (b100, 2);
+ int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
+
+ /* Compute the desired time in time_t precision. Overflow might
+ occur here. */
+ time_t tyear1 = year1;
+ time_t years = tyear1 - year0;
+ time_t days = 365 * years + yday1 - yday0 + intervening_leap_days;
+ time_t hours = 24 * days + hour1 - hour0;
+ time_t minutes = 60 * hours + min1 - min0;
+ time_t seconds = 60 * minutes + sec1 - sec0;
+ return seconds;
+}
+
+
+/* Return a time_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC),
+ assuming that *T corresponds to *TP and that no clock adjustments
+ occurred between *TP and the desired time.
+ If TP is null, return a value not equal to *T; this avoids false matches.
+ If overflow occurs, yield the minimal or maximal value, except do not
+ yield a value equal to *T. */
+static time_t
+guess_time_tm (long int year, long int yday, int hour, int min, int sec,
+ const time_t *t, const struct tm *tp)
+{
+ if (tp)
+ {
+ time_t d = ydhms_diff (year, yday, hour, min, sec,
+ tp->tm_year, tp->tm_yday,
+ tp->tm_hour, tp->tm_min, tp->tm_sec);
+ time_t t1 = *t + d;
+ if ((t1 < *t) == (TYPE_SIGNED (time_t) ? d < 0 : TIME_T_MAX / 2 < d))
+ return t1;
+ }
+
+ /* Overflow occurred one way or another. Return the nearest result
+ that is actually in range, except don't report a zero difference
+ if the actual difference is nonzero, as that would cause a false
+ match; and don't oscillate between two values, as that would
+ confuse the spring-forward gap detector. */
+ return (*t < TIME_T_MIDPOINT
+ ? (*t <= TIME_T_MIN + 1 ? *t + 1 : TIME_T_MIN)
+ : (TIME_T_MAX - 1 <= *t ? *t - 1 : TIME_T_MAX));
+}
+
+/* Use CONVERT to convert *T to a broken down time in *TP.
+ If *T is out of range for conversion, adjust it so that
+ it is the nearest in-range value and then convert that. */
+static struct tm *
+ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
+ time_t *t, struct tm *tp)
+{
+ struct tm *r = convert (t, tp);
+
+ if (!r && *t)
+ {
+ time_t bad = *t;
+ time_t ok = 0;
+
+ /* BAD is a known unconvertible time_t, and OK is a known good one.
+ Use binary search to narrow the range between BAD and OK until
+ they differ by 1. */
+ while (bad != ok + (bad < 0 ? -1 : 1))
+ {
+ time_t mid = *t = (bad < 0
+ ? bad + ((ok - bad) >> 1)
+ : ok + ((bad - ok) >> 1));
+ r = convert (t, tp);
+ if (r)
+ ok = mid;
+ else
+ bad = mid;
+ }
+
+ if (!r && ok)
+ {
+ /* The last conversion attempt failed;
+ revert to the most recent successful attempt. */
+ *t = ok;
+ r = convert (t, tp);
+ }
+ }
+
+ return r;
+}
+
+
+/* Convert *TP to a time_t value, inverting
+ the monotonic and mostly-unit-linear conversion function CONVERT.
+ Use *OFFSET to keep track of a guess at the offset of the result,
+ compared to what the result would be for UTC without leap seconds.
+ If *OFFSET's guess is correct, only one CONVERT call is needed.
+ This function is external because it is used also by timegm.c. */
+time_t
+__mktime_internal (struct tm *tp,
+ struct tm *(*convert) (const time_t *, struct tm *),
+ time_t *offset)
+{
+ time_t t, gt, t0, t1, t2;
+ struct tm tm;
+
+ /* The maximum number of probes (calls to CONVERT) should be enough
+ to handle any combinations of time zone rule changes, solar time,
+ leap seconds, and oscillations around a spring-forward gap.
+ POSIX.1 prohibits leap seconds, but some hosts have them anyway. */
+ int remaining_probes = 6;
+
+ /* Time requested. Copy it in case CONVERT modifies *TP; this can
+ occur if TP is localtime's returned value and CONVERT is localtime. */
+ int sec = tp->tm_sec;
+ int min = tp->tm_min;
+ int hour = tp->tm_hour;
+ int mday = tp->tm_mday;
+ int mon = tp->tm_mon;
+ int year_requested = tp->tm_year;
+ int isdst = tp->tm_isdst;
+
+ /* 1 if the previous probe was DST. */
+ int dst2;
+
+ /* Ensure that mon is in range, and set year accordingly. */
+ int mon_remainder = mon % 12;
+ int negative_mon_remainder = mon_remainder < 0;
+ int mon_years = mon / 12 - negative_mon_remainder;
+ long int lyear_requested = year_requested;
+ long int year = lyear_requested + mon_years;
+
+ /* The other values need not be in range:
+ the remaining code handles minor overflows correctly,
+ assuming int and time_t arithmetic wraps around.
+ Major overflows are caught at the end. */
+
+ /* Calculate day of year from year, month, and day of month.
+ The result need not be in range. */
+ int mon_yday = ((__mon_yday[leapyear (year)]
+ [mon_remainder + 12 * negative_mon_remainder])
+ - 1);
+ long int lmday = mday;
+ long int yday = mon_yday + lmday;
+
+ time_t guessed_offset = *offset;
+
+ int sec_requested = sec;
+
+ if (LEAP_SECONDS_POSSIBLE)
+ {
+ /* Handle out-of-range seconds specially,
+ since ydhms_tm_diff assumes every minute has 60 seconds. */
+ if (sec < 0)
+ sec = 0;
+ if (59 < sec)
+ sec = 59;
+ }
+
+ /* Invert CONVERT by probing. First assume the same offset as last
+ time. */
+
+ t0 = ydhms_diff (year, yday, hour, min, sec,
+ EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0, - guessed_offset);
+
+ if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
+ {
+ /* time_t isn't large enough to rule out overflows, so check
+ for major overflows. A gross check suffices, since if t0
+ has overflowed, it is off by a multiple of TIME_T_MAX -
+ TIME_T_MIN + 1. So ignore any component of the difference
+ that is bounded by a small value. */
+
+ /* Approximate log base 2 of the number of time units per
+ biennium. A biennium is 2 years; use this unit instead of
+ years to avoid integer overflow. For example, 2 average
+ Gregorian years are 2 * 365.2425 * 24 * 60 * 60 seconds,
+ which is 63113904 seconds, and rint (log2 (63113904)) is
+ 26. */
+ int ALOG2_SECONDS_PER_BIENNIUM = 26;
+ int ALOG2_MINUTES_PER_BIENNIUM = 20;
+ int ALOG2_HOURS_PER_BIENNIUM = 14;
+ int ALOG2_DAYS_PER_BIENNIUM = 10;
+ int LOG2_YEARS_PER_BIENNIUM = 1;
+
+ int approx_requested_biennia =
+ (SHR (year_requested, LOG2_YEARS_PER_BIENNIUM)
+ - SHR (EPOCH_YEAR - TM_YEAR_BASE, LOG2_YEARS_PER_BIENNIUM)
+ + SHR (mday, ALOG2_DAYS_PER_BIENNIUM)
+ + SHR (hour, ALOG2_HOURS_PER_BIENNIUM)
+ + SHR (min, ALOG2_MINUTES_PER_BIENNIUM)
+ + (LEAP_SECONDS_POSSIBLE
+ ? 0
+ : SHR (sec, ALOG2_SECONDS_PER_BIENNIUM)));
+
+ int approx_biennia = SHR (t0, ALOG2_SECONDS_PER_BIENNIUM);
+ int diff = approx_biennia - approx_requested_biennia;
+ int abs_diff = diff < 0 ? - diff : diff;
+
+ /* IRIX 4.0.5 cc miscaculates TIME_T_MIN / 3: it erroneously
+ gives a positive value of 715827882. Setting a variable
+ first then doing math on it seems to work.
+ (ghazi@caip.rutgers.edu) */
+ time_t time_t_max = TIME_T_MAX;
+ time_t time_t_min = TIME_T_MIN;
+ time_t overflow_threshold =
+ (time_t_max / 3 - time_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM;
+
+ if (overflow_threshold < abs_diff)
+ {
+ /* Overflow occurred. Try repairing it; this might work if
+ the time zone offset is enough to undo the overflow. */
+ time_t repaired_t0 = -1 - t0;
+ approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM);
+ diff = approx_biennia - approx_requested_biennia;
+ abs_diff = diff < 0 ? - diff : diff;
+ if (overflow_threshold < abs_diff)
+ return -1;
+ guessed_offset += repaired_t0 - t0;
+ t0 = repaired_t0;
+ }
+ }
+
+ /* Repeatedly use the error to improve the guess. */
+
+ for (t = t1 = t2 = t0, dst2 = 0;
+ (gt = guess_time_tm (year, yday, hour, min, sec, &t,
+ ranged_convert (convert, &t, &tm)),
+ t != gt);
+ t1 = t2, t2 = t, t = gt, dst2 = tm.tm_isdst != 0)
+ if (t == t1 && t != t2
+ && (tm.tm_isdst < 0
+ || (isdst < 0
+ ? dst2 <= (tm.tm_isdst != 0)
+ : (isdst != 0) != (tm.tm_isdst != 0))))
+ /* We can't possibly find a match, as we are oscillating
+ between two values. The requested time probably falls
+ within a spring-forward gap of size GT - T. Follow the common
+ practice in this case, which is to return a time that is GT - T
+ away from the requested time, preferring a time whose
+ tm_isdst differs from the requested value. (If no tm_isdst
+ was requested and only one of the two values has a nonzero
+ tm_isdst, prefer that value.) In practice, this is more
+ useful than returning -1. */
+ goto offset_found;
+ else if (--remaining_probes == 0)
+ return -1;
+
+ /* We have a match. Check whether tm.tm_isdst has the requested
+ value, if any. */
+ if (isdst != tm.tm_isdst && 0 <= isdst && 0 <= tm.tm_isdst)
+ {
+ /* tm.tm_isdst has the wrong value. Look for a neighboring
+ time with the right value, and use its UTC offset.
+
+ Heuristic: probe the adjacent timestamps in both directions,
+ looking for the desired isdst. This should work for all real
+ time zone histories in the tz database. */
+
+ /* Distance between probes when looking for a DST boundary. In
+ tzdata2003a, the shortest period of DST is 601200 seconds
+ (e.g., America/Recife starting 2000-10-08 01:00), and the
+ shortest period of non-DST surrounded by DST is 694800
+ seconds (Africa/Tunis starting 1943-04-17 01:00). Use the
+ minimum of these two values, so we don't miss these short
+ periods when probing. */
+ int stride = 601200;
+
+ /* The longest period of DST in tzdata2003a is 536454000 seconds
+ (e.g., America/Jujuy starting 1946-10-01 01:00). The longest
+ period of non-DST is much longer, but it makes no real sense
+ to search for more than a year of non-DST, so use the DST
+ max. */
+ int duration_max = 536454000;
+
+ /* Search in both directions, so the maximum distance is half
+ the duration; add the stride to avoid off-by-1 problems. */
+ int delta_bound = duration_max / 2 + stride;
+
+ int delta, direction;
+
+ for (delta = stride; delta < delta_bound; delta += stride)
+ for (direction = -1; direction <= 1; direction += 2)
+ {
+ time_t ot = t + delta * direction;
+ if ((ot < t) == (direction < 0))
+ {
+ struct tm otm;
+ ranged_convert (convert, &ot, &otm);
+ if (otm.tm_isdst == isdst)
+ {
+ /* We found the desired tm_isdst.
+ Extrapolate back to the desired time. */
+ t = guess_time_tm (year, yday, hour, min, sec, &ot, &otm);
+ ranged_convert (convert, &t, &tm);
+ goto offset_found;
+ }
+ }
+ }
+ }
+
+ offset_found:
+ *offset = guessed_offset + t - t0;
+
+ if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)
+ {
+ /* Adjust time to reflect the tm_sec requested, not the normalized value.
+ Also, repair any damage from a false match due to a leap second. */
+ int sec_adjustment = (sec == 0 && tm.tm_sec == 60) - sec;
+ t1 = t + sec_requested;
+ t2 = t1 + sec_adjustment;
+ if (((t1 < t) != (sec_requested < 0))
+ | ((t2 < t1) != (sec_adjustment < 0))
+ | ! convert (&t2, &tm))
+ return -1;
+ t = t2;
+ }
+
+ *tp = tm;
+ return t;
+}
+
+
+/* FIXME: This should use a signed type wide enough to hold any UTC
+ offset in seconds. 'int' should be good enough for GNU code. We
+ can't fix this unilaterally though, as other modules invoke
+ __mktime_internal. */
+static time_t localtime_offset;
+
+/* Convert *TP to a time_t value. */
+time_t
+mktime (struct tm *tp)
+{
+#ifdef _LIBC
+ /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
+ time zone names contained in the external variable `tzname' shall
+ be set as if the tzset() function had been called. */
+ __tzset ();
+#endif
+
+ return __mktime_internal (tp, __localtime_r, &localtime_offset);
+}
+
+#ifdef weak_alias
+weak_alias (mktime, timelocal)
+#endif
+
+#ifdef _LIBC
+libc_hidden_def (mktime)
+libc_hidden_weak (timelocal)
+#endif
+
+#if DEBUG
+
+static int
+not_equal_tm (const struct tm *a, const struct tm *b)
+{
+ return ((a->tm_sec ^ b->tm_sec)
+ | (a->tm_min ^ b->tm_min)
+ | (a->tm_hour ^ b->tm_hour)
+ | (a->tm_mday ^ b->tm_mday)
+ | (a->tm_mon ^ b->tm_mon)
+ | (a->tm_year ^ b->tm_year)
+ | (a->tm_yday ^ b->tm_yday)
+ | (a->tm_isdst ^ b->tm_isdst));
+}
+
+static void
+print_tm (const struct tm *tp)
+{
+ if (tp)
+ printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
+ tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
+ tp->tm_hour, tp->tm_min, tp->tm_sec,
+ tp->tm_yday, tp->tm_wday, tp->tm_isdst);
+ else
+ printf ("0");
+}
+
+static int
+check_result (time_t tk, struct tm tmk, time_t tl, const struct tm *lt)
+{
+ if (tk != tl || !lt || not_equal_tm (&tmk, lt))
+ {
+ printf ("mktime (");
+ print_tm (lt);
+ printf (")\nyields (");
+ print_tm (&tmk);
+ printf (") == %ld, should be %ld\n", (long int) tk, (long int) tl);
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+ int status = 0;
+ struct tm tm, tmk, tml;
+ struct tm *lt;
+ time_t tk, tl, tl1;
+ char trailer;
+
+ if ((argc == 3 || argc == 4)
+ && (sscanf (argv[1], "%d-%d-%d%c",
+ &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
+ == 3)
+ && (sscanf (argv[2], "%d:%d:%d%c",
+ &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
+ == 3))
+ {
+ tm.tm_year -= TM_YEAR_BASE;
+ tm.tm_mon--;
+ tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
+ tmk = tm;
+ tl = mktime (&tmk);
+ lt = localtime (&tl);
+ if (lt)
+ {
+ tml = *lt;
+ lt = &tml;
+ }
+ printf ("mktime returns %ld == ", (long int) tl);
+ print_tm (&tmk);
+ printf ("\n");
+ status = check_result (tl, tmk, tl, lt);
+ }
+ else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
+ {
+ time_t from = atol (argv[1]);
+ time_t by = atol (argv[2]);
+ time_t to = atol (argv[3]);
+
+ if (argc == 4)
+ for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)
+ {
+ lt = localtime (&tl);
+ if (lt)
+ {
+ tmk = tml = *lt;
+ tk = mktime (&tmk);
+ status |= check_result (tk, tmk, tl, &tml);
+ }
+ else
+ {
+ printf ("localtime (%ld) yields 0\n", (long int) tl);
+ status = 1;
+ }
+ tl1 = tl + by;
+ if ((tl1 < tl) != (by < 0))
+ break;
+ }
+ else
+ for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)
+ {
+ /* Null benchmark. */
+ lt = localtime (&tl);
+ if (lt)
+ {
+ tmk = tml = *lt;
+ tk = tl;
+ status |= check_result (tk, tmk, tl, &tml);
+ }
+ else
+ {
+ printf ("localtime (%ld) yields 0\n", (long int) tl);
+ status = 1;
+ }
+ tl1 = tl + by;
+ if ((tl1 < tl) != (by < 0))
+ break;
+ }
+ }
+ else
+ printf ("Usage:\
+\t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
+\t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
+\t%s FROM BY TO - # Do not test those values (for benchmark).\n",
+ argv[0], argv[0], argv[0]);
+
+ return status;
+}
+
+#endif /* DEBUG */
+
+/*
+Local Variables:
+compile-command: "gcc -DDEBUG -Wall -W -O -g mktime.c -o mktime"
+End:
+*/
diff --git a/lib/obstack.c b/lib/obstack.c
new file mode 100644
index 0000000..5cd0b7a
--- /dev/null
+++ b/lib/obstack.c
@@ -0,0 +1,431 @@
+/* obstack.c - subroutines used implicitly by object stack macros
+
+ Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997,
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+ Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef _LIBC
+# include <obstack.h>
+# include <shlib-compat.h>
+#else
+# include <config.h>
+# include "obstack.h"
+#endif
+
+/* NOTE BEFORE MODIFYING THIS FILE: This version number must be
+ incremented whenever callers compiled using an old obstack.h can no
+ longer properly call the functions in this obstack.c. */
+#define OBSTACK_INTERFACE_VERSION 1
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself, and the installed library
+ supports the same library interface we do. This code is part of the GNU
+ C Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object
+ files, it is simpler to just do this in the source for each such file. */
+
+#include <stdio.h> /* Random thing to get __GNU_LIBRARY__. */
+#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
+# include <gnu-versions.h>
+# if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
+# define ELIDE_CODE
+# endif
+#endif
+
+#include <stddef.h>
+
+#ifndef ELIDE_CODE
+
+# include <stdint.h>
+
+/* Determine default alignment. */
+union fooround
+{
+ uintmax_t i;
+ long double d;
+ void *p;
+};
+struct fooalign
+{
+ char c;
+ union fooround u;
+};
+/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
+ But in fact it might be less smart and round addresses to as much as
+ DEFAULT_ROUNDING. So we prepare for it to do that. */
+enum
+ {
+ DEFAULT_ALIGNMENT = offsetof (struct fooalign, u),
+ DEFAULT_ROUNDING = sizeof (union fooround)
+ };
+
+/* When we copy a long block of data, this is the unit to do it with.
+ On some machines, copying successive ints does not work;
+ in such a case, redefine COPYING_UNIT to `long' (if that works)
+ or `char' as a last resort. */
+# ifndef COPYING_UNIT
+# define COPYING_UNIT int
+# endif
+
+
+/* The functions allocating more room by calling `obstack_chunk_alloc'
+ jump to the handler pointed to by `obstack_alloc_failed_handler'.
+ This can be set to a user defined function which should either
+ abort gracefully or use longjump - but shouldn't return. This
+ variable by default points to the internal function
+ `print_and_abort'. */
+static void print_and_abort (void);
+void (*obstack_alloc_failed_handler) (void) = print_and_abort;
+
+/* Exit value used when `print_and_abort' is used. */
+# include <stdlib.h>
+# ifdef _LIBC
+int obstack_exit_failure = EXIT_FAILURE;
+# else
+# include "exitfail.h"
+# define obstack_exit_failure exit_failure
+# endif
+
+# ifdef _LIBC
+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
+/* A looong time ago (before 1994, anyway; we're not sure) this global variable
+ was used by non-GNU-C macros to avoid multiple evaluation. The GNU C
+ library still exports it because somebody might use it. */
+struct obstack *_obstack_compat;
+compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
+# endif
+# endif
+
+/* Define a macro that either calls functions with the traditional malloc/free
+ calling interface, or calls functions with the mmalloc/mfree interface
+ (that adds an extra first argument), based on the state of use_extra_arg.
+ For free, do not use ?:, since some compilers, like the MIPS compilers,
+ do not allow (expr) ? void : void. */
+
+# define CALL_CHUNKFUN(h, size) \
+ (((h) -> use_extra_arg) \
+ ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
+ : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
+
+# define CALL_FREEFUN(h, old_chunk) \
+ do { \
+ if ((h) -> use_extra_arg) \
+ (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
+ else \
+ (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
+ } while (0)
+
+
+/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
+ Objects start on multiples of ALIGNMENT (0 means use default).
+ CHUNKFUN is the function to use to allocate chunks,
+ and FREEFUN the function to free them.
+
+ Return nonzero if successful, calls obstack_alloc_failed_handler if
+ allocation fails. */
+
+int
+_obstack_begin (struct obstack *h,
+ int size, int alignment,
+ void *(*chunkfun) (long),
+ void (*freefun) (void *))
+{
+ register struct _obstack_chunk *chunk; /* points to new chunk */
+
+ if (alignment == 0)
+ alignment = DEFAULT_ALIGNMENT;
+ if (size == 0)
+ /* Default size is what GNU malloc can fit in a 4096-byte block. */
+ {
+ /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
+ Use the values for range checking, because if range checking is off,
+ the extra bytes won't be missed terribly, but if range checking is on
+ and we used a larger request, a whole extra 4096 bytes would be
+ allocated.
+
+ These number are irrelevant to the new GNU malloc. I suspect it is
+ less sensitive to the size of the request. */
+ int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+ + 4 + DEFAULT_ROUNDING - 1)
+ & ~(DEFAULT_ROUNDING - 1));
+ size = 4096 - extra;
+ }
+
+ h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
+ h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+ h->chunk_size = size;
+ h->alignment_mask = alignment - 1;
+ h->use_extra_arg = 0;
+
+ chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
+ if (!chunk)
+ (*obstack_alloc_failed_handler) ();
+ h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
+ alignment - 1);
+ h->chunk_limit = chunk->limit
+ = (char *) chunk + h->chunk_size;
+ chunk->prev = 0;
+ /* The initial chunk now contains no empty object. */
+ h->maybe_empty_object = 0;
+ h->alloc_failed = 0;
+ return 1;
+}
+
+int
+_obstack_begin_1 (struct obstack *h, int size, int alignment,
+ void *(*chunkfun) (void *, long),
+ void (*freefun) (void *, void *),
+ void *arg)
+{
+ register struct _obstack_chunk *chunk; /* points to new chunk */
+
+ if (alignment == 0)
+ alignment = DEFAULT_ALIGNMENT;
+ if (size == 0)
+ /* Default size is what GNU malloc can fit in a 4096-byte block. */
+ {
+ /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
+ Use the values for range checking, because if range checking is off,
+ the extra bytes won't be missed terribly, but if range checking is on
+ and we used a larger request, a whole extra 4096 bytes would be
+ allocated.
+
+ These number are irrelevant to the new GNU malloc. I suspect it is
+ less sensitive to the size of the request. */
+ int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+ + 4 + DEFAULT_ROUNDING - 1)
+ & ~(DEFAULT_ROUNDING - 1));
+ size = 4096 - extra;
+ }
+
+ h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
+ h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+ h->chunk_size = size;
+ h->alignment_mask = alignment - 1;
+ h->extra_arg = arg;
+ h->use_extra_arg = 1;
+
+ chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
+ if (!chunk)
+ (*obstack_alloc_failed_handler) ();
+ h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
+ alignment - 1);
+ h->chunk_limit = chunk->limit
+ = (char *) chunk + h->chunk_size;
+ chunk->prev = 0;
+ /* The initial chunk now contains no empty object. */
+ h->maybe_empty_object = 0;
+ h->alloc_failed = 0;
+ return 1;
+}
+
+/* Allocate a new current chunk for the obstack *H
+ on the assumption that LENGTH bytes need to be added
+ to the current object, or a new object of length LENGTH allocated.
+ Copies any partial object from the end of the old chunk
+ to the beginning of the new one. */
+
+void
+_obstack_newchunk (struct obstack *h, int length)
+{
+ register struct _obstack_chunk *old_chunk = h->chunk;
+ register struct _obstack_chunk *new_chunk;
+ register long new_size;
+ register long obj_size = h->next_free - h->object_base;
+ register long i;
+ long already;
+ char *object_base;
+
+ /* Compute size for new chunk. */
+ new_size = (obj_size + length) + (obj_size >> 3) + h->alignment_mask + 100;
+ if (new_size < h->chunk_size)
+ new_size = h->chunk_size;
+
+ /* Allocate and initialize the new chunk. */
+ new_chunk = CALL_CHUNKFUN (h, new_size);
+ if (!new_chunk)
+ (*obstack_alloc_failed_handler) ();
+ h->chunk = new_chunk;
+ new_chunk->prev = old_chunk;
+ new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
+
+ /* Compute an aligned object_base in the new chunk */
+ object_base =
+ __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask);
+
+ /* Move the existing object to the new chunk.
+ Word at a time is fast and is safe if the object
+ is sufficiently aligned. */
+ if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
+ {
+ for (i = obj_size / sizeof (COPYING_UNIT) - 1;
+ i >= 0; i--)
+ ((COPYING_UNIT *)object_base)[i]
+ = ((COPYING_UNIT *)h->object_base)[i];
+ /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
+ but that can cross a page boundary on a machine
+ which does not do strict alignment for COPYING_UNITS. */
+ already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
+ }
+ else
+ already = 0;
+ /* Copy remaining bytes one by one. */
+ for (i = already; i < obj_size; i++)
+ object_base[i] = h->object_base[i];
+
+ /* If the object just copied was the only data in OLD_CHUNK,
+ free that chunk and remove it from the chain.
+ But not if that chunk might contain an empty object. */
+ if (! h->maybe_empty_object
+ && (h->object_base
+ == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,
+ h->alignment_mask)))
+ {
+ new_chunk->prev = old_chunk->prev;
+ CALL_FREEFUN (h, old_chunk);
+ }
+
+ h->object_base = object_base;
+ h->next_free = h->object_base + obj_size;
+ /* The new chunk certainly contains no empty object yet. */
+ h->maybe_empty_object = 0;
+}
+# ifdef _LIBC
+libc_hidden_def (_obstack_newchunk)
+# endif
+
+/* Return nonzero if object OBJ has been allocated from obstack H.
+ This is here for debugging.
+ If you use it in a program, you are probably losing. */
+
+/* Suppress -Wmissing-prototypes warning. We don't want to declare this in
+ obstack.h because it is just for debugging. */
+int _obstack_allocated_p (struct obstack *h, void *obj);
+
+int
+_obstack_allocated_p (struct obstack *h, void *obj)
+{
+ register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk *plp; /* point to previous chunk if any */
+
+ lp = (h)->chunk;
+ /* We use >= rather than > since the object cannot be exactly at
+ the beginning of the chunk but might be an empty object exactly
+ at the end of an adjacent chunk. */
+ while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
+ {
+ plp = lp->prev;
+ lp = plp;
+ }
+ return lp != 0;
+}
+
+/* Free objects in obstack H, including OBJ and everything allocate
+ more recently than OBJ. If OBJ is zero, free everything in H. */
+
+# undef obstack_free
+
+void
+__obstack_free (struct obstack *h, void *obj)
+{
+ register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk *plp; /* point to previous chunk if any */
+
+ lp = h->chunk;
+ /* We use >= because there cannot be an object at the beginning of a chunk.
+ But there can be an empty object at that address
+ at the end of another chunk. */
+ while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
+ {
+ plp = lp->prev;
+ CALL_FREEFUN (h, lp);
+ lp = plp;
+ /* If we switch chunks, we can't tell whether the new current
+ chunk contains an empty object, so assume that it may. */
+ h->maybe_empty_object = 1;
+ }
+ if (lp)
+ {
+ h->object_base = h->next_free = (char *) (obj);
+ h->chunk_limit = lp->limit;
+ h->chunk = lp;
+ }
+ else if (obj != 0)
+ /* obj is not in any of the chunks! */
+ abort ();
+}
+
+# ifdef _LIBC
+/* Older versions of libc used a function _obstack_free intended to be
+ called by non-GCC compilers. */
+strong_alias (obstack_free, _obstack_free)
+# endif
+
+int
+_obstack_memory_used (struct obstack *h)
+{
+ register struct _obstack_chunk* lp;
+ register int nbytes = 0;
+
+ for (lp = h->chunk; lp != 0; lp = lp->prev)
+ {
+ nbytes += lp->limit - (char *) lp;
+ }
+ return nbytes;
+}
+
+/* Define the error handler. */
+# ifdef _LIBC
+# include <libintl.h>
+# else
+# include "gettext.h"
+# endif
+# ifndef _
+# define _(msgid) gettext (msgid)
+# endif
+
+# ifdef _LIBC
+# include <libio/iolibio.h>
+# endif
+
+# ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
+# define __attribute__(Spec) /* empty */
+# endif
+# endif
+
+static void
+__attribute__ ((noreturn))
+print_and_abort (void)
+{
+ /* Don't change any of these strings. Yes, it would be possible to add
+ the newline to the string and use fputs or so. But this must not
+ happen because the "memory exhausted" message appears in other places
+ like this and the translation should be reused instead of creating
+ a very similar string which requires a separate translation. */
+# ifdef _LIBC
+ (void) __fxprintf (NULL, "%s\n", _("memory exhausted"));
+# else
+ fprintf (stderr, "%s\n", _("memory exhausted"));
+# endif
+ exit (obstack_exit_failure);
+}
+
+#endif /* !ELIDE_CODE */
diff --git a/lib/obstack.h b/lib/obstack.h
new file mode 100644
index 0000000..3315dfe
--- /dev/null
+++ b/lib/obstack.h
@@ -0,0 +1,513 @@
+/* obstack.h - object stack macros
+ Copyright (C) 1988-1994,1996-1999,2003,2004,2005,2006
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Summary:
+
+All the apparent functions defined here are macros. The idea
+is that you would use these pre-tested macros to solve a
+very specific set of problems, and they would run fast.
+Caution: no side-effects in arguments please!! They may be
+evaluated MANY times!!
+
+These macros operate a stack of objects. Each object starts life
+small, and may grow to maturity. (Consider building a word syllable
+by syllable.) An object can move while it is growing. Once it has
+been "finished" it never changes address again. So the "top of the
+stack" is typically an immature growing object, while the rest of the
+stack is of mature, fixed size and fixed address objects.
+
+These routines grab large chunks of memory, using a function you
+supply, called `obstack_chunk_alloc'. On occasion, they free chunks,
+by calling `obstack_chunk_free'. You must define them and declare
+them before using any obstack macros.
+
+Each independent stack is represented by a `struct obstack'.
+Each of the obstack macros expects a pointer to such a structure
+as the first argument.
+
+One motivation for this package is the problem of growing char strings
+in symbol tables. Unless you are "fascist pig with a read-only mind"
+--Gosper's immortal quote from HAKMEM item 154, out of context--you
+would not like to put any arbitrary upper limit on the length of your
+symbols.
+
+In practice this often means you will build many short symbols and a
+few long symbols. At the time you are reading a symbol you don't know
+how long it is. One traditional method is to read a symbol into a
+buffer, realloc()ating the buffer every time you try to read a symbol
+that is longer than the buffer. This is beaut, but you still will
+want to copy the symbol from the buffer to a more permanent
+symbol-table entry say about half the time.
+
+With obstacks, you can work differently. Use one obstack for all symbol
+names. As you read a symbol, grow the name in the obstack gradually.
+When the name is complete, finalize it. Then, if the symbol exists already,
+free the newly read name.
+
+The way we do this is to take a large chunk, allocating memory from
+low addresses. When you want to build a symbol in the chunk you just
+add chars above the current "high water mark" in the chunk. When you
+have finished adding chars, because you got to the end of the symbol,
+you know how long the chars are, and you can create a new object.
+Mostly the chars will not burst over the highest address of the chunk,
+because you would typically expect a chunk to be (say) 100 times as
+long as an average object.
+
+In case that isn't clear, when we have enough chars to make up
+the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
+so we just point to it where it lies. No moving of chars is
+needed and this is the second win: potentially long strings need
+never be explicitly shuffled. Once an object is formed, it does not
+change its address during its lifetime.
+
+When the chars burst over a chunk boundary, we allocate a larger
+chunk, and then copy the partly formed object from the end of the old
+chunk to the beginning of the new larger chunk. We then carry on
+accreting characters to the end of the object as we normally would.
+
+A special macro is provided to add a single char at a time to a
+growing object. This allows the use of register variables, which
+break the ordinary 'growth' macro.
+
+Summary:
+ We allocate large chunks.
+ We carve out one object at a time from the current chunk.
+ Once carved, an object never moves.
+ We are free to append data of any size to the currently
+ growing object.
+ Exactly one object is growing in an obstack at any one time.
+ You can run one obstack per control block.
+ You may have as many control blocks as you dare.
+ Because of the way we do it, you can `unwind' an obstack
+ back to a previous state. (You may remove objects much
+ as you would with a stack.)
+*/
+
+
+/* Don't do the contents of this file more than once. */
+
+#ifndef _OBSTACK_H
+#define _OBSTACK_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* We need the type of a pointer subtraction. If __PTRDIFF_TYPE__ is
+ defined, as with GNU C, use that; that way we don't pollute the
+ namespace with <stddef.h>'s symbols. Otherwise, include <stddef.h>
+ and use ptrdiff_t. */
+
+#ifdef __PTRDIFF_TYPE__
+# define PTR_INT_TYPE __PTRDIFF_TYPE__
+#else
+# include <stddef.h>
+# define PTR_INT_TYPE ptrdiff_t
+#endif
+
+/* If B is the base of an object addressed by P, return the result of
+ aligning P to the next multiple of A + 1. B and P must be of type
+ char *. A + 1 must be a power of 2. */
+
+#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A)))
+
+/* Similiar to _BPTR_ALIGN (B, P, A), except optimize the common case
+ where pointers can be converted to integers, aligned as integers,
+ and converted back again. If PTR_INT_TYPE is narrower than a
+ pointer (e.g., the AS/400), play it safe and compute the alignment
+ relative to B. Otherwise, use the faster strategy of computing the
+ alignment relative to 0. */
+
+#define __PTR_ALIGN(B, P, A) \
+ __BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \
+ P, A)
+
+#include <string.h>
+
+struct _obstack_chunk /* Lives at front of each chunk. */
+{
+ char *limit; /* 1 past end of this chunk */
+ struct _obstack_chunk *prev; /* address of prior chunk or NULL */
+ char contents[4]; /* objects begin here */
+};
+
+struct obstack /* control current object in current chunk */
+{
+ long chunk_size; /* preferred size to allocate chunks in */
+ struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */
+ char *object_base; /* address of object we are building */
+ char *next_free; /* where to add next char to current object */
+ char *chunk_limit; /* address of char after current chunk */
+ union
+ {
+ PTR_INT_TYPE tempint;
+ void *tempptr;
+ } temp; /* Temporary for some macros. */
+ int alignment_mask; /* Mask of alignment for each object. */
+ /* These prototypes vary based on `use_extra_arg', and we use
+ casts to the prototypeless function type in all assignments,
+ but having prototypes here quiets -Wstrict-prototypes. */
+ struct _obstack_chunk *(*chunkfun) (void *, long);
+ void (*freefun) (void *, struct _obstack_chunk *);
+ void *extra_arg; /* first arg for chunk alloc/dealloc funcs */
+ unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */
+ unsigned maybe_empty_object:1;/* There is a possibility that the current
+ chunk contains a zero-length object. This
+ prevents freeing the chunk if we allocate
+ a bigger chunk to replace it. */
+ unsigned alloc_failed:1; /* No longer used, as we now call the failed
+ handler on error, but retained for binary
+ compatibility. */
+};
+
+/* Declare the external functions we use; they are in obstack.c. */
+
+extern void _obstack_newchunk (struct obstack *, int);
+extern int _obstack_begin (struct obstack *, int, int,
+ void *(*) (long), void (*) (void *));
+extern int _obstack_begin_1 (struct obstack *, int, int,
+ void *(*) (void *, long),
+ void (*) (void *, void *), void *);
+extern int _obstack_memory_used (struct obstack *);
+
+/* The default name of the function for freeing a chunk is 'obstack_free',
+ but gnulib users can override this by defining '__obstack_free'. */
+#ifndef __obstack_free
+# define __obstack_free obstack_free
+#endif
+extern void __obstack_free (struct obstack *obstack, void *block);
+
+
+/* Error handler called when `obstack_chunk_alloc' failed to allocate
+ more memory. This can be set to a user defined function which
+ should either abort gracefully or use longjump - but shouldn't
+ return. The default action is to print a message and abort. */
+extern void (*obstack_alloc_failed_handler) (void);
+
+/* Exit value used when `print_and_abort' is used. */
+extern int obstack_exit_failure;
+
+/* Pointer to beginning of object being allocated or to be allocated next.
+ Note that this might not be the final address of the object
+ because a new chunk might be needed to hold the final size. */
+
+#define obstack_base(h) ((void *) (h)->object_base)
+
+/* Size for allocating ordinary chunks. */
+
+#define obstack_chunk_size(h) ((h)->chunk_size)
+
+/* Pointer to next byte not yet allocated in current chunk. */
+
+#define obstack_next_free(h) ((h)->next_free)
+
+/* Mask specifying low bits that should be clear in address of an object. */
+
+#define obstack_alignment_mask(h) ((h)->alignment_mask)
+
+/* To prevent prototype warnings provide complete argument list. */
+#define obstack_init(h) \
+ _obstack_begin ((h), 0, 0, \
+ (void *(*) (long)) obstack_chunk_alloc, \
+ (void (*) (void *)) obstack_chunk_free)
+
+#define obstack_begin(h, size) \
+ _obstack_begin ((h), (size), 0, \
+ (void *(*) (long)) obstack_chunk_alloc, \
+ (void (*) (void *)) obstack_chunk_free)
+
+#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
+ _obstack_begin ((h), (size), (alignment), \
+ (void *(*) (long)) (chunkfun), \
+ (void (*) (void *)) (freefun))
+
+#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
+ _obstack_begin_1 ((h), (size), (alignment), \
+ (void *(*) (void *, long)) (chunkfun), \
+ (void (*) (void *, void *)) (freefun), (arg))
+
+#define obstack_chunkfun(h, newchunkfun) \
+ ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun))
+
+#define obstack_freefun(h, newfreefun) \
+ ((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun))
+
+#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = (achar))
+
+#define obstack_blank_fast(h,n) ((h)->next_free += (n))
+
+#define obstack_memory_used(h) _obstack_memory_used (h)
+
+#if defined __GNUC__ && defined __STDC__ && __STDC__
+/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and
+ does not implement __extension__. But that compiler doesn't define
+ __GNUC_MINOR__. */
+# if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__)
+# define __extension__
+# endif
+
+/* For GNU C, if not -traditional,
+ we can define these macros to compute all args only once
+ without using a global variable.
+ Also, we can avoid using the `temp' slot, to make faster code. */
+
+# define obstack_object_size(OBSTACK) \
+ __extension__ \
+ ({ struct obstack const *__o = (OBSTACK); \
+ (unsigned) (__o->next_free - __o->object_base); })
+
+# define obstack_room(OBSTACK) \
+ __extension__ \
+ ({ struct obstack const *__o = (OBSTACK); \
+ (unsigned) (__o->chunk_limit - __o->next_free); })
+
+# define obstack_make_room(OBSTACK,length) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ if (__o->chunk_limit - __o->next_free < __len) \
+ _obstack_newchunk (__o, __len); \
+ (void) 0; })
+
+# define obstack_empty_p(OBSTACK) \
+ __extension__ \
+ ({ struct obstack const *__o = (OBSTACK); \
+ (__o->chunk->prev == 0 \
+ && __o->next_free == __PTR_ALIGN ((char *) __o->chunk, \
+ __o->chunk->contents, \
+ __o->alignment_mask)); })
+
+# define obstack_grow(OBSTACK,where,length) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ if (__o->next_free + __len > __o->chunk_limit) \
+ _obstack_newchunk (__o, __len); \
+ memcpy (__o->next_free, where, __len); \
+ __o->next_free += __len; \
+ (void) 0; })
+
+# define obstack_grow0(OBSTACK,where,length) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ if (__o->next_free + __len + 1 > __o->chunk_limit) \
+ _obstack_newchunk (__o, __len + 1); \
+ memcpy (__o->next_free, where, __len); \
+ __o->next_free += __len; \
+ *(__o->next_free)++ = 0; \
+ (void) 0; })
+
+# define obstack_1grow(OBSTACK,datum) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ if (__o->next_free + 1 > __o->chunk_limit) \
+ _obstack_newchunk (__o, 1); \
+ obstack_1grow_fast (__o, datum); \
+ (void) 0; })
+
+/* These assume that the obstack alignment is good enough for pointers
+ or ints, and that the data added so far to the current object
+ shares that much alignment. */
+
+# define obstack_ptr_grow(OBSTACK,datum) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ if (__o->next_free + sizeof (void *) > __o->chunk_limit) \
+ _obstack_newchunk (__o, sizeof (void *)); \
+ obstack_ptr_grow_fast (__o, datum); }) \
+
+# define obstack_int_grow(OBSTACK,datum) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ if (__o->next_free + sizeof (int) > __o->chunk_limit) \
+ _obstack_newchunk (__o, sizeof (int)); \
+ obstack_int_grow_fast (__o, datum); })
+
+# define obstack_ptr_grow_fast(OBSTACK,aptr) \
+__extension__ \
+({ struct obstack *__o1 = (OBSTACK); \
+ *(const void **) __o1->next_free = (aptr); \
+ __o1->next_free += sizeof (const void *); \
+ (void) 0; })
+
+# define obstack_int_grow_fast(OBSTACK,aint) \
+__extension__ \
+({ struct obstack *__o1 = (OBSTACK); \
+ *(int *) __o1->next_free = (aint); \
+ __o1->next_free += sizeof (int); \
+ (void) 0; })
+
+# define obstack_blank(OBSTACK,length) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ if (__o->chunk_limit - __o->next_free < __len) \
+ _obstack_newchunk (__o, __len); \
+ obstack_blank_fast (__o, __len); \
+ (void) 0; })
+
+# define obstack_alloc(OBSTACK,length) \
+__extension__ \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_blank (__h, (length)); \
+ obstack_finish (__h); })
+
+# define obstack_copy(OBSTACK,where,length) \
+__extension__ \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_grow (__h, (where), (length)); \
+ obstack_finish (__h); })
+
+# define obstack_copy0(OBSTACK,where,length) \
+__extension__ \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_grow0 (__h, (where), (length)); \
+ obstack_finish (__h); })
+
+/* The local variable is named __o1 to avoid a name conflict
+ when obstack_blank is called. */
+# define obstack_finish(OBSTACK) \
+__extension__ \
+({ struct obstack *__o1 = (OBSTACK); \
+ void *__value = (void *) __o1->object_base; \
+ if (__o1->next_free == __value) \
+ __o1->maybe_empty_object = 1; \
+ __o1->next_free \
+ = __PTR_ALIGN (__o1->object_base, __o1->next_free, \
+ __o1->alignment_mask); \
+ if (__o1->next_free - (char *)__o1->chunk \
+ > __o1->chunk_limit - (char *)__o1->chunk) \
+ __o1->next_free = __o1->chunk_limit; \
+ __o1->object_base = __o1->next_free; \
+ __value; })
+
+# define obstack_free(OBSTACK, OBJ) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ void *__obj = (OBJ); \
+ if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
+ __o->next_free = __o->object_base = (char *)__obj; \
+ else (__obstack_free) (__o, __obj); })
+
+#else /* not __GNUC__ or not __STDC__ */
+
+# define obstack_object_size(h) \
+ (unsigned) ((h)->next_free - (h)->object_base)
+
+# define obstack_room(h) \
+ (unsigned) ((h)->chunk_limit - (h)->next_free)
+
+# define obstack_empty_p(h) \
+ ((h)->chunk->prev == 0 \
+ && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk, \
+ (h)->chunk->contents, \
+ (h)->alignment_mask))
+
+/* Note that the call to _obstack_newchunk is enclosed in (..., 0)
+ so that we can avoid having void expressions
+ in the arms of the conditional expression.
+ Casting the third operand to void was tried before,
+ but some compilers won't accept it. */
+
+# define obstack_make_room(h,length) \
+( (h)->temp.tempint = (length), \
+ (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0))
+
+# define obstack_grow(h,where,length) \
+( (h)->temp.tempint = (length), \
+ (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \
+ memcpy ((h)->next_free, where, (h)->temp.tempint), \
+ (h)->next_free += (h)->temp.tempint)
+
+# define obstack_grow0(h,where,length) \
+( (h)->temp.tempint = (length), \
+ (((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), (h)->temp.tempint + 1), 0) : 0), \
+ memcpy ((h)->next_free, where, (h)->temp.tempint), \
+ (h)->next_free += (h)->temp.tempint, \
+ *((h)->next_free)++ = 0)
+
+# define obstack_1grow(h,datum) \
+( (((h)->next_free + 1 > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), 1), 0) : 0), \
+ obstack_1grow_fast (h, datum))
+
+# define obstack_ptr_grow(h,datum) \
+( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
+ obstack_ptr_grow_fast (h, datum))
+
+# define obstack_int_grow(h,datum) \
+( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
+ obstack_int_grow_fast (h, datum))
+
+# define obstack_ptr_grow_fast(h,aptr) \
+ (((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr))
+
+# define obstack_int_grow_fast(h,aint) \
+ (((int *) ((h)->next_free += sizeof (int)))[-1] = (aint))
+
+# define obstack_blank(h,length) \
+( (h)->temp.tempint = (length), \
+ (((h)->chunk_limit - (h)->next_free < (h)->temp.tempint) \
+ ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \
+ obstack_blank_fast (h, (h)->temp.tempint))
+
+# define obstack_alloc(h,length) \
+ (obstack_blank ((h), (length)), obstack_finish ((h)))
+
+# define obstack_copy(h,where,length) \
+ (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
+
+# define obstack_copy0(h,where,length) \
+ (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
+
+# define obstack_finish(h) \
+( ((h)->next_free == (h)->object_base \
+ ? (((h)->maybe_empty_object = 1), 0) \
+ : 0), \
+ (h)->temp.tempptr = (h)->object_base, \
+ (h)->next_free \
+ = __PTR_ALIGN ((h)->object_base, (h)->next_free, \
+ (h)->alignment_mask), \
+ (((h)->next_free - (char *) (h)->chunk \
+ > (h)->chunk_limit - (char *) (h)->chunk) \
+ ? ((h)->next_free = (h)->chunk_limit) : 0), \
+ (h)->object_base = (h)->next_free, \
+ (h)->temp.tempptr)
+
+# define obstack_free(h,obj) \
+( (h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk, \
+ ((((h)->temp.tempint > 0 \
+ && (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk)) \
+ ? (int) ((h)->next_free = (h)->object_base \
+ = (h)->temp.tempint + (char *) (h)->chunk) \
+ : (((__obstack_free) ((h), (h)->temp.tempint + (char *) (h)->chunk), 0), 0)))
+
+#endif /* not __GNUC__ or not __STDC__ */
+
+#ifdef __cplusplus
+} /* C++ */
+#endif
+
+#endif /* obstack.h */
diff --git a/lib/offtostr.c b/lib/offtostr.c
new file mode 100644
index 0000000..45196e2
--- /dev/null
+++ b/lib/offtostr.c
@@ -0,0 +1,3 @@
+#define inttostr offtostr
+#define inttype off_t
+#include "inttostr.c"
diff --git a/lib/open-safer.c b/lib/open-safer.c
new file mode 100644
index 0000000..04a72eb
--- /dev/null
+++ b/lib/open-safer.c
@@ -0,0 +1,50 @@
+/* Invoke open, but avoid some glitches.
+
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert. */
+
+#include <config.h>
+
+#include "fcntl-safer.h"
+
+#include <fcntl.h>
+#include <stdarg.h>
+#include "unistd-safer.h"
+
+int
+open_safer (char const *file, int flags, ...)
+{
+ mode_t mode = 0;
+
+ if (flags & O_CREAT)
+ {
+ va_list ap;
+ va_start (ap, flags);
+
+ /* Assume mode_t promotes to int if and only if it is smaller.
+ This assumption isn't guaranteed by the C standard, but we
+ don't know of any real-world counterexamples. */
+ mode = (sizeof (mode_t) < sizeof (int)
+ ? va_arg (ap, int)
+ : va_arg (ap, mode_t));
+
+ va_end (ap);
+ }
+
+ return fd_safer (open (file, flags, mode));
+}
diff --git a/lib/openat-die.c b/lib/openat-die.c
new file mode 100644
index 0000000..7a28570
--- /dev/null
+++ b/lib/openat-die.c
@@ -0,0 +1,51 @@
+/* Report a save- or restore-cwd failure in our openat replacement and then exit.
+
+ 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. */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include "error.h"
+#include "exitfail.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+void
+openat_save_fail (int errno)
+{
+ error (exit_failure, errno,
+ _("unable to record current working directory"));
+
+ /* The `noreturn' attribute cannot be applied to error, since it returns
+ when its first argument is 0. To help compilers understand that this
+ function does not return, call abort. Also, the abort is a
+ safety feature if exit_failure is 0 (which shouldn't happen). */
+ abort ();
+}
+
+void
+openat_restore_fail (int errno)
+{
+ error (exit_failure, errno,
+ _("failed to return to initial working directory"));
+
+ /* As above. */
+ abort ();
+}
diff --git a/lib/openat-priv.h b/lib/openat-priv.h
new file mode 100644
index 0000000..2d98821
--- /dev/null
+++ b/lib/openat-priv.h
@@ -0,0 +1,55 @@
+/* Internals for openat-like functions.
+
+ 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 Jim Meyering */
+
+#include <errno.h>
+#include <stdlib.h>
+
+#define OPENAT_BUFFER_SIZE 512
+char *openat_proc_name (char buf[OPENAT_BUFFER_SIZE], int fd, char const *file);
+
+/* Some systems don't have ENOSYS. */
+#ifndef ENOSYS
+# ifdef ENOTSUP
+# define ENOSYS ENOTSUP
+# else
+/* Some systems don't have ENOTSUP either. */
+# define ENOSYS EINVAL
+# endif
+#endif
+
+/* Some systems don't have EOPNOTSUPP. */
+#ifndef EOPNOTSUPP
+# ifdef ENOTSUP
+# define EOPNOTSUPP ENOTSUP
+# else
+/* Some systems don't have ENOTSUP either. */
+# define EOPNOTSUPP EINVAL
+# endif
+#endif
+
+/* Trying to access a BUILD_PROC_NAME file will fail on systems without
+ /proc support, and even on systems *with* ProcFS support. Return
+ nonzero if the failure may be legitimate, e.g., because /proc is not
+ readable, or the particular .../fd/N directory is not present. */
+#define EXPECTED_ERRNO(Errno) \
+ ((Errno) == ENOTDIR || (Errno) == ENOENT \
+ || (Errno) == EPERM || (Errno) == EACCES \
+ || (Errno) == ENOSYS /* Solaris 8 */ \
+ || (Errno) == EOPNOTSUPP /* FreeBSD */)
diff --git a/lib/openat-proc.c b/lib/openat-proc.c
new file mode 100644
index 0000000..ff2fff0
--- /dev/null
+++ b/lib/openat-proc.c
@@ -0,0 +1,95 @@
+/* Create /proc/self/fd-related names for subfiles of open directories.
+
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert. */
+
+#include <config.h>
+
+#include "openat-priv.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "dirname.h"
+#include "intprops.h"
+#include "same-inode.h"
+#include "xalloc.h"
+
+/* The results of open() in this file are not used with fchdir,
+ therefore save some unnecessary work in fchdir.c. */
+#undef open
+#undef close
+
+#define PROC_SELF_FD_FORMAT "/proc/self/fd/%d/%s"
+
+#define PROC_SELF_FD_NAME_SIZE_BOUND(len) \
+ (sizeof PROC_SELF_FD_FORMAT - sizeof "%d%s" \
+ + INT_STRLEN_BOUND (int) + (len) + 1)
+
+
+/* Set BUF to the expansion of PROC_SELF_FD_FORMAT, using FD and FILE
+ respectively for %d and %s. If successful, return BUF if the
+ result fits in BUF, dynamically allocated memory otherwise. But
+ return NULL if /proc is not reliable. */
+char *
+openat_proc_name (char buf[OPENAT_BUFFER_SIZE], int fd, char const *file)
+{
+ static int proc_status = 0;
+
+ if (! proc_status)
+ {
+ /* Set PROC_STATUS to a positive value if /proc/self/fd is
+ reliable, and a negative value otherwise. Solaris 10
+ /proc/self/fd mishandles "..", and any file name might expand
+ to ".." after symbolic link expansion, so avoid /proc/self/fd
+ if it mishandles "..". Solaris 10 has openat, but this
+ problem is exhibited on code that built on Solaris 8 and
+ running on Solaris 10. */
+
+ int proc_self_fd = open ("/proc/self/fd", O_RDONLY);
+ if (proc_self_fd < 0)
+ proc_status = -1;
+ else
+ {
+ struct stat proc_self_fd_dotdot_st;
+ struct stat proc_self_st;
+ char dotdot_buf[PROC_SELF_FD_NAME_SIZE_BOUND (sizeof ".." - 1)];
+ sprintf (dotdot_buf, PROC_SELF_FD_FORMAT, proc_self_fd, "..");
+ proc_status =
+ ((stat (dotdot_buf, &proc_self_fd_dotdot_st) == 0
+ && stat ("/proc/self", &proc_self_st) == 0
+ && SAME_INODE (proc_self_fd_dotdot_st, proc_self_st))
+ ? 1 : -1);
+ close (proc_self_fd);
+ }
+ }
+
+ if (proc_status < 0)
+ return NULL;
+ else
+ {
+ size_t bufsize = PROC_SELF_FD_NAME_SIZE_BOUND (strlen (file));
+ char *result = (bufsize < OPENAT_BUFFER_SIZE ? buf : xmalloc (bufsize));
+ sprintf (result, PROC_SELF_FD_FORMAT, fd, file);
+ return result;
+ }
+}
diff --git a/lib/openat.c b/lib/openat.c
new file mode 100644
index 0000000..cd49654
--- /dev/null
+++ b/lib/openat.c
@@ -0,0 +1,270 @@
+/* provide a replacement openat function
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* written by Jim Meyering */
+
+#include <config.h>
+
+#include "openat.h"
+
+#include <stdarg.h>
+#include <stddef.h>
+
+#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
+#include "fcntl--.h"
+#include "lchown.h"
+#include "lstat.h"
+#include "openat-priv.h"
+#include "save-cwd.h"
+
+/* Replacement for Solaris' openat function.
+ <http://www.google.com/search?q=openat+site:docs.sun.com>
+ First, try to simulate it via open ("/proc/self/fd/FD/FILE").
+ Failing that, simulate it by doing save_cwd/fchdir/open/restore_cwd.
+ If either the save_cwd or the restore_cwd fails (relatively unlikely),
+ then give a diagnostic and exit nonzero.
+ Otherwise, upon failure, set errno and return -1, as openat does.
+ Upon successful completion, return a file descriptor. */
+int
+openat (int fd, char const *file, int flags, ...)
+{
+ mode_t mode = 0;
+
+ if (flags & O_CREAT)
+ {
+ va_list arg;
+ va_start (arg, flags);
+
+ /* If mode_t is narrower than int, use the promoted type (int),
+ not mode_t. Use sizeof to guess whether mode_t is narrower;
+ we don't know of any practical counterexamples. */
+ mode = (sizeof (mode_t) < sizeof (int)
+ ? va_arg (arg, int)
+ : va_arg (arg, mode_t));
+
+ va_end (arg);
+ }
+
+ return openat_permissive (fd, file, flags, mode, NULL);
+}
+
+/* Like openat (FD, FILE, FLAGS, MODE), but if CWD_ERRNO is
+ nonnull, set *CWD_ERRNO to an errno value if unable to save
+ or restore the initial working directory. This is needed only
+ the first time remove.c's remove_dir opens a command-line
+ directory argument.
+
+ If a previous attempt to restore the current working directory
+ failed, then we must not even try to access a `.'-relative name.
+ It is the caller's responsibility not to call this function
+ in that case. */
+
+int
+openat_permissive (int fd, char const *file, int flags, mode_t mode,
+ int *cwd_errno)
+{
+ struct saved_cwd saved_cwd;
+ int saved_errno;
+ int err;
+ bool save_ok;
+
+ if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file))
+ return open (file, flags, mode);
+
+ {
+ char buf[OPENAT_BUFFER_SIZE];
+ char *proc_file = openat_proc_name (buf, fd, file);
+ if (proc_file)
+ {
+ int open_result = open (proc_file, flags, mode);
+ int open_errno = errno;
+ if (proc_file != buf)
+ free (proc_file);
+ /* If the syscall succeeds, or if it fails with an unexpected
+ errno value, then return right away. Otherwise, fall through
+ and resort to using save_cwd/restore_cwd. */
+ if (0 <= open_result || ! EXPECTED_ERRNO (open_errno))
+ {
+ errno = open_errno;
+ return open_result;
+ }
+ }
+ }
+
+ save_ok = (save_cwd (&saved_cwd) == 0);
+ if (! save_ok)
+ {
+ if (! cwd_errno)
+ openat_save_fail (errno);
+ *cwd_errno = errno;
+ }
+
+ err = fchdir (fd);
+ saved_errno = errno;
+
+ if (! err)
+ {
+ err = open (file, flags, mode);
+ saved_errno = errno;
+ if (save_ok && restore_cwd (&saved_cwd) != 0)
+ {
+ if (! cwd_errno)
+ openat_restore_fail (errno);
+ *cwd_errno = errno;
+ }
+ }
+
+ free_cwd (&saved_cwd);
+ errno = saved_errno;
+ return err;
+}
+
+/* Return true if our openat implementation must resort to
+ using save_cwd and restore_cwd. */
+bool
+openat_needs_fchdir (void)
+{
+ bool needs_fchdir = true;
+ int fd = open ("/", O_RDONLY);
+
+ if (0 <= fd)
+ {
+ char buf[OPENAT_BUFFER_SIZE];
+ char *proc_file = openat_proc_name (buf, fd, ".");
+ if (proc_file)
+ {
+ needs_fchdir = false;
+ if (proc_file != buf)
+ free (proc_file);
+ }
+ close (fd);
+ }
+
+ return needs_fchdir;
+}
+
+#if !HAVE_FDOPENDIR
+
+/* Replacement for Solaris' function by the same name.
+ <http://www.google.com/search?q=fdopendir+site:docs.sun.com>
+ First, try to simulate it via opendir ("/proc/self/fd/FD"). Failing
+ that, simulate it by doing save_cwd/fchdir/opendir(".")/restore_cwd.
+ If either the save_cwd or the restore_cwd fails (relatively unlikely),
+ then give a diagnostic and exit nonzero.
+ Otherwise, this function works just like Solaris' fdopendir.
+
+ W A R N I N G:
+ Unlike the other fd-related functions here, this one
+ effectively consumes its FD parameter. The caller should not
+ close or otherwise manipulate FD if this function returns successfully. */
+DIR *
+fdopendir (int fd)
+{
+ struct saved_cwd saved_cwd;
+ int saved_errno;
+ DIR *dir;
+
+ char buf[OPENAT_BUFFER_SIZE];
+ char *proc_file = openat_proc_name (buf, fd, ".");
+ if (proc_file)
+ {
+ dir = opendir (proc_file);
+ saved_errno = errno;
+ }
+ else
+ {
+ dir = NULL;
+ saved_errno = EOPNOTSUPP;
+ }
+
+ /* If the syscall fails with an expected errno value, resort to
+ save_cwd/restore_cwd. */
+ if (! dir && EXPECTED_ERRNO (saved_errno))
+ {
+ if (save_cwd (&saved_cwd) != 0)
+ openat_save_fail (errno);
+
+ if (fchdir (fd) != 0)
+ {
+ dir = NULL;
+ saved_errno = errno;
+ }
+ else
+ {
+ dir = opendir (".");
+ saved_errno = errno;
+
+ if (restore_cwd (&saved_cwd) != 0)
+ openat_restore_fail (errno);
+ }
+
+ free_cwd (&saved_cwd);
+ }
+
+ if (dir)
+ close (fd);
+ if (proc_file != buf)
+ free (proc_file);
+ errno = saved_errno;
+ return dir;
+}
+
+#endif
+
+/* Replacement for Solaris' function by the same name.
+ <http://www.google.com/search?q=fstatat+site:docs.sun.com>
+ First, try to simulate it via l?stat ("/proc/self/fd/FD/FILE").
+ Failing that, simulate it via save_cwd/fchdir/(stat|lstat)/restore_cwd.
+ If either the save_cwd or the restore_cwd fails (relatively unlikely),
+ then give a diagnostic and exit nonzero.
+ Otherwise, this function works just like Solaris' fstatat. */
+
+#define AT_FUNC_NAME fstatat
+#define AT_FUNC_F1 lstat
+#define AT_FUNC_F2 stat
+#define AT_FUNC_USE_F1_COND flag == AT_SYMLINK_NOFOLLOW
+#define AT_FUNC_POST_FILE_PARAM_DECLS , struct stat *st, int flag
+#define AT_FUNC_POST_FILE_ARGS , st
+#include "at-func.c"
+#undef AT_FUNC_NAME
+#undef AT_FUNC_F1
+#undef AT_FUNC_F2
+#undef AT_FUNC_USE_F1_COND
+#undef AT_FUNC_POST_FILE_PARAM_DECLS
+#undef AT_FUNC_POST_FILE_ARGS
+
+/* Replacement for Solaris' function by the same name.
+ <http://www.google.com/search?q=unlinkat+site:docs.sun.com>
+ First, try to simulate it via (unlink|rmdir) ("/proc/self/fd/FD/FILE").
+ Failing that, simulate it via save_cwd/fchdir/(unlink|rmdir)/restore_cwd.
+ If either the save_cwd or the restore_cwd fails (relatively unlikely),
+ then give a diagnostic and exit nonzero.
+ Otherwise, this function works just like Solaris' unlinkat. */
+
+#define AT_FUNC_NAME unlinkat
+#define AT_FUNC_F1 rmdir
+#define AT_FUNC_F2 unlink
+#define AT_FUNC_USE_F1_COND flag == AT_REMOVEDIR
+#define AT_FUNC_POST_FILE_PARAM_DECLS , int flag
+#define AT_FUNC_POST_FILE_ARGS /* empty */
+#include "at-func.c"
+#undef AT_FUNC_NAME
+#undef AT_FUNC_F1
+#undef AT_FUNC_F2
+#undef AT_FUNC_USE_F1_COND
+#undef AT_FUNC_POST_FILE_PARAM_DECLS
+#undef AT_FUNC_POST_FILE_ARGS
diff --git a/lib/openat.h b/lib/openat.h
new file mode 100644
index 0000000..f8333f0
--- /dev/null
+++ b/lib/openat.h
@@ -0,0 +1,127 @@
+/* provide a replacement openat function
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* written by Jim Meyering */
+
+#include <fcntl.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#ifndef __attribute__
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
+# define __attribute__(x) /* empty */
+# endif
+#endif
+
+#ifndef ATTRIBUTE_NORETURN
+# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
+#endif
+
+/* Work around a bug in Solaris 9 and 10: AT_FDCWD is positive. Its
+ value exceeds INT_MAX, so its use as an int doesn't conform to the
+ C standard, and GCC and Sun C complain in some cases. If the bug
+ is present, undef AT_FDCWD here, so it can be redefined below. */
+#if 0 < AT_FDCWD && AT_FDCWD == 0xffd19553
+# undef AT_FDCWD
+#endif
+
+/* Use the same bit pattern as Solaris 9, but with the proper
+ signedness. The bit pattern is important, in case this actually is
+ Solaris with the above workaround. */
+#ifndef AT_FDCWD
+# define AT_FDCWD (-3041965)
+#endif
+
+/* Use the same values as Solaris 9. This shouldn't matter, but
+ there's no real reason to differ. */
+#ifndef AT_SYMLINK_NOFOLLOW
+# define AT_SYMLINK_NOFOLLOW 4096
+# define AT_REMOVEDIR 1
+#endif
+
+#ifdef __OPENAT_PREFIX
+
+# undef openat
+# define __OPENAT_CONCAT(x, y) x ## y
+# define __OPENAT_XCONCAT(x, y) __OPENAT_CONCAT (x, y)
+# define __OPENAT_ID(y) __OPENAT_XCONCAT (__OPENAT_PREFIX, y)
+# define openat __OPENAT_ID (openat)
+int openat (int fd, char const *file, int flags, /* mode_t mode */ ...);
+int openat_permissive (int fd, char const *file, int flags, mode_t mode,
+ int *cwd_errno);
+# if ! HAVE_FDOPENDIR
+# define fdopendir __OPENAT_ID (fdopendir)
+# endif
+DIR *fdopendir (int fd);
+# define fstatat __OPENAT_ID (fstatat)
+int fstatat (int fd, char const *file, struct stat *st, int flag);
+# define unlinkat __OPENAT_ID (unlinkat)
+int unlinkat (int fd, char const *file, int flag);
+bool openat_needs_fchdir (void);
+
+#else
+
+# define openat_permissive(Fd, File, Flags, Mode, Cwd_errno) \
+ openat (Fd, File, Flags, Mode)
+# define openat_needs_fchdir() false
+
+#endif
+
+#if HAVE_OPENAT && ! LSTAT_FOLLOWS_SLASHED_SYMLINK
+int rpl_fstatat (int fd, char const *file, struct stat *st, int flag);
+# if !COMPILING_FSTATAT
+# undef fstatat
+# define fstatat rpl_fstatat
+# endif
+#endif
+
+int mkdirat (int fd, char const *file, mode_t mode);
+void openat_restore_fail (int) ATTRIBUTE_NORETURN;
+void openat_save_fail (int) ATTRIBUTE_NORETURN;
+int fchmodat (int fd, char const *file, mode_t mode, int flag);
+int fchownat (int fd, char const *file, uid_t owner, gid_t group, int flag);
+
+/* Using these function names makes application code
+ slightly more readable than it would be with
+ fchownat (..., 0) or fchownat (..., AT_SYMLINK_NOFOLLOW). */
+static inline int
+chownat (int fd, char const *file, uid_t owner, gid_t group)
+{
+ return fchownat (fd, file, owner, group, 0);
+}
+
+static inline int
+lchownat (int fd, char const *file, uid_t owner, gid_t group)
+{
+ return fchownat (fd, file, owner, group, AT_SYMLINK_NOFOLLOW);
+}
+
+static inline int
+chmodat (int fd, char const *file, mode_t mode)
+{
+ return fchmodat (fd, file, mode, 0);
+}
+
+static inline int
+lchmodat (int fd, char const *file, mode_t mode)
+{
+ return fchmodat (fd, file, mode, AT_SYMLINK_NOFOLLOW);
+}
diff --git a/lib/pathmax.h b/lib/pathmax.h
new file mode 100644
index 0000000..6941e45
--- /dev/null
+++ b/lib/pathmax.h
@@ -0,0 +1,47 @@
+/* Define PATH_MAX somehow. Requires sys/types.h.
+ Copyright (C) 1992, 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. */
+
+#ifndef _PATHMAX_H
+# define _PATHMAX_H
+
+# include <unistd.h>
+
+# include <limits.h>
+
+# ifndef _POSIX_PATH_MAX
+# define _POSIX_PATH_MAX 256
+# endif
+
+# if !defined PATH_MAX && defined _PC_PATH_MAX
+# define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 \
+ : pathconf ("/", _PC_PATH_MAX))
+# endif
+
+/* Don't include sys/param.h if it already has been. */
+# if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
+# include <sys/param.h>
+# endif
+
+# if !defined PATH_MAX && defined MAXPATHLEN
+# define PATH_MAX MAXPATHLEN
+# endif
+
+# ifndef PATH_MAX
+# define PATH_MAX _POSIX_PATH_MAX
+# endif
+
+#endif /* _PATHMAX_H */
diff --git a/lib/paxerror.c b/lib/paxerror.c
new file mode 100644
index 0000000..000d9e4
--- /dev/null
+++ b/lib/paxerror.c
@@ -0,0 +1,365 @@
+/* Miscellaneous error functions
+
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <system.h>
+#include <paxlib.h>
+#include <quote.h>
+#include <quotearg.h>
+
+/* Decode MODE from its binary form in a stat structure, and encode it
+ into a 9-byte string STRING, terminated with a NUL. */
+
+void
+pax_decode_mode (mode_t mode, char *string)
+{
+ *string++ = mode & S_IRUSR ? 'r' : '-';
+ *string++ = mode & S_IWUSR ? 'w' : '-';
+ *string++ = (mode & S_ISUID
+ ? (mode & S_IXUSR ? 's' : 'S')
+ : (mode & S_IXUSR ? 'x' : '-'));
+ *string++ = mode & S_IRGRP ? 'r' : '-';
+ *string++ = mode & S_IWGRP ? 'w' : '-';
+ *string++ = (mode & S_ISGID
+ ? (mode & S_IXGRP ? 's' : 'S')
+ : (mode & S_IXGRP ? 'x' : '-'));
+ *string++ = mode & S_IROTH ? 'r' : '-';
+ *string++ = mode & S_IWOTH ? 'w' : '-';
+ *string++ = (mode & S_ISVTX
+ ? (mode & S_IXOTH ? 't' : 'T')
+ : (mode & S_IXOTH ? 'x' : '-'));
+ *string = '\0';
+}
+
+/* Report an error associated with the system call CALL and the
+ optional name NAME. */
+void
+call_arg_error (char const *call, char const *name)
+{
+ int e = errno;
+ /* TRANSLATORS: %s after `Cannot' is a function name, e.g. `Cannot open'.
+ Directly translating this to another language will not work, first because
+ %s itself is not translated.
+ Translate it as `%s: Function %s failed'. */
+ ERROR ((0, e, _("%s: Cannot %s"), quotearg_colon (name), call));
+}
+
+/* Report a fatal error associated with the system call CALL and
+ the optional file name NAME. */
+void
+call_arg_fatal (char const *call, char const *name)
+{
+ int e = errno;
+ /* TRANSLATORS: %s after `Cannot' is a function name, e.g. `Cannot open'.
+ Directly translating this to another language will not work, first because
+ %s itself is not translated.
+ Translate it as `%s: Function %s failed'. */
+ FATAL_ERROR ((0, e, _("%s: Cannot %s"), quotearg_colon (name), call));
+}
+
+/* Report a warning associated with the system call CALL and
+ the optional file name NAME. */
+void
+call_arg_warn (char const *call, char const *name)
+{
+ int e = errno;
+ /* TRANSLATORS: %s after `Cannot' is a function name, e.g. `Cannot open'.
+ Directly translating this to another language will not work, first because
+ %s itself is not translated.
+ Translate it as `%s: Function %s failed'. */
+ WARN ((0, e, _("%s: Warning: Cannot %s"), quotearg_colon (name), call));
+}
+
+void
+chmod_error_details (char const *name, mode_t mode)
+{
+ int e = errno;
+ char buf[10];
+ pax_decode_mode (mode, buf);
+ ERROR ((0, e, _("%s: Cannot change mode to %s"),
+ quotearg_colon (name), buf));
+}
+
+void
+chown_error_details (char const *name, uid_t uid, gid_t gid)
+{
+ int e = errno;
+ ERROR ((0, e, _("%s: Cannot change ownership to uid %lu, gid %lu"),
+ quotearg_colon (name), (unsigned long) uid, (unsigned long) gid));
+}
+
+void
+close_error (char const *name)
+{
+ call_arg_error ("close", name);
+}
+
+void
+close_warn (char const *name)
+{
+ call_arg_warn ("close", name);
+}
+
+void
+exec_fatal (char const *name)
+{
+ call_arg_fatal ("exec", name);
+}
+
+void
+link_error (char const *target, char const *source)
+{
+ int e = errno;
+ ERROR ((0, e, _("%s: Cannot hard link to %s"),
+ quotearg_colon (source), quote_n (1, target)));
+}
+
+void
+mkdir_error (char const *name)
+{
+ call_arg_error ("mkdir", name);
+}
+
+void
+mkfifo_error (char const *name)
+{
+ call_arg_error ("mkfifo", name);
+}
+
+void
+mknod_error (char const *name)
+{
+ call_arg_error ("mknod", name);
+}
+
+void
+open_error (char const *name)
+{
+ call_arg_error ("open", name);
+}
+
+void
+open_fatal (char const *name)
+{
+ call_arg_fatal ("open", name);
+}
+
+void
+open_warn (char const *name)
+{
+ call_arg_warn ("open", name);
+}
+
+void
+read_error (char const *name)
+{
+ call_arg_error ("read", name);
+}
+
+void
+read_error_details (char const *name, off_t offset, size_t size)
+{
+ char buf[UINTMAX_STRSIZE_BOUND];
+ int e = errno;
+ ERROR ((0, e,
+ ngettext ("%s: Read error at byte %s, while reading %lu byte",
+ "%s: Read error at byte %s, while reading %lu bytes",
+ size),
+ quotearg_colon (name), STRINGIFY_BIGINT (offset, buf),
+ (unsigned long) size));
+}
+
+void
+read_warn_details (char const *name, off_t offset, size_t size)
+{
+ char buf[UINTMAX_STRSIZE_BOUND];
+ int e = errno;
+ WARN ((0, e,
+ ngettext ("%s: Warning: Read error at byte %s, while reading %lu byte",
+ "%s: Warning: Read error at byte %s, while reading %lu bytes",
+ size),
+ quotearg_colon (name), STRINGIFY_BIGINT (offset, buf),
+ (unsigned long) size));
+}
+
+void
+read_fatal (char const *name)
+{
+ call_arg_fatal ("read", name);
+}
+
+void
+read_fatal_details (char const *name, off_t offset, size_t size)
+{
+ char buf[UINTMAX_STRSIZE_BOUND];
+ int e = errno;
+ FATAL_ERROR ((0, e,
+ ngettext ("%s: Read error at byte %s, while reading %lu byte",
+ "%s: Read error at byte %s, while reading %lu bytes",
+ size),
+ quotearg_colon (name), STRINGIFY_BIGINT (offset, buf),
+ (unsigned long) size));
+}
+
+void
+readlink_error (char const *name)
+{
+ call_arg_error ("readlink", name);
+}
+
+void
+readlink_warn (char const *name)
+{
+ call_arg_warn ("readlink", name);
+}
+
+void
+rmdir_error (char const *name)
+{
+ call_arg_error ("rmdir", name);
+}
+
+void
+savedir_error (char const *name)
+{
+ call_arg_error ("savedir", name);
+}
+
+void
+savedir_warn (char const *name)
+{
+ call_arg_warn ("savedir", name);
+}
+
+void
+seek_error (char const *name)
+{
+ call_arg_error ("seek", name);
+}
+
+void
+seek_error_details (char const *name, off_t offset)
+{
+ char buf[UINTMAX_STRSIZE_BOUND];
+ int e = errno;
+ ERROR ((0, e, _("%s: Cannot seek to %s"),
+ quotearg_colon (name),
+ STRINGIFY_BIGINT (offset, buf)));
+}
+
+void
+seek_warn (char const *name)
+{
+ call_arg_warn ("seek", name);
+}
+
+void
+seek_warn_details (char const *name, off_t offset)
+{
+ char buf[UINTMAX_STRSIZE_BOUND];
+ int e = errno;
+ WARN ((0, e, _("%s: Warning: Cannot seek to %s"),
+ quotearg_colon (name),
+ STRINGIFY_BIGINT (offset, buf)));
+}
+
+void
+symlink_error (char const *contents, char const *name)
+{
+ int e = errno;
+ ERROR ((0, e, _("%s: Cannot create symlink to %s"),
+ quotearg_colon (name), quote_n (1, contents)));
+}
+
+void
+stat_fatal (char const *name)
+{
+ call_arg_fatal ("stat", name);
+}
+
+void
+stat_error (char const *name)
+{
+ call_arg_error ("stat", name);
+}
+
+void
+stat_warn (char const *name)
+{
+ call_arg_warn ("stat", name);
+}
+
+void
+truncate_error (char const *name)
+{
+ call_arg_error ("truncate", name);
+}
+
+void
+truncate_warn (char const *name)
+{
+ call_arg_warn ("truncate", name);
+}
+
+void
+unlink_error (char const *name)
+{
+ call_arg_error ("unlink", name);
+}
+
+void
+utime_error (char const *name)
+{
+ call_arg_error ("utime", name);
+}
+
+void
+waitpid_error (char const *name)
+{
+ call_arg_error ("waitpid", name);
+}
+
+void
+write_error (char const *name)
+{
+ call_arg_error ("write", name);
+}
+
+void
+write_error_details (char const *name, size_t status, size_t size)
+{
+ if (status == 0)
+ write_error (name);
+ else
+ ERROR ((0, 0,
+ ngettext ("%s: Wrote only %lu of %lu byte",
+ "%s: Wrote only %lu of %lu bytes",
+ size),
+ name, (unsigned long int) status, (unsigned long int) size));
+}
+
+void
+write_fatal (char const *name)
+{
+ call_arg_fatal ("write", name);
+}
+
+void
+chdir_fatal (char const *name)
+{
+ call_arg_fatal ("chdir", name);
+}
diff --git a/lib/exit.c b/lib/paxexit.c
index 1a2e5b5..a511f79 100644
--- a/lib/exit.c
+++ b/lib/paxexit.c
@@ -1,10 +1,10 @@
/* Miscellaneous error functions
- Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+ 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 3, or (at your option) any later
+ 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
diff --git a/lib/paxlib.h b/lib/paxlib.h
index 2fa396a..381c4c7 100644
--- a/lib/paxlib.h
+++ b/lib/paxlib.h
@@ -1,11 +1,11 @@
/* This file is part of GNU paxutils
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
- 2005, 2007 Free Software Foundation, Inc.
+ 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 3, or (at your option)
+ 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,
diff --git a/lib/names.c b/lib/paxnames.c
index 80fa83e..3ca8bfa 100644
--- a/lib/names.c
+++ b/lib/paxnames.c
@@ -1,9 +1,9 @@
/* This file is part of GNU paxutils
- Copyright (C) 2005, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2005 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 3, or (at your option) any later
+ 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
@@ -36,27 +36,15 @@ hash_string_compare (void const *name1, void const *name2)
return strcmp (name1, name2) == 0;
}
-/* Return zero if TABLE contains a LEN-character long prefix of STRING,
- otherwise, insert a newly allocated copy of this prefix to TABLE and
- return 1. If RETURN_PREFIX is not NULL, point it to the allocated
- copy. */
-static bool
-hash_string_insert_prefix (Hash_table **table, char const *string, size_t len,
- const char **return_prefix)
+/* Return zero if TABLE contains a copy of STRING; otherwise, insert a
+ copy of STRING to TABLE and return 1. */
+bool
+hash_string_insert (Hash_table **table, char const *string)
{
Hash_table *t = *table;
- char *s;
+ char *s = xstrdup (string);
char *e;
- if (len)
- {
- s = xmalloc (len + 1);
- memcpy (s, string, len);
- s[len] = 0;
- }
- else
- s = xstrdup (string);
-
if (! ((t
|| (*table = t = hash_initialize (0, 0, hash_string_hasher,
hash_string_compare, 0)))
@@ -64,11 +52,7 @@ hash_string_insert_prefix (Hash_table **table, char const *string, size_t len,
xalloc_die ();
if (e == s)
- {
- if (return_prefix)
- *return_prefix = s;
- return 1;
- }
+ return 1;
else
{
free (s);
@@ -76,14 +60,6 @@ hash_string_insert_prefix (Hash_table **table, char const *string, size_t len,
}
}
-/* Return zero if TABLE contains a copy of STRING; otherwise, insert a
- copy of STRING to TABLE and return 1. */
-bool
-hash_string_insert (Hash_table **table, char const *string)
-{
- return hash_string_insert_prefix (table, string, 0, NULL);
-}
-
/* Return 1 if TABLE contains STRING. */
bool
hash_string_lookup (Hash_table const *table, char const *string)
@@ -112,8 +88,7 @@ removed_prefixes_p (void)
If ABSOLUTE_NAMES is 0, strip filesystem prefix from the file name. */
char *
-safer_name_suffix (char const *file_name, bool link_target,
- bool absolute_names)
+safer_name_suffix (char const *file_name, bool link_target, bool absolute_names)
{
char const *p;
@@ -146,9 +121,11 @@ safer_name_suffix (char const *file_name, bool link_target,
if (prefix_len)
{
- const char *prefix;
- if (hash_string_insert_prefix (&prefix_table[link_target], file_name,
- prefix_len, &prefix))
+ char *prefix = alloca (prefix_len + 1);
+ memcpy (prefix, file_name, prefix_len);
+ prefix[prefix_len] = '\0';
+
+ if (hash_string_insert (&prefix_table[link_target], prefix))
{
static char const *const diagnostic[] =
{
diff --git a/lib/pipe-safer.c b/lib/pipe-safer.c
new file mode 100644
index 0000000..e4431b3
--- /dev/null
+++ b/lib/pipe-safer.c
@@ -0,0 +1,57 @@
+/* Invoke pipe, but avoid some glitches.
+ 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 Jim Meyering. */
+
+#include <config.h>
+
+#include "unistd-safer.h"
+
+#include <unistd.h>
+#include <errno.h>
+
+/* Like pipe, but ensure that neither of the file descriptors is
+ STDIN_FILENO, STDOUT_FILENO, or STDERR_FILENO. Fail with ENOSYS on
+ platforms that lack pipe. */
+
+int
+pipe_safer (int fd[2])
+{
+#if HAVE_PIPE
+ if (pipe (fd) == 0)
+ {
+ int i;
+ for (i = 0; i < 2; i++)
+ {
+ fd[i] = fd_safer (fd[i]);
+ if (fd[i] < 0)
+ {
+ int e = errno;
+ close (fd[1 - i]);
+ errno = e;
+ return -1;
+ }
+ }
+
+ return 0;
+ }
+#else
+ errno = ENOSYS;
+#endif
+
+ return -1;
+}
diff --git a/lib/printf-args.c b/lib/printf-args.c
new file mode 100644
index 0000000..f039b2d
--- /dev/null
+++ b/lib/printf-args.c
@@ -0,0 +1,139 @@
+/* Decomposed printf argument list.
+ Copyright (C) 1999, 2002-2003, 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. */
+
+#include <config.h>
+
+/* Specification. */
+#include "printf-args.h"
+
+#ifdef STATIC
+STATIC
+#endif
+int
+printf_fetchargs (va_list args, arguments *a)
+{
+ size_t i;
+ argument *ap;
+
+ for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++)
+ switch (ap->type)
+ {
+ case TYPE_SCHAR:
+ ap->a.a_schar = va_arg (args, /*signed char*/ int);
+ break;
+ case TYPE_UCHAR:
+ ap->a.a_uchar = va_arg (args, /*unsigned char*/ int);
+ break;
+ case TYPE_SHORT:
+ ap->a.a_short = va_arg (args, /*short*/ int);
+ break;
+ case TYPE_USHORT:
+ ap->a.a_ushort = va_arg (args, /*unsigned short*/ int);
+ break;
+ case TYPE_INT:
+ ap->a.a_int = va_arg (args, int);
+ break;
+ case TYPE_UINT:
+ ap->a.a_uint = va_arg (args, unsigned int);
+ break;
+ case TYPE_LONGINT:
+ ap->a.a_longint = va_arg (args, long int);
+ break;
+ case TYPE_ULONGINT:
+ ap->a.a_ulongint = va_arg (args, unsigned long int);
+ break;
+#if HAVE_LONG_LONG_INT
+ case TYPE_LONGLONGINT:
+ ap->a.a_longlongint = va_arg (args, long long int);
+ break;
+ case TYPE_ULONGLONGINT:
+ ap->a.a_ulonglongint = va_arg (args, unsigned long long int);
+ break;
+#endif
+ case TYPE_DOUBLE:
+ ap->a.a_double = va_arg (args, double);
+ break;
+ case TYPE_LONGDOUBLE:
+ ap->a.a_longdouble = va_arg (args, long double);
+ break;
+ case TYPE_CHAR:
+ ap->a.a_char = va_arg (args, int);
+ break;
+#if HAVE_WINT_T
+ case TYPE_WIDE_CHAR:
+ /* Although ISO C 99 7.24.1.(2) says that wint_t is "unchanged by
+ default argument promotions", this is not the case in mingw32,
+ where wint_t is 'unsigned short'. */
+ ap->a.a_wide_char =
+ (sizeof (wint_t) < sizeof (int)
+ ? va_arg (args, int)
+ : va_arg (args, wint_t));
+ break;
+#endif
+ case TYPE_STRING:
+ ap->a.a_string = va_arg (args, const char *);
+ /* A null pointer is an invalid argument for "%s", but in practice
+ it occurs quite frequently in printf statements that produce
+ debug output. Use a fallback in this case. */
+ if (ap->a.a_string == NULL)
+ ap->a.a_string = "(NULL)";
+ break;
+#if HAVE_WCHAR_T
+ case TYPE_WIDE_STRING:
+ ap->a.a_wide_string = va_arg (args, const wchar_t *);
+ /* A null pointer is an invalid argument for "%ls", but in practice
+ it occurs quite frequently in printf statements that produce
+ debug output. Use a fallback in this case. */
+ if (ap->a.a_wide_string == NULL)
+ {
+ static const wchar_t wide_null_string[] =
+ {
+ (wchar_t)'(',
+ (wchar_t)'N', (wchar_t)'U', (wchar_t)'L', (wchar_t)'L',
+ (wchar_t)')',
+ (wchar_t)0
+ };
+ ap->a.a_wide_string = wide_null_string;
+ }
+ break;
+#endif
+ case TYPE_POINTER:
+ ap->a.a_pointer = va_arg (args, void *);
+ break;
+ case TYPE_COUNT_SCHAR_POINTER:
+ ap->a.a_count_schar_pointer = va_arg (args, signed char *);
+ break;
+ case TYPE_COUNT_SHORT_POINTER:
+ ap->a.a_count_short_pointer = va_arg (args, short *);
+ break;
+ case TYPE_COUNT_INT_POINTER:
+ ap->a.a_count_int_pointer = va_arg (args, int *);
+ break;
+ case TYPE_COUNT_LONGINT_POINTER:
+ ap->a.a_count_longint_pointer = va_arg (args, long int *);
+ break;
+#if HAVE_LONG_LONG_INT
+ case TYPE_COUNT_LONGLONGINT_POINTER:
+ ap->a.a_count_longlongint_pointer = va_arg (args, long long int *);
+ break;
+#endif
+ default:
+ /* Unknown type. */
+ return -1;
+ }
+ return 0;
+}
diff --git a/lib/printf-args.h b/lib/printf-args.h
new file mode 100644
index 0000000..bcf4470
--- /dev/null
+++ b/lib/printf-args.h
@@ -0,0 +1,132 @@
+/* Decomposed printf argument list.
+ Copyright (C) 1999, 2002-2003, 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. */
+
+#ifndef _PRINTF_ARGS_H
+#define _PRINTF_ARGS_H
+
+/* Get size_t. */
+#include <stddef.h>
+
+/* Get wchar_t. */
+#if HAVE_WCHAR_T
+# include <stddef.h>
+#endif
+
+/* Get wint_t. */
+#if HAVE_WINT_T
+# include <wchar.h>
+#endif
+
+/* Get va_list. */
+#include <stdarg.h>
+
+
+/* Argument types */
+typedef enum
+{
+ TYPE_NONE,
+ TYPE_SCHAR,
+ TYPE_UCHAR,
+ TYPE_SHORT,
+ TYPE_USHORT,
+ TYPE_INT,
+ TYPE_UINT,
+ TYPE_LONGINT,
+ TYPE_ULONGINT,
+#if HAVE_LONG_LONG_INT
+ TYPE_LONGLONGINT,
+ TYPE_ULONGLONGINT,
+#endif
+ TYPE_DOUBLE,
+ TYPE_LONGDOUBLE,
+ TYPE_CHAR,
+#if HAVE_WINT_T
+ TYPE_WIDE_CHAR,
+#endif
+ TYPE_STRING,
+#if HAVE_WCHAR_T
+ TYPE_WIDE_STRING,
+#endif
+ TYPE_POINTER,
+ TYPE_COUNT_SCHAR_POINTER,
+ TYPE_COUNT_SHORT_POINTER,
+ TYPE_COUNT_INT_POINTER,
+ TYPE_COUNT_LONGINT_POINTER
+#if HAVE_LONG_LONG_INT
+, TYPE_COUNT_LONGLONGINT_POINTER
+#endif
+} arg_type;
+
+/* Polymorphic argument */
+typedef struct
+{
+ arg_type type;
+ union
+ {
+ signed char a_schar;
+ unsigned char a_uchar;
+ short a_short;
+ unsigned short a_ushort;
+ int a_int;
+ unsigned int a_uint;
+ long int a_longint;
+ unsigned long int a_ulongint;
+#if HAVE_LONG_LONG_INT
+ long long int a_longlongint;
+ unsigned long long int a_ulonglongint;
+#endif
+ float a_float;
+ double a_double;
+ long double a_longdouble;
+ int a_char;
+#if HAVE_WINT_T
+ wint_t a_wide_char;
+#endif
+ const char* a_string;
+#if HAVE_WCHAR_T
+ const wchar_t* a_wide_string;
+#endif
+ void* a_pointer;
+ signed char * a_count_schar_pointer;
+ short * a_count_short_pointer;
+ int * a_count_int_pointer;
+ long int * a_count_longint_pointer;
+#if HAVE_LONG_LONG_INT
+ long long int * a_count_longlongint_pointer;
+#endif
+ }
+ a;
+}
+argument;
+
+typedef struct
+{
+ size_t count;
+ argument *arg;
+}
+arguments;
+
+
+/* Fetch the arguments, putting them into a. */
+#ifdef STATIC
+STATIC
+#else
+extern
+#endif
+int printf_fetchargs (va_list args, arguments *a);
+
+#endif /* _PRINTF_ARGS_H */
diff --git a/lib/printf-parse.c b/lib/printf-parse.c
new file mode 100644
index 0000000..7de0b9f
--- /dev/null
+++ b/lib/printf-parse.c
@@ -0,0 +1,543 @@
+/* Formatted output to strings.
+ Copyright (C) 1999-2000, 2002-2003, 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>
+
+/* Specification. */
+#if WIDE_CHAR_VERSION
+# include "wprintf-parse.h"
+#else
+# include "printf-parse.h"
+#endif
+
+/* Get size_t, NULL. */
+#include <stddef.h>
+
+/* Get intmax_t. */
+#ifdef IN_LIBINTL
+# if HAVE_STDINT_H_WITH_UINTMAX
+# include <stdint.h>
+# endif
+# if HAVE_INTTYPES_H_WITH_UINTMAX
+# include <inttypes.h>
+# endif
+#else
+# include <stdint.h>
+#endif
+
+/* malloc(), realloc(), free(). */
+#include <stdlib.h>
+
+/* Checked size_t computations. */
+#include "xsize.h"
+
+#if WIDE_CHAR_VERSION
+# define PRINTF_PARSE wprintf_parse
+# define CHAR_T wchar_t
+# define DIRECTIVE wchar_t_directive
+# define DIRECTIVES wchar_t_directives
+#else
+# define PRINTF_PARSE printf_parse
+# define CHAR_T char
+# define DIRECTIVE char_directive
+# define DIRECTIVES char_directives
+#endif
+
+#ifdef STATIC
+STATIC
+#endif
+int
+PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
+{
+ const CHAR_T *cp = format; /* pointer into format */
+ size_t arg_posn = 0; /* number of regular arguments consumed */
+ size_t d_allocated; /* allocated elements of d->dir */
+ size_t a_allocated; /* allocated elements of a->arg */
+ size_t max_width_length = 0;
+ size_t max_precision_length = 0;
+
+ d->count = 0;
+ d_allocated = 1;
+ d->dir = (DIRECTIVE *) malloc (d_allocated * sizeof (DIRECTIVE));
+ if (d->dir == NULL)
+ /* Out of memory. */
+ return -1;
+
+ a->count = 0;
+ a_allocated = 0;
+ a->arg = NULL;
+
+#define REGISTER_ARG(_index_,_type_) \
+ { \
+ size_t n = (_index_); \
+ if (n >= a_allocated) \
+ { \
+ size_t memory_size; \
+ argument *memory; \
+ \
+ a_allocated = xtimes (a_allocated, 2); \
+ if (a_allocated <= n) \
+ a_allocated = xsum (n, 1); \
+ memory_size = xtimes (a_allocated, sizeof (argument)); \
+ if (size_overflow_p (memory_size)) \
+ /* Overflow, would lead to out of memory. */ \
+ goto error; \
+ memory = (argument *) (a->arg \
+ ? realloc (a->arg, memory_size) \
+ : malloc (memory_size)); \
+ if (memory == NULL) \
+ /* Out of memory. */ \
+ goto error; \
+ a->arg = memory; \
+ } \
+ while (a->count <= n) \
+ a->arg[a->count++].type = TYPE_NONE; \
+ if (a->arg[n].type == TYPE_NONE) \
+ a->arg[n].type = (_type_); \
+ else if (a->arg[n].type != (_type_)) \
+ /* Ambiguous type for positional argument. */ \
+ goto error; \
+ }
+
+ while (*cp != '\0')
+ {
+ CHAR_T c = *cp++;
+ if (c == '%')
+ {
+ size_t arg_index = ARG_NONE;
+ DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */
+
+ /* Initialize the next directive. */
+ dp->dir_start = cp - 1;
+ dp->flags = 0;
+ dp->width_start = NULL;
+ dp->width_end = NULL;
+ dp->width_arg_index = ARG_NONE;
+ dp->precision_start = NULL;
+ dp->precision_end = NULL;
+ dp->precision_arg_index = ARG_NONE;
+ dp->arg_index = ARG_NONE;
+
+ /* Test for positional argument. */
+ if (*cp >= '0' && *cp <= '9')
+ {
+ const CHAR_T *np;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ ;
+ if (*np == '$')
+ {
+ size_t n = 0;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ n = xsum (xtimes (n, 10), *np - '0');
+ if (n == 0)
+ /* Positional argument 0. */
+ goto error;
+ if (size_overflow_p (n))
+ /* n too large, would lead to out of memory later. */
+ goto error;
+ arg_index = n - 1;
+ cp = np + 1;
+ }
+ }
+
+ /* Read the flags. */
+ for (;;)
+ {
+ if (*cp == '\'')
+ {
+ dp->flags |= FLAG_GROUP;
+ cp++;
+ }
+ else if (*cp == '-')
+ {
+ dp->flags |= FLAG_LEFT;
+ cp++;
+ }
+ else if (*cp == '+')
+ {
+ dp->flags |= FLAG_SHOWSIGN;
+ cp++;
+ }
+ else if (*cp == ' ')
+ {
+ dp->flags |= FLAG_SPACE;
+ cp++;
+ }
+ else if (*cp == '#')
+ {
+ dp->flags |= FLAG_ALT;
+ cp++;
+ }
+ else if (*cp == '0')
+ {
+ dp->flags |= FLAG_ZERO;
+ cp++;
+ }
+ else
+ break;
+ }
+
+ /* Parse the field width. */
+ if (*cp == '*')
+ {
+ dp->width_start = cp;
+ cp++;
+ dp->width_end = cp;
+ if (max_width_length < 1)
+ max_width_length = 1;
+
+ /* Test for positional argument. */
+ if (*cp >= '0' && *cp <= '9')
+ {
+ const CHAR_T *np;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ ;
+ if (*np == '$')
+ {
+ size_t n = 0;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ n = xsum (xtimes (n, 10), *np - '0');
+ if (n == 0)
+ /* Positional argument 0. */
+ goto error;
+ if (size_overflow_p (n))
+ /* n too large, would lead to out of memory later. */
+ goto error;
+ dp->width_arg_index = n - 1;
+ cp = np + 1;
+ }
+ }
+ if (dp->width_arg_index == ARG_NONE)
+ {
+ dp->width_arg_index = arg_posn++;
+ if (dp->width_arg_index == ARG_NONE)
+ /* arg_posn wrapped around. */
+ goto error;
+ }
+ REGISTER_ARG (dp->width_arg_index, TYPE_INT);
+ }
+ else if (*cp >= '0' && *cp <= '9')
+ {
+ size_t width_length;
+
+ dp->width_start = cp;
+ for (; *cp >= '0' && *cp <= '9'; cp++)
+ ;
+ dp->width_end = cp;
+ width_length = dp->width_end - dp->width_start;
+ if (max_width_length < width_length)
+ max_width_length = width_length;
+ }
+
+ /* Parse the precision. */
+ if (*cp == '.')
+ {
+ cp++;
+ if (*cp == '*')
+ {
+ dp->precision_start = cp - 1;
+ cp++;
+ dp->precision_end = cp;
+ if (max_precision_length < 2)
+ max_precision_length = 2;
+
+ /* Test for positional argument. */
+ if (*cp >= '0' && *cp <= '9')
+ {
+ const CHAR_T *np;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ ;
+ if (*np == '$')
+ {
+ size_t n = 0;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ n = xsum (xtimes (n, 10), *np - '0');
+ if (n == 0)
+ /* Positional argument 0. */
+ goto error;
+ if (size_overflow_p (n))
+ /* n too large, would lead to out of memory
+ later. */
+ goto error;
+ dp->precision_arg_index = n - 1;
+ cp = np + 1;
+ }
+ }
+ if (dp->precision_arg_index == ARG_NONE)
+ {
+ dp->precision_arg_index = arg_posn++;
+ if (dp->precision_arg_index == ARG_NONE)
+ /* arg_posn wrapped around. */
+ goto error;
+ }
+ REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
+ }
+ else
+ {
+ size_t precision_length;
+
+ dp->precision_start = cp - 1;
+ for (; *cp >= '0' && *cp <= '9'; cp++)
+ ;
+ dp->precision_end = cp;
+ precision_length = dp->precision_end - dp->precision_start;
+ if (max_precision_length < precision_length)
+ max_precision_length = precision_length;
+ }
+ }
+
+ {
+ arg_type type;
+
+ /* Parse argument type/size specifiers. */
+ {
+ int flags = 0;
+
+ for (;;)
+ {
+ if (*cp == 'h')
+ {
+ flags |= (1 << (flags & 1));
+ cp++;
+ }
+ else if (*cp == 'L')
+ {
+ flags |= 4;
+ cp++;
+ }
+ else if (*cp == 'l')
+ {
+ flags += 8;
+ cp++;
+ }
+ else if (*cp == 'j')
+ {
+ if (sizeof (intmax_t) > sizeof (long))
+ {
+ /* intmax_t = long long */
+ flags += 16;
+ }
+ else if (sizeof (intmax_t) > sizeof (int))
+ {
+ /* intmax_t = long */
+ flags += 8;
+ }
+ cp++;
+ }
+ else if (*cp == 'z' || *cp == 'Z')
+ {
+ /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
+ because the warning facility in gcc-2.95.2 understands
+ only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
+ if (sizeof (size_t) > sizeof (long))
+ {
+ /* size_t = long long */
+ flags += 16;
+ }
+ else if (sizeof (size_t) > sizeof (int))
+ {
+ /* size_t = long */
+ flags += 8;
+ }
+ cp++;
+ }
+ else if (*cp == 't')
+ {
+ if (sizeof (ptrdiff_t) > sizeof (long))
+ {
+ /* ptrdiff_t = long long */
+ flags += 16;
+ }
+ else if (sizeof (ptrdiff_t) > sizeof (int))
+ {
+ /* ptrdiff_t = long */
+ flags += 8;
+ }
+ cp++;
+ }
+ else
+ break;
+ }
+
+ /* Read the conversion character. */
+ c = *cp++;
+ switch (c)
+ {
+ case 'd': case 'i':
+#if HAVE_LONG_LONG_INT
+ /* If 'long long' exists and is larger than 'long': */
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_LONGLONGINT;
+ else
+#endif
+ /* If 'long long' exists and is the same as 'long', we parse
+ "lld" into TYPE_LONGINT. */
+ if (flags >= 8)
+ type = TYPE_LONGINT;
+ else if (flags & 2)
+ type = TYPE_SCHAR;
+ else if (flags & 1)
+ type = TYPE_SHORT;
+ else
+ type = TYPE_INT;
+ break;
+ case 'o': case 'u': case 'x': case 'X':
+#if HAVE_LONG_LONG_INT
+ /* If 'long long' exists and is larger than 'long': */
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_ULONGLONGINT;
+ else
+#endif
+ /* If 'unsigned long long' exists and is the same as
+ 'unsigned long', we parse "llu" into TYPE_ULONGINT. */
+ if (flags >= 8)
+ type = TYPE_ULONGINT;
+ else if (flags & 2)
+ type = TYPE_UCHAR;
+ else if (flags & 1)
+ type = TYPE_USHORT;
+ else
+ type = TYPE_UINT;
+ break;
+ case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
+ case 'a': case 'A':
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_LONGDOUBLE;
+ else
+ type = TYPE_DOUBLE;
+ break;
+ case 'c':
+ if (flags >= 8)
+#if HAVE_WINT_T
+ type = TYPE_WIDE_CHAR;
+#else
+ goto error;
+#endif
+ else
+ type = TYPE_CHAR;
+ break;
+#if HAVE_WINT_T
+ case 'C':
+ type = TYPE_WIDE_CHAR;
+ c = 'c';
+ break;
+#endif
+ case 's':
+ if (flags >= 8)
+#if HAVE_WCHAR_T
+ type = TYPE_WIDE_STRING;
+#else
+ goto error;
+#endif
+ else
+ type = TYPE_STRING;
+ break;
+#if HAVE_WCHAR_T
+ case 'S':
+ type = TYPE_WIDE_STRING;
+ c = 's';
+ break;
+#endif
+ case 'p':
+ type = TYPE_POINTER;
+ break;
+ case 'n':
+#if HAVE_LONG_LONG_INT
+ /* If 'long long' exists and is larger than 'long': */
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_COUNT_LONGLONGINT_POINTER;
+ else
+#endif
+ /* If 'long long' exists and is the same as 'long', we parse
+ "lln" into TYPE_COUNT_LONGINT_POINTER. */
+ if (flags >= 8)
+ type = TYPE_COUNT_LONGINT_POINTER;
+ else if (flags & 2)
+ type = TYPE_COUNT_SCHAR_POINTER;
+ else if (flags & 1)
+ type = TYPE_COUNT_SHORT_POINTER;
+ else
+ type = TYPE_COUNT_INT_POINTER;
+ break;
+ case '%':
+ type = TYPE_NONE;
+ break;
+ default:
+ /* Unknown conversion character. */
+ goto error;
+ }
+ }
+
+ if (type != TYPE_NONE)
+ {
+ dp->arg_index = arg_index;
+ if (dp->arg_index == ARG_NONE)
+ {
+ dp->arg_index = arg_posn++;
+ if (dp->arg_index == ARG_NONE)
+ /* arg_posn wrapped around. */
+ goto error;
+ }
+ REGISTER_ARG (dp->arg_index, type);
+ }
+ dp->conversion = c;
+ dp->dir_end = cp;
+ }
+
+ d->count++;
+ if (d->count >= d_allocated)
+ {
+ size_t memory_size;
+ DIRECTIVE *memory;
+
+ d_allocated = xtimes (d_allocated, 2);
+ memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
+ if (size_overflow_p (memory_size))
+ /* Overflow, would lead to out of memory. */
+ goto error;
+ memory = (DIRECTIVE *) realloc (d->dir, memory_size);
+ if (memory == NULL)
+ /* Out of memory. */
+ goto error;
+ d->dir = memory;
+ }
+ }
+ }
+ d->dir[d->count].dir_start = cp;
+
+ d->max_width_length = max_width_length;
+ d->max_precision_length = max_precision_length;
+ return 0;
+
+error:
+ if (a->arg)
+ free (a->arg);
+ if (d->dir)
+ free (d->dir);
+ return -1;
+}
+
+#undef DIRECTIVES
+#undef DIRECTIVE
+#undef CHAR_T
+#undef PRINTF_PARSE
diff --git a/lib/printf-parse.h b/lib/printf-parse.h
new file mode 100644
index 0000000..82a0d37
--- /dev/null
+++ b/lib/printf-parse.h
@@ -0,0 +1,74 @@
+/* Parse printf format string.
+ Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _PRINTF_PARSE_H
+#define _PRINTF_PARSE_H
+
+#include "printf-args.h"
+
+
+/* Flags */
+#define FLAG_GROUP 1 /* ' flag */
+#define FLAG_LEFT 2 /* - flag */
+#define FLAG_SHOWSIGN 4 /* + flag */
+#define FLAG_SPACE 8 /* space flag */
+#define FLAG_ALT 16 /* # flag */
+#define FLAG_ZERO 32
+
+/* arg_index value indicating that no argument is consumed. */
+#define ARG_NONE (~(size_t)0)
+
+/* A parsed directive. */
+typedef struct
+{
+ const char* dir_start;
+ const char* dir_end;
+ int flags;
+ const char* width_start;
+ const char* width_end;
+ size_t width_arg_index;
+ const char* precision_start;
+ const char* precision_end;
+ size_t precision_arg_index;
+ char conversion; /* d i o u x X f e E g G c s p n U % but not C S */
+ size_t arg_index;
+}
+char_directive;
+
+/* A parsed format string. */
+typedef struct
+{
+ size_t count;
+ char_directive *dir;
+ size_t max_width_length;
+ size_t max_precision_length;
+}
+char_directives;
+
+
+/* Parses the format string. Fills in the number N of directives, and fills
+ in directives[0], ..., directives[N-1], and sets directives[N].dir_start
+ to the end of the format string. Also fills in the arg_type fields of the
+ arguments and the needed count of arguments. */
+#ifdef STATIC
+STATIC
+#else
+extern
+#endif
+int printf_parse (const char *format, char_directives *d, arguments *a);
+
+#endif /* _PRINTF_PARSE_H */
diff --git a/lib/quote.c b/lib/quote.c
new file mode 100644
index 0000000..119be72
--- /dev/null
+++ b/lib/quote.c
@@ -0,0 +1,41 @@
+/* quote.c - quote arguments for output
+
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005, 2006 Free
+ Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert <eggert@twinsun.com> */
+
+#include <config.h>
+
+#include "quotearg.h"
+#include "quote.h"
+
+/* Return an unambiguous printable representation of NAME,
+ allocated in slot N, suitable for diagnostics. */
+char const *
+quote_n (int n, char const *name)
+{
+ return quotearg_n_style (n, locale_quoting_style, name);
+}
+
+/* Return an unambiguous printable representation of NAME,
+ suitable for diagnostics. */
+char const *
+quote (char const *name)
+{
+ return quote_n (0, name);
+}
diff --git a/lib/quote.h b/lib/quote.h
new file mode 100644
index 0000000..5400ead
--- /dev/null
+++ b/lib/quote.h
@@ -0,0 +1,22 @@
+/* quote.h - prototypes for quote.c
+
+ Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software
+ Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+
+char const *quote_n (int n, char const *name);
+char const *quote (char const *name);
diff --git a/lib/quotearg.c b/lib/quotearg.c
new file mode 100644
index 0000000..f7f326a
--- /dev/null
+++ b/lib/quotearg.c
@@ -0,0 +1,697 @@
+/* quotearg.c - quote arguments for output
+
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 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. */
+
+/* Written by Paul Eggert <eggert@twinsun.com> */
+
+#include <config.h>
+
+#include "quotearg.h"
+
+#include "xalloc.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+#if !HAVE_MBRTOWC
+/* Disable multibyte processing entirely. Since MB_CUR_MAX is 1, the
+ other macros are defined only for documentation and to satisfy C
+ syntax. */
+# undef MB_CUR_MAX
+# define MB_CUR_MAX 1
+# undef mbstate_t
+# define mbstate_t int
+# define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0)
+# define iswprint(wc) isprint ((unsigned char) (wc))
+# undef HAVE_MBSINIT
+#endif
+
+#if !defined mbsinit && !HAVE_MBSINIT
+# define mbsinit(ps) 1
+#endif
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+#define INT_BITS (sizeof (int) * CHAR_BIT)
+
+struct quoting_options
+{
+ /* Basic quoting style. */
+ enum quoting_style style;
+
+ /* Quote the characters indicated by this bit vector even if the
+ quoting style would not normally require them to be quoted. */
+ unsigned int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
+};
+
+/* Names of quoting styles. */
+char const *const quoting_style_args[] =
+{
+ "literal",
+ "shell",
+ "shell-always",
+ "c",
+ "escape",
+ "locale",
+ "clocale",
+ 0
+};
+
+/* Correspondences to quoting style names. */
+enum quoting_style const quoting_style_vals[] =
+{
+ literal_quoting_style,
+ shell_quoting_style,
+ shell_always_quoting_style,
+ c_quoting_style,
+ escape_quoting_style,
+ locale_quoting_style,
+ clocale_quoting_style
+};
+
+/* The default quoting options. */
+static struct quoting_options default_quoting_options;
+
+/* Allocate a new set of quoting options, with contents initially identical
+ to O if O is not null, or to the default if O is null.
+ It is the caller's responsibility to free the result. */
+struct quoting_options *
+clone_quoting_options (struct quoting_options *o)
+{
+ int e = errno;
+ struct quoting_options *p = xmemdup (o ? o : &default_quoting_options,
+ sizeof *o);
+ errno = e;
+ return p;
+}
+
+/* Get the value of O's quoting style. If O is null, use the default. */
+enum quoting_style
+get_quoting_style (struct quoting_options *o)
+{
+ return (o ? o : &default_quoting_options)->style;
+}
+
+/* In O (or in the default if O is null),
+ set the value of the quoting style to S. */
+void
+set_quoting_style (struct quoting_options *o, enum quoting_style s)
+{
+ (o ? o : &default_quoting_options)->style = s;
+}
+
+/* In O (or in the default if O is null),
+ set the value of the quoting options for character C to I.
+ Return the old value. Currently, the only values defined for I are
+ 0 (the default) and 1 (which means to quote the character even if
+ it would not otherwise be quoted). */
+int
+set_char_quoting (struct quoting_options *o, char c, int i)
+{
+ unsigned char uc = c;
+ unsigned int *p =
+ (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
+ int shift = uc % INT_BITS;
+ int r = (*p >> shift) & 1;
+ *p ^= ((i & 1) ^ r) << shift;
+ return r;
+}
+
+/* MSGID approximates a quotation mark. Return its translation if it
+ has one; otherwise, return either it or "\"", depending on S. */
+static char const *
+gettext_quote (char const *msgid, enum quoting_style s)
+{
+ char const *translation = _(msgid);
+ if (translation == msgid && s == clocale_quoting_style)
+ translation = "\"";
+ return translation;
+}
+
+/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
+ argument ARG (of size ARGSIZE), using QUOTING_STYLE and the
+ non-quoting-style part of O to control quoting.
+ Terminate the output with a null character, and return the written
+ size of the output, not counting the terminating null.
+ If BUFFERSIZE is too small to store the output string, return the
+ value that would have been returned had BUFFERSIZE been large enough.
+ If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE.
+
+ This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
+ ARGSIZE, O), except it uses QUOTING_STYLE instead of the quoting
+ style specified by O, and O may not be null. */
+
+static size_t
+quotearg_buffer_restyled (char *buffer, size_t buffersize,
+ char const *arg, size_t argsize,
+ enum quoting_style quoting_style,
+ struct quoting_options const *o)
+{
+ size_t i;
+ size_t len = 0;
+ char const *quote_string = 0;
+ size_t quote_string_len = 0;
+ bool backslash_escapes = false;
+ bool unibyte_locale = MB_CUR_MAX == 1;
+
+#define STORE(c) \
+ do \
+ { \
+ if (len < buffersize) \
+ buffer[len] = (c); \
+ len++; \
+ } \
+ while (0)
+
+ switch (quoting_style)
+ {
+ case c_quoting_style:
+ STORE ('"');
+ backslash_escapes = true;
+ quote_string = "\"";
+ quote_string_len = 1;
+ break;
+
+ case escape_quoting_style:
+ backslash_escapes = true;
+ break;
+
+ case locale_quoting_style:
+ case clocale_quoting_style:
+ {
+ /* TRANSLATORS:
+ Get translations for open and closing quotation marks.
+
+ The message catalog should translate "`" to a left
+ quotation mark suitable for the locale, and similarly for
+ "'". If the catalog has no translation,
+ locale_quoting_style quotes `like this', and
+ clocale_quoting_style quotes "like this".
+
+ For example, an American English Unicode locale should
+ translate "`" to U+201C (LEFT DOUBLE QUOTATION MARK), and
+ should translate "'" to U+201D (RIGHT DOUBLE QUOTATION
+ MARK). A British English Unicode locale should instead
+ translate these to U+2018 (LEFT SINGLE QUOTATION MARK) and
+ U+2019 (RIGHT SINGLE QUOTATION MARK), respectively.
+
+ If you don't know what to put here, please see
+ <http://en.wikipedia.org/wiki/Quotation_mark#Glyphs>
+ and use glyphs suitable for your language. */
+
+ char const *left = gettext_quote (N_("`"), quoting_style);
+ char const *right = gettext_quote (N_("'"), quoting_style);
+ for (quote_string = left; *quote_string; quote_string++)
+ STORE (*quote_string);
+ backslash_escapes = true;
+ quote_string = right;
+ quote_string_len = strlen (quote_string);
+ }
+ break;
+
+ case shell_always_quoting_style:
+ STORE ('\'');
+ quote_string = "'";
+ quote_string_len = 1;
+ break;
+
+ default:
+ break;
+ }
+
+ for (i = 0; ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize); i++)
+ {
+ unsigned char c;
+ unsigned char esc;
+
+ if (backslash_escapes
+ && quote_string_len
+ && i + quote_string_len <= argsize
+ && memcmp (arg + i, quote_string, quote_string_len) == 0)
+ STORE ('\\');
+
+ c = arg[i];
+ switch (c)
+ {
+ case '\0':
+ if (backslash_escapes)
+ {
+ STORE ('\\');
+ STORE ('0');
+ STORE ('0');
+ c = '0';
+ }
+ break;
+
+ case '?':
+ switch (quoting_style)
+ {
+ case shell_quoting_style:
+ goto use_shell_always_quoting_style;
+
+ case c_quoting_style:
+ if (i + 2 < argsize && arg[i + 1] == '?')
+ switch (arg[i + 2])
+ {
+ case '!': case '\'':
+ case '(': case ')': case '-': case '/':
+ case '<': case '=': case '>':
+ /* Escape the second '?' in what would otherwise be
+ a trigraph. */
+ c = arg[i + 2];
+ i += 2;
+ STORE ('?');
+ STORE ('\\');
+ STORE ('?');
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case '\a': esc = 'a'; goto c_escape;
+ case '\b': esc = 'b'; goto c_escape;
+ case '\f': esc = 'f'; goto c_escape;
+ case '\n': esc = 'n'; goto c_and_shell_escape;
+ case '\r': esc = 'r'; goto c_and_shell_escape;
+ case '\t': esc = 't'; goto c_and_shell_escape;
+ case '\v': esc = 'v'; goto c_escape;
+ case '\\': esc = c; goto c_and_shell_escape;
+
+ c_and_shell_escape:
+ if (quoting_style == shell_quoting_style)
+ goto use_shell_always_quoting_style;
+ c_escape:
+ if (backslash_escapes)
+ {
+ c = esc;
+ goto store_escape;
+ }
+ break;
+
+ case '{': case '}': /* sometimes special if isolated */
+ if (! (argsize == SIZE_MAX ? arg[1] == '\0' : argsize == 1))
+ break;
+ /* Fall through. */
+ case '#': case '~':
+ if (i != 0)
+ break;
+ /* Fall through. */
+ case ' ':
+ case '!': /* special in bash */
+ case '"': case '$': case '&':
+ case '(': case ')': case '*': case ';':
+ case '<':
+ case '=': /* sometimes special in 0th or (with "set -k") later args */
+ case '>': case '[':
+ case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
+ case '`': case '|':
+ /* A shell special character. In theory, '$' and '`' could
+ be the first bytes of multibyte characters, which means
+ we should check them with mbrtowc, but in practice this
+ doesn't happen so it's not worth worrying about. */
+ if (quoting_style == shell_quoting_style)
+ goto use_shell_always_quoting_style;
+ break;
+
+ case '\'':
+ switch (quoting_style)
+ {
+ case shell_quoting_style:
+ goto use_shell_always_quoting_style;
+
+ case shell_always_quoting_style:
+ STORE ('\'');
+ STORE ('\\');
+ STORE ('\'');
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case '%': case '+': case ',': case '-': case '.': case '/':
+ case '0': case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9': case ':':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+ case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+ case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+ case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
+ case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
+ case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
+ case 'o': case 'p': case 'q': case 'r': case 's': case 't':
+ case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
+ /* These characters don't cause problems, no matter what the
+ quoting style is. They cannot start multibyte sequences. */
+ break;
+
+ default:
+ /* If we have a multibyte sequence, copy it until we reach
+ its end, find an error, or come back to the initial shift
+ state. For C-like styles, if the sequence has
+ unprintable characters, escape the whole sequence, since
+ we can't easily escape single characters within it. */
+ {
+ /* Length of multibyte sequence found so far. */
+ size_t m;
+
+ bool printable;
+
+ if (unibyte_locale)
+ {
+ m = 1;
+ printable = isprint (c) != 0;
+ }
+ else
+ {
+ mbstate_t mbstate;
+ memset (&mbstate, 0, sizeof mbstate);
+
+ m = 0;
+ printable = true;
+ if (argsize == SIZE_MAX)
+ argsize = strlen (arg);
+
+ do
+ {
+ wchar_t w;
+ size_t bytes = mbrtowc (&w, &arg[i + m],
+ argsize - (i + m), &mbstate);
+ if (bytes == 0)
+ break;
+ else if (bytes == (size_t) -1)
+ {
+ printable = false;
+ break;
+ }
+ else if (bytes == (size_t) -2)
+ {
+ printable = false;
+ while (i + m < argsize && arg[i + m])
+ m++;
+ break;
+ }
+ else
+ {
+ /* Work around a bug with older shells that "see" a '\'
+ that is really the 2nd byte of a multibyte character.
+ In practice the problem is limited to ASCII
+ chars >= '@' that are shell special chars. */
+ if ('[' == 0x5b && quoting_style == shell_quoting_style)
+ {
+ size_t j;
+ for (j = 1; j < bytes; j++)
+ switch (arg[i + m + j])
+ {
+ case '[': case '\\': case '^':
+ case '`': case '|':
+ goto use_shell_always_quoting_style;
+
+ default:
+ break;
+ }
+ }
+
+ if (! iswprint (w))
+ printable = false;
+ m += bytes;
+ }
+ }
+ while (! mbsinit (&mbstate));
+ }
+
+ if (1 < m || (backslash_escapes && ! printable))
+ {
+ /* Output a multibyte sequence, or an escaped
+ unprintable unibyte character. */
+ size_t ilim = i + m;
+
+ for (;;)
+ {
+ if (backslash_escapes && ! printable)
+ {
+ STORE ('\\');
+ STORE ('0' + (c >> 6));
+ STORE ('0' + ((c >> 3) & 7));
+ c = '0' + (c & 7);
+ }
+ if (ilim <= i + 1)
+ break;
+ STORE (c);
+ c = arg[++i];
+ }
+
+ goto store_c;
+ }
+ }
+ }
+
+ if (! (backslash_escapes
+ && o->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
+ goto store_c;
+
+ store_escape:
+ STORE ('\\');
+
+ store_c:
+ STORE (c);
+ }
+
+ if (i == 0 && quoting_style == shell_quoting_style)
+ goto use_shell_always_quoting_style;
+
+ if (quote_string)
+ for (; *quote_string; quote_string++)
+ STORE (*quote_string);
+
+ if (len < buffersize)
+ buffer[len] = '\0';
+ return len;
+
+ use_shell_always_quoting_style:
+ return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
+ shell_always_quoting_style, o);
+}
+
+/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
+ argument ARG (of size ARGSIZE), using O to control quoting.
+ If O is null, use the default.
+ Terminate the output with a null character, and return the written
+ size of the output, not counting the terminating null.
+ If BUFFERSIZE is too small to store the output string, return the
+ value that would have been returned had BUFFERSIZE been large enough.
+ If ARGSIZE is SIZE_MAX, use the string length of the argument for
+ ARGSIZE. */
+size_t
+quotearg_buffer (char *buffer, size_t buffersize,
+ char const *arg, size_t argsize,
+ struct quoting_options const *o)
+{
+ struct quoting_options const *p = o ? o : &default_quoting_options;
+ int e = errno;
+ size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
+ p->style, p);
+ errno = e;
+ return r;
+}
+
+/* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly
+ allocated storage containing the quoted string. */
+char *
+quotearg_alloc (char const *arg, size_t argsize,
+ struct quoting_options const *o)
+{
+ int e = errno;
+ size_t bufsize = quotearg_buffer (0, 0, arg, argsize, o) + 1;
+ char *buf = xcharalloc (bufsize);
+ quotearg_buffer (buf, bufsize, arg, argsize, o);
+ errno = e;
+ return buf;
+}
+
+/* A storage slot with size and pointer to a value. */
+struct slotvec
+{
+ size_t size;
+ char *val;
+};
+
+/* Preallocate a slot 0 buffer, so that the caller can always quote
+ one small component of a "memory exhausted" message in slot 0. */
+static char slot0[256];
+static unsigned int nslots = 1;
+static struct slotvec slotvec0 = {sizeof slot0, slot0};
+static struct slotvec *slotvec = &slotvec0;
+
+void
+quotearg_free (void)
+{
+ struct slotvec *sv = slotvec;
+ unsigned int i;
+ for (i = 1; i < nslots; i++)
+ free (sv[i].val);
+ if (sv[0].val != slot0)
+ {
+ free (sv[0].val);
+ slotvec0.size = sizeof slot0;
+ slotvec0.val = slot0;
+ }
+ if (sv != &slotvec0)
+ {
+ free (sv);
+ slotvec = &slotvec0;
+ }
+ nslots = 1;
+}
+
+/* Use storage slot N to return a quoted version of argument ARG.
+ ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a
+ null-terminated string.
+ OPTIONS specifies the quoting options.
+ The returned value points to static storage that can be
+ reused by the next call to this function with the same value of N.
+ N must be nonnegative. N is deliberately declared with type "int"
+ to allow for future extensions (using negative values). */
+static char *
+quotearg_n_options (int n, char const *arg, size_t argsize,
+ struct quoting_options const *options)
+{
+ int e = errno;
+
+ unsigned int n0 = n;
+ struct slotvec *sv = slotvec;
+
+ if (n < 0)
+ abort ();
+
+ if (nslots <= n0)
+ {
+ /* FIXME: technically, the type of n1 should be `unsigned int',
+ but that evokes an unsuppressible warning from gcc-4.0.1 and
+ older. If gcc ever provides an option to suppress that warning,
+ revert to the original type, so that the test in xalloc_oversized
+ is once again performed only at compile time. */
+ size_t n1 = n0 + 1;
+ bool preallocated = (sv == &slotvec0);
+
+ if (xalloc_oversized (n1, sizeof *sv))
+ xalloc_die ();
+
+ slotvec = sv = xrealloc (preallocated ? NULL : sv, n1 * sizeof *sv);
+ if (preallocated)
+ *sv = slotvec0;
+ memset (sv + nslots, 0, (n1 - nslots) * sizeof *sv);
+ nslots = n1;
+ }
+
+ {
+ size_t size = sv[n].size;
+ char *val = sv[n].val;
+ size_t qsize = quotearg_buffer (val, size, arg, argsize, options);
+
+ if (size <= qsize)
+ {
+ sv[n].size = size = qsize + 1;
+ if (val != slot0)
+ free (val);
+ sv[n].val = val = xcharalloc (size);
+ quotearg_buffer (val, size, arg, argsize, options);
+ }
+
+ errno = e;
+ return val;
+ }
+}
+
+char *
+quotearg_n (int n, char const *arg)
+{
+ return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options);
+}
+
+char *
+quotearg (char const *arg)
+{
+ return quotearg_n (0, arg);
+}
+
+/* Return quoting options for STYLE, with no extra quoting. */
+static struct quoting_options
+quoting_options_from_style (enum quoting_style style)
+{
+ struct quoting_options o;
+ o.style = style;
+ memset (o.quote_these_too, 0, sizeof o.quote_these_too);
+ return o;
+}
+
+char *
+quotearg_n_style (int n, enum quoting_style s, char const *arg)
+{
+ struct quoting_options const o = quoting_options_from_style (s);
+ return quotearg_n_options (n, arg, SIZE_MAX, &o);
+}
+
+char *
+quotearg_n_style_mem (int n, enum quoting_style s,
+ char const *arg, size_t argsize)
+{
+ struct quoting_options const o = quoting_options_from_style (s);
+ return quotearg_n_options (n, arg, argsize, &o);
+}
+
+char *
+quotearg_style (enum quoting_style s, char const *arg)
+{
+ return quotearg_n_style (0, s, arg);
+}
+
+char *
+quotearg_char (char const *arg, char ch)
+{
+ struct quoting_options options;
+ options = default_quoting_options;
+ set_char_quoting (&options, ch, 1);
+ return quotearg_n_options (0, arg, SIZE_MAX, &options);
+}
+
+char *
+quotearg_colon (char const *arg)
+{
+ return quotearg_char (arg, ':');
+}
diff --git a/lib/quotearg.h b/lib/quotearg.h
new file mode 100644
index 0000000..4887df3
--- /dev/null
+++ b/lib/quotearg.h
@@ -0,0 +1,140 @@
+/* quotearg.h - quote arguments for output
+
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006 Free
+ Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert <eggert@twinsun.com> */
+
+#ifndef QUOTEARG_H_
+# define QUOTEARG_H_ 1
+
+# include <stddef.h>
+
+/* Basic quoting styles. */
+enum quoting_style
+ {
+ /* Output names as-is (ls --quoting-style=literal). */
+ literal_quoting_style,
+
+ /* Quote names for the shell if they contain shell metacharacters
+ or would cause ambiguous output (ls --quoting-style=shell). */
+ shell_quoting_style,
+
+ /* Quote names for the shell, even if they would normally not
+ require quoting (ls --quoting-style=shell-always). */
+ shell_always_quoting_style,
+
+ /* Quote names as for a C language string (ls --quoting-style=c). */
+ c_quoting_style,
+
+ /* Like c_quoting_style except omit the surrounding double-quote
+ characters (ls --quoting-style=escape). */
+ escape_quoting_style,
+
+ /* Like clocale_quoting_style, but quote `like this' instead of
+ "like this" in the default C locale (ls --quoting-style=locale). */
+ locale_quoting_style,
+
+ /* Like c_quoting_style except use quotation marks appropriate for
+ the locale (ls --quoting-style=clocale). */
+ clocale_quoting_style
+ };
+
+/* For now, --quoting-style=literal is the default, but this may change. */
+# ifndef DEFAULT_QUOTING_STYLE
+# define DEFAULT_QUOTING_STYLE literal_quoting_style
+# endif
+
+/* Names of quoting styles and their corresponding values. */
+extern char const *const quoting_style_args[];
+extern enum quoting_style const quoting_style_vals[];
+
+struct quoting_options;
+
+/* The functions listed below set and use a hidden variable
+ that contains the default quoting style options. */
+
+/* Allocate a new set of quoting options, with contents initially identical
+ to O if O is not null, or to the default if O is null.
+ It is the caller's responsibility to free the result. */
+struct quoting_options *clone_quoting_options (struct quoting_options *o);
+
+/* Get the value of O's quoting style. If O is null, use the default. */
+enum quoting_style get_quoting_style (struct quoting_options *o);
+
+/* In O (or in the default if O is null),
+ set the value of the quoting style to S. */
+void set_quoting_style (struct quoting_options *o, enum quoting_style s);
+
+/* In O (or in the default if O is null),
+ set the value of the quoting options for character C to I.
+ Return the old value. Currently, the only values defined for I are
+ 0 (the default) and 1 (which means to quote the character even if
+ it would not otherwise be quoted). */
+int set_char_quoting (struct quoting_options *o, char c, int i);
+
+/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
+ argument ARG (of size ARGSIZE), using O to control quoting.
+ If O is null, use the default.
+ Terminate the output with a null character, and return the written
+ size of the output, not counting the terminating null.
+ If BUFFERSIZE is too small to store the output string, return the
+ value that would have been returned had BUFFERSIZE been large enough.
+ If ARGSIZE is -1, use the string length of the argument for ARGSIZE. */
+size_t quotearg_buffer (char *buffer, size_t buffersize,
+ char const *arg, size_t argsize,
+ struct quoting_options const *o);
+
+/* Like quotearg_buffer, except return the result in a newly allocated
+ buffer. It is the caller's responsibility to free the result. */
+char *quotearg_alloc (char const *arg, size_t argsize,
+ struct quoting_options const *o);
+
+/* Use storage slot N to return a quoted version of the string ARG.
+ Use the default quoting options.
+ The returned value points to static storage that can be
+ reused by the next call to this function with the same value of N.
+ N must be nonnegative. */
+char *quotearg_n (int n, char const *arg);
+
+/* Equivalent to quotearg_n (0, ARG). */
+char *quotearg (char const *arg);
+
+/* Use style S and storage slot N to return a quoted version of the string ARG.
+ This is like quotearg_n (N, ARG), except that it uses S with no other
+ options to specify the quoting method. */
+char *quotearg_n_style (int n, enum quoting_style s, char const *arg);
+
+/* Use style S and storage slot N to return a quoted version of the
+ argument ARG of size ARGSIZE. This is like quotearg_n_style
+ (N, S, ARG), except it can quote null bytes. */
+char *quotearg_n_style_mem (int n, enum quoting_style s,
+ char const *arg, size_t argsize);
+
+/* Equivalent to quotearg_n_style (0, S, ARG). */
+char *quotearg_style (enum quoting_style s, char const *arg);
+
+/* Like quotearg (ARG), except also quote any instances of CH. */
+char *quotearg_char (char const *arg, char ch);
+
+/* Equivalent to quotearg_char (ARG, ':'). */
+char *quotearg_colon (char const *arg);
+
+/* Free any dynamically allocated memory. */
+void quotearg_free (void);
+
+#endif /* !QUOTEARG_H_ */
diff --git a/lib/readlink.c b/lib/readlink.c
new file mode 100644
index 0000000..3cbdc1c
--- /dev/null
+++ b/lib/readlink.c
@@ -0,0 +1,50 @@
+/* Stub for readlink().
+ Copyright (C) 2003-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>
+
+/* Specification. */
+#include <unistd.h>
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stddef.h>
+
+#if !HAVE_READLINK
+
+/* readlink() substitute for systems that don't have a readlink() function,
+ such as DJGPP 2.03 and mingw32. */
+
+/* The official POSIX return type of readlink() is ssize_t, but since here
+ we have no declaration in a public header file, we use 'int' as return
+ type. */
+
+int
+readlink (const char *path, char *buf, size_t bufsize)
+{
+ struct stat statbuf;
+
+ /* In general we should use lstat() here, not stat(). But on platforms
+ without symbolic links lstat() - if it exists - would be equivalent to
+ stat(), therefore we can use stat(). This saves us a configure check. */
+ if (stat (path, &statbuf) >= 0)
+ errno = EINVAL;
+ return -1;
+}
+
+#endif
diff --git a/lib/rmt-command.h b/lib/rmt-command.h
new file mode 100644
index 0000000..7460e6f
--- /dev/null
+++ b/lib/rmt-command.h
@@ -0,0 +1,4 @@
+#define LOCALEDIR "/usr/local/share/locale"
+#ifndef DEFAULT_RMT_COMMAND
+# define DEFAULT_RMT_COMMAND "/usr/local/libexec/rmt"
+#endif
diff --git a/lib/rmt.h b/lib/rmt.h
index 2ce9dc5..9f96cdb 100644
--- a/lib/rmt.h
+++ b/lib/rmt.h
@@ -1,11 +1,11 @@
/* Definitions for communicating with a remote tape drive.
- Copyright (C) 1988, 1992, 1996, 1997, 2001, 2003, 2004, 2007 Free
+ Copyright (C) 1988, 1992, 1996, 1997, 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 3, or (at your option)
+ 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,
@@ -61,7 +61,7 @@ extern bool force_local_option;
#define rmtcreat(dev_name, mode, command) \
(_remdev (dev_name) \
- ? rmt_open__ (dev_name, O_CREAT | O_WRONLY, __REM_BIAS, command) \
+ ? rmt_open__ (dev_name, 1 | O_CREAT, __REM_BIAS, command) \
: creat (dev_name, mode))
#define rmtlstat(dev_name, muffer) \
diff --git a/lib/rtapelib.c b/lib/rtapelib.c
index cb645db..af19b04 100644
--- a/lib/rtapelib.c
+++ b/lib/rtapelib.c
@@ -1,11 +1,11 @@
/* Functions for communicating with a remote tape drive.
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2004,
- 2005, 2006, 2007 Free Software Foundation, Inc.
+ 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 3, or (at your option)
+ 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,
@@ -425,10 +425,7 @@ rmt_open__ (const char *file_name, int open_mode, int bias,
}
/* FIXME: Should somewhat validate the decoding, here. */
- if (gethostbyname (remote_host) == NULL)
- error (EXIT_ON_EXEC_ERROR, 0, _("Cannot connect to %s: resolve failed"),
- remote_host);
-
+
if (remote_user && *remote_user == '\0')
remote_user = 0;
@@ -464,7 +461,7 @@ rmt_open__ (const char *file_name, int open_mode, int bias,
return -1;
#endif
}
- remote_shell_basename = last_component (remote_shell);
+ remote_shell_basename = base_name (remote_shell);
/* Set up the pipes for the `rsh' command, and fork. */
@@ -573,8 +570,7 @@ rmt_read__ (int handle, char *buffer, size_t length)
sprintf (command_buffer, "R%lu\n", (unsigned long) length);
if (do_command (handle, command_buffer) == -1
- || (status = get_status (handle)) == SAFE_READ_ERROR
- || status > length)
+ || (status = get_status (handle)) == SAFE_READ_ERROR)
return SAFE_READ_ERROR;
for (counter = 0; counter < status; counter += rlen, buffer += rlen)
@@ -710,12 +706,6 @@ rmt_ioctl__ (int handle, int operation, char *argument)
|| (status = get_status (handle), status == -1))
return -1;
- if (status > sizeof (struct mtop))
- {
- errno = EOVERFLOW;
- return -1;
- }
-
for (; status > 0; status -= counter, argument += counter)
{
counter = safe_read (READ_SIDE (handle), argument, status);
diff --git a/lib/safe-read.c b/lib/safe-read.c
new file mode 100644
index 0000000..b7bf1d5
--- /dev/null
+++ b/lib/safe-read.c
@@ -0,0 +1,78 @@
+/* An interface to read and write that retries after interrupts.
+
+ Copyright (C) 1993, 1994, 1998, 2002, 2003, 2004, 2005, 2006 Free
+ Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+/* Specification. */
+#ifdef SAFE_WRITE
+# include "safe-write.h"
+#else
+# include "safe-read.h"
+#endif
+
+/* Get ssize_t. */
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <errno.h>
+
+#ifdef EINTR
+# define IS_EINTR(x) ((x) == EINTR)
+#else
+# define IS_EINTR(x) 0
+#endif
+
+#include <limits.h>
+
+#ifdef SAFE_WRITE
+# define safe_rw safe_write
+# define rw write
+#else
+# define safe_rw safe_read
+# define rw read
+# undef const
+# define const /* empty */
+#endif
+
+/* Read(write) up to COUNT bytes at BUF from(to) descriptor FD, retrying if
+ interrupted. Return the actual number of bytes read(written), zero for EOF,
+ or SAFE_READ_ERROR(SAFE_WRITE_ERROR) upon error. */
+size_t
+safe_rw (int fd, void const *buf, size_t count)
+{
+ /* Work around a bug in Tru64 5.1. Attempting to read more than
+ INT_MAX bytes fails with errno == EINVAL. See
+ <http://lists.gnu.org/archive/html/bug-gnu-utils/2002-04/msg00010.html>.
+ When decreasing COUNT, keep it block-aligned. */
+ enum { BUGGY_READ_MAXIMUM = INT_MAX & ~8191 };
+
+ for (;;)
+ {
+ ssize_t result = rw (fd, buf, count);
+
+ if (0 <= result)
+ return result;
+ else if (IS_EINTR (errno))
+ continue;
+ else if (errno == EINVAL && BUGGY_READ_MAXIMUM < count)
+ count = BUGGY_READ_MAXIMUM;
+ else
+ return result;
+ }
+}
diff --git a/lib/safe-read.h b/lib/safe-read.h
new file mode 100644
index 0000000..3451955
--- /dev/null
+++ b/lib/safe-read.h
@@ -0,0 +1,35 @@
+/* An interface to read() that retries after interrupts.
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define SAFE_READ_ERROR ((size_t) -1)
+
+/* Read up to COUNT bytes at BUF from descriptor FD, retrying if interrupted.
+ Return the actual number of bytes read, zero for EOF, or SAFE_READ_ERROR
+ upon error. */
+extern size_t safe_read (int fd, void *buf, size_t count);
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/lib/safe-write.c b/lib/safe-write.c
new file mode 100644
index 0000000..4c375a6
--- /dev/null
+++ b/lib/safe-write.c
@@ -0,0 +1,19 @@
+/* An interface to write that retries after interrupts.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#define SAFE_WRITE
+#include "safe-read.c"
diff --git a/lib/safe-write.h b/lib/safe-write.h
new file mode 100644
index 0000000..c194636
--- /dev/null
+++ b/lib/safe-write.h
@@ -0,0 +1,25 @@
+/* An interface to write() that retries after interrupts.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <stddef.h>
+
+#define SAFE_WRITE_ERROR ((size_t) -1)
+
+/* Write up to COUNT bytes at BUF to descriptor FD, retrying if interrupted.
+ Return the actual number of bytes written, zero for EOF, or SAFE_WRITE_ERROR
+ upon error. */
+extern size_t safe_write (int fd, const void *buf, size_t count);
diff --git a/lib/same-inode.h b/lib/same-inode.h
new file mode 100644
index 0000000..deca87b
--- /dev/null
+++ b/lib/same-inode.h
@@ -0,0 +1,26 @@
+/* Determine whether two stat buffers refer to the same file.
+
+ Copyright (C) 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. */
+
+#ifndef SAME_INODE_H
+# define SAME_INODE_H 1
+
+# define SAME_INODE(Stat_buf_1, Stat_buf_2) \
+ ((Stat_buf_1).st_ino == (Stat_buf_2).st_ino \
+ && (Stat_buf_1).st_dev == (Stat_buf_2).st_dev)
+
+#endif
diff --git a/lib/save-cwd.c b/lib/save-cwd.c
new file mode 100644
index 0000000..f07973a
--- /dev/null
+++ b/lib/save-cwd.c
@@ -0,0 +1,103 @@
+/* save-cwd.c -- Save and restore current working directory.
+
+ Copyright (C) 1995, 1997, 1998, 2003, 2004, 2005, 2006 Free
+ Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Jim Meyering. */
+
+#include <config.h>
+
+#include "save-cwd.h"
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "chdir-long.h"
+#include "fcntl--.h"
+#include "xgetcwd.h"
+
+/* On systems without the fchdir function (WOE), pretend that open
+ always returns -1 so that save_cwd resorts to using xgetcwd.
+ Since chdir_long requires fchdir, use chdir instead. */
+#if !HAVE_FCHDIR
+# undef open
+# define open(File, Flags) (-1)
+# undef fchdir
+# define fchdir(Fd) (abort (), -1)
+# undef chdir_long
+# define chdir_long(Dir) chdir (Dir)
+#endif
+
+/* Record the location of the current working directory in CWD so that
+ the program may change to other directories and later use restore_cwd
+ to return to the recorded location. This function may allocate
+ space using malloc (via xgetcwd) or leave a file descriptor open;
+ use free_cwd to perform the necessary free or close. Upon failure,
+ no memory is allocated, any locally opened file descriptors are
+ closed; return non-zero -- in that case, free_cwd need not be
+ called, but doing so is ok. Otherwise, return zero.
+
+ The `raison d'etre' for this interface is that the working directory
+ is sometimes inaccessible, and getcwd is not robust or as efficient.
+ So, we prefer to use the open/fchdir approach, but fall back on
+ getcwd if necessary.
+
+ Some systems lack fchdir altogether: e.g., OS/2, pre-2001 Cygwin,
+ SCO Xenix. Also, SunOS 4 and Irix 5.3 provide the function, yet it
+ doesn't work for partitions on which auditing is enabled. If
+ you're still using an obsolete system with these problems, please
+ send email to the maintainer of this code. */
+
+int
+save_cwd (struct saved_cwd *cwd)
+{
+ cwd->name = NULL;
+
+ cwd->desc = open (".", O_RDONLY);
+ if (cwd->desc < 0)
+ {
+ cwd->name = xgetcwd ();
+ return cwd->name ? 0 : -1;
+ }
+
+ return 0;
+}
+
+/* Change to recorded location, CWD, in directory hierarchy.
+ Upon failure, return -1 (errno is set by chdir or fchdir).
+ Upon success, return zero. */
+
+int
+restore_cwd (const struct saved_cwd *cwd)
+{
+ if (0 <= cwd->desc)
+ return fchdir (cwd->desc);
+ else
+ return chdir_long (cwd->name);
+}
+
+void
+free_cwd (struct saved_cwd *cwd)
+{
+ if (cwd->desc >= 0)
+ close (cwd->desc);
+ if (cwd->name)
+ free (cwd->name);
+}
diff --git a/lib/save-cwd.h b/lib/save-cwd.h
new file mode 100644
index 0000000..d646b55
--- /dev/null
+++ b/lib/save-cwd.h
@@ -0,0 +1,34 @@
+/* Save and restore current working directory.
+
+ Copyright (C) 1995, 1997, 1998, 2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Jim Meyering. */
+
+#ifndef SAVE_CWD_H
+# define SAVE_CWD_H 1
+
+struct saved_cwd
+ {
+ int desc;
+ char *name;
+ };
+
+int save_cwd (struct saved_cwd *cwd);
+int restore_cwd (const struct saved_cwd *cwd);
+void free_cwd (struct saved_cwd *cwd);
+
+#endif /* SAVE_CWD_H */
diff --git a/lib/savedir.c b/lib/savedir.c
new file mode 100644
index 0000000..d930fb4
--- /dev/null
+++ b/lib/savedir.c
@@ -0,0 +1,137 @@
+/* savedir.c -- save the list of files in a directory in a string
+
+ Copyright (C) 1990, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+ 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
+
+#include <config.h>
+
+#include "savedir.h"
+
+#include <sys/types.h>
+
+#include <errno.h>
+
+#include <dirent.h>
+#ifndef _D_EXACT_NAMLEN
+# define _D_EXACT_NAMLEN(dp) strlen ((dp)->d_name)
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "openat.h"
+#include "xalloc.h"
+
+#ifndef NAME_SIZE_DEFAULT
+# define NAME_SIZE_DEFAULT 512
+#endif
+
+/* The results of opendir() in this file are not used with dirfd and fchdir,
+ therefore save some unnecessary work in fchdir.c. */
+#undef opendir
+#undef closedir
+
+/* Return a freshly allocated string containing the file names
+ in directory DIRP, separated by '\0' characters;
+ the end is marked by two '\0' characters in a row.
+ Return NULL (setting errno) if DIRP cannot be read or closed.
+ If DIRP is NULL, return NULL without affecting errno. */
+
+static char *
+savedirstream (DIR *dirp)
+{
+ char *name_space;
+ size_t allocated = NAME_SIZE_DEFAULT;
+ size_t used = 0;
+ int save_errno;
+
+ if (dirp == NULL)
+ return NULL;
+
+ name_space = xmalloc (allocated);
+
+ for (;;)
+ {
+ struct dirent const *dp;
+ char const *entry;
+
+ errno = 0;
+ dp = readdir (dirp);
+ if (! dp)
+ break;
+
+ /* Skip "", ".", and "..". "" is returned by at least one buggy
+ implementation: Solaris 2.4 readdir on NFS file systems. */
+ entry = dp->d_name;
+ if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0')
+ {
+ size_t entry_size = _D_EXACT_NAMLEN (dp) + 1;
+ if (used + entry_size < used)
+ xalloc_die ();
+ if (allocated <= used + entry_size)
+ {
+ do
+ {
+ if (2 * allocated < allocated)
+ xalloc_die ();
+ allocated *= 2;
+ }
+ while (allocated <= used + entry_size);
+
+ name_space = xrealloc (name_space, allocated);
+ }
+ memcpy (name_space + used, entry, entry_size);
+ used += entry_size;
+ }
+ }
+ name_space[used] = '\0';
+ save_errno = errno;
+ if (closedir (dirp) != 0)
+ save_errno = errno;
+ if (save_errno != 0)
+ {
+ free (name_space);
+ errno = save_errno;
+ return NULL;
+ }
+ return name_space;
+}
+
+/* Return a freshly allocated string containing the file names
+ 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. */
+
+char *
+savedir (char const *dir)
+{
+ return savedirstream (opendir (dir));
+}
+
+/* Return a freshly allocated string containing the file names
+ in directory FD, separated by '\0' characters;
+ the end is marked by two '\0' characters in a row.
+ Return NULL (setting errno) if FD cannot be read or closed. */
+
+char *
+fdsavedir (int fd)
+{
+ return savedirstream (fdopendir (fd));
+}
diff --git a/lib/savedir.h b/lib/savedir.h
new file mode 100644
index 0000000..5b7bef9
--- /dev/null
+++ b/lib/savedir.h
@@ -0,0 +1,27 @@
+/* Save the list of files in a directory in a string.
+
+ Copyright (C) 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 David MacKenzie <djm@gnu.ai.mit.edu>. */
+
+#if !defined SAVEDIR_H_
+# define SAVEDIR_H_
+
+char *savedir (char const *dir);
+char *fdsavedir (int fd);
+
+#endif
diff --git a/lib/setenv.c b/lib/setenv.c
new file mode 100644
index 0000000..c54c28d
--- /dev/null
+++ b/lib/setenv.c
@@ -0,0 +1,332 @@
+/* Copyright (C) 1992,1995-1999,2000-2003,2005-2007 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#if !_LIBC
+# include <config.h>
+#endif
+#include <alloca.h>
+
+#include <errno.h>
+#ifndef __set_errno
+# define __set_errno(ev) ((errno) = (ev))
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#if _LIBC || HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if _LIBC || !HAVE_SETENV
+
+#if !_LIBC
+# include "allocsa.h"
+#endif
+
+#if !_LIBC
+# define __environ environ
+# ifndef HAVE_ENVIRON_DECL
+extern char **environ;
+# endif
+#endif
+
+#if _LIBC
+/* This lock protects against simultaneous modifications of `environ'. */
+# include <bits/libc-lock.h>
+__libc_lock_define_initialized (static, envlock)
+# define LOCK __libc_lock_lock (envlock)
+# define UNLOCK __libc_lock_unlock (envlock)
+#else
+# define LOCK
+# define UNLOCK
+#endif
+
+/* In the GNU C library we must keep the namespace clean. */
+#ifdef _LIBC
+# define setenv __setenv
+# define clearenv __clearenv
+# define tfind __tfind
+# define tsearch __tsearch
+#endif
+
+/* In the GNU C library implementation we try to be more clever and
+ allow arbitrarily many changes of the environment given that the used
+ values are from a small set. Outside glibc this will eat up all
+ memory after a while. */
+#if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH \
+ && defined __GNUC__)
+# define USE_TSEARCH 1
+# include <search.h>
+typedef int (*compar_fn_t) (const void *, const void *);
+
+/* This is a pointer to the root of the search tree with the known
+ values. */
+static void *known_values;
+
+# define KNOWN_VALUE(Str) \
+ ({ \
+ void *value = tfind (Str, &known_values, (compar_fn_t) strcmp); \
+ value != NULL ? *(char **) value : NULL; \
+ })
+# define STORE_VALUE(Str) \
+ tsearch (Str, &known_values, (compar_fn_t) strcmp)
+
+#else
+# undef USE_TSEARCH
+
+# define KNOWN_VALUE(Str) NULL
+# define STORE_VALUE(Str) do { } while (0)
+
+#endif
+
+
+/* If this variable is not a null pointer we allocated the current
+ environment. */
+static char **last_environ;
+
+
+/* This function is used by `setenv' and `putenv'. The difference between
+ the two functions is that for the former must create a new string which
+ is then placed in the environment, while the argument of `putenv'
+ must be used directly. This is all complicated by the fact that we try
+ to reuse values once generated for a `setenv' call since we can never
+ free the strings. */
+int
+__add_to_environ (const char *name, const char *value, const char *combined,
+ int replace)
+{
+ register char **ep;
+ register size_t size;
+ const size_t namelen = strlen (name);
+ const size_t vallen = value != NULL ? strlen (value) + 1 : 0;
+
+ LOCK;
+
+ /* We have to get the pointer now that we have the lock and not earlier
+ since another thread might have created a new environment. */
+ ep = __environ;
+
+ size = 0;
+ if (ep != NULL)
+ {
+ for (; *ep != NULL; ++ep)
+ if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
+ break;
+ else
+ ++size;
+ }
+
+ if (ep == NULL || *ep == NULL)
+ {
+ char **new_environ;
+#ifdef USE_TSEARCH
+ char *new_value;
+#endif
+
+ /* We allocated this space; we can extend it. */
+ new_environ =
+ (char **) (last_environ == NULL
+ ? malloc ((size + 2) * sizeof (char *))
+ : realloc (last_environ, (size + 2) * sizeof (char *)));
+ if (new_environ == NULL)
+ {
+ UNLOCK;
+ return -1;
+ }
+
+ /* If the whole entry is given add it. */
+ if (combined != NULL)
+ /* We must not add the string to the search tree since it belongs
+ to the user. */
+ new_environ[size] = (char *) combined;
+ else
+ {
+ /* See whether the value is already known. */
+#ifdef USE_TSEARCH
+# ifdef _LIBC
+ new_value = (char *) alloca (namelen + 1 + vallen);
+ __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
+ value, vallen);
+# else
+ new_value = (char *) allocsa (namelen + 1 + vallen);
+ if (new_value == NULL)
+ {
+ __set_errno (ENOMEM);
+ UNLOCK;
+ return -1;
+ }
+ memcpy (new_value, name, namelen);
+ new_value[namelen] = '=';
+ memcpy (&new_value[namelen + 1], value, vallen);
+# endif
+
+ new_environ[size] = KNOWN_VALUE (new_value);
+ if (new_environ[size] == NULL)
+#endif
+ {
+ new_environ[size] = (char *) malloc (namelen + 1 + vallen);
+ if (new_environ[size] == NULL)
+ {
+#if defined USE_TSEARCH && !defined _LIBC
+ freesa (new_value);
+#endif
+ __set_errno (ENOMEM);
+ UNLOCK;
+ return -1;
+ }
+
+#ifdef USE_TSEARCH
+ memcpy (new_environ[size], new_value, namelen + 1 + vallen);
+#else
+ memcpy (new_environ[size], name, namelen);
+ new_environ[size][namelen] = '=';
+ memcpy (&new_environ[size][namelen + 1], value, vallen);
+#endif
+ /* And save the value now. We cannot do this when we remove
+ the string since then we cannot decide whether it is a
+ user string or not. */
+ STORE_VALUE (new_environ[size]);
+ }
+#if defined USE_TSEARCH && !defined _LIBC
+ freesa (new_value);
+#endif
+ }
+
+ if (__environ != last_environ)
+ memcpy ((char *) new_environ, (char *) __environ,
+ size * sizeof (char *));
+
+ new_environ[size + 1] = NULL;
+
+ last_environ = __environ = new_environ;
+ }
+ else if (replace)
+ {
+ char *np;
+
+ /* Use the user string if given. */
+ if (combined != NULL)
+ np = (char *) combined;
+ else
+ {
+#ifdef USE_TSEARCH
+ char *new_value;
+# ifdef _LIBC
+ new_value = alloca (namelen + 1 + vallen);
+ __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
+ value, vallen);
+# else
+ new_value = allocsa (namelen + 1 + vallen);
+ if (new_value == NULL)
+ {
+ __set_errno (ENOMEM);
+ UNLOCK;
+ return -1;
+ }
+ memcpy (new_value, name, namelen);
+ new_value[namelen] = '=';
+ memcpy (&new_value[namelen + 1], value, vallen);
+# endif
+
+ np = KNOWN_VALUE (new_value);
+ if (np == NULL)
+#endif
+ {
+ np = malloc (namelen + 1 + vallen);
+ if (np == NULL)
+ {
+#if defined USE_TSEARCH && !defined _LIBC
+ freesa (new_value);
+#endif
+ __set_errno (ENOMEM);
+ UNLOCK;
+ return -1;
+ }
+
+#ifdef USE_TSEARCH
+ memcpy (np, new_value, namelen + 1 + vallen);
+#else
+ memcpy (np, name, namelen);
+ np[namelen] = '=';
+ memcpy (&np[namelen + 1], value, vallen);
+#endif
+ /* And remember the value. */
+ STORE_VALUE (np);
+ }
+#if defined USE_TSEARCH && !defined _LIBC
+ freesa (new_value);
+#endif
+ }
+
+ *ep = np;
+ }
+
+ UNLOCK;
+
+ return 0;
+}
+
+int
+setenv (const char *name, const char *value, int replace)
+{
+ return __add_to_environ (name, value, NULL, replace);
+}
+
+/* The `clearenv' was planned to be added to POSIX.1 but probably
+ never made it. Nevertheless the POSIX.9 standard (POSIX bindings
+ for Fortran 77) requires this function. */
+int
+clearenv (void)
+{
+ LOCK;
+
+ if (__environ == last_environ && __environ != NULL)
+ {
+ /* We allocated this environment so we can free it. */
+ free (__environ);
+ last_environ = NULL;
+ }
+
+ /* Clear the environment pointer removes the whole environment. */
+ __environ = NULL;
+
+ UNLOCK;
+
+ return 0;
+}
+
+#ifdef _LIBC
+static void
+free_mem (void)
+{
+ /* Remove all traces. */
+ clearenv ();
+
+ /* Now remove the search tree. */
+ __tdestroy (known_values, free);
+ known_values = NULL;
+}
+text_set_element (__libc_subfreeres, free_mem);
+
+
+# undef setenv
+# undef clearenv
+weak_alias (__setenv, setenv)
+weak_alias (__clearenv, clearenv)
+#endif
+
+#endif /* _LIBC || !HAVE_SETENV */
diff --git a/lib/setenv.h b/lib/setenv.h
new file mode 100644
index 0000000..92e7bba
--- /dev/null
+++ b/lib/setenv.h
@@ -0,0 +1,54 @@
+/* Setting environment variables.
+ Copyright (C) 2001-2004, 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. */
+
+#if HAVE_SETENV || HAVE_UNSETENV
+
+/* Get setenv(), unsetenv() declarations. */
+# include <stdlib.h>
+
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !HAVE_SETENV
+
+/* Set NAME to VALUE in the environment.
+ If REPLACE is nonzero, overwrite an existing value. */
+extern int setenv (const char *name, const char *value, int replace);
+
+#endif
+
+#if HAVE_UNSETENV
+
+# if VOID_UNSETENV
+/* On some systems, unsetenv() returns void.
+ This is the case for FreeBSD 4.8, NetBSD 1.6, OpenBSD 3.4. */
+# define unsetenv(name) ((unsetenv)(name), 0)
+# endif
+
+#else
+
+/* Remove the variable NAME from the environment. */
+extern int unsetenv (const char *name);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/lib/sleep.c b/lib/sleep.c
new file mode 100644
index 0000000..037559b
--- /dev/null
+++ b/lib/sleep.c
@@ -0,0 +1,47 @@
+/* Pausing execution of the current thread.
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2007.
+
+ 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>
+
+/* Specification. */
+#include <unistd.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+# define WIN32_LEAN_AND_MEAN /* avoid including junk */
+# include <windows.h>
+
+unsigned int
+sleep (unsigned int seconds)
+{
+ unsigned int remaining;
+
+ /* Sleep for 1 second many times, because
+ 1. Sleep is not interruptiple by Ctrl-C,
+ 2. we want to avoid arithmetic overflow while multiplying with 1000. */
+ for (remaining = seconds; remaining > 0; remaining--)
+ Sleep (1000);
+
+ return remaining;
+}
+
+#else
+
+ #error "Please port gnulib sleep.c to your platform, possibly using usleep() or select(), then report this to bug-gnulib."
+
+#endif
diff --git a/lib/stdbool_.h b/lib/stdbool_.h
new file mode 100644
index 0000000..150a010
--- /dev/null
+++ b/lib/stdbool_.h
@@ -0,0 +1,118 @@
+/* Copyright (C) 2001, 2002, 2003, 2006, 2007 Free Software Foundation, Inc.
+ Written by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _GL_STDBOOL_H
+#define _GL_STDBOOL_H
+
+/* ISO C 99 <stdbool.h> for platforms that lack it. */
+
+/* Usage suggestions:
+
+ Programs that use <stdbool.h> should be aware of some limitations
+ and standards compliance issues.
+
+ Standards compliance:
+
+ - <stdbool.h> must be #included before 'bool', 'false', 'true'
+ can be used.
+
+ - You cannot assume that sizeof (bool) == 1.
+
+ - Programs should not undefine the macros bool, true, and false,
+ as C99 lists that as an "obsolescent feature".
+
+ Limitations of this substitute, when used in a C89 environment:
+
+ - <stdbool.h> must be #included before the '_Bool' type can be used.
+
+ - You cannot assume that _Bool is a typedef; it might be a macro.
+
+ - Bit-fields of type 'bool' are not supported. Portable code
+ should use 'unsigned int foo : 1;' rather than 'bool foo : 1;'.
+
+ - In C99, casts and automatic conversions to '_Bool' or 'bool' are
+ performed in such a way that every nonzero value gets converted
+ to 'true', and zero gets converted to 'false'. This doesn't work
+ with this substitute. With this substitute, only the values 0 and 1
+ give the expected result when converted to _Bool' or 'bool'.
+
+ Also, it is suggested that programs use 'bool' rather than '_Bool';
+ this isn't required, but 'bool' is more common. */
+
+
+/* 7.16. Boolean type and values */
+
+/* BeOS <sys/socket.h> already #defines false 0, true 1. We use the same
+ definitions below, but temporarily we have to #undef them. */
+#ifdef __BEOS__
+# include <OS.h> /* defines bool but not _Bool */
+# undef false
+# undef true
+#endif
+
+/* For the sake of symbolic names in gdb, we define true and false as
+ enum constants, not only as macros.
+ It is tempting to write
+ typedef enum { false = 0, true = 1 } _Bool;
+ so that gdb prints values of type 'bool' symbolically. But if we do
+ this, values of type '_Bool' may promote to 'int' or 'unsigned int'
+ (see ISO C 99 6.7.2.2.(4)); however, '_Bool' must promote to 'int'
+ (see ISO C 99 6.3.1.1.(2)). So we add a negative value to the
+ enum; this ensures that '_Bool' promotes to 'int'. */
+#if defined __cplusplus || defined __BEOS__
+ /* A compiler known to have 'bool'. */
+ /* If the compiler already has both 'bool' and '_Bool', we can assume they
+ are the same types. */
+# if !@HAVE__BOOL@
+typedef bool _Bool;
+# endif
+#else
+# if !defined __GNUC__
+ /* If @HAVE__BOOL@:
+ Some HP-UX cc and AIX IBM C compiler versions have compiler bugs when
+ the built-in _Bool type is used. See
+ http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
+ http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
+ http://lists.gnu.org/archive/html/bug-coreutils/2005-10/msg00086.html
+ Similar bugs are likely with other compilers as well; this file
+ wouldn't be used if <stdbool.h> was working.
+ So we override the _Bool type.
+ If !@HAVE__BOOL@:
+ Need to define _Bool ourselves. As 'signed char' or as an enum type?
+ Use of a typedef, with SunPRO C, leads to a stupid
+ "warning: _Bool is a keyword in ISO C99".
+ Use of an enum type, with IRIX cc, leads to a stupid
+ "warning(1185): enumerated type mixed with another type".
+ The only benefit of the enum type, debuggability, is not important
+ with these compilers. So use 'signed char' and no typedef. */
+# define _Bool signed char
+enum { false = 0, true = 1 };
+# else
+ /* With this compiler, trust the _Bool type if the compiler has it. */
+# if !@HAVE__BOOL@
+typedef enum { _Bool_must_promote_to_int = -1, false = 0, true = 1 } _Bool;
+# endif
+# endif
+#endif
+#define bool _Bool
+
+/* The other macros must be usable in preprocessor directives. */
+#define false 0
+#define true 1
+#define __bool_true_false_are_defined 1
+
+#endif /* _GL_STDBOOL_H */
diff --git a/lib/stdint_.h b/lib/stdint_.h
new file mode 100644
index 0000000..d374535
--- /dev/null
+++ b/lib/stdint_.h
@@ -0,0 +1,512 @@
+/* Copyright (C) 2001-2002, 2004-2007 Free Software Foundation, Inc.
+ Written by Paul Eggert, Bruno Haible, Sam Steingold, Peter Burwood.
+ This file is part of gnulib.
+
+ 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. */
+
+/*
+ * ISO C 99 <stdint.h> for platforms that lack it.
+ * <http://www.opengroup.org/susv3xbd/stdint.h.html>
+ */
+
+#ifndef _GL_STDINT_H
+
+/* Get those types that are already defined in other system include
+ files, so that we can "#define int8_t signed char" below without
+ worrying about a later system include file containing a "typedef
+ signed char int8_t;" that will get messed up by our macro. Our
+ macros should all be consistent with the system versions, except
+ for the "fast" types and macros, which we recommend against using
+ in public interfaces due to compiler differences. */
+
+#if @HAVE_STDINT_H@
+# if defined __sgi && ! defined __c99
+ /* Bypass IRIX's <stdint.h> if in C89 mode, since it merely annoys users
+ with "This header file is to be used only for c99 mode compilations"
+ diagnostics. */
+# define __STDINT_H__
+# endif
+ /* Other systems may have an incomplete or buggy <stdint.h>.
+ Include it before <inttypes.h>, since any "#include <stdint.h>"
+ in <inttypes.h> would reinclude us, skipping our contents because
+ _GL_STDINT_H is defined.
+ The include_next requires a split double-inclusion guard. */
+# if @HAVE_INCLUDE_NEXT@
+# include_next <stdint.h>
+# else
+# include @ABSOLUTE_STDINT_H@
+# endif
+#endif
+
+#ifndef _GL_STDINT_H
+#define _GL_STDINT_H
+
+/* <sys/types.h> defines some of the stdint.h types as well, on glibc,
+ IRIX 6.5, and OpenBSD 3.8 (via <machine/types.h>).
+ AIX 5.2 <sys/types.h> isn't needed and causes troubles.
+ MacOS X 10.4.6 <sys/types.h> includes <stdint.h> (which is us), but
+ relies on the system <stdint.h> definitions, so include
+ <sys/types.h> after @ABSOLUTE_STDINT_H@. */
+#if @HAVE_SYS_TYPES_H@ && ! defined _AIX
+# include <sys/types.h>
+#endif
+
+/* Get LONG_MIN, LONG_MAX, ULONG_MAX. */
+#include <limits.h>
+
+#if @HAVE_INTTYPES_H@
+ /* In OpenBSD 3.8, <inttypes.h> includes <machine/types.h>, which defines
+ int{8,16,32,64}_t, uint{8,16,32,64}_t and __BIT_TYPES_DEFINED__.
+ <inttypes.h> also defines intptr_t and uintptr_t. */
+# define _GL_JUST_INCLUDE_ABSOLUTE_INTTYPES_H
+# include <inttypes.h>
+# undef _GL_JUST_INCLUDE_ABSOLUTE_INTTYPES_H
+#elif @HAVE_SYS_INTTYPES_H@
+ /* Solaris 7 <sys/inttypes.h> has the types except the *_fast*_t types, and
+ the macros except for *_FAST*_*, INTPTR_MIN, PTRDIFF_MIN, PTRDIFF_MAX. */
+# include <sys/inttypes.h>
+#endif
+
+#if @HAVE_SYS_BITYPES_H@ && ! defined __BIT_TYPES_DEFINED__
+ /* Linux libc4 >= 4.6.7 and libc5 have a <sys/bitypes.h> that defines
+ int{8,16,32,64}_t and __BIT_TYPES_DEFINED__. In libc5 >= 5.2.2 it is
+ included by <sys/types.h>. */
+# include <sys/bitypes.h>
+#endif
+
+#if ! defined __cplusplus || defined __STDC_CONSTANT_MACROS
+
+/* Get WCHAR_MIN, WCHAR_MAX. */
+# if ! (defined WCHAR_MIN && defined WCHAR_MAX)
+# include <wchar.h>
+# endif
+
+#endif
+
+/* Minimum and maximum values for a integer type under the usual assumption.
+ Return an unspecified value if BITS == 0, adding a check to pacify
+ picky compilers. */
+
+#define _STDINT_MIN(signed, bits, zero) \
+ ((signed) ? (- ((zero) + 1) << ((bits) ? (bits) - 1 : 0)) : (zero))
+
+#define _STDINT_MAX(signed, bits, zero) \
+ ((signed) \
+ ? ~ _STDINT_MIN (signed, bits, zero) \
+ : ((((zero) + 1) << ((bits) ? (bits) - 1 : 0)) - 1) * 2 + 1)
+
+/* 7.18.1.1. Exact-width integer types */
+
+/* Here we assume a standard architecture where the hardware integer
+ types have 8, 16, 32, optionally 64 bits. */
+
+#undef int8_t
+#undef uint8_t
+#define int8_t signed char
+#define uint8_t unsigned char
+
+#undef int16_t
+#undef uint16_t
+#define int16_t short int
+#define uint16_t unsigned short int
+
+#undef int32_t
+#undef uint32_t
+#define int32_t int
+#define uint32_t unsigned int
+
+/* Do not undefine int64_t if gnulib is not being used with 64-bit
+ types, since otherwise it breaks platforms like Tandem/NSK. */
+#if LONG_MAX >> 31 >> 31 == 1
+# undef int64_t
+# define int64_t long int
+# define GL_INT64_T
+#elif defined _MSC_VER
+# undef int64_t
+# define int64_t __int64
+# define GL_INT64_T
+#elif @HAVE_LONG_LONG_INT@
+# undef int64_t
+# define int64_t long long int
+# define GL_INT64_T
+#endif
+
+#if ULONG_MAX >> 31 >> 31 >> 1 == 1
+# undef uint64_t
+# define uint64_t unsigned long int
+# define GL_UINT64_T
+#elif defined _MSC_VER
+# undef uint64_t
+# define uint64_t unsigned __int64
+# define GL_UINT64_T
+#elif @HAVE_UNSIGNED_LONG_LONG_INT@
+# undef uint64_t
+# define uint64_t unsigned long long int
+# define GL_UINT64_T
+#endif
+
+/* Avoid collision with Solaris 2.5.1 <pthread.h> etc. */
+#define _UINT8_T
+#define _UINT32_T
+#define _UINT64_T
+
+
+/* 7.18.1.2. Minimum-width integer types */
+
+/* Here we assume a standard architecture where the hardware integer
+ types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types
+ are the same as the corresponding N_t types. */
+
+#undef int_least8_t
+#undef uint_least8_t
+#undef int_least16_t
+#undef uint_least16_t
+#undef int_least32_t
+#undef uint_least32_t
+#undef int_least64_t
+#undef uint_least64_t
+#define int_least8_t int8_t
+#define uint_least8_t uint8_t
+#define int_least16_t int16_t
+#define uint_least16_t uint16_t
+#define int_least32_t int32_t
+#define uint_least32_t uint32_t
+#ifdef GL_INT64_T
+# define int_least64_t int64_t
+#endif
+#ifdef GL_UINT64_T
+# define uint_least64_t uint64_t
+#endif
+
+/* 7.18.1.3. Fastest minimum-width integer types */
+
+/* Note: Other <stdint.h> substitutes may define these types differently.
+ It is not recommended to use these types in public header files. */
+
+/* Here we assume a standard architecture where the hardware integer
+ types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types
+ are taken from the same list of types. Assume that 'long int'
+ is fast enough for all narrower integers. */
+
+#undef int_fast8_t
+#undef uint_fast8_t
+#undef int_fast16_t
+#undef uint_fast16_t
+#undef int_fast32_t
+#undef uint_fast32_t
+#undef int_fast64_t
+#undef uint_fast64_t
+#define int_fast8_t long int
+#define uint_fast8_t unsigned int_fast8_t
+#define int_fast16_t long int
+#define uint_fast16_t unsigned int_fast16_t
+#define int_fast32_t long int
+#define uint_fast32_t unsigned int_fast32_t
+#ifdef GL_INT64_T
+# define int_fast64_t int64_t
+#endif
+#ifdef GL_UINT64_T
+# define uint_fast64_t uint64_t
+#endif
+
+/* 7.18.1.4. Integer types capable of holding object pointers */
+
+#undef intptr_t
+#undef uintptr_t
+#define intptr_t long int
+#define uintptr_t unsigned long int
+
+/* 7.18.1.5. Greatest-width integer types */
+
+/* Note: These types are compiler dependent. It may be unwise to use them in
+ public header files. */
+
+#undef intmax_t
+#if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1
+# define intmax_t long long int
+#elif defined GL_INT64_T
+# define intmax_t int64_t
+#else
+# define intmax_t long int
+#endif
+
+#undef uintmax_t
+#if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1
+# define uintmax_t unsigned long long int
+#elif defined GL_UINT64_T
+# define uintmax_t uint64_t
+#else
+# define uintmax_t unsigned long int
+#endif
+
+/* 7.18.2. Limits of specified-width integer types */
+
+#if ! defined __cplusplus || defined __STDC_LIMIT_MACROS
+
+/* 7.18.2.1. Limits of exact-width integer types */
+
+/* Here we assume a standard architecture where the hardware integer
+ types have 8, 16, 32, optionally 64 bits. */
+
+#undef INT8_MIN
+#undef INT8_MAX
+#undef UINT8_MAX
+#define INT8_MIN (~ INT8_MAX)
+#define INT8_MAX 127
+#define UINT8_MAX 255
+
+#undef INT16_MIN
+#undef INT16_MAX
+#undef UINT16_MAX
+#define INT16_MIN (~ INT16_MAX)
+#define INT16_MAX 32767
+#define UINT16_MAX 65535
+
+#undef INT32_MIN
+#undef INT32_MAX
+#undef UINT32_MAX
+#define INT32_MIN (~ INT32_MAX)
+#define INT32_MAX 2147483647
+#define UINT32_MAX 4294967295U
+
+#undef INT64_MIN
+#undef INT64_MAX
+#ifdef GL_INT64_T
+/* Prefer (- INTMAX_C (1) << 63) over (~ INT64_MAX) because SunPRO C 5.0
+ evaluates the latter incorrectly in preprocessor expressions. */
+# define INT64_MIN (- INTMAX_C (1) << 63)
+# define INT64_MAX INTMAX_C (9223372036854775807)
+#endif
+
+#undef UINT64_MAX
+#ifdef GL_UINT64_T
+# define UINT64_MAX UINTMAX_C (18446744073709551615)
+#endif
+
+/* 7.18.2.2. Limits of minimum-width integer types */
+
+/* Here we assume a standard architecture where the hardware integer
+ types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types
+ are the same as the corresponding N_t types. */
+
+#undef INT_LEAST8_MIN
+#undef INT_LEAST8_MAX
+#undef UINT_LEAST8_MAX
+#define INT_LEAST8_MIN INT8_MIN
+#define INT_LEAST8_MAX INT8_MAX
+#define UINT_LEAST8_MAX UINT8_MAX
+
+#undef INT_LEAST16_MIN
+#undef INT_LEAST16_MAX
+#undef UINT_LEAST16_MAX
+#define INT_LEAST16_MIN INT16_MIN
+#define INT_LEAST16_MAX INT16_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+
+#undef INT_LEAST32_MIN
+#undef INT_LEAST32_MAX
+#undef UINT_LEAST32_MAX
+#define INT_LEAST32_MIN INT32_MIN
+#define INT_LEAST32_MAX INT32_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+
+#undef INT_LEAST64_MIN
+#undef INT_LEAST64_MAX
+#ifdef GL_INT64_T
+# define INT_LEAST64_MIN INT64_MIN
+# define INT_LEAST64_MAX INT64_MAX
+#endif
+
+#undef UINT_LEAST64_MAX
+#ifdef GL_UINT64_T
+# define UINT_LEAST64_MAX UINT64_MAX
+#endif
+
+/* 7.18.2.3. Limits of fastest minimum-width integer types */
+
+/* Here we assume a standard architecture where the hardware integer
+ types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types
+ are taken from the same list of types. */
+
+#undef INT_FAST8_MIN
+#undef INT_FAST8_MAX
+#undef UINT_FAST8_MAX
+#define INT_FAST8_MIN LONG_MIN
+#define INT_FAST8_MAX LONG_MAX
+#define UINT_FAST8_MAX ULONG_MAX
+
+#undef INT_FAST16_MIN
+#undef INT_FAST16_MAX
+#undef UINT_FAST16_MAX
+#define INT_FAST16_MIN LONG_MIN
+#define INT_FAST16_MAX LONG_MAX
+#define UINT_FAST16_MAX ULONG_MAX
+
+#undef INT_FAST32_MIN
+#undef INT_FAST32_MAX
+#undef UINT_FAST32_MAX
+#define INT_FAST32_MIN LONG_MIN
+#define INT_FAST32_MAX LONG_MAX
+#define UINT_FAST32_MAX ULONG_MAX
+
+#undef INT_FAST64_MIN
+#undef INT_FAST64_MAX
+#ifdef GL_INT64_T
+# define INT_FAST64_MIN INT64_MIN
+# define INT_FAST64_MAX INT64_MAX
+#endif
+
+#undef UINT_FAST64_MAX
+#ifdef GL_UINT64_T
+# define UINT_FAST64_MAX UINT64_MAX
+#endif
+
+/* 7.18.2.4. Limits of integer types capable of holding object pointers */
+
+#undef INTPTR_MIN
+#undef INTPTR_MAX
+#undef UINTPTR_MAX
+#define INTPTR_MIN LONG_MIN
+#define INTPTR_MAX LONG_MAX
+#define UINTPTR_MAX ULONG_MAX
+
+/* 7.18.2.5. Limits of greatest-width integer types */
+
+#undef INTMAX_MIN
+#undef INTMAX_MAX
+#ifdef INT64_MAX
+# define INTMAX_MIN INT64_MIN
+# define INTMAX_MAX INT64_MAX
+#else
+# define INTMAX_MIN INT32_MIN
+# define INTMAX_MAX INT32_MAX
+#endif
+
+#undef UINTMAX_MAX
+#ifdef UINT64_MAX
+# define UINTMAX_MAX UINT64_MAX
+#else
+# define UINTMAX_MAX UINT32_MAX
+#endif
+
+/* 7.18.3. Limits of other integer types */
+
+/* ptrdiff_t limits */
+#undef PTRDIFF_MIN
+#undef PTRDIFF_MAX
+#define PTRDIFF_MIN \
+ _STDINT_MIN (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@)
+#define PTRDIFF_MAX \
+ _STDINT_MAX (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@)
+
+/* sig_atomic_t limits */
+#undef SIG_ATOMIC_MIN
+#undef SIG_ATOMIC_MAX
+#define SIG_ATOMIC_MIN \
+ _STDINT_MIN (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \
+ 0@SIG_ATOMIC_T_SUFFIX@)
+#define SIG_ATOMIC_MAX \
+ _STDINT_MAX (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \
+ 0@SIG_ATOMIC_T_SUFFIX@)
+
+
+/* size_t limit */
+#undef SIZE_MAX
+#define SIZE_MAX _STDINT_MAX (0, @BITSIZEOF_SIZE_T@, 0@SIZE_T_SUFFIX@)
+
+/* wchar_t limits */
+#undef WCHAR_MIN
+#undef WCHAR_MAX
+#define WCHAR_MIN \
+ _STDINT_MIN (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@)
+#define WCHAR_MAX \
+ _STDINT_MAX (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@)
+
+/* wint_t limits */
+#undef WINT_MIN
+#undef WINT_MAX
+#define WINT_MIN \
+ _STDINT_MIN (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@)
+#define WINT_MAX \
+ _STDINT_MAX (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@)
+
+#endif /* !defined __cplusplus || defined __STDC_LIMIT_MACROS */
+
+/* 7.18.4. Macros for integer constants */
+
+#if ! defined __cplusplus || defined __STDC_CONSTANT_MACROS
+
+/* 7.18.4.1. Macros for minimum-width integer constants */
+/* According to ISO C 99 Technical Corrigendum 1 */
+
+/* Here we assume a standard architecture where the hardware integer
+ types have 8, 16, 32, optionally 64 bits, and int is 32 bits. */
+
+#undef INT8_C
+#undef UINT8_C
+#define INT8_C(x) x
+#define UINT8_C(x) x
+
+#undef INT16_C
+#undef UINT16_C
+#define INT16_C(x) x
+#define UINT16_C(x) x
+
+#undef INT32_C
+#undef UINT32_C
+#define INT32_C(x) x
+#define UINT32_C(x) x ## U
+
+#undef INT64_C
+#undef UINT64_C
+#if LONG_MAX >> 31 >> 31 == 1
+# define INT64_C(x) x##L
+#elif defined _MSC_VER
+# define INT64_C(x) x##i64
+#elif @HAVE_LONG_LONG_INT@
+# define INT64_C(x) x##LL
+#endif
+#if ULONG_MAX >> 31 >> 31 >> 1 == 1
+# define UINT64_C(x) x##UL
+#elif defined _MSC_VER
+# define UINT64_C(x) x##ui64
+#elif @HAVE_UNSIGNED_LONG_LONG_INT@
+# define UINT64_C(x) x##ULL
+#endif
+
+/* 7.18.4.2. Macros for greatest-width integer constants */
+
+#undef INTMAX_C
+#if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1
+# define INTMAX_C(x) x##LL
+#elif defined GL_INT64_T
+# define INTMAX_C(x) INT64_C(x)
+#else
+# define INTMAX_C(x) x##L
+#endif
+
+#undef UINTMAX_C
+#if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1
+# define UINTMAX_C(x) x##ULL
+#elif defined GL_UINT64_T
+# define UINTMAX_C(x) UINT64_C(x)
+#else
+# define UINTMAX_C(x) x##UL
+#endif
+
+#endif /* !defined __cplusplus || defined __STDC_CONSTANT_MACROS */
+
+#endif /* _GL_STDINT_H */
+#endif /* _GL_STDINT_H */
diff --git a/lib/stdio_.h b/lib/stdio_.h
new file mode 100644
index 0000000..7afaede
--- /dev/null
+++ b/lib/stdio_.h
@@ -0,0 +1,320 @@
+/* A GNU-like <stdio.h>.
+
+ Copyright (C) 2004, 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. */
+
+#if defined __need_FILE || defined __need___FILE
+/* Special invocation convention inside glibc header files. */
+
+#if @HAVE_INCLUDE_NEXT@
+# include_next <stdio.h>
+#else
+# include @ABSOLUTE_STDIO_H@
+#endif
+
+#else
+/* Normal invocation convention. */
+
+#ifndef _GL_STDIO_H
+
+/* The include_next requires a split double-inclusion guard. */
+#if @HAVE_INCLUDE_NEXT@
+# include_next <stdio.h>
+#else
+# include @ABSOLUTE_STDIO_H@
+#endif
+
+#ifndef _GL_STDIO_H
+#define _GL_STDIO_H
+
+#include <stdarg.h>
+#include <stddef.h>
+
+#if (@GNULIB_FSEEKO@ && @REPLACE_FSEEKO@) || (@GNULIB_FTELLO@ && @REPLACE_FTELLO@)
+/* Get off_t. */
+# include <sys/types.h>
+#endif
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
+# define __attribute__(Spec) /* empty */
+# endif
+/* The __-protected variants of `format' and `printf' attributes
+ are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+# define __format__ format
+# define __printf__ printf
+# endif
+#endif
+
+
+/* The definition of GL_LINK_WARNING is copied here. */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if @GNULIB_FPRINTF_POSIX@
+# if @REPLACE_FPRINTF@
+# define fprintf rpl_fprintf
+extern int fprintf (FILE *fp, const char *format, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef fprintf
+# define fprintf \
+ (GL_LINK_WARNING ("fprintf is not always POSIX compliant - " \
+ "use gnulib module fprintf-posix for portable " \
+ "POSIX compliance"), \
+ fprintf)
+#endif
+
+#if @GNULIB_VFPRINTF_POSIX@
+# if @REPLACE_VFPRINTF@
+# define vfprintf rpl_vfprintf
+extern int vfprintf (FILE *fp, const char *format, va_list args)
+ __attribute__ ((__format__ (__printf__, 2, 0)));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef vfprintf
+# define vfprintf(s,f,a) \
+ (GL_LINK_WARNING ("vfprintf is not always POSIX compliant - " \
+ "use gnulib module vfprintf-posix for portable " \
+ "POSIX compliance"), \
+ vfprintf (s, f, a))
+#endif
+
+#if @GNULIB_PRINTF_POSIX@
+# if @REPLACE_PRINTF@
+/* Don't break __attribute__((format(printf,M,N))). */
+# define printf __printf__
+extern int printf (const char *format, ...)
+ __attribute__ ((__format__ (__printf__, 1, 2)));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef printf
+# define printf \
+ (GL_LINK_WARNING ("printf is not always POSIX compliant - " \
+ "use gnulib module printf-posix for portable " \
+ "POSIX compliance"), \
+ printf)
+/* Don't break __attribute__((format(printf,M,N))). */
+# define format(kind,m,n) format (__##kind##__, m, n)
+# define __format__(kind,m,n) __format__ (__##kind##__, m, n)
+# define ____printf____ __printf__
+# define ____scanf____ __scanf__
+# define ____strftime____ __strftime__
+# define ____strfmon____ __strfmon__
+#endif
+
+#if @GNULIB_VPRINTF_POSIX@
+# if @REPLACE_VPRINTF@
+# define vprintf rpl_vprintf
+extern int vprintf (const char *format, va_list args)
+ __attribute__ ((__format__ (__printf__, 1, 0)));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef vprintf
+# define vprintf(f,a) \
+ (GL_LINK_WARNING ("vprintf is not always POSIX compliant - " \
+ "use gnulib module vprintf-posix for portable " \
+ "POSIX compliance"), \
+ vprintf (f, a))
+#endif
+
+#if @GNULIB_SNPRINTF@
+# if @REPLACE_SNPRINTF@
+# define snprintf rpl_snprintf
+# endif
+# if @REPLACE_SNPRINTF@ || !@HAVE_DECL_SNPRINTF@
+extern int snprintf (char *str, size_t size, const char *format, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef snprintf
+# define snprintf \
+ (GL_LINK_WARNING ("snprintf is unportable - " \
+ "use gnulib module snprintf for portability"), \
+ snprintf)
+#endif
+
+#if @GNULIB_VSNPRINTF@
+# if @REPLACE_VSNPRINTF@
+# define vsnprintf rpl_vsnprintf
+# endif
+# if @REPLACE_VSNPRINTF@ || !@HAVE_DECL_VSNPRINTF@
+extern int vsnprintf (char *str, size_t size, const char *format, va_list args)
+ __attribute__ ((__format__ (__printf__, 3, 0)));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef vsnprintf
+# define vsnprintf(b,s,f,a) \
+ (GL_LINK_WARNING ("vsnprintf is unportable - " \
+ "use gnulib module vsnprintf for portability"), \
+ vsnprintf (b, s, f, a))
+#endif
+
+#if @GNULIB_SPRINTF_POSIX@
+# if @REPLACE_SPRINTF@
+# define sprintf rpl_sprintf
+extern int sprintf (char *str, const char *format, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef sprintf
+# define sprintf \
+ (GL_LINK_WARNING ("sprintf is not always POSIX compliant - " \
+ "use gnulib module sprintf-posix for portable " \
+ "POSIX compliance"), \
+ sprintf)
+#endif
+
+#if @GNULIB_VSPRINTF_POSIX@
+# if @REPLACE_VSPRINTF@
+# define vsprintf rpl_vsprintf
+extern int vsprintf (char *str, const char *format, va_list args)
+ __attribute__ ((__format__ (__printf__, 2, 0)));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef vsprintf
+# define vsprintf(b,f,a) \
+ (GL_LINK_WARNING ("vsprintf is not always POSIX compliant - " \
+ "use gnulib module vsprintf-posix for portable " \
+ "POSIX compliance"), \
+ vsprintf (b, f, a))
+#endif
+
+#if @GNULIB_VASPRINTF@
+# if @REPLACE_VASPRINTF@
+# define asprintf rpl_asprintf
+# define vasprintf rpl_vasprintf
+# endif
+# if @REPLACE_VASPRINTF@ || !@HAVE_VASPRINTF@
+ /* Write formatted output to a string dynamically allocated with malloc().
+ If the memory allocation succeeds, store the address of the string in
+ *RESULT and return the number of resulting bytes, excluding the trailing
+ NUL. Upon memory allocation error, or some other error, return -1. */
+ extern int asprintf (char **result, const char *format, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)));
+ extern int vasprintf (char **result, const char *format, va_list args)
+ __attribute__ ((__format__ (__printf__, 2, 0)));
+# endif
+#endif
+
+#if @GNULIB_FSEEKO@
+# if @REPLACE_FSEEKO@
+/* Provide fseek, fseeko functions that are aware of a preceding
+ fflush(), and which detect pipes. */
+# define fseeko rpl_fseeko
+extern int fseeko (FILE *fp, off_t offset, int whence);
+# define fseek(fp, offset, whence) fseeko (fp, (off_t)(offset), whence)
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef fseeko
+# define fseeko(f,o,w) \
+ (GL_LINK_WARNING ("fseeko is unportable - " \
+ "use gnulib module fseeko for portability"), \
+ fseeko (f, o, w))
+#endif
+
+#if @GNULIB_FSEEK@ && @REPLACE_FSEEK@
+extern int rpl_fseek (FILE *fp, long offset, int whence);
+# undef fseek
+# if defined GNULIB_POSIXCHECK
+# define fseek(f,o,w) \
+ (GL_LINK_WARNING ("fseek cannot handle files larger than 4 GB " \
+ "on 32-bit platforms - " \
+ "use fseeko function for handling of large files"), \
+ rpl_fseek (f, o, w))
+# else
+# define fseek rpl_fseek
+# endif
+#elif defined GNULIB_POSIXCHECK
+# ifndef fseek
+# define fseek(f,o,w) \
+ (GL_LINK_WARNING ("fseek cannot handle files larger than 4 GB " \
+ "on 32-bit platforms - " \
+ "use fseeko function for handling of large files"), \
+ fseek (f, o, w))
+# endif
+#endif
+
+#if @GNULIB_FTELLO@
+# if @REPLACE_FTELLO@
+# define ftello rpl_ftello
+extern off_t ftello (FILE *fp);
+# define ftell(fp) ftello (fp)
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef ftello
+# define ftello(f) \
+ (GL_LINK_WARNING ("ftello is unportable - " \
+ "use gnulib module ftello for portability"), \
+ ftello (f))
+#endif
+
+#if @GNULIB_FTELL@ && @REPLACE_FTELL@
+extern long rpl_ftell (FILE *fp);
+# undef ftell
+# if GNULIB_POSIXCHECK
+# define ftell(f) \
+ (GL_LINK_WARNING ("ftell cannot handle files larger than 4 GB " \
+ "on 32-bit platforms - " \
+ "use ftello function for handling of large files"), \
+ rpl_ftell (f))
+# else
+# define ftell rpl_ftell
+# endif
+#elif defined GNULIB_POSIXCHECK
+# ifndef ftell
+# define ftell(f) \
+ (GL_LINK_WARNING ("ftell cannot handle files larger than 4 GB " \
+ "on 32-bit platforms - " \
+ "use ftello function for handling of large files"), \
+ ftell (f))
+# endif
+#endif
+
+#if @GNULIB_FFLUSH@
+# if @REPLACE_FFLUSH@
+# define fflush rpl_fflush
+ /* Flush all pending data on STREAM according to POSIX rules. Both
+ output and seekable input streams are supported.
+ Note! LOSS OF DATA can occur if fflush is applied on an input stream
+ that is _not_seekable_ or on an update stream that is _not_seekable_
+ and in which the most recent operation was input. Seekability can
+ be tested with lseek(fileno(fp),0,SEEK_CUR). */
+ extern int fflush (FILE *gl_stream);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef fflush
+# define fflush(f) \
+ (GL_LINK_WARNING ("fflush is not always POSIX compliant - " \
+ "use gnulib module fflush for portable " \
+ "POSIX compliance"), \
+ fflush (f))
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GL_STDIO_H */
+#endif /* _GL_STDIO_H */
+#endif
diff --git a/lib/stdlib_.h b/lib/stdlib_.h
new file mode 100644
index 0000000..130f071
--- /dev/null
+++ b/lib/stdlib_.h
@@ -0,0 +1,140 @@
+/* A GNU-like <stdlib.h>.
+
+ Copyright (C) 1995, 2001-2002, 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. */
+
+#if defined __need_malloc_and_calloc
+/* Special invocation convention inside glibc header files. */
+
+#if @HAVE_INCLUDE_NEXT@
+# include_next <stdlib.h>
+#else
+# include @ABSOLUTE_STDLIB_H@
+#endif
+
+#else
+/* Normal invocation convention. */
+
+#ifndef _GL_STDLIB_H
+
+/* The include_next requires a split double-inclusion guard. */
+#if @HAVE_INCLUDE_NEXT@
+# include_next <stdlib.h>
+#else
+# include @ABSOLUTE_STDLIB_H@
+#endif
+
+#ifndef _GL_STDLIB_H
+#define _GL_STDLIB_H
+
+
+/* The definition of GL_LINK_WARNING is copied here. */
+
+
+/* Some systems do not define EXIT_*, despite otherwise supporting C89. */
+#ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+#endif
+/* Tandem/NSK and other platforms that define EXIT_FAILURE as -1 interfere
+ with proper operation of xargs. */
+#ifndef EXIT_FAILURE
+# define EXIT_FAILURE 1
+#elif EXIT_FAILURE != 1
+# undef EXIT_FAILURE
+# define EXIT_FAILURE 1
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if @GNULIB_GETSUBOPT@
+/* Assuming *OPTIONP is a comma separated list of elements of the form
+ "token" or "token=value", getsubopt parses the first of these elements.
+ If the first element refers to a "token" that is member of the given
+ NULL-terminated array of tokens:
+ - It replaces the comma with a NUL byte, updates *OPTIONP to point past
+ the first option and the comma, sets *VALUEP to the value of the
+ element (or NULL if it doesn't contain an "=" sign),
+ - It returns the index of the "token" in the given array of tokens.
+ Otherwise it returns -1, and *OPTIONP and *VALUEP are undefined.
+ For more details see the POSIX:2001 specification.
+ http://www.opengroup.org/susv3xsh/getsubopt.html */
+# if !@HAVE_GETSUBOPT@
+extern int getsubopt (char **optionp, char *const *tokens, char **valuep);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef getsubopt
+# define getsubopt(o,t,v) \
+ (GL_LINK_WARNING ("getsubopt is unportable - " \
+ "use gnulib module getsubopt for portability"), \
+ getsubopt (o, t, v))
+#endif
+
+
+#if @GNULIB_MKDTEMP@
+# if !@HAVE_MKDTEMP@
+/* Create a unique temporary directory from TEMPLATE.
+ The last six characters of TEMPLATE must be "XXXXXX";
+ they are replaced with a string that makes the directory name unique.
+ Returns TEMPLATE, or a null pointer if it cannot get a unique name.
+ The directory is created mode 700. */
+extern char * mkdtemp (char * /*template*/);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef mkdtemp
+# define mkdtemp(t) \
+ (GL_LINK_WARNING ("mkdtemp is unportable - " \
+ "use gnulib module mkdtemp for portability"), \
+ mkdtemp (t))
+#endif
+
+
+#if @GNULIB_MKSTEMP@
+# if @REPLACE_MKSTEMP@
+/* Create a unique temporary file from TEMPLATE.
+ The last six characters of TEMPLATE must be "XXXXXX";
+ they are replaced with a string that makes the file name unique.
+ The file is then created, ensuring it didn't exist before.
+ The file is created read-write (mask at least 0600 & ~umask), but it may be
+ world-readable and world-writable (mask 0666 & ~umask), depending on the
+ implementation.
+ Returns the open file descriptor if successful, otherwise -1 and errno
+ set. */
+# define mkstemp rpl_mkstemp
+extern int mkstemp (char * /*template*/);
+# else
+/* On MacOS X 10.3, only <unistd.h> declares mkstemp. */
+# include <unistd.h>
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef mkstemp
+# define mkstemp(t) \
+ (GL_LINK_WARNING ("mkstemp is unportable - " \
+ "use gnulib module mkstemp for portability"), \
+ mkstemp (t))
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GL_STDLIB_H */
+#endif /* _GL_STDLIB_H */
+#endif
diff --git a/lib/stpcpy.c b/lib/stpcpy.c
new file mode 100644
index 0000000..4089d39
--- /dev/null
+++ b/lib/stpcpy.c
@@ -0,0 +1,49 @@
+/* stpcpy.c -- copy a string and return pointer to end of new string
+ Copyright (C) 1992, 1995, 1997-1998, 2006 Free Software Foundation, Inc.
+
+ NOTE: The canonical source of this file is maintained with the GNU C Library.
+ Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+#include <string.h>
+
+#undef __stpcpy
+#ifdef _LIBC
+# undef stpcpy
+#endif
+
+#ifndef weak_alias
+# define __stpcpy stpcpy
+#endif
+
+/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */
+char *
+__stpcpy (char *dest, const char *src)
+{
+ register char *d = dest;
+ register const char *s = src;
+
+ do
+ *d++ = *s;
+ while (*s++ != '\0');
+
+ return d - 1;
+}
+#ifdef weak_alias
+weak_alias (__stpcpy, stpcpy)
+#endif
diff --git a/lib/strcasecmp.c b/lib/strcasecmp.c
new file mode 100644
index 0000000..c605fb0
--- /dev/null
+++ b/lib/strcasecmp.c
@@ -0,0 +1,63 @@
+/* Case-insensitive string comparison function.
+ Copyright (C) 1998-1999, 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. */
+
+#include <config.h>
+
+/* Specification. */
+#include <string.h>
+
+#include <ctype.h>
+#include <limits.h>
+
+#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
+
+/* Compare strings S1 and S2, ignoring case, returning less than, equal to or
+ greater than zero if S1 is lexicographically less than, equal to or greater
+ than S2.
+ Note: This function does not work with multibyte strings! */
+
+int
+strcasecmp (const char *s1, const char *s2)
+{
+ const unsigned char *p1 = (const unsigned char *) s1;
+ const unsigned char *p2 = (const unsigned char *) s2;
+ unsigned char c1, c2;
+
+ if (p1 == p2)
+ return 0;
+
+ do
+ {
+ c1 = TOLOWER (*p1);
+ c2 = TOLOWER (*p2);
+
+ if (c1 == '\0')
+ break;
+
+ ++p1;
+ ++p2;
+ }
+ while (c1 == c2);
+
+ if (UCHAR_MAX <= INT_MAX)
+ return c1 - c2;
+ else
+ /* On machines where 'char' and 'int' are types of the same size, the
+ difference of two 'unsigned char' values - including the sign bit -
+ doesn't fit in an 'int'. */
+ return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+}
diff --git a/lib/strchrnul.c b/lib/strchrnul.c
new file mode 100644
index 0000000..07014be
--- /dev/null
+++ b/lib/strchrnul.c
@@ -0,0 +1,32 @@
+/* Searching in a string.
+ Copyright (C) 2003, 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>
+
+/* Specification. */
+#include <string.h>
+
+/* Find the first occurrence of C in S or the final NUL byte. */
+char *
+strchrnul (const char *s, int c_in)
+{
+ char c = c_in;
+ while (*s && (*s != c))
+ s++;
+
+ return (char *) s;
+}
diff --git a/lib/strdup.c b/lib/strdup.c
new file mode 100644
index 0000000..c614108
--- /dev/null
+++ b/lib/strdup.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 1991, 1996, 1997, 1998, 2002, 2003, 2004, 2006, 2007 Free
+ Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+/* Get specification. */
+#include <string.h>
+
+#include <stdlib.h>
+
+#undef __strdup
+#ifdef _LIBC
+# undef strdup
+#endif
+
+#ifndef weak_alias
+# define __strdup strdup
+#endif
+
+/* Duplicate S, returning an identical malloc'd string. */
+char *
+__strdup (const char *s)
+{
+ size_t len = strlen (s) + 1;
+ void *new = malloc (len);
+
+ if (new == NULL)
+ return NULL;
+
+ return (char *) memcpy (new, s, len);
+}
+#ifdef libc_hidden_def
+libc_hidden_def (__strdup)
+#endif
+#ifdef weak_alias
+weak_alias (__strdup, strdup)
+#endif
diff --git a/lib/strerror.c b/lib/strerror.c
new file mode 100644
index 0000000..54b851b
--- /dev/null
+++ b/lib/strerror.c
@@ -0,0 +1,57 @@
+/* strerror.c --- ANSI C compatible system error routine
+
+ Copyright (C) 1986, 1988, 1989, 1991, 2002, 2003, 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>
+
+#if !HAVE_STRERROR
+
+#include <limits.h>
+
+/* Don't include <stdio.h>, since it may or may not declare
+ sys_errlist and its declarations may collide with ours. Just
+ declare the stuff that we need directly. Standard hosted C89
+ implementations define strerror and they don't need this strerror
+ function, so take some liberties with the standard to cater to
+ ancient or limited freestanding implementations. */
+int sprintf (char *, char const *, ...);
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+char *
+strerror (int n)
+{
+ static char const fmt[] = "Unknown error (%d)";
+ static char mesg[sizeof fmt + sizeof n * CHAR_BIT / 3];
+
+ if (n < 0 || n >= sys_nerr)
+ {
+ sprintf (mesg, fmt, n);
+ return mesg;
+ }
+ else
+ return sys_errlist[n];
+}
+
+#else
+
+/* This declaration is solely to ensure that after preprocessing
+ this file is never empty. */
+typedef int dummy;
+
+#endif
diff --git a/lib/string_.h b/lib/string_.h
new file mode 100644
index 0000000..6ec72c3
--- /dev/null
+++ b/lib/string_.h
@@ -0,0 +1,546 @@
+/* A GNU-like <string.h>.
+
+ Copyright (C) 1995-1996, 2001-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. */
+
+#ifndef _GL_STRING_H
+
+/* The include_next requires a split double-inclusion guard. */
+#if @HAVE_INCLUDE_NEXT@
+# include_next <string.h>
+#else
+# include @ABSOLUTE_STRING_H@
+#endif
+
+#ifndef _GL_STRING_H
+#define _GL_STRING_H
+
+
+/* The definition of GL_LINK_WARNING is copied here. */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Return the first occurrence of NEEDLE in HAYSTACK. */
+#if @GNULIB_MEMMEM@
+# if ! @HAVE_DECL_MEMMEM@
+extern void *memmem (void const *__haystack, size_t __haystack_len,
+ void const *__needle, size_t __needle_len);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef memmem
+# define memmem(a,al,b,bl) \
+ (GL_LINK_WARNING ("memmem is unportable - " \
+ "use gnulib module memmem for portability"), \
+ memmem (a, al, b, bl))
+#endif
+
+/* Copy N bytes of SRC to DEST, return pointer to bytes after the
+ last written byte. */
+#if @GNULIB_MEMPCPY@
+# if ! @HAVE_MEMPCPY@
+extern void *mempcpy (void *restrict __dest, void const *restrict __src,
+ size_t __n);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef mempcpy
+# define mempcpy(a,b,n) \
+ (GL_LINK_WARNING ("mempcpy is unportable - " \
+ "use gnulib module mempcpy for portability"), \
+ mempcpy (a, b, n))
+#endif
+
+/* Search backwards through a block for a byte (specified as an int). */
+#if @GNULIB_MEMRCHR@
+# if ! @HAVE_DECL_MEMRCHR@
+extern void *memrchr (void const *, int, size_t);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef memrchr
+# define memrchr(a,b,c) \
+ (GL_LINK_WARNING ("memrchr is unportable - " \
+ "use gnulib module memrchr for portability"), \
+ memrchr (a, b, c))
+#endif
+
+/* Copy SRC to DST, returning the address of the terminating '\0' in DST. */
+#if @GNULIB_STPCPY@
+# if ! @HAVE_STPCPY@
+extern char *stpcpy (char *restrict __dst, char const *restrict __src);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef stpcpy
+# define stpcpy(a,b) \
+ (GL_LINK_WARNING ("stpcpy is unportable - " \
+ "use gnulib module stpcpy for portability"), \
+ stpcpy (a, b))
+#endif
+
+/* Copy no more than N bytes of SRC to DST, returning a pointer past the
+ last non-NUL byte written into DST. */
+#if @GNULIB_STPNCPY@
+# if ! @HAVE_STPNCPY@
+# define stpncpy gnu_stpncpy
+extern char *stpncpy (char *restrict __dst, char const *restrict __src,
+ size_t __n);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef stpncpy
+# define stpncpy(a,b,n) \
+ (GL_LINK_WARNING ("stpncpy is unportable - " \
+ "use gnulib module stpncpy for portability"), \
+ stpncpy (a, b, n))
+#endif
+
+/* Compare strings S1 and S2, ignoring case, returning less than, equal to or
+ greater than zero if S1 is lexicographically less than, equal to or greater
+ than S2.
+ Note: This function does not work in multibyte locales. */
+#if ! @HAVE_STRCASECMP@
+extern int strcasecmp (char const *s1, char const *s2);
+#endif
+#if defined GNULIB_POSIXCHECK
+/* strcasecmp() does not work with multibyte strings:
+ POSIX says that it operates on "strings", and "string" in POSIX is defined
+ as a sequence of bytes, not of characters. */
+# undef strcasecmp
+# define strcasecmp(a,b) \
+ (GL_LINK_WARNING ("strcasecmp cannot work correctly on character strings " \
+ "in multibyte locales - " \
+ "use mbscasecmp if you care about " \
+ "internationalization, or use c_strcasecmp (from " \
+ "gnulib module c-strcase) if you want a locale " \
+ "independent function"), \
+ strcasecmp (a, b))
+#endif
+
+/* Compare no more than N bytes of strings S1 and S2, ignoring case,
+ returning less than, equal to or greater than zero if S1 is
+ lexicographically less than, equal to or greater than S2.
+ Note: This function cannot work correctly in multibyte locales. */
+#if ! @HAVE_DECL_STRNCASECMP@
+extern int strncasecmp (char const *s1, char const *s2, size_t n);
+#endif
+#if defined GNULIB_POSIXCHECK
+/* strncasecmp() does not work with multibyte strings:
+ POSIX says that it operates on "strings", and "string" in POSIX is defined
+ as a sequence of bytes, not of characters. */
+# undef strncasecmp
+# define strncasecmp(a,b,n) \
+ (GL_LINK_WARNING ("strncasecmp cannot work correctly on character " \
+ "strings in multibyte locales - " \
+ "use mbsncasecmp or mbspcasecmp if you care about " \
+ "internationalization, or use c_strncasecmp (from " \
+ "gnulib module c-strcase) if you want a locale " \
+ "independent function"), \
+ strncasecmp (a, b, n))
+#endif
+
+#if defined GNULIB_POSIXCHECK
+/* strchr() does not work with multibyte strings if the locale encoding is
+ GB18030 and the character to be searched is a digit. */
+# undef strchr
+# define strchr(s,c) \
+ (GL_LINK_WARNING ("strchr cannot work correctly on character strings " \
+ "in some multibyte locales - " \
+ "use mbschr if you care about internationalization"), \
+ strchr (s, c))
+#endif
+
+/* Find the first occurrence of C in S or the final NUL byte. */
+#if @GNULIB_STRCHRNUL@
+# if ! @HAVE_STRCHRNUL@
+extern char *strchrnul (char const *__s, int __c_in);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef strchrnul
+# define strchrnul(a,b) \
+ (GL_LINK_WARNING ("strchrnul is unportable - " \
+ "use gnulib module strchrnul for portability"), \
+ strchrnul (a, b))
+#endif
+
+/* Duplicate S, returning an identical malloc'd string. */
+#if @GNULIB_STRDUP@
+# if ! @HAVE_DECL_STRDUP@ && ! defined strdup
+extern char *strdup (char const *__s);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef strdup
+# define strdup(a) \
+ (GL_LINK_WARNING ("strdup is unportable - " \
+ "use gnulib module strdup for portability"), \
+ strdup (a))
+#endif
+
+/* Return a newly allocated copy of at most N bytes of STRING. */
+#if @GNULIB_STRNDUP@
+# if ! @HAVE_STRNDUP@
+# undef strndup
+# define strndup rpl_strndup
+# endif
+# if ! @HAVE_STRNDUP@ || ! @HAVE_DECL_STRNDUP@
+extern char *strndup (char const *__string, size_t __n);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef strndup
+# define strndup(a,n) \
+ (GL_LINK_WARNING ("strndup is unportable - " \
+ "use gnulib module strndup for portability"), \
+ strndup (a, n))
+#endif
+
+/* Find the length (number of bytes) of STRING, but scan at most
+ MAXLEN bytes. If no '\0' terminator is found in that many bytes,
+ return MAXLEN. */
+#if @GNULIB_STRNLEN@
+# if ! @HAVE_DECL_STRNLEN@
+extern size_t strnlen (char const *__string, size_t __maxlen);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef strnlen
+# define strnlen(a,n) \
+ (GL_LINK_WARNING ("strnlen is unportable - " \
+ "use gnulib module strnlen for portability"), \
+ strnlen (a, n))
+#endif
+
+#if defined GNULIB_POSIXCHECK
+/* strcspn() assumes the second argument is a list of single-byte characters.
+ Even in this simple case, it does not work with multibyte strings if the
+ locale encoding is GB18030 and one of the characters to be searched is a
+ digit. */
+# undef strcspn
+# define strcspn(s,a) \
+ (GL_LINK_WARNING ("strcspn cannot work correctly on character strings " \
+ "in multibyte locales - " \
+ "use mbscspn if you care about internationalization"), \
+ strcspn (s, a))
+#endif
+
+/* Find the first occurrence in S of any character in ACCEPT. */
+#if @GNULIB_STRPBRK@
+# if ! @HAVE_STRPBRK@
+extern char *strpbrk (char const *__s, char const *__accept);
+# endif
+# if defined GNULIB_POSIXCHECK
+/* strpbrk() assumes the second argument is a list of single-byte characters.
+ Even in this simple case, it does not work with multibyte strings if the
+ locale encoding is GB18030 and one of the characters to be searched is a
+ digit. */
+# undef strpbrk
+# define strpbrk(s,a) \
+ (GL_LINK_WARNING ("strpbrk cannot work correctly on character strings " \
+ "in multibyte locales - " \
+ "use mbspbrk if you care about internationalization"), \
+ strpbrk (s, a))
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef strpbrk
+# define strpbrk(s,a) \
+ (GL_LINK_WARNING ("strpbrk is unportable - " \
+ "use gnulib module strpbrk for portability"), \
+ strpbrk (s, a))
+#endif
+
+#if defined GNULIB_POSIXCHECK
+/* strspn() assumes the second argument is a list of single-byte characters.
+ Even in this simple case, it cannot work with multibyte strings. */
+# undef strspn
+# define strspn(s,a) \
+ (GL_LINK_WARNING ("strspn cannot work correctly on character strings " \
+ "in multibyte locales - " \
+ "use mbsspn if you care about internationalization"), \
+ strspn (s, a))
+#endif
+
+#if defined GNULIB_POSIXCHECK
+/* strrchr() does not work with multibyte strings if the locale encoding is
+ GB18030 and the character to be searched is a digit. */
+# undef strrchr
+# define strrchr(s,c) \
+ (GL_LINK_WARNING ("strrchr cannot work correctly on character strings " \
+ "in some multibyte locales - " \
+ "use mbsrchr if you care about internationalization"), \
+ strrchr (s, c))
+#endif
+
+/* Search the next delimiter (char listed in DELIM) starting at *STRINGP.
+ If one is found, overwrite it with a NUL, and advance *STRINGP
+ to point to the next char after it. Otherwise, set *STRINGP to NULL.
+ If *STRINGP was already NULL, nothing happens.
+ Return the old value of *STRINGP.
+
+ This is a variant of strtok() that is multithread-safe and supports
+ empty fields.
+
+ Caveat: It modifies the original string.
+ Caveat: These functions cannot be used on constant strings.
+ Caveat: The identity of the delimiting character is lost.
+ Caveat: It doesn't work with multibyte strings unless all of the delimiter
+ characters are ASCII characters < 0x30.
+
+ See also strtok_r(). */
+#if @GNULIB_STRSEP@
+# if ! @HAVE_STRSEP@
+extern char *strsep (char **restrict __stringp, char const *restrict __delim);
+# endif
+# if defined GNULIB_POSIXCHECK
+# undef strsep
+# define strsep(s,d) \
+ (GL_LINK_WARNING ("strsep cannot work correctly on character strings " \
+ "in multibyte locales - " \
+ "use mbssep if you care about internationalization"), \
+ strsep (s, d))
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef strsep
+# define strsep(s,d) \
+ (GL_LINK_WARNING ("strsep is unportable - " \
+ "use gnulib module strsep for portability"), \
+ strsep (s, d))
+#endif
+
+#if defined GNULIB_POSIXCHECK
+/* strstr() does not work with multibyte strings if the locale encoding is
+ different from UTF-8:
+ POSIX says that it operates on "strings", and "string" in POSIX is defined
+ as a sequence of bytes, not of characters. */
+# undef strstr
+# define strstr(a,b) \
+ (GL_LINK_WARNING ("strstr cannot work correctly on character strings " \
+ "in most multibyte locales - " \
+ "use mbsstr if you care about internationalization"), \
+ strstr (a, b))
+#endif
+
+/* Find the first occurrence of NEEDLE in HAYSTACK, using case-insensitive
+ comparison. */
+#if ! @HAVE_STRCASESTR@
+extern char *strcasestr (const char *haystack, const char *needle);
+#endif
+#if defined GNULIB_POSIXCHECK
+/* strcasestr() does not work with multibyte strings:
+ It is a glibc extension, and glibc implements it only for unibyte
+ locales. */
+# undef strcasestr
+# define strcasestr(a,b) \
+ (GL_LINK_WARNING ("strcasestr does work correctly on character strings " \
+ "in multibyte locales - " \
+ "use mbscasestr if you care about " \
+ "internationalization, or use c-strcasestr if you want " \
+ "a locale independent function"), \
+ strcasestr (a, b))
+#endif
+
+/* Parse S into tokens separated by characters in DELIM.
+ If S is NULL, the saved pointer in SAVE_PTR is used as
+ the next starting point. For example:
+ char s[] = "-abc-=-def";
+ char *sp;
+ x = strtok_r(s, "-", &sp); // x = "abc", sp = "=-def"
+ x = strtok_r(NULL, "-=", &sp); // x = "def", sp = NULL
+ x = strtok_r(NULL, "=", &sp); // x = NULL
+ // s = "abc\0-def\0"
+
+ This is a variant of strtok() that is multithread-safe.
+
+ For the POSIX documentation for this function, see:
+ http://www.opengroup.org/susv3xsh/strtok.html
+
+ Caveat: It modifies the original string.
+ Caveat: These functions cannot be used on constant strings.
+ Caveat: The identity of the delimiting character is lost.
+ Caveat: It doesn't work with multibyte strings unless all of the delimiter
+ characters are ASCII characters < 0x30.
+
+ See also strsep(). */
+#if @GNULIB_STRTOK_R@
+# if ! @HAVE_DECL_STRTOK_R@
+extern char *strtok_r (char *restrict s, char const *restrict delim,
+ char **restrict save_ptr);
+# endif
+# if defined GNULIB_POSIXCHECK
+# undef strtok_r
+# define strtok_r(s,d,p) \
+ (GL_LINK_WARNING ("strtok_r cannot work correctly on character strings " \
+ "in multibyte locales - " \
+ "use mbstok_r if you care about internationalization"), \
+ strtok_r (s, d, p))
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef strtok_r
+# define strtok_r(s,d,p) \
+ (GL_LINK_WARNING ("strtok_r is unportable - " \
+ "use gnulib module strtok_r for portability"), \
+ strtok_r (s, d, p))
+#endif
+
+
+/* The following functions are not specified by POSIX. They are gnulib
+ extensions. */
+
+#if @GNULIB_MBSLEN@
+/* Return the number of multibyte characters in the character string STRING.
+ This considers multibyte characters, unlike strlen, which counts bytes. */
+extern size_t mbslen (const char *string);
+#endif
+
+#if @GNULIB_MBSCHR@
+/* Locate the first single-byte character C in the character string STRING,
+ and return a pointer to it. Return NULL if C is not found in STRING.
+ Unlike strchr(), this function works correctly in multibyte locales with
+ encodings such as GB18030. */
+# define mbschr rpl_mbschr /* avoid collision with HP-UX function */
+extern char * mbschr (const char *string, int c);
+#endif
+
+#if @GNULIB_MBSRCHR@
+/* Locate the last single-byte character C in the character string STRING,
+ and return a pointer to it. Return NULL if C is not found in STRING.
+ Unlike strrchr(), this function works correctly in multibyte locales with
+ encodings such as GB18030. */
+# define mbsrchr rpl_mbsrchr /* avoid collision with HP-UX function */
+extern char * mbsrchr (const char *string, int c);
+#endif
+
+#if @GNULIB_MBSSTR@
+/* Find the first occurrence of the character string NEEDLE in the character
+ string HAYSTACK. Return NULL if NEEDLE is not found in HAYSTACK.
+ Unlike strstr(), this function works correctly in multibyte locales with
+ encodings different from UTF-8. */
+extern char * mbsstr (const char *haystack, const char *needle);
+#endif
+
+#if @GNULIB_MBSCASECMP@
+/* Compare the character strings S1 and S2, ignoring case, returning less than,
+ equal to or greater than zero if S1 is lexicographically less than, equal to
+ or greater than S2.
+ Note: This function may, in multibyte locales, return 0 for strings of
+ different lengths!
+ Unlike strcasecmp(), this function works correctly in multibyte locales. */
+extern int mbscasecmp (const char *s1, const char *s2);
+#endif
+
+#if @GNULIB_MBSNCASECMP@
+/* Compare the initial segment of the character string S1 consisting of at most
+ N characters with the initial segment of the character string S2 consisting
+ of at most N characters, ignoring case, returning less than, equal to or
+ greater than zero if the initial segment of S1 is lexicographically less
+ than, equal to or greater than the initial segment of S2.
+ Note: This function may, in multibyte locales, return 0 for initial segments
+ of different lengths!
+ Unlike strncasecmp(), this function works correctly in multibyte locales.
+ But beware that N is not a byte count but a character count! */
+extern int mbsncasecmp (const char *s1, const char *s2, size_t n);
+#endif
+
+#if @GNULIB_MBSPCASECMP@
+/* Compare the initial segment of the character string STRING consisting of
+ at most mbslen (PREFIX) characters with the character string PREFIX,
+ ignoring case, returning less than, equal to or greater than zero if this
+ initial segment is lexicographically less than, equal to or greater than
+ PREFIX.
+ Note: This function may, in multibyte locales, return 0 if STRING is of
+ smaller length than PREFIX!
+ Unlike strncasecmp(), this function works correctly in multibyte
+ locales. */
+extern char * mbspcasecmp (const char *string, const char *prefix);
+#endif
+
+#if @GNULIB_MBSCASESTR@
+/* Find the first occurrence of the character string NEEDLE in the character
+ string HAYSTACK, using case-insensitive comparison.
+ Note: This function may, in multibyte locales, return success even if
+ strlen (haystack) < strlen (needle) !
+ Unlike strcasestr(), this function works correctly in multibyte locales. */
+extern char * mbscasestr (const char *haystack, const char *needle);
+#endif
+
+#if @GNULIB_MBSCSPN@
+/* Find the first occurrence in the character string STRING of any character
+ in the character string ACCEPT. Return the number of bytes from the
+ beginning of the string to this occurrence, or to the end of the string
+ if none exists.
+ Unlike strcspn(), this function works correctly in multibyte locales. */
+extern size_t mbscspn (const char *string, const char *accept);
+#endif
+
+#if @GNULIB_MBSPBRK@
+/* Find the first occurrence in the character string STRING of any character
+ in the character string ACCEPT. Return the pointer to it, or NULL if none
+ exists.
+ Unlike strpbrk(), this function works correctly in multibyte locales. */
+# define mbspbrk rpl_mbspbrk /* avoid collision with HP-UX function */
+extern char * mbspbrk (const char *string, const char *accept);
+#endif
+
+#if @GNULIB_MBSSPN@
+/* Find the first occurrence in the character string STRING of any character
+ not in the character string REJECT. Return the number of bytes from the
+ beginning of the string to this occurrence, or to the end of the string
+ if none exists.
+ Unlike strspn(), this function works correctly in multibyte locales. */
+extern size_t mbsspn (const char *string, const char *reject);
+#endif
+
+#if @GNULIB_MBSSEP@
+/* Search the next delimiter (multibyte character listed in the character
+ string DELIM) starting at the character string *STRINGP.
+ If one is found, overwrite it with a NUL, and advance *STRINGP to point
+ to the next multibyte character after it. Otherwise, set *STRINGP to NULL.
+ If *STRINGP was already NULL, nothing happens.
+ Return the old value of *STRINGP.
+
+ This is a variant of mbstok_r() that supports empty fields.
+
+ Caveat: It modifies the original string.
+ Caveat: These functions cannot be used on constant strings.
+ Caveat: The identity of the delimiting character is lost.
+
+ See also mbstok_r(). */
+extern char * mbssep (char **stringp, const char *delim);
+#endif
+
+#if @GNULIB_MBSTOK_R@
+/* Parse the character string STRING into tokens separated by characters in
+ the character string DELIM.
+ If STRING is NULL, the saved pointer in SAVE_PTR is used as
+ the next starting point. For example:
+ char s[] = "-abc-=-def";
+ char *sp;
+ x = mbstok_r(s, "-", &sp); // x = "abc", sp = "=-def"
+ x = mbstok_r(NULL, "-=", &sp); // x = "def", sp = NULL
+ x = mbstok_r(NULL, "=", &sp); // x = NULL
+ // s = "abc\0-def\0"
+
+ Caveat: It modifies the original string.
+ Caveat: These functions cannot be used on constant strings.
+ Caveat: The identity of the delimiting character is lost.
+
+ See also mbssep(). */
+extern char * mbstok_r (char *string, const char *delim, char **save_ptr);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GL_STRING_H */
+#endif /* _GL_STRING_H */
diff --git a/lib/stripslash.c b/lib/stripslash.c
new file mode 100644
index 0000000..342d497
--- /dev/null
+++ b/lib/stripslash.c
@@ -0,0 +1,45 @@
+/* stripslash.c -- remove redundant trailing slashes from a file name
+
+ Copyright (C) 1990, 2001, 2003-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. */
+
+#include <config.h>
+
+#include "dirname.h"
+
+/* Remove trailing slashes from FILE. Return true if a trailing slash
+ was removed. This is useful when using file name completion from a
+ shell that adds a "/" after directory names (such as tcsh and
+ bash), because on symlinks to directories, several system calls
+ have different semantics according to whether a trailing slash is
+ present. */
+
+bool
+strip_trailing_slashes (char *file)
+{
+ char *base = last_component (file);
+ char *base_lim;
+ bool had_slash;
+
+ /* last_component returns "" for file system roots, but we need to turn
+ `///' into `/'. */
+ if (! *base)
+ base = file;
+ base_lim = base + base_len (base);
+ had_slash = (*base_lim != '\0');
+ *base_lim = '\0';
+ return had_slash;
+}
diff --git a/lib/strncasecmp.c b/lib/strncasecmp.c
new file mode 100644
index 0000000..473a610
--- /dev/null
+++ b/lib/strncasecmp.c
@@ -0,0 +1,63 @@
+/* strncasecmp.c -- case insensitive string comparator
+ Copyright (C) 1998-1999, 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. */
+
+#include <config.h>
+
+/* Specification. */
+#include <string.h>
+
+#include <ctype.h>
+#include <limits.h>
+
+#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
+
+/* Compare no more than N bytes of strings S1 and S2, ignoring case,
+ returning less than, equal to or greater than zero if S1 is
+ lexicographically less than, equal to or greater than S2.
+ Note: This function cannot work correctly in multibyte locales. */
+
+int
+strncasecmp (const char *s1, const char *s2, size_t n)
+{
+ register const unsigned char *p1 = (const unsigned char *) s1;
+ register const unsigned char *p2 = (const unsigned char *) s2;
+ unsigned char c1, c2;
+
+ if (p1 == p2 || n == 0)
+ return 0;
+
+ do
+ {
+ c1 = TOLOWER (*p1);
+ c2 = TOLOWER (*p2);
+
+ if (--n == 0 || c1 == '\0')
+ break;
+
+ ++p1;
+ ++p2;
+ }
+ while (c1 == c2);
+
+ if (UCHAR_MAX <= INT_MAX)
+ return c1 - c2;
+ else
+ /* On machines where 'char' and 'int' are types of the same size, the
+ difference of two 'unsigned char' values - including the sign bit -
+ doesn't fit in an 'int'. */
+ return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+}
diff --git a/lib/strndup.c b/lib/strndup.c
new file mode 100644
index 0000000..3a1b0ea
--- /dev/null
+++ b/lib/strndup.c
@@ -0,0 +1,37 @@
+/* A replacement function, for systems that lack strndup.
+
+ Copyright (C) 1996, 1997, 1998, 2001, 2002, 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>
+
+#include <string.h>
+
+#include <stdlib.h>
+
+char *
+strndup (char const *s, size_t n)
+{
+ size_t len = strnlen (s, n);
+ char *new = malloc (len + 1);
+
+ if (new == NULL)
+ return NULL;
+
+ new[len] = '\0';
+ return memcpy (new, s, len);
+}
diff --git a/lib/strnlen.c b/lib/strnlen.c
new file mode 100644
index 0000000..d346d32
--- /dev/null
+++ b/lib/strnlen.c
@@ -0,0 +1,31 @@
+/* Find the length of STRING, but scan at most MAXLEN characters.
+ Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+ Written by Simon Josefsson.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+#include <string.h>
+
+/* Find the length of STRING, but scan at most MAXLEN characters.
+ If no '\0' terminator is found in that many characters, return MAXLEN. */
+
+size_t
+strnlen (const char *string, size_t maxlen)
+{
+ const char *end = memchr (string, '\0', maxlen);
+ return end ? (size_t) (end - string) : maxlen;
+}
diff --git a/lib/strtol.c b/lib/strtol.c
new file mode 100644
index 0000000..e14d3cf
--- /dev/null
+++ b/lib/strtol.c
@@ -0,0 +1,436 @@
+/* Convert string representation of a number into an integer value.
+
+ Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2003, 2005,
+ 2006, 2007
+ Free Software Foundation, Inc.
+
+ NOTE: The canonical source of this file is maintained with the GNU C
+ Library. Bugs can be reported to bug-glibc@gnu.org.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef _LIBC
+# define USE_NUMBER_GROUPING
+#else
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#ifndef __set_errno
+# define __set_errno(Val) errno = (Val)
+#endif
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef USE_NUMBER_GROUPING
+# include "../locale/localeinfo.h"
+#endif
+
+/* Nonzero if we are defining `strtoul' or `strtoull', operating on
+ unsigned integers. */
+#ifndef UNSIGNED
+# define UNSIGNED 0
+# define INT LONG int
+#else
+# define INT unsigned LONG int
+#endif
+
+/* Determine the name. */
+#ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# if UNSIGNED
+# ifdef USE_WIDE_CHAR
+# ifdef QUAD
+# define strtol __wcstoull_l
+# else
+# define strtol __wcstoul_l
+# endif
+# else
+# ifdef QUAD
+# define strtol __strtoull_l
+# else
+# define strtol __strtoul_l
+# endif
+# endif
+# else
+# ifdef USE_WIDE_CHAR
+# ifdef QUAD
+# define strtol __wcstoll_l
+# else
+# define strtol __wcstol_l
+# endif
+# else
+# ifdef QUAD
+# define strtol __strtoll_l
+# else
+# define strtol __strtol_l
+# endif
+# endif
+# endif
+#else
+# if UNSIGNED
+# ifdef USE_WIDE_CHAR
+# ifdef QUAD
+# define strtol wcstoull
+# else
+# define strtol wcstoul
+# endif
+# else
+# ifdef QUAD
+# define strtol strtoull
+# else
+# define strtol strtoul
+# endif
+# endif
+# else
+# ifdef USE_WIDE_CHAR
+# ifdef QUAD
+# define strtol wcstoll
+# else
+# define strtol wcstol
+# endif
+# else
+# ifdef QUAD
+# define strtol strtoll
+# endif
+# endif
+# endif
+#endif
+
+/* If QUAD is defined, we are defining `strtoll' or `strtoull',
+ operating on `long long int's. */
+#ifdef QUAD
+# define LONG long long
+# define STRTOL_LONG_MIN LONG_LONG_MIN
+# define STRTOL_LONG_MAX LONG_LONG_MAX
+# define STRTOL_ULONG_MAX ULONG_LONG_MAX
+
+/* The extra casts in the following macros work around compiler bugs,
+ e.g., in Cray C 5.0.3.0. */
+
+/* True if negative values of the signed integer type T use two's
+ complement, ones' complement, or signed magnitude representation,
+ respectively. Much GNU code assumes two's complement, but some
+ people like to be portable to all possible C hosts. */
+# define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
+# define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0)
+# define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1)
+
+/* True if the arithmetic type T is signed. */
+# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+
+/* The maximum and minimum values for the integer type T. These
+ macros have undefined behavior if T is signed and has padding bits.
+ If this is a problem for you, please let us know how to fix it for
+ your host. */
+# define TYPE_MINIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) 0 \
+ : TYPE_SIGNED_MAGNITUDE (t) \
+ ? ~ (t) 0 \
+ : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))
+# define TYPE_MAXIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) -1 \
+ : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
+
+# ifndef ULONG_LONG_MAX
+# define ULONG_LONG_MAX TYPE_MAXIMUM (unsigned long long)
+# endif
+# ifndef LONG_LONG_MAX
+# define LONG_LONG_MAX TYPE_MAXIMUM (long long int)
+# endif
+# ifndef LONG_LONG_MIN
+# define LONG_LONG_MIN TYPE_MINIMUM (long long int)
+# endif
+
+# if __GNUC__ == 2 && __GNUC_MINOR__ < 7
+ /* Work around gcc bug with using this constant. */
+ static const unsigned long long int maxquad = ULONG_LONG_MAX;
+# undef STRTOL_ULONG_MAX
+# define STRTOL_ULONG_MAX maxquad
+# endif
+#else
+# define LONG long
+# define STRTOL_LONG_MIN LONG_MIN
+# define STRTOL_LONG_MAX LONG_MAX
+# define STRTOL_ULONG_MAX ULONG_MAX
+#endif
+
+
+/* We use this code also for the extended locale handling where the
+ function gets as an additional argument the locale which has to be
+ used. To access the values we have to redefine the _NL_CURRENT
+ macro. */
+#ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# undef _NL_CURRENT
+# define _NL_CURRENT(category, item) \
+ (current->values[_NL_ITEM_INDEX (item)].string)
+# define LOCALE_PARAM , loc
+# define LOCALE_PARAM_PROTO , __locale_t loc
+#else
+# define LOCALE_PARAM
+# define LOCALE_PARAM_PROTO
+#endif
+
+#include <wchar.h>
+
+#ifdef USE_WIDE_CHAR
+# include <wctype.h>
+# define L_(Ch) L##Ch
+# define UCHAR_TYPE wint_t
+# define STRING_TYPE wchar_t
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# define ISSPACE(Ch) __iswspace_l ((Ch), loc)
+# define ISALPHA(Ch) __iswalpha_l ((Ch), loc)
+# define TOUPPER(Ch) __towupper_l ((Ch), loc)
+# else
+# define ISSPACE(Ch) iswspace (Ch)
+# define ISALPHA(Ch) iswalpha (Ch)
+# define TOUPPER(Ch) towupper (Ch)
+# endif
+#else
+# define L_(Ch) Ch
+# define UCHAR_TYPE unsigned char
+# define STRING_TYPE char
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+# define ISSPACE(Ch) __isspace_l ((Ch), loc)
+# define ISALPHA(Ch) __isalpha_l ((Ch), loc)
+# define TOUPPER(Ch) __toupper_l ((Ch), loc)
+# else
+# define ISSPACE(Ch) isspace (Ch)
+# define ISALPHA(Ch) isalpha (Ch)
+# define TOUPPER(Ch) toupper (Ch)
+# endif
+#endif
+
+#define INTERNAL(X) INTERNAL1(X)
+#define INTERNAL1(X) __##X##_internal
+#define WEAKNAME(X) WEAKNAME1(X)
+
+#ifdef USE_NUMBER_GROUPING
+/* This file defines a function to check for correct grouping. */
+# include "grouping.h"
+#endif
+
+
+
+/* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
+ If BASE is 0 the base is determined by the presence of a leading
+ zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
+ If BASE is < 2 or > 36, it is reset to 10.
+ If ENDPTR is not NULL, a pointer to the character after the last
+ one converted is stored in *ENDPTR. */
+
+INT
+INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
+ int base, int group LOCALE_PARAM_PROTO)
+{
+ int negative;
+ register unsigned LONG int cutoff;
+ register unsigned int cutlim;
+ register unsigned LONG int i;
+ register const STRING_TYPE *s;
+ register UCHAR_TYPE c;
+ const STRING_TYPE *save, *end;
+ int overflow;
+
+#ifdef USE_NUMBER_GROUPING
+# ifdef USE_IN_EXTENDED_LOCALE_MODEL
+ struct locale_data *current = loc->__locales[LC_NUMERIC];
+# endif
+ /* The thousands character of the current locale. */
+ wchar_t thousands = L'\0';
+ /* The numeric grouping specification of the current locale,
+ in the format described in <locale.h>. */
+ const char *grouping;
+
+ if (group)
+ {
+ grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
+ if (*grouping <= 0 || *grouping == CHAR_MAX)
+ grouping = NULL;
+ else
+ {
+ /* Figure out the thousands separator character. */
+# if defined _LIBC || defined _HAVE_BTOWC
+ thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP));
+ if (thousands == WEOF)
+ thousands = L'\0';
+# endif
+ if (thousands == L'\0')
+ grouping = NULL;
+ }
+ }
+ else
+ grouping = NULL;
+#endif
+
+ if (base < 0 || base == 1 || base > 36)
+ {
+ __set_errno (EINVAL);
+ return 0;
+ }
+
+ save = s = nptr;
+
+ /* Skip white space. */
+ while (ISSPACE (*s))
+ ++s;
+ if (*s == L_('\0'))
+ goto noconv;
+
+ /* Check for a sign. */
+ if (*s == L_('-'))
+ {
+ negative = 1;
+ ++s;
+ }
+ else if (*s == L_('+'))
+ {
+ negative = 0;
+ ++s;
+ }
+ else
+ negative = 0;
+
+ /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
+ if (*s == L_('0'))
+ {
+ if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X'))
+ {
+ s += 2;
+ base = 16;
+ }
+ else if (base == 0)
+ base = 8;
+ }
+ else if (base == 0)
+ base = 10;
+
+ /* Save the pointer so we can check later if anything happened. */
+ save = s;
+
+#ifdef USE_NUMBER_GROUPING
+ if (group)
+ {
+ /* Find the end of the digit string and check its grouping. */
+ end = s;
+ for (c = *end; c != L_('\0'); c = *++end)
+ if ((wchar_t) c != thousands
+ && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9'))
+ && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base))
+ break;
+ if (*s == thousands)
+ end = s;
+ else
+ end = correctly_grouped_prefix (s, end, thousands, grouping);
+ }
+ else
+#endif
+ end = NULL;
+
+ cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base;
+ cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base;
+
+ overflow = 0;
+ i = 0;
+ for (c = *s; c != L_('\0'); c = *++s)
+ {
+ if (s == end)
+ break;
+ if (c >= L_('0') && c <= L_('9'))
+ c -= L_('0');
+ else if (ISALPHA (c))
+ c = TOUPPER (c) - L_('A') + 10;
+ else
+ break;
+ if ((int) c >= base)
+ break;
+ /* Check for overflow. */
+ if (i > cutoff || (i == cutoff && c > cutlim))
+ overflow = 1;
+ else
+ {
+ i *= (unsigned LONG int) base;
+ i += c;
+ }
+ }
+
+ /* Check if anything actually happened. */
+ if (s == save)
+ goto noconv;
+
+ /* Store in ENDPTR the address of one character
+ past the last character we converted. */
+ if (endptr != NULL)
+ *endptr = (STRING_TYPE *) s;
+
+#if !UNSIGNED
+ /* Check for a value that is within the range of
+ `unsigned LONG int', but outside the range of `LONG int'. */
+ if (overflow == 0
+ && i > (negative
+ ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1
+ : (unsigned LONG int) STRTOL_LONG_MAX))
+ overflow = 1;
+#endif
+
+ if (overflow)
+ {
+ __set_errno (ERANGE);
+#if UNSIGNED
+ return STRTOL_ULONG_MAX;
+#else
+ return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;
+#endif
+ }
+
+ /* Return the result of the appropriate sign. */
+ return negative ? -i : i;
+
+noconv:
+ /* We must handle a special case here: the base is 0 or 16 and the
+ first two characters are '0' and 'x', but the rest are no
+ hexadecimal digits. This is no error case. We return 0 and
+ ENDPTR points to the `x`. */
+ if (endptr != NULL)
+ {
+ if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
+ && save[-2] == L_('0'))
+ *endptr = (STRING_TYPE *) &save[-1];
+ else
+ /* There was no number to convert. */
+ *endptr = (STRING_TYPE *) nptr;
+ }
+
+ return 0L;
+}
+
+/* External user entry point. */
+
+
+INT
+#ifdef weak_function
+weak_function
+#endif
+strtol (const STRING_TYPE *nptr, STRING_TYPE **endptr,
+ int base LOCALE_PARAM_PROTO)
+{
+ return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM);
+}
diff --git a/lib/sys_stat_.h b/lib/sys_stat_.h
new file mode 100644
index 0000000..13333d3
--- /dev/null
+++ b/lib/sys_stat_.h
@@ -0,0 +1,284 @@
+/* Provide a more complete sys/stat header file.
+ Copyright (C) 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. */
+
+/* Written by Eric Blake, Paul Eggert, and Jim Meyering. */
+
+/* This file is supposed to be used on platforms where <sys/stat.h> is
+ incomplete. It is intended to provide definitions and prototypes
+ needed by an application. Start with what the system provides. */
+
+#ifndef _GL_SYS_STAT_H
+
+/* The include_next requires a split double-inclusion guard. */
+#if @HAVE_INCLUDE_NEXT@
+# include_next <sys/stat.h>
+#else
+# include @ABSOLUTE_SYS_STAT_H@
+#endif
+
+#ifndef _GL_SYS_STAT_H
+#define _GL_SYS_STAT_H
+
+#ifndef S_IFMT
+# define S_IFMT 0170000
+#endif
+
+#if STAT_MACROS_BROKEN
+# undef S_ISBLK
+# undef S_ISCHR
+# undef S_ISDIR
+# undef S_ISFIFO
+# undef S_ISLNK
+# undef S_ISNAM
+# undef S_ISMPB
+# undef S_ISMPC
+# undef S_ISNWK
+# undef S_ISREG
+# undef S_ISSOCK
+#endif
+
+#ifndef S_ISBLK
+# ifdef S_IFBLK
+# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+# else
+# define S_ISBLK(m) 0
+# endif
+#endif
+
+#ifndef S_ISCHR
+# ifdef S_IFCHR
+# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+# else
+# define S_ISCHR(m) 0
+# endif
+#endif
+
+#ifndef S_ISDIR
+# ifdef S_IFDIR
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+# else
+# define S_ISDIR(m) 0
+# endif
+#endif
+
+#ifndef S_ISDOOR /* Solaris 2.5 and up */
+# define S_ISDOOR(m) 0
+#endif
+
+#ifndef S_ISFIFO
+# ifdef S_IFIFO
+# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+# else
+# define S_ISFIFO(m) 0
+# endif
+#endif
+
+#ifndef S_ISLNK
+# ifdef S_IFLNK
+# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+# else
+# define S_ISLNK(m) 0
+# endif
+#endif
+
+#ifndef S_ISMPB /* V7 */
+# ifdef S_IFMPB
+# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
+# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
+# else
+# define S_ISMPB(m) 0
+# define S_ISMPC(m) 0
+# endif
+#endif
+
+#ifndef S_ISNAM /* Xenix */
+# ifdef S_IFNAM
+# define S_ISNAM(m) (((m) & S_IFMT) == S_IFNAM)
+# else
+# define S_ISNAM(m) 0
+# endif
+#endif
+
+#ifndef S_ISNWK /* HP/UX */
+# ifdef S_IFNWK
+# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
+# else
+# define S_ISNWK(m) 0
+# endif
+#endif
+
+#ifndef S_ISPORT /* Solaris 10 and up */
+# define S_ISPORT(m) 0
+#endif
+
+#ifndef S_ISREG
+# ifdef S_IFREG
+# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+# else
+# define S_ISREG(m) 0
+# endif
+#endif
+
+#ifndef S_ISSOCK
+# ifdef S_IFSOCK
+# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+# else
+# define S_ISSOCK(m) 0
+# endif
+#endif
+
+
+#ifndef S_TYPEISMQ
+# define S_TYPEISMQ(p) 0
+#endif
+
+#ifndef S_TYPEISTMO
+# define S_TYPEISTMO(p) 0
+#endif
+
+
+#ifndef S_TYPEISSEM
+# ifdef S_INSEM
+# define S_TYPEISSEM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSEM)
+# else
+# define S_TYPEISSEM(p) 0
+# endif
+#endif
+
+#ifndef S_TYPEISSHM
+# ifdef S_INSHD
+# define S_TYPEISSHM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSHD)
+# else
+# define S_TYPEISSHM(p) 0
+# endif
+#endif
+
+/* high performance ("contiguous data") */
+#ifndef S_ISCTG
+# define S_ISCTG(p) 0
+#endif
+
+/* Cray DMF (data migration facility): off line, with data */
+#ifndef S_ISOFD
+# define S_ISOFD(p) 0
+#endif
+
+/* Cray DMF (data migration facility): off line, with no data */
+#ifndef S_ISOFL
+# define S_ISOFL(p) 0
+#endif
+
+/* 4.4BSD whiteout */
+#ifndef S_ISWHT
+# define S_ISWHT(m) 0
+#endif
+
+/* If any of the following are undefined,
+ define them to their de facto standard values. */
+#if !S_ISUID
+# define S_ISUID 04000
+#endif
+#if !S_ISGID
+# define S_ISGID 02000
+#endif
+
+/* S_ISVTX is a common extension to POSIX. */
+#ifndef S_ISVTX
+# define S_ISVTX 01000
+#endif
+
+#if !S_IRUSR && S_IREAD
+# define S_IRUSR S_IREAD
+#endif
+#if !S_IRUSR
+# define S_IRUSR 00400
+#endif
+#if !S_IRGRP
+# define S_IRGRP (S_IRUSR >> 3)
+#endif
+#if !S_IROTH
+# define S_IROTH (S_IRUSR >> 6)
+#endif
+
+#if !S_IWUSR && S_IWRITE
+# define S_IWUSR S_IWRITE
+#endif
+#if !S_IWUSR
+# define S_IWUSR 00200
+#endif
+#if !S_IWGRP
+# define S_IWGRP (S_IWUSR >> 3)
+#endif
+#if !S_IWOTH
+# define S_IWOTH (S_IWUSR >> 6)
+#endif
+
+#if !S_IXUSR && S_IEXEC
+# define S_IXUSR S_IEXEC
+#endif
+#if !S_IXUSR
+# define S_IXUSR 00100
+#endif
+#if !S_IXGRP
+# define S_IXGRP (S_IXUSR >> 3)
+#endif
+#if !S_IXOTH
+# define S_IXOTH (S_IXUSR >> 6)
+#endif
+
+#if !S_IRWXU
+# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR)
+#endif
+#if !S_IRWXG
+# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
+#endif
+#if !S_IRWXO
+# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
+#endif
+
+/* S_IXUGO is a common extension to POSIX. */
+#if !S_IXUGO
+# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
+#endif
+
+#ifndef S_IRWXUGO
+# define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO)
+#endif
+
+/* mingw does not support symlinks, therefore it does not have lstat. But
+ without links, stat does just fine. */
+#if ! @HAVE_LSTAT@
+# define lstat stat
+#endif
+
+/* mingw's _mkdir() function has 1 argument, but we pass 2 arguments.
+ Additionally, it declares _mkdir (and depending on compile flags, an
+ alias mkdir), only in the nonstandard io.h. */
+#if ! @HAVE_DECL_MKDIR@ && @HAVE_IO_H@
+# include <io.h>
+
+static inline int
+rpl_mkdir (char const *name, mode_t mode)
+{
+ return _mkdir (name);
+}
+
+# define mkdir rpl_mkdir
+#endif
+
+#endif /* _GL_SYS_STAT_H */
+#endif /* _GL_SYS_STAT_H */
diff --git a/lib/sys_time_.h b/lib/sys_time_.h
new file mode 100644
index 0000000..253316f
--- /dev/null
+++ b/lib/sys_time_.h
@@ -0,0 +1,52 @@
+/* Provide a more complete sys/time.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. */
+
+/* Written by Paul Eggert. */
+
+#ifndef _GL_SYS_TIME_H
+
+/* The include_next requires a split double-inclusion guard. */
+#if @HAVE_SYS_TIME_H@
+# if @HAVE_INCLUDE_NEXT@
+# include_next <sys/time.h>
+# else
+# include @ABSOLUTE_SYS_TIME_H@
+# endif
+#else
+# include <time.h>
+#endif
+
+#ifndef _GL_SYS_TIME_H
+#define _GL_SYS_TIME_H
+
+#if ! @HAVE_STRUCT_TIMEVAL@
+struct timeval
+{
+ time_t tv_sec;
+ long int tv_usec;
+};
+#endif
+
+#if @REPLACE_GETTIMEOFDAY@
+# undef gettimeofday
+# define gettimeofday rpl_gettimeofday
+int gettimeofday (struct timeval *restrict, void *restrict);
+#endif
+
+#endif /* _GL_SYS_TIME_H */
+#endif /* _GL_SYS_TIME_H */
diff --git a/lib/sysdep.c b/lib/sysdep.c
deleted file mode 100644
index 5da330a..0000000
--- a/lib/sysdep.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/* -*- buffer-read-only: t -*- vi: set ro:
- THIS FILE IS GENERATED AUTOMATICALLY. PLEASE DO NOT EDIT.
-*/
-
-
-/* System dependent functions for GNU cpio.
-
- Copyright (C) 2007, 2010 Free Software Foundation, Inc.
-
- GNU cpio is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
-
- GNU cpio 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 GNU cpiio. If not, see <http://www.gnu.org/licenses/>. */
-
-
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <unistd.h>
-#include <errno.h>
-
-
-
-
-#ifndef HAVE_GETPWUID
-# warning "Providing stub placeholder for getpwuid function"
-struct passwd *
-getpwuid ( uid_t uid __attribute__ ((unused)) )
-{
- errno = ENOSYS;
- return NULL;
-}
-#endif
-
-#ifndef HAVE_GETPWNAM
-# warning "Providing stub placeholder for getpwnam function"
-struct passwd *
-getpwnam ( const char *name __attribute__ ((unused)) )
-{
- errno = ENOSYS;
- return NULL;
-}
-#endif
-
-#ifndef HAVE_GETGRGID
-# warning "Providing stub placeholder for getgrgid function"
-struct group *
-getgrgid ( gid_t gid __attribute__ ((unused)) )
-{
- errno = ENOSYS;
- return NULL;
-}
-#endif
-
-#ifndef HAVE_GETGRNAM
-# warning "Providing stub placeholder for getgrnam function"
-struct group *
-getgrnam ( const char *name __attribute__ ((unused)) )
-{
- errno = ENOSYS;
- return NULL;
-}
-#endif
-
-#ifndef HAVE_PIPE
-# warning "Providing stub placeholder for pipe function"
-int
-pipe ( int filedes[2] __attribute__ ((unused)) )
-{
- errno = ENOSYS;
- return -1;
-}
-#endif
-
-#ifndef HAVE_FORK
-# warning "Providing stub placeholder for fork function"
-int
-fork (void)
-{
- errno = ENOSYS;
- return -1;
-}
-#endif
-
-
-
-#ifndef HAVE_GETUID
-# warning "Providing stub placeholder for getuid function"
-int
-getuid (void)
-{
- errno = ENOSYS;
- return -1;
-}
-#endif
-
-
-
-#ifndef HAVE_GETEUID
-# warning "Providing stub placeholder for geteuid function"
-int
-geteuid (void)
-{
- errno = ENOSYS;
- return -1;
-}
-#endif
-
-
-
-#ifndef HAVE_GETGID
-# warning "Providing stub placeholder for getgid function"
-int
-getgid (void)
-{
- errno = ENOSYS;
- return -1;
-}
-#endif
-
-
-#ifndef HAVE_SETUID
-# warning "Providing stub placeholder for setuid function"
-int
-setuid ( int newuid __attribute__ ((unused)) )
-{
- errno = ENOSYS;
- return -1;
-}
-#endif
-
-#ifndef HAVE_SETGID
-# warning "Providing stub placeholder for setgid function"
-int
-setgid ( int newgid __attribute__ ((unused)) )
-{
- errno = ENOSYS;
- return -1;
-}
-#endif
-
-#ifndef HAVE_MKNOD
-# warning "Providing stub placeholder for mknod function"
-int
-mknod ( const char *filename __attribute__ ((unused)) , int mode __attribute__ ((unused)) , int dev __attribute__ ((unused)) )
-{
- errno = ENOSYS;
- return -1;
-}
-#endif
-
-#ifndef HAVE_SYMLINK
-# warning "Providing stub placeholder for symlink function"
-int
-symlink ( const char *oldname __attribute__ ((unused)) , const char *newname __attribute__ ((unused)) )
-{
- errno = ENOSYS;
- return -1;
-}
-#endif
-
-#ifndef HAVE_LINK
-# warning "Providing stub placeholder for link function"
-int
-link ( const char *oldname __attribute__ ((unused)) , const char *newname __attribute__ ((unused)) )
-{
- errno = ENOSYS;
- return -1;
-}
-#endif
-
-#ifndef HAVE_CHOWN
-# warning "Providing stub placeholder for chown function"
-int
-chown ( const char *filename __attribute__ ((unused)) , int owner __attribute__ ((unused)) , int group __attribute__ ((unused)) )
-{
- errno = ENOSYS;
- return -1;
-}
-#endif
-
diff --git a/lib/sysdep.h b/lib/sysdep.h
deleted file mode 100644
index 32cb52e..0000000
--- a/lib/sysdep.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/* -*- buffer-read-only: t -*- vi: set ro:
- THIS FILE IS GENERATED AUTOMATICALLY. PLEASE DO NOT EDIT.
-*/
-
-
-/* System dependent functions for GNU cpio.
-
- Copyright (C) 2007, 2010 Free Software Foundation, Inc.
-
- GNU cpio is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
-
- GNU cpio 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 GNU cpiio. If not, see <http://www.gnu.org/licenses/>. */
-
-
-#ifdef HAVE_PROCESS_H
-# include <process.h>
-#endif
-
-#ifndef HAVE_PWD_H
-/* Borrowed from GNU libc */
-/* The passwd structure. */
-struct passwd
-{
- char *pw_name; /* Username. */
- char *pw_passwd; /* Password. */
- int pw_uid; /* User ID. */
- int pw_gid; /* Group ID. */
- char *pw_gecos; /* Real name. */
- char *pw_dir; /* Home directory. */
- char *pw_shell; /* Shell program. */
-};
-#endif
-#ifndef HAVE_GRP_H
-/* Borrowed from GNU libc */
-/* The group structure. */
-struct group
- {
- char *gr_name; /* Group name. */
- char *gr_passwd; /* Password. */
- int gr_gid; /* Group ID. */
- char **gr_mem; /* Member list. */
- };
-#endif
-
-#include <signal.h>
-#ifndef SIGPIPE
-# define SIGPIPE -1
-#endif
-
-
-
-
-
-#ifndef HAVE_GETPWUID
-struct passwd * getpwuid (uid_t uid);
-#endif
-
-
-#ifndef HAVE_GETPWNAM
-struct passwd * getpwnam (const char *name);
-#endif
-
-
-#ifndef HAVE_GETGRGID
-struct group * getgrgid (gid_t gid);
-#endif
-
-
-#ifndef HAVE_GETGRNAM
-struct group * getgrnam (const char *name);
-#endif
-
-
-#ifndef HAVE_PIPE
-int pipe (int filedes[2]);
-#endif
-
-
-#ifndef HAVE_FORK
-int fork (void);
-#endif
-
-
-
-
-#ifndef HAVE_GETUID
-int getuid (void);
-#endif
-
-
-
-
-#ifndef HAVE_GETEUID
-int geteuid (void);
-#endif
-
-
-
-
-#ifndef HAVE_GETGID
-int getgid (void);
-#endif
-
-
-
-#ifndef HAVE_SETUID
-int setuid (int newuid);
-#endif
-
-
-#ifndef HAVE_SETGID
-int setgid (int newgid);
-#endif
-
-
-#ifndef HAVE_MKNOD
-int mknod (const char *filename,int mode,int dev);
-#endif
-
-
-#ifndef HAVE_SYMLINK
-int symlink (const char *oldname,const char *newname);
-#endif
-
-
-#ifndef HAVE_LINK
-int link (const char *oldname,const char *newname);
-#endif
-
-
-#ifndef HAVE_CHOWN
-int chown (const char *filename,int owner,int group);
-#endif
-
-
diff --git a/lib/sysexits_.h b/lib/sysexits_.h
new file mode 100644
index 0000000..ba12aa2
--- /dev/null
+++ b/lib/sysexits_.h
@@ -0,0 +1,72 @@
+/* exit() exit codes for some BSD system programs.
+ Copyright (C) 2003, 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. */
+
+/* Written by Simon Josefsson based on sysexits(3) man page */
+
+#ifndef _GL_SYSEXITS_H
+
+#if @HAVE_SYSEXITS_H@
+
+/* IRIX 6.5 has an <unistd.h> that defines a macro EX_OK with a nonzero
+ value. Override it. See
+ <http://lists.gnu.org/archive/html/bug-gnulib/2007-03/msg00361.html> */
+# ifdef __sgi
+# include <unistd.h>
+# undef EX_OK
+# endif
+
+/* The include_next requires a split double-inclusion guard. */
+# if @HAVE_INCLUDE_NEXT@
+# include_next <sysexits.h>
+# else
+# include @ABSOLUTE_SYSEXITS_H@
+# endif
+
+/* HP-UX 11 <sysexits.h> ends at EX_NOPERM. */
+# ifndef EX_CONFIG
+# define EX_CONFIG 78
+# endif
+
+#endif
+
+#ifndef _GL_SYSEXITS_H
+#define _GL_SYSEXITS_H
+
+#if !@HAVE_SYSEXITS_H@
+
+# define EX_OK 0 /* same value as EXIT_SUCCESS */
+
+# define EX_USAGE 64
+# define EX_DATAERR 65
+# define EX_NOINPUT 66
+# define EX_NOUSER 67
+# define EX_NOHOST 68
+# define EX_UNAVAILABLE 69
+# define EX_SOFTWARE 70
+# define EX_OSERR 71
+# define EX_OSFILE 72
+# define EX_CANTCREAT 73
+# define EX_IOERR 74
+# define EX_TEMPFAIL 75
+# define EX_PROTOCOL 76
+# define EX_NOPERM 77
+# define EX_CONFIG 78
+
+#endif
+
+#endif /* _GL_SYSEXITS_H */
+#endif /* _GL_SYSEXITS_H */
diff --git a/lib/system-ioctl.h b/lib/system-ioctl.h
index f3276cf..a61c5fd 100644
--- a/lib/system-ioctl.h
+++ b/lib/system-ioctl.h
@@ -1,11 +1,11 @@
/* System dependent definitions for GNU tar's use of ioctl macros.
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
- 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2004, 2005, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
+ 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,
diff --git a/lib/system.h b/lib/system.h
index 38859c6..7602263 100644
--- a/lib/system.h
+++ b/lib/system.h
@@ -1,11 +1,11 @@
/* System dependent definitions for GNU tar.
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
- 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2004, 2005, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
+ 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,
@@ -453,13 +453,6 @@ char *getenv ();
#define _(msgid) gettext (msgid)
#define N_(msgid) msgid
-#ifdef HAVE_PWD_H
-# include <pwd.h>
-#endif
-#ifdef HAVE_GRP_H
-# include <grp.h>
-#endif
-
#if MSDOS
# include <process.h>
# define SET_BINARY_MODE(arc) setmode(arc, O_BINARY)
@@ -468,6 +461,8 @@ char *getenv ();
# define TTY_NAME "con"
# define sys_reset_uid_gid()
#else
+# include <pwd.h>
+# include <grp.h>
# define SET_BINARY_MODE(arc)
# define ERRNO_IS_EACCES 0
# define TTY_NAME "/dev/tty"
@@ -478,4 +473,3 @@ char *getenv ();
#if XENIX
# include <sys/inode.h>
#endif
-#include "sysdep.h"
diff --git a/lib/time_.h b/lib/time_.h
new file mode 100644
index 0000000..9a0507e
--- /dev/null
+++ b/lib/time_.h
@@ -0,0 +1,125 @@
+/* A more-standard <time.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. */
+
+/* Don't get in the way of glibc when it includes time.h merely to
+ declare a few standard symbols, rather than to declare all the
+ symbols. */
+#if defined __need_time_t || defined __need_clock_t || defined __need_timespec
+
+# if @HAVE_INCLUDE_NEXT@
+# include_next <time.h>
+# else
+# include @ABSOLUTE_TIME_H@
+# endif
+
+#else
+/* Normal invocation convention. */
+
+# if ! defined _GL_TIME_H
+
+/* The include_next requires a split double-inclusion guard. */
+# if @HAVE_INCLUDE_NEXT@
+# include_next <time.h>
+# else
+# include @ABSOLUTE_TIME_H@
+# endif
+
+# if ! defined _GL_TIME_H
+# define _GL_TIME_H
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/* Some systems don't define struct timespec (e.g., AIX 4.1, Ultrix 4.3).
+ Or they define it with the wrong member names or define it in <sys/time.h>
+ (e.g., FreeBSD circa 1997). */
+# if ! @TIME_H_DEFINES_STRUCT_TIMESPEC@
+# if @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@
+# include <sys/time.h>
+# else
+# undef timespec
+# define timespec rpl_timespec
+struct timespec
+{
+ time_t tv_sec;
+ long int tv_nsec;
+};
+# endif
+# endif
+
+/* Sleep for at least RQTP seconds unless interrupted, If interrupted,
+ return -1 and store the remaining time into RMTP. See
+ <http://www.opengroup.org/susv3xsh/nanosleep.html>. */
+# if @REPLACE_NANOSLEEP@
+# define nanosleep rpl_nanosleep
+int nanosleep (struct timespec const *__rqtp, struct timespec *__rmtp);
+# endif
+
+/* Convert TIMER to RESULT, assuming local time and UTC respectively. See
+ <http://www.opengroup.org/susv3xsh/localtime_r.html> and
+ <http://www.opengroup.org/susv3xsh/gmtime_r.html>. */
+# if @REPLACE_LOCALTIME_R@
+# undef localtime_r
+# define localtime_r rpl_localtime_r
+# undef gmtime_r
+# define gmtime_r rpl_gmtime_r
+struct tm *localtime_r (time_t const *restrict __timer,
+ struct tm *restrict __result);
+struct tm *gmtime_r (time_t const *restrict __timer,
+ struct tm *restrict __result);
+# endif
+
+/* Parse BUF as a time stamp, assuming FORMAT specifies its layout, and store
+ the resulting broken-down time into TM. See
+ <http://www.opengroup.org/susv3xsh/strptime.html>. */
+# if @REPLACE_STRPTIME@
+# undef strptime
+# define strptime rpl_strptime
+char *strptime (char const *restrict __buf, char const *restrict __format,
+ struct tm *restrict __tm);
+# endif
+
+/* Convert TM to a time_t value, assuming UTC. */
+# if @REPLACE_TIMEGM@
+# undef timegm
+# define timegm rpl_timegm
+time_t timegm (struct tm *__tm);
+# endif
+
+/* Encourage applications to avoid unsafe functions that can overrun
+ buffers when given outlandish struct tm values. Portable
+ applications should use strftime (or even sprintf) instead. */
+# if GNULIB_PORTCHECK
+# undef asctime
+# define asctime eschew_asctime
+# undef asctime_r
+# define asctime_r eschew_asctime_r
+# undef ctime
+# define ctime eschew_ctime
+# undef ctime_r
+# define ctime_r eschew_ctime_r
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+
+# endif /* _GL_TIME_H */
+# endif /* _GL_TIME_H */
+#endif
diff --git a/lib/time_r.c b/lib/time_r.c
new file mode 100644
index 0000000..2b72692
--- /dev/null
+++ b/lib/time_r.c
@@ -0,0 +1,47 @@
+/* Reentrant time functions like localtime_r.
+
+ Copyright (C) 2003, 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. */
+
+/* Written by Paul Eggert. */
+
+#include <config.h>
+
+#include <time.h>
+
+#include <string.h>
+
+static struct tm *
+copy_tm_result (struct tm *dest, struct tm const *src)
+{
+ if (! src)
+ return 0;
+ *dest = *src;
+ return dest;
+}
+
+
+struct tm *
+gmtime_r (time_t const * restrict t, struct tm * restrict tp)
+{
+ return copy_tm_result (tp, gmtime (t));
+}
+
+struct tm *
+localtime_r (time_t const * restrict t, struct tm * restrict tp)
+{
+ return copy_tm_result (tp, localtime (t));
+}
diff --git a/lib/timespec.h b/lib/timespec.h
new file mode 100644
index 0000000..cce2d66
--- /dev/null
+++ b/lib/timespec.h
@@ -0,0 +1,37 @@
+/* timespec -- System time interface
+
+ Copyright (C) 2000, 2002, 2004, 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. */
+
+#if ! defined TIMESPEC_H
+# define TIMESPEC_H
+
+# include <time.h>
+
+/* Return negative, zero, positive if A < B, A == B, A > B, respectively.
+ Assume the nanosecond components are in range, or close to it. */
+static inline int
+timespec_cmp (struct timespec a, struct timespec b)
+{
+ return (a.tv_sec < b.tv_sec ? -1
+ : a.tv_sec > b.tv_sec ? 1
+ : a.tv_nsec - b.tv_nsec);
+}
+
+void gettime (struct timespec *);
+int settime (struct timespec const *);
+
+#endif
diff --git a/lib/uinttostr.c b/lib/uinttostr.c
new file mode 100644
index 0000000..52d288e
--- /dev/null
+++ b/lib/uinttostr.c
@@ -0,0 +1,3 @@
+#define inttostr uinttostr
+#define inttype unsigned int
+#include "inttostr.c"
diff --git a/lib/umaxtostr.c b/lib/umaxtostr.c
new file mode 100644
index 0000000..4f49a7f
--- /dev/null
+++ b/lib/umaxtostr.c
@@ -0,0 +1,3 @@
+#define inttostr umaxtostr
+#define inttype uintmax_t
+#include "inttostr.c"
diff --git a/lib/unistd--.h b/lib/unistd--.h
new file mode 100644
index 0000000..1fe6ce8
--- /dev/null
+++ b/lib/unistd--.h
@@ -0,0 +1,28 @@
+/* Like unistd.h, but redefine some names to avoid glitches.
+
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert. */
+
+#include <unistd.h>
+#include "unistd-safer.h"
+
+#undef dup
+#define dup dup_safer
+
+#undef pipe
+#define pipe pipe_safer
diff --git a/lib/unistd-safer.h b/lib/unistd-safer.h
new file mode 100644
index 0000000..f95999d
--- /dev/null
+++ b/lib/unistd-safer.h
@@ -0,0 +1,23 @@
+/* Invoke unistd-like functions, but avoid some glitches.
+
+ Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert. */
+
+int dup_safer (int);
+int fd_safer (int);
+int pipe_safer (int[2]);
diff --git a/lib/unistd_.h b/lib/unistd_.h
new file mode 100644
index 0000000..f34bc66
--- /dev/null
+++ b/lib/unistd_.h
@@ -0,0 +1,242 @@
+/* Substitute for and wrapper around <unistd.h>.
+ Copyright (C) 2004-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. */
+
+#ifndef _GL_UNISTD_H
+
+/* The include_next requires a split double-inclusion guard. */
+#if @HAVE_UNISTD_H@
+# if @HAVE_INCLUDE_NEXT@
+# include_next <unistd.h>
+# else
+# include @ABSOLUTE_UNISTD_H@
+# endif
+#endif
+
+#ifndef _GL_UNISTD_H
+#define _GL_UNISTD_H
+
+/* mingw doesn't define the SEEK_* macros in <unistd.h>. */
+#if !(defined SEEK_CUR && defined SEEK_END && defined SEEK_SET)
+# include <stdio.h>
+#endif
+
+/* mingw fails to declare _exit in <unistd.h>. */
+#include <stdlib.h>
+
+/* The definition of GL_LINK_WARNING is copied here. */
+
+
+/* Declare overridden functions. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if @GNULIB_CHOWN@
+# if @REPLACE_CHOWN@
+/* Change the owner of FILE to UID (if UID is not -1) and the group of FILE
+ to GID (if GID is not -1).
+ Return 0 if successful, otherwise -1 and errno set.
+ See the POSIX:2001 specification
+ <http://www.opengroup.org/susv3xsh/chown.html>. */
+# define chown rpl_chown
+extern int chown (const char *file, uid_t uid, gid_t gid);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef chown
+# define chown(f,u,g) \
+ (GL_LINK_WARNING ("chown fails to follow symlinks on some systems and " \
+ "doesn't treat a uid or gid of -1 on some systems - " \
+ "use gnulib module chown for portability"), \
+ chown (f, u, g))
+#endif
+
+
+#if @GNULIB_DUP2@
+# if !@HAVE_DUP2@
+/* Copy the file descriptor OLDFD into file descriptor NEWFD. Do nothing if
+ NEWFD = OLDFD, otherwise close NEWFD first if it is open.
+ Return 0 if successful, otherwise -1 and errno set.
+ See the POSIX:2001 specification
+ <http://www.opengroup.org/susv3xsh/dup2.html>. */
+extern int dup2 (int oldfd, int newfd);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef dup2
+# define dup2(o,n) \
+ (GL_LINK_WARNING ("dup2 is unportable - " \
+ "use gnulib module dup2 for portability"), \
+ dup2 (o, n))
+#endif
+
+
+#if @GNULIB_FCHDIR@
+# if @REPLACE_FCHDIR@
+
+/* Change the process' current working directory to the directory on which
+ the given file descriptor is open.
+ Return 0 if successful, otherwise -1 and errno set.
+ See the POSIX:2001 specification
+ <http://www.opengroup.org/susv3xsh/fchdir.html>. */
+extern int fchdir (int /*fd*/);
+
+# define close rpl_close
+extern int close (int);
+# define dup rpl_dup
+extern int dup (int);
+# define dup2 rpl_dup2
+extern int dup2 (int, int);
+
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef fchdir
+# define fchdir(f) \
+ (GL_LINK_WARNING ("fchdir is unportable - " \
+ "use gnulib module fchdir for portability"), \
+ fchdir (f))
+#endif
+
+
+#if @GNULIB_FTRUNCATE@
+# if !@HAVE_FTRUNCATE@
+/* Change the size of the file to which FD is opened to become equal to LENGTH.
+ Return 0 if successful, otherwise -1 and errno set.
+ See the POSIX:2001 specification
+ <http://www.opengroup.org/susv3xsh/ftruncate.html>. */
+extern int ftruncate (int fd, off_t length);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef ftruncate
+# define ftruncate(f,l) \
+ (GL_LINK_WARNING ("ftruncate is unportable - " \
+ "use gnulib module ftruncate for portability"), \
+ ftruncate (f, l))
+#endif
+
+
+#if @GNULIB_GETCWD@
+/* Include the headers that might declare getcwd so that they will not
+ cause confusion if included after this file. */
+# include <stdlib.h>
+# if @REPLACE_GETCWD@
+/* Get the name of the current working directory, and put it in SIZE bytes
+ of BUF.
+ Return BUF if successful, or NULL if the directory couldn't be determined
+ or SIZE was too small.
+ See the POSIX:2001 specification
+ <http://www.opengroup.org/susv3xsh/getcwd.html>.
+ Additionally, the gnulib module 'getcwd' guarantees the following GNU
+ extension: If BUF is NULL, an array is allocated with 'malloc'; the array
+ is SIZE bytes long, unless SIZE == 0, in which case it is as big as
+ necessary. */
+# define getcwd rpl_getcwd
+extern char * getcwd (char *buf, size_t size);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef getcwd
+# define getcwd(b,s) \
+ (GL_LINK_WARNING ("getcwd is unportable - " \
+ "use gnulib module getcwd for portability"), \
+ getcwd (b, s))
+#endif
+
+
+#if @GNULIB_GETLOGIN_R@
+/* Copies the user's login name to NAME.
+ The array pointed to by NAME has room for SIZE bytes.
+
+ Returns 0 if successful. Upon error, an error number is returned, or -1 in
+ the case that the login name cannot be found but no specific error is
+ provided (this case is hopefully rare but is left open by the POSIX spec).
+
+ See <http://www.opengroup.org/susv3xsh/getlogin.html>.
+ */
+# if !@HAVE_DECL_GETLOGIN_R@
+# include <stddef.h>
+extern int getlogin_r (char *name, size_t size);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef getlogin_r
+# define getlogin_r(n,s) \
+ (GL_LINK_WARNING ("getlogin_r is unportable - " \
+ "use gnulib module getlogin_r for portability"), \
+ getlogin_r (n, s))
+#endif
+
+
+#if @GNULIB_LSEEK@
+# if @REPLACE_LSEEK@
+/* Set the offset of FD relative to SEEK_SET, SEEK_CUR, or SEEK_END.
+ Return the new offset if successful, otherwise -1 and errno set.
+ See the POSIX:2001 specification
+ <http://www.opengroup.org/susv3xsh/lseek.html>. */
+# define lseek rpl_lseek
+ extern off_t lseek (int fd, off_t offset, int whence);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef lseek
+# define lseek(f,o,w) \
+ (GL_LINK_WARNING ("lseek does not fail with ESPIPE on pipes on some " \
+ "systems - use gnulib module lseek for portability"), \
+ lseek (f, o, w))
+#endif
+
+
+#if @GNULIB_READLINK@
+/* Read the contents of the symbolic link FILE and place the first BUFSIZE
+ bytes of it into BUF. Return the number of bytes placed into BUF if
+ successful, otherwise -1 and errno set.
+ See the POSIX:2001 specification
+ <http://www.opengroup.org/susv3xsh/readlink.html>. */
+# if !@HAVE_READLINK@
+# include <stddef.h>
+extern int readlink (const char *file, char *buf, size_t bufsize);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef readlink
+# define readlink(f,b,s) \
+ (GL_LINK_WARNING ("readlink is unportable - " \
+ "use gnulib module readlink for portability"), \
+ readlink (f, b, s))
+#endif
+
+
+#if @GNULIB_SLEEP@
+/* Pause the execution of the current thread for N seconds.
+ Returns the number of seconds left to sleep.
+ See the POSIX:2001 specification
+ <http://www.opengroup.org/susv3xsh/sleep.html>. */
+# if !@HAVE_SLEEP@
+extern unsigned int sleep (unsigned int n);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef sleep
+# define sleep(n) \
+ (GL_LINK_WARNING ("sleep is unportable - " \
+ "use gnulib module sleep for portability"), \
+ sleep (n))
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _GL_UNISTD_H */
+#endif /* _GL_UNISTD_H */
diff --git a/lib/unlocked-io.h b/lib/unlocked-io.h
new file mode 100644
index 0000000..d009303
--- /dev/null
+++ b/lib/unlocked-io.h
@@ -0,0 +1,137 @@
+/* Prefer faster, non-thread-safe stdio functions if available.
+
+ Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Jim Meyering. */
+
+#ifndef UNLOCKED_IO_H
+# define UNLOCKED_IO_H 1
+
+/* These are wrappers for functions/macros from the GNU C library, and
+ from other C libraries supporting POSIX's optional thread-safe functions.
+
+ The standard I/O functions are thread-safe. These *_unlocked ones are
+ more efficient but not thread-safe. That they're not thread-safe is
+ fine since all of the applications in this package are single threaded.
+
+ Also, some code that is shared with the GNU C library may invoke
+ the *_unlocked functions directly. On hosts that lack those
+ functions, invoke the non-thread-safe versions instead. */
+
+# include <stdio.h>
+
+# if HAVE_DECL_CLEARERR_UNLOCKED
+# undef clearerr
+# define clearerr(x) clearerr_unlocked (x)
+# else
+# define clearerr_unlocked(x) clearerr (x)
+# endif
+
+# if HAVE_DECL_FEOF_UNLOCKED
+# undef feof
+# define feof(x) feof_unlocked (x)
+# else
+# define feof_unlocked(x) feof (x)
+# endif
+
+# if HAVE_DECL_FERROR_UNLOCKED
+# undef ferror
+# define ferror(x) ferror_unlocked (x)
+# else
+# define ferror_unlocked(x) ferror (x)
+# endif
+
+# if HAVE_DECL_FFLUSH_UNLOCKED
+# undef fflush
+# define fflush(x) fflush_unlocked (x)
+# else
+# define fflush_unlocked(x) fflush (x)
+# endif
+
+# if HAVE_DECL_FGETS_UNLOCKED
+# undef fgets
+# define fgets(x,y,z) fgets_unlocked (x,y,z)
+# else
+# define fgets_unlocked(x,y,z) fgets (x,y,z)
+# endif
+
+# if HAVE_DECL_FPUTC_UNLOCKED
+# undef fputc
+# define fputc(x,y) fputc_unlocked (x,y)
+# else
+# define fputc_unlocked(x,y) fputc (x,y)
+# endif
+
+# if HAVE_DECL_FPUTS_UNLOCKED
+# undef fputs
+# define fputs(x,y) fputs_unlocked (x,y)
+# else
+# define fputs_unlocked(x,y) fputs (x,y)
+# endif
+
+# if HAVE_DECL_FREAD_UNLOCKED
+# undef fread
+# define fread(w,x,y,z) fread_unlocked (w,x,y,z)
+# else
+# define fread_unlocked(w,x,y,z) fread (w,x,y,z)
+# endif
+
+# if HAVE_DECL_FWRITE_UNLOCKED
+# undef fwrite
+# define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z)
+# else
+# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
+# endif
+
+# if HAVE_DECL_GETC_UNLOCKED
+# undef getc
+# define getc(x) getc_unlocked (x)
+# else
+# define getc_unlocked(x) getc (x)
+# endif
+
+# if HAVE_DECL_GETCHAR_UNLOCKED
+# undef getchar
+# define getchar() getchar_unlocked ()
+# else
+# define getchar_unlocked() getchar ()
+# endif
+
+# if HAVE_DECL_PUTC_UNLOCKED
+# undef putc
+# define putc(x,y) putc_unlocked (x,y)
+# else
+# define putc_unlocked(x,y) putc (x,y)
+# endif
+
+# if HAVE_DECL_PUTCHAR_UNLOCKED
+# undef putchar
+# define putchar(x) putchar_unlocked (x)
+# else
+# define putchar_unlocked(x) putchar (x)
+# endif
+
+# undef flockfile
+# define flockfile(x) ((void) 0)
+
+# undef ftrylockfile
+# define ftrylockfile(x) 0
+
+# undef funlockfile
+# define funlockfile(x) ((void) 0)
+
+#endif /* UNLOCKED_IO_H */
diff --git a/lib/unsetenv.c b/lib/unsetenv.c
new file mode 100644
index 0000000..0f83744
--- /dev/null
+++ b/lib/unsetenv.c
@@ -0,0 +1,92 @@
+/* Copyright (C) 1992,1995-1999,2000-2002,2005-2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+#include <errno.h>
+#if !_LIBC
+# define __set_errno(ev) ((errno) = (ev))
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#if !_LIBC
+# define __environ environ
+# ifndef HAVE_ENVIRON_DECL
+extern char **environ;
+# endif
+#endif
+
+#if _LIBC
+/* This lock protects against simultaneous modifications of `environ'. */
+# include <bits/libc-lock.h>
+__libc_lock_define_initialized (static, envlock)
+# define LOCK __libc_lock_lock (envlock)
+# define UNLOCK __libc_lock_unlock (envlock)
+#else
+# define LOCK
+# define UNLOCK
+#endif
+
+/* In the GNU C library we must keep the namespace clean. */
+#ifdef _LIBC
+# define unsetenv __unsetenv
+#endif
+
+
+int
+unsetenv (const char *name)
+{
+ size_t len;
+ char **ep;
+
+ if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ len = strlen (name);
+
+ LOCK;
+
+ ep = __environ;
+ while (*ep != NULL)
+ if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
+ {
+ /* Found it. Remove this pointer by moving later ones back. */
+ char **dp = ep;
+
+ do
+ dp[0] = dp[1];
+ while (*dp++);
+ /* Continue the loop in case NAME appears again. */
+ }
+ else
+ ++ep;
+
+ UNLOCK;
+
+ return 0;
+}
+
+#ifdef _LIBC
+# undef unsetenv
+weak_alias (__unsetenv, unsetenv)
+#endif
diff --git a/lib/utimens.c b/lib/utimens.c
new file mode 100644
index 0000000..7e3175a
--- /dev/null
+++ b/lib/utimens.c
@@ -0,0 +1,189 @@
+/* Set file access and modification times.
+
+ Copyright (C) 2003, 2004, 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. */
+
+/* Written by Paul Eggert. */
+
+/* derived from a function in touch.c */
+
+#include <config.h>
+
+#include "utimens.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#if HAVE_UTIME_H
+# include <utime.h>
+#endif
+
+/* Some systems (even some that do have <utime.h>) don't declare this
+ structure anywhere. */
+#ifndef HAVE_STRUCT_UTIMBUF
+struct utimbuf
+{
+ long actime;
+ long modtime;
+};
+#endif
+
+/* Some systems don't have ENOSYS. */
+#ifndef ENOSYS
+# ifdef ENOTSUP
+# define ENOSYS ENOTSUP
+# else
+/* Some systems don't have ENOTSUP either. */
+# define ENOSYS EINVAL
+# endif
+#endif
+
+#ifndef __attribute__
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
+# define __attribute__(x)
+# endif
+#endif
+
+#ifndef ATTRIBUTE_UNUSED
+# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif
+
+/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
+ TIMESPEC[0] and TIMESPEC[1], respectively.
+ FD must be either negative -- in which case it is ignored --
+ or a file descriptor that is open on FILE.
+ If FD is nonnegative, then FILE can be NULL, which means
+ use just futimes (or equivalent) instead of utimes (or equivalent),
+ and fail if on an old system without futimes (or equivalent).
+ If TIMESPEC is null, set the time stamps to the current time.
+ Return 0 on success, -1 (setting errno) on failure. */
+
+int
+gl_futimens (int fd ATTRIBUTE_UNUSED,
+ char const *file, struct timespec const timespec[2])
+{
+ /* Some Linux-based NFS clients are buggy, and mishandle time stamps
+ of files in NFS file systems in some cases. We have no
+ configure-time test for this, but please see
+ <http://bugs.gentoo.org/show_bug.cgi?id=132673> for references to
+ some of the problems with Linux 2.6.16. If this affects you,
+ compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to
+ help in some cases, albeit at a cost in performance. But you
+ really should upgrade your kernel to a fixed version, since the
+ problem affects many applications. */
+
+#if HAVE_BUGGY_NFS_TIME_STAMPS
+ if (fd < 0)
+ sync ();
+ else
+ fsync (fd);
+#endif
+
+ /* There's currently no interface to set file timestamps with
+ nanosecond resolution, so do the best we can, discarding any
+ fractional part of the timestamp. */
+#if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
+ struct timeval timeval[2];
+ struct timeval const *t;
+ if (timespec)
+ {
+ timeval[0].tv_sec = timespec[0].tv_sec;
+ timeval[0].tv_usec = timespec[0].tv_nsec / 1000;
+ timeval[1].tv_sec = timespec[1].tv_sec;
+ timeval[1].tv_usec = timespec[1].tv_nsec / 1000;
+ t = timeval;
+ }
+ else
+ t = NULL;
+
+
+ if (fd < 0)
+ {
+# if HAVE_FUTIMESAT
+ return futimesat (AT_FDCWD, file, t);
+# endif
+ }
+ else
+ {
+ /* If futimesat or futimes fails here, don't try to speed things
+ up by returning right away. glibc can incorrectly fail with
+ errno == ENOENT if /proc isn't mounted. Also, Mandrake 10.0
+ in high security mode doesn't allow ordinary users to read
+ /proc/self, so glibc incorrectly fails with errno == EACCES.
+ If errno == EIO, EPERM, or EROFS, it's probably safe to fail
+ right away, but these cases are rare enough that they're not
+ worth optimizing, and who knows what other messed-up systems
+ are out there? So play it safe and fall back on the code
+ below. */
+# if HAVE_FUTIMESAT
+ if (futimesat (fd, NULL, t) == 0)
+ return 0;
+# elif HAVE_FUTIMES
+ if (futimes (fd, t) == 0)
+ return 0;
+# endif
+ }
+#endif
+
+ if (!file)
+ {
+#if ! (HAVE_FUTIMESAT || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
+ errno = ENOSYS;
+#endif
+
+ /* Prefer EBADF to ENOSYS if both error numbers apply. */
+ if (errno == ENOSYS)
+ {
+ int fd2 = dup (fd);
+ int dup_errno = errno;
+ if (0 <= fd2)
+ close (fd2);
+ errno = (fd2 < 0 && dup_errno == EBADF ? EBADF : ENOSYS);
+ }
+
+ return -1;
+ }
+
+#if HAVE_WORKING_UTIMES
+ return utimes (file, t);
+#else
+ {
+ struct utimbuf utimbuf;
+ struct utimbuf const *ut;
+ if (timespec)
+ {
+ utimbuf.actime = timespec[0].tv_sec;
+ utimbuf.modtime = timespec[1].tv_sec;
+ ut = &utimbuf;
+ }
+ else
+ ut = NULL;
+
+ return utime (file, ut);
+ }
+#endif
+}
+
+/* Set the access and modification time stamps of FILE to be
+ TIMESPEC[0] and TIMESPEC[1], respectively. */
+int
+utimens (char const *file, struct timespec const timespec[2])
+{
+ return gl_futimens (-1, file, timespec);
+}
diff --git a/lib/utimens.h b/lib/utimens.h
new file mode 100644
index 0000000..169521d
--- /dev/null
+++ b/lib/utimens.h
@@ -0,0 +1,3 @@
+#include <time.h>
+int gl_futimens (int, char const *, struct timespec const [2]);
+int utimens (char const *, struct timespec const [2]);
diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c
new file mode 100644
index 0000000..c60888c
--- /dev/null
+++ b/lib/vasnprintf.c
@@ -0,0 +1,3193 @@
+/* vsprintf with automatic memory allocation.
+ Copyright (C) 1999, 2002-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. */
+
+/* Tell glibc's <stdio.h> to provide a prototype for snprintf().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#include <config.h>
+#ifndef IN_LIBINTL
+# include <alloca.h>
+#endif
+
+/* Specification. */
+#if WIDE_CHAR_VERSION
+# include "vasnwprintf.h"
+#else
+# include "vasnprintf.h"
+#endif
+
+#include <locale.h> /* localeconv() */
+#include <stdio.h> /* snprintf(), sprintf() */
+#include <stdlib.h> /* abort(), malloc(), realloc(), free() */
+#include <string.h> /* memcpy(), strlen() */
+#include <errno.h> /* errno */
+#include <limits.h> /* CHAR_BIT */
+#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
+#if HAVE_NL_LANGINFO
+# include <langinfo.h>
+#endif
+#if WIDE_CHAR_VERSION
+# include "wprintf-parse.h"
+#else
+# include "printf-parse.h"
+#endif
+
+/* Checked size_t computations. */
+#include "xsize.h"
+
+#if NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL
+# include <math.h>
+# include "float+.h"
+#endif
+
+#if NEED_PRINTF_INFINITE_DOUBLE && !defined IN_LIBINTL
+# include <math.h>
+# include "isnan.h"
+#endif
+
+#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !defined IN_LIBINTL
+# include <math.h>
+# include "isnanl-nolibm.h"
+#endif
+
+#if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL
+# include <math.h>
+# include "isnan.h"
+# include "printf-frexp.h"
+# include "isnanl-nolibm.h"
+# include "printf-frexpl.h"
+# include "fpucw.h"
+#endif
+
+/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */
+#ifndef EOVERFLOW
+# define EOVERFLOW E2BIG
+#endif
+
+#if HAVE_WCHAR_T
+# if HAVE_WCSLEN
+# define local_wcslen wcslen
+# else
+ /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
+ a dependency towards this library, here is a local substitute.
+ Define this substitute only once, even if this file is included
+ twice in the same compilation unit. */
+# ifndef local_wcslen_defined
+# define local_wcslen_defined 1
+static size_t
+local_wcslen (const wchar_t *s)
+{
+ const wchar_t *ptr;
+
+ for (ptr = s; *ptr != (wchar_t) 0; ptr++)
+ ;
+ return ptr - s;
+}
+# endif
+# endif
+#endif
+
+#if WIDE_CHAR_VERSION
+# define VASNPRINTF vasnwprintf
+# define CHAR_T wchar_t
+# define DIRECTIVE wchar_t_directive
+# define DIRECTIVES wchar_t_directives
+# define PRINTF_PARSE wprintf_parse
+# define USE_SNPRINTF 1
+# if HAVE_DECL__SNWPRINTF
+ /* On Windows, the function swprintf() has a different signature than
+ on Unix; we use the _snwprintf() function instead. */
+# define SNPRINTF _snwprintf
+# else
+ /* Unix. */
+# define SNPRINTF swprintf
+# endif
+#else
+# define VASNPRINTF vasnprintf
+# define CHAR_T char
+# define DIRECTIVE char_directive
+# define DIRECTIVES char_directives
+# define PRINTF_PARSE printf_parse
+# /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'.
+ But don't use it on BeOS, since BeOS snprintf produces no output if the
+ size argument is >= 0x3000000. */
+# if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__
+# define USE_SNPRINTF 1
+# else
+# define USE_SNPRINTF 0
+# endif
+# if HAVE_DECL__SNPRINTF
+ /* Windows. */
+# define SNPRINTF _snprintf
+# else
+ /* Unix. */
+# define SNPRINTF snprintf
+ /* Here we need to call the native snprintf, not rpl_snprintf. */
+# undef snprintf
+# endif
+#endif
+/* Here we need to call the native sprintf, not rpl_sprintf. */
+#undef sprintf
+
+#if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL
+/* Determine the decimal-point character according to the current locale. */
+# ifndef decimal_point_char_defined
+# define decimal_point_char_defined 1
+static char
+decimal_point_char ()
+{
+ const char *point;
+ /* Determine it in a multithread-safe way. We know nl_langinfo is
+ multithread-safe on glibc systems, but is not required to be multithread-
+ safe by POSIX. sprintf(), however, is multithread-safe. localeconv()
+ is rarely multithread-safe. */
+# if HAVE_NL_LANGINFO && __GLIBC__
+ point = nl_langinfo (RADIXCHAR);
+# elif 1
+ char pointbuf[5];
+ sprintf (pointbuf, "%#.0f", 1.0);
+ point = &pointbuf[1];
+# else
+ point = localeconv () -> decimal_point;
+# endif
+ /* The decimal point is always a single byte: either '.' or ','. */
+ return (point[0] != '\0' ? point[0] : '.');
+}
+# endif
+#endif
+
+#if NEED_PRINTF_INFINITE_DOUBLE && !defined IN_LIBINTL
+
+/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */
+static int
+is_infinite_or_zero (double x)
+{
+ return isnan (x) || x + x == x;
+}
+
+#endif
+
+#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !defined IN_LIBINTL
+
+/* Equivalent to !isfinite(x), but does not require libm. */
+static int
+is_infinitel (long double x)
+{
+ return isnanl (x) || (x + x == x && x != 0.0L);
+}
+
+#endif
+
+#if NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL
+
+/* Converting 'long double' to decimal without rare rounding bugs requires
+ real bignums. We use the naming conventions of GNU gmp, but vastly simpler
+ (and slower) algorithms. */
+
+typedef unsigned int mp_limb_t;
+# define GMP_LIMB_BITS 32
+typedef int mp_limb_verify[2 * (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS) - 1];
+
+typedef unsigned long long mp_twolimb_t;
+# define GMP_TWOLIMB_BITS 64
+typedef int mp_twolimb_verify[2 * (sizeof (mp_twolimb_t) * CHAR_BIT == GMP_TWOLIMB_BITS) - 1];
+
+/* Representation of a bignum >= 0. */
+typedef struct
+{
+ size_t nlimbs;
+ mp_limb_t *limbs; /* Bits in little-endian order, allocated with malloc(). */
+} mpn_t;
+
+/* Compute the product of two bignums >= 0.
+ Return the allocated memory in case of success, NULL in case of memory
+ allocation failure. */
+static void *
+multiply (mpn_t src1, mpn_t src2, mpn_t *dest)
+{
+ const mp_limb_t *p1;
+ const mp_limb_t *p2;
+ size_t len1;
+ size_t len2;
+
+ if (src1.nlimbs <= src2.nlimbs)
+ {
+ len1 = src1.nlimbs;
+ p1 = src1.limbs;
+ len2 = src2.nlimbs;
+ p2 = src2.limbs;
+ }
+ else
+ {
+ len1 = src2.nlimbs;
+ p1 = src2.limbs;
+ len2 = src1.nlimbs;
+ p2 = src1.limbs;
+ }
+ /* Now 0 <= len1 <= len2. */
+ if (len1 == 0)
+ {
+ /* src1 or src2 is zero. */
+ dest->nlimbs = 0;
+ dest->limbs = (mp_limb_t *) malloc (1);
+ }
+ else
+ {
+ /* Here 1 <= len1 <= len2. */
+ size_t dlen;
+ mp_limb_t *dp;
+ size_t k, i, j;
+
+ dlen = len1 + len2;
+ dp = (mp_limb_t *) malloc (dlen * sizeof (mp_limb_t));
+ if (dp == NULL)
+ return NULL;
+ for (k = len2; k > 0; )
+ dp[--k] = 0;
+ for (i = 0; i < len1; i++)
+ {
+ mp_limb_t digit1 = p1[i];
+ mp_twolimb_t carry = 0;
+ for (j = 0; j < len2; j++)
+ {
+ mp_limb_t digit2 = p2[j];
+ carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
+ carry += dp[i + j];
+ dp[i + j] = (mp_limb_t) carry;
+ carry = carry >> GMP_LIMB_BITS;
+ }
+ dp[i + len2] = (mp_limb_t) carry;
+ }
+ /* Normalise. */
+ while (dlen > 0 && dp[dlen - 1] == 0)
+ dlen--;
+ dest->nlimbs = dlen;
+ dest->limbs = dp;
+ }
+ return dest->limbs;
+}
+
+/* Compute the quotient of a bignum a >= 0 and a bignum b > 0.
+ a is written as a = q * b + r with 0 <= r < b. q is the quotient, r
+ the remainder.
+ Finally, round-to-even is performed: If r > b/2 or if r = b/2 and q is odd,
+ q is incremented.
+ Return the allocated memory in case of success, NULL in case of memory
+ allocation failure. */
+static void *
+divide (mpn_t a, mpn_t b, mpn_t *q)
+{
+ /* Algorithm:
+ First normalise a and b: a=[a[m-1],...,a[0]], b=[b[n-1],...,b[0]]
+ with m>=0 and n>0 (in base beta = 2^GMP_LIMB_BITS).
+ If m<n, then q:=0 and r:=a.
+ If m>=n=1, perform a single-precision division:
+ r:=0, j:=m,
+ while j>0 do
+ {Here (q[m-1]*beta^(m-1)+...+q[j]*beta^j) * b[0] + r*beta^j =
+ = a[m-1]*beta^(m-1)+...+a[j]*beta^j und 0<=r<b[0]<beta}
+ j:=j-1, r:=r*beta+a[j], q[j]:=floor(r/b[0]), r:=r-b[0]*q[j].
+ Normalise [q[m-1],...,q[0]], yields q.
+ If m>=n>1, perform a multiple-precision division:
+ We have a/b < beta^(m-n+1).
+ s:=intDsize-1-(hightest bit in b[n-1]), 0<=s<intDsize.
+ Shift a and b left by s bits, copying them. r:=a.
+ r=[r[m],...,r[0]], b=[b[n-1],...,b[0]] with b[n-1]>=beta/2.
+ For j=m-n,...,0: {Here 0 <= r < b*beta^(j+1).}
+ Compute q* :
+ q* := floor((r[j+n]*beta+r[j+n-1])/b[n-1]).
+ In case of overflow (q* >= beta) set q* := beta-1.
+ Compute c2 := ((r[j+n]*beta+r[j+n-1]) - q* * b[n-1])*beta + r[j+n-2]
+ and c3 := b[n-2] * q*.
+ {We have 0 <= c2 < 2*beta^2, even 0 <= c2 < beta^2 if no overflow
+ occurred. Furthermore 0 <= c3 < beta^2.
+ If there was overflow and
+ r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta, i.e. c2 >= beta^2,
+ the next test can be skipped.}
+ While c3 > c2, {Here 0 <= c2 < c3 < beta^2}
+ Put q* := q* - 1, c2 := c2 + b[n-1]*beta, c3 := c3 - b[n-2].
+ If q* > 0:
+ Put r := r - b * q* * beta^j. In detail:
+ [r[n+j],...,r[j]] := [r[n+j],...,r[j]] - q* * [b[n-1],...,b[0]].
+ hence: u:=0, for i:=0 to n-1 do
+ u := u + q* * b[i],
+ r[j+i]:=r[j+i]-(u mod beta) (+ beta, if carry),
+ u:=u div beta (+ 1, if carry in subtraction)
+ r[n+j]:=r[n+j]-u.
+ {Since always u = (q* * [b[i-1],...,b[0]] div beta^i) + 1
+ < q* + 1 <= beta,
+ the carry u does not overflow.}
+ If a negative carry occurs, put q* := q* - 1
+ and [r[n+j],...,r[j]] := [r[n+j],...,r[j]] + [0,b[n-1],...,b[0]].
+ Set q[j] := q*.
+ Normalise [q[m-n],..,q[0]]; this yields the quotient q.
+ Shift [r[n-1],...,r[0]] right by s bits and normalise; this yields the
+ rest r.
+ The room for q[j] can be allocated at the memory location of r[n+j].
+ Finally, round-to-even:
+ Shift r left by 1 bit.
+ If r > b or if r = b and q[0] is odd, q := q+1.
+ */
+ const mp_limb_t *a_ptr = a.limbs;
+ size_t a_len = a.nlimbs;
+ const mp_limb_t *b_ptr = b.limbs;
+ size_t b_len = b.nlimbs;
+ mp_limb_t *roomptr;
+ mp_limb_t *tmp_roomptr = NULL;
+ mp_limb_t *q_ptr;
+ size_t q_len;
+ mp_limb_t *r_ptr;
+ size_t r_len;
+
+ /* Allocate room for a_len+2 digits.
+ (Need a_len+1 digits for the real division and 1 more digit for the
+ final rounding of q.) */
+ roomptr = (mp_limb_t *) malloc ((a_len + 2) * sizeof (mp_limb_t));
+ if (roomptr == NULL)
+ return NULL;
+
+ /* Normalise a. */
+ while (a_len > 0 && a_ptr[a_len - 1] == 0)
+ a_len--;
+
+ /* Normalise b. */
+ for (;;)
+ {
+ if (b_len == 0)
+ /* Division by zero. */
+ abort ();
+ if (b_ptr[b_len - 1] == 0)
+ b_len--;
+ else
+ break;
+ }
+
+ /* Here m = a_len >= 0 and n = b_len > 0. */
+
+ if (a_len < b_len)
+ {
+ /* m<n: trivial case. q=0, r := copy of a. */
+ r_ptr = roomptr;
+ r_len = a_len;
+ memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
+ q_ptr = roomptr + a_len;
+ q_len = 0;
+ }
+ else if (b_len == 1)
+ {
+ /* n=1: single precision division.
+ beta^(m-1) <= a < beta^m ==> beta^(m-2) <= a/b < beta^m */
+ r_ptr = roomptr;
+ q_ptr = roomptr + 1;
+ {
+ mp_limb_t den = b_ptr[0];
+ mp_limb_t remainder = 0;
+ const mp_limb_t *sourceptr = a_ptr + a_len;
+ mp_limb_t *destptr = q_ptr + a_len;
+ size_t count;
+ for (count = a_len; count > 0; count--)
+ {
+ mp_twolimb_t num =
+ ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--sourceptr;
+ *--destptr = num / den;
+ remainder = num % den;
+ }
+ /* Normalise and store r. */
+ if (remainder > 0)
+ {
+ r_ptr[0] = remainder;
+ r_len = 1;
+ }
+ else
+ r_len = 0;
+ /* Normalise q. */
+ q_len = a_len;
+ if (q_ptr[q_len - 1] == 0)
+ q_len--;
+ }
+ }
+ else
+ {
+ /* n>1: multiple precision division.
+ beta^(m-1) <= a < beta^m, beta^(n-1) <= b < beta^n ==>
+ beta^(m-n-1) <= a/b < beta^(m-n+1). */
+ /* Determine s. */
+ size_t s;
+ {
+ mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */
+ s = 31;
+ if (msd >= 0x10000)
+ {
+ msd = msd >> 16;
+ s -= 16;
+ }
+ if (msd >= 0x100)
+ {
+ msd = msd >> 8;
+ s -= 8;
+ }
+ if (msd >= 0x10)
+ {
+ msd = msd >> 4;
+ s -= 4;
+ }
+ if (msd >= 0x4)
+ {
+ msd = msd >> 2;
+ s -= 2;
+ }
+ if (msd >= 0x2)
+ {
+ msd = msd >> 1;
+ s -= 1;
+ }
+ }
+ /* 0 <= s < GMP_LIMB_BITS.
+ Copy b, shifting it left by s bits. */
+ if (s > 0)
+ {
+ tmp_roomptr = (mp_limb_t *) malloc (b_len * sizeof (mp_limb_t));
+ if (tmp_roomptr == NULL)
+ {
+ free (roomptr);
+ return NULL;
+ }
+ {
+ const mp_limb_t *sourceptr = b_ptr;
+ mp_limb_t *destptr = tmp_roomptr;
+ mp_twolimb_t accu = 0;
+ size_t count;
+ for (count = b_len; count > 0; count--)
+ {
+ accu += (mp_twolimb_t) *sourceptr++ << s;
+ *destptr++ = (mp_limb_t) accu;
+ accu = accu >> GMP_LIMB_BITS;
+ }
+ /* accu must be zero, since that was how s was determined. */
+ if (accu != 0)
+ abort ();
+ }
+ b_ptr = tmp_roomptr;
+ }
+ /* Copy a, shifting it left by s bits, yields r.
+ Memory layout:
+ At the beginning: r = roomptr[0..a_len],
+ at the end: r = roomptr[0..b_len-1], q = roomptr[b_len..a_len] */
+ r_ptr = roomptr;
+ if (s == 0)
+ {
+ memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
+ r_ptr[a_len] = 0;
+ }
+ else
+ {
+ const mp_limb_t *sourceptr = a_ptr;
+ mp_limb_t *destptr = r_ptr;
+ mp_twolimb_t accu = 0;
+ size_t count;
+ for (count = a_len; count > 0; count--)
+ {
+ accu += (mp_twolimb_t) *sourceptr++ << s;
+ *destptr++ = (mp_limb_t) accu;
+ accu = accu >> GMP_LIMB_BITS;
+ }
+ *destptr++ = (mp_limb_t) accu;
+ }
+ q_ptr = roomptr + b_len;
+ q_len = a_len - b_len + 1; /* q will have m-n+1 limbs */
+ {
+ size_t j = a_len - b_len; /* m-n */
+ mp_limb_t b_msd = b_ptr[b_len - 1]; /* b[n-1] */
+ mp_limb_t b_2msd = b_ptr[b_len - 2]; /* b[n-2] */
+ mp_twolimb_t b_msdd = /* b[n-1]*beta+b[n-2] */
+ ((mp_twolimb_t) b_msd << GMP_LIMB_BITS) | b_2msd;
+ /* Division loop, traversed m-n+1 times.
+ j counts down, b is unchanged, beta/2 <= b[n-1] < beta. */
+ for (;;)
+ {
+ mp_limb_t q_star;
+ mp_limb_t c1;
+ if (r_ptr[j + b_len] < b_msd) /* r[j+n] < b[n-1] ? */
+ {
+ /* Divide r[j+n]*beta+r[j+n-1] by b[n-1], no overflow. */
+ mp_twolimb_t num =
+ ((mp_twolimb_t) r_ptr[j + b_len] << GMP_LIMB_BITS)
+ | r_ptr[j + b_len - 1];
+ q_star = num / b_msd;
+ c1 = num % b_msd;
+ }
+ else
+ {
+ /* Overflow, hence r[j+n]*beta+r[j+n-1] >= beta*b[n-1]. */
+ q_star = (mp_limb_t)~(mp_limb_t)0; /* q* = beta-1 */
+ /* Test whether r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] >= beta
+ <==> r[j+n]*beta+r[j+n-1] + b[n-1] >= beta*b[n-1]+beta
+ <==> b[n-1] < floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta)
+ {<= beta !}.
+ If yes, jump directly to the subtraction loop.
+ (Otherwise, r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] < beta
+ <==> floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) = b[n-1] ) */
+ if (r_ptr[j + b_len] > b_msd
+ || (c1 = r_ptr[j + b_len - 1] + b_msd) < b_msd)
+ /* r[j+n] >= b[n-1]+1 or
+ r[j+n] = b[n-1] and the addition r[j+n-1]+b[n-1] gives a
+ carry. */
+ goto subtract;
+ }
+ /* q_star = q*,
+ c1 = (r[j+n]*beta+r[j+n-1]) - q* * b[n-1] (>=0, <beta). */
+ {
+ mp_twolimb_t c2 = /* c1*beta+r[j+n-2] */
+ ((mp_twolimb_t) c1 << GMP_LIMB_BITS) | r_ptr[j + b_len - 2];
+ mp_twolimb_t c3 = /* b[n-2] * q* */
+ (mp_twolimb_t) b_2msd * (mp_twolimb_t) q_star;
+ /* While c2 < c3, increase c2 and decrease c3.
+ Consider c3-c2. While it is > 0, decrease it by
+ b[n-1]*beta+b[n-2]. Because of b[n-1]*beta+b[n-2] >= beta^2/2
+ this can happen only twice. */
+ if (c3 > c2)
+ {
+ q_star = q_star - 1; /* q* := q* - 1 */
+ if (c3 - c2 > b_msdd)
+ q_star = q_star - 1; /* q* := q* - 1 */
+ }
+ }
+ if (q_star > 0)
+ subtract:
+ {
+ /* Subtract r := r - b * q* * beta^j. */
+ mp_limb_t cr;
+ {
+ const mp_limb_t *sourceptr = b_ptr;
+ mp_limb_t *destptr = r_ptr + j;
+ mp_twolimb_t carry = 0;
+ size_t count;
+ for (count = b_len; count > 0; count--)
+ {
+ /* Here 0 <= carry <= q*. */
+ carry =
+ carry
+ + (mp_twolimb_t) q_star * (mp_twolimb_t) *sourceptr++
+ + (mp_limb_t) ~(*destptr);
+ /* Here 0 <= carry <= beta*q* + beta-1. */
+ *destptr++ = ~(mp_limb_t) carry;
+ carry = carry >> GMP_LIMB_BITS; /* <= q* */
+ }
+ cr = (mp_limb_t) carry;
+ }
+ /* Subtract cr from r_ptr[j + b_len], then forget about
+ r_ptr[j + b_len]. */
+ if (cr > r_ptr[j + b_len])
+ {
+ /* Subtraction gave a carry. */
+ q_star = q_star - 1; /* q* := q* - 1 */
+ /* Add b back. */
+ {
+ const mp_limb_t *sourceptr = b_ptr;
+ mp_limb_t *destptr = r_ptr + j;
+ mp_limb_t carry = 0;
+ size_t count;
+ for (count = b_len; count > 0; count--)
+ {
+ mp_limb_t source1 = *sourceptr++;
+ mp_limb_t source2 = *destptr;
+ *destptr++ = source1 + source2 + carry;
+ carry =
+ (carry
+ ? source1 >= (mp_limb_t) ~source2
+ : source1 > (mp_limb_t) ~source2);
+ }
+ }
+ /* Forget about the carry and about r[j+n]. */
+ }
+ }
+ /* q* is determined. Store it as q[j]. */
+ q_ptr[j] = q_star;
+ if (j == 0)
+ break;
+ j--;
+ }
+ }
+ r_len = b_len;
+ /* Normalise q. */
+ if (q_ptr[q_len - 1] == 0)
+ q_len--;
+# if 0 /* Not needed here, since we need r only to compare it with b/2, and
+ b is shifted left by s bits. */
+ /* Shift r right by s bits. */
+ if (s > 0)
+ {
+ mp_limb_t ptr = r_ptr + r_len;
+ mp_twolimb_t accu = 0;
+ size_t count;
+ for (count = r_len; count > 0; count--)
+ {
+ accu = (mp_twolimb_t) (mp_limb_t) accu << GMP_LIMB_BITS;
+ accu += (mp_twolimb_t) *--ptr << (GMP_LIMB_BITS - s);
+ *ptr = (mp_limb_t) (accu >> GMP_LIMB_BITS);
+ }
+ }
+# endif
+ /* Normalise r. */
+ while (r_len > 0 && r_ptr[r_len - 1] == 0)
+ r_len--;
+ }
+ /* Compare r << 1 with b. */
+ if (r_len > b_len)
+ goto increment_q;
+ {
+ size_t i;
+ for (i = b_len;;)
+ {
+ mp_limb_t r_i =
+ (i <= r_len && i > 0 ? r_ptr[i - 1] >> (GMP_LIMB_BITS - 1) : 0)
+ | (i < r_len ? r_ptr[i] << 1 : 0);
+ mp_limb_t b_i = (i < b_len ? b_ptr[i] : 0);
+ if (r_i > b_i)
+ goto increment_q;
+ if (r_i < b_i)
+ goto keep_q;
+ if (i == 0)
+ break;
+ i--;
+ }
+ }
+ if (q_len > 0 && ((q_ptr[0] & 1) != 0))
+ /* q is odd. */
+ increment_q:
+ {
+ size_t i;
+ for (i = 0; i < q_len; i++)
+ if (++(q_ptr[i]) != 0)
+ goto keep_q;
+ q_ptr[q_len++] = 1;
+ }
+ keep_q:
+ if (tmp_roomptr != NULL)
+ free (tmp_roomptr);
+ q->limbs = q_ptr;
+ q->nlimbs = q_len;
+ return roomptr;
+}
+
+/* Convert a bignum a >= 0, multiplied with 10^extra_zeroes, to decimal
+ representation.
+ Destroys the contents of a.
+ Return the allocated memory - containing the decimal digits in low-to-high
+ order, terminated with a NUL character - in case of success, NULL in case
+ of memory allocation failure. */
+static char *
+convert_to_decimal (mpn_t a, size_t extra_zeroes)
+{
+ mp_limb_t *a_ptr = a.limbs;
+ size_t a_len = a.nlimbs;
+ /* 0.03345 is slightly larger than log(2)/(9*log(10)). */
+ size_t c_len = 9 * ((size_t)(a_len * (GMP_LIMB_BITS * 0.03345f)) + 1);
+ char *c_ptr = (char *) malloc (xsum (c_len, extra_zeroes));
+ if (c_ptr != NULL)
+ {
+ char *d_ptr = c_ptr;
+ for (; extra_zeroes > 0; extra_zeroes--)
+ *d_ptr++ = '0';
+ while (a_len > 0)
+ {
+ /* Divide a by 10^9, in-place. */
+ mp_limb_t remainder = 0;
+ mp_limb_t *ptr = a_ptr + a_len;
+ size_t count;
+ for (count = a_len; count > 0; count--)
+ {
+ mp_twolimb_t num =
+ ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--ptr;
+ *ptr = num / 1000000000;
+ remainder = num % 1000000000;
+ }
+ /* Store the remainder as 9 decimal digits. */
+ for (count = 9; count > 0; count--)
+ {
+ *d_ptr++ = '0' + (remainder % 10);
+ remainder = remainder / 10;
+ }
+ /* Normalize a. */
+ if (a_ptr[a_len - 1] == 0)
+ a_len--;
+ }
+ /* Remove leading zeroes. */
+ while (d_ptr > c_ptr && d_ptr[-1] == '0')
+ d_ptr--;
+ /* But keep at least one zero. */
+ if (d_ptr == c_ptr)
+ *d_ptr++ = '0';
+ /* Terminate the string. */
+ *d_ptr = '\0';
+ }
+ return c_ptr;
+}
+
+/* Assuming x is finite and >= 0:
+ write x as x = 2^e * m, where m is a bignum.
+ Return the allocated memory in case of success, NULL in case of memory
+ allocation failure. */
+static void *
+decode_long_double (long double x, int *ep, mpn_t *mp)
+{
+ mpn_t m;
+ int exp;
+ long double y;
+ size_t i;
+
+ /* Allocate memory for result. */
+ m.nlimbs = (LDBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
+ m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
+ if (m.limbs == NULL)
+ return NULL;
+ /* Split into exponential part and mantissa. */
+ y = frexpl (x, &exp);
+ if (!(y >= 0.0L && y < 1.0L))
+ abort ();
+ /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * LDBL_MANT_BIT), and the
+ latter is an integer. */
+ /* Convert the mantissa (y * LDBL_MANT_BIT) to a sequence of limbs.
+ I'm not sure whether it's safe to cast a 'long double' value between
+ 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
+ 'long double' values between 0 and 2^16 (to 'unsigned int' or 'int',
+ doesn't matter). */
+# if (LDBL_MANT_BIT % GMP_LIMB_BITS) != 0
+# if (LDBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
+ {
+ mp_limb_t hi, lo;
+ y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % (GMP_LIMB_BITS / 2));
+ hi = (int) y;
+ y -= hi;
+ if (!(y >= 0.0L && y < 1.0L))
+ abort ();
+ y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
+ lo = (int) y;
+ y -= lo;
+ if (!(y >= 0.0L && y < 1.0L))
+ abort ();
+ m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
+ }
+# else
+ {
+ mp_limb_t d;
+ y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % GMP_LIMB_BITS);
+ d = (int) y;
+ y -= d;
+ if (!(y >= 0.0L && y < 1.0L))
+ abort ();
+ m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = d;
+ }
+# endif
+# endif
+ for (i = LDBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
+ {
+ mp_limb_t hi, lo;
+ y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
+ hi = (int) y;
+ y -= hi;
+ if (!(y >= 0.0L && y < 1.0L))
+ abort ();
+ y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
+ lo = (int) y;
+ y -= lo;
+ if (!(y >= 0.0L && y < 1.0L))
+ abort ();
+ m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
+ }
+ if (!(y == 0.0L))
+ abort ();
+ /* Normalise. */
+ while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
+ m.nlimbs--;
+ *mp = m;
+ *ep = exp - LDBL_MANT_BIT;
+ return m.limbs;
+}
+
+/* Assuming x is finite and >= 0, and n is an integer:
+ Returns the decimal representation of round (x * 10^n).
+ Return the allocated memory - containing the decimal digits in low-to-high
+ order, terminated with a NUL character - in case of success, NULL in case
+ of memory allocation failure. */
+static char *
+scale10_round_decimal_long_double (long double x, int n)
+{
+ int e;
+ mpn_t m;
+ void *memory = decode_long_double (x, &e, &m);
+ int s;
+ size_t extra_zeroes;
+ unsigned int abs_n;
+ unsigned int abs_s;
+ mp_limb_t *pow5_ptr;
+ size_t pow5_len;
+ unsigned int s_limbs;
+ unsigned int s_bits;
+ mpn_t pow5;
+ mpn_t z;
+ void *z_memory;
+ char *digits;
+
+ if (memory == NULL)
+ return NULL;
+ /* x = 2^e * m, hence
+ y = round (2^e * 10^n * m) = round (2^(e+n) * 5^n * m)
+ = round (2^s * 5^n * m). */
+ s = e + n;
+ extra_zeroes = 0;
+ /* Factor out a common power of 10 if possible. */
+ if (s > 0 && n > 0)
+ {
+ extra_zeroes = (s < n ? s : n);
+ s -= extra_zeroes;
+ n -= extra_zeroes;
+ }
+ /* Here y = round (2^s * 5^n * m) * 10^extra_zeroes.
+ Before converting to decimal, we need to compute
+ z = round (2^s * 5^n * m). */
+ /* Compute 5^|n|, possibly shifted by |s| bits if n and s have the same
+ sign. 2.322 is slightly larger than log(5)/log(2). */
+ abs_n = (n >= 0 ? n : -n);
+ abs_s = (s >= 0 ? s : -s);
+ pow5_ptr = (mp_limb_t *) malloc (((int)(abs_n * (2.322f / GMP_LIMB_BITS)) + 1
+ + abs_s / GMP_LIMB_BITS + 1)
+ * sizeof (mp_limb_t));
+ if (pow5_ptr == NULL)
+ {
+ free (memory);
+ return NULL;
+ }
+ /* Initialize with 1. */
+ pow5_ptr[0] = 1;
+ pow5_len = 1;
+ /* Multiply with 5^|n|. */
+ if (abs_n > 0)
+ {
+ static mp_limb_t const small_pow5[13 + 1] =
+ {
+ 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625,
+ 48828125, 244140625, 1220703125
+ };
+ unsigned int n13;
+ for (n13 = 0; n13 <= abs_n; n13 += 13)
+ {
+ mp_limb_t digit1 = small_pow5[n13 + 13 <= abs_n ? 13 : abs_n - n13];
+ size_t j;
+ mp_twolimb_t carry = 0;
+ for (j = 0; j < pow5_len; j++)
+ {
+ mp_limb_t digit2 = pow5_ptr[j];
+ carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
+ pow5_ptr[j] = (mp_limb_t) carry;
+ carry = carry >> GMP_LIMB_BITS;
+ }
+ if (carry > 0)
+ pow5_ptr[pow5_len++] = (mp_limb_t) carry;
+ }
+ }
+ s_limbs = abs_s / GMP_LIMB_BITS;
+ s_bits = abs_s % GMP_LIMB_BITS;
+ if (n >= 0 ? s >= 0 : s <= 0)
+ {
+ /* Multiply with 2^|s|. */
+ if (s_bits > 0)
+ {
+ mp_limb_t *ptr = pow5_ptr;
+ mp_twolimb_t accu = 0;
+ size_t count;
+ for (count = pow5_len; count > 0; count--)
+ {
+ accu += (mp_twolimb_t) *ptr << s_bits;
+ *ptr++ = (mp_limb_t) accu;
+ accu = accu >> GMP_LIMB_BITS;
+ }
+ if (accu > 0)
+ {
+ *ptr = (mp_limb_t) accu;
+ pow5_len++;
+ }
+ }
+ if (s_limbs > 0)
+ {
+ size_t count;
+ for (count = pow5_len; count > 0;)
+ {
+ count--;
+ pow5_ptr[s_limbs + count] = pow5_ptr[count];
+ }
+ for (count = s_limbs; count > 0;)
+ {
+ count--;
+ pow5_ptr[count] = 0;
+ }
+ pow5_len += s_limbs;
+ }
+ pow5.limbs = pow5_ptr;
+ pow5.nlimbs = pow5_len;
+ if (n >= 0)
+ {
+ /* Multiply m with pow5. No division needed. */
+ z_memory = multiply (m, pow5, &z);
+ }
+ else
+ {
+ /* Divide m by pow5 and round. */
+ z_memory = divide (m, pow5, &z);
+ }
+ }
+ else
+ {
+ pow5.limbs = pow5_ptr;
+ pow5.nlimbs = pow5_len;
+ if (n >= 0)
+ {
+ /* n >= 0, s < 0.
+ Multiply m with pow5, then divide by 2^|s|. */
+ mpn_t numerator;
+ mpn_t denominator;
+ void *tmp_memory;
+ tmp_memory = multiply (m, pow5, &numerator);
+ if (tmp_memory == NULL)
+ {
+ free (pow5_ptr);
+ free (memory);
+ return NULL;
+ }
+ /* Construct 2^|s|. */
+ {
+ mp_limb_t *ptr = pow5_ptr + pow5_len;
+ size_t i;
+ for (i = 0; i < s_limbs; i++)
+ ptr[i] = 0;
+ ptr[s_limbs] = (mp_limb_t) 1 << s_bits;
+ denominator.limbs = ptr;
+ denominator.nlimbs = s_limbs + 1;
+ }
+ z_memory = divide (numerator, denominator, &z);
+ free (tmp_memory);
+ }
+ else
+ {
+ /* n < 0, s > 0.
+ Multiply m with 2^s, then divide by pow5. */
+ mpn_t numerator;
+ mp_limb_t *num_ptr;
+ num_ptr = (mp_limb_t *) malloc ((m.nlimbs + s_limbs + 1)
+ * sizeof (mp_limb_t));
+ if (num_ptr == NULL)
+ {
+ free (pow5_ptr);
+ free (memory);
+ return NULL;
+ }
+ {
+ mp_limb_t *destptr = num_ptr;
+ {
+ size_t i;
+ for (i = 0; i < s_limbs; i++)
+ *destptr++ = 0;
+ }
+ if (s_bits > 0)
+ {
+ const mp_limb_t *sourceptr = m.limbs;
+ mp_twolimb_t accu = 0;
+ size_t count;
+ for (count = m.nlimbs; count > 0; count--)
+ {
+ accu += (mp_twolimb_t) *sourceptr++ << s;
+ *destptr++ = (mp_limb_t) accu;
+ accu = accu >> GMP_LIMB_BITS;
+ }
+ if (accu > 0)
+ *destptr++ = (mp_limb_t) accu;
+ }
+ else
+ {
+ const mp_limb_t *sourceptr = m.limbs;
+ size_t count;
+ for (count = m.nlimbs; count > 0; count--)
+ *destptr++ = *sourceptr++;
+ }
+ numerator.limbs = num_ptr;
+ numerator.nlimbs = destptr - num_ptr;
+ }
+ z_memory = divide (numerator, pow5, &z);
+ free (num_ptr);
+ }
+ }
+ free (pow5_ptr);
+ free (memory);
+
+ /* Here y = round (x * 10^n) = z * 10^extra_zeroes. */
+
+ if (z_memory == NULL)
+ return NULL;
+ digits = convert_to_decimal (z, extra_zeroes);
+ free (z_memory);
+ return digits;
+}
+
+/* Assuming x is finite and > 0:
+ Return an approximation for n with 10^n <= x < 10^(n+1).
+ The approximation is usually the right n, but may be off by 1 sometimes. */
+static int
+floorlog10l (long double x)
+{
+ int exp;
+ long double y;
+ double z;
+ double l;
+
+ /* Split into exponential part and mantissa. */
+ y = frexpl (x, &exp);
+ if (!(y >= 0.0L && y < 1.0L))
+ abort ();
+ if (y == 0.0L)
+ return INT_MIN;
+ if (y < 0.5L)
+ {
+ while (y < (1.0L / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2))))
+ {
+ y *= 1.0L * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
+ exp -= GMP_LIMB_BITS;
+ }
+ if (y < (1.0L / (1 << 16)))
+ {
+ y *= 1.0L * (1 << 16);
+ exp -= 16;
+ }
+ if (y < (1.0L / (1 << 8)))
+ {
+ y *= 1.0L * (1 << 8);
+ exp -= 8;
+ }
+ if (y < (1.0L / (1 << 4)))
+ {
+ y *= 1.0L * (1 << 4);
+ exp -= 4;
+ }
+ if (y < (1.0L / (1 << 2)))
+ {
+ y *= 1.0L * (1 << 2);
+ exp -= 2;
+ }
+ if (y < (1.0L / (1 << 1)))
+ {
+ y *= 1.0L * (1 << 1);
+ exp -= 1;
+ }
+ }
+ if (!(y >= 0.5L && y < 1.0L))
+ abort ();
+ /* Compute an approximation for l = log2(x) = exp + log2(y). */
+ l = exp;
+ z = y;
+ if (z < 0.70710678118654752444)
+ {
+ z *= 1.4142135623730950488;
+ l -= 0.5;
+ }
+ if (z < 0.8408964152537145431)
+ {
+ z *= 1.1892071150027210667;
+ l -= 0.25;
+ }
+ if (z < 0.91700404320467123175)
+ {
+ z *= 1.0905077326652576592;
+ l -= 0.125;
+ }
+ if (z < 0.9576032806985736469)
+ {
+ z *= 1.0442737824274138403;
+ l -= 0.0625;
+ }
+ /* Now 0.95 <= z <= 1.01. */
+ z = 1 - z;
+ /* log(1-z) = - z - z^2/2 - z^3/3 - z^4/4 - ...
+ Four terms are enough to get an approximation with error < 10^-7. */
+ l -= z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
+ /* Finally multiply with log(2)/log(10), yields an approximation for
+ log10(x). */
+ l *= 0.30102999566398119523;
+ /* Round down to the next integer. */
+ return (int) l + (l < 0 ? -1 : 0);
+}
+
+#endif
+
+CHAR_T *
+VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args)
+{
+ DIRECTIVES d;
+ arguments a;
+
+ if (PRINTF_PARSE (format, &d, &a) < 0)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+#define CLEANUP() \
+ free (d.dir); \
+ if (a.arg) \
+ free (a.arg);
+
+ if (printf_fetchargs (args, &a) < 0)
+ {
+ CLEANUP ();
+ errno = EINVAL;
+ return NULL;
+ }
+
+ {
+ size_t buf_neededlength;
+ CHAR_T *buf;
+ CHAR_T *buf_malloced;
+ const CHAR_T *cp;
+ size_t i;
+ DIRECTIVE *dp;
+ /* Output string accumulator. */
+ CHAR_T *result;
+ size_t allocated;
+ size_t length;
+
+ /* Allocate a small buffer that will hold a directive passed to
+ sprintf or snprintf. */
+ buf_neededlength =
+ xsum4 (7, d.max_width_length, d.max_precision_length, 6);
+#if HAVE_ALLOCA
+ if (buf_neededlength < 4000 / sizeof (CHAR_T))
+ {
+ buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T));
+ buf_malloced = NULL;
+ }
+ else
+#endif
+ {
+ size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T));
+ if (size_overflow_p (buf_memsize))
+ goto out_of_memory_1;
+ buf = (CHAR_T *) malloc (buf_memsize);
+ if (buf == NULL)
+ goto out_of_memory_1;
+ buf_malloced = buf;
+ }
+
+ if (resultbuf != NULL)
+ {
+ result = resultbuf;
+ allocated = *lengthp;
+ }
+ else
+ {
+ result = NULL;
+ allocated = 0;
+ }
+ length = 0;
+ /* Invariants:
+ result is either == resultbuf or == NULL or malloc-allocated.
+ If length > 0, then result != NULL. */
+
+ /* Ensures that allocated >= needed. Aborts through a jump to
+ out_of_memory if needed is SIZE_MAX or otherwise too big. */
+#define ENSURE_ALLOCATION(needed) \
+ if ((needed) > allocated) \
+ { \
+ size_t memory_size; \
+ CHAR_T *memory; \
+ \
+ allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \
+ if ((needed) > allocated) \
+ allocated = (needed); \
+ memory_size = xtimes (allocated, sizeof (CHAR_T)); \
+ if (size_overflow_p (memory_size)) \
+ goto out_of_memory; \
+ if (result == resultbuf || result == NULL) \
+ memory = (CHAR_T *) malloc (memory_size); \
+ else \
+ memory = (CHAR_T *) realloc (result, memory_size); \
+ if (memory == NULL) \
+ goto out_of_memory; \
+ if (result == resultbuf && length > 0) \
+ memcpy (memory, result, length * sizeof (CHAR_T)); \
+ result = memory; \
+ }
+
+ for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
+ {
+ if (cp != dp->dir_start)
+ {
+ size_t n = dp->dir_start - cp;
+ size_t augmented_length = xsum (length, n);
+
+ ENSURE_ALLOCATION (augmented_length);
+ memcpy (result + length, cp, n * sizeof (CHAR_T));
+ length = augmented_length;
+ }
+ if (i == d.count)
+ break;
+
+ /* Execute a single directive. */
+ if (dp->conversion == '%')
+ {
+ size_t augmented_length;
+
+ if (!(dp->arg_index == ARG_NONE))
+ abort ();
+ augmented_length = xsum (length, 1);
+ ENSURE_ALLOCATION (augmented_length);
+ result[length] = '%';
+ length = augmented_length;
+ }
+ else
+ {
+ if (!(dp->arg_index != ARG_NONE))
+ abort ();
+
+ if (dp->conversion == 'n')
+ {
+ switch (a.arg[dp->arg_index].type)
+ {
+ case TYPE_COUNT_SCHAR_POINTER:
+ *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
+ break;
+ case TYPE_COUNT_SHORT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_short_pointer = length;
+ break;
+ case TYPE_COUNT_INT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_int_pointer = length;
+ break;
+ case TYPE_COUNT_LONGINT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
+ break;
+#if HAVE_LONG_LONG_INT
+ case TYPE_COUNT_LONGLONGINT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
+ break;
+#endif
+ default:
+ abort ();
+ }
+ }
+#if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
+ else if ((dp->conversion == 'f' || dp->conversion == 'F'
+ || dp->conversion == 'e' || dp->conversion == 'E'
+ || dp->conversion == 'g' || dp->conversion == 'G')
+ && (0
+# if NEED_PRINTF_INFINITE_DOUBLE
+ || (a.arg[dp->arg_index].type == TYPE_DOUBLE
+ /* The systems (mingw) which produce wrong output
+ for Inf, -Inf, and NaN also do so for -0.0.
+ Therefore we treat this case here as well. */
+ && is_infinite_or_zero (a.arg[dp->arg_index].a.a_double))
+# endif
+# if NEED_PRINTF_LONG_DOUBLE
+ || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
+# elif NEED_PRINTF_INFINITE_LONG_DOUBLE
+ || (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
+ /* Some systems produce wrong output for Inf,
+ -Inf, and NaN. */
+ && is_infinitel (a.arg[dp->arg_index].a.a_longdouble))
+# endif
+ ))
+ {
+# if NEED_PRINTF_INFINITE_DOUBLE && (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE)
+ arg_type type = a.arg[dp->arg_index].type;
+# endif
+ int flags = dp->flags;
+ int has_width;
+ size_t width;
+ int has_precision;
+ size_t precision;
+ size_t tmp_length;
+ CHAR_T tmpbuf[700];
+ CHAR_T *tmp;
+ CHAR_T *pad_ptr;
+ CHAR_T *p;
+
+ has_width = 0;
+ width = 0;
+ if (dp->width_start != dp->width_end)
+ {
+ if (dp->width_arg_index != ARG_NONE)
+ {
+ int arg;
+
+ if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->width_arg_index].a.a_int;
+ if (arg < 0)
+ {
+ /* "A negative field width is taken as a '-' flag
+ followed by a positive field width." */
+ flags |= FLAG_LEFT;
+ width = (unsigned int) (-arg);
+ }
+ else
+ width = arg;
+ }
+ else
+ {
+ const CHAR_T *digitp = dp->width_start;
+
+ do
+ width = xsum (xtimes (width, 10), *digitp++ - '0');
+ while (digitp != dp->width_end);
+ }
+ has_width = 1;
+ }
+
+ has_precision = 0;
+ precision = 0;
+ if (dp->precision_start != dp->precision_end)
+ {
+ if (dp->precision_arg_index != ARG_NONE)
+ {
+ int arg;
+
+ if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->precision_arg_index].a.a_int;
+ /* "A negative precision is taken as if the precision
+ were omitted." */
+ if (arg >= 0)
+ {
+ precision = arg;
+ has_precision = 1;
+ }
+ }
+ else
+ {
+ const CHAR_T *digitp = dp->precision_start + 1;
+
+ precision = 0;
+ while (digitp != dp->precision_end)
+ precision = xsum (xtimes (precision, 10), *digitp++ - '0');
+ has_precision = 1;
+ }
+ }
+
+ /* POSIX specifies the default precision to be 6 for %f, %F,
+ %e, %E, but not for %g, %G. Implementations appear to use
+ the same default precision also for %g, %G. */
+ if (!has_precision)
+ precision = 6;
+
+ /* Allocate a temporary buffer of sufficient size. */
+# if NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE
+ tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : 0);
+# elif NEED_PRINTF_LONG_DOUBLE
+ tmp_length = LDBL_DIG + 1;
+# else
+ tmp_length = 0;
+# endif
+ if (tmp_length < precision)
+ tmp_length = precision;
+# if NEED_PRINTF_LONG_DOUBLE
+# if NEED_PRINTF_INFINITE_DOUBLE
+ if (type == TYPE_LONGDOUBLE)
+# endif
+ if (dp->conversion == 'f' || dp->conversion == 'F')
+ {
+ long double arg = a.arg[dp->arg_index].a.a_longdouble;
+ if (!(isnanl (arg) || arg + arg == arg))
+ {
+ /* arg is finite and nonzero. */
+ int exponent = floorlog10l (arg < 0 ? -arg : arg);
+ if (exponent >= 0 && tmp_length < exponent + precision)
+ tmp_length = exponent + precision;
+ }
+ }
+# endif
+ /* Account for sign, decimal point etc. */
+ tmp_length = xsum (tmp_length, 12);
+
+ if (tmp_length < width)
+ tmp_length = width;
+
+ tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
+
+ if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
+ tmp = tmpbuf;
+ else
+ {
+ size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
+
+ if (size_overflow_p (tmp_memsize))
+ /* Overflow, would lead to out of memory. */
+ goto out_of_memory;
+ tmp = (CHAR_T *) malloc (tmp_memsize);
+ if (tmp == NULL)
+ /* Out of memory. */
+ goto out_of_memory;
+ }
+
+ pad_ptr = NULL;
+ p = tmp;
+
+# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
+# if NEED_PRINTF_INFINITE_DOUBLE
+ if (type == TYPE_LONGDOUBLE)
+# endif
+ {
+ long double arg = a.arg[dp->arg_index].a.a_longdouble;
+
+ if (isnanl (arg))
+ {
+ if (dp->conversion >= 'A' && dp->conversion <= 'Z')
+ {
+ *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
+ }
+ else
+ {
+ *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
+ }
+ }
+ else
+ {
+ int sign = 0;
+ DECL_LONG_DOUBLE_ROUNDING
+
+ BEGIN_LONG_DOUBLE_ROUNDING ();
+
+ if (signbit (arg)) /* arg < 0.0L or negative zero */
+ {
+ sign = -1;
+ arg = -arg;
+ }
+
+ if (sign < 0)
+ *p++ = '-';
+ else if (flags & FLAG_SHOWSIGN)
+ *p++ = '+';
+ else if (flags & FLAG_SPACE)
+ *p++ = ' ';
+
+ if (arg > 0.0L && arg + arg == arg)
+ {
+ if (dp->conversion >= 'A' && dp->conversion <= 'Z')
+ {
+ *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
+ }
+ else
+ {
+ *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
+ }
+ }
+ else
+ {
+# if NEED_PRINTF_LONG_DOUBLE
+ pad_ptr = p;
+
+ if (dp->conversion == 'f' || dp->conversion == 'F')
+ {
+ char *digits;
+ size_t ndigits;
+
+ digits =
+ scale10_round_decimal_long_double (arg, precision);
+ if (digits == NULL)
+ {
+ END_LONG_DOUBLE_ROUNDING ();
+ goto out_of_memory;
+ }
+ ndigits = strlen (digits);
+
+ if (ndigits > precision)
+ do
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ while (ndigits > precision);
+ else
+ *p++ = '0';
+ /* Here ndigits <= precision. */
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ for (; precision > ndigits; precision--)
+ *p++ = '0';
+ while (ndigits > 0)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+
+ free (digits);
+ }
+ else if (dp->conversion == 'e' || dp->conversion == 'E')
+ {
+ int exponent;
+
+ if (arg == 0.0L)
+ {
+ exponent = 0;
+ *p++ = '0';
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ for (; precision > 0; precision--)
+ *p++ = '0';
+ }
+ }
+ else
+ {
+ /* arg > 0.0L. */
+ int adjusted;
+ char *digits;
+ size_t ndigits;
+
+ exponent = floorlog10l (arg);
+ adjusted = 0;
+ for (;;)
+ {
+ digits =
+ scale10_round_decimal_long_double (arg,
+ (int)precision - exponent);
+ if (digits == NULL)
+ {
+ END_LONG_DOUBLE_ROUNDING ();
+ goto out_of_memory;
+ }
+ ndigits = strlen (digits);
+
+ if (ndigits == precision + 1)
+ break;
+ if (ndigits < precision
+ || ndigits > precision + 2)
+ /* The exponent was not guessed
+ precisely enough. */
+ abort ();
+ if (adjusted)
+ /* None of two values of exponent is
+ the right one. Prevent an endless
+ loop. */
+ abort ();
+ free (digits);
+ if (ndigits == precision)
+ exponent -= 1;
+ else
+ exponent += 1;
+ adjusted = 1;
+ }
+
+ /* Here ndigits = precision+1. */
+ *p++ = digits[--ndigits];
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ while (ndigits > 0)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+
+ free (digits);
+ }
+
+ *p++ = dp->conversion; /* 'e' or 'E' */
+# if WIDE_CHAR_VERSION
+ {
+ static const wchar_t decimal_format[] =
+ { '%', '+', '.', '2', 'd', '\0' };
+ SNPRINTF (p, 6 + 1, decimal_format, exponent);
+ }
+# else
+ sprintf (p, "%+.2d", exponent);
+# endif
+ while (*p != '\0')
+ p++;
+ }
+ else if (dp->conversion == 'g' || dp->conversion == 'G')
+ {
+ if (precision == 0)
+ precision = 1;
+ /* precision >= 1. */
+
+ if (arg == 0.0L)
+ /* The exponent is 0, >= -4, < precision.
+ Use fixed-point notation. */
+ {
+ size_t ndigits = precision;
+ /* Number of trailing zeroes that have to be
+ dropped. */
+ size_t nzeroes =
+ (flags & FLAG_ALT ? 0 : precision - 1);
+
+ --ndigits;
+ *p++ = '0';
+ if ((flags & FLAG_ALT) || ndigits > nzeroes)
+ {
+ *p++ = decimal_point_char ();
+ while (ndigits > nzeroes)
+ {
+ --ndigits;
+ *p++ = '0';
+ }
+ }
+ }
+ else
+ {
+ /* arg > 0.0L. */
+ int exponent;
+ int adjusted;
+ char *digits;
+ size_t ndigits;
+ size_t nzeroes;
+
+ exponent = floorlog10l (arg);
+ adjusted = 0;
+ for (;;)
+ {
+ digits =
+ scale10_round_decimal_long_double (arg,
+ (int)(precision - 1) - exponent);
+ if (digits == NULL)
+ {
+ END_LONG_DOUBLE_ROUNDING ();
+ goto out_of_memory;
+ }
+ ndigits = strlen (digits);
+
+ if (ndigits == precision)
+ break;
+ if (ndigits < precision - 1
+ || ndigits > precision + 1)
+ /* The exponent was not guessed
+ precisely enough. */
+ abort ();
+ if (adjusted)
+ /* None of two values of exponent is
+ the right one. Prevent an endless
+ loop. */
+ abort ();
+ free (digits);
+ if (ndigits < precision)
+ exponent -= 1;
+ else
+ exponent += 1;
+ adjusted = 1;
+ }
+ /* Here ndigits = precision. */
+
+ /* Determine the number of trailing zeroes
+ that have to be dropped. */
+ nzeroes = 0;
+ if ((flags & FLAG_ALT) == 0)
+ while (nzeroes < ndigits
+ && digits[nzeroes] == '0')
+ nzeroes++;
+
+ /* The exponent is now determined. */
+ if (exponent >= -4
+ && exponent < (long)precision)
+ {
+ /* Fixed-point notation:
+ max(exponent,0)+1 digits, then the
+ decimal point, then the remaining
+ digits without trailing zeroes. */
+ if (exponent >= 0)
+ {
+ size_t count = exponent + 1;
+ /* Note: count <= precision = ndigits. */
+ for (; count > 0; count--)
+ *p++ = digits[--ndigits];
+ if ((flags & FLAG_ALT) || ndigits > nzeroes)
+ {
+ *p++ = decimal_point_char ();
+ while (ndigits > nzeroes)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+ }
+ else
+ {
+ size_t count = -exponent - 1;
+ *p++ = '0';
+ *p++ = decimal_point_char ();
+ for (; count > 0; count--)
+ *p++ = '0';
+ while (ndigits > nzeroes)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+ }
+ else
+ {
+ /* Exponential notation. */
+ *p++ = digits[--ndigits];
+ if ((flags & FLAG_ALT) || ndigits > nzeroes)
+ {
+ *p++ = decimal_point_char ();
+ while (ndigits > nzeroes)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+ *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
+# if WIDE_CHAR_VERSION
+ {
+ static const wchar_t decimal_format[] =
+ { '%', '+', '.', '2', 'd', '\0' };
+ SNPRINTF (p, 6 + 1, decimal_format, exponent);
+ }
+# else
+ sprintf (p, "%+.2d", exponent);
+# endif
+ while (*p != '\0')
+ p++;
+ }
+
+ free (digits);
+ }
+ }
+ else
+ abort ();
+# else
+ /* arg is finite. */
+ abort ();
+# endif
+ }
+
+ END_LONG_DOUBLE_ROUNDING ();
+ }
+ }
+# if NEED_PRINTF_INFINITE_DOUBLE
+ else
+# endif
+# endif
+# if NEED_PRINTF_INFINITE_DOUBLE
+ {
+ /* Simpler than above: handle only NaN, Infinity, zero. */
+ double arg = a.arg[dp->arg_index].a.a_double;
+
+ if (isnan (arg))
+ {
+ if (dp->conversion >= 'A' && dp->conversion <= 'Z')
+ {
+ *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
+ }
+ else
+ {
+ *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
+ }
+ }
+ else
+ {
+ int sign = 0;
+
+ if (signbit (arg)) /* arg < 0.0L or negative zero */
+ {
+ sign = -1;
+ arg = -arg;
+ }
+
+ if (sign < 0)
+ *p++ = '-';
+ else if (flags & FLAG_SHOWSIGN)
+ *p++ = '+';
+ else if (flags & FLAG_SPACE)
+ *p++ = ' ';
+
+ if (arg > 0.0 && arg + arg == arg)
+ {
+ if (dp->conversion >= 'A' && dp->conversion <= 'Z')
+ {
+ *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
+ }
+ else
+ {
+ *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
+ }
+ }
+ else
+ {
+ if (!(arg == 0.0))
+ abort ();
+
+ pad_ptr = p;
+
+ if (dp->conversion == 'f' || dp->conversion == 'F')
+ {
+ *p++ = '0';
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ for (; precision > 0; precision--)
+ *p++ = '0';
+ }
+ }
+ else if (dp->conversion == 'e' || dp->conversion == 'E')
+ {
+ *p++ = '0';
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ for (; precision > 0; precision--)
+ *p++ = '0';
+ }
+ *p++ = dp->conversion; /* 'e' or 'E' */
+ *p++ = '+';
+ /* Produce the same number of exponent digits as
+ the native printf implementation. */
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ *p++ = '0';
+# endif
+ *p++ = '0';
+ *p++ = '0';
+ }
+ else if (dp->conversion == 'g' || dp->conversion == 'G')
+ {
+ *p++ = '0';
+ if (flags & FLAG_ALT)
+ {
+ size_t ndigits =
+ (precision > 0 ? precision - 1 : 0);
+ *p++ = decimal_point_char ();
+ for (; ndigits > 0; --ndigits)
+ *p++ = '0';
+ }
+ }
+ else
+ abort ();
+ }
+ }
+ }
+# endif
+
+ /* The generated string now extends from tmp to p, with the
+ zero padding insertion point being at pad_ptr. */
+ if (has_width && p - tmp < width)
+ {
+ size_t pad = width - (p - tmp);
+ CHAR_T *end = p + pad;
+
+ if (flags & FLAG_LEFT)
+ {
+ /* Pad with spaces on the right. */
+ for (; pad > 0; pad--)
+ *p++ = ' ';
+ }
+ else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
+ {
+ /* Pad with zeroes. */
+ CHAR_T *q = end;
+
+ while (p > pad_ptr)
+ *--q = *--p;
+ for (; pad > 0; pad--)
+ *p++ = '0';
+ }
+ else
+ {
+ /* Pad with spaces on the left. */
+ CHAR_T *q = end;
+
+ while (p > tmp)
+ *--q = *--p;
+ for (; pad > 0; pad--)
+ *p++ = ' ';
+ }
+
+ p = end;
+ }
+
+ {
+ size_t count = p - tmp;
+
+ if (count >= tmp_length)
+ /* tmp_length was incorrectly calculated - fix the
+ code above! */
+ abort ();
+
+ /* Make room for the result. */
+ if (count >= allocated - length)
+ {
+ size_t n = xsum (length, count);
+
+ ENSURE_ALLOCATION (n);
+ }
+
+ /* Append the result. */
+ memcpy (result + length, tmp, count * sizeof (CHAR_T));
+ if (tmp != tmpbuf)
+ free (tmp);
+ length += count;
+ }
+ }
+#endif
+#if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL
+ else if (dp->conversion == 'a' || dp->conversion == 'A')
+ {
+ arg_type type = a.arg[dp->arg_index].type;
+ int flags = dp->flags;
+ int has_width;
+ size_t width;
+ int has_precision;
+ size_t precision;
+ size_t tmp_length;
+ CHAR_T tmpbuf[700];
+ CHAR_T *tmp;
+ CHAR_T *pad_ptr;
+ CHAR_T *p;
+
+ has_width = 0;
+ width = 0;
+ if (dp->width_start != dp->width_end)
+ {
+ if (dp->width_arg_index != ARG_NONE)
+ {
+ int arg;
+
+ if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->width_arg_index].a.a_int;
+ if (arg < 0)
+ {
+ /* "A negative field width is taken as a '-' flag
+ followed by a positive field width." */
+ flags |= FLAG_LEFT;
+ width = (unsigned int) (-arg);
+ }
+ else
+ width = arg;
+ }
+ else
+ {
+ const CHAR_T *digitp = dp->width_start;
+
+ do
+ width = xsum (xtimes (width, 10), *digitp++ - '0');
+ while (digitp != dp->width_end);
+ }
+ has_width = 1;
+ }
+
+ has_precision = 0;
+ precision = 0;
+ if (dp->precision_start != dp->precision_end)
+ {
+ if (dp->precision_arg_index != ARG_NONE)
+ {
+ int arg;
+
+ if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->precision_arg_index].a.a_int;
+ /* "A negative precision is taken as if the precision
+ were omitted." */
+ if (arg >= 0)
+ {
+ precision = arg;
+ has_precision = 1;
+ }
+ }
+ else
+ {
+ const CHAR_T *digitp = dp->precision_start + 1;
+
+ precision = 0;
+ while (digitp != dp->precision_end)
+ precision = xsum (xtimes (precision, 10), *digitp++ - '0');
+ has_precision = 1;
+ }
+ }
+
+ /* Allocate a temporary buffer of sufficient size. */
+ if (type == TYPE_LONGDOUBLE)
+ tmp_length =
+ (unsigned int) ((LDBL_DIG + 1)
+ * 0.831 /* decimal -> hexadecimal */
+ )
+ + 1; /* turn floor into ceil */
+ else
+ tmp_length =
+ (unsigned int) ((DBL_DIG + 1)
+ * 0.831 /* decimal -> hexadecimal */
+ )
+ + 1; /* turn floor into ceil */
+ if (tmp_length < precision)
+ tmp_length = precision;
+ /* Account for sign, decimal point etc. */
+ tmp_length = xsum (tmp_length, 12);
+
+ if (tmp_length < width)
+ tmp_length = width;
+
+ tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
+
+ if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
+ tmp = tmpbuf;
+ else
+ {
+ size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
+
+ if (size_overflow_p (tmp_memsize))
+ /* Overflow, would lead to out of memory. */
+ goto out_of_memory;
+ tmp = (CHAR_T *) malloc (tmp_memsize);
+ if (tmp == NULL)
+ /* Out of memory. */
+ goto out_of_memory;
+ }
+
+ pad_ptr = NULL;
+ p = tmp;
+ if (type == TYPE_LONGDOUBLE)
+ {
+ long double arg = a.arg[dp->arg_index].a.a_longdouble;
+
+ if (isnanl (arg))
+ {
+ if (dp->conversion == 'A')
+ {
+ *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
+ }
+ else
+ {
+ *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
+ }
+ }
+ else
+ {
+ int sign = 0;
+ DECL_LONG_DOUBLE_ROUNDING
+
+ BEGIN_LONG_DOUBLE_ROUNDING ();
+
+ if (signbit (arg)) /* arg < 0.0L or negative zero */
+ {
+ sign = -1;
+ arg = -arg;
+ }
+
+ if (sign < 0)
+ *p++ = '-';
+ else if (flags & FLAG_SHOWSIGN)
+ *p++ = '+';
+ else if (flags & FLAG_SPACE)
+ *p++ = ' ';
+
+ if (arg > 0.0L && arg + arg == arg)
+ {
+ if (dp->conversion == 'A')
+ {
+ *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
+ }
+ else
+ {
+ *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
+ }
+ }
+ else
+ {
+ int exponent;
+ long double mantissa;
+
+ if (arg > 0.0L)
+ mantissa = printf_frexpl (arg, &exponent);
+ else
+ {
+ exponent = 0;
+ mantissa = 0.0L;
+ }
+
+ if (has_precision
+ && precision < (unsigned int) ((LDBL_DIG + 1) * 0.831) + 1)
+ {
+ /* Round the mantissa. */
+ long double tail = mantissa;
+ size_t q;
+
+ for (q = precision; ; q--)
+ {
+ int digit = (int) tail;
+ tail -= digit;
+ if (q == 0)
+ {
+ if (digit & 1 ? tail >= 0.5L : tail > 0.5L)
+ tail = 1 - tail;
+ else
+ tail = - tail;
+ break;
+ }
+ tail *= 16.0L;
+ }
+ if (tail != 0.0L)
+ for (q = precision; q > 0; q--)
+ tail *= 0.0625L;
+ mantissa += tail;
+ }
+
+ *p++ = '0';
+ *p++ = dp->conversion - 'A' + 'X';
+ pad_ptr = p;
+ {
+ int digit;
+
+ digit = (int) mantissa;
+ mantissa -= digit;
+ *p++ = '0' + digit;
+ if ((flags & FLAG_ALT)
+ || mantissa > 0.0L || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ /* This loop terminates because we assume
+ that FLT_RADIX is a power of 2. */
+ while (mantissa > 0.0L)
+ {
+ mantissa *= 16.0L;
+ digit = (int) mantissa;
+ mantissa -= digit;
+ *p++ = digit
+ + (digit < 10
+ ? '0'
+ : dp->conversion - 10);
+ if (precision > 0)
+ precision--;
+ }
+ while (precision > 0)
+ {
+ *p++ = '0';
+ precision--;
+ }
+ }
+ }
+ *p++ = dp->conversion - 'A' + 'P';
+# if WIDE_CHAR_VERSION
+ {
+ static const wchar_t decimal_format[] =
+ { '%', '+', 'd', '\0' };
+ SNPRINTF (p, 6 + 1, decimal_format, exponent);
+ }
+# else
+ sprintf (p, "%+d", exponent);
+# endif
+ while (*p != '\0')
+ p++;
+ }
+
+ END_LONG_DOUBLE_ROUNDING ();
+ }
+ }
+ else
+ {
+ double arg = a.arg[dp->arg_index].a.a_double;
+
+ if (isnan (arg))
+ {
+ if (dp->conversion == 'A')
+ {
+ *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
+ }
+ else
+ {
+ *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
+ }
+ }
+ else
+ {
+ int sign = 0;
+
+ if (signbit (arg)) /* arg < 0.0 or negative zero */
+ {
+ sign = -1;
+ arg = -arg;
+ }
+
+ if (sign < 0)
+ *p++ = '-';
+ else if (flags & FLAG_SHOWSIGN)
+ *p++ = '+';
+ else if (flags & FLAG_SPACE)
+ *p++ = ' ';
+
+ if (arg > 0.0 && arg + arg == arg)
+ {
+ if (dp->conversion == 'A')
+ {
+ *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
+ }
+ else
+ {
+ *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
+ }
+ }
+ else
+ {
+ int exponent;
+ double mantissa;
+
+ if (arg > 0.0)
+ mantissa = printf_frexp (arg, &exponent);
+ else
+ {
+ exponent = 0;
+ mantissa = 0.0;
+ }
+
+ if (has_precision
+ && precision < (unsigned int) ((DBL_DIG + 1) * 0.831) + 1)
+ {
+ /* Round the mantissa. */
+ double tail = mantissa;
+ size_t q;
+
+ for (q = precision; ; q--)
+ {
+ int digit = (int) tail;
+ tail -= digit;
+ if (q == 0)
+ {
+ if (digit & 1 ? tail >= 0.5 : tail > 0.5)
+ tail = 1 - tail;
+ else
+ tail = - tail;
+ break;
+ }
+ tail *= 16.0;
+ }
+ if (tail != 0.0)
+ for (q = precision; q > 0; q--)
+ tail *= 0.0625;
+ mantissa += tail;
+ }
+
+ *p++ = '0';
+ *p++ = dp->conversion - 'A' + 'X';
+ pad_ptr = p;
+ {
+ int digit;
+
+ digit = (int) mantissa;
+ mantissa -= digit;
+ *p++ = '0' + digit;
+ if ((flags & FLAG_ALT)
+ || mantissa > 0.0 || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ /* This loop terminates because we assume
+ that FLT_RADIX is a power of 2. */
+ while (mantissa > 0.0)
+ {
+ mantissa *= 16.0;
+ digit = (int) mantissa;
+ mantissa -= digit;
+ *p++ = digit
+ + (digit < 10
+ ? '0'
+ : dp->conversion - 10);
+ if (precision > 0)
+ precision--;
+ }
+ while (precision > 0)
+ {
+ *p++ = '0';
+ precision--;
+ }
+ }
+ }
+ *p++ = dp->conversion - 'A' + 'P';
+# if WIDE_CHAR_VERSION
+ {
+ static const wchar_t decimal_format[] =
+ { '%', '+', 'd', '\0' };
+ SNPRINTF (p, 6 + 1, decimal_format, exponent);
+ }
+# else
+ sprintf (p, "%+d", exponent);
+# endif
+ while (*p != '\0')
+ p++;
+ }
+ }
+ }
+ /* The generated string now extends from tmp to p, with the
+ zero padding insertion point being at pad_ptr. */
+ if (has_width && p - tmp < width)
+ {
+ size_t pad = width - (p - tmp);
+ CHAR_T *end = p + pad;
+
+ if (flags & FLAG_LEFT)
+ {
+ /* Pad with spaces on the right. */
+ for (; pad > 0; pad--)
+ *p++ = ' ';
+ }
+ else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
+ {
+ /* Pad with zeroes. */
+ CHAR_T *q = end;
+
+ while (p > pad_ptr)
+ *--q = *--p;
+ for (; pad > 0; pad--)
+ *p++ = '0';
+ }
+ else
+ {
+ /* Pad with spaces on the left. */
+ CHAR_T *q = end;
+
+ while (p > tmp)
+ *--q = *--p;
+ for (; pad > 0; pad--)
+ *p++ = ' ';
+ }
+
+ p = end;
+ }
+
+ {
+ size_t count = p - tmp;
+
+ if (count >= tmp_length)
+ /* tmp_length was incorrectly calculated - fix the
+ code above! */
+ abort ();
+
+ /* Make room for the result. */
+ if (count >= allocated - length)
+ {
+ size_t n = xsum (length, count);
+
+ ENSURE_ALLOCATION (n);
+ }
+
+ /* Append the result. */
+ memcpy (result + length, tmp, count * sizeof (CHAR_T));
+ if (tmp != tmpbuf)
+ free (tmp);
+ length += count;
+ }
+ }
+#endif
+ else
+ {
+ arg_type type = a.arg[dp->arg_index].type;
+ int flags = dp->flags;
+#if !USE_SNPRINTF || NEED_PRINTF_FLAG_ZERO
+ int has_width;
+ size_t width;
+#endif
+#if NEED_PRINTF_FLAG_ZERO
+ int pad_ourselves;
+#else
+# define pad_ourselves 0
+#endif
+ CHAR_T *fbp;
+ unsigned int prefix_count;
+ int prefixes[2];
+#if !USE_SNPRINTF
+ size_t tmp_length;
+ CHAR_T tmpbuf[700];
+ CHAR_T *tmp;
+#endif
+
+#if !USE_SNPRINTF || NEED_PRINTF_FLAG_ZERO
+ has_width = 0;
+ width = 0;
+ if (dp->width_start != dp->width_end)
+ {
+ if (dp->width_arg_index != ARG_NONE)
+ {
+ int arg;
+
+ if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->width_arg_index].a.a_int;
+ if (arg < 0)
+ {
+ /* "A negative field width is taken as a '-' flag
+ followed by a positive field width." */
+ flags |= FLAG_LEFT;
+ width = (unsigned int) (-arg);
+ }
+ else
+ width = arg;
+ }
+ else
+ {
+ const CHAR_T *digitp = dp->width_start;
+
+ do
+ width = xsum (xtimes (width, 10), *digitp++ - '0');
+ while (digitp != dp->width_end);
+ }
+ has_width = 1;
+ }
+#endif
+
+#if !USE_SNPRINTF
+ /* Allocate a temporary buffer of sufficient size for calling
+ sprintf. */
+ {
+ size_t precision;
+
+ precision = 6;
+ if (dp->precision_start != dp->precision_end)
+ {
+ if (dp->precision_arg_index != ARG_NONE)
+ {
+ int arg;
+
+ if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->precision_arg_index].a.a_int;
+ precision = (arg < 0 ? 0 : arg);
+ }
+ else
+ {
+ const CHAR_T *digitp = dp->precision_start + 1;
+
+ precision = 0;
+ while (digitp != dp->precision_end)
+ precision = xsum (xtimes (precision, 10), *digitp++ - '0');
+ }
+ }
+
+ switch (dp->conversion)
+ {
+
+ case 'd': case 'i': case 'u':
+# if HAVE_LONG_LONG_INT
+ if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+ * 0.30103 /* binary -> decimal */
+ )
+ + 1; /* turn floor into ceil */
+ else
+# endif
+ if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+ * 0.30103 /* binary -> decimal */
+ )
+ + 1; /* turn floor into ceil */
+ else
+ tmp_length =
+ (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+ * 0.30103 /* binary -> decimal */
+ )
+ + 1; /* turn floor into ceil */
+ if (tmp_length < precision)
+ tmp_length = precision;
+ /* Multiply by 2, as an estimate for FLAG_GROUP. */
+ tmp_length = xsum (tmp_length, tmp_length);
+ /* Add 1, to account for a leading sign. */
+ tmp_length = xsum (tmp_length, 1);
+ break;
+
+ case 'o':
+# if HAVE_LONG_LONG_INT
+ if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+ * 0.333334 /* binary -> octal */
+ )
+ + 1; /* turn floor into ceil */
+ else
+# endif
+ if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+ * 0.333334 /* binary -> octal */
+ )
+ + 1; /* turn floor into ceil */
+ else
+ tmp_length =
+ (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+ * 0.333334 /* binary -> octal */
+ )
+ + 1; /* turn floor into ceil */
+ if (tmp_length < precision)
+ tmp_length = precision;
+ /* Add 1, to account for a leading sign. */
+ tmp_length = xsum (tmp_length, 1);
+ break;
+
+ case 'x': case 'X':
+# if HAVE_LONG_LONG_INT
+ if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1; /* turn floor into ceil */
+ else
+# endif
+ if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1; /* turn floor into ceil */
+ else
+ tmp_length =
+ (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1; /* turn floor into ceil */
+ if (tmp_length < precision)
+ tmp_length = precision;
+ /* Add 2, to account for a leading sign or alternate form. */
+ tmp_length = xsum (tmp_length, 2);
+ break;
+
+ case 'f': case 'F':
+ if (type == TYPE_LONGDOUBLE)
+ tmp_length =
+ (unsigned int) (LDBL_MAX_EXP
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + 10; /* sign, decimal point etc. */
+ else
+ tmp_length =
+ (unsigned int) (DBL_MAX_EXP
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + 10; /* sign, decimal point etc. */
+ tmp_length = xsum (tmp_length, precision);
+ break;
+
+ case 'e': case 'E': case 'g': case 'G':
+ tmp_length =
+ 12; /* sign, decimal point, exponent etc. */
+ tmp_length = xsum (tmp_length, precision);
+ break;
+
+ case 'a': case 'A':
+ if (type == TYPE_LONGDOUBLE)
+ tmp_length =
+ (unsigned int) (LDBL_DIG
+ * 0.831 /* decimal -> hexadecimal */
+ )
+ + 1; /* turn floor into ceil */
+ else
+ tmp_length =
+ (unsigned int) (DBL_DIG
+ * 0.831 /* decimal -> hexadecimal */
+ )
+ + 1; /* turn floor into ceil */
+ if (tmp_length < precision)
+ tmp_length = precision;
+ /* Account for sign, decimal point etc. */
+ tmp_length = xsum (tmp_length, 12);
+ break;
+
+ case 'c':
+# if HAVE_WINT_T && !WIDE_CHAR_VERSION
+ if (type == TYPE_WIDE_CHAR)
+ tmp_length = MB_CUR_MAX;
+ else
+# endif
+ tmp_length = 1;
+ break;
+
+ case 's':
+# if HAVE_WCHAR_T
+ if (type == TYPE_WIDE_STRING)
+ {
+ tmp_length =
+ local_wcslen (a.arg[dp->arg_index].a.a_wide_string);
+
+# if !WIDE_CHAR_VERSION
+ tmp_length = xtimes (tmp_length, MB_CUR_MAX);
+# endif
+ }
+ else
+# endif
+ tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
+ break;
+
+ case 'p':
+ tmp_length =
+ (unsigned int) (sizeof (void *) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1 /* turn floor into ceil */
+ + 2; /* account for leading 0x */
+ break;
+
+ default:
+ abort ();
+ }
+
+ if (tmp_length < width)
+ tmp_length = width;
+
+ tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
+ }
+
+ if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
+ tmp = tmpbuf;
+ else
+ {
+ size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
+
+ if (size_overflow_p (tmp_memsize))
+ /* Overflow, would lead to out of memory. */
+ goto out_of_memory;
+ tmp = (CHAR_T *) malloc (tmp_memsize);
+ if (tmp == NULL)
+ /* Out of memory. */
+ goto out_of_memory;
+ }
+#endif
+
+ /* Decide whether to perform the padding ourselves. */
+#if NEED_PRINTF_FLAG_ZERO
+ switch (dp->conversion)
+ {
+ case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
+ case 'a': case 'A':
+ pad_ourselves = 1;
+ break;
+ default:
+ pad_ourselves = 0;
+ break;
+ }
+#endif
+
+ /* Construct the format string for calling snprintf or
+ sprintf. */
+ fbp = buf;
+ *fbp++ = '%';
+#if NEED_PRINTF_FLAG_GROUPING
+ /* The underlying implementation doesn't support the ' flag.
+ Produce no grouping characters in this case; this is
+ acceptable because the grouping is locale dependent. */
+#else
+ if (flags & FLAG_GROUP)
+ *fbp++ = '\'';
+#endif
+ if (flags & FLAG_LEFT)
+ *fbp++ = '-';
+ if (flags & FLAG_SHOWSIGN)
+ *fbp++ = '+';
+ if (flags & FLAG_SPACE)
+ *fbp++ = ' ';
+ if (flags & FLAG_ALT)
+ *fbp++ = '#';
+ if (!pad_ourselves)
+ {
+ if (flags & FLAG_ZERO)
+ *fbp++ = '0';
+ if (dp->width_start != dp->width_end)
+ {
+ size_t n = dp->width_end - dp->width_start;
+ memcpy (fbp, dp->width_start, n * sizeof (CHAR_T));
+ fbp += n;
+ }
+ }
+ if (dp->precision_start != dp->precision_end)
+ {
+ size_t n = dp->precision_end - dp->precision_start;
+ memcpy (fbp, dp->precision_start, n * sizeof (CHAR_T));
+ fbp += n;
+ }
+
+ switch (type)
+ {
+#if HAVE_LONG_LONG_INT
+ case TYPE_LONGLONGINT:
+ case TYPE_ULONGLONGINT:
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ *fbp++ = 'I';
+ *fbp++ = '6';
+ *fbp++ = '4';
+ break;
+# else
+ *fbp++ = 'l';
+ /*FALLTHROUGH*/
+# endif
+#endif
+ case TYPE_LONGINT:
+ case TYPE_ULONGINT:
+#if HAVE_WINT_T
+ case TYPE_WIDE_CHAR:
+#endif
+#if HAVE_WCHAR_T
+ case TYPE_WIDE_STRING:
+#endif
+ *fbp++ = 'l';
+ break;
+ case TYPE_LONGDOUBLE:
+ *fbp++ = 'L';
+ break;
+ default:
+ break;
+ }
+#if NEED_PRINTF_DIRECTIVE_F
+ if (dp->conversion == 'F')
+ *fbp = 'f';
+ else
+#endif
+ *fbp = dp->conversion;
+#if USE_SNPRINTF
+ fbp[1] = '%';
+ fbp[2] = 'n';
+ fbp[3] = '\0';
+#else
+ fbp[1] = '\0';
+#endif
+
+ /* Construct the arguments for calling snprintf or sprintf. */
+ prefix_count = 0;
+ if (!pad_ourselves && dp->width_arg_index != ARG_NONE)
+ {
+ if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+ abort ();
+ prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
+ }
+ if (dp->precision_arg_index != ARG_NONE)
+ {
+ if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+ abort ();
+ prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
+ }
+
+#if USE_SNPRINTF
+ /* Prepare checking whether snprintf returns the count
+ via %n. */
+ ENSURE_ALLOCATION (xsum (length, 1));
+ result[length] = '\0';
+#endif
+
+ for (;;)
+ {
+ size_t maxlen;
+ int count;
+ int retcount;
+
+ maxlen = allocated - length;
+ count = -1;
+ retcount = 0;
+
+#if USE_SNPRINTF
+ /* SNPRINTF can fail if maxlen > INT_MAX. */
+ if (maxlen > INT_MAX)
+ goto overflow;
+# define SNPRINTF_BUF(arg) \
+ switch (prefix_count) \
+ { \
+ case 0: \
+ retcount = SNPRINTF (result + length, maxlen, buf, \
+ arg, &count); \
+ break; \
+ case 1: \
+ retcount = SNPRINTF (result + length, maxlen, buf, \
+ prefixes[0], arg, &count); \
+ break; \
+ case 2: \
+ retcount = SNPRINTF (result + length, maxlen, buf, \
+ prefixes[0], prefixes[1], arg, \
+ &count); \
+ break; \
+ default: \
+ abort (); \
+ }
+#else
+# define SNPRINTF_BUF(arg) \
+ switch (prefix_count) \
+ { \
+ case 0: \
+ count = sprintf (tmp, buf, arg); \
+ break; \
+ case 1: \
+ count = sprintf (tmp, buf, prefixes[0], arg); \
+ break; \
+ case 2: \
+ count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
+ arg); \
+ break; \
+ default: \
+ abort (); \
+ }
+#endif
+
+ switch (type)
+ {
+ case TYPE_SCHAR:
+ {
+ int arg = a.arg[dp->arg_index].a.a_schar;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_UCHAR:
+ {
+ unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_SHORT:
+ {
+ int arg = a.arg[dp->arg_index].a.a_short;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_USHORT:
+ {
+ unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_INT:
+ {
+ int arg = a.arg[dp->arg_index].a.a_int;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_UINT:
+ {
+ unsigned int arg = a.arg[dp->arg_index].a.a_uint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_LONGINT:
+ {
+ long int arg = a.arg[dp->arg_index].a.a_longint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_ULONGINT:
+ {
+ unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#if HAVE_LONG_LONG_INT
+ case TYPE_LONGLONGINT:
+ {
+ long long int arg = a.arg[dp->arg_index].a.a_longlongint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_ULONGLONGINT:
+ {
+ unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+ case TYPE_DOUBLE:
+ {
+ double arg = a.arg[dp->arg_index].a.a_double;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_LONGDOUBLE:
+ {
+ long double arg = a.arg[dp->arg_index].a.a_longdouble;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_CHAR:
+ {
+ int arg = a.arg[dp->arg_index].a.a_char;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#if HAVE_WINT_T
+ case TYPE_WIDE_CHAR:
+ {
+ wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+ case TYPE_STRING:
+ {
+ const char *arg = a.arg[dp->arg_index].a.a_string;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#if HAVE_WCHAR_T
+ case TYPE_WIDE_STRING:
+ {
+ const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+ case TYPE_POINTER:
+ {
+ void *arg = a.arg[dp->arg_index].a.a_pointer;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ default:
+ abort ();
+ }
+
+#if USE_SNPRINTF
+ /* Portability: Not all implementations of snprintf()
+ are ISO C 99 compliant. Determine the number of
+ bytes that snprintf() has produced or would have
+ produced. */
+ if (count >= 0)
+ {
+ /* Verify that snprintf() has NUL-terminated its
+ result. */
+ if (count < maxlen && result[length + count] != '\0')
+ abort ();
+ /* Portability hack. */
+ if (retcount > count)
+ count = retcount;
+ }
+ else
+ {
+ /* snprintf() doesn't understand the '%n'
+ directive. */
+ if (fbp[1] != '\0')
+ {
+ /* Don't use the '%n' directive; instead, look
+ at the snprintf() return value. */
+ fbp[1] = '\0';
+ continue;
+ }
+ else
+ {
+ /* Look at the snprintf() return value. */
+ if (retcount < 0)
+ {
+ /* HP-UX 10.20 snprintf() is doubly deficient:
+ It doesn't understand the '%n' directive,
+ *and* it returns -1 (rather than the length
+ that would have been required) when the
+ buffer is too small. */
+ size_t bigger_need =
+ xsum (xtimes (allocated, 2), 12);
+ ENSURE_ALLOCATION (bigger_need);
+ continue;
+ }
+ else
+ count = retcount;
+ }
+ }
+#endif
+
+ /* Attempt to handle failure. */
+ if (count < 0)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = EINVAL;
+ return NULL;
+ }
+
+ /* Make room for the result. */
+ if (count >= maxlen)
+ {
+ /* Need at least count bytes. But allocate
+ proportionally, to avoid looping eternally if
+ snprintf() reports a too small count. */
+ size_t n =
+ xmax (xsum (length, count), xtimes (allocated, 2));
+
+ ENSURE_ALLOCATION (n);
+#if USE_SNPRINTF
+ continue;
+#else
+ maxlen = allocated - length;
+#endif
+ }
+
+ /* Perform padding. */
+#if NEED_PRINTF_FLAG_ZERO
+ if (pad_ourselves && has_width && count < width)
+ {
+# if USE_SNPRINTF
+ /* Make room for the result. */
+ if (width >= maxlen)
+ {
+ /* Need at least width bytes. But allocate
+ proportionally, to avoid looping eternally if
+ snprintf() reports a too small count. */
+ size_t n =
+ xmax (xsum (length + 1, width),
+ xtimes (allocated, 2));
+
+ length += count;
+ ENSURE_ALLOCATION (n);
+ length -= count;
+ maxlen = allocated - length; /* > width */
+ }
+ /* Here width < maxlen. */
+# endif
+ {
+# if USE_SNPRINTF
+ CHAR_T * const rp = result + length;
+# else
+ CHAR_T * const rp = tmp;
+# endif
+ CHAR_T *p = rp + count;
+ size_t pad = width - count;
+ CHAR_T *end = p + pad;
+ CHAR_T *pad_ptr = (*rp == '-' ? rp + 1 : rp);
+ /* No zero-padding of "inf" and "nan". */
+ if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z')
+ || (*pad_ptr >= 'a' && *pad_ptr <= 'z'))
+ pad_ptr = NULL;
+ /* The generated string now extends from rp to p,
+ with the zero padding insertion point being at
+ pad_ptr. */
+
+ if (flags & FLAG_LEFT)
+ {
+ /* Pad with spaces on the right. */
+ for (; pad > 0; pad--)
+ *p++ = ' ';
+ }
+ else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
+ {
+ /* Pad with zeroes. */
+ CHAR_T *q = end;
+
+ while (p > pad_ptr)
+ *--q = *--p;
+ for (; pad > 0; pad--)
+ *p++ = '0';
+ }
+ else
+ {
+ /* Pad with spaces on the left. */
+ CHAR_T *q = end;
+
+ while (p > rp)
+ *--q = *--p;
+ for (; pad > 0; pad--)
+ *p++ = ' ';
+ }
+
+ count = width; /* = count + pad = end - rp */
+ }
+ }
+#endif
+
+#if !USE_SNPRINTF
+ if (count >= tmp_length)
+ /* tmp_length was incorrectly calculated - fix the
+ code above! */
+ abort ();
+#endif
+
+ /* Here still count < maxlen. */
+
+#if USE_SNPRINTF
+ /* The snprintf() result did fit. */
+#else
+ /* Append the sprintf() result. */
+ memcpy (result + length, tmp, count * sizeof (CHAR_T));
+ if (tmp != tmpbuf)
+ free (tmp);
+#endif
+
+#if NEED_PRINTF_DIRECTIVE_F
+ if (dp->conversion == 'F')
+ {
+ /* Convert the %f result to upper case for %F. */
+ CHAR_T *rp = result + length;
+ size_t rc;
+ for (rc = count; rc > 0; rc--, rp++)
+ if (*rp >= 'a' && *rp <= 'z')
+ *rp = *rp - 'a' + 'A';
+ }
+#endif
+
+ length += count;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Add the final NUL. */
+ ENSURE_ALLOCATION (xsum (length, 1));
+ result[length] = '\0';
+
+ if (result != resultbuf && length + 1 < allocated)
+ {
+ /* Shrink the allocated memory if possible. */
+ CHAR_T *memory;
+
+ memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T));
+ if (memory != NULL)
+ result = memory;
+ }
+
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ *lengthp = length;
+ /* Note that we can produce a big string of a length > INT_MAX. POSIX
+ says that snprintf() fails with errno = EOVERFLOW in this case, but
+ that's only because snprintf() returns an 'int'. This function does
+ not have this limitation. */
+ return result;
+
+ overflow:
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = EOVERFLOW;
+ return NULL;
+
+ out_of_memory:
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ out_of_memory_1:
+ CLEANUP ();
+ errno = ENOMEM;
+ return NULL;
+ }
+}
+
+#undef SNPRINTF
+#undef USE_SNPRINTF
+#undef PRINTF_PARSE
+#undef DIRECTIVES
+#undef DIRECTIVE
+#undef CHAR_T
+#undef VASNPRINTF
diff --git a/lib/vasnprintf.h b/lib/vasnprintf.h
new file mode 100644
index 0000000..7a0c01f
--- /dev/null
+++ b/lib/vasnprintf.h
@@ -0,0 +1,81 @@
+/* vsprintf with automatic memory allocation.
+ Copyright (C) 2002-2004, 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. */
+
+#ifndef _VASNPRINTF_H
+#define _VASNPRINTF_H
+
+/* Get va_list. */
+#include <stdarg.h>
+
+/* Get size_t. */
+#include <stddef.h>
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
+# define __attribute__(Spec) /* empty */
+# endif
+/* The __-protected variants of `format' and `printf' attributes
+ are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+# define __format__ format
+# define __printf__ printf
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Write formatted output to a string dynamically allocated with malloc().
+ You can pass a preallocated buffer for the result in RESULTBUF and its
+ size in *LENGTHP; otherwise you pass RESULTBUF = NULL.
+ If successful, return the address of the string (this may be = RESULTBUF
+ if no dynamic memory allocation was necessary) and set *LENGTHP to the
+ number of resulting bytes, excluding the trailing NUL. Upon error, set
+ errno and return NULL.
+
+ When dynamic memory allocation occurs, the preallocated buffer is left
+ alone (with possibly modified contents). This makes it possible to use
+ a statically allocated or stack-allocated buffer, like this:
+
+ char buf[100];
+ size_t len = sizeof (buf);
+ char *output = vasnprintf (buf, &len, format, args);
+ if (output == NULL)
+ ... error handling ...;
+ else
+ {
+ ... use the output string ...;
+ if (output != buf)
+ free (output);
+ }
+ */
+#if REPLACE_VASNPRINTF
+# define asnprintf rpl_asnprintf
+# define vasnprintf rpl_vasnprintf
+#endif
+extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+extern char * vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
+ __attribute__ ((__format__ (__printf__, 3, 0)));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VASNPRINTF_H */
diff --git a/lib/verify.h b/lib/verify.h
new file mode 100644
index 0000000..d603b17
--- /dev/null
+++ b/lib/verify.h
@@ -0,0 +1,141 @@
+/* Compile-time assert-like macros.
+
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */
+
+#ifndef VERIFY_H
+# define VERIFY_H 1
+
+/* Each of these macros verifies that its argument R is nonzero. To
+ be portable, R should be an integer constant expression. Unlike
+ assert (R), there is no run-time overhead.
+
+ There are two macros, since no single macro can be used in all
+ contexts in C. verify_true (R) is for scalar contexts, including
+ integer constant expression contexts. verify (R) is for declaration
+ contexts, e.g., the top level.
+
+ Symbols ending in "__" are private to this header.
+
+ The code below uses several ideas.
+
+ * The first step is ((R) ? 1 : -1). Given an expression R, of
+ integral or boolean or floating-point type, this yields an
+ expression of integral type, whose value is later verified to be
+ constant and nonnegative.
+
+ * Next this expression W is wrapped in a type
+ struct verify_type__ { unsigned int verify_error_if_negative_size__: W; }.
+ If W is negative, this yields a compile-time error. No compiler can
+ deal with a bit-field of negative size.
+
+ One might think that an array size check would have the same
+ effect, that is, that the type struct { unsigned int dummy[W]; }
+ would work as well. However, inside a function, some compilers
+ (such as C++ compilers and GNU C) allow local parameters and
+ variables inside array size expressions. With these compilers,
+ an array size check would not properly diagnose this misuse of
+ the verify macro:
+
+ void function (int n) { verify (n < 0); }
+
+ * For the verify macro, the struct verify_type__ will need to
+ somehow be embedded into a declaration. To be portable, this
+ declaration must declare an object, a constant, a function, or a
+ typedef name. If the declared entity uses the type directly,
+ such as in
+
+ struct dummy {...};
+ typedef struct {...} dummy;
+ extern struct {...} *dummy;
+ extern void dummy (struct {...} *);
+ extern struct {...} *dummy (void);
+
+ two uses of the verify macro would yield colliding declarations
+ if the entity names are not disambiguated. A workaround is to
+ attach the current line number to the entity name:
+
+ #define GL_CONCAT0(x, y) x##y
+ #define GL_CONCAT(x, y) GL_CONCAT0 (x, y)
+ extern struct {...} * GL_CONCAT(dummy,__LINE__);
+
+ But this has the problem that two invocations of verify from
+ within the same macro would collide, since the __LINE__ value
+ would be the same for both invocations.
+
+ A solution is to use the sizeof operator. It yields a number,
+ getting rid of the identity of the type. Declarations like
+
+ extern int dummy [sizeof (struct {...})];
+ extern void dummy (int [sizeof (struct {...})]);
+ extern int (*dummy (void)) [sizeof (struct {...})];
+
+ can be repeated.
+
+ * Should the implementation use a named struct or an unnamed struct?
+ Which of the following alternatives can be used?
+
+ extern int dummy [sizeof (struct {...})];
+ extern int dummy [sizeof (struct verify_type__ {...})];
+ extern void dummy (int [sizeof (struct {...})]);
+ extern void dummy (int [sizeof (struct verify_type__ {...})]);
+ extern int (*dummy (void)) [sizeof (struct {...})];
+ extern int (*dummy (void)) [sizeof (struct verify_type__ {...})];
+
+ In the second and sixth case, the struct type is exported to the
+ outer scope; two such declarations therefore collide. GCC warns
+ about the first, third, and fourth cases. So the only remaining
+ possibility is the fifth case:
+
+ extern int (*dummy (void)) [sizeof (struct {...})];
+
+ * This implementation exploits the fact that GCC does not warn about
+ the last declaration mentioned above. If a future version of GCC
+ introduces a warning for this, the problem could be worked around
+ by using code specialized to GCC, e.g.,:
+
+ #if 4 <= __GNUC__
+ # define verify(R) \
+ extern int (* verify_function__ (void)) \
+ [__builtin_constant_p (R) && (R) ? 1 : -1]
+ #endif
+
+ * In C++, any struct definition inside sizeof is invalid.
+ Use a template type to work around the problem. */
+
+
+/* Verify requirement R at compile-time, as an integer constant expression.
+ Return 1. */
+
+# ifdef __cplusplus
+template <int w>
+ struct verify_type__ { unsigned int verify_error_if_negative_size__: w; };
+# define verify_true(R) \
+ (!!sizeof (verify_type__<(R) ? 1 : -1>))
+# else
+# define verify_true(R) \
+ (!!sizeof \
+ (struct { unsigned int verify_error_if_negative_size__: (R) ? 1 : -1; }))
+# endif
+
+/* Verify requirement R at compile-time, as a declaration without a
+ trailing ';'. */
+
+# define verify(R) extern int (* verify_function__ (void)) [verify_true (R)]
+
+#endif
diff --git a/lib/version-etc-fsf.c b/lib/version-etc-fsf.c
new file mode 100644
index 0000000..f25eb65
--- /dev/null
+++ b/lib/version-etc-fsf.c
@@ -0,0 +1,31 @@
+/* Variable with FSF copyright information, for version-etc.
+ Copyright (C) 1999-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 Jim Meyering. */
+
+#include <config.h>
+
+/* Specification. */
+#include "version-etc.h"
+
+/* Default copyright goes to the FSF. */
+
+const char version_etc_copyright[] =
+ /* Do *not* mark this string for translation. %s is a copyright
+ symbol suitable for this locale, and %d is the copyright
+ year. */
+ "Copyright %s %d Free Software Foundation, Inc.";
diff --git a/lib/version-etc.c b/lib/version-etc.c
new file mode 100644
index 0000000..1ae82c4
--- /dev/null
+++ b/lib/version-etc.c
@@ -0,0 +1,173 @@
+/* Utility to help print --version output in a consistent format.
+ Copyright (C) 1999-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 Jim Meyering. */
+
+#include <config.h>
+
+/* Specification. */
+#include "version-etc.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if USE_UNLOCKED_IO
+# include "unlocked-io.h"
+#endif
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+enum { COPYRIGHT_YEAR = 2007 };
+
+/* Like version_etc, below, but with the NULL-terminated author list
+ provided via a variable of type va_list. */
+void
+version_etc_va (FILE *stream,
+ const char *command_name, const char *package,
+ const char *version, va_list authors)
+{
+ size_t n_authors;
+
+ /* Count the number of authors. */
+ {
+ va_list tmp_authors;
+
+ va_copy (tmp_authors, authors);
+
+ n_authors = 0;
+ while (va_arg (tmp_authors, const char *) != NULL)
+ ++n_authors;
+ }
+
+ if (command_name)
+ fprintf (stream, "%s (%s) %s\n", command_name, package, version);
+ else
+ fprintf (stream, "%s %s\n", package, version);
+
+ /* TRANSLATORS: Translate "(C)" to the copyright symbol
+ (C-in-a-circle), if this symbol is available in the user's
+ locale. Otherwise, do not translate "(C)"; leave it as-is. */
+ fprintf (stream, version_etc_copyright, _("(C)"), COPYRIGHT_YEAR);
+
+ fputs (_("\
+\n\
+License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>\n\
+This is free software: you are free to change and redistribute it.\n\
+There is NO WARRANTY, to the extent permitted by law.\n\
+\n\
+"),
+ stream);
+
+ switch (n_authors)
+ {
+ case 0:
+ /* The caller must provide at least one author name. */
+ abort ();
+ case 1:
+ /* TRANSLATORS: %s denotes an author name. */
+ vfprintf (stream, _("Written by %s.\n"), authors);
+ break;
+ case 2:
+ /* TRANSLATORS: Each %s denotes an author name. */
+ vfprintf (stream, _("Written by %s and %s.\n"), authors);
+ break;
+ case 3:
+ /* TRANSLATORS: Each %s denotes an author name. */
+ vfprintf (stream, _("Written by %s, %s, and %s.\n"), authors);
+ break;
+ case 4:
+ /* TRANSLATORS: Each %s denotes an author name.
+ You can use line breaks, estimating that each author name occupies
+ ca. 16 screen columns and that a screen line has ca. 80 columns. */
+ vfprintf (stream, _("Written by %s, %s, %s,\nand %s.\n"), authors);
+ break;
+ case 5:
+ /* TRANSLATORS: Each %s denotes an author name.
+ You can use line breaks, estimating that each author name occupies
+ ca. 16 screen columns and that a screen line has ca. 80 columns. */
+ vfprintf (stream, _("Written by %s, %s, %s,\n%s, and %s.\n"), authors);
+ break;
+ case 6:
+ /* TRANSLATORS: Each %s denotes an author name.
+ You can use line breaks, estimating that each author name occupies
+ ca. 16 screen columns and that a screen line has ca. 80 columns. */
+ vfprintf (stream, _("Written by %s, %s, %s,\n%s, %s, and %s.\n"),
+ authors);
+ break;
+ case 7:
+ /* TRANSLATORS: Each %s denotes an author name.
+ You can use line breaks, estimating that each author name occupies
+ ca. 16 screen columns and that a screen line has ca. 80 columns. */
+ vfprintf (stream, _("Written by %s, %s, %s,\n%s, %s, %s, and %s.\n"),
+ authors);
+ break;
+ case 8:
+ /* TRANSLATORS: Each %s denotes an author name.
+ You can use line breaks, estimating that each author name occupies
+ ca. 16 screen columns and that a screen line has ca. 80 columns. */
+ vfprintf (stream, _("\
+Written by %s, %s, %s,\n%s, %s, %s, %s,\nand %s.\n"),
+ authors);
+ break;
+ case 9:
+ /* TRANSLATORS: Each %s denotes an author name.
+ You can use line breaks, estimating that each author name occupies
+ ca. 16 screen columns and that a screen line has ca. 80 columns. */
+ vfprintf (stream, _("\
+Written by %s, %s, %s,\n%s, %s, %s, %s,\n%s, and %s.\n"),
+ authors);
+ break;
+ default:
+ /* 10 or more authors. Use an abbreviation, since the human reader
+ will probably not want to read the entire list anyway. */
+ /* TRANSLATORS: Each %s denotes an author name.
+ You can use line breaks, estimating that each author name occupies
+ ca. 16 screen columns and that a screen line has ca. 80 columns. */
+ vfprintf (stream, _("\
+Written by %s, %s, %s,\n%s, %s, %s, %s,\n%s, %s, and others.\n"),
+ authors);
+ break;
+ }
+ va_end (authors);
+}
+
+
+/* Display the --version information the standard way.
+
+ If COMMAND_NAME is NULL, the PACKAGE is asumed to be the name of
+ the program. The formats are therefore:
+
+ PACKAGE VERSION
+
+ or
+
+ COMMAND_NAME (PACKAGE) VERSION.
+
+ The author names are passed as separate arguments, with an additional
+ NULL argument at the end. */
+void
+version_etc (FILE *stream,
+ const char *command_name, const char *package,
+ const char *version, /* const char *author1, ...*/ ...)
+{
+ va_list authors;
+
+ va_start (authors, version);
+ version_etc_va (stream, command_name, package, version, authors);
+}
diff --git a/lib/version-etc.h b/lib/version-etc.h
new file mode 100644
index 0000000..84da535
--- /dev/null
+++ b/lib/version-etc.h
@@ -0,0 +1,37 @@
+/* Utility to help print --version output in a consistent format.
+ Copyright (C) 1999, 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 Jim Meyering. */
+
+#ifndef VERSION_ETC_H
+# define VERSION_ETC_H 1
+
+# include <stdarg.h>
+# include <stdio.h>
+
+extern const char version_etc_copyright[];
+
+extern void version_etc_va (FILE *stream,
+ const char *command_name, const char *package,
+ const char *version, va_list authors);
+
+extern void version_etc (FILE *stream,
+ const char *command_name, const char *package,
+ const char *version,
+ /* const char *author1, ...*/ ...);
+
+#endif /* VERSION_ETC_H */
diff --git a/lib/vsnprintf.c b/lib/vsnprintf.c
new file mode 100644
index 0000000..4f841fc
--- /dev/null
+++ b/lib/vsnprintf.c
@@ -0,0 +1,76 @@
+/* Formatted output to strings.
+ Copyright (C) 2004, 2006-2007 Free Software Foundation, Inc.
+ Written by Simon Josefsson and Yoann Vandoorselaere <yoann@prelude-ids.org>.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include <stdio.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vasnprintf.h"
+
+/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */
+#ifndef EOVERFLOW
+# define EOVERFLOW E2BIG
+#endif
+
+/* Print formatted output to string STR. Similar to vsprintf, but
+ additional length SIZE limit how much is written into STR. Returns
+ string length of formatted string (which may be larger than SIZE).
+ STR may be NULL, in which case nothing will be written. On error,
+ return a negative value. */
+int
+vsnprintf (char *str, size_t size, const char *format, va_list args)
+{
+ char *output;
+ size_t len;
+ size_t lenbuf = size;
+
+ output = vasnprintf (str, &lenbuf, format, args);
+ len = lenbuf;
+
+ if (!output)
+ return -1;
+
+ if (output != str)
+ {
+ if (size)
+ {
+ size_t pruned_len = (len < size ? len : size - 1);
+ memcpy (str, output, pruned_len);
+ str[pruned_len] = '\0';
+ }
+
+ free (output);
+ }
+
+ if (len > INT_MAX)
+ {
+ errno = EOVERFLOW;
+ return -1;
+ }
+
+ return len;
+}
diff --git a/lib/wchar_.h b/lib/wchar_.h
new file mode 100644
index 0000000..2a71b8b
--- /dev/null
+++ b/lib/wchar_.h
@@ -0,0 +1,50 @@
+/* A substitute for ISO C99 <wchar.h>, for platforms that have issues.
+
+ 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. */
+
+/* Written by Eric Blake. */
+
+/*
+ * ISO C 99 <wchar.h> for platforms that have issues.
+ * <http://www.opengroup.org/susv3xbd/wchar.h.html>
+ *
+ * For now, this just ensures proper prerequisite inclusion order.
+ */
+
+#ifndef _GL_WCHAR_H
+
+/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
+ <wchar.h>.
+ BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
+ included before <wchar.h>. */
+#include <stddef.h>
+#include <stdio.h>
+#include <time.h>
+
+/* Include the original <wchar.h>. */
+/* The include_next requires a split double-inclusion guard. */
+#if @HAVE_INCLUDE_NEXT@
+# include_next <wchar.h>
+#else
+# include @ABSOLUTE_WCHAR_H@
+#endif
+
+#ifndef _GL_WCHAR_H
+#define _GL_WCHAR_H
+
+#endif /* _GL_WCHAR_H */
+#endif /* _GL_WCHAR_H */
diff --git a/lib/wctype_.h b/lib/wctype_.h
new file mode 100644
index 0000000..ebbfca4
--- /dev/null
+++ b/lib/wctype_.h
@@ -0,0 +1,165 @@
+/* A substitute for ISO C99 <wctype.h>, for platforms that lack it.
+
+ Copyright (C) 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. */
+
+/* Written by Bruno Haible and Paul Eggert. */
+
+/*
+ * ISO C 99 <wctype.h> for platforms that lack it.
+ * <http://www.opengroup.org/susv3xbd/wctype.h.html>
+ *
+ * iswctype, towctrans, towlower, towupper, wctrans, wctype,
+ * wctrans_t, and wctype_t are not yet implemented.
+ */
+
+#ifndef _GL_WCTYPE_H
+
+#if @HAVE_WINT_T@
+/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.
+ Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
+ <wchar.h>.
+ BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
+ included before <wchar.h>. */
+# include <stddef.h>
+# include <stdio.h>
+# include <time.h>
+# include <wchar.h>
+#endif
+
+/* Include the original <wctype.h> if it exists.
+ BeOS 5 has the functions but no <wctype.h>. */
+/* The include_next requires a split double-inclusion guard. */
+#if @HAVE_WCTYPE_H@
+# if @HAVE_INCLUDE_NEXT@
+# include_next <wctype.h>
+# else
+# include @ABSOLUTE_WCTYPE_H@
+# endif
+#endif
+
+#ifndef _GL_WCTYPE_H
+#define _GL_WCTYPE_H
+
+#if @HAVE_WINT_T@
+typedef wint_t __wctype_wint_t;
+#else
+typedef int __wctype_wint_t;
+#endif
+
+/* FreeBSD 4.4 to 4.11 has <wctype.h> but lacks the functions.
+ Assume all 12 functions are implemented the same way, or not at all. */
+#if ! @HAVE_ISWCNTRL@
+
+/* IRIX 5.3 has macros but no functions, its isw* macros refer to an
+ undefined variable _ctmp_ and to <ctype.h> macros like _P, and they
+ refer to system functions like _iswctype that are not in the
+ standard C library. Rather than try to get ancient buggy
+ implementations like this to work, just disable them. */
+# undef iswalnum
+# undef iswalpha
+# undef iswblank
+# undef iswcntrl
+# undef iswdigit
+# undef iswgraph
+# undef iswlower
+# undef iswprint
+# undef iswpunct
+# undef iswspace
+# undef iswupper
+# undef iswxdigit
+
+static inline int
+iswalnum (__wctype_wint_t wc)
+{
+ return ((wc >= '0' && wc <= '9')
+ || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z'));
+}
+
+static inline int
+iswalpha (__wctype_wint_t wc)
+{
+ return (wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z';
+}
+
+static inline int
+iswblank (__wctype_wint_t wc)
+{
+ return wc == ' ' || wc == '\t';
+}
+
+static inline int
+iswcntrl (__wctype_wint_t wc)
+{
+ return (wc & ~0x1f) == 0 || wc == 0x7f;
+}
+
+static inline int
+iswdigit (__wctype_wint_t wc)
+{
+ return wc >= '0' && wc <= '9';
+}
+
+static inline int
+iswgraph (__wctype_wint_t wc)
+{
+ return wc >= '!' && wc <= '~';
+}
+
+static inline int
+iswlower (__wctype_wint_t wc)
+{
+ return wc >= 'a' && wc <= 'z';
+}
+
+static inline int
+iswprint (__wctype_wint_t wc)
+{
+ return wc >= ' ' && wc <= '~';
+}
+
+static inline int
+iswpunct (__wctype_wint_t wc)
+{
+ return (wc >= '!' && wc <= '~'
+ && !((wc >= '0' && wc <= '9')
+ || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z')));
+}
+
+static inline int
+iswspace (__wctype_wint_t wc)
+{
+ return (wc == ' ' || wc == '\t'
+ || wc == '\n' || wc == '\v' || wc == '\f' || wc == '\r');
+}
+
+static inline int
+iswupper (__wctype_wint_t wc)
+{
+ return wc >= 'A' && wc <= 'Z';
+}
+
+static inline int
+iswxdigit (__wctype_wint_t wc)
+{
+ return ((wc >= '0' && wc <= '9')
+ || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'F'));
+}
+
+# endif /* ! HAVE_ISWCNTRL */
+
+#endif /* _GL_WCTYPE_H */
+#endif /* _GL_WCTYPE_H */
diff --git a/lib/xalloc-die.c b/lib/xalloc-die.c
new file mode 100644
index 0000000..090f060
--- /dev/null
+++ b/lib/xalloc-die.c
@@ -0,0 +1,42 @@
+/* Report a memory allocation failure and exit.
+
+ Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2006 Free
+ Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+#include "xalloc.h"
+
+#include <stdlib.h>
+
+#include "error.h"
+#include "exitfail.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+void
+xalloc_die (void)
+{
+ error (exit_failure, 0, "%s", _("memory exhausted"));
+
+ /* The `noreturn' cannot be given to error, since it may return if
+ its first argument is 0. To help compilers understand the
+ xalloc_die does not return, call abort. Also, the abort is a
+ safety feature if exit_failure is 0 (which shouldn't happen). */
+ abort ();
+}
diff --git a/lib/xalloc.h b/lib/xalloc.h
new file mode 100644
index 0000000..0c6d8dc
--- /dev/null
+++ b/lib/xalloc.h
@@ -0,0 +1,271 @@
+/* xalloc.h -- malloc with out-of-memory checking
+
+ Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000, 2003, 2004, 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. */
+
+#ifndef XALLOC_H_
+# define XALLOC_H_
+
+# include <stddef.h>
+
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+
+# ifndef __attribute__
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
+# define __attribute__(x)
+# endif
+# endif
+
+# ifndef ATTRIBUTE_NORETURN
+# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
+# endif
+
+/* This function is always triggered when memory is exhausted.
+ It must be defined by the application, either explicitly
+ or by using gnulib's xalloc-die module. This is the
+ function to call when one wants the program to die because of a
+ memory allocation failure. */
+extern void xalloc_die (void) ATTRIBUTE_NORETURN;
+
+void *xmalloc (size_t s);
+void *xzalloc (size_t s);
+void *xcalloc (size_t n, size_t s);
+void *xrealloc (void *p, size_t s);
+void *x2realloc (void *p, size_t *pn);
+void *xmemdup (void const *p, size_t s);
+char *xstrdup (char const *str);
+
+/* Return 1 if an array of N objects, each of size S, cannot exist due
+ to size arithmetic overflow. S must be positive and N must be
+ nonnegative. This is a macro, not an inline function, so that it
+ works correctly even when SIZE_MAX < N.
+
+ By gnulib convention, SIZE_MAX represents overflow in size
+ calculations, so the conservative dividend to use here is
+ SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
+ However, malloc (SIZE_MAX) fails on all known hosts where
+ sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
+ exactly-SIZE_MAX allocations on such hosts; this avoids a test and
+ branch when S is known to be 1. */
+# define xalloc_oversized(n, s) \
+ ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
+
+
+/* In the following macros, T must be an elementary or structure/union or
+ typedef'ed type, or a pointer to such a type. To apply one of the
+ following macros to a function pointer or array type, you need to typedef
+ it first and use the typedef name. */
+
+/* Allocate an object of type T dynamically, with error checking. */
+/* extern t *XMALLOC (typename t); */
+# define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
+
+/* Allocate memory for N elements of type T, with error checking. */
+/* extern t *XNMALLOC (size_t n, typename t); */
+# define XNMALLOC(n, t) \
+ ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))))
+
+/* Allocate an object of type T dynamically, with error checking,
+ and zero it. */
+/* extern t *XZALLOC (typename t); */
+# define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
+
+/* Allocate memory for N elements of type T, with error checking,
+ and zero it. */
+/* extern t *XCALLOC (size_t n, typename t); */
+# define XCALLOC(n, t) \
+ ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))))
+
+
+# if HAVE_INLINE
+# define static_inline static inline
+# else
+ void *xnmalloc (size_t n, size_t s);
+ void *xnrealloc (void *p, size_t n, size_t s);
+ void *x2nrealloc (void *p, size_t *pn, size_t s);
+ char *xcharalloc (size_t n);
+# endif
+
+# ifdef static_inline
+
+/* Allocate an array of N objects, each with S bytes of memory,
+ dynamically, with error checking. S must be nonzero. */
+
+static_inline void *
+xnmalloc (size_t n, size_t s)
+{
+ if (xalloc_oversized (n, s))
+ xalloc_die ();
+ return xmalloc (n * s);
+}
+
+/* Change the size of an allocated block of memory P to an array of N
+ objects each of S bytes, with error checking. S must be nonzero. */
+
+static_inline void *
+xnrealloc (void *p, size_t n, size_t s)
+{
+ if (xalloc_oversized (n, s))
+ xalloc_die ();
+ return xrealloc (p, n * s);
+}
+
+/* If P is null, allocate a block of at least *PN such objects;
+ otherwise, reallocate P so that it contains more than *PN objects
+ each of S bytes. *PN must be nonzero unless P is null, and S must
+ be nonzero. Set *PN to the new number of objects, and return the
+ pointer to the new block. *PN is never set to zero, and the
+ returned pointer is never null.
+
+ Repeated reallocations are guaranteed to make progress, either by
+ allocating an initial block with a nonzero size, or by allocating a
+ larger block.
+
+ In the following implementation, nonzero sizes are increased by a
+ factor of approximately 1.5 so that repeated reallocations have
+ O(N) overall cost rather than O(N**2) cost, but the
+ specification for this function does not guarantee that rate.
+
+ Here is an example of use:
+
+ int *p = NULL;
+ size_t used = 0;
+ size_t allocated = 0;
+
+ void
+ append_int (int value)
+ {
+ if (used == allocated)
+ p = x2nrealloc (p, &allocated, sizeof *p);
+ p[used++] = value;
+ }
+
+ This causes x2nrealloc to allocate a block of some nonzero size the
+ first time it is called.
+
+ To have finer-grained control over the initial size, set *PN to a
+ nonzero value before calling this function with P == NULL. For
+ example:
+
+ int *p = NULL;
+ size_t used = 0;
+ size_t allocated = 0;
+ size_t allocated1 = 1000;
+
+ void
+ append_int (int value)
+ {
+ if (used == allocated)
+ {
+ p = x2nrealloc (p, &allocated1, sizeof *p);
+ allocated = allocated1;
+ }
+ p[used++] = value;
+ }
+
+ */
+
+static_inline void *
+x2nrealloc (void *p, size_t *pn, size_t s)
+{
+ size_t n = *pn;
+
+ if (! p)
+ {
+ if (! n)
+ {
+ /* The approximate size to use for initial small allocation
+ requests, when the invoking code specifies an old size of
+ zero. 64 bytes is the largest "small" request for the
+ GNU C library malloc. */
+ enum { DEFAULT_MXFAST = 64 };
+
+ n = DEFAULT_MXFAST / s;
+ n += !n;
+ }
+ }
+ else
+ {
+ /* Set N = ceil (1.5 * N) so that progress is made if N == 1.
+ Check for overflow, so that N * S stays in size_t range.
+ The check is slightly conservative, but an exact check isn't
+ worth the trouble. */
+ if ((size_t) -1 / 3 * 2 / s <= n)
+ xalloc_die ();
+ n += (n + 1) / 2;
+ }
+
+ *pn = n;
+ return xrealloc (p, n * s);
+}
+
+/* Return a pointer to a new buffer of N bytes. This is like xmalloc,
+ except it returns char *. */
+
+static_inline char *
+xcharalloc (size_t n)
+{
+ return XNMALLOC (n, char);
+}
+
+# endif
+
+# ifdef __cplusplus
+}
+
+/* C++ does not allow conversions from void * to other pointer types
+ without a cast. Use templates to work around the problem when
+ possible. */
+
+template <typename T> inline T *
+xrealloc (T *p, size_t s)
+{
+ return (T *) xrealloc ((void *) p, s);
+}
+
+template <typename T> inline T *
+xnrealloc (T *p, size_t n, size_t s)
+{
+ return (T *) xnrealloc ((void *) p, n, s);
+}
+
+template <typename T> inline T *
+x2realloc (T *p, size_t *pn)
+{
+ return (T *) x2realloc ((void *) p, pn);
+}
+
+template <typename T> inline T *
+x2nrealloc (T *p, size_t *pn, size_t s)
+{
+ return (T *) x2nrealloc ((void *) p, pn, s);
+}
+
+template <typename T> inline T *
+xmemdup (T const *p, size_t s)
+{
+ return (T *) xmemdup ((void const *) p, s);
+}
+
+# endif
+
+
+#endif /* !XALLOC_H_ */
diff --git a/lib/xgetcwd.c b/lib/xgetcwd.c
new file mode 100644
index 0000000..26ea5da
--- /dev/null
+++ b/lib/xgetcwd.c
@@ -0,0 +1,41 @@
+/* xgetcwd.c -- return current directory with unlimited length
+
+ Copyright (C) 2001, 2003, 2004, 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. */
+
+/* Written by Jim Meyering. */
+
+#include <config.h>
+
+#include "xgetcwd.h"
+
+#include <errno.h>
+#include <unistd.h>
+
+#include "xalloc.h"
+
+/* Return the current directory, newly allocated.
+ Upon an out-of-memory error, call xalloc_die.
+ Upon any other type of error, return NULL. */
+
+char *
+xgetcwd (void)
+{
+ char *cwd = getcwd (NULL, 0);
+ if (! cwd && errno == ENOMEM)
+ xalloc_die ();
+ return cwd;
+}
diff --git a/lib/xgetcwd.h b/lib/xgetcwd.h
new file mode 100644
index 0000000..70afe35
--- /dev/null
+++ b/lib/xgetcwd.h
@@ -0,0 +1,18 @@
+/* prototype for xgetcwd
+ Copyright (C) 1995, 2001, 2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+extern char *xgetcwd (void);
diff --git a/lib/xmalloc.c b/lib/xmalloc.c
new file mode 100644
index 0000000..318e0dd
--- /dev/null
+++ b/lib/xmalloc.c
@@ -0,0 +1,123 @@
+/* xmalloc.c -- malloc with out of memory checking
+
+ Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000, 2002, 2003, 2004, 2005, 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. */
+
+#include <config.h>
+
+#if ! HAVE_INLINE
+# define static_inline
+#endif
+#include "xalloc.h"
+#undef static_inline
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+/* 1 if calloc is known to be compatible with GNU calloc. This
+ matters if we are not also using the calloc module, which defines
+ HAVE_CALLOC and supports the GNU API even on non-GNU platforms. */
+#if defined HAVE_CALLOC || defined __GLIBC__
+enum { HAVE_GNU_CALLOC = 1 };
+#else
+enum { HAVE_GNU_CALLOC = 0 };
+#endif
+
+/* Allocate N bytes of memory dynamically, with error checking. */
+
+void *
+xmalloc (size_t n)
+{
+ void *p = malloc (n);
+ if (!p && n != 0)
+ xalloc_die ();
+ return p;
+}
+
+/* Change the size of an allocated block of memory P to N bytes,
+ with error checking. */
+
+void *
+xrealloc (void *p, size_t n)
+{
+ p = realloc (p, n);
+ if (!p && n != 0)
+ xalloc_die ();
+ return p;
+}
+
+/* If P is null, allocate a block of at least *PN bytes; otherwise,
+ reallocate P so that it contains more than *PN bytes. *PN must be
+ nonzero unless P is null. Set *PN to the new block's size, and
+ return the pointer to the new block. *PN is never set to zero, and
+ the returned pointer is never null. */
+
+void *
+x2realloc (void *p, size_t *pn)
+{
+ return x2nrealloc (p, pn, 1);
+}
+
+/* Allocate S bytes of zeroed memory dynamically, with error checking.
+ There's no need for xnzalloc (N, S), since it would be equivalent
+ to xcalloc (N, S). */
+
+void *
+xzalloc (size_t s)
+{
+ return memset (xmalloc (s), 0, s);
+}
+
+/* Allocate zeroed memory for N elements of S bytes, with error
+ checking. S must be nonzero. */
+
+void *
+xcalloc (size_t n, size_t s)
+{
+ void *p;
+ /* Test for overflow, since some calloc implementations don't have
+ proper overflow checks. But omit overflow and size-zero tests if
+ HAVE_GNU_CALLOC, since GNU calloc catches overflow and never
+ returns NULL if successful. */
+ if ((! HAVE_GNU_CALLOC && xalloc_oversized (n, s))
+ || (! (p = calloc (n, s)) && (HAVE_GNU_CALLOC || n != 0)))
+ xalloc_die ();
+ return p;
+}
+
+/* Clone an object P of size S, with error checking. There's no need
+ for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any
+ need for an arithmetic overflow check. */
+
+void *
+xmemdup (void const *p, size_t s)
+{
+ return memcpy (xmalloc (s), p, s);
+}
+
+/* Clone STRING. */
+
+char *
+xstrdup (char const *string)
+{
+ return xmemdup (string, strlen (string) + 1);
+}
diff --git a/lib/xsize.h b/lib/xsize.h
new file mode 100644
index 0000000..341fb16
--- /dev/null
+++ b/lib/xsize.h
@@ -0,0 +1,108 @@
+/* xsize.h -- Checked size_t computations.
+
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _XSIZE_H
+#define _XSIZE_H
+
+/* Get size_t. */
+#include <stddef.h>
+
+/* Get SIZE_MAX. */
+#include <limits.h>
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+/* The size of memory objects is often computed through expressions of
+ type size_t. Example:
+ void* p = malloc (header_size + n * element_size).
+ These computations can lead to overflow. When this happens, malloc()
+ returns a piece of memory that is way too small, and the program then
+ crashes while attempting to fill the memory.
+ To avoid this, the functions and macros in this file check for overflow.
+ The convention is that SIZE_MAX represents overflow.
+ malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc
+ implementation that uses mmap --, it's recommended to use size_overflow_p()
+ or size_in_bounds_p() before invoking malloc().
+ The example thus becomes:
+ size_t size = xsum (header_size, xtimes (n, element_size));
+ void *p = (size_in_bounds_p (size) ? malloc (size) : NULL);
+*/
+
+/* Convert an arbitrary value >= 0 to type size_t. */
+#define xcast_size_t(N) \
+ ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX)
+
+/* Sum of two sizes, with overflow check. */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xsum (size_t size1, size_t size2)
+{
+ size_t sum = size1 + size2;
+ return (sum >= size1 ? sum : SIZE_MAX);
+}
+
+/* Sum of three sizes, with overflow check. */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xsum3 (size_t size1, size_t size2, size_t size3)
+{
+ return xsum (xsum (size1, size2), size3);
+}
+
+/* Sum of four sizes, with overflow check. */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xsum4 (size_t size1, size_t size2, size_t size3, size_t size4)
+{
+ return xsum (xsum (xsum (size1, size2), size3), size4);
+}
+
+/* Maximum of two sizes, with overflow check. */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xmax (size_t size1, size_t size2)
+{
+ /* No explicit check is needed here, because for any n:
+ max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX. */
+ return (size1 >= size2 ? size1 : size2);
+}
+
+/* Multiplication of a count with an element size, with overflow check.
+ The count must be >= 0 and the element size must be > 0.
+ This is a macro, not an inline function, so that it works correctly even
+ when N is of a wider tupe and N > SIZE_MAX. */
+#define xtimes(N, ELSIZE) \
+ ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX)
+
+/* Check for overflow. */
+#define size_overflow_p(SIZE) \
+ ((SIZE) == SIZE_MAX)
+/* Check against overflow. */
+#define size_in_bounds_p(SIZE) \
+ ((SIZE) != SIZE_MAX)
+
+#endif /* _XSIZE_H */
diff --git a/lib/xstrndup.c b/lib/xstrndup.c
new file mode 100644
index 0000000..7ccefd7
--- /dev/null
+++ b/lib/xstrndup.c
@@ -0,0 +1,37 @@
+/* Duplicate a bounded initial segment of a string, with out-of-memory
+ checking.
+ Copyright (C) 2003, 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>
+
+/* Specification. */
+#include "xstrndup.h"
+
+#include <string.h>
+#include "xalloc.h"
+
+/* Return a newly allocated copy of at most N bytes of STRING.
+ In other words, return a copy of the initial segment of length N of
+ STRING. */
+char *
+xstrndup (const char *string, size_t n)
+{
+ char *s = strndup (string, n);
+ if (! s)
+ xalloc_die ();
+ return s;
+}
diff --git a/lib/xstrndup.h b/lib/xstrndup.h
new file mode 100644
index 0000000..88354cf
--- /dev/null
+++ b/lib/xstrndup.h
@@ -0,0 +1,24 @@
+/* Duplicate a bounded initial segment of a string, with out-of-memory
+ checking.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <stddef.h>
+
+/* Return a newly allocated copy of at most N bytes of STRING.
+ In other words, return a copy of the initial segment of length N of
+ STRING. */
+extern char *xstrndup (const char *string, size_t n);