This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Add gnulib modules to replace missing libc functionality


This enables us to build a fully featured elfutils package on systems
with reduced C libraries, such as windows. All the modules are built
into libgnu.a, which is then linked into all binaries if
--enable-gnulib is given on the configure line.

Signed-off-by: Ulf Hermann <ulf.hermann@qt.io>
---
 .gitignore                   |   21 +
 ChangeLog                    |    7 +
 Makefile.am                  |    2 +-
 backends/ChangeLog           |    4 +
 backends/Makefile.am         |    9 +-
 config/ChangeLog             |    4 +
 config/eu.am                 |    3 +
 configure.ac                 |   13 +
 libasm/ChangeLog             |    4 +
 libasm/Makefile.am           |    3 +
 libcpu/ChangeLog             |    4 +
 libcpu/Makefile.am           |    8 +-
 libdw/ChangeLog              |    4 +
 libdw/Makefile.am            |    8 +-
 libelf/ChangeLog             |    4 +
 libelf/Makefile.am           |    3 +
 libgnu/Makefile.am           |   41 +
 libgnu/_Noreturn.h           |   10 +
 libgnu/alignof.h             |   50 +
 libgnu/alloca.c              |  478 ++++
 libgnu/alloca.in.h           |   65 +
 libgnu/areadlink-with-size.c |  104 +
 libgnu/areadlink.h           |   33 +
 libgnu/arg-nonnull.h         |   26 +
 libgnu/argp-ba.c             |   34 +
 libgnu/argp-eexst.c          |   30 +
 libgnu/argp-fmtstream.c      |  434 ++++
 libgnu/argp-fmtstream.h      |  310 +++
 libgnu/argp-fs-xinl.c        |   46 +
 libgnu/argp-help.c           | 1909 ++++++++++++++
 libgnu/argp-namefrob.h       |  157 ++
 libgnu/argp-parse.c          |  954 +++++++
 libgnu/argp-pin.c            |   33 +
 libgnu/argp-pv.c             |   33 +
 libgnu/argp-pvh.c            |   30 +
 libgnu/argp-xinl.c           |   46 +
 libgnu/argp.h                |  631 +++++
 libgnu/asnprintf.c           |   34 +
 libgnu/assure.h              |   37 +
 libgnu/at-func.c             |  146 ++
 libgnu/basename-lgpl.c       |   75 +
 libgnu/basename.c            |   58 +
 libgnu/bitrotate.c           |    3 +
 libgnu/bitrotate.h           |  136 +
 libgnu/c++defs.h             |  316 +++
 libgnu/canonicalize.c        |  354 +++
 libgnu/canonicalize.h        |   48 +
 libgnu/chdir-long.c          |  264 ++
 libgnu/chdir-long.h          |   30 +
 libgnu/cloexec.c             |   83 +
 libgnu/cloexec.h             |   38 +
 libgnu/close.c               |   69 +
 libgnu/closedir.c            |   71 +
 libgnu/config.charset        |  682 +++++
 libgnu/creat-safer.c         |   31 +
 libgnu/cycle-check.c         |   85 +
 libgnu/cycle-check.h         |   52 +
 libgnu/dev-ino.h             |   13 +
 libgnu/dirent--.h            |   24 +
 libgnu/dirent-private.h      |   40 +
 libgnu/dirent-safer.h        |   22 +
 libgnu/dirent.in.h           |  267 ++
 libgnu/dirfd.c               |   98 +
 libgnu/dirname-lgpl.c        |   86 +
 libgnu/dirname.c             |   38 +
 libgnu/dirname.h             |   54 +
 libgnu/dosname.h             |   53 +
 libgnu/dup-safer.c           |   34 +
 libgnu/dup.c                 |   86 +
 libgnu/dup2.c                |  215 ++
 libgnu/errno.in.h            |  279 +++
 libgnu/error.c               |  406 +++
 libgnu/error.h               |   75 +
 libgnu/exitfail.c            |   24 +
 libgnu/exitfail.h            |   18 +
 libgnu/fchdir.c              |  208 ++
 libgnu/fcntl--.h             |   32 +
 libgnu/fcntl-safer.h         |   27 +
 libgnu/fcntl.c               |  414 ++++
 libgnu/fcntl.in.h            |  363 +++
 libgnu/fd-hook.c             |  116 +
 libgnu/fd-hook.h             |  119 +
 libgnu/fd-safer.c            |   49 +
 libgnu/fdopendir.c           |  249 ++
 libgnu/ffs.c                 |   56 +
 libgnu/file-set.c            |   74 +
 libgnu/file-set.h            |   15 +
 libgnu/filename.h            |   54 +
 libgnu/filenamecat-lgpl.c    |   88 +
 libgnu/filenamecat.h         |   27 +
 libgnu/flexmember.h          |   42 +
 libgnu/float+.h              |  147 ++
 libgnu/float.c               |   33 +
 libgnu/float.in.h            |  188 ++
 libgnu/fnmatch.c             |  348 +++
 libgnu/fnmatch.in.h          |   67 +
 libgnu/fnmatch_loop.c        | 1219 +++++++++
 libgnu/fstat.c               |   88 +
 libgnu/fstatat.c             |  135 +
 libgnu/fts-cycle.c           |  160 ++
 libgnu/fts.c                 | 2132 ++++++++++++++++
 libgnu/fts_.h                |  282 +++
 libgnu/getcwd-lgpl.c         |  126 +
 libgnu/getcwd.c              |  446 ++++
 libgnu/getdelim.c            |  147 ++
 libgnu/getdtablesize.c       |  121 +
 libgnu/getline.c             |   27 +
 libgnu/getopt-cdefs.in.h     |   67 +
 libgnu/getopt-core.h         |   96 +
 libgnu/getopt-ext.h          |   77 +
 libgnu/getopt-pfx-core.h     |   54 +
 libgnu/getopt-pfx-ext.h      |   64 +
 libgnu/getopt.c              |  810 ++++++
 libgnu/getopt.in.h           |   61 +
 libgnu/getopt1.c             |  159 ++
 libgnu/getopt_int.h          |  118 +
 libgnu/getprogname.c         |  185 ++
 libgnu/getprogname.h         |   40 +
 libgnu/gettext.h             |  292 +++
 libgnu/gettimeofday.c        |  154 ++
 libgnu/gnulib.am             | 2614 ++++++++++++++++++++
 libgnu/hard-locale.c         |   72 +
 libgnu/hard-locale.h         |   25 +
 libgnu/hash-pjw.c            |   40 +
 libgnu/hash-pjw.h            |   23 +
 libgnu/hash-triple.c         |   77 +
 libgnu/hash-triple.h         |   24 +
 libgnu/hash.c                | 1225 +++++++++
 libgnu/hash.h                |  103 +
 libgnu/i-ring.c              |   68 +
 libgnu/i-ring.h              |   44 +
 libgnu/intprops.h            |  467 ++++
 libgnu/itold.c               |   28 +
 libgnu/langinfo.in.h         |  194 ++
 libgnu/limits.in.h           |   74 +
 libgnu/link.c                |  211 ++
 libgnu/localcharset.c        |  613 +++++
 libgnu/localcharset.h        |   40 +
 libgnu/lseek.c               |   67 +
 libgnu/lstat.c               |   97 +
 libgnu/malloc.c              |   56 +
 libgnu/mbrtowc.c             |  407 +++
 libgnu/mbsinit.c             |   61 +
 libgnu/mbsrtowcs-impl.h      |  122 +
 libgnu/mbsrtowcs-state.c     |   37 +
 libgnu/mbsrtowcs.c           |   32 +
 libgnu/memchr.c              |  172 ++
 libgnu/memchr.valgrind       |   14 +
 libgnu/mempcpy.c             |   28 +
 libgnu/memrchr.c             |  161 ++
 libgnu/msvc-inval.c          |  129 +
 libgnu/msvc-inval.h          |  222 ++
 libgnu/msvc-nothrow.c        |   49 +
 libgnu/msvc-nothrow.h        |   43 +
 libgnu/obstack.c             |  354 +++
 libgnu/obstack.h             |  546 ++++
 libgnu/obstack_printf.c      |   91 +
 libgnu/open-safer.c          |   46 +
 libgnu/open.c                |  181 ++
 libgnu/openat-die.c          |   62 +
 libgnu/openat-priv.h         |   64 +
 libgnu/openat-proc.c         |  134 +
 libgnu/openat-safer.c        |   46 +
 libgnu/openat.c              |  286 +++
 libgnu/openat.h              |  123 +
 libgnu/opendir-safer.c       |   76 +
 libgnu/opendir.c             |  169 ++
 libgnu/pathmax.h             |   83 +
 libgnu/pipe-safer.c          |   56 +
 libgnu/pread.c               |   65 +
 libgnu/printf-args.c         |  187 ++
 libgnu/printf-args.h         |  158 ++
 libgnu/printf-parse.c        |  638 +++++
 libgnu/printf-parse.h        |  193 ++
 libgnu/pwrite.c              |   64 +
 libgnu/qsort.c               |  258 ++
 libgnu/qsort_r.c             |   51 +
 libgnu/raise.c               |   79 +
 libgnu/rawmemchr.c           |  136 +
 libgnu/rawmemchr.valgrind    |   12 +
 libgnu/read.c                |   85 +
 libgnu/readdir.c             |   98 +
 libgnu/readlink.c            |   74 +
 libgnu/realloc.c             |   79 +
 libgnu/ref-add.sin           |   29 +
 libgnu/ref-del.sin           |   24 +
 libgnu/rewinddir.c           |   49 +
 libgnu/same-inode.h          |   37 +
 libgnu/same.c                |  123 +
 libgnu/same.h                |   25 +
 libgnu/save-cwd.c            |   99 +
 libgnu/save-cwd.h            |   34 +
 libgnu/signal.in.h           |  463 ++++
 libgnu/size_max.h            |   30 +
 libgnu/sleep.c               |   76 +
 libgnu/stat.c                |  138 ++
 libgnu/stdalign.in.h         |  121 +
 libgnu/stdbool.in.h          |  132 +
 libgnu/stddef.in.h           |  110 +
 libgnu/stdint.in.h           |  726 ++++++
 libgnu/stdio.in.h            | 1377 +++++++++++
 libgnu/stdlib.in.h           |  992 ++++++++
 libgnu/stpcpy.c              |   49 +
 libgnu/stpncpy.c             |   92 +
 libgnu/strcasecmp.c          |   62 +
 libgnu/strchrnul.c           |  142 ++
 libgnu/strchrnul.valgrind    |   12 +
 libgnu/strdup.c              |   54 +
 libgnu/streq.h               |  176 ++
 libgnu/strerror-override.c   |  302 +++
 libgnu/strerror-override.h   |   56 +
 libgnu/strerror.c            |   71 +
 libgnu/string.in.h           | 1046 ++++++++
 libgnu/strings.in.h          |  122 +
 libgnu/stripslash.c          |   45 +
 libgnu/strncasecmp.c         |   62 +
 libgnu/strndup.c             |   36 +
 libgnu/strnlen.c             |   30 +
 libgnu/strnlen1.c            |   35 +
 libgnu/strnlen1.h            |   40 +
 libgnu/strsep.c              |   57 +
 libgnu/sys_stat.in.h         |  732 ++++++
 libgnu/sys_time.in.h         |  220 ++
 libgnu/sys_types.in.h        |   53 +
 libgnu/sys_utsname.in.h      |  108 +
 libgnu/sys_wait.in.h         |  129 +
 libgnu/sysexits.in.h         |   72 +
 libgnu/time.in.h             |  297 +++
 libgnu/unistd--.h            |   32 +
 libgnu/unistd-safer.h        |   31 +
 libgnu/unistd.c              |    4 +
 libgnu/unistd.in.h           | 1590 ++++++++++++
 libgnu/vasnprintf.c          | 5598 ++++++++++++++++++++++++++++++++++++++++++
 libgnu/vasnprintf.h          |   79 +
 libgnu/verify.h              |  284 +++
 libgnu/vsnprintf.c           |   70 +
 libgnu/warn-on-use.h         |  109 +
 libgnu/wchar.in.h            | 1041 ++++++++
 libgnu/wctype-h.c            |    4 +
 libgnu/wctype.in.h           |  527 ++++
 libgnu/write.c               |  145 ++
 libgnu/xalloc-die.c          |   41 +
 libgnu/xalloc-oversized.h    |   60 +
 libgnu/xalloc.h              |  266 ++
 libgnu/xgetcwd.c             |   41 +
 libgnu/xgetcwd.h             |   17 +
 libgnu/xmalloc.c             |  122 +
 libgnu/xsize.c               |    3 +
 libgnu/xsize.h               |  117 +
 libgnu/xstrndup.c            |   36 +
 libgnu/xstrndup.h            |   23 +
 m4/00gnulib.m4               |   46 +
 m4/Makefile.am               |    2 +-
 m4/absolute-header.m4        |  102 +
 m4/alloca.m4                 |  121 +
 m4/argp.m4                   |   62 +
 m4/builtin-expect.m4         |   49 +
 m4/canonicalize.m4           |  129 +
 m4/chdir-long.m4             |   30 +
 m4/close.m4                  |   33 +
 m4/closedir.m4               |   30 +
 m4/codeset.m4                |   27 +-
 m4/configmake.m4             |   55 +
 m4/cycle-check.m4            |    7 +
 m4/d-ino.m4                  |   56 +
 m4/d-type.m4                 |   32 +
 m4/dirent-safer.m4           |   10 +
 m4/dirent_h.m4               |   64 +
 m4/dirfd.m4                  |   85 +
 m4/dirname.m4                |   19 +
 m4/double-slash-root.m4      |   38 +
 m4/dup.m4                    |   45 +
 m4/dup2.m4                   |  117 +
 m4/errno_h.m4                |  137 ++
 m4/error.m4                  |   27 +
 m4/exponentd.m4              |  116 +
 m4/extensions.m4             |  173 ++
 m4/extern-inline.m4          |  102 +
 m4/fchdir.m4                 |   61 +
 m4/fcntl-o.m4                |  134 +
 m4/fcntl-safer.m4            |   16 +
 m4/fcntl.m4                  |  126 +
 m4/fcntl_h.m4                |   50 +
 m4/fdopendir.m4              |   61 +
 m4/ffs.m4                    |   14 +
 m4/filenamecat.m4            |   16 +
 m4/flexmember.m4             |   46 +
 m4/float_h.m4                |   98 +
 m4/fnmatch.m4                |  156 ++
 m4/fstat.m4                  |   36 +
 m4/fstatat.m4                |   60 +
 m4/fts.m4                    |   22 +
 m4/getcwd-abort-bug.m4       |  140 ++
 m4/getcwd-path-max.m4        |  217 ++
 m4/getcwd.m4                 |  162 ++
 m4/getdelim.m4               |   90 +
 m4/getdtablesize.m4          |   46 +
 m4/getline.m4                |   99 +
 m4/getopt.m4                 |  379 +++
 m4/getprogname.m4            |   43 +
 m4/gettimeofday.m4           |  138 ++
 m4/glibc21.m4                |   34 +
 m4/gnulib-cache.m4           |   71 +
 m4/gnulib-common.m4          |  467 ++++
 m4/gnulib-comp.m4            | 1667 +++++++++++++
 m4/gnulib-tool.m4            |   57 +
 m4/hard-locale.m4            |   11 +
 m4/i-ring.m4                 |   10 +
 m4/include_next.m4           |  223 ++
 m4/intmax_t.m4               |   67 +
 m4/inttypes_h.m4             |   29 +
 m4/langinfo_h.m4             |  105 +
 m4/largefile.m4              |  146 ++
 m4/limits-h.m4               |   31 +
 m4/link.m4                   |   56 +
 m4/localcharset.m4           |   17 +
 m4/locale-fr.m4              |  250 ++
 m4/locale-ja.m4              |  136 +
 m4/locale-zh.m4              |  130 +
 m4/longlong.m4               |  113 +
 m4/lseek.m4                  |   71 +
 m4/lstat.m4                  |   71 +
 m4/malloc.m4                 |  101 +
 m4/math_h.m4                 |  365 +++
 m4/mbrtowc.m4                |  664 +++++
 m4/mbsinit.m4                |   51 +
 m4/mbsrtowcs.m4              |  155 ++
 m4/mbstate_t.m4              |   41 +
 m4/memchr.m4                 |   88 +
 m4/mempcpy.m4                |   26 +
 m4/memrchr.m4                |   23 +
 m4/mmap-anon.m4              |   55 +
 m4/mode_t.m4                 |   26 +
 m4/msvc-inval.m4             |   19 +
 m4/msvc-nothrow.m4           |   10 +
 m4/multiarch.m4              |   62 +
 m4/nocrash.m4                |  131 +
 m4/obstack-printf.m4         |   41 +
 m4/obstack.m4                |   35 +
 m4/off_t.m4                  |   18 +
 m4/open.m4                   |   91 +
 m4/openat.m4                 |   36 +
 m4/opendir.m4                |   31 +
 m4/pathmax.m4                |   42 +
 m4/pread.m4                  |   85 +
 m4/printf.m4                 | 1557 ++++++++++++
 m4/pwrite.m4                 |   99 +
 m4/qsort_r.m4                |   52 +
 m4/raise.m4                  |   34 +
 m4/rawmemchr.m4              |   20 +
 m4/read.m4                   |   26 +
 m4/readdir.m4                |   15 +
 m4/readlink.m4               |   71 +
 m4/realloc.m4                |   79 +
 m4/rewinddir.m4              |   15 +
 m4/same.m4                   |   13 +
 m4/save-cwd.m4               |   11 +
 m4/signal_h.m4               |   83 +
 m4/size_max.m4               |   79 +
 m4/sleep.m4                  |   62 +
 m4/ssize_t.m4                |   23 +
 m4/stat.m4                   |   71 +
 m4/stdalign.m4               |   57 +
 m4/stdbool.m4                |  108 +
 m4/stddef_h.m4               |   51 +
 m4/stdint.m4                 |  541 ++++
 m4/stdint_h.m4               |   27 +
 m4/stdio_h.m4                |  225 ++
 m4/stdlib_h.m4               |  120 +
 m4/stpcpy.m4                 |   25 +
 m4/stpncpy.m4                |   97 +
 m4/strcase.m4                |   45 +
 m4/strchrnul.m4              |   50 +
 m4/strdup.m4                 |   36 +
 m4/strerror.m4               |   96 +
 m4/string_h.m4               |  120 +
 m4/strings_h.m4              |   52 +
 m4/strndup.m4                |   58 +
 m4/strnlen.m4                |   30 +
 m4/strsep.m4                 |   23 +
 m4/sys_socket_h.m4           |  176 ++
 m4/sys_stat_h.m4             |   96 +
 m4/sys_time_h.m4             |  111 +
 m4/sys_types_h.m4            |   49 +
 m4/sys_utsname_h.m4          |   54 +
 m4/sys_wait_h.m4             |   36 +
 m4/sysexits.m4               |   44 +
 m4/time_h.m4                 |  134 +
 m4/unistd-safer.m4           |   10 +
 m4/unistd_h.m4               |  190 ++
 m4/vasnprintf.m4             |  291 +++
 m4/vsnprintf.m4              |   62 +
 m4/warn-on-use.m4            |   47 +
 m4/wchar_h.m4                |  233 ++
 m4/wchar_t.m4                |   24 +
 m4/wctype_h.m4               |  209 ++
 m4/wint_t.m4                 |   62 +
 m4/write.m4                  |   32 +
 m4/xalloc.m4                 |    7 +
 m4/xgetcwd.m4                |   10 +
 m4/xsize.m4                  |   12 +
 m4/xstrndup.m4               |   15 +
 src/ChangeLog                |    4 +
 src/Makefile.am              |   35 +-
 tests/ChangeLog              |    4 +
 tests/Makefile.am            |  187 +-
 406 files changed, 66797 insertions(+), 123 deletions(-)
 create mode 100644 libgnu/Makefile.am
 create mode 100644 libgnu/_Noreturn.h
 create mode 100644 libgnu/alignof.h
 create mode 100644 libgnu/alloca.c
 create mode 100644 libgnu/alloca.in.h
 create mode 100644 libgnu/areadlink-with-size.c
 create mode 100644 libgnu/areadlink.h
 create mode 100644 libgnu/arg-nonnull.h
 create mode 100644 libgnu/argp-ba.c
 create mode 100644 libgnu/argp-eexst.c
 create mode 100644 libgnu/argp-fmtstream.c
 create mode 100644 libgnu/argp-fmtstream.h
 create mode 100644 libgnu/argp-fs-xinl.c
 create mode 100644 libgnu/argp-help.c
 create mode 100644 libgnu/argp-namefrob.h
 create mode 100644 libgnu/argp-parse.c
 create mode 100644 libgnu/argp-pin.c
 create mode 100644 libgnu/argp-pv.c
 create mode 100644 libgnu/argp-pvh.c
 create mode 100644 libgnu/argp-xinl.c
 create mode 100644 libgnu/argp.h
 create mode 100644 libgnu/asnprintf.c
 create mode 100644 libgnu/assure.h
 create mode 100644 libgnu/at-func.c
 create mode 100644 libgnu/basename-lgpl.c
 create mode 100644 libgnu/basename.c
 create mode 100644 libgnu/bitrotate.c
 create mode 100644 libgnu/bitrotate.h
 create mode 100644 libgnu/c++defs.h
 create mode 100644 libgnu/canonicalize.c
 create mode 100644 libgnu/canonicalize.h
 create mode 100644 libgnu/chdir-long.c
 create mode 100644 libgnu/chdir-long.h
 create mode 100644 libgnu/cloexec.c
 create mode 100644 libgnu/cloexec.h
 create mode 100644 libgnu/close.c
 create mode 100644 libgnu/closedir.c
 create mode 100644 libgnu/config.charset
 create mode 100644 libgnu/creat-safer.c
 create mode 100644 libgnu/cycle-check.c
 create mode 100644 libgnu/cycle-check.h
 create mode 100644 libgnu/dev-ino.h
 create mode 100644 libgnu/dirent--.h
 create mode 100644 libgnu/dirent-private.h
 create mode 100644 libgnu/dirent-safer.h
 create mode 100644 libgnu/dirent.in.h
 create mode 100644 libgnu/dirfd.c
 create mode 100644 libgnu/dirname-lgpl.c
 create mode 100644 libgnu/dirname.c
 create mode 100644 libgnu/dirname.h
 create mode 100644 libgnu/dosname.h
 create mode 100644 libgnu/dup-safer.c
 create mode 100644 libgnu/dup.c
 create mode 100644 libgnu/dup2.c
 create mode 100644 libgnu/errno.in.h
 create mode 100644 libgnu/error.c
 create mode 100644 libgnu/error.h
 create mode 100644 libgnu/exitfail.c
 create mode 100644 libgnu/exitfail.h
 create mode 100644 libgnu/fchdir.c
 create mode 100644 libgnu/fcntl--.h
 create mode 100644 libgnu/fcntl-safer.h
 create mode 100644 libgnu/fcntl.c
 create mode 100644 libgnu/fcntl.in.h
 create mode 100644 libgnu/fd-hook.c
 create mode 100644 libgnu/fd-hook.h
 create mode 100644 libgnu/fd-safer.c
 create mode 100644 libgnu/fdopendir.c
 create mode 100644 libgnu/ffs.c
 create mode 100644 libgnu/file-set.c
 create mode 100644 libgnu/file-set.h
 create mode 100644 libgnu/filename.h
 create mode 100644 libgnu/filenamecat-lgpl.c
 create mode 100644 libgnu/filenamecat.h
 create mode 100644 libgnu/flexmember.h
 create mode 100644 libgnu/float+.h
 create mode 100644 libgnu/float.c
 create mode 100644 libgnu/float.in.h
 create mode 100644 libgnu/fnmatch.c
 create mode 100644 libgnu/fnmatch.in.h
 create mode 100644 libgnu/fnmatch_loop.c
 create mode 100644 libgnu/fstat.c
 create mode 100644 libgnu/fstatat.c
 create mode 100644 libgnu/fts-cycle.c
 create mode 100644 libgnu/fts.c
 create mode 100644 libgnu/fts_.h
 create mode 100644 libgnu/getcwd-lgpl.c
 create mode 100644 libgnu/getcwd.c
 create mode 100644 libgnu/getdelim.c
 create mode 100644 libgnu/getdtablesize.c
 create mode 100644 libgnu/getline.c
 create mode 100644 libgnu/getopt-cdefs.in.h
 create mode 100644 libgnu/getopt-core.h
 create mode 100644 libgnu/getopt-ext.h
 create mode 100644 libgnu/getopt-pfx-core.h
 create mode 100644 libgnu/getopt-pfx-ext.h
 create mode 100644 libgnu/getopt.c
 create mode 100644 libgnu/getopt.in.h
 create mode 100644 libgnu/getopt1.c
 create mode 100644 libgnu/getopt_int.h
 create mode 100644 libgnu/getprogname.c
 create mode 100644 libgnu/getprogname.h
 create mode 100644 libgnu/gettext.h
 create mode 100644 libgnu/gettimeofday.c
 create mode 100644 libgnu/gnulib.am
 create mode 100644 libgnu/hard-locale.c
 create mode 100644 libgnu/hard-locale.h
 create mode 100644 libgnu/hash-pjw.c
 create mode 100644 libgnu/hash-pjw.h
 create mode 100644 libgnu/hash-triple.c
 create mode 100644 libgnu/hash-triple.h
 create mode 100644 libgnu/hash.c
 create mode 100644 libgnu/hash.h
 create mode 100644 libgnu/i-ring.c
 create mode 100644 libgnu/i-ring.h
 create mode 100644 libgnu/intprops.h
 create mode 100644 libgnu/itold.c
 create mode 100644 libgnu/langinfo.in.h
 create mode 100644 libgnu/limits.in.h
 create mode 100644 libgnu/link.c
 create mode 100644 libgnu/localcharset.c
 create mode 100644 libgnu/localcharset.h
 create mode 100644 libgnu/lseek.c
 create mode 100644 libgnu/lstat.c
 create mode 100644 libgnu/malloc.c
 create mode 100644 libgnu/mbrtowc.c
 create mode 100644 libgnu/mbsinit.c
 create mode 100644 libgnu/mbsrtowcs-impl.h
 create mode 100644 libgnu/mbsrtowcs-state.c
 create mode 100644 libgnu/mbsrtowcs.c
 create mode 100644 libgnu/memchr.c
 create mode 100644 libgnu/memchr.valgrind
 create mode 100644 libgnu/mempcpy.c
 create mode 100644 libgnu/memrchr.c
 create mode 100644 libgnu/msvc-inval.c
 create mode 100644 libgnu/msvc-inval.h
 create mode 100644 libgnu/msvc-nothrow.c
 create mode 100644 libgnu/msvc-nothrow.h
 create mode 100644 libgnu/obstack.c
 create mode 100644 libgnu/obstack.h
 create mode 100644 libgnu/obstack_printf.c
 create mode 100644 libgnu/open-safer.c
 create mode 100644 libgnu/open.c
 create mode 100644 libgnu/openat-die.c
 create mode 100644 libgnu/openat-priv.h
 create mode 100644 libgnu/openat-proc.c
 create mode 100644 libgnu/openat-safer.c
 create mode 100644 libgnu/openat.c
 create mode 100644 libgnu/openat.h
 create mode 100644 libgnu/opendir-safer.c
 create mode 100644 libgnu/opendir.c
 create mode 100644 libgnu/pathmax.h
 create mode 100644 libgnu/pipe-safer.c
 create mode 100644 libgnu/pread.c
 create mode 100644 libgnu/printf-args.c
 create mode 100644 libgnu/printf-args.h
 create mode 100644 libgnu/printf-parse.c
 create mode 100644 libgnu/printf-parse.h
 create mode 100644 libgnu/pwrite.c
 create mode 100644 libgnu/qsort.c
 create mode 100644 libgnu/qsort_r.c
 create mode 100644 libgnu/raise.c
 create mode 100644 libgnu/rawmemchr.c
 create mode 100644 libgnu/rawmemchr.valgrind
 create mode 100644 libgnu/read.c
 create mode 100644 libgnu/readdir.c
 create mode 100644 libgnu/readlink.c
 create mode 100644 libgnu/realloc.c
 create mode 100644 libgnu/ref-add.sin
 create mode 100644 libgnu/ref-del.sin
 create mode 100644 libgnu/rewinddir.c
 create mode 100644 libgnu/same-inode.h
 create mode 100644 libgnu/same.c
 create mode 100644 libgnu/same.h
 create mode 100644 libgnu/save-cwd.c
 create mode 100644 libgnu/save-cwd.h
 create mode 100644 libgnu/signal.in.h
 create mode 100644 libgnu/size_max.h
 create mode 100644 libgnu/sleep.c
 create mode 100644 libgnu/stat.c
 create mode 100644 libgnu/stdalign.in.h
 create mode 100644 libgnu/stdbool.in.h
 create mode 100644 libgnu/stddef.in.h
 create mode 100644 libgnu/stdint.in.h
 create mode 100644 libgnu/stdio.in.h
 create mode 100644 libgnu/stdlib.in.h
 create mode 100644 libgnu/stpcpy.c
 create mode 100644 libgnu/stpncpy.c
 create mode 100644 libgnu/strcasecmp.c
 create mode 100644 libgnu/strchrnul.c
 create mode 100644 libgnu/strchrnul.valgrind
 create mode 100644 libgnu/strdup.c
 create mode 100644 libgnu/streq.h
 create mode 100644 libgnu/strerror-override.c
 create mode 100644 libgnu/strerror-override.h
 create mode 100644 libgnu/strerror.c
 create mode 100644 libgnu/string.in.h
 create mode 100644 libgnu/strings.in.h
 create mode 100644 libgnu/stripslash.c
 create mode 100644 libgnu/strncasecmp.c
 create mode 100644 libgnu/strndup.c
 create mode 100644 libgnu/strnlen.c
 create mode 100644 libgnu/strnlen1.c
 create mode 100644 libgnu/strnlen1.h
 create mode 100644 libgnu/strsep.c
 create mode 100644 libgnu/sys_stat.in.h
 create mode 100644 libgnu/sys_time.in.h
 create mode 100644 libgnu/sys_types.in.h
 create mode 100644 libgnu/sys_utsname.in.h
 create mode 100644 libgnu/sys_wait.in.h
 create mode 100644 libgnu/sysexits.in.h
 create mode 100644 libgnu/time.in.h
 create mode 100644 libgnu/unistd--.h
 create mode 100644 libgnu/unistd-safer.h
 create mode 100644 libgnu/unistd.c
 create mode 100644 libgnu/unistd.in.h
 create mode 100644 libgnu/vasnprintf.c
 create mode 100644 libgnu/vasnprintf.h
 create mode 100644 libgnu/verify.h
 create mode 100644 libgnu/vsnprintf.c
 create mode 100644 libgnu/warn-on-use.h
 create mode 100644 libgnu/wchar.in.h
 create mode 100644 libgnu/wctype-h.c
 create mode 100644 libgnu/wctype.in.h
 create mode 100644 libgnu/write.c
 create mode 100644 libgnu/xalloc-die.c
 create mode 100644 libgnu/xalloc-oversized.h
 create mode 100644 libgnu/xalloc.h
 create mode 100644 libgnu/xgetcwd.c
 create mode 100644 libgnu/xgetcwd.h
 create mode 100644 libgnu/xmalloc.c
 create mode 100644 libgnu/xsize.c
 create mode 100644 libgnu/xsize.h
 create mode 100644 libgnu/xstrndup.c
 create mode 100644 libgnu/xstrndup.h
 create mode 100644 m4/00gnulib.m4
 create mode 100644 m4/absolute-header.m4
 create mode 100644 m4/alloca.m4
 create mode 100644 m4/argp.m4
 create mode 100644 m4/builtin-expect.m4
 create mode 100644 m4/canonicalize.m4
 create mode 100644 m4/chdir-long.m4
 create mode 100644 m4/close.m4
 create mode 100644 m4/closedir.m4
 create mode 100644 m4/configmake.m4
 create mode 100644 m4/cycle-check.m4
 create mode 100644 m4/d-ino.m4
 create mode 100644 m4/d-type.m4
 create mode 100644 m4/dirent-safer.m4
 create mode 100644 m4/dirent_h.m4
 create mode 100644 m4/dirfd.m4
 create mode 100644 m4/dirname.m4
 create mode 100644 m4/double-slash-root.m4
 create mode 100644 m4/dup.m4
 create mode 100644 m4/dup2.m4
 create mode 100644 m4/errno_h.m4
 create mode 100644 m4/error.m4
 create mode 100644 m4/exponentd.m4
 create mode 100644 m4/extensions.m4
 create mode 100644 m4/extern-inline.m4
 create mode 100644 m4/fchdir.m4
 create mode 100644 m4/fcntl-o.m4
 create mode 100644 m4/fcntl-safer.m4
 create mode 100644 m4/fcntl.m4
 create mode 100644 m4/fcntl_h.m4
 create mode 100644 m4/fdopendir.m4
 create mode 100644 m4/ffs.m4
 create mode 100644 m4/filenamecat.m4
 create mode 100644 m4/flexmember.m4
 create mode 100644 m4/float_h.m4
 create mode 100644 m4/fnmatch.m4
 create mode 100644 m4/fstat.m4
 create mode 100644 m4/fstatat.m4
 create mode 100644 m4/fts.m4
 create mode 100644 m4/getcwd-abort-bug.m4
 create mode 100644 m4/getcwd-path-max.m4
 create mode 100644 m4/getcwd.m4
 create mode 100644 m4/getdelim.m4
 create mode 100644 m4/getdtablesize.m4
 create mode 100644 m4/getline.m4
 create mode 100644 m4/getopt.m4
 create mode 100644 m4/getprogname.m4
 create mode 100644 m4/gettimeofday.m4
 create mode 100644 m4/glibc21.m4
 create mode 100644 m4/gnulib-cache.m4
 create mode 100644 m4/gnulib-common.m4
 create mode 100644 m4/gnulib-comp.m4
 create mode 100644 m4/gnulib-tool.m4
 create mode 100644 m4/hard-locale.m4
 create mode 100644 m4/i-ring.m4
 create mode 100644 m4/include_next.m4
 create mode 100644 m4/intmax_t.m4
 create mode 100644 m4/inttypes_h.m4
 create mode 100644 m4/langinfo_h.m4
 create mode 100644 m4/largefile.m4
 create mode 100644 m4/limits-h.m4
 create mode 100644 m4/link.m4
 create mode 100644 m4/localcharset.m4
 create mode 100644 m4/locale-fr.m4
 create mode 100644 m4/locale-ja.m4
 create mode 100644 m4/locale-zh.m4
 create mode 100644 m4/longlong.m4
 create mode 100644 m4/lseek.m4
 create mode 100644 m4/lstat.m4
 create mode 100644 m4/malloc.m4
 create mode 100644 m4/math_h.m4
 create mode 100644 m4/mbrtowc.m4
 create mode 100644 m4/mbsinit.m4
 create mode 100644 m4/mbsrtowcs.m4
 create mode 100644 m4/mbstate_t.m4
 create mode 100644 m4/memchr.m4
 create mode 100644 m4/mempcpy.m4
 create mode 100644 m4/memrchr.m4
 create mode 100644 m4/mmap-anon.m4
 create mode 100644 m4/mode_t.m4
 create mode 100644 m4/msvc-inval.m4
 create mode 100644 m4/msvc-nothrow.m4
 create mode 100644 m4/multiarch.m4
 create mode 100644 m4/nocrash.m4
 create mode 100644 m4/obstack-printf.m4
 create mode 100644 m4/obstack.m4
 create mode 100644 m4/off_t.m4
 create mode 100644 m4/open.m4
 create mode 100644 m4/openat.m4
 create mode 100644 m4/opendir.m4
 create mode 100644 m4/pathmax.m4
 create mode 100644 m4/pread.m4
 create mode 100644 m4/printf.m4
 create mode 100644 m4/pwrite.m4
 create mode 100644 m4/qsort_r.m4
 create mode 100644 m4/raise.m4
 create mode 100644 m4/rawmemchr.m4
 create mode 100644 m4/read.m4
 create mode 100644 m4/readdir.m4
 create mode 100644 m4/readlink.m4
 create mode 100644 m4/realloc.m4
 create mode 100644 m4/rewinddir.m4
 create mode 100644 m4/same.m4
 create mode 100644 m4/save-cwd.m4
 create mode 100644 m4/signal_h.m4
 create mode 100644 m4/size_max.m4
 create mode 100644 m4/sleep.m4
 create mode 100644 m4/ssize_t.m4
 create mode 100644 m4/stat.m4
 create mode 100644 m4/stdalign.m4
 create mode 100644 m4/stdbool.m4
 create mode 100644 m4/stddef_h.m4
 create mode 100644 m4/stdint.m4
 create mode 100644 m4/stdint_h.m4
 create mode 100644 m4/stdio_h.m4
 create mode 100644 m4/stdlib_h.m4
 create mode 100644 m4/stpcpy.m4
 create mode 100644 m4/stpncpy.m4
 create mode 100644 m4/strcase.m4
 create mode 100644 m4/strchrnul.m4
 create mode 100644 m4/strdup.m4
 create mode 100644 m4/strerror.m4
 create mode 100644 m4/string_h.m4
 create mode 100644 m4/strings_h.m4
 create mode 100644 m4/strndup.m4
 create mode 100644 m4/strnlen.m4
 create mode 100644 m4/strsep.m4
 create mode 100644 m4/sys_socket_h.m4
 create mode 100644 m4/sys_stat_h.m4
 create mode 100644 m4/sys_time_h.m4
 create mode 100644 m4/sys_types_h.m4
 create mode 100644 m4/sys_utsname_h.m4
 create mode 100644 m4/sys_wait_h.m4
 create mode 100644 m4/sysexits.m4
 create mode 100644 m4/time_h.m4
 create mode 100644 m4/unistd-safer.m4
 create mode 100644 m4/unistd_h.m4
 create mode 100644 m4/vasnprintf.m4
 create mode 100644 m4/vsnprintf.m4
 create mode 100644 m4/warn-on-use.m4
 create mode 100644 m4/wchar_h.m4
 create mode 100644 m4/wchar_t.m4
 create mode 100644 m4/wctype_h.m4
 create mode 100644 m4/wint_t.m4
 create mode 100644 m4/write.m4
 create mode 100644 m4/xalloc.m4
 create mode 100644 m4/xgetcwd.m4
 create mode 100644 m4/xsize.m4
 create mode 100644 m4/xstrndup.m4

diff --git a/.gitignore b/.gitignore
index 43a8d6e..3d99b0d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,6 +44,27 @@ Makefile.in
 /libcpu/*_lex.c
 /libcpu/*_parse.[ch]
 /libdw/known-dwarf.h
+/libgnu/alloca.h
+/libgnu/dirent.h
+/libgnu/fcntl.h
+/libgnu/getopt-cdefs.h
+/libgnu/getopt.h
+/libgnu/langinfo.h
+/libgnu/limits.h
+/libgnu/stddef.h
+/libgnu/stdint.h
+/libgnu/stdio.h
+/libgnu/stdlib.h
+/libgnu/string.h
+/libgnu/strings.h
+/libgnu/sys/stat.h
+/libgnu/sys/time.h
+/libgnu/sys/types.h
+/libgnu/sys/utsname.h
+/libgnu/sys/wait.h
+/libgnu/time.h
+/libgnu/unistd.h
+/libgnu/wchar.h
 /po/*.gmo
 /po/*.pot
 /po/en@boldquot.insert-header
diff --git a/ChangeLog b/ChangeLog
index 48185c3..324d406 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2017-04-21  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* .gitignore: Add generated gnulib headers.
+	* Makefile.am (SUBDIRS): Add libgnu.
+	* configure.ac: Add option to enable gnulib
+	and gl_EARLY and gl_INIT macros, as well as libgnu/Makefile.
+
 2017-02-15  Ulf Hermann  <ulf.hermann@qt.io>
 
 	* configure.ac: Add check for mempcpy.
diff --git a/Makefile.am b/Makefile.am
index 2ff444e..b852e57 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -27,7 +27,7 @@ AM_MAKEFLAGS = --no-print-directory
 pkginclude_HEADERS = version.h
 
 # Add doc back when we have some real content.
-SUBDIRS = config m4 lib libelf libebl libdwelf libdwfl libdw libcpu libasm \
+SUBDIRS = config m4 libgnu lib libelf libebl libdwelf libdwfl libdw libcpu libasm \
 	  backends src po tests
 
 EXTRA_DIST = elfutils.spec GPG-KEY NOTES CONTRIBUTING \
diff --git a/backends/ChangeLog b/backends/ChangeLog
index c6e0e08..594aa98 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,7 @@
+2017-04-21  Ulf Hermann <ulf.hermann@qt.io>
+
+	* Makefile.am: Link backends against libgnu.a if requested.
+
 2017-04-20  Ulf Hermann <ulf.hermann@qt.io>
 
 	* aarch64_initreg.c: Compile register initialization only on linux.
diff --git a/backends/Makefile.am b/backends/Makefile.am
index b553ec3..5dcb3e1 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -45,6 +45,11 @@ noinst_DATA = $(libebl_pic:_pic.a=.so)
 
 libelf = ../libelf/libelf.so
 libdw = ../libdw/libdw.so
+if USE_GNULIB
+libgnu = ../libgnu/libgnu.a
+else
+libgnu =
+endif
 
 i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c i386_cfi.c \
 	    i386_retval.c i386_regs.c i386_auxv.c i386_syscall.c \
@@ -129,14 +134,14 @@ libebl_bpf_pic_a_SOURCES = $(bpf_SRCS)
 am_libebl_bpf_pic_a_OBJECTS = $(bpf_SRCS:.c=.os)
 
 
-libebl_%.so libebl_%.map: libebl_%_pic.a $(libelf) $(libdw)
+libebl_%.so libebl_%.map: libebl_%_pic.a $(libelf) $(libdw) $(libgnu)
 	@rm -f $(@:.so=.map)
 	$(AM_V_at)echo 'ELFUTILS_$(PACKAGE_VERSION) { global: $*_init; local: *; };' \
 	  > $(@:.so=.map)
 	$(AM_V_CCLD)$(LINK) -shared -o $(@:.map=.so) \
 		-Wl,--whole-archive $< $(cpu_$*) -Wl,--no-whole-archive \
 		-Wl,--version-script,$(@:.so=.map) \
-		-Wl,-z,defs -Wl,--as-needed $(libelf) $(libdw)
+		-Wl,-z,defs -Wl,--as-needed $(libelf) $(libdw) $(libgnu)
 	@$(textrel_check)
 
 libebl_i386.so: $(cpu_i386)
diff --git a/config/ChangeLog b/config/ChangeLog
index 8a39e98..756bab6 100644
--- a/config/ChangeLog
+++ b/config/ChangeLog
@@ -1,3 +1,7 @@
+2017-04-21  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* eu.am: Add $(top_srcdir)libgnu and $(top_builddir)/libgnu to -I if requested.
+
 2016-12-27  Mark Wielaard  <mjw@redhat.com>
 
 	* elfutils.spec.in: Update for 0.168 and new project location.
diff --git a/config/eu.am b/config/eu.am
index 8fe1e25..11c2fec 100644
--- a/config/eu.am
+++ b/config/eu.am
@@ -31,6 +31,9 @@
 
 DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -DLOCALEDIR='"${localedir}"'
 AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_srcdir)/lib -I..
+if USE_GNULIB
+AM_CPPFLAGS += -I$(top_srcdir)/libgnu -I$(top_builddir)/libgnu
+endif
 
 # Drop the 'u' flag that automake adds by default. It is incompatible
 # with deterministic archives.
diff --git a/configure.ac b/configure.ac
index 3c35dac..a5aea7f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -85,7 +85,16 @@ AS_IF([test "$use_locks" = yes],
 
 AH_TEMPLATE([USE_LOCKS], [Defined if libraries should be thread-safe.])
 
+AC_ARG_ENABLE([gnulib],
+AS_HELP_STRING([--enable-gnulib],
+               [use gnulib modules to replace functionality missing from libc. This affects the license choices for the resulting binaries.]),
+               use_gnulib=$enableval, use_gnulib=no)
+AM_CONDITIONAL(USE_GNULIB, test "$use_gnulib" = yes)
+
 AC_PROG_CC
+
+gl_EARLY
+
 AC_PROG_RANLIB
 AC_PROG_YACC
 AM_PROG_LEX
@@ -389,8 +398,12 @@ dnl Check if we have <linux/bpf.h> for EM_BPF disassembly.
 AC_CHECK_HEADERS(linux/bpf.h)
 AM_CONDITIONAL(HAVE_LINUX_BPF_H, [test "x$ac_cv_header_linux_bpf_h" = "xyes"])
 
+gl_INIT
+
 dnl The directories with content.
 
+AC_CONFIG_FILES([libgnu/Makefile])
+
 dnl Documentation.
 dnl Commented out for now.
 dnl AC_CONFIG_FILES([doc/Makefile])
diff --git a/libasm/ChangeLog b/libasm/ChangeLog
index 1656842..ef183a6 100644
--- a/libasm/ChangeLog
+++ b/libasm/ChangeLog
@@ -1,3 +1,7 @@
+2017-02-21  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* Makefile.am: Link libasm agaist libgnu.a if requested.
+
 2017-02-12  Mark Wielaard  <mjw@redhat.com>
 
 	* asm_newsym.c (asm_newsym): Increase TEMPSYMLEN to 13.
diff --git a/libasm/Makefile.am b/libasm/Makefile.am
index 8094b05..8713070 100644
--- a/libasm/Makefile.am
+++ b/libasm/Makefile.am
@@ -59,6 +59,9 @@ libasm_so_LDLIBS =
 if USE_LOCKS
 libasm_so_LDLIBS += -lpthread
 endif
+if USE_GNULIB
+libasm_so_LDLIBS += ../libgnu/libgnu.a
+endif
 
 libasm_so_SOURCES =
 libasm.so$(EXEEXT): libasm_pic.a libasm.map
diff --git a/libcpu/ChangeLog b/libcpu/ChangeLog
index 7fe4345..9235b1b 100644
--- a/libcpu/ChangeLog
+++ b/libcpu/ChangeLog
@@ -1,3 +1,7 @@
+2017-02-21  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* Makefile.am: Link gendis agaist libgnu.a if requested.
+
 2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
 
 	* Makefile.am: Add EXEEXT to gendis.
diff --git a/libcpu/Makefile.am b/libcpu/Makefile.am
index 31fc906..30a6799 100644
--- a/libcpu/Makefile.am
+++ b/libcpu/Makefile.am
@@ -80,11 +80,17 @@ i386_lex_no_Werror = yes
 
 libeu = ../lib/libeu.a
 
+if USE_GNULIB
+libgnu = ../libgnu/libgnu.a
+else
+libgnu =
+endif
+
 i386_lex_CFLAGS = -Wno-unused-label -Wno-unused-function -Wno-sign-compare
 i386_parse.o: i386_parse.c i386.mnemonics
 i386_parse_CFLAGS = -DNMNES="`wc -l < i386.mnemonics`"
 i386_lex.o: i386_parse.h
-i386_gendis_LDADD = $(libeu) -lm
+i386_gendis_LDADD = $(libeu) $(libgnu) -lm
 
 i386_parse.h: i386_parse.c ;
 
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 8802853..8052b5b 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,7 @@
+2017-02-21  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* Makefile.am: Link libdw agaist libgnu.a if requested.
+
 2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
 
 	* dwarf_begin_elf.c: Include endian.h.
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index 082d96c..2c3efca 100644
--- a/libdw/Makefile.am
+++ b/libdw/Makefile.am
@@ -102,6 +102,12 @@ endif
 libdw_pic_a_SOURCES =
 am_libdw_pic_a_OBJECTS = $(libdw_a_SOURCES:.c=.os)
 
+if USE_GNULIB
+libgnu = ../libgnu/libgnu.a
+else
+libgnu =
+endif
+
 libdw_so_SOURCES =
 libdw.so$(EXEEXT): $(srcdir)/libdw.map libdw_pic.a ../libdwelf/libdwelf_pic.a \
 	  ../libdwfl/libdwfl_pic.a ../libebl/libebl.a \
@@ -112,7 +118,7 @@ libdw.so$(EXEEXT): $(srcdir)/libdw.map libdw_pic.a ../libdwelf/libdwelf_pic.a \
 		-Wl,--enable-new-dtags,-rpath,$(pkglibdir) \
 		-Wl,--version-script,$<,--no-undefined \
 		-Wl,--whole-archive $(filter-out $<,$^) -Wl,--no-whole-archive\
-		-ldl -lz $(argp_LDADD) $(zip_LIBS)
+		-ldl -lz $(argp_LDADD) $(zip_LIBS) $(libgnu)
 	@$(textrel_check)
 	$(AM_V_at)ln -fs $@ $@.$(VERSION)
 
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 225c7c8..d9ac7c6 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,7 @@
+2017-04-21  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* Makefile.am: Link libelf agaist libgnu.a if requested.
+
 2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
 
 	* elf_update.c: Set ELF_F_MMAPPED flag if we mmap from elf_update.
diff --git a/libelf/Makefile.am b/libelf/Makefile.am
index 167a832..d141c64 100644
--- a/libelf/Makefile.am
+++ b/libelf/Makefile.am
@@ -99,6 +99,9 @@ libelf_so_LDLIBS = -lz
 if USE_LOCKS
 libelf_so_LDLIBS += -lpthread
 endif
+if USE_GNULIB
+libelf_so_LDLIBS += ../libgnu/libgnu.a
+endif
 
 libelf_so_SOURCES =
 libelf.so$(EXEEXT): libelf_pic.a libelf.map
diff --git a/libgnu/Makefile.am b/libgnu/Makefile.am
new file mode 100644
index 0000000..c4a90e8
--- /dev/null
+++ b/libgnu/Makefile.am
@@ -0,0 +1,41 @@
+## Process this file with automake to create Makefile.in
+##
+## Copyright (C) 2017 The Qt Company Ltd.
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of either
+##
+##   * the GNU Lesser General Public License as published by the Free
+##     Software Foundation; either version 3 of the License, or (at
+##     your option) any later version
+##
+## or
+##
+##   * the GNU General Public License as published by the Free
+##     Software Foundation; either version 2 of the License, or (at
+##     your option) any later version
+##
+## or both in parallel, as here.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received copies of the GNU General Public License and
+## the GNU Lesser General Public License along with this program.  If
+## not, see <http://www.gnu.org/licenses/>.
+##
+
+# for eu-config.h
+AM_CPPFLAGS = -I$(top_srcdir)/lib
+AM_CFLAGS = -fPIC
+noinst_LIBRARIES =
+MOSTLYCLEANFILES =
+MOSTLYCLEANDIRS =
+BUILT_SOURCES =
+EXTRA_DIST =
+CLEANFILES =
+SUFFIXES =
+include gnulib.am
diff --git a/libgnu/_Noreturn.h b/libgnu/_Noreturn.h
new file mode 100644
index 0000000..c44ad89
--- /dev/null
+++ b/libgnu/_Noreturn.h
@@ -0,0 +1,10 @@
+#if !defined _Noreturn && __STDC_VERSION__ < 201112
+# if (3 <= __GNUC__ || (__GNUC__ == 2 && 8 <= __GNUC_MINOR__) \
+      || 0x5110 <= __SUNPRO_C)
+#  define _Noreturn __attribute__ ((__noreturn__))
+# elif 1200 <= _MSC_VER
+#  define _Noreturn __declspec (noreturn)
+# else
+#  define _Noreturn
+# endif
+#endif
diff --git a/libgnu/alignof.h b/libgnu/alignof.h
new file mode 100644
index 0000000..e64e2c7
--- /dev/null
+++ b/libgnu/alignof.h
@@ -0,0 +1,50 @@
+/* Determine alignment of types.
+   Copyright (C) 2003-2004, 2006, 2009-2017 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 version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _ALIGNOF_H
+#define _ALIGNOF_H
+
+#include <stddef.h>
+
+/* alignof_slot (TYPE)
+   Determine the alignment of a structure slot (field) of a given type,
+   at compile time.  Note that the result depends on the ABI.
+   This is the same as alignof (TYPE) and _Alignof (TYPE), defined in
+   <stdalign.h> if __alignof_is_defined is 1.
+   Note: The result cannot be used as a value for an 'enum' constant,
+   due to bugs in HP-UX 10.20 cc and AIX 3.2.5 xlc.  */
+#if defined __cplusplus
+  template <class type> struct alignof_helper { char __slot1; type __slot2; };
+# define alignof_slot(type) offsetof (alignof_helper<type>, __slot2)
+#else
+# define alignof_slot(type) offsetof (struct { char __slot1; type __slot2; }, __slot2)
+#endif
+
+/* alignof_type (TYPE)
+   Determine the good alignment of an object of the given type at compile time.
+   Note that this is not necessarily the same as alignof_slot(type).
+   For example, with GNU C on x86 platforms: alignof_type(double) = 8, but
+   - when -malign-double is not specified:  alignof_slot(double) = 4,
+   - when -malign-double is specified:      alignof_slot(double) = 8.
+   Note: The result cannot be used as a value for an 'enum' constant,
+   due to bugs in HP-UX 10.20 cc and AIX 3.2.5 xlc.  */
+#if defined __GNUC__ || defined __IBM__ALIGNOF__
+# define alignof_type __alignof__
+#else
+# define alignof_type alignof_slot
+#endif
+
+#endif /* _ALIGNOF_H */
diff --git a/libgnu/alloca.c b/libgnu/alloca.c
new file mode 100644
index 0000000..ee0f018
--- /dev/null
+++ b/libgnu/alloca.c
@@ -0,0 +1,478 @@
+/* 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 int
+find_stack_direction (int *addr, int depth)
+{
+  int dir, dummy = 0;
+  if (! addr)
+    addr = &dummy;
+  *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1;
+  dir = depth ? find_stack_direction (addr, depth - 1) : 0;
+  return dir + dummy;
+}
+
+#  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.  */
+    STACK_DIR = find_stack_direction (NULL, (size & 1) + 20);
+#  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 2 */
diff --git a/libgnu/alloca.in.h b/libgnu/alloca.in.h
new file mode 100644
index 0000000..c3dc38a
--- /dev/null
+++ b/libgnu/alloca.in.h
@@ -0,0 +1,65 @@
+/* Memory allocation on the stack.
+
+   Copyright (C) 1995, 1999, 2001-2004, 2006-2017 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 version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+  */
+
+/* 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
+# elif defined __DECC && defined __VMS
+#  define alloca __ALLOCA
+# elif defined __TANDEM && defined _TNS_E_TARGET
+#  ifdef  __cplusplus
+extern "C"
+#  endif
+void *_alloca (unsigned short);
+#  pragma intrinsic (_alloca)
+#  define alloca _alloca
+# elif defined __MVS__
+#  include <stdlib.h>
+# else
+#  include <stddef.h>
+#  ifdef  __cplusplus
+extern "C"
+#  endif
+void *alloca (size_t);
+# endif
+#endif
+
+#endif /* _GL_ALLOCA_H */
diff --git a/libgnu/areadlink-with-size.c b/libgnu/areadlink-with-size.c
new file mode 100644
index 0000000..cc08317
--- /dev/null
+++ b/libgnu/areadlink-with-size.c
@@ -0,0 +1,104 @@
+/* readlink wrapper to return the link name in malloc'd storage.
+   Unlike xreadlink and xreadlink_with_size, don't ever call exit.
+
+   Copyright (C) 2001, 2003-2007, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Jim Meyering <jim@meyering.net>  */
+
+#include <config.h>
+
+#include "areadlink.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifndef SSIZE_MAX
+# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
+#endif
+
+/* SYMLINK_MAX is used only for an initial memory-allocation sanity
+   check, so it's OK to guess too small on hosts where there is no
+   arbitrary limit to symbolic link length.  */
+#ifndef SYMLINK_MAX
+# define SYMLINK_MAX 1024
+#endif
+
+#define MAXSIZE (SIZE_MAX < SSIZE_MAX ? SIZE_MAX : SSIZE_MAX)
+
+/* Call readlink to get the symbolic link value of FILE.
+   SIZE is a hint as to how long the link is expected to be;
+   typically it is taken from st_size.  It need not be correct.
+   Return a pointer to that NUL-terminated string in malloc'd storage.
+   If readlink fails, malloc fails, or if the link value is longer
+   than SSIZE_MAX, return NULL (caller may use errno to diagnose).  */
+
+char *
+areadlink_with_size (char const *file, size_t size)
+{
+  /* Some buggy file systems report garbage in st_size.  Defend
+     against them by ignoring outlandish st_size values in the initial
+     memory allocation.  */
+  size_t symlink_max = SYMLINK_MAX;
+  size_t INITIAL_LIMIT_BOUND = 8 * 1024;
+  size_t initial_limit = (symlink_max < INITIAL_LIMIT_BOUND
+                          ? symlink_max + 1
+                          : INITIAL_LIMIT_BOUND);
+
+  /* The initial buffer size for the link value.  */
+  size_t buf_size = size < initial_limit ? size + 1 : initial_limit;
+
+  while (1)
+    {
+      ssize_t r;
+      size_t link_length;
+      char *buffer = malloc (buf_size);
+
+      if (buffer == NULL)
+        return NULL;
+      r = readlink (file, buffer, buf_size);
+      link_length = r;
+
+      /* On AIX 5L v5.3 and HP-UX 11i v2 04/09, readlink returns -1
+         with errno == ERANGE if the buffer is too small.  */
+      if (r < 0 && errno != ERANGE)
+        {
+          int saved_errno = errno;
+          free (buffer);
+          errno = saved_errno;
+          return NULL;
+        }
+
+      if (link_length < buf_size)
+        {
+          buffer[link_length] = 0;
+          return buffer;
+        }
+
+      free (buffer);
+      if (buf_size <= MAXSIZE / 2)
+        buf_size *= 2;
+      else if (buf_size < MAXSIZE)
+        buf_size = MAXSIZE;
+      else
+        {
+          errno = ENOMEM;
+          return NULL;
+        }
+    }
+}
diff --git a/libgnu/areadlink.h b/libgnu/areadlink.h
new file mode 100644
index 0000000..cb3b5e2
--- /dev/null
+++ b/libgnu/areadlink.h
@@ -0,0 +1,33 @@
+/* Read symbolic links without size limitation.
+
+   Copyright (C) 2001, 2003-2004, 2007, 2009-2017 Free Software Foundation,
+   Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Jim Meyering <jim@meyering.net>  */
+
+#include <stddef.h>
+
+extern char *areadlink (char const *filename);
+extern char *areadlink_with_size (char const *filename, size_t size_hint);
+
+#if GNULIB_AREADLINKAT
+extern char *areadlinkat (int fd, char const *filename);
+#endif
+
+#if GNULIB_AREADLINKAT_WITH_SIZE
+extern char *areadlinkat_with_size (int fd, char const *filename,
+                                    size_t size_hint);
+#endif
diff --git a/libgnu/arg-nonnull.h b/libgnu/arg-nonnull.h
new file mode 100644
index 0000000..1e62cc8
--- /dev/null
+++ b/libgnu/arg-nonnull.h
@@ -0,0 +1,26 @@
+/* A C macro for declaring that specific arguments must not be NULL.
+   Copyright (C) 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* _GL_ARG_NONNULL((n,...,m)) tells the compiler and static analyzer tools
+   that the values passed as arguments n, ..., m must be non-NULL pointers.
+   n = 1 stands for the first argument, n = 2 for the second argument etc.  */
+#ifndef _GL_ARG_NONNULL
+# if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || __GNUC__ > 3
+#  define _GL_ARG_NONNULL(params) __attribute__ ((__nonnull__ params))
+# else
+#  define _GL_ARG_NONNULL(params)
+# endif
+#endif
diff --git a/libgnu/argp-ba.c b/libgnu/argp-ba.c
new file mode 100644
index 0000000..73f07bd
--- /dev/null
+++ b/libgnu/argp-ba.c
@@ -0,0 +1,34 @@
+/* Default definition for ARGP_PROGRAM_BUG_ADDRESS.
+   Copyright (C) 1996-2017 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* 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
+/* This variable should be zero-initialized.  On most systems, putting it into
+   BSS is sufficient.  Not so on Mac OS X 10.3 and 10.4, see
+   <http://lists.gnu.org/archive/html/bug-gnulib/2009-01/msg00329.html>
+   <http://lists.gnu.org/archive/html/bug-gnulib/2009-08/msg00096.html>.  */
+#if defined __ELF__
+  /* On ELF systems, variables in BSS behave well.  */
+#else
+  = (const char *) 0
+#endif
+  ;
diff --git a/libgnu/argp-eexst.c b/libgnu/argp-eexst.c
new file mode 100644
index 0000000..7ee8998
--- /dev/null
+++ b/libgnu/argp-eexst.c
@@ -0,0 +1,30 @@
+/* Default definition for ARGP_ERR_EXIT_STATUS
+   Copyright (C) 1997, 2009-2017 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#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/libgnu/argp-fmtstream.c b/libgnu/argp-fmtstream.c
new file mode 100644
index 0000000..fe0d608
--- /dev/null
+++ b/libgnu/argp-fmtstream.c
@@ -0,0 +1,434 @@
+/* Word-wrapping and line-truncating streams
+   Copyright (C) 1997-2017 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* 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
+
+#ifdef _LIBC
+# 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 _LIBC
+      __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 _LIBC
+                  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 ((unsigned char) *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 ((unsigned char) *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 ((unsigned char) *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 ((unsigned char) *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 _LIBC
+              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/libgnu/argp-fmtstream.h b/libgnu/argp-fmtstream.h
new file mode 100644
index 0000000..7ca2492
--- /dev/null
+++ b/libgnu/argp-fmtstream.h
@@ -0,0 +1,310 @@
+/* Word-wrapping and line-truncating streams.
+   Copyright (C) 1997-2017 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* 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>
+
+/* The __attribute__ feature is available in gcc versions 2.5 and later.
+   The __-protected variants of the attributes 'format' and 'printf' are
+   accepted by gcc versions 2.6.4 (effectively 2.7) and later.
+   We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, because
+   gnulib and libintl do '#define printf __printf__' when they override
+   the 'printf' function.  */
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
+#else
+# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */
+#endif
+
+#if 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, ...)
+     _GL_ATTRIBUTE_FORMAT ((printf, 2, 3));
+extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs,
+                                      const char *__fmt, ...)
+     _GL_ATTRIBUTE_FORMAT ((printf, 2, 3));
+
+#if _LIBC
+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);
+#endif
+
+/* 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
+
+#if _LIBC
+/* 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);
+#endif
+
+/* 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);
+
+#if !_LIBC || defined __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
+#ifndef _GL_INLINE_HEADER_BEGIN
+ #error "Please include config.h first."
+#endif
+_GL_INLINE_HEADER_BEGIN
+#ifndef ARGP_FS_EI
+# define ARGP_FS_EI _GL_INLINE
+#endif
+#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
+_GL_INLINE_HEADER_END
+#endif
+
+#endif /* !_LIBC || __OPTIMIZE__ */
+
+#endif /* ARGP_FMTSTREAM_USE_LINEWRAP */
+
+#endif /* argp-fmtstream.h */
diff --git a/libgnu/argp-fs-xinl.c b/libgnu/argp-fs-xinl.c
new file mode 100644
index 0000000..362b555
--- /dev/null
+++ b/libgnu/argp-fs-xinl.c
@@ -0,0 +1,46 @@
+/* Real definitions for extern inline functions in argp-fmtstream.h
+   Copyright (C) 1997-2017 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# define ARGP_FS_EI
+#else
+# define ARGP_FS_EI _GL_EXTERN_INLINE
+#endif
+#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/libgnu/argp-help.c b/libgnu/argp-help.c
new file mode 100644
index 0000000..5567eee
--- /dev/null
+++ b/libgnu/argp-help.c
@@ -0,0 +1,1909 @@
+/* Hierarchical argument parsing help output
+   Copyright (C) 1995-2017 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE    1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <alloca.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <limits.h>
+#ifdef _LIBC
+# include <../libio/libioP.h>
+# include <wchar.h>
+#endif
+
+#ifdef _LIBC
+# include <libintl.h>
+# undef dgettext
+# define dgettext(domain, msgid) \
+   __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
+};
+
+/* A particular uparam, and what the user name is.  */
+struct uparam_name
+{
+  const char name[14];          /* User name.  */
+  bool is_bool;                 /* Whether it's 'boolean'.  */
+  unsigned char 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",       true, offsetof (struct uparams, dup_args) },
+  { "dup-args-note",  true, offsetof (struct uparams, dup_args_note) },
+  { "short-opt-col",  false, offsetof (struct uparams, short_opt_col) },
+  { "long-opt-col",   false, offsetof (struct uparams, long_opt_col) },
+  { "doc-opt-col",    false, offsetof (struct uparams, doc_opt_col) },
+  { "opt-doc-col",    false, offsetof (struct uparams, opt_doc_col) },
+  { "header-col",     false, offsetof (struct uparams, header_col) },
+  { "usage-indent",   false, offsetof (struct uparams, usage_indent) },
+  { "rmargin",        false, offsetof (struct uparams, rmargin) }
+};
+#define nuparam_names (sizeof (uparam_names) / sizeof (uparam_names[0]))
+
+static void
+validate_uparams (const struct argp_state *state, struct uparams *upptr)
+{
+  const struct uparam_name *up;
+
+  for (up = uparam_names; up < uparam_names + nuparam_names; 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 appropriately.  */
+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 < uparam_names + nuparam_names;
+                   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 == NULL ? NULL
+                                                : state->root_argp->argp_domain,
+                                                "\
+%.*s: ARGP_HELP_FMT parameter requires a value"),
+                                      (int) var_len, var);
+                    else
+                      *(int *)((char *)&new_params + un->uparams_offs) = val;
+                    break;
+                  }
+              if (un == uparam_names + nuparam_names)
+                __argp_failure (state, 0, 0,
+                                dgettext (state == NULL ? NULL
+                                          : 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 == NULL ? NULL
+                                        : 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 a 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 "]" appropriately if the argument is
+   optional.  The documentation string is word-wrapped appropriately, 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 slightly 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 an 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
+#if __GNUC__ >= 3
+__attribute__ ((always_inline))
+#endif
+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 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 its 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.  */
+  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 an 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;
+  /* Skip initial whitespace.  */
+  while (isspace (**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 (**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;
+
+  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 appropriate 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 last.  */
+        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 hol_cluster_cmp (entry1->cluster, entry2->cluster);
+    }
+  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 = long1 != NULL && canon_doc_option (&long1);
+      if (doc2)
+        doc2 = long2 != NULL && 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 __strcasecmp (long1, long2);
+      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 : first2 - first1;
+        }
+    }
+  else
+    /* Within the same cluster, but not the same group, so just compare
+       groups.  */
+    return group_cmp (group1, group2, 0);
+}
+
+/* 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 && 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 appropriately, 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 = { entry, stream, hhstate, 1, 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 == NULL ? NULL : 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 && 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,
+                                   dgettext (state == NULL ? NULL
+                                             : state->root_argp->argp_domain,
+                                             opt->name));
+          }
+    }
+  else
+    /* A real long option.  */
+    {
+      __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);
+            arg (real, "=%s", "[=%s]",
+                 state == NULL ? NULL : state->root_argp->argp_domain, stream);
+          }
+    }
+
+  /* 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 == NULL ? NULL
+                                               : 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 == NULL ? NULL
+                                   : 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))
+    {
+      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;
+  void *input = 0;
+  int anything = 0;
+  size_t inp_text_limit = 0;
+  const char *doc = dgettext (argp->argp_domain, argp->doc);
+  const struct argp_child *child = argp->children;
+
+  if (doc)
+    {
+      char *vt = strchr (doc, '\v');
+      inp_text = post ? (vt ? vt + 1 : 0) : doc;
+      inp_text_limit = (!post && vt) ? (vt - doc) : 0;
+    }
+  else
+    inp_text = 0;
+
+  if (argp->help_filter)
+    /* We have to filter the doc strings.  */
+    {
+      if (inp_text_limit)
+        /* Copy INP_TEXT so that it's nul-terminated.  */
+        inp_text = __strndup (inp_text, inp_text_limit);
+      input = __argp_input (argp, state);
+      text =
+        (*argp->help_filter) (post
+                              ? ARGP_KEY_HELP_POST_DOC
+                              : ARGP_KEY_HELP_PRE_DOC,
+                              inp_text, input);
+    }
+  else
+    text = (const char *) inp_text;
+
+  if (text)
+    {
+      if (pre_blank)
+        __argp_fmtstream_putc (stream, '\n');
+
+      if (text == inp_text && inp_text_limit)
+        __argp_fmtstream_write (stream, inp_text, inp_text_limit);
+      else
+        __argp_fmtstream_puts (stream, text);
+
+      if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream))
+        __argp_fmtstream_putc (stream, '\n');
+
+      anything = 1;
+    }
+
+  if (text && text != inp_text)
+    free ((char *) text);       /* Free TEXT returned from the help filter.  */
+  if (inp_text && inp_text_limit && argp->help_filter)
+    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)
+{
+  _help (argp, 0, 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
+  char *name = strrchr (program_invocation_name, '/');
+  return name ? name + 1 : 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 _LIBC
+          char *buf;
+
+          if (_IO_vasprintf (&buf, fmt, ap) < 0)
+            buf = NULL;
+
+          __fxprintf (stream, "%s: %s\n",
+                      state ? state->name : __argp_short_program_name (), buf);
+
+          free (buf);
+#else
+          fputs_unlocked (state ? state->name : __argp_short_program_name (),
+                          stream);
+          putc_unlocked (':', stream);
+          putc_unlocked (' ', stream);
+
+          vfprintf (stream, fmt, ap);
+
+          putc_unlocked ('\n', stream);
+#endif
+
+          __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 _LIBC
+          __fxprintf (stream, "%s",
+                      state ? state->name : __argp_short_program_name ());
+#else
+          fputs_unlocked (state ? state->name : __argp_short_program_name (),
+                          stream);
+#endif
+
+          if (fmt)
+            {
+              va_list ap;
+
+              va_start (ap, fmt);
+#ifdef _LIBC
+              char *buf;
+
+              if (_IO_vasprintf (&buf, fmt, ap) < 0)
+                buf = NULL;
+
+              __fxprintf (stream, ": %s", buf);
+
+              free (buf);
+#else
+              putc_unlocked (':', stream);
+              putc_unlocked (' ', stream);
+
+              vfprintf (stream, fmt, ap);
+#endif
+
+              va_end (ap);
+            }
+
+          if (errnum)
+            {
+              char buf[200];
+
+#ifdef _LIBC
+              __fxprintf (stream, ": %s",
+                          __strerror_r (errnum, buf, sizeof (buf)));
+#else
+              char const *s = NULL;
+              putc_unlocked (':', stream);
+              putc_unlocked (' ', stream);
+# if HAVE_DECL_STRERROR_R
+#  if STRERROR_R_CHAR_P
+              s = __strerror_r (errnum, buf, sizeof buf);
+#  else
+              if (__strerror_r (errnum, buf, sizeof buf) == 0)
+                s = buf;
+#  endif
+# endif
+              if (! s && ! (s = strerror (errnum)))
+                s = dgettext (state->root_argp->argp_domain,
+                              "Unknown system error");
+              fputs_unlocked (s, stream);
+#endif
+            }
+
+#if _LIBC
+          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/libgnu/argp-namefrob.h b/libgnu/argp-namefrob.h
new file mode 100644
index 0000000..baea162
--- /dev/null
+++ b/libgnu/argp-namefrob.h
@@ -0,0 +1,157 @@
+/* Name frobnication for compiling argp outside of glibc
+   Copyright (C) 1997-2017 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#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 last_component
+#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/libgnu/argp-parse.c b/libgnu/argp-parse.c
new file mode 100644
index 0000000..3f723bc
--- /dev/null
+++ b/libgnu/argp-parse.c
@@ -0,0 +1,954 @@
+/* Hierarchical argument parsing, layered over getopt
+   Copyright (C) 1995-2017 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <alloca.h>
+#include <stdalign.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) \
+   __dcgettext (domain, msgid, LC_MESSAGES)
+#else
+# include "gettext.h"
+#endif
+#define N_(msgid) msgid
+
+#include "argp.h"
+#include "argp-namefrob.h"
+
+#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, "%s",
+                      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 successfully 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;
+  /* A 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 ? 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 appropriately 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))
+    {
+#if HAVE_DECL_PROGRAM_INVOCATION_NAME
+      if (!program_invocation_name)
+        program_invocation_name = argv[0];
+#endif
+#if 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/libgnu/argp-pin.c b/libgnu/argp-pin.c
new file mode 100644
index 0000000..64d831d
--- /dev/null
+++ b/libgnu/argp-pin.c
@@ -0,0 +1,33 @@
+/* Full and short program names for argp module
+   Copyright (C) 2005, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#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
+
+#if (defined HAVE_PROGRAM_INVOCATION_SHORT_NAME \
+     && defined HAVE_PROGRAM_INVOCATION_NAME)
+/* This declaration is solely to ensure that after preprocessing
+   this file is never empty.  */
+typedef int dummy;
+#endif
diff --git a/libgnu/argp-pv.c b/libgnu/argp-pv.c
new file mode 100644
index 0000000..ce13267
--- /dev/null
+++ b/libgnu/argp-pv.c
@@ -0,0 +1,33 @@
+/* Default definition for ARGP_PROGRAM_VERSION.
+   Copyright (C) 1996-2017 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* 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
+/* This variable should be zero-initialized.  On most systems, putting it into
+   BSS is sufficient.  Not so on Mac OS X 10.3 and 10.4, see
+   <http://lists.gnu.org/archive/html/bug-gnulib/2009-01/msg00329.html>
+   <http://lists.gnu.org/archive/html/bug-gnulib/2009-08/msg00096.html>.  */
+#if defined __ELF__
+  /* On ELF systems, variables in BSS behave well.  */
+#else
+  = (const char *) 0
+#endif
+  ;
diff --git a/libgnu/argp-pvh.c b/libgnu/argp-pvh.c
new file mode 100644
index 0000000..f7e50f3
--- /dev/null
+++ b/libgnu/argp-pvh.c
@@ -0,0 +1,30 @@
+/* Default definition for ARGP_PROGRAM_VERSION_HOOK.
+   Copyright (C) 1996-2017 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#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/libgnu/argp-xinl.c b/libgnu/argp-xinl.c
new file mode 100644
index 0000000..73dd62a
--- /dev/null
+++ b/libgnu/argp-xinl.c
@@ -0,0 +1,46 @@
+/* Real definitions for extern inline functions in argp.h
+   Copyright (C) 1997-2017 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#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
+#ifdef _LIBC
+# define ARGP_EI
+#else
+# define ARGP_EI _GL_EXTERN_INLINE
+#endif
+#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/libgnu/argp.h b/libgnu/argp.h
new file mode 100644
index 0000000..2a7bf5c
--- /dev/null
+++ b/libgnu/argp.h
@@ -0,0 +1,631 @@
+/* Hierarchical argument parsing, layered over getopt.
+   Copyright (C) 1995-2017 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _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
+
+/* The __attribute__ feature is available in gcc versions 2.5 and later.
+   The __-protected variants of the attributes 'format' and 'printf' are
+   accepted by gcc versions 2.6.4 (effectively 2.7) and later.
+   We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, because
+   gnulib and libintl do '#define printf __printf__' when they override
+   the 'printf' function.  */
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
+#else
+# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */
+#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 preceding 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 appropriate 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);
+
+#if _LIBC
+/* 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);
+#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).  */
+extern void argp_error (const struct argp_state *__restrict __state,
+                        const char *__restrict __fmt, ...)
+     _GL_ATTRIBUTE_FORMAT ((__printf__, 2, 3));
+extern void __argp_error (const struct argp_state *__restrict __state,
+                          const char *__restrict __fmt, ...)
+     _GL_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, ...)
+     _GL_ATTRIBUTE_FORMAT ((__printf__, 4, 5));
+extern void __argp_failure (const struct argp_state *__restrict __state,
+                            int __status, int __errnum,
+                            const char *__restrict __fmt, ...)
+     _GL_ATTRIBUTE_FORMAT ((__printf__, 4, 5));
+
+#if _LIBC
+/* 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;
+#endif
+
+/* 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;
+
+#if !_LIBC || defined __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
+#ifndef _GL_INLINE_HEADER_BEGIN
+ #error "Please include config.h first."
+#endif
+_GL_INLINE_HEADER_BEGIN
+#  ifndef ARGP_EI
+#   define ARGP_EI _GL_INLINE
+#  endif
+# 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
+_GL_INLINE_HEADER_END
+# endif
+#endif /* Use extern inlines.  */
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* argp.h */
diff --git a/libgnu/asnprintf.c b/libgnu/asnprintf.c
new file mode 100644
index 0000000..14ab3e8
--- /dev/null
+++ b/libgnu/asnprintf.c
@@ -0,0 +1,34 @@
+/* Formatted output to strings.
+   Copyright (C) 1999, 2002, 2006, 2009-2017 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 version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "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/libgnu/assure.h b/libgnu/assure.h
new file mode 100644
index 0000000..2fc3043
--- /dev/null
+++ b/libgnu/assure.h
@@ -0,0 +1,37 @@
+/* Run-time assert-like macros.
+
+   Copyright (C) 2014-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Paul Eggert.  */
+
+#ifndef _GL_ASSURE_H
+#define _GL_ASSURE_H
+
+#include <assert.h>
+
+/* Check E's value at runtime, and report an error and abort if not.
+   However, do nothng if NDEBUG is defined.
+
+   Unlike standard 'assert', this macro always compiles E even when NDEBUG
+   is defined, so as to catch typos and avoid some GCC warnings.  */
+
+#ifdef NDEBUG
+# define assure(E) ((void) (0 && (E)))
+#else
+# define assure(E) assert (E)
+#endif
+
+#endif
diff --git a/libgnu/at-func.c b/libgnu/at-func.c
new file mode 100644
index 0000000..9eaa993
--- /dev/null
+++ b/libgnu/at-func.c
@@ -0,0 +1,146 @@
+/* Define at-style functions like fstatat, unlinkat, fchownat, etc.
+   Copyright (C) 2006, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* written by Jim Meyering */
+
+#include "dosname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
+
+#ifdef GNULIB_SUPPORT_ONLY_AT_FDCWD
+# include <errno.h>
+# ifndef ENOTSUP
+#  define ENOTSUP EINVAL
+# endif
+#else
+# include "openat.h"
+# include "openat-priv.h"
+# include "save-cwd.h"
+#endif
+
+#ifdef AT_FUNC_USE_F1_COND
+# define CALL_FUNC(F)                           \
+  (flag == AT_FUNC_USE_F1_COND                  \
+    ? AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS)     \
+    : AT_FUNC_F2 (F AT_FUNC_POST_FILE_ARGS))
+# define VALIDATE_FLAG(F)                       \
+  if (flag & ~AT_FUNC_USE_F1_COND)              \
+    {                                           \
+      errno = EINVAL;                           \
+      return FUNC_FAIL;                         \
+    }
+#else
+# define CALL_FUNC(F) (AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS))
+# define VALIDATE_FLAG(F) /* empty */
+#endif
+
+#ifdef AT_FUNC_RESULT
+# define FUNC_RESULT AT_FUNC_RESULT
+#else
+# define FUNC_RESULT int
+#endif
+
+#ifdef AT_FUNC_FAIL
+# define FUNC_FAIL AT_FUNC_FAIL
+#else
+# define FUNC_FAIL -1
+#endif
+
+/* Call AT_FUNC_F1 to operate on FILE, which is in the directory
+   open on descriptor FD.  If AT_FUNC_USE_F1_COND is defined to a value,
+   AT_FUNC_POST_FILE_PARAM_DECLS must include a parameter named flag;
+   call AT_FUNC_F2 if FLAG is 0 or fail if FLAG contains more bits than
+   AT_FUNC_USE_F1_COND.  Return int and fail with -1 unless AT_FUNC_RESULT
+   or AT_FUNC_FAIL are defined.  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.  */
+FUNC_RESULT
+AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS)
+{
+  VALIDATE_FLAG (flag);
+
+  if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file))
+    return CALL_FUNC (file);
+
+#ifdef GNULIB_SUPPORT_ONLY_AT_FDCWD
+  errno = ENOTSUP;
+  return FUNC_FAIL;
+#else
+  {
+  /* Be careful to choose names unlikely to conflict with
+     AT_FUNC_POST_FILE_PARAM_DECLS.  */
+  struct saved_cwd saved_cwd;
+  int saved_errno;
+  FUNC_RESULT err;
+
+  {
+    char proc_buf[OPENAT_BUFFER_SIZE];
+    char *proc_file = openat_proc_name (proc_buf, fd, file);
+    if (proc_file)
+      {
+        FUNC_RESULT proc_result = CALL_FUNC (proc_file);
+        int proc_errno = errno;
+        if (proc_file != proc_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 (FUNC_FAIL != 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 (0 <= fd && fd == saved_cwd.desc)
+    {
+      /* If saving the working directory collides with the user's
+         requested fd, then the user's fd must have been closed to
+         begin with.  */
+      free_cwd (&saved_cwd);
+      errno = EBADF;
+      return FUNC_FAIL;
+    }
+
+  if (fchdir (fd) != 0)
+    {
+      saved_errno = errno;
+      free_cwd (&saved_cwd);
+      errno = saved_errno;
+      return FUNC_FAIL;
+    }
+
+  err = CALL_FUNC (file);
+  saved_errno = (err == FUNC_FAIL ? errno : 0);
+
+  if (restore_cwd (&saved_cwd) != 0)
+    openat_restore_fail (errno);
+
+  free_cwd (&saved_cwd);
+
+  if (saved_errno)
+    errno = saved_errno;
+  return err;
+  }
+#endif
+}
+#undef CALL_FUNC
+#undef FUNC_RESULT
+#undef FUNC_FAIL
diff --git a/libgnu/basename-lgpl.c b/libgnu/basename-lgpl.c
new file mode 100644
index 0000000..54d3cc0
--- /dev/null
+++ b/libgnu/basename-lgpl.c
@@ -0,0 +1,75 @@
+/* basename.c -- return the last element in a file name
+
+   Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2017 Free Software
+   Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include "dirname.h"
+
+#include <string.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;
+}
+
+/* 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/libgnu/basename.c b/libgnu/basename.c
new file mode 100644
index 0000000..0353635
--- /dev/null
+++ b/libgnu/basename.c
@@ -0,0 +1,58 @@
+/* basename.c -- return the last element in a file name
+
+   Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2017 Free Software
+   Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include "dirname.h"
+
+#include <string.h>
+#include "xalloc.h"
+#include "xstrndup.h"
+
+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);
+}
diff --git a/libgnu/bitrotate.c b/libgnu/bitrotate.c
new file mode 100644
index 0000000..a8f6028
--- /dev/null
+++ b/libgnu/bitrotate.c
@@ -0,0 +1,3 @@
+#include <config.h>
+#define BITROTATE_INLINE _GL_EXTERN_INLINE
+#include "bitrotate.h"
diff --git a/libgnu/bitrotate.h b/libgnu/bitrotate.h
new file mode 100644
index 0000000..ea14afb
--- /dev/null
+++ b/libgnu/bitrotate.h
@@ -0,0 +1,136 @@
+/* bitrotate.h - Rotate bits in integers
+   Copyright (C) 2008-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Simon Josefsson <simon@josefsson.org>, 2008. */
+
+#ifndef _GL_BITROTATE_H
+#define _GL_BITROTATE_H
+
+#include <limits.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifndef _GL_INLINE_HEADER_BEGIN
+ #error "Please include config.h first."
+#endif
+_GL_INLINE_HEADER_BEGIN
+#ifndef BITROTATE_INLINE
+# define BITROTATE_INLINE _GL_INLINE
+#endif
+
+#ifdef UINT64_MAX
+/* Given an unsigned 64-bit argument X, return the value corresponding
+   to rotating the bits N steps to the left.  N must be between 1 and
+   63 inclusive. */
+BITROTATE_INLINE uint64_t
+rotl64 (uint64_t x, int n)
+{
+  return ((x << n) | (x >> (64 - n))) & UINT64_MAX;
+}
+
+/* Given an unsigned 64-bit argument X, return the value corresponding
+   to rotating the bits N steps to the right.  N must be between 1 to
+   63 inclusive.*/
+BITROTATE_INLINE uint64_t
+rotr64 (uint64_t x, int n)
+{
+  return ((x >> n) | (x << (64 - n))) & UINT64_MAX;
+}
+#endif
+
+/* Given an unsigned 32-bit argument X, return the value corresponding
+   to rotating the bits N steps to the left.  N must be between 1 and
+   31 inclusive. */
+BITROTATE_INLINE uint32_t
+rotl32 (uint32_t x, int n)
+{
+  return ((x << n) | (x >> (32 - n))) & UINT32_MAX;
+}
+
+/* Given an unsigned 32-bit argument X, return the value corresponding
+   to rotating the bits N steps to the right.  N must be between 1 to
+   31 inclusive.*/
+BITROTATE_INLINE uint32_t
+rotr32 (uint32_t x, int n)
+{
+  return ((x >> n) | (x << (32 - n))) & UINT32_MAX;
+}
+
+/* Given a size_t argument X, return the value corresponding
+   to rotating the bits N steps to the left.  N must be between 1 and
+   (CHAR_BIT * sizeof (size_t) - 1) inclusive.  */
+BITROTATE_INLINE size_t
+rotl_sz (size_t x, int n)
+{
+  return ((x << n) | (x >> ((CHAR_BIT * sizeof x) - n))) & SIZE_MAX;
+}
+
+/* Given a size_t argument X, return the value corresponding
+   to rotating the bits N steps to the right.  N must be between 1 to
+   (CHAR_BIT * sizeof (size_t) - 1) inclusive.  */
+BITROTATE_INLINE size_t
+rotr_sz (size_t x, int n)
+{
+  return ((x >> n) | (x << ((CHAR_BIT * sizeof x) - n))) & SIZE_MAX;
+}
+
+/* Given an unsigned 16-bit argument X, return the value corresponding
+   to rotating the bits N steps to the left.  N must be between 1 to
+   15 inclusive, but on most relevant targets N can also be 0 and 16
+   because 'int' is at least 32 bits and the arguments must widen
+   before shifting. */
+BITROTATE_INLINE uint16_t
+rotl16 (uint16_t x, int n)
+{
+  return ((x << n) | (x >> (16 - n))) & UINT16_MAX;
+}
+
+/* Given an unsigned 16-bit argument X, return the value corresponding
+   to rotating the bits N steps to the right.  N must be in 1 to 15
+   inclusive, but on most relevant targets N can also be 0 and 16
+   because 'int' is at least 32 bits and the arguments must widen
+   before shifting. */
+BITROTATE_INLINE uint16_t
+rotr16 (uint16_t x, int n)
+{
+  return ((x >> n) | (x << (16 - n))) & UINT16_MAX;
+}
+
+/* Given an unsigned 8-bit argument X, return the value corresponding
+   to rotating the bits N steps to the left.  N must be between 1 to 7
+   inclusive, but on most relevant targets N can also be 0 and 8
+   because 'int' is at least 32 bits and the arguments must widen
+   before shifting. */
+BITROTATE_INLINE uint8_t
+rotl8 (uint8_t x, int n)
+{
+  return ((x << n) | (x >> (8 - n))) & UINT8_MAX;
+}
+
+/* Given an unsigned 8-bit argument X, return the value corresponding
+   to rotating the bits N steps to the right.  N must be in 1 to 7
+   inclusive, but on most relevant targets N can also be 0 and 8
+   because 'int' is at least 32 bits and the arguments must widen
+   before shifting. */
+BITROTATE_INLINE uint8_t
+rotr8 (uint8_t x, int n)
+{
+  return ((x >> n) | (x << (8 - n))) & UINT8_MAX;
+}
+
+_GL_INLINE_HEADER_END
+
+#endif /* _GL_BITROTATE_H */
diff --git a/libgnu/c++defs.h b/libgnu/c++defs.h
new file mode 100644
index 0000000..f03f359
--- /dev/null
+++ b/libgnu/c++defs.h
@@ -0,0 +1,316 @@
+/* C++ compatible function declaration macros.
+   Copyright (C) 2010-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _GL_CXXDEFS_H
+#define _GL_CXXDEFS_H
+
+/* Begin/end the GNULIB_NAMESPACE namespace.  */
+#if defined __cplusplus && defined GNULIB_NAMESPACE
+# define _GL_BEGIN_NAMESPACE namespace GNULIB_NAMESPACE {
+# define _GL_END_NAMESPACE }
+#else
+# define _GL_BEGIN_NAMESPACE
+# define _GL_END_NAMESPACE
+#endif
+
+/* The three most frequent use cases of these macros are:
+
+   * For providing a substitute for a function that is missing on some
+     platforms, but is declared and works fine on the platforms on which
+     it exists:
+
+       #if @GNULIB_FOO@
+       # if !@HAVE_FOO@
+       _GL_FUNCDECL_SYS (foo, ...);
+       # endif
+       _GL_CXXALIAS_SYS (foo, ...);
+       _GL_CXXALIASWARN (foo);
+       #elif defined GNULIB_POSIXCHECK
+       ...
+       #endif
+
+   * For providing a replacement for a function that exists on all platforms,
+     but is broken/insufficient and needs to be replaced on some platforms:
+
+       #if @GNULIB_FOO@
+       # if @REPLACE_FOO@
+       #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+       #   undef foo
+       #   define foo rpl_foo
+       #  endif
+       _GL_FUNCDECL_RPL (foo, ...);
+       _GL_CXXALIAS_RPL (foo, ...);
+       # else
+       _GL_CXXALIAS_SYS (foo, ...);
+       # endif
+       _GL_CXXALIASWARN (foo);
+       #elif defined GNULIB_POSIXCHECK
+       ...
+       #endif
+
+   * For providing a replacement for a function that exists on some platforms
+     but is broken/insufficient and needs to be replaced on some of them and
+     is additionally either missing or undeclared on some other platforms:
+
+       #if @GNULIB_FOO@
+       # if @REPLACE_FOO@
+       #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+       #   undef foo
+       #   define foo rpl_foo
+       #  endif
+       _GL_FUNCDECL_RPL (foo, ...);
+       _GL_CXXALIAS_RPL (foo, ...);
+       # else
+       #  if !@HAVE_FOO@   or   if !@HAVE_DECL_FOO@
+       _GL_FUNCDECL_SYS (foo, ...);
+       #  endif
+       _GL_CXXALIAS_SYS (foo, ...);
+       # endif
+       _GL_CXXALIASWARN (foo);
+       #elif defined GNULIB_POSIXCHECK
+       ...
+       #endif
+*/
+
+/* _GL_EXTERN_C declaration;
+   performs the declaration with C linkage.  */
+#if defined __cplusplus
+# define _GL_EXTERN_C extern "C"
+#else
+# define _GL_EXTERN_C extern
+#endif
+
+/* _GL_FUNCDECL_RPL (func, rettype, parameters_and_attributes);
+   declares a replacement function, named rpl_func, with the given prototype,
+   consisting of return type, parameters, and attributes.
+   Example:
+     _GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...)
+                                  _GL_ARG_NONNULL ((1)));
+ */
+#define _GL_FUNCDECL_RPL(func,rettype,parameters_and_attributes) \
+  _GL_FUNCDECL_RPL_1 (rpl_##func, rettype, parameters_and_attributes)
+#define _GL_FUNCDECL_RPL_1(rpl_func,rettype,parameters_and_attributes) \
+  _GL_EXTERN_C rettype rpl_func parameters_and_attributes
+
+/* _GL_FUNCDECL_SYS (func, rettype, parameters_and_attributes);
+   declares the system function, named func, with the given prototype,
+   consisting of return type, parameters, and attributes.
+   Example:
+     _GL_FUNCDECL_SYS (open, int, (const char *filename, int flags, ...)
+                                  _GL_ARG_NONNULL ((1)));
+ */
+#define _GL_FUNCDECL_SYS(func,rettype,parameters_and_attributes) \
+  _GL_EXTERN_C rettype func parameters_and_attributes
+
+/* _GL_CXXALIAS_RPL (func, rettype, parameters);
+   declares a C++ alias called GNULIB_NAMESPACE::func
+   that redirects to rpl_func, if GNULIB_NAMESPACE is defined.
+   Example:
+     _GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...));
+
+   Wrapping rpl_func in an object with an inline conversion operator
+   avoids a reference to rpl_func unless GNULIB_NAMESPACE::func is
+   actually used in the program.  */
+#define _GL_CXXALIAS_RPL(func,rettype,parameters) \
+  _GL_CXXALIAS_RPL_1 (func, rpl_##func, rettype, parameters)
+#if defined __cplusplus && defined GNULIB_NAMESPACE
+# define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \
+    namespace GNULIB_NAMESPACE                                \
+    {                                                         \
+      static const struct _gl_ ## func ## _wrapper            \
+      {                                                       \
+        typedef rettype (*type) parameters;                   \
+                                                              \
+        inline operator type () const                         \
+        {                                                     \
+          return ::rpl_func;                                  \
+        }                                                     \
+      } func = {};                                            \
+    }                                                         \
+    _GL_EXTERN_C int _gl_cxxalias_dummy
+#else
+# define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \
+    _GL_EXTERN_C int _gl_cxxalias_dummy
+#endif
+
+/* _GL_CXXALIAS_RPL_CAST_1 (func, rpl_func, rettype, parameters);
+   is like  _GL_CXXALIAS_RPL_1 (func, rpl_func, rettype, parameters);
+   except that the C function rpl_func may have a slightly different
+   declaration.  A cast is used to silence the "invalid conversion" error
+   that would otherwise occur.  */
+#if defined __cplusplus && defined GNULIB_NAMESPACE
+# define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \
+    namespace GNULIB_NAMESPACE                                     \
+    {                                                              \
+      static const struct _gl_ ## func ## _wrapper                 \
+      {                                                            \
+        typedef rettype (*type) parameters;                        \
+                                                                   \
+        inline operator type () const                              \
+        {                                                          \
+          return reinterpret_cast<type>(::rpl_func);               \
+        }                                                          \
+      } func = {};                                                 \
+    }                                                              \
+    _GL_EXTERN_C int _gl_cxxalias_dummy
+#else
+# define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \
+    _GL_EXTERN_C int _gl_cxxalias_dummy
+#endif
+
+/* _GL_CXXALIAS_SYS (func, rettype, parameters);
+   declares a C++ alias called GNULIB_NAMESPACE::func
+   that redirects to the system provided function func, if GNULIB_NAMESPACE
+   is defined.
+   Example:
+     _GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...));
+
+   Wrapping func in an object with an inline conversion operator
+   avoids a reference to func unless GNULIB_NAMESPACE::func is
+   actually used in the program.  */
+#if defined __cplusplus && defined GNULIB_NAMESPACE
+# define _GL_CXXALIAS_SYS(func,rettype,parameters)            \
+    namespace GNULIB_NAMESPACE                                \
+    {                                                         \
+      static const struct _gl_ ## func ## _wrapper            \
+      {                                                       \
+        typedef rettype (*type) parameters;                   \
+                                                              \
+        inline operator type () const                         \
+        {                                                     \
+          return ::func;                                      \
+        }                                                     \
+      } func = {};                                            \
+    }                                                         \
+    _GL_EXTERN_C int _gl_cxxalias_dummy
+#else
+# define _GL_CXXALIAS_SYS(func,rettype,parameters) \
+    _GL_EXTERN_C int _gl_cxxalias_dummy
+#endif
+
+/* _GL_CXXALIAS_SYS_CAST (func, rettype, parameters);
+   is like  _GL_CXXALIAS_SYS (func, rettype, parameters);
+   except that the C function func may have a slightly different declaration.
+   A cast is used to silence the "invalid conversion" error that would
+   otherwise occur.  */
+#if defined __cplusplus && defined GNULIB_NAMESPACE
+# define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \
+    namespace GNULIB_NAMESPACE                          \
+    {                                                   \
+      static const struct _gl_ ## func ## _wrapper      \
+      {                                                 \
+        typedef rettype (*type) parameters;             \
+                                                        \
+        inline operator type () const                   \
+        {                                               \
+          return reinterpret_cast<type>(::func);        \
+        }                                               \
+      } func = {};                                      \
+    }                                                   \
+    _GL_EXTERN_C int _gl_cxxalias_dummy
+#else
+# define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \
+    _GL_EXTERN_C int _gl_cxxalias_dummy
+#endif
+
+/* _GL_CXXALIAS_SYS_CAST2 (func, rettype, parameters, rettype2, parameters2);
+   is like  _GL_CXXALIAS_SYS (func, rettype, parameters);
+   except that the C function is picked among a set of overloaded functions,
+   namely the one with rettype2 and parameters2.  Two consecutive casts
+   are used to silence the "cannot find a match" and "invalid conversion"
+   errors that would otherwise occur.  */
+#if defined __cplusplus && defined GNULIB_NAMESPACE
+  /* The outer cast must be a reinterpret_cast.
+     The inner cast: When the function is defined as a set of overloaded
+     functions, it works as a static_cast<>, choosing the designated variant.
+     When the function is defined as a single variant, it works as a
+     reinterpret_cast<>. The parenthesized cast syntax works both ways.  */
+# define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \
+    namespace GNULIB_NAMESPACE                                                \
+    {                                                                         \
+      static const struct _gl_ ## func ## _wrapper                            \
+      {                                                                       \
+        typedef rettype (*type) parameters;                                   \
+                                                                              \
+        inline operator type () const                                         \
+        {                                                                     \
+          return reinterpret_cast<type>((rettype2 (*) parameters2)(::func));  \
+        }                                                                     \
+      } func = {};                                                            \
+    }                                                                         \
+    _GL_EXTERN_C int _gl_cxxalias_dummy
+#else
+# define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \
+    _GL_EXTERN_C int _gl_cxxalias_dummy
+#endif
+
+/* _GL_CXXALIASWARN (func);
+   causes a warning to be emitted when ::func is used but not when
+   GNULIB_NAMESPACE::func is used.  func must be defined without overloaded
+   variants.  */
+#if defined __cplusplus && defined GNULIB_NAMESPACE
+# define _GL_CXXALIASWARN(func) \
+   _GL_CXXALIASWARN_1 (func, GNULIB_NAMESPACE)
+# define _GL_CXXALIASWARN_1(func,namespace) \
+   _GL_CXXALIASWARN_2 (func, namespace)
+/* To work around GCC bug <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43881>,
+   we enable the warning only when not optimizing.  */
+# if !__OPTIMIZE__
+#  define _GL_CXXALIASWARN_2(func,namespace) \
+    _GL_WARN_ON_USE (func, \
+                     "The symbol ::" #func " refers to the system function. " \
+                     "Use " #namespace "::" #func " instead.")
+# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
+#  define _GL_CXXALIASWARN_2(func,namespace) \
+     extern __typeof__ (func) func
+# else
+#  define _GL_CXXALIASWARN_2(func,namespace) \
+     _GL_EXTERN_C int _gl_cxxalias_dummy
+# endif
+#else
+# define _GL_CXXALIASWARN(func) \
+    _GL_EXTERN_C int _gl_cxxalias_dummy
+#endif
+
+/* _GL_CXXALIASWARN1 (func, rettype, parameters_and_attributes);
+   causes a warning to be emitted when the given overloaded variant of ::func
+   is used but not when GNULIB_NAMESPACE::func is used.  */
+#if defined __cplusplus && defined GNULIB_NAMESPACE
+# define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \
+   _GL_CXXALIASWARN1_1 (func, rettype, parameters_and_attributes, \
+                        GNULIB_NAMESPACE)
+# define _GL_CXXALIASWARN1_1(func,rettype,parameters_and_attributes,namespace) \
+   _GL_CXXALIASWARN1_2 (func, rettype, parameters_and_attributes, namespace)
+/* To work around GCC bug <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43881>,
+   we enable the warning only when not optimizing.  */
+# if !__OPTIMIZE__
+#  define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \
+    _GL_WARN_ON_USE_CXX (func, rettype, parameters_and_attributes, \
+                         "The symbol ::" #func " refers to the system function. " \
+                         "Use " #namespace "::" #func " instead.")
+# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
+#  define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \
+     extern __typeof__ (func) func
+# else
+#  define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \
+     _GL_EXTERN_C int _gl_cxxalias_dummy
+# endif
+#else
+# define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \
+    _GL_EXTERN_C int _gl_cxxalias_dummy
+#endif
+
+#endif /* _GL_CXXDEFS_H */
diff --git a/libgnu/canonicalize.c b/libgnu/canonicalize.c
new file mode 100644
index 0000000..a2f533f
--- /dev/null
+++ b/libgnu/canonicalize.c
@@ -0,0 +1,354 @@
+/* Return the canonical absolute name of a given file.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include "canonicalize.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "areadlink.h"
+#include "file-set.h"
+#include "hash-triple.h"
+#include "pathmax.h"
+#include "xalloc.h"
+#include "xgetcwd.h"
+#include "dosname.h"
+
+#define MULTIPLE_BITS_SET(i) (((i) & ((i) - 1)) != 0)
+
+/* In this file, we cannot handle file names longer than PATH_MAX.
+   On systems with no file name length limit, use a fallback.  */
+#ifndef PATH_MAX
+# define PATH_MAX 8192
+#endif
+
+#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
+# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
+#endif
+
+#if ISSLASH ('\\')
+# define SLASHES "/\\"
+#else
+# define SLASHES "/"
+#endif
+
+#if !((HAVE_CANONICALIZE_FILE_NAME && FUNC_REALPATH_WORKS)      \
+      || GNULIB_CANONICALIZE_LGPL)
+/* Return the canonical absolute name of file NAME.  A canonical name
+   does not contain any ".", ".." components nor any repeated file name
+   separators ('/') or symlinks.  All components must exist.
+   The result is malloc'd.  */
+
+char *
+canonicalize_file_name (const char *name)
+{
+  return canonicalize_filename_mode (name, CAN_EXISTING);
+}
+#endif /* !HAVE_CANONICALIZE_FILE_NAME */
+
+/* Return true if we've already seen the triple, <FILENAME, dev, ino>.
+   If *HT is not initialized, initialize it.  */
+static bool
+seen_triple (Hash_table **ht, char const *filename, struct stat const *st)
+{
+  if (*ht == NULL)
+    {
+      size_t initial_capacity = 7;
+      *ht = hash_initialize (initial_capacity,
+                            NULL,
+                            triple_hash,
+                            triple_compare_ino_str,
+                            triple_free);
+      if (*ht == NULL)
+        xalloc_die ();
+    }
+
+  if (seen_file (*ht, filename, st))
+    return true;
+
+  record_file (*ht, filename, st);
+  return false;
+}
+
+/* Return the canonical absolute name of file NAME, while treating
+   missing elements according to CAN_MODE.  A canonical name
+   does not contain any ".", ".." components nor any repeated file name
+   separators ('/') or, depending on other CAN_MODE flags, symlinks.
+   Whether components must exist or not depends on canonicalize mode.
+   The result is malloc'd.  */
+
+char *
+canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode)
+{
+  char *rname, *dest, *extra_buf = NULL;
+  char const *start;
+  char const *end;
+  char const *rname_limit;
+  size_t extra_len = 0;
+  Hash_table *ht = NULL;
+  int saved_errno;
+  int can_flags = can_mode & ~CAN_MODE_MASK;
+  bool logical = can_flags & CAN_NOLINKS;
+  size_t prefix_len;
+
+  can_mode &= CAN_MODE_MASK;
+
+  if (MULTIPLE_BITS_SET (can_mode))
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+
+  if (name == NULL)
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+
+  if (name[0] == '\0')
+    {
+      errno = ENOENT;
+      return NULL;
+    }
+
+  /* This is always zero for Posix hosts, but can be 2 for MS-Windows
+     and MS-DOS X:/foo/bar file names.  */
+  prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
+
+  if (!IS_ABSOLUTE_FILE_NAME (name))
+    {
+      rname = xgetcwd ();
+      if (!rname)
+        return NULL;
+      dest = strchr (rname, '\0');
+      if (dest - rname < PATH_MAX)
+        {
+          char *p = xrealloc (rname, PATH_MAX);
+          dest = p + (dest - rname);
+          rname = p;
+          rname_limit = rname + PATH_MAX;
+        }
+      else
+        {
+          rname_limit = dest;
+        }
+      start = name;
+      prefix_len = FILE_SYSTEM_PREFIX_LEN (rname);
+    }
+  else
+    {
+      rname = xmalloc (PATH_MAX);
+      rname_limit = rname + PATH_MAX;
+      dest = rname;
+      if (prefix_len)
+        {
+          memcpy (rname, name, prefix_len);
+          dest += prefix_len;
+        }
+      *dest++ = '/';
+      if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
+        {
+          if (ISSLASH (name[1]) && !ISSLASH (name[2]) && !prefix_len)
+            *dest++ = '/';
+          *dest = '\0';
+        }
+      start = name + prefix_len;
+    }
+
+  for ( ; *start; start = end)
+    {
+      /* Skip sequence of multiple file name separators.  */
+      while (ISSLASH (*start))
+        ++start;
+
+      /* Find end of component.  */
+      for (end = start; *end && !ISSLASH (*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 > rname + prefix_len + 1)
+            for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
+              continue;
+          if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
+              && !prefix_len && ISSLASH (*dest) && !ISSLASH (dest[1]))
+            dest++;
+        }
+      else
+        {
+          struct stat st;
+
+          if (!ISSLASH (dest[-1]))
+            *dest++ = '/';
+
+          if (dest + (end - start) >= rname_limit)
+            {
+              ptrdiff_t dest_offset = dest - rname;
+              size_t new_size = rname_limit - rname;
+
+              if (end - start + 1 > PATH_MAX)
+                new_size += end - start + 1;
+              else
+                new_size += PATH_MAX;
+              rname = xrealloc (rname, new_size);
+              rname_limit = rname + new_size;
+
+              dest = rname + dest_offset;
+            }
+
+          dest = memcpy (dest, start, end - start);
+          dest += end - start;
+          *dest = '\0';
+
+          if (logical && (can_mode == CAN_MISSING))
+            {
+              /* Avoid the stat in this case as it's inconsequential.
+                 i.e. we're neither resolving symlinks or testing
+                 component existence.  */
+              st.st_mode = 0;
+            }
+          else if ((logical ? stat (rname, &st) : lstat (rname, &st)) != 0)
+            {
+              saved_errno = errno;
+              if (can_mode == CAN_EXISTING)
+                goto error;
+              if (can_mode == CAN_ALL_BUT_LAST)
+                {
+                  if (end[strspn (end, SLASHES)] || saved_errno != ENOENT)
+                    goto error;
+                  continue;
+                }
+              st.st_mode = 0;
+            }
+
+          if (S_ISLNK (st.st_mode))
+            {
+              char *buf;
+              size_t n, len;
+
+              /* Detect loops.  We cannot use the cycle-check module here,
+                 since it's actually possible to encounter the same symlink
+                 more than once in a given traversal.  However, encountering
+                 the same symlink,NAME pair twice does indicate a loop.  */
+              if (seen_triple (&ht, name, &st))
+                {
+                  if (can_mode == CAN_MISSING)
+                    continue;
+                  saved_errno = ELOOP;
+                  goto error;
+                }
+
+              buf = areadlink_with_size (rname, st.st_size);
+              if (!buf)
+                {
+                  if (can_mode == CAN_MISSING && errno != ENOMEM)
+                    continue;
+                  saved_errno = errno;
+                  goto error;
+                }
+
+              n = strlen (buf);
+              len = strlen (end);
+
+              if (!extra_len)
+                {
+                  extra_len =
+                    ((n + len + 1) > PATH_MAX) ? (n + len + 1) : PATH_MAX;
+                  extra_buf = xmalloc (extra_len);
+                }
+              else if ((n + len + 1) > extra_len)
+                {
+                  extra_len = n + len + 1;
+                  extra_buf = xrealloc (extra_buf, extra_len);
+                }
+
+              /* 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 (IS_ABSOLUTE_FILE_NAME (buf))
+                {
+                  size_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
+
+                  if (pfxlen)
+                    memcpy (rname, buf, pfxlen);
+                  dest = rname + pfxlen;
+                  *dest++ = '/'; /* It's an absolute symlink */
+                  if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
+                    {
+                      if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen)
+                        *dest++ = '/';
+                      *dest = '\0';
+                    }
+                  /* Install the new prefix to be in effect hereafter.  */
+                  prefix_len = pfxlen;
+                }
+              else
+                {
+                  /* Back up to previous component, ignore if at root
+                     already: */
+                  if (dest > rname + prefix_len + 1)
+                    for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
+                      continue;
+                  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
+                      && ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len)
+                    dest++;
+                }
+
+              free (buf);
+            }
+          else
+            {
+              if (!S_ISDIR (st.st_mode) && *end && (can_mode != CAN_MISSING))
+                {
+                  saved_errno = ENOTDIR;
+                  goto error;
+                }
+            }
+        }
+    }
+  if (dest > rname + prefix_len + 1 && ISSLASH (dest[-1]))
+    --dest;
+  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 && !prefix_len
+      && ISSLASH (*dest) && !ISSLASH (dest[1]))
+    dest++;
+  *dest = '\0';
+  if (rname_limit != dest + 1)
+    rname = xrealloc (rname, dest - rname + 1);
+
+  free (extra_buf);
+  if (ht)
+    hash_free (ht);
+  return rname;
+
+error:
+  free (extra_buf);
+  free (rname);
+  if (ht)
+    hash_free (ht);
+  errno = saved_errno;
+  return NULL;
+}
diff --git a/libgnu/canonicalize.h b/libgnu/canonicalize.h
new file mode 100644
index 0000000..772eecc
--- /dev/null
+++ b/libgnu/canonicalize.h
@@ -0,0 +1,48 @@
+/* Return the canonical absolute name of a given file.
+   Copyright (C) 1996-2007, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef CANONICALIZE_H_
+# define CANONICALIZE_H_
+
+#include <stdlib.h> /* for canonicalize_file_name */
+
+#define CAN_MODE_MASK (CAN_EXISTING | CAN_ALL_BUT_LAST | CAN_MISSING)
+
+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,
+
+    /* Don't expand symlinks.  */
+    CAN_NOLINKS = 4
+  };
+typedef enum canonicalize_mode_t canonicalize_mode_t;
+
+/* Return the canonical absolute name of file NAME, while treating
+   missing elements according to CAN_MODE.  A canonical name
+   does not contain any `.', `..' components nor any repeated file name
+   separators ('/') or, depending on other CAN_MODE flags, symlinks.
+   Whether components must exist or not depends on canonicalize mode.
+   The result is malloc'd.  */
+char *canonicalize_filename_mode (const char *, canonicalize_mode_t);
+
+#endif /* !CANONICALIZE_H_ */
diff --git a/libgnu/chdir-long.c b/libgnu/chdir-long.c
new file mode 100644
index 0000000..d6c35c9
--- /dev/null
+++ b/libgnu/chdir-long.c
@@ -0,0 +1,264 @@
+/* provide a chdir function that tries not to fail due to ENAMETOOLONG
+   Copyright (C) 2004-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* written by Jim Meyering */
+
+#include <config.h>
+
+#include "chdir-long.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "assure.h"
+
+#ifndef PATH_MAX
+# error "compile this file only if your system defines PATH_MAX"
+#endif
+
+/* The results of openat() in this file are not leaked to any
+   single-threaded code that could use stdio.
+   FIXME - if the kernel ever adds support for multi-thread safety for
+   avoiding standard fds, then we should use openat_safer.  */
+
+struct cd_buf
+{
+  int fd;
+};
+
+static void
+cdb_init (struct cd_buf *cdb)
+{
+  cdb->fd = AT_FDCWD;
+}
+
+static int
+cdb_fchdir (struct cd_buf const *cdb)
+{
+  return fchdir (cdb->fd);
+}
+
+static void
+cdb_free (struct cd_buf const *cdb)
+{
+  if (0 <= cdb->fd)
+    {
+      bool close_fail = close (cdb->fd);
+      assure (! 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_SEARCH | 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 char * _GL_ATTRIBUTE_PURE
+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.  */
+    assure (0 < len);
+    assure (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;
+      }
+
+    assure (*dir != '/');
+    assure (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';
+        assure (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 "closeout.h"
+# include "error.h"
+
+int
+main (int argc, char *argv[])
+{
+  char *line = NULL;
+  size_t n = 0;
+  int len;
+
+  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/libgnu/chdir-long.h b/libgnu/chdir-long.h
new file mode 100644
index 0000000..6f5d331
--- /dev/null
+++ b/libgnu/chdir-long.h
@@ -0,0 +1,30 @@
+/* provide a chdir function that tries not to fail due to ENAMETOOLONG
+   Copyright (C) 2004-2005, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Jim Meyering.  */
+
+#include <unistd.h>
+#include <limits.h>
+
+#include "pathmax.h"
+
+/* 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/libgnu/cloexec.c b/libgnu/cloexec.c
new file mode 100644
index 0000000..a5ad0b5
--- /dev/null
+++ b/libgnu/cloexec.c
@@ -0,0 +1,83 @@
+/* closexec.c - set or clear the close-on-exec descriptor flag
+
+   Copyright (C) 1991, 2004-2006, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+   The code is taken from glibc/manual/llio.texi  */
+
+#include <config.h>
+
+#include "cloexec.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true,
+   or clear the flag if VALUE is false.
+   Return 0 on success, or -1 on error with 'errno' set.
+
+   Note that on MingW, this function does NOT protect DESC from being
+   inherited into spawned children.  Instead, either use dup_cloexec
+   followed by closing the original DESC, or use interfaces such as
+   open or pipe2 that accept flags like O_CLOEXEC to create DESC
+   non-inheritable in the first place.  */
+
+int
+set_cloexec_flag (int desc, bool value)
+{
+#ifdef F_SETFD
+
+  int flags = fcntl (desc, F_GETFD, 0);
+
+  if (0 <= flags)
+    {
+      int newflags = (value ? flags | FD_CLOEXEC : flags & ~FD_CLOEXEC);
+
+      if (flags == newflags
+          || fcntl (desc, F_SETFD, newflags) != -1)
+        return 0;
+    }
+
+  return -1;
+
+#else /* !F_SETFD */
+
+  /* Use dup2 to reject invalid file descriptors; the cloexec flag
+     will be unaffected.  */
+  if (desc < 0)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  if (dup2 (desc, desc) < 0)
+    /* errno is EBADF here.  */
+    return -1;
+
+  /* There is nothing we can do on this kind of platform.  Punt.  */
+  return 0;
+#endif /* !F_SETFD */
+}
+
+
+/* Duplicates a file handle FD, while marking the copy to be closed
+   prior to exec or spawn.  Returns -1 and sets errno if FD could not
+   be duplicated.  */
+
+int
+dup_cloexec (int fd)
+{
+  return fcntl (fd, F_DUPFD_CLOEXEC, 0);
+}
diff --git a/libgnu/cloexec.h b/libgnu/cloexec.h
new file mode 100644
index 0000000..2990e82
--- /dev/null
+++ b/libgnu/cloexec.h
@@ -0,0 +1,38 @@
+/* closexec.c - set or clear the close-on-exec descriptor flag
+
+   Copyright (C) 2004, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <stdbool.h>
+
+/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true,
+   or clear the flag if VALUE is false.
+   Return 0 on success, or -1 on error with 'errno' set.
+
+   Note that on MingW, this function does NOT protect DESC from being
+   inherited into spawned children.  Instead, either use dup_cloexec
+   followed by closing the original DESC, or use interfaces such as
+   open or pipe2 that accept flags like O_CLOEXEC to create DESC
+   non-inheritable in the first place.  */
+
+int set_cloexec_flag (int desc, bool value);
+
+/* Duplicates a file handle FD, while marking the copy to be closed
+   prior to exec or spawn.  Returns -1 and sets errno if FD could not
+   be duplicated.  */
+
+int dup_cloexec (int fd);
diff --git a/libgnu/close.c b/libgnu/close.c
new file mode 100644
index 0000000..3e45187
--- /dev/null
+++ b/libgnu/close.c
@@ -0,0 +1,69 @@
+/* close replacement.
+   Copyright (C) 2008-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include <errno.h>
+
+#include "fd-hook.h"
+#include "msvc-inval.h"
+
+#undef close
+
+#if HAVE_MSVC_INVALID_PARAMETER_HANDLER
+static int
+close_nothrow (int fd)
+{
+  int result;
+
+  TRY_MSVC_INVAL
+    {
+      result = close (fd);
+    }
+  CATCH_MSVC_INVAL
+    {
+      result = -1;
+      errno = EBADF;
+    }
+  DONE_MSVC_INVAL;
+
+  return result;
+}
+#else
+# define close_nothrow close
+#endif
+
+/* Override close() to call into other gnulib modules.  */
+
+int
+rpl_close (int fd)
+{
+#if WINDOWS_SOCKETS
+  int retval = execute_all_close_hooks (close_nothrow, fd);
+#else
+  int retval = close_nothrow (fd);
+#endif
+
+#if REPLACE_FCHDIR
+  if (retval >= 0)
+    _gl_unregister_fd (fd);
+#endif
+
+  return retval;
+}
diff --git a/libgnu/closedir.c b/libgnu/closedir.c
new file mode 100644
index 0000000..71fa0b0
--- /dev/null
+++ b/libgnu/closedir.c
@@ -0,0 +1,71 @@
+/* Stop reading the entries of a directory.
+   Copyright (C) 2006-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <dirent.h>
+
+#if REPLACE_FCHDIR
+# include <unistd.h>
+#endif
+
+#if HAVE_CLOSEDIR
+
+/* Override closedir(), to keep track of the open file descriptors.
+   Needed because there is a function dirfd().  */
+
+#else
+
+# include <stdlib.h>
+
+# include "dirent-private.h"
+
+#endif
+
+int
+closedir (DIR *dirp)
+{
+# if REPLACE_FCHDIR || REPLACE_DIRFD
+  int fd = dirfd (dirp);
+# endif
+  int retval;
+
+#if HAVE_CLOSEDIR
+# undef closedir
+
+  retval = closedir (dirp);
+
+# ifdef __KLIBC__
+  if (!retval)
+    _gl_unregister_dirp_fd (fd);
+# endif
+#else
+
+  if (dirp->current != INVALID_HANDLE_VALUE)
+    FindClose (dirp->current);
+  free (dirp);
+
+  retval = 0;
+
+#endif
+
+#if REPLACE_FCHDIR
+  if (retval >= 0)
+    _gl_unregister_fd (fd);
+#endif
+  return retval;
+}
diff --git a/libgnu/config.charset b/libgnu/config.charset
new file mode 100644
index 0000000..8bedbf3
--- /dev/null
+++ b/libgnu/config.charset
@@ -0,0 +1,682 @@
+#! /bin/sh
+# Output a system dependent table of character encoding aliases.
+#
+#   Copyright (C) 2000-2004, 2006-2017 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 version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# The table consists of lines of the form
+#    ALIAS  CANONICAL
+#
+# ALIAS is the (system dependent) result of "nl_langinfo (CODESET)".
+# ALIAS is compared in a case sensitive way.
+#
+# CANONICAL is the GNU canonical name for this character encoding.
+# It must be an encoding supported by libiconv. Support by GNU libc is
+# also desirable. CANONICAL is case insensitive. Usually an upper case
+# MIME charset name is preferred.
+# The current list of GNU canonical charset names is as follows.
+#
+#       name              MIME?             used by which systems
+#                                    (darwin = Mac OS X, woe32 = native Windows)
+#
+#   ASCII, ANSI_X3.4-1968       glibc solaris freebsd netbsd darwin cygwin
+#   ISO-8859-1              Y   glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
+#   ISO-8859-2              Y   glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
+#   ISO-8859-3              Y   glibc solaris cygwin
+#   ISO-8859-4              Y   osf solaris freebsd netbsd openbsd darwin
+#   ISO-8859-5              Y   glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
+#   ISO-8859-6              Y   glibc aix hpux solaris cygwin
+#   ISO-8859-7              Y   glibc aix hpux irix osf solaris netbsd openbsd darwin cygwin
+#   ISO-8859-8              Y   glibc aix hpux osf solaris cygwin
+#   ISO-8859-9              Y   glibc aix hpux irix osf solaris darwin cygwin
+#   ISO-8859-13                 glibc netbsd openbsd darwin cygwin
+#   ISO-8859-14                 glibc cygwin
+#   ISO-8859-15                 glibc aix osf solaris freebsd netbsd openbsd darwin cygwin
+#   KOI8-R                  Y   glibc solaris freebsd netbsd openbsd darwin
+#   KOI8-U                  Y   glibc freebsd netbsd openbsd darwin cygwin
+#   KOI8-T                      glibc
+#   CP437                       dos
+#   CP775                       dos
+#   CP850                       aix osf dos
+#   CP852                       dos
+#   CP855                       dos
+#   CP856                       aix
+#   CP857                       dos
+#   CP861                       dos
+#   CP862                       dos
+#   CP864                       dos
+#   CP865                       dos
+#   CP866                       freebsd netbsd openbsd darwin dos
+#   CP869                       dos
+#   CP874                       woe32 dos
+#   CP922                       aix
+#   CP932                       aix cygwin woe32 dos
+#   CP943                       aix
+#   CP949                       osf darwin woe32 dos
+#   CP950                       woe32 dos
+#   CP1046                      aix
+#   CP1124                      aix
+#   CP1125                      dos
+#   CP1129                      aix
+#   CP1131                      darwin
+#   CP1250                      woe32
+#   CP1251                      glibc solaris netbsd openbsd darwin cygwin woe32
+#   CP1252                      aix woe32
+#   CP1253                      woe32
+#   CP1254                      woe32
+#   CP1255                      glibc woe32
+#   CP1256                      woe32
+#   CP1257                      woe32
+#   GB2312                  Y   glibc aix hpux irix solaris freebsd netbsd darwin
+#   EUC-JP                  Y   glibc aix hpux irix osf solaris freebsd netbsd darwin
+#   EUC-KR                  Y   glibc aix hpux irix osf solaris freebsd netbsd darwin cygwin
+#   EUC-TW                      glibc aix hpux irix osf solaris netbsd
+#   BIG5                    Y   glibc aix hpux osf solaris freebsd netbsd darwin cygwin
+#   BIG5-HKSCS                  glibc solaris darwin
+#   GBK                         glibc aix osf solaris darwin cygwin woe32 dos
+#   GB18030                     glibc solaris netbsd darwin
+#   SHIFT_JIS               Y   hpux osf solaris freebsd netbsd darwin
+#   JOHAB                       glibc solaris woe32
+#   TIS-620                     glibc aix hpux osf solaris cygwin
+#   VISCII                  Y   glibc
+#   TCVN5712-1                  glibc
+#   ARMSCII-8                   glibc darwin
+#   GEORGIAN-PS                 glibc cygwin
+#   PT154                       glibc
+#   HP-ROMAN8                   hpux
+#   HP-ARABIC8                  hpux
+#   HP-GREEK8                   hpux
+#   HP-HEBREW8                  hpux
+#   HP-TURKISH8                 hpux
+#   HP-KANA8                    hpux
+#   DEC-KANJI                   osf
+#   DEC-HANYU                   osf
+#   UTF-8                   Y   glibc aix hpux osf solaris netbsd darwin cygwin
+#
+# Note: Names which are not marked as being a MIME name should not be used in
+# Internet protocols for information interchange (mail, news, etc.).
+#
+# Note: ASCII and ANSI_X3.4-1968 are synonymous canonical names. Applications
+# must understand both names and treat them as equivalent.
+#
+# The first argument passed to this file is the canonical host specification,
+#    CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or
+#    CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+
+host="$1"
+os=`echo "$host" | sed -e 's/^[^-]*-[^-]*-\(.*\)$/\1/'`
+echo "# This file contains a table of character encoding aliases,"
+echo "# suitable for operating system '${os}'."
+echo "# It was automatically generated from config.charset."
+# List of references, updated during installation:
+echo "# Packages using this file: "
+case "$os" in
+  linux-gnulibc1*)
+    # Linux libc5 doesn't have nl_langinfo(CODESET); therefore
+    # localcharset.c falls back to using the full locale name
+    # from the environment variables.
+    echo "C ASCII"
+    echo "POSIX ASCII"
+    for l in af af_ZA ca ca_ES da da_DK de de_AT de_BE de_CH de_DE de_LU \
+             en en_AU en_BW en_CA en_DK en_GB en_IE en_NZ en_US en_ZA \
+             en_ZW es es_AR es_BO es_CL es_CO es_DO es_EC es_ES es_GT \
+             es_HN es_MX es_PA es_PE es_PY es_SV es_US es_UY es_VE et \
+             et_EE eu eu_ES fi fi_FI fo fo_FO fr fr_BE fr_CA fr_CH fr_FR \
+             fr_LU ga ga_IE gl gl_ES id id_ID in in_ID is is_IS it it_CH \
+             it_IT kl kl_GL nl nl_BE nl_NL no no_NO pt pt_BR pt_PT sv \
+             sv_FI sv_SE; do
+      echo "$l ISO-8859-1"
+      echo "$l.iso-8859-1 ISO-8859-1"
+      echo "$l.iso-8859-15 ISO-8859-15"
+      echo "$l.iso-8859-15@euro ISO-8859-15"
+      echo "$l@euro ISO-8859-15"
+      echo "$l.cp-437 CP437"
+      echo "$l.cp-850 CP850"
+      echo "$l.cp-1252 CP1252"
+      echo "$l.cp-1252@euro CP1252"
+      #echo "$l.atari-st ATARI-ST" # not a commonly used encoding
+      echo "$l.utf-8 UTF-8"
+      echo "$l.utf-8@euro UTF-8"
+    done
+    for l in cs cs_CZ hr hr_HR hu hu_HU pl pl_PL ro ro_RO sk sk_SK sl \
+             sl_SI sr sr_CS sr_YU; do
+      echo "$l ISO-8859-2"
+      echo "$l.iso-8859-2 ISO-8859-2"
+      echo "$l.cp-852 CP852"
+      echo "$l.cp-1250 CP1250"
+      echo "$l.utf-8 UTF-8"
+    done
+    for l in mk mk_MK ru ru_RU; do
+      echo "$l ISO-8859-5"
+      echo "$l.iso-8859-5 ISO-8859-5"
+      echo "$l.koi8-r KOI8-R"
+      echo "$l.cp-866 CP866"
+      echo "$l.cp-1251 CP1251"
+      echo "$l.utf-8 UTF-8"
+    done
+    for l in ar ar_SA; do
+      echo "$l ISO-8859-6"
+      echo "$l.iso-8859-6 ISO-8859-6"
+      echo "$l.cp-864 CP864"
+      #echo "$l.cp-868 CP868" # not a commonly used encoding
+      echo "$l.cp-1256 CP1256"
+      echo "$l.utf-8 UTF-8"
+    done
+    for l in el el_GR gr gr_GR; do
+      echo "$l ISO-8859-7"
+      echo "$l.iso-8859-7 ISO-8859-7"
+      echo "$l.cp-869 CP869"
+      echo "$l.cp-1253 CP1253"
+      echo "$l.cp-1253@euro CP1253"
+      echo "$l.utf-8 UTF-8"
+      echo "$l.utf-8@euro UTF-8"
+    done
+    for l in he he_IL iw iw_IL; do
+      echo "$l ISO-8859-8"
+      echo "$l.iso-8859-8 ISO-8859-8"
+      echo "$l.cp-862 CP862"
+      echo "$l.cp-1255 CP1255"
+      echo "$l.utf-8 UTF-8"
+    done
+    for l in tr tr_TR; do
+      echo "$l ISO-8859-9"
+      echo "$l.iso-8859-9 ISO-8859-9"
+      echo "$l.cp-857 CP857"
+      echo "$l.cp-1254 CP1254"
+      echo "$l.utf-8 UTF-8"
+    done
+    for l in lt lt_LT lv lv_LV; do
+      #echo "$l BALTIC" # not a commonly used encoding, wrong encoding name
+      echo "$l ISO-8859-13"
+    done
+    for l in ru_UA uk uk_UA; do
+      echo "$l KOI8-U"
+    done
+    for l in zh zh_CN; do
+      #echo "$l GB_2312-80" # not a commonly used encoding, wrong encoding name
+      echo "$l GB2312"
+    done
+    for l in ja ja_JP ja_JP.EUC; do
+      echo "$l EUC-JP"
+    done
+    for l in ko ko_KR; do
+      echo "$l EUC-KR"
+    done
+    for l in th th_TH; do
+      echo "$l TIS-620"
+    done
+    for l in fa fa_IR; do
+      #echo "$l ISIRI-3342" # a broken encoding
+      echo "$l.utf-8 UTF-8"
+    done
+    ;;
+  linux* | *-gnu*)
+    # With glibc-2.1 or newer, we don't need any canonicalization,
+    # because glibc has iconv and both glibc and libiconv support all
+    # GNU canonical names directly. Therefore, the Makefile does not
+    # need to install the alias file at all.
+    # The following applies only to glibc-2.0.x and older libcs.
+    echo "ISO_646.IRV:1983 ASCII"
+    ;;
+  aix*)
+    echo "ISO8859-1 ISO-8859-1"
+    echo "ISO8859-2 ISO-8859-2"
+    echo "ISO8859-5 ISO-8859-5"
+    echo "ISO8859-6 ISO-8859-6"
+    echo "ISO8859-7 ISO-8859-7"
+    echo "ISO8859-8 ISO-8859-8"
+    echo "ISO8859-9 ISO-8859-9"
+    echo "ISO8859-15 ISO-8859-15"
+    echo "IBM-850 CP850"
+    echo "IBM-856 CP856"
+    echo "IBM-921 ISO-8859-13"
+    echo "IBM-922 CP922"
+    echo "IBM-932 CP932"
+    echo "IBM-943 CP943"
+    echo "IBM-1046 CP1046"
+    echo "IBM-1124 CP1124"
+    echo "IBM-1129 CP1129"
+    echo "IBM-1252 CP1252"
+    echo "IBM-eucCN GB2312"
+    echo "IBM-eucJP EUC-JP"
+    echo "IBM-eucKR EUC-KR"
+    echo "IBM-eucTW EUC-TW"
+    echo "big5 BIG5"
+    echo "GBK GBK"
+    echo "TIS-620 TIS-620"
+    echo "UTF-8 UTF-8"
+    ;;
+  hpux*)
+    echo "iso88591 ISO-8859-1"
+    echo "iso88592 ISO-8859-2"
+    echo "iso88595 ISO-8859-5"
+    echo "iso88596 ISO-8859-6"
+    echo "iso88597 ISO-8859-7"
+    echo "iso88598 ISO-8859-8"
+    echo "iso88599 ISO-8859-9"
+    echo "iso885915 ISO-8859-15"
+    echo "roman8 HP-ROMAN8"
+    echo "arabic8 HP-ARABIC8"
+    echo "greek8 HP-GREEK8"
+    echo "hebrew8 HP-HEBREW8"
+    echo "turkish8 HP-TURKISH8"
+    echo "kana8 HP-KANA8"
+    echo "tis620 TIS-620"
+    echo "big5 BIG5"
+    echo "eucJP EUC-JP"
+    echo "eucKR EUC-KR"
+    echo "eucTW EUC-TW"
+    echo "hp15CN GB2312"
+    #echo "ccdc ?" # what is this?
+    echo "SJIS SHIFT_JIS"
+    echo "utf8 UTF-8"
+    ;;
+  irix*)
+    echo "ISO8859-1 ISO-8859-1"
+    echo "ISO8859-2 ISO-8859-2"
+    echo "ISO8859-5 ISO-8859-5"
+    echo "ISO8859-7 ISO-8859-7"
+    echo "ISO8859-9 ISO-8859-9"
+    echo "eucCN GB2312"
+    echo "eucJP EUC-JP"
+    echo "eucKR EUC-KR"
+    echo "eucTW EUC-TW"
+    ;;
+  osf*)
+    echo "ISO8859-1 ISO-8859-1"
+    echo "ISO8859-2 ISO-8859-2"
+    echo "ISO8859-4 ISO-8859-4"
+    echo "ISO8859-5 ISO-8859-5"
+    echo "ISO8859-7 ISO-8859-7"
+    echo "ISO8859-8 ISO-8859-8"
+    echo "ISO8859-9 ISO-8859-9"
+    echo "ISO8859-15 ISO-8859-15"
+    echo "cp850 CP850"
+    echo "big5 BIG5"
+    echo "dechanyu DEC-HANYU"
+    echo "dechanzi GB2312"
+    echo "deckanji DEC-KANJI"
+    echo "deckorean EUC-KR"
+    echo "eucJP EUC-JP"
+    echo "eucKR EUC-KR"
+    echo "eucTW EUC-TW"
+    echo "GBK GBK"
+    echo "KSC5601 CP949"
+    echo "sdeckanji EUC-JP"
+    echo "SJIS SHIFT_JIS"
+    echo "TACTIS TIS-620"
+    echo "UTF-8 UTF-8"
+    ;;
+  solaris*)
+    echo "646 ASCII"
+    echo "ISO8859-1 ISO-8859-1"
+    echo "ISO8859-2 ISO-8859-2"
+    echo "ISO8859-3 ISO-8859-3"
+    echo "ISO8859-4 ISO-8859-4"
+    echo "ISO8859-5 ISO-8859-5"
+    echo "ISO8859-6 ISO-8859-6"
+    echo "ISO8859-7 ISO-8859-7"
+    echo "ISO8859-8 ISO-8859-8"
+    echo "ISO8859-9 ISO-8859-9"
+    echo "ISO8859-15 ISO-8859-15"
+    echo "koi8-r KOI8-R"
+    echo "ansi-1251 CP1251"
+    echo "BIG5 BIG5"
+    echo "Big5-HKSCS BIG5-HKSCS"
+    echo "gb2312 GB2312"
+    echo "GBK GBK"
+    echo "GB18030 GB18030"
+    echo "cns11643 EUC-TW"
+    echo "5601 EUC-KR"
+    echo "ko_KR.johap92 JOHAB"
+    echo "eucJP EUC-JP"
+    echo "PCK SHIFT_JIS"
+    echo "TIS620.2533 TIS-620"
+    #echo "sun_eu_greek ?" # what is this?
+    echo "UTF-8 UTF-8"
+    ;;
+  freebsd*)
+    # FreeBSD 4.2 doesn't have nl_langinfo(CODESET); therefore
+    # localcharset.c falls back to using the full locale name
+    # from the environment variables.
+    echo "C ASCII"
+    echo "US-ASCII ASCII"
+    for l in la_LN lt_LN; do
+      echo "$l.ASCII ASCII"
+    done
+    for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \
+             fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT la_LN \
+             lt_LN nl_BE nl_NL no_NO pt_PT sv_SE; do
+      echo "$l.ISO_8859-1 ISO-8859-1"
+      echo "$l.DIS_8859-15 ISO-8859-15"
+    done
+    for l in cs_CZ hr_HR hu_HU la_LN lt_LN pl_PL sl_SI; do
+      echo "$l.ISO_8859-2 ISO-8859-2"
+    done
+    for l in la_LN lt_LT; do
+      echo "$l.ISO_8859-4 ISO-8859-4"
+    done
+    for l in ru_RU ru_SU; do
+      echo "$l.KOI8-R KOI8-R"
+      echo "$l.ISO_8859-5 ISO-8859-5"
+      echo "$l.CP866 CP866"
+    done
+    echo "uk_UA.KOI8-U KOI8-U"
+    echo "zh_TW.BIG5 BIG5"
+    echo "zh_TW.Big5 BIG5"
+    echo "zh_CN.EUC GB2312"
+    echo "ja_JP.EUC EUC-JP"
+    echo "ja_JP.SJIS SHIFT_JIS"
+    echo "ja_JP.Shift_JIS SHIFT_JIS"
+    echo "ko_KR.EUC EUC-KR"
+    ;;
+  netbsd*)
+    echo "646 ASCII"
+    echo "ISO8859-1 ISO-8859-1"
+    echo "ISO8859-2 ISO-8859-2"
+    echo "ISO8859-4 ISO-8859-4"
+    echo "ISO8859-5 ISO-8859-5"
+    echo "ISO8859-7 ISO-8859-7"
+    echo "ISO8859-13 ISO-8859-13"
+    echo "ISO8859-15 ISO-8859-15"
+    echo "eucCN GB2312"
+    echo "eucJP EUC-JP"
+    echo "eucKR EUC-KR"
+    echo "eucTW EUC-TW"
+    echo "BIG5 BIG5"
+    echo "SJIS SHIFT_JIS"
+    ;;
+  openbsd*)
+    echo "646 ASCII"
+    echo "ISO8859-1 ISO-8859-1"
+    echo "ISO8859-2 ISO-8859-2"
+    echo "ISO8859-4 ISO-8859-4"
+    echo "ISO8859-5 ISO-8859-5"
+    echo "ISO8859-7 ISO-8859-7"
+    echo "ISO8859-13 ISO-8859-13"
+    echo "ISO8859-15 ISO-8859-15"
+    ;;
+  darwin[56]*)
+    # Darwin 6.8 doesn't have nl_langinfo(CODESET); therefore
+    # localcharset.c falls back to using the full locale name
+    # from the environment variables.
+    echo "C ASCII"
+    for l in en_AU en_CA en_GB en_US la_LN; do
+      echo "$l.US-ASCII ASCII"
+    done
+    for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \
+             fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT nl_BE \
+             nl_NL no_NO pt_PT sv_SE; do
+      echo "$l ISO-8859-1"
+      echo "$l.ISO8859-1 ISO-8859-1"
+      echo "$l.ISO8859-15 ISO-8859-15"
+    done
+    for l in la_LN; do
+      echo "$l.ISO8859-1 ISO-8859-1"
+      echo "$l.ISO8859-15 ISO-8859-15"
+    done
+    for l in cs_CZ hr_HR hu_HU la_LN pl_PL sl_SI; do
+      echo "$l.ISO8859-2 ISO-8859-2"
+    done
+    for l in la_LN lt_LT; do
+      echo "$l.ISO8859-4 ISO-8859-4"
+    done
+    for l in ru_RU; do
+      echo "$l.KOI8-R KOI8-R"
+      echo "$l.ISO8859-5 ISO-8859-5"
+      echo "$l.CP866 CP866"
+    done
+    for l in bg_BG; do
+      echo "$l.CP1251 CP1251"
+    done
+    echo "uk_UA.KOI8-U KOI8-U"
+    echo "zh_TW.BIG5 BIG5"
+    echo "zh_TW.Big5 BIG5"
+    echo "zh_CN.EUC GB2312"
+    echo "ja_JP.EUC EUC-JP"
+    echo "ja_JP.SJIS SHIFT_JIS"
+    echo "ko_KR.EUC EUC-KR"
+    ;;
+  darwin*)
+    # Darwin 7.5 has nl_langinfo(CODESET), but sometimes its value is
+    # useless:
+    # - It returns the empty string when LANG is set to a locale of the
+    #   form ll_CC, although ll_CC/LC_CTYPE is a symlink to an UTF-8
+    #   LC_CTYPE file.
+    # - The environment variables LANG, LC_CTYPE, LC_ALL are not set by
+    #   the system; nl_langinfo(CODESET) returns "US-ASCII" in this case.
+    # - The documentation says:
+    #     "... all code that calls BSD system routines should ensure
+    #      that the const *char parameters of these routines are in UTF-8
+    #      encoding. All BSD system functions expect their string
+    #      parameters to be in UTF-8 encoding and nothing else."
+    #   It also says
+    #     "An additional caveat is that string parameters for files,
+    #      paths, and other file-system entities must be in canonical
+    #      UTF-8. In a canonical UTF-8 Unicode string, all decomposable
+    #      characters are decomposed ..."
+    #   but this is not true: You can pass non-decomposed UTF-8 strings
+    #   to file system functions, and it is the OS which will convert
+    #   them to decomposed UTF-8 before accessing the file system.
+    # - The Apple Terminal application displays UTF-8 by default.
+    # - However, other applications are free to use different encodings:
+    #   - xterm uses ISO-8859-1 by default.
+    #   - TextEdit uses MacRoman by default.
+    # We prefer UTF-8 over decomposed UTF-8-MAC because one should
+    # minimize the use of decomposed Unicode. Unfortunately, through the
+    # Darwin file system, decomposed UTF-8 strings are leaked into user
+    # space nevertheless.
+    # Then there are also the locales with encodings other than US-ASCII
+    # and UTF-8. These locales can be occasionally useful to users (e.g.
+    # when grepping through ISO-8859-1 encoded text files), when all their
+    # file names are in US-ASCII.
+    echo "ISO8859-1 ISO-8859-1"
+    echo "ISO8859-2 ISO-8859-2"
+    echo "ISO8859-4 ISO-8859-4"
+    echo "ISO8859-5 ISO-8859-5"
+    echo "ISO8859-7 ISO-8859-7"
+    echo "ISO8859-9 ISO-8859-9"
+    echo "ISO8859-13 ISO-8859-13"
+    echo "ISO8859-15 ISO-8859-15"
+    echo "KOI8-R KOI8-R"
+    echo "KOI8-U KOI8-U"
+    echo "CP866 CP866"
+    echo "CP949 CP949"
+    echo "CP1131 CP1131"
+    echo "CP1251 CP1251"
+    echo "eucCN GB2312"
+    echo "GB2312 GB2312"
+    echo "eucJP EUC-JP"
+    echo "eucKR EUC-KR"
+    echo "Big5 BIG5"
+    echo "Big5HKSCS BIG5-HKSCS"
+    echo "GBK GBK"
+    echo "GB18030 GB18030"
+    echo "SJIS SHIFT_JIS"
+    echo "ARMSCII-8 ARMSCII-8"
+    echo "PT154 PT154"
+    #echo "ISCII-DEV ?"
+    echo "* UTF-8"
+    ;;
+  beos* | haiku*)
+    # BeOS and Haiku have a single locale, and it has UTF-8 encoding.
+    echo "* UTF-8"
+    ;;
+  msdosdjgpp*)
+    # DJGPP 2.03 doesn't have nl_langinfo(CODESET); therefore
+    # localcharset.c falls back to using the full locale name
+    # from the environment variables.
+    echo "#"
+    echo "# The encodings given here may not all be correct."
+    echo "# If you find that the encoding given for your language and"
+    echo "# country is not the one your DOS machine actually uses, just"
+    echo "# correct it in this file, and send a mail to"
+    echo "# Juan Manuel Guerrero <juan.guerrero@gmx.de>"
+    echo "# and Bruno Haible <bruno@clisp.org>."
+    echo "#"
+    echo "C ASCII"
+    # ISO-8859-1 languages
+    echo "ca CP850"
+    echo "ca_ES CP850"
+    echo "da CP865"    # not CP850 ??
+    echo "da_DK CP865" # not CP850 ??
+    echo "de CP850"
+    echo "de_AT CP850"
+    echo "de_CH CP850"
+    echo "de_DE CP850"
+    echo "en CP850"
+    echo "en_AU CP850" # not CP437 ??
+    echo "en_CA CP850"
+    echo "en_GB CP850"
+    echo "en_NZ CP437"
+    echo "en_US CP437"
+    echo "en_ZA CP850" # not CP437 ??
+    echo "es CP850"
+    echo "es_AR CP850"
+    echo "es_BO CP850"
+    echo "es_CL CP850"
+    echo "es_CO CP850"
+    echo "es_CR CP850"
+    echo "es_CU CP850"
+    echo "es_DO CP850"
+    echo "es_EC CP850"
+    echo "es_ES CP850"
+    echo "es_GT CP850"
+    echo "es_HN CP850"
+    echo "es_MX CP850"
+    echo "es_NI CP850"
+    echo "es_PA CP850"
+    echo "es_PY CP850"
+    echo "es_PE CP850"
+    echo "es_SV CP850"
+    echo "es_UY CP850"
+    echo "es_VE CP850"
+    echo "et CP850"
+    echo "et_EE CP850"
+    echo "eu CP850"
+    echo "eu_ES CP850"
+    echo "fi CP850"
+    echo "fi_FI CP850"
+    echo "fr CP850"
+    echo "fr_BE CP850"
+    echo "fr_CA CP850"
+    echo "fr_CH CP850"
+    echo "fr_FR CP850"
+    echo "ga CP850"
+    echo "ga_IE CP850"
+    echo "gd CP850"
+    echo "gd_GB CP850"
+    echo "gl CP850"
+    echo "gl_ES CP850"
+    echo "id CP850"    # not CP437 ??
+    echo "id_ID CP850" # not CP437 ??
+    echo "is CP861"    # not CP850 ??
+    echo "is_IS CP861" # not CP850 ??
+    echo "it CP850"
+    echo "it_CH CP850"
+    echo "it_IT CP850"
+    echo "lt CP775"
+    echo "lt_LT CP775"
+    echo "lv CP775"
+    echo "lv_LV CP775"
+    echo "nb CP865"    # not CP850 ??
+    echo "nb_NO CP865" # not CP850 ??
+    echo "nl CP850"
+    echo "nl_BE CP850"
+    echo "nl_NL CP850"
+    echo "nn CP865"    # not CP850 ??
+    echo "nn_NO CP865" # not CP850 ??
+    echo "no CP865"    # not CP850 ??
+    echo "no_NO CP865" # not CP850 ??
+    echo "pt CP850"
+    echo "pt_BR CP850"
+    echo "pt_PT CP850"
+    echo "sv CP850"
+    echo "sv_SE CP850"
+    # ISO-8859-2 languages
+    echo "cs CP852"
+    echo "cs_CZ CP852"
+    echo "hr CP852"
+    echo "hr_HR CP852"
+    echo "hu CP852"
+    echo "hu_HU CP852"
+    echo "pl CP852"
+    echo "pl_PL CP852"
+    echo "ro CP852"
+    echo "ro_RO CP852"
+    echo "sk CP852"
+    echo "sk_SK CP852"
+    echo "sl CP852"
+    echo "sl_SI CP852"
+    echo "sq CP852"
+    echo "sq_AL CP852"
+    echo "sr CP852"    # CP852 or CP866 or CP855 ??
+    echo "sr_CS CP852" # CP852 or CP866 or CP855 ??
+    echo "sr_YU CP852" # CP852 or CP866 or CP855 ??
+    # ISO-8859-3 languages
+    echo "mt CP850"
+    echo "mt_MT CP850"
+    # ISO-8859-5 languages
+    echo "be CP866"
+    echo "be_BE CP866"
+    echo "bg CP866"    # not CP855 ??
+    echo "bg_BG CP866" # not CP855 ??
+    echo "mk CP866"    # not CP855 ??
+    echo "mk_MK CP866" # not CP855 ??
+    echo "ru CP866"
+    echo "ru_RU CP866"
+    echo "uk CP1125"
+    echo "uk_UA CP1125"
+    # ISO-8859-6 languages
+    echo "ar CP864"
+    echo "ar_AE CP864"
+    echo "ar_DZ CP864"
+    echo "ar_EG CP864"
+    echo "ar_IQ CP864"
+    echo "ar_IR CP864"
+    echo "ar_JO CP864"
+    echo "ar_KW CP864"
+    echo "ar_MA CP864"
+    echo "ar_OM CP864"
+    echo "ar_QA CP864"
+    echo "ar_SA CP864"
+    echo "ar_SY CP864"
+    # ISO-8859-7 languages
+    echo "el CP869"
+    echo "el_GR CP869"
+    # ISO-8859-8 languages
+    echo "he CP862"
+    echo "he_IL CP862"
+    # ISO-8859-9 languages
+    echo "tr CP857"
+    echo "tr_TR CP857"
+    # Japanese
+    echo "ja CP932"
+    echo "ja_JP CP932"
+    # Chinese
+    echo "zh_CN GBK"
+    echo "zh_TW CP950" # not CP938 ??
+    # Korean
+    echo "kr CP949"    # not CP934 ??
+    echo "kr_KR CP949" # not CP934 ??
+    # Thai
+    echo "th CP874"
+    echo "th_TH CP874"
+    # Other
+    echo "eo CP850"
+    echo "eo_EO CP850"
+    ;;
+esac
diff --git a/libgnu/creat-safer.c b/libgnu/creat-safer.c
new file mode 100644
index 0000000..e48cadc
--- /dev/null
+++ b/libgnu/creat-safer.c
@@ -0,0 +1,31 @@
+/* Invoke creat, but avoid some glitches.
+
+   Copyright (C) 2005-2006, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* 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/libgnu/cycle-check.c b/libgnu/cycle-check.c
new file mode 100644
index 0000000..6add64b
--- /dev/null
+++ b/libgnu/cycle-check.c
@@ -0,0 +1,85 @@
+/* help detect directory cycles efficiently
+
+   Copyright (C) 2003-2006, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Jim Meyering */
+
+#include <config.h>
+
+#include "cycle-check.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include "assure.h"
+
+#define CC_MAGIC 9827862
+
+/* Return true if I is a power of 2, or is zero.  */
+
+static bool
+is_zero_or_power_of_two (uintmax_t i)
+{
+  return (i & (i - 1)) == 0;
+}
+
+void
+cycle_check_init (struct cycle_check_state *state)
+{
+  state->chdir_counter = 0;
+  state->magic = CC_MAGIC;
+}
+
+/* In traversing a directory hierarchy, call this function once for each
+   descending chdir call, with SB corresponding to the chdir operand.
+   If SB corresponds to a directory that has already been seen,
+   return true to indicate that there is a directory cycle.
+   Note that this is done "lazily", which means that some of
+   the directories in the cycle may be processed twice before
+   the cycle is detected.  */
+
+bool
+cycle_check (struct cycle_check_state *state, struct stat const *sb)
+{
+  assure (state->magic == CC_MAGIC);
+
+  /* If the current directory ever happens to be the same
+     as the one we last recorded for the cycle detection,
+     then it's obviously part of a cycle.  */
+  if (state->chdir_counter && SAME_INODE (*sb, state->dev_ino))
+    return true;
+
+  /* If the number of "descending" chdir calls is a power of two,
+     record the dev/ino of the current directory.  */
+  if (is_zero_or_power_of_two (++(state->chdir_counter)))
+    {
+      /* On all architectures that we know about, if the counter
+         overflows then there is a directory cycle here somewhere,
+         even if we haven't detected it yet.  Typically this happens
+         only after the counter is incremented 2**64 times, so it's a
+         fairly theoretical point.  */
+      if (state->chdir_counter == 0)
+        return true;
+
+      state->dev_ino.st_dev = sb->st_dev;
+      state->dev_ino.st_ino = sb->st_ino;
+    }
+
+  return false;
+}
diff --git a/libgnu/cycle-check.h b/libgnu/cycle-check.h
new file mode 100644
index 0000000..0c9a68b
--- /dev/null
+++ b/libgnu/cycle-check.h
@@ -0,0 +1,52 @@
+/* help detect directory cycles efficiently
+
+   Copyright (C) 2003-2004, 2006, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Jim Meyering */
+
+#ifndef CYCLE_CHECK_H
+# define CYCLE_CHECK_H 1
+
+# include <stdint.h>
+# include <stdbool.h>
+# include "dev-ino.h"
+# include "same-inode.h"
+
+struct cycle_check_state
+{
+  struct dev_ino dev_ino;
+  uintmax_t chdir_counter;
+  int magic;
+};
+
+void cycle_check_init (struct cycle_check_state *state);
+bool cycle_check (struct cycle_check_state *state, struct stat const *sb);
+
+# define CYCLE_CHECK_REFLECT_CHDIR_UP(State, SB_dir, SB_subdir) \
+  do                                                            \
+    {                                                           \
+      /* You must call cycle_check at least once before using this macro.  */ \
+      if ((State)->chdir_counter == 0)                          \
+        abort ();                                               \
+      if (SAME_INODE ((State)->dev_ino, SB_subdir))             \
+        {                                                       \
+          (State)->dev_ino.st_dev = (SB_dir).st_dev;            \
+          (State)->dev_ino.st_ino = (SB_dir).st_ino;            \
+        }                                                       \
+    }                                                           \
+  while (0)
+
+#endif
diff --git a/libgnu/dev-ino.h b/libgnu/dev-ino.h
new file mode 100644
index 0000000..695d38c
--- /dev/null
+++ b/libgnu/dev-ino.h
@@ -0,0 +1,13 @@
+#ifndef DEV_INO_H
+# define DEV_INO_H 1
+
+# include <sys/types.h>
+# include <sys/stat.h>
+
+struct dev_ino
+{
+  ino_t st_ino;
+  dev_t st_dev;
+};
+
+#endif
diff --git a/libgnu/dirent--.h b/libgnu/dirent--.h
new file mode 100644
index 0000000..5f477e8
--- /dev/null
+++ b/libgnu/dirent--.h
@@ -0,0 +1,24 @@
+/* Like dirent.h, but redefine some names to avoid glitches.
+
+   Copyright (C) 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Eric Blake.  */
+
+#include "dirent-safer.h"
+
+#undef opendir
+#define opendir opendir_safer
+#define GNULIB_defined_opendir 1
diff --git a/libgnu/dirent-private.h b/libgnu/dirent-private.h
new file mode 100644
index 0000000..4a0b1c5
--- /dev/null
+++ b/libgnu/dirent-private.h
@@ -0,0 +1,40 @@
+/* Private details of the DIR type.
+   Copyright (C) 2011-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _DIRENT_PRIVATE_H
+#define _DIRENT_PRIVATE_H 1
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+struct gl_directory
+{
+  /* Status, or error code to produce in next readdir() call.
+     -2 means the end of the directory is already reached,
+     -1 means the entry was already filled by FindFirstFile,
+     0 means the entry needs to be filled using FindNextFile.
+     A positive value is an error code.  */
+  int status;
+  /* Handle, reading the directory, at current position.  */
+  HANDLE current;
+  /* Found directory entry.  */
+  WIN32_FIND_DATA entry;
+  /* Argument to pass to FindFirstFile.  It consists of the absolutized
+     directory name, followed by a directory separator and the wildcards.  */
+  char dir_name_mask[1];
+};
+
+#endif /* _DIRENT_PRIVATE_H */
diff --git a/libgnu/dirent-safer.h b/libgnu/dirent-safer.h
new file mode 100644
index 0000000..a595797
--- /dev/null
+++ b/libgnu/dirent-safer.h
@@ -0,0 +1,22 @@
+/* Invoke dirent-like functions, but avoid some glitches.
+
+   Copyright (C) 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Eric Blake.  */
+
+#include <dirent.h>
+
+DIR *opendir_safer (const char *name);
diff --git a/libgnu/dirent.in.h b/libgnu/dirent.in.h
new file mode 100644
index 0000000..f591787
--- /dev/null
+++ b/libgnu/dirent.in.h
@@ -0,0 +1,267 @@
+/* A GNU-like <dirent.h>.
+   Copyright (C) 2006-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _@GUARD_PREFIX@_DIRENT_H
+
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+@PRAGMA_COLUMNS@
+
+/* The include_next requires a split double-inclusion guard.  */
+#if @HAVE_DIRENT_H@
+# @INCLUDE_NEXT@ @NEXT_DIRENT_H@
+#endif
+
+#ifndef _@GUARD_PREFIX@_DIRENT_H
+#define _@GUARD_PREFIX@_DIRENT_H
+
+/* Get ino_t.  Needed on some systems, including glibc 2.8.  */
+#include <sys/types.h>
+
+#if !@HAVE_DIRENT_H@
+/* Define types DIR and 'struct dirent'.  */
+# if !GNULIB_defined_struct_dirent
+struct dirent
+{
+  char d_type;
+  char d_name[1];
+};
+/* Possible values for 'd_type'.  */
+#  define DT_UNKNOWN 0
+#  define DT_FIFO    1          /* FIFO */
+#  define DT_CHR     2          /* character device */
+#  define DT_DIR     4          /* directory */
+#  define DT_BLK     6          /* block device */
+#  define DT_REG     8          /* regular file */
+#  define DT_LNK    10          /* symbolic link */
+#  define DT_SOCK   12          /* socket */
+#  define DT_WHT    14          /* whiteout */
+typedef struct gl_directory DIR;
+#  define GNULIB_defined_struct_dirent 1
+# endif
+#endif
+
+/* The __attribute__ feature is available in gcc versions 2.5 and later.
+   The attribute __pure__ was added in gcc 2.96.  */
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
+# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
+#else
+# define _GL_ATTRIBUTE_PURE /* empty */
+#endif
+
+/* The definitions of _GL_FUNCDECL_RPL etc. are copied here.  */
+
+/* The definition of _GL_ARG_NONNULL is copied here.  */
+
+/* The definition of _GL_WARN_ON_USE is copied here.  */
+
+
+/* Declare overridden functions.  */
+
+#if @GNULIB_OPENDIR@
+# if @REPLACE_OPENDIR@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef opendir
+#   define opendir rpl_opendir
+#   define GNULIB_defined_opendir 1
+#  endif
+_GL_FUNCDECL_RPL (opendir, DIR *, (const char *dir_name) _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (opendir, DIR *, (const char *dir_name));
+# else
+#  if !@HAVE_OPENDIR@
+_GL_FUNCDECL_SYS (opendir, DIR *, (const char *dir_name) _GL_ARG_NONNULL ((1)));
+#  endif
+_GL_CXXALIAS_SYS (opendir, DIR *, (const char *dir_name));
+# endif
+_GL_CXXALIASWARN (opendir);
+#elif defined GNULIB_POSIXCHECK
+# undef opendir
+# if HAVE_RAW_DECL_OPENDIR
+_GL_WARN_ON_USE (opendir, "opendir is not portable - "
+                 "use gnulib module opendir for portability");
+# endif
+#endif
+
+#if @GNULIB_READDIR@
+# if !@HAVE_READDIR@
+_GL_FUNCDECL_SYS (readdir, struct dirent *, (DIR *dirp) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (readdir, struct dirent *, (DIR *dirp));
+_GL_CXXALIASWARN (readdir);
+#elif defined GNULIB_POSIXCHECK
+# undef readdir
+# if HAVE_RAW_DECL_READDIR
+_GL_WARN_ON_USE (readdir, "readdir is not portable - "
+                 "use gnulib module readdir for portability");
+# endif
+#endif
+
+#if @GNULIB_REWINDDIR@
+# if !@HAVE_REWINDDIR@
+_GL_FUNCDECL_SYS (rewinddir, void, (DIR *dirp) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (rewinddir, void, (DIR *dirp));
+_GL_CXXALIASWARN (rewinddir);
+#elif defined GNULIB_POSIXCHECK
+# undef rewinddir
+# if HAVE_RAW_DECL_REWINDDIR
+_GL_WARN_ON_USE (rewinddir, "rewinddir is not portable - "
+                 "use gnulib module rewinddir for portability");
+# endif
+#endif
+
+#if @GNULIB_CLOSEDIR@
+# if @REPLACE_CLOSEDIR@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef closedir
+#   define closedir rpl_closedir
+#   define GNULIB_defined_closedir 1
+#  endif
+_GL_FUNCDECL_RPL (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (closedir, int, (DIR *dirp));
+# else
+#  if !@HAVE_CLOSEDIR@
+_GL_FUNCDECL_SYS (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1)));
+#  endif
+_GL_CXXALIAS_SYS (closedir, int, (DIR *dirp));
+# endif
+_GL_CXXALIASWARN (closedir);
+#elif defined GNULIB_POSIXCHECK
+# undef closedir
+# if HAVE_RAW_DECL_CLOSEDIR
+_GL_WARN_ON_USE (closedir, "closedir is not portable - "
+                 "use gnulib module closedir for portability");
+# endif
+#endif
+
+#if @GNULIB_DIRFD@
+/* Return the file descriptor associated with the given directory stream,
+   or -1 if none exists.  */
+# if @REPLACE_DIRFD@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef dirfd
+#   define dirfd rpl_dirfd
+#  endif
+_GL_FUNCDECL_RPL (dirfd, int, (DIR *) _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (dirfd, int, (DIR *));
+
+#  ifdef __KLIBC__
+/* Gnulib internal hooks needed to maintain the dirfd metadata.  */
+_GL_EXTERN_C int _gl_register_dirp_fd (int fd, DIR *dirp)
+     _GL_ARG_NONNULL ((2));
+_GL_EXTERN_C void _gl_unregister_dirp_fd (int fd);
+#  endif
+# else
+#  if defined __cplusplus && defined GNULIB_NAMESPACE && defined dirfd
+    /* dirfd is defined as a macro and not as a function.
+       Turn it into a function and get rid of the macro.  */
+static inline int (dirfd) (DIR *dp) { return dirfd (dp); }
+#   undef dirfd
+#  endif
+#  if !(@HAVE_DECL_DIRFD@ || defined dirfd)
+_GL_FUNCDECL_SYS (dirfd, int, (DIR *) _GL_ARG_NONNULL ((1)));
+#  endif
+_GL_CXXALIAS_SYS (dirfd, int, (DIR *));
+# endif
+_GL_CXXALIASWARN (dirfd);
+#elif defined GNULIB_POSIXCHECK
+# undef dirfd
+# if HAVE_RAW_DECL_DIRFD
+_GL_WARN_ON_USE (dirfd, "dirfd is unportable - "
+                 "use gnulib module dirfd for portability");
+# endif
+#endif
+
+#if @GNULIB_FDOPENDIR@
+/* Open a directory stream visiting the given directory file
+   descriptor.  Return NULL and set errno if fd is not visiting a
+   directory.  On success, this function consumes fd (it will be
+   implicitly closed either by this function or by a subsequent
+   closedir).  */
+# if @REPLACE_FDOPENDIR@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef fdopendir
+#   define fdopendir rpl_fdopendir
+#  endif
+_GL_FUNCDECL_RPL (fdopendir, DIR *, (int fd));
+_GL_CXXALIAS_RPL (fdopendir, DIR *, (int fd));
+# else
+#  if !@HAVE_FDOPENDIR@ || !@HAVE_DECL_FDOPENDIR@
+_GL_FUNCDECL_SYS (fdopendir, DIR *, (int fd));
+#  endif
+_GL_CXXALIAS_SYS (fdopendir, DIR *, (int fd));
+# endif
+_GL_CXXALIASWARN (fdopendir);
+#elif defined GNULIB_POSIXCHECK
+# undef fdopendir
+# if HAVE_RAW_DECL_FDOPENDIR
+_GL_WARN_ON_USE (fdopendir, "fdopendir is unportable - "
+                 "use gnulib module fdopendir for portability");
+# endif
+#endif
+
+#if @GNULIB_SCANDIR@
+/* Scan the directory DIR, calling FILTER on each directory entry.
+   Entries for which FILTER returns nonzero are individually malloc'd,
+   sorted using qsort with CMP, and collected in a malloc'd array in
+   *NAMELIST.  Returns the number of entries selected, or -1 on error.  */
+# if !@HAVE_SCANDIR@
+_GL_FUNCDECL_SYS (scandir, int,
+                  (const char *dir, struct dirent ***namelist,
+                   int (*filter) (const struct dirent *),
+                   int (*cmp) (const struct dirent **, const struct dirent **))
+                  _GL_ARG_NONNULL ((1, 2, 4)));
+# endif
+/* Need to cast, because on glibc systems, the fourth parameter is
+                        int (*cmp) (const void *, const void *).  */
+_GL_CXXALIAS_SYS_CAST (scandir, int,
+                       (const char *dir, struct dirent ***namelist,
+                        int (*filter) (const struct dirent *),
+                        int (*cmp) (const struct dirent **, const struct dirent **)));
+_GL_CXXALIASWARN (scandir);
+#elif defined GNULIB_POSIXCHECK
+# undef scandir
+# if HAVE_RAW_DECL_SCANDIR
+_GL_WARN_ON_USE (scandir, "scandir is unportable - "
+                 "use gnulib module scandir for portability");
+# endif
+#endif
+
+#if @GNULIB_ALPHASORT@
+/* Compare two 'struct dirent' entries alphabetically.  */
+# if !@HAVE_ALPHASORT@
+_GL_FUNCDECL_SYS (alphasort, int,
+                  (const struct dirent **, const struct dirent **)
+                  _GL_ATTRIBUTE_PURE
+                  _GL_ARG_NONNULL ((1, 2)));
+# endif
+/* Need to cast, because on glibc systems, the parameters are
+                       (const void *, const void *).  */
+_GL_CXXALIAS_SYS_CAST (alphasort, int,
+                       (const struct dirent **, const struct dirent **));
+_GL_CXXALIASWARN (alphasort);
+#elif defined GNULIB_POSIXCHECK
+# undef alphasort
+# if HAVE_RAW_DECL_ALPHASORT
+_GL_WARN_ON_USE (alphasort, "alphasort is unportable - "
+                 "use gnulib module alphasort for portability");
+# endif
+#endif
+
+
+#endif /* _@GUARD_PREFIX@_DIRENT_H */
+#endif /* _@GUARD_PREFIX@_DIRENT_H */
diff --git a/libgnu/dirfd.c b/libgnu/dirfd.c
new file mode 100644
index 0000000..6b1a7b2
--- /dev/null
+++ b/libgnu/dirfd.c
@@ -0,0 +1,98 @@
+/* dirfd.c -- return the file descriptor associated with an open DIR*
+
+   Copyright (C) 2001, 2006, 2008-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Jim Meyering. */
+
+#include <config.h>
+
+#include <dirent.h>
+#include <errno.h>
+
+#ifdef __KLIBC__
+# include <stdlib.h>
+# include <io.h>
+
+static struct dirp_fd_list
+{
+  DIR *dirp;
+  int fd;
+  struct dirp_fd_list *next;
+} *dirp_fd_start = NULL;
+
+/* Register fd associated with dirp to dirp_fd_list. */
+int
+_gl_register_dirp_fd (int fd, DIR *dirp)
+{
+  struct dirp_fd_list *new_dirp_fd = malloc (sizeof *new_dirp_fd);
+  if (!new_dirp_fd)
+    return -1;
+
+  new_dirp_fd->dirp = dirp;
+  new_dirp_fd->fd = fd;
+  new_dirp_fd->next = dirp_fd_start;
+
+  dirp_fd_start = new_dirp_fd;
+
+  return 0;
+}
+
+/* Unregister fd from dirp_fd_list with closing it */
+void
+_gl_unregister_dirp_fd (int fd)
+{
+  struct dirp_fd_list *dirp_fd;
+  struct dirp_fd_list *dirp_fd_prev;
+
+  for (dirp_fd_prev = NULL, dirp_fd = dirp_fd_start; dirp_fd;
+       dirp_fd_prev = dirp_fd, dirp_fd = dirp_fd->next)
+    {
+      if (dirp_fd->fd == fd)
+        {
+          if (dirp_fd_prev)
+            dirp_fd_prev->next = dirp_fd->next;
+          else  /* dirp_fd == dirp_fd_start */
+            dirp_fd_start = dirp_fd_start->next;
+
+          close (fd);
+          free (dirp_fd);
+          break;
+        }
+    }
+}
+#endif
+
+int
+dirfd (DIR *dir_p)
+{
+  int fd = DIR_TO_FD (dir_p);
+  if (fd == -1)
+#ifndef __KLIBC__
+    errno = ENOTSUP;
+#else
+    {
+      struct dirp_fd_list *dirp_fd;
+
+      for (dirp_fd = dirp_fd_start; dirp_fd; dirp_fd = dirp_fd->next)
+        if (dirp_fd->dirp == dir_p)
+          return dirp_fd->fd;
+
+      errno = EINVAL;
+    }
+#endif
+
+  return fd;
+}
diff --git a/libgnu/dirname-lgpl.c b/libgnu/dirname-lgpl.c
new file mode 100644
index 0000000..b549ca9
--- /dev/null
+++ b/libgnu/dirname-lgpl.c
@@ -0,0 +1,86 @@
+/* dirname.c -- return all but the last element in a file name
+
+   Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2017 Free Software
+   Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include "dirname.h"
+
+#include <stdlib.h>
+#include <string.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 malloc.
+   Works properly even if there are trailing slashes (by effectively
+   ignoring them).  Return NULL on failure.
+
+   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 *
+mdir_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 = malloc (length + append_dot + 1);
+  if (!dir)
+    return NULL;
+  memcpy (dir, file, length);
+  if (append_dot)
+    dir[length++] = '.';
+  dir[length] = '\0';
+  return dir;
+}
diff --git a/libgnu/dirname.c b/libgnu/dirname.c
new file mode 100644
index 0000000..ed57557
--- /dev/null
+++ b/libgnu/dirname.c
@@ -0,0 +1,38 @@
+/* dirname.c -- return all but the last element in a file name
+
+   Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2017 Free Software
+   Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include "dirname.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include "xalloc.h"
+
+/* Just like mdir_name (dirname-lgpl.c), except, rather than
+   returning NULL upon malloc failure, here, we report the
+   "memory exhausted" condition and exit.  */
+
+char *
+dir_name (char const *file)
+{
+  char *result = mdir_name (file);
+  if (!result)
+    xalloc_die ();
+  return result;
+}
diff --git a/libgnu/dirname.h b/libgnu/dirname.h
new file mode 100644
index 0000000..dbf920b
--- /dev/null
+++ b/libgnu/dirname.h
@@ -0,0 +1,54 @@
+/*  Take file names apart into directory and base names.
+
+    Copyright (C) 1998, 2001, 2003-2006, 2009-2017 Free Software Foundation,
+    Inc.
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef DIRNAME_H_
+# define DIRNAME_H_ 1
+
+# include <stdbool.h>
+# include <stddef.h>
+# include "dosname.h"
+
+# ifndef DIRECTORY_SEPARATOR
+#  define DIRECTORY_SEPARATOR '/'
+# endif
+
+# ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
+#  define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
+# endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+# if GNULIB_DIRNAME
+char *base_name (char const *file);
+char *dir_name (char const *file);
+# endif
+
+char *mdir_name (char const *file);
+size_t base_len (char const *file) _GL_ATTRIBUTE_PURE;
+size_t dir_len (char const *file) _GL_ATTRIBUTE_PURE;
+char *last_component (char const *file) _GL_ATTRIBUTE_PURE;
+
+bool strip_trailing_slashes (char *file);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* not DIRNAME_H_ */
diff --git a/libgnu/dosname.h b/libgnu/dosname.h
new file mode 100644
index 0000000..dd5c177
--- /dev/null
+++ b/libgnu/dosname.h
@@ -0,0 +1,53 @@
+/* File names on MS-DOS/Windows systems.
+
+   Copyright (C) 2000-2001, 2004-2006, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+   From Paul Eggert and Jim Meyering.  */
+
+#ifndef _DOSNAME_H
+#define _DOSNAME_H
+
+#if (defined _WIN32 || defined __WIN32__ ||     \
+     defined __MSDOS__ || defined __CYGWIN__ || \
+     defined __EMX__ || defined __DJGPP__)
+   /* 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)
+# ifndef __CYGWIN__
+#  define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 1
+# endif
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+#else
+# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
+# define ISSLASH(C) ((C) == '/')
+#endif
+
+#ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
+# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 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]) || FILE_SYSTEM_PREFIX_LEN (F) != 0)
+#endif
+#define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
+
+#endif /* DOSNAME_H_ */
diff --git a/libgnu/dup-safer.c b/libgnu/dup-safer.c
new file mode 100644
index 0000000..d00997c
--- /dev/null
+++ b/libgnu/dup-safer.c
@@ -0,0 +1,34 @@
+/* Invoke dup, but avoid some glitches.
+
+   Copyright (C) 2001, 2004-2006, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Paul Eggert.  */
+
+#include <config.h>
+
+#include "unistd-safer.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+/* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or
+   STDERR_FILENO.  */
+
+int
+dup_safer (int fd)
+{
+  return fcntl (fd, F_DUPFD, STDERR_FILENO + 1);
+}
diff --git a/libgnu/dup.c b/libgnu/dup.c
new file mode 100644
index 0000000..819e9e3
--- /dev/null
+++ b/libgnu/dup.c
@@ -0,0 +1,86 @@
+/* Duplicate an open file descriptor.
+
+   Copyright (C) 2011-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include <errno.h>
+
+#include "msvc-inval.h"
+
+#undef dup
+
+#if HAVE_MSVC_INVALID_PARAMETER_HANDLER
+static int
+dup_nothrow (int fd)
+{
+  int result;
+
+  TRY_MSVC_INVAL
+    {
+      result = dup (fd);
+    }
+  CATCH_MSVC_INVAL
+    {
+      result = -1;
+      errno = EBADF;
+    }
+  DONE_MSVC_INVAL;
+
+  return result;
+}
+#elif defined __KLIBC__
+# include <fcntl.h>
+# include <sys/stat.h>
+
+# include <InnoTekLIBC/backend.h>
+
+static int
+dup_nothrow (int fd)
+{
+  int dupfd;
+  struct stat sbuf;
+
+  dupfd = dup (fd);
+  if (dupfd == -1 && errno == ENOTSUP \
+      && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
+    {
+      char path[_MAX_PATH];
+
+      /* Get a path from fd */
+      if (!__libc_Back_ioFHToPath (fd, path, sizeof (path)))
+        dupfd = open (path, O_RDONLY);
+    }
+
+  return dupfd;
+}
+#else
+# define dup_nothrow dup
+#endif
+
+int
+rpl_dup (int fd)
+{
+  int result = dup_nothrow (fd);
+#if REPLACE_FCHDIR
+  if (result >= 0)
+    result = _gl_register_dup (fd, result);
+#endif
+  return result;
+}
diff --git a/libgnu/dup2.c b/libgnu/dup2.c
new file mode 100644
index 0000000..c0c7cad
--- /dev/null
+++ b/libgnu/dup2.c
@@ -0,0 +1,215 @@
+/* Duplicate an open file descriptor to a specified file descriptor.
+
+   Copyright (C) 1999, 2004-2007, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* written by Paul Eggert */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include <errno.h>
+#include <fcntl.h>
+
+#if HAVE_DUP2
+
+# undef dup2
+
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+/* Get declarations of the native Windows API functions.  */
+#  define WIN32_LEAN_AND_MEAN
+#  include <windows.h>
+
+#  include "msvc-inval.h"
+
+/* Get _get_osfhandle.  */
+#  include "msvc-nothrow.h"
+
+static int
+ms_windows_dup2 (int fd, int desired_fd)
+{
+  int result;
+
+  /* If fd is closed, mingw hangs on dup2 (fd, fd).  If fd is open,
+     dup2 (fd, fd) returns 0, but all further attempts to use fd in
+     future dup2 calls will hang.  */
+  if (fd == desired_fd)
+    {
+      if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE)
+        {
+          errno = EBADF;
+          return -1;
+        }
+      return fd;
+    }
+
+  /* Wine 1.0.1 return 0 when desired_fd is negative but not -1:
+     http://bugs.winehq.org/show_bug.cgi?id=21289 */
+  if (desired_fd < 0)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  TRY_MSVC_INVAL
+    {
+      result = dup2 (fd, desired_fd);
+    }
+  CATCH_MSVC_INVAL
+    {
+      errno = EBADF;
+      result = -1;
+    }
+  DONE_MSVC_INVAL;
+
+  if (result == 0)
+    result = desired_fd;
+
+  return result;
+}
+
+#  define dup2 ms_windows_dup2
+
+# elif defined __KLIBC__
+
+#  include <InnoTekLIBC/backend.h>
+
+static int
+klibc_dup2dirfd (int fd, int desired_fd)
+{
+  int tempfd;
+  int dupfd;
+
+  tempfd = open ("NUL", O_RDONLY);
+  if (tempfd == -1)
+    return -1;
+
+  if (tempfd == desired_fd)
+    {
+      close (tempfd);
+
+      char path[_MAX_PATH];
+      if (__libc_Back_ioFHToPath (fd, path, sizeof (path)))
+        return -1;
+
+      return open(path, O_RDONLY);
+    }
+
+  dupfd = klibc_dup2dirfd (fd, desired_fd);
+
+  close (tempfd);
+
+  return dupfd;
+}
+
+static int
+klibc_dup2 (int fd, int desired_fd)
+{
+  int dupfd;
+  struct stat sbuf;
+
+  dupfd = dup2 (fd, desired_fd);
+  if (dupfd == -1 && errno == ENOTSUP \
+      && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
+    {
+      close (desired_fd);
+
+      return klibc_dup2dirfd (fd, desired_fd);
+    }
+
+  return dupfd;
+}
+
+#  define dup2 klibc_dup2
+# endif
+
+int
+rpl_dup2 (int fd, int desired_fd)
+{
+  int result;
+
+# ifdef F_GETFL
+  /* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF.
+     On Cygwin 1.5.x, dup2 (1, 1) returns 0.
+     On Cygwin 1.7.17, dup2 (1, -1) dumps core.
+     On Cygwin 1.7.25, dup2 (1, 256) can dump core.
+     On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC.  */
+#  if HAVE_SETDTABLESIZE
+  setdtablesize (desired_fd + 1);
+#  endif
+  if (desired_fd < 0)
+    fd = desired_fd;
+  if (fd == desired_fd)
+    return fcntl (fd, F_GETFL) == -1 ? -1 : fd;
+# endif
+
+  result = dup2 (fd, desired_fd);
+
+  /* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x.  */
+  if (result == -1 && errno == EMFILE)
+    errno = EBADF;
+# if REPLACE_FCHDIR
+  if (fd != desired_fd && result != -1)
+    result = _gl_register_dup (fd, result);
+# endif
+  return result;
+}
+
+#else /* !HAVE_DUP2 */
+
+/* On older platforms, dup2 did not exist.  */
+
+# 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)
+{
+  int result = fcntl (fd, F_GETFL) < 0 ? -1 : fd;
+  if (result == -1 || fd == desired_fd)
+    return result;
+  close (desired_fd);
+# ifdef F_DUPFD
+  result = fcntl (fd, F_DUPFD, desired_fd);
+#  if REPLACE_FCHDIR
+  if (0 <= result)
+    result = _gl_register_dup (fd, result);
+#  endif
+# else
+  result = dupfd (fd, desired_fd);
+# endif
+  if (result == -1 && (errno == EMFILE || errno == EINVAL))
+    errno = EBADF;
+  return result;
+}
+#endif /* !HAVE_DUP2 */
diff --git a/libgnu/errno.in.h b/libgnu/errno.in.h
new file mode 100644
index 0000000..13194f9
--- /dev/null
+++ b/libgnu/errno.in.h
@@ -0,0 +1,279 @@
+/* A POSIX-like <errno.h>.
+
+   Copyright (C) 2008-2017 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 version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _@GUARD_PREFIX@_ERRNO_H
+
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+@PRAGMA_COLUMNS@
+
+/* The include_next requires a split double-inclusion guard.  */
+#@INCLUDE_NEXT@ @NEXT_ERRNO_H@
+
+#ifndef _@GUARD_PREFIX@_ERRNO_H
+#define _@GUARD_PREFIX@_ERRNO_H
+
+
+/* On native Windows platforms, many macros are not defined.  */
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+/* These are the same values as defined by MSVC 10, for interoperability.  */
+
+#  ifndef ENOMSG
+#   define ENOMSG    122
+#   define GNULIB_defined_ENOMSG 1
+#  endif
+
+#  ifndef EIDRM
+#   define EIDRM     111
+#   define GNULIB_defined_EIDRM 1
+#  endif
+
+#  ifndef ENOLINK
+#   define ENOLINK   121
+#   define GNULIB_defined_ENOLINK 1
+#  endif
+
+#  ifndef EPROTO
+#   define EPROTO    134
+#   define GNULIB_defined_EPROTO 1
+#  endif
+
+#  ifndef EBADMSG
+#   define EBADMSG   104
+#   define GNULIB_defined_EBADMSG 1
+#  endif
+
+#  ifndef EOVERFLOW
+#   define EOVERFLOW 132
+#   define GNULIB_defined_EOVERFLOW 1
+#  endif
+
+#  ifndef ENOTSUP
+#   define ENOTSUP   129
+#   define GNULIB_defined_ENOTSUP 1
+#  endif
+
+#  ifndef ENETRESET
+#   define ENETRESET 117
+#   define GNULIB_defined_ENETRESET 1
+#  endif
+
+#  ifndef ECONNABORTED
+#   define ECONNABORTED 106
+#   define GNULIB_defined_ECONNABORTED 1
+#  endif
+
+#  ifndef ECANCELED
+#   define ECANCELED 105
+#   define GNULIB_defined_ECANCELED 1
+#  endif
+
+#  ifndef EOWNERDEAD
+#   define EOWNERDEAD 133
+#   define GNULIB_defined_EOWNERDEAD 1
+#  endif
+
+#  ifndef ENOTRECOVERABLE
+#   define ENOTRECOVERABLE 127
+#   define GNULIB_defined_ENOTRECOVERABLE 1
+#  endif
+
+#  ifndef EINPROGRESS
+#   define EINPROGRESS     112
+#   define EALREADY        103
+#   define ENOTSOCK        128
+#   define EDESTADDRREQ    109
+#   define EMSGSIZE        115
+#   define EPROTOTYPE      136
+#   define ENOPROTOOPT     123
+#   define EPROTONOSUPPORT 135
+#   define EOPNOTSUPP      130
+#   define EAFNOSUPPORT    102
+#   define EADDRINUSE      100
+#   define EADDRNOTAVAIL   101
+#   define ENETDOWN        116
+#   define ENETUNREACH     118
+#   define ECONNRESET      108
+#   define ENOBUFS         119
+#   define EISCONN         113
+#   define ENOTCONN        126
+#   define ETIMEDOUT       138
+#   define ECONNREFUSED    107
+#   define ELOOP           114
+#   define EHOSTUNREACH    110
+#   define EWOULDBLOCK     140
+#   define GNULIB_defined_ESOCK 1
+#  endif
+
+#  ifndef ETXTBSY
+#   define ETXTBSY         139
+#   define ENODATA         120  /* not required by POSIX */
+#   define ENOSR           124  /* not required by POSIX */
+#   define ENOSTR          125  /* not required by POSIX */
+#   define ETIME           137  /* not required by POSIX */
+#   define EOTHER          131  /* not required by POSIX */
+#   define GNULIB_defined_ESTREAMS 1
+#  endif
+
+/* These are intentionally the same values as the WSA* error numbers, defined
+   in <winsock2.h>.  */
+#  define ESOCKTNOSUPPORT 10044  /* not required by POSIX */
+#  define EPFNOSUPPORT    10046  /* not required by POSIX */
+#  define ESHUTDOWN       10058  /* not required by POSIX */
+#  define ETOOMANYREFS    10059  /* not required by POSIX */
+#  define EHOSTDOWN       10064  /* not required by POSIX */
+#  define EPROCLIM        10067  /* not required by POSIX */
+#  define EUSERS          10068  /* not required by POSIX */
+#  define EDQUOT          10069
+#  define ESTALE          10070
+#  define EREMOTE         10071  /* not required by POSIX */
+#  define GNULIB_defined_EWINSOCK 1
+
+# endif
+
+
+/* On OSF/1 5.1, when _XOPEN_SOURCE_EXTENDED is not defined, the macros
+   EMULTIHOP, ENOLINK, EOVERFLOW are not defined.  */
+# if @EMULTIHOP_HIDDEN@
+#  define EMULTIHOP @EMULTIHOP_VALUE@
+#  define GNULIB_defined_EMULTIHOP 1
+# endif
+# if @ENOLINK_HIDDEN@
+#  define ENOLINK   @ENOLINK_VALUE@
+#  define GNULIB_defined_ENOLINK 1
+# endif
+# if @EOVERFLOW_HIDDEN@
+#  define EOVERFLOW @EOVERFLOW_VALUE@
+#  define GNULIB_defined_EOVERFLOW 1
+# endif
+
+
+/* On OpenBSD 4.0 and on native Windows, the macros ENOMSG, EIDRM, ENOLINK,
+   EPROTO, EMULTIHOP, EBADMSG, EOVERFLOW, ENOTSUP, ECANCELED are not defined.
+   Likewise, on NonStop Kernel, EDQUOT is not defined.
+   Define them here.  Values >= 2000 seem safe to use: Solaris ESTALE = 151,
+   HP-UX EWOULDBLOCK = 246, IRIX EDQUOT = 1133.
+
+   Note: When one of these systems defines some of these macros some day,
+   binaries will have to be recompiled so that they recognizes the new
+   errno values from the system.  */
+
+# ifndef ENOMSG
+#  define ENOMSG    2000
+#  define GNULIB_defined_ENOMSG 1
+# endif
+
+# ifndef EIDRM
+#  define EIDRM     2001
+#  define GNULIB_defined_EIDRM 1
+# endif
+
+# ifndef ENOLINK
+#  define ENOLINK   2002
+#  define GNULIB_defined_ENOLINK 1
+# endif
+
+# ifndef EPROTO
+#  define EPROTO    2003
+#  define GNULIB_defined_EPROTO 1
+# endif
+
+# ifndef EMULTIHOP
+#  define EMULTIHOP 2004
+#  define GNULIB_defined_EMULTIHOP 1
+# endif
+
+# ifndef EBADMSG
+#  define EBADMSG   2005
+#  define GNULIB_defined_EBADMSG 1
+# endif
+
+# ifndef EOVERFLOW
+#  define EOVERFLOW 2006
+#  define GNULIB_defined_EOVERFLOW 1
+# endif
+
+# ifndef ENOTSUP
+#  define ENOTSUP   2007
+#  define GNULIB_defined_ENOTSUP 1
+# endif
+
+# ifndef ENETRESET
+#  define ENETRESET 2011
+#  define GNULIB_defined_ENETRESET 1
+# endif
+
+# ifndef ECONNABORTED
+#  define ECONNABORTED 2012
+#  define GNULIB_defined_ECONNABORTED 1
+# endif
+
+# ifndef ESTALE
+#  define ESTALE    2009
+#  define GNULIB_defined_ESTALE 1
+# endif
+
+# ifndef EDQUOT
+#  define EDQUOT 2010
+#  define GNULIB_defined_EDQUOT 1
+# endif
+
+# ifndef ECANCELED
+#  define ECANCELED 2008
+#  define GNULIB_defined_ECANCELED 1
+# endif
+
+/* On many platforms, the macros EOWNERDEAD and ENOTRECOVERABLE are not
+   defined.  */
+
+# ifndef EOWNERDEAD
+#  if defined __sun
+    /* Use the same values as defined for Solaris >= 8, for
+       interoperability.  */
+#   define EOWNERDEAD      58
+#   define ENOTRECOVERABLE 59
+#  elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+    /* We have a conflict here: pthreads-win32 defines these values
+       differently than MSVC 10.  It's hairy to decide which one to use.  */
+#   if defined __MINGW32__ && !defined USE_WINDOWS_THREADS
+     /* Use the same values as defined by pthreads-win32, for
+        interoperability.  */
+#    define EOWNERDEAD      43
+#    define ENOTRECOVERABLE 44
+#   else
+     /* Use the same values as defined by MSVC 10, for
+        interoperability.  */
+#    define EOWNERDEAD      133
+#    define ENOTRECOVERABLE 127
+#   endif
+#  else
+#   define EOWNERDEAD      2013
+#   define ENOTRECOVERABLE 2014
+#  endif
+#  define GNULIB_defined_EOWNERDEAD 1
+#  define GNULIB_defined_ENOTRECOVERABLE 1
+# endif
+
+# ifndef EILSEQ
+#  define EILSEQ 2015
+#  define GNULIB_defined_EILSEQ 1
+# endif
+
+#endif /* _@GUARD_PREFIX@_ERRNO_H */
+#endif /* _@GUARD_PREFIX@_ERRNO_H */
diff --git a/libgnu/error.c b/libgnu/error.c
new file mode 100644
index 0000000..535d8a2
--- /dev/null
+++ b/libgnu/error.c
@@ -0,0 +1,406 @@
+/* Error handler for noninteractive utilities
+   Copyright (C) 1990-1998, 2000-2007, 2009-2017 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* 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"
+# define _(msgid) gettext (msgid)
+#endif
+
+#ifdef _LIBC
+# include <libintl.h>
+# include <stdbool.h>
+# include <stdint.h>
+# include <wchar.h>
+# define mbsrtowcs __mbsrtowcs
+# define USE_UNLOCKED_IO 0
+# define _GL_ATTRIBUTE_FORMAT_PRINTF(a, b)
+# define _GL_ARG_NONNULL(a)
+#else
+# include "getprogname.h"
+#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) _IO_fflush (s)
+# undef putc
+# define putc(c, fp) _IO_putc (c, fp)
+
+# include <bits/libc-lock.h>
+
+#else /* not _LIBC */
+
+# include <fcntl.h>
+# include <unistd.h>
+
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+/* Get declarations of the native Windows API functions.  */
+#  define WIN32_LEAN_AND_MEAN
+#  include <windows.h>
+/* Get _get_osfhandle.  */
+#  include "msvc-nothrow.h"
+# endif
+
+/* The gnulib override of fcntl is not needed in this file.  */
+# undef fcntl
+
+# if !HAVE_DECL_STRERROR_R
+#  ifndef HAVE_DECL_STRERROR_R
+"this configure-time declaration test was not run"
+#  endif
+#  if STRERROR_R_CHAR_P
+char *strerror_r ();
+#  else
+int strerror_r ();
+#  endif
+# endif
+
+#define program_name getprogname ()
+
+# if HAVE_STRERROR_R || defined strerror_r
+#  define __strerror_r strerror_r
+# endif /* HAVE_STRERROR_R || defined strerror_r */
+#endif  /* not _LIBC */
+
+#if !_LIBC
+/* Return non-zero if FD is open.  */
+static int
+is_open (int fd)
+{
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+  /* On native Windows: The initial state of unassigned standard file
+     descriptors is that they are open but point to an INVALID_HANDLE_VALUE.
+     There is no fcntl, and the gnulib replacement fcntl does not support
+     F_GETFL.  */
+  return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
+# else
+#  ifndef F_GETFL
+#   error Please port fcntl to your platform
+#  endif
+  return 0 <= fcntl (fd, F_GETFL);
+# endif
+}
+#endif
+
+static void
+flush_stdout (void)
+{
+#if !_LIBC
+  int stdout_fd;
+
+# if GNULIB_FREOPEN_SAFER
+  /* Use of gnulib's freopen-safer module normally ensures that
+       fileno (stdout) == 1
+     whenever stdout is open.  */
+  stdout_fd = STDOUT_FILENO;
+# else
+  /* POSIX states that fileno (stdout) after fclose is unspecified.  But in
+     practice it is not a problem, because stdout is statically allocated and
+     the fd of a FILE stream is stored as a field in its allocated memory.  */
+  stdout_fd = fileno (stdout);
+# endif
+  /* POSIX states that fflush (stdout) after fclose is unspecified; it
+     is safe in glibc, but not on all other platforms.  fflush (NULL)
+     is always defined, but too draconian.  */
+  if (0 <= stdout_fd && is_open (stdout_fd))
+#endif
+    fflush (stdout);
+}
+
+static void
+print_errno_message (int errnum)
+{
+  char const *s;
+
+#if defined HAVE_STRERROR_R || _LIBC
+  char errbuf[1024];
+# if _LIBC || STRERROR_R_CHAR_P
+  s = __strerror_r (errnum, errbuf, sizeof errbuf);
+# else
+  if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
+    s = errbuf;
+  else
+    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 _GL_ATTRIBUTE_FORMAT_PRINTF (3, 0) _GL_ARG_NONNULL ((3))
+error_tail (int status, int errnum, const char *message, va_list args)
+{
+#if _LIBC
+  if (_IO_fwide (stderr, 0) > 0)
+    {
+      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 / sizeof (wchar_t) / 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
+
+  flush_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
+              || (old_file_name != NULL
+                  && file_name != NULL
+                  && 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
+
+  flush_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:%u: " : " ",
+              file_name, line_number);
+#else
+  fprintf (stderr, file_name != NULL ? "%s:%u: " : " ",
+           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/libgnu/error.h b/libgnu/error.h
new file mode 100644
index 0000000..ef024d9
--- /dev/null
+++ b/libgnu/error.h
@@ -0,0 +1,75 @@
+/* Declaration for error-reporting function
+   Copyright (C) 1995-1997, 2003, 2006, 2008-2017 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _ERROR_H
+#define _ERROR_H 1
+
+/* The __attribute__ feature is available in gcc versions 2.5 and later.
+   The __-protected variants of the attributes 'format' and 'printf' are
+   accepted by gcc versions 2.6.4 (effectively 2.7) and later.
+   We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, because
+   gnulib and libintl do '#define printf __printf__' when they override
+   the 'printf' function.  */
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
+#else
+# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */
+#endif
+
+/* On mingw, the flavor of printf depends on whether the extensions module
+ * is in use; the check for <stdio.h> determines the witness macro.  */
+#ifndef _GL_ATTRIBUTE_SPEC_PRINTF
+# if GNULIB_PRINTF_ATTRIBUTE_FLAVOR_GNU
+#  define _GL_ATTRIBUTE_SPEC_PRINTF __gnu_printf__
+# else
+#  define _GL_ATTRIBUTE_SPEC_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, ...)
+     _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF, 3, 4));
+
+extern void error_at_line (int __status, int __errnum, const char *__fname,
+                           unsigned int __lineno, const char *__format, ...)
+     _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_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/libgnu/exitfail.c b/libgnu/exitfail.c
new file mode 100644
index 0000000..524eb5c
--- /dev/null
+++ b/libgnu/exitfail.c
@@ -0,0 +1,24 @@
+/* Failure exit status
+
+   Copyright (C) 2002-2003, 2005-2007, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include "exitfail.h"
+
+#include <stdlib.h>
+
+int volatile exit_failure = EXIT_FAILURE;
diff --git a/libgnu/exitfail.h b/libgnu/exitfail.h
new file mode 100644
index 0000000..895511f
--- /dev/null
+++ b/libgnu/exitfail.h
@@ -0,0 +1,18 @@
+/* Failure exit status
+
+   Copyright (C) 2002, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+extern int volatile exit_failure;
diff --git a/libgnu/fchdir.c b/libgnu/fchdir.c
new file mode 100644
index 0000000..63a90f5
--- /dev/null
+++ b/libgnu/fchdir.c
@@ -0,0 +1,208 @@
+/* fchdir replacement.
+   Copyright (C) 2006-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "assure.h"
+#include "dosname.h"
+#include "filenamecat.h"
+
+#ifndef REPLACE_OPEN_DIRECTORY
+# define REPLACE_OPEN_DIRECTORY 0
+#endif
+
+/* This replacement assumes that a directory is not renamed while opened
+   through a file descriptor.
+
+   FIXME: On mingw, this would be possible to enforce if we were to
+   also open a HANDLE to each directory currently visited by a file
+   descriptor, since mingw refuses to rename any in-use file system
+   object.  */
+
+/* Array of file descriptors opened.  If REPLACE_OPEN_DIRECTORY or if it points
+   to a directory, it stores info about this directory.  */
+typedef struct
+{
+  char *name;       /* Absolute name of the directory, or NULL.  */
+  /* FIXME - add a DIR* member to make dirfd possible on mingw?  */
+} 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; free any
+   contents already in that slot.  Return false and set errno to
+   ENOMEM on allocation failure.  */
+static bool
+ensure_dirs_slot (size_t fd)
+{
+  if (fd < dirs_allocated)
+    free (dirs[fd].name);
+  else
+    {
+      size_t new_allocated;
+      dir_info_t *new_dirs;
+
+      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 *dirs)
+         : (dir_info_t *) malloc (new_allocated * sizeof *dirs));
+      if (new_dirs == NULL)
+        return false;
+      memset (new_dirs + dirs_allocated, 0,
+              (new_allocated - dirs_allocated) * sizeof *dirs);
+      dirs = new_dirs;
+      dirs_allocated = new_allocated;
+    }
+  return true;
+}
+
+/* Return an absolute name of DIR in malloc'd storage.  */
+static char *
+get_name (char const *dir)
+{
+  char *cwd;
+  char *result;
+  int saved_errno;
+
+  if (IS_ABSOLUTE_FILE_NAME (dir))
+    return strdup (dir);
+
+  /* We often encounter "."; treat it as a special case.  */
+  cwd = getcwd (NULL, 0);
+  if (!cwd || (dir[0] == '.' && dir[1] == '\0'))
+    return cwd;
+
+  result = mfile_name_concat (cwd, dir, NULL);
+  saved_errno = errno;
+  free (cwd);
+  errno = saved_errno;
+  return result;
+}
+
+/* Hook into the gnulib replacements for open() and close() to keep track
+   of the open file descriptors.  */
+
+/* Close FD, cleaning up any fd to name mapping if fd was visiting a
+   directory.  */
+void
+_gl_unregister_fd (int fd)
+{
+  if (fd >= 0 && fd < dirs_allocated)
+    {
+      free (dirs[fd].name);
+      dirs[fd].name = NULL;
+    }
+}
+
+/* Mark FD as visiting FILENAME.  FD must be non-negative, and refer
+   to an open file descriptor.  If REPLACE_OPEN_DIRECTORY is non-zero,
+   this should only be called if FD is visiting a directory.  Close FD
+   and return -1 if there is insufficient memory to track the
+   directory name; otherwise return FD.  */
+int
+_gl_register_fd (int fd, const char *filename)
+{
+  struct stat statbuf;
+
+  assure (0 <= fd);
+  if (REPLACE_OPEN_DIRECTORY
+      || (fstat (fd, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)))
+    {
+      if (!ensure_dirs_slot (fd)
+          || (dirs[fd].name = get_name (filename)) == NULL)
+        {
+          int saved_errno = errno;
+          close (fd);
+          errno = saved_errno;
+          return -1;
+        }
+    }
+  return fd;
+}
+
+/* Mark NEWFD as a duplicate of OLDFD; useful from dup, dup2, dup3,
+   and fcntl.  Both arguments must be valid and distinct file
+   descriptors.  Close NEWFD and return -1 if OLDFD is tracking a
+   directory, but there is insufficient memory to track the same
+   directory in NEWFD; otherwise return NEWFD.  */
+int
+_gl_register_dup (int oldfd, int newfd)
+{
+  assure (0 <= oldfd && 0 <= newfd && oldfd != newfd);
+  if (oldfd < dirs_allocated && dirs[oldfd].name)
+    {
+      /* Duplicated a directory; must ensure newfd is allocated.  */
+      if (!ensure_dirs_slot (newfd)
+          || (dirs[newfd].name = strdup (dirs[oldfd].name)) == NULL)
+        {
+          int saved_errno = errno;
+          close (newfd);
+          errno = saved_errno;
+          newfd = -1;
+        }
+    }
+  else if (newfd < dirs_allocated)
+    {
+      /* Duplicated a non-directory; ensure newfd is cleared.  */
+      free (dirs[newfd].name);
+      dirs[newfd].name = NULL;
+    }
+  return newfd;
+}
+
+/* If FD is currently visiting a directory, then return the name of
+   that directory.  Otherwise, return NULL and set errno.  */
+const char *
+_gl_directory_name (int fd)
+{
+  if (0 <= fd && fd < dirs_allocated && dirs[fd].name != NULL)
+    return dirs[fd].name;
+  /* At this point, fd is either invalid, or open but not a directory.
+     If dup2 fails, errno is correctly EBADF.  */
+  if (0 <= fd)
+    {
+      if (dup2 (fd, fd) == fd)
+        errno = ENOTDIR;
+    }
+  else
+    errno = EBADF;
+  return NULL;
+}
+
+
+/* Implement fchdir() in terms of chdir().  */
+
+int
+fchdir (int fd)
+{
+  const char *name = _gl_directory_name (fd);
+  return name ? chdir (name) : -1;
+}
diff --git a/libgnu/fcntl--.h b/libgnu/fcntl--.h
new file mode 100644
index 0000000..ba87d79
--- /dev/null
+++ b/libgnu/fcntl--.h
@@ -0,0 +1,32 @@
+/* Like fcntl.h, but redefine some names to avoid glitches.
+
+   Copyright (C) 2005, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Paul Eggert.  */
+
+#include <fcntl.h>
+#include "fcntl-safer.h"
+
+#undef open
+#define open open_safer
+
+#undef creat
+#define creat creat_safer
+
+#if GNULIB_OPENAT_SAFER
+# undef openat
+# define openat openat_safer
+#endif
diff --git a/libgnu/fcntl-safer.h b/libgnu/fcntl-safer.h
new file mode 100644
index 0000000..252fe73
--- /dev/null
+++ b/libgnu/fcntl-safer.h
@@ -0,0 +1,27 @@
+/* Invoke fcntl-like functions, but avoid some glitches.
+
+   Copyright (C) 2005, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Paul Eggert.  */
+
+#include <sys/types.h>
+
+int open_safer (char const *, int, ...);
+int creat_safer (char const *, mode_t);
+
+#if GNULIB_OPENAT_SAFER
+int openat_safer (int, char const *, int, ...);
+#endif
diff --git a/libgnu/fcntl.c b/libgnu/fcntl.c
new file mode 100644
index 0000000..afe1546
--- /dev/null
+++ b/libgnu/fcntl.c
@@ -0,0 +1,414 @@
+/* Provide file descriptor control.
+
+   Copyright (C) 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Eric Blake <ebb9@byu.net>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <fcntl.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#if !HAVE_FCNTL
+# define rpl_fcntl fcntl
+#endif
+#undef fcntl
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+/* Get declarations of the native Windows API functions.  */
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+
+/* Get _get_osfhandle.  */
+# include "msvc-nothrow.h"
+
+/* Upper bound on getdtablesize().  See lib/getdtablesize.c.  */
+# define OPEN_MAX_MAX 0x10000
+
+/* Duplicate OLDFD into the first available slot of at least NEWFD,
+   which must be positive, with FLAGS determining whether the duplicate
+   will be inheritable.  */
+static int
+dupfd (int oldfd, int newfd, int flags)
+{
+  /* Mingw has no way to create an arbitrary fd.  Iterate until all
+     file descriptors less than newfd are filled up.  */
+  HANDLE curr_process = GetCurrentProcess ();
+  HANDLE old_handle = (HANDLE) _get_osfhandle (oldfd);
+  unsigned char fds_to_close[OPEN_MAX_MAX / CHAR_BIT];
+  unsigned int fds_to_close_bound = 0;
+  int result;
+  BOOL inherit = flags & O_CLOEXEC ? FALSE : TRUE;
+  int mode;
+
+  if (newfd < 0 || getdtablesize () <= newfd)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  if (old_handle == INVALID_HANDLE_VALUE
+      || (mode = setmode (oldfd, O_BINARY)) == -1)
+    {
+      /* oldfd is not open, or is an unassigned standard file
+         descriptor.  */
+      errno = EBADF;
+      return -1;
+    }
+  setmode (oldfd, mode);
+  flags |= mode;
+
+  for (;;)
+    {
+      HANDLE new_handle;
+      int duplicated_fd;
+      unsigned int index;
+
+      if (!DuplicateHandle (curr_process,           /* SourceProcessHandle */
+                            old_handle,             /* SourceHandle */
+                            curr_process,           /* TargetProcessHandle */
+                            (PHANDLE) &new_handle,  /* TargetHandle */
+                            (DWORD) 0,              /* DesiredAccess */
+                            inherit,                /* InheritHandle */
+                            DUPLICATE_SAME_ACCESS)) /* Options */
+        {
+          switch (GetLastError ())
+            {
+              case ERROR_TOO_MANY_OPEN_FILES:
+                errno = EMFILE;
+                break;
+              case ERROR_INVALID_HANDLE:
+              case ERROR_INVALID_TARGET_HANDLE:
+              case ERROR_DIRECT_ACCESS_HANDLE:
+                errno = EBADF;
+                break;
+              case ERROR_INVALID_PARAMETER:
+              case ERROR_INVALID_FUNCTION:
+              case ERROR_INVALID_ACCESS:
+                errno = EINVAL;
+                break;
+              default:
+                errno = EACCES;
+                break;
+            }
+          result = -1;
+          break;
+        }
+      duplicated_fd = _open_osfhandle ((intptr_t) new_handle, flags);
+      if (duplicated_fd < 0)
+        {
+          CloseHandle (new_handle);
+          result = -1;
+          break;
+        }
+      if (newfd <= duplicated_fd)
+        {
+          result = duplicated_fd;
+          break;
+        }
+
+      /* Set the bit duplicated_fd in fds_to_close[].  */
+      index = (unsigned int) duplicated_fd / CHAR_BIT;
+      if (fds_to_close_bound <= index)
+        {
+          if (sizeof fds_to_close <= index)
+            /* Need to increase OPEN_MAX_MAX.  */
+            abort ();
+          memset (fds_to_close + fds_to_close_bound, '\0',
+                  index + 1 - fds_to_close_bound);
+          fds_to_close_bound = index + 1;
+        }
+      fds_to_close[index] |= 1 << ((unsigned int) duplicated_fd % CHAR_BIT);
+    }
+
+  /* Close the previous fds that turned out to be too small.  */
+  {
+    int saved_errno = errno;
+    unsigned int duplicated_fd;
+
+    for (duplicated_fd = 0;
+         duplicated_fd < fds_to_close_bound * CHAR_BIT;
+         duplicated_fd++)
+      if ((fds_to_close[duplicated_fd / CHAR_BIT]
+           >> (duplicated_fd % CHAR_BIT))
+          & 1)
+        close (duplicated_fd);
+
+    errno = saved_errno;
+  }
+
+# if REPLACE_FCHDIR
+  if (0 <= result)
+    result = _gl_register_dup (oldfd, result);
+# endif
+  return result;
+}
+#endif /* W32 */
+
+#ifdef __KLIBC__
+
+# define INCL_DOS
+# include <os2.h>
+
+static int
+klibc_fcntl (int fd, int action, /* arg */...)
+{
+  va_list arg_ptr;
+  int arg;
+  struct stat sbuf;
+  int result = -1;
+
+  va_start (arg_ptr, action);
+  arg = va_arg (arg_ptr, int);
+  result = fcntl (fd, action, arg);
+  /* EPERM for F_DUPFD, ENOTSUP for others */
+  if (result == -1 && (errno == EPERM || errno == ENOTSUP)
+      && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
+  {
+    ULONG ulMode;
+
+    switch (action)
+      {
+      case F_DUPFD:
+        /* Find available fd */
+        while (fcntl (arg, F_GETFL) != -1 || errno != EBADF)
+          arg++;
+
+        result = dup2 (fd, arg);
+        break;
+
+      /* Using underlying APIs is right ? */
+      case F_GETFD:
+        if (DosQueryFHState (fd, &ulMode))
+          break;
+
+        result = (ulMode & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0;
+        break;
+
+      case F_SETFD:
+        if (arg & ~FD_CLOEXEC)
+          break;
+
+        if (DosQueryFHState (fd, &ulMode))
+          break;
+
+        if (arg & FD_CLOEXEC)
+          ulMode |= OPEN_FLAGS_NOINHERIT;
+        else
+          ulMode &= ~OPEN_FLAGS_NOINHERIT;
+
+        /* Filter supported flags.  */
+        ulMode &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR
+                   | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT);
+
+        if (DosSetFHState (fd, ulMode))
+          break;
+
+        result = 0;
+        break;
+
+      case F_GETFL:
+        result = 0;
+        break;
+
+      case F_SETFL:
+        if (arg != 0)
+          break;
+
+        result = 0;
+        break;
+
+      default :
+        errno = EINVAL;
+        break;
+      }
+  }
+
+  va_end (arg_ptr);
+
+  return result;
+}
+
+# define fcntl klibc_fcntl
+#endif
+
+/* Perform the specified ACTION on the file descriptor FD, possibly
+   using the argument ARG further described below.  This replacement
+   handles the following actions, and forwards all others on to the
+   native fcntl.  An unrecognized ACTION returns -1 with errno set to
+   EINVAL.
+
+   F_DUPFD - duplicate FD, with int ARG being the minimum target fd.
+   If successful, return the duplicate, which will be inheritable;
+   otherwise return -1 and set errno.
+
+   F_DUPFD_CLOEXEC - duplicate FD, with int ARG being the minimum
+   target fd.  If successful, return the duplicate, which will not be
+   inheritable; otherwise return -1 and set errno.
+
+   F_GETFD - ARG need not be present.  If successful, return a
+   non-negative value containing the descriptor flags of FD (only
+   FD_CLOEXEC is portable, but other flags may be present); otherwise
+   return -1 and set errno.  */
+
+int
+rpl_fcntl (int fd, int action, /* arg */...)
+{
+  va_list arg;
+  int result = -1;
+  va_start (arg, action);
+  switch (action)
+    {
+
+#if !HAVE_FCNTL
+    case F_DUPFD:
+      {
+        int target = va_arg (arg, int);
+        result = dupfd (fd, target, 0);
+        break;
+      }
+#elif FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR
+    case F_DUPFD:
+      {
+        int target = va_arg (arg, int);
+        /* Detect invalid target; needed for cygwin 1.5.x.  */
+        if (target < 0 || getdtablesize () <= target)
+          errno = EINVAL;
+        else
+          {
+            /* Haiku alpha 2 loses fd flags on original.  */
+            int flags = fcntl (fd, F_GETFD);
+            if (flags < 0)
+              {
+                result = -1;
+                break;
+              }
+            result = fcntl (fd, action, target);
+            if (0 <= result && fcntl (fd, F_SETFD, flags) == -1)
+              {
+                int saved_errno = errno;
+                close (result);
+                result = -1;
+                errno = saved_errno;
+              }
+# if REPLACE_FCHDIR
+            if (0 <= result)
+              result = _gl_register_dup (fd, result);
+# endif
+          }
+        break;
+      } /* F_DUPFD */
+#endif /* FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR */
+
+    case F_DUPFD_CLOEXEC:
+      {
+        int target = va_arg (arg, int);
+
+#if !HAVE_FCNTL
+        result = dupfd (fd, target, O_CLOEXEC);
+        break;
+#else /* HAVE_FCNTL */
+        /* Try the system call first, if the headers claim it exists
+           (that is, if GNULIB_defined_F_DUPFD_CLOEXEC is 0), since we
+           may be running with a glibc that has the macro but with an
+           older kernel that does not support it.  Cache the
+           information on whether the system call really works, but
+           avoid caching failure if the corresponding F_DUPFD fails
+           for any reason.  0 = unknown, 1 = yes, -1 = no.  */
+        static int have_dupfd_cloexec = GNULIB_defined_F_DUPFD_CLOEXEC ? -1 : 0;
+        if (0 <= have_dupfd_cloexec)
+          {
+            result = fcntl (fd, action, target);
+            if (0 <= result || errno != EINVAL)
+              {
+                have_dupfd_cloexec = 1;
+# if REPLACE_FCHDIR
+                if (0 <= result)
+                  result = _gl_register_dup (fd, result);
+# endif
+              }
+            else
+              {
+                result = rpl_fcntl (fd, F_DUPFD, target);
+                if (result < 0)
+                  break;
+                have_dupfd_cloexec = -1;
+              }
+          }
+        else
+          result = rpl_fcntl (fd, F_DUPFD, target);
+        if (0 <= result && have_dupfd_cloexec == -1)
+          {
+            int flags = fcntl (result, F_GETFD);
+            if (flags < 0 || fcntl (result, F_SETFD, flags | FD_CLOEXEC) == -1)
+              {
+                int saved_errno = errno;
+                close (result);
+                errno = saved_errno;
+                result = -1;
+              }
+          }
+        break;
+#endif /* HAVE_FCNTL */
+      } /* F_DUPFD_CLOEXEC */
+
+#if !HAVE_FCNTL
+    case F_GETFD:
+      {
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+        HANDLE handle = (HANDLE) _get_osfhandle (fd);
+        DWORD flags;
+        if (handle == INVALID_HANDLE_VALUE
+            || GetHandleInformation (handle, &flags) == 0)
+          errno = EBADF;
+        else
+          result = (flags & HANDLE_FLAG_INHERIT) ? 0 : FD_CLOEXEC;
+# else /* !W32 */
+        /* Use dup2 to reject invalid file descriptors.  No way to
+           access this information, so punt.  */
+        if (0 <= dup2 (fd, fd))
+          result = 0;
+# endif /* !W32 */
+        break;
+      } /* F_GETFD */
+#endif /* !HAVE_FCNTL */
+
+      /* Implementing F_SETFD on mingw is not trivial - there is no
+         API for changing the O_NOINHERIT bit on an fd, and merely
+         changing the HANDLE_FLAG_INHERIT bit on the underlying handle
+         can lead to odd state.  It may be possible by duplicating the
+         handle, using _open_osfhandle with the right flags, then
+         using dup2 to move the duplicate onto the original, but that
+         is not supported for now.  */
+
+    default:
+      {
+#if HAVE_FCNTL
+        void *p = va_arg (arg, void *);
+        result = fcntl (fd, action, p);
+#else
+        errno = EINVAL;
+#endif
+        break;
+      }
+    }
+  va_end (arg);
+  return result;
+}
diff --git a/libgnu/fcntl.in.h b/libgnu/fcntl.in.h
new file mode 100644
index 0000000..4a1d40a
--- /dev/null
+++ b/libgnu/fcntl.in.h
@@ -0,0 +1,363 @@
+/* Like <fcntl.h>, but with non-working flags defined to 0.
+
+   Copyright (C) 2006-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* written by Paul Eggert */
+
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+@PRAGMA_COLUMNS@
+
+#if defined __need_system_fcntl_h
+/* Special invocation convention.  */
+
+/* Needed before <sys/stat.h>.
+   May also define off_t to a 64-bit type on native Windows.  */
+#include <sys/types.h>
+/* On some systems other than glibc, <sys/stat.h> is a prerequisite of
+   <fcntl.h>.  On glibc systems, we would like to avoid namespace pollution.
+   But on glibc systems, <fcntl.h> includes <sys/stat.h> inside an
+   extern "C" { ... } block, which leads to errors in C++ mode with the
+   overridden <sys/stat.h> from gnulib.  These errors are known to be gone
+   with g++ version >= 4.3.  */
+#if !(defined __GLIBC__ || defined __UCLIBC__) || (defined __cplusplus && defined GNULIB_NAMESPACE && (defined __ICC || !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))))
+# include <sys/stat.h>
+#endif
+#@INCLUDE_NEXT@ @NEXT_FCNTL_H@
+
+#else
+/* Normal invocation convention.  */
+
+#ifndef _@GUARD_PREFIX@_FCNTL_H
+
+/* Needed before <sys/stat.h>.
+   May also define off_t to a 64-bit type on native Windows.  */
+#include <sys/types.h>
+/* On some systems other than glibc, <sys/stat.h> is a prerequisite of
+   <fcntl.h>.  On glibc systems, we would like to avoid namespace pollution.
+   But on glibc systems, <fcntl.h> includes <sys/stat.h> inside an
+   extern "C" { ... } block, which leads to errors in C++ mode with the
+   overridden <sys/stat.h> from gnulib.  These errors are known to be gone
+   with g++ version >= 4.3.  */
+#if !(defined __GLIBC__ || defined __UCLIBC__) || (defined __cplusplus && defined GNULIB_NAMESPACE && (defined __ICC || !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))))
+# include <sys/stat.h>
+#endif
+/* The include_next requires a split double-inclusion guard.  */
+#@INCLUDE_NEXT@ @NEXT_FCNTL_H@
+
+#ifndef _@GUARD_PREFIX@_FCNTL_H
+#define _@GUARD_PREFIX@_FCNTL_H
+
+#ifndef __GLIBC__ /* Avoid namespace pollution on glibc systems.  */
+# include <unistd.h>
+#endif
+
+/* Native Windows platforms declare open(), creat() in <io.h>.  */
+#if (@GNULIB_OPEN@ || defined GNULIB_POSIXCHECK) \
+    && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
+# include <io.h>
+#endif
+
+
+/* The definitions of _GL_FUNCDECL_RPL etc. are copied here.  */
+
+/* The definition of _GL_ARG_NONNULL is copied here.  */
+
+/* The definition of _GL_WARN_ON_USE is copied here.  */
+
+
+/* Declare overridden functions.  */
+
+#if @GNULIB_FCNTL@
+# if @REPLACE_FCNTL@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef fcntl
+#   define fcntl rpl_fcntl
+#  endif
+_GL_FUNCDECL_RPL (fcntl, int, (int fd, int action, ...));
+_GL_CXXALIAS_RPL (fcntl, int, (int fd, int action, ...));
+# else
+#  if !@HAVE_FCNTL@
+_GL_FUNCDECL_SYS (fcntl, int, (int fd, int action, ...));
+#  endif
+_GL_CXXALIAS_SYS (fcntl, int, (int fd, int action, ...));
+# endif
+_GL_CXXALIASWARN (fcntl);
+#elif defined GNULIB_POSIXCHECK
+# undef fcntl
+# if HAVE_RAW_DECL_FCNTL
+_GL_WARN_ON_USE (fcntl, "fcntl is not always POSIX compliant - "
+                 "use gnulib module fcntl for portability");
+# endif
+#endif
+
+#if @GNULIB_OPEN@
+# if @REPLACE_OPEN@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef open
+#   define open rpl_open
+#  endif
+_GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...)
+                             _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...));
+# else
+_GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...));
+# endif
+/* On HP-UX 11, in C++ mode, open() is defined as an inline function with a
+   default argument.  _GL_CXXALIASWARN does not work in this case.  */
+# if !defined __hpux
+_GL_CXXALIASWARN (open);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef open
+/* Assume open is always declared.  */
+_GL_WARN_ON_USE (open, "open is not always POSIX compliant - "
+                 "use gnulib module open for portability");
+#endif
+
+#if @GNULIB_OPENAT@
+# if @REPLACE_OPENAT@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef openat
+#   define openat rpl_openat
+#  endif
+_GL_FUNCDECL_RPL (openat, int,
+                  (int fd, char const *file, int flags, /* mode_t mode */ ...)
+                  _GL_ARG_NONNULL ((2)));
+_GL_CXXALIAS_RPL (openat, int,
+                  (int fd, char const *file, int flags, /* mode_t mode */ ...));
+# else
+#  if !@HAVE_OPENAT@
+_GL_FUNCDECL_SYS (openat, int,
+                  (int fd, char const *file, int flags, /* mode_t mode */ ...)
+                  _GL_ARG_NONNULL ((2)));
+#  endif
+_GL_CXXALIAS_SYS (openat, int,
+                  (int fd, char const *file, int flags, /* mode_t mode */ ...));
+# endif
+_GL_CXXALIASWARN (openat);
+#elif defined GNULIB_POSIXCHECK
+# undef openat
+# if HAVE_RAW_DECL_OPENAT
+_GL_WARN_ON_USE (openat, "openat is not portable - "
+                 "use gnulib module openat for portability");
+# endif
+#endif
+
+
+/* Fix up the FD_* macros, only known to be missing on mingw.  */
+
+#ifndef FD_CLOEXEC
+# define FD_CLOEXEC 1
+#endif
+
+/* Fix up the supported F_* macros.  Intentionally leave other F_*
+   macros undefined.  Only known to be missing on mingw.  */
+
+#ifndef F_DUPFD_CLOEXEC
+# define F_DUPFD_CLOEXEC 0x40000000
+/* Witness variable: 1 if gnulib defined F_DUPFD_CLOEXEC, 0 otherwise.  */
+# define GNULIB_defined_F_DUPFD_CLOEXEC 1
+#else
+# define GNULIB_defined_F_DUPFD_CLOEXEC 0
+#endif
+
+#ifndef F_DUPFD
+# define F_DUPFD 1
+#endif
+
+#ifndef F_GETFD
+# define F_GETFD 2
+#endif
+
+/* Fix up the O_* macros.  */
+
+/* AIX 7.1 with XL C 12.1 defines O_CLOEXEC, O_NOFOLLOW, and O_TTY_INIT
+   to values outside 'int' range, so omit these misdefinitions.
+   But avoid namespace pollution on non-AIX systems.  */
+#ifdef _AIX
+# include <limits.h>
+# if defined O_CLOEXEC && ! (INT_MIN <= O_CLOEXEC && O_CLOEXEC <= INT_MAX)
+#  undef O_CLOEXEC
+# endif
+# if defined O_NOFOLLOW && ! (INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX)
+#  undef O_NOFOLLOW
+# endif
+# if defined O_TTY_INIT && ! (INT_MIN <= O_TTY_INIT && O_TTY_INIT <= INT_MAX)
+#  undef O_TTY_INIT
+# endif
+#endif
+
+#if !defined O_DIRECT && defined O_DIRECTIO
+/* Tru64 spells it 'O_DIRECTIO'.  */
+# define O_DIRECT O_DIRECTIO
+#endif
+
+#if !defined O_CLOEXEC && defined O_NOINHERIT
+/* Mingw spells it 'O_NOINHERIT'.  */
+# define O_CLOEXEC O_NOINHERIT
+#endif
+
+#ifndef O_CLOEXEC
+# define O_CLOEXEC 0
+#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_EXEC
+# define O_EXEC O_RDONLY /* This is often close enough in older systems.  */
+#endif
+
+#ifndef O_IGNORE_CTTY
+# define O_IGNORE_CTTY 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
+
+/* If the gnulib module 'nonblocking' is in use, guarantee a working non-zero
+   value of O_NONBLOCK.  Otherwise, O_NONBLOCK is defined (above) to O_NDELAY
+   or to 0 as fallback.  */
+#if @GNULIB_NONBLOCKING@
+# if O_NONBLOCK
+#  define GNULIB_defined_O_NONBLOCK 0
+# else
+#  define GNULIB_defined_O_NONBLOCK 1
+#  undef O_NONBLOCK
+#  define O_NONBLOCK 0x40000000
+# endif
+#endif
+
+#ifndef O_NOCTTY
+# define O_NOCTTY 0
+#endif
+
+#ifndef O_NOFOLLOW
+# define O_NOFOLLOW 0
+#endif
+
+#ifndef O_NOLINK
+# define O_NOLINK 0
+#endif
+
+#ifndef O_NOLINKS
+# define O_NOLINKS 0
+#endif
+
+#ifndef O_NOTRANS
+# define O_NOTRANS 0
+#endif
+
+#ifndef O_RSYNC
+# define O_RSYNC 0
+#endif
+
+#ifndef O_SEARCH
+# define O_SEARCH O_RDONLY /* This is often close enough in older systems.  */
+#endif
+
+#ifndef O_SYNC
+# define O_SYNC 0
+#endif
+
+#ifndef O_TTY_INIT
+# define O_TTY_INIT 0
+#endif
+
+#if ~O_ACCMODE & (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH)
+# undef O_ACCMODE
+# define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH)
+#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
+
+#if defined __BEOS__ || defined __HAIKU__
+  /* BeOS 5 and Haiku have 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
+
+/* Fix up the AT_* macros.  */
+
+/* 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
+#endif
+
+#ifndef AT_REMOVEDIR
+# define AT_REMOVEDIR 1
+#endif
+
+/* Solaris 9 lacks these two, so just pick unique values.  */
+#ifndef AT_SYMLINK_FOLLOW
+# define AT_SYMLINK_FOLLOW 2
+#endif
+
+#ifndef AT_EACCESS
+# define AT_EACCESS 4
+#endif
+
+
+#endif /* _@GUARD_PREFIX@_FCNTL_H */
+#endif /* _@GUARD_PREFIX@_FCNTL_H */
+#endif
diff --git a/libgnu/fd-hook.c b/libgnu/fd-hook.c
new file mode 100644
index 0000000..ab5847a
--- /dev/null
+++ b/libgnu/fd-hook.c
@@ -0,0 +1,116 @@
+/* Hook for making making file descriptor functions close(), ioctl() extensible.
+   Copyright (C) 2009-2017 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2009.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "fd-hook.h"
+
+#include <stdlib.h>
+
+/* Currently, this entire code is only needed for the handling of sockets
+   on native Windows platforms.  */
+#if WINDOWS_SOCKETS
+
+/* The first and last link in the doubly linked list.
+   Initially the list is empty.  */
+static struct fd_hook anchor = { &anchor, &anchor, NULL, NULL };
+
+int
+execute_close_hooks (const struct fd_hook *remaining_list, gl_close_fn primary,
+                     int fd)
+{
+  if (remaining_list == &anchor)
+    /* End of list reached.  */
+    return primary (fd);
+  else
+    return remaining_list->private_close_fn (remaining_list->private_next,
+                                             primary, fd);
+}
+
+int
+execute_all_close_hooks (gl_close_fn primary, int fd)
+{
+  return execute_close_hooks (anchor.private_next, primary, fd);
+}
+
+int
+execute_ioctl_hooks (const struct fd_hook *remaining_list, gl_ioctl_fn primary,
+                     int fd, int request, void *arg)
+{
+  if (remaining_list == &anchor)
+    /* End of list reached.  */
+    return primary (fd, request, arg);
+  else
+    return remaining_list->private_ioctl_fn (remaining_list->private_next,
+                                             primary, fd, request, arg);
+}
+
+int
+execute_all_ioctl_hooks (gl_ioctl_fn primary,
+                         int fd, int request, void *arg)
+{
+  return execute_ioctl_hooks (anchor.private_next, primary, fd, request, arg);
+}
+
+void
+register_fd_hook (close_hook_fn close_hook, ioctl_hook_fn ioctl_hook, struct fd_hook *link)
+{
+  if (close_hook == NULL)
+    close_hook = execute_close_hooks;
+  if (ioctl_hook == NULL)
+    ioctl_hook = execute_ioctl_hooks;
+
+  if (link->private_next == NULL && link->private_prev == NULL)
+    {
+      /* Add the link to the doubly linked list.  */
+      link->private_next = anchor.private_next;
+      link->private_prev = &anchor;
+      link->private_close_fn = close_hook;
+      link->private_ioctl_fn = ioctl_hook;
+      anchor.private_next->private_prev = link;
+      anchor.private_next = link;
+    }
+  else
+    {
+      /* The link is already in use.  */
+      if (link->private_close_fn != close_hook
+          || link->private_ioctl_fn != ioctl_hook)
+        abort ();
+    }
+}
+
+void
+unregister_fd_hook (struct fd_hook *link)
+{
+  struct fd_hook *next = link->private_next;
+  struct fd_hook *prev = link->private_prev;
+
+  if (next != NULL && prev != NULL)
+    {
+      /* The link is in use.  Remove it from the doubly linked list.  */
+      prev->private_next = next;
+      next->private_prev = prev;
+      /* Clear the link, to mark it unused.  */
+      link->private_next = NULL;
+      link->private_prev = NULL;
+      link->private_close_fn = NULL;
+      link->private_ioctl_fn = NULL;
+    }
+}
+
+#endif
diff --git a/libgnu/fd-hook.h b/libgnu/fd-hook.h
new file mode 100644
index 0000000..fe0d1b0
--- /dev/null
+++ b/libgnu/fd-hook.h
@@ -0,0 +1,119 @@
+/* Hook for making making file descriptor functions close(), ioctl() extensible.
+   Copyright (C) 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifndef FD_HOOK_H
+#define FD_HOOK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Currently, this entire code is only needed for the handling of sockets
+   on native Windows platforms.  */
+#if WINDOWS_SOCKETS
+
+
+/* Type of function that closes FD.  */
+typedef int (*gl_close_fn) (int fd);
+
+/* Type of function that applies a control request to FD.  */
+typedef int (*gl_ioctl_fn) (int fd, int request, void *arg);
+
+/* An element of the list of file descriptor hooks.
+   In CLOS (Common Lisp Object System) speak, it consists of an "around"
+   method for the close() function and an "around" method for the ioctl()
+   function.
+   The fields of this structure are considered private.  */
+struct fd_hook
+{
+  /* Doubly linked list.  */
+  struct fd_hook *private_next;
+  struct fd_hook *private_prev;
+  /* Function that treats the types of FD that it knows about and calls
+     execute_close_hooks (REMAINING_LIST, PRIMARY, FD) as a fallback.  */
+  int (*private_close_fn) (const struct fd_hook *remaining_list,
+                           gl_close_fn primary,
+                           int fd);
+  /* Function that treats the types of FD that it knows about and calls
+     execute_ioctl_hooks (REMAINING_LIST, PRIMARY, FD, REQUEST, ARG) as a
+     fallback.  */
+  int (*private_ioctl_fn) (const struct fd_hook *remaining_list,
+                           gl_ioctl_fn primary,
+                           int fd, int request, void *arg);
+};
+
+/* This type of function closes FD, applying special knowledge for the FD
+   types it knows about, and calls
+   execute_close_hooks (REMAINING_LIST, PRIMARY, FD)
+   for the other FD types.
+   In CLOS speak, REMAINING_LIST is the remaining list of "around" methods,
+   and PRIMARY is the "primary" method for close().  */
+typedef int (*close_hook_fn) (const struct fd_hook *remaining_list,
+                              gl_close_fn primary,
+                              int fd);
+
+/* Execute the close hooks in REMAINING_LIST, with PRIMARY as "primary" method.
+   Return 0 or -1, like close() would do.  */
+extern int execute_close_hooks (const struct fd_hook *remaining_list,
+                                gl_close_fn primary,
+                                int fd);
+
+/* Execute all close hooks, with PRIMARY as "primary" method.
+   Return 0 or -1, like close() would do.  */
+extern int execute_all_close_hooks (gl_close_fn primary, int fd);
+
+/* This type of function applies a control request to FD, applying special
+   knowledge for the FD types it knows about, and calls
+   execute_ioctl_hooks (REMAINING_LIST, PRIMARY, FD, REQUEST, ARG)
+   for the other FD types.
+   In CLOS speak, REMAINING_LIST is the remaining list of "around" methods,
+   and PRIMARY is the "primary" method for ioctl().  */
+typedef int (*ioctl_hook_fn) (const struct fd_hook *remaining_list,
+                              gl_ioctl_fn primary,
+                              int fd, int request, void *arg);
+
+/* Execute the ioctl hooks in REMAINING_LIST, with PRIMARY as "primary" method.
+   Return 0 or -1, like ioctl() would do.  */
+extern int execute_ioctl_hooks (const struct fd_hook *remaining_list,
+                                gl_ioctl_fn primary,
+                                int fd, int request, void *arg);
+
+/* Execute all ioctl hooks, with PRIMARY as "primary" method.
+   Return 0 or -1, like ioctl() would do.  */
+extern int execute_all_ioctl_hooks (gl_ioctl_fn primary,
+                                    int fd, int request, void *arg);
+
+/* Add a function pair to the list of file descriptor hooks.
+   CLOSE_HOOK and IOCTL_HOOK may be NULL, indicating no change.
+   The LINK variable points to a piece of memory which is guaranteed to be
+   accessible until the corresponding call to unregister_fd_hook.  */
+extern void register_fd_hook (close_hook_fn close_hook, ioctl_hook_fn ioctl_hook,
+                              struct fd_hook *link);
+
+/* Removes a hook from the list of file descriptor hooks.  */
+extern void unregister_fd_hook (struct fd_hook *link);
+
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FD_HOOK_H */
diff --git a/libgnu/fd-safer.c b/libgnu/fd-safer.c
new file mode 100644
index 0000000..da09128
--- /dev/null
+++ b/libgnu/fd-safer.c
@@ -0,0 +1,49 @@
+/* Return a safer copy of a file descriptor.
+
+   Copyright (C) 2005-2006, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Paul Eggert.  */
+
+#include <config.h>
+
+#include "unistd-safer.h"
+
+#include <errno.h>
+#include <unistd.h>
+
+/* 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/libgnu/fdopendir.c b/libgnu/fdopendir.c
new file mode 100644
index 0000000..03be92a
--- /dev/null
+++ b/libgnu/fdopendir.c
@@ -0,0 +1,249 @@
+/* provide a replacement fdopendir function
+   Copyright (C) 2004-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* written by Jim Meyering */
+
+#include <config.h>
+
+#include <dirent.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#if !HAVE_FDOPENDIR
+
+# include "openat.h"
+# include "openat-priv.h"
+# include "save-cwd.h"
+
+# if GNULIB_DIRENT_SAFER
+#  include "dirent--.h"
+# endif
+
+# ifndef REPLACE_FCHDIR
+#  define REPLACE_FCHDIR 0
+# endif
+
+static DIR *fdopendir_with_dup (int, int, struct saved_cwd const *);
+static DIR *fd_clone_opendir (int, struct saved_cwd const *);
+
+/* Replacement for POSIX fdopendir.
+
+   First, try to simulate it via opendir ("/proc/self/fd/...").  Failing
+   that, simulate it by using fchdir metadata, or 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.
+
+   If successful, the resulting stream is based on FD in
+   implementations where streams are based on file descriptors and in
+   applications where no other thread or signal handler allocates or
+   frees file descriptors.  In other cases, consult dirfd on the result
+   to find out whether FD is still being used.
+
+   Otherwise, this function works just like POSIX fdopendir.
+
+   W A R N I N G:
+
+   Unlike other fd-related functions, this one places constraints on FD.
+   If this function returns successfully, FD is under control of the
+   dirent.h system, and the caller should not close or modify the state of
+   FD other than by the dirent.h functions.  */
+# ifdef __KLIBC__
+#  include <InnoTekLIBC/backend.h>
+
+DIR *
+fdopendir (int fd)
+{
+  char path[_MAX_PATH];
+  DIR *dirp;
+
+  /* Get a path from fd */
+  if (__libc_Back_ioFHToPath (fd, path, sizeof (path)))
+    return NULL;
+
+  dirp = opendir (path);
+  if (!dirp)
+    return NULL;
+
+  /* Unregister fd registered by opendir() */
+  _gl_unregister_dirp_fd (dirfd (dirp));
+
+  /* Register our fd */
+  if (_gl_register_dirp_fd (fd, dirp))
+    {
+      int saved_errno = errno;
+
+      closedir (dirp);
+
+      errno = saved_errno;
+
+      dirp = NULL;
+    }
+
+  return dirp;
+}
+# else
+DIR *
+fdopendir (int fd)
+{
+  DIR *dir = fdopendir_with_dup (fd, -1, NULL);
+
+  if (! REPLACE_FCHDIR && ! dir)
+    {
+      int saved_errno = errno;
+      if (EXPECTED_ERRNO (saved_errno))
+        {
+          struct saved_cwd cwd;
+          if (save_cwd (&cwd) != 0)
+            openat_save_fail (errno);
+          dir = fdopendir_with_dup (fd, -1, &cwd);
+          saved_errno = errno;
+          free_cwd (&cwd);
+          errno = saved_errno;
+        }
+    }
+
+  return dir;
+}
+# endif
+
+/* Like fdopendir, except that if OLDER_DUPFD is not -1, it is known
+   to be a dup of FD which is less than FD - 1 and which will be
+   closed by the caller and not otherwise used by the caller.  This
+   function makes sure that FD is closed and all file descriptors less
+   than FD are open, and then calls fd_clone_opendir on a dup of FD.
+   That way, barring race conditions, fd_clone_opendir returns a
+   stream whose file descriptor is FD.
+
+   If REPLACE_FCHDIR or CWD is null, use opendir ("/proc/self/fd/...",
+   falling back on fchdir metadata.  Otherwise, CWD is a saved version
+   of the working directory; use fchdir/opendir(".")/restore_cwd(CWD).  */
+static DIR *
+fdopendir_with_dup (int fd, int older_dupfd, struct saved_cwd const *cwd)
+{
+  int dupfd = dup (fd);
+  if (dupfd < 0 && errno == EMFILE)
+    dupfd = older_dupfd;
+  if (dupfd < 0)
+    return NULL;
+  else
+    {
+      DIR *dir;
+      int saved_errno;
+      if (dupfd < fd - 1 && dupfd != older_dupfd)
+        {
+          dir = fdopendir_with_dup (fd, dupfd, cwd);
+          saved_errno = errno;
+        }
+      else
+        {
+          close (fd);
+          dir = fd_clone_opendir (dupfd, cwd);
+          saved_errno = errno;
+          if (! dir)
+            {
+              int fd1 = dup (dupfd);
+              if (fd1 != fd)
+                openat_save_fail (fd1 < 0 ? errno : EBADF);
+            }
+        }
+
+      if (dupfd != older_dupfd)
+        close (dupfd);
+      errno = saved_errno;
+      return dir;
+    }
+}
+
+/* Like fdopendir, except the result controls a clone of FD.  It is
+   the caller's responsibility both to close FD and (if the result is
+   not null) to closedir the result.  */
+static DIR *
+fd_clone_opendir (int fd, struct saved_cwd const *cwd)
+{
+  if (REPLACE_FCHDIR || ! cwd)
+    {
+      DIR *dir = NULL;
+      int saved_errno = EOPNOTSUPP;
+      char buf[OPENAT_BUFFER_SIZE];
+      char *proc_file = openat_proc_name (buf, fd, ".");
+      if (proc_file)
+        {
+          dir = opendir (proc_file);
+          saved_errno = errno;
+          if (proc_file != buf)
+            free (proc_file);
+        }
+# if REPLACE_FCHDIR
+      if (! dir && EXPECTED_ERRNO (saved_errno))
+        {
+          char const *name = _gl_directory_name (fd);
+          DIR *dp = name ? opendir (name) : NULL;
+
+          /* The caller has done an elaborate dance to arrange for opendir to
+             consume just the right file descriptor.  If dirfd returns -1,
+             though, we're on a system like mingw where opendir does not
+             consume a file descriptor.  Consume it via 'dup' instead.  */
+          if (dp && dirfd (dp) < 0)
+            dup (fd);
+
+          return dp;
+        }
+# endif
+      errno = saved_errno;
+      return dir;
+    }
+  else
+    {
+      if (fchdir (fd) != 0)
+        return NULL;
+      else
+        {
+          DIR *dir = opendir (".");
+          int saved_errno = errno;
+          if (restore_cwd (cwd) != 0)
+            openat_restore_fail (errno);
+          errno = saved_errno;
+          return dir;
+        }
+    }
+}
+
+#else /* HAVE_FDOPENDIR */
+
+# include <errno.h>
+# include <sys/stat.h>
+
+# undef fdopendir
+
+/* Like fdopendir, but work around GNU/Hurd bug by validating FD.  */
+
+DIR *
+rpl_fdopendir (int fd)
+{
+  struct stat st;
+  if (fstat (fd, &st))
+    return NULL;
+  if (!S_ISDIR (st.st_mode))
+    {
+      errno = ENOTDIR;
+      return NULL;
+    }
+  return fdopendir (fd);
+}
+
+#endif /* HAVE_FDOPENDIR */
diff --git a/libgnu/ffs.c b/libgnu/ffs.c
new file mode 100644
index 0000000..d10a733
--- /dev/null
+++ b/libgnu/ffs.c
@@ -0,0 +1,56 @@
+/* ffs.c -- find the first set bit in a word.
+   Copyright (C) 2011-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Eric Blake.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <strings.h>
+
+#include <limits.h>
+
+int
+ffs (int i)
+{
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+  return __builtin_ffs (i);
+#else
+  /* http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup
+     gives this deBruijn constant for a branch-less computation, although
+     that table counted trailing zeros rather than bit position.  This
+     requires 32-bit int, we fall back to a naive algorithm on the rare
+     platforms where that assumption is not true.  */
+  if (CHAR_BIT * sizeof i == 32)
+    {
+      static unsigned int table[] = {
+        1, 2, 29, 3, 30, 15, 25, 4, 31, 23, 21, 16, 26, 18, 5, 9,
+        32, 28, 14, 24, 22, 20, 17, 8, 27, 13, 19, 7, 12, 6, 11, 10
+      };
+      unsigned int u = i;
+      unsigned int bit = u & -u;
+      return table[(bit * 0x077cb531U) >> 27] - !i;
+    }
+  else
+    {
+      unsigned int j;
+      for (j = 0; j < CHAR_BIT * sizeof i; j++)
+        if (i & (1U << j))
+          return j + 1;
+      return 0;
+    }
+#endif
+}
diff --git a/libgnu/file-set.c b/libgnu/file-set.c
new file mode 100644
index 0000000..d71006f
--- /dev/null
+++ b/libgnu/file-set.c
@@ -0,0 +1,74 @@
+/* Specialized functions to manipulate a set of files.
+   Copyright (C) 2007, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* written by Jim Meyering */
+
+#include <config.h>
+#include "file-set.h"
+
+#include "hash-triple.h"
+#include "xalloc.h"
+
+/* Record file, FILE, and dev/ino from *STATS, in the hash table, HT.
+   If HT is NULL, return immediately.
+   If memory allocation fails, exit immediately.  */
+void
+record_file (Hash_table *ht, char const *file, struct stat const *stats)
+{
+  struct F_triple *ent;
+
+  if (ht == NULL)
+    return;
+
+  ent = xmalloc (sizeof *ent);
+  ent->name = xstrdup (file);
+  ent->st_ino = stats->st_ino;
+  ent->st_dev = stats->st_dev;
+
+  {
+    struct F_triple *ent_from_table = hash_insert (ht, ent);
+    if (ent_from_table == NULL)
+      {
+        /* Insertion failed due to lack of memory.  */
+        xalloc_die ();
+      }
+
+    if (ent_from_table != ent)
+      {
+        /* There was alread a matching entry in the table, so ENT was
+           not inserted.  Free it.  */
+        triple_free (ent);
+      }
+  }
+}
+
+/* Return true if there is an entry in hash table, HT,
+   for the file described by FILE and STATS.  */
+bool
+seen_file (Hash_table const *ht, char const *file,
+           struct stat const *stats)
+{
+  struct F_triple new_ent;
+
+  if (ht == NULL)
+    return false;
+
+  new_ent.name = (char *) file;
+  new_ent.st_ino = stats->st_ino;
+  new_ent.st_dev = stats->st_dev;
+
+  return !!hash_lookup (ht, &new_ent);
+}
diff --git a/libgnu/file-set.h b/libgnu/file-set.h
new file mode 100644
index 0000000..4e47d95
--- /dev/null
+++ b/libgnu/file-set.h
@@ -0,0 +1,15 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdbool.h>
+
+#include "hash.h"
+
+extern void record_file (Hash_table *ht, char const *file,
+                         struct stat const *stats)
+#if defined __GNUC__ && ((__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || __GNUC__ > 3)
+  __attribute__ ((nonnull (2, 3)))
+#endif
+;
+
+extern bool seen_file (Hash_table const *ht, char const *file,
+                       struct stat const *stats);
diff --git a/libgnu/filename.h b/libgnu/filename.h
new file mode 100644
index 0000000..0ea7e95
--- /dev/null
+++ b/libgnu/filename.h
@@ -0,0 +1,54 @@
+/* Basic filename support macros.
+   Copyright (C) 2001-2004, 2007-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _FILENAME_H
+#define _FILENAME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Pathname support.
+   ISSLASH(C)           tests whether C is a directory separator character.
+   IS_ABSOLUTE_PATH(P)  tests whether P is an absolute path.  If it is not,
+                        it may be concatenated to a directory pathname.
+   IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.
+ */
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
+  /* Native Windows, Cygwin, OS/2, DOS */
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+# define HAS_DEVICE(P) \
+    ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
+     && (P)[1] == ':')
+# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
+# define IS_PATH_WITH_DIR(P) \
+    (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
+# define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
+#else
+  /* Unix */
+# define ISSLASH(C) ((C) == '/')
+# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
+# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
+# define FILE_SYSTEM_PREFIX_LEN(P) 0
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FILENAME_H */
diff --git a/libgnu/filenamecat-lgpl.c b/libgnu/filenamecat-lgpl.c
new file mode 100644
index 0000000..6dade12
--- /dev/null
+++ b/libgnu/filenamecat-lgpl.c
@@ -0,0 +1,88 @@
+/* Concatenate two arbitrary file names.
+
+   Copyright (C) 1996-2007, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Jim Meyering.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "filenamecat.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "dirname.h"
+
+#if ! HAVE_MEMPCPY && ! defined mempcpy
+# define mempcpy(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N)))
+#endif
+
+/* Return the longest suffix of F that is a relative file name.
+   If it has no such suffix, return the empty string.  */
+
+static char const * _GL_ATTRIBUTE_PURE
+longest_relative_suffix (char const *f)
+{
+  for (f += FILE_SYSTEM_PREFIX_LEN (f); ISSLASH (*f); f++)
+    continue;
+  return f;
+}
+
+/* Concatenate two file name components, DIR and ABASE, in
+   newly-allocated storage and return the result.
+   The resulting file name F is such that the commands "ls F" and "(cd
+   DIR; ls BASE)" refer to the same file, where BASE is ABASE with any
+   file system prefixes and leading separators removed.
+   Arrange for a directory separator if necessary between DIR and BASE
+   in the result, removing any redundant separators.
+   In any case, if BASE_IN_RESULT is non-NULL, set
+   *BASE_IN_RESULT to point to the copy of ABASE in the returned
+   concatenation.  However, if ABASE begins with more than one slash,
+   set *BASE_IN_RESULT to point to the sole corresponding slash that
+   is copied into the result buffer.
+
+   Return NULL if malloc fails.  */
+
+char *
+mfile_name_concat (char const *dir, char const *abase, char **base_in_result)
+{
+  char const *dirbase = last_component (dir);
+  size_t dirbaselen = base_len (dirbase);
+  size_t dirlen = dirbase - dir + dirbaselen;
+  size_t needs_separator = (dirbaselen && ! ISSLASH (dirbase[dirbaselen - 1]));
+
+  char const *base = longest_relative_suffix (abase);
+  size_t baselen = strlen (base);
+
+  char *p_concat = malloc (dirlen + needs_separator + baselen + 1);
+  char *p;
+
+  if (p_concat == NULL)
+    return NULL;
+
+  p = mempcpy (p_concat, dir, dirlen);
+  *p = DIRECTORY_SEPARATOR;
+  p += needs_separator;
+
+  if (base_in_result)
+    *base_in_result = p - IS_ABSOLUTE_FILE_NAME (abase);
+
+  p = mempcpy (p, base, baselen);
+  *p = '\0';
+
+  return p_concat;
+}
diff --git a/libgnu/filenamecat.h b/libgnu/filenamecat.h
new file mode 100644
index 0000000..feb906a
--- /dev/null
+++ b/libgnu/filenamecat.h
@@ -0,0 +1,27 @@
+/* Concatenate two arbitrary file names.
+
+   Copyright (C) 1996-1997, 2003, 2005, 2007, 2009-2017 Free Software
+   Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Jim Meyering.  */
+
+#if GNULIB_FILENAMECAT
+char *file_name_concat (char const *dir, char const *base,
+                        char **base_in_result);
+#endif
+
+char *mfile_name_concat (char const *dir, char const *base,
+                         char **base_in_result);
diff --git a/libgnu/flexmember.h b/libgnu/flexmember.h
new file mode 100644
index 0000000..c71ea65
--- /dev/null
+++ b/libgnu/flexmember.h
@@ -0,0 +1,42 @@
+/* Sizes of structs with flexible array members.
+
+   Copyright 2016-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+   Written by Paul Eggert.  */
+
+#include <stddef.h>
+
+/* Nonzero multiple of alignment of TYPE, suitable for FLEXSIZEOF below.
+   On older platforms without _Alignof, use a pessimistic bound that is
+   safe in practice even if FLEXIBLE_ARRAY_MEMBER is 1.
+   On newer platforms, use _Alignof to get a tighter bound.  */
+
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112
+# define FLEXALIGNOF(type) (sizeof (type) & ~ (sizeof (type) - 1))
+#else
+# define FLEXALIGNOF(type) _Alignof (type)
+#endif
+
+/* Upper bound on the size of a struct of type TYPE with a flexible
+   array member named MEMBER that is followed by N bytes of other data.
+   This is not simply sizeof (TYPE) + N, since it may require
+   alignment on unusually picky C11 platforms, and
+   FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms.
+   Yield a value less than N if and only if arithmetic overflow occurs.  */
+
+#define FLEXSIZEOF(type, member, n) \
+   ((offsetof (type, member) + FLEXALIGNOF (type) - 1 + (n)) \
+    & ~ (FLEXALIGNOF (type) - 1))
diff --git a/libgnu/float+.h b/libgnu/float+.h
new file mode 100644
index 0000000..ba8ecb7
--- /dev/null
+++ b/libgnu/float+.h
@@ -0,0 +1,147 @@
+/* Supplemental information about the floating-point formats.
+   Copyright (C) 2007, 2009-2017 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 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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _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[SIZEOF_FLT <= sizeof (float) ? 1 : -1];
+typedef int verify_sizeof_dbl[SIZEOF_DBL <= sizeof (double) ? 1 : - 1];
+typedef int verify_sizeof_ldbl[SIZEOF_LDBL <= sizeof (long double) ? 1 : - 1];
+
+#endif /* _FLOATPLUS_H */
diff --git a/libgnu/float.c b/libgnu/float.c
new file mode 100644
index 0000000..b9103ec
--- /dev/null
+++ b/libgnu/float.c
@@ -0,0 +1,33 @@
+/* Auxiliary definitions for <float.h>.
+   Copyright (C) 2011-2017 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2011.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <float.h>
+
+#if (defined _ARCH_PPC || defined _POWER) && (defined _AIX || defined __linux__) && (LDBL_MANT_DIG == 106) && defined __GNUC__
+const union gl_long_double_union gl_LDBL_MAX =
+  { { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL } };
+#elif defined __i386__
+const union gl_long_double_union gl_LDBL_MAX =
+  { { 0xFFFFFFFF, 0xFFFFFFFF, 32766 } };
+#else
+/* This declaration is solely to ensure that after preprocessing
+   this file is never empty.  */
+typedef int dummy;
+#endif
diff --git a/libgnu/float.in.h b/libgnu/float.in.h
new file mode 100644
index 0000000..3e01200
--- /dev/null
+++ b/libgnu/float.in.h
@@ -0,0 +1,188 @@
+/* A correct <float.h>.
+
+   Copyright (C) 2007-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _@GUARD_PREFIX@_FLOAT_H
+
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+@PRAGMA_COLUMNS@
+
+/* The include_next requires a split double-inclusion guard.  */
+#@INCLUDE_NEXT@ @NEXT_FLOAT_H@
+
+#ifndef _@GUARD_PREFIX@_FLOAT_H
+#define _@GUARD_PREFIX@_FLOAT_H
+
+/* 'long double' properties.  */
+
+#if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__)
+/* 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
+
+/* On FreeBSD/x86 6.4, the 'long double' type really has only 53 bits of
+   precision in the compiler but 64 bits of precision at runtime.  See
+   <http://lists.gnu.org/archive/html/bug-gnulib/2008-07/msg00063.html>.  */
+#if defined __i386__ && defined __FreeBSD__
+/* 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.084202172485504434007452800869941711426e-19L /* 2^-63 */
+/* 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.3621031431120935E-4932L /* = 0x1p-16382L */
+/* Maximum representable finite number.  */
+# undef LDBL_MAX
+/* LDBL_MAX is represented as { 0xFFFFFFFF, 0xFFFFFFFF, 32766 }.
+   But the largest literal that GCC allows us to write is
+   0x0.fffffffffffff8p16384L = { 0xFFFFF800, 0xFFFFFFFF, 32766 }.
+   So, define it like this through a reference to an external variable
+
+     const unsigned int LDBL_MAX[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 32766 };
+     extern const long double LDBL_MAX;
+
+   Unfortunately, this is not a constant expression.  */
+union gl_long_double_union
+  {
+    struct { unsigned int lo; unsigned int hi; unsigned int exponent; } xd;
+    long double ld;
+  };
+extern const union gl_long_double_union gl_LDBL_MAX;
+# define LDBL_MAX (gl_LDBL_MAX.ld)
+/* 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
+
+/* On AIX 7.1 with gcc 4.2, the values of LDBL_MIN_EXP, LDBL_MIN, LDBL_MAX are
+   wrong.
+   On Linux/PowerPC with gcc 4.4, the value of LDBL_MAX is wrong.  */
+#if (defined _ARCH_PPC || defined _POWER) && defined _AIX && (LDBL_MANT_DIG == 106) && defined __GNUC__
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP DBL_MIN_EXP
+# undef LDBL_MIN_10_EXP
+# define LDBL_MIN_10_EXP DBL_MIN_10_EXP
+# undef LDBL_MIN
+# define LDBL_MIN 2.22507385850720138309023271733240406422e-308L /* DBL_MIN = 2^-1022 */
+#endif
+#if (defined _ARCH_PPC || defined _POWER) && (defined _AIX || defined __linux__) && (LDBL_MANT_DIG == 106) && defined __GNUC__
+# undef LDBL_MAX
+/* LDBL_MAX is represented as { 0x7FEFFFFF, 0xFFFFFFFF, 0x7C8FFFFF, 0xFFFFFFFF }.
+   It is not easy to define:
+     #define LDBL_MAX 1.79769313486231580793728971405302307166e308L
+   is too small, whereas
+     #define LDBL_MAX 1.79769313486231580793728971405302307167e308L
+   is too large.  Apparently a bug in GCC decimal-to-binary conversion.
+   Also, I can't get values larger than
+     #define LDBL63 ((long double) (1ULL << 63))
+     #define LDBL882 (LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63)
+     #define LDBL945 (LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63)
+     #define LDBL1008 (LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63)
+     #define LDBL_MAX (LDBL1008 * 65535.0L + LDBL945 * (long double) 9223372036821221375ULL + LDBL882 * (long double) 4611686018427387904ULL)
+   which is represented as { 0x7FEFFFFF, 0xFFFFFFFF, 0x7C8FFFFF, 0xF8000000 }.
+   So, define it like this through a reference to an external variable
+
+     const double LDBL_MAX[2] = { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL };
+     extern const long double LDBL_MAX;
+
+   or through a pointer cast
+
+     #define LDBL_MAX \
+       (*(const long double *) (double[]) { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL })
+
+   Unfortunately, this is not a constant expression, and the latter expression
+   does not work well when GCC is optimizing..  */
+union gl_long_double_union
+  {
+    struct { double hi; double lo; } dd;
+    long double ld;
+  };
+extern const union gl_long_double_union gl_LDBL_MAX;
+# define LDBL_MAX (gl_LDBL_MAX.ld)
+#endif
+
+/* On IRIX 6.5, with cc, the value of LDBL_MANT_DIG is wrong.
+   On IRIX 6.5, with gcc 4.2, the values of LDBL_MIN_EXP, LDBL_MIN, LDBL_EPSILON
+   are wrong.  */
+#if defined __sgi && (LDBL_MANT_DIG >= 106)
+# undef LDBL_MANT_DIG
+# define LDBL_MANT_DIG 106
+# if defined __GNUC__
+#  undef LDBL_MIN_EXP
+#  define LDBL_MIN_EXP DBL_MIN_EXP
+#  undef LDBL_MIN_10_EXP
+#  define LDBL_MIN_10_EXP DBL_MIN_10_EXP
+#  undef LDBL_MIN
+#  define LDBL_MIN 2.22507385850720138309023271733240406422e-308L /* DBL_MIN = 2^-1022 */
+#  undef LDBL_EPSILON
+#  define LDBL_EPSILON 2.46519032881566189191165176650870696773e-32L /* 2^-105 */
+# endif
+#endif
+
+#if @REPLACE_ITOLD@
+/* Pull in a function that fixes the 'int' to 'long double' conversion
+   of glibc 2.7.  */
+extern
+# ifdef __cplusplus
+"C"
+# endif
+void _Qp_itoq (long double *, int);
+static void (*_gl_float_fix_itold) (long double *, int) = _Qp_itoq;
+#endif
+
+#endif /* _@GUARD_PREFIX@_FLOAT_H */
+#endif /* _@GUARD_PREFIX@_FLOAT_H */
diff --git a/libgnu/fnmatch.c b/libgnu/fnmatch.c
new file mode 100644
index 0000000..709d4ff
--- /dev/null
+++ b/libgnu/fnmatch.c
@@ -0,0 +1,348 @@
+/* Copyright (C) 1991-1993, 1996-2007, 2009-2017 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 version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+/* Enable GNU extensions in fnmatch.h.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE    1
+#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 amendment 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
+
+#include "flexmember.h"
+
+/* 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_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 amendment 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)
+# 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 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/libgnu/fnmatch.in.h b/libgnu/fnmatch.in.h
new file mode 100644
index 0000000..1782ad2
--- /dev/null
+++ b/libgnu/fnmatch.in.h
@@ -0,0 +1,67 @@
+/* Copyright (C) 1991-1993, 1996-1999, 2001-2003, 2005, 2007, 2009-2017 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 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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _FNMATCH_H
+#define _FNMATCH_H      1
+
+/* The definition of _GL_ARG_NONNULL is copied here.  */
+
+#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)
+     _GL_ARG_NONNULL ((1, 2));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* fnmatch.h */
diff --git a/libgnu/fnmatch_loop.c b/libgnu/fnmatch_loop.c
new file mode 100644
index 0000000..97a1b9a
--- /dev/null
+++ b/libgnu/fnmatch_loop.c
@@ -0,0 +1,1219 @@
+/* Copyright (C) 1991-1993, 1996-2006, 2009-2017 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 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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+/* 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.  */
+            const CHAR *p_init = p;
+            const CHAR *n_init = n;
+            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 (;;)
+              {
+		bool is_range = false;
+
+                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
+                               equivalence class value.  */
+                            int len = weights[idx & 0xffffff];
+                            int32_t idx2;
+                            const UCHAR *np = (const UCHAR *) n;
+
+                            idx2 = findidx (&np);
+                            if (idx2 != 0
+                                && (idx >> 24) == (idx2 >> 24)
+                                && len == weights[idx2 & 0xffffff])
+                              {
+                                int cnt = 0;
+
+                                idx &= 0xffffff;
+                                idx2 &= 0xffffff;
+
+                                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, treat as normal character.  */
+                    p = p_init;
+                    n = n_init;
+                    c = L_('[');
+                    goto normal_match;
+                  }
+                else
+                  {
+#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[FLEXIBLE_ARRAY_MEMBER];
+  } *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 + 1UL);                                      \
+            plensize = plen * sizeof (CHAR);                                  \
+            newpsize = FLEXSIZEOF (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 STRLEN
+#undef STRCAT
+#undef L_
+#undef BTOWC
diff --git a/libgnu/fstat.c b/libgnu/fstat.c
new file mode 100644
index 0000000..a5aabc5
--- /dev/null
+++ b/libgnu/fstat.c
@@ -0,0 +1,88 @@
+/* fstat() replacement.
+   Copyright (C) 2011-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* If the user's config.h happens to include <sys/stat.h>, let it include only
+   the system's <sys/stat.h> here, so that orig_fstat doesn't recurse to
+   rpl_fstat.  */
+#define __need_system_sys_stat_h
+#include <config.h>
+
+/* Get the original definition of fstat.  It might be defined as a macro.  */
+#include <sys/types.h>
+#include <sys/stat.h>
+#if _GL_WINDOWS_64_BIT_ST_SIZE
+# undef stat /* avoid warning on mingw64 with _FILE_OFFSET_BITS=64 */
+# define stat _stati64
+# undef fstat /* avoid warning on mingw64 with _FILE_OFFSET_BITS=64 */
+# define fstat _fstati64
+#endif
+#undef __need_system_sys_stat_h
+
+static int
+orig_fstat (int fd, struct stat *buf)
+{
+  return fstat (fd, buf);
+}
+
+/* Specification.  */
+/* Write "sys/stat.h" here, not <sys/stat.h>, otherwise OSF/1 5.1 DTK cc
+   eliminates this include because of the preliminary #include <sys/stat.h>
+   above.  */
+#include "sys/stat.h"
+
+#include <errno.h>
+#include <unistd.h>
+
+#if HAVE_MSVC_INVALID_PARAMETER_HANDLER
+# include "msvc-inval.h"
+#endif
+
+#if HAVE_MSVC_INVALID_PARAMETER_HANDLER
+static int
+fstat_nothrow (int fd, struct stat *buf)
+{
+  int result;
+
+  TRY_MSVC_INVAL
+    {
+      result = orig_fstat (fd, buf);
+    }
+  CATCH_MSVC_INVAL
+    {
+      result = -1;
+      errno = EBADF;
+    }
+  DONE_MSVC_INVAL;
+
+  return result;
+}
+#else
+# define fstat_nothrow orig_fstat
+#endif
+
+int
+rpl_fstat (int fd, struct stat *buf)
+{
+#if REPLACE_FCHDIR && REPLACE_OPEN_DIRECTORY
+  /* Handle the case when rpl_open() used a dummy file descriptor to work
+     around an open() that can't normally visit directories.  */
+  const char *name = _gl_directory_name (fd);
+  if (name != NULL)
+    return stat (name, buf);
+#endif
+
+  return fstat_nothrow (fd, buf);
+}
diff --git a/libgnu/fstatat.c b/libgnu/fstatat.c
new file mode 100644
index 0000000..70799be
--- /dev/null
+++ b/libgnu/fstatat.c
@@ -0,0 +1,135 @@
+/* Work around an fstatat bug on Solaris 9.
+
+   Copyright (C) 2006, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Paul Eggert and Jim Meyering.  */
+
+/* If the user's config.h happens to include <sys/stat.h>, let it include only
+   the system's <sys/stat.h> here, so that orig_fstatat doesn't recurse to
+   rpl_fstatat.  */
+#define __need_system_sys_stat_h
+#include <config.h>
+
+/* Get the original definition of fstatat.  It might be defined as a macro.  */
+#include <sys/types.h>
+#include <sys/stat.h>
+#undef __need_system_sys_stat_h
+
+#if HAVE_FSTATAT
+static int
+orig_fstatat (int fd, char const *filename, struct stat *buf, int flags)
+{
+  return fstatat (fd, filename, buf, flags);
+}
+#endif
+
+/* Write "sys/stat.h" here, not <sys/stat.h>, otherwise OSF/1 5.1 DTK cc
+   eliminates this include because of the preliminary #include <sys/stat.h>
+   above.  */
+#include "sys/stat.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+
+#if HAVE_FSTATAT && HAVE_WORKING_FSTATAT_ZERO_FLAG
+
+# ifndef LSTAT_FOLLOWS_SLASHED_SYMLINK
+#  define LSTAT_FOLLOWS_SLASHED_SYMLINK 0
+# endif
+
+/* fstatat should always follow symbolic links that end in /, but on
+   Solaris 9 it doesn't if AT_SYMLINK_NOFOLLOW is specified.
+   Likewise, trailing slash on a non-directory should be an error.
+   These are the same problems that lstat.c and stat.c address, so
+   solve it in a similar way.
+
+   AIX 7.1 fstatat (AT_FDCWD, ..., 0) always fails, which is a bug.
+   Work around this bug if FSTATAT_AT_FDCWD_0_BROKEN is nonzero.  */
+
+int
+rpl_fstatat (int fd, char const *file, struct stat *st, int flag)
+{
+  int result = orig_fstatat (fd, file, st, flag);
+  size_t len;
+
+  if (LSTAT_FOLLOWS_SLASHED_SYMLINK || result != 0)
+    return result;
+  len = strlen (file);
+  if (flag & AT_SYMLINK_NOFOLLOW)
+    {
+      /* Fix lstat behavior.  */
+      if (file[len - 1] != '/' || S_ISDIR (st->st_mode))
+        return 0;
+      if (!S_ISLNK (st->st_mode))
+        {
+          errno = ENOTDIR;
+          return -1;
+        }
+      result = orig_fstatat (fd, file, st, flag & ~AT_SYMLINK_NOFOLLOW);
+    }
+  /* Fix stat behavior.  */
+  if (result == 0 && !S_ISDIR (st->st_mode) && file[len - 1] == '/')
+    {
+      errno = ENOTDIR;
+      return -1;
+    }
+  return result;
+}
+
+#else /* ! (HAVE_FSTATAT && HAVE_WORKING_FSTATAT_ZERO_FLAG) */
+
+/* On mingw, the gnulib <sys/stat.h> defines 'stat' as a function-like
+   macro; but using it in AT_FUNC_F2 causes compilation failure
+   because the preprocessor sees a use of a macro that requires two
+   arguments but is only given one.  Hence, we need an inline
+   forwarder to get past the preprocessor.  */
+static int
+stat_func (char const *name, struct stat *st)
+{
+  return stat (name, st);
+}
+
+/* Likewise, if there is no native 'lstat', then the gnulib
+   <sys/stat.h> defined it as stat, which also needs adjustment.  */
+# if !HAVE_LSTAT
+#  undef lstat
+#  define lstat stat_func
+# 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_func
+# define AT_FUNC_USE_F1_COND 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
+
+#endif /* !HAVE_FSTATAT */
diff --git a/libgnu/fts-cycle.c b/libgnu/fts-cycle.c
new file mode 100644
index 0000000..9c6a1b0
--- /dev/null
+++ b/libgnu/fts-cycle.c
@@ -0,0 +1,160 @@
+/* Detect cycles in file tree walks.
+
+   Copyright (C) 2003-2006, 2009-2017 Free Software Foundation, Inc.
+
+   Written by Jim Meyering.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "cycle-check.h"
+#include "hash.h"
+
+/* Use each of these to map a device/inode pair to an FTSENT.  */
+struct Active_dir
+{
+  dev_t dev;
+  ino_t ino;
+  FTSENT *fts_ent;
+};
+
+static bool
+AD_compare (void const *x, void const *y)
+{
+  struct Active_dir const *ax = x;
+  struct Active_dir const *ay = y;
+  return ax->ino == ay->ino
+      && ax->dev == ay->dev;
+}
+
+static size_t
+AD_hash (void const *x, size_t table_size)
+{
+  struct Active_dir const *ax = x;
+  return (uintmax_t) ax->ino % table_size;
+}
+
+/* Set up the cycle-detection machinery.  */
+
+static bool
+setup_dir (FTS *fts)
+{
+  if (fts->fts_options & (FTS_TIGHT_CYCLE_CHECK | FTS_LOGICAL))
+    {
+      enum { HT_INITIAL_SIZE = 31 };
+      fts->fts_cycle.ht = hash_initialize (HT_INITIAL_SIZE, NULL, AD_hash,
+                                           AD_compare, free);
+      if (! fts->fts_cycle.ht)
+        return false;
+    }
+  else
+    {
+      fts->fts_cycle.state = malloc (sizeof *fts->fts_cycle.state);
+      if (! fts->fts_cycle.state)
+        return false;
+      cycle_check_init (fts->fts_cycle.state);
+    }
+
+  return true;
+}
+
+/* Enter a directory during a file tree walk.  */
+
+static bool
+enter_dir (FTS *fts, FTSENT *ent)
+{
+  if (fts->fts_options & (FTS_TIGHT_CYCLE_CHECK | FTS_LOGICAL))
+    {
+      struct stat const *st = ent->fts_statp;
+      struct Active_dir *ad = malloc (sizeof *ad);
+      struct Active_dir *ad_from_table;
+
+      if (!ad)
+        return false;
+
+      ad->dev = st->st_dev;
+      ad->ino = st->st_ino;
+      ad->fts_ent = ent;
+
+      /* See if we've already encountered this directory.
+         This can happen when following symlinks as well as
+         with a corrupted directory hierarchy. */
+      ad_from_table = hash_insert (fts->fts_cycle.ht, ad);
+
+      if (ad_from_table != ad)
+        {
+          free (ad);
+          if (!ad_from_table)
+            return false;
+
+          /* There was an entry with matching dev/inode already in the table.
+             Record the fact that we've found a cycle.  */
+          ent->fts_cycle = ad_from_table->fts_ent;
+          ent->fts_info = FTS_DC;
+        }
+    }
+  else
+    {
+      if (cycle_check (fts->fts_cycle.state, ent->fts_statp))
+        {
+          /* FIXME: setting fts_cycle like this isn't proper.
+             To do what the documentation requires, we'd have to
+             go around the cycle again and find the right entry.
+             But no callers in coreutils use the fts_cycle member. */
+          ent->fts_cycle = ent;
+          ent->fts_info = FTS_DC;
+        }
+    }
+
+  return true;
+}
+
+/* Leave a directory during a file tree walk.  */
+
+static void
+leave_dir (FTS *fts, FTSENT *ent)
+{
+  struct stat const *st = ent->fts_statp;
+  if (fts->fts_options & (FTS_TIGHT_CYCLE_CHECK | FTS_LOGICAL))
+    {
+      struct Active_dir obj;
+      void *found;
+      obj.dev = st->st_dev;
+      obj.ino = st->st_ino;
+      found = hash_delete (fts->fts_cycle.ht, &obj);
+      if (!found)
+        abort ();
+      free (found);
+    }
+  else
+    {
+      FTSENT *parent = ent->fts_parent;
+      if (parent != NULL && 0 <= parent->fts_level)
+        CYCLE_CHECK_REFLECT_CHDIR_UP (fts->fts_cycle.state,
+                                      *(parent->fts_statp), *st);
+    }
+}
+
+/* Free any memory used for cycle detection.  */
+
+static void
+free_dir (FTS *sp)
+{
+  if (sp->fts_options & (FTS_TIGHT_CYCLE_CHECK | FTS_LOGICAL))
+    {
+      if (sp->fts_cycle.ht)
+        hash_free (sp->fts_cycle.ht);
+    }
+  else
+    free (sp->fts_cycle.state);
+}
diff --git a/libgnu/fts.c b/libgnu/fts.c
new file mode 100644
index 0000000..fabaa97
--- /dev/null
+++ b/libgnu/fts.c
@@ -0,0 +1,2132 @@
+/* Traverse a file hierarchy.
+
+   Copyright (C) 2004-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#if defined LIBC_SCCS && !defined GCC_LINT && !defined lint
+static char sccsid[] = "@(#)fts.c       8.6 (Berkeley) 8/14/94";
+#endif
+
+#include "fts_.h"
+
+#if HAVE_SYS_PARAM_H || defined _LIBC
+# include <sys/param.h>
+#endif
+#ifdef _LIBC
+# include <include/sys/stat.h>
+#else
+# include <sys/stat.h>
+#endif
+#include <fcntl.h>
+#include <errno.h>
+#include <stdalign.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#if ! _LIBC
+# include "fcntl--.h"
+# include "dirent--.h"
+# include "unistd--.h"
+/* FIXME - use fcntl(F_DUPFD_CLOEXEC)/openat(O_CLOEXEC) once they are
+   supported.  */
+# include "cloexec.h"
+# include "flexmember.h"
+# include "openat.h"
+# include "same-inode.h"
+#endif
+
+#include <dirent.h>
+#ifndef _D_EXACT_NAMLEN
+# define _D_EXACT_NAMLEN(dirent) strlen ((dirent)->d_name)
+#endif
+
+#if HAVE_STRUCT_DIRENT_D_TYPE
+/* True if the type of the directory entry D is known.  */
+# define DT_IS_KNOWN(d) ((d)->d_type != DT_UNKNOWN)
+/* True if the type of the directory entry D must be T.  */
+# define DT_MUST_BE(d, t) ((d)->d_type == (t))
+# define D_TYPE(d) ((d)->d_type)
+#else
+# define DT_IS_KNOWN(d) false
+# define DT_MUST_BE(d, t) false
+# define D_TYPE(d) DT_UNKNOWN
+
+# undef DT_UNKNOWN
+# define DT_UNKNOWN 0
+
+/* Any nonzero values will do here, so long as they're distinct.
+   Undef any existing macros out of the way.  */
+# undef DT_BLK
+# undef DT_CHR
+# undef DT_DIR
+# undef DT_FIFO
+# undef DT_LNK
+# undef DT_REG
+# undef DT_SOCK
+# define DT_BLK 1
+# define DT_CHR 2
+# define DT_DIR 3
+# define DT_FIFO 4
+# define DT_LNK 5
+# define DT_REG 6
+# define DT_SOCK 7
+#endif
+
+#ifndef S_IFLNK
+# define S_IFLNK 0
+#endif
+#ifndef S_IFSOCK
+# define S_IFSOCK 0
+#endif
+
+enum
+{
+  NOT_AN_INODE_NUMBER = 0
+};
+
+#ifdef D_INO_IN_DIRENT
+# define D_INO(dp) (dp)->d_ino
+#else
+/* Some systems don't have inodes, so fake them to avoid lots of ifdefs.  */
+# define D_INO(dp) NOT_AN_INODE_NUMBER
+#endif
+
+/* If possible (see max_entries, below), read no more than this many directory
+   entries at a time.  Without this limit (i.e., when using non-NULL
+   fts_compar), processing a directory with 4,000,000 entries requires ~1GiB
+   of memory, and handling 64M entries would require 16GiB of memory.  */
+#ifndef FTS_MAX_READDIR_ENTRIES
+# define FTS_MAX_READDIR_ENTRIES 100000
+#endif
+
+/* If there are more than this many entries in a directory,
+   and the conditions mentioned below are satisfied, then sort
+   the entries on inode number before any further processing.  */
+#ifndef FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD
+# define FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD 10000
+#endif
+
+enum
+{
+  _FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD = FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD
+};
+
+enum Fts_stat
+{
+  FTS_NO_STAT_REQUIRED = 1,
+  FTS_STAT_REQUIRED = 2
+};
+
+#ifdef _LIBC
+# undef close
+# define close __close
+# undef closedir
+# define closedir __closedir
+# undef fchdir
+# define fchdir __fchdir
+# undef open
+# define open __open
+# undef readdir
+# define readdir __readdir
+#else
+# undef internal_function
+# define internal_function /* empty */
+#endif
+
+#ifndef __set_errno
+# define __set_errno(Val) errno = (Val)
+#endif
+
+/* If this host provides the openat function, then we can avoid
+   attempting to open "." in some initialization code below.  */
+#ifdef HAVE_OPENAT
+# define HAVE_OPENAT_SUPPORT 1
+#else
+# define HAVE_OPENAT_SUPPORT 0
+#endif
+
+#ifdef NDEBUG
+# define fts_assert(expr) ((void) (0 && (expr)))
+#else
+# define fts_assert(expr)       \
+    do                          \
+      {                         \
+        if (!(expr))            \
+          abort ();             \
+      }                         \
+    while (false)
+#endif
+
+static FTSENT   *fts_alloc (FTS *, const char *, size_t) internal_function;
+static FTSENT   *fts_build (FTS *, int) internal_function;
+static void      fts_lfree (FTSENT *) internal_function;
+static void      fts_load (FTS *, FTSENT *) internal_function;
+static size_t    fts_maxarglen (char * const *) internal_function;
+static void      fts_padjust (FTS *, FTSENT *) internal_function;
+static bool      fts_palloc (FTS *, size_t) internal_function;
+static FTSENT   *fts_sort (FTS *, FTSENT *, size_t) internal_function;
+static unsigned short int fts_stat (FTS *, FTSENT *, bool) internal_function;
+static int      fts_safe_changedir (FTS *, FTSENT *, int, const char *)
+     internal_function;
+
+#include "fts-cycle.c"
+
+#ifndef MAX
+# define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+#define ISDOT(a)        (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
+#define STREQ(a, b)     (strcmp (a, b) == 0)
+
+#define CLR(opt)        (sp->fts_options &= ~(opt))
+#define ISSET(opt)      (sp->fts_options & (opt))
+#define SET(opt)        (sp->fts_options |= (opt))
+
+/* FIXME: FTS_NOCHDIR is now misnamed.
+   Call it FTS_USE_FULL_RELATIVE_FILE_NAMES instead. */
+#define FCHDIR(sp, fd)                                  \
+  (!ISSET(FTS_NOCHDIR) && (ISSET(FTS_CWDFD)             \
+                           ? (cwd_advance_fd ((sp), (fd), true), 0) \
+                           : fchdir (fd)))
+
+
+/* fts_build flags */
+/* FIXME: make this an enum */
+#define BCHILD          1               /* fts_children */
+#define BNAMES          2               /* fts_children, names only */
+#define BREAD           3               /* fts_read */
+
+#if FTS_DEBUG
+# include <inttypes.h>
+# include <stdint.h>
+# include <stdio.h>
+# include "getcwdat.h"
+bool fts_debug = false;
+# define Dprintf(x) do { if (fts_debug) printf x; } while (false)
+#else
+# define Dprintf(x)
+# define fd_ring_check(x)
+# define fd_ring_print(a, b, c)
+#endif
+
+#define LEAVE_DIR(Fts, Ent, Tag)                                \
+  do                                                            \
+    {                                                           \
+      Dprintf (("  %s-leaving: %s\n", Tag, (Ent)->fts_path));   \
+      leave_dir (Fts, Ent);                                     \
+      fd_ring_check (Fts);                                      \
+    }                                                           \
+  while (false)
+
+static void
+fd_ring_clear (I_ring *fd_ring)
+{
+  while ( ! i_ring_empty (fd_ring))
+    {
+      int fd = i_ring_pop (fd_ring);
+      if (0 <= fd)
+        close (fd);
+    }
+}
+
+/* Overload the fts_statp->st_size member (otherwise unused, when
+   fts_info is FTS_NSOK) to indicate whether fts_read should stat
+   this entry or not.  */
+static void
+fts_set_stat_required (FTSENT *p, bool required)
+{
+  fts_assert (p->fts_info == FTS_NSOK);
+  p->fts_statp->st_size = (required
+                           ? FTS_STAT_REQUIRED
+                           : FTS_NO_STAT_REQUIRED);
+}
+
+/* file-descriptor-relative opendir.  */
+/* FIXME: if others need this function, move it into lib/openat.c */
+static DIR *
+internal_function
+opendirat (int fd, char const *dir, int extra_flags, int *pdir_fd)
+{
+  int new_fd = openat (fd, dir,
+                       (O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
+                        | extra_flags));
+  DIR *dirp;
+
+  if (new_fd < 0)
+    return NULL;
+  set_cloexec_flag (new_fd, true);
+  dirp = fdopendir (new_fd);
+  if (dirp)
+    *pdir_fd = new_fd;
+  else
+    {
+      int saved_errno = errno;
+      close (new_fd);
+      errno = saved_errno;
+    }
+  return dirp;
+}
+
+/* Virtual fchdir.  Advance SP's working directory file descriptor,
+   SP->fts_cwd_fd, to FD, and push the previous value onto the fd_ring.
+   CHDIR_DOWN_ONE is true if FD corresponds to an entry in the directory
+   open on sp->fts_cwd_fd; i.e., to move the working directory one level
+   down.  */
+static void
+internal_function
+cwd_advance_fd (FTS *sp, int fd, bool chdir_down_one)
+{
+  int old = sp->fts_cwd_fd;
+  fts_assert (old != fd || old == AT_FDCWD);
+
+  if (chdir_down_one)
+    {
+      /* Push "old" onto the ring.
+         If the displaced file descriptor is non-negative, close it.  */
+      int prev_fd_in_slot = i_ring_push (&sp->fts_fd_ring, old);
+      fd_ring_print (sp, stderr, "post-push");
+      if (0 <= prev_fd_in_slot)
+        close (prev_fd_in_slot); /* ignore any close failure */
+    }
+  else if ( ! ISSET (FTS_NOCHDIR))
+    {
+      if (0 <= old)
+        close (old); /* ignore any close failure */
+    }
+
+  sp->fts_cwd_fd = fd;
+}
+
+/* Restore the initial, pre-traversal, "working directory".
+   In FTS_CWDFD mode, we merely call cwd_advance_fd, otherwise,
+   we may actually change the working directory.
+   Return 0 upon success. Upon failure, set errno and return nonzero.  */
+static int
+restore_initial_cwd (FTS *sp)
+{
+  int fail = FCHDIR (sp, ISSET (FTS_CWDFD) ? AT_FDCWD : sp->fts_rfd);
+  fd_ring_clear (&(sp->fts_fd_ring));
+  return fail;
+}
+
+/* Open the directory DIR if possible, and return a file
+   descriptor.  Return -1 and set errno on failure.  It doesn't matter
+   whether the file descriptor has read or write access.  */
+
+static int
+internal_function
+diropen (FTS const *sp, char const *dir)
+{
+  int open_flags = (O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
+                    | (ISSET (FTS_PHYSICAL) ? O_NOFOLLOW : 0)
+                    | (ISSET (FTS_NOATIME) ? O_NOATIME : 0));
+
+  int fd = (ISSET (FTS_CWDFD)
+            ? openat (sp->fts_cwd_fd, dir, open_flags)
+            : open (dir, open_flags));
+  if (0 <= fd)
+    set_cloexec_flag (fd, true);
+  return fd;
+}
+
+FTS *
+fts_open (char * const *argv,
+          register int options,
+          int (*compar) (FTSENT const **, FTSENT const **))
+{
+        register FTS *sp;
+        register FTSENT *p, *root;
+        register size_t nitems;
+        FTSENT *parent = NULL;
+        FTSENT *tmp = NULL;     /* pacify gcc */
+        bool defer_stat;
+
+        /* Options check. */
+        if (options & ~FTS_OPTIONMASK) {
+                __set_errno (EINVAL);
+                return (NULL);
+        }
+        if ((options & FTS_NOCHDIR) && (options & FTS_CWDFD)) {
+                __set_errno (EINVAL);
+                return (NULL);
+        }
+        if ( ! (options & (FTS_LOGICAL | FTS_PHYSICAL))) {
+                __set_errno (EINVAL);
+                return (NULL);
+        }
+
+        /* Allocate/initialize the stream */
+        if ((sp = malloc(sizeof(FTS))) == NULL)
+                return (NULL);
+        memset(sp, 0, sizeof(FTS));
+        sp->fts_compar = compar;
+        sp->fts_options = options;
+
+        /* Logical walks turn on NOCHDIR; symbolic links are too hard. */
+        if (ISSET(FTS_LOGICAL)) {
+                SET(FTS_NOCHDIR);
+                CLR(FTS_CWDFD);
+        }
+
+        /* Initialize fts_cwd_fd.  */
+        sp->fts_cwd_fd = AT_FDCWD;
+        if ( ISSET(FTS_CWDFD) && ! HAVE_OPENAT_SUPPORT)
+          {
+            /* While it isn't technically necessary to open "." this
+               early, doing it here saves us the trouble of ensuring
+               later (where it'd be messier) that "." can in fact
+               be opened.  If not, revert to FTS_NOCHDIR mode.  */
+            int fd = open (".",
+                           O_SEARCH | (ISSET (FTS_NOATIME) ? O_NOATIME : 0));
+            if (fd < 0)
+              {
+                /* Even if "." is unreadable, don't revert to FTS_NOCHDIR mode
+                   on systems like Linux+PROC_FS, where our openat emulation
+                   is good enough.  Note: on a system that emulates
+                   openat via /proc, this technique can still fail, but
+                   only in extreme conditions, e.g., when the working
+                   directory cannot be saved (i.e. save_cwd fails) --
+                   and that happens on Linux only when "." is unreadable
+                   and the CWD would be longer than PATH_MAX.
+                   FIXME: once Linux kernel openat support is well established,
+                   replace the above open call and this entire if/else block
+                   with the body of the if-block below.  */
+                if ( openat_needs_fchdir ())
+                  {
+                    SET(FTS_NOCHDIR);
+                    CLR(FTS_CWDFD);
+                  }
+              }
+            else
+              {
+                close (fd);
+              }
+          }
+
+        /*
+         * Start out with 1K of file name space, and enough, in any case,
+         * to hold the user's file names.
+         */
+#ifndef MAXPATHLEN
+# define MAXPATHLEN 1024
+#endif
+        {
+          size_t maxarglen = fts_maxarglen(argv);
+          if (! fts_palloc(sp, MAX(maxarglen, MAXPATHLEN)))
+                  goto mem1;
+        }
+
+        /* Allocate/initialize root's parent. */
+        if (*argv != NULL) {
+                if ((parent = fts_alloc(sp, "", 0)) == NULL)
+                        goto mem2;
+                parent->fts_level = FTS_ROOTPARENTLEVEL;
+          }
+
+        /* The classic fts implementation would call fts_stat with
+           a new entry for each iteration of the loop below.
+           If the comparison function is not specified or if the
+           FTS_DEFER_STAT option is in effect, don't stat any entry
+           in this loop.  This is an attempt to minimize the interval
+           between the initial stat/lstat/fstatat and the point at which
+           a directory argument is first opened.  This matters for any
+           directory command line argument that resides on a file system
+           without genuine i-nodes.  If you specify FTS_DEFER_STAT along
+           with a comparison function, that function must not access any
+           data via the fts_statp pointer.  */
+        defer_stat = (compar == NULL || ISSET(FTS_DEFER_STAT));
+
+        /* Allocate/initialize root(s). */
+        for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {
+                /* *Do* allow zero-length file names. */
+                size_t len = strlen(*argv);
+
+                if ( ! (options & FTS_VERBATIM))
+                  {
+                    /* If there are two or more trailing slashes, trim all but one,
+                       but don't change "//" to "/", and do map "///" to "/".  */
+                    char const *v = *argv;
+                    if (2 < len && v[len - 1] == '/')
+                      while (1 < len && v[len - 2] == '/')
+                        --len;
+                  }
+
+                if ((p = fts_alloc(sp, *argv, len)) == NULL)
+                        goto mem3;
+                p->fts_level = FTS_ROOTLEVEL;
+                p->fts_parent = parent;
+                p->fts_accpath = p->fts_name;
+                /* Even when defer_stat is true, be sure to stat the first
+                   command line argument, since fts_read (at least with
+                   FTS_XDEV) requires that.  */
+                if (defer_stat && root != NULL) {
+                        p->fts_info = FTS_NSOK;
+                        fts_set_stat_required(p, true);
+                } else {
+                        p->fts_info = fts_stat(sp, p, false);
+                }
+
+                /*
+                 * If comparison routine supplied, traverse in sorted
+                 * order; otherwise traverse in the order specified.
+                 */
+                if (compar) {
+                        p->fts_link = root;
+                        root = p;
+                } else {
+                        p->fts_link = NULL;
+                        if (root == NULL)
+                                tmp = root = p;
+                        else {
+                                tmp->fts_link = p;
+                                tmp = p;
+                        }
+                }
+        }
+        if (compar && nitems > 1)
+                root = fts_sort(sp, root, nitems);
+
+        /*
+         * Allocate a dummy pointer and make fts_read think that we've just
+         * finished the node before the root(s); set p->fts_info to FTS_INIT
+         * so that everything about the "current" node is ignored.
+         */
+        if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
+                goto mem3;
+        sp->fts_cur->fts_link = root;
+        sp->fts_cur->fts_info = FTS_INIT;
+        if (! setup_dir (sp))
+                goto mem3;
+
+        /*
+         * If using chdir(2), grab a file descriptor pointing to dot to ensure
+         * that we can get back here; this could be avoided for some file names,
+         * but almost certainly not worth the effort.  Slashes, symbolic links,
+         * and ".." are all fairly nasty problems.  Note, if we can't get the
+         * descriptor we run anyway, just more slowly.
+         */
+        if (!ISSET(FTS_NOCHDIR) && !ISSET(FTS_CWDFD)
+            && (sp->fts_rfd = diropen (sp, ".")) < 0)
+                SET(FTS_NOCHDIR);
+
+        i_ring_init (&sp->fts_fd_ring, -1);
+        return (sp);
+
+mem3:   fts_lfree(root);
+        free(parent);
+mem2:   free(sp->fts_path);
+mem1:   free(sp);
+        return (NULL);
+}
+
+static void
+internal_function
+fts_load (FTS *sp, register FTSENT *p)
+{
+        register size_t len;
+        register char *cp;
+
+        /*
+         * Load the stream structure for the next traversal.  Since we don't
+         * actually enter the directory until after the preorder visit, set
+         * the fts_accpath field specially so the chdir gets done to the right
+         * place and the user can access the first node.  From fts_open it's
+         * known that the file name will fit.
+         */
+        len = p->fts_pathlen = p->fts_namelen;
+        memmove(sp->fts_path, p->fts_name, len + 1);
+        if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
+                len = strlen(++cp);
+                memmove(p->fts_name, cp, len + 1);
+                p->fts_namelen = len;
+        }
+        p->fts_accpath = p->fts_path = sp->fts_path;
+}
+
+int
+fts_close (FTS *sp)
+{
+        register FTSENT *freep, *p;
+        int saved_errno = 0;
+
+        /*
+         * This still works if we haven't read anything -- the dummy structure
+         * points to the root list, so we step through to the end of the root
+         * list which has a valid parent pointer.
+         */
+        if (sp->fts_cur) {
+                for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
+                        freep = p;
+                        p = p->fts_link != NULL ? p->fts_link : p->fts_parent;
+                        free(freep);
+                }
+                free(p);
+        }
+
+        /* Free up child linked list, sort array, file name buffer. */
+        if (sp->fts_child)
+                fts_lfree(sp->fts_child);
+        free(sp->fts_array);
+        free(sp->fts_path);
+
+        if (ISSET(FTS_CWDFD))
+          {
+            if (0 <= sp->fts_cwd_fd)
+              if (close (sp->fts_cwd_fd))
+                saved_errno = errno;
+          }
+        else if (!ISSET(FTS_NOCHDIR))
+          {
+            /* Return to original directory, save errno if necessary. */
+            if (fchdir(sp->fts_rfd))
+              saved_errno = errno;
+
+            /* If close fails, record errno only if saved_errno is zero,
+               so that we report the probably-more-meaningful fchdir errno.  */
+            if (close (sp->fts_rfd))
+              if (saved_errno == 0)
+                saved_errno = errno;
+          }
+
+        fd_ring_clear (&sp->fts_fd_ring);
+
+        if (sp->fts_leaf_optimization_works_ht)
+          hash_free (sp->fts_leaf_optimization_works_ht);
+
+        free_dir (sp);
+
+        /* Free up the stream pointer. */
+        free(sp);
+
+        /* Set errno and return. */
+        if (saved_errno) {
+                __set_errno (saved_errno);
+                return (-1);
+        }
+
+        return (0);
+}
+
+#if defined __linux__ \
+  && HAVE_SYS_VFS_H && HAVE_FSTATFS && HAVE_STRUCT_STATFS_F_TYPE
+
+# include <sys/vfs.h>
+
+/* Linux-specific constants from coreutils' src/fs.h */
+# define S_MAGIC_TMPFS 0x1021994
+# define S_MAGIC_NFS 0x6969
+# define S_MAGIC_REISERFS 0x52654973
+# define S_MAGIC_XFS 0x58465342
+# define S_MAGIC_PROC 0x9FA0
+
+/* Return false if it is easy to determine the file system type of
+   the directory on which DIR_FD is open, and sorting dirents on
+   inode numbers is known not to improve traversal performance with
+   that type of file system.  Otherwise, return true.  */
+static bool
+dirent_inode_sort_may_be_useful (int dir_fd)
+{
+  /* Skip the sort only if we can determine efficiently
+     that skipping it is the right thing to do.
+     The cost of performing an unnecessary sort is negligible,
+     while the cost of *not* performing it can be O(N^2) with
+     a very large constant.  */
+  struct statfs fs_buf;
+
+  /* If fstatfs fails, assume sorting would be useful.  */
+  if (fstatfs (dir_fd, &fs_buf) != 0)
+    return true;
+
+  /* FIXME: what about when f_type is not an integral type?
+     deal with that if/when it's encountered.  */
+  switch (fs_buf.f_type)
+    {
+    case S_MAGIC_TMPFS:
+    case S_MAGIC_NFS:
+      /* On a file system of any of these types, sorting
+         is unnecessary, and hence wasteful.  */
+      return false;
+
+    default:
+      return true;
+    }
+}
+
+/* Given a file descriptor DIR_FD open on a directory D,
+   return true if it is valid to apply the leaf-optimization
+   technique of counting directories in D via stat.st_nlink.  */
+static bool
+leaf_optimization_applies (int dir_fd)
+{
+  struct statfs fs_buf;
+
+  /* If fstatfs fails, assume we can't use the optimization.  */
+  if (fstatfs (dir_fd, &fs_buf) != 0)
+    return false;
+
+  /* FIXME: do we need to detect AFS mount points?  I doubt it,
+     unless fstatfs can report S_MAGIC_REISERFS for such a directory.  */
+
+  switch (fs_buf.f_type)
+    {
+      /* List here the file system types that lack usable dirent.d_type
+         info, yet for which the optimization does apply.  */
+    case S_MAGIC_REISERFS:
+    case S_MAGIC_XFS:
+      return true;
+
+      /* Explicitly list here any other file system type for which the
+         optimization is not applicable, but need documentation.  */
+    case S_MAGIC_NFS:
+      /* NFS provides usable dirent.d_type but not necessarily for all entries
+         of large directories, so as per <https://bugzilla.redhat.com/1252549>
+         NFS should return true.  However st_nlink values are not accurate on
+         all implementations as per <https://bugzilla.redhat.com/1299169>.  */
+      /* fall through */
+    case S_MAGIC_PROC:
+      /* Per <http://bugs.debian.org/143111> /proc may have
+         bogus stat.st_nlink values.  */
+      /* fall through */
+    default:
+      return false;
+    }
+}
+
+#else
+static bool
+dirent_inode_sort_may_be_useful (int dir_fd _GL_UNUSED) { return true; }
+static bool
+leaf_optimization_applies (int dir_fd _GL_UNUSED) { return false; }
+#endif
+
+/* link-count-optimization entry:
+   map a stat.st_dev number to a boolean: leaf_optimization_works */
+struct LCO_ent
+{
+  dev_t st_dev;
+  bool opt_ok;
+};
+
+/* Use a tiny initial size.  If a traversal encounters more than
+   a few devices, the cost of growing/rehashing this table will be
+   rendered negligible by the number of inodes processed.  */
+enum { LCO_HT_INITIAL_SIZE = 13 };
+
+static size_t
+LCO_hash (void const *x, size_t table_size)
+{
+  struct LCO_ent const *ax = x;
+  return (uintmax_t) ax->st_dev % table_size;
+}
+
+static bool
+LCO_compare (void const *x, void const *y)
+{
+  struct LCO_ent const *ax = x;
+  struct LCO_ent const *ay = y;
+  return ax->st_dev == ay->st_dev;
+}
+
+/* Ask the same question as leaf_optimization_applies, but query
+   the cache first (FTS.fts_leaf_optimization_works_ht), and if necessary,
+   update that cache.  */
+static bool
+link_count_optimize_ok (FTSENT const *p)
+{
+  FTS *sp = p->fts_fts;
+  Hash_table *h = sp->fts_leaf_optimization_works_ht;
+  struct LCO_ent tmp;
+  struct LCO_ent *ent;
+  bool opt_ok;
+  struct LCO_ent *t2;
+
+  /* If we're not in CWDFD mode, don't bother with this optimization,
+     since the caller is not serious about performance. */
+  if (!ISSET(FTS_CWDFD))
+    return false;
+
+  /* map st_dev to the boolean, leaf_optimization_works */
+  if (h == NULL)
+    {
+      h = sp->fts_leaf_optimization_works_ht
+        = hash_initialize (LCO_HT_INITIAL_SIZE, NULL, LCO_hash,
+                           LCO_compare, free);
+      if (h == NULL)
+        return false;
+    }
+  tmp.st_dev = p->fts_statp->st_dev;
+  ent = hash_lookup (h, &tmp);
+  if (ent)
+    return ent->opt_ok;
+
+  /* Look-up failed.  Query directly and cache the result.  */
+  t2 = malloc (sizeof *t2);
+  if (t2 == NULL)
+    return false;
+
+  /* Is it ok to perform the optimization in the dir, FTS_CWD_FD?  */
+  opt_ok = leaf_optimization_applies (sp->fts_cwd_fd);
+  t2->opt_ok = opt_ok;
+  t2->st_dev = p->fts_statp->st_dev;
+
+  ent = hash_insert (h, t2);
+  if (ent == NULL)
+    {
+      /* insertion failed */
+      free (t2);
+      return false;
+    }
+  fts_assert (ent == t2);
+
+  return opt_ok;
+}
+
+/*
+ * Special case of "/" at the end of the file name so that slashes aren't
+ * appended which would cause file names to be written as "....//foo".
+ */
+#define NAPPEND(p)                                                      \
+        (p->fts_path[p->fts_pathlen - 1] == '/'                         \
+            ? p->fts_pathlen - 1 : p->fts_pathlen)
+
+FTSENT *
+fts_read (register FTS *sp)
+{
+        register FTSENT *p, *tmp;
+        register unsigned short int instr;
+        register char *t;
+
+        /* If finished or unrecoverable error, return NULL. */
+        if (sp->fts_cur == NULL || ISSET(FTS_STOP))
+                return (NULL);
+
+        /* Set current node pointer. */
+        p = sp->fts_cur;
+
+        /* Save and zero out user instructions. */
+        instr = p->fts_instr;
+        p->fts_instr = FTS_NOINSTR;
+
+        /* Any type of file may be re-visited; re-stat and re-turn. */
+        if (instr == FTS_AGAIN) {
+                p->fts_info = fts_stat(sp, p, false);
+                return (p);
+        }
+        Dprintf (("fts_read: p=%s\n",
+                  p->fts_info == FTS_INIT ? "" : p->fts_path));
+
+        /*
+         * Following a symlink -- SLNONE test allows application to see
+         * SLNONE and recover.  If indirecting through a symlink, have
+         * keep a pointer to current location.  If unable to get that
+         * pointer, follow fails.
+         */
+        if (instr == FTS_FOLLOW &&
+            (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
+                p->fts_info = fts_stat(sp, p, true);
+                if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
+                        if ((p->fts_symfd = diropen (sp, ".")) < 0) {
+                                p->fts_errno = errno;
+                                p->fts_info = FTS_ERR;
+                        } else
+                                p->fts_flags |= FTS_SYMFOLLOW;
+                }
+                goto check_for_dir;
+        }
+
+        /* Directory in pre-order. */
+        if (p->fts_info == FTS_D) {
+                /* If skipped or crossed mount point, do post-order visit. */
+                if (instr == FTS_SKIP ||
+                    (ISSET(FTS_XDEV) && p->fts_statp->st_dev != sp->fts_dev)) {
+                        if (p->fts_flags & FTS_SYMFOLLOW)
+                                (void)close(p->fts_symfd);
+                        if (sp->fts_child) {
+                                fts_lfree(sp->fts_child);
+                                sp->fts_child = NULL;
+                        }
+                        p->fts_info = FTS_DP;
+                        LEAVE_DIR (sp, p, "1");
+                        return (p);
+                }
+
+                /* Rebuild if only read the names and now traversing. */
+                if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) {
+                        CLR(FTS_NAMEONLY);
+                        fts_lfree(sp->fts_child);
+                        sp->fts_child = NULL;
+                }
+
+                /*
+                 * Cd to the subdirectory.
+                 *
+                 * If have already read and now fail to chdir, whack the list
+                 * to make the names come out right, and set the parent errno
+                 * so the application will eventually get an error condition.
+                 * Set the FTS_DONTCHDIR flag so that when we logically change
+                 * directories back to the parent we don't do a chdir.
+                 *
+                 * If haven't read do so.  If the read fails, fts_build sets
+                 * FTS_STOP or the fts_info field of the node.
+                 */
+                if (sp->fts_child != NULL) {
+                        if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
+                                p->fts_errno = errno;
+                                p->fts_flags |= FTS_DONTCHDIR;
+                                for (p = sp->fts_child; p != NULL;
+                                     p = p->fts_link)
+                                        p->fts_accpath =
+                                            p->fts_parent->fts_accpath;
+                        }
+                } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
+                        if (ISSET(FTS_STOP))
+                                return (NULL);
+                        /* If fts_build's call to fts_safe_changedir failed
+                           because it was not able to fchdir into a
+                           subdirectory, tell the caller.  */
+                        if (p->fts_errno && p->fts_info != FTS_DNR)
+                                p->fts_info = FTS_ERR;
+                        LEAVE_DIR (sp, p, "2");
+                        return (p);
+                }
+                p = sp->fts_child;
+                sp->fts_child = NULL;
+                goto name;
+        }
+
+        /* Move to the next node on this level. */
+next:   tmp = p;
+
+        /* If we have so many directory entries that we're reading them
+           in batches, and we've reached the end of the current batch,
+           read in a new batch.  */
+        if (p->fts_link == NULL && p->fts_parent->fts_dirp)
+          {
+            p = tmp->fts_parent;
+            sp->fts_cur = p;
+            sp->fts_path[p->fts_pathlen] = '\0';
+
+            if ((p = fts_build (sp, BREAD)) == NULL)
+              {
+                if (ISSET(FTS_STOP))
+                  return NULL;
+                goto cd_dot_dot;
+              }
+
+            free(tmp);
+            goto name;
+          }
+
+        if ((p = p->fts_link) != NULL) {
+                sp->fts_cur = p;
+                free(tmp);
+
+                /*
+                 * If reached the top, return to the original directory (or
+                 * the root of the tree), and load the file names for the next
+                 * root.
+                 */
+                if (p->fts_level == FTS_ROOTLEVEL) {
+                        if (restore_initial_cwd(sp)) {
+                                SET(FTS_STOP);
+                                return (NULL);
+                        }
+                        free_dir(sp);
+                        fts_load(sp, p);
+                        setup_dir(sp);
+                        goto check_for_dir;
+                }
+
+                /*
+                 * User may have called fts_set on the node.  If skipped,
+                 * ignore.  If followed, get a file descriptor so we can
+                 * get back if necessary.
+                 */
+                if (p->fts_instr == FTS_SKIP)
+                        goto next;
+                if (p->fts_instr == FTS_FOLLOW) {
+                        p->fts_info = fts_stat(sp, p, true);
+                        if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
+                                if ((p->fts_symfd = diropen (sp, ".")) < 0) {
+                                        p->fts_errno = errno;
+                                        p->fts_info = FTS_ERR;
+                                } else
+                                        p->fts_flags |= FTS_SYMFOLLOW;
+                        }
+                        p->fts_instr = FTS_NOINSTR;
+                }
+
+name:           t = sp->fts_path + NAPPEND(p->fts_parent);
+                *t++ = '/';
+                memmove(t, p->fts_name, p->fts_namelen + 1);
+check_for_dir:
+                sp->fts_cur = p;
+                if (p->fts_info == FTS_NSOK)
+                  {
+                    if (p->fts_statp->st_size == FTS_STAT_REQUIRED)
+                      {
+                        FTSENT *parent = p->fts_parent;
+                        if (FTS_ROOTLEVEL < p->fts_level
+                            /* ->fts_n_dirs_remaining is not valid
+                               for command-line-specified names.  */
+                            && parent->fts_n_dirs_remaining == 0
+                            && ISSET(FTS_NOSTAT)
+                            && ISSET(FTS_PHYSICAL)
+                            && link_count_optimize_ok (parent))
+                          {
+                            /* nothing more needed */
+                          }
+                        else
+                          {
+                            p->fts_info = fts_stat(sp, p, false);
+                            if (S_ISDIR(p->fts_statp->st_mode)
+                                && p->fts_level != FTS_ROOTLEVEL
+                                && parent->fts_n_dirs_remaining)
+                                  parent->fts_n_dirs_remaining--;
+                          }
+                      }
+                    else
+                      fts_assert (p->fts_statp->st_size == FTS_NO_STAT_REQUIRED);
+                  }
+
+                if (p->fts_info == FTS_D)
+                  {
+                    /* Now that P->fts_statp is guaranteed to be valid,
+                       if this is a command-line directory, record its
+                       device number, to be used for FTS_XDEV.  */
+                    if (p->fts_level == FTS_ROOTLEVEL)
+                      sp->fts_dev = p->fts_statp->st_dev;
+                    Dprintf (("  entering: %s\n", p->fts_path));
+                    if (! enter_dir (sp, p))
+                      {
+                        __set_errno (ENOMEM);
+                        return NULL;
+                      }
+                  }
+                return p;
+        }
+cd_dot_dot:
+
+        /* Move up to the parent node. */
+        p = tmp->fts_parent;
+        sp->fts_cur = p;
+        free(tmp);
+
+        if (p->fts_level == FTS_ROOTPARENTLEVEL) {
+                /*
+                 * Done; free everything up and set errno to 0 so the user
+                 * can distinguish between error and EOF.
+                 */
+                free(p);
+                __set_errno (0);
+                return (sp->fts_cur = NULL);
+        }
+
+        fts_assert (p->fts_info != FTS_NSOK);
+
+        /* NUL terminate the file name.  */
+        sp->fts_path[p->fts_pathlen] = '\0';
+
+        /*
+         * Return to the parent directory.  If at a root node, restore
+         * the initial working directory.  If we came through a symlink,
+         * go back through the file descriptor.  Otherwise, move up
+         * one level, via "..".
+         */
+        if (p->fts_level == FTS_ROOTLEVEL) {
+                if (restore_initial_cwd(sp)) {
+                        p->fts_errno = errno;
+                        SET(FTS_STOP);
+                }
+        } else if (p->fts_flags & FTS_SYMFOLLOW) {
+                if (FCHDIR(sp, p->fts_symfd)) {
+                        p->fts_errno = errno;
+                        SET(FTS_STOP);
+                }
+                (void)close(p->fts_symfd);
+        } else if (!(p->fts_flags & FTS_DONTCHDIR) &&
+                   fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
+                p->fts_errno = errno;
+                SET(FTS_STOP);
+        }
+
+        /* If the directory causes a cycle, preserve the FTS_DC flag and keep
+           the corresponding dev/ino pair in the hash table.  It is going to be
+           removed when leaving the original directory.  */
+        if (p->fts_info != FTS_DC) {
+                p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
+                if (p->fts_errno == 0)
+                        LEAVE_DIR (sp, p, "3");
+        }
+        return ISSET(FTS_STOP) ? NULL : p;
+}
+
+/*
+ * Fts_set takes the stream as an argument although it's not used in this
+ * implementation; it would be necessary if anyone wanted to add global
+ * semantics to fts using fts_set.  An error return is allowed for similar
+ * reasons.
+ */
+/* ARGSUSED */
+int
+fts_set(FTS *sp _GL_UNUSED, FTSENT *p, int instr)
+{
+        if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
+            instr != FTS_NOINSTR && instr != FTS_SKIP) {
+                __set_errno (EINVAL);
+                return (1);
+        }
+        p->fts_instr = instr;
+        return (0);
+}
+
+FTSENT *
+fts_children (register FTS *sp, int instr)
+{
+        register FTSENT *p;
+        int fd;
+
+        if (instr != 0 && instr != FTS_NAMEONLY) {
+                __set_errno (EINVAL);
+                return (NULL);
+        }
+
+        /* Set current node pointer. */
+        p = sp->fts_cur;
+
+        /*
+         * Errno set to 0 so user can distinguish empty directory from
+         * an error.
+         */
+        __set_errno (0);
+
+        /* Fatal errors stop here. */
+        if (ISSET(FTS_STOP))
+                return (NULL);
+
+        /* Return logical hierarchy of user's arguments. */
+        if (p->fts_info == FTS_INIT)
+                return (p->fts_link);
+
+        /*
+         * If not a directory being visited in pre-order, stop here.  Could
+         * allow FTS_DNR, assuming the user has fixed the problem, but the
+         * same effect is available with FTS_AGAIN.
+         */
+        if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
+                return (NULL);
+
+        /* Free up any previous child list. */
+        if (sp->fts_child != NULL)
+                fts_lfree(sp->fts_child);
+
+        if (instr == FTS_NAMEONLY) {
+                SET(FTS_NAMEONLY);
+                instr = BNAMES;
+        } else
+                instr = BCHILD;
+
+        /*
+         * If using chdir on a relative file name and called BEFORE fts_read
+         * does its chdir to the root of a traversal, we can lose -- we need to
+         * chdir into the subdirectory, and we don't know where the current
+         * directory is, so we can't get back so that the upcoming chdir by
+         * fts_read will work.
+         */
+        if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
+            ISSET(FTS_NOCHDIR))
+                return (sp->fts_child = fts_build(sp, instr));
+
+        if ((fd = diropen (sp, ".")) < 0)
+                return (sp->fts_child = NULL);
+        sp->fts_child = fts_build(sp, instr);
+        if (ISSET(FTS_CWDFD))
+          {
+            cwd_advance_fd (sp, fd, true);
+          }
+        else
+          {
+            if (fchdir(fd))
+              {
+                int saved_errno = errno;
+                close (fd);
+                __set_errno (saved_errno);
+                return NULL;
+              }
+            close (fd);
+          }
+        return (sp->fts_child);
+}
+
+/* A comparison function to sort on increasing inode number.
+   For some file system types, sorting either way makes a huge
+   performance difference for a directory with very many entries,
+   but sorting on increasing values is slightly better than sorting
+   on decreasing values.  The difference is in the 5% range.  */
+static int
+fts_compare_ino (struct _ftsent const **a, struct _ftsent const **b)
+{
+  return (a[0]->fts_statp->st_ino < b[0]->fts_statp->st_ino ? -1
+          : b[0]->fts_statp->st_ino < a[0]->fts_statp->st_ino ? 1 : 0);
+}
+
+/* Map the dirent.d_type value, DTYPE, to the corresponding stat.st_mode
+   S_IF* bit and set ST.st_mode, thus clearing all other bits in that field.  */
+static void
+set_stat_type (struct stat *st, unsigned int dtype)
+{
+  mode_t type;
+  switch (dtype)
+    {
+    case DT_BLK:
+      type = S_IFBLK;
+      break;
+    case DT_CHR:
+      type = S_IFCHR;
+      break;
+    case DT_DIR:
+      type = S_IFDIR;
+      break;
+    case DT_FIFO:
+      type = S_IFIFO;
+      break;
+    case DT_LNK:
+      type = S_IFLNK;
+      break;
+    case DT_REG:
+      type = S_IFREG;
+      break;
+    case DT_SOCK:
+      type = S_IFSOCK;
+      break;
+    default:
+      type = 0;
+    }
+  st->st_mode = type;
+}
+
+#define closedir_and_clear(dirp)                \
+  do                                            \
+    {                                           \
+      closedir (dirp);                          \
+      dirp = NULL;                              \
+    }                                           \
+  while (0)
+
+#define fts_opendir(file, Pdir_fd)                              \
+        opendirat((! ISSET(FTS_NOCHDIR) && ISSET(FTS_CWDFD)     \
+                   ? sp->fts_cwd_fd : AT_FDCWD),                \
+                  file,                                         \
+                  (((ISSET(FTS_PHYSICAL)                        \
+                     && ! (ISSET(FTS_COMFOLLOW)                 \
+                           && cur->fts_level == FTS_ROOTLEVEL)) \
+                    ? O_NOFOLLOW : 0)                           \
+                   | (ISSET (FTS_NOATIME) ? O_NOATIME : 0)),    \
+                  Pdir_fd)
+
+/*
+ * This is the tricky part -- do not casually change *anything* in here.  The
+ * idea is to build the linked list of entries that are used by fts_children
+ * and fts_read.  There are lots of special cases.
+ *
+ * The real slowdown in walking the tree is the stat calls.  If FTS_NOSTAT is
+ * set and it's a physical walk (so that symbolic links can't be directories),
+ * we can do things quickly.  First, if it's a 4.4BSD file system, the type
+ * of the file is in the directory entry.  Otherwise, we assume that the number
+ * of subdirectories in a node is equal to the number of links to the parent.
+ * The former skips all stat calls.  The latter skips stat calls in any leaf
+ * directories and for any files after the subdirectories in the directory have
+ * been found, cutting the stat calls by about 2/3.
+ */
+static FTSENT *
+internal_function
+fts_build (register FTS *sp, int type)
+{
+        register FTSENT *p, *head;
+        register size_t nitems;
+        FTSENT *tail;
+        void *oldaddr;
+        int saved_errno;
+        bool descend;
+        bool doadjust;
+        ptrdiff_t level;
+        nlink_t nlinks;
+        bool nostat;
+        size_t len, maxlen, new_len;
+        char *cp;
+        int dir_fd;
+        FTSENT *cur = sp->fts_cur;
+        bool continue_readdir = !!cur->fts_dirp;
+        size_t max_entries;
+
+        /* When cur->fts_dirp is non-NULL, that means we should
+           continue calling readdir on that existing DIR* pointer
+           rather than opening a new one.  */
+        if (continue_readdir)
+          {
+            DIR *dp = cur->fts_dirp;
+            dir_fd = dirfd (dp);
+            if (dir_fd < 0)
+              {
+                closedir_and_clear (cur->fts_dirp);
+                if (type == BREAD)
+                  {
+                    cur->fts_info = FTS_DNR;
+                    cur->fts_errno = errno;
+                  }
+                return NULL;
+              }
+          }
+        else
+          {
+            /* Open the directory for reading.  If this fails, we're done.
+               If being called from fts_read, set the fts_info field. */
+            if ((cur->fts_dirp = fts_opendir(cur->fts_accpath, &dir_fd)) == NULL)
+              {
+                if (type == BREAD)
+                  {
+                    cur->fts_info = FTS_DNR;
+                    cur->fts_errno = errno;
+                  }
+                return NULL;
+              }
+            /* Rather than calling fts_stat for each and every entry encountered
+               in the readdir loop (below), stat each directory only right after
+               opening it.  */
+            if (cur->fts_info == FTS_NSOK)
+              cur->fts_info = fts_stat(sp, cur, false);
+            else if (sp->fts_options & FTS_TIGHT_CYCLE_CHECK)
+              {
+                /* Now read the stat info again after opening a directory to
+                   reveal eventual changes caused by a submount triggered by
+                   the traversal.  But do it only for utilities which use
+                   FTS_TIGHT_CYCLE_CHECK.  Therefore, only find and du
+                   benefit/suffer from this feature for now.  */
+                LEAVE_DIR (sp, cur, "4");
+                fts_stat (sp, cur, false);
+                if (! enter_dir (sp, cur))
+                  {
+                    __set_errno (ENOMEM);
+                    return NULL;
+                  }
+              }
+          }
+
+        /* Maximum number of readdir entries to read at one time.  This
+           limitation is to avoid reading millions of entries into memory
+           at once.  When an fts_compar function is specified, we have no
+           choice: we must read all entries into memory before calling that
+           function.  But when no such function is specified, we can read
+           entries in batches that are large enough to help us with inode-
+           sorting, yet not so large that we risk exhausting memory.  */
+        max_entries = sp->fts_compar ? SIZE_MAX : FTS_MAX_READDIR_ENTRIES;
+
+        /*
+         * Nlinks is the number of possible entries of type directory in the
+         * directory if we're cheating on stat calls, 0 if we're not doing
+         * any stat calls at all, (nlink_t) -1 if we're statting everything.
+         */
+        if (type == BNAMES) {
+                nlinks = 0;
+                /* Be quiet about nostat, GCC. */
+                nostat = false;
+        } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
+                nlinks = (cur->fts_statp->st_nlink
+                          - (ISSET(FTS_SEEDOT) ? 0 : 2));
+                nostat = true;
+        } else {
+                nlinks = -1;
+                nostat = false;
+        }
+
+        /*
+         * If we're going to need to stat anything or we want to descend
+         * and stay in the directory, chdir.  If this fails we keep going,
+         * but set a flag so we don't chdir after the post-order visit.
+         * We won't be able to stat anything, but we can still return the
+         * names themselves.  Note, that since fts_read won't be able to
+         * chdir into the directory, it will have to return different file
+         * names than before, i.e. "a/b" instead of "b".  Since the node
+         * has already been visited in pre-order, have to wait until the
+         * post-order visit to return the error.  There is a special case
+         * here, if there was nothing to stat then it's not an error to
+         * not be able to stat.  This is all fairly nasty.  If a program
+         * needed sorted entries or stat information, they had better be
+         * checking FTS_NS on the returned nodes.
+         */
+        if (continue_readdir)
+          {
+            /* When resuming a short readdir run, we already have
+               the required dirp and dir_fd.  */
+            descend = true;
+          }
+        else if (nlinks || type == BREAD) {
+                if (ISSET(FTS_CWDFD))
+                  {
+                    dir_fd = dup (dir_fd);
+                    if (0 <= dir_fd)
+                      set_cloexec_flag (dir_fd, true);
+                  }
+                if (dir_fd < 0 || fts_safe_changedir(sp, cur, dir_fd, NULL)) {
+                        if (nlinks && type == BREAD)
+                                cur->fts_errno = errno;
+                        cur->fts_flags |= FTS_DONTCHDIR;
+                        descend = false;
+                        closedir_and_clear(cur->fts_dirp);
+                        if (ISSET(FTS_CWDFD) && 0 <= dir_fd)
+                                close (dir_fd);
+                        cur->fts_dirp = NULL;
+                } else
+                        descend = true;
+        } else
+                descend = false;
+
+        /*
+         * Figure out the max file name length that can be stored in the
+         * current buffer -- the inner loop allocates more space as necessary.
+         * We really wouldn't have to do the maxlen calculations here, we
+         * could do them in fts_read before returning the name, but it's a
+         * lot easier here since the length is part of the dirent structure.
+         *
+         * If not changing directories set a pointer so that can just append
+         * each new component into the file name.
+         */
+        len = NAPPEND(cur);
+        if (ISSET(FTS_NOCHDIR)) {
+                cp = sp->fts_path + len;
+                *cp++ = '/';
+        } else {
+                /* GCC, you're too verbose. */
+                cp = NULL;
+        }
+        len++;
+        maxlen = sp->fts_pathlen - len;
+
+        level = cur->fts_level + 1;
+
+        /* Read the directory, attaching each entry to the "link" pointer. */
+        doadjust = false;
+        head = NULL;
+        tail = NULL;
+        nitems = 0;
+        while (cur->fts_dirp) {
+                bool is_dir;
+                size_t d_namelen;
+                __set_errno (0);
+                struct dirent *dp = readdir(cur->fts_dirp);
+                if (dp == NULL) {
+                        if (errno) {
+                                cur->fts_errno = errno;
+                                /* If we've not read any items yet, treat
+                                   the error as if we can't access the dir.  */
+                                cur->fts_info = (continue_readdir || nitems)
+                                                ? FTS_ERR : FTS_DNR;
+                        }
+                        break;
+                }
+                if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
+                        continue;
+
+                d_namelen = _D_EXACT_NAMLEN (dp);
+                p = fts_alloc (sp, dp->d_name, d_namelen);
+                if (!p)
+                        goto mem1;
+                if (d_namelen >= maxlen) {
+                        /* include space for NUL */
+                        oldaddr = sp->fts_path;
+                        if (! fts_palloc(sp, d_namelen + len + 1)) {
+                                /*
+                                 * No more memory.  Save
+                                 * errno, free up the current structure and the
+                                 * structures already allocated.
+                                 */
+mem1:                           saved_errno = errno;
+                                free(p);
+                                fts_lfree(head);
+                                closedir_and_clear(cur->fts_dirp);
+                                cur->fts_info = FTS_ERR;
+                                SET(FTS_STOP);
+                                __set_errno (saved_errno);
+                                return (NULL);
+                        }
+                        /* Did realloc() change the pointer? */
+                        if (oldaddr != sp->fts_path) {
+                                doadjust = true;
+                                if (ISSET(FTS_NOCHDIR))
+                                        cp = sp->fts_path + len;
+                        }
+                        maxlen = sp->fts_pathlen - len;
+                }
+
+                new_len = len + d_namelen;
+                if (new_len < len) {
+                        /*
+                         * In the unlikely event that we would end up
+                         * with a file name longer than SIZE_MAX, free up
+                         * the current structure and the structures already
+                         * allocated, then error out with ENAMETOOLONG.
+                         */
+                        free(p);
+                        fts_lfree(head);
+                        closedir_and_clear(cur->fts_dirp);
+                        cur->fts_info = FTS_ERR;
+                        SET(FTS_STOP);
+                        __set_errno (ENAMETOOLONG);
+                        return (NULL);
+                }
+                p->fts_level = level;
+                p->fts_parent = sp->fts_cur;
+                p->fts_pathlen = new_len;
+
+                /* Store dirent.d_ino, in case we need to sort
+                   entries before processing them.  */
+                p->fts_statp->st_ino = D_INO (dp);
+
+                /* Build a file name for fts_stat to stat. */
+                if (ISSET(FTS_NOCHDIR)) {
+                        p->fts_accpath = p->fts_path;
+                        memmove(cp, p->fts_name, p->fts_namelen + 1);
+                } else
+                        p->fts_accpath = p->fts_name;
+
+                if (sp->fts_compar == NULL || ISSET(FTS_DEFER_STAT)) {
+                        /* Record what fts_read will have to do with this
+                           entry. In many cases, it will simply fts_stat it,
+                           but we can take advantage of any d_type information
+                           to optimize away the unnecessary stat calls.  I.e.,
+                           if FTS_NOSTAT is in effect and we're not following
+                           symlinks (FTS_PHYSICAL) and d_type indicates this
+                           is *not* a directory, then we won't have to stat it
+                           at all.  If it *is* a directory, then (currently)
+                           we stat it regardless, in order to get device and
+                           inode numbers.  Some day we might optimize that
+                           away, too, for directories where d_ino is known to
+                           be valid.  */
+                        bool skip_stat = (ISSET(FTS_PHYSICAL)
+                                          && ISSET(FTS_NOSTAT)
+                                          && DT_IS_KNOWN(dp)
+                                          && ! DT_MUST_BE(dp, DT_DIR));
+                        p->fts_info = FTS_NSOK;
+                        /* Propagate dirent.d_type information back
+                           to caller, when possible.  */
+                        set_stat_type (p->fts_statp, D_TYPE (dp));
+                        fts_set_stat_required(p, !skip_stat);
+                        is_dir = (ISSET(FTS_PHYSICAL)
+                                  && DT_MUST_BE(dp, DT_DIR));
+                } else {
+                        p->fts_info = fts_stat(sp, p, false);
+                        is_dir = (p->fts_info == FTS_D
+                                  || p->fts_info == FTS_DC
+                                  || p->fts_info == FTS_DOT);
+                }
+
+                /* Decrement link count if applicable. */
+                if (nlinks > 0 && is_dir)
+                        nlinks -= nostat;
+
+                /* We walk in directory order so "ls -f" doesn't get upset. */
+                p->fts_link = NULL;
+                if (head == NULL)
+                        head = tail = p;
+                else {
+                        tail->fts_link = p;
+                        tail = p;
+                }
+                ++nitems;
+                if (max_entries <= nitems) {
+                        /* When there are too many dir entries, leave
+                           fts_dirp open, so that a subsequent fts_read
+                           can take up where we leave off.  */
+                        goto break_without_closedir;
+                }
+        }
+
+        if (cur->fts_dirp)
+                closedir_and_clear(cur->fts_dirp);
+
+ break_without_closedir:
+
+        /*
+         * If realloc() changed the address of the file name, adjust the
+         * addresses for the rest of the tree and the dir list.
+         */
+        if (doadjust)
+                fts_padjust(sp, head);
+
+        /*
+         * If not changing directories, reset the file name back to original
+         * state.
+         */
+        if (ISSET(FTS_NOCHDIR)) {
+                if (len == sp->fts_pathlen || nitems == 0)
+                        --cp;
+                *cp = '\0';
+        }
+
+        /*
+         * If descended after called from fts_children or after called from
+         * fts_read and nothing found, get back.  At the root level we use
+         * the saved fd; if one of fts_open()'s arguments is a relative name
+         * to an empty directory, we wind up here with no other way back.  If
+         * can't get back, we're done.
+         */
+        if (!continue_readdir && descend && (type == BCHILD || !nitems) &&
+            (cur->fts_level == FTS_ROOTLEVEL
+             ? restore_initial_cwd(sp)
+             : fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
+                cur->fts_info = FTS_ERR;
+                SET(FTS_STOP);
+                fts_lfree(head);
+                return (NULL);
+        }
+
+        /* If didn't find anything, return NULL. */
+        if (!nitems) {
+                if (type == BREAD
+                    && cur->fts_info != FTS_DNR && cur->fts_info != FTS_ERR)
+                        cur->fts_info = FTS_DP;
+                fts_lfree(head);
+                return (NULL);
+        }
+
+        /* If there are many entries, no sorting function has been specified,
+           and this file system is of a type that may be slow with a large
+           number of entries, then sort the directory entries on increasing
+           inode numbers.  */
+        if (nitems > _FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD
+            && !sp->fts_compar
+            && ISSET (FTS_CWDFD)
+            && dirent_inode_sort_may_be_useful (sp->fts_cwd_fd)) {
+                sp->fts_compar = fts_compare_ino;
+                head = fts_sort (sp, head, nitems);
+                sp->fts_compar = NULL;
+        }
+
+        /* Sort the entries. */
+        if (sp->fts_compar && nitems > 1)
+                head = fts_sort(sp, head, nitems);
+        return (head);
+}
+
+#if FTS_DEBUG
+
+/* Walk ->fts_parent links starting at E_CURR, until the root of the
+   current hierarchy.  There should be a directory with dev/inode
+   matching those of AD.  If not, print a lot of diagnostics.  */
+static void
+find_matching_ancestor (FTSENT const *e_curr, struct Active_dir const *ad)
+{
+  FTSENT const *ent;
+  for (ent = e_curr; ent->fts_level >= FTS_ROOTLEVEL; ent = ent->fts_parent)
+    {
+      if (ad->ino == ent->fts_statp->st_ino
+          && ad->dev == ent->fts_statp->st_dev)
+        return;
+    }
+  printf ("ERROR: tree dir, %s, not active\n", ad->fts_ent->fts_accpath);
+  printf ("active dirs:\n");
+  for (ent = e_curr;
+       ent->fts_level >= FTS_ROOTLEVEL; ent = ent->fts_parent)
+    printf ("  %s(%"PRIuMAX"/%"PRIuMAX") to %s(%"PRIuMAX"/%"PRIuMAX")...\n",
+            ad->fts_ent->fts_accpath,
+            (uintmax_t) ad->dev,
+            (uintmax_t) ad->ino,
+            ent->fts_accpath,
+            (uintmax_t) ent->fts_statp->st_dev,
+            (uintmax_t) ent->fts_statp->st_ino);
+}
+
+void
+fts_cross_check (FTS const *sp)
+{
+  FTSENT const *ent = sp->fts_cur;
+  FTSENT const *t;
+  if ( ! ISSET (FTS_TIGHT_CYCLE_CHECK))
+    return;
+
+  Dprintf (("fts-cross-check cur=%s\n", ent->fts_path));
+  /* Make sure every parent dir is in the tree.  */
+  for (t = ent->fts_parent; t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
+    {
+      struct Active_dir ad;
+      ad.ino = t->fts_statp->st_ino;
+      ad.dev = t->fts_statp->st_dev;
+      if ( ! hash_lookup (sp->fts_cycle.ht, &ad))
+        printf ("ERROR: active dir, %s, not in tree\n", t->fts_path);
+    }
+
+  /* Make sure every dir in the tree is an active dir.
+     But ENT is not necessarily a directory.  If so, just skip this part. */
+  if (ent->fts_parent->fts_level >= FTS_ROOTLEVEL
+      && (ent->fts_info == FTS_DP
+          || ent->fts_info == FTS_D))
+    {
+      struct Active_dir *ad;
+      for (ad = hash_get_first (sp->fts_cycle.ht); ad != NULL;
+           ad = hash_get_next (sp->fts_cycle.ht, ad))
+        {
+          find_matching_ancestor (ent, ad);
+        }
+    }
+}
+
+static bool
+same_fd (int fd1, int fd2)
+{
+  struct stat sb1, sb2;
+  return (fstat (fd1, &sb1) == 0
+          && fstat (fd2, &sb2) == 0
+          && SAME_INODE (sb1, sb2));
+}
+
+static void
+fd_ring_print (FTS const *sp, FILE *stream, char const *msg)
+{
+  I_ring const *fd_ring = &sp->fts_fd_ring;
+  unsigned int i = fd_ring->fts_front;
+  char *cwd = getcwdat (sp->fts_cwd_fd, NULL, 0);
+  fprintf (stream, "=== %s ========== %s\n", msg, cwd);
+  free (cwd);
+  if (i_ring_empty (fd_ring))
+    return;
+
+  while (true)
+    {
+      int fd = fd_ring->fts_fd_ring[i];
+      if (fd < 0)
+        fprintf (stream, "%d: %d:\n", i, fd);
+      else
+        {
+          char *wd = getcwdat (fd, NULL, 0);
+          fprintf (stream, "%d: %d: %s\n", i, fd, wd);
+          free (wd);
+        }
+      if (i == fd_ring->fts_back)
+        break;
+      i = (i + I_RING_SIZE - 1) % I_RING_SIZE;
+    }
+}
+
+/* Ensure that each file descriptor on the fd_ring matches a
+   parent, grandparent, etc. of the current working directory.  */
+static void
+fd_ring_check (FTS const *sp)
+{
+  if (!fts_debug)
+    return;
+
+  /* Make a writable copy.  */
+  I_ring fd_w = sp->fts_fd_ring;
+
+  int cwd_fd = sp->fts_cwd_fd;
+  cwd_fd = dup (cwd_fd);
+  char *dot = getcwdat (cwd_fd, NULL, 0);
+  error (0, 0, "===== check ===== cwd: %s", dot);
+  free (dot);
+  while ( ! i_ring_empty (&fd_w))
+    {
+      int fd = i_ring_pop (&fd_w);
+      if (0 <= fd)
+        {
+          int parent_fd = openat (cwd_fd, "..", O_SEARCH | O_NOATIME);
+          if (parent_fd < 0)
+            {
+              // Warn?
+              break;
+            }
+          if (!same_fd (fd, parent_fd))
+            {
+              char *cwd = getcwdat (fd, NULL, 0);
+              error (0, errno, "ring  : %s", cwd);
+              char *c2 = getcwdat (parent_fd, NULL, 0);
+              error (0, errno, "parent: %s", c2);
+              free (cwd);
+              free (c2);
+              fts_assert (0);
+            }
+          close (cwd_fd);
+          cwd_fd = parent_fd;
+        }
+    }
+  close (cwd_fd);
+}
+#endif
+
+static unsigned short int
+internal_function
+fts_stat(FTS *sp, register FTSENT *p, bool follow)
+{
+        struct stat *sbp = p->fts_statp;
+        int saved_errno;
+
+        if (p->fts_level == FTS_ROOTLEVEL && ISSET(FTS_COMFOLLOW))
+                follow = true;
+
+        /*
+         * If doing a logical walk, or application requested FTS_FOLLOW, do
+         * a stat(2).  If that fails, check for a non-existent symlink.  If
+         * fail, set the errno from the stat call.
+         */
+        if (ISSET(FTS_LOGICAL) || follow) {
+                if (stat(p->fts_accpath, sbp)) {
+                        saved_errno = errno;
+                        if (errno == ENOENT
+                            && lstat(p->fts_accpath, sbp) == 0) {
+                                __set_errno (0);
+                                return (FTS_SLNONE);
+                        }
+                        p->fts_errno = saved_errno;
+                        goto err;
+                }
+        } else if (fstatat(sp->fts_cwd_fd, p->fts_accpath, sbp,
+                           AT_SYMLINK_NOFOLLOW)) {
+                p->fts_errno = errno;
+err:            memset(sbp, 0, sizeof(struct stat));
+                return (FTS_NS);
+        }
+
+        if (S_ISDIR(sbp->st_mode)) {
+                p->fts_n_dirs_remaining = (sbp->st_nlink
+                                           - (ISSET(FTS_SEEDOT) ? 0 : 2));
+                if (ISDOT(p->fts_name)) {
+                        /* Command-line "." and ".." are real directories. */
+                        return (p->fts_level == FTS_ROOTLEVEL ? FTS_D : FTS_DOT);
+                }
+
+                return (FTS_D);
+        }
+        if (S_ISLNK(sbp->st_mode))
+                return (FTS_SL);
+        if (S_ISREG(sbp->st_mode))
+                return (FTS_F);
+        return (FTS_DEFAULT);
+}
+
+static int
+fts_compar (void const *a, void const *b)
+{
+  /* Convert A and B to the correct types, to pacify the compiler, and
+     for portability to bizarre hosts where "void const *" and "FTSENT
+     const **" differ in runtime representation.  The comparison
+     function cannot modify *a and *b, but there is no compile-time
+     check for this.  */
+  FTSENT const **pa = (FTSENT const **) a;
+  FTSENT const **pb = (FTSENT const **) b;
+  return pa[0]->fts_fts->fts_compar (pa, pb);
+}
+
+static FTSENT *
+internal_function
+fts_sort (FTS *sp, FTSENT *head, register size_t nitems)
+{
+        register FTSENT **ap, *p;
+
+        /* On most modern hosts, void * and FTSENT ** have the same
+           run-time representation, and one can convert sp->fts_compar to
+           the type qsort expects without problem.  Use the heuristic that
+           this is OK if the two pointer types are the same size, and if
+           converting FTSENT ** to long int is the same as converting
+           FTSENT ** to void * and then to long int.  This heuristic isn't
+           valid in general but we don't know of any counterexamples.  */
+        FTSENT *dummy;
+        int (*compare) (void const *, void const *) =
+          ((sizeof &dummy == sizeof (void *)
+            && (long int) &dummy == (long int) (void *) &dummy)
+           ? (int (*) (void const *, void const *)) sp->fts_compar
+           : fts_compar);
+
+        /*
+         * Construct an array of pointers to the structures and call qsort(3).
+         * Reassemble the array in the order returned by qsort.  If unable to
+         * sort for memory reasons, return the directory entries in their
+         * current order.  Allocate enough space for the current needs plus
+         * 40 so don't realloc one entry at a time.
+         */
+        if (nitems > sp->fts_nitems) {
+                FTSENT **a;
+
+                sp->fts_nitems = nitems + 40;
+                if (SIZE_MAX / sizeof *a < sp->fts_nitems
+                    || ! (a = realloc (sp->fts_array,
+                                       sp->fts_nitems * sizeof *a))) {
+                        free(sp->fts_array);
+                        sp->fts_array = NULL;
+                        sp->fts_nitems = 0;
+                        return (head);
+                }
+                sp->fts_array = a;
+        }
+        for (ap = sp->fts_array, p = head; p; p = p->fts_link)
+                *ap++ = p;
+        qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), compare);
+        for (head = *(ap = sp->fts_array); --nitems; ++ap)
+                ap[0]->fts_link = ap[1];
+        ap[0]->fts_link = NULL;
+        return (head);
+}
+
+static FTSENT *
+internal_function
+fts_alloc (FTS *sp, const char *name, register size_t namelen)
+{
+        register FTSENT *p;
+        size_t len;
+
+        /*
+         * The file name is a variable length array.  Allocate the FTSENT
+         * structure and the file name in one chunk.
+         */
+        len = FLEXSIZEOF(FTSENT, fts_name, namelen + 1);
+        if ((p = malloc(len)) == NULL)
+                return (NULL);
+
+        /* Copy the name and guarantee NUL termination. */
+        memcpy(p->fts_name, name, namelen);
+        p->fts_name[namelen] = '\0';
+
+        p->fts_namelen = namelen;
+        p->fts_fts = sp;
+        p->fts_path = sp->fts_path;
+        p->fts_errno = 0;
+        p->fts_dirp = NULL;
+        p->fts_flags = 0;
+        p->fts_instr = FTS_NOINSTR;
+        p->fts_number = 0;
+        p->fts_pointer = NULL;
+        return (p);
+}
+
+static void
+internal_function
+fts_lfree (register FTSENT *head)
+{
+        register FTSENT *p;
+
+        /* Free a linked list of structures. */
+        while ((p = head)) {
+                head = head->fts_link;
+                if (p->fts_dirp)
+                        closedir (p->fts_dirp);
+                free(p);
+        }
+}
+
+/*
+ * Allow essentially unlimited file name lengths; find, rm, ls should
+ * all work on any tree.  Most systems will allow creation of file
+ * names much longer than MAXPATHLEN, even though the kernel won't
+ * resolve them.  Add the size (not just what's needed) plus 256 bytes
+ * so don't realloc the file name 2 bytes at a time.
+ */
+static bool
+internal_function
+fts_palloc (FTS *sp, size_t more)
+{
+        char *p;
+        size_t new_len = sp->fts_pathlen + more + 256;
+
+        /*
+         * See if fts_pathlen would overflow.
+         */
+        if (new_len < sp->fts_pathlen) {
+                free(sp->fts_path);
+                sp->fts_path = NULL;
+                __set_errno (ENAMETOOLONG);
+                return false;
+        }
+        sp->fts_pathlen = new_len;
+        p = realloc(sp->fts_path, sp->fts_pathlen);
+        if (p == NULL) {
+                free(sp->fts_path);
+                sp->fts_path = NULL;
+                return false;
+        }
+        sp->fts_path = p;
+        return true;
+}
+
+/*
+ * When the file name is realloc'd, have to fix all of the pointers in
+ *  structures already returned.
+ */
+static void
+internal_function
+fts_padjust (FTS *sp, FTSENT *head)
+{
+        FTSENT *p;
+        char *addr = sp->fts_path;
+
+#define ADJUST(p) do {                                                  \
+        if ((p)->fts_accpath != (p)->fts_name) {                        \
+                (p)->fts_accpath =                                      \
+                    (char *)addr + ((p)->fts_accpath - (p)->fts_path);  \
+        }                                                               \
+        (p)->fts_path = addr;                                           \
+} while (0)
+        /* Adjust the current set of children. */
+        for (p = sp->fts_child; p; p = p->fts_link)
+                ADJUST(p);
+
+        /* Adjust the rest of the tree, including the current level. */
+        for (p = head; p->fts_level >= FTS_ROOTLEVEL;) {
+                ADJUST(p);
+                p = p->fts_link ? p->fts_link : p->fts_parent;
+        }
+}
+
+static size_t
+internal_function _GL_ATTRIBUTE_PURE
+fts_maxarglen (char * const *argv)
+{
+        size_t len, max;
+
+        for (max = 0; *argv; ++argv)
+                if ((len = strlen(*argv)) > max)
+                        max = len;
+        return (max + 1);
+}
+
+/*
+ * Change to dir specified by fd or file name without getting
+ * tricked by someone changing the world out from underneath us.
+ * Assumes p->fts_statp->st_dev and p->fts_statp->st_ino are filled in.
+ * If FD is non-negative, expect it to be used after this function returns,
+ * and to be closed eventually.  So don't pass e.g., 'dirfd(dirp)' and then
+ * do closedir(dirp), because that would invalidate the saved FD.
+ * Upon failure, close FD immediately and return nonzero.
+ */
+static int
+internal_function
+fts_safe_changedir (FTS *sp, FTSENT *p, int fd, char const *dir)
+{
+        int ret;
+        bool is_dotdot = dir && STREQ (dir, "..");
+        int newfd;
+
+        /* This clause handles the unusual case in which FTS_NOCHDIR
+           is specified, along with FTS_CWDFD.  In that case, there is
+           no need to change even the virtual cwd file descriptor.
+           However, if FD is non-negative, we do close it here.  */
+        if (ISSET (FTS_NOCHDIR))
+          {
+            if (ISSET (FTS_CWDFD) && 0 <= fd)
+              close (fd);
+            return 0;
+          }
+
+        if (fd < 0 && is_dotdot && ISSET (FTS_CWDFD))
+          {
+            /* When possible, skip the diropen and subsequent fstat+dev/ino
+               comparison.  I.e., when changing to parent directory
+               (chdir ("..")), use a file descriptor from the ring and
+               save the overhead of diropen+fstat, as well as avoiding
+               failure when we lack "x" access to the virtual cwd.  */
+            if ( ! i_ring_empty (&sp->fts_fd_ring))
+              {
+                int parent_fd;
+                fd_ring_print (sp, stderr, "pre-pop");
+                parent_fd = i_ring_pop (&sp->fts_fd_ring);
+                is_dotdot = true;
+                if (0 <= parent_fd)
+                  {
+                    fd = parent_fd;
+                    dir = NULL;
+                  }
+              }
+          }
+
+        newfd = fd;
+        if (fd < 0 && (newfd = diropen (sp, dir)) < 0)
+          return -1;
+
+        /* The following dev/inode check is necessary if we're doing a
+           "logical" traversal (through symlinks, a la chown -L), if the
+           system lacks O_NOFOLLOW support, or if we're changing to ".."
+           (but not via a popped file descriptor).  When changing to the
+           name "..", O_NOFOLLOW can't help.  In general, when the target is
+           not "..", diropen's use of O_NOFOLLOW ensures we don't mistakenly
+           follow a symlink, so we can avoid the expense of this fstat.  */
+        if (ISSET(FTS_LOGICAL) || ! HAVE_WORKING_O_NOFOLLOW
+            || (dir && STREQ (dir, "..")))
+          {
+            struct stat sb;
+            if (fstat(newfd, &sb))
+              {
+                ret = -1;
+                goto bail;
+              }
+            if (p->fts_statp->st_dev != sb.st_dev
+                || p->fts_statp->st_ino != sb.st_ino)
+              {
+                __set_errno (ENOENT);           /* disinformation */
+                ret = -1;
+                goto bail;
+              }
+          }
+
+        if (ISSET(FTS_CWDFD))
+          {
+            cwd_advance_fd (sp, newfd, ! is_dotdot);
+            return 0;
+          }
+
+        ret = fchdir(newfd);
+bail:
+        if (fd < 0)
+          {
+            int oerrno = errno;
+            (void)close(newfd);
+            __set_errno (oerrno);
+          }
+        return ret;
+}
diff --git a/libgnu/fts_.h b/libgnu/fts_.h
new file mode 100644
index 0000000..46fd0df
--- /dev/null
+++ b/libgnu/fts_.h
@@ -0,0 +1,282 @@
+/* Traverse a file hierarchy.
+
+   Copyright (C) 2004-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/*
+ * Copyright (c) 1989, 1993
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *      @(#)fts.h       8.3 (Berkeley) 8/14/94
+ */
+
+#ifndef _FTS_H
+# define _FTS_H 1
+
+# ifdef _LIBC
+#  include <features.h>
+#  if __STDC_VERSION__ < 199901L
+#   define __FLEXIBLE_ARRAY_MEMBER 1
+#  else
+#   define __FLEXIBLE_ARRAY_MEMBER
+#  endif
+# else
+#  define __FLEXIBLE_ARRAY_MEMBER FLEXIBLE_ARRAY_MEMBER
+#  undef __THROW
+#  define __THROW
+#  undef __BEGIN_DECLS
+#  undef __END_DECLS
+#  ifdef __cplusplus
+#   define __BEGIN_DECLS extern "C" {
+#   define __END_DECLS }
+#  else
+#   define __BEGIN_DECLS
+#   define __END_DECLS
+#  endif
+# endif
+
+# include <stddef.h>
+# include <sys/types.h>
+# include <dirent.h>
+# include <sys/stat.h>
+# include "i-ring.h"
+
+typedef struct {
+        struct _ftsent *fts_cur;        /* current node */
+        struct _ftsent *fts_child;      /* linked list of children */
+        struct _ftsent **fts_array;     /* sort array */
+        dev_t fts_dev;                  /* starting device # */
+        char *fts_path;                 /* file name for this descent */
+        int fts_rfd;                    /* fd for root */
+        int fts_cwd_fd;                 /* the file descriptor on which the
+                                           virtual cwd is open, or AT_FDCWD */
+        size_t fts_pathlen;             /* sizeof(path) */
+        size_t fts_nitems;              /* elements in the sort array */
+        int (*fts_compar) (struct _ftsent const **, struct _ftsent const **);
+                                        /* compare fn */
+
+# define FTS_COMFOLLOW  0x0001          /* follow command line symlinks */
+# define FTS_LOGICAL    0x0002          /* logical walk */
+# define FTS_NOCHDIR    0x0004          /* don't change directories */
+# define FTS_NOSTAT     0x0008          /* don't get stat info */
+# define FTS_PHYSICAL   0x0010          /* physical walk */
+# define FTS_SEEDOT     0x0020          /* return dot and dot-dot */
+# define FTS_XDEV       0x0040          /* don't cross devices */
+# define FTS_WHITEOUT   0x0080          /* return whiteout information */
+
+  /* There are two ways to detect cycles.
+     The lazy way (which works only with FTS_PHYSICAL),
+     with which one may process a directory that is a
+     part of the cycle several times before detecting the cycle.
+     The "tight" way, whereby fts uses more memory (proportional
+     to number of "active" directories, aka distance from root
+     of current tree to current directory -- see active_dir_ht)
+     to detect any cycle right away.  For example, du must use
+     this option to avoid counting disk space in a cycle multiple
+     times, but chown -R need not.
+     The default is to use the constant-memory lazy way, when possible
+     (see below).
+
+     However, with FTS_LOGICAL (when following symlinks, e.g., chown -L)
+     using lazy cycle detection is inadequate.  For example, traversing
+     a directory containing a symbolic link to a peer directory, it is
+     possible to encounter the same directory twice even though there
+     is no cycle:
+     dir
+     ...
+     slink -> dir
+     So, when FTS_LOGICAL is selected, we have to use a different
+     mode of cycle detection: FTS_TIGHT_CYCLE_CHECK.  */
+# define FTS_TIGHT_CYCLE_CHECK  0x0100
+
+  /* Use this flag to enable semantics with which the parent
+     application may be made both more efficient and more robust.
+     Whereas the default is to visit each directory in a recursive
+     traversal (via chdir), using this flag makes it so the initial
+     working directory is never changed.  Instead, these functions
+     perform the traversal via a virtual working directory, maintained
+     through the file descriptor member, fts_cwd_fd.  */
+# define FTS_CWDFD              0x0200
+
+  /* Historically, for each directory that fts initially encounters, it would
+     open it, read all entries, and stat each entry, storing the results, and
+     then it would process the first entry.  But that behavior is bad for
+     locality of reference, and also causes trouble with inode-simulating
+     file systems like FAT, CIFS, FUSE-based ones, etc., when entries from
+     their name/inode cache are flushed too early.
+     Use this flag to make fts_open and fts_read defer the stat/lstat/fststat
+     of each entry until it is actually processed.  However, note that if you
+     use this option and also specify a comparison function, that function may
+     not examine any data via fts_statp.  However, when fts_statp->st_mode is
+     nonzero, the S_IFMT type bits are valid, with mapped dirent.d_type data.
+     Of course, that happens only on file systems that provide useful
+     dirent.d_type data.  */
+# define FTS_DEFER_STAT         0x0400
+
+# define FTS_NOATIME    0x0800          /* use O_NOATIME during traversal */
+
+  /* Use this flag to disable stripping of trailing slashes
+     from input path names during fts_open initialization.  */
+# define FTS_VERBATIM   0x1000
+
+# define FTS_OPTIONMASK 0x1fff          /* valid user option mask */
+
+# define FTS_NAMEONLY   0x2000          /* (private) child names only */
+# define FTS_STOP       0x4000          /* (private) unrecoverable error */
+        int fts_options;                /* fts_open options, global flags */
+
+        /* Map a directory's device number to a boolean.  The boolean is
+           true if for that file system (type determined by a single fstatfs
+           call per FS) st_nlink can be used to calculate the number of
+           sub-directory entries in a directory.
+           Using this table is an optimization that permits us to look up
+           file system type on a per-inode basis at the minimal cost of
+           calling fstatfs only once per traversed device.  */
+        struct hash_table *fts_leaf_optimization_works_ht;
+
+        union {
+                /* This data structure is used if FTS_TIGHT_CYCLE_CHECK is
+                   specified.  It records the directories between a starting
+                   point and the current directory.  I.e., a directory is
+                   recorded here IFF we have visited it once, but we have not
+                   yet completed processing of all its entries.  Every time we
+                   visit a new directory, we add that directory to this set.
+                   When we finish with a directory (usually by visiting it a
+                   second time), we remove it from this set.  Each entry in
+                   this data structure is a device/inode pair.  This data
+                   structure is used to detect directory cycles efficiently and
+                   promptly even when the depth of a hierarchy is in the tens
+                   of thousands.  */
+                struct hash_table *ht;
+
+                /* FIXME: rename these two members to have the fts_ prefix */
+                /* This data structure uses a lazy cycle-detection algorithm,
+                   as done by rm via cycle-check.c.  It's the default,
+                   but it's not appropriate for programs like du.  */
+                struct cycle_check_state *state;
+        } fts_cycle;
+
+        /* A stack of the file descriptors corresponding to the
+           most-recently traversed parent directories.
+           Currently used only in FTS_CWDFD mode.  */
+        I_ring fts_fd_ring;
+} FTS;
+
+typedef struct _ftsent {
+        struct _ftsent *fts_cycle;      /* cycle node */
+        struct _ftsent *fts_parent;     /* parent directory */
+        struct _ftsent *fts_link;       /* next file in directory */
+        DIR *fts_dirp;                  /* Dir pointer for any directory
+                                           containing more entries than we
+                                           read at one time.  */
+        long fts_number;                /* local numeric value */
+        void *fts_pointer;              /* local address value */
+        char *fts_accpath;              /* access file name */
+        char *fts_path;                 /* root name; == fts_fts->fts_path */
+        int fts_errno;                  /* errno for this node */
+        int fts_symfd;                  /* fd for symlink */
+        size_t fts_pathlen;             /* strlen(fts_path) */
+
+        FTS *fts_fts;                   /* the file hierarchy itself */
+
+# define FTS_ROOTPARENTLEVEL    (-1)
+# define FTS_ROOTLEVEL           0
+        ptrdiff_t fts_level;            /* depth (-1 to N) */
+
+        size_t fts_namelen;             /* strlen(fts_name) */
+        nlink_t fts_n_dirs_remaining;   /* count down from st_nlink */
+
+# define FTS_D           1              /* preorder directory */
+# define FTS_DC          2              /* directory that causes cycles */
+# define FTS_DEFAULT     3              /* none of the above */
+# define FTS_DNR         4              /* unreadable directory */
+# define FTS_DOT         5              /* dot or dot-dot */
+# define FTS_DP          6              /* postorder directory */
+# define FTS_ERR         7              /* error; errno is set */
+# define FTS_F           8              /* regular file */
+# define FTS_INIT        9              /* initialized only */
+# define FTS_NS         10              /* stat(2) failed */
+# define FTS_NSOK       11              /* no stat(2) requested */
+# define FTS_SL         12              /* symbolic link */
+# define FTS_SLNONE     13              /* symbolic link without target */
+# define FTS_W          14              /* whiteout object */
+        unsigned short int fts_info;    /* user flags for FTSENT structure */
+
+# define FTS_DONTCHDIR   0x01           /* don't chdir .. to the parent */
+# define FTS_SYMFOLLOW   0x02           /* followed a symlink to get here */
+        unsigned short int fts_flags;   /* private flags for FTSENT structure */
+
+# define FTS_AGAIN       1              /* read node again */
+# define FTS_FOLLOW      2              /* follow symbolic link */
+# define FTS_NOINSTR     3              /* no instructions */
+# define FTS_SKIP        4              /* discard node */
+        unsigned short int fts_instr;   /* fts_set() instructions */
+
+        struct stat fts_statp[1];       /* stat(2) information */
+        char fts_name[__FLEXIBLE_ARRAY_MEMBER]; /* file name */
+} FTSENT;
+
+#ifndef __GNUC_PREREQ
+# if defined __GNUC__ && defined __GNUC_MINOR__
+#  define __GNUC_PREREQ(maj, min) \
+         ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+# else
+#  define __GNUC_PREREQ(maj, min) 0
+# endif
+#endif
+
+#if __GNUC_PREREQ (3,4)
+# undef __attribute_warn_unused_result__
+# define __attribute_warn_unused_result__ \
+   __attribute__ ((__warn_unused_result__))
+#else
+# define __attribute_warn_unused_result__ /* empty */
+#endif
+
+__BEGIN_DECLS
+FTSENT  *fts_children (FTS *, int) __THROW __attribute_warn_unused_result__;
+int      fts_close (FTS *) __THROW __attribute_warn_unused_result__;
+FTS     *fts_open (char * const *, int,
+                   int (*)(const FTSENT **, const FTSENT **))
+  __THROW __attribute_warn_unused_result__;
+FTSENT  *fts_read (FTS *) __THROW __attribute_warn_unused_result__;
+int      fts_set (FTS *, FTSENT *, int) __THROW;
+__END_DECLS
+
+#endif /* fts.h */
diff --git a/libgnu/getcwd-lgpl.c b/libgnu/getcwd-lgpl.c
new file mode 100644
index 0000000..34603c1
--- /dev/null
+++ b/libgnu/getcwd-lgpl.c
@@ -0,0 +1,126 @@
+/* Copyright (C) 2011-2017 Free Software Foundation, Inc.
+   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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification */
+#include <unistd.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if GNULIB_GETCWD
+/* Favor GPL getcwd.c if both getcwd and getcwd-lgpl modules are in use.  */
+typedef int dummy;
+#else
+
+/* 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
+   (perhaps because the absolute name was longer than PATH_MAX, or
+   because of missing read/search permissions on parent directories)
+   or SIZE was too small.  If successful, returns BUF.  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.  */
+
+# undef getcwd
+char *
+rpl_getcwd (char *buf, size_t size)
+{
+  char *ptr;
+  char *result;
+
+  /* Handle single size operations.  */
+  if (buf)
+    {
+      if (!size)
+        {
+          errno = EINVAL;
+          return NULL;
+        }
+      return getcwd (buf, size);
+    }
+
+  if (size)
+    {
+      buf = malloc (size);
+      if (!buf)
+        {
+          errno = ENOMEM;
+          return NULL;
+        }
+      result = getcwd (buf, size);
+      if (!result)
+        {
+          int saved_errno = errno;
+          free (buf);
+          errno = saved_errno;
+        }
+      return result;
+    }
+
+  /* Flexible sizing requested.  Avoid over-allocation for the common
+     case of a name that fits within a 4k page, minus some space for
+     local variables, to be sure we don't skip over a guard page.  */
+  {
+    char tmp[4032];
+    size = sizeof tmp;
+    ptr = getcwd (tmp, size);
+    if (ptr)
+      {
+        result = strdup (ptr);
+        if (!result)
+          errno = ENOMEM;
+        return result;
+      }
+    if (errno != ERANGE)
+      return NULL;
+  }
+
+  /* My what a large directory name we have.  */
+  do
+    {
+      size <<= 1;
+      ptr = realloc (buf, size);
+      if (ptr == NULL)
+        {
+          free (buf);
+          errno = ENOMEM;
+          return NULL;
+        }
+      buf = ptr;
+      result = getcwd (buf, size);
+    }
+  while (!result && errno == ERANGE);
+
+  if (!result)
+    {
+      int saved_errno = errno;
+      free (buf);
+      errno = saved_errno;
+    }
+  else
+    {
+      /* Trim to fit, if possible.  */
+      result = realloc (buf, strlen (buf) + 1);
+      if (!result)
+        result = buf;
+    }
+  return result;
+}
+
+#endif
diff --git a/libgnu/getcwd.c b/libgnu/getcwd.c
new file mode 100644
index 0000000..d91cf37
--- /dev/null
+++ b/libgnu/getcwd.c
@@ -0,0 +1,446 @@
+/* Copyright (C) 1991-1999, 2004-2017 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#if !_LIBC
+# include <config.h>
+# include <unistd.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.  */
+
+/* If this host provides the openat function or if we're using the
+   gnulib replacement function with a native fdopendir, then enable
+   code below to make getcwd more efficient and robust.  */
+#if defined HAVE_OPENAT || (defined GNULIB_OPENAT && defined HAVE_FDOPENDIR)
+# define HAVE_OPENAT_SUPPORT 1
+#else
+# define HAVE_OPENAT_SUPPORT 0
+#endif
+
+#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
+
+#ifndef MAX
+# define MAX(a, b) ((a) < (b) ? (b) : (a))
+#endif
+#ifndef MIN
+# define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#include "pathmax.h"
+
+/* In this file, PATH_MAX only serves as a threshold for choosing among two
+   algorithms.  */
+#ifndef PATH_MAX
+# define PATH_MAX 8192
+#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 rpl_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,
+   and we do not leak fds to any single-threaded code that could use stdio,
+   therefore save some unnecessary recursion in fchdir.c.
+   FIXME - if the kernel ever adds support for multi-thread safety for
+   avoiding standard fds, then we should use opendir_safer and
+   openat_safer.  */
+#ifdef GNULIB_defined_opendir
+# undef opendir
+#endif
+#ifdef GNULIB_defined_closedir
+# undef closedir
+#endif
+
+/* 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
+    };
+
+#if HAVE_OPENAT_SUPPORT
+  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_MINIMALLY_WORKING_GETCWD
+  /* 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.
+
+     But on AIX 5.1..7.1, the system getcwd is not even minimally
+     working: If the current directory name is slightly longer than
+     PATH_MAX, it omits the first directory component and returns
+     this wrong result with errno = 0.  */
+
+# undef getcwd
+  dir = getcwd (buf, size);
+  if (dir || (size && errno == ERANGE))
+    return dir;
+
+  /* Solaris getcwd (NULL, 0) fails with errno == EINVAL, but it has
+     internal magic that lets it work even if an ancestor directory is
+     inaccessible, which is better in many cases.  So in this case try
+     again with a buffer that's almost always big enough.  */
+  if (errno == EINVAL && buf == NULL && size == 0)
+    {
+      char big_buffer[BIG_FILE_NAME_LENGTH + 1];
+      dir = getcwd (big_buffer, sizeof big_buffer);
+      if (dir)
+        return strdup (dir);
+    }
+
+# 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 (errno != ERANGE && errno != ENAMETOOLONG && errno != ENOENT)
+    return NULL;
+# endif
+#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.  */
+#if HAVE_OPENAT_SUPPORT
+      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.  */
+#if HAVE_OPENAT_SUPPORT
+      dirstream = fdopendir (fd);
+      if (dirstream == NULL)
+        goto lose;
+      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;
+#if HAVE_OPENAT_SUPPORT
+            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 = '/';
+
+#if ! HAVE_OPENAT_SUPPORT
+  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);
+#if HAVE_OPENAT_SUPPORT
+    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/libgnu/getdelim.c b/libgnu/getdelim.c
new file mode 100644
index 0000000..e2e0885
--- /dev/null
+++ b/libgnu/getdelim.c
@@ -0,0 +1,147 @@
+/* getdelim.c --- Implementation of replacement getdelim function.
+   Copyright (C) 1994, 1996-1998, 2001, 2003, 2005-2017 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 version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+/* Ported from glibc by Simon Josefsson. */
+
+/* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
+   optimizes away the lineptr == NULL || n == NULL || fp == NULL tests below.  */
+#define _GL_ARG_NONNULL(params)
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#ifndef SSIZE_MAX
+# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
+#endif
+
+#if USE_UNLOCKED_IO
+# include "unlocked-io.h"
+# define getc_maybe_unlocked(fp)        getc(fp)
+#elif !HAVE_FLOCKFILE || !HAVE_FUNLOCKFILE || !HAVE_DECL_GETC_UNLOCKED
+# undef flockfile
+# undef funlockfile
+# define flockfile(x) ((void) 0)
+# define funlockfile(x) ((void) 0)
+# define getc_maybe_unlocked(fp)        getc(fp)
+#else
+# define getc_maybe_unlocked(fp)        getc_unlocked(fp)
+#endif
+
+static void
+alloc_failed (void)
+{
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+  /* Avoid errno problem without using the realloc module; see:
+     http://lists.gnu.org/archive/html/bug-gnulib/2016-08/msg00025.html  */
+  errno = ENOMEM;
+#endif
+}
+
+/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and
+   NUL-terminate it).  *LINEPTR is a pointer returned from malloc (or
+   NULL), pointing to *N characters of space.  It is realloc'ed as
+   necessary.  Returns the number of characters read (not including
+   the null terminator), or -1 on error or EOF.  */
+
+ssize_t
+getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
+{
+  ssize_t result;
+  size_t cur_len = 0;
+
+  if (lineptr == NULL || n == NULL || fp == NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  flockfile (fp);
+
+  if (*lineptr == NULL || *n == 0)
+    {
+      char *new_lineptr;
+      *n = 120;
+      new_lineptr = (char *) realloc (*lineptr, *n);
+      if (new_lineptr == NULL)
+        {
+          alloc_failed ();
+          result = -1;
+          goto unlock_return;
+        }
+      *lineptr = new_lineptr;
+    }
+
+  for (;;)
+    {
+      int i;
+
+      i = getc_maybe_unlocked (fp);
+      if (i == EOF)
+        {
+          result = -1;
+          break;
+        }
+
+      /* Make enough space for len+1 (for final NUL) bytes.  */
+      if (cur_len + 1 >= *n)
+        {
+          size_t needed_max =
+            SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
+          size_t needed = 2 * *n + 1;   /* Be generous. */
+          char *new_lineptr;
+
+          if (needed_max < needed)
+            needed = needed_max;
+          if (cur_len + 1 >= needed)
+            {
+              result = -1;
+              errno = EOVERFLOW;
+              goto unlock_return;
+            }
+
+          new_lineptr = (char *) realloc (*lineptr, needed);
+          if (new_lineptr == NULL)
+            {
+              alloc_failed ();
+              result = -1;
+              goto unlock_return;
+            }
+
+          *lineptr = new_lineptr;
+          *n = needed;
+        }
+
+      (*lineptr)[cur_len] = i;
+      cur_len++;
+
+      if (i == delimiter)
+        break;
+    }
+  (*lineptr)[cur_len] = '\0';
+  result = cur_len ? cur_len : result;
+
+ unlock_return:
+  funlockfile (fp); /* doesn't set errno */
+
+  return result;
+}
diff --git a/libgnu/getdtablesize.c b/libgnu/getdtablesize.c
new file mode 100644
index 0000000..7fabb51
--- /dev/null
+++ b/libgnu/getdtablesize.c
@@ -0,0 +1,121 @@
+/* getdtablesize() function for platforms that don't have it.
+   Copyright (C) 2008-2017 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2008.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+# include <stdio.h>
+
+# include "msvc-inval.h"
+
+# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
+static int
+_setmaxstdio_nothrow (int newmax)
+{
+  int result;
+
+  TRY_MSVC_INVAL
+    {
+      result = _setmaxstdio (newmax);
+    }
+  CATCH_MSVC_INVAL
+    {
+      result = -1;
+    }
+  DONE_MSVC_INVAL;
+
+  return result;
+}
+#  define _setmaxstdio _setmaxstdio_nothrow
+# endif
+
+/* Cache for the previous getdtablesize () result.  Safe to cache because
+   Windows also lacks setrlimit.  */
+static int dtablesize;
+
+int
+getdtablesize (void)
+{
+  if (dtablesize == 0)
+    {
+      /* We are looking for the number N such that the valid file descriptors
+         are 0..N-1.  It can be obtained through a loop as follows:
+           {
+             int fd;
+             for (fd = 3; fd < 65536; fd++)
+               if (dup2 (0, fd) == -1)
+                 break;
+             return fd;
+           }
+         On Windows XP, the result is 2048.
+         The drawback of this loop is that it allocates memory for a libc
+         internal array that is never freed.
+
+         The number N can also be obtained as the upper bound for
+         _getmaxstdio ().  _getmaxstdio () returns the maximum number of open
+         FILE objects.  The sanity check in _setmaxstdio reveals the maximum
+         number of file descriptors.  This too allocates memory, but it is
+         freed when we call _setmaxstdio with the original value.  */
+      int orig_max_stdio = _getmaxstdio ();
+      unsigned int bound;
+      for (bound = 0x10000; _setmaxstdio (bound) < 0; bound = bound / 2)
+        ;
+      _setmaxstdio (orig_max_stdio);
+      dtablesize = bound;
+    }
+  return dtablesize;
+}
+
+#else
+
+# include <limits.h>
+# include <sys/resource.h>
+
+# ifndef RLIM_SAVED_CUR
+#  define RLIM_SAVED_CUR RLIM_INFINITY
+# endif
+# ifndef RLIM_SAVED_MAX
+#  define RLIM_SAVED_MAX RLIM_INFINITY
+# endif
+
+# ifdef __CYGWIN__
+  /* Cygwin 1.7.25 auto-increases the RLIMIT_NOFILE soft limit until it
+     hits the compile-time constant hard limit of 3200.  We might as
+     well just report the hard limit.  */
+#  define rlim_cur rlim_max
+# endif
+
+int
+getdtablesize (void)
+{
+  struct rlimit lim;
+
+  if (getrlimit (RLIMIT_NOFILE, &lim) == 0
+      && 0 <= lim.rlim_cur && lim.rlim_cur <= INT_MAX
+      && lim.rlim_cur != RLIM_INFINITY
+      && lim.rlim_cur != RLIM_SAVED_CUR
+      && lim.rlim_cur != RLIM_SAVED_MAX)
+    return lim.rlim_cur;
+
+  return INT_MAX;
+}
+
+#endif
diff --git a/libgnu/getline.c b/libgnu/getline.c
new file mode 100644
index 0000000..8b7c9f7
--- /dev/null
+++ b/libgnu/getline.c
@@ -0,0 +1,27 @@
+/* getline.c --- Implementation of replacement getline function.
+   Copyright (C) 2005-2007, 2009-2017 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 version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Simon Josefsson. */
+
+#include <config.h>
+
+#include <stdio.h>
+
+ssize_t
+getline (char **lineptr, size_t *n, FILE *stream)
+{
+  return getdelim (lineptr, n, '\n', stream);
+}
diff --git a/libgnu/getopt-cdefs.in.h b/libgnu/getopt-cdefs.in.h
new file mode 100644
index 0000000..c71a4f1
--- /dev/null
+++ b/libgnu/getopt-cdefs.in.h
@@ -0,0 +1,67 @@
+/* getopt-on-non-glibc compatibility macros.
+   Copyright (C) 1989-2017 Free Software Foundation, Inc.
+   This file is part of gnulib.
+   Unlike most of the getopt implementation, it is NOT shared
+   with the GNU C Library.
+
+   gnulib is free software; you can 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.
+
+   gnulib is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with gnulib; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _GETOPT_CDEFS_H
+#define _GETOPT_CDEFS_H 1
+
+/* This header should not be used directly; include getopt.h or
+   unistd.h instead.  It does not have a protective #error, because
+   the guard macro for getopt.h in gnulib is not fixed.  */
+
+/* getopt-core.h and getopt-ext.h are shared with GNU libc, and expect
+   a number of the internal macros supplied to GNU libc's headers by
+   sys/cdefs.h.  Provide fallback definitions for all of them.  */
+#if @HAVE_SYS_CDEFS_H@
+# include <sys/cdefs.h>
+#endif
+
+#ifndef __BEGIN_DECLS
+# ifdef __cplusplus
+#  define __BEGIN_DECLS extern "C" {
+# else
+#  define __BEGIN_DECLS /* nothing */
+# endif
+#endif
+#ifndef __END_DECLS
+# ifdef __cplusplus
+#  define __END_DECLS }
+# else
+#  define __END_DECLS /* nothing */
+# endif
+#endif
+
+#ifndef __GNUC_PREREQ
+# if defined __GNUC__ && defined __GNUC_VERSION__
+# define __GNUC_PREREQ(maj, min) \
+        ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+# else
+#  define __GNUC_PREREQ(maj, min) 0
+# endif
+#endif
+
+#ifndef __THROW
+# if defined __cplusplus && __GNUC_PREREQ (2,8)
+#  define __THROW       throw ()
+# else
+#  define __THROW
+# endif
+#endif
+
+#endif /* _GETOPT_CDEFS_H */
diff --git a/libgnu/getopt-core.h b/libgnu/getopt-core.h
new file mode 100644
index 0000000..d315891
--- /dev/null
+++ b/libgnu/getopt-core.h
@@ -0,0 +1,96 @@
+/* Declarations for getopt (basic, portable features only).
+   Copyright (C) 1989-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library and is also part of gnulib.
+   Patches to this file should be submitted to both projects.
+
+   The GNU C Library is free software; you can 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.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _GETOPT_CORE_H
+#define _GETOPT_CORE_H 1
+
+/* This header should not be used directly; include getopt.h or
+   unistd.h instead.  Unlike most bits headers, it does not have
+   a protective #error, because the guard macro for getopt.h in
+   gnulib is not fixed.  */
+
+__BEGIN_DECLS
+
+/* 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;
+
+/* 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.
+
+   For standards compliance, the 'argv' argument has the type
+   char *const *, but this is inaccurate; if argument permutation is
+   enabled, the argv array (not the strings it points to) must be
+   writable.  */
+
+extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
+       __THROW _GL_ARG_NONNULL ((2, 3));
+
+__END_DECLS
+
+#endif /* _GETOPT_CORE_H */
diff --git a/libgnu/getopt-ext.h b/libgnu/getopt-ext.h
new file mode 100644
index 0000000..e4da22f
--- /dev/null
+++ b/libgnu/getopt-ext.h
@@ -0,0 +1,77 @@
+/* Declarations for getopt (GNU extensions).
+   Copyright (C) 1989-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library and is also part of gnulib.
+   Patches to this file should be submitted to both projects.
+
+   The GNU C Library is free software; you can 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.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _GETOPT_EXT_H
+#define _GETOPT_EXT_H 1
+
+/* This header should not be used directly; include getopt.h instead.
+   Unlike most bits headers, it does not have a protective #error,
+   because the guard macro for getopt.h in gnulib is not fixed.  */
+
+__BEGIN_DECLS
+
+/* 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
+
+extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv,
+			const char *__shortopts,
+		        const struct option *__longopts, int *__longind)
+       __THROW _GL_ARG_NONNULL ((2, 3));
+extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv,
+			     const char *__shortopts,
+		             const struct option *__longopts, int *__longind)
+       __THROW _GL_ARG_NONNULL ((2, 3));
+
+__END_DECLS
+
+#endif /* _GETOPT_EXT_H */
diff --git a/libgnu/getopt-pfx-core.h b/libgnu/getopt-pfx-core.h
new file mode 100644
index 0000000..4dc427d
--- /dev/null
+++ b/libgnu/getopt-pfx-core.h
@@ -0,0 +1,54 @@
+/* getopt (basic, portable features) gnulib wrapper header.
+   Copyright (C) 1989-2017 Free Software Foundation, Inc.
+   This file is part of gnulib.
+   Unlike most of the getopt implementation, it is NOT shared
+   with the GNU C Library.
+
+   gnulib is free software; you can 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.
+
+   gnulib is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with gnulib; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _GETOPT_PFX_CORE_H
+#define _GETOPT_PFX_CORE_H 1
+
+/* This header should not be used directly; include getopt.h or
+   unistd.h instead.  It does not have a protective #error, because
+   the guard macro for getopt.h in gnulib is not fixed.  */
+
+/* Standalone applications should #define __GETOPT_PREFIX to an
+   identifier that prefixes the external functions and variables
+   defined in getopt-core.h and getopt-ext.h.  Systematically
+   rename identifiers so that they do not collide with the system
+   functions and variables.  Renaming avoids problems with some
+   compilers and linkers.  */
+#ifdef __GETOPT_PREFIX
+# ifndef __GETOPT_ID
+#  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)
+# endif
+# undef getopt
+# undef optarg
+# undef opterr
+# undef optind
+# undef optopt
+# define getopt __GETOPT_ID (getopt)
+# define optarg __GETOPT_ID (optarg)
+# define opterr __GETOPT_ID (opterr)
+# define optind __GETOPT_ID (optind)
+# define optopt __GETOPT_ID (optopt)
+#endif
+
+#include <getopt-core.h>
+
+#endif /* _GETOPT_PFX_CORE_H */
diff --git a/libgnu/getopt-pfx-ext.h b/libgnu/getopt-pfx-ext.h
new file mode 100644
index 0000000..bc6052a
--- /dev/null
+++ b/libgnu/getopt-pfx-ext.h
@@ -0,0 +1,64 @@
+/* getopt (GNU extensions) gnulib wrapper header.
+   Copyright (C) 1989-2017 Free Software Foundation, Inc.
+   This file is part of gnulib.
+   Unlike most of the getopt implementation, it is NOT shared
+   with the GNU C Library.
+
+   gnulib is free software; you can 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.
+
+   gnulib is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with gnulib; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _GETOPT_PFX_EXT_H
+#define _GETOPT_PFX_EXT_H 1
+
+/* This header should not be used directly; include getopt.h instead.
+   It does not have a protective #error, because the guard macro for
+   getopt.h in gnulib is not fixed.  */
+
+/* Standalone applications should #define __GETOPT_PREFIX to an
+   identifier that prefixes the external functions and variables
+   defined in getopt-core.h and getopt-ext.h.  Systematically
+   rename identifiers so that they do not collide with the system
+   functions and variables.  Renaming avoids problems with some
+   compilers and linkers.  */
+#ifdef __GETOPT_PREFIX
+# ifndef __GETOPT_ID
+#  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)
+# endif
+# undef getopt_long
+# undef getopt_long_only
+# undef option
+# define getopt_long __GETOPT_ID (getopt_long)
+# define getopt_long_only __GETOPT_ID (getopt_long_only)
+# define option __GETOPT_ID (option)
+#endif
+
+/* Standalone applications get correct prototypes for getopt_long and
+   getopt_long_only; they declare "char **argv".  For backward
+   compatibility with old applications, if __GETOPT_PREFIX is not
+   defined, we supply GNU-libc-compatible, but incorrect, prototypes
+   using "char *const *argv".  (GNU libc is stuck with the incorrect
+   prototypes, as they are baked into older versions of LSB.)  */
+#ifndef __getopt_argv_const
+# if defined __GETOPT_PREFIX
+#  define __getopt_argv_const /* empty */
+# else
+#  define __getopt_argv_const const
+# endif
+#endif
+
+#include <getopt-ext.h>
+
+#endif /* _GETOPT_PFX_EXT_H */
diff --git a/libgnu/getopt.c b/libgnu/getopt.c
new file mode 100644
index 0000000..a7db39b
--- /dev/null
+++ b/libgnu/getopt.c
@@ -0,0 +1,810 @@
+/* Getopt for GNU.
+   Copyright (C) 1987-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library and is also part of gnulib.
+   Patches to this file should be submitted to both projects.
+
+   The GNU C Library is free software; you can 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.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+#include "getopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef _LIBC
+/* When used as part of glibc, error printing must be done differently
+   for standards compliance.  getopt is not a cancellation point, so
+   it must not call functions that are, and it is specified by an
+   older standard than stdio locking, so it must not refer to
+   functions in the "user namespace" related to stdio locking.
+   Finally, it must use glibc's internal message translation so that
+   the messages are looked up in the proper text domain.  */
+# include <libintl.h>
+# define fprintf __fxprintf_nocancel
+# define flockfile(fp) _IO_flockfile (fp)
+# define funlockfile(fp) _IO_funlockfile (fp)
+#else
+# include "gettext.h"
+# define _(msgid) gettext (msgid)
+/* When used standalone, flockfile and funlockfile might not be
+   available.  */
+# ifndef _POSIX_THREAD_SAFE_FUNCTIONS
+#  define flockfile(fp) /* nop */
+#  define funlockfile(fp) /* nop */
+# endif
+/* When used standalone, do not attempt to use alloca.  */
+# define __libc_use_alloca(size) 0
+# undef alloca
+# define alloca(size) (abort (), (void *)0)
+#endif
+
+/* This implementation of 'getopt' has three modes for handling
+   options interspersed with non-option arguments.  It can stop
+   scanning for options at the first non-option argument encountered,
+   as POSIX specifies.  It can continue scanning for options after the
+   first non-option argument, but permute 'argv' as it goes so that,
+   after 'getopt' is done, all the options precede all the non-option
+   arguments and 'optind' points to the first non-option argument.
+   Or, it can report non-option arguments as if they were arguments to
+   the option character '\x01'.
+
+   The default behavior of 'getopt_long' is to permute the argument list.
+   When this implementation is used standalone, the default behavior of
+   'getopt' is to stop at the first non-option argument, but when it is
+   used as part of GNU libc it also permutes the argument list.  In both
+   cases, setting the environment variable POSIXLY_CORRECT to any value
+   disables permutation.
+
+   If the first character of the OPTSTRING argument to 'getopt' or
+   'getopt_long' is '+', both functions will stop at the first
+   non-option argument.  If it is '-', both functions will report
+   non-option arguments as arguments to the option character '\x01'.  */
+
+#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;
+
+/* 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.  */
+
+  while (top > middle && middle > bottom)
+    {
+      if (top - middle > middle - bottom)
+	{
+	  /* Bottom segment is the short one.  */
+	  int len = middle - bottom;
+	  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;
+	    }
+	  /* Exclude the moved bottom segment from further swapping.  */
+	  top -= len;
+	}
+      else
+	{
+	  /* Top segment is the short one.  */
+	  int len = top - middle;
+	  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;
+	    }
+	  /* 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;
+}
+
+/* Process the argument starting with d->__nextchar as a long option.
+   d->optind should *not* have been advanced over this argument.
+
+   If the value returned is -1, it was not actually a long option, the
+   state is unchanged, and the argument should be processed as a set
+   of short options (this can only happen when long_only is true).
+   Otherwise, the option (and its argument, if any) have been consumed
+   and the return value is the value to return from _getopt_internal_r.  */
+static int
+process_long_option (int argc, char **argv, const char *optstring,
+		     const struct option *longopts, int *longind,
+		     int long_only, struct _getopt_data *d,
+		     int print_errors, const char *prefix)
+{
+  char *nameend;
+  size_t namelen;
+  const struct option *p;
+  const struct option *pfound = NULL;
+  int n_options;
+  int option_index;
+
+  for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
+    /* Do nothing.  */ ;
+  namelen = nameend - d->__nextchar;
+
+  /* First look for an exact match, counting the options as a side
+     effect.  */
+  for (p = longopts, n_options = 0; p->name; p++, n_options++)
+    if (!strncmp (p->name, d->__nextchar, namelen)
+	&& namelen == strlen (p->name))
+      {
+	/* Exact match found.  */
+	pfound = p;
+	option_index = n_options;
+	break;
+      }
+
+  if (pfound == NULL)
+    {
+      /* Didn't find an exact match, so look for abbreviations.  */
+      unsigned char *ambig_set = NULL;
+      int ambig_malloced = 0;
+      int ambig_fallback = 0;
+      int indfound = -1;
+
+      for (p = longopts, option_index = 0; p->name; p++, option_index++)
+	if (!strncmp (p->name, d->__nextchar, namelen))
+	  {
+	    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.  */
+		if (!ambig_fallback)
+		  {
+		    if (!print_errors)
+		      /* Don't waste effort tracking the ambig set if
+			 we're not going to print it anyway.  */
+		      ambig_fallback = 1;
+		    else if (!ambig_set)
+		      {
+			if (__libc_use_alloca (n_options))
+			  ambig_set = alloca (n_options);
+			else if ((ambig_set = malloc (n_options)) == NULL)
+			  /* Fall back to simpler error message.  */
+			  ambig_fallback = 1;
+			else
+			  ambig_malloced = 1;
+
+			if (ambig_set)
+			  {
+			    memset (ambig_set, 0, n_options);
+			    ambig_set[indfound] = 1;
+			  }
+		      }
+		    if (ambig_set)
+		      ambig_set[option_index] = 1;
+		  }
+	      }
+	  }
+
+      if (ambig_set || ambig_fallback)
+	{
+	  if (print_errors)
+	    {
+	      if (ambig_fallback)
+		fprintf (stderr, _("%s: option '%s%s' is ambiguous\n"),
+			 argv[0], prefix, d->__nextchar);
+	      else
+		{
+		  flockfile (stderr);
+		  fprintf (stderr,
+			   _("%s: option '%s%s' is ambiguous; possibilities:"),
+			   argv[0], prefix, d->__nextchar);
+
+		  for (option_index = 0; option_index < n_options; option_index++)
+		    if (ambig_set[option_index])
+		      fprintf (stderr, " '%s%s'",
+			       prefix, longopts[option_index].name);
+
+		  /* This must use 'fprintf' even though it's only
+		     printing a single character, so that it goes through
+		     __fxprintf_nocancel when compiled as part of glibc.  */
+		  fprintf (stderr, "\n");
+		  funlockfile (stderr);
+		}
+	    }
+	  if (ambig_malloced)
+	    free (ambig_set);
+	  d->__nextchar += strlen (d->__nextchar);
+	  d->optind++;
+	  d->optopt = 0;
+	  return '?';
+	}
+
+      option_index = indfound;
+    }
+
+  if (pfound == NULL)
+    {
+      /* 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.  */
+      if (!long_only || argv[d->optind][1] == '-'
+	  || strchr (optstring, *d->__nextchar) == NULL)
+	{
+	  if (print_errors)
+	    fprintf (stderr, _("%s: unrecognized option '%s%s'\n"),
+		     argv[0], prefix, d->__nextchar);
+
+	  d->__nextchar = NULL;
+	  d->optind++;
+	  d->optopt = 0;
+	  return '?';
+	}
+
+      /* Otherwise interpret it as a short option.  */
+      return -1;
+    }
+
+  /* We have found a matching long option.  Consume it.  */
+  d->optind++;
+  d->__nextchar = NULL;
+  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)
+	    fprintf (stderr,
+		     _("%s: option '%s%s' doesn't allow an argument\n"),
+		     argv[0], prefix, pfound->name);
+
+	  d->optopt = pfound->val;
+	  return '?';
+	}
+    }
+  else if (pfound->has_arg == 1)
+    {
+      if (d->optind < argc)
+	d->optarg = argv[d->optind++];
+      else
+	{
+	  if (print_errors)
+	    fprintf (stderr,
+		     _("%s: option '%s%s' requires an argument\n"),
+		     argv[0], prefix, pfound->name);
+
+	  d->optopt = pfound->val;
+	  return optstring[0] == ':' ? ':' : '?';
+	}
+    }
+
+  if (longind != NULL)
+    *longind = option_index;
+  if (pfound->flag)
+    {
+      *(pfound->flag) = pfound->val;
+      return 0;
+    }
+  return pfound->val;
+}
+
+/* Initialize internal data upon the first call to getopt.  */
+
+static const char *
+_getopt_initialize (int argc _GL_UNUSED,
+		    char **argv _GL_UNUSED, const char *optstring,
+		    struct _getopt_data *d, int posixly_correct)
+{
+  /* 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.  */
+  if (d->optind == 0)
+    d->optind = 1;
+
+  d->__first_nonopt = d->__last_nonopt = d->optind;
+  d->__nextchar = NULL;
+
+  /* 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 (posixly_correct || !!getenv ("POSIXLY_CORRECT"))
+    d->__ordering = REQUIRE_ORDER;
+  else
+    d->__ordering = PERMUTE;
+
+  d->__initialized = 1;
+  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.
+
+   The elements of ARGV aren't really const, because we permute them.
+   But we pretend they're const in the prototype to be compatible
+   with other systems.
+
+   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.  */
+
+int
+_getopt_internal_r (int argc, char **argv, const char *optstring,
+		    const struct option *longopts, int *longind,
+		    int long_only, struct _getopt_data *d, int posixly_correct)
+{
+  int print_errors = d->opterr;
+
+  if (argc < 1)
+    return -1;
+
+  d->optarg = NULL;
+
+  if (d->optind == 0 || !d->__initialized)
+    optstring = _getopt_initialize (argc, argv, optstring, d, posixly_correct);
+  else if (optstring[0] == '-' || optstring[0] == '+')
+    optstring++;
+
+  if (optstring[0] == ':')
+    print_errors = 0;
+
+  /* Test whether ARGV[optind] points to a non-option argument.  */
+#define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')
+
+  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 (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 (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.
+	 Check whether it might be a long option.  */
+      if (longopts)
+	{
+	  if (argv[d->optind][1] == '-')
+	    {
+	      /* "--foo" is always a long option.  The special option
+		 "--" was handled above.  */
+	      d->__nextchar = argv[d->optind] + 2;
+	      return process_long_option (argc, argv, optstring, longopts,
+					  longind, long_only, d,
+					  print_errors, "--");
+	    }
+
+	  /* 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 (long_only && (argv[d->optind][2]
+			    || !strchr (optstring, argv[d->optind][1])))
+	    {
+	      int code;
+	      d->__nextchar = argv[d->optind] + 1;
+	      code = process_long_option (argc, argv, optstring, longopts,
+					  longind, long_only, d,
+					  print_errors, "-");
+	      if (code != -1)
+		return code;
+	    }
+	}
+
+      /* It is not a long option.  Skip the initial punctuation.  */
+      d->__nextchar = argv[d->optind] + 1;
+    }
+
+  /* Look at and handle the next short option-character.  */
+
+  {
+    char c = *d->__nextchar++;
+    const 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 == ':' || c == ';')
+      {
+	if (print_errors)
+	  fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c);
+	d->optopt = c;
+	return '?';
+      }
+
+    /* Convenience. Treat POSIX -W foo same as long option --foo */
+    if (temp[0] == 'W' && temp[1] == ';' && longopts != NULL)
+      {
+	/* This is an option that requires an argument.  */
+	if (*d->__nextchar != '\0')
+	  d->optarg = d->__nextchar;
+	else if (d->optind == argc)
+	  {
+	    if (print_errors)
+	      fprintf (stderr,
+		       _("%s: option requires an argument -- '%c'\n"),
+		       argv[0], c);
+
+	    d->optopt = c;
+	    if (optstring[0] == ':')
+	      c = ':';
+	    else
+	      c = '?';
+	    return c;
+	  }
+	else
+	  d->optarg = argv[d->optind];
+
+	d->__nextchar = d->optarg;
+	d->optarg = NULL;
+	return process_long_option (argc, argv, optstring, longopts, longind,
+				    0 /* long_only */, d, print_errors, "-W ");
+      }
+    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)
+		  fprintf (stderr,
+			   _("%s: option requires an argument -- '%c'\n"),
+			   argv[0], c);
+
+		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, &getopt_data,
+			       posixly_correct);
+
+  optind = getopt_data.optind;
+  optarg = getopt_data.optarg;
+  optopt = getopt_data.optopt;
+
+  return result;
+}
+
+/* glibc gets a LSB-compliant getopt and a POSIX-complaint __posix_getopt.
+   Standalone applications just get a POSIX-compliant getopt.
+   POSIX and LSB both require these functions to take 'char *const *argv'
+   even though this is incorrect (because of the permutation).  */
+#define GETOPT_ENTRY(NAME, POSIXLY_CORRECT)			\
+  int								\
+  NAME (int argc, char *const *argv, const char *optstring)	\
+  {								\
+    return _getopt_internal (argc, (char **)argv, optstring,	\
+			     0, 0, 0, POSIXLY_CORRECT);		\
+  }
+
+#ifdef _LIBC
+GETOPT_ENTRY(getopt, 0)
+GETOPT_ENTRY(__posix_getopt, 1)
+#else
+GETOPT_ENTRY(getopt, 1)
+#endif
+
+
+#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/libgnu/getopt.in.h b/libgnu/getopt.in.h
new file mode 100644
index 0000000..4ce1eb4
--- /dev/null
+++ b/libgnu/getopt.in.h
@@ -0,0 +1,61 @@
+/* Declarations for getopt.
+   Copyright (C) 1989-2017 Free Software Foundation, Inc.
+   This file is part of gnulib.
+   Unlike most of the getopt implementation, it is NOT shared
+   with the GNU C Library, which supplies a different version of
+   this file.
+
+   gnulib is free software; you can 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.
+
+   gnulib is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with gnulib; if not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _@GUARD_PREFIX@_GETOPT_H
+
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+@PRAGMA_COLUMNS@
+
+/* The include_next requires a split double-inclusion guard.  We must
+   also inform the replacement unistd.h to not recursively use
+   <getopt.h>; our definitions will be present soon enough.  */
+#if @HAVE_GETOPT_H@
+# define _GL_SYSTEM_GETOPT
+# @INCLUDE_NEXT@ @NEXT_GETOPT_H@
+# undef _GL_SYSTEM_GETOPT
+#endif
+
+#define _@GUARD_PREFIX@_GETOPT_H 1
+
+/* Standalone applications should #define __GETOPT_PREFIX to an
+   identifier that prefixes the external functions and variables
+   defined in getopt-core.h and getopt-ext.h.  When this happens,
+   include the headers that might declare getopt so that they will not
+   cause confusion if included after this file (if the system had
+   <getopt.h>, we have already included it).  */
+#if defined __GETOPT_PREFIX
+# if !@HAVE_GETOPT_H@
+#  define __need_system_stdlib_h
+#  include <stdlib.h>
+#  undef __need_system_stdlib_h
+#  include <stdio.h>
+#  include <unistd.h>
+# endif
+#endif
+
+/* The definition of _GL_ARG_NONNULL is copied here.  */
+
+#include <getopt-cdefs.h>
+#include <getopt-pfx-core.h>
+#include <getopt-pfx-ext.h>
+
+#endif /* _@GUARD_PREFIX@_GETOPT_H */
diff --git a/libgnu/getopt1.c b/libgnu/getopt1.c
new file mode 100644
index 0000000..2bc5926
--- /dev/null
+++ b/libgnu/getopt1.c
@@ -0,0 +1,159 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+   Copyright (C) 1987-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library and is also part of gnulib.
+   Patches to this file should be submitted to both projects.
+
+   The GNU C Library is free software; you can 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.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+#include "getopt.h"
+#include "getopt_int.h"
+
+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, d, 0);
+}
+
+/* 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, d, 0);
+}
+
+
+#ifdef TEST
+
+#include <stdio.h>
+#include <stdlib.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 const 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/libgnu/getopt_int.h b/libgnu/getopt_int.h
new file mode 100644
index 0000000..a556219
--- /dev/null
+++ b/libgnu/getopt_int.h
@@ -0,0 +1,118 @@
+/* Internal declarations for getopt.
+   Copyright (C) 1989-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library and is also part of gnulib.
+   Patches to this file should be submitted to both projects.
+
+   The GNU C Library is free software; you can 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.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _GETOPT_INT_H
+#define _GETOPT_INT_H	1
+
+#include <getopt.h>
+
+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.  */
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+   REQUIRE_ORDER means don't recognize them as options; stop option
+   processing when the first non-option is seen.  This is what POSIX
+   specifies should happen.
+
+   PERMUTE means 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.
+
+   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 __ord
+  {
+    REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+  };
+
+/* 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;
+
+  /* See __ord above.  */
+  enum __ord __ordering;
+
+  /* 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;
+};
+
+/* 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, struct _getopt_data *__data,
+			       int __posixly_correct);
+
+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/libgnu/getprogname.c b/libgnu/getprogname.c
new file mode 100644
index 0000000..5295484
--- /dev/null
+++ b/libgnu/getprogname.c
@@ -0,0 +1,185 @@
+/* Program name management.
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "getprogname.h"
+
+#include <errno.h> /* get program_invocation_name declaration */
+#include <stdlib.h> /* get __argv declaration */
+
+#ifdef _AIX
+# include <unistd.h>
+# include <procinfo.h>
+# include <string.h>
+#endif
+
+#ifdef __MVS__
+# ifndef _OPEN_SYS
+#  define _OPEN_SYS
+# endif
+# include <string.h>
+# include <sys/ps.h>
+#endif
+
+#ifdef __hpux
+# include <unistd.h>
+# include <sys/param.h>
+# include <sys/pstat.h>
+# include <string.h>
+#endif
+
+#ifdef __sgi
+# include <string.h>
+# include <unistd.h>
+# include <stdio.h>
+# include <fcntl.h>
+# include <sys/procfs.h>
+#endif
+
+#include "dirname.h"
+
+#ifndef HAVE_GETPROGNAME             /* not Mac OS X, FreeBSD, NetBSD, OpenBSD >= 5.4, Cygwin */
+char const *
+getprogname (void)
+{
+# if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME                /* glibc, BeOS */
+  /* https://www.gnu.org/software/libc/manual/html_node/Error-Messages.html */
+  return program_invocation_short_name;
+# elif HAVE_DECL_PROGRAM_INVOCATION_NAME                    /* glibc, BeOS */
+  /* https://www.gnu.org/software/libc/manual/html_node/Error-Messages.html */
+  return last_component (program_invocation_name);
+# elif HAVE_GETEXECNAME                                     /* Solaris */
+  /* http://docs.oracle.com/cd/E19253-01/816-5168/6mbb3hrb1/index.html */
+  const char *p = getexecname ();
+  if (!p)
+    p = "?";
+  return last_component (p);
+# elif HAVE_DECL___ARGV                                     /* mingw, MSVC */
+  /* https://msdn.microsoft.com/en-us/library/dn727674.aspx */
+  const char *p = __argv && __argv[0] ? __argv[0] : "?";
+  return last_component (p);
+# elif HAVE_VAR___PROGNAME                                  /* OpenBSD, QNX */
+  /* http://man.openbsd.org/style.9 */
+  /* http://www.qnx.de/developers/docs/6.5.0/index.jsp?topic=%2Fcom.qnx.doc.neutrino_lib_ref%2Fp%2F__progname.html */
+  /* Be careful to declare this only when we absolutely need it
+     (OpenBSD 5.1), rather than when it's available.  Otherwise,
+     its mere declaration makes program_invocation_short_name
+     malfunction (have zero length) with Fedora 25's glibc.  */
+  extern char *__progname;
+  const char *p = __progname;
+  return p && p[0] ? p : "?";
+# elif _AIX                                                 /* AIX */
+  /* Idea by Bastien ROUCARIÈS,
+     http://lists.gnu.org/archive/html/bug-gnulib/2010-12/msg00095.html
+     Reference: http://
+   ibm.biz/knowctr#ssw_aix_53/com.ibm.aix.basetechref/doc/basetrf1/getprocs.htm
+  */
+  static char *p;
+  static int first = 1;
+  if (first)
+    {
+      first = 0;
+      pid_t pid = getpid ();
+      struct procentry64 procs;
+      p = (0 < getprocs64 (&procs, sizeof procs, NULL, 0, &pid, 1)
+           ? strdup (procs.pi_comm)
+           : NULL);
+      if (!p)
+        p = "?";
+    }
+  return p;
+# elif defined __hpux
+  static char *p;
+  static int first = 1;
+  if (first)
+    {
+      first = 0;
+      pid_t pid = getpid ();
+      struct pst_status status;
+      p = (0 < pstat_getproc (&status, sizeof status, 0, pid)
+           ? strdup (status.pst_ucomm)
+           : NULL);
+      if (!p)
+        p = "?";
+    }
+  return p;
+# elif __MVS__                                              /* z/OS */
+  /* https://www.ibm.com/support/knowledgecenter/SSLTBW_2.1.0/com.ibm.zos.v2r1.bpxbd00/rtwgetp.htm */
+  static char *p = "?";
+  static int first = 1;
+  if (first)
+    {
+      pid_t pid = getpid ();
+      int token;
+      W_PSPROC buf;
+      first = 0;
+      memset (&buf, 0, sizeof(buf));
+      buf.ps_cmdptr    = (char *) malloc (buf.ps_cmdlen    = PS_CMDBLEN_LONG);
+      buf.ps_conttyptr = (char *) malloc (buf.ps_conttylen = PS_CONTTYBLEN);
+      buf.ps_pathptr   = (char *) malloc (buf.ps_pathlen   = PS_PATHBLEN);
+      if (buf.ps_cmdptr && buf.ps_conttyptr && buf.ps_pathptr)
+        {
+          for (token = 0; token >= 0;
+               token = w_getpsent (token, &buf, sizeof(buf)))
+            {
+              if (token > 0 && buf.ps_pid == pid)
+                {
+                  char *s = strdup (last_component (buf.ps_pathptr));
+                  if (s)
+                    p = s;
+                  break;
+                }
+            }
+        }
+      free (buf.ps_cmdptr);
+      free (buf.ps_conttyptr);
+      free (buf.ps_pathptr);
+    }
+  return p;
+# elif defined __sgi                                        /* IRIX */
+  char filename[50];
+  int fd;
+
+  sprintf (filename, "/proc/pinfo/%d", (int) getpid ());
+  fd = open (filename, O_RDONLY);
+  if (0 <= fd)
+    {
+      prpsinfo_t buf;
+      int ioctl_ok = 0 <= ioctl (fd, PIOCPSINFO, &buf);
+      close (fd);
+      if (ioctl_ok)
+        {
+          char *name = buf.pr_fname;
+          char *namesize = sizeof buf.pr_fname;
+          char *namenul = memchr (name, '\0', namesize);
+          size_t namelen = namenul ? namenul - name : namesize;
+          char *namecopy = malloc (namelen + 1);
+          if (namecopy)
+            {
+              namecopy[namelen] = 0;
+              return memcpy (namecopy, name, namelen);
+            }
+        }
+    }
+  return NULL;
+# else
+#  error "getprogname module not ported to this OS"
+# endif
+}
+
+#endif
diff --git a/libgnu/getprogname.h b/libgnu/getprogname.h
new file mode 100644
index 0000000..9ab924c
--- /dev/null
+++ b/libgnu/getprogname.h
@@ -0,0 +1,40 @@
+/* Program name management.
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _GL_GETPROGNAME_H
+#define _GL_GETPROGNAME_H
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Return the base name of the executing program.
+   On native Windows this will usually end in ".exe" or ".EXE". */
+#ifndef HAVE_GETPROGNAME
+extern char const *getprogname (void)
+# ifdef HAVE_DECL_PROGRAM_INVOCATION_NAME
+  _GL_ATTRIBUTE_PURE
+# endif
+  ;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libgnu/gettext.h b/libgnu/gettext.h
new file mode 100644
index 0000000..0465d7a
--- /dev/null
+++ b/libgnu/gettext.h
@@ -0,0 +1,292 @@
+/* Convenience header for conditional use of GNU <libintl.h>.
+   Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2017 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 version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _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 && !defined __UCLIBC__) || _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".  */
+# undef gettext
+# define gettext(Msgid) ((const char *) (Msgid))
+# undef dgettext
+# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
+# undef dcgettext
+# define dcgettext(Domainname, Msgid, Category) \
+    ((void) (Category), dgettext (Domainname, Msgid))
+# undef ngettext
+# define ngettext(Msgid1, Msgid2, N) \
+    ((N) == 1 \
+     ? ((void) (Msgid2), (const char *) (Msgid1)) \
+     : ((void) (Msgid1), (const char *) (Msgid2)))
+# undef dngettext
+# define dngettext(Domainname, Msgid1, Msgid2, N) \
+    ((void) (Domainname), ngettext (Msgid1, Msgid2, N))
+# undef dcngettext
+# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+    ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N))
+# undef textdomain
+# define textdomain(Domainname) ((const char *) (Domainname))
+# undef bindtextdomain
+# define bindtextdomain(Domainname, Dirname) \
+    ((void) (Domainname), (const char *) (Dirname))
+# undef bind_textdomain_codeset
+# define bind_textdomain_codeset(Domainname, Codeset) \
+    ((void) (Domainname), (const char *) (Codeset))
+
+#endif
+
+/* Prefer gnulib's setlocale override over libintl's setlocale override.  */
+#ifdef GNULIB_defined_setlocale
+# undef setlocale
+# define setlocale rpl_setlocale
+#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>
+
+#if (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \
+     /* || __STDC_VERSION__ >= 199901L */ )
+# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1
+#else
+# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0
+#endif
+
+#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
+    {
+      int found_translation;
+      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);
+      found_translation = (translation != msg_ctxt_id);
+#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+      if (msg_ctxt_id != buf)
+        free (msg_ctxt_id);
+#endif
+      if (found_translation)
+        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
+    {
+      int found_translation;
+      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);
+      found_translation = !(translation == msg_ctxt_id || translation == msgid_plural);
+#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+      if (msg_ctxt_id != buf)
+        free (msg_ctxt_id);
+#endif
+      if (found_translation)
+        return translation;
+    }
+  return (n == 1 ? msgid : msgid_plural);
+}
+
+#endif /* _LIBGETTEXT_H */
diff --git a/libgnu/gettimeofday.c b/libgnu/gettimeofday.c
new file mode 100644
index 0000000..18dcbda
--- /dev/null
+++ b/libgnu/gettimeofday.c
@@ -0,0 +1,154 @@
+/* Provide gettimeofday for systems that don't have it or for which it's broken.
+
+   Copyright (C) 2001-2003, 2005-2007, 2009-2017 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 version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+/* 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;
+
+# undef localtime
+extern struct tm *localtime (time_t const *);
+
+# undef gmtime
+extern struct tm *gmtime (time_t const *);
+
+/* 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 *
+rpl_localtime (time_t const *timep)
+{
+  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 *
+rpl_gmtime (time_t const *timep)
+{
+  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
+
+# undef tzset
+extern void tzset (void);
+
+/* This is a wrapper for tzset, for systems on which tzset may clobber
+   the static buffer used for localtime's result.  */
+void
+rpl_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
+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
+
+# if defined timeval /* 'struct timeval' overridden by gnulib?  */
+#  undef timeval
+  struct timeval otv;
+  int result = gettimeofday (&otv, (struct timezone *) tz);
+  if (result == 0)
+    {
+      tv->tv_sec = otv.tv_sec;
+      tv->tv_usec = otv.tv_usec;
+    }
+# else
+  int result = gettimeofday (tv, (struct timezone *) tz);
+# endif
+
+# 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/libgnu/gnulib.am b/libgnu/gnulib.am
new file mode 100644
index 0000000..1d37150
--- /dev/null
+++ b/libgnu/gnulib.am
@@ -0,0 +1,2614 @@
+## DO NOT EDIT! GENERATED AUTOMATICALLY!
+## Process this file with automake to produce Makefile.in.
+# Copyright (C) 2002-2017 Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this file.  If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License,
+# this file may be distributed as part of a program that
+# contains a configuration script generated by Autoconf, under
+# the same distribution terms as the rest of that program.
+#
+# Generated by gnulib-tool.
+# Reproduce by: gnulib-tool --import --lib=libgnu --source-base=libgnu --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=config --makefile-name=gnulib.am --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files argp canonicalize error fcntl ffs fnmatch-gnu fts getline langinfo link mempcpy memrchr obstack obstack-printf pread pwrite qsort_r rawmemchr stpcpy stpncpy strsep sys_utsname sys_wait
+
+
+MOSTLYCLEANFILES += core *.stackdump
+# No GNU Make output.
+
+noinst_LIBRARIES += libgnu.a
+
+libgnu_a_SOURCES =
+libgnu_a_LIBADD = $(gl_LIBOBJS)
+libgnu_a_DEPENDENCIES = $(gl_LIBOBJS)
+EXTRA_libgnu_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 alignof
+
+
+EXTRA_DIST += alignof.h
+
+## end   gnulib module alignof
+
+## begin gnulib module alloca
+
+
+libgnu_a_LIBADD += @ALLOCA@
+libgnu_a_DEPENDENCIES += @ALLOCA@
+EXTRA_DIST += alloca.c
+
+EXTRA_libgnu_a_SOURCES += alloca.c
+
+## 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.
+if GL_GENERATE_ALLOCA_H
+alloca.h: alloca.in.h $(top_builddir)/config.status
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  cat $(srcdir)/alloca.in.h; \
+	} > $@-t && \
+	mv -f $@-t $@
+else
+alloca.h: $(top_builddir)/config.status
+	rm -f $@
+endif
+MOSTLYCLEANFILES += alloca.h alloca.h-t
+
+EXTRA_DIST += alloca.in.h
+
+## end   gnulib module alloca-opt
+
+## begin gnulib module areadlink-with-size
+
+libgnu_a_SOURCES += areadlink-with-size.c
+
+EXTRA_DIST += areadlink.h
+
+## end   gnulib module areadlink-with-size
+
+## begin gnulib module argp
+
+libgnu_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 assure
+
+
+EXTRA_DIST += assure.h
+
+## end   gnulib module assure
+
+## begin gnulib module at-internal
+
+if gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b
+
+endif
+EXTRA_DIST += openat-priv.h openat-proc.c
+
+EXTRA_libgnu_a_SOURCES += openat-proc.c
+
+## end   gnulib module at-internal
+
+## begin gnulib module bitrotate
+
+libgnu_a_SOURCES += bitrotate.h bitrotate.c
+
+## end   gnulib module bitrotate
+
+## begin gnulib module canonicalize
+
+libgnu_a_SOURCES += canonicalize.c
+
+EXTRA_DIST += canonicalize.h
+
+## end   gnulib module canonicalize
+
+## begin gnulib module chdir-long
+
+if gl_GNULIB_ENABLED_8198daae261b932d64a998f8586f5005
+
+endif
+EXTRA_DIST += chdir-long.c chdir-long.h
+
+EXTRA_libgnu_a_SOURCES += chdir-long.c
+
+## end   gnulib module chdir-long
+
+## begin gnulib module cloexec
+
+libgnu_a_SOURCES += cloexec.c
+
+EXTRA_DIST += cloexec.h
+
+## end   gnulib module cloexec
+
+## begin gnulib module close
+
+if gl_GNULIB_ENABLED_close
+
+endif
+EXTRA_DIST += close.c
+
+EXTRA_libgnu_a_SOURCES += close.c
+
+## end   gnulib module close
+
+## begin gnulib module closedir
+
+
+EXTRA_DIST += closedir.c dirent-private.h
+
+EXTRA_libgnu_a_SOURCES += closedir.c
+
+## end   gnulib module closedir
+
+## begin gnulib module configmake
+
+if gl_GNULIB_ENABLED_configmake
+# Listed in the same order as the GNU makefile conventions, and
+# provided by autoconf 2.59c+ or 2.70.
+# The Automake-defined pkg* macros are appended, in the order
+# listed in the Automake 1.10a+ documentation.
+configmake.h: Makefile
+	$(AM_V_GEN)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 RUNSTATEDIR "$(runstatedir)"'; \
+	  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 -f $@-t $@
+
+BUILT_SOURCES += configmake.h
+CLEANFILES += configmake.h configmake.h-t
+
+endif
+## end   gnulib module configmake
+
+## begin gnulib module cycle-check
+
+libgnu_a_SOURCES += cycle-check.c
+
+EXTRA_DIST += cycle-check.h
+
+## end   gnulib module cycle-check
+
+## begin gnulib module dev-ino
+
+
+EXTRA_DIST += dev-ino.h
+
+## end   gnulib module dev-ino
+
+## begin gnulib module dirent
+
+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.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''HAVE_DIRENT_H''@|$(HAVE_DIRENT_H)|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_DIRENT_H''@|$(NEXT_DIRENT_H)|g' \
+	      -e 's/@''GNULIB_OPENDIR''@/$(GNULIB_OPENDIR)/g' \
+	      -e 's/@''GNULIB_READDIR''@/$(GNULIB_READDIR)/g' \
+	      -e 's/@''GNULIB_REWINDDIR''@/$(GNULIB_REWINDDIR)/g' \
+	      -e 's/@''GNULIB_CLOSEDIR''@/$(GNULIB_CLOSEDIR)/g' \
+	      -e 's/@''GNULIB_DIRFD''@/$(GNULIB_DIRFD)/g' \
+	      -e 's/@''GNULIB_FDOPENDIR''@/$(GNULIB_FDOPENDIR)/g' \
+	      -e 's/@''GNULIB_SCANDIR''@/$(GNULIB_SCANDIR)/g' \
+	      -e 's/@''GNULIB_ALPHASORT''@/$(GNULIB_ALPHASORT)/g' \
+	      -e 's/@''HAVE_OPENDIR''@/$(HAVE_OPENDIR)/g' \
+	      -e 's/@''HAVE_READDIR''@/$(HAVE_READDIR)/g' \
+	      -e 's/@''HAVE_REWINDDIR''@/$(HAVE_REWINDDIR)/g' \
+	      -e 's/@''HAVE_CLOSEDIR''@/$(HAVE_CLOSEDIR)/g' \
+	      -e 's|@''HAVE_DECL_DIRFD''@|$(HAVE_DECL_DIRFD)|g' \
+	      -e 's|@''HAVE_DECL_FDOPENDIR''@|$(HAVE_DECL_FDOPENDIR)|g' \
+	      -e 's|@''HAVE_FDOPENDIR''@|$(HAVE_FDOPENDIR)|g' \
+	      -e 's|@''HAVE_SCANDIR''@|$(HAVE_SCANDIR)|g' \
+	      -e 's|@''HAVE_ALPHASORT''@|$(HAVE_ALPHASORT)|g' \
+	      -e 's|@''REPLACE_OPENDIR''@|$(REPLACE_OPENDIR)|g' \
+	      -e 's|@''REPLACE_CLOSEDIR''@|$(REPLACE_CLOSEDIR)|g' \
+	      -e 's|@''REPLACE_DIRFD''@|$(REPLACE_DIRFD)|g' \
+	      -e 's|@''REPLACE_FDOPENDIR''@|$(REPLACE_FDOPENDIR)|g' \
+	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+	      < $(srcdir)/dirent.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += dirent.h dirent.h-t
+
+EXTRA_DIST += dirent.in.h
+
+## end   gnulib module dirent
+
+## begin gnulib module dirent-safer
+
+libgnu_a_SOURCES += opendir-safer.c
+
+EXTRA_DIST += dirent--.h dirent-safer.h
+
+## end   gnulib module dirent-safer
+
+## begin gnulib module dirfd
+
+
+EXTRA_DIST += dirfd.c
+
+EXTRA_libgnu_a_SOURCES += dirfd.c
+
+## end   gnulib module dirfd
+
+## begin gnulib module dirname
+
+libgnu_a_SOURCES += dirname.c basename.c
+
+EXTRA_DIST += stripslash.c
+
+EXTRA_libgnu_a_SOURCES += stripslash.c
+
+## end   gnulib module dirname
+
+## begin gnulib module dirname-lgpl
+
+libgnu_a_SOURCES += dirname-lgpl.c basename-lgpl.c stripslash.c
+
+EXTRA_DIST += dirname.h
+
+## end   gnulib module dirname-lgpl
+
+## begin gnulib module dosname
+
+
+EXTRA_DIST += dosname.h
+
+## end   gnulib module dosname
+
+## begin gnulib module dup
+
+
+EXTRA_DIST += dup.c
+
+EXTRA_libgnu_a_SOURCES += dup.c
+
+## end   gnulib module dup
+
+## begin gnulib module dup2
+
+
+EXTRA_DIST += dup2.c
+
+EXTRA_libgnu_a_SOURCES += dup2.c
+
+## end   gnulib module dup2
+
+## begin gnulib module errno
+
+BUILT_SOURCES += $(ERRNO_H)
+
+# We need the following in order to create <errno.h> when the system
+# doesn't have one that is POSIX compliant.
+if GL_GENERATE_ERRNO_H
+errno.h: errno.in.h $(top_builddir)/config.status
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_ERRNO_H''@|$(NEXT_ERRNO_H)|g' \
+	      -e 's|@''EMULTIHOP_HIDDEN''@|$(EMULTIHOP_HIDDEN)|g' \
+	      -e 's|@''EMULTIHOP_VALUE''@|$(EMULTIHOP_VALUE)|g' \
+	      -e 's|@''ENOLINK_HIDDEN''@|$(ENOLINK_HIDDEN)|g' \
+	      -e 's|@''ENOLINK_VALUE''@|$(ENOLINK_VALUE)|g' \
+	      -e 's|@''EOVERFLOW_HIDDEN''@|$(EOVERFLOW_HIDDEN)|g' \
+	      -e 's|@''EOVERFLOW_VALUE''@|$(EOVERFLOW_VALUE)|g' \
+	      < $(srcdir)/errno.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+else
+errno.h: $(top_builddir)/config.status
+	rm -f $@
+endif
+MOSTLYCLEANFILES += errno.h errno.h-t
+
+EXTRA_DIST += errno.in.h
+
+## end   gnulib module errno
+
+## begin gnulib module error
+
+
+EXTRA_DIST += error.c error.h
+
+EXTRA_libgnu_a_SOURCES += error.c
+
+## end   gnulib module error
+
+## begin gnulib module exitfail
+
+libgnu_a_SOURCES += exitfail.c
+
+EXTRA_DIST += exitfail.h
+
+## end   gnulib module exitfail
+
+## begin gnulib module fchdir
+
+
+EXTRA_DIST += fchdir.c
+
+EXTRA_libgnu_a_SOURCES += fchdir.c
+
+## end   gnulib module fchdir
+
+## begin gnulib module fcntl
+
+
+EXTRA_DIST += fcntl.c
+
+EXTRA_libgnu_a_SOURCES += fcntl.c
+
+## end   gnulib module fcntl
+
+## begin gnulib module fcntl-h
+
+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.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_FCNTL_H''@|$(NEXT_FCNTL_H)|g' \
+	      -e 's/@''GNULIB_FCNTL''@/$(GNULIB_FCNTL)/g' \
+	      -e 's/@''GNULIB_NONBLOCKING''@/$(GNULIB_NONBLOCKING)/g' \
+	      -e 's/@''GNULIB_OPEN''@/$(GNULIB_OPEN)/g' \
+	      -e 's/@''GNULIB_OPENAT''@/$(GNULIB_OPENAT)/g' \
+	      -e 's|@''HAVE_FCNTL''@|$(HAVE_FCNTL)|g' \
+	      -e 's|@''HAVE_OPENAT''@|$(HAVE_OPENAT)|g' \
+	      -e 's|@''REPLACE_FCNTL''@|$(REPLACE_FCNTL)|g' \
+	      -e 's|@''REPLACE_OPEN''@|$(REPLACE_OPEN)|g' \
+	      -e 's|@''REPLACE_OPENAT''@|$(REPLACE_OPENAT)|g' \
+	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+	      < $(srcdir)/fcntl.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += fcntl.h fcntl.h-t
+
+EXTRA_DIST += fcntl.in.h
+
+## end   gnulib module fcntl-h
+
+## begin gnulib module fcntl-safer
+
+libgnu_a_SOURCES += creat-safer.c open-safer.c
+
+EXTRA_DIST += fcntl--.h fcntl-safer.h
+
+## end   gnulib module fcntl-safer
+
+## begin gnulib module fd-hook
+
+if gl_GNULIB_ENABLED_43fe87a341d9b4b93c47c3ad819a5239
+libgnu_a_SOURCES += fd-hook.c
+
+endif
+EXTRA_DIST += fd-hook.h
+
+## end   gnulib module fd-hook
+
+## begin gnulib module fdopendir
+
+
+EXTRA_DIST += fdopendir.c
+
+EXTRA_libgnu_a_SOURCES += fdopendir.c
+
+## end   gnulib module fdopendir
+
+## begin gnulib module ffs
+
+
+EXTRA_DIST += ffs.c
+
+EXTRA_libgnu_a_SOURCES += ffs.c
+
+## end   gnulib module ffs
+
+## begin gnulib module file-set
+
+libgnu_a_SOURCES += file-set.c
+
+EXTRA_DIST += file-set.h
+
+## end   gnulib module file-set
+
+## begin gnulib module filename
+
+if gl_GNULIB_ENABLED_filename
+
+endif
+EXTRA_DIST += filename.h
+
+## end   gnulib module filename
+
+## begin gnulib module filenamecat-lgpl
+
+if gl_GNULIB_ENABLED_fca9852db2a43bb33f02f0fbdbc174f6
+libgnu_a_SOURCES += filenamecat-lgpl.c
+
+endif
+EXTRA_DIST += filenamecat.h
+
+## end   gnulib module filenamecat-lgpl
+
+## begin gnulib module flexmember
+
+
+EXTRA_DIST += flexmember.h
+
+## end   gnulib module flexmember
+
+## 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.
+if GL_GENERATE_FLOAT_H
+float.h: float.in.h $(top_builddir)/config.status
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_FLOAT_H''@|$(NEXT_FLOAT_H)|g' \
+	      -e 's|@''REPLACE_ITOLD''@|$(REPLACE_ITOLD)|g' \
+	      < $(srcdir)/float.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+else
+float.h: $(top_builddir)/config.status
+	rm -f $@
+endif
+MOSTLYCLEANFILES += float.h float.h-t
+
+EXTRA_DIST += float.c float.in.h itold.c
+
+EXTRA_libgnu_a_SOURCES += float.c itold.c
+
+## 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.
+if GL_GENERATE_FNMATCH_H
+fnmatch.h: fnmatch.in.h $(top_builddir)/config.status $(ARG_NONNULL_H)
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      < $(srcdir)/fnmatch.in.h; \
+	} > $@-t && \
+	mv -f $@-t $@
+else
+fnmatch.h: $(top_builddir)/config.status
+	rm -f $@
+endif
+MOSTLYCLEANFILES += fnmatch.h fnmatch.h-t
+
+EXTRA_DIST += fnmatch.c fnmatch.in.h fnmatch_loop.c
+
+EXTRA_libgnu_a_SOURCES += fnmatch.c fnmatch_loop.c
+
+## end   gnulib module fnmatch
+
+## begin gnulib module fstat
+
+
+EXTRA_DIST += fstat.c
+
+EXTRA_libgnu_a_SOURCES += fstat.c
+
+## end   gnulib module fstat
+
+## begin gnulib module fstatat
+
+if gl_GNULIB_ENABLED_fstatat
+
+endif
+EXTRA_DIST += at-func.c fstatat.c
+
+EXTRA_libgnu_a_SOURCES += at-func.c fstatat.c
+
+## end   gnulib module fstatat
+
+## begin gnulib module fts
+
+
+EXTRA_DIST += fts-cycle.c fts.c fts_.h
+
+EXTRA_libgnu_a_SOURCES += fts-cycle.c fts.c
+
+## end   gnulib module fts
+
+## begin gnulib module getcwd
+
+
+EXTRA_DIST += getcwd.c
+
+EXTRA_libgnu_a_SOURCES += getcwd.c
+
+## end   gnulib module getcwd
+
+## begin gnulib module getcwd-lgpl
+
+if gl_GNULIB_ENABLED_3d094ef542bfdd238a5194e172bfe5f6
+
+endif
+EXTRA_DIST += getcwd-lgpl.c
+
+EXTRA_libgnu_a_SOURCES += getcwd-lgpl.c
+
+## end   gnulib module getcwd-lgpl
+
+## begin gnulib module getdelim
+
+if gl_GNULIB_ENABLED_getdelim
+
+endif
+EXTRA_DIST += getdelim.c
+
+EXTRA_libgnu_a_SOURCES += getdelim.c
+
+## end   gnulib module getdelim
+
+## begin gnulib module getdtablesize
+
+if gl_GNULIB_ENABLED_getdtablesize
+
+endif
+EXTRA_DIST += getdtablesize.c
+
+EXTRA_libgnu_a_SOURCES += getdtablesize.c
+
+## end   gnulib module getdtablesize
+
+## begin gnulib module getline
+
+
+EXTRA_DIST += getline.c
+
+EXTRA_libgnu_a_SOURCES += getline.c
+
+## end   gnulib module getline
+
+## begin gnulib module getopt-posix
+
+BUILT_SOURCES += $(GETOPT_H) $(GETOPT_CDEFS_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.in.h $(top_builddir)/config.status
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''HAVE_GETOPT_H''@|$(HAVE_GETOPT_H)|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_GETOPT_H''@|$(NEXT_GETOPT_H)|g' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      < $(srcdir)/getopt.in.h; \
+	} > $@-t && \
+	mv -f $@-t $@
+
+getopt-cdefs.h: getopt-cdefs.in.h $(top_builddir)/config.status
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+          sed -e 's|@''HAVE_SYS_CDEFS_H''@|$(HAVE_SYS_CDEFS_H)|g' \
+	      < $(srcdir)/getopt-cdefs.in.h; \
+	} > $@-t && \
+	mv -f $@-t $@
+
+MOSTLYCLEANFILES += getopt.h getopt.h-t getopt-cdefs.h getopt-cdefs.h-t
+
+EXTRA_DIST += getopt-cdefs.in.h getopt-core.h getopt-ext.h getopt-pfx-core.h getopt-pfx-ext.h getopt.c getopt.in.h getopt1.c getopt_int.h
+
+EXTRA_libgnu_a_SOURCES += getopt.c getopt1.c
+
+## end   gnulib module getopt-posix
+
+## begin gnulib module getprogname
+
+libgnu_a_SOURCES += getprogname.h getprogname.c
+
+## end   gnulib module getprogname
+
+## begin gnulib module gettext-h
+
+libgnu_a_SOURCES += gettext.h
+
+## end   gnulib module gettext-h
+
+## begin gnulib module gettimeofday
+
+
+EXTRA_DIST += gettimeofday.c
+
+EXTRA_libgnu_a_SOURCES += gettimeofday.c
+
+## end   gnulib module gettimeofday
+
+## begin gnulib module hard-locale
+
+if gl_GNULIB_ENABLED_30838f5439487421042f2225bed3af76
+libgnu_a_SOURCES += hard-locale.c
+
+endif
+EXTRA_DIST += hard-locale.h
+
+## end   gnulib module hard-locale
+
+## begin gnulib module hash
+
+libgnu_a_SOURCES += hash.c
+
+EXTRA_DIST += hash.h
+
+## end   gnulib module hash
+
+## begin gnulib module hash-pjw
+
+libgnu_a_SOURCES += hash-pjw.h hash-pjw.c
+
+## end   gnulib module hash-pjw
+
+## begin gnulib module hash-triple
+
+libgnu_a_SOURCES += hash-triple.c
+
+EXTRA_DIST += hash-triple.h
+
+## end   gnulib module hash-triple
+
+## begin gnulib module i-ring
+
+libgnu_a_SOURCES += i-ring.c
+
+EXTRA_DIST += i-ring.h
+
+## end   gnulib module i-ring
+
+## begin gnulib module intprops
+
+if gl_GNULIB_ENABLED_intprops
+
+endif
+EXTRA_DIST += intprops.h
+
+## end   gnulib module intprops
+
+## begin gnulib module langinfo
+
+BUILT_SOURCES += langinfo.h
+
+# We need the following in order to create an empty placeholder for
+# <langinfo.h> when the system doesn't have one.
+langinfo.h: langinfo.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H)
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''HAVE_LANGINFO_H''@|$(HAVE_LANGINFO_H)|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_LANGINFO_H''@|$(NEXT_LANGINFO_H)|g' \
+	      -e 's/@''GNULIB_NL_LANGINFO''@/$(GNULIB_NL_LANGINFO)/g' \
+	      -e 's|@''HAVE_LANGINFO_CODESET''@|$(HAVE_LANGINFO_CODESET)|g' \
+	      -e 's|@''HAVE_LANGINFO_T_FMT_AMPM''@|$(HAVE_LANGINFO_T_FMT_AMPM)|g' \
+	      -e 's|@''HAVE_LANGINFO_ERA''@|$(HAVE_LANGINFO_ERA)|g' \
+	      -e 's|@''HAVE_LANGINFO_YESEXPR''@|$(HAVE_LANGINFO_YESEXPR)|g' \
+	      -e 's|@''HAVE_NL_LANGINFO''@|$(HAVE_NL_LANGINFO)|g' \
+	      -e 's|@''REPLACE_NL_LANGINFO''@|$(REPLACE_NL_LANGINFO)|g' \
+	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+	      < $(srcdir)/langinfo.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += langinfo.h langinfo.h-t
+
+EXTRA_DIST += langinfo.in.h
+
+## end   gnulib module langinfo
+
+## begin gnulib module limits-h
+
+BUILT_SOURCES += $(LIMITS_H)
+
+# We need the following in order to create <limits.h> when the system
+# doesn't have one that is compatible with GNU.
+if GL_GENERATE_LIMITS_H
+limits.h: limits.in.h $(top_builddir)/config.status
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_LIMITS_H''@|$(NEXT_LIMITS_H)|g' \
+	      < $(srcdir)/limits.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+else
+limits.h: $(top_builddir)/config.status
+	rm -f $@
+endif
+MOSTLYCLEANFILES += limits.h limits.h-t
+
+EXTRA_DIST += limits.in.h
+
+## end   gnulib module limits-h
+
+## begin gnulib module link
+
+
+EXTRA_DIST += link.c
+
+EXTRA_libgnu_a_SOURCES += link.c
+
+## end   gnulib module link
+
+## begin gnulib module localcharset
+
+if gl_GNULIB_ENABLED_localcharset
+libgnu_a_SOURCES += localcharset.h localcharset.c
+
+# We need the following in order to install a simple file in $(libdir)
+# which is shared with other installed packages. We use a list of referencing
+# packages so that "make uninstall" will remove the file if and only if it
+# is not used by another installed package.
+# On systems with glibc-2.1 or newer, the file is redundant, therefore we
+# avoid installing it.
+
+all-local: charset.alias ref-add.sed ref-del.sed
+
+charset_alias = $(DESTDIR)$(libdir)/charset.alias
+charset_tmp = $(DESTDIR)$(libdir)/charset.tmp
+install-exec-local: install-exec-localcharset
+install-exec-localcharset: all-local
+	if test $(GLIBC21) = no; then \
+	  case '$(host_os)' in \
+	    darwin[56]*) \
+	      need_charset_alias=true ;; \
+	    darwin* | cygwin* | mingw* | pw32* | cegcc*) \
+	      need_charset_alias=false ;; \
+	    *) \
+	      need_charset_alias=true ;; \
+	  esac ; \
+	else \
+	  need_charset_alias=false ; \
+	fi ; \
+	if $$need_charset_alias; then \
+	  $(mkinstalldirs) $(DESTDIR)$(libdir) ; \
+	fi ; \
+	if test -f $(charset_alias); then \
+	  sed -f ref-add.sed $(charset_alias) > $(charset_tmp) ; \
+	  $(INSTALL_DATA) $(charset_tmp) $(charset_alias) ; \
+	  rm -f $(charset_tmp) ; \
+	else \
+	  if $$need_charset_alias; then \
+	    sed -f ref-add.sed charset.alias > $(charset_tmp) ; \
+	    $(INSTALL_DATA) $(charset_tmp) $(charset_alias) ; \
+	    rm -f $(charset_tmp) ; \
+	  fi ; \
+	fi
+
+uninstall-local: uninstall-localcharset
+uninstall-localcharset: all-local
+	if test -f $(charset_alias); then \
+	  sed -f ref-del.sed $(charset_alias) > $(charset_tmp); \
+	  if grep '^# Packages using this file: $$' $(charset_tmp) \
+	      > /dev/null; then \
+	    rm -f $(charset_alias); \
+	  else \
+	    $(INSTALL_DATA) $(charset_tmp) $(charset_alias); \
+	  fi; \
+	  rm -f $(charset_tmp); \
+	fi
+
+charset.alias: config.charset
+	$(AM_V_GEN)rm -f t-$@ $@ && \
+	$(SHELL) $(srcdir)/config.charset '$(host)' > t-$@ && \
+	mv t-$@ $@
+
+SUFFIXES += .sed .sin
+.sin.sed:
+	$(AM_V_GEN)rm -f t-$@ $@ && \
+	sed -e '/^#/d' -e 's/@''PACKAGE''@/$(PACKAGE)/g' $< > t-$@ && \
+	mv t-$@ $@
+
+CLEANFILES += charset.alias ref-add.sed ref-del.sed
+
+endif
+EXTRA_DIST += config.charset ref-add.sin ref-del.sin
+
+## end   gnulib module localcharset
+
+## begin gnulib module lseek
+
+if gl_GNULIB_ENABLED_lseek
+
+endif
+EXTRA_DIST += lseek.c
+
+EXTRA_libgnu_a_SOURCES += lseek.c
+
+## end   gnulib module lseek
+
+## begin gnulib module lstat
+
+
+EXTRA_DIST += lstat.c
+
+EXTRA_libgnu_a_SOURCES += lstat.c
+
+## end   gnulib module lstat
+
+## begin gnulib module malloc-gnu
+
+
+EXTRA_DIST += malloc.c
+
+EXTRA_libgnu_a_SOURCES += malloc.c
+
+## end   gnulib module malloc-gnu
+
+## begin gnulib module malloc-posix
+
+
+EXTRA_DIST += malloc.c
+
+EXTRA_libgnu_a_SOURCES += malloc.c
+
+## end   gnulib module malloc-posix
+
+## begin gnulib module mbrtowc
+
+if gl_GNULIB_ENABLED_mbrtowc
+
+endif
+EXTRA_DIST += mbrtowc.c
+
+EXTRA_libgnu_a_SOURCES += mbrtowc.c
+
+## end   gnulib module mbrtowc
+
+## begin gnulib module mbsinit
+
+if gl_GNULIB_ENABLED_mbsinit
+
+endif
+EXTRA_DIST += mbsinit.c
+
+EXTRA_libgnu_a_SOURCES += mbsinit.c
+
+## end   gnulib module mbsinit
+
+## begin gnulib module mbsrtowcs
+
+if gl_GNULIB_ENABLED_mbsrtowcs
+
+endif
+EXTRA_DIST += mbsrtowcs-impl.h mbsrtowcs-state.c mbsrtowcs.c
+
+EXTRA_libgnu_a_SOURCES += mbsrtowcs-state.c mbsrtowcs.c
+
+## end   gnulib module mbsrtowcs
+
+## begin gnulib module memchr
+
+
+EXTRA_DIST += memchr.c memchr.valgrind
+
+EXTRA_libgnu_a_SOURCES += memchr.c
+
+## end   gnulib module memchr
+
+## begin gnulib module mempcpy
+
+
+EXTRA_DIST += mempcpy.c
+
+EXTRA_libgnu_a_SOURCES += mempcpy.c
+
+## end   gnulib module mempcpy
+
+## begin gnulib module memrchr
+
+
+EXTRA_DIST += memrchr.c
+
+EXTRA_libgnu_a_SOURCES += memrchr.c
+
+## end   gnulib module memrchr
+
+## begin gnulib module msvc-inval
+
+if gl_GNULIB_ENABLED_f691f076f650964c9f5598c3ee487616
+
+endif
+EXTRA_DIST += msvc-inval.c msvc-inval.h
+
+EXTRA_libgnu_a_SOURCES += msvc-inval.c
+
+## end   gnulib module msvc-inval
+
+## begin gnulib module msvc-nothrow
+
+if gl_GNULIB_ENABLED_676220fa4366efa9bdbfccf11a857c07
+
+endif
+EXTRA_DIST += msvc-nothrow.c msvc-nothrow.h
+
+EXTRA_libgnu_a_SOURCES += msvc-nothrow.c
+
+## end   gnulib module msvc-nothrow
+
+## begin gnulib module obstack
+
+
+EXTRA_DIST += obstack.c obstack.h
+
+EXTRA_libgnu_a_SOURCES += obstack.c
+
+## end   gnulib module obstack
+
+## begin gnulib module obstack-printf
+
+
+EXTRA_DIST += obstack_printf.c
+
+EXTRA_libgnu_a_SOURCES += obstack_printf.c
+
+## end   gnulib module obstack-printf
+
+## begin gnulib module open
+
+
+EXTRA_DIST += open.c
+
+EXTRA_libgnu_a_SOURCES += open.c
+
+## end   gnulib module open
+
+## begin gnulib module openat
+
+
+EXTRA_DIST += openat.c
+
+EXTRA_libgnu_a_SOURCES += openat.c
+
+## end   gnulib module openat
+
+## begin gnulib module openat-die
+
+if gl_GNULIB_ENABLED_1840129d490f3a00c8a098316d0fa345
+libgnu_a_SOURCES += openat-die.c
+
+endif
+## end   gnulib module openat-die
+
+## begin gnulib module openat-h
+
+
+EXTRA_DIST += openat.h
+
+## end   gnulib module openat-h
+
+## begin gnulib module openat-safer
+
+libgnu_a_SOURCES += openat-safer.c
+
+EXTRA_DIST += fcntl--.h fcntl-safer.h
+
+## end   gnulib module openat-safer
+
+## begin gnulib module opendir
+
+
+EXTRA_DIST += dirent-private.h opendir.c
+
+EXTRA_libgnu_a_SOURCES += opendir.c
+
+## end   gnulib module opendir
+
+## begin gnulib module pathmax
+
+
+EXTRA_DIST += pathmax.h
+
+## end   gnulib module pathmax
+
+## begin gnulib module pread
+
+
+EXTRA_DIST += pread.c
+
+EXTRA_libgnu_a_SOURCES += pread.c
+
+## end   gnulib module pread
+
+## begin gnulib module pwrite
+
+
+EXTRA_DIST += pwrite.c
+
+EXTRA_libgnu_a_SOURCES += pwrite.c
+
+## end   gnulib module pwrite
+
+## begin gnulib module qsort_r
+
+
+EXTRA_DIST += qsort.c qsort_r.c
+
+EXTRA_libgnu_a_SOURCES += qsort.c qsort_r.c
+
+## end   gnulib module qsort_r
+
+## begin gnulib module raise
+
+if gl_GNULIB_ENABLED_raise
+
+endif
+EXTRA_DIST += raise.c
+
+EXTRA_libgnu_a_SOURCES += raise.c
+
+## end   gnulib module raise
+
+## begin gnulib module rawmemchr
+
+
+EXTRA_DIST += rawmemchr.c rawmemchr.valgrind
+
+EXTRA_libgnu_a_SOURCES += rawmemchr.c
+
+## end   gnulib module rawmemchr
+
+## begin gnulib module read
+
+if gl_GNULIB_ENABLED_read
+
+endif
+EXTRA_DIST += read.c
+
+EXTRA_libgnu_a_SOURCES += read.c
+
+## end   gnulib module read
+
+## begin gnulib module readdir
+
+
+EXTRA_DIST += dirent-private.h readdir.c
+
+EXTRA_libgnu_a_SOURCES += readdir.c
+
+## end   gnulib module readdir
+
+## begin gnulib module readlink
+
+
+EXTRA_DIST += readlink.c
+
+EXTRA_libgnu_a_SOURCES += readlink.c
+
+## end   gnulib module readlink
+
+## begin gnulib module realloc-posix
+
+if gl_GNULIB_ENABLED_61bcaca76b3e6f9ae55d57a1c3193bc4
+
+endif
+EXTRA_DIST += realloc.c
+
+EXTRA_libgnu_a_SOURCES += realloc.c
+
+## end   gnulib module realloc-posix
+
+## begin gnulib module rewinddir
+
+if gl_GNULIB_ENABLED_rewinddir
+
+endif
+EXTRA_DIST += dirent-private.h rewinddir.c
+
+EXTRA_libgnu_a_SOURCES += rewinddir.c
+
+## end   gnulib module rewinddir
+
+## begin gnulib module same
+
+libgnu_a_SOURCES += same.c
+
+EXTRA_DIST += same.h
+
+## end   gnulib module same
+
+## begin gnulib module same-inode
+
+
+EXTRA_DIST += same-inode.h
+
+## end   gnulib module same-inode
+
+## begin gnulib module save-cwd
+
+if gl_GNULIB_ENABLED_d4850532688ba16d685f036076611f21
+libgnu_a_SOURCES += save-cwd.c
+
+endif
+EXTRA_DIST += save-cwd.h
+
+## end   gnulib module save-cwd
+
+## begin gnulib module signal-h
+
+if gl_GNULIB_ENABLED_af7e3f0204832604ea56703236d065c9
+BUILT_SOURCES += signal.h
+
+# We need the following in order to create <signal.h> when the system
+# doesn't have a complete one.
+signal.h: signal.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_SIGNAL_H''@|$(NEXT_SIGNAL_H)|g' \
+	      -e 's|@''GNULIB_PTHREAD_SIGMASK''@|$(GNULIB_PTHREAD_SIGMASK)|g' \
+	      -e 's|@''GNULIB_RAISE''@|$(GNULIB_RAISE)|g' \
+	      -e 's/@''GNULIB_SIGNAL_H_SIGPIPE''@/$(GNULIB_SIGNAL_H_SIGPIPE)/g' \
+	      -e 's/@''GNULIB_SIGPROCMASK''@/$(GNULIB_SIGPROCMASK)/g' \
+	      -e 's/@''GNULIB_SIGACTION''@/$(GNULIB_SIGACTION)/g' \
+	      -e 's|@''HAVE_POSIX_SIGNALBLOCKING''@|$(HAVE_POSIX_SIGNALBLOCKING)|g' \
+	      -e 's|@''HAVE_PTHREAD_SIGMASK''@|$(HAVE_PTHREAD_SIGMASK)|g' \
+	      -e 's|@''HAVE_RAISE''@|$(HAVE_RAISE)|g' \
+	      -e 's|@''HAVE_SIGSET_T''@|$(HAVE_SIGSET_T)|g' \
+	      -e 's|@''HAVE_SIGINFO_T''@|$(HAVE_SIGINFO_T)|g' \
+	      -e 's|@''HAVE_SIGACTION''@|$(HAVE_SIGACTION)|g' \
+	      -e 's|@''HAVE_STRUCT_SIGACTION_SA_SIGACTION''@|$(HAVE_STRUCT_SIGACTION_SA_SIGACTION)|g' \
+	      -e 's|@''HAVE_TYPE_VOLATILE_SIG_ATOMIC_T''@|$(HAVE_TYPE_VOLATILE_SIG_ATOMIC_T)|g' \
+	      -e 's|@''HAVE_SIGHANDLER_T''@|$(HAVE_SIGHANDLER_T)|g' \
+	      -e 's|@''REPLACE_PTHREAD_SIGMASK''@|$(REPLACE_PTHREAD_SIGMASK)|g' \
+	      -e 's|@''REPLACE_RAISE''@|$(REPLACE_RAISE)|g' \
+	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+	      < $(srcdir)/signal.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += signal.h signal.h-t
+
+endif
+EXTRA_DIST += signal.in.h
+
+## end   gnulib module signal-h
+
+## begin gnulib module size_max
+
+libgnu_a_SOURCES += size_max.h
+
+## end   gnulib module size_max
+
+## begin gnulib module sleep
+
+
+EXTRA_DIST += sleep.c
+
+EXTRA_libgnu_a_SOURCES += sleep.c
+
+## end   gnulib module sleep
+
+## begin gnulib module snippet/_Noreturn
+
+# Because this Makefile snippet defines a variable used by other
+# gnulib Makefile snippets, it must be present in all makefiles that
+# need it. This is ensured by the applicability 'all' defined above.
+
+_NORETURN_H=$(srcdir)/_Noreturn.h
+
+EXTRA_DIST += _Noreturn.h
+
+## end   gnulib module snippet/_Noreturn
+
+## begin gnulib module snippet/arg-nonnull
+
+# Because this Makefile snippet defines a variable used by other
+# gnulib Makefile snippets, it must be present in all makefiles that
+# need it. This is ensured by the applicability 'all' defined above.
+
+ARG_NONNULL_H=$(srcdir)/arg-nonnull.h
+
+EXTRA_DIST += arg-nonnull.h
+
+## end   gnulib module snippet/arg-nonnull
+
+## begin gnulib module snippet/c++defs
+
+# Because this Makefile snippet defines a variable used by other
+# gnulib Makefile snippets, it must be present in all makefiles that
+# need it. This is ensured by the applicability 'all' defined above.
+
+CXXDEFS_H=$(srcdir)/c++defs.h
+
+EXTRA_DIST += c++defs.h
+
+## end   gnulib module snippet/c++defs
+
+## begin gnulib module snippet/warn-on-use
+
+# Because this Makefile snippet defines a variable used by other
+# gnulib Makefile snippets, it must be present in all makefiles that
+# need it. This is ensured by the applicability 'all' defined above.
+
+WARN_ON_USE_H=$(srcdir)/warn-on-use.h
+
+EXTRA_DIST += warn-on-use.h
+
+## end   gnulib module snippet/warn-on-use
+
+## begin gnulib module stat
+
+
+EXTRA_DIST += stat.c
+
+EXTRA_libgnu_a_SOURCES += stat.c
+
+## end   gnulib module stat
+
+## begin gnulib module stdalign
+
+BUILT_SOURCES += $(STDALIGN_H)
+
+# We need the following in order to create <stdalign.h> when the system
+# doesn't have one that works.
+if GL_GENERATE_STDALIGN_H
+stdalign.h: stdalign.in.h $(top_builddir)/config.status
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  cat $(srcdir)/stdalign.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+else
+stdalign.h: $(top_builddir)/config.status
+	rm -f $@
+endif
+MOSTLYCLEANFILES += stdalign.h stdalign.h-t
+
+EXTRA_DIST += stdalign.in.h
+
+## end   gnulib module stdalign
+
+## begin gnulib module stdbool
+
+BUILT_SOURCES += $(STDBOOL_H)
+
+# We need the following in order to create <stdbool.h> when the system
+# doesn't have one that works.
+if GL_GENERATE_STDBOOL_H
+stdbool.h: stdbool.in.h $(top_builddir)/config.status
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+else
+stdbool.h: $(top_builddir)/config.status
+	rm -f $@
+endif
+MOSTLYCLEANFILES += stdbool.h stdbool.h-t
+
+EXTRA_DIST += stdbool.in.h
+
+## end   gnulib module stdbool
+
+## begin gnulib module stddef
+
+BUILT_SOURCES += $(STDDEF_H)
+
+# We need the following in order to create <stddef.h> when the system
+# doesn't have one that works with the given compiler.
+if GL_GENERATE_STDDEF_H
+stddef.h: stddef.in.h $(top_builddir)/config.status
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_STDDEF_H''@|$(NEXT_STDDEF_H)|g' \
+	      -e 's|@''HAVE_MAX_ALIGN_T''@|$(HAVE_MAX_ALIGN_T)|g' \
+	      -e 's|@''HAVE_WCHAR_T''@|$(HAVE_WCHAR_T)|g' \
+	      -e 's|@''REPLACE_NULL''@|$(REPLACE_NULL)|g' \
+	      < $(srcdir)/stddef.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+else
+stddef.h: $(top_builddir)/config.status
+	rm -f $@
+endif
+MOSTLYCLEANFILES += stddef.h stddef.h-t
+
+EXTRA_DIST += stddef.in.h
+
+## end   gnulib module stddef
+
+## begin gnulib module stdint
+
+BUILT_SOURCES += $(STDINT_H)
+
+# We need the following in order to create <stdint.h> when the system
+# doesn't have one that works with the given compiler.
+if GL_GENERATE_STDINT_H
+stdint.h: stdint.in.h $(top_builddir)/config.status
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's/@''HAVE_STDINT_H''@/$(HAVE_STDINT_H)/g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_STDINT_H''@|$(NEXT_STDINT_H)|g' \
+	      -e 's/@''HAVE_C99_STDINT_H''@/$(HAVE_C99_STDINT_H)/g' \
+	      -e 's/@''HAVE_SYS_TYPES_H''@/$(HAVE_SYS_TYPES_H)/g' \
+	      -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \
+	      -e 's/@''HAVE_SYS_INTTYPES_H''@/$(HAVE_SYS_INTTYPES_H)/g' \
+	      -e 's/@''HAVE_SYS_BITYPES_H''@/$(HAVE_SYS_BITYPES_H)/g' \
+	      -e 's/@''HAVE_WCHAR_H''@/$(HAVE_WCHAR_H)/g' \
+	      -e 's/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \
+	      -e 's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/g' \
+	      -e 's/@''APPLE_UNIVERSAL_BUILD''@/$(APPLE_UNIVERSAL_BUILD)/g' \
+	      -e 's/@''BITSIZEOF_PTRDIFF_T''@/$(BITSIZEOF_PTRDIFF_T)/g' \
+	      -e 's/@''PTRDIFF_T_SUFFIX''@/$(PTRDIFF_T_SUFFIX)/g' \
+	      -e 's/@''BITSIZEOF_SIG_ATOMIC_T''@/$(BITSIZEOF_SIG_ATOMIC_T)/g' \
+	      -e 's/@''HAVE_SIGNED_SIG_ATOMIC_T''@/$(HAVE_SIGNED_SIG_ATOMIC_T)/g' \
+	      -e 's/@''SIG_ATOMIC_T_SUFFIX''@/$(SIG_ATOMIC_T_SUFFIX)/g' \
+	      -e 's/@''BITSIZEOF_SIZE_T''@/$(BITSIZEOF_SIZE_T)/g' \
+	      -e 's/@''SIZE_T_SUFFIX''@/$(SIZE_T_SUFFIX)/g' \
+	      -e 's/@''BITSIZEOF_WCHAR_T''@/$(BITSIZEOF_WCHAR_T)/g' \
+	      -e 's/@''HAVE_SIGNED_WCHAR_T''@/$(HAVE_SIGNED_WCHAR_T)/g' \
+	      -e 's/@''WCHAR_T_SUFFIX''@/$(WCHAR_T_SUFFIX)/g' \
+	      -e 's/@''BITSIZEOF_WINT_T''@/$(BITSIZEOF_WINT_T)/g' \
+	      -e 's/@''HAVE_SIGNED_WINT_T''@/$(HAVE_SIGNED_WINT_T)/g' \
+	      -e 's/@''WINT_T_SUFFIX''@/$(WINT_T_SUFFIX)/g' \
+	      -e 's/@''GNULIB_OVERRIDES_WINT_T''@/$(GNULIB_OVERRIDES_WINT_T)/g' \
+	      < $(srcdir)/stdint.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+else
+stdint.h: $(top_builddir)/config.status
+	rm -f $@
+endif
+MOSTLYCLEANFILES += stdint.h stdint.h-t
+
+EXTRA_DIST += stdint.in.h
+
+## end   gnulib module stdint
+
+## begin gnulib module 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.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_STDIO_H''@|$(NEXT_STDIO_H)|g' \
+	      -e 's/@''GNULIB_DPRINTF''@/$(GNULIB_DPRINTF)/g' \
+	      -e 's/@''GNULIB_FCLOSE''@/$(GNULIB_FCLOSE)/g' \
+	      -e 's/@''GNULIB_FDOPEN''@/$(GNULIB_FDOPEN)/g' \
+	      -e 's/@''GNULIB_FFLUSH''@/$(GNULIB_FFLUSH)/g' \
+	      -e 's/@''GNULIB_FGETC''@/$(GNULIB_FGETC)/g' \
+	      -e 's/@''GNULIB_FGETS''@/$(GNULIB_FGETS)/g' \
+	      -e 's/@''GNULIB_FOPEN''@/$(GNULIB_FOPEN)/g' \
+	      -e 's/@''GNULIB_FPRINTF''@/$(GNULIB_FPRINTF)/g' \
+	      -e 's/@''GNULIB_FPRINTF_POSIX''@/$(GNULIB_FPRINTF_POSIX)/g' \
+	      -e 's/@''GNULIB_FPURGE''@/$(GNULIB_FPURGE)/g' \
+	      -e 's/@''GNULIB_FPUTC''@/$(GNULIB_FPUTC)/g' \
+	      -e 's/@''GNULIB_FPUTS''@/$(GNULIB_FPUTS)/g' \
+	      -e 's/@''GNULIB_FREAD''@/$(GNULIB_FREAD)/g' \
+	      -e 's/@''GNULIB_FREOPEN''@/$(GNULIB_FREOPEN)/g' \
+	      -e 's/@''GNULIB_FSCANF''@/$(GNULIB_FSCANF)/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_FWRITE''@/$(GNULIB_FWRITE)/g' \
+	      -e 's/@''GNULIB_GETC''@/$(GNULIB_GETC)/g' \
+	      -e 's/@''GNULIB_GETCHAR''@/$(GNULIB_GETCHAR)/g' \
+	      -e 's/@''GNULIB_GETDELIM''@/$(GNULIB_GETDELIM)/g' \
+	      -e 's/@''GNULIB_GETLINE''@/$(GNULIB_GETLINE)/g' \
+	      -e 's/@''GNULIB_OBSTACK_PRINTF''@/$(GNULIB_OBSTACK_PRINTF)/g' \
+	      -e 's/@''GNULIB_OBSTACK_PRINTF_POSIX''@/$(GNULIB_OBSTACK_PRINTF_POSIX)/g' \
+	      -e 's/@''GNULIB_PCLOSE''@/$(GNULIB_PCLOSE)/g' \
+	      -e 's/@''GNULIB_PERROR''@/$(GNULIB_PERROR)/g' \
+	      -e 's/@''GNULIB_POPEN''@/$(GNULIB_POPEN)/g' \
+	      -e 's/@''GNULIB_PRINTF''@/$(GNULIB_PRINTF)/g' \
+	      -e 's/@''GNULIB_PRINTF_POSIX''@/$(GNULIB_PRINTF_POSIX)/g' \
+	      -e 's/@''GNULIB_PUTC''@/$(GNULIB_PUTC)/g' \
+	      -e 's/@''GNULIB_PUTCHAR''@/$(GNULIB_PUTCHAR)/g' \
+	      -e 's/@''GNULIB_PUTS''@/$(GNULIB_PUTS)/g' \
+	      -e 's/@''GNULIB_REMOVE''@/$(GNULIB_REMOVE)/g' \
+	      -e 's/@''GNULIB_RENAME''@/$(GNULIB_RENAME)/g' \
+	      -e 's/@''GNULIB_RENAMEAT''@/$(GNULIB_RENAMEAT)/g' \
+	      -e 's/@''GNULIB_SCANF''@/$(GNULIB_SCANF)/g' \
+	      -e 's/@''GNULIB_SNPRINTF''@/$(GNULIB_SNPRINTF)/g' \
+	      -e 's/@''GNULIB_SPRINTF_POSIX''@/$(GNULIB_SPRINTF_POSIX)/g' \
+	      -e 's/@''GNULIB_STDIO_H_NONBLOCKING''@/$(GNULIB_STDIO_H_NONBLOCKING)/g' \
+	      -e 's/@''GNULIB_STDIO_H_SIGPIPE''@/$(GNULIB_STDIO_H_SIGPIPE)/g' \
+	      -e 's/@''GNULIB_TMPFILE''@/$(GNULIB_TMPFILE)/g' \
+	      -e 's/@''GNULIB_VASPRINTF''@/$(GNULIB_VASPRINTF)/g' \
+	      -e 's/@''GNULIB_VDPRINTF''@/$(GNULIB_VDPRINTF)/g' \
+	      -e 's/@''GNULIB_VFPRINTF''@/$(GNULIB_VFPRINTF)/g' \
+	      -e 's/@''GNULIB_VFPRINTF_POSIX''@/$(GNULIB_VFPRINTF_POSIX)/g' \
+	      -e 's/@''GNULIB_VFSCANF''@/$(GNULIB_VFSCANF)/g' \
+	      -e 's/@''GNULIB_VSCANF''@/$(GNULIB_VSCANF)/g' \
+	      -e 's/@''GNULIB_VPRINTF''@/$(GNULIB_VPRINTF)/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' \
+	      < $(srcdir)/stdio.in.h | \
+	  sed -e 's|@''HAVE_DECL_FPURGE''@|$(HAVE_DECL_FPURGE)|g' \
+	      -e 's|@''HAVE_DECL_FSEEKO''@|$(HAVE_DECL_FSEEKO)|g' \
+	      -e 's|@''HAVE_DECL_FTELLO''@|$(HAVE_DECL_FTELLO)|g' \
+	      -e 's|@''HAVE_DECL_GETDELIM''@|$(HAVE_DECL_GETDELIM)|g' \
+	      -e 's|@''HAVE_DECL_GETLINE''@|$(HAVE_DECL_GETLINE)|g' \
+	      -e 's|@''HAVE_DECL_OBSTACK_PRINTF''@|$(HAVE_DECL_OBSTACK_PRINTF)|g' \
+	      -e 's|@''HAVE_DECL_SNPRINTF''@|$(HAVE_DECL_SNPRINTF)|g' \
+	      -e 's|@''HAVE_DECL_VSNPRINTF''@|$(HAVE_DECL_VSNPRINTF)|g' \
+	      -e 's|@''HAVE_DPRINTF''@|$(HAVE_DPRINTF)|g' \
+	      -e 's|@''HAVE_FSEEKO''@|$(HAVE_FSEEKO)|g' \
+	      -e 's|@''HAVE_FTELLO''@|$(HAVE_FTELLO)|g' \
+	      -e 's|@''HAVE_PCLOSE''@|$(HAVE_PCLOSE)|g' \
+	      -e 's|@''HAVE_POPEN''@|$(HAVE_POPEN)|g' \
+	      -e 's|@''HAVE_RENAMEAT''@|$(HAVE_RENAMEAT)|g' \
+	      -e 's|@''HAVE_VASPRINTF''@|$(HAVE_VASPRINTF)|g' \
+	      -e 's|@''HAVE_VDPRINTF''@|$(HAVE_VDPRINTF)|g' \
+	      -e 's|@''REPLACE_DPRINTF''@|$(REPLACE_DPRINTF)|g' \
+	      -e 's|@''REPLACE_FCLOSE''@|$(REPLACE_FCLOSE)|g' \
+	      -e 's|@''REPLACE_FDOPEN''@|$(REPLACE_FDOPEN)|g' \
+	      -e 's|@''REPLACE_FFLUSH''@|$(REPLACE_FFLUSH)|g' \
+	      -e 's|@''REPLACE_FOPEN''@|$(REPLACE_FOPEN)|g' \
+	      -e 's|@''REPLACE_FPRINTF''@|$(REPLACE_FPRINTF)|g' \
+	      -e 's|@''REPLACE_FPURGE''@|$(REPLACE_FPURGE)|g' \
+	      -e 's|@''REPLACE_FREOPEN''@|$(REPLACE_FREOPEN)|g' \
+	      -e 's|@''REPLACE_FSEEK''@|$(REPLACE_FSEEK)|g' \
+	      -e 's|@''REPLACE_FSEEKO''@|$(REPLACE_FSEEKO)|g' \
+	      -e 's|@''REPLACE_FTELL''@|$(REPLACE_FTELL)|g' \
+	      -e 's|@''REPLACE_FTELLO''@|$(REPLACE_FTELLO)|g' \
+	      -e 's|@''REPLACE_GETDELIM''@|$(REPLACE_GETDELIM)|g' \
+	      -e 's|@''REPLACE_GETLINE''@|$(REPLACE_GETLINE)|g' \
+	      -e 's|@''REPLACE_OBSTACK_PRINTF''@|$(REPLACE_OBSTACK_PRINTF)|g' \
+	      -e 's|@''REPLACE_PERROR''@|$(REPLACE_PERROR)|g' \
+	      -e 's|@''REPLACE_POPEN''@|$(REPLACE_POPEN)|g' \
+	      -e 's|@''REPLACE_PRINTF''@|$(REPLACE_PRINTF)|g' \
+	      -e 's|@''REPLACE_REMOVE''@|$(REPLACE_REMOVE)|g' \
+	      -e 's|@''REPLACE_RENAME''@|$(REPLACE_RENAME)|g' \
+	      -e 's|@''REPLACE_RENAMEAT''@|$(REPLACE_RENAMEAT)|g' \
+	      -e 's|@''REPLACE_SNPRINTF''@|$(REPLACE_SNPRINTF)|g' \
+	      -e 's|@''REPLACE_SPRINTF''@|$(REPLACE_SPRINTF)|g' \
+	      -e 's|@''REPLACE_STDIO_READ_FUNCS''@|$(REPLACE_STDIO_READ_FUNCS)|g' \
+	      -e 's|@''REPLACE_STDIO_WRITE_FUNCS''@|$(REPLACE_STDIO_WRITE_FUNCS)|g' \
+	      -e 's|@''REPLACE_TMPFILE''@|$(REPLACE_TMPFILE)|g' \
+	      -e 's|@''REPLACE_VASPRINTF''@|$(REPLACE_VASPRINTF)|g' \
+	      -e 's|@''REPLACE_VDPRINTF''@|$(REPLACE_VDPRINTF)|g' \
+	      -e 's|@''REPLACE_VFPRINTF''@|$(REPLACE_VFPRINTF)|g' \
+	      -e 's|@''REPLACE_VPRINTF''@|$(REPLACE_VPRINTF)|g' \
+	      -e 's|@''REPLACE_VSNPRINTF''@|$(REPLACE_VSNPRINTF)|g' \
+	      -e 's|@''REPLACE_VSPRINTF''@|$(REPLACE_VSPRINTF)|g' \
+	      -e 's|@''ASM_SYMBOL_PREFIX''@|$(ASM_SYMBOL_PREFIX)|g' \
+	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += stdio.h stdio.h-t
+
+EXTRA_DIST += stdio.in.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.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
+  $(_NORETURN_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_STDLIB_H''@|$(NEXT_STDLIB_H)|g' \
+	      -e 's/@''GNULIB__EXIT''@/$(GNULIB__EXIT)/g' \
+	      -e 's/@''GNULIB_ATOLL''@/$(GNULIB_ATOLL)/g' \
+	      -e 's/@''GNULIB_CALLOC_POSIX''@/$(GNULIB_CALLOC_POSIX)/g' \
+	      -e 's/@''GNULIB_CANONICALIZE_FILE_NAME''@/$(GNULIB_CANONICALIZE_FILE_NAME)/g' \
+	      -e 's/@''GNULIB_GETLOADAVG''@/$(GNULIB_GETLOADAVG)/g' \
+	      -e 's/@''GNULIB_GETSUBOPT''@/$(GNULIB_GETSUBOPT)/g' \
+	      -e 's/@''GNULIB_GRANTPT''@/$(GNULIB_GRANTPT)/g' \
+	      -e 's/@''GNULIB_MALLOC_POSIX''@/$(GNULIB_MALLOC_POSIX)/g' \
+	      -e 's/@''GNULIB_MBTOWC''@/$(GNULIB_MBTOWC)/g' \
+	      -e 's/@''GNULIB_MKDTEMP''@/$(GNULIB_MKDTEMP)/g' \
+	      -e 's/@''GNULIB_MKOSTEMP''@/$(GNULIB_MKOSTEMP)/g' \
+	      -e 's/@''GNULIB_MKOSTEMPS''@/$(GNULIB_MKOSTEMPS)/g' \
+	      -e 's/@''GNULIB_MKSTEMP''@/$(GNULIB_MKSTEMP)/g' \
+	      -e 's/@''GNULIB_MKSTEMPS''@/$(GNULIB_MKSTEMPS)/g' \
+	      -e 's/@''GNULIB_POSIX_OPENPT''@/$(GNULIB_POSIX_OPENPT)/g' \
+	      -e 's/@''GNULIB_PTSNAME''@/$(GNULIB_PTSNAME)/g' \
+	      -e 's/@''GNULIB_PTSNAME_R''@/$(GNULIB_PTSNAME_R)/g' \
+	      -e 's/@''GNULIB_PUTENV''@/$(GNULIB_PUTENV)/g' \
+	      -e 's/@''GNULIB_QSORT_R''@/$(GNULIB_QSORT_R)/g' \
+	      -e 's/@''GNULIB_RANDOM''@/$(GNULIB_RANDOM)/g' \
+	      -e 's/@''GNULIB_RANDOM_R''@/$(GNULIB_RANDOM_R)/g' \
+	      -e 's/@''GNULIB_REALLOC_POSIX''@/$(GNULIB_REALLOC_POSIX)/g' \
+	      -e 's/@''GNULIB_REALPATH''@/$(GNULIB_REALPATH)/g' \
+	      -e 's/@''GNULIB_RPMATCH''@/$(GNULIB_RPMATCH)/g' \
+	      -e 's/@''GNULIB_SECURE_GETENV''@/$(GNULIB_SECURE_GETENV)/g' \
+	      -e 's/@''GNULIB_SETENV''@/$(GNULIB_SETENV)/g' \
+	      -e 's/@''GNULIB_STRTOD''@/$(GNULIB_STRTOD)/g' \
+	      -e 's/@''GNULIB_STRTOLL''@/$(GNULIB_STRTOLL)/g' \
+	      -e 's/@''GNULIB_STRTOULL''@/$(GNULIB_STRTOULL)/g' \
+	      -e 's/@''GNULIB_SYSTEM_POSIX''@/$(GNULIB_SYSTEM_POSIX)/g' \
+	      -e 's/@''GNULIB_UNLOCKPT''@/$(GNULIB_UNLOCKPT)/g' \
+	      -e 's/@''GNULIB_UNSETENV''@/$(GNULIB_UNSETENV)/g' \
+	      -e 's/@''GNULIB_WCTOMB''@/$(GNULIB_WCTOMB)/g' \
+	      < $(srcdir)/stdlib.in.h | \
+	  sed -e 's|@''HAVE__EXIT''@|$(HAVE__EXIT)|g' \
+	      -e 's|@''HAVE_ATOLL''@|$(HAVE_ATOLL)|g' \
+	      -e 's|@''HAVE_CANONICALIZE_FILE_NAME''@|$(HAVE_CANONICALIZE_FILE_NAME)|g' \
+	      -e 's|@''HAVE_DECL_GETLOADAVG''@|$(HAVE_DECL_GETLOADAVG)|g' \
+	      -e 's|@''HAVE_GETSUBOPT''@|$(HAVE_GETSUBOPT)|g' \
+	      -e 's|@''HAVE_GRANTPT''@|$(HAVE_GRANTPT)|g' \
+	      -e 's|@''HAVE_MKDTEMP''@|$(HAVE_MKDTEMP)|g' \
+	      -e 's|@''HAVE_MKOSTEMP''@|$(HAVE_MKOSTEMP)|g' \
+	      -e 's|@''HAVE_MKOSTEMPS''@|$(HAVE_MKOSTEMPS)|g' \
+	      -e 's|@''HAVE_MKSTEMP''@|$(HAVE_MKSTEMP)|g' \
+	      -e 's|@''HAVE_MKSTEMPS''@|$(HAVE_MKSTEMPS)|g' \
+	      -e 's|@''HAVE_POSIX_OPENPT''@|$(HAVE_POSIX_OPENPT)|g' \
+	      -e 's|@''HAVE_PTSNAME''@|$(HAVE_PTSNAME)|g' \
+	      -e 's|@''HAVE_PTSNAME_R''@|$(HAVE_PTSNAME_R)|g' \
+	      -e 's|@''HAVE_QSORT_R''@|$(HAVE_QSORT_R)|g' \
+	      -e 's|@''HAVE_RANDOM''@|$(HAVE_RANDOM)|g' \
+	      -e 's|@''HAVE_RANDOM_H''@|$(HAVE_RANDOM_H)|g' \
+	      -e 's|@''HAVE_RANDOM_R''@|$(HAVE_RANDOM_R)|g' \
+	      -e 's|@''HAVE_REALPATH''@|$(HAVE_REALPATH)|g' \
+	      -e 's|@''HAVE_RPMATCH''@|$(HAVE_RPMATCH)|g' \
+	      -e 's|@''HAVE_SECURE_GETENV''@|$(HAVE_SECURE_GETENV)|g' \
+	      -e 's|@''HAVE_DECL_SETENV''@|$(HAVE_DECL_SETENV)|g' \
+	      -e 's|@''HAVE_STRTOD''@|$(HAVE_STRTOD)|g' \
+	      -e 's|@''HAVE_STRTOLL''@|$(HAVE_STRTOLL)|g' \
+	      -e 's|@''HAVE_STRTOULL''@|$(HAVE_STRTOULL)|g' \
+	      -e 's|@''HAVE_STRUCT_RANDOM_DATA''@|$(HAVE_STRUCT_RANDOM_DATA)|g' \
+	      -e 's|@''HAVE_SYS_LOADAVG_H''@|$(HAVE_SYS_LOADAVG_H)|g' \
+	      -e 's|@''HAVE_UNLOCKPT''@|$(HAVE_UNLOCKPT)|g' \
+	      -e 's|@''HAVE_DECL_UNSETENV''@|$(HAVE_DECL_UNSETENV)|g' \
+	      -e 's|@''REPLACE_CALLOC''@|$(REPLACE_CALLOC)|g' \
+	      -e 's|@''REPLACE_CANONICALIZE_FILE_NAME''@|$(REPLACE_CANONICALIZE_FILE_NAME)|g' \
+	      -e 's|@''REPLACE_MALLOC''@|$(REPLACE_MALLOC)|g' \
+	      -e 's|@''REPLACE_MBTOWC''@|$(REPLACE_MBTOWC)|g' \
+	      -e 's|@''REPLACE_MKSTEMP''@|$(REPLACE_MKSTEMP)|g' \
+	      -e 's|@''REPLACE_PTSNAME''@|$(REPLACE_PTSNAME)|g' \
+	      -e 's|@''REPLACE_PTSNAME_R''@|$(REPLACE_PTSNAME_R)|g' \
+	      -e 's|@''REPLACE_PUTENV''@|$(REPLACE_PUTENV)|g' \
+	      -e 's|@''REPLACE_QSORT_R''@|$(REPLACE_QSORT_R)|g' \
+	      -e 's|@''REPLACE_RANDOM_R''@|$(REPLACE_RANDOM_R)|g' \
+	      -e 's|@''REPLACE_REALLOC''@|$(REPLACE_REALLOC)|g' \
+	      -e 's|@''REPLACE_REALPATH''@|$(REPLACE_REALPATH)|g' \
+	      -e 's|@''REPLACE_SETENV''@|$(REPLACE_SETENV)|g' \
+	      -e 's|@''REPLACE_STRTOD''@|$(REPLACE_STRTOD)|g' \
+	      -e 's|@''REPLACE_UNSETENV''@|$(REPLACE_UNSETENV)|g' \
+	      -e 's|@''REPLACE_WCTOMB''@|$(REPLACE_WCTOMB)|g' \
+	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+	      -e '/definition of _Noreturn/r $(_NORETURN_H)' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += stdlib.h stdlib.h-t
+
+EXTRA_DIST += stdlib.in.h
+
+## end   gnulib module stdlib
+
+## begin gnulib module stpcpy
+
+
+EXTRA_DIST += stpcpy.c
+
+EXTRA_libgnu_a_SOURCES += stpcpy.c
+
+## end   gnulib module stpcpy
+
+## begin gnulib module stpncpy
+
+
+EXTRA_DIST += stpncpy.c
+
+EXTRA_libgnu_a_SOURCES += stpncpy.c
+
+## end   gnulib module stpncpy
+
+## begin gnulib module strcase
+
+
+EXTRA_DIST += strcasecmp.c strncasecmp.c
+
+EXTRA_libgnu_a_SOURCES += strcasecmp.c strncasecmp.c
+
+## end   gnulib module strcase
+
+## begin gnulib module strchrnul
+
+
+EXTRA_DIST += strchrnul.c strchrnul.valgrind
+
+EXTRA_libgnu_a_SOURCES += strchrnul.c
+
+## end   gnulib module strchrnul
+
+## begin gnulib module strdup-posix
+
+if gl_GNULIB_ENABLED_f9850631dca91859e9cddac9359921c0
+
+endif
+EXTRA_DIST += strdup.c
+
+EXTRA_libgnu_a_SOURCES += strdup.c
+
+## end   gnulib module strdup-posix
+
+## begin gnulib module streq
+
+if gl_GNULIB_ENABLED_streq
+
+endif
+EXTRA_DIST += streq.h
+
+## end   gnulib module streq
+
+## begin gnulib module strerror
+
+
+EXTRA_DIST += strerror.c
+
+EXTRA_libgnu_a_SOURCES += strerror.c
+
+## end   gnulib module strerror
+
+## begin gnulib module strerror-override
+
+if gl_GNULIB_ENABLED_dbb57f49352be8fb86869629a254fb72
+
+endif
+EXTRA_DIST += strerror-override.c strerror-override.h
+
+EXTRA_libgnu_a_SOURCES += strerror-override.c
+
+## end   gnulib module strerror-override
+
+## 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.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_STRING_H''@|$(NEXT_STRING_H)|g' \
+	      -e 's/@''GNULIB_FFSL''@/$(GNULIB_FFSL)/g' \
+	      -e 's/@''GNULIB_FFSLL''@/$(GNULIB_FFSLL)/g' \
+	      -e 's/@''GNULIB_MBSLEN''@/$(GNULIB_MBSLEN)/g' \
+	      -e 's/@''GNULIB_MBSNLEN''@/$(GNULIB_MBSNLEN)/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_MEMCHR''@/$(GNULIB_MEMCHR)/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_RAWMEMCHR''@/$(GNULIB_RAWMEMCHR)/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_STRNCAT''@/$(GNULIB_STRNCAT)/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_STRSTR''@/$(GNULIB_STRSTR)/g' \
+	      -e 's/@''GNULIB_STRCASESTR''@/$(GNULIB_STRCASESTR)/g' \
+	      -e 's/@''GNULIB_STRTOK_R''@/$(GNULIB_STRTOK_R)/g' \
+	      -e 's/@''GNULIB_STRERROR''@/$(GNULIB_STRERROR)/g' \
+	      -e 's/@''GNULIB_STRERROR_R''@/$(GNULIB_STRERROR_R)/g' \
+	      -e 's/@''GNULIB_STRSIGNAL''@/$(GNULIB_STRSIGNAL)/g' \
+	      -e 's/@''GNULIB_STRVERSCMP''@/$(GNULIB_STRVERSCMP)/g' \
+	      < $(srcdir)/string.in.h | \
+	  sed -e 's|@''HAVE_FFSL''@|$(HAVE_FFSL)|g' \
+	      -e 's|@''HAVE_FFSLL''@|$(HAVE_FFSLL)|g' \
+	      -e 's|@''HAVE_MBSLEN''@|$(HAVE_MBSLEN)|g' \
+	      -e 's|@''HAVE_MEMCHR''@|$(HAVE_MEMCHR)|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_RAWMEMCHR''@|$(HAVE_RAWMEMCHR)|g' \
+	      -e 's|@''HAVE_STPCPY''@|$(HAVE_STPCPY)|g' \
+	      -e 's|@''HAVE_STPNCPY''@|$(HAVE_STPNCPY)|g' \
+	      -e 's|@''HAVE_STRCHRNUL''@|$(HAVE_STRCHRNUL)|g' \
+	      -e 's|@''HAVE_DECL_STRDUP''@|$(HAVE_DECL_STRDUP)|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 's|@''HAVE_DECL_STRERROR_R''@|$(HAVE_DECL_STRERROR_R)|g' \
+	      -e 's|@''HAVE_DECL_STRSIGNAL''@|$(HAVE_DECL_STRSIGNAL)|g' \
+	      -e 's|@''HAVE_STRVERSCMP''@|$(HAVE_STRVERSCMP)|g' \
+	      -e 's|@''REPLACE_STPNCPY''@|$(REPLACE_STPNCPY)|g' \
+	      -e 's|@''REPLACE_MEMCHR''@|$(REPLACE_MEMCHR)|g' \
+	      -e 's|@''REPLACE_MEMMEM''@|$(REPLACE_MEMMEM)|g' \
+	      -e 's|@''REPLACE_STRCASESTR''@|$(REPLACE_STRCASESTR)|g' \
+	      -e 's|@''REPLACE_STRCHRNUL''@|$(REPLACE_STRCHRNUL)|g' \
+	      -e 's|@''REPLACE_STRDUP''@|$(REPLACE_STRDUP)|g' \
+	      -e 's|@''REPLACE_STRSTR''@|$(REPLACE_STRSTR)|g' \
+	      -e 's|@''REPLACE_STRERROR''@|$(REPLACE_STRERROR)|g' \
+	      -e 's|@''REPLACE_STRERROR_R''@|$(REPLACE_STRERROR_R)|g' \
+	      -e 's|@''REPLACE_STRNCAT''@|$(REPLACE_STRNCAT)|g' \
+	      -e 's|@''REPLACE_STRNDUP''@|$(REPLACE_STRNDUP)|g' \
+	      -e 's|@''REPLACE_STRNLEN''@|$(REPLACE_STRNLEN)|g' \
+	      -e 's|@''REPLACE_STRSIGNAL''@|$(REPLACE_STRSIGNAL)|g' \
+	      -e 's|@''REPLACE_STRTOK_R''@|$(REPLACE_STRTOK_R)|g' \
+	      -e 's|@''UNDEFINE_STRTOK_R''@|$(UNDEFINE_STRTOK_R)|g' \
+	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \
+	      < $(srcdir)/string.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += string.h string.h-t
+
+EXTRA_DIST += string.in.h
+
+## end   gnulib module string
+
+## begin gnulib module strings
+
+BUILT_SOURCES += strings.h
+
+# We need the following in order to create <strings.h> when the system
+# doesn't have one that works with the given compiler.
+strings.h: strings.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) $(ARG_NONNULL_H)
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''HAVE_STRINGS_H''@|$(HAVE_STRINGS_H)|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_STRINGS_H''@|$(NEXT_STRINGS_H)|g' \
+	      -e 's|@''GNULIB_FFS''@|$(GNULIB_FFS)|g' \
+	      -e 's|@''HAVE_FFS''@|$(HAVE_FFS)|g' \
+	      -e 's|@''HAVE_STRCASECMP''@|$(HAVE_STRCASECMP)|g' \
+	      -e 's|@''HAVE_DECL_STRNCASECMP''@|$(HAVE_DECL_STRNCASECMP)|g' \
+	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+	      < $(srcdir)/strings.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += strings.h strings.h-t
+
+EXTRA_DIST += strings.in.h
+
+## end   gnulib module strings
+
+## begin gnulib module strndup
+
+
+EXTRA_DIST += strndup.c
+
+EXTRA_libgnu_a_SOURCES += strndup.c
+
+## end   gnulib module strndup
+
+## begin gnulib module strnlen
+
+if gl_GNULIB_ENABLED_strnlen
+
+endif
+EXTRA_DIST += strnlen.c
+
+EXTRA_libgnu_a_SOURCES += strnlen.c
+
+## end   gnulib module strnlen
+
+## begin gnulib module strnlen1
+
+if gl_GNULIB_ENABLED_strnlen1
+libgnu_a_SOURCES += strnlen1.h strnlen1.c
+
+endif
+## end   gnulib module strnlen1
+
+## begin gnulib module strsep
+
+
+EXTRA_DIST += strsep.c
+
+EXTRA_libgnu_a_SOURCES += strsep.c
+
+## end   gnulib module strsep
+
+## 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.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
+	$(AM_V_at)$(MKDIR_P) sys
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_SYS_STAT_H''@|$(NEXT_SYS_STAT_H)|g' \
+	      -e 's|@''WINDOWS_64_BIT_ST_SIZE''@|$(WINDOWS_64_BIT_ST_SIZE)|g' \
+	      -e 's/@''GNULIB_FCHMODAT''@/$(GNULIB_FCHMODAT)/g' \
+	      -e 's/@''GNULIB_FSTAT''@/$(GNULIB_FSTAT)/g' \
+	      -e 's/@''GNULIB_FSTATAT''@/$(GNULIB_FSTATAT)/g' \
+	      -e 's/@''GNULIB_FUTIMENS''@/$(GNULIB_FUTIMENS)/g' \
+	      -e 's/@''GNULIB_LCHMOD''@/$(GNULIB_LCHMOD)/g' \
+	      -e 's/@''GNULIB_LSTAT''@/$(GNULIB_LSTAT)/g' \
+	      -e 's/@''GNULIB_MKDIRAT''@/$(GNULIB_MKDIRAT)/g' \
+	      -e 's/@''GNULIB_MKFIFO''@/$(GNULIB_MKFIFO)/g' \
+	      -e 's/@''GNULIB_MKFIFOAT''@/$(GNULIB_MKFIFOAT)/g' \
+	      -e 's/@''GNULIB_MKNOD''@/$(GNULIB_MKNOD)/g' \
+	      -e 's/@''GNULIB_MKNODAT''@/$(GNULIB_MKNODAT)/g' \
+	      -e 's/@''GNULIB_STAT''@/$(GNULIB_STAT)/g' \
+	      -e 's/@''GNULIB_UTIMENSAT''@/$(GNULIB_UTIMENSAT)/g' \
+	      -e 's|@''HAVE_FCHMODAT''@|$(HAVE_FCHMODAT)|g' \
+	      -e 's|@''HAVE_FSTATAT''@|$(HAVE_FSTATAT)|g' \
+	      -e 's|@''HAVE_FUTIMENS''@|$(HAVE_FUTIMENS)|g' \
+	      -e 's|@''HAVE_LCHMOD''@|$(HAVE_LCHMOD)|g' \
+	      -e 's|@''HAVE_LSTAT''@|$(HAVE_LSTAT)|g' \
+	      -e 's|@''HAVE_MKDIRAT''@|$(HAVE_MKDIRAT)|g' \
+	      -e 's|@''HAVE_MKFIFO''@|$(HAVE_MKFIFO)|g' \
+	      -e 's|@''HAVE_MKFIFOAT''@|$(HAVE_MKFIFOAT)|g' \
+	      -e 's|@''HAVE_MKNOD''@|$(HAVE_MKNOD)|g' \
+	      -e 's|@''HAVE_MKNODAT''@|$(HAVE_MKNODAT)|g' \
+	      -e 's|@''HAVE_UTIMENSAT''@|$(HAVE_UTIMENSAT)|g' \
+	      -e 's|@''REPLACE_FSTAT''@|$(REPLACE_FSTAT)|g' \
+	      -e 's|@''REPLACE_FSTATAT''@|$(REPLACE_FSTATAT)|g' \
+	      -e 's|@''REPLACE_FUTIMENS''@|$(REPLACE_FUTIMENS)|g' \
+	      -e 's|@''REPLACE_LSTAT''@|$(REPLACE_LSTAT)|g' \
+	      -e 's|@''REPLACE_MKDIR''@|$(REPLACE_MKDIR)|g' \
+	      -e 's|@''REPLACE_MKFIFO''@|$(REPLACE_MKFIFO)|g' \
+	      -e 's|@''REPLACE_MKNOD''@|$(REPLACE_MKNOD)|g' \
+	      -e 's|@''REPLACE_STAT''@|$(REPLACE_STAT)|g' \
+	      -e 's|@''REPLACE_UTIMENSAT''@|$(REPLACE_UTIMENSAT)|g' \
+	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+	      < $(srcdir)/sys_stat.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += sys/stat.h sys/stat.h-t
+MOSTLYCLEANDIRS += sys
+
+EXTRA_DIST += sys_stat.in.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.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
+	$(AM_V_at)$(MKDIR_P) sys
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's/@''HAVE_SYS_TIME_H''@/$(HAVE_SYS_TIME_H)/g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_SYS_TIME_H''@|$(NEXT_SYS_TIME_H)|g' \
+	      -e 's/@''GNULIB_GETTIMEOFDAY''@/$(GNULIB_GETTIMEOFDAY)/g' \
+	      -e 's|@''HAVE_WINSOCK2_H''@|$(HAVE_WINSOCK2_H)|g' \
+	      -e 's/@''HAVE_GETTIMEOFDAY''@/$(HAVE_GETTIMEOFDAY)/g' \
+	      -e 's/@''HAVE_STRUCT_TIMEVAL''@/$(HAVE_STRUCT_TIMEVAL)/g' \
+	      -e 's/@''REPLACE_GETTIMEOFDAY''@/$(REPLACE_GETTIMEOFDAY)/g' \
+	      -e 's/@''REPLACE_STRUCT_TIMEVAL''@/$(REPLACE_STRUCT_TIMEVAL)/g' \
+	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+	      < $(srcdir)/sys_time.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += sys/time.h sys/time.h-t
+
+EXTRA_DIST += sys_time.in.h
+
+## end   gnulib module sys_time
+
+## begin gnulib module sys_types
+
+BUILT_SOURCES += sys/types.h
+
+# We need the following in order to create <sys/types.h> when the system
+# doesn't have one that works with the given compiler.
+sys/types.h: sys_types.in.h $(top_builddir)/config.status
+	$(AM_V_at)$(MKDIR_P) sys
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_SYS_TYPES_H''@|$(NEXT_SYS_TYPES_H)|g' \
+	      -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \
+	      < $(srcdir)/sys_types.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += sys/types.h sys/types.h-t
+
+EXTRA_DIST += sys_types.in.h
+
+## end   gnulib module sys_types
+
+## begin gnulib module sys_utsname
+
+BUILT_SOURCES += sys/utsname.h
+
+# We need the following in order to create <sys/utsname.h> when the system
+# does not have one.
+sys/utsname.h: sys_utsname.in.h $(top_builddir)/config.status $(WARN_ON_USE_H) $(ARG_NONNULL_H)
+	$(AM_V_at)$(MKDIR_P) sys
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's/@''HAVE_SYS_UTSNAME_H''@/$(HAVE_SYS_UTSNAME_H)/g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_SYS_UTSNAME_H''@|$(NEXT_SYS_UTSNAME_H)|g' \
+	      -e 's/@''GNULIB_UNAME''@/$(GNULIB_UNAME)/g' \
+	      -e 's|@''HAVE_STRUCT_UTSNAME''@|$(HAVE_STRUCT_UTSNAME)|g' \
+	      -e 's|@''HAVE_UNAME''@|$(HAVE_UNAME)|g' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+	      < $(srcdir)/sys_utsname.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += sys/utsname.h sys/utsname.h-t
+MOSTLYCLEANDIRS += sys
+
+EXTRA_DIST += sys_utsname.in.h
+
+## end   gnulib module sys_utsname
+
+## begin gnulib module sys_wait
+
+BUILT_SOURCES += sys/wait.h
+
+# We need the following in order to create <sys/wait.h> when the system
+# has one that is incomplete.
+sys/wait.h: sys_wait.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H)
+	$(AM_V_at)$(MKDIR_P) sys
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_SYS_WAIT_H''@|$(NEXT_SYS_WAIT_H)|g' \
+	      -e 's/@''GNULIB_WAITPID''@/$(GNULIB_WAITPID)/g' \
+	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+	      < $(srcdir)/sys_wait.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += sys/wait.h sys/wait.h-t
+MOSTLYCLEANDIRS += sys
+
+EXTRA_DIST += sys_wait.in.h
+
+## end   gnulib module sys_wait
+
+## 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.
+if GL_GENERATE_SYSEXITS_H
+sysexits.h: sysexits.in.h $(top_builddir)/config.status
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''HAVE_SYSEXITS_H''@|$(HAVE_SYSEXITS_H)|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_SYSEXITS_H''@|$(NEXT_SYSEXITS_H)|g' \
+	      < $(srcdir)/sysexits.in.h; \
+	} > $@-t && \
+	mv -f $@-t $@
+else
+sysexits.h: $(top_builddir)/config.status
+	rm -f $@
+endif
+MOSTLYCLEANFILES += sysexits.h sysexits.h-t
+
+EXTRA_DIST += sysexits.in.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.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_TIME_H''@|$(NEXT_TIME_H)|g' \
+	      -e 's/@''GNULIB_GETTIMEOFDAY''@/$(GNULIB_GETTIMEOFDAY)/g' \
+	      -e 's/@''GNULIB_MKTIME''@/$(GNULIB_MKTIME)/g' \
+	      -e 's/@''GNULIB_NANOSLEEP''@/$(GNULIB_NANOSLEEP)/g' \
+	      -e 's/@''GNULIB_STRPTIME''@/$(GNULIB_STRPTIME)/g' \
+	      -e 's/@''GNULIB_TIMEGM''@/$(GNULIB_TIMEGM)/g' \
+	      -e 's/@''GNULIB_TIME_R''@/$(GNULIB_TIME_R)/g' \
+	      -e 's/@''GNULIB_TIME_RZ''@/$(GNULIB_TIME_RZ)/g' \
+	      -e 's|@''HAVE_DECL_LOCALTIME_R''@|$(HAVE_DECL_LOCALTIME_R)|g' \
+	      -e 's|@''HAVE_NANOSLEEP''@|$(HAVE_NANOSLEEP)|g' \
+	      -e 's|@''HAVE_STRPTIME''@|$(HAVE_STRPTIME)|g' \
+	      -e 's|@''HAVE_TIMEGM''@|$(HAVE_TIMEGM)|g' \
+	      -e 's|@''HAVE_TIMEZONE_T''@|$(HAVE_TIMEZONE_T)|g' \
+	      -e 's|@''REPLACE_GMTIME''@|$(REPLACE_GMTIME)|g' \
+	      -e 's|@''REPLACE_LOCALTIME''@|$(REPLACE_LOCALTIME)|g' \
+	      -e 's|@''REPLACE_LOCALTIME_R''@|$(REPLACE_LOCALTIME_R)|g' \
+	      -e 's|@''REPLACE_MKTIME''@|$(REPLACE_MKTIME)|g' \
+	      -e 's|@''REPLACE_NANOSLEEP''@|$(REPLACE_NANOSLEEP)|g' \
+	      -e 's|@''REPLACE_TIMEGM''@|$(REPLACE_TIMEGM)|g' \
+	      -e 's|@''PTHREAD_H_DEFINES_STRUCT_TIMESPEC''@|$(PTHREAD_H_DEFINES_STRUCT_TIMESPEC)|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' \
+	      -e 's|@''UNISTD_H_DEFINES_STRUCT_TIMESPEC''@|$(UNISTD_H_DEFINES_STRUCT_TIMESPEC)|g' \
+	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+	      < $(srcdir)/time.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += time.h time.h-t
+
+EXTRA_DIST += time.in.h
+
+## end   gnulib module time
+
+## begin gnulib module unistd
+
+BUILT_SOURCES += unistd.h
+libgnu_a_SOURCES += unistd.c
+
+# We need the following in order to create an empty placeholder for
+# <unistd.h> when the system doesn't have one.
+unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''HAVE_UNISTD_H''@|$(HAVE_UNISTD_H)|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_UNISTD_H''@|$(NEXT_UNISTD_H)|g' \
+	      -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \
+	      -e 's/@''GNULIB_CHDIR''@/$(GNULIB_CHDIR)/g' \
+	      -e 's/@''GNULIB_CHOWN''@/$(GNULIB_CHOWN)/g' \
+	      -e 's/@''GNULIB_CLOSE''@/$(GNULIB_CLOSE)/g' \
+	      -e 's/@''GNULIB_DUP''@/$(GNULIB_DUP)/g' \
+	      -e 's/@''GNULIB_DUP2''@/$(GNULIB_DUP2)/g' \
+	      -e 's/@''GNULIB_DUP3''@/$(GNULIB_DUP3)/g' \
+	      -e 's/@''GNULIB_ENVIRON''@/$(GNULIB_ENVIRON)/g' \
+	      -e 's/@''GNULIB_EUIDACCESS''@/$(GNULIB_EUIDACCESS)/g' \
+	      -e 's/@''GNULIB_FACCESSAT''@/$(GNULIB_FACCESSAT)/g' \
+	      -e 's/@''GNULIB_FCHDIR''@/$(GNULIB_FCHDIR)/g' \
+	      -e 's/@''GNULIB_FCHOWNAT''@/$(GNULIB_FCHOWNAT)/g' \
+	      -e 's/@''GNULIB_FDATASYNC''@/$(GNULIB_FDATASYNC)/g' \
+	      -e 's/@''GNULIB_FSYNC''@/$(GNULIB_FSYNC)/g' \
+	      -e 's/@''GNULIB_FTRUNCATE''@/$(GNULIB_FTRUNCATE)/g' \
+	      -e 's/@''GNULIB_GETCWD''@/$(GNULIB_GETCWD)/g' \
+	      -e 's/@''GNULIB_GETDOMAINNAME''@/$(GNULIB_GETDOMAINNAME)/g' \
+	      -e 's/@''GNULIB_GETDTABLESIZE''@/$(GNULIB_GETDTABLESIZE)/g' \
+	      -e 's/@''GNULIB_GETGROUPS''@/$(GNULIB_GETGROUPS)/g' \
+	      -e 's/@''GNULIB_GETHOSTNAME''@/$(GNULIB_GETHOSTNAME)/g' \
+	      -e 's/@''GNULIB_GETLOGIN''@/$(GNULIB_GETLOGIN)/g' \
+	      -e 's/@''GNULIB_GETLOGIN_R''@/$(GNULIB_GETLOGIN_R)/g' \
+	      -e 's/@''GNULIB_GETPAGESIZE''@/$(GNULIB_GETPAGESIZE)/g' \
+	      -e 's/@''GNULIB_GETUSERSHELL''@/$(GNULIB_GETUSERSHELL)/g' \
+	      -e 's/@''GNULIB_GROUP_MEMBER''@/$(GNULIB_GROUP_MEMBER)/g' \
+	      -e 's/@''GNULIB_ISATTY''@/$(GNULIB_ISATTY)/g' \
+	      -e 's/@''GNULIB_LCHOWN''@/$(GNULIB_LCHOWN)/g' \
+	      -e 's/@''GNULIB_LINK''@/$(GNULIB_LINK)/g' \
+	      -e 's/@''GNULIB_LINKAT''@/$(GNULIB_LINKAT)/g' \
+	      -e 's/@''GNULIB_LSEEK''@/$(GNULIB_LSEEK)/g' \
+	      -e 's/@''GNULIB_PIPE''@/$(GNULIB_PIPE)/g' \
+	      -e 's/@''GNULIB_PIPE2''@/$(GNULIB_PIPE2)/g' \
+	      -e 's/@''GNULIB_PREAD''@/$(GNULIB_PREAD)/g' \
+	      -e 's/@''GNULIB_PWRITE''@/$(GNULIB_PWRITE)/g' \
+	      -e 's/@''GNULIB_READ''@/$(GNULIB_READ)/g' \
+	      -e 's/@''GNULIB_READLINK''@/$(GNULIB_READLINK)/g' \
+	      -e 's/@''GNULIB_READLINKAT''@/$(GNULIB_READLINKAT)/g' \
+	      -e 's/@''GNULIB_RMDIR''@/$(GNULIB_RMDIR)/g' \
+	      -e 's/@''GNULIB_SETHOSTNAME''@/$(GNULIB_SETHOSTNAME)/g' \
+	      -e 's/@''GNULIB_SLEEP''@/$(GNULIB_SLEEP)/g' \
+	      -e 's/@''GNULIB_SYMLINK''@/$(GNULIB_SYMLINK)/g' \
+	      -e 's/@''GNULIB_SYMLINKAT''@/$(GNULIB_SYMLINKAT)/g' \
+	      -e 's/@''GNULIB_TTYNAME_R''@/$(GNULIB_TTYNAME_R)/g' \
+	      -e 's/@''GNULIB_UNISTD_H_GETOPT''@/0$(GNULIB_GL_UNISTD_H_GETOPT)/g' \
+	      -e 's/@''GNULIB_UNISTD_H_NONBLOCKING''@/$(GNULIB_UNISTD_H_NONBLOCKING)/g' \
+	      -e 's/@''GNULIB_UNISTD_H_SIGPIPE''@/$(GNULIB_UNISTD_H_SIGPIPE)/g' \
+	      -e 's/@''GNULIB_UNLINK''@/$(GNULIB_UNLINK)/g' \
+	      -e 's/@''GNULIB_UNLINKAT''@/$(GNULIB_UNLINKAT)/g' \
+	      -e 's/@''GNULIB_USLEEP''@/$(GNULIB_USLEEP)/g' \
+	      -e 's/@''GNULIB_WRITE''@/$(GNULIB_WRITE)/g' \
+	      < $(srcdir)/unistd.in.h | \
+	  sed -e 's|@''HAVE_CHOWN''@|$(HAVE_CHOWN)|g' \
+	      -e 's|@''HAVE_DUP2''@|$(HAVE_DUP2)|g' \
+	      -e 's|@''HAVE_DUP3''@|$(HAVE_DUP3)|g' \
+	      -e 's|@''HAVE_EUIDACCESS''@|$(HAVE_EUIDACCESS)|g' \
+	      -e 's|@''HAVE_FACCESSAT''@|$(HAVE_FACCESSAT)|g' \
+	      -e 's|@''HAVE_FCHDIR''@|$(HAVE_FCHDIR)|g' \
+	      -e 's|@''HAVE_FCHOWNAT''@|$(HAVE_FCHOWNAT)|g' \
+	      -e 's|@''HAVE_FDATASYNC''@|$(HAVE_FDATASYNC)|g' \
+	      -e 's|@''HAVE_FSYNC''@|$(HAVE_FSYNC)|g' \
+	      -e 's|@''HAVE_FTRUNCATE''@|$(HAVE_FTRUNCATE)|g' \
+	      -e 's|@''HAVE_GETDTABLESIZE''@|$(HAVE_GETDTABLESIZE)|g' \
+	      -e 's|@''HAVE_GETGROUPS''@|$(HAVE_GETGROUPS)|g' \
+	      -e 's|@''HAVE_GETHOSTNAME''@|$(HAVE_GETHOSTNAME)|g' \
+	      -e 's|@''HAVE_GETPAGESIZE''@|$(HAVE_GETPAGESIZE)|g' \
+	      -e 's|@''HAVE_GROUP_MEMBER''@|$(HAVE_GROUP_MEMBER)|g' \
+	      -e 's|@''HAVE_LCHOWN''@|$(HAVE_LCHOWN)|g' \
+	      -e 's|@''HAVE_LINK''@|$(HAVE_LINK)|g' \
+	      -e 's|@''HAVE_LINKAT''@|$(HAVE_LINKAT)|g' \
+	      -e 's|@''HAVE_PIPE''@|$(HAVE_PIPE)|g' \
+	      -e 's|@''HAVE_PIPE2''@|$(HAVE_PIPE2)|g' \
+	      -e 's|@''HAVE_PREAD''@|$(HAVE_PREAD)|g' \
+	      -e 's|@''HAVE_PWRITE''@|$(HAVE_PWRITE)|g' \
+	      -e 's|@''HAVE_READLINK''@|$(HAVE_READLINK)|g' \
+	      -e 's|@''HAVE_READLINKAT''@|$(HAVE_READLINKAT)|g' \
+	      -e 's|@''HAVE_SETHOSTNAME''@|$(HAVE_SETHOSTNAME)|g' \
+	      -e 's|@''HAVE_SLEEP''@|$(HAVE_SLEEP)|g' \
+	      -e 's|@''HAVE_SYMLINK''@|$(HAVE_SYMLINK)|g' \
+	      -e 's|@''HAVE_SYMLINKAT''@|$(HAVE_SYMLINKAT)|g' \
+	      -e 's|@''HAVE_UNLINKAT''@|$(HAVE_UNLINKAT)|g' \
+	      -e 's|@''HAVE_USLEEP''@|$(HAVE_USLEEP)|g' \
+	      -e 's|@''HAVE_DECL_ENVIRON''@|$(HAVE_DECL_ENVIRON)|g' \
+	      -e 's|@''HAVE_DECL_FCHDIR''@|$(HAVE_DECL_FCHDIR)|g' \
+	      -e 's|@''HAVE_DECL_FDATASYNC''@|$(HAVE_DECL_FDATASYNC)|g' \
+	      -e 's|@''HAVE_DECL_GETDOMAINNAME''@|$(HAVE_DECL_GETDOMAINNAME)|g' \
+	      -e 's|@''HAVE_DECL_GETLOGIN''@|$(HAVE_DECL_GETLOGIN)|g' \
+	      -e 's|@''HAVE_DECL_GETLOGIN_R''@|$(HAVE_DECL_GETLOGIN_R)|g' \
+	      -e 's|@''HAVE_DECL_GETPAGESIZE''@|$(HAVE_DECL_GETPAGESIZE)|g' \
+	      -e 's|@''HAVE_DECL_GETUSERSHELL''@|$(HAVE_DECL_GETUSERSHELL)|g' \
+	      -e 's|@''HAVE_DECL_SETHOSTNAME''@|$(HAVE_DECL_SETHOSTNAME)|g' \
+	      -e 's|@''HAVE_DECL_TTYNAME_R''@|$(HAVE_DECL_TTYNAME_R)|g' \
+	      -e 's|@''HAVE_OS_H''@|$(HAVE_OS_H)|g' \
+	      -e 's|@''HAVE_SYS_PARAM_H''@|$(HAVE_SYS_PARAM_H)|g' \
+	  | \
+	  sed -e 's|@''REPLACE_CHOWN''@|$(REPLACE_CHOWN)|g' \
+	      -e 's|@''REPLACE_CLOSE''@|$(REPLACE_CLOSE)|g' \
+	      -e 's|@''REPLACE_DUP''@|$(REPLACE_DUP)|g' \
+	      -e 's|@''REPLACE_DUP2''@|$(REPLACE_DUP2)|g' \
+	      -e 's|@''REPLACE_FCHOWNAT''@|$(REPLACE_FCHOWNAT)|g' \
+	      -e 's|@''REPLACE_FTRUNCATE''@|$(REPLACE_FTRUNCATE)|g' \
+	      -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \
+	      -e 's|@''REPLACE_GETDOMAINNAME''@|$(REPLACE_GETDOMAINNAME)|g' \
+	      -e 's|@''REPLACE_GETDTABLESIZE''@|$(REPLACE_GETDTABLESIZE)|g' \
+	      -e 's|@''REPLACE_GETLOGIN_R''@|$(REPLACE_GETLOGIN_R)|g' \
+	      -e 's|@''REPLACE_GETGROUPS''@|$(REPLACE_GETGROUPS)|g' \
+	      -e 's|@''REPLACE_GETPAGESIZE''@|$(REPLACE_GETPAGESIZE)|g' \
+	      -e 's|@''REPLACE_ISATTY''@|$(REPLACE_ISATTY)|g' \
+	      -e 's|@''REPLACE_LCHOWN''@|$(REPLACE_LCHOWN)|g' \
+	      -e 's|@''REPLACE_LINK''@|$(REPLACE_LINK)|g' \
+	      -e 's|@''REPLACE_LINKAT''@|$(REPLACE_LINKAT)|g' \
+	      -e 's|@''REPLACE_LSEEK''@|$(REPLACE_LSEEK)|g' \
+	      -e 's|@''REPLACE_PREAD''@|$(REPLACE_PREAD)|g' \
+	      -e 's|@''REPLACE_PWRITE''@|$(REPLACE_PWRITE)|g' \
+	      -e 's|@''REPLACE_READ''@|$(REPLACE_READ)|g' \
+	      -e 's|@''REPLACE_READLINK''@|$(REPLACE_READLINK)|g' \
+	      -e 's|@''REPLACE_READLINKAT''@|$(REPLACE_READLINKAT)|g' \
+	      -e 's|@''REPLACE_RMDIR''@|$(REPLACE_RMDIR)|g' \
+	      -e 's|@''REPLACE_SLEEP''@|$(REPLACE_SLEEP)|g' \
+	      -e 's|@''REPLACE_SYMLINK''@|$(REPLACE_SYMLINK)|g' \
+	      -e 's|@''REPLACE_SYMLINKAT''@|$(REPLACE_SYMLINKAT)|g' \
+	      -e 's|@''REPLACE_TTYNAME_R''@|$(REPLACE_TTYNAME_R)|g' \
+	      -e 's|@''REPLACE_UNLINK''@|$(REPLACE_UNLINK)|g' \
+	      -e 's|@''REPLACE_UNLINKAT''@|$(REPLACE_UNLINKAT)|g' \
+	      -e 's|@''REPLACE_USLEEP''@|$(REPLACE_USLEEP)|g' \
+	      -e 's|@''REPLACE_WRITE''@|$(REPLACE_WRITE)|g' \
+	      -e 's|@''UNISTD_H_HAVE_WINSOCK2_H''@|$(UNISTD_H_HAVE_WINSOCK2_H)|g' \
+	      -e 's|@''UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS''@|$(UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS)|g' \
+	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += unistd.h unistd.h-t
+
+EXTRA_DIST += unistd.in.h
+
+## end   gnulib module unistd
+
+## begin gnulib module unistd-safer
+
+libgnu_a_SOURCES += dup-safer.c fd-safer.c pipe-safer.c
+
+EXTRA_DIST += unistd--.h unistd-safer.h
+
+## end   gnulib module unistd-safer
+
+## 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_libgnu_a_SOURCES += asnprintf.c printf-args.c printf-parse.c vasnprintf.c
+
+## end   gnulib module vasnprintf
+
+## begin gnulib module verify
+
+
+EXTRA_DIST += verify.h
+
+## end   gnulib module verify
+
+## begin gnulib module vsnprintf
+
+
+EXTRA_DIST += vsnprintf.c
+
+EXTRA_libgnu_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.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''HAVE_FEATURES_H''@|$(HAVE_FEATURES_H)|g' \
+	      -e 's|@''NEXT_WCHAR_H''@|$(NEXT_WCHAR_H)|g' \
+	      -e 's|@''HAVE_WCHAR_H''@|$(HAVE_WCHAR_H)|g' \
+	      -e 's/@''GNULIB_OVERRIDES_WINT_T''@/$(GNULIB_OVERRIDES_WINT_T)/g' \
+	      -e 's/@''GNULIB_BTOWC''@/$(GNULIB_BTOWC)/g' \
+	      -e 's/@''GNULIB_WCTOB''@/$(GNULIB_WCTOB)/g' \
+	      -e 's/@''GNULIB_MBSINIT''@/$(GNULIB_MBSINIT)/g' \
+	      -e 's/@''GNULIB_MBRTOWC''@/$(GNULIB_MBRTOWC)/g' \
+	      -e 's/@''GNULIB_MBRLEN''@/$(GNULIB_MBRLEN)/g' \
+	      -e 's/@''GNULIB_MBSRTOWCS''@/$(GNULIB_MBSRTOWCS)/g' \
+	      -e 's/@''GNULIB_MBSNRTOWCS''@/$(GNULIB_MBSNRTOWCS)/g' \
+	      -e 's/@''GNULIB_WCRTOMB''@/$(GNULIB_WCRTOMB)/g' \
+	      -e 's/@''GNULIB_WCSRTOMBS''@/$(GNULIB_WCSRTOMBS)/g' \
+	      -e 's/@''GNULIB_WCSNRTOMBS''@/$(GNULIB_WCSNRTOMBS)/g' \
+	      -e 's/@''GNULIB_WCWIDTH''@/$(GNULIB_WCWIDTH)/g' \
+	      -e 's/@''GNULIB_WMEMCHR''@/$(GNULIB_WMEMCHR)/g' \
+	      -e 's/@''GNULIB_WMEMCMP''@/$(GNULIB_WMEMCMP)/g' \
+	      -e 's/@''GNULIB_WMEMCPY''@/$(GNULIB_WMEMCPY)/g' \
+	      -e 's/@''GNULIB_WMEMMOVE''@/$(GNULIB_WMEMMOVE)/g' \
+	      -e 's/@''GNULIB_WMEMSET''@/$(GNULIB_WMEMSET)/g' \
+	      -e 's/@''GNULIB_WCSLEN''@/$(GNULIB_WCSLEN)/g' \
+	      -e 's/@''GNULIB_WCSNLEN''@/$(GNULIB_WCSNLEN)/g' \
+	      -e 's/@''GNULIB_WCSCPY''@/$(GNULIB_WCSCPY)/g' \
+	      -e 's/@''GNULIB_WCPCPY''@/$(GNULIB_WCPCPY)/g' \
+	      -e 's/@''GNULIB_WCSNCPY''@/$(GNULIB_WCSNCPY)/g' \
+	      -e 's/@''GNULIB_WCPNCPY''@/$(GNULIB_WCPNCPY)/g' \
+	      -e 's/@''GNULIB_WCSCAT''@/$(GNULIB_WCSCAT)/g' \
+	      -e 's/@''GNULIB_WCSNCAT''@/$(GNULIB_WCSNCAT)/g' \
+	      -e 's/@''GNULIB_WCSCMP''@/$(GNULIB_WCSCMP)/g' \
+	      -e 's/@''GNULIB_WCSNCMP''@/$(GNULIB_WCSNCMP)/g' \
+	      -e 's/@''GNULIB_WCSCASECMP''@/$(GNULIB_WCSCASECMP)/g' \
+	      -e 's/@''GNULIB_WCSNCASECMP''@/$(GNULIB_WCSNCASECMP)/g' \
+	      -e 's/@''GNULIB_WCSCOLL''@/$(GNULIB_WCSCOLL)/g' \
+	      -e 's/@''GNULIB_WCSXFRM''@/$(GNULIB_WCSXFRM)/g' \
+	      -e 's/@''GNULIB_WCSDUP''@/$(GNULIB_WCSDUP)/g' \
+	      -e 's/@''GNULIB_WCSCHR''@/$(GNULIB_WCSCHR)/g' \
+	      -e 's/@''GNULIB_WCSRCHR''@/$(GNULIB_WCSRCHR)/g' \
+	      -e 's/@''GNULIB_WCSCSPN''@/$(GNULIB_WCSCSPN)/g' \
+	      -e 's/@''GNULIB_WCSSPN''@/$(GNULIB_WCSSPN)/g' \
+	      -e 's/@''GNULIB_WCSPBRK''@/$(GNULIB_WCSPBRK)/g' \
+	      -e 's/@''GNULIB_WCSSTR''@/$(GNULIB_WCSSTR)/g' \
+	      -e 's/@''GNULIB_WCSTOK''@/$(GNULIB_WCSTOK)/g' \
+	      -e 's/@''GNULIB_WCSWIDTH''@/$(GNULIB_WCSWIDTH)/g' \
+	      < $(srcdir)/wchar.in.h | \
+	  sed -e 's|@''HAVE_WINT_T''@|$(HAVE_WINT_T)|g' \
+	      -e 's|@''HAVE_BTOWC''@|$(HAVE_BTOWC)|g' \
+	      -e 's|@''HAVE_MBSINIT''@|$(HAVE_MBSINIT)|g' \
+	      -e 's|@''HAVE_MBRTOWC''@|$(HAVE_MBRTOWC)|g' \
+	      -e 's|@''HAVE_MBRLEN''@|$(HAVE_MBRLEN)|g' \
+	      -e 's|@''HAVE_MBSRTOWCS''@|$(HAVE_MBSRTOWCS)|g' \
+	      -e 's|@''HAVE_MBSNRTOWCS''@|$(HAVE_MBSNRTOWCS)|g' \
+	      -e 's|@''HAVE_WCRTOMB''@|$(HAVE_WCRTOMB)|g' \
+	      -e 's|@''HAVE_WCSRTOMBS''@|$(HAVE_WCSRTOMBS)|g' \
+	      -e 's|@''HAVE_WCSNRTOMBS''@|$(HAVE_WCSNRTOMBS)|g' \
+	      -e 's|@''HAVE_WMEMCHR''@|$(HAVE_WMEMCHR)|g' \
+	      -e 's|@''HAVE_WMEMCMP''@|$(HAVE_WMEMCMP)|g' \
+	      -e 's|@''HAVE_WMEMCPY''@|$(HAVE_WMEMCPY)|g' \
+	      -e 's|@''HAVE_WMEMMOVE''@|$(HAVE_WMEMMOVE)|g' \
+	      -e 's|@''HAVE_WMEMSET''@|$(HAVE_WMEMSET)|g' \
+	      -e 's|@''HAVE_WCSLEN''@|$(HAVE_WCSLEN)|g' \
+	      -e 's|@''HAVE_WCSNLEN''@|$(HAVE_WCSNLEN)|g' \
+	      -e 's|@''HAVE_WCSCPY''@|$(HAVE_WCSCPY)|g' \
+	      -e 's|@''HAVE_WCPCPY''@|$(HAVE_WCPCPY)|g' \
+	      -e 's|@''HAVE_WCSNCPY''@|$(HAVE_WCSNCPY)|g' \
+	      -e 's|@''HAVE_WCPNCPY''@|$(HAVE_WCPNCPY)|g' \
+	      -e 's|@''HAVE_WCSCAT''@|$(HAVE_WCSCAT)|g' \
+	      -e 's|@''HAVE_WCSNCAT''@|$(HAVE_WCSNCAT)|g' \
+	      -e 's|@''HAVE_WCSCMP''@|$(HAVE_WCSCMP)|g' \
+	      -e 's|@''HAVE_WCSNCMP''@|$(HAVE_WCSNCMP)|g' \
+	      -e 's|@''HAVE_WCSCASECMP''@|$(HAVE_WCSCASECMP)|g' \
+	      -e 's|@''HAVE_WCSNCASECMP''@|$(HAVE_WCSNCASECMP)|g' \
+	      -e 's|@''HAVE_WCSCOLL''@|$(HAVE_WCSCOLL)|g' \
+	      -e 's|@''HAVE_WCSXFRM''@|$(HAVE_WCSXFRM)|g' \
+	      -e 's|@''HAVE_WCSDUP''@|$(HAVE_WCSDUP)|g' \
+	      -e 's|@''HAVE_WCSCHR''@|$(HAVE_WCSCHR)|g' \
+	      -e 's|@''HAVE_WCSRCHR''@|$(HAVE_WCSRCHR)|g' \
+	      -e 's|@''HAVE_WCSCSPN''@|$(HAVE_WCSCSPN)|g' \
+	      -e 's|@''HAVE_WCSSPN''@|$(HAVE_WCSSPN)|g' \
+	      -e 's|@''HAVE_WCSPBRK''@|$(HAVE_WCSPBRK)|g' \
+	      -e 's|@''HAVE_WCSSTR''@|$(HAVE_WCSSTR)|g' \
+	      -e 's|@''HAVE_WCSTOK''@|$(HAVE_WCSTOK)|g' \
+	      -e 's|@''HAVE_WCSWIDTH''@|$(HAVE_WCSWIDTH)|g' \
+	      -e 's|@''HAVE_DECL_WCTOB''@|$(HAVE_DECL_WCTOB)|g' \
+	      -e 's|@''HAVE_DECL_WCWIDTH''@|$(HAVE_DECL_WCWIDTH)|g' \
+	  | \
+	  sed -e 's|@''REPLACE_MBSTATE_T''@|$(REPLACE_MBSTATE_T)|g' \
+	      -e 's|@''REPLACE_BTOWC''@|$(REPLACE_BTOWC)|g' \
+	      -e 's|@''REPLACE_WCTOB''@|$(REPLACE_WCTOB)|g' \
+	      -e 's|@''REPLACE_MBSINIT''@|$(REPLACE_MBSINIT)|g' \
+	      -e 's|@''REPLACE_MBRTOWC''@|$(REPLACE_MBRTOWC)|g' \
+	      -e 's|@''REPLACE_MBRLEN''@|$(REPLACE_MBRLEN)|g' \
+	      -e 's|@''REPLACE_MBSRTOWCS''@|$(REPLACE_MBSRTOWCS)|g' \
+	      -e 's|@''REPLACE_MBSNRTOWCS''@|$(REPLACE_MBSNRTOWCS)|g' \
+	      -e 's|@''REPLACE_WCRTOMB''@|$(REPLACE_WCRTOMB)|g' \
+	      -e 's|@''REPLACE_WCSRTOMBS''@|$(REPLACE_WCSRTOMBS)|g' \
+	      -e 's|@''REPLACE_WCSNRTOMBS''@|$(REPLACE_WCSNRTOMBS)|g' \
+	      -e 's|@''REPLACE_WCWIDTH''@|$(REPLACE_WCWIDTH)|g' \
+	      -e 's|@''REPLACE_WCSWIDTH''@|$(REPLACE_WCSWIDTH)|g' \
+	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += wchar.h wchar.h-t
+
+EXTRA_DIST += wchar.in.h
+
+## end   gnulib module wchar
+
+## begin gnulib module wctype-h
+
+if gl_GNULIB_ENABLED_3dcce957eadc896e63ab5f137947b410
+BUILT_SOURCES += wctype.h
+libgnu_a_SOURCES += wctype-h.c
+
+# 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.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H)
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+	      -e 's/@''HAVE_WCTYPE_H''@/$(HAVE_WCTYPE_H)/g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_WCTYPE_H''@|$(NEXT_WCTYPE_H)|g' \
+	      -e 's/@''GNULIB_OVERRIDES_WINT_T''@/$(GNULIB_OVERRIDES_WINT_T)/g' \
+	      -e 's/@''GNULIB_ISWBLANK''@/$(GNULIB_ISWBLANK)/g' \
+	      -e 's/@''GNULIB_WCTYPE''@/$(GNULIB_WCTYPE)/g' \
+	      -e 's/@''GNULIB_ISWCTYPE''@/$(GNULIB_ISWCTYPE)/g' \
+	      -e 's/@''GNULIB_WCTRANS''@/$(GNULIB_WCTRANS)/g' \
+	      -e 's/@''GNULIB_TOWCTRANS''@/$(GNULIB_TOWCTRANS)/g' \
+	      -e 's/@''HAVE_ISWBLANK''@/$(HAVE_ISWBLANK)/g' \
+	      -e 's/@''HAVE_ISWCNTRL''@/$(HAVE_ISWCNTRL)/g' \
+	      -e 's/@''HAVE_WCTYPE_T''@/$(HAVE_WCTYPE_T)/g' \
+	      -e 's/@''HAVE_WCTRANS_T''@/$(HAVE_WCTRANS_T)/g' \
+	      -e 's/@''HAVE_WINT_T''@/$(HAVE_WINT_T)/g' \
+	      -e 's/@''REPLACE_ISWBLANK''@/$(REPLACE_ISWBLANK)/g' \
+	      -e 's/@''REPLACE_ISWCNTRL''@/$(REPLACE_ISWCNTRL)/g' \
+	      -e 's/@''REPLACE_TOWLOWER''@/$(REPLACE_TOWLOWER)/g' \
+	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+	      < $(srcdir)/wctype.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += wctype.h wctype.h-t
+
+endif
+EXTRA_DIST += wctype.in.h
+
+## end   gnulib module wctype-h
+
+## begin gnulib module write
+
+if gl_GNULIB_ENABLED_write
+
+endif
+EXTRA_DIST += write.c
+
+EXTRA_libgnu_a_SOURCES += write.c
+
+## end   gnulib module write
+
+## begin gnulib module xalloc
+
+libgnu_a_SOURCES += xmalloc.c
+
+EXTRA_DIST += xalloc.h
+
+## end   gnulib module xalloc
+
+## begin gnulib module xalloc-die
+
+libgnu_a_SOURCES += xalloc-die.c
+
+## end   gnulib module xalloc-die
+
+## begin gnulib module xalloc-oversized
+
+
+EXTRA_DIST += xalloc-oversized.h
+
+## end   gnulib module xalloc-oversized
+
+## begin gnulib module xgetcwd
+
+libgnu_a_SOURCES += xgetcwd.c
+
+EXTRA_DIST += xgetcwd.h
+
+## end   gnulib module xgetcwd
+
+## begin gnulib module xsize
+
+libgnu_a_SOURCES += xsize.h xsize.c
+
+## end   gnulib module xsize
+
+## begin gnulib module xstrndup
+
+libgnu_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/libgnu/hard-locale.c b/libgnu/hard-locale.c
new file mode 100644
index 0000000..57ed42b
--- /dev/null
+++ b/libgnu/hard-locale.c
@@ -0,0 +1,72 @@
+/* hard-locale.c -- Determine whether a locale is hard.
+
+   Copyright (C) 1997-1999, 2002-2004, 2006-2007, 2009-2017 Free Software
+   Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include "hard-locale.h"
+
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __GLIBC__
+# define GLIBC_VERSION __GLIBC__
+#elif defined __UCLIBC__
+# define GLIBC_VERSION 2
+#else
+# define GLIBC_VERSION 0
+#endif
+
+/* Return true if the current CATEGORY locale is hard, i.e. if you
+   can't get away with assuming traditional C or POSIX behavior.  */
+bool
+hard_locale (int category)
+{
+  bool hard = true;
+  char const *p = setlocale (category, NULL);
+
+  if (p)
+    {
+      if (2 <= GLIBC_VERSION)
+        {
+          if (strcmp (p, "C") == 0 || strcmp (p, "POSIX") == 0)
+            hard = false;
+        }
+      else
+        {
+          char *locale = strdup (p);
+          if (locale)
+            {
+              /* Temporarily set the locale to the "C" and "POSIX" locales
+                 to find their names, so that we can determine whether one
+                 or the other is the caller's locale.  */
+              if (((p = setlocale (category, "C"))
+                   && strcmp (p, locale) == 0)
+                  || ((p = setlocale (category, "POSIX"))
+                      && strcmp (p, locale) == 0))
+                hard = false;
+
+              /* Restore the caller's locale.  */
+              setlocale (category, locale);
+              free (locale);
+            }
+        }
+    }
+
+  return hard;
+}
diff --git a/libgnu/hard-locale.h b/libgnu/hard-locale.h
new file mode 100644
index 0000000..ba424af
--- /dev/null
+++ b/libgnu/hard-locale.h
@@ -0,0 +1,25 @@
+/* Determine whether a locale is hard.
+
+   Copyright (C) 1999, 2003-2004, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef HARD_LOCALE_H_
+# define HARD_LOCALE_H_ 1
+
+# include <stdbool.h>
+
+bool hard_locale (int);
+
+#endif /* HARD_LOCALE_H_ */
diff --git a/libgnu/hash-pjw.c b/libgnu/hash-pjw.c
new file mode 100644
index 0000000..a886b49
--- /dev/null
+++ b/libgnu/hash-pjw.c
@@ -0,0 +1,40 @@
+/* hash-pjw.c -- compute a hash value from a NUL-terminated string.
+
+   Copyright (C) 2001, 2003, 2006, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include "hash-pjw.h"
+
+#include <limits.h>
+
+#define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
+
+/* A hash function for NUL-terminated char* strings using
+   the method described by Bruno Haible.
+   See http://www.haible.de/bruno/hashfunc.html.  */
+
+size_t
+hash_pjw (const void *x, size_t tablesize)
+{
+  const char *s;
+  size_t h = 0;
+
+  for (s = x; *s; s++)
+    h = *s + ((h << 9) | (h >> (SIZE_BITS - 9)));
+
+  return h % tablesize;
+}
diff --git a/libgnu/hash-pjw.h b/libgnu/hash-pjw.h
new file mode 100644
index 0000000..2e7d230
--- /dev/null
+++ b/libgnu/hash-pjw.h
@@ -0,0 +1,23 @@
+/* hash-pjw.h -- declaration for a simple hash function
+   Copyright (C) 2001, 2003, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+
+/* Compute a hash code for a NUL-terminated string starting at X,
+   and return the hash code modulo TABLESIZE.
+   The result is platform dependent: it depends on the size of the 'size_t'
+   type and on the signedness of the 'char' type.  */
+extern size_t hash_pjw (void const *x, size_t tablesize) _GL_ATTRIBUTE_PURE;
diff --git a/libgnu/hash-triple.c b/libgnu/hash-triple.c
new file mode 100644
index 0000000..f892161
--- /dev/null
+++ b/libgnu/hash-triple.c
@@ -0,0 +1,77 @@
+/* Hash functions for file-related triples: name, device, inode.
+   Copyright (C) 2007, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* written by Jim Meyering */
+
+#include <config.h>
+
+#include "hash-triple.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "hash-pjw.h"
+#include "same.h"
+#include "same-inode.h"
+
+#define STREQ(a, b) (strcmp (a, b) == 0)
+
+/* Hash an F_triple, and *do* consider the file name.  */
+size_t
+triple_hash (void const *x, size_t table_size)
+{
+  struct F_triple const *p = x;
+  size_t tmp = hash_pjw (p->name, table_size);
+
+  /* Ignoring the device number here should be fine.  */
+  return (tmp ^ p->st_ino) % table_size;
+}
+
+/* Hash an F_triple, without considering the file name.  */
+size_t
+triple_hash_no_name (void const *x, size_t table_size)
+{
+  struct F_triple const *p = x;
+
+  /* Ignoring the device number here should be fine.  */
+  return p->st_ino % table_size;
+}
+
+/* Compare two F_triple structs.  */
+bool
+triple_compare (void const *x, void const *y)
+{
+  struct F_triple const *a = x;
+  struct F_triple const *b = y;
+  return (SAME_INODE (*a, *b) && same_name (a->name, b->name)) ? true : false;
+}
+
+bool
+triple_compare_ino_str (void const *x, void const *y)
+{
+  struct F_triple const *a = x;
+  struct F_triple const *b = y;
+  return (SAME_INODE (*a, *b) && STREQ (a->name, b->name)) ? true : false;
+}
+
+/* Free an F_triple.  */
+void
+triple_free (void *x)
+{
+  struct F_triple *a = x;
+  free (a->name);
+  free (a);
+}
diff --git a/libgnu/hash-triple.h b/libgnu/hash-triple.h
new file mode 100644
index 0000000..0658d81
--- /dev/null
+++ b/libgnu/hash-triple.h
@@ -0,0 +1,24 @@
+#ifndef HASH_TRIPLE_H
+#define HASH_TRIPLE_H
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdbool.h>
+
+/* Describe a just-created or just-renamed destination file.  */
+struct F_triple
+{
+  char *name;
+  ino_t st_ino;
+  dev_t st_dev;
+};
+
+extern size_t triple_hash (void const *x, size_t table_size) _GL_ATTRIBUTE_PURE;
+extern size_t triple_hash_no_name (void const *x, size_t table_size)
+  _GL_ATTRIBUTE_PURE;
+extern bool triple_compare (void const *x, void const *y);
+extern bool triple_compare_ino_str (void const *x, void const *y)
+  _GL_ATTRIBUTE_PURE;
+extern void triple_free (void *x);
+
+#endif
diff --git a/libgnu/hash.c b/libgnu/hash.c
new file mode 100644
index 0000000..04f64d1
--- /dev/null
+++ b/libgnu/hash.c
@@ -0,0 +1,1225 @@
+/* hash - hashing table processing.
+
+   Copyright (C) 1998-2004, 2006-2007, 2009-2017 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* 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 "bitrotate.h"
+#include "xalloc-oversized.h"
+
+#include <stdint.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
+
+struct hash_entry
+  {
+    void *data;
+    struct hash_entry *next;
+  };
+
+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 physically 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.8f
+#define DEFAULT_GROWTH_FACTOR 1.414f
+
+/* 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.0f
+#define DEFAULT_SHRINK_FACTOR 1.0f
+
+/* 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);
+}
+
+/* Hash KEY and return a pointer to the selected bucket.
+   If TABLE->hasher misbehaves, abort.  */
+static struct hash_entry *
+safe_hasher (const Hash_table *table, const void *key)
+{
+  size_t n = table->hasher (key, table->n_buckets);
+  if (! (n < table->n_buckets))
+    abort ();
+  return table->bucket + n;
+}
+
+/* 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 = safe_hasher (table, entry);
+  struct hash_entry const *cursor;
+
+  if (bucket->data == NULL)
+    return NULL;
+
+  for (cursor = bucket; cursor; cursor = cursor->next)
+    if (entry == cursor->data || 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, and an entry
+   may be removed only if there is no shrink threshold and the entry being
+   removed has already been passed to hash_get_next.  */
+
+/* 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 = safe_hasher (table, entry);
+  struct hash_entry const *cursor;
+
+  /* Find next entry in the same bucket.  */
+  cursor = bucket;
+  do
+    {
+      if (cursor->data == entry && cursor->next)
+        return cursor->next->data;
+      cursor = cursor->next;
+    }
+  while (cursor != NULL);
+
+  /* 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 HASH_ONE_CHAR(Value, Byte) \
+  ((Byte) + rotl_sz (Value, 7))
+
+  size_t value = 0;
+  unsigned char ch;
+
+  for (; (ch = *string); string++)
+    value = HASH_ONE_CHAR (value, ch);
+  return value % n_buckets;
+
+# 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 _GL_ATTRIBUTE_CONST
+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 _GL_ATTRIBUTE_CONST
+next_prime (size_t candidate)
+{
+  /* Skip small primes.  */
+  if (candidate < 10)
+    candidate = 10;
+
+  /* Make it definitely odd.  */
+  candidate |= 1;
+
+  while (SIZE_MAX != candidate && !is_prime (candidate))
+    candidate += 2;
+
+  return candidate;
+}
+
+void
+hash_reset_tuning (Hash_tuning *tuning)
+{
+  *tuning = default_tuning;
+}
+
+/* If the user passes a NULL hasher, we hash the raw pointer.  */
+static size_t
+raw_hasher (const void *data, size_t n)
+{
+  /* When hashing unique pointers, it is often the case that they were
+     generated by malloc and thus have the property that the low-order
+     bits are 0.  As this tends to give poorer performance with small
+     tables, we rotate the pointer value before performing division,
+     in an attempt to improve hash quality.  */
+  size_t val = rotr_sz ((size_t) data, 3);
+  return val % n;
+}
+
+/* If the user passes a NULL comparator, we use pointer comparison.  */
+static bool
+raw_comparator (const void *a, const void *b)
+{
+  return a == b;
+}
+
+
+/* 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;
+  float epsilon;
+  if (tuning == &default_tuning)
+    return true;
+
+  /* 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.  */
+  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;
+}
+
+/* Compute the size of the bucket array for the given CANDIDATE and
+   TUNING, or return 0 if there is no possible way to allocate that
+   many entries.  */
+
+static size_t _GL_ATTRIBUTE_PURE
+compute_bucket_size (size_t candidate, const Hash_tuning *tuning)
+{
+  if (!tuning->is_n_buckets)
+    {
+      float new_candidate = candidate / tuning->growth_threshold;
+      if (SIZE_MAX <= new_candidate)
+        return 0;
+      candidate = new_candidate;
+    }
+  candidate = next_prime (candidate);
+  if (xalloc_oversized (candidate, sizeof (struct hash_entry *)))
+    return 0;
+  return candidate;
+}
+
+/* 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.  If TUNING is
+   provided but the values requested are out of bounds or might cause
+   rounding errors, return NULL.
+
+   The user-supplied HASHER function, when not NULL, 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, when not NULL, 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,
+   but which are distinct pointers.
+
+   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)
+    hasher = raw_hasher;
+  if (comparator == NULL)
+    comparator = raw_comparator;
+
+  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;
+    }
+
+  table->n_buckets = compute_bucket_size (candidate, tuning);
+  if (!table->n_buckets)
+    goto fail;
+
+  table->bucket = calloc (table->n_buckets, sizeof *table->bucket);
+  if (table->bucket == NULL)
+    goto fail;
+  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 recycling 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 = safe_hasher (table, entry);
+  struct hash_entry *cursor;
+
+  *bucket_head = bucket;
+
+  /* Test for empty bucket.  */
+  if (bucket->data == NULL)
+    return NULL;
+
+  /* See if the entry is the first in the bucket.  */
+  if (entry == bucket->data || 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 (entry == cursor->next->data
+          || 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;
+}
+
+/* Internal helper, to move entries from SRC to DST.  Both tables must
+   share the same free entry list.  If SAFE, only move overflow
+   entries, saving bucket heads for later, so that no allocations will
+   occur.  Return false if the free entry list is exhausted and an
+   allocation fails.  */
+
+static bool
+transfer_entries (Hash_table *dst, Hash_table *src, bool safe)
+{
+  struct hash_entry *bucket;
+  struct hash_entry *cursor;
+  struct hash_entry *next;
+  for (bucket = src->bucket; bucket < src->bucket_limit; bucket++)
+    if (bucket->data)
+      {
+        void *data;
+        struct hash_entry *new_bucket;
+
+        /* Within each bucket, transfer overflow entries first and
+           then the bucket head, to minimize memory pressure.  After
+           all, the only time we might allocate is when moving the
+           bucket head, but moving overflow entries first may create
+           free entries that can be recycled by the time we finally
+           get to the bucket head.  */
+        for (cursor = bucket->next; cursor; cursor = next)
+          {
+            data = cursor->data;
+            new_bucket = safe_hasher (dst, data);
+
+            next = cursor->next;
+
+            if (new_bucket->data)
+              {
+                /* 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.  */
+                new_bucket->data = data;
+                dst->n_buckets_used++;
+                free_entry (dst, cursor);
+              }
+          }
+        /* Now move the bucket head.  Be sure that if we fail due to
+           allocation failure that the src table is in a consistent
+           state.  */
+        data = bucket->data;
+        bucket->next = NULL;
+        if (safe)
+          continue;
+        new_bucket = safe_hasher (dst, data);
+
+        if (new_bucket->data)
+          {
+            /* Allocate or recycle an entry, when moving from a bucket
+               header into a bucket overflow.  */
+            struct hash_entry *new_entry = allocate_entry (dst);
+
+            if (new_entry == NULL)
+              return false;
+
+            new_entry->data = data;
+            new_entry->next = new_bucket->next;
+            new_bucket->next = new_entry;
+          }
+        else
+          {
+            /* Move from one bucket header to another.  */
+            new_bucket->data = data;
+            dst->n_buckets_used++;
+          }
+        bucket->data = NULL;
+        src->n_buckets_used--;
+      }
+  return true;
+}
+
+/* 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.  Return true iff the rehash succeeded.  */
+
+bool
+hash_rehash (Hash_table *table, size_t candidate)
+{
+  Hash_table storage;
+  Hash_table *new_table;
+  size_t new_size = compute_bucket_size (candidate, table->tuning);
+
+  if (!new_size)
+    return false;
+  if (new_size == table->n_buckets)
+    return true;
+  new_table = &storage;
+  new_table->bucket = calloc (new_size, sizeof *new_table->bucket);
+  if (new_table->bucket == NULL)
+    return false;
+  new_table->n_buckets = new_size;
+  new_table->bucket_limit = new_table->bucket + new_size;
+  new_table->n_buckets_used = 0;
+  new_table->n_entries = 0;
+  new_table->tuning = table->tuning;
+  new_table->hasher = table->hasher;
+  new_table->comparator = table->comparator;
+  new_table->data_freer = table->data_freer;
+
+  /* In order for the transfer to successfully complete, we need
+     additional overflow entries when distinct buckets in the old
+     table collide into a common bucket in the new table.  The worst
+     case possible is a hasher that gives a good spread with the old
+     size, but returns a constant with the new size; if we were to
+     guarantee table->n_buckets_used-1 free entries in advance, then
+     the transfer would be guaranteed to not allocate memory.
+     However, for large tables, a guarantee of no further allocation
+     introduces a lot of extra memory pressure, all for an unlikely
+     corner case (most rehashes reduce, rather than increase, the
+     number of overflow entries needed).  So, we instead ensure that
+     the transfer process can be reversed if we hit a memory
+     allocation failure mid-transfer.  */
+
+  /* Merely reuse the extra old space into the new table.  */
+#if USE_OBSTACK
+  new_table->entry_stack = table->entry_stack;
+#endif
+  new_table->free_entry_list = table->free_entry_list;
+
+  if (transfer_entries (new_table, table, false))
+    {
+      /* Entries transferred successfully; tie up the loose ends.  */
+      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 and table->entry_stack already hold their value.  */
+      return true;
+    }
+
+  /* We've allocated new_table->bucket (and possibly some entries),
+     exhausted the free list, and moved some but not all entries into
+     new_table.  We must undo the partial move before returning
+     failure.  The only way to get into this situation is if new_table
+     uses fewer buckets than the old table, so we will reclaim some
+     free entries as overflows in the new table are put back into
+     distinct buckets in the old table.
+
+     There are some pathological cases where a single pass through the
+     table requires more intermediate overflow entries than using two
+     passes.  Two passes give worse cache performance and takes
+     longer, but at this point, we're already out of memory, so slow
+     and safe is better than failure.  */
+  table->free_entry_list = new_table->free_entry_list;
+  if (! (transfer_entries (table, new_table, true)
+         && transfer_entries (table, new_table, false)))
+    abort ();
+  /* table->n_entries already holds its value.  */
+  free (new_table->bucket);
+  return false;
+}
+
+/* Insert ENTRY into hash TABLE if there is not already a matching entry.
+
+   Return -1 upon memory allocation failure.
+   Return 1 if insertion succeeded.
+   Return 0 if there is already a matching entry in the table,
+   and in that case, if MATCHED_ENT is non-NULL, set *MATCHED_ENT
+   to that entry.
+
+   This interface is easier to use than hash_insert when you must
+   distinguish between the latter two cases.  More importantly,
+   hash_insert is unusable for some types of ENTRY values.  When using
+   hash_insert, the only way to distinguish those cases is to compare
+   the return value and ENTRY.  That works only when you can have two
+   different ENTRY values that point to data that compares "equal".  Thus,
+   when the ENTRY value is a simple scalar, you must use
+   hash_insert_if_absent.  ENTRY must not be NULL.  */
+int
+hash_insert_if_absent (Hash_table *table, void const *entry,
+                       void const **matched_ent)
+{
+  void *data;
+  struct hash_entry *bucket;
+
+  /* The caller cannot insert a NULL entry, since hash_lookup returns NULL
+     to indicate "not found", and hash_find_entry uses "bucket->data == NULL"
+     to indicate an empty bucket.  */
+  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)
+    {
+      if (matched_ent)
+        *matched_ent = data;
+      return 0;
+    }
+
+  /* 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 -1;
+
+          /* If the rehash fails, arrange to return NULL.  */
+          if (!hash_rehash (table, candidate))
+            return -1;
+
+          /* Update the bucket we are interested in.  */
+          if (hash_find_entry (table, entry, &bucket, false) != NULL)
+            abort ();
+        }
+    }
+
+  /* ENTRY is not matched, it should be inserted.  */
+
+  if (bucket->data)
+    {
+      struct hash_entry *new_entry = allocate_entry (table);
+
+      if (new_entry == NULL)
+        return -1;
+
+      /* 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 1;
+    }
+
+  /* Add ENTRY right in the bucket head.  */
+
+  bucket->data = (void *) entry;
+  table->n_entries++;
+  table->n_buckets_used++;
+
+  return 1;
+}
+
+/* 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.
+   This implementation does not support duplicate entries or insertion of
+   NULL.  */
+
+void *
+hash_insert (Hash_table *table, void const *entry)
+{
+  void const *matched_ent;
+  int err = hash_insert_if_absent (table, entry, &matched_ent);
+  return (err == -1
+          ? NULL
+          : (void *) (err == 0 ? matched_ent : 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));
+
+              if (!hash_rehash (table, candidate))
+                {
+                  /* Failure to allocate memory in an attempt to
+                     shrink the table is not fatal.  But since memory
+                     is low, we can at least be kind and free any
+                     spare entries, rather than keeping them tied up
+                     in the free entry list.  */
+#if ! USE_OBSTACK
+                  struct hash_entry *cursor = table->free_entry_list;
+                  struct hash_entry *next;
+                  while (cursor)
+                    {
+                      next = cursor->next;
+                      free (cursor);
+                      cursor = next;
+                    }
+                  table->free_entry_list = NULL;
+#endif
+                }
+            }
+        }
+    }
+
+  return data;
+}
+
+/* Testing.  */
+
+#if TESTING
+
+void
+hash_print (const Hash_table *table)
+{
+  struct hash_entry *bucket = (struct hash_entry *) table->bucket;
+
+  for ( ; 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/libgnu/hash.h b/libgnu/hash.h
new file mode 100644
index 0000000..cc5e2b4
--- /dev/null
+++ b/libgnu/hash.h
@@ -0,0 +1,103 @@
+/* hash - hashing table processing.
+   Copyright (C) 1998-1999, 2001, 2003, 2009-2017 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* 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>
+
+/* The __attribute__ feature is available in gcc versions 2.5 and later.
+   The warn_unused_result attribute appeared first in gcc-3.4.0.  */
+# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#  define _GL_ATTRIBUTE_WUR __attribute__ ((__warn_unused_result__))
+# else
+#  define _GL_ATTRIBUTE_WUR /* empty */
+# endif
+
+# ifndef _GL_ATTRIBUTE_DEPRECATED
+/* The __attribute__((__deprecated__)) feature
+   is available in gcc versions 3.1 and newer.  */
+#  if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 1)
+#   define _GL_ATTRIBUTE_DEPRECATED /* empty */
+#  else
+#   define _GL_ATTRIBUTE_DEPRECATED __attribute__ ((__deprecated__))
+#  endif
+# endif
+
+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_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 *) _GL_ATTRIBUTE_PURE;
+size_t hash_get_n_buckets_used (const Hash_table *) _GL_ATTRIBUTE_PURE;
+size_t hash_get_n_entries (const Hash_table *) _GL_ATTRIBUTE_PURE;
+size_t hash_get_max_bucket_length (const Hash_table *) _GL_ATTRIBUTE_PURE;
+bool hash_table_ok (const Hash_table *) _GL_ATTRIBUTE_PURE;
+void hash_print_statistics (const Hash_table *, FILE *);
+void *hash_lookup (const Hash_table *, const void *);
+
+/* Walking.  */
+void *hash_get_first (const Hash_table *) _GL_ATTRIBUTE_PURE;
+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) _GL_ATTRIBUTE_PURE;
+void hash_reset_tuning (Hash_tuning *);
+Hash_table *hash_initialize (size_t, const Hash_tuning *,
+                             Hash_hasher, Hash_comparator,
+                             Hash_data_freer) _GL_ATTRIBUTE_WUR;
+void hash_clear (Hash_table *);
+void hash_free (Hash_table *);
+
+/* Insertion and deletion.  */
+bool hash_rehash (Hash_table *, size_t) _GL_ATTRIBUTE_WUR;
+void *hash_insert (Hash_table *, const void *) _GL_ATTRIBUTE_WUR;
+
+int hash_insert_if_absent (Hash_table *table, const void *entry,
+                           const void **matched_ent);
+void *hash_delete (Hash_table *, const void *);
+
+#endif
diff --git a/libgnu/i-ring.c b/libgnu/i-ring.c
new file mode 100644
index 0000000..b69a0c2
--- /dev/null
+++ b/libgnu/i-ring.c
@@ -0,0 +1,68 @@
+/* a simple ring buffer
+   Copyright (C) 2006, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* written by Jim Meyering */
+
+#include <config.h>
+#include "i-ring.h"
+
+#include <stdlib.h>
+
+void
+i_ring_init (I_ring *ir, int default_val)
+{
+  int i;
+  ir->ir_empty = true;
+  ir->ir_front = 0;
+  ir->ir_back = 0;
+  for (i = 0; i < I_RING_SIZE; i++)
+    ir->ir_data[i] = default_val;
+  ir->ir_default_val = default_val;
+}
+
+bool
+i_ring_empty (I_ring const *ir)
+{
+  return ir->ir_empty;
+}
+
+int
+i_ring_push (I_ring *ir, int val)
+{
+  unsigned int dest_idx = (ir->ir_front + !ir->ir_empty) % I_RING_SIZE;
+  int old_val = ir->ir_data[dest_idx];
+  ir->ir_data[dest_idx] = val;
+  ir->ir_front = dest_idx;
+  if (dest_idx == ir->ir_back)
+    ir->ir_back = (ir->ir_back + !ir->ir_empty) % I_RING_SIZE;
+  ir->ir_empty = false;
+  return old_val;
+}
+
+int
+i_ring_pop (I_ring *ir)
+{
+  int top_val;
+  if (i_ring_empty (ir))
+    abort ();
+  top_val = ir->ir_data[ir->ir_front];
+  ir->ir_data[ir->ir_front] = ir->ir_default_val;
+  if (ir->ir_front == ir->ir_back)
+    ir->ir_empty = true;
+  else
+    ir->ir_front = ((ir->ir_front + I_RING_SIZE - 1) % I_RING_SIZE);
+  return top_val;
+}
diff --git a/libgnu/i-ring.h b/libgnu/i-ring.h
new file mode 100644
index 0000000..38ad9cc
--- /dev/null
+++ b/libgnu/i-ring.h
@@ -0,0 +1,44 @@
+/* definitions for a simple ring buffer
+   Copyright (C) 2006, 2009-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stdbool.h>
+#include "verify.h"
+
+enum { I_RING_SIZE = 4 };
+verify (1 <= I_RING_SIZE);
+
+/* When ir_empty is true, the ring is empty.
+   Otherwise, ir_data[B..F] are defined, where B..F is the contiguous
+   range of indices, modulo I_RING_SIZE, from back to front, inclusive.
+   Undefined elements of ir_data are always set to ir_default_val.
+   Popping from an empty ring aborts.
+   Pushing onto a full ring returns the displaced value.
+   An empty ring has F==B and ir_empty == true.
+   A ring with one entry still has F==B, but now ir_empty == false.  */
+struct I_ring
+{
+  int ir_data[I_RING_SIZE];
+  int ir_default_val;
+  unsigned int ir_front;
+  unsigned int ir_back;
+  bool ir_empty;
+};
+typedef struct I_ring I_ring;
+
+void i_ring_init (I_ring *ir, int ir_default_val);
+int i_ring_push (I_ring *ir, int val);
+int i_ring_pop (I_ring *ir);
+bool i_ring_empty (I_ring const *ir) _GL_ATTRIBUTE_PURE;
diff --git a/libgnu/intprops.h b/libgnu/intprops.h
new file mode 100644
index 0000000..1ea9647
--- /dev/null
+++ b/libgnu/intprops.h
@@ -0,0 +1,467 @@
+/* intprops.h -- properties of integer types
+
+   Copyright (C) 2001-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Paul Eggert.  */
+
+#ifndef _GL_INTPROPS_H
+#define _GL_INTPROPS_H
+
+#include <limits.h>
+#include <verify.h>
+
+/* Return a value with the common real type of E and V and the value of V.  */
+#define _GL_INT_CONVERT(e, v) (0 * (e) + (v))
+
+/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see
+   <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00406.html>.  */
+#define _GL_INT_NEGATE_CONVERT(e, v) (0 * (e) - (v))
+
+/* 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 the real type T is signed.  */
+#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+
+/* Return 1 if the real expression E, after promotion, has a
+   signed or floating type.  */
+#define EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)
+
+
+/* Minimum and maximum values for integer types and expressions.  */
+
+/* The width in bits of the integer type or expression T.
+   Padding bits are not supported; this is checked at compile-time below.  */
+#define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT)
+
+/* The maximum and minimum values for the integer type T.  */
+#define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t))
+#define TYPE_MAXIMUM(t)                                                 \
+  ((t) (! TYPE_SIGNED (t)                                               \
+        ? (t) -1                                                        \
+        : ((((t) 1 << (TYPE_WIDTH (t) - 2)) - 1) * 2 + 1)))
+
+/* The maximum and minimum values for the type of the expression E,
+   after integer promotion.  E should not have side effects.  */
+#define _GL_INT_MINIMUM(e)                                              \
+  (EXPR_SIGNED (e)                                                      \
+   ? ~ _GL_SIGNED_INT_MAXIMUM (e)                                       \
+   : _GL_INT_CONVERT (e, 0))
+#define _GL_INT_MAXIMUM(e)                                              \
+  (EXPR_SIGNED (e)                                                      \
+   ? _GL_SIGNED_INT_MAXIMUM (e)                                         \
+   : _GL_INT_NEGATE_CONVERT (e, 1))
+#define _GL_SIGNED_INT_MAXIMUM(e)                                       \
+  (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH ((e) + 0) - 2)) - 1) * 2 + 1)
+
+/* Work around OpenVMS incompatibility with C99.  */
+#if !defined LLONG_MAX && defined __INT64_MAX
+# define LLONG_MAX __INT64_MAX
+# define LLONG_MIN __INT64_MIN
+#endif
+
+/* This include file assumes that signed types are two's complement without
+   padding bits; the above macros have undefined behavior otherwise.
+   If this is a problem for you, please let us know how to fix it for your host.
+   As a sanity check, test the assumption for some signed types that
+   <limits.h> bounds.  */
+verify (TYPE_MINIMUM (signed char) == SCHAR_MIN);
+verify (TYPE_MAXIMUM (signed char) == SCHAR_MAX);
+verify (TYPE_MINIMUM (short int) == SHRT_MIN);
+verify (TYPE_MAXIMUM (short int) == SHRT_MAX);
+verify (TYPE_MINIMUM (int) == INT_MIN);
+verify (TYPE_MAXIMUM (int) == INT_MAX);
+verify (TYPE_MINIMUM (long int) == LONG_MIN);
+verify (TYPE_MAXIMUM (long int) == LONG_MAX);
+#ifdef LLONG_MAX
+verify (TYPE_MINIMUM (long long int) == LLONG_MIN);
+verify (TYPE_MAXIMUM (long long int) == LLONG_MAX);
+#endif
+/* Similarly, sanity-check one ISO/IEC TS 18661-1:2014 macro if defined.  */
+#ifdef UINT_WIDTH
+verify (TYPE_WIDTH (unsigned int) == UINT_WIDTH);
+#endif
+
+/* Does the __typeof__ keyword work?  This could be done by
+   'configure', but for now it's easier to do it by hand.  */
+#if (2 <= __GNUC__ \
+     || (1210 <= __IBMC__ && defined __IBM__TYPEOF__) \
+     || (0x5110 <= __SUNPRO_C && !__STDC__))
+# define _GL_HAVE___TYPEOF__ 1
+#else
+# define _GL_HAVE___TYPEOF__ 0
+#endif
+
+/* Return 1 if the integer type or expression T might be signed.  Return 0
+   if it is definitely unsigned.  This macro does not evaluate its argument,
+   and expands to an integer constant expression.  */
+#if _GL_HAVE___TYPEOF__
+# define _GL_SIGNED_TYPE_OR_EXPR(t) TYPE_SIGNED (__typeof__ (t))
+#else
+# define _GL_SIGNED_TYPE_OR_EXPR(t) 1
+#endif
+
+/* Bound on length of the string representing an unsigned integer
+   value representable in B bits.  log10 (2.0) < 146/485.  The
+   smallest value of B where this bound is not tight is 2621.  */
+#define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485)
+
+/* Bound on length of the string representing an integer type or expression T.
+   Subtract 1 for the sign bit if T is signed, and then add 1 more for
+   a minus sign if needed.
+
+   Because _GL_SIGNED_TYPE_OR_EXPR sometimes returns 0 when its argument is
+   signed, this macro may overestimate the true bound by one byte when
+   applied to unsigned types of size 2, 4, 16, ... bytes.  */
+#define INT_STRLEN_BOUND(t)                                     \
+  (INT_BITS_STRLEN_BOUND (TYPE_WIDTH (t) - _GL_SIGNED_TYPE_OR_EXPR (t)) \
+   + _GL_SIGNED_TYPE_OR_EXPR (t))
+
+/* 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)
+
+
+/* Range overflow checks.
+
+   The INT_<op>_RANGE_OVERFLOW macros return 1 if the corresponding C
+   operators might not yield numerically correct answers due to
+   arithmetic overflow.  They do not rely on undefined or
+   implementation-defined behavior.  Their implementations are simple
+   and straightforward, but they are a bit harder to use than the
+   INT_<op>_OVERFLOW macros described below.
+
+   Example usage:
+
+     long int i = ...;
+     long int j = ...;
+     if (INT_MULTIPLY_RANGE_OVERFLOW (i, j, LONG_MIN, LONG_MAX))
+       printf ("multiply would overflow");
+     else
+       printf ("product is %ld", i * j);
+
+   Restrictions on *_RANGE_OVERFLOW macros:
+
+   These macros do not check for all possible numerical problems or
+   undefined or unspecified behavior: they do not check for division
+   by zero, for bad shift counts, or for shifting negative numbers.
+
+   These macros may evaluate their arguments zero or multiple times,
+   so the arguments should not have side effects.  The arithmetic
+   arguments (including the MIN and MAX arguments) must be of the same
+   integer type after the usual arithmetic conversions, and the type
+   must have minimum value MIN and maximum MAX.  Unsigned types should
+   use a zero MIN of the proper type.
+
+   These macros are tuned for constant MIN and MAX.  For commutative
+   operations such as A + B, they are also tuned for constant B.  */
+
+/* Return 1 if A + B would overflow in [MIN,MAX] arithmetic.
+   See above for restrictions.  */
+#define INT_ADD_RANGE_OVERFLOW(a, b, min, max)          \
+  ((b) < 0                                              \
+   ? (a) < (min) - (b)                                  \
+   : (max) - (b) < (a))
+
+/* Return 1 if A - B would overflow in [MIN,MAX] arithmetic.
+   See above for restrictions.  */
+#define INT_SUBTRACT_RANGE_OVERFLOW(a, b, min, max)     \
+  ((b) < 0                                              \
+   ? (max) + (b) < (a)                                  \
+   : (a) < (min) + (b))
+
+/* Return 1 if - A would overflow in [MIN,MAX] arithmetic.
+   See above for restrictions.  */
+#define INT_NEGATE_RANGE_OVERFLOW(a, min, max)          \
+  ((min) < 0                                            \
+   ? (a) < - (max)                                      \
+   : 0 < (a))
+
+/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic.
+   See above for restrictions.  Avoid && and || as they tickle
+   bugs in Sun C 5.11 2010/08/13 and other compilers; see
+   <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00401.html>.  */
+#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max)     \
+  ((b) < 0                                              \
+   ? ((a) < 0                                           \
+      ? (a) < (max) / (b)                               \
+      : (b) == -1                                       \
+      ? 0                                               \
+      : (min) / (b) < (a))                              \
+   : (b) == 0                                           \
+   ? 0                                                  \
+   : ((a) < 0                                           \
+      ? (a) < (min) / (b)                               \
+      : (max) / (b) < (a)))
+
+/* Return 1 if A / B would overflow in [MIN,MAX] arithmetic.
+   See above for restrictions.  Do not check for division by zero.  */
+#define INT_DIVIDE_RANGE_OVERFLOW(a, b, min, max)       \
+  ((min) < 0 && (b) == -1 && (a) < - (max))
+
+/* Return 1 if A % B would overflow in [MIN,MAX] arithmetic.
+   See above for restrictions.  Do not check for division by zero.
+   Mathematically, % should never overflow, but on x86-like hosts
+   INT_MIN % -1 traps, and the C standard permits this, so treat this
+   as an overflow too.  */
+#define INT_REMAINDER_RANGE_OVERFLOW(a, b, min, max)    \
+  INT_DIVIDE_RANGE_OVERFLOW (a, b, min, max)
+
+/* Return 1 if A << B would overflow in [MIN,MAX] arithmetic.
+   See above for restrictions.  Here, MIN and MAX are for A only, and B need
+   not be of the same type as the other arguments.  The C standard says that
+   behavior is undefined for shifts unless 0 <= B < wordwidth, and that when
+   A is negative then A << B has undefined behavior and A >> B has
+   implementation-defined behavior, but do not check these other
+   restrictions.  */
+#define INT_LEFT_SHIFT_RANGE_OVERFLOW(a, b, min, max)   \
+  ((a) < 0                                              \
+   ? (a) < (min) >> (b)                                 \
+   : (max) >> (b) < (a))
+
+/* True if __builtin_add_overflow (A, B, P) works when P is non-null.  */
+#define _GL_HAS_BUILTIN_OVERFLOW (5 <= __GNUC__)
+
+/* True if __builtin_add_overflow_p (A, B, C) works.  */
+#define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__)
+
+/* The _GL*_OVERFLOW macros have the same restrictions as the
+   *_RANGE_OVERFLOW macros, except that they do not assume that operands
+   (e.g., A and B) have the same type as MIN and MAX.  Instead, they assume
+   that the result (e.g., A + B) has that type.  */
+#if _GL_HAS_BUILTIN_OVERFLOW_P
+# define _GL_ADD_OVERFLOW(a, b, min, max)                               \
+   __builtin_add_overflow_p (a, b, (__typeof__ ((a) + (b))) 0)
+# define _GL_SUBTRACT_OVERFLOW(a, b, min, max)                          \
+   __builtin_sub_overflow_p (a, b, (__typeof__ ((a) - (b))) 0)
+# define _GL_MULTIPLY_OVERFLOW(a, b, min, max)                          \
+   __builtin_mul_overflow_p (a, b, (__typeof__ ((a) * (b))) 0)
+#else
+# define _GL_ADD_OVERFLOW(a, b, min, max)                                \
+   ((min) < 0 ? INT_ADD_RANGE_OVERFLOW (a, b, min, max)                  \
+    : (a) < 0 ? (b) <= (a) + (b)                                         \
+    : (b) < 0 ? (a) <= (a) + (b)                                         \
+    : (a) + (b) < (b))
+# define _GL_SUBTRACT_OVERFLOW(a, b, min, max)                           \
+   ((min) < 0 ? INT_SUBTRACT_RANGE_OVERFLOW (a, b, min, max)             \
+    : (a) < 0 ? 1                                                        \
+    : (b) < 0 ? (a) - (b) <= (a)                                         \
+    : (a) < (b))
+# define _GL_MULTIPLY_OVERFLOW(a, b, min, max)                           \
+   (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a))))       \
+    || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max))
+#endif
+#define _GL_DIVIDE_OVERFLOW(a, b, min, max)                             \
+  ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max)  \
+   : (a) < 0 ? (b) <= (a) + (b) - 1                                     \
+   : (b) < 0 && (a) + (b) <= (a))
+#define _GL_REMAINDER_OVERFLOW(a, b, min, max)                          \
+  ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max)  \
+   : (a) < 0 ? (a) % (b) != ((max) - (b) + 1) % (b)                     \
+   : (b) < 0 && ! _GL_UNSIGNED_NEG_MULTIPLE (a, b, max))
+
+/* Return a nonzero value if A is a mathematical multiple of B, where
+   A is unsigned, B is negative, and MAX is the maximum value of A's
+   type.  A's type must be the same as (A % B)'s type.  Normally (A %
+   -B == 0) suffices, but things get tricky if -B would overflow.  */
+#define _GL_UNSIGNED_NEG_MULTIPLE(a, b, max)                            \
+  (((b) < -_GL_SIGNED_INT_MAXIMUM (b)                                   \
+    ? (_GL_SIGNED_INT_MAXIMUM (b) == (max)                              \
+       ? (a)                                                            \
+       : (a) % (_GL_INT_CONVERT (a, _GL_SIGNED_INT_MAXIMUM (b)) + 1))   \
+    : (a) % - (b))                                                      \
+   == 0)
+
+/* Check for integer overflow, and report low order bits of answer.
+
+   The INT_<op>_OVERFLOW macros return 1 if the corresponding C operators
+   might not yield numerically correct answers due to arithmetic overflow.
+   The INT_<op>_WRAPV macros also store the low-order bits of the answer.
+   These macros work correctly on all known practical hosts, and do not rely
+   on undefined behavior due to signed arithmetic overflow.
+
+   Example usage, assuming A and B are long int:
+
+     if (INT_MULTIPLY_OVERFLOW (a, b))
+       printf ("result would overflow\n");
+     else
+       printf ("result is %ld (no overflow)\n", a * b);
+
+   Example usage with WRAPV flavor:
+
+     long int result;
+     bool overflow = INT_MULTIPLY_WRAPV (a, b, &result);
+     printf ("result is %ld (%s)\n", result,
+             overflow ? "after overflow" : "no overflow");
+
+   Restrictions on these macros:
+
+   These macros do not check for all possible numerical problems or
+   undefined or unspecified behavior: they do not check for division
+   by zero, for bad shift counts, or for shifting negative numbers.
+
+   These macros may evaluate their arguments zero or multiple times, so the
+   arguments should not have side effects.
+
+   The WRAPV macros are not constant expressions.  They support only
+   +, binary -, and *.  The result type must be signed.
+
+   These macros are tuned for their last argument being a constant.
+
+   Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B,
+   A % B, and A << B would overflow, respectively.  */
+
+#define INT_ADD_OVERFLOW(a, b) \
+  _GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW)
+#define INT_SUBTRACT_OVERFLOW(a, b) \
+  _GL_BINARY_OP_OVERFLOW (a, b, _GL_SUBTRACT_OVERFLOW)
+#if _GL_HAS_BUILTIN_OVERFLOW_P
+# define INT_NEGATE_OVERFLOW(a) INT_SUBTRACT_OVERFLOW (0, a)
+#else
+# define INT_NEGATE_OVERFLOW(a) \
+   INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))
+#endif
+#define INT_MULTIPLY_OVERFLOW(a, b) \
+  _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW)
+#define INT_DIVIDE_OVERFLOW(a, b) \
+  _GL_BINARY_OP_OVERFLOW (a, b, _GL_DIVIDE_OVERFLOW)
+#define INT_REMAINDER_OVERFLOW(a, b) \
+  _GL_BINARY_OP_OVERFLOW (a, b, _GL_REMAINDER_OVERFLOW)
+#define INT_LEFT_SHIFT_OVERFLOW(a, b) \
+  INT_LEFT_SHIFT_RANGE_OVERFLOW (a, b, \
+                                 _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))
+
+/* Return 1 if the expression A <op> B would overflow,
+   where OP_RESULT_OVERFLOW (A, B, MIN, MAX) does the actual test,
+   assuming MIN and MAX are the minimum and maximum for the result type.
+   Arguments should be free of side effects.  */
+#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow)        \
+  op_result_overflow (a, b,                                     \
+                      _GL_INT_MINIMUM (0 * (b) + (a)),          \
+                      _GL_INT_MAXIMUM (0 * (b) + (a)))
+
+/* Store the low-order bits of A + B, A - B, A * B, respectively, into *R.
+   Return 1 if the result overflows.  See above for restrictions.  */
+#define INT_ADD_WRAPV(a, b, r) \
+  _GL_INT_OP_WRAPV (a, b, r, +, __builtin_add_overflow, INT_ADD_OVERFLOW)
+#define INT_SUBTRACT_WRAPV(a, b, r) \
+  _GL_INT_OP_WRAPV (a, b, r, -, __builtin_sub_overflow, INT_SUBTRACT_OVERFLOW)
+#define INT_MULTIPLY_WRAPV(a, b, r) \
+  _GL_INT_OP_WRAPV (a, b, r, *, __builtin_mul_overflow, INT_MULTIPLY_OVERFLOW)
+
+/* Nonzero if this compiler has GCC bug 68193 or Clang bug 25390.  See:
+   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68193
+   https://llvm.org/bugs/show_bug.cgi?id=25390
+   For now, assume all versions of GCC-like compilers generate bogus
+   warnings for _Generic.  This matters only for older compilers that
+   lack __builtin_add_overflow.  */
+#if __GNUC__
+# define _GL__GENERIC_BOGUS 1
+#else
+# define _GL__GENERIC_BOGUS 0
+#endif
+
+/* Store the low-order bits of A <op> B into *R, where OP specifies
+   the operation.  BUILTIN is the builtin operation, and OVERFLOW the
+   overflow predicate.  Return 1 if the result overflows.  See above
+   for restrictions.  */
+#if _GL_HAS_BUILTIN_OVERFLOW
+# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) builtin (a, b, r)
+#elif 201112 <= __STDC_VERSION__ && !_GL__GENERIC_BOGUS
+# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \
+   (_Generic \
+    (*(r), \
+     signed char: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                        signed char, SCHAR_MIN, SCHAR_MAX), \
+     short int: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                        short int, SHRT_MIN, SHRT_MAX), \
+     int: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                        int, INT_MIN, INT_MAX), \
+     long int: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+                        long int, LONG_MIN, LONG_MAX), \
+     long long int: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
+                        long long int, LLONG_MIN, LLONG_MAX)))
+#else
+# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \
+   (sizeof *(r) == sizeof (signed char) \
+    ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                       signed char, SCHAR_MIN, SCHAR_MAX) \
+    : sizeof *(r) == sizeof (short int) \
+    ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                       short int, SHRT_MIN, SHRT_MAX) \
+    : sizeof *(r) == sizeof (int) \
+    ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                       int, INT_MIN, INT_MAX) \
+    : _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow))
+# ifdef LLONG_MAX
+#  define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \
+    (sizeof *(r) == sizeof (long int) \
+     ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+                        long int, LONG_MIN, LONG_MAX) \
+     : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
+                        long long int, LLONG_MIN, LLONG_MAX))
+# else
+#  define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \
+    _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+                     long int, LONG_MIN, LONG_MAX)
+# endif
+#endif
+
+/* Store the low-order bits of A <op> B into *R, where the operation
+   is given by OP.  Use the unsigned type UT for calculation to avoid
+   overflow problems.  *R's type is T, with extrema TMIN and TMAX.
+   T must be a signed integer type.  Return 1 if the result overflows.  */
+#define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \
+  (sizeof ((a) op (b)) < sizeof (t) \
+   ? _GL_INT_OP_CALC1 ((t) (a), (t) (b), r, op, overflow, ut, t, tmin, tmax) \
+   : _GL_INT_OP_CALC1 (a, b, r, op, overflow, ut, t, tmin, tmax))
+#define _GL_INT_OP_CALC1(a, b, r, op, overflow, ut, t, tmin, tmax) \
+  ((overflow (a, b) \
+    || (EXPR_SIGNED ((a) op (b)) && ((a) op (b)) < (tmin)) \
+    || (tmax) < ((a) op (b))) \
+   ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 1) \
+   : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 0))
+
+/* Return the low-order bits of A <op> B, where the operation is given
+   by OP.  Use the unsigned type UT for calculation to avoid undefined
+   behavior on signed integer overflow, and convert the result to type T.
+   UT is at least as wide as T and is no narrower than unsigned int,
+   T is two's complement, and there is no padding or trap representations.
+   Assume that converting UT to T yields the low-order bits, as is
+   done in all known two's-complement C compilers.  E.g., see:
+   https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html
+
+   According to the C standard, converting UT to T yields an
+   implementation-defined result or signal for values outside T's
+   range.  However, code that works around this theoretical problem
+   runs afoul of a compiler bug in Oracle Studio 12.3 x86.  See:
+   http://lists.gnu.org/archive/html/bug-gnulib/2017-04/msg00049.html
+   As the compiler bug is real, don't try to work around the
+   theoretical problem.  */
+
+#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t) \
+  ((t) ((ut) (a) op (ut) (b)))
+
+#endif /* _GL_INTPROPS_H */
diff --git a/libgnu/itold.c b/libgnu/itold.c
new file mode 100644
index 0000000..9eb9507
--- /dev/null
+++ b/libgnu/itold.c
@@ -0,0 +1,28 @@
+/* Replacement for 'int' to 'long double' conversion routine.
+   Copyright (C) 2011-2017 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2011.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <float.h>
+
+void
+_Qp_itoq (long double *result, int a)
+{
+  /* Convert from 'int' to 'double', then from 'double' to 'long double'.  */
+  *result = (double) a;
+}
diff --git a/libgnu/langinfo.in.h b/libgnu/langinfo.in.h
new file mode 100644
index 0000000..7981cbf
--- /dev/null
+++ b/libgnu/langinfo.in.h
@@ -0,0 +1,194 @@
+/* Substitute for and wrapper around <langinfo.h>.
+   Copyright (C) 2009-2017 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 version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+/*
+ * POSIX <langinfo.h> for platforms that lack it or have an incomplete one.
+ * <http://www.opengroup.org/onlinepubs/9699919799/basedefs/langinfo.h.html>
+ */
+
+#ifndef _@GUARD_PREFIX@_LANGINFO_H
+
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+@PRAGMA_COLUMNS@
+
+/* The include_next requires a split double-inclusion guard.  */
+#if @HAVE_LANGINFO_H@
+# @INCLUDE_NEXT@ @NEXT_LANGINFO_H@
+#endif
+
+#ifndef _@GUARD_PREFIX@_LANGINFO_H
+#define _@GUARD_PREFIX@_LANGINFO_H
+
+
+#if !@HAVE_LANGINFO_H@
+
+/* A platform that lacks <langinfo.h>.  */
+
+/* Assume that it also lacks <nl_types.h> and the nl_item type.  */
+# if !GNULIB_defined_nl_item
+typedef int nl_item;
+#  define GNULIB_defined_nl_item 1
+# endif
+
+/* nl_langinfo items of the LC_CTYPE category */
+# define CODESET     10000
+/* nl_langinfo items of the LC_NUMERIC category */
+# define RADIXCHAR   10001
+# define DECIMAL_POINT RADIXCHAR
+# define THOUSEP     10002
+# define THOUSANDS_SEP THOUSEP
+# define GROUPING    10114
+/* nl_langinfo items of the LC_TIME category */
+# define D_T_FMT     10003
+# define D_FMT       10004
+# define T_FMT       10005
+# define T_FMT_AMPM  10006
+# define AM_STR      10007
+# define PM_STR      10008
+# define DAY_1       10009
+# define DAY_2       (DAY_1 + 1)
+# define DAY_3       (DAY_1 + 2)
+# define DAY_4       (DAY_1 + 3)
+# define DAY_5       (DAY_1 + 4)
+# define DAY_6       (DAY_1 + 5)
+# define DAY_7       (DAY_1 + 6)
+# define ABDAY_1     10016
+# define ABDAY_2     (ABDAY_1 + 1)
+# define ABDAY_3     (ABDAY_1 + 2)
+# define ABDAY_4     (ABDAY_1 + 3)
+# define ABDAY_5     (ABDAY_1 + 4)
+# define ABDAY_6     (ABDAY_1 + 5)
+# define ABDAY_7     (ABDAY_1 + 6)
+# define MON_1       10023
+# define MON_2       (MON_1 + 1)
+# define MON_3       (MON_1 + 2)
+# define MON_4       (MON_1 + 3)
+# define MON_5       (MON_1 + 4)
+# define MON_6       (MON_1 + 5)
+# define MON_7       (MON_1 + 6)
+# define MON_8       (MON_1 + 7)
+# define MON_9       (MON_1 + 8)
+# define MON_10      (MON_1 + 9)
+# define MON_11      (MON_1 + 10)
+# define MON_12      (MON_1 + 11)
+# define ABMON_1     10035
+# define ABMON_2     (ABMON_1 + 1)
+# define ABMON_3     (ABMON_1 + 2)
+# define ABMON_4     (ABMON_1 + 3)
+# define ABMON_5     (ABMON_1 + 4)
+# define ABMON_6     (ABMON_1 + 5)
+# define ABMON_7     (ABMON_1 + 6)
+# define ABMON_8     (ABMON_1 + 7)
+# define ABMON_9     (ABMON_1 + 8)
+# define ABMON_10    (ABMON_1 + 9)
+# define ABMON_11    (ABMON_1 + 10)
+# define ABMON_12    (ABMON_1 + 11)
+# define ERA         10047
+# define ERA_D_FMT   10048
+# define ERA_D_T_FMT 10049
+# define ERA_T_FMT   10050
+# define ALT_DIGITS  10051
+/* nl_langinfo items of the LC_MONETARY category */
+# define CRNCYSTR    10052
+# define CURRENCY_SYMBOL   CRNCYSTR
+# define INT_CURR_SYMBOL   10100
+# define MON_DECIMAL_POINT 10101
+# define MON_THOUSANDS_SEP 10102
+# define MON_GROUPING      10103
+# define POSITIVE_SIGN     10104
+# define NEGATIVE_SIGN     10105
+# define FRAC_DIGITS       10106
+# define INT_FRAC_DIGITS   10107
+# define P_CS_PRECEDES     10108
+# define N_CS_PRECEDES     10109
+# define P_SEP_BY_SPACE    10110
+# define N_SEP_BY_SPACE    10111
+# define P_SIGN_POSN       10112
+# define N_SIGN_POSN       10113
+/* nl_langinfo items of the LC_MESSAGES category */
+# define YESEXPR     10053
+# define NOEXPR      10054
+
+#else
+
+/* A platform that has <langinfo.h>.  */
+
+# if !@HAVE_LANGINFO_CODESET@
+#  define CODESET     10000
+#  define GNULIB_defined_CODESET 1
+# endif
+
+# if !@HAVE_LANGINFO_T_FMT_AMPM@
+#  define T_FMT_AMPM  10006
+#  define GNULIB_defined_T_FMT_AMPM 1
+# endif
+
+# if !@HAVE_LANGINFO_ERA@
+#  define ERA         10047
+#  define ERA_D_FMT   10048
+#  define ERA_D_T_FMT 10049
+#  define ERA_T_FMT   10050
+#  define ALT_DIGITS  10051
+#  define GNULIB_defined_ERA 1
+# endif
+
+# if !@HAVE_LANGINFO_YESEXPR@
+#  define YESEXPR     10053
+#  define NOEXPR      10054
+#  define GNULIB_defined_YESEXPR 1
+# endif
+
+#endif
+
+/* The definitions of _GL_FUNCDECL_RPL etc. are copied here.  */
+
+/* The definition of _GL_WARN_ON_USE is copied here.  */
+
+/* Declare overridden functions.  */
+
+
+/* Return a piece of locale dependent information.
+   Note: The difference between nl_langinfo (CODESET) and locale_charset ()
+   is that the latter normalizes the encoding names to GNU conventions.  */
+
+#if @GNULIB_NL_LANGINFO@
+# if @REPLACE_NL_LANGINFO@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef nl_langinfo
+#   define nl_langinfo rpl_nl_langinfo
+#  endif
+_GL_FUNCDECL_RPL (nl_langinfo, char *, (nl_item item));
+_GL_CXXALIAS_RPL (nl_langinfo, char *, (nl_item item));
+# else
+#  if !@HAVE_NL_LANGINFO@
+_GL_FUNCDECL_SYS (nl_langinfo, char *, (nl_item item));
+#  endif
+_GL_CXXALIAS_SYS (nl_langinfo, char *, (nl_item item));
+# endif
+_GL_CXXALIASWARN (nl_langinfo);
+#elif defined GNULIB_POSIXCHECK
+# undef nl_langinfo
+# if HAVE_RAW_DECL_NL_LANGINFO
+_GL_WARN_ON_USE (nl_langinfo, "nl_langinfo is not portable - "
+                 "use gnulib module nl_langinfo for portability");
+# endif
+#endif
+
+
+#endif /* _@GUARD_PREFIX@_LANGINFO_H */
+#endif /* _@GUARD_PREFIX@_LANGINFO_H */
diff --git a/libgnu/limits.in.h b/libgnu/limits.in.h
new file mode 100644
index 0000000..08d3c32
--- /dev/null
+++ b/libgnu/limits.in.h
@@ -0,0 +1,74 @@
+/* A GNU-like <limits.h>.
+
+   Copyright 2016-2017 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 version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _@GUARD_PREFIX@_LIMITS_H
+
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+@PRAGMA_COLUMNS@
+
+/* The include_next requires a split double-inclusion guard.  */
+#@INCLUDE_NEXT@ @NEXT_LIMITS_H@
+
+#ifndef _@GUARD_PREFIX@_LIMITS_H
+#define _@GUARD_PREFIX@_LIMITS_H
+
+/* For HP-UX 11.31.  */
+#if defined LONG_LONG_MIN && !defined LLONG_MIN
+# define LLONG_MIN LONG_LONG_MIN
+#endif
+#if defined LONG_LONG_MAX && !defined LLONG_MAX
+# define LLONG_MAX LONG_LONG_MAX
+#endif
+#if defined ULONG_LONG_MAX && !defined ULLONG_MAX
+# define ULLONG_MAX ULONG_LONG_MAX
+#endif
+
+/* The number of usable bits in an unsigned or signed integer type
+   with minimum value MIN and maximum value MAX, as an int expression
+   suitable in #if.  Cover all known practical hosts.  This
+   implementation exploits the fact that MAX is 1 less than a power of
+   2, and merely counts the number of 1 bits in MAX; "COBn" means
+   "count the number of 1 bits in the low-order n bits").  */
+#define _GL_INTEGER_WIDTH(min, max) (((min) < 0) + _GL_COB128 (max))
+#define _GL_COB128(n) (_GL_COB64 ((n) >> 31 >> 31 >> 2) + _GL_COB64 (n))
+#define _GL_COB64(n) (_GL_COB32 ((n) >> 31 >> 1) + _GL_COB32 (n))
+#define _GL_COB32(n) (_GL_COB16 ((n) >> 16) + _GL_COB16 (n))
+#define _GL_COB16(n) (_GL_COB8 ((n) >> 8) + _GL_COB8 (n))
+#define _GL_COB8(n) (_GL_COB4 ((n) >> 4) + _GL_COB4 (n))
+#define _GL_COB4(n) (!!((n) & 8) + !!((n) & 4) + !!((n) & 2) + !!((n) & 1))
+
+/* Macros specified by ISO/IEC TS 18661-1:2014.  */
+
+#if (! defined ULLONG_WIDTH                                             \
+     && (defined _GNU_SOURCE || defined __STDC_WANT_IEC_60559_BFP_EXT__))
+# define CHAR_WIDTH _GL_INTEGER_WIDTH (CHAR_MIN, CHAR_MAX)
+# define SCHAR_WIDTH _GL_INTEGER_WIDTH (SCHAR_MIN, SCHAR_MAX)
+# define UCHAR_WIDTH _GL_INTEGER_WIDTH (0, UCHAR_MAX)
+# define SHRT_WIDTH _GL_INTEGER_WIDTH (SHRT_MIN, SHRT_MAX)
+# define USHRT_WIDTH _GL_INTEGER_WIDTH (0, USHRT_MAX)
+# define INT_WIDTH _GL_INTEGER_WIDTH (INT_MIN, INT_MAX)
+# define UINT_WIDTH _GL_INTEGER_WIDTH (0, UINT_MAX)
+# define LONG_WIDTH _GL_INTEGER_WIDTH (LONG_MIN, LONG_MAX)
+# define ULONG_WIDTH _GL_INTEGER_WIDTH (0, ULONG_MAX)
+# define LLONG_WIDTH _GL_INTEGER_WIDTH (LLONG_MIN, LLONG_MAX)
+# define ULLONG_WIDTH _GL_INTEGER_WIDTH (0, ULLONG_MAX)
+#endif /* !ULLONG_WIDTH && (_GNU_SOURCE || __STDC_WANT_IEC_60559_BFP_EXT__) */
+
+#endif /* _@GUARD_PREFIX@_LIMITS_H */
+#endif /* _@GUARD_PREFIX@_LIMITS_H */
diff --git a/libgnu/link.c b/libgnu/link.c
new file mode 100644
index 0000000..e821e2d
--- /dev/null
+++ b/libgnu/link.c
@@ -0,0 +1,211 @@
+/* Emulate link on platforms that lack it, namely native Windows platforms.
+
+   Copyright (C) 2009-2017 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 version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#if !HAVE_LINK
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+#  define WIN32_LEAN_AND_MEAN
+#  include <windows.h>
+
+/* CreateHardLink was introduced only in Windows 2000.  */
+typedef BOOL (WINAPI * CreateHardLinkFuncType) (LPCTSTR lpFileName,
+                                                LPCTSTR lpExistingFileName,
+                                                LPSECURITY_ATTRIBUTES lpSecurityAttributes);
+static CreateHardLinkFuncType CreateHardLinkFunc = NULL;
+static BOOL initialized = FALSE;
+
+static void
+initialize (void)
+{
+  HMODULE kernel32 = GetModuleHandle ("kernel32.dll");
+  if (kernel32 != NULL)
+    {
+      CreateHardLinkFunc =
+        (CreateHardLinkFuncType) GetProcAddress (kernel32, "CreateHardLinkA");
+    }
+  initialized = TRUE;
+}
+
+int
+link (const char *file1, const char *file2)
+{
+  char *dir;
+  size_t len1 = strlen (file1);
+  size_t len2 = strlen (file2);
+  if (!initialized)
+    initialize ();
+  if (CreateHardLinkFunc == NULL)
+    {
+      /* System does not support hard links.  */
+      errno = EPERM;
+      return -1;
+    }
+  /* Reject trailing slashes on non-directories; mingw does not
+     support hard-linking directories.  */
+  if ((len1 && (file1[len1 - 1] == '/' || file1[len1 - 1] == '\\'))
+      || (len2 && (file2[len2 - 1] == '/' || file2[len2 - 1] == '\\')))
+    {
+      struct stat st;
+      if (stat (file1, &st) == 0 && S_ISDIR (st.st_mode))
+        errno = EPERM;
+      else
+        errno = ENOTDIR;
+      return -1;
+    }
+  /* CreateHardLink("b/.","a",NULL) creates file "b", so we must check
+     that dirname(file2) exists.  */
+  dir = strdup (file2);
+  if (!dir)
+    return -1;
+  {
+    struct stat st;
+    char *p = strchr (dir, '\0');
+    while (dir < p && (*--p != '/' && *p != '\\'));
+    *p = '\0';
+    if (p != dir && stat (dir, &st) == -1)
+      {
+        int saved_errno = errno;
+        free (dir);
+        errno = saved_errno;
+        return -1;
+      }
+    free (dir);
+  }
+  /* Now create the link.  */
+  if (CreateHardLinkFunc (file2, file1, NULL) == 0)
+    {
+      /* It is not documented which errors CreateHardLink() can produce.
+       * The following conversions are based on tests on a Windows XP SP2
+       * system. */
+      DWORD err = GetLastError ();
+      switch (err)
+        {
+        case ERROR_ACCESS_DENIED:
+          errno = EACCES;
+          break;
+
+        case ERROR_INVALID_FUNCTION:    /* fs does not support hard links */
+          errno = EPERM;
+          break;
+
+        case ERROR_NOT_SAME_DEVICE:
+          errno = EXDEV;
+          break;
+
+        case ERROR_PATH_NOT_FOUND:
+        case ERROR_FILE_NOT_FOUND:
+          errno = ENOENT;
+          break;
+
+        case ERROR_INVALID_PARAMETER:
+          errno = ENAMETOOLONG;
+          break;
+
+        case ERROR_TOO_MANY_LINKS:
+          errno = EMLINK;
+          break;
+
+        case ERROR_ALREADY_EXISTS:
+          errno = EEXIST;
+          break;
+
+        default:
+          errno = EIO;
+        }
+      return -1;
+    }
+
+  return 0;
+}
+
+# else /* !Windows */
+
+#  error "This platform lacks a link function, and Gnulib doesn't provide a replacement. This is a bug in Gnulib."
+
+# endif /* !Windows */
+#else /* HAVE_LINK */
+
+# undef link
+
+/* Create a hard link from FILE1 to FILE2, working around platform bugs.  */
+int
+rpl_link (char const *file1, char const *file2)
+{
+  size_t len1;
+  size_t len2;
+  struct stat st;
+
+  /* Don't allow IRIX to dereference dangling file2 symlink.  */
+  if (!lstat (file2, &st))
+    {
+      errno = EEXIST;
+      return -1;
+    }
+
+  /* Reject trailing slashes on non-directories.  */
+  len1 = strlen (file1);
+  len2 = strlen (file2);
+  if ((len1 && file1[len1 - 1] == '/')
+      || (len2 && file2[len2 - 1] == '/'))
+    {
+      /* Let link() decide whether hard-linking directories is legal.
+         If stat() fails, then link() should fail for the same reason
+         (although on Solaris 9, link("file/","oops") mistakenly
+         succeeds); if stat() succeeds, require a directory.  */
+      if (stat (file1, &st))
+        return -1;
+      if (!S_ISDIR (st.st_mode))
+        {
+          errno = ENOTDIR;
+          return -1;
+        }
+    }
+  else
+    {
+      /* Fix Cygwin 1.5.x bug where link("a","b/.") creates file "b".  */
+      char *dir = strdup (file2);
+      char *p;
+      if (!dir)
+        return -1;
+      /* We already know file2 does not end in slash.  Strip off the
+         basename, then check that the dirname exists.  */
+      p = strrchr (dir, '/');
+      if (p)
+        {
+          *p = '\0';
+          if (stat (dir, &st) == -1)
+            {
+              int saved_errno = errno;
+              free (dir);
+              errno = saved_errno;
+              return -1;
+            }
+        }
+      free (dir);
+    }
+  return link (file1, file2);
+}
+#endif /* HAVE_LINK */
diff --git a/libgnu/localcharset.c b/libgnu/localcharset.c
new file mode 100644
index 0000000..9d0a1b8
--- /dev/null
+++ b/libgnu/localcharset.c
@@ -0,0 +1,613 @@
+/* Determine a canonical name for the current locale's character encoding.
+
+   Copyright (C) 2000-2006, 2008-2017 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 version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "localcharset.h"
+
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#if defined __APPLE__ && defined __MACH__ && HAVE_LANGINFO_CODESET
+# define DARWIN7 /* Darwin 7 or newer, i.e. Mac OS X 10.3 or newer */
+#endif
+
+#if defined _WIN32 || defined __WIN32__
+# define WINDOWS_NATIVE
+# include <locale.h>
+#endif
+
+#if defined __EMX__
+/* Assume EMX program runs on OS/2, even if compiled under DOS.  */
+# ifndef OS2
+#  define OS2
+# endif
+#endif
+
+#if !defined WINDOWS_NATIVE
+# include <unistd.h>
+# if HAVE_LANGINFO_CODESET
+#  include <langinfo.h>
+# else
+#  if 0 /* see comment below */
+#   include <locale.h>
+#  endif
+# endif
+# ifdef __CYGWIN__
+#  define WIN32_LEAN_AND_MEAN
+#  include <windows.h>
+# endif
+#elif defined WINDOWS_NATIVE
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+#if defined OS2
+# define INCL_DOS
+# include <os2.h>
+#endif
+
+/* For MB_CUR_MAX_L */
+#if defined DARWIN7
+# include <xlocale.h>
+#endif
+
+#if ENABLE_RELOCATABLE
+# include "relocatable.h"
+#else
+# define relocate(pathname) (pathname)
+#endif
+
+/* Get LIBDIR.  */
+#ifndef LIBDIR
+# include "configmake.h"
+#endif
+
+/* Define O_NOFOLLOW to 0 on platforms where it does not exist.  */
+#ifndef O_NOFOLLOW
+# define O_NOFOLLOW 0
+#endif
+
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
+  /* Native Windows, Cygwin, OS/2, DOS */
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+#endif
+
+#ifndef DIRECTORY_SEPARATOR
+# define DIRECTORY_SEPARATOR '/'
+#endif
+
+#ifndef ISSLASH
+# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
+#endif
+
+#if HAVE_DECL_GETC_UNLOCKED
+# undef getc
+# define getc getc_unlocked
+#endif
+
+/* The following static variable is declared 'volatile' to avoid a
+   possible multithread problem in the function get_charset_aliases. If we
+   are running in a threaded environment, and if two threads initialize
+   'charset_aliases' simultaneously, both will produce the same value,
+   and everything will be ok if the two assignments to 'charset_aliases'
+   are atomic. But I don't know what will happen if the two assignments mix.  */
+#if __STDC__ != 1
+# define volatile /* empty */
+#endif
+/* Pointer to the contents of the charset.alias file, if it has already been
+   read, else NULL.  Its format is:
+   ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0'  */
+static const char * volatile charset_aliases;
+
+/* Return a pointer to the contents of the charset.alias file.  */
+static const char *
+get_charset_aliases (void)
+{
+  const char *cp;
+
+  cp = charset_aliases;
+  if (cp == NULL)
+    {
+#if !(defined DARWIN7 || defined VMS || defined WINDOWS_NATIVE || defined __CYGWIN__ || defined OS2)
+      const char *dir;
+      const char *base = "charset.alias";
+      char *file_name;
+
+      /* Make it possible to override the charset.alias location.  This is
+         necessary for running the testsuite before "make install".  */
+      dir = getenv ("CHARSETALIASDIR");
+      if (dir == NULL || dir[0] == '\0')
+        dir = relocate (LIBDIR);
+
+      /* Concatenate dir and base into freshly allocated file_name.  */
+      {
+        size_t dir_len = strlen (dir);
+        size_t base_len = strlen (base);
+        int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1]));
+        file_name = (char *) malloc (dir_len + add_slash + base_len + 1);
+        if (file_name != NULL)
+          {
+            memcpy (file_name, dir, dir_len);
+            if (add_slash)
+              file_name[dir_len] = DIRECTORY_SEPARATOR;
+            memcpy (file_name + dir_len + add_slash, base, base_len + 1);
+          }
+      }
+
+      if (file_name == NULL)
+        /* Out of memory.  Treat the file as empty.  */
+        cp = "";
+      else
+        {
+          int fd;
+
+          /* Open the file.  Reject symbolic links on platforms that support
+             O_NOFOLLOW.  This is a security feature.  Without it, an attacker
+             could retrieve parts of the contents (namely, the tail of the
+             first line that starts with "* ") of an arbitrary file by placing
+             a symbolic link to that file under the name "charset.alias" in
+             some writable directory and defining the environment variable
+             CHARSETALIASDIR to point to that directory.  */
+          fd = open (file_name,
+                     O_RDONLY | (HAVE_WORKING_O_NOFOLLOW ? O_NOFOLLOW : 0));
+          if (fd < 0)
+            /* File not found.  Treat it as empty.  */
+            cp = "";
+          else
+            {
+              FILE *fp;
+
+              fp = fdopen (fd, "r");
+              if (fp == NULL)
+                {
+                  /* Out of memory.  Treat the file as empty.  */
+                  close (fd);
+                  cp = "";
+                }
+              else
+                {
+                  /* Parse the file's contents.  */
+                  char *res_ptr = NULL;
+                  size_t res_size = 0;
+
+                  for (;;)
+                    {
+                      int c;
+                      char buf1[50+1];
+                      char buf2[50+1];
+                      size_t l1, l2;
+                      char *old_res_ptr;
+
+                      c = getc (fp);
+                      if (c == EOF)
+                        break;
+                      if (c == '\n' || c == ' ' || c == '\t')
+                        continue;
+                      if (c == '#')
+                        {
+                          /* Skip comment, to end of line.  */
+                          do
+                            c = getc (fp);
+                          while (!(c == EOF || c == '\n'));
+                          if (c == EOF)
+                            break;
+                          continue;
+                        }
+                      ungetc (c, fp);
+                      if (fscanf (fp, "%50s %50s", buf1, buf2) < 2)
+                        break;
+                      l1 = strlen (buf1);
+                      l2 = strlen (buf2);
+                      old_res_ptr = res_ptr;
+                      if (res_size == 0)
+                        {
+                          res_size = l1 + 1 + l2 + 1;
+                          res_ptr = (char *) malloc (res_size + 1);
+                        }
+                      else
+                        {
+                          res_size += l1 + 1 + l2 + 1;
+                          res_ptr = (char *) realloc (res_ptr, res_size + 1);
+                        }
+                      if (res_ptr == NULL)
+                        {
+                          /* Out of memory. */
+                          res_size = 0;
+                          free (old_res_ptr);
+                          break;
+                        }
+                      strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1);
+                      strcpy (res_ptr + res_size - (l2 + 1), buf2);
+                    }
+                  fclose (fp);
+                  if (res_size == 0)
+                    cp = "";
+                  else
+                    {
+                      *(res_ptr + res_size) = '\0';
+                      cp = res_ptr;
+                    }
+                }
+            }
+
+          free (file_name);
+        }
+
+#else
+
+# if defined DARWIN7
+      /* To avoid the trouble of installing a file that is shared by many
+         GNU packages -- many packaging systems have problems with this --,
+         simply inline the aliases here.  */
+      cp = "ISO8859-1" "\0" "ISO-8859-1" "\0"
+           "ISO8859-2" "\0" "ISO-8859-2" "\0"
+           "ISO8859-4" "\0" "ISO-8859-4" "\0"
+           "ISO8859-5" "\0" "ISO-8859-5" "\0"
+           "ISO8859-7" "\0" "ISO-8859-7" "\0"
+           "ISO8859-9" "\0" "ISO-8859-9" "\0"
+           "ISO8859-13" "\0" "ISO-8859-13" "\0"
+           "ISO8859-15" "\0" "ISO-8859-15" "\0"
+           "KOI8-R" "\0" "KOI8-R" "\0"
+           "KOI8-U" "\0" "KOI8-U" "\0"
+           "CP866" "\0" "CP866" "\0"
+           "CP949" "\0" "CP949" "\0"
+           "CP1131" "\0" "CP1131" "\0"
+           "CP1251" "\0" "CP1251" "\0"
+           "eucCN" "\0" "GB2312" "\0"
+           "GB2312" "\0" "GB2312" "\0"
+           "eucJP" "\0" "EUC-JP" "\0"
+           "eucKR" "\0" "EUC-KR" "\0"
+           "Big5" "\0" "BIG5" "\0"
+           "Big5HKSCS" "\0" "BIG5-HKSCS" "\0"
+           "GBK" "\0" "GBK" "\0"
+           "GB18030" "\0" "GB18030" "\0"
+           "SJIS" "\0" "SHIFT_JIS" "\0"
+           "ARMSCII-8" "\0" "ARMSCII-8" "\0"
+           "PT154" "\0" "PT154" "\0"
+         /*"ISCII-DEV" "\0" "?" "\0"*/
+           "*" "\0" "UTF-8" "\0";
+# endif
+
+# if defined VMS
+      /* To avoid the troubles of an extra file charset.alias_vms in the
+         sources of many GNU packages, simply inline the aliases here.  */
+      /* The list of encodings is taken from the OpenVMS 7.3-1 documentation
+         "Compaq C Run-Time Library Reference Manual for OpenVMS systems"
+         section 10.7 "Handling Different Character Sets".  */
+      cp = "ISO8859-1" "\0" "ISO-8859-1" "\0"
+           "ISO8859-2" "\0" "ISO-8859-2" "\0"
+           "ISO8859-5" "\0" "ISO-8859-5" "\0"
+           "ISO8859-7" "\0" "ISO-8859-7" "\0"
+           "ISO8859-8" "\0" "ISO-8859-8" "\0"
+           "ISO8859-9" "\0" "ISO-8859-9" "\0"
+           /* Japanese */
+           "eucJP" "\0" "EUC-JP" "\0"
+           "SJIS" "\0" "SHIFT_JIS" "\0"
+           "DECKANJI" "\0" "DEC-KANJI" "\0"
+           "SDECKANJI" "\0" "EUC-JP" "\0"
+           /* Chinese */
+           "eucTW" "\0" "EUC-TW" "\0"
+           "DECHANYU" "\0" "DEC-HANYU" "\0"
+           "DECHANZI" "\0" "GB2312" "\0"
+           /* Korean */
+           "DECKOREAN" "\0" "EUC-KR" "\0";
+# endif
+
+# if defined WINDOWS_NATIVE || defined __CYGWIN__
+      /* To avoid the troubles of installing a separate file in the same
+         directory as the DLL and of retrieving the DLL's directory at
+         runtime, simply inline the aliases here.  */
+
+      cp = "CP936" "\0" "GBK" "\0"
+           "CP1361" "\0" "JOHAB" "\0"
+           "CP20127" "\0" "ASCII" "\0"
+           "CP20866" "\0" "KOI8-R" "\0"
+           "CP20936" "\0" "GB2312" "\0"
+           "CP21866" "\0" "KOI8-RU" "\0"
+           "CP28591" "\0" "ISO-8859-1" "\0"
+           "CP28592" "\0" "ISO-8859-2" "\0"
+           "CP28593" "\0" "ISO-8859-3" "\0"
+           "CP28594" "\0" "ISO-8859-4" "\0"
+           "CP28595" "\0" "ISO-8859-5" "\0"
+           "CP28596" "\0" "ISO-8859-6" "\0"
+           "CP28597" "\0" "ISO-8859-7" "\0"
+           "CP28598" "\0" "ISO-8859-8" "\0"
+           "CP28599" "\0" "ISO-8859-9" "\0"
+           "CP28605" "\0" "ISO-8859-15" "\0"
+           "CP38598" "\0" "ISO-8859-8" "\0"
+           "CP51932" "\0" "EUC-JP" "\0"
+           "CP51936" "\0" "GB2312" "\0"
+           "CP51949" "\0" "EUC-KR" "\0"
+           "CP51950" "\0" "EUC-TW" "\0"
+           "CP54936" "\0" "GB18030" "\0"
+           "CP65001" "\0" "UTF-8" "\0";
+# endif
+# if defined OS2
+      /* To avoid the troubles of installing a separate file in the same
+         directory as the DLL and of retrieving the DLL's directory at
+         runtime, simply inline the aliases here.  */
+
+      /* The list of encodings is taken from "List of OS/2 Codepages"
+         by Alex Taylor:
+         <http://altsan.org/os2/toolkits/uls/index.html#codepages>.
+         See also "IBM Globalization - Code page identifiers":
+         <http://www-01.ibm.com/software/globalization/cp/cp_cpgid.html>.  */
+      cp = "CP813" "\0" "ISO-8859-7" "\0"
+           "CP878" "\0" "KOI8-R" "\0"
+           "CP819" "\0" "ISO-8859-1" "\0"
+           "CP912" "\0" "ISO-8859-2" "\0"
+           "CP913" "\0" "ISO-8859-3" "\0"
+           "CP914" "\0" "ISO-8859-4" "\0"
+           "CP915" "\0" "ISO-8859-5" "\0"
+           "CP916" "\0" "ISO-8859-8" "\0"
+           "CP920" "\0" "ISO-8859-9" "\0"
+           "CP921" "\0" "ISO-8859-13" "\0"
+           "CP923" "\0" "ISO-8859-15" "\0"
+           "CP954" "\0" "EUC-JP" "\0"
+           "CP964" "\0" "EUC-TW" "\0"
+           "CP970" "\0" "EUC-KR" "\0"
+           "CP1089" "\0" "ISO-8859-6" "\0"
+           "CP1208" "\0" "UTF-8" "\0"
+           "CP1381" "\0" "GB2312" "\0"
+           "CP1386" "\0" "GBK" "\0"
+           "CP3372" "\0" "EUC-JP" "\0";
+# endif
+#endif
+
+      charset_aliases = cp;
+    }
+
+  return cp;
+}
+
+/* Determine the current locale's character encoding, and canonicalize it
+   into one of the canonical names listed in config.charset.
+   The result must not be freed; it is statically allocated.
+   If the canonical name cannot be determined, the result is a non-canonical
+   name.  */
+
+#ifdef STATIC
+STATIC
+#endif
+const char *
+locale_charset (void)
+{
+  const char *codeset;
+  const char *aliases;
+
+#if !(defined WINDOWS_NATIVE || defined OS2)
+
+# if HAVE_LANGINFO_CODESET
+
+  /* Most systems support nl_langinfo (CODESET) nowadays.  */
+  codeset = nl_langinfo (CODESET);
+
+#  ifdef __CYGWIN__
+  /* Cygwin < 1.7 does not have locales.  nl_langinfo (CODESET) always
+     returns "US-ASCII".  Return the suffix of the locale name from the
+     environment variables (if present) or the codepage as a number.  */
+  if (codeset != NULL && strcmp (codeset, "US-ASCII") == 0)
+    {
+      const char *locale;
+      static char buf[2 + 10 + 1];
+
+      locale = getenv ("LC_ALL");
+      if (locale == NULL || locale[0] == '\0')
+        {
+          locale = getenv ("LC_CTYPE");
+          if (locale == NULL || locale[0] == '\0')
+            locale = getenv ("LANG");
+        }
+      if (locale != NULL && locale[0] != '\0')
+        {
+          /* If the locale name contains an encoding after the dot, return
+             it.  */
+          const char *dot = strchr (locale, '.');
+
+          if (dot != NULL)
+            {
+              const char *modifier;
+
+              dot++;
+              /* Look for the possible @... trailer and remove it, if any.  */
+              modifier = strchr (dot, '@');
+              if (modifier == NULL)
+                return dot;
+              if (modifier - dot < sizeof (buf))
+                {
+                  memcpy (buf, dot, modifier - dot);
+                  buf [modifier - dot] = '\0';
+                  return buf;
+                }
+            }
+        }
+
+      /* The Windows API has a function returning the locale's codepage as a
+         number: GetACP().  This encoding is used by Cygwin, unless the user
+         has set the environment variable CYGWIN=codepage:oem (which very few
+         people do).
+         Output directed to console windows needs to be converted (to
+         GetOEMCP() if the console is using a raster font, or to
+         GetConsoleOutputCP() if it is using a TrueType font).  Cygwin does
+         this conversion transparently (see winsup/cygwin/fhandler_console.cc),
+         converting to GetConsoleOutputCP().  This leads to correct results,
+         except when SetConsoleOutputCP has been called and a raster font is
+         in use.  */
+      sprintf (buf, "CP%u", GetACP ());
+      codeset = buf;
+    }
+#  endif
+
+# else
+
+  /* On old systems which lack it, use setlocale or getenv.  */
+  const char *locale = NULL;
+
+  /* But most old systems don't have a complete set of locales.  Some
+     (like SunOS 4 or DJGPP) have only the C locale.  Therefore we don't
+     use setlocale here; it would return "C" when it doesn't support the
+     locale name the user has set.  */
+#  if 0
+  locale = setlocale (LC_CTYPE, NULL);
+#  endif
+  if (locale == NULL || locale[0] == '\0')
+    {
+      locale = getenv ("LC_ALL");
+      if (locale == NULL || locale[0] == '\0')
+        {
+          locale = getenv ("LC_CTYPE");
+          if (locale == NULL || locale[0] == '\0')
+            locale = getenv ("LANG");
+        }
+    }
+
+  /* On some old systems, one used to set locale = "iso8859_1". On others,
+     you set it to "language_COUNTRY.charset". In any case, we resolve it
+     through the charset.alias file.  */
+  codeset = locale;
+
+# endif
+
+#elif defined WINDOWS_NATIVE
+
+  static char buf[2 + 10 + 1];
+
+  /* The Windows API has a function returning the locale's codepage as
+     a number, but the value doesn't change according to what the
+     'setlocale' call specified.  So we use it as a last resort, in
+     case the string returned by 'setlocale' doesn't specify the
+     codepage.  */
+  char *current_locale = setlocale (LC_ALL, NULL);
+  char *pdot;
+
+  /* If they set different locales for different categories,
+     'setlocale' will return a semi-colon separated list of locale
+     values.  To make sure we use the correct one, we choose LC_CTYPE.  */
+  if (strchr (current_locale, ';'))
+    current_locale = setlocale (LC_CTYPE, NULL);
+
+  pdot = strrchr (current_locale, '.');
+  if (pdot && 2 + strlen (pdot + 1) + 1 <= sizeof (buf))
+    sprintf (buf, "CP%s", pdot + 1);
+  else
+    {
+      /* The Windows API has a function returning the locale's codepage as a
+        number: GetACP().
+        When the output goes to a console window, it needs to be provided in
+        GetOEMCP() encoding if the console is using a raster font, or in
+        GetConsoleOutputCP() encoding if it is using a TrueType font.
+        But in GUI programs and for output sent to files and pipes, GetACP()
+        encoding is the best bet.  */
+      sprintf (buf, "CP%u", GetACP ());
+    }
+  codeset = buf;
+
+#elif defined OS2
+
+  const char *locale;
+  static char buf[2 + 10 + 1];
+  ULONG cp[3];
+  ULONG cplen;
+
+  codeset = NULL;
+
+  /* Allow user to override the codeset, as set in the operating system,
+     with standard language environment variables.  */
+  locale = getenv ("LC_ALL");
+  if (locale == NULL || locale[0] == '\0')
+    {
+      locale = getenv ("LC_CTYPE");
+      if (locale == NULL || locale[0] == '\0')
+        locale = getenv ("LANG");
+    }
+  if (locale != NULL && locale[0] != '\0')
+    {
+      /* If the locale name contains an encoding after the dot, return it.  */
+      const char *dot = strchr (locale, '.');
+
+      if (dot != NULL)
+        {
+          const char *modifier;
+
+          dot++;
+          /* Look for the possible @... trailer and remove it, if any.  */
+          modifier = strchr (dot, '@');
+          if (modifier == NULL)
+            return dot;
+          if (modifier - dot < sizeof (buf))
+            {
+              memcpy (buf, dot, modifier - dot);
+              buf [modifier - dot] = '\0';
+              return buf;
+            }
+        }
+
+      /* For the POSIX locale, don't use the system's codepage.  */
+      if (strcmp (locale, "C") == 0 || strcmp (locale, "POSIX") == 0)
+        codeset = "";
+    }
+
+  if (codeset == NULL)
+    {
+      /* OS/2 has a function returning the locale's codepage as a number.  */
+      if (DosQueryCp (sizeof (cp), cp, &cplen))
+        codeset = "";
+      else
+        {
+          sprintf (buf, "CP%u", cp[0]);
+          codeset = buf;
+        }
+    }
+
+#endif
+
+  if (codeset == NULL)
+    /* The canonical name cannot be determined.  */
+    codeset = "";
+
+  /* Resolve alias. */
+  for (aliases = get_charset_aliases ();
+       *aliases != '\0';
+       aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1)
+    if (strcmp (codeset, aliases) == 0
+        || (aliases[0] == '*' && aliases[1] == '\0'))
+      {
+        codeset = aliases + strlen (aliases) + 1;
+        break;
+      }
+
+  /* Don't return an empty string.  GNU libc and GNU libiconv interpret
+     the empty string as denoting "the locale's character encoding",
+     thus GNU libiconv would call this function a second time.  */
+  if (codeset[0] == '\0')
+    codeset = "ASCII";
+
+#ifdef DARWIN7
+  /* Mac OS X sets MB_CUR_MAX to 1 when LC_ALL=C, and "UTF-8"
+     (the default codeset) does not work when MB_CUR_MAX is 1.  */
+  if (strcmp (codeset, "UTF-8") == 0 && MB_CUR_MAX_L (uselocale (NULL)) <= 1)
+    codeset = "ASCII";
+#endif
+
+  return codeset;
+}
diff --git a/libgnu/localcharset.h b/libgnu/localcharset.h
new file mode 100644
index 0000000..a2e2a7b
--- /dev/null
+++ b/libgnu/localcharset.h
@@ -0,0 +1,40 @@
+/* Determine a canonical name for the current locale's character encoding.
+   Copyright (C) 2000-2003, 2009-2017 Free Software Foundation, Inc.
+   This file is part of the GNU CHARSET 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 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.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LOCALCHARSET_H
+#define _LOCALCHARSET_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Determine the current locale's character encoding, and canonicalize it
+   into one of the canonical names listed in config.charset.
+   The result must not be freed; it is statically allocated.
+   If the canonical name cannot be determined, the result is a non-canonical
+   name.  */
+extern const char * locale_charset (void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _LOCALCHARSET_H */
diff --git a/libgnu/lseek.c b/libgnu/lseek.c
new file mode 100644
index 0000000..3b2fdf2
--- /dev/null
+++ b/libgnu/lseek.c
@@ -0,0 +1,67 @@
+/* An lseek() function that detects pipes.
+   Copyright (C) 2007, 2009-2017 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 version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+/* Windows platforms.  */
+/* Get GetFileType.  */
+# include <windows.h>
+/* Get _get_osfhandle.  */
+# include "msvc-nothrow.h"
+#else
+# include <sys/stat.h>
+#endif
+#include <errno.h>
+
+#undef lseek
+
+off_t
+rpl_lseek (int fd, off_t offset, int whence)
+{
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+  /* mingw lseek mistakenly succeeds on pipes, sockets, and terminals.  */
+  HANDLE h = (HANDLE) _get_osfhandle (fd);
+  if (h == INVALID_HANDLE_VALUE)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  if (GetFileType (h) != FILE_TYPE_DISK)
+    {
+      errno = ESPIPE;
+      return -1;
+    }
+#else
+  /* BeOS lseek mistakenly succeeds on pipes...  */
+  struct stat statbuf;
+  if (fstat (fd, &statbuf) < 0)
+    return -1;
+  if (!S_ISREG (statbuf.st_mode))
+    {
+      errno = ESPIPE;
+      return -1;
+    }
+#endif
+#if _GL_WINDOWS_64_BIT_OFF_T
+  return _lseeki64 (fd, offset, whence);
+#else
+  return lseek (fd, offset, whence);
+#endif
+}
diff --git a/libgnu/lstat.c b/libgnu/lstat.c
new file mode 100644
index 0000000..f4dc43e
--- /dev/null
+++ b/libgnu/lstat.c
@@ -0,0 +1,97 @@
+/* Work around a bug of lstat on some systems
+
+   Copyright (C) 1997-2006, 2008-2017 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* written by Jim Meyering */
+
+/* If the user's config.h happens to include <sys/stat.h>, let it include only
+   the system's <sys/stat.h> here, so that orig_lstat doesn't recurse to
+   rpl_lstat.  */
+#define __need_system_sys_stat_h
+#include <config.h>
+
+#if !HAVE_LSTAT
+/* On systems that lack symlinks, our replacement <sys/stat.h> already
+   defined lstat as stat, so there is nothing further to do other than
+   avoid an empty file.  */
+typedef int dummy;
+#else /* HAVE_LSTAT */
+
+/* Get the original definition of lstat.  It might be defined as a macro.  */
+# include <sys/types.h>
+# include <sys/stat.h>
+# undef __need_system_sys_stat_h
+
+static int
+orig_lstat (const char *filename, struct stat *buf)
+{
+  return lstat (filename, buf);
+}
+
+/* Specification.  */
+/* Write "sys/stat.h" here, not <sys/stat.h>, otherwise OSF/1 5.1 DTK cc
+   eliminates this include because of the preliminary #include <sys/stat.h>
+   above.  */
+# 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 = orig_lstat (file, sbuf);
+
+  if (lstat_result != 0)
+    return lstat_result;
+
+  /* This replacement file can blindly check against '/' rather than
+     using the ISSLASH macro, because all platforms with '\\' either
+     lack symlinks (mingw) or have working lstat (cygwin) and thus do
+     not compile this file.  0 len should have already been filtered
+     out above, with a failure return of ENOENT.  */
+  len = strlen (file);
+  if (file[len - 1] != '/' || S_ISDIR (sbuf->st_mode))
+    return 0;
+
+  /* At this point, a trailing slash is only permitted on
+     symlink-to-dir; but it should have found information on the
+     directory, not the symlink.  Call stat() to get info about the
+     link's referent.  Our replacement stat guarantees valid results,
+     even if the symlink is not pointing to a directory.  */
+  if (!S_ISLNK (sbuf->st_mode))
+    {
+      errno = ENOTDIR;
+      return -1;
+    }
+  return stat (file, sbuf);
+}
+
+#endif /* HAVE_LSTAT */
diff --git a/libgnu/malloc.c b/libgnu/malloc.c
new file mode 100644
index 0000000..eeaf12b
--- /dev/null
+++ b/libgnu/malloc.c
@@ -0,0 +1,56 @@
+/* malloc() function that is glibc compatible.
+
+   Copyright (C) 1997-1998, 2006-2007, 2009-2017 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 version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+/* written by Jim Meyering and Bruno Haible */
+
+#define _GL_USE_STDLIB_ALLOC 1
+#include <config.h>
+/* Only the AC_FUNC_MALLOC macro defines 'malloc' already in config.h.  */
+#ifdef malloc
+# define NEED_MALLOC_GNU 1
+# undef malloc
+/* Whereas the gnulib module 'malloc-gnu' defines HAVE_MALLOC_GNU.  */
+#elif GNULIB_MALLOC_GNU && !HAVE_MALLOC_GNU
+# define NEED_MALLOC_GNU 1
+#endif
+
+#include <stdlib.h>
+
+#include <errno.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)
+{
+  void *result;
+
+#if NEED_MALLOC_GNU
+  if (n == 0)
+    n = 1;
+#endif
+
+  result = malloc (n);
+
+#if !HAVE_MALLOC_POSIX
+  if (result == NULL)
+    errno = ENOMEM;
+#endif
+
+  return result;
+}
diff --git a/libgnu/mbrtowc.c b/libgnu/mbrtowc.c
new file mode 100644
index 0000000..d4809f6
--- /dev/null
+++ b/libgnu/mbrtowc.c
@@ -0,0 +1,407 @@
+/* Convert multibyte character to wide character.
+   Copyright (C) 1999-2002, 2005-2017 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2008.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <wchar.h>
+
+#if C_LOCALE_MAYBE_EILSEQ
+# include "hard-locale.h"
+# include <locale.h>
+#endif
+
+#if GNULIB_defined_mbstate_t
+/* Implement mbrtowc() on top of mbtowc().  */
+
+# include <errno.h>
+# include <stdlib.h>
+
+# include "localcharset.h"
+# include "streq.h"
+# include "verify.h"
+
+
+verify (sizeof (mbstate_t) >= 4);
+
+static char internal_state[4];
+
+size_t
+mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
+{
+  char *pstate = (char *)ps;
+
+  if (s == NULL)
+    {
+      pwc = NULL;
+      s = "";
+      n = 1;
+    }
+
+  if (n == 0)
+    return (size_t)(-2);
+
+  /* Here n > 0.  */
+
+  if (pstate == NULL)
+    pstate = internal_state;
+
+  {
+    size_t nstate = pstate[0];
+    char buf[4];
+    const char *p;
+    size_t m;
+
+    switch (nstate)
+      {
+      case 0:
+        p = s;
+        m = n;
+        break;
+      case 3:
+        buf[2] = pstate[3];
+        /*FALLTHROUGH*/
+      case 2:
+        buf[1] = pstate[2];
+        /*FALLTHROUGH*/
+      case 1:
+        buf[0] = pstate[1];
+        p = buf;
+        m = nstate;
+        buf[m++] = s[0];
+        if (n >= 2 && m < 4)
+          {
+            buf[m++] = s[1];
+            if (n >= 3 && m < 4)
+              buf[m++] = s[2];
+          }
+        break;
+      default:
+        errno = EINVAL;
+        return (size_t)(-1);
+      }
+
+    /* Here m > 0.  */
+
+# if __GLIBC__ || defined __UCLIBC__
+    /* Work around bug <http://sourceware.org/bugzilla/show_bug.cgi?id=9674> */
+    mbtowc (NULL, NULL, 0);
+# endif
+    {
+      int res = mbtowc (pwc, p, m);
+
+      if (res >= 0)
+        {
+          if (pwc != NULL && ((*pwc == 0) != (res == 0)))
+            abort ();
+          if (nstate >= (res > 0 ? res : 1))
+            abort ();
+          res -= nstate;
+          pstate[0] = 0;
+          return res;
+        }
+
+      /* mbtowc does not distinguish between invalid and incomplete multibyte
+         sequences.  But mbrtowc needs to make this distinction.
+         There are two possible approaches:
+           - Use iconv() and its return value.
+           - Use built-in knowledge about the possible encodings.
+         Given the low quality of implementation of iconv() on the systems that
+         lack mbrtowc(), we use the second approach.
+         The possible encodings are:
+           - 8-bit encodings,
+           - EUC-JP, EUC-KR, GB2312, EUC-TW, BIG5, GB18030, SJIS,
+           - UTF-8.
+         Use specialized code for each.  */
+      if (m >= 4 || m >= MB_CUR_MAX)
+        goto invalid;
+      /* Here MB_CUR_MAX > 1 and 0 < m < 4.  */
+      {
+        const char *encoding = locale_charset ();
+
+        if (STREQ_OPT (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0))
+          {
+            /* Cf. unistr/u8-mblen.c.  */
+            unsigned char c = (unsigned char) p[0];
+
+            if (c >= 0xc2)
+              {
+                if (c < 0xe0)
+                  {
+                    if (m == 1)
+                      goto incomplete;
+                  }
+                else if (c < 0xf0)
+                  {
+                    if (m == 1)
+                      goto incomplete;
+                    if (m == 2)
+                      {
+                        unsigned char c2 = (unsigned char) p[1];
+
+                        if ((c2 ^ 0x80) < 0x40
+                            && (c >= 0xe1 || c2 >= 0xa0)
+                            && (c != 0xed || c2 < 0xa0))
+                          goto incomplete;
+                      }
+                  }
+                else if (c <= 0xf4)
+                  {
+                    if (m == 1)
+                      goto incomplete;
+                    else /* m == 2 || m == 3 */
+                      {
+                        unsigned char c2 = (unsigned char) p[1];
+
+                        if ((c2 ^ 0x80) < 0x40
+                            && (c >= 0xf1 || c2 >= 0x90)
+                            && (c < 0xf4 || (c == 0xf4 && c2 < 0x90)))
+                          {
+                            if (m == 2)
+                              goto incomplete;
+                            else /* m == 3 */
+                              {
+                                unsigned char c3 = (unsigned char) p[2];
+
+                                if ((c3 ^ 0x80) < 0x40)
+                                  goto incomplete;
+                              }
+                          }
+                      }
+                  }
+              }
+            goto invalid;
+          }
+
+        /* As a reference for this code, you can use the GNU libiconv
+           implementation.  Look for uses of the RET_TOOFEW macro.  */
+
+        if (STREQ_OPT (encoding,
+                       "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0))
+          {
+            if (m == 1)
+              {
+                unsigned char c = (unsigned char) p[0];
+
+                if ((c >= 0xa1 && c < 0xff) || c == 0x8e || c == 0x8f)
+                  goto incomplete;
+              }
+            if (m == 2)
+              {
+                unsigned char c = (unsigned char) p[0];
+
+                if (c == 0x8f)
+                  {
+                    unsigned char c2 = (unsigned char) p[1];
+
+                    if (c2 >= 0xa1 && c2 < 0xff)
+                      goto incomplete;
+                  }
+              }
+            goto invalid;
+          }
+        if (STREQ_OPT (encoding,
+                       "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0)
+            || STREQ_OPT (encoding,
+                          "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0)
+            || STREQ_OPT (encoding,
+                          "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0))
+          {
+            if (m == 1)
+              {
+                unsigned char c = (unsigned char) p[0];
+
+                if (c >= 0xa1 && c < 0xff)
+                  goto incomplete;
+              }
+            goto invalid;
+          }
+        if (STREQ_OPT (encoding,
+                       "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0))
+          {
+            if (m == 1)
+              {
+                unsigned char c = (unsigned char) p[0];
+
+                if ((c >= 0xa1 && c < 0xff) || c == 0x8e)
+                  goto incomplete;
+              }
+            else /* m == 2 || m == 3 */
+              {
+                unsigned char c = (unsigned char) p[0];
+
+                if (c == 0x8e)
+                  goto incomplete;
+              }
+            goto invalid;
+          }
+        if (STREQ_OPT (encoding,
+                       "GB18030", 'G', 'B', '1', '8', '0', '3', '0', 0, 0))
+          {
+            if (m == 1)
+              {
+                unsigned char c = (unsigned char) p[0];
+
+                if ((c >= 0x90 && c <= 0xe3) || (c >= 0xf8 && c <= 0xfe))
+                  goto incomplete;
+              }
+            else /* m == 2 || m == 3 */
+              {
+                unsigned char c = (unsigned char) p[0];
+
+                if (c >= 0x90 && c <= 0xe3)
+                  {
+                    unsigned char c2 = (unsigned char) p[1];
+
+                    if (c2 >= 0x30 && c2 <= 0x39)
+                      {
+                        if (m == 2)
+                          goto incomplete;
+                        else /* m == 3 */
+                          {
+                            unsigned char c3 = (unsigned char) p[2];
+
+                            if (c3 >= 0x81 && c3 <= 0xfe)
+                              goto incomplete;
+                          }
+                      }
+                  }
+              }
+            goto invalid;
+          }
+        if (STREQ_OPT (encoding, "SJIS", 'S', 'J', 'I', 'S', 0, 0, 0, 0, 0))
+          {
+            if (m == 1)
+              {
+                unsigned char c = (unsigned char) p[0];
+
+                if ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xea)
+                    || (c >= 0xf0 && c <= 0xf9))
+                  goto incomplete;
+              }
+            goto invalid;
+          }
+
+        /* An unknown multibyte encoding.  */
+        goto incomplete;
+      }
+
+     incomplete:
+      {
+        size_t k = nstate;
+        /* Here 0 <= k < m < 4.  */
+        pstate[++k] = s[0];
+        if (k < m)
+          {
+            pstate[++k] = s[1];
+            if (k < m)
+              pstate[++k] = s[2];
+          }
+        if (k != m)
+          abort ();
+      }
+      pstate[0] = m;
+      return (size_t)(-2);
+
+     invalid:
+      errno = EILSEQ;
+      /* The conversion state is undefined, says POSIX.  */
+      return (size_t)(-1);
+    }
+  }
+}
+
+#else
+/* Override the system's mbrtowc() function.  */
+
+# undef mbrtowc
+
+size_t
+rpl_mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
+{
+  size_t ret;
+  wchar_t wc;
+
+# if MBRTOWC_NULL_ARG2_BUG || MBRTOWC_RETVAL_BUG || MBRTOWC_EMPTY_INPUT_BUG
+  if (s == NULL)
+    {
+      pwc = NULL;
+      s = "";
+      n = 1;
+    }
+# endif
+
+# if MBRTOWC_EMPTY_INPUT_BUG
+  if (n == 0)
+    return (size_t) -2;
+# endif
+
+  if (! pwc)
+    pwc = &wc;
+
+# if MBRTOWC_RETVAL_BUG
+  {
+    static mbstate_t internal_state;
+
+    /* Override mbrtowc's internal state.  We cannot call mbsinit() on the
+       hidden internal state, but we can call it on our variable.  */
+    if (ps == NULL)
+      ps = &internal_state;
+
+    if (!mbsinit (ps))
+      {
+        /* Parse the rest of the multibyte character byte for byte.  */
+        size_t count = 0;
+        for (; n > 0; s++, n--)
+          {
+            ret = mbrtowc (&wc, s, 1, ps);
+
+            if (ret == (size_t)(-1))
+              return (size_t)(-1);
+            count++;
+            if (ret != (size_t)(-2))
+              {
+                /* The multibyte character has been completed.  */
+                *pwc = wc;
+                return (wc == 0 ? 0 : count);
+              }
+          }
+        return (size_t)(-2);
+      }
+  }
+# endif
+
+  ret = mbrtowc (pwc, s, n, ps);
+
+# if MBRTOWC_NUL_RETVAL_BUG
+  if (ret < (size_t) -2 && !*pwc)
+    return 0;
+# endif
+
+# if C_LOCALE_MAYBE_EILSEQ
+  if ((size_t) -2 <= ret && n != 0 && ! hard_locale (LC_CTYPE))
+    {
+      unsigned char uc = *s;
+      *pwc = uc;
+      return 1;
+    }
+# endif
+
+  return ret;
+}
+
+#endif
diff --git a/libgnu/mbsinit.c b/libgnu/mbsinit.c
new file mode 100644
index 0000000..58e0441
--- /dev/null
+++ b/libgnu/mbsinit.c
@@ -0,0 +1,61 @@
+/* Test for initial conversion state.
+   Copyright (C) 2008-2017 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2008.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <wchar.h>
+
+#include "verify.h"
+
+#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__
+
+/* On native Windows, 'mbstate_t' is defined as 'int'.  */
+
+int
+mbsinit (const mbstate_t *ps)
+{
+  return ps == NULL || *ps == 0;
+}
+
+#else
+
+/* Platforms that lack mbsinit() also lack mbrlen(), mbrtowc(), mbsrtowcs()
+   and wcrtomb(), wcsrtombs().
+   We assume that
+     - sizeof (mbstate_t) >= 4,
+     - only stateless encodings are supported (such as UTF-8 and EUC-JP, but
+       not ISO-2022 variants),
+     - for each encoding, the number of bytes for a wide character is <= 4.
+       (This maximum is attained for UTF-8, GB18030, EUC-TW.)
+   We define the meaning of mbstate_t as follows:
+     - In mb -> wc direction, mbstate_t's first byte contains the number of
+       buffered bytes (in the range 0..3), followed by up to 3 buffered bytes.
+     - In wc -> mb direction, mbstate_t contains no information. In other
+       words, it is always in the initial state.  */
+
+verify (sizeof (mbstate_t) >= 4);
+
+int
+mbsinit (const mbstate_t *ps)
+{
+  const char *pstate = (const char *)ps;
+
+  return pstate == NULL || pstate[0] == 0;
+}
+
+#endif
diff --git a/libgnu/mbsrtowcs-impl.h b/libgnu/mbsrtowcs-impl.h
new file mode 100644
index 0000000..d787c07
--- /dev/null
+++ b/libgnu/mbsrtowcs-impl.h
@@ -0,0 +1,122 @@
+/* Convert string to wide string.
+   Copyright (C) 2008-2017 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2008.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+size_t
+mbsrtowcs (wchar_t *dest, const char **srcp, size_t len, mbstate_t *ps)
+{
+  if (ps == NULL)
+    ps = &_gl_mbsrtowcs_state;
+  {
+    const char *src = *srcp;
+
+    if (dest != NULL)
+      {
+        wchar_t *destptr = dest;
+
+        for (; len > 0; destptr++, len--)
+          {
+            size_t src_avail;
+            size_t ret;
+
+            /* An optimized variant of
+               src_avail = strnlen1 (src, MB_LEN_MAX);  */
+            if (src[0] == '\0')
+              src_avail = 1;
+            else if (src[1] == '\0')
+              src_avail = 2;
+            else if (src[2] == '\0')
+              src_avail = 3;
+            else if (MB_LEN_MAX <= 4 || src[3] == '\0')
+              src_avail = 4;
+            else
+              src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4);
+
+            /* Parse the next multibyte character.  */
+            ret = mbrtowc (destptr, src, src_avail, ps);
+
+            if (ret == (size_t)(-2))
+              /* Encountered a multibyte character that extends past a '\0' byte
+                 or that is longer than MB_LEN_MAX bytes.  Cannot happen.  */
+              abort ();
+
+            if (ret == (size_t)(-1))
+              goto bad_input;
+            if (ret == 0)
+              {
+                src = NULL;
+                /* Here mbsinit (ps).  */
+                break;
+              }
+            src += ret;
+          }
+
+        *srcp = src;
+        return destptr - dest;
+      }
+    else
+      {
+        /* Ignore dest and len, don't store *srcp at the end, and
+           don't clobber *ps.  */
+        mbstate_t state = *ps;
+        size_t totalcount = 0;
+
+        for (;; totalcount++)
+          {
+            size_t src_avail;
+            size_t ret;
+
+            /* An optimized variant of
+               src_avail = strnlen1 (src, MB_LEN_MAX);  */
+            if (src[0] == '\0')
+              src_avail = 1;
+            else if (src[1] == '\0')
+              src_avail = 2;
+            else if (src[2] == '\0')
+              src_avail = 3;
+            else if (MB_LEN_MAX <= 4 || src[3] == '\0')
+              src_avail = 4;
+            else
+              src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4);
+
+            /* Parse the next multibyte character.  */
+            ret = mbrtowc (NULL, src, src_avail, &state);
+
+            if (ret == (size_t)(-2))
+              /* Encountered a multibyte character that extends past a '\0' byte
+                 or that is longer than MB_LEN_MAX bytes.  Cannot happen.  */
+              abort ();
+
+            if (ret == (size_t)(-1))
+              goto bad_input2;
+            if (ret == 0)
+              {
+                /* Here mbsinit (&state).  */
+                break;
+              }
+            src += ret;
+          }
+
+        return totalcount;
+      }
+
+   bad_input:
+    *srcp = src;
+   bad_input2:
+    errno = EILSEQ;
+    return (size_t)(-1);
+  }
+}
diff --git a/libgnu/mbsrtowcs-state.c b/libgnu/mbsrtowcs-state.c
new file mode 100644
index 0000000..4c213e4
--- /dev/null
+++ b/libgnu/mbsrtowcs-state.c
@@ -0,0 +1,37 @@
+/* Convert string to wide string.
+   Copyright (C) 2008-2017 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2008.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <wchar.h>
+
+/* Internal state used by the functions mbsrtowcs() and mbsnrtowcs().  */
+mbstate_t _gl_mbsrtowcs_state
+/* The state must initially be in the "initial state"; so, zero-initialize it.
+   On most systems, putting it into BSS is sufficient.  Not so on Mac OS X 10.3,
+   see <http://lists.gnu.org/archive/html/bug-gnulib/2009-01/msg00329.html>.
+   When it needs an initializer, use 0 or {0} as initializer? 0 only works
+   when mbstate_t is a scalar type (such as when gnulib defines it, or on
+   AIX, IRIX, mingw). {0} works as an initializer in all cases: for a struct
+   or union type, but also for a scalar type (ISO C 99, 6.7.8.(11)).  */
+#if defined __ELF__
+  /* On ELF systems, variables in BSS behave well.  */
+#else
+  /* Use braces, to be on the safe side.  */
+  = { 0 }
+#endif
+  ;
diff --git a/libgnu/mbsrtowcs.c b/libgnu/mbsrtowcs.c
new file mode 100644
index 0000000..7896e94
--- /dev/null
+++ b/libgnu/mbsrtowcs.c
@@ -0,0 +1,32 @@
+/* Convert string to wide string.
+   Copyright (C) 2008-2017 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2008.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <wchar.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include "strnlen1.h"
+
+
+extern mbstate_t _gl_mbsrtowcs_state;
+
+#include "mbsrtowcs-impl.h"
diff --git a/libgnu/memchr.c b/libgnu/memchr.c
new file mode 100644
index 0000000..3481260
--- /dev/null
+++ b/libgnu/memchr.c
@@ -0,0 +1,172 @@
+/* Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2004, 2006, 2008-2017
+   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).
+
+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 3 of the License, or any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <stddef.h>
+
+#if defined _LIBC
+# include <memcopy.h>
+#else
+# define reg_char char
+#endif
+
+#include <limits.h>
+
+#if HAVE_BP_SYM_H || defined _LIBC
+# include <bp-sym.h>
+#else
+# define BP_SYM(sym) sym
+#endif
+
+#undef __memchr
+#ifdef _LIBC
+# undef memchr
+#endif
+
+#ifndef weak_alias
+# define __memchr memchr
+#endif
+
+/* Search no more than N bytes of S for C.  */
+void *
+__memchr (void const *s, int c_in, size_t n)
+{
+  /* On 32-bit hardware, choosing longword to be a 32-bit unsigned
+     long instead of a 64-bit uintmax_t tends to give better
+     performance.  On 64-bit hardware, unsigned long is generally 64
+     bits already.  Change this typedef to experiment with
+     performance.  */
+  typedef unsigned long int longword;
+
+  const unsigned char *char_ptr;
+  const longword *longword_ptr;
+  longword repeated_one;
+  longword repeated_c;
+  unsigned reg_char c;
+
+  c = (unsigned char) c_in;
+
+  /* Handle the first few bytes by reading one byte at a time.
+     Do this until CHAR_PTR is aligned on a longword boundary.  */
+  for (char_ptr = (const unsigned char *) s;
+       n > 0 && (size_t) char_ptr % sizeof (longword) != 0;
+       --n, ++char_ptr)
+    if (*char_ptr == c)
+      return (void *) char_ptr;
+
+  longword_ptr = (const longword *) char_ptr;
+
+  /* All these elucidatory comments refer to 4-byte longwords,
+     but the theory applies equally well to any size longwords.  */
+
+  /* Compute auxiliary longword values:
+     repeated_one is a value which has a 1 in every byte.
+     repeated_c has c in every byte.  */
+  repeated_one = 0x01010101;
+  repeated_c = c | (c << 8);
+  repeated_c |= repeated_c << 16;
+  if (0xffffffffU < (longword) -1)
+    {
+      repeated_one |= repeated_one << 31 << 1;
+      repeated_c |= repeated_c << 31 << 1;
+      if (8 < sizeof (longword))
+        {
+          size_t i;
+
+          for (i = 64; i < sizeof (longword) * 8; i *= 2)
+            {
+              repeated_one |= repeated_one << i;
+              repeated_c |= repeated_c << i;
+            }
+        }
+    }
+
+  /* Instead of the traditional loop which tests each byte, 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 equal to c.  We first use an xor
+     with repeated_c.  This reduces the task to testing whether *any of the
+     four* bytes in longword1 is zero.
+
+     We compute tmp =
+       ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7).
+     That is, we perform the following operations:
+       1. Subtract repeated_one.
+       2. & ~longword1.
+       3. & a mask consisting of 0x80 in every byte.
+     Consider what happens in each byte:
+       - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
+         and step 3 transforms it into 0x80.  A carry can also be propagated
+         to more significant bytes.
+       - If a byte of longword1 is nonzero, let its lowest 1 bit be at
+         position k (0 <= k <= 7); so the lowest k bits are 0.  After step 1,
+         the byte ends in a single bit of value 0 and k bits of value 1.
+         After step 2, the result is just k bits of value 1: 2^k - 1.  After
+         step 3, the result is 0.  And no carry is produced.
+     So, if longword1 has only non-zero bytes, tmp is zero.
+     Whereas if longword1 has a zero byte, call j the position of the least
+     significant zero byte.  Then the result has a zero at positions 0, ...,
+     j-1 and a 0x80 at position j.  We cannot predict the result at the more
+     significant bytes (positions j+1..3), but it does not matter since we
+     already have a non-zero bit at position 8*j+7.
+
+     So, the test whether any byte in longword1 is zero is equivalent to
+     testing whether tmp is nonzero.  */
+
+  while (n >= sizeof (longword))
+    {
+      longword longword1 = *longword_ptr ^ repeated_c;
+
+      if ((((longword1 - repeated_one) & ~longword1)
+           & (repeated_one << 7)) != 0)
+        break;
+      longword_ptr++;
+      n -= sizeof (longword);
+    }
+
+  char_ptr = (const unsigned char *) longword_ptr;
+
+  /* At this point, we know that either n < sizeof (longword), or one of the
+     sizeof (longword) bytes starting at char_ptr is == c.  On little-endian
+     machines, we could determine the first such byte without any further
+     memory accesses, just by looking at the tmp result from the last loop
+     iteration.  But this does not work on big-endian machines.  Choose code
+     that works in both cases.  */
+
+  for (; n > 0; --n, ++char_ptr)
+    {
+      if (*char_ptr == c)
+        return (void *) char_ptr;
+    }
+
+  return NULL;
+}
+#ifdef weak_alias
+weak_alias (__memchr, BP_SYM (memchr))
+#endif
diff --git a/libgnu/memchr.valgrind b/libgnu/memchr.valgrind
new file mode 100644
index 0000000..60f247e
--- /dev/null
+++ b/libgnu/memchr.valgrind
@@ -0,0 +1,14 @@
+# Suppress a valgrind message about use of uninitialized memory in memchr().
+# POSIX states that when the character is found, memchr must not read extra
+# bytes in an overestimated length (for example, where memchr is used to
+# implement strnlen).  However, we use a safe word read to provide a speedup.
+{
+    memchr-value4
+    Memcheck:Value4
+    fun:rpl_memchr
+}
+{
+    memchr-value8
+    Memcheck:Value8
+    fun:rpl_memchr
+}
diff --git a/libgnu/mempcpy.c b/libgnu/mempcpy.c
new file mode 100644
index 0000000..e9a0678
--- /dev/null
+++ b/libgnu/mempcpy.c
@@ -0,0 +1,28 @@
+/* Copy memory area and return pointer after last written byte.
+   Copyright (C) 2003, 2007, 2009-2017 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 version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <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/libgnu/memrchr.c b/libgnu/memrchr.c
new file mode 100644
index 0000000..fefe16c
--- /dev/null
+++ b/libgnu/memrchr.c
@@ -0,0 +1,161 @@
+/* memrchr -- find the last occurrence of a byte in a memory block
+
+   Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2017 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#if defined _LIBC
+# include <memcopy.h>
+#else
+# include <config.h>
+# define reg_char char
+#endif
+
+#include <string.h>
+#include <limits.h>
+
+#undef __memrchr
+#ifdef _LIBC
+# undef memrchr
+#endif
+
+#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)
+{
+  /* On 32-bit hardware, choosing longword to be a 32-bit unsigned
+     long instead of a 64-bit uintmax_t tends to give better
+     performance.  On 64-bit hardware, unsigned long is generally 64
+     bits already.  Change this typedef to experiment with
+     performance.  */
+  typedef unsigned long int longword;
+
+  const unsigned char *char_ptr;
+  const longword *longword_ptr;
+  longword repeated_one;
+  longword repeated_c;
+  unsigned reg_char c;
+
+  c = (unsigned char) c_in;
+
+  /* Handle the last few bytes by reading one byte 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;
+
+  longword_ptr = (const longword *) char_ptr;
+
+  /* All these elucidatory comments refer to 4-byte longwords,
+     but the theory applies equally well to any size longwords.  */
+
+  /* Compute auxiliary longword values:
+     repeated_one is a value which has a 1 in every byte.
+     repeated_c has c in every byte.  */
+  repeated_one = 0x01010101;
+  repeated_c = c | (c << 8);
+  repeated_c |= repeated_c << 16;
+  if (0xffffffffU < (longword) -1)
+    {
+      repeated_one |= repeated_one << 31 << 1;
+      repeated_c |= repeated_c << 31 << 1;
+      if (8 < sizeof (longword))
+        {
+          size_t i;
+
+          for (i = 64; i < sizeof (longword) * 8; i *= 2)
+            {
+              repeated_one |= repeated_one << i;
+              repeated_c |= repeated_c << i;
+            }
+        }
+    }
+
+  /* Instead of the traditional loop which tests each byte, 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 equal to c.  We first use an xor
+     with repeated_c.  This reduces the task to testing whether *any of the
+     four* bytes in longword1 is zero.
+
+     We compute tmp =
+       ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7).
+     That is, we perform the following operations:
+       1. Subtract repeated_one.
+       2. & ~longword1.
+       3. & a mask consisting of 0x80 in every byte.
+     Consider what happens in each byte:
+       - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
+         and step 3 transforms it into 0x80.  A carry can also be propagated
+         to more significant bytes.
+       - If a byte of longword1 is nonzero, let its lowest 1 bit be at
+         position k (0 <= k <= 7); so the lowest k bits are 0.  After step 1,
+         the byte ends in a single bit of value 0 and k bits of value 1.
+         After step 2, the result is just k bits of value 1: 2^k - 1.  After
+         step 3, the result is 0.  And no carry is produced.
+     So, if longword1 has only non-zero bytes, tmp is zero.
+     Whereas if longword1 has a zero byte, call j the position of the least
+     significant zero byte.  Then the result has a zero at positions 0, ...,
+     j-1 and a 0x80 at position j.  We cannot predict the result at the more
+     significant bytes (positions j+1..3), but it does not matter since we
+     already have a non-zero bit at position 8*j+7.
+
+     So, the test whether any byte in longword1 is zero is equivalent to
+     testing whether tmp is nonzero.  */
+
+  while (n >= sizeof (longword))
+    {
+      longword longword1 = *--longword_ptr ^ repeated_c;
+
+      if ((((longword1 - repeated_one) & ~longword1)
+           & (repeated_one << 7)) != 0)
+        {
+          longword_ptr++;
+          break;
+        }
+      n -= sizeof (longword);
+    }
+
+  char_ptr = (const unsigned char *) longword_ptr;
+
+  /* At this point, we know that either n < sizeof (longword), or one of the
+     sizeof (longword) bytes starting at char_ptr is == c.  On little-endian
+     machines, we could determine the first such byte without any further
+     memory accesses, just by looking at the tmp result from the last loop
+     iteration.  But this does not work on big-endian machines.  Choose code
+     that works in both cases.  */
+
+  while (n-- > 0)
+    {
+      if (*--char_ptr == c)
+        return (void *) char_ptr;
+    }
+
+  return NULL;
+}
+#ifdef weak_alias
+weak_alias (__memrchr, memrchr)
+#endif
diff --git a/libgnu/msvc-inval.c b/libgnu/msvc-inval.c
new file mode 100644
index 0000000..7139e93
--- /dev/null
+++ b/libgnu/msvc-inval.c
@@ -0,0 +1,129 @@
+/* Invalid parameter handler for MSVC runtime libraries.
+   Copyright (C) 2011-2017 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 version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "msvc-inval.h"
+
+#if HAVE_MSVC_INVALID_PARAMETER_HANDLER \
+    && !(MSVC_INVALID_PARAMETER_HANDLING == SANE_LIBRARY_HANDLING)
+
+/* Get _invalid_parameter_handler type and _set_invalid_parameter_handler
+   declaration.  */
+# include <stdlib.h>
+
+# if MSVC_INVALID_PARAMETER_HANDLING == DEFAULT_HANDLING
+
+static void __cdecl
+gl_msvc_invalid_parameter_handler (const wchar_t *expression,
+                                   const wchar_t *function,
+                                   const wchar_t *file,
+                                   unsigned int line,
+                                   uintptr_t dummy)
+{
+}
+
+# else
+
+/* Get declarations of the native Windows API functions.  */
+#  define WIN32_LEAN_AND_MEAN
+#  include <windows.h>
+
+#  if defined _MSC_VER
+
+static void __cdecl
+gl_msvc_invalid_parameter_handler (const wchar_t *expression,
+                                   const wchar_t *function,
+                                   const wchar_t *file,
+                                   unsigned int line,
+                                   uintptr_t dummy)
+{
+  RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL);
+}
+
+#  else
+
+/* An index to thread-local storage.  */
+static DWORD tls_index;
+static int tls_initialized /* = 0 */;
+
+/* Used as a fallback only.  */
+static struct gl_msvc_inval_per_thread not_per_thread;
+
+struct gl_msvc_inval_per_thread *
+gl_msvc_inval_current (void)
+{
+  if (!tls_initialized)
+    {
+      tls_index = TlsAlloc ();
+      tls_initialized = 1;
+    }
+  if (tls_index == TLS_OUT_OF_INDEXES)
+    /* TlsAlloc had failed.  */
+    return &not_per_thread;
+  else
+    {
+      struct gl_msvc_inval_per_thread *pointer =
+        (struct gl_msvc_inval_per_thread *) TlsGetValue (tls_index);
+      if (pointer == NULL)
+        {
+          /* First call.  Allocate a new 'struct gl_msvc_inval_per_thread'.  */
+          pointer =
+            (struct gl_msvc_inval_per_thread *)
+            malloc (sizeof (struct gl_msvc_inval_per_thread));
+          if (pointer == NULL)
+            /* Could not allocate memory.  Use the global storage.  */
+            pointer = &not_per_thread;
+          TlsSetValue (tls_index, pointer);
+        }
+      return pointer;
+    }
+}
+
+static void __cdecl
+gl_msvc_invalid_parameter_handler (const wchar_t *expression,
+                                   const wchar_t *function,
+                                   const wchar_t *file,
+                                   unsigned int line,
+                                   uintptr_t dummy)
+{
+  struct gl_msvc_inval_per_thread *current = gl_msvc_inval_current ();
+  if (current->restart_valid)
+    longjmp (current->restart, 1);
+  else
+    /* An invalid parameter notification from outside the gnulib code.
+       Give the caller a chance to intervene.  */
+    RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL);
+}
+
+#  endif
+
+# endif
+
+static int gl_msvc_inval_initialized /* = 0 */;
+
+void
+gl_msvc_inval_ensure_handler (void)
+{
+  if (gl_msvc_inval_initialized == 0)
+    {
+      _set_invalid_parameter_handler (gl_msvc_invalid_parameter_handler);
+      gl_msvc_inval_initialized = 1;
+    }
+}
+
+#endif
diff --git a/libgnu/msvc-inval.h b/libgnu/msvc-inval.h
new file mode 100644
index 0000000..6e216d6
--- /dev/null
+++ b/libgnu/msvc-inval.h
@@ -0,0 +1,222 @@
+/* Invalid parameter handler for MSVC runtime libraries.
+   Copyright (C) 2011-2017 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 version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _MSVC_INVAL_H
+#define _MSVC_INVAL_H
+
+/* With MSVC runtime libraries with the "invalid parameter handler" concept,
+   functions like fprintf(), dup2(), or close() crash when the caller passes
+   an invalid argument.  But POSIX wants error codes (such as EINVAL or EBADF)
+   instead.
+   This file defines macros that turn such an invalid parameter notification
+   into a non-local exit.  An error code can then be produced at the target
+   of this exit.  You can thus write code like
+
+     TRY_MSVC_INVAL
+       {
+         <Code that can trigger an invalid parameter notification
+          but does not do 'return', 'break', 'continue', nor 'goto'.>
+       }
+     CATCH_MSVC_INVAL
+       {
+         <Code that handles an invalid parameter notification
+          but does not do 'return', 'break', 'continue', nor 'goto'.>
+       }
+     DONE_MSVC_INVAL;
+
+   This entire block expands to a single statement.
+
+   The handling of invalid parameters can be done in three ways:
+
+     * The default way, which is reasonable for programs (not libraries):
+       AC_DEFINE([MSVC_INVALID_PARAMETER_HANDLING], [DEFAULT_HANDLING])
+
+     * The way for libraries that make "hairy" calls (like close(-1), or
+       fclose(fp) where fileno(fp) is closed, or simply getdtablesize()):
+       AC_DEFINE([MSVC_INVALID_PARAMETER_HANDLING], [HAIRY_LIBRARY_HANDLING])
+
+     * The way for libraries that make no "hairy" calls:
+       AC_DEFINE([MSVC_INVALID_PARAMETER_HANDLING], [SANE_LIBRARY_HANDLING])
+ */
+
+#define DEFAULT_HANDLING       0
+#define HAIRY_LIBRARY_HANDLING 1
+#define SANE_LIBRARY_HANDLING  2
+
+#if HAVE_MSVC_INVALID_PARAMETER_HANDLER \
+    && !(MSVC_INVALID_PARAMETER_HANDLING == SANE_LIBRARY_HANDLING)
+/* A native Windows platform with the "invalid parameter handler" concept,
+   and either DEFAULT_HANDLING or HAIRY_LIBRARY_HANDLING.  */
+
+# if MSVC_INVALID_PARAMETER_HANDLING == DEFAULT_HANDLING
+/* Default handling.  */
+
+#  ifdef __cplusplus
+extern "C" {
+#  endif
+
+/* Ensure that the invalid parameter handler in installed that just returns.
+   Because we assume no other part of the program installs a different
+   invalid parameter handler, this solution is multithread-safe.  */
+extern void gl_msvc_inval_ensure_handler (void);
+
+#  ifdef __cplusplus
+}
+#  endif
+
+#  define TRY_MSVC_INVAL \
+     do                                                                        \
+       {                                                                       \
+         gl_msvc_inval_ensure_handler ();                                      \
+         if (1)
+#  define CATCH_MSVC_INVAL \
+         else
+#  define DONE_MSVC_INVAL \
+       }                                                                       \
+     while (0)
+
+# else
+/* Handling for hairy libraries.  */
+
+#  include <excpt.h>
+
+/* Gnulib can define its own status codes, as described in the page
+   "Raising Software Exceptions" on microsoft.com
+   <http://msdn.microsoft.com/en-us/library/het71c37.aspx>.
+   Our status codes are composed of
+     - 0xE0000000, mandatory for all user-defined status codes,
+     - 0x474E550, a API identifier ("GNU"),
+     - 0, 1, 2, ..., used to distinguish different status codes from the
+       same API.  */
+#  define STATUS_GNULIB_INVALID_PARAMETER (0xE0000000 + 0x474E550 + 0)
+
+#  if defined _MSC_VER
+/* A compiler that supports __try/__except, as described in the page
+   "try-except statement" on microsoft.com
+   <http://msdn.microsoft.com/en-us/library/s58ftw19.aspx>.
+   With __try/__except, we can use the multithread-safe exception handling.  */
+
+#   ifdef __cplusplus
+extern "C" {
+#   endif
+
+/* Ensure that the invalid parameter handler in installed that raises a
+   software exception with code STATUS_GNULIB_INVALID_PARAMETER.
+   Because we assume no other part of the program installs a different
+   invalid parameter handler, this solution is multithread-safe.  */
+extern void gl_msvc_inval_ensure_handler (void);
+
+#   ifdef __cplusplus
+}
+#   endif
+
+#   define TRY_MSVC_INVAL \
+      do                                                                       \
+        {                                                                      \
+          gl_msvc_inval_ensure_handler ();                                     \
+          __try
+#   define CATCH_MSVC_INVAL \
+          __except (GetExceptionCode () == STATUS_GNULIB_INVALID_PARAMETER     \
+                    ? EXCEPTION_EXECUTE_HANDLER                                \
+                    : EXCEPTION_CONTINUE_SEARCH)
+#   define DONE_MSVC_INVAL \
+        }                                                                      \
+      while (0)
+
+#  else
+/* Any compiler.
+   We can only use setjmp/longjmp.  */
+
+#   include <setjmp.h>
+
+#   ifdef __cplusplus
+extern "C" {
+#   endif
+
+struct gl_msvc_inval_per_thread
+{
+  /* The restart that will resume execution at the code between
+     CATCH_MSVC_INVAL and DONE_MSVC_INVAL.  It is enabled only between
+     TRY_MSVC_INVAL and CATCH_MSVC_INVAL.  */
+  jmp_buf restart;
+
+  /* Tells whether the contents of restart is valid.  */
+  int restart_valid;
+};
+
+/* Ensure that the invalid parameter handler in installed that passes
+   control to the gl_msvc_inval_restart if it is valid, or raises a
+   software exception with code STATUS_GNULIB_INVALID_PARAMETER otherwise.
+   Because we assume no other part of the program installs a different
+   invalid parameter handler, this solution is multithread-safe.  */
+extern void gl_msvc_inval_ensure_handler (void);
+
+/* Return a pointer to the per-thread data for the current thread.  */
+extern struct gl_msvc_inval_per_thread *gl_msvc_inval_current (void);
+
+#   ifdef __cplusplus
+}
+#   endif
+
+#   define TRY_MSVC_INVAL \
+      do                                                                       \
+        {                                                                      \
+          struct gl_msvc_inval_per_thread *msvc_inval_current;                 \
+          gl_msvc_inval_ensure_handler ();                                     \
+          msvc_inval_current = gl_msvc_inval_current ();                       \
+          /* First, initialize gl_msvc_inval_restart.  */                      \
+          if (setjmp (msvc_inval_current->restart) == 0)                       \
+            {                                                                  \
+              /* Then, mark it as valid.  */                                   \
+              msvc_inval_current->restart_valid = 1;
+#   define CATCH_MSVC_INVAL \
+              /* Execution completed.                                          \
+                 Mark gl_msvc_inval_restart as invalid.  */                    \
+              msvc_inval_current->restart_valid = 0;                           \
+            }                                                                  \
+          else                                                                 \
+            {                                                                  \
+              /* Execution triggered an invalid parameter notification.        \
+                 Mark gl_msvc_inval_restart as invalid.  */                    \
+              msvc_inval_current->restart_valid = 0;
+#   define DONE_MSVC_INVAL \
+            }                                                                  \
+        }                                                                      \
+      while (0)
+
+#  endif
+
+# endif
+
+#else
+/* A platform that does not need to the invalid parameter handler,
+   or when SANE_LIBRARY_HANDLING is desired.  */
+
+/* The braces here avoid GCC warnings like
+   "warning: suggest explicit braces to avoid ambiguous 'else'".  */
+# define TRY_MSVC_INVAL \
+    do                                                                         \
+      {                                                                        \
+        if (1)
+# define CATCH_MSVC_INVAL \
+        else
+# define DONE_MSVC_INVAL \
+      }                                                                        \
+    while (0)
+
+#endif
+
+#endif /* _MSVC_INVAL_H */
diff --git a/libgnu/msvc-nothrow.c b/libgnu/msvc-nothrow.c
new file mode 100644
index 0000000..d127eb4
--- /dev/null
+++ b/libgnu/msvc-nothrow.c
@@ -0,0 +1,49 @@
+/* Wrappers that don't throw invalid parameter notifications
+   with MSVC runtime libraries.
+   Copyright (C) 2011-2017 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 version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "msvc-nothrow.h"
+
+/* Get declarations of the native Windows API functions.  */
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include "msvc-inval.h"
+
+#undef _get_osfhandle
+
+#if HAVE_MSVC_INVALID_PARAMETER_HANDLER
+intptr_t
+_gl_nothrow_get_osfhandle (int fd)
+{
+  intptr_t result;
+
+  TRY_MSVC_INVAL
+    {
+      result = _get_osfhandle (fd);
+    }
+  CATCH_MSVC_INVAL
+    {
+      result = (intptr_t) INVALID_HANDLE_VALUE;
+    }
+  DONE_MSVC_INVAL;
+
+  return result;
+}
+#endif
diff --git a/libgnu/msvc-nothrow.h b/libgnu/msvc-nothrow.h
new file mode 100644
index 0000000..c70efc7
--- /dev/null
+++ b/libgnu/msvc-nothrow.h
@@ -0,0 +1,43 @@
+/* Wrappers that don't throw invalid parameter notifications
+   with MSVC runtime libraries.
+   Copyright (C) 2011-2017 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 version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _MSVC_NOTHROW_H
+#define _MSVC_NOTHROW_H
+
+/* With MSVC runtime libraries with the "invalid parameter handler" concept,
+   functions like fprintf(), dup2(), or close() crash when the caller passes
+   an invalid argument.  But POSIX wants error codes (such as EINVAL or EBADF)
+   instead.
+   This file defines wrappers that turn such an invalid parameter notification
+   into an error code.  */
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+/* Get original declaration of _get_osfhandle.  */
+# include <io.h>
+
+# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
+
+/* Override _get_osfhandle.  */
+extern intptr_t _gl_nothrow_get_osfhandle (int fd);
+#  define _get_osfhandle _gl_nothrow_get_osfhandle
+
+# endif
+
+#endif
+
+#endif /* _MSVC_NOTHROW_H */
diff --git a/libgnu/obstack.c b/libgnu/obstack.c
new file mode 100644
index 0000000..54b675d
--- /dev/null
+++ b/libgnu/obstack.c
@@ -0,0 +1,354 @@
+/* obstack.c - subroutines used implicitly by object stack macros
+   Copyright (C) 1988-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can 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.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+
+#ifdef _LIBC
+# include <obstack.h>
+#else
+# include <config.h>
+# include "obstack.h"
+#endif
+
+/* NOTE BEFORE MODIFYING THIS FILE: _OBSTACK_INTERFACE_VERSION in
+   obstack.h must be incremented whenever callers compiled using an old
+   obstack.h can no longer properly call the functions in this file.  */
+
+/* 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.  */
+#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
+# include <gnu-versions.h>
+# if (_GNU_OBSTACK_INTERFACE_VERSION == _OBSTACK_INTERFACE_VERSION	      \
+      || (_GNU_OBSTACK_INTERFACE_VERSION == 1				      \
+          && _OBSTACK_INTERFACE_VERSION == 2				      \
+          && defined SIZEOF_INT && defined SIZEOF_SIZE_T		      \
+          && SIZEOF_INT == SIZEOF_SIZE_T))
+#  define _OBSTACK_ELIDE_CODE
+# endif
+#endif
+
+#ifndef _OBSTACK_ELIDE_CODE
+/* If GCC, or if an oddball (testing?) host that #defines __alignof__,
+   use the already-supplied __alignof__.  Otherwise, this must be Gnulib
+   (as glibc assumes GCC); defer to Gnulib's alignof_type.  */
+# if !defined __GNUC__ && !defined __alignof__
+#  include <alignof.h>
+#  define __alignof__(type) alignof_type (type)
+# endif
+# include <stdlib.h>
+# include <stdint.h>
+
+# ifndef MAX
+#  define MAX(a,b) ((a) > (b) ? (a) : (b))
+# endif
+
+/* Determine default alignment.  */
+
+/* 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.
+
+   DEFAULT_ALIGNMENT cannot be an enum constant; see gnulib's alignof.h.  */
+#define DEFAULT_ALIGNMENT MAX (__alignof__ (long double),		      \
+                               MAX (__alignof__ (uintmax_t),		      \
+                                    __alignof__ (void *)))
+#define DEFAULT_ROUNDING MAX (sizeof (long double),			      \
+                               MAX (sizeof (uintmax_t),			      \
+                                    sizeof (void *)))
+
+/* Call functions with either the traditional malloc/free calling
+   interface, or the mmalloc/mfree interface (that adds an extra first
+   argument), based on the value of use_extra_arg.  */
+
+static void *
+call_chunkfun (struct obstack *h, s