libprelude/master: Use posix version of GnuLib snprintf/vsnprintf module

[email protected] Tue, 16 Mar 2010 15:51:57 +0100 (CET)
Newsgroups gmane.comp.security.ids.prelude.cvs
Message-ID <[email protected]>
--===============1472291964296053651==
Content-type: text

commit 5245209e041a9f3e51b844ec91ece07a1c608190
Author: Yoann Vandoorselaere <[email protected]>
Date:   Mon Feb 8 11:18:30 2010 +0100

    Use posix version of GnuLib snprintf/vsnprintf module
    
    Prelude user can now rely on C99 format definition when using prelude-string.


========================================

 libmissing/Makefile.am                  |  185 ++-
 libmissing/fpucw.h                      |  107 ++
 libmissing/frexp.c                      |  166 ++
 libmissing/frexpl.c                     |   18 +
 libmissing/isnan.c                      |  173 ++
 libmissing/isnand-nolibm.h              |   33 +
 libmissing/isnand.c                     |   19 +
 libmissing/isnanf-nolibm.h              |   33 +
 libmissing/isnanf.c                     |   20 +
 libmissing/isnanl-nolibm.h              |   33 +
 libmissing/isnanl.c                     |   20 +
 libmissing/m4/exponentd.m4              |  114 ++
 libmissing/m4/exponentf.m4              |   91 +
 libmissing/m4/exponentl.m4              |   97 +
 libmissing/m4/fpieee.m4                 |   52 +
 libmissing/m4/frexp.m4                  |  146 ++
 libmissing/m4/frexpl.m4                 |  186 ++
 libmissing/m4/getdelim.m4               |   65 +-
 libmissing/m4/getline.m4                |   38 +-
 libmissing/m4/gettimeofday.m4           |   61 +-
 libmissing/m4/gnulib-cache.m4           |    6 +-
 libmissing/m4/gnulib-comp.m4            |   80 +
 libmissing/m4/isnand.m4                 |   95 +
 libmissing/m4/isnanf.m4                 |  179 ++
 libmissing/m4/isnanl.m4                 |  245 +++
 libmissing/m4/ldexpl.m4                 |   88 +
 libmissing/m4/math_h.m4                 |  128 ++
 libmissing/m4/nocrash.m4                |  102 +
 libmissing/m4/printf-frexp.m4           |   45 +
 libmissing/m4/printf-frexpl.m4          |   64 +
 libmissing/m4/regex.m4                  |    7 +
 libmissing/m4/signbit.m4                |  287 +++
 libmissing/m4/snprintf-posix.m4         |  126 ++
 libmissing/m4/stdio_h.m4                |    3 +-
 libmissing/m4/sys_time_h.m4             |   44 +-
 libmissing/m4/vsnprintf-posix.m4        |  127 ++
 libmissing/math.in.h                    |  633 +++++++
 libmissing/printf-frexp.c               |  188 ++
 libmissing/printf-frexp.h               |   23 +
 libmissing/printf-frexpl.c              |   18 +
 libmissing/printf-frexpl.h              |   23 +
 libmissing/regcomp.c                    |   15 +-
 libmissing/signbitd.c                   |   64 +
 libmissing/signbitf.c                   |   64 +
 libmissing/signbitl.c                   |   64 +
 libmissing/stdio.in.h                   |    6 +-
 libmissing/sys_time.in.h                |   16 +-
 libmissing/tests/Makefile.am            |  102 +
 libmissing/tests/ignore-value.h         |   37 +
 libmissing/tests/nan.h                  |   60 +
 libmissing/tests/test-frexp.c           |  199 ++
 libmissing/tests/test-frexpl.c          |  223 +++
 libmissing/tests/test-getdelim.c        |   19 +-
 libmissing/tests/test-getline.c         |   19 +-
 libmissing/tests/test-gettimeofday.c    |    8 +-
 libmissing/tests/test-isnand-nolibm.c   |   22 +
 libmissing/tests/test-isnand.h          |   65 +
 libmissing/tests/test-isnanf-nolibm.c   |   21 +
 libmissing/tests/test-isnanf.h          |   67 +
 libmissing/tests/test-isnanl-nolibm.c   |   23 +
 libmissing/tests/test-isnanl.h          |  141 ++
 libmissing/tests/test-lstat.c           |    3 +-
 libmissing/tests/test-math.c            |   53 +
 libmissing/tests/test-poll.c            |    2 +-
 libmissing/tests/test-printf-frexp.c    |  119 ++
 libmissing/tests/test-printf-frexpl.c   |  134 ++
 libmissing/tests/test-signbit.c         |  197 ++
 libmissing/tests/test-snprintf-posix.c  |   38 +
 libmissing/tests/test-snprintf-posix.h  | 3113 +++++++++++++++++++++++++++++++
 libmissing/tests/test-symlink.c         |    3 +-
 libmissing/tests/test-vsnprintf-posix.c |   51 +
 71 files changed, 9026 insertions(+), 90 deletions(-)

========================================

diff --git a/libmissing/Makefile.am b/libmissing/Makefile.am
index a8c4cbf..eead8a8 100644
--- a/libmissing/Makefile.am
+++ b/libmissing/Makefile.am
@@ -9,7 +9,7 @@
 # the same distribution terms as the rest of that program.
 #
 # Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --lib=libmissing --source-base=libmissing --m4-base=libmissing/m4 --doc-base=libmissing/doc --tests-base=libmissing/tests --aux-dir=. --with-tests --lgpl --libtool --macro-prefix=gl --no-vc-files accept bind close cond connect dup2 fclose fopen ftw getaddrinfo getpass getsockname gettimeofday inet_ntop inet_pton ioctl listen lock lseek memmem minmax pathmax perror poll regex relocatable-lib-lgpl select setsockopt sigprocmask sleep snprintf socket socklen strcase strcasestr strdup strerror strndup strptime strsep sys_stat thread time_r timegm tls uname vsnprintf write
+# Reproduce by: gnulib-tool --import --dir=. --lib=libmissing --source-base=libmissing --m4-base=libmissing/m4 --doc-base=libmissing/doc --tests-base=libmissing/tests --aux-dir=. --with-tests --lgpl --libtool --macro-prefix=gl --no-vc-files accept bind close cond connect dup2 fclose fopen ftw getaddrinfo getpass getsockname gettimeofday inet_ntop inet_pton ioctl listen lock lseek memmem minmax pathmax perror poll regex relocatable-lib-lgpl select setsockopt sigprocmask sleep snprintf-posix socket socklen strcase strcasestr strdup strerror strndup strptime strsep sys_stat thread time_r timegm tls uname vsnprintf-posix write
 
 AUTOMAKE_OPTIONS = 1.5 gnits subdir-objects
 
@@ -330,6 +330,31 @@ EXTRA_libmissing_la_SOURCES += fopen.c
 
 ## end   gnulib module fopen
 
+## begin gnulib module fpucw
+
+
+EXTRA_DIST += fpucw.h
+
+## end   gnulib module fpucw
+
+## begin gnulib module frexp-nolibm
+
+
+EXTRA_DIST += frexp.c
+
+EXTRA_libmissing_la_SOURCES += frexp.c
+
+## end   gnulib module frexp-nolibm
+
+## begin gnulib module frexpl-nolibm
+
+
+EXTRA_DIST += frexp.c frexpl.c
+
+EXTRA_libmissing_la_SOURCES += frexp.c frexpl.c
+
+## end   gnulib module frexpl-nolibm
+
 ## begin gnulib module fseeko
 
 
@@ -459,6 +484,33 @@ EXTRA_libmissing_la_SOURCES += ioctl.c
 
 ## end   gnulib module ioctl
 
+## begin gnulib module isnand-nolibm
+
+
+EXTRA_DIST += float+.h isnan.c isnand-nolibm.h isnand.c
+
+EXTRA_libmissing_la_SOURCES += isnan.c isnand.c
+
+## end   gnulib module isnand-nolibm
+
+## begin gnulib module isnanf-nolibm
+
+
+EXTRA_DIST += float+.h isnan.c isnanf-nolibm.h isnanf.c
+
+EXTRA_libmissing_la_SOURCES += isnan.c isnanf.c
+
+## end   gnulib module isnanf-nolibm
+
+## begin gnulib module isnanl-nolibm
+
+
+EXTRA_DIST += float+.h isnan.c isnanl-nolibm.h isnanl.c
+
+EXTRA_libmissing_la_SOURCES += isnan.c isnanl.c
+
+## end   gnulib module isnanl-nolibm
+
 ## begin gnulib module langinfo
 
 BUILT_SOURCES += langinfo.h
@@ -603,6 +655,101 @@ EXTRA_libmissing_la_SOURCES += malloc.c
 
 ## end   gnulib module malloc-posix
 
+## begin gnulib module math
+
+BUILT_SOURCES += math.h
+
+# We need the following in order to create <math.h> when the system
+# doesn't have one that works with the given compiler.
+math.h: math.in.h $(WARN_ON_USE_H) $(ARG_NONNULL_H)
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+	  sed -e 's|@''INCLUDE_NEXT_AS_FIRST_DIRECTIVE''@|$(INCLUDE_NEXT_AS_FIRST_DIRECTIVE)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''NEXT_AS_FIRST_DIRECTIVE_MATH_H''@|$(NEXT_AS_FIRST_DIRECTIVE_MATH_H)|g' \
+	      -e 's|@''GNULIB_ACOSL''@|$(GNULIB_ACOSL)|g' \
+	      -e 's|@''GNULIB_ASINL''@|$(GNULIB_ASINL)|g' \
+	      -e 's|@''GNULIB_ATANL''@|$(GNULIB_ATANL)|g' \
+	      -e 's|@''GNULIB_CEILF''@|$(GNULIB_CEILF)|g' \
+	      -e 's|@''GNULIB_CEILL''@|$(GNULIB_CEILL)|g' \
+	      -e 's|@''GNULIB_COSL''@|$(GNULIB_COSL)|g' \
+	      -e 's|@''GNULIB_EXPL''@|$(GNULIB_EXPL)|g' \
+	      -e 's|@''GNULIB_FLOORF''@|$(GNULIB_FLOORF)|g' \
+	      -e 's|@''GNULIB_FLOORL''@|$(GNULIB_FLOORL)|g' \
+	      -e 's|@''GNULIB_FREXP''@|$(GNULIB_FREXP)|g' \
+	      -e 's|@''GNULIB_FREXPL''@|$(GNULIB_FREXPL)|g' \
+	      -e 's|@''GNULIB_ISFINITE''@|$(GNULIB_ISFINITE)|g' \
+	      -e 's|@''GNULIB_ISINF''@|$(GNULIB_ISINF)|g' \
+	      -e 's|@''GNULIB_ISNAN''@|$(GNULIB_ISNAN)|g' \
+	      -e 's|@''GNULIB_ISNANF''@|$(GNULIB_ISNANF)|g' \
+	      -e 's|@''GNULIB_ISNAND''@|$(GNULIB_ISNAND)|g' \
+	      -e 's|@''GNULIB_ISNANL''@|$(GNULIB_ISNANL)|g' \
+	      -e 's|@''GNULIB_LDEXPL''@|$(GNULIB_LDEXPL)|g' \
+	      -e 's|@''GNULIB_LOGL''@|$(GNULIB_LOGL)|g' \
+	      -e 's|@''GNULIB_ROUND''@|$(GNULIB_ROUND)|g' \
+	      -e 's|@''GNULIB_ROUNDF''@|$(GNULIB_ROUNDF)|g' \
+	      -e 's|@''GNULIB_ROUNDL''@|$(GNULIB_ROUNDL)|g' \
+	      -e 's|@''GNULIB_SIGNBIT''@|$(GNULIB_SIGNBIT)|g' \
+	      -e 's|@''GNULIB_SINL''@|$(GNULIB_SINL)|g' \
+	      -e 's|@''GNULIB_SQRTL''@|$(GNULIB_SQRTL)|g' \
+	      -e 's|@''GNULIB_TANL''@|$(GNULIB_TANL)|g' \
+	      -e 's|@''GNULIB_TRUNC''@|$(GNULIB_TRUNC)|g' \
+	      -e 's|@''GNULIB_TRUNCF''@|$(GNULIB_TRUNCF)|g' \
+	      -e 's|@''GNULIB_TRUNCL''@|$(GNULIB_TRUNCL)|g' \
+	      -e 's|@''HAVE_ACOSL''@|$(HAVE_ACOSL)|g' \
+	      -e 's|@''HAVE_ASINL''@|$(HAVE_ASINL)|g' \
+	      -e 's|@''HAVE_ATANL''@|$(HAVE_ATANL)|g' \
+	      -e 's|@''HAVE_COSL''@|$(HAVE_COSL)|g' \
+	      -e 's|@''HAVE_EXPL''@|$(HAVE_EXPL)|g' \
+	      -e 's|@''HAVE_ISNANF''@|$(HAVE_ISNANF)|g' \
+	      -e 's|@''HAVE_ISNAND''@|$(HAVE_ISNAND)|g' \
+	      -e 's|@''HAVE_ISNANL''@|$(HAVE_ISNANL)|g' \
+	      -e 's|@''HAVE_LOGL''@|$(HAVE_LOGL)|g' \
+	      -e 's|@''HAVE_SINL''@|$(HAVE_SINL)|g' \
+	      -e 's|@''HAVE_SQRTL''@|$(HAVE_SQRTL)|g' \
+	      -e 's|@''HAVE_TANL''@|$(HAVE_TANL)|g' \
+	      -e 's|@''HAVE_DECL_ACOSL''@|$(HAVE_DECL_ACOSL)|g' \
+	      -e 's|@''HAVE_DECL_ASINL''@|$(HAVE_DECL_ASINL)|g' \
+	      -e 's|@''HAVE_DECL_ATANL''@|$(HAVE_DECL_ATANL)|g' \
+	      -e 's|@''HAVE_DECL_COSL''@|$(HAVE_DECL_COSL)|g' \
+	      -e 's|@''HAVE_DECL_EXPL''@|$(HAVE_DECL_EXPL)|g' \
+	      -e 's|@''HAVE_DECL_FREXPL''@|$(HAVE_DECL_FREXPL)|g' \
+	      -e 's|@''HAVE_DECL_LDEXPL''@|$(HAVE_DECL_LDEXPL)|g' \
+	      -e 's|@''HAVE_DECL_LOGL''@|$(HAVE_DECL_LOGL)|g' \
+	      -e 's|@''HAVE_DECL_SINL''@|$(HAVE_DECL_SINL)|g' \
+	      -e 's|@''HAVE_DECL_SQRTL''@|$(HAVE_DECL_SQRTL)|g' \
+	      -e 's|@''HAVE_DECL_TANL''@|$(HAVE_DECL_TANL)|g' \
+	      -e 's|@''HAVE_DECL_TRUNC''@|$(HAVE_DECL_TRUNC)|g' \
+	      -e 's|@''HAVE_DECL_TRUNCF''@|$(HAVE_DECL_TRUNCF)|g' \
+	      -e 's|@''REPLACE_CEILF''@|$(REPLACE_CEILF)|g' \
+	      -e 's|@''REPLACE_CEILL''@|$(REPLACE_CEILL)|g' \
+	      -e 's|@''REPLACE_FLOORF''@|$(REPLACE_FLOORF)|g' \
+	      -e 's|@''REPLACE_FLOORL''@|$(REPLACE_FLOORL)|g' \
+	      -e 's|@''REPLACE_FREXP''@|$(REPLACE_FREXP)|g' \
+	      -e 's|@''REPLACE_FREXPL''@|$(REPLACE_FREXPL)|g' \
+	      -e 's|@''REPLACE_HUGE_VAL''@|$(REPLACE_HUGE_VAL)|g' \
+	      -e 's|@''REPLACE_ISFINITE''@|$(REPLACE_ISFINITE)|g' \
+	      -e 's|@''REPLACE_ISINF''@|$(REPLACE_ISINF)|g' \
+	      -e 's|@''REPLACE_ISNAN''@|$(REPLACE_ISNAN)|g' \
+	      -e 's|@''REPLACE_LDEXPL''@|$(REPLACE_LDEXPL)|g' \
+	      -e 's|@''REPLACE_NAN''@|$(REPLACE_NAN)|g' \
+	      -e 's|@''REPLACE_ROUND''@|$(REPLACE_ROUND)|g' \
+	      -e 's|@''REPLACE_ROUNDF''@|$(REPLACE_ROUNDF)|g' \
+	      -e 's|@''REPLACE_ROUNDL''@|$(REPLACE_ROUNDL)|g' \
+	      -e 's|@''REPLACE_SIGNBIT''@|$(REPLACE_SIGNBIT)|g' \
+	      -e 's|@''REPLACE_SIGNBIT_USING_GCC''@|$(REPLACE_SIGNBIT_USING_GCC)|g' \
+	      -e 's|@''REPLACE_TRUNCL''@|$(REPLACE_TRUNCL)|g' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+	      < $(srcdir)/math.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += math.h math.h-t
+
+EXTRA_DIST += math.in.h
+
+## end   gnulib module math
+
 ## begin gnulib module mbrtowc
 
 
@@ -752,6 +899,24 @@ EXTRA_libmissing_la_SOURCES += poll.c
 
 ## end   gnulib module poll
 
+## begin gnulib module printf-frexp
+
+libmissing_la_SOURCES += printf-frexp.c
+
+EXTRA_DIST += printf-frexp.h
+
+## end   gnulib module printf-frexp
+
+## begin gnulib module printf-frexpl
+
+libmissing_la_SOURCES += printf-frexpl.c
+
+EXTRA_DIST += printf-frexp.c printf-frexpl.h
+
+EXTRA_libmissing_la_SOURCES += printf-frexp.c
+
+## end   gnulib module printf-frexpl
+
 ## begin gnulib module realloc-posix
 
 
@@ -830,6 +995,15 @@ EXTRA_DIST += signal.in.h
 
 ## end   gnulib module signal
 
+## begin gnulib module signbit
+
+
+EXTRA_DIST += float+.h signbitd.c signbitf.c signbitl.c
+
+EXTRA_libmissing_la_SOURCES += signbitd.c signbitf.c signbitl.c
+
+## end   gnulib module signbit
+
 ## begin gnulib module sigprocmask
 
 
@@ -1046,6 +1220,7 @@ stdio.h: stdio.in.h $(WARN_ON_USE_H) $(ARG_NONNULL_H)
 	      -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' \
@@ -1508,11 +1683,11 @@ EXTRA_DIST += sys_stat.in.h
 
 ## begin gnulib module sys_time
 
-BUILT_SOURCES += $(SYS_TIME_H)
+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 $(ARG_NONNULL_H)
+sys/time.h: sys_time.in.h $(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! */'; \
@@ -1520,9 +1695,11 @@ sys/time.h: sys_time.in.h $(ARG_NONNULL_H)
 	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
 	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
 	      -e 's|@''NEXT_SYS_TIME_H''@|$(NEXT_SYS_TIME_H)|g' \
-	      -e 's/@''REPLACE_GETTIMEOFDAY''@/$(REPLACE_GETTIMEOFDAY)/g' \
+	      -e 's/@''GNULIB_GETTIMEOFDAY''@/$(GNULIB_GETTIMEOFDAY)/g' \
 	      -e 's/@''HAVE_STRUCT_TIMEVAL''@/$(HAVE_STRUCT_TIMEVAL)/g' \
+	      -e 's/@''REPLACE_GETTIMEOFDAY''@/$(REPLACE_GETTIMEOFDAY)/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_time.in.h; \
 	} > $@-t && \
 	mv $@-t $@
diff --git a/libmissing/fpucw.h b/libmissing/fpucw.h
new file mode 100644
index 0000000..dbbe363
--- /dev/null
+++ b/libmissing/fpucw.h
@@ -0,0 +1,107 @@
+/* Manipulating the FPU control word.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+   Written by Bruno Haible <[email protected]>, 2007.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _FPUCW_H
+#define _FPUCW_H
+
+/* The i386 floating point hardware (the 387 compatible FPU, not the modern
+   SSE/SSE2 hardware) has a controllable rounding precision.  It is specified
+   through the 'PC' bits in the FPU control word ('fctrl' register).  (See
+   the GNU libc i386 <fpu_control.h> header for details.)
+
+   On some platforms, such as Linux or Solaris, the default precision setting
+   is set to "extended precision".  This means that 'long double' instructions
+   operate correctly, but 'double' computations often produce slightly
+   different results as on strictly IEEE 754 conforming systems.
+
+   On some platforms, such as NetBSD, the default precision is set to
+   "double precision".  This means that 'long double' instructions will operate
+   only as 'double', i.e. lead wrong results.
+
+   The FPU control word is under control of the application, i.e. it is
+   not required to be set either way by the ABI.  (In fact, the i386 ABI
+   http://refspecs.freestandards.org/elf/abi386-4.pdf page 3-12 = page 38
+   is not clear about it.  But in any case, gcc treats the control word
+   like a "preserved" register: it emits code that assumes that the control
+   word is preserved across calls, and it restores the control word at the
+   end of functions that modify it.)
+
+   See Vincent Lefèvre's page http://www.vinc17.org/research/extended.en.html
+   for a good explanation.
+   See http://www.uwsg.iu.edu/hypermail/linux/kernel/0103.0/0453.html for
+   some argumentation which setting should be the default.  */
+
+/* This header file provides the following facilities:
+     fpucw_t                        integral type holding the value of 'fctrl'
+     FPU_PC_MASK                    bit mask denoting the precision control
+     FPU_PC_DOUBLE                  precision control for 53 bits mantissa
+     FPU_PC_EXTENDED                precision control for 64 bits mantissa
+     GET_FPUCW ()                   yields the current FPU control word
+     SET_FPUCW (word)               sets the FPU control word
+     DECL_LONG_DOUBLE_ROUNDING      variable declaration for
+                                    BEGIN/END_LONG_DOUBLE_ROUNDING
+     BEGIN_LONG_DOUBLE_ROUNDING ()  starts a sequence of instructions with
+                                    'long double' safe operation precision
+     END_LONG_DOUBLE_ROUNDING ()    ends a sequence of instructions with
+                                    'long double' safe operation precision
+ */
+
+/* Inline assembler like this works only with GNU C.  */
+#if (defined __i386__ || defined __x86_64__) && defined __GNUC__
+
+typedef unsigned short fpucw_t; /* glibc calls this fpu_control_t */
+
+# define FPU_PC_MASK 0x0300
+# define FPU_PC_DOUBLE 0x200    /* glibc calls this _FPU_DOUBLE */
+# define FPU_PC_EXTENDED 0x300  /* glibc calls this _FPU_EXTENDED */
+
+# define GET_FPUCW() \
+  ({ fpucw_t _cw;                                               \
+     __asm__ __volatile__ ("fnstcw %0" : "=m" (*&_cw));         \
+     _cw;                                                       \
+   })
+# define SET_FPUCW(word) \
+  (void)({ fpucw_t _ncw = (word);                               \
+           __asm__ __volatile__ ("fldcw %0" : : "m" (*&_ncw));  \
+         })
+
+# define DECL_LONG_DOUBLE_ROUNDING \
+  fpucw_t oldcw;
+# define BEGIN_LONG_DOUBLE_ROUNDING() \
+  (void)(oldcw = GET_FPUCW (),                                  \
+         SET_FPUCW ((oldcw & ~FPU_PC_MASK) | FPU_PC_EXTENDED))
+# define END_LONG_DOUBLE_ROUNDING() \
+  SET_FPUCW (oldcw)
+
+#else
+
+typedef unsigned int fpucw_t;
+
+# define FPU_PC_MASK 0
+# define FPU_PC_DOUBLE 0
+# define FPU_PC_EXTENDED 0
+
+# define GET_FPUCW() 0
+# define SET_FPUCW(word) (void)(word)
+
+# define DECL_LONG_DOUBLE_ROUNDING
+# define BEGIN_LONG_DOUBLE_ROUNDING()
+# define END_LONG_DOUBLE_ROUNDING()
+
+#endif
+
+#endif /* _FPUCW_H */
diff --git a/libmissing/frexp.c b/libmissing/frexp.c
new file mode 100644
index 0000000..5828d62
--- /dev/null
+++ b/libmissing/frexp.c
@@ -0,0 +1,166 @@
+/* Split a double into fraction and mantissa.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Paolo Bonzini <[email protected]>, 2003, and
+   Bruno Haible <[email protected]>, 2007.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <math.h>
+
+#include <float.h>
+#ifdef USE_LONG_DOUBLE
+# include "isnanl-nolibm.h"
+# include "fpucw.h"
+#else
+# include "isnand-nolibm.h"
+#endif
+
+/* This file assumes FLT_RADIX = 2.  If FLT_RADIX is a power of 2 greater
+   than 2, or not even a power of 2, some rounding errors can occur, so that
+   then the returned mantissa is only guaranteed to be <= 1.0, not < 1.0.  */
+
+#ifdef USE_LONG_DOUBLE
+# define FUNC frexpl
+# define DOUBLE long double
+# define ISNAN isnanl
+# define DECL_ROUNDING DECL_LONG_DOUBLE_ROUNDING
+# define BEGIN_ROUNDING() BEGIN_LONG_DOUBLE_ROUNDING ()
+# define END_ROUNDING() END_LONG_DOUBLE_ROUNDING ()
+# define L_(literal) literal##L
+#else
+# define FUNC frexp
+# define DOUBLE double
+# define ISNAN isnand
+# define DECL_ROUNDING
+# define BEGIN_ROUNDING()
+# define END_ROUNDING()
+# define L_(literal) literal
+#endif
+
+DOUBLE
+FUNC (DOUBLE x, int *expptr)
+{
+  int sign;
+  int exponent;
+  DECL_ROUNDING
+
+  /* Test for NaN, infinity, and zero.  */
+  if (ISNAN (x) || x + x == x)
+    {
+      *expptr = 0;
+      return x;
+    }
+
+  sign = 0;
+  if (x < 0)
+    {
+      x = - x;
+      sign = -1;
+    }
+
+  BEGIN_ROUNDING ();
+
+  {
+    /* Since the exponent is an 'int', it fits in 64 bits.  Therefore the
+       loops are executed no more than 64 times.  */
+    DOUBLE pow2[64]; /* pow2[i] = 2^2^i */
+    DOUBLE powh[64]; /* powh[i] = 2^-2^i */
+    int i;
+
+    exponent = 0;
+    if (x >= L_(1.0))
+      {
+        /* A positive exponent.  */
+        DOUBLE pow2_i; /* = pow2[i] */
+        DOUBLE powh_i; /* = powh[i] */
+
+        /* Invariants: pow2_i = 2^2^i, powh_i = 2^-2^i,
+           x * 2^exponent = argument, x >= 1.0.  */
+        for (i = 0, pow2_i = L_(2.0), powh_i = L_(0.5);
+             ;
+             i++, pow2_i = pow2_i * pow2_i, powh_i = powh_i * powh_i)
+          {
+            if (x >= pow2_i)
+              {
+                exponent += (1 << i);
+                x *= powh_i;
+              }
+            else
+              break;
+
+            pow2[i] = pow2_i;
+            powh[i] = powh_i;
+          }
+        /* Avoid making x too small, as it could become a denormalized
+           number and thus lose precision.  */
+        while (i > 0 && x < pow2[i - 1])
+          {
+            i--;
+            powh_i = powh[i];
+          }
+        exponent += (1 << i);
+        x *= powh_i;
+        /* Here 2^-2^i <= x < 1.0.  */
+      }
+    else
+      {
+        /* A negative or zero exponent.  */
+        DOUBLE pow2_i; /* = pow2[i] */
+        DOUBLE powh_i; /* = powh[i] */
+
+        /* Invariants: pow2_i = 2^2^i, powh_i = 2^-2^i,
+           x * 2^exponent = argument, x < 1.0.  */
+        for (i = 0, pow2_i = L_(2.0), powh_i = L_(0.5);
+             ;
+             i++, pow2_i = pow2_i * pow2_i, powh_i = powh_i * powh_i)
+          {
+            if (x < powh_i)
+              {
+                exponent -= (1 << i);
+                x *= pow2_i;
+              }
+            else
+              break;
+
+            pow2[i] = pow2_i;
+            powh[i] = powh_i;
+          }
+        /* Here 2^-2^i <= x < 1.0.  */
+      }
+
+    /* Invariants: x * 2^exponent = argument, and 2^-2^i <= x < 1.0.  */
+    while (i > 0)
+      {
+        i--;
+        if (x < powh[i])
+          {
+            exponent -= (1 << i);
+            x *= pow2[i];
+          }
+      }
+    /* Here 0.5 <= x < 1.0.  */
+  }
+
+  if (sign < 0)
+    x = - x;
+
+  END_ROUNDING ();
+
+  *expptr = exponent;
+  return x;
+}
diff --git a/libmissing/frexpl.c b/libmissing/frexpl.c
new file mode 100644
index 0000000..9cf9bf6
--- /dev/null
+++ b/libmissing/frexpl.c
@@ -0,0 +1,18 @@
+/* Split a 'long double' into fraction and mantissa.
+   Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#define USE_LONG_DOUBLE
+#include "frexp.c"
diff --git a/libmissing/isnan.c b/libmissing/isnan.c
new file mode 100644
index 0000000..a59dea7
--- /dev/null
+++ b/libmissing/isnan.c
@@ -0,0 +1,173 @@
+/* Test for NaN that does not need libm.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2007.  */
+
+#include <config.h>
+
+/* Specification.  */
+#ifdef USE_LONG_DOUBLE
+/* Specification found in math.h or isnanl-nolibm.h.  */
+extern int rpl_isnanl (long double x);
+#elif ! defined USE_FLOAT
+/* Specification found in math.h or isnand-nolibm.h.  */
+extern int rpl_isnand (double x);
+#else /* defined USE_FLOAT */
+/* Specification found in math.h or isnanf-nolibm.h.  */
+extern int rpl_isnanf (float x);
+#endif
+
+#include <float.h>
+#include <string.h>
+
+#include "float+.h"
+
+#ifdef USE_LONG_DOUBLE
+# define FUNC rpl_isnanl
+# define DOUBLE long double
+# define MAX_EXP LDBL_MAX_EXP
+# define MIN_EXP LDBL_MIN_EXP
+# if defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT
+#  define KNOWN_EXPBIT0_LOCATION
+#  define EXPBIT0_WORD LDBL_EXPBIT0_WORD
+#  define EXPBIT0_BIT LDBL_EXPBIT0_BIT
+# endif
+# define SIZE SIZEOF_LDBL
+# define L_(literal) literal##L
+#elif ! defined USE_FLOAT
+# define FUNC rpl_isnand
+# define DOUBLE double
+# define MAX_EXP DBL_MAX_EXP
+# define MIN_EXP DBL_MIN_EXP
+# if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT
+#  define KNOWN_EXPBIT0_LOCATION
+#  define EXPBIT0_WORD DBL_EXPBIT0_WORD
+#  define EXPBIT0_BIT DBL_EXPBIT0_BIT
+# endif
+# define SIZE SIZEOF_DBL
+# define L_(literal) literal
+#else /* defined USE_FLOAT */
+# define FUNC rpl_isnanf
+# define DOUBLE float
+# define MAX_EXP FLT_MAX_EXP
+# define MIN_EXP FLT_MIN_EXP
+# if defined FLT_EXPBIT0_WORD && defined FLT_EXPBIT0_BIT
+#  define KNOWN_EXPBIT0_LOCATION
+#  define EXPBIT0_WORD FLT_EXPBIT0_WORD
+#  define EXPBIT0_BIT FLT_EXPBIT0_BIT
+# endif
+# define SIZE SIZEOF_FLT
+# define L_(literal) literal##f
+#endif
+
+#define EXP_MASK ((MAX_EXP - MIN_EXP) | 7)
+
+#define NWORDS \
+  ((sizeof (DOUBLE) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+typedef union { DOUBLE value; unsigned int word[NWORDS]; } memory_double;
+
+int
+FUNC (DOUBLE x)
+{
+#ifdef KNOWN_EXPBIT0_LOCATION
+# if defined USE_LONG_DOUBLE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_))
+  /* Special CPU dependent code is needed to treat bit patterns outside the
+     IEEE 754 specification (such as Pseudo-NaNs, Pseudo-Infinities,
+     Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals) as NaNs.
+     These bit patterns are:
+       - exponent = 0x0001..0x7FFF, mantissa bit 63 = 0,
+       - exponent = 0x0000, mantissa bit 63 = 1.
+     The NaN bit pattern is:
+       - exponent = 0x7FFF, mantissa >= 0x8000000000000001.  */
+  memory_double m;
+  unsigned int exponent;
+
+  m.value = x;
+  exponent = (m.word[EXPBIT0_WORD] >> EXPBIT0_BIT) & EXP_MASK;
+#  ifdef WORDS_BIGENDIAN
+  /* Big endian: EXPBIT0_WORD = 0, EXPBIT0_BIT = 16.  */
+  if (exponent == 0)
+    return 1 & (m.word[0] >> 15);
+  else if (exponent == EXP_MASK)
+    return (((m.word[0] ^ 0x8000U) << 16) | m.word[1] | (m.word[2] >> 16)) != 0;
+  else
+    return 1 & ~(m.word[0] >> 15);
+#  else
+  /* Little endian: EXPBIT0_WORD = 2, EXPBIT0_BIT = 0.  */
+  if (exponent == 0)
+    return (m.word[1] >> 31);
+  else if (exponent == EXP_MASK)
+    return ((m.word[1] ^ 0x80000000U) | m.word[0]) != 0;
+  else
+    return (m.word[1] >> 31) ^ 1;
+#  endif
+# else
+  /* Be careful to not do any floating-point operation on x, such as x == x,
+     because x may be a signaling NaN.  */
+#  if defined __SUNPRO_C || defined __DECC || (defined __sgi && !defined __GNUC__)
+  /* The Sun C 5.0 compilers and the Compaq (ex-DEC) 6.4 compilers don't
+     recognize the initializers as constant expressions.  The latter compiler
+     also fails when constant-folding 0.0 / 0.0 even when constant-folding is
+     not required.  The SGI MIPSpro C compiler complains about "floating-point
+     operation result is out of range".  */
+  static DOUBLE zero = L_(0.0);
+  memory_double nan;
+  DOUBLE plus_inf = L_(1.0) / L_(0.0);
+  DOUBLE minus_inf = -L_(1.0) / L_(0.0);
+  nan.value = zero / zero;
+#  else
+  static memory_double nan = { L_(0.0) / L_(0.0) };
+  static DOUBLE plus_inf = L_(1.0) / L_(0.0);
+  static DOUBLE minus_inf = -L_(1.0) / L_(0.0);
+#  endif
+  {
+    memory_double m;
+
+    /* A NaN can be recognized through its exponent.  But exclude +Infinity and
+       -Infinity, which have the same exponent.  */
+    m.value = x;
+    if (((m.word[EXPBIT0_WORD] ^ nan.word[EXPBIT0_WORD])
+         & (EXP_MASK << EXPBIT0_BIT))
+        == 0)
+      return (memcmp (&m.value, &plus_inf, SIZE) != 0
+              && memcmp (&m.value, &minus_inf, SIZE) != 0);
+    else
+      return 0;
+  }
+# endif
+#else
+  /* The configuration did not find sufficient information.  Give up about
+     the signaling NaNs, handle only the quiet NaNs.  */
+  if (x == x)
+    {
+# if defined USE_LONG_DOUBLE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_))
+      /* Detect any special bit patterns that pass ==; see comment above.  */
+      memory_double m1;
+      memory_double m2;
+
+      memset (&m1.value, 0, SIZE);
+      memset (&m2.value, 0, SIZE);
+      m1.value = x;
+      m2.value = x + (x ? 0.0L : -0.0L);
+      if (memcmp (&m1.value, &m2.value, SIZE) != 0)
+        return 1;
+# endif
+      return 0;
+    }
+  else
+    return 1;
+#endif
+}
diff --git a/libmissing/isnand-nolibm.h b/libmissing/isnand-nolibm.h
new file mode 100644
index 0000000..cc1d476
--- /dev/null
+++ b/libmissing/isnand-nolibm.h
@@ -0,0 +1,33 @@
+/* Test for NaN that does not need libm.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#if HAVE_ISNAND_IN_LIBC
+/* Get declaration of isnan macro.  */
+# include <math.h>
+# if __GNUC__ >= 4
+   /* GCC 4.0 and newer provides three built-ins for isnan.  */
+#  undef isnand
+#  define isnand(x) __builtin_isnan ((double)(x))
+# else
+#  undef isnand
+#  define isnand(x) isnan ((double)(x))
+# endif
+#else
+/* Test whether X is a NaN.  */
+# undef isnand
+# define isnand rpl_isnand
+extern int isnand (double x);
+#endif
diff --git a/libmissing/isnand.c b/libmissing/isnand.c
new file mode 100644
index 0000000..f7a1565
--- /dev/null
+++ b/libmissing/isnand.c
@@ -0,0 +1,19 @@
+/* Test for NaN that does not need libm.
+   Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2008.  */
+
+#include "isnan.c"
diff --git a/libmissing/isnanf-nolibm.h b/libmissing/isnanf-nolibm.h
new file mode 100644
index 0000000..5e29207
--- /dev/null
+++ b/libmissing/isnanf-nolibm.h
@@ -0,0 +1,33 @@
+/* Test for NaN that does not need libm.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#if HAVE_ISNANF_IN_LIBC
+/* Get declaration of isnan macro or (older) isnanf function.  */
+# include <math.h>
+# if __GNUC__ >= 4
+   /* GCC 4.0 and newer provides three built-ins for isnan.  */
+#  undef isnanf
+#  define isnanf(x) __builtin_isnanf ((float)(x))
+# elif defined isnan
+#  undef isnanf
+#  define isnanf(x) isnan ((float)(x))
+# endif
+#else
+/* Test whether X is a NaN.  */
+# undef isnanf
+# define isnanf rpl_isnanf
+extern int isnanf (float x);
+#endif
diff --git a/libmissing/isnanf.c b/libmissing/isnanf.c
new file mode 100644
index 0000000..a352fdb
--- /dev/null
+++ b/libmissing/isnanf.c
@@ -0,0 +1,20 @@
+/* Test for NaN that does not need libm.
+   Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2007.  */
+
+#define USE_FLOAT
+#include "isnan.c"
diff --git a/libmissing/isnanl-nolibm.h b/libmissing/isnanl-nolibm.h
new file mode 100644
index 0000000..e89a7fe
--- /dev/null
+++ b/libmissing/isnanl-nolibm.h
@@ -0,0 +1,33 @@
+/* Test for NaN that does not need libm.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#if HAVE_ISNANL_IN_LIBC
+/* Get declaration of isnan macro or (older) isnanl function.  */
+# include <math.h>
+# if __GNUC__ >= 4
+   /* GCC 4.0 and newer provides three built-ins for isnan.  */
+#  undef isnanl
+#  define isnanl(x) __builtin_isnanl ((long double)(x))
+# elif defined isnan
+#  undef isnanl
+#  define isnanl(x) isnan ((long double)(x))
+# endif
+#else
+/* Test whether X is a NaN.  */
+# undef isnanl
+# define isnanl rpl_isnanl
+extern int isnanl (long double x);
+#endif
diff --git a/libmissing/isnanl.c b/libmissing/isnanl.c
new file mode 100644
index 0000000..b45fef0
--- /dev/null
+++ b/libmissing/isnanl.c
@@ -0,0 +1,20 @@
+/* Test for NaN that does not need libm.
+   Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2007.  */
+
+#define USE_LONG_DOUBLE
+#include "isnan.c"
diff --git a/libmissing/m4/exponentd.m4 b/libmissing/m4/exponentd.m4
new file mode 100644
index 0000000..5d44d0e
--- /dev/null
+++ b/libmissing/m4/exponentd.m4
@@ -0,0 +1,114 @@
+# exponentd.m4 serial 1
+dnl Copyright (C) 2007-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+AC_DEFUN([gl_DOUBLE_EXPONENT_LOCATION],
+[
+  AC_CACHE_CHECK([where to find the exponent in a 'double'],
+    [gl_cv_cc_double_expbit0],
+    [
+      AC_TRY_RUN([
+#include <float.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#define NWORDS \
+  ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+typedef union { double value; unsigned int word[NWORDS]; } memory_double;
+static unsigned int ored_words[NWORDS];
+static unsigned int anded_words[NWORDS];
+static void add_to_ored_words (double x)
+{
+  memory_double m;
+  size_t i;
+  /* Clear it first, in case sizeof (double) < sizeof (memory_double).  */
+  memset (&m, 0, sizeof (memory_double));
+  m.value = x;
+  for (i = 0; i < NWORDS; i++)
+    {
+      ored_words[i] |= m.word[i];
+      anded_words[i] &= m.word[i];
+    }
+}
+int main ()
+{
+  size_t j;
+  FILE *fp = fopen ("conftest.out", "w");
+  if (fp == NULL)
+    return 1;
+  for (j = 0; j < NWORDS; j++)
+    anded_words[j] = ~ (unsigned int) 0;
+  add_to_ored_words (0.25);
+  add_to_ored_words (0.5);
+  add_to_ored_words (1.0);
+  add_to_ored_words (2.0);
+  add_to_ored_words (4.0);
+  /* Remove bits that are common (e.g. if representation of the first mantissa
+     bit is explicit).  */
+  for (j = 0; j < NWORDS; j++)
+    ored_words[j] &= ~anded_words[j];
+  /* Now find the nonzero word.  */
+  for (j = 0; j < NWORDS; j++)
+    if (ored_words[j] != 0)
+      break;
+  if (j < NWORDS)
+    {
+      size_t i;
+      for (i = j + 1; i < NWORDS; i++)
+        if (ored_words[i] != 0)
+          {
+            fprintf (fp, "unknown");
+            return (fclose (fp) != 0);
+          }
+      for (i = 0; ; i++)
+        if ((ored_words[j] >> i) & 1)
+          {
+            fprintf (fp, "word %d bit %d", (int) j, (int) i);
+            return (fclose (fp) != 0);
+          }
+    }
+  fprintf (fp, "unknown");
+  return (fclose (fp) != 0);
+}
+        ],
+        [gl_cv_cc_double_expbit0=`cat conftest.out`],
+        [gl_cv_cc_double_expbit0="unknown"],
+        [
+          dnl On ARM, there are two 'double' floating-point formats, used by
+          dnl different sets of instructions: The older FPA instructions assume
+          dnl that they are stored in big-endian word order, while the words
+          dnl (like integer types) are stored in little-endian byte order.
+          dnl The newer VFP instructions assume little-endian order consistenly.
+          AC_EGREP_CPP([mixed_endianness], [
+#if defined arm || defined __arm || defined __arm__
+  mixed_endianness
+#endif
+            ],
+            [gl_cv_cc_double_expbit0="unknown"],
+            [
+              pushdef([AC_MSG_CHECKING],[:])dnl
+              pushdef([AC_MSG_RESULT],[:])dnl
+              pushdef([AC_MSG_RESULT_UNQUOTED],[:])dnl
+              AC_C_BIGENDIAN(
+                [gl_cv_cc_double_expbit0="word 0 bit 20"],
+                [gl_cv_cc_double_expbit0="word 1 bit 20"],
+                [gl_cv_cc_double_expbit0="unknown"])
+              popdef([AC_MSG_RESULT_UNQUOTED])dnl
+              popdef([AC_MSG_RESULT])dnl
+              popdef([AC_MSG_CHECKING])dnl
+            ])
+        ])
+      rm -f conftest.out
+    ])
+  case "$gl_cv_cc_double_expbit0" in
+    word*bit*)
+      word=`echo "$gl_cv_cc_double_expbit0" | sed -e 's/word //' -e 's/ bit.*//'`
+      bit=`echo "$gl_cv_cc_double_expbit0" | sed -e 's/word.*bit //'`
+      AC_DEFINE_UNQUOTED([DBL_EXPBIT0_WORD], [$word],
+        [Define as the word index where to find the exponent of 'double'.])
+      AC_DEFINE_UNQUOTED([DBL_EXPBIT0_BIT], [$bit],
+        [Define as the bit index in the word where to find bit 0 of the exponent of 'double'.])
+      ;;
+  esac
+])
diff --git a/libmissing/m4/exponentf.m4 b/libmissing/m4/exponentf.m4
new file mode 100644
index 0000000..4d8063f
--- /dev/null
+++ b/libmissing/m4/exponentf.m4
@@ -0,0 +1,91 @@
+# exponentf.m4 serial 1
+dnl Copyright (C) 2007-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+AC_DEFUN([gl_FLOAT_EXPONENT_LOCATION],
+[
+  AC_CACHE_CHECK([where to find the exponent in a 'float'],
+    [gl_cv_cc_float_expbit0],
+    [
+      AC_TRY_RUN([
+#include <float.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#define NWORDS \
+  ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+typedef union { float value; unsigned int word[NWORDS]; } memory_float;
+static unsigned int ored_words[NWORDS];
+static unsigned int anded_words[NWORDS];
+static void add_to_ored_words (float x)
+{
+  memory_float m;
+  size_t i;
+  /* Clear it first, in case
+     sizeof (float) < sizeof (memory_float).  */
+  memset (&m, 0, sizeof (memory_float));
+  m.value = x;
+  for (i = 0; i < NWORDS; i++)
+    {
+      ored_words[i] |= m.word[i];
+      anded_words[i] &= m.word[i];
+    }
+}
+int main ()
+{
+  size_t j;
+  FILE *fp = fopen ("conftest.out", "w");
+  if (fp == NULL)
+    return 1;
+  for (j = 0; j < NWORDS; j++)
+    anded_words[j] = ~ (unsigned int) 0;
+  add_to_ored_words (0.25f);
+  add_to_ored_words (0.5f);
+  add_to_ored_words (1.0f);
+  add_to_ored_words (2.0f);
+  add_to_ored_words (4.0f);
+  /* Remove bits that are common (e.g. if representation of the first mantissa
+     bit is explicit).  */
+  for (j = 0; j < NWORDS; j++)
+    ored_words[j] &= ~anded_words[j];
+  /* Now find the nonzero word.  */
+  for (j = 0; j < NWORDS; j++)
+    if (ored_words[j] != 0)
+      break;
+  if (j < NWORDS)
+    {
+      size_t i;
+      for (i = j + 1; i < NWORDS; i++)
+        if (ored_words[i] != 0)
+          {
+            fprintf (fp, "unknown");
+            return (fclose (fp) != 0);
+          }
+      for (i = 0; ; i++)
+        if ((ored_words[j] >> i) & 1)
+          {
+            fprintf (fp, "word %d bit %d", (int) j, (int) i);
+            return (fclose (fp) != 0);
+          }
+    }
+  fprintf (fp, "unknown");
+  return (fclose (fp) != 0);
+}
+        ],
+        [gl_cv_cc_float_expbit0=`cat conftest.out`],
+        [gl_cv_cc_float_expbit0="unknown"],
+        [gl_cv_cc_float_expbit0="word 0 bit 23"])
+      rm -f conftest.out
+    ])
+  case "$gl_cv_cc_float_expbit0" in
+    word*bit*)
+      word=`echo "$gl_cv_cc_float_expbit0" | sed -e 's/word //' -e 's/ bit.*//'`
+      bit=`echo "$gl_cv_cc_float_expbit0" | sed -e 's/word.*bit //'`
+      AC_DEFINE_UNQUOTED([FLT_EXPBIT0_WORD], [$word],
+        [Define as the word index where to find the exponent of 'float'.])
+      AC_DEFINE_UNQUOTED([FLT_EXPBIT0_BIT], [$bit],
+        [Define as the bit index in the word where to find bit 0 of the exponent of 'float'.])
+      ;;
+  esac
+])
diff --git a/libmissing/m4/exponentl.m4 b/libmissing/m4/exponentl.m4
new file mode 100644
index 0000000..a700d3b
--- /dev/null
+++ b/libmissing/m4/exponentl.m4
@@ -0,0 +1,97 @@
+# exponentl.m4 serial 2
+dnl Copyright (C) 2007-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+AC_DEFUN([gl_LONG_DOUBLE_EXPONENT_LOCATION],
+[
+  AC_REQUIRE([gl_BIGENDIAN])
+  AC_CACHE_CHECK([where to find the exponent in a 'long double'],
+    [gl_cv_cc_long_double_expbit0],
+    [
+      AC_TRY_RUN([
+#include <float.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#define NWORDS \
+  ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+typedef union { long double value; unsigned int word[NWORDS]; }
+        memory_long_double;
+static unsigned int ored_words[NWORDS];
+static unsigned int anded_words[NWORDS];
+static void add_to_ored_words (long double x)
+{
+  memory_long_double m;
+  size_t i;
+  /* Clear it first, in case
+     sizeof (long double) < sizeof (memory_long_double).  */
+  memset (&m, 0, sizeof (memory_long_double));
+  m.value = x;
+  for (i = 0; i < NWORDS; i++)
+    {
+      ored_words[i] |= m.word[i];
+      anded_words[i] &= m.word[i];
+    }
+}
+int main ()
+{
+  size_t j;
+  FILE *fp = fopen ("conftest.out", "w");
+  if (fp == NULL)
+    return 1;
+  for (j = 0; j < NWORDS; j++)
+    anded_words[j] = ~ (unsigned int) 0;
+  add_to_ored_words (0.25L);
+  add_to_ored_words (0.5L);
+  add_to_ored_words (1.0L);
+  add_to_ored_words (2.0L);
+  add_to_ored_words (4.0L);
+  /* Remove bits that are common (e.g. if representation of the first mantissa
+     bit is explicit).  */
+  for (j = 0; j < NWORDS; j++)
+    ored_words[j] &= ~anded_words[j];
+  /* Now find the nonzero word.  */
+  for (j = 0; j < NWORDS; j++)
+    if (ored_words[j] != 0)
+      break;
+  if (j < NWORDS)
+    {
+      size_t i;
+      for (i = j + 1; i < NWORDS; i++)
+        if (ored_words[i] != 0)
+          {
+            fprintf (fp, "unknown");
+            return (fclose (fp) != 0);
+          }
+      for (i = 0; ; i++)
+        if ((ored_words[j] >> i) & 1)
+          {
+            fprintf (fp, "word %d bit %d", (int) j, (int) i);
+            return (fclose (fp) != 0);
+          }
+    }
+  fprintf (fp, "unknown");
+  return (fclose (fp) != 0);
+}
+        ],
+        [gl_cv_cc_long_double_expbit0=`cat conftest.out`],
+        [gl_cv_cc_long_double_expbit0="unknown"],
+        [
+          dnl When cross-compiling, we don't know. It depends on the
+          dnl ABI and compiler version. There are too many cases.
+          gl_cv_cc_long_double_expbit0="unknown"
+        ])
+      rm -f conftest.out
+    ])
+  case "$gl_cv_cc_long_double_expbit0" in
+    word*bit*)
+      word=`echo "$gl_cv_cc_long_double_expbit0" | sed -e 's/word //' -e 's/ bit.*//'`
+      bit=`echo "$gl_cv_cc_long_double_expbit0" | sed -e 's/word.*bit //'`
+      AC_DEFINE_UNQUOTED([LDBL_EXPBIT0_WORD], [$word],
+        [Define as the word index where to find the exponent of 'long double'.])
+      AC_DEFINE_UNQUOTED([LDBL_EXPBIT0_BIT], [$bit],
+        [Define as the bit index in the word where to find bit 0 of the exponent of 'long double'.])
+      ;;
+  esac
+])
diff --git a/libmissing/m4/fpieee.m4 b/libmissing/m4/fpieee.m4
new file mode 100644
index 0000000..532802d
--- /dev/null
+++ b/libmissing/m4/fpieee.m4
@@ -0,0 +1,52 @@
+# fpieee.m4 serial 1
+dnl Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl IEEE 754 standardized three items:
+dnl - The formats of single-float and double-float - nowadays commonly
+dnl   available as 'float' and 'double' in C and C++.
+dnl   No autoconf test needed.
+dnl - The overflow and division by zero behaviour: The result are values
+dnl   '±Inf' and 'NaN', rather than exceptions as it was before.
+dnl   This file provides an autoconf macro for ensuring this behaviour of
+dnl   floating-point operations.
+dnl - A set of conditions (overflow, underflow, inexact, etc.) which can
+dnl   be configured to trigger an exception.
+dnl   This cannot be done in a portable way: it depends on the compiler,
+dnl   libc, kernel, and CPU.  No autoconf macro is provided for this.
+
+dnl Ensure non-trapping behaviour of floating-point overflow and
+dnl floating-point division by zero.
+dnl (For integer overflow, see gcc's -ftrapv option; for integer division by
+dnl zero, see the autoconf macro in intdiv0.m4.)
+
+AC_DEFUN([gl_FP_IEEE],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  # IEEE behaviour is the default on all CPUs except Alpha and SH
+  # (according to the test results of Bruno Haible's ieeefp/fenv_default.m4
+  # and the GCC 4.1.2 manual).
+  case "$host_cpu" in
+    alpha*)
+      # On Alpha systems, a compiler option provides the behaviour.
+      # See the ieee(3) manual page, also available at
+      # <http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/V51B_HTML/MAN/MAN3/0600____.HTM>
+      if test -n "$GCC"; then
+        # GCC has the option -mieee.
+        CPPFLAGS="$CPPFLAGS -mieee"
+      else
+        # Compaq (ex-DEC) C has the option -ieee.
+        CPPFLAGS="$CPPFLAGS -ieee"
+      fi
+      ;;
+    sh*)
+      if test -n "$GCC"; then
+        # GCC has the option -mieee.
+        CPPFLAGS="$CPPFLAGS -mieee"
+      fi
+      ;;
+  esac
+])
diff --git a/libmissing/m4/frexp.m4 b/libmissing/m4/frexp.m4
new file mode 100644
index 0000000..3a450f6
--- /dev/null
+++ b/libmissing/m4/frexp.m4
@@ -0,0 +1,146 @@
+# frexp.m4 serial 7
+dnl Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_FREXP],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  FREXP_LIBM=
+  AC_CACHE_CHECK([whether frexp() can be used without linking with libm],
+    [gl_cv_func_frexp_no_libm],
+    [
+      AC_TRY_LINK([#include <math.h>
+                   double x;],
+                  [int e; return frexp (x, &e) > 0;],
+        [gl_cv_func_frexp_no_libm=yes],
+        [gl_cv_func_frexp_no_libm=no])
+    ])
+  if test $gl_cv_func_frexp_no_libm = no; then
+    AC_CACHE_CHECK([whether frexp() can be used with libm],
+      [gl_cv_func_frexp_in_libm],
+      [
+        save_LIBS="$LIBS"
+        LIBS="$LIBS -lm"
+        AC_TRY_LINK([#include <math.h>
+                     double x;],
+                    [int e; return frexp (x, &e) > 0;],
+          [gl_cv_func_frexp_in_libm=yes],
+          [gl_cv_func_frexp_in_libm=no])
+        LIBS="$save_LIBS"
+      ])
+    if test $gl_cv_func_frexp_in_libm = yes; then
+      FREXP_LIBM=-lm
+    fi
+  fi
+  if test $gl_cv_func_frexp_no_libm = yes \
+     || test $gl_cv_func_frexp_in_libm = yes; then
+    save_LIBS="$LIBS"
+    LIBS="$LIBS $FREXP_LIBM"
+    gl_FUNC_FREXP_WORKS
+    LIBS="$save_LIBS"
+    case "$gl_cv_func_frexp_works" in
+      *yes) gl_func_frexp=yes ;;
+      *)    gl_func_frexp=no; REPLACE_FREXP=1; FREXP_LIBM= ;;
+    esac
+  else
+    gl_func_frexp=no
+  fi
+  if test $gl_func_frexp = yes; then
+    AC_DEFINE([HAVE_FREXP], [1],
+      [Define if the frexp() function is available and works.])
+  else
+    AC_LIBOBJ([frexp])
+  fi
+  AC_SUBST([FREXP_LIBM])
+])
+
+AC_DEFUN([gl_FUNC_FREXP_NO_LIBM],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  AC_CACHE_CHECK([whether frexp() can be used without linking with libm],
+    [gl_cv_func_frexp_no_libm],
+    [
+      AC_TRY_LINK([#include <math.h>
+                   double x;],
+                  [int e; return frexp (x, &e) > 0;],
+        [gl_cv_func_frexp_no_libm=yes],
+        [gl_cv_func_frexp_no_libm=no])
+    ])
+  if test $gl_cv_func_frexp_no_libm = yes; then
+    gl_FUNC_FREXP_WORKS
+    case "$gl_cv_func_frexp_works" in
+      *yes) gl_func_frexp_no_libm=yes ;;
+      *)    gl_func_frexp_no_libm=no; REPLACE_FREXP=1 ;;
+    esac
+  else
+    gl_func_frexp_no_libm=no
+    dnl Set REPLACE_FREXP here because the system may have frexp in libm.
+    REPLACE_FREXP=1
+  fi
+  if test $gl_func_frexp_no_libm = yes; then
+    AC_DEFINE([HAVE_FREXP_IN_LIBC], [1],
+      [Define if the frexp() function is available in libc.])
+  else
+    AC_LIBOBJ([frexp])
+  fi
+])
+
+dnl Test whether frexp() works also on denormalized numbers (this fails e.g. on
+dnl NetBSD 3.0), on infinite numbers (this fails e.g. on IRIX 6.5 and mingw),
+dnl and on negative zero (this fails e.g. on NetBSD 4.99).
+AC_DEFUN([gl_FUNC_FREXP_WORKS],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether frexp works], [gl_cv_func_frexp_works],
+    [
+      AC_TRY_RUN([
+#include <float.h>
+#include <math.h>
+#include <string.h>
+int main()
+{
+  int i;
+  volatile double x;
+/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0.
+   So we use -zero instead.  */
+  double zero = 0.0;
+  /* Test on denormalized numbers.  */
+  for (i = 1, x = 1.0; i >= DBL_MIN_EXP; i--, x *= 0.5)
+    ;
+  if (x > 0.0)
+    {
+      int exp;
+      double y = frexp (x, &exp);
+      /* On machines with IEEE754 arithmetic: x = 1.11254e-308, exp = -1022.
+         On NetBSD: y = 0.75. Correct: y = 0.5.  */
+      if (y != 0.5)
+        return 1;
+    }
+  /* Test on infinite numbers.  */
+  x = 1.0 / 0.0;
+  {
+    int exp;
+    double y = frexp (x, &exp);
+    if (y != x)
+      return 1;
+  }
+  /* Test on negative zero.  */
+  x = -zero;
+  {
+    int exp;
+    double y = frexp (x, &exp);
+    if (memcmp (&y, &x, sizeof x))
+      return 1;
+  }
+  return 0;
+}], [gl_cv_func_frexp_works=yes], [gl_cv_func_frexp_works=no],
+      [case "$host_os" in
+         netbsd* | irix* | mingw*) gl_cv_func_frexp_works="guessing no";;
+         *)                        gl_cv_func_frexp_works="guessing yes";;
+       esac
+      ])
+    ])
+])
diff --git a/libmissing/m4/frexpl.m4 b/libmissing/m4/frexpl.m4
new file mode 100644
index 0000000..0fbc893
--- /dev/null
+++ b/libmissing/m4/frexpl.m4
@@ -0,0 +1,186 @@
+# frexpl.m4 serial 9
+dnl Copyright (C) 2007-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_FREXPL],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  FREXPL_LIBM=
+  AC_CACHE_CHECK([whether frexpl() can be used without linking with libm],
+    [gl_cv_func_frexpl_no_libm],
+    [
+      AC_TRY_LINK([#include <math.h>
+                   long double x;],
+                  [int e; return frexpl (x, &e) > 0;],
+        [gl_cv_func_frexpl_no_libm=yes],
+        [gl_cv_func_frexpl_no_libm=no])
+    ])
+  if test $gl_cv_func_frexpl_no_libm = no; then
+    AC_CACHE_CHECK([whether frexpl() can be used with libm],
+      [gl_cv_func_frexpl_in_libm],
+      [
+        save_LIBS="$LIBS"
+        LIBS="$LIBS -lm"
+        AC_TRY_LINK([#include <math.h>
+                     long double x;],
+                    [int e; return frexpl (x, &e) > 0;],
+          [gl_cv_func_frexpl_in_libm=yes],
+          [gl_cv_func_frexpl_in_libm=no])
+        LIBS="$save_LIBS"
+      ])
+    if test $gl_cv_func_frexpl_in_libm = yes; then
+      FREXPL_LIBM=-lm
+    fi
+  fi
+  if test $gl_cv_func_frexpl_no_libm = yes \
+     || test $gl_cv_func_frexpl_in_libm = yes; then
+    save_LIBS="$LIBS"
+    LIBS="$LIBS $FREXPL_LIBM"
+    gl_FUNC_FREXPL_WORKS
+    LIBS="$save_LIBS"
+    case "$gl_cv_func_frexpl_works" in
+      *yes) gl_func_frexpl=yes ;;
+      *)    gl_func_frexpl=no; REPLACE_FREXPL=1; FREXPL_LIBM= ;;
+    esac
+  else
+    gl_func_frexpl=no
+  fi
+  if test $gl_func_frexpl = yes; then
+    AC_DEFINE([HAVE_FREXPL], [1],
+      [Define if the frexpl() function is available.])
+    dnl Also check whether it's declared.
+    dnl MacOS X 10.3 has frexpl() in libc but doesn't declare it in <math.h>.
+    AC_CHECK_DECL([frexpl], , [HAVE_DECL_FREXPL=0], [#include <math.h>])
+  else
+    HAVE_DECL_FREXPL=0
+    AC_LIBOBJ([frexpl])
+  fi
+  AC_SUBST([FREXPL_LIBM])
+])
+
+AC_DEFUN([gl_FUNC_FREXPL_NO_LIBM],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  AC_CACHE_CHECK([whether frexpl() can be used without linking with libm],
+    [gl_cv_func_frexpl_no_libm],
+    [
+      AC_TRY_LINK([#include <math.h>
+                   long double x;],
+                  [int e; return frexpl (x, &e) > 0;],
+        [gl_cv_func_frexpl_no_libm=yes],
+        [gl_cv_func_frexpl_no_libm=no])
+    ])
+  if test $gl_cv_func_frexpl_no_libm = yes; then
+    gl_FUNC_FREXPL_WORKS
+    case "$gl_cv_func_frexpl_works" in
+      *yes) gl_func_frexpl_no_libm=yes ;;
+      *)    gl_func_frexpl_no_libm=no; REPLACE_FREXPL=1 ;;
+    esac
+  else
+    gl_func_frexpl_no_libm=no
+    dnl Set REPLACE_FREXPL here because the system may have frexpl in libm.
+    REPLACE_FREXPL=1
+  fi
+  if test $gl_func_frexpl_no_libm = yes; then
+    AC_DEFINE([HAVE_FREXPL_IN_LIBC], [1],
+      [Define if the frexpl() function is available in libc.])
+    dnl Also check whether it's declared.
+    dnl MacOS X 10.3 has frexpl() in libc but doesn't declare it in <math.h>.
+    AC_CHECK_DECL([frexpl], , [HAVE_DECL_FREXPL=0], [#include <math.h>])
+  else
+    HAVE_DECL_FREXPL=0
+    AC_LIBOBJ([frexpl])
+  fi
+])
+
+dnl Test whether frexpl() works on finite numbers (this fails on
+dnl MacOS X 10.4/PowerPC, on AIX 5.1, and on BeOS), on denormalized numbers
+dnl (this fails on MacOS X 10.5/i386), and also on infinite numbers (this
+dnl fails e.g. on IRIX 6.5 and mingw).
+AC_DEFUN([gl_FUNC_FREXPL_WORKS],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether frexpl works], [gl_cv_func_frexpl_works],
+    [
+      AC_TRY_RUN([
+#include <float.h>
+#include <math.h>
+/* Override the values of <float.h>, like done in float.in.h.  */
+#if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__)
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP    (-16381)
+#endif
+extern long double frexpl (long double, int *);
+int main()
+{
+  volatile long double x;
+  /* Test on finite numbers that fails on AIX 5.1.  */
+  x = 16.0L;
+  {
+    int exp = -9999;
+    frexpl (x, &exp);
+    if (exp != 5)
+      return 1;
+  }
+  /* Test on finite numbers that fails on MacOS X 10.4, because its frexpl
+     function returns an invalid (incorrectly normalized) value: it returns
+               y = { 0x3fe028f5, 0xc28f5c28, 0x3c9eb851, 0xeb851eb8 }
+     but the correct result is
+          0.505L = { 0x3fe028f5, 0xc28f5c29, 0xbc547ae1, 0x47ae1480 }  */
+  x = 1.01L;
+  {
+    int exp = -9999;
+    long double y = frexpl (x, &exp);
+    if (!(exp == 1 && y == 0.505L))
+      return 1;
+  }
+  /* Test on large finite numbers.  This fails on BeOS at i = 16322, while
+     LDBL_MAX_EXP = 16384.
+     In the loop end test, we test x against Infinity, rather than comparing
+     i with LDBL_MAX_EXP, because BeOS <float.h> has a wrong LDBL_MAX_EXP.  */
+  {
+    int i;
+    for (i = 1, x = 1.0L; x != x + x; i++, x *= 2.0L)
+      {
+        int exp = -9999;
+        frexpl (x, &exp);
+        if (exp != i)
+          return 1;
+      }
+  }
+  /* Test on denormalized numbers.  */
+  {
+    int i;
+    for (i = 1, x = 1.0L; i >= LDBL_MIN_EXP; i--, x *= 0.5L)
+      ;
+    if (x > 0.0L)
+      {
+        int exp;
+        long double y = frexpl (x, &exp);
+        /* On machines with IEEE854 arithmetic: x = 1.68105e-4932,
+           exp = -16382, y = 0.5.  On MacOS X 10.5: exp = -16384, y = 0.5.  */
+        if (exp != LDBL_MIN_EXP - 1)
+          return 1;
+      }
+  }
+  /* Test on infinite numbers.  */
+  x = 1.0L / 0.0L;
+  {
+    int exp;
+    long double y = frexpl (x, &exp);
+    if (y != x)
+      return 1;
+  }
+  return 0;
+}], [gl_cv_func_frexpl_works=yes], [gl_cv_func_frexpl_works=no],
+      [case "$host_os" in
+         aix* | beos* | darwin* | irix* | mingw* | pw*)
+            gl_cv_func_frexpl_works="guessing no";;
+         *) gl_cv_func_frexpl_works="guessing yes";;
+       esac
+      ])
+    ])
+])
diff --git a/libmissing/m4/getdelim.m4 b/libmissing/m4/getdelim.m4
index 9e5ad5b..4beb150 100644
--- a/libmissing/m4/getdelim.m4
+++ b/libmissing/m4/getdelim.m4
@@ -1,6 +1,6 @@
-# getdelim.m4 serial 5
+# getdelim.m4 serial 6
 
-dnl Copyright (C) 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
+dnl Copyright (C) 2005-2007, 2009-2010 Free Software Foundation, Inc.
 dnl
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -15,16 +15,71 @@ AC_DEFUN([gl_FUNC_GETDELIM],
   dnl Persuade glibc <stdio.h> to declare getdelim().
   AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
 
-  AC_REPLACE_FUNCS([getdelim])
   AC_CHECK_DECLS_ONCE([getdelim])
 
-  if test $ac_cv_func_getdelim = no; then
-    gl_PREREQ_GETDELIM
+  AC_CHECK_FUNCS_ONCE([getdelim])
+  if test $ac_cv_func_getdelim = yes; then
+    dnl Found it in some library.  Verify that it works.
+    AC_CACHE_CHECK([for working getdelim function], [gl_cv_func_working_getdelim],
+    [echo fooNbarN | tr -d '\012' | tr N '\012' > conftest.data
+    AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#    include <stdio.h>
+#    include <stdlib.h>
+#    include <string.h>
+    int main ()
+    {
+      FILE *in = fopen ("./conftest.data", "r");
+      if (!in)
+        return 1;
+      {
+        /* Test result for a NULL buffer and a zero size.
+           Based on a test program from Karl Heuer.  */
+        char *line = NULL;
+        size_t siz = 0;
+        int len = getdelim (&line, &siz, '\n', in);
+        if (!(len == 4 && line && strcmp (line, "foo\n") == 0))
+          return 1;
+      }
+      {
+        /* Test result for a NULL buffer and a non-zero size.
+           This crashes on FreeBSD 8.0.  */
+        char *line = NULL;
+        size_t siz = (size_t)(~0) / 4;
+        if (getdelim (&line, &siz, '\n', in) == -1)
+          return 1;
+      }
+      return 0;
+    }
+    ]])], [gl_cv_func_working_getdelim=yes] dnl The library version works.
+    , [gl_cv_func_working_getdelim=no] dnl The library version does NOT work.
+    , dnl We're cross compiling. Assume it works on glibc2 systems.
+      [AC_EGREP_CPP([Lucky GNU user],
+         [
+#include <features.h>
+#ifdef __GNU_LIBRARY__
+ #if (__GLIBC__ >= 2)
+  Lucky GNU user
+ #endif
+#endif
+         ],
+         [gl_cv_func_working_getdelim=yes],
+         [gl_cv_func_working_getdelim=no])]
+    )])
+  else
+    gl_cv_func_working_getdelim=no
   fi
 
   if test $ac_cv_have_decl_getdelim = no; then
     HAVE_DECL_GETDELIM=0
   fi
+
+  if test $gl_cv_func_working_getdelim = no; then
+    if test $ac_cv_func_getdelim = yes; then
+      REPLACE_GETDELIM=1
+    fi
+    AC_LIBOBJ([getdelim])
+    gl_PREREQ_GETDELIM
+  fi
 ])
 
 # Prerequisites of lib/getdelim.c.
diff --git a/libmissing/m4/getline.m4 b/libmissing/m4/getline.m4
index 5b8a712..8300560 100644
--- a/libmissing/m4/getline.m4
+++ b/libmissing/m4/getline.m4
@@ -1,4 +1,4 @@
-# getline.m4 serial 20
+# getline.m4 serial 21
 
 dnl Copyright (C) 1998-2003, 2005-2007, 2009-2010 Free Software Foundation,
 dnl Inc.
@@ -24,26 +24,39 @@ AC_DEFUN([gl_FUNC_GETLINE],
 
   gl_getline_needs_run_time_check=no
   AC_CHECK_FUNC([getline],
-                dnl Found it in some library.  Verify that it works.
-                gl_getline_needs_run_time_check=yes,
-                am_cv_func_working_getline=no)
+                [dnl Found it in some library.  Verify that it works.
+                 gl_getline_needs_run_time_check=yes],
+                [am_cv_func_working_getline=no])
   if test $gl_getline_needs_run_time_check = yes; then
     AC_CACHE_CHECK([for working getline function], [am_cv_func_working_getline],
-    [echo fooN |tr -d '\012'|tr N '\012' > conftest.data
+    [echo fooNbarN | tr -d '\012' | tr N '\012' > conftest.data
     AC_RUN_IFELSE([AC_LANG_SOURCE([[
 #    include <stdio.h>
 #    include <stdlib.h>
 #    include <string.h>
     int main ()
-    { /* Based on a test program from Karl Heuer.  */
-      char *line = NULL;
-      size_t siz = 0;
-      int len;
+    {
       FILE *in = fopen ("./conftest.data", "r");
       if (!in)
         return 1;
-      len = getline (&line, &siz, in);
-      exit ((len == 4 && line && strcmp (line, "foo\n") == 0) ? 0 : 1);
+      {
+        /* Test result for a NULL buffer and a zero size.
+           Based on a test program from Karl Heuer.  */
+        char *line = NULL;
+        size_t siz = 0;
+        int len = getline (&line, &siz, in);
+        if (!(len == 4 && line && strcmp (line, "foo\n") == 0))
+          return 1;
+      }
+      {
+        /* Test result for a NULL buffer and a non-zero size.
+           This crashes on FreeBSD 8.0.  */
+        char *line = NULL;
+        size_t siz = (size_t)(~0) / 4;
+        if (getline (&line, &siz, in) == -1)
+          return 1;
+      }
+      return 0;
     }
     ]])], [am_cv_func_working_getline=yes] dnl The library version works.
     , [am_cv_func_working_getline=no] dnl The library version does NOT work.
@@ -67,6 +80,9 @@ AC_DEFUN([gl_FUNC_GETLINE],
   fi
 
   if test $am_cv_func_working_getline = no; then
+    dnl Set REPLACE_GETLINE always: Even if we have not found the broken
+    dnl getline function among $LIBS, it may exist in libinet and the
+    dnl executable may be linked with -linet.
     REPLACE_GETLINE=1
     AC_LIBOBJ([getline])
 
diff --git a/libmissing/m4/gettimeofday.m4 b/libmissing/m4/gettimeofday.m4
index 735123e..32e4f29 100644
--- a/libmissing/m4/gettimeofday.m4
+++ b/libmissing/m4/gettimeofday.m4
@@ -1,4 +1,4 @@
-# serial 12
+# serial 14
 
 # Copyright (C) 2001-2003, 2005, 2007, 2009-2010 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
@@ -11,33 +11,49 @@ AC_DEFUN([gl_FUNC_GETTIMEOFDAY],
 [
   AC_REQUIRE([AC_C_RESTRICT])
   AC_REQUIRE([gl_HEADER_SYS_TIME_H])
+  AC_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS])
   AC_CHECK_FUNCS_ONCE([gettimeofday])
 
-  AC_CACHE_CHECK([for gettimeofday with POSIX signature],
-    [gl_cv_func_gettimeofday_posix_signature],
-    [AC_COMPILE_IFELSE(
-       [AC_LANG_PROGRAM(
-          [[#include <sys/time.h>
-            struct timeval c;
-          ]],
-          [[
-            int (*f) (struct timeval *restrict, void *restrict) = gettimeofday;
-            int x = f (&c, 0);
-            return !(x | c.tv_sec | c.tv_usec);
-          ]])],
-        [gl_cv_func_gettimeofday_posix_signature=yes],
-        [gl_cv_func_gettimeofday_posix_signature=no])])
-
-  gl_FUNC_GETTIMEOFDAY_CLOBBER
-
-  if test $gl_cv_func_gettimeofday_posix_signature != yes; then
-    REPLACE_GETTIMEOFDAY=1
-    SYS_TIME_H=sys/time.h
-    if test $gl_cv_func_gettimeofday_clobber != yes; then
+  gl_gettimeofday_timezone=void
+  if test $ac_cv_func_gettimeofday = yes; then
+    gl_FUNC_GETTIMEOFDAY_CLOBBER
+    AC_CACHE_CHECK([for gettimeofday with POSIX signature],
+      [gl_cv_func_gettimeofday_posix_signature],
+      [AC_COMPILE_IFELSE(
+         [AC_LANG_PROGRAM(
+            [[#include <sys/time.h>
+              struct timeval c;
+              int gettimeofday (struct timeval *restrict, void *restrict);
+            ]],
+            [[/* glibc uses struct timezone * rather than the POSIX void *
+                 if _GNU_SOURCE is defined.  However, since the only portable
+                 use of gettimeofday uses NULL as the second parameter, and
+                 since the glibc definition is actually more typesafe, it is
+                 not worth wrapping this to get a compliant signature.  */
+              int (*f) (struct timeval *restrict, void *restrict)
+                = gettimeofday;
+              int x = f (&c, 0);
+              return !(x | c.tv_sec | c.tv_usec);
+            ]])],
+          [gl_cv_func_gettimeofday_posix_signature=yes],
+          [AC_COMPILE_IFELSE(
+            [AC_LANG_PROGRAM(
+              [[#include <sys/time.h>
+int gettimeofday (struct timeval *restrict, struct timezone *restrict);
+              ]])],
+            [gl_cv_func_gettimeofday_posix_signature=almost],
+            [gl_cv_func_gettimeofday_posix_signature=no])])])
+    if test $gl_cv_func_gettimeofday_posix_signature = almost; then
+      gl_gettimeofday_timezone='struct timezone'
+    elif test $gl_cv_func_gettimeofday_posix_signature != yes; then
+      REPLACE_GETTIMEOFDAY=1
       AC_LIBOBJ([gettimeofday])
       gl_PREREQ_GETTIMEOFDAY
     fi
   fi
+  AC_DEFINE_UNQUOTED([GETTIMEOFDAY_TIMEZONE], [$gl_gettimeofday_timezone],
+    [Define this to 'void' or 'struct timezone' to match the system's
+     declaration of the second argument to gettimeofday.])
 ])
 
 
@@ -78,7 +94,6 @@ AC_DEFUN([gl_FUNC_GETTIMEOFDAY_CLOBBER],
 
  if test $gl_cv_func_gettimeofday_clobber = yes; then
    REPLACE_GETTIMEOFDAY=1
-   SYS_TIME_H=sys/time.h
    gl_GETTIMEOFDAY_REPLACE_LOCALTIME
    AC_DEFINE([GETTIMEOFDAY_CLOBBERS_LOCALTIME], [1],
      [Define if gettimeofday clobbers the localtime buffer.])
diff --git a/libmissing/m4/gnulib-cache.m4 b/libmissing/m4/gnulib-cache.m4
index 1c76550..32f9a11 100644
--- a/libmissing/m4/gnulib-cache.m4
+++ b/libmissing/m4/gnulib-cache.m4
@@ -15,7 +15,7 @@
 
 
 # Specification in the form of a command-line invocation:
-#   gnulib-tool --import --dir=. --lib=libmissing --source-base=libmissing --m4-base=libmissing/m4 --doc-base=libmissing/doc --tests-base=libmissing/tests --aux-dir=. --with-tests --lgpl --libtool --macro-prefix=gl --no-vc-files accept bind close cond connect dup2 fclose fopen ftw getaddrinfo getpass getsockname gettimeofday inet_ntop inet_pton ioctl listen lock lseek memmem minmax pathmax perror poll regex relocatable-lib-lgpl select setsockopt sigprocmask sleep snprintf socket socklen strcase strcasestr strdup strerror strndup strptime strsep sys_stat thread time_r timegm tls uname vsnprintf write
+#   gnulib-tool --import --dir=. --lib=libmissing --source-base=libmissing --m4-base=libmissing/m4 --doc-base=libmissing/doc --tests-base=libmissing/tests --aux-dir=. --with-tests --lgpl --libtool --macro-prefix=gl --no-vc-files accept bind close cond connect dup2 fclose fopen ftw getaddrinfo getpass getsockname gettimeofday inet_ntop inet_pton ioctl listen lock lseek memmem minmax pathmax perror poll regex relocatable-lib-lgpl select setsockopt sigprocmask sleep snprintf-posix socket socklen strcase strcasestr strdup strerror strndup strptime strsep sys_stat thread time_r timegm tls uname vsnprintf-posix write
 
 # Specification in the form of a few gnulib-tool.m4 macro invocations:
 gl_LOCAL_DIR([])
@@ -50,7 +50,7 @@ gl_MODULES([
   setsockopt
   sigprocmask
   sleep
-  snprintf
+  snprintf-posix
   socket
   socklen
   strcase
@@ -66,7 +66,7 @@ gl_MODULES([
   timegm
   tls
   uname
-  vsnprintf
+  vsnprintf-posix
   write
 ])
 gl_AVOID([])
diff --git a/libmissing/m4/gnulib-comp.m4 b/libmissing/m4/gnulib-comp.m4
index c34c33c..0f912fd 100644
--- a/libmissing/m4/gnulib-comp.m4
+++ b/libmissing/m4/gnulib-comp.m4
@@ -27,6 +27,7 @@ AC_DEFUN([gl_EARLY],
   AC_REQUIRE([AC_PROG_RANLIB])
   AC_REQUIRE([AM_PROG_CC_C_O])
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+  AC_REQUIRE([gl_FP_IEEE])
   AC_REQUIRE([AC_FUNC_FSEEKO])
   gl_THREADLIB_EARLY
 ])
@@ -79,6 +80,10 @@ AC_SUBST([LTALLOCA])
   gl_FLOAT_H
   gl_FUNC_FOPEN
   gl_STDIO_MODULE_INDICATOR([fopen])
+  gl_FUNC_FREXP_NO_LIBM
+  gl_MATH_MODULE_INDICATOR([frexp])
+  gl_FUNC_FREXPL_NO_LIBM
+  gl_MATH_MODULE_INDICATOR([frexpl])
   gl_FUNC_FSEEKO
   gl_STDIO_MODULE_INDICATOR([fseeko])
   gl_FUNC_FTW
@@ -99,6 +104,7 @@ AC_SUBST([LTALLOCA])
   AC_SUBST([LIBINTL])
   AC_SUBST([LTLIBINTL])
   gl_FUNC_GETTIMEOFDAY
+  gl_SYS_TIME_MODULE_INDICATOR([gettimeofday])
   gl_HOSTENT
   gl_INET_NTOP
   gl_ARPA_INET_MODULE_INDICATOR([inet_ntop])
@@ -114,6 +120,9 @@ AC_SUBST([LTALLOCA])
   fi
   gl_SYS_IOCTL_MODULE_INDICATOR([ioctl])
   gl_MODULE_INDICATOR([ioctl])
+  gl_FUNC_ISNAND_NO_LIBM
+  gl_FUNC_ISNANF_NO_LIBM
+  gl_FUNC_ISNANL_NO_LIBM
   gl_LANGINFO_H
   AC_REQUIRE([gl_HEADER_SYS_SOCKET])
   if test "$ac_cv_header_winsock2_h" = yes; then
@@ -130,6 +139,7 @@ AC_SUBST([LTALLOCA])
   AC_DEFINE([GNULIB_MALLOC_GNU], 1, [Define to indicate the 'malloc' module.])
   gl_FUNC_MALLOC_POSIX
   gl_STDLIB_MODULE_INDICATOR([malloc-posix])
+  gl_MATH_H
   gl_FUNC_MBRTOWC
   gl_WCHAR_MODULE_INDICATOR([mbrtowc])
   gl_FUNC_MBSINIT
@@ -151,6 +161,9 @@ AC_SUBST([LTALLOCA])
   gl_FUNC_PERROR
   gl_STRING_MODULE_INDICATOR([perror])
   gl_FUNC_POLL
+  gl_FUNC_PRINTF_FREXP
+  gl_FUNC_PRINTF_FREXPL
+  m4_divert_text([INIT_PREPARE], [gl_printf_safe=yes])
   gl_FUNC_REALLOC_POSIX
   gl_STDLIB_MODULE_INDICATOR([realloc-posix])
   gl_REGEX
@@ -164,6 +177,8 @@ AC_SUBST([LTALLOCA])
   fi
   gl_SYS_SOCKET_MODULE_INDICATOR([setsockopt])
   gl_SIGNAL_H
+  gl_SIGNBIT
+  gl_MATH_MODULE_INDICATOR([signbit])
   gl_SIGNALBLOCKING
   gl_SIGNAL_MODULE_INDICATOR([sigprocmask])
   gl_SIZE_MAX
@@ -171,6 +186,7 @@ AC_SUBST([LTALLOCA])
   gl_UNISTD_MODULE_INDICATOR([sleep])
   gl_FUNC_SNPRINTF
   gl_STDIO_MODULE_INDICATOR([snprintf])
+  gl_FUNC_SNPRINTF_POSIX
   AC_REQUIRE([gl_HEADER_SYS_SOCKET])
   if test "$ac_cv_header_winsock2_h" = yes; then
     AC_LIBOBJ([socket])
@@ -238,6 +254,7 @@ AC_SUBST([LTALLOCA])
   gl_FUNC_VASNPRINTF
   gl_FUNC_VSNPRINTF
   gl_STDIO_MODULE_INDICATOR([vsnprintf])
+  gl_FUNC_VSNPRINTF_POSIX
   gl_WCHAR_H
   gl_FUNC_WCRTOMB
   gl_WCHAR_MODULE_INDICATOR([wcrtomb])
@@ -292,8 +309,12 @@ AC_SUBST([LTALLOCA])
   gl_FUNC_UNGETC_WORKS
   gl_FUNC_GETPAGESIZE
   gl_UNISTD_MODULE_INDICATOR([getpagesize])
+  AC_REQUIRE([AC_C_INLINE])
   AC_C_BIGENDIAN
   AC_C_BIGENDIAN
+  gl_DOUBLE_EXPONENT_LOCATION
+  gl_FLOAT_EXPONENT_LOCATION
+  gl_LONG_DOUBLE_EXPONENT_LOCATION
   gl_FUNC_LSTAT
   gl_SYS_STAT_MODULE_INDICATOR([lstat])
   gt_LOCALE_FR
@@ -312,13 +333,20 @@ AC_SUBST([LTALLOCA])
   gl_FCNTL_MODULE_INDICATOR([open])
   AC_CHECK_HEADERS_ONCE([unistd.h sys/wait.h])
   AC_CHECK_HEADERS_ONCE([unistd.h sys/wait.h])
+  AC_REQUIRE([gl_FLOAT_EXPONENT_LOCATION])
+  AC_REQUIRE([gl_DOUBLE_EXPONENT_LOCATION])
+  AC_REQUIRE([gl_LONG_DOUBLE_EXPONENT_LOCATION])
   AC_CHECK_DECLS_ONCE([alarm])
+  AC_DEFINE([CHECK_SNPRINTF_POSIX], 1,
+    [Define to 1 for strict checking in test-snprintf.c.])
   gt_TYPE_WCHAR_T
   gt_TYPE_WINT_T
   AC_CHECK_DECLS_ONCE([alarm])
   gl_FUNC_SYMLINK
   gl_UNISTD_MODULE_INDICATOR([symlink])
   AC_CHECK_FUNCS_ONCE([shutdown])
+  AC_DEFINE([CHECK_VSNPRINTF_POSIX], 1,
+    [Define to 1 for strict checking in test-vsnprintf.c.])
   gt_LOCALE_FR
   gt_LOCALE_FR_UTF8
   gt_LOCALE_JA
@@ -442,6 +470,9 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/float+.h
   lib/float.in.h
   lib/fopen.c
+  lib/fpucw.h
+  lib/frexp.c
+  lib/frexpl.c
   lib/fseeko.c
   lib/ftw.c
   lib/ftw_.h
@@ -468,12 +499,20 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/inet_pton.c
   lib/intprops.h
   lib/ioctl.c
+  lib/isnan.c
+  lib/isnand-nolibm.h
+  lib/isnand.c
+  lib/isnanf-nolibm.h
+  lib/isnanf.c
+  lib/isnanl-nolibm.h
+  lib/isnanl.c
   lib/langinfo.in.h
   lib/listen.c
   lib/localcharset.c
   lib/localcharset.h
   lib/lseek.c
   lib/malloc.c
+  lib/math.in.h
   lib/mbrtowc.c
   lib/mbsinit.c
   lib/memchr.c
@@ -491,6 +530,10 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/poll.in.h
   lib/printf-args.c
   lib/printf-args.h
+  lib/printf-frexp.c
+  lib/printf-frexp.h
+  lib/printf-frexpl.c
+  lib/printf-frexpl.h
   lib/printf-parse.c
   lib/printf-parse.h
   lib/realloc.c
@@ -507,6 +550,9 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/select.c
   lib/setsockopt.c
   lib/signal.in.h
+  lib/signbitd.c
+  lib/signbitf.c
+  lib/signbitl.c
   lib/sigprocmask.c
   lib/size_max.h
   lib/sleep.c
@@ -566,12 +612,18 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/dos.m4
   m4/dup2.m4
   m4/errno_h.m4
+  m4/exponentd.m4
+  m4/exponentf.m4
+  m4/exponentl.m4
   m4/extensions.m4
   m4/fclose.m4
   m4/fcntl-o.m4
   m4/fcntl_h.m4
   m4/float_h.m4
   m4/fopen.m4
+  m4/fpieee.m4
+  m4/frexp.m4
+  m4/frexpl.m4
   m4/fseeko.m4
   m4/ftw.m4
   m4/getaddrinfo.m4
@@ -589,7 +641,11 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/inet_pton.m4
   m4/intmax_t.m4
   m4/inttypes_h.m4
+  m4/isnand.m4
+  m4/isnanf.m4
+  m4/isnanl.m4
   m4/langinfo_h.m4
+  m4/ldexpl.m4
   m4/lib-ld.m4
   m4/lib-link.m4
   m4/lib-prefix.m4
@@ -603,6 +659,7 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/lseek.m4
   m4/lstat.m4
   m4/malloc.m4
+  m4/math_h.m4
   m4/mbrtowc.m4
   m4/mbsinit.m4
   m4/mbstate_t.m4
@@ -616,11 +673,14 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/netdb_h.m4
   m4/netinet_in_h.m4
   m4/nl_langinfo.m4
+  m4/nocrash.m4
   m4/onceonly.m4
   m4/open.m4
   m4/pathmax.m4
   m4/perror.m4
   m4/poll.m4
+  m4/printf-frexp.m4
+  m4/printf-frexpl.m4
   m4/printf.m4
   m4/realloc.m4
   m4/regex.m4
@@ -629,8 +689,10 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/servent.m4
   m4/signal_h.m4
   m4/signalblocking.m4
+  m4/signbit.m4
   m4/size_max.m4
   m4/sleep.m4
+  m4/snprintf-posix.m4
   m4/snprintf.m4
   m4/sockets.m4
   m4/socklen.m4
@@ -671,6 +733,7 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/ungetc.m4
   m4/unistd_h.m4
   m4/vasnprintf.m4
+  m4/vsnprintf-posix.m4
   m4/vsnprintf.m4
   m4/warn-on-use.m4
   m4/wchar.m4
@@ -683,6 +746,7 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/xsize.m4
   m4/yield.m4
   tests/macros.h
+  tests/nan.h
   tests/signature.h
   tests/test-alignof.c
   tests/test-alloca-opt.c
@@ -702,6 +766,8 @@ AC_DEFUN([gl_FILE_LIST], [
   tests/test-fcntl-h.c
   tests/test-fopen.c
   tests/test-fopen.h
+  tests/test-frexp.c
+  tests/test-frexpl.c
   tests/test-fseeko.c
   tests/test-fseeko.sh
   tests/test-fseeko2.sh
@@ -712,12 +778,19 @@ AC_DEFUN([gl_FILE_LIST], [
   tests/test-gettimeofday.c
   tests/test-inet_ntop.c
   tests/test-inet_pton.c
+  tests/test-isnand-nolibm.c
+  tests/test-isnand.h
+  tests/test-isnanf-nolibm.c
+  tests/test-isnanf.h
+  tests/test-isnanl-nolibm.c
+  tests/test-isnanl.h
   tests/test-langinfo.c
   tests/test-lock.c
   tests/test-lseek.c
   tests/test-lseek.sh
   tests/test-lstat.c
   tests/test-lstat.h
+  tests/test-math.c
   tests/test-mbrtowc.c
   tests/test-mbrtowc1.sh
   tests/test-mbrtowc2.sh
@@ -736,13 +809,18 @@ AC_DEFUN([gl_FILE_LIST], [
   tests/test-perror.c
   tests/test-perror.sh
   tests/test-poll.c
+  tests/test-printf-frexp.c
+  tests/test-printf-frexpl.c
   tests/test-select-fd.c
   tests/test-select-in.sh
   tests/test-select-out.sh
   tests/test-select-stdin.c
   tests/test-select.c
   tests/test-signal.c
+  tests/test-signbit.c
   tests/test-sleep.c
+  tests/test-snprintf-posix.c
+  tests/test-snprintf-posix.h
   tests/test-snprintf.c
   tests/test-sockets.c
   tests/test-stat.c
@@ -769,6 +847,7 @@ AC_DEFUN([gl_FILE_LIST], [
   tests/test-uname.c
   tests/test-unistd.c
   tests/test-vasnprintf.c
+  tests/test-vsnprintf-posix.c
   tests/test-vsnprintf.c
   tests/test-wchar.c
   tests/test-wcrtomb.c
@@ -782,6 +861,7 @@ AC_DEFUN([gl_FILE_LIST], [
   tests=lib/fcntl.in.h
   tests=lib/getpagesize.c
   tests=lib/glthread/yield.h
+  tests=lib/ignore-value.h
   tests=lib/lstat.c
   tests=lib/open.c
   tests=lib/same-inode.h
diff --git a/libmissing/m4/isnand.m4 b/libmissing/m4/isnand.m4
new file mode 100644
index 0000000..cd91628
--- /dev/null
+++ b/libmissing/m4/isnand.m4
@@ -0,0 +1,95 @@
+# isnand.m4 serial 6
+dnl Copyright (C) 2007-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl Check how to get or define isnand().
+
+AC_DEFUN([gl_FUNC_ISNAND],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  ISNAND_LIBM=
+  gl_HAVE_ISNAND_NO_LIBM
+  if test $gl_cv_func_isnand_no_libm = no; then
+    gl_HAVE_ISNAND_IN_LIBM
+    if test $gl_cv_func_isnand_in_libm = yes; then
+      ISNAND_LIBM=-lm
+    fi
+  fi
+  dnl The variable gl_func_isnand set here is used by isnan.m4.
+  if test $gl_cv_func_isnand_no_libm = yes \
+     || test $gl_cv_func_isnand_in_libm = yes; then
+    gl_func_isnand=yes
+  else
+    gl_func_isnand=no
+    HAVE_ISNAND=0
+    gl_BUILD_ISNAND
+  fi
+  AC_SUBST([ISNAND_LIBM])
+])
+
+dnl Check how to get or define isnand() without linking with libm.
+
+AC_DEFUN([gl_FUNC_ISNAND_NO_LIBM],
+[
+  gl_HAVE_ISNAND_NO_LIBM
+  if test $gl_cv_func_isnand_no_libm = yes; then
+    AC_DEFINE([HAVE_ISNAND_IN_LIBC], [1],
+      [Define if the isnan(double) function is available in libc.])
+  else
+    gl_BUILD_ISNAND
+  fi
+])
+
+dnl Pull in replacement isnand definition. It does not need -lm.
+AC_DEFUN([gl_BUILD_ISNAND],
+[
+  AC_LIBOBJ([isnand])
+  gl_DOUBLE_EXPONENT_LOCATION
+])
+
+dnl Test whether isnand() can be used with libm.
+
+AC_DEFUN([gl_HAVE_ISNAND_IN_LIBM],
+[
+  AC_CACHE_CHECK([whether isnan(double) can be used with libm],
+    [gl_cv_func_isnand_in_libm],
+    [
+      save_LIBS="$LIBS"
+      LIBS="$LIBS -lm"
+      AC_TRY_LINK([#include <math.h>
+                   #if __GNUC__ >= 4
+                   # undef isnand
+                   # define isnand(x) __builtin_isnand ((double)(x))
+                   #elif defined isnan
+                   # undef isnand
+                   # define isnand(x) isnan ((double)(x))
+                   #endif
+                   double x;],
+                  [return isnand (x);],
+        [gl_cv_func_isnand_in_libm=yes],
+        [gl_cv_func_isnand_in_libm=no])
+      LIBS="$save_LIBS"
+    ])
+])
+
+AC_DEFUN([gl_HAVE_ISNAND_NO_LIBM],
+[
+  AC_CACHE_CHECK([whether isnan(double) can be used without linking with libm],
+    [gl_cv_func_isnand_no_libm],
+    [
+      AC_TRY_LINK([#include <math.h>
+                   #if __GNUC__ >= 4
+                   # undef isnand
+                   # define isnand(x) __builtin_isnan ((double)(x))
+                   #else
+                   # undef isnand
+                   # define isnand(x) isnan ((double)(x))
+                   #endif
+                   double x;],
+                  [return isnand (x);],
+        [gl_cv_func_isnand_no_libm=yes],
+        [gl_cv_func_isnand_no_libm=no])
+    ])
+])
diff --git a/libmissing/m4/isnanf.m4 b/libmissing/m4/isnanf.m4
new file mode 100644
index 0000000..1509fb4
--- /dev/null
+++ b/libmissing/m4/isnanf.m4
@@ -0,0 +1,179 @@
+# isnanf.m4 serial 10
+dnl Copyright (C) 2007-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl Check how to get or define isnanf().
+
+AC_DEFUN([gl_FUNC_ISNANF],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  ISNANF_LIBM=
+  gl_HAVE_ISNANF_NO_LIBM
+  if test $gl_cv_func_isnanf_no_libm = no; then
+    gl_HAVE_ISNANF_IN_LIBM
+    if test $gl_cv_func_isnanf_in_libm = yes; then
+      ISNANF_LIBM=-lm
+    fi
+  fi
+  if test $gl_cv_func_isnanf_no_libm = yes \
+     || test $gl_cv_func_isnanf_in_libm = yes; then
+    save_LIBS="$LIBS"
+    LIBS="$LIBS $ISNANF_LIBM"
+    gl_ISNANF_WORKS
+    LIBS="$save_LIBS"
+    case "$gl_cv_func_isnanf_works" in
+      *yes) gl_func_isnanf=yes ;;
+      *)    gl_func_isnanf=no; ISNANF_LIBM= ;;
+    esac
+  else
+    gl_func_isnanf=no
+  fi
+  if test $gl_func_isnanf != yes; then
+    HAVE_ISNANF=0
+    gl_BUILD_ISNANF
+  fi
+  AC_SUBST([ISNANF_LIBM])
+])
+
+dnl Check how to get or define isnanf() without linking with libm.
+
+AC_DEFUN([gl_FUNC_ISNANF_NO_LIBM],
+[
+  gl_HAVE_ISNANF_NO_LIBM
+  if test $gl_cv_func_isnanf_no_libm = yes; then
+    gl_ISNANF_WORKS
+  fi
+  if test $gl_cv_func_isnanf_no_libm = yes \
+     && { case "$gl_cv_func_isnanf_works" in
+            *yes) true;;
+            *) false;;
+          esac
+        }; then
+    AC_DEFINE([HAVE_ISNANF_IN_LIBC], [1],
+      [Define if the isnan(float) function is available in libc.])
+  else
+    gl_BUILD_ISNANF
+  fi
+])
+
+dnl Pull in replacement isnanf definition. It does not need -lm.
+AC_DEFUN([gl_BUILD_ISNANF],
+[
+  AC_LIBOBJ([isnanf])
+  gl_FLOAT_EXPONENT_LOCATION
+])
+
+dnl Test whether isnanf() can be used without libm.
+AC_DEFUN([gl_HAVE_ISNANF_NO_LIBM],
+[
+  AC_CACHE_CHECK([whether isnan(float) can be used without linking with libm],
+    [gl_cv_func_isnanf_no_libm],
+    [
+      AC_TRY_LINK([#include <math.h>
+                   #if __GNUC__ >= 4
+                   # undef isnanf
+                   # define isnanf(x) __builtin_isnanf ((float)(x))
+                   #elif defined isnan
+                   # undef isnanf
+                   # define isnanf(x) isnan ((float)(x))
+                   #endif
+                   float x;],
+                  [return isnanf (x);],
+        [gl_cv_func_isnanf_no_libm=yes],
+        [gl_cv_func_isnanf_no_libm=no])
+    ])
+])
+
+dnl Test whether isnanf() can be used with libm.
+AC_DEFUN([gl_HAVE_ISNANF_IN_LIBM],
+[
+  AC_CACHE_CHECK([whether isnan(float) can be used with libm],
+    [gl_cv_func_isnanf_in_libm],
+    [
+      save_LIBS="$LIBS"
+      LIBS="$LIBS -lm"
+      AC_TRY_LINK([#include <math.h>
+                   #if __GNUC__ >= 4
+                   # undef isnanf
+                   # define isnanf(x) __builtin_isnanf ((float)(x))
+                   #elif defined isnan
+                   # undef isnanf
+                   # define isnanf(x) isnan ((float)(x))
+                   #endif
+                   float x;],
+                  [return isnanf (x);],
+        [gl_cv_func_isnanf_in_libm=yes],
+        [gl_cv_func_isnanf_in_libm=no])
+      LIBS="$save_LIBS"
+    ])
+])
+
+dnl Test whether isnanf() rejects Infinity (this fails on Solaris 2.5.1),
+dnl recognizes a NaN (this fails on IRIX 6.5 with cc), and recognizes a NaN
+dnl with in-memory representation 0x7fbfffff (this fails on IRIX 6.5).
+AC_DEFUN([gl_ISNANF_WORKS],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_REQUIRE([gl_FLOAT_EXPONENT_LOCATION])
+  AC_CACHE_CHECK([whether isnan(float) works], [gl_cv_func_isnanf_works],
+    [
+      AC_TRY_RUN([
+#include <math.h>
+#if __GNUC__ >= 4
+# undef isnanf
+# define isnanf(x) __builtin_isnanf ((float)(x))
+#elif defined isnan
+# undef isnanf
+# define isnanf(x) isnan ((float)(x))
+#endif
+/* The Compaq (ex-DEC) C 6.4 compiler chokes on the expression 0.0 / 0.0.  */
+#ifdef __DECC
+static float
+NaN ()
+{
+  static float zero = 0.0f;
+  return zero / zero;
+}
+#else
+# define NaN() (0.0f / 0.0f)
+#endif
+#define NWORDS \
+  ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+typedef union { unsigned int word[NWORDS]; float value; } memory_float;
+int main()
+{
+  memory_float m;
+
+  if (isnanf (1.0f / 0.0f))
+    return 1;
+
+  if (!isnanf (NaN ()))
+    return 1;
+
+#if defined FLT_EXPBIT0_WORD && defined FLT_EXPBIT0_BIT
+  /* The isnanf function should be immune against changes in the sign bit and
+     in the mantissa bits.  The xor operation twiddles a bit that can only be
+     a sign bit or a mantissa bit.  */
+  if (FLT_EXPBIT0_WORD == 0 && FLT_EXPBIT0_BIT > 0)
+    {
+      m.value = NaN ();
+      /* Set the bits below the exponent to 01111...111.  */
+      m.word[0] &= -1U << FLT_EXPBIT0_BIT;
+      m.word[0] |= 1U << (FLT_EXPBIT0_BIT - 1) - 1;
+      if (!isnanf (m.value))
+        return 1;
+    }
+#endif
+
+  return 0;
+}], [gl_cv_func_isnanf_works=yes], [gl_cv_func_isnanf_works=no],
+        [case "$host_os" in
+           irix* | solaris*) gl_cv_func_isnanf_works="guessing no";;
+           *)                gl_cv_func_isnanf_works="guessing yes";;
+         esac
+        ])
+    ])
+])
diff --git a/libmissing/m4/isnanl.m4 b/libmissing/m4/isnanl.m4
new file mode 100644
index 0000000..25daeca
--- /dev/null
+++ b/libmissing/m4/isnanl.m4
@@ -0,0 +1,245 @@
+# isnanl.m4 serial 12
+dnl Copyright (C) 2007-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_ISNANL],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  ISNANL_LIBM=
+  gl_HAVE_ISNANL_NO_LIBM
+  if test $gl_cv_func_isnanl_no_libm = no; then
+    gl_HAVE_ISNANL_IN_LIBM
+    if test $gl_cv_func_isnanl_in_libm = yes; then
+      ISNANL_LIBM=-lm
+    fi
+  fi
+  if test $gl_cv_func_isnanl_no_libm = yes \
+     || test $gl_cv_func_isnanl_in_libm = yes; then
+    save_LIBS="$LIBS"
+    LIBS="$LIBS $ISNANL_LIBM"
+    gl_FUNC_ISNANL_WORKS
+    LIBS="$save_LIBS"
+    case "$gl_cv_func_isnanl_works" in
+      *yes) gl_func_isnanl=yes ;;
+      *)    gl_func_isnanl=no; ISNANL_LIBM= ;;
+    esac
+  else
+    gl_func_isnanl=no
+  fi
+  if test $gl_func_isnanl != yes; then
+    HAVE_ISNANL=0
+    gl_BUILD_ISNANL
+  fi
+  AC_SUBST([ISNANL_LIBM])
+])
+
+AC_DEFUN([gl_FUNC_ISNANL_NO_LIBM],
+[
+  gl_HAVE_ISNANL_NO_LIBM
+  gl_func_isnanl_no_libm=$gl_cv_func_isnanl_no_libm
+  if test $gl_func_isnanl_no_libm = yes; then
+    gl_FUNC_ISNANL_WORKS
+    case "$gl_cv_func_isnanl_works" in
+      *yes) ;;
+      *)    gl_func_isnanl_no_libm=no ;;
+    esac
+  fi
+  if test $gl_func_isnanl_no_libm = yes; then
+    AC_DEFINE([HAVE_ISNANL_IN_LIBC], [1],
+      [Define if the isnan(long double) function is available in libc.])
+  else
+    gl_BUILD_ISNANL
+  fi
+])
+
+dnl Pull in replacement isnanl definition. It does not need -lm.
+AC_DEFUN([gl_BUILD_ISNANL],
+[
+  AC_LIBOBJ([isnanl])
+  gl_LONG_DOUBLE_EXPONENT_LOCATION
+])
+
+dnl Test whether isnanl() can be used without libm.
+AC_DEFUN([gl_HAVE_ISNANL_NO_LIBM],
+[
+  AC_CACHE_CHECK([whether isnan(long double) can be used without linking with libm],
+    [gl_cv_func_isnanl_no_libm],
+    [
+      AC_TRY_LINK([#include <math.h>
+                   #if __GNUC__ >= 4
+                   # undef isnanl
+                   # define isnanl(x) __builtin_isnanl ((long double)(x))
+                   #elif defined isnan
+                   # undef isnanl
+                   # define isnanl(x) isnan ((long double)(x))
+                   #endif
+                   long double x;],
+                  [return isnanl (x);],
+        [gl_cv_func_isnanl_no_libm=yes],
+        [gl_cv_func_isnanl_no_libm=no])
+    ])
+])
+
+dnl Test whether isnanl() can be used with libm.
+AC_DEFUN([gl_HAVE_ISNANL_IN_LIBM],
+[
+  AC_CACHE_CHECK([whether isnan(long double) can be used with libm],
+    [gl_cv_func_isnanl_in_libm],
+    [
+      save_LIBS="$LIBS"
+      LIBS="$LIBS -lm"
+      AC_TRY_LINK([#include <math.h>
+                   #if __GNUC__ >= 4
+                   # undef isnanl
+                   # define isnanl(x) __builtin_isnanl ((long double)(x))
+                   #elif defined isnan
+                   # undef isnanl
+                   # define isnanl(x) isnan ((long double)(x))
+                   #endif
+                   long double x;],
+                  [return isnanl (x);],
+        [gl_cv_func_isnanl_in_libm=yes],
+        [gl_cv_func_isnanl_in_libm=no])
+      LIBS="$save_LIBS"
+    ])
+])
+
+dnl Test whether isnanl() recognizes all numbers which are neither finite nor
+dnl infinite. This test fails e.g. on NetBSD/i386 and on glibc/ia64.
+dnl Also, the GCC >= 4.0 built-in __builtin_isnanl does not pass the tests
+dnl - for pseudo-denormals on i686 and x86_64,
+dnl - for pseudo-zeroes, unnormalized numbers, and pseudo-denormals on ia64.
+AC_DEFUN([gl_FUNC_ISNANL_WORKS],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([gl_BIGENDIAN])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether isnanl works], [gl_cv_func_isnanl_works],
+    [
+      AC_TRY_RUN([
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#if __GNUC__ >= 4
+# undef isnanl
+# define isnanl(x) __builtin_isnanl ((long double)(x))
+#elif defined isnan
+# undef isnanl
+# define isnanl(x) isnan ((long double)(x))
+#endif
+#define NWORDS \
+  ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+typedef union { unsigned int word[NWORDS]; long double value; }
+        memory_long_double;
+/* On Irix 6.5, gcc 3.4.3 can't compute compile-time NaN, and needs the
+   runtime type conversion.  */
+#ifdef __sgi
+static long double NaNl ()
+{
+  double zero = 0.0;
+  return zero / zero;
+}
+#else
+# define NaNl() (0.0L / 0.0L)
+#endif
+int main ()
+{
+  memory_long_double m;
+  unsigned int i;
+
+  if (!isnanl (NaNl ()))
+    return 1;
+
+  /* The isnanl function should be immune against changes in the sign bit and
+     in the mantissa bits.  The xor operation twiddles a bit that can only be
+     a sign bit or a mantissa bit (since the exponent never extends to
+     bit 31).  */
+  m.value = NaNl ();
+  m.word[NWORDS / 2] ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1);
+  for (i = 0; i < NWORDS; i++)
+    m.word[i] |= 1;
+  if (!isnanl (m.value))
+    return 1;
+
+#if ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_))
+/* Representation of an 80-bit 'long double' as an initializer for a sequence
+   of 'unsigned int' words.  */
+# ifdef WORDS_BIGENDIAN
+#  define LDBL80_WORDS(exponent,manthi,mantlo) \
+     { ((unsigned int) (exponent) << 16) | ((unsigned int) (manthi) >> 16), \
+       ((unsigned int) (manthi) << 16) | (unsigned int) (mantlo) >> 16),    \
+       (unsigned int) (mantlo) << 16                                        \
+     }
+# else
+#  define LDBL80_WORDS(exponent,manthi,mantlo) \
+     { mantlo, manthi, exponent }
+# endif
+  { /* Quiet NaN.  */
+    static memory_long_double x =
+      { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) };
+    if (!isnanl (x.value))
+      return 1;
+  }
+  {
+    /* Signalling NaN.  */
+    static memory_long_double x =
+      { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) };
+    if (!isnanl (x.value))
+      return 1;
+  }
+  /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities,
+     Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in
+       Intel IA-64 Architecture Software Developer's Manual, Volume 1:
+       Application Architecture.
+       Table 5-2 "Floating-Point Register Encodings"
+       Figure 5-6 "Memory to Floating-Point Register Data Translation"
+   */
+  { /* Pseudo-NaN.  */
+    static memory_long_double x =
+      { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) };
+    if (!isnanl (x.value))
+      return 1;
+  }
+  { /* Pseudo-Infinity.  */
+    static memory_long_double x =
+      { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) };
+    if (!isnanl (x.value))
+      return 1;
+  }
+  { /* Pseudo-Zero.  */
+    static memory_long_double x =
+      { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) };
+    if (!isnanl (x.value))
+      return 1;
+  }
+  { /* Unnormalized number.  */
+    static memory_long_double x =
+      { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) };
+    if (!isnanl (x.value))
+      return 1;
+  }
+  { /* Pseudo-Denormal.  */
+    static memory_long_double x =
+      { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) };
+    if (!isnanl (x.value))
+      return 1;
+  }
+#endif
+
+  return 0;
+}], [gl_cv_func_isnanl_works=yes], [gl_cv_func_isnanl_works=no],
+      [case "$host_cpu" in
+                               # Guess no on ia64, x86_64, i386.
+         ia64 | x86_64 | i*86) gl_cv_func_isnanl_works="guessing no";;
+         *)
+           case "$host_os" in
+             netbsd*) gl_cv_func_isnanl_works="guessing no";;
+             *)       gl_cv_func_isnanl_works="guessing yes";;
+           esac
+           ;;
+       esac
+      ])
+    ])
+])
diff --git a/libmissing/m4/ldexpl.m4 b/libmissing/m4/ldexpl.m4
new file mode 100644
index 0000000..bcc76b2
--- /dev/null
+++ b/libmissing/m4/ldexpl.m4
@@ -0,0 +1,88 @@
+# ldexpl.m4 serial 4
+dnl Copyright (C) 2007-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_LDEXPL],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  LDEXPL_LIBM=
+  AC_CACHE_CHECK([whether ldexpl() can be used without linking with libm],
+    [gl_cv_func_ldexpl_no_libm],
+    [
+      AC_TRY_LINK([#include <math.h>
+                   long double x;],
+                  [return ldexpl (x, -1) > 0;],
+        [gl_cv_func_ldexpl_no_libm=yes],
+        [gl_cv_func_ldexpl_no_libm=no])
+    ])
+  if test $gl_cv_func_ldexpl_no_libm = no; then
+    AC_CACHE_CHECK([whether ldexpl() can be used with libm],
+      [gl_cv_func_ldexpl_in_libm],
+      [
+        save_LIBS="$LIBS"
+        LIBS="$LIBS -lm"
+        AC_TRY_LINK([#include <math.h>
+                     long double x;],
+                    [return ldexpl (x, -1) > 0;],
+          [gl_cv_func_ldexpl_in_libm=yes],
+          [gl_cv_func_ldexpl_in_libm=no])
+        LIBS="$save_LIBS"
+      ])
+    if test $gl_cv_func_ldexpl_in_libm = yes; then
+      LDEXPL_LIBM=-lm
+    fi
+  fi
+  if test $gl_cv_func_ldexpl_no_libm = yes \
+     || test $gl_cv_func_ldexpl_in_libm = yes; then
+    save_LIBS="$LIBS"
+    LIBS="$LIBS $LDEXPL_LIBM"
+    gl_FUNC_LDEXPL_WORKS
+    LIBS="$save_LIBS"
+    case "$gl_cv_func_ldexpl_works" in
+      *yes) gl_func_ldexpl=yes ;;
+      *)    gl_func_ldexpl=no; REPLACE_LDEXPL=1; LDEXPL_LIBM= ;;
+    esac
+  else
+    gl_func_ldexpl=no
+  fi
+  if test $gl_func_ldexpl = yes; then
+    AC_DEFINE([HAVE_LDEXPL], [1],
+      [Define if the ldexpl() function is available.])
+    dnl Also check whether it's declared.
+    dnl MacOS X 10.3 has ldexpl() in libc but doesn't declare it in <math.h>.
+    AC_CHECK_DECL([ldexpl], , [HAVE_DECL_LDEXPL=0], [#include <math.h>])
+  else
+    HAVE_DECL_LDEXPL=0
+    AC_LIBOBJ([ldexpl])
+  fi
+  AC_SUBST([LDEXPL_LIBM])
+])
+
+dnl Test whether ldexpl() works on finite numbers (this fails on AIX 5.1
+dnl and MacOS X 10.4/PowerPC).
+AC_DEFUN([gl_FUNC_LDEXPL_WORKS],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether ldexpl works], [gl_cv_func_ldexpl_works],
+    [
+      AC_TRY_RUN([
+#include <math.h>
+extern long double ldexpl (long double, int);
+int main()
+{
+  volatile long double x1 = 1.0;
+  volatile long double y1 = ldexpl (x1, -1);
+  volatile long double x2 = 1.73205L;
+  volatile long double y2 = ldexpl (x2, 0);
+  return (y1 != 0.5L) || (y2 != x2);
+}], [gl_cv_func_ldexpl_works=yes], [gl_cv_func_ldexpl_works=no],
+      [case "$host_os" in
+         aix*) gl_cv_func_ldexpl_works="guessing no";;
+         *)    gl_cv_func_ldexpl_works="guessing yes";;
+       esac
+      ])
+    ])
+])
diff --git a/libmissing/m4/math_h.m4 b/libmissing/m4/math_h.m4
new file mode 100644
index 0000000..e3b499e
--- /dev/null
+++ b/libmissing/m4/math_h.m4
@@ -0,0 +1,128 @@
+# math_h.m4 serial 17
+dnl Copyright (C) 2007-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_MATH_H],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  gl_CHECK_NEXT_HEADERS([math.h])
+  AC_REQUIRE([AC_C_INLINE])
+
+  AC_CACHE_CHECK([whether NAN macro works], [gl_cv_header_math_nan_works],
+    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <math.h>]],
+      [[/* Solaris 10 has a broken definition of NAN.  Other platforms
+        fail to provide NAN, or provide it only in C99 mode; this
+        test only needs to fail when NAN is provided but wrong.  */
+         float f = 1.0f;
+#ifdef NAN
+         f = NAN;
+#endif
+         return f == 0;]])],
+      [gl_cv_header_math_nan_works=yes],
+      [gl_cv_header_math_nan_works=no])])
+  if test $gl_cv_header_math_nan_works = no; then
+    REPLACE_NAN=1
+  fi
+  AC_CACHE_CHECK([whether HUGE_VAL works], [gl_cv_header_math_huge_val_works],
+    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <math.h>]],
+      [[/* Solaris 10 has a broken definition of HUGE_VAL.  */
+         double d = HUGE_VAL;
+         return d == 0;]])],
+      [gl_cv_header_math_huge_val_works=yes],
+      [gl_cv_header_math_huge_val_works=no])])
+  if test $gl_cv_header_math_huge_val_works = no; then
+    REPLACE_HUGE_VAL=1
+  fi
+
+  dnl Check for declarations of anything we want to poison if the
+  dnl corresponding gnulib module is not in use.
+  gl_WARN_ON_USE_PREPARE([[#include <math.h>
+    ]], [acosl asinl atanl ceilf ceill cosl expl floorf floorl frexpl
+    ldexpl logl round roundf roundl sinl sqrtl tanl trunc truncf truncl])
+])
+
+AC_DEFUN([gl_MATH_MODULE_INDICATOR],
+[
+  dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  GNULIB_[]m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./-],[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])=1
+])
+
+AC_DEFUN([gl_MATH_H_DEFAULTS],
+[
+  GNULIB_ACOSL=0;    AC_SUBST([GNULIB_ACOSL])
+  GNULIB_ASINL=0;    AC_SUBST([GNULIB_ASINL])
+  GNULIB_ATANL=0;    AC_SUBST([GNULIB_ATANL])
+  GNULIB_CEILF=0;    AC_SUBST([GNULIB_CEILF])
+  GNULIB_CEILL=0;    AC_SUBST([GNULIB_CEILL])
+  GNULIB_COSL=0;     AC_SUBST([GNULIB_COSL])
+  GNULIB_EXPL=0;     AC_SUBST([GNULIB_EXPL])
+  GNULIB_FLOORF=0;   AC_SUBST([GNULIB_FLOORF])
+  GNULIB_FLOORL=0;   AC_SUBST([GNULIB_FLOORL])
+  GNULIB_FREXP=0;    AC_SUBST([GNULIB_FREXP])
+  GNULIB_FREXPL=0;   AC_SUBST([GNULIB_FREXPL])
+  GNULIB_ISFINITE=0; AC_SUBST([GNULIB_ISFINITE])
+  GNULIB_ISINF=0;    AC_SUBST([GNULIB_ISINF])
+  GNULIB_ISNAN=0;    AC_SUBST([GNULIB_ISNAN])
+  GNULIB_ISNANF=0;   AC_SUBST([GNULIB_ISNANF])
+  GNULIB_ISNAND=0;   AC_SUBST([GNULIB_ISNAND])
+  GNULIB_ISNANL=0;   AC_SUBST([GNULIB_ISNANL])
+  GNULIB_LDEXPL=0;   AC_SUBST([GNULIB_LDEXPL])
+  GNULIB_LOGL=0;     AC_SUBST([GNULIB_LOGL])
+  GNULIB_ROUND=0;    AC_SUBST([GNULIB_ROUND])
+  GNULIB_ROUNDF=0;   AC_SUBST([GNULIB_ROUNDF])
+  GNULIB_ROUNDL=0;   AC_SUBST([GNULIB_ROUNDL])
+  GNULIB_SIGNBIT=0;  AC_SUBST([GNULIB_SIGNBIT])
+  GNULIB_SINL=0;     AC_SUBST([GNULIB_SINL])
+  GNULIB_SQRTL=0;    AC_SUBST([GNULIB_SQRTL])
+  GNULIB_TANL=0;     AC_SUBST([GNULIB_TANL])
+  GNULIB_TRUNC=0;    AC_SUBST([GNULIB_TRUNC])
+  GNULIB_TRUNCF=0;   AC_SUBST([GNULIB_TRUNCF])
+  GNULIB_TRUNCL=0;   AC_SUBST([GNULIB_TRUNCL])
+  dnl Assume proper GNU behavior unless another module says otherwise.
+  HAVE_ACOSL=1;                AC_SUBST([HAVE_ACOSL])
+  HAVE_ASINL=1;                AC_SUBST([HAVE_ASINL])
+  HAVE_ATANL=1;                AC_SUBST([HAVE_ATANL])
+  HAVE_COSL=1;                 AC_SUBST([HAVE_COSL])
+  HAVE_EXPL=1;                 AC_SUBST([HAVE_EXPL])
+  HAVE_ISNANF=1;               AC_SUBST([HAVE_ISNANF])
+  HAVE_ISNAND=1;               AC_SUBST([HAVE_ISNAND])
+  HAVE_ISNANL=1;               AC_SUBST([HAVE_ISNANL])
+  HAVE_LOGL=1;                 AC_SUBST([HAVE_LOGL])
+  HAVE_SINL=1;                 AC_SUBST([HAVE_SINL])
+  HAVE_SQRTL=1;                AC_SUBST([HAVE_SQRTL])
+  HAVE_TANL=1;                 AC_SUBST([HAVE_TANL])
+  HAVE_DECL_ACOSL=1;           AC_SUBST([HAVE_DECL_ACOSL])
+  HAVE_DECL_ASINL=1;           AC_SUBST([HAVE_DECL_ASINL])
+  HAVE_DECL_ATANL=1;           AC_SUBST([HAVE_DECL_ATANL])
+  HAVE_DECL_COSL=1;            AC_SUBST([HAVE_DECL_COSL])
+  HAVE_DECL_EXPL=1;            AC_SUBST([HAVE_DECL_EXPL])
+  HAVE_DECL_FREXPL=1;          AC_SUBST([HAVE_DECL_FREXPL])
+  HAVE_DECL_LDEXPL=1;          AC_SUBST([HAVE_DECL_LDEXPL])
+  HAVE_DECL_LOGL=1;            AC_SUBST([HAVE_DECL_LOGL])
+  HAVE_DECL_SINL=1;            AC_SUBST([HAVE_DECL_SINL])
+  HAVE_DECL_SQRTL=1;           AC_SUBST([HAVE_DECL_SQRTL])
+  HAVE_DECL_TANL=1;            AC_SUBST([HAVE_DECL_TANL])
+  HAVE_DECL_TRUNC=1;           AC_SUBST([HAVE_DECL_TRUNC])
+  HAVE_DECL_TRUNCF=1;          AC_SUBST([HAVE_DECL_TRUNCF])
+  REPLACE_CEILF=0;             AC_SUBST([REPLACE_CEILF])
+  REPLACE_CEILL=0;             AC_SUBST([REPLACE_CEILL])
+  REPLACE_FLOORF=0;            AC_SUBST([REPLACE_FLOORF])
+  REPLACE_FLOORL=0;            AC_SUBST([REPLACE_FLOORL])
+  REPLACE_FREXP=0;             AC_SUBST([REPLACE_FREXP])
+  REPLACE_FREXPL=0;            AC_SUBST([REPLACE_FREXPL])
+  REPLACE_HUGE_VAL=0;          AC_SUBST([REPLACE_HUGE_VAL])
+  REPLACE_ISFINITE=0;          AC_SUBST([REPLACE_ISFINITE])
+  REPLACE_ISINF=0;             AC_SUBST([REPLACE_ISINF])
+  REPLACE_ISNAN=0;             AC_SUBST([REPLACE_ISNAN])
+  REPLACE_LDEXPL=0;            AC_SUBST([REPLACE_LDEXPL])
+  REPLACE_NAN=0;               AC_SUBST([REPLACE_NAN])
+  REPLACE_ROUND=0;             AC_SUBST([REPLACE_ROUND])
+  REPLACE_ROUNDF=0;            AC_SUBST([REPLACE_ROUNDF])
+  REPLACE_ROUNDL=0;            AC_SUBST([REPLACE_ROUNDL])
+  REPLACE_SIGNBIT=0;           AC_SUBST([REPLACE_SIGNBIT])
+  REPLACE_SIGNBIT_USING_GCC=0; AC_SUBST([REPLACE_SIGNBIT_USING_GCC])
+  REPLACE_TRUNCL=0;            AC_SUBST([REPLACE_TRUNCL])
+])
diff --git a/libmissing/m4/nocrash.m4 b/libmissing/m4/nocrash.m4
new file mode 100644
index 0000000..efbcfa6
--- /dev/null
+++ b/libmissing/m4/nocrash.m4
@@ -0,0 +1,102 @@
+# nocrash.m4 serial 2
+dnl Copyright (C) 2005, 2009, 2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl Based on libsigsegv, from Bruno Haible and Paolo Bonzini.
+
+AC_PREREQ([2.13])
+
+dnl Expands to some code for use in .c programs that will cause the configure
+dnl test to exit instead of crashing. This is useful to avoid triggering
+dnl action from a background debugger and to avoid core dumps.
+dnl Usage:   ...
+dnl          ]GL_NOCRASH[
+dnl          ...
+dnl          int main() { nocrash_init(); ... }
+AC_DEFUN([GL_NOCRASH],[[
+#include <stdlib.h>
+#if defined __MACH__ && defined __APPLE__
+/* Avoid a crash on MacOS X.  */
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <mach/thread_status.h>
+#include <mach/exception.h>
+#include <mach/task.h>
+#include <pthread.h>
+/* The exception port on which our thread listens.  */
+static mach_port_t our_exception_port;
+/* The main function of the thread listening for exceptions of type
+   EXC_BAD_ACCESS.  */
+static void *
+mach_exception_thread (void *arg)
+{
+  /* Buffer for a message to be received.  */
+  struct {
+    mach_msg_header_t head;
+    mach_msg_body_t msgh_body;
+    char data[1024];
+  } msg;
+  mach_msg_return_t retval;
+  /* Wait for a message on the exception port.  */
+  retval = mach_msg (&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof (msg),
+                     our_exception_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+  if (retval != MACH_MSG_SUCCESS)
+    abort ();
+  exit (1);
+}
+static void
+nocrash_init (void)
+{
+  mach_port_t self = mach_task_self ();
+  /* Allocate a port on which the thread shall listen for exceptions.  */
+  if (mach_port_allocate (self, MACH_PORT_RIGHT_RECEIVE, &our_exception_port)
+      == KERN_SUCCESS) {
+    /* See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/mach_port_insert_right.html.  */
+    if (mach_port_insert_right (self, our_exception_port, our_exception_port,
+                                MACH_MSG_TYPE_MAKE_SEND)
+        == KERN_SUCCESS) {
+      /* The exceptions we want to catch.  Only EXC_BAD_ACCESS is interesting
+         for us.  */
+      exception_mask_t mask = EXC_MASK_BAD_ACCESS;
+      /* Create the thread listening on the exception port.  */
+      pthread_attr_t attr;
+      pthread_t thread;
+      if (pthread_attr_init (&attr) == 0
+          && pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED) == 0
+          && pthread_create (&thread, &attr, mach_exception_thread, NULL) == 0) {
+        pthread_attr_destroy (&attr);
+        /* Replace the exception port info for these exceptions with our own.
+           Note that we replace the exception port for the entire task, not only
+           for a particular thread.  This has the effect that when our exception
+           port gets the message, the thread specific exception port has already
+           been asked, and we don't need to bother about it.
+           See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_set_exception_ports.html.  */
+        task_set_exception_ports (self, mask, our_exception_port,
+                                  EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
+      }
+    }
+  }
+}
+#else
+/* Avoid a crash on POSIX systems.  */
+#include <signal.h>
+/* A POSIX signal handler.  */
+static void
+exception_handler (int sig)
+{
+  exit (1);
+}
+static void
+nocrash_init (void)
+{
+#ifdef SIGSEGV
+  signal (SIGSEGV, exception_handler);
+#endif
+#ifdef SIGBUS
+  signal (SIGBUS, exception_handler);
+#endif
+}
+#endif
+]])
diff --git a/libmissing/m4/printf-frexp.m4 b/libmissing/m4/printf-frexp.m4
new file mode 100644
index 0000000..c42391a
--- /dev/null
+++ b/libmissing/m4/printf-frexp.m4
@@ -0,0 +1,45 @@
+# printf-frexp.m4 serial 3
+dnl Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl Check how to define printf_frexp() without linking with libm.
+
+AC_DEFUN([gl_FUNC_PRINTF_FREXP],
+[
+  AC_CACHE_CHECK([whether frexp can be used without linking with libm],
+    [gl_cv_func_frexp_no_libm],
+    [
+      AC_TRY_LINK([#include <math.h>
+                   double x;
+                   int y;],
+                  [return frexp (x, &y) < 1;],
+        [gl_cv_func_frexp_no_libm=yes],
+        [gl_cv_func_frexp_no_libm=no])
+    ])
+  if test $gl_cv_func_frexp_no_libm = yes; then
+    gl_FUNC_FREXP_WORKS
+    case "$gl_cv_func_frexp_works" in
+      *yes)
+        AC_DEFINE([HAVE_FREXP_IN_LIBC], [1],
+          [Define if the frexp function is available in libc.])
+        ;;
+    esac
+  fi
+
+  AC_CACHE_CHECK([whether ldexp can be used without linking with libm],
+    [gl_cv_func_ldexp_no_libm],
+    [
+      AC_TRY_LINK([#include <math.h>
+                   double x;
+                   int y;],
+                  [return ldexp (x, y) < 1;],
+        [gl_cv_func_ldexp_no_libm=yes],
+        [gl_cv_func_ldexp_no_libm=no])
+    ])
+  if test $gl_cv_func_ldexp_no_libm = yes; then
+    AC_DEFINE([HAVE_LDEXP_IN_LIBC], [1],
+      [Define if the ldexp function is available in libc.])
+  fi
+])
diff --git a/libmissing/m4/printf-frexpl.m4 b/libmissing/m4/printf-frexpl.m4
new file mode 100644
index 0000000..14ffe1f
--- /dev/null
+++ b/libmissing/m4/printf-frexpl.m4
@@ -0,0 +1,64 @@
+# printf-frexpl.m4 serial 6
+dnl Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl Check how to define printf_frexpl() without linking with libm.
+
+AC_DEFUN([gl_FUNC_PRINTF_FREXPL],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  dnl Subset of gl_FUNC_FREXPL_NO_LIBM.
+  AC_CACHE_CHECK([whether frexpl can be used without linking with libm],
+    [gl_cv_func_frexpl_no_libm],
+    [
+      AC_TRY_LINK([#include <math.h>
+                   long double x;
+                   int y;],
+                  [return frexpl (x, &y) < 1;],
+        [gl_cv_func_frexpl_no_libm=yes],
+        [gl_cv_func_frexpl_no_libm=no])
+    ])
+  if test $gl_cv_func_frexpl_no_libm = yes; then
+    gl_FUNC_FREXPL_WORKS
+    case "$gl_cv_func_frexpl_works" in
+      *yes) gl_func_frexpl_no_libm=yes ;;
+      *)    gl_func_frexpl_no_libm=no; REPLACE_FREXPL=1 ;;
+    esac
+  else
+    gl_func_frexpl_no_libm=no
+    dnl Set REPLACE_FREXPL here because the system may have frexpl in libm.
+    REPLACE_FREXPL=1
+  fi
+  if test $gl_func_frexpl_no_libm = yes; then
+    AC_DEFINE([HAVE_FREXPL_IN_LIBC], [1],
+      [Define if the frexpl function is available in libc.])
+    dnl Also check whether it's declared.
+    dnl MacOS X 10.3 has frexpl() in libc but doesn't declare it in <math.h>.
+    AC_CHECK_DECL([frexpl], , [HAVE_DECL_FREXPL=0], [#include <math.h>])
+  fi
+
+  AC_CACHE_CHECK([whether ldexpl can be used without linking with libm],
+    [gl_cv_func_ldexpl_no_libm],
+    [
+      AC_TRY_LINK([#include <math.h>
+                   long double x;
+                   int y;],
+                  [return ldexpl (x, y) < 1;],
+        [gl_cv_func_ldexpl_no_libm=yes],
+        [gl_cv_func_ldexpl_no_libm=no])
+    ])
+  if test $gl_cv_func_ldexpl_no_libm = yes; then
+    gl_FUNC_LDEXPL_WORKS
+    case "$gl_cv_func_ldexpl_works" in
+      *yes)
+        AC_DEFINE([HAVE_LDEXPL_IN_LIBC], [1],
+          [Define if the ldexpl function is available in libc.])
+        dnl Also check whether it's declared.
+        dnl MacOS X 10.3 has ldexpl() in libc but doesn't declare it in <math.h>.
+        AC_CHECK_DECL([ldexpl], , [HAVE_DECL_LDEXPL=0], [#include <math.h>])
+        ;;
+    esac
+  fi
+])
diff --git a/libmissing/m4/regex.m4 b/libmissing/m4/regex.m4
index a702252..6bd6b8f 100644
--- a/libmissing/m4/regex.m4
+++ b/libmissing/m4/regex.m4
@@ -96,6 +96,13 @@ AC_DEFUN([gl_REGEX],
             if (!s)
               return 1;
 
+            /* Ensure that [b-a] is diagnosed as invalid. */
+            re_set_syntax (RE_SYNTAX_POSIX_EGREP);
+            memset (&regex, 0, sizeof regex);
+            s = re_compile_pattern ("a[b-a]", 6, &regex);
+            if (s == 0)
+              return 1;
+
             /* This should succeed, but does not for glibc-2.1.3.  */
             memset (&regex, 0, sizeof regex);
             s = re_compile_pattern ("{1", 2, &regex);
diff --git a/libmissing/m4/signbit.m4 b/libmissing/m4/signbit.m4
new file mode 100644
index 0000000..56ff825
--- /dev/null
+++ b/libmissing/m4/signbit.m4
@@ -0,0 +1,287 @@
+# signbit.m4 serial 6
+dnl Copyright (C) 2007-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_SIGNBIT],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  AC_CACHE_CHECK([for signbit macro], [gl_cv_func_signbit],
+    [
+      AC_TRY_RUN([
+#include <math.h>
+/* If signbit is defined as a function, don't use it, since calling it for
+   'float' or 'long double' arguments would involve conversions.
+   If signbit is not declared at all but exists as a library function, don't
+   use it, since the prototype may not match.
+   If signbit is not declared at all but exists as a compiler built-in, don't
+   use it, since it's preferable to use __builtin_signbit* (no warnings,
+   no conversions).  */
+#ifndef signbit
+# error "signbit should be a macro"
+#endif
+#include <string.h>
+]gl_SIGNBIT_TEST_PROGRAM
+, [gl_cv_func_signbit=yes], [gl_cv_func_signbit=no],
+        [gl_cv_func_signbit="guessing no"])
+    ])
+  dnl GCC 4.0 and newer provides three built-ins for signbit.
+  dnl They can be used without warnings, also in C++, regardless of <math.h>.
+  dnl But they may expand to calls to functions, which may or may not be in
+  dnl libc.
+  AC_CACHE_CHECK([for signbit compiler built-ins], [gl_cv_func_signbit_gcc],
+    [
+      AC_TRY_RUN([
+#if __GNUC__ >= 4
+# define signbit(x) \
+   (sizeof (x) == sizeof (long double) ? __builtin_signbitl (x) : \
+    sizeof (x) == sizeof (double) ? __builtin_signbit (x) : \
+    __builtin_signbitf (x))
+#else
+# error "signbit should be three compiler built-ins"
+#endif
+#include <string.h>
+]gl_SIGNBIT_TEST_PROGRAM
+, [gl_cv_func_signbit_gcc=yes], [gl_cv_func_signbit_gcc=no],
+        [gl_cv_func_signbit_gcc="guessing no"])
+    ])
+  dnl Use the compiler built-ins whenever possible, because they are more
+  dnl efficient than the system library functions (if they exist).
+  if test "$gl_cv_func_signbit_gcc" = yes; then
+    REPLACE_SIGNBIT_USING_GCC=1
+  else
+    if test "$gl_cv_func_signbit" != yes; then
+      REPLACE_SIGNBIT=1
+      AC_LIBOBJ([signbitf])
+      AC_LIBOBJ([signbitd])
+      AC_LIBOBJ([signbitl])
+      gl_FLOAT_SIGN_LOCATION
+      gl_DOUBLE_SIGN_LOCATION
+      gl_LONG_DOUBLE_SIGN_LOCATION
+      if test "$gl_cv_cc_float_signbit" = unknown; then
+        dnl Test whether copysignf() is declared.
+        AC_CHECK_DECLS([copysignf], , , [#include <math.h>])
+        if test "$ac_cv_have_decl_copysignf" = yes; then
+          dnl Test whether copysignf() can be used without libm.
+          AC_CACHE_CHECK([whether copysignf can be used without linking with libm],
+            [gl_cv_func_copysignf_no_libm],
+            [
+              AC_TRY_LINK([#include <math.h>
+                           float x, y;],
+                          [return copysignf (x, y) < 0;],
+                [gl_cv_func_copysignf_no_libm=yes],
+                [gl_cv_func_copysignf_no_libm=no])
+            ])
+          if test $gl_cv_func_copysignf_no_libm = yes; then
+            AC_DEFINE([HAVE_COPYSIGNF_IN_LIBC], [1],
+              [Define if the copysignf function is declared in <math.h> and available in libc.])
+          fi
+        fi
+      fi
+      if test "$gl_cv_cc_double_signbit" = unknown; then
+        dnl Test whether copysign() is declared.
+        AC_CHECK_DECLS([copysign], , , [#include <math.h>])
+        if test "$ac_cv_have_decl_copysign" = yes; then
+          dnl Test whether copysign() can be used without libm.
+          AC_CACHE_CHECK([whether copysign can be used without linking with libm],
+            [gl_cv_func_copysign_no_libm],
+            [
+              AC_TRY_LINK([#include <math.h>
+                           double x, y;],
+                          [return copysign (x, y) < 0;],
+                [gl_cv_func_copysign_no_libm=yes],
+                [gl_cv_func_copysign_no_libm=no])
+            ])
+          if test $gl_cv_func_copysign_no_libm = yes; then
+            AC_DEFINE([HAVE_COPYSIGN_IN_LIBC], [1],
+              [Define if the copysign function is declared in <math.h> and available in libc.])
+          fi
+        fi
+      fi
+      if test "$gl_cv_cc_long_double_signbit" = unknown; then
+        dnl Test whether copysignl() is declared.
+        AC_CHECK_DECLS([copysignl], , , [#include <math.h>])
+        if test "$ac_cv_have_decl_copysignl" = yes; then
+          dnl Test whether copysignl() can be used without libm.
+          AC_CACHE_CHECK([whether copysignl can be used without linking with libm],
+            [gl_cv_func_copysignl_no_libm],
+            [
+              AC_TRY_LINK([#include <math.h>
+                           long double x, y;],
+                          [return copysignl (x, y) < 0;],
+                [gl_cv_func_copysignl_no_libm=yes],
+                [gl_cv_func_copysignl_no_libm=no])
+            ])
+          if test $gl_cv_func_copysignl_no_libm = yes; then
+            AC_DEFINE([HAVE_COPYSIGNL_IN_LIBC], [1],
+              [Define if the copysignl function is declared in <math.h> and available in libc.])
+          fi
+        fi
+      fi
+    fi
+  fi
+])
+
+AC_DEFUN([gl_SIGNBIT_TEST_PROGRAM], [[
+/* Global variables.
+   Needed because GCC 4 constant-folds __builtin_signbitl (literal)
+   but cannot constant-fold            __builtin_signbitl (variable).  */
+float vf;
+double vd;
+long double vl;
+int main ()
+{
+/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0.
+   So we use -p0f and -p0d instead.  */
+float p0f = 0.0f;
+float m0f = -p0f;
+double p0d = 0.0;
+double m0d = -p0d;
+/* On HP-UX 10.20, negating 0.0L does not yield -0.0L.
+   So we use another constant expression instead.
+   But that expression does not work on other platforms, such as when
+   cross-compiling to PowerPC on MacOS X 10.5.  */
+long double p0l = 0.0L;
+#if defined __hpux || defined __sgi
+long double m0l = -LDBL_MIN * LDBL_MIN;
+#else
+long double m0l = -p0l;
+#endif
+  if (signbit (vf))
+    vf++;
+  {
+    float plus_inf = 1.0f / p0f;
+    float minus_inf = -1.0f / p0f;
+    if (!(!signbit (255.0f)
+          && signbit (-255.0f)
+          && !signbit (p0f)
+          && (memcmp (&m0f, &p0f, sizeof (float)) == 0 || signbit (m0f))
+          && !signbit (plus_inf)
+          && signbit (minus_inf)))
+      return 1;
+  }
+  if (signbit (vd))
+    vd++;
+  {
+    double plus_inf = 1.0 / p0d;
+    double minus_inf = -1.0 / p0d;
+    if (!(!signbit (255.0)
+          && signbit (-255.0)
+          && !signbit (p0d)
+          && (memcmp (&m0d, &p0d, sizeof (double)) == 0 || signbit (m0d))
+          && !signbit (plus_inf)
+          && signbit (minus_inf)))
+      return 1;
+  }
+  if (signbit (vl))
+    vl++;
+  {
+    long double plus_inf = 1.0L / p0l;
+    long double minus_inf = -1.0L / p0l;
+    if (!(!signbit (255.0L)
+          && signbit (-255.0L)
+          && !signbit (p0l)
+          && (memcmp (&m0l, &p0l, sizeof (long double)) == 0 || signbit (m0l))
+          && !signbit (plus_inf)
+          && signbit (minus_inf)))
+      return 1;
+  }
+  return 0;
+}
+]])
+
+AC_DEFUN([gl_FLOAT_SIGN_LOCATION],
+[
+  gl_FLOATTYPE_SIGN_LOCATION([float], [gl_cv_cc_float_signbit], [f], [FLT])
+])
+
+AC_DEFUN([gl_DOUBLE_SIGN_LOCATION],
+[
+  gl_FLOATTYPE_SIGN_LOCATION([double], [gl_cv_cc_double_signbit], [], [DBL])
+])
+
+AC_DEFUN([gl_LONG_DOUBLE_SIGN_LOCATION],
+[
+  gl_FLOATTYPE_SIGN_LOCATION([long double], [gl_cv_cc_long_double_signbit], [L], [LDBL])
+])
+
+AC_DEFUN([gl_FLOATTYPE_SIGN_LOCATION],
+[
+  AC_CACHE_CHECK([where to find the sign bit in a '$1'],
+    [$2],
+    [
+      AC_TRY_RUN([
+#include <stddef.h>
+#include <stdio.h>
+#define NWORDS \
+  ((sizeof ($1) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+typedef union { $1 value; unsigned int word[NWORDS]; }
+        memory_float;
+static memory_float plus = { 1.0$3 };
+static memory_float minus = { -1.0$3 };
+int main ()
+{
+  size_t j, k, i;
+  unsigned int m;
+  FILE *fp = fopen ("conftest.out", "w");
+  if (fp == NULL)
+    return 1;
+  /* Find the different bit.  */
+  k = 0; m = 0;
+  for (j = 0; j < NWORDS; j++)
+    {
+      unsigned int x = plus.word[j] ^ minus.word[j];
+      if ((x & (x - 1)) || (x && m))
+        {
+          /* More than one bit difference.  */
+          fprintf (fp, "unknown");
+          return 1;
+        }
+      if (x)
+        {
+          k = j;
+          m = x;
+        }
+    }
+  if (m == 0)
+    {
+      /* No difference.  */
+      fprintf (fp, "unknown");
+      return 1;
+    }
+  /* Now m = plus.word[k] ^ ~minus.word[k].  */
+  if (plus.word[k] & ~minus.word[k])
+    {
+      /* Oh? The sign bit is set in the positive and cleared in the negative
+         numbers?  */
+      fprintf (fp, "unknown");
+      return 1;
+    }
+  for (i = 0; ; i++)
+    if ((m >> i) & 1)
+      break;
+  fprintf (fp, "word %d bit %d", (int) k, (int) i);
+  return (fclose (fp) != 0);
+}
+        ],
+        [$2=`cat conftest.out`],
+        [$2="unknown"],
+        [
+          dnl When cross-compiling, we don't know. It depends on the
+          dnl ABI and compiler version. There are too many cases.
+          $2="unknown"
+        ])
+      rm -f conftest.out
+    ])
+  case "$]$2[" in
+    word*bit*)
+      word=`echo "$]$2[" | sed -e 's/word //' -e 's/ bit.*//'`
+      bit=`echo "$]$2[" | sed -e 's/word.*bit //'`
+      AC_DEFINE_UNQUOTED([$4][_SIGNBIT_WORD], [$word],
+        [Define as the word index where to find the sign of '$1'.])
+      AC_DEFINE_UNQUOTED([$4][_SIGNBIT_BIT], [$bit],
+        [Define as the bit index in the word where to find the sign of '$1'.])
+      ;;
+  esac
+])
diff --git a/libmissing/m4/snprintf-posix.m4 b/libmissing/m4/snprintf-posix.m4
new file mode 100644
index 0000000..77a2481
--- /dev/null
+++ b/libmissing/m4/snprintf-posix.m4
@@ -0,0 +1,126 @@
+# snprintf-posix.m4 serial 14
+dnl Copyright (C) 2007-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_SNPRINTF_POSIX],
+[
+  AC_REQUIRE([gl_PRINTF_SIZES_C99])
+  AC_REQUIRE([gl_PRINTF_LONG_DOUBLE])
+  AC_REQUIRE([gl_PRINTF_INFINITE])
+  AC_REQUIRE([gl_PRINTF_INFINITE_LONG_DOUBLE])
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_A])
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_F])
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_N])
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_LS])
+  AC_REQUIRE([gl_PRINTF_POSITIONS])
+  AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
+  AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST])
+  AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
+  AC_REQUIRE([gl_PRINTF_PRECISION])
+  AC_REQUIRE([gl_PRINTF_ENOMEM])
+  gl_cv_func_snprintf_posix=no
+  AC_CHECK_FUNCS([snprintf])
+  if test $ac_cv_func_snprintf = yes; then
+    gl_SNPRINTF_TRUNCATION_C99
+    gl_SNPRINTF_RETVAL_C99
+    gl_SNPRINTF_DIRECTIVE_N
+    gl_SNPRINTF_SIZE1
+    gl_VSNPRINTF_ZEROSIZE_C99
+    case "$gl_cv_func_printf_sizes_c99" in
+      *yes)
+        case "$gl_cv_func_printf_long_double" in
+          *yes)
+            case "$gl_cv_func_printf_infinite" in
+              *yes)
+                case "$gl_cv_func_printf_infinite_long_double" in
+                  *yes)
+                    case "$gl_cv_func_printf_directive_a" in
+                      *yes)
+                        case "$gl_cv_func_printf_directive_f" in
+                          *yes)
+                            case "$gl_cv_func_printf_directive_n" in
+                              *yes)
+                                case "$gl_cv_func_printf_directive_ls" in
+                                  *yes)
+                                    case "$gl_cv_func_printf_positions" in
+                                      *yes)
+                                        case "$gl_cv_func_printf_flag_grouping" in
+                                          *yes)
+                                            case "$gl_cv_func_printf_flag_leftadjust" in
+                                              *yes)
+                                                case "$gl_cv_func_printf_flag_zero" in
+                                                  *yes)
+                                                    case "$gl_cv_func_printf_precision" in
+                                                      *yes)
+                                                        case "$gl_cv_func_printf_enomem" in
+                                                          *yes)
+                                                            case "$gl_cv_func_snprintf_truncation_c99" in
+                                                              *yes)
+                                                                case "$gl_cv_func_snprintf_retval_c99" in
+                                                                  *yes)
+                                                                    case "$gl_cv_func_snprintf_directive_n" in
+                                                                      *yes)
+                                                                        case "$gl_cv_func_snprintf_size1" in
+                                                                          *yes)
+                                                                            case "$gl_cv_func_vsnprintf_zerosize_c99" in
+                                                                              *yes)
+                                                                                # snprintf exists and is
+                                                                                # already POSIX compliant.
+                                                                                gl_cv_func_snprintf_posix=yes
+                                                                                ;;
+                                                                            esac
+                                                                            ;;
+                                                                        esac
+                                                                        ;;
+                                                                    esac
+                                                                    ;;
+                                                                esac
+                                                                ;;
+                                                            esac
+                                                            ;;
+                                                        esac
+                                                        ;;
+                                                    esac
+                                                    ;;
+                                                esac
+                                                ;;
+                                            esac
+                                            ;;
+                                        esac
+                                        ;;
+                                    esac
+                                    ;;
+                                esac
+                                ;;
+                            esac
+                            ;;
+                        esac
+                        ;;
+                    esac
+                    ;;
+                esac
+                ;;
+            esac
+            ;;
+        esac
+        ;;
+    esac
+  fi
+  if test $gl_cv_func_snprintf_posix = no; then
+    gl_PREREQ_VASNPRINTF_LONG_DOUBLE
+    gl_PREREQ_VASNPRINTF_INFINITE_DOUBLE
+    gl_PREREQ_VASNPRINTF_INFINITE_LONG_DOUBLE
+    gl_PREREQ_VASNPRINTF_DIRECTIVE_A
+    gl_PREREQ_VASNPRINTF_DIRECTIVE_F
+    gl_PREREQ_VASNPRINTF_DIRECTIVE_LS
+    gl_PREREQ_VASNPRINTF_FLAG_GROUPING
+    gl_PREREQ_VASNPRINTF_FLAG_LEFTADJUST
+    gl_PREREQ_VASNPRINTF_FLAG_ZERO
+    gl_PREREQ_VASNPRINTF_PRECISION
+    gl_PREREQ_VASNPRINTF_ENOMEM
+    gl_REPLACE_VASNPRINTF
+    gl_REPLACE_SNPRINTF
+  fi
+])
diff --git a/libmissing/m4/stdio_h.m4 b/libmissing/m4/stdio_h.m4
index 20af579..781fa8d 100644
--- a/libmissing/m4/stdio_h.m4
+++ b/libmissing/m4/stdio_h.m4
@@ -1,4 +1,4 @@
-# stdio_h.m4 serial 24
+# stdio_h.m4 serial 25
 dnl Copyright (C) 2007-2010 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -111,6 +111,7 @@ AC_DEFUN([gl_STDIO_H_DEFAULTS],
   REPLACE_FSEEKO=0;              AC_SUBST([REPLACE_FSEEKO])
   REPLACE_FTELL=0;               AC_SUBST([REPLACE_FTELL])
   REPLACE_FTELLO=0;              AC_SUBST([REPLACE_FTELLO])
+  REPLACE_GETDELIM=0;            AC_SUBST([REPLACE_GETDELIM])
   REPLACE_GETLINE=0;             AC_SUBST([REPLACE_GETLINE])
   REPLACE_OBSTACK_PRINTF=0;      AC_SUBST([REPLACE_OBSTACK_PRINTF])
   REPLACE_PERROR=0;              AC_SUBST([REPLACE_PERROR])
diff --git a/libmissing/m4/sys_time_h.m4 b/libmissing/m4/sys_time_h.m4
index 9c16487..b14bc4b 100644
--- a/libmissing/m4/sys_time_h.m4
+++ b/libmissing/m4/sys_time_h.m4
@@ -1,5 +1,5 @@
 # Configure a replacement for <sys/time.h>.
-# serial 2
+# serial 3
 
 # Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
@@ -19,15 +19,13 @@ AC_DEFUN([gl_HEADER_SYS_TIME_H],
 AC_DEFUN([gl_HEADER_SYS_TIME_H_BODY],
 [
   AC_REQUIRE([AC_C_RESTRICT])
+  AC_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS])
   AC_CHECK_HEADERS_ONCE([sys/time.h])
   gl_CHECK_NEXT_HEADERS([sys/time.h])
 
-  if test $ac_cv_header_sys_time_h = yes; then
-    HAVE_SYS_TIME_H=1
-  else
+  if test $ac_cv_header_sys_time_h != yes; then
     HAVE_SYS_TIME_H=0
   fi
-  AC_SUBST([HAVE_SYS_TIME_H])
 
   AC_CACHE_CHECK([for struct timeval], [gl_cv_sys_struct_timeval],
     [AC_COMPILE_IFELSE(
@@ -40,20 +38,32 @@ AC_DEFUN([gl_HEADER_SYS_TIME_H_BODY],
           [[static struct timeval x; x.tv_sec = x.tv_usec;]])],
        [gl_cv_sys_struct_timeval=yes],
        [gl_cv_sys_struct_timeval=no])])
-  if test $gl_cv_sys_struct_timeval = yes; then
-    HAVE_STRUCT_TIMEVAL=1
-  else
+  if test $gl_cv_sys_struct_timeval != yes; then
     HAVE_STRUCT_TIMEVAL=0
   fi
-  AC_SUBST([HAVE_STRUCT_TIMEVAL])
 
+  dnl Check for declarations of anything we want to poison if the
+  dnl corresponding gnulib module is not in use.
+  gl_WARN_ON_USE_PREPARE([[
+#if HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include <time.h>
+    ]], [gettimeofday])
+])
+
+AC_DEFUN([gl_SYS_TIME_MODULE_INDICATOR],
+[
+  dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
+  AC_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS])
+  GNULIB_[]m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./-],[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])=1
+])
+
+AC_DEFUN([gl_HEADER_SYS_TIME_H_DEFAULTS],
+[
+  GNULIB_GETTIMEOFDAY=0;     AC_SUBST([GNULIB_GETTIMEOFDAY])
   dnl Assume POSIX behavior unless another module says otherwise.
-  REPLACE_GETTIMEOFDAY=0
-  AC_SUBST([REPLACE_GETTIMEOFDAY])
-  if test $HAVE_SYS_TIME_H = 0 || test $HAVE_STRUCT_TIMEVAL = 0; then
-    SYS_TIME_H=sys/time.h
-  else
-    SYS_TIME_H=
-  fi
-  AC_SUBST([SYS_TIME_H])
+  HAVE_STRUCT_TIMEVAL=1;     AC_SUBST([HAVE_STRUCT_TIMEVAL])
+  HAVE_SYS_TIME_H=1;         AC_SUBST([HAVE_SYS_TIME_H])
+  REPLACE_GETTIMEOFDAY=0;    AC_SUBST([REPLACE_GETTIMEOFDAY])
 ])
diff --git a/libmissing/m4/vsnprintf-posix.m4 b/libmissing/m4/vsnprintf-posix.m4
new file mode 100644
index 0000000..1243717
--- /dev/null
+++ b/libmissing/m4/vsnprintf-posix.m4
@@ -0,0 +1,127 @@
+# vsnprintf-posix.m4 serial 14
+dnl Copyright (C) 2007-2010 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_VSNPRINTF_POSIX],
+[
+  AC_REQUIRE([gl_PRINTF_SIZES_C99])
+  AC_REQUIRE([gl_PRINTF_LONG_DOUBLE])
+  AC_REQUIRE([gl_PRINTF_INFINITE])
+  AC_REQUIRE([gl_PRINTF_INFINITE_LONG_DOUBLE])
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_A])
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_F])
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_N])
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_LS])
+  AC_REQUIRE([gl_PRINTF_POSITIONS])
+  AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
+  AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST])
+  AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
+  AC_REQUIRE([gl_PRINTF_PRECISION])
+  AC_REQUIRE([gl_PRINTF_ENOMEM])
+  gl_cv_func_vsnprintf_posix=no
+  AC_CHECK_FUNCS([vsnprintf])
+  if test $ac_cv_func_vsnprintf = yes; then
+    dnl Assume that if vsnprintf() exists, snprintf() also exists.
+    gl_SNPRINTF_TRUNCATION_C99
+    gl_SNPRINTF_RETVAL_C99
+    gl_SNPRINTF_DIRECTIVE_N
+    gl_SNPRINTF_SIZE1
+    gl_VSNPRINTF_ZEROSIZE_C99
+    case "$gl_cv_func_printf_sizes_c99" in
+      *yes)
+        case "$gl_cv_func_printf_long_double" in
+          *yes)
+            case "$gl_cv_func_printf_infinite" in
+              *yes)
+                case "$gl_cv_func_printf_infinite_long_double" in
+                  *yes)
+                    case "$gl_cv_func_printf_directive_a" in
+                      *yes)
+                        case "$gl_cv_func_printf_directive_f" in
+                          *yes)
+                            case "$gl_cv_func_printf_directive_n" in
+                              *yes)
+                                case "$gl_cv_func_printf_directive_ls" in
+                                  *yes)
+                                    case "$gl_cv_func_printf_positions" in
+                                      *yes)
+                                        case "$gl_cv_func_printf_flag_grouping" in
+                                          *yes)
+                                            case "$gl_cv_func_printf_flag_leftadjust" in
+                                              *yes)
+                                                case "$gl_cv_func_printf_flag_zero" in
+                                                  *yes)
+                                                    case "$gl_cv_func_printf_precision" in
+                                                      *yes)
+                                                        case "$gl_cv_func_printf_enomem" in
+                                                          *yes)
+                                                            case "$gl_cv_func_snprintf_truncation_c99" in
+                                                              *yes)
+                                                                case "$gl_cv_func_snprintf_retval_c99" in
+                                                                  *yes)
+                                                                    case "$gl_cv_func_snprintf_directive_n" in
+                                                                      *yes)
+                                                                        case "$gl_cv_func_snprintf_size1" in
+                                                                          *yes)
+                                                                            case "$gl_cv_func_vsnprintf_zerosize_c99" in
+                                                                              *yes)
+                                                                                # vsnprintf exists and is
+                                                                                # already POSIX compliant.
+                                                                                gl_cv_func_vsnprintf_posix=yes
+                                                                                ;;
+                                                                            esac
+                                                                            ;;
+                                                                        esac
+                                                                        ;;
+                                                                    esac
+                                                                    ;;
+                                                                esac
+                                                                ;;
+                                                            esac
+                                                            ;;
+                                                        esac
+                                                        ;;
+                                                    esac
+                                                    ;;
+                                                esac
+                                                ;;
+                                            esac
+                                            ;;
+                                        esac
+                                        ;;
+                                    esac
+                                    ;;
+                                esac
+                                ;;
+                            esac
+                            ;;
+                        esac
+                        ;;
+                    esac
+                    ;;
+                esac
+                ;;
+            esac
+            ;;
+        esac
+        ;;
+    esac
+  fi
+  if test $gl_cv_func_vsnprintf_posix = no; then
+    gl_PREREQ_VASNPRINTF_LONG_DOUBLE
+    gl_PREREQ_VASNPRINTF_INFINITE_DOUBLE
+    gl_PREREQ_VASNPRINTF_INFINITE_LONG_DOUBLE
+    gl_PREREQ_VASNPRINTF_DIRECTIVE_A
+    gl_PREREQ_VASNPRINTF_DIRECTIVE_F
+    gl_PREREQ_VASNPRINTF_DIRECTIVE_LS
+    gl_PREREQ_VASNPRINTF_FLAG_GROUPING
+    gl_PREREQ_VASNPRINTF_FLAG_LEFTADJUST
+    gl_PREREQ_VASNPRINTF_FLAG_ZERO
+    gl_PREREQ_VASNPRINTF_PRECISION
+    gl_PREREQ_VASNPRINTF_ENOMEM
+    gl_REPLACE_VASNPRINTF
+    gl_REPLACE_VSNPRINTF
+  fi
+])
diff --git a/libmissing/math.in.h b/libmissing/math.in.h
new file mode 100644
index 0000000..4ddc953
--- /dev/null
+++ b/libmissing/math.in.h
@@ -0,0 +1,633 @@
+/* A GNU-like <math.h>.
+
+   Copyright (C) 2002-2003, 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _GL_MATH_H
+
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+
+/* The include_next requires a split double-inclusion guard.  */
+#@INCLUDE_NEXT_AS_FIRST_DIRECTIVE@ @NEXT_AS_FIRST_DIRECTIVE_MATH_H@
+
+#ifndef _GL_MATH_H
+#define _GL_MATH_H
+
+
+/* The definition of _GL_ARG_NONNULL is copied here.  */
+
+/* The definition of _GL_WARN_ON_USE is copied here.  */
+
+/* Helper macros to define a portability warning for the
+   classification macro FUNC called with VALUE.  POSIX declares the
+   classification macros with an argument of real-floating (that is,
+   one of float, double, or long double).  */
+#define _GL_WARN_REAL_FLOATING_DECL(func) \
+static inline int                                                   \
+rpl_ ## func ## f (float f)                                         \
+{                                                                   \
+  return func (f);                                                  \
+}                                                                   \
+static inline int                                                   \
+rpl_ ## func ## d (double d)                                        \
+{                                                                   \
+  return func (d);                                                  \
+}                                                                   \
+static inline int                                                   \
+rpl_ ## func ## l (long double l)                                   \
+{                                                                   \
+  return func (l);                                                  \
+}                                                                   \
+_GL_WARN_ON_USE (rpl_ ## func ## f, #func " is unportable - "       \
+                 "use gnulib module " #func " for portability");    \
+_GL_WARN_ON_USE (rpl_ ## func ## d, #func " is unportable - "       \
+                 "use gnulib module " #func " for portability");    \
+_GL_WARN_ON_USE (rpl_ ## func ## l, #func " is unportable - "       \
+                 "use gnulib module " #func " for portability")
+#define _GL_WARN_REAL_FLOATING_IMPL(func, value) \
+  (sizeof (value) == sizeof (float) ? rpl_ ## func ## f (value)     \
+   : sizeof (value) == sizeof (double) ? rpl_ ## func ## d (value)  \
+   : rpl_ ## func ## l (value))
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* POSIX allows platforms that don't support NAN.  But all major
+   machines in the past 15 years have supported something close to
+   IEEE NaN, so we define this unconditionally.  We also must define
+   it on platforms like Solaris 10, where NAN is present but defined
+   as a function pointer rather than a floating point constant.  */
+#if !defined NAN || @REPLACE_NAN@
+# undef NAN
+  /* The Compaq (ex-DEC) C 6.4 compiler chokes on the expression 0.0 / 0.0.  */
+# ifdef __DECC
+static float
+_NaN ()
+{
+  static float zero = 0.0f;
+  return zero / zero;
+}
+#  define NAN (_NaN())
+# else
+#  define NAN (0.0f / 0.0f)
+# endif
+#endif
+
+/* Solaris 10 defines HUGE_VAL, but as a function pointer rather
+   than a floating point constant.  */
+#if @REPLACE_HUGE_VAL@
+# undef HUGE_VAL
+# define HUGE_VAL (1.0 / 0.0)
+#endif
+
+/* Write x as
+     x = mantissa * 2^exp
+   where
+     If x finite and nonzero: 0.5 <= |mantissa| < 1.0.
+     If x is zero: mantissa = x, exp = 0.
+     If x is infinite or NaN: mantissa = x, exp unspecified.
+   Store exp in *EXPPTR and return mantissa.  */
+#if @GNULIB_FREXP@
+# if @REPLACE_FREXP@
+#  define frexp rpl_frexp
+extern double frexp (double x, int *expptr) _GL_ARG_NONNULL ((2));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef frexp
+/* Assume frexp is always declared.  */
+_GL_WARN_ON_USE (frexp, "frexp is unportable - "
+                 "use gnulib module frexp for portability");
+#endif
+
+
+#if @GNULIB_ACOSL@
+# if !@HAVE_ACOSL@ || !@HAVE_DECL_ACOSL@
+extern long double acosl (long double x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef acosl
+# if HAVE_RAW_DECL_ACOSL
+_GL_WARN_ON_USE (acosl, "acosl is unportable - "
+                 "use gnulib module mathl for portability");
+# endif
+#endif
+
+
+#if @GNULIB_ASINL@
+# if !@HAVE_ASINL@ || !@HAVE_DECL_ASINL@
+extern long double asinl (long double x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef asinl
+# if HAVE_RAW_DECL_ASINL
+_GL_WARN_ON_USE (asinl, "asinl is unportable - "
+                 "use gnulib module mathl for portability");
+# endif
+#endif
+
+
+#if @GNULIB_ATANL@
+# if !@HAVE_ATANL@ || !@HAVE_DECL_ATANL@
+extern long double atanl (long double x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef atanl
+# if HAVE_RAW_DECL_ATANL
+_GL_WARN_ON_USE (atanl, "atanl is unportable - "
+                 "use gnulib module mathl for portability");
+# endif
+#endif
+
+
+#if @GNULIB_CEILF@
+# if @REPLACE_CEILF@
+#  define ceilf rpl_ceilf
+extern float ceilf (float x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef ceilf
+# if HAVE_RAW_DECL_CEILF
+_GL_WARN_ON_USE (ceilf, "ceilf is unportable - "
+                 "use gnulib module ceilf for portability");
+# endif
+#endif
+
+#if @GNULIB_CEILL@
+# if @REPLACE_CEILL@
+#  define ceill rpl_ceill
+extern long double ceill (long double x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef ceill
+# if HAVE_RAW_DECL_CEILL
+_GL_WARN_ON_USE (ceill, "ceill is unportable - "
+                 "use gnulib module ceill for portability");
+# endif
+#endif
+
+
+#if @GNULIB_COSL@
+# if !@HAVE_COSL@
+#  undef cosl
+#  define cosl rpl_cosl
+# endif
+# if !@HAVE_COSL@ || !@HAVE_DECL_COSL@
+extern long double cosl (long double x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef cosl
+# if HAVE_RAW_DECL_COSL
+_GL_WARN_ON_USE (cosl, "cosl is unportable - "
+                 "use gnulib module mathl for portability");
+# endif
+#endif
+
+
+#if @GNULIB_EXPL@
+# if !@HAVE_EXPL@ || !@HAVE_DECL_EXPL@
+extern long double expl (long double x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef expl
+# if HAVE_RAW_DECL_EXPL
+_GL_WARN_ON_USE (expl, "expl is unportable - "
+                 "use gnulib module mathl for portability");
+# endif
+#endif
+
+
+#if @GNULIB_FLOORF@
+# if @REPLACE_FLOORF@
+#  define floorf rpl_floorf
+extern float floorf (float x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef floorf
+# if HAVE_RAW_DECL_FLOORF
+_GL_WARN_ON_USE (floorf, "floorf is unportable - "
+                 "use gnulib module floorf for portability");
+# endif
+#endif
+
+#if @GNULIB_FLOORL@
+# if @REPLACE_FLOORL@
+#  define floorl rpl_floorl
+extern long double floorl (long double x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef floorl
+# if HAVE_RAW_DECL_FLOORL
+_GL_WARN_ON_USE (floorl, "floorl is unportable - "
+                 "use gnulib module floorl for portability");
+# endif
+#endif
+
+
+/* Write x as
+     x = mantissa * 2^exp
+   where
+     If x finite and nonzero: 0.5 <= |mantissa| < 1.0.
+     If x is zero: mantissa = x, exp = 0.
+     If x is infinite or NaN: mantissa = x, exp unspecified.
+   Store exp in *EXPPTR and return mantissa.  */
+#if @GNULIB_FREXPL@ && @REPLACE_FREXPL@
+# define frexpl rpl_frexpl
+#endif
+#if (@GNULIB_FREXPL@ && @REPLACE_FREXPL@) || !@HAVE_DECL_FREXPL@
+extern long double frexpl (long double x, int *expptr) _GL_ARG_NONNULL ((2));
+#endif
+#if !@GNULIB_FREXPL@ && defined GNULIB_POSIXCHECK
+# undef frexpl
+# if HAVE_RAW_DECL_FREXPL
+_GL_WARN_ON_USE (frexpl, "frexpl is unportable - "
+                 "use gnulib module frexpl for portability");
+# endif
+#endif
+
+
+/* Return x * 2^exp.  */
+#if @GNULIB_LDEXPL@ && @REPLACE_LDEXPL@
+# define ldexpl rpl_ldexpl
+#endif
+#if (@GNULIB_LDEXPL@ && @REPLACE_LDEXPL@) || !@HAVE_DECL_LDEXPL@
+extern long double ldexpl (long double x, int exp);
+#endif
+#if !@GNULIB_LDEXPL@ && defined GNULIB_POSIXCHECK
+# undef ldexpl
+# if HAVE_RAW_DECL_LDEXPL
+_GL_WARN_ON_USE (ldexpl, "ldexpl is unportable - "
+                 "use gnulib module ldexpl for portability");
+# endif
+#endif
+
+
+#if @GNULIB_LOGL@
+# if !@HAVE_LOGL@
+#  undef logl
+#  define logl rpl_logl
+# endif
+# if !@HAVE_LOGL@ || !@HAVE_DECL_LOGL@
+extern long double logl (long double x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef logl
+# if HAVE_RAW_DECL_LOGL
+_GL_WARN_ON_USE (logl, "logl is unportable - "
+                 "use gnulib module mathl for portability");
+# endif
+#endif
+
+
+#if @GNULIB_ROUNDF@
+# if @REPLACE_ROUNDF@
+#  undef roundf
+#  define roundf rpl_roundf
+extern float roundf (float x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef roundf
+# if HAVE_RAW_DECL_ROUNDF
+_GL_WARN_ON_USE (roundf, "roundf is unportable - "
+                 "use gnulib module roundf for portability");
+# endif
+#endif
+
+#if @GNULIB_ROUND@
+# if @REPLACE_ROUND@
+#  undef round
+#  define round rpl_round
+extern double round (double x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef round
+# if HAVE_RAW_DECL_ROUND
+_GL_WARN_ON_USE (round, "round is unportable - "
+                 "use gnulib module round for portability");
+# endif
+#endif
+
+#if @GNULIB_ROUNDL@
+# if @REPLACE_ROUNDL@
+#  undef roundl
+#  define roundl rpl_roundl
+extern long double roundl (long double x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef roundl
+# if HAVE_RAW_DECL_ROUNDL
+_GL_WARN_ON_USE (roundl, "roundl is unportable - "
+                 "use gnulib module roundl for portability");
+# endif
+#endif
+
+
+#if @GNULIB_SINL@
+# if !@HAVE_SINL@
+#  undef sinl
+#  define sinl rpl_sinl
+# endif
+# if !@HAVE_SINL@ || !@HAVE_DECL_SINL@
+extern long double sinl (long double x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef sinl
+# if HAVE_RAW_DECL_SINL
+_GL_WARN_ON_USE (sinl, "sinl is unportable - "
+                 "use gnulib module mathl for portability");
+# endif
+#endif
+
+
+#if @GNULIB_SQRTL@
+# if !@HAVE_SQRTL@ || !@HAVE_DECL_SQRTL@
+extern long double sqrtl (long double x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef sqrtl
+# if HAVE_RAW_DECL_SQRTL
+_GL_WARN_ON_USE (sqrtl, "sqrtl is unportable - "
+                 "use gnulib module mathl for portability");
+# endif
+#endif
+
+
+#if @GNULIB_TANL@
+# if !@HAVE_TANL@ || !@HAVE_DECL_TANL@
+extern long double tanl (long double x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef tanl
+# if HAVE_RAW_DECL_TANL
+_GL_WARN_ON_USE (tanl, "tanl is unportable - "
+                 "use gnulib module mathl for portability");
+# endif
+#endif
+
+
+#if @GNULIB_TRUNCF@
+# if !@HAVE_DECL_TRUNCF@
+#  define truncf rpl_truncf
+extern float truncf (float x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef truncf
+# if HAVE_RAW_DECL_TRUNCF
+_GL_WARN_ON_USE (truncf, "truncf is unportable - "
+                 "use gnulib module truncf for portability");
+# endif
+#endif
+
+#if @GNULIB_TRUNC@
+# if !@HAVE_DECL_TRUNC@
+#  define trunc rpl_trunc
+extern double trunc (double x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef trunc
+# if HAVE_RAW_DECL_TRUNC
+_GL_WARN_ON_USE (trunc, "trunc is unportable - "
+                 "use gnulib module trunc for portability");
+# endif
+#endif
+
+#if @GNULIB_TRUNCL@
+# if @REPLACE_TRUNCL@
+#  undef truncl
+#  define truncl rpl_truncl
+extern long double truncl (long double x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef truncl
+# if HAVE_RAW_DECL_TRUNCL
+_GL_WARN_ON_USE (truncl, "truncl is unportable - "
+                 "use gnulib module truncl for portability");
+# endif
+#endif
+
+
+#if @GNULIB_ISFINITE@
+# if @REPLACE_ISFINITE@
+extern int gl_isfinitef (float x);
+extern int gl_isfinited (double x);
+extern int gl_isfinitel (long double x);
+#  undef isfinite
+#  define isfinite(x) \
+   (sizeof (x) == sizeof (long double) ? gl_isfinitel (x) : \
+    sizeof (x) == sizeof (double) ? gl_isfinited (x) : \
+    gl_isfinitef (x))
+# endif
+#elif defined GNULIB_POSIXCHECK
+# if defined isfinite
+_GL_WARN_REAL_FLOATING_DECL (isfinite);
+#  undef isfinite
+#  define isfinite(x) _GL_WARN_REAL_FLOATING_IMPL (isfinite, x)
+# endif
+#endif
+
+
+#if @GNULIB_ISINF@
+# if @REPLACE_ISINF@
+extern int gl_isinff (float x);
+extern int gl_isinfd (double x);
+extern int gl_isinfl (long double x);
+#  undef isinf
+#  define isinf(x) \
+   (sizeof (x) == sizeof (long double) ? gl_isinfl (x) : \
+    sizeof (x) == sizeof (double) ? gl_isinfd (x) : \
+    gl_isinff (x))
+# endif
+#elif defined GNULIB_POSIXCHECK
+# if defined isinf
+_GL_WARN_REAL_FLOATING_DECL (isinf);
+#  undef isinf
+#  define isinf(x) _GL_WARN_REAL_FLOATING_IMPL (isinf, x)
+# endif
+#endif
+
+
+#if @GNULIB_ISNANF@
+/* Test for NaN for 'float' numbers.  */
+# if @HAVE_ISNANF@
+/* The original <math.h> included above provides a declaration of isnan macro
+   or (older) isnanf function.  */
+#  if __GNUC__ >= 4
+    /* GCC 4.0 and newer provides three built-ins for isnan.  */
+#   undef isnanf
+#   define isnanf(x) __builtin_isnanf ((float)(x))
+#  elif defined isnan
+#   undef isnanf
+#   define isnanf(x) isnan ((float)(x))
+#  endif
+# else
+/* Test whether X is a NaN.  */
+#  undef isnanf
+#  define isnanf rpl_isnanf
+extern int isnanf (float x);
+# endif
+#endif
+
+#if @GNULIB_ISNAND@
+/* Test for NaN for 'double' numbers.
+   This function is a gnulib extension, unlike isnan() which applied only
+   to 'double' numbers earlier but now is a type-generic macro.  */
+# if @HAVE_ISNAND@
+/* The original <math.h> included above provides a declaration of isnan macro.  */
+#  if __GNUC__ >= 4
+    /* GCC 4.0 and newer provides three built-ins for isnan.  */
+#   undef isnand
+#   define isnand(x) __builtin_isnan ((double)(x))
+#  else
+#   undef isnand
+#   define isnand(x) isnan ((double)(x))
+#  endif
+# else
+/* Test whether X is a NaN.  */
+#  undef isnand
+#  define isnand rpl_isnand
+extern int isnand (double x);
+# endif
+#endif
+
+#if @GNULIB_ISNANL@
+/* Test for NaN for 'long double' numbers.  */
+# if @HAVE_ISNANL@
+/* The original <math.h> included above provides a declaration of isnan macro or (older) isnanl function.  */
+#  if __GNUC__ >= 4
+    /* GCC 4.0 and newer provides three built-ins for isnan.  */
+#   undef isnanl
+#   define isnanl(x) __builtin_isnanl ((long double)(x))
+#  elif defined isnan
+#   undef isnanl
+#   define isnanl(x) isnan ((long double)(x))
+#  endif
+# else
+/* Test whether X is a NaN.  */
+#  undef isnanl
+#  define isnanl rpl_isnanl
+extern int isnanl (long double x);
+# endif
+#endif
+
+/* This must come *after* the snippets for GNULIB_ISNANF and GNULIB_ISNANL!  */
+#if @GNULIB_ISNAN@
+# if @REPLACE_ISNAN@
+/* We can't just use the isnanf macro (e.g.) as exposed by
+   isnanf.h (e.g.) here, because those may end up being macros
+   that recursively expand back to isnan.  So use the gnulib
+   replacements for them directly. */
+#  if @HAVE_ISNANF@ && __GNUC__ >= 4
+#   define gl_isnan_f(x) __builtin_isnan ((float)(x))
+#  else
+extern int rpl_isnanf (float x);
+#   define gl_isnan_f(x) rpl_isnanf (x)
+#  endif
+#  if @HAVE_ISNAND@ && __GNUC__ >= 4
+#   define gl_isnan_d(x) __builtin_isnan ((double)(x))
+#  else
+extern int rpl_isnand (double x);
+#   define gl_isnan_d(x) rpl_isnand (x)
+#  endif
+#  if @HAVE_ISNANL@ && __GNUC__ >= 4
+#   define gl_isnan_l(x) __builtin_isnan ((long double)(x))
+#  else
+extern int rpl_isnanl (long double x);
+#   define gl_isnan_l(x) rpl_isnanl (x)
+#  endif
+#  undef isnan
+#  define isnan(x) \
+   (sizeof (x) == sizeof (long double) ? gl_isnan_l (x) : \
+    sizeof (x) == sizeof (double) ? gl_isnan_d (x) : \
+    gl_isnan_f (x))
+# endif
+#elif defined GNULIB_POSIXCHECK
+# if defined isnan
+_GL_WARN_REAL_FLOATING_DECL (isnan);
+#  undef isnan
+#  define isnan(x) _GL_WARN_REAL_FLOATING_IMPL (isnan, x)
+# endif
+#endif
+
+
+#if @GNULIB_SIGNBIT@
+# if @REPLACE_SIGNBIT_USING_GCC@
+#  undef signbit
+   /* GCC 4.0 and newer provides three built-ins for signbit.  */
+#  define signbit(x) \
+   (sizeof (x) == sizeof (long double) ? __builtin_signbitl (x) : \
+    sizeof (x) == sizeof (double) ? __builtin_signbit (x) : \
+    __builtin_signbitf (x))
+# endif
+# if @REPLACE_SIGNBIT@
+#  undef signbit
+extern int gl_signbitf (float arg);
+extern int gl_signbitd (double arg);
+extern int gl_signbitl (long double arg);
+#  if __GNUC__ >= 2 && !__STRICT_ANSI__
+#   if defined FLT_SIGNBIT_WORD && defined FLT_SIGNBIT_BIT && !defined gl_signbitf
+#    define gl_signbitf_OPTIMIZED_MACRO
+#    define gl_signbitf(arg) \
+       ({ union { float _value;                                         \
+                  unsigned int _word[(sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int)]; \
+                } _m;                                                   \
+          _m._value = (arg);                                            \
+          (_m._word[FLT_SIGNBIT_WORD] >> FLT_SIGNBIT_BIT) & 1;          \
+        })
+#   endif
+#   if defined DBL_SIGNBIT_WORD && defined DBL_SIGNBIT_BIT && !defined gl_signbitd
+#    define gl_signbitd_OPTIMIZED_MACRO
+#    define gl_signbitd(arg) \
+       ({ union { double _value;                                                \
+                  unsigned int _word[(sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)]; \
+                } _m;                                                   \
+          _m._value = (arg);                                            \
+          (_m._word[DBL_SIGNBIT_WORD] >> DBL_SIGNBIT_BIT) & 1;          \
+        })
+#   endif
+#   if defined LDBL_SIGNBIT_WORD && defined LDBL_SIGNBIT_BIT && !defined gl_signbitl
+#    define gl_signbitl_OPTIMIZED_MACRO
+#    define gl_signbitl(arg) \
+       ({ union { long double _value;                                   \
+                  unsigned int _word[(sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)]; \
+                } _m;                                                   \
+          _m._value = (arg);                                            \
+          (_m._word[LDBL_SIGNBIT_WORD] >> LDBL_SIGNBIT_BIT) & 1;                \
+        })
+#   endif
+#  endif
+#  define signbit(x) \
+   (sizeof (x) == sizeof (long double) ? gl_signbitl (x) : \
+    sizeof (x) == sizeof (double) ? gl_signbitd (x) : \
+    gl_signbitf (x))
+# endif
+#elif defined GNULIB_POSIXCHECK
+# if defined signbit
+_GL_WARN_REAL_FLOATING_DECL (signbit);
+#  undef signbit
+#  define signbit(x) _GL_WARN_REAL_FLOATING_IMPL (signbit, x)
+# endif
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GL_MATH_H */
+#endif /* _GL_MATH_H */
diff --git a/libmissing/printf-frexp.c b/libmissing/printf-frexp.c
new file mode 100644
index 0000000..cf6efdb
--- /dev/null
+++ b/libmissing/printf-frexp.c
@@ -0,0 +1,188 @@
+/* Split a double into fraction and mantissa, for hexadecimal printf.
+   Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#ifdef USE_LONG_DOUBLE
+# include "printf-frexpl.h"
+#else
+# include "printf-frexp.h"
+#endif
+
+#include <float.h>
+#include <math.h>
+#ifdef USE_LONG_DOUBLE
+# include "fpucw.h"
+#endif
+
+/* This file assumes FLT_RADIX = 2.  If FLT_RADIX is a power of 2 greater
+   than 2, or not even a power of 2, some rounding errors can occur, so that
+   then the returned mantissa is only guaranteed to be <= 2.0, not < 2.0.  */
+
+#ifdef USE_LONG_DOUBLE
+# define FUNC printf_frexpl
+# define DOUBLE long double
+# define MIN_EXP LDBL_MIN_EXP
+# if HAVE_FREXPL_IN_LIBC && HAVE_LDEXPL_IN_LIBC
+#  define USE_FREXP_LDEXP
+#  define FREXP frexpl
+#  define LDEXP ldexpl
+# endif
+# define DECL_ROUNDING DECL_LONG_DOUBLE_ROUNDING
+# define BEGIN_ROUNDING() BEGIN_LONG_DOUBLE_ROUNDING ()
+# define END_ROUNDING() END_LONG_DOUBLE_ROUNDING ()
+# define L_(literal) literal##L
+#else
+# define FUNC printf_frexp
+# define DOUBLE double
+# define MIN_EXP DBL_MIN_EXP
+# if HAVE_FREXP_IN_LIBC && HAVE_LDEXP_IN_LIBC
+#  define USE_FREXP_LDEXP
+#  define FREXP frexp
+#  define LDEXP ldexp
+# endif
+# define DECL_ROUNDING
+# define BEGIN_ROUNDING()
+# define END_ROUNDING()
+# define L_(literal) literal
+#endif
+
+DOUBLE
+FUNC (DOUBLE x, int *expptr)
+{
+  int exponent;
+  DECL_ROUNDING
+
+  BEGIN_ROUNDING ();
+
+#ifdef USE_FREXP_LDEXP
+  /* frexp and ldexp are usually faster than the loop below.  */
+  x = FREXP (x, &exponent);
+
+  x = x + x;
+  exponent -= 1;
+
+  if (exponent < MIN_EXP - 1)
+    {
+      x = LDEXP (x, exponent - (MIN_EXP - 1));
+      exponent = MIN_EXP - 1;
+    }
+#else
+  {
+    /* Since the exponent is an 'int', it fits in 64 bits.  Therefore the
+       loops are executed no more than 64 times.  */
+    DOUBLE pow2[64]; /* pow2[i] = 2^2^i */
+    DOUBLE powh[64]; /* powh[i] = 2^-2^i */
+    int i;
+
+    exponent = 0;
+    if (x >= L_(1.0))
+      {
+        /* A nonnegative exponent.  */
+        {
+          DOUBLE pow2_i; /* = pow2[i] */
+          DOUBLE powh_i; /* = powh[i] */
+
+          /* Invariants: pow2_i = 2^2^i, powh_i = 2^-2^i,
+             x * 2^exponent = argument, x >= 1.0.  */
+          for (i = 0, pow2_i = L_(2.0), powh_i = L_(0.5);
+               ;
+               i++, pow2_i = pow2_i * pow2_i, powh_i = powh_i * powh_i)
+            {
+              if (x >= pow2_i)
+                {
+                  exponent += (1 << i);
+                  x *= powh_i;
+                }
+              else
+                break;
+
+              pow2[i] = pow2_i;
+              powh[i] = powh_i;
+            }
+        }
+        /* Here 1.0 <= x < 2^2^i.  */
+      }
+    else
+      {
+        /* A negative exponent.  */
+        {
+          DOUBLE pow2_i; /* = pow2[i] */
+          DOUBLE powh_i; /* = powh[i] */
+
+          /* Invariants: pow2_i = 2^2^i, powh_i = 2^-2^i,
+             x * 2^exponent = argument, x < 1.0, exponent >= MIN_EXP - 1.  */
+          for (i = 0, pow2_i = L_(2.0), powh_i = L_(0.5);
+               ;
+               i++, pow2_i = pow2_i * pow2_i, powh_i = powh_i * powh_i)
+            {
+              if (exponent - (1 << i) < MIN_EXP - 1)
+                break;
+
+              exponent -= (1 << i);
+              x *= pow2_i;
+              if (x >= L_(1.0))
+                break;
+
+              pow2[i] = pow2_i;
+              powh[i] = powh_i;
+            }
+        }
+        /* Here either x < 1.0 and exponent - 2^i < MIN_EXP - 1 <= exponent,
+           or 1.0 <= x < 2^2^i and exponent >= MIN_EXP - 1.  */
+
+        if (x < L_(1.0))
+          /* Invariants: x * 2^exponent = argument, x < 1.0 and
+             exponent - 2^i < MIN_EXP - 1 <= exponent.  */
+          while (i > 0)
+            {
+              i--;
+              if (exponent - (1 << i) >= MIN_EXP - 1)
+                {
+                  exponent -= (1 << i);
+                  x *= pow2[i];
+                  if (x >= L_(1.0))
+                    break;
+                }
+            }
+
+        /* Here either x < 1.0 and exponent = MIN_EXP - 1,
+           or 1.0 <= x < 2^2^i and exponent >= MIN_EXP - 1.  */
+      }
+
+    /* Invariants: x * 2^exponent = argument, and
+       either x < 1.0 and exponent = MIN_EXP - 1,
+       or 1.0 <= x < 2^2^i and exponent >= MIN_EXP - 1.  */
+    while (i > 0)
+      {
+        i--;
+        if (x >= pow2[i])
+          {
+            exponent += (1 << i);
+            x *= powh[i];
+          }
+      }
+    /* Here either x < 1.0 and exponent = MIN_EXP - 1,
+       or 1.0 <= x < 2.0 and exponent >= MIN_EXP - 1.  */
+  }
+#endif
+
+  END_ROUNDING ();
+
+  *expptr = exponent;
+  return x;
+}
diff --git a/libmissing/printf-frexp.h b/libmissing/printf-frexp.h
new file mode 100644
index 0000000..1cbb096
--- /dev/null
+++ b/libmissing/printf-frexp.h
@@ -0,0 +1,23 @@
+/* Split a double into fraction and mantissa, for hexadecimal printf.
+   Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Write a finite, positive number x as
+     x = mantissa * 2^exp
+   where exp >= DBL_MIN_EXP - 1,
+         mantissa < 2.0,
+         if x is not a denormalized number then mantissa >= 1.0.
+   Store exp in *EXPPTR and return mantissa.  */
+extern double printf_frexp (double x, int *expptr);
diff --git a/libmissing/printf-frexpl.c b/libmissing/printf-frexpl.c
new file mode 100644
index 0000000..6ee1e9b
--- /dev/null
+++ b/libmissing/printf-frexpl.c
@@ -0,0 +1,18 @@
+/* Split a 'long double' into fraction and mantissa, for hexadecimal printf.
+   Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#define USE_LONG_DOUBLE
+#include "printf-frexp.c"
diff --git a/libmissing/printf-frexpl.h b/libmissing/printf-frexpl.h
new file mode 100644
index 0000000..4783bbb
--- /dev/null
+++ b/libmissing/printf-frexpl.h
@@ -0,0 +1,23 @@
+/* Split a 'long double' into fraction and mantissa, for hexadecimal printf.
+   Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Write a finite, positive number x as
+     x = mantissa * 2^exp
+   where exp >= LDBL_MIN_EXP - 1,
+         mantissa < 2.0,
+         if x is not a denormalized number then mantissa >= 1.0.
+   Store exp in *EXPPTR and return mantissa.  */
+extern long double printf_frexpl (long double x, int *expptr);
diff --git a/libmissing/regcomp.c b/libmissing/regcomp.c
index f8c4aaa..fd1cc69 100644
--- a/libmissing/regcomp.c
+++ b/libmissing/regcomp.c
@@ -1021,11 +1021,10 @@ create_initial_state (re_dfa_t *dfa)
 	    Idx dest_idx = dfa->edests[node_idx].elems[0];
 	    if (!re_node_set_contains (&init_nodes, dest_idx))
 	      {
-		reg_errcode_t err = re_node_set_merge (&init_nodes,
-						       dfa->eclosures
-						       + dest_idx);
-		if (err != REG_NOERROR)
-		  return err;
+		reg_errcode_t merge_err
+                  = re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx);
+		if (merge_err != REG_NOERROR)
+		  return merge_err;
 		i = 0;
 	      }
 	  }
@@ -2578,10 +2577,14 @@ parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa,
   if (BE (tree == NULL, 0))
     goto parse_dup_op_espace;
 
+/* From gnulib's "intprops.h":
+   True if the arithmetic type T is signed.  */
+#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+
   /* This loop is actually executed only when end != REG_MISSING,
      to rewrite <re>{0,n} as (<re>(<re>...<re>?)?)?...  We have
      already created the start+1-th copy.  */
-  if ((Idx) -1 < 0 || end != REG_MISSING)
+  if (TYPE_SIGNED (Idx) || end != REG_MISSING)
     for (i = start + 2; i <= end; ++i)
       {
 	elem = duplicate_tree (elem, dfa);
diff --git a/libmissing/signbitd.c b/libmissing/signbitd.c
new file mode 100644
index 0000000..d0fb4a9
--- /dev/null
+++ b/libmissing/signbitd.c
@@ -0,0 +1,64 @@
+/* signbit() macro: Determine the sign bit of a floating-point number.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <math.h>
+
+#include <string.h>
+#include "isnand-nolibm.h"
+#include "float+.h"
+
+#ifdef gl_signbitd_OPTIMIZED_MACRO
+# undef gl_signbitd
+#endif
+
+int
+gl_signbitd (double arg)
+{
+#if defined DBL_SIGNBIT_WORD && defined DBL_SIGNBIT_BIT
+  /* The use of a union to extract the bits of the representation of a
+     'long double' is safe in practice, despite of the "aliasing rules" of
+     C99, because the GCC docs say
+       "Even with '-fstrict-aliasing', type-punning is allowed, provided the
+        memory is accessed through the union type."
+     and similarly for other compilers.  */
+# define NWORDS \
+    ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+  union { double value; unsigned int word[NWORDS]; } m;
+  m.value = arg;
+  return (m.word[DBL_SIGNBIT_WORD] >> DBL_SIGNBIT_BIT) & 1;
+#elif HAVE_COPYSIGN_IN_LIBC
+  return copysign (1.0, arg) < 0;
+#else
+  /* This does not do the right thing for NaN, but this is irrelevant for
+     most use cases.  */
+  if (isnand (arg))
+    return 0;
+  if (arg < 0.0)
+    return 1;
+  else if (arg == 0.0)
+    {
+      /* Distinguish 0.0 and -0.0.  */
+      static double plus_zero = 0.0;
+      double arg_mem = arg;
+      return (memcmp (&plus_zero, &arg_mem, SIZEOF_DBL) != 0);
+    }
+  else
+    return 0;
+#endif
+}
diff --git a/libmissing/signbitf.c b/libmissing/signbitf.c
new file mode 100644
index 0000000..f2ef1d9
--- /dev/null
+++ b/libmissing/signbitf.c
@@ -0,0 +1,64 @@
+/* signbit() macro: Determine the sign bit of a floating-point number.
+   Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <math.h>
+
+#include <string.h>
+#include "isnanf-nolibm.h"
+#include "float+.h"
+
+#ifdef gl_signbitf_OPTIMIZED_MACRO
+# undef gl_signbitf
+#endif
+
+int
+gl_signbitf (float arg)
+{
+#if defined FLT_SIGNBIT_WORD && defined FLT_SIGNBIT_BIT
+  /* The use of a union to extract the bits of the representation of a
+     'long double' is safe in practice, despite of the "aliasing rules" of
+     C99, because the GCC docs say
+       "Even with '-fstrict-aliasing', type-punning is allowed, provided the
+        memory is accessed through the union type."
+     and similarly for other compilers.  */
+# define NWORDS \
+    ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+  union { float value; unsigned int word[NWORDS]; } m;
+  m.value = arg;
+  return (m.word[FLT_SIGNBIT_WORD] >> FLT_SIGNBIT_BIT) & 1;
+#elif HAVE_COPYSIGNF_IN_LIBC
+  return copysignf (1.0f, arg) < 0;
+#else
+  /* This does not do the right thing for NaN, but this is irrelevant for
+     most use cases.  */
+  if (isnanf (arg))
+    return 0;
+  if (arg < 0.0f)
+    return 1;
+  else if (arg == 0.0f)
+    {
+      /* Distinguish 0.0f and -0.0f.  */
+      static float plus_zero = 0.0f;
+      float arg_mem = arg;
+      return (memcmp (&plus_zero, &arg_mem, SIZEOF_FLT) != 0);
+    }
+  else
+    return 0;
+#endif
+}
diff --git a/libmissing/signbitl.c b/libmissing/signbitl.c
new file mode 100644
index 0000000..adcb71e
--- /dev/null
+++ b/libmissing/signbitl.c
@@ -0,0 +1,64 @@
+/* signbit() macro: Determine the sign bit of a floating-point number.
+   Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <math.h>
+
+#include <string.h>
+#include "isnanl-nolibm.h"
+#include "float+.h"
+
+#ifdef gl_signbitl_OPTIMIZED_MACRO
+# undef gl_signbitl
+#endif
+
+int
+gl_signbitl (long double arg)
+{
+#if defined LDBL_SIGNBIT_WORD && defined LDBL_SIGNBIT_BIT
+  /* The use of a union to extract the bits of the representation of a
+     'long double' is safe in practice, despite of the "aliasing rules" of
+     C99, because the GCC docs say
+       "Even with '-fstrict-aliasing', type-punning is allowed, provided the
+        memory is accessed through the union type."
+     and similarly for other compilers.  */
+# define NWORDS \
+    ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+  union { long double value; unsigned int word[NWORDS]; } m;
+  m.value = arg;
+  return (m.word[LDBL_SIGNBIT_WORD] >> LDBL_SIGNBIT_BIT) & 1;
+#elif HAVE_COPYSIGNL_IN_LIBC
+  return copysignl (1.0L, arg) < 0;
+#else
+  /* This does not do the right thing for NaN, but this is irrelevant for
+     most use cases.  */
+  if (isnanl (arg))
+    return 0;
+  if (arg < 0.0L)
+    return 1;
+  else if (arg == 0.0L)
+    {
+      /* Distinguish 0.0L and -0.0L.  */
+      static long double plus_zero = 0.0L;
+      long double arg_mem = arg;
+      return (memcmp (&plus_zero, &arg_mem, SIZEOF_LDBL) != 0);
+    }
+  else
+    return 0;
+#endif
+}
diff --git a/libmissing/stdio.in.h b/libmissing/stdio.in.h
index 5454245..f5d5d88 100644
--- a/libmissing/stdio.in.h
+++ b/libmissing/stdio.in.h
@@ -340,7 +340,11 @@ extern size_t fwrite (const void *ptr, size_t s, size_t n, FILE *stream)
 #endif
 
 #if @GNULIB_GETDELIM@
-# if !@HAVE_DECL_GETDELIM@
+# if @REPLACE_GETDELIM@
+#  undef getdelim
+#  define getdelim rpl_getdelim
+# endif
+# if !@HAVE_DECL_GETDELIM@ || @REPLACE_GETDELIM@
 /* Read input, up to (and including) the next occurrence of DELIMITER, from
    STREAM, store it in *LINEPTR (and NUL-terminate it).
    *LINEPTR is a pointer returned from malloc (or NULL), pointing to *LINESIZE
diff --git a/libmissing/sys_time.in.h b/libmissing/sys_time.in.h
index 544a725..00a497f 100644
--- a/libmissing/sys_time.in.h
+++ b/libmissing/sys_time.in.h
@@ -41,6 +41,8 @@
 
 /* The definition of _GL_ARG_NONNULL is copied here.  */
 
+/* The definition of _GL_WARN_ON_USE is copied here.  */
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -53,11 +55,19 @@ struct timeval
 };
 # endif
 
-# if @REPLACE_GETTIMEOFDAY@
-#  undef gettimeofday
-#  define gettimeofday rpl_gettimeofday
+# if @GNULIB_GETTIMEOFDAY@
+#  if @REPLACE_GETTIMEOFDAY@
+#   undef gettimeofday
+#   define gettimeofday rpl_gettimeofday
 extern int gettimeofday (struct timeval *restrict, void *restrict)
      _GL_ARG_NONNULL ((1));
+#  endif
+# elif defined GNULIB_POSIXCHECK
+#  undef gettimeofday
+#  if HAVE_RAW_DECL_GETTIMEOFDAY
+_GL_WARN_ON_USE (gettimeofday, "gettimeofday is unportable - "
+		 "use gnulib module gettimeofday for portability");
+#  endif
 # endif
 
 #ifdef __cplusplus
diff --git a/libmissing/tests/Makefile.am b/libmissing/tests/Makefile.am
index a384629..9ef6d4b 100644
--- a/libmissing/tests/Makefile.am
+++ b/libmissing/tests/Makefile.am
@@ -218,6 +218,24 @@ EXTRA_DIST += test-fopen.h test-fopen.c signature.h macros.h
 
 ## end   gnulib module fopen-tests
 
+## begin gnulib module frexp-nolibm-tests
+
+TESTS += test-frexp-nolibm
+check_PROGRAMS += test-frexp-nolibm
+test_frexp_nolibm_SOURCES = test-frexp.c
+EXTRA_DIST += test-frexp.c signature.h macros.h
+
+## end   gnulib module frexp-nolibm-tests
+
+## begin gnulib module frexpl-nolibm-tests
+
+TESTS += test-frexpl-nolibm
+check_PROGRAMS += test-frexpl-nolibm
+test_frexpl_nolibm_SOURCES = test-frexpl.c
+EXTRA_DIST += test-frexpl.c signature.h macros.h
+
+## end   gnulib module frexpl-nolibm-tests
+
 ## begin gnulib module fseeko-tests
 
 TESTS += test-fseeko.sh test-fseeko2.sh
@@ -280,6 +298,12 @@ EXTRA_DIST += signature.h test-gettimeofday.c
 
 ## end   gnulib module gettimeofday-tests
 
+## begin gnulib module ignore-value
+
+libtests_a_SOURCES += ignore-value.h
+
+## end   gnulib module ignore-value
+
 ## begin gnulib module inet_ntop-tests
 
 TESTS += test-inet_ntop
@@ -298,6 +322,33 @@ EXTRA_DIST += test-inet_pton.c signature.h macros.h
 
 ## end   gnulib module inet_pton-tests
 
+## begin gnulib module isnand-nolibm-tests
+
+TESTS += test-isnand-nolibm
+check_PROGRAMS += test-isnand-nolibm
+
+EXTRA_DIST += test-isnand-nolibm.c test-isnand.h nan.h macros.h
+
+## end   gnulib module isnand-nolibm-tests
+
+## begin gnulib module isnanf-nolibm-tests
+
+TESTS += test-isnanf-nolibm
+check_PROGRAMS += test-isnanf-nolibm
+
+EXTRA_DIST += test-isnanf-nolibm.c test-isnanf.h nan.h macros.h
+
+## end   gnulib module isnanf-nolibm-tests
+
+## begin gnulib module isnanl-nolibm-tests
+
+TESTS += test-isnanl-nolibm
+check_PROGRAMS += test-isnanl-nolibm
+
+EXTRA_DIST += test-isnanl-nolibm.c test-isnanl.h nan.h macros.h
+
+## end   gnulib module isnanl-nolibm-tests
+
 ## begin gnulib module langinfo-tests
 
 TESTS += test-langinfo
@@ -340,6 +391,14 @@ EXTRA_DIST += test-lstat.h test-lstat.c signature.h macros.h
 
 ## end   gnulib module lstat-tests
 
+## begin gnulib module math-tests
+
+TESTS += test-math
+check_PROGRAMS += test-math
+EXTRA_DIST += test-math.c
+
+## end   gnulib module math-tests
+
 ## begin gnulib module mbrtowc-tests
 
 TESTS += test-mbrtowc1.sh test-mbrtowc2.sh test-mbrtowc3.sh test-mbrtowc4.sh
@@ -440,6 +499,22 @@ EXTRA_DIST += signature.h test-poll.c
 
 ## end   gnulib module poll-tests
 
+## begin gnulib module printf-frexp-tests
+
+TESTS += test-printf-frexp
+check_PROGRAMS += test-printf-frexp
+EXTRA_DIST += test-printf-frexp.c macros.h
+
+## end   gnulib module printf-frexp-tests
+
+## begin gnulib module printf-frexpl-tests
+
+TESTS += test-printf-frexpl
+check_PROGRAMS += test-printf-frexpl
+EXTRA_DIST += test-printf-frexpl.c macros.h
+
+## end   gnulib module printf-frexpl-tests
+
 ## begin gnulib module same-inode
 
 
@@ -467,6 +542,15 @@ EXTRA_DIST += test-signal.c
 
 ## end   gnulib module signal-tests
 
+## begin gnulib module signbit-tests
+
+TESTS += test-signbit
+check_PROGRAMS += test-signbit
+
+EXTRA_DIST += test-signbit.c macros.h
+
+## end   gnulib module signbit-tests
+
 ## begin gnulib module sleep-tests
 
 TESTS += test-sleep
@@ -475,6 +559,15 @@ EXTRA_DIST += test-sleep.c signature.h macros.h
 
 ## end   gnulib module sleep-tests
 
+## begin gnulib module snprintf-posix-tests
+
+TESTS += test-snprintf-posix test-snprintf
+check_PROGRAMS += test-snprintf-posix test-snprintf
+
+EXTRA_DIST += test-snprintf-posix.c test-snprintf-posix.h test-snprintf.c nan.h signature.h macros.h
+
+## end   gnulib module snprintf-posix-tests
+
 ## begin gnulib module snprintf-tests
 
 TESTS += test-snprintf
@@ -683,6 +776,15 @@ EXTRA_DIST += test-vasnprintf.c macros.h
 
 ## end   gnulib module vasnprintf-tests
 
+## begin gnulib module vsnprintf-posix-tests
+
+TESTS += test-vsnprintf-posix test-vsnprintf
+check_PROGRAMS += test-vsnprintf-posix test-vsnprintf
+
+EXTRA_DIST += test-vsnprintf-posix.c test-snprintf-posix.h test-vsnprintf.c nan.h signature.h macros.h
+
+## end   gnulib module vsnprintf-posix-tests
+
 ## begin gnulib module vsnprintf-tests
 
 TESTS += test-vsnprintf
diff --git a/libmissing/tests/ignore-value.h b/libmissing/tests/ignore-value.h
new file mode 100644
index 0000000..2eb6918
--- /dev/null
+++ b/libmissing/tests/ignore-value.h
@@ -0,0 +1,37 @@
+/* ignore a function return without a compiler warning
+
+   Copyright (C) 2008-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Jim Meyering.  */
+
+/* Use these functions to avoid a warning when using a function declared with
+   gcc's warn_unused_result attribute, but for which you really do want to
+   ignore the result.  Traditionally, people have used a "(void)" cast to
+   indicate that a function's return value is deliberately unused.  However,
+   if the function is declared with __attribute__((warn_unused_result)),
+   gcc issues a warning even with the cast.
+
+   Caution: most of the time, you really should heed gcc's warning, and
+   check the return value.  However, in those exceptional cases in which
+   you're sure you know what you're doing, use this function.
+
+   For the record, here's one of the ignorable warnings:
+   "copy.c:233: warning: ignoring return value of 'fchown',
+   declared with attribute warn_unused_result".  */
+
+static inline void ignore_value (int i) { (void) i; }
+static inline void ignore_ptr (void* p) { (void) p; }
+/* FIXME: what about aggregate types? */
diff --git a/libmissing/tests/nan.h b/libmissing/tests/nan.h
new file mode 100644
index 0000000..611eed3
--- /dev/null
+++ b/libmissing/tests/nan.h
@@ -0,0 +1,60 @@
+/* Macros for not-a-number.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+
+/* NaNf () returns a 'float' not-a-number.  */
+
+/* The Compaq (ex-DEC) C 6.4 compiler chokes on the expression 0.0 / 0.0.  */
+#ifdef __DECC
+static float
+NaNf ()
+{
+  static float zero = 0.0f;
+  return zero / zero;
+}
+#else
+# define NaNf() (0.0f / 0.0f)
+#endif
+
+
+/* NaNd () returns a 'double' not-a-number.  */
+
+/* The Compaq (ex-DEC) C 6.4 compiler chokes on the expression 0.0 / 0.0.  */
+#ifdef __DECC
+static double
+NaNd ()
+{
+  static double zero = 0.0;
+  return zero / zero;
+}
+#else
+# define NaNd() (0.0 / 0.0)
+#endif
+
+
+/* NaNl () returns a 'long double' not-a-number.  */
+
+/* On Irix 6.5, gcc 3.4.3 can't compute compile-time NaN, and needs the
+   runtime type conversion.  */
+#ifdef __sgi
+static long double NaNl ()
+{
+  double zero = 0.0;
+  return zero / zero;
+}
+#else
+# define NaNl() (0.0L / 0.0L)
+#endif
diff --git a/libmissing/tests/test-frexp.c b/libmissing/tests/test-frexp.c
new file mode 100644
index 0000000..d5ab7e5
--- /dev/null
+++ b/libmissing/tests/test-frexp.c
@@ -0,0 +1,199 @@
+/* Test of splitting a double into fraction and mantissa.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2007.  */
+
+#include <config.h>
+
+#include <math.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (frexp, double, (double, int *));
+
+#include <float.h>
+
+#include "isnand-nolibm.h"
+#include "nan.h"
+#include "macros.h"
+
+/* Avoid some warnings from "gcc -Wshadow".
+   This file doesn't use the exp() function.  */
+#undef exp
+#define exp exponent
+
+/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0.
+   So we use -zero instead.  */
+double zero = 0.0;
+
+static double
+my_ldexp (double x, int d)
+{
+  for (; d > 0; d--)
+    x *= 2.0;
+  for (; d < 0; d++)
+    x *= 0.5;
+  return x;
+}
+
+int
+main ()
+{
+  int i;
+  /* The use of 'volatile' guarantees that excess precision bits are dropped
+     when dealing with denormalized numbers.  It is necessary on x86 systems
+     where double-floats are not IEEE compliant by default, to avoid that the
+     results become platform and compiler option dependent.  'volatile' is a
+     portable alternative to gcc's -ffloat-store option.  */
+  volatile double x;
+
+  { /* NaN.  */
+    int exp = -9999;
+    double mantissa;
+    x = NaNd ();
+    mantissa = frexp (x, &exp);
+    ASSERT (isnand (mantissa));
+  }
+
+  { /* Positive infinity.  */
+    int exp = -9999;
+    double mantissa;
+    x = 1.0 / 0.0;
+    mantissa = frexp (x, &exp);
+    ASSERT (mantissa == x);
+  }
+
+  { /* Negative infinity.  */
+    int exp = -9999;
+    double mantissa;
+    x = -1.0 / 0.0;
+    mantissa = frexp (x, &exp);
+    ASSERT (mantissa == x);
+  }
+
+  { /* Positive zero.  */
+    int exp = -9999;
+    double mantissa;
+    x = 0.0;
+    mantissa = frexp (x, &exp);
+    ASSERT (exp == 0);
+    ASSERT (mantissa == x);
+    ASSERT (!signbit (mantissa));
+  }
+
+  { /* Negative zero.  */
+    int exp = -9999;
+    double mantissa;
+    x = -zero;
+    mantissa = frexp (x, &exp);
+    ASSERT (exp == 0);
+    ASSERT (mantissa == x);
+    ASSERT (signbit (mantissa));
+  }
+
+  for (i = 1, x = 1.0; i <= DBL_MAX_EXP; i++, x *= 2.0)
+    {
+      int exp = -9999;
+      double mantissa = frexp (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == 0.5);
+    }
+  for (i = 1, x = 1.0; i >= DBL_MIN_EXP; i--, x *= 0.5)
+    {
+      int exp = -9999;
+      double mantissa = frexp (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == 0.5);
+    }
+  for (; i >= DBL_MIN_EXP - 100 && x > 0.0; i--, x *= 0.5)
+    {
+      int exp = -9999;
+      double mantissa = frexp (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == 0.5);
+    }
+
+  for (i = 1, x = -1.0; i <= DBL_MAX_EXP; i++, x *= 2.0)
+    {
+      int exp = -9999;
+      double mantissa = frexp (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == -0.5);
+    }
+  for (i = 1, x = -1.0; i >= DBL_MIN_EXP; i--, x *= 0.5)
+    {
+      int exp = -9999;
+      double mantissa = frexp (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == -0.5);
+    }
+  for (; i >= DBL_MIN_EXP - 100 && x < 0.0; i--, x *= 0.5)
+    {
+      int exp = -9999;
+      double mantissa = frexp (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == -0.5);
+    }
+
+  for (i = 1, x = 1.01; i <= DBL_MAX_EXP; i++, x *= 2.0)
+    {
+      int exp = -9999;
+      double mantissa = frexp (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == 0.505);
+    }
+  for (i = 1, x = 1.01; i >= DBL_MIN_EXP; i--, x *= 0.5)
+    {
+      int exp = -9999;
+      double mantissa = frexp (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == 0.505);
+    }
+  for (; i >= DBL_MIN_EXP - 100 && x > 0.0; i--, x *= 0.5)
+    {
+      int exp = -9999;
+      double mantissa = frexp (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa >= 0.5);
+      ASSERT (mantissa < 1.0);
+      ASSERT (mantissa == my_ldexp (x, - exp));
+    }
+
+  for (i = 1, x = 1.73205; i <= DBL_MAX_EXP; i++, x *= 2.0)
+    {
+      int exp = -9999;
+      double mantissa = frexp (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == 0.866025);
+    }
+  for (i = 1, x = 1.73205; i >= DBL_MIN_EXP; i--, x *= 0.5)
+    {
+      int exp = -9999;
+      double mantissa = frexp (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == 0.866025);
+    }
+  for (; i >= DBL_MIN_EXP - 100 && x > 0.0; i--, x *= 0.5)
+    {
+      int exp = -9999;
+      double mantissa = frexp (x, &exp);
+      ASSERT (exp == i || exp == i + 1);
+      ASSERT (mantissa >= 0.5);
+      ASSERT (mantissa < 1.0);
+      ASSERT (mantissa == my_ldexp (x, - exp));
+    }
+
+  return 0;
+}
diff --git a/libmissing/tests/test-frexpl.c b/libmissing/tests/test-frexpl.c
new file mode 100644
index 0000000..8d9d41d
--- /dev/null
+++ b/libmissing/tests/test-frexpl.c
@@ -0,0 +1,223 @@
+/* Test of splitting a 'long double' into fraction and mantissa.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2007.  */
+
+#include <config.h>
+
+#include <math.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (frexpl, long double, (long double, int *));
+
+#include <float.h>
+
+#include "fpucw.h"
+#include "isnanl-nolibm.h"
+#include "nan.h"
+#include "macros.h"
+
+/* Avoid some warnings from "gcc -Wshadow".
+   This file doesn't use the exp() function.  */
+#undef exp
+#define exp exponent
+
+/* On MIPS IRIX machines, LDBL_MIN_EXP is -1021, but the smallest reliable
+   exponent for 'long double' is -964.  Similarly, on PowerPC machines,
+   LDBL_MIN_EXP is -1021, but the smallest reliable exponent for 'long double'
+   is -968.  For exponents below that, the precision may be truncated to the
+   precision used for 'double'.  */
+#ifdef __sgi
+# define MIN_NORMAL_EXP (LDBL_MIN_EXP + 57)
+#elif defined __ppc || defined __ppc__ || defined __powerpc || defined __powerpc__
+# define MIN_NORMAL_EXP (LDBL_MIN_EXP + 53)
+#else
+# define MIN_NORMAL_EXP LDBL_MIN_EXP
+#endif
+
+/* On HP-UX 10.20, negating 0.0L does not yield -0.0L.
+   So we use minus_zero instead.
+   IRIX cc can't put -0.0L into .data, but can compute at runtime.
+   Note that the expression -LDBL_MIN * LDBL_MIN does not work on other
+   platforms, such as when cross-compiling to PowerPC on MacOS X 10.5.  */
+#if defined __hpux || defined __sgi
+static long double
+compute_minus_zero (void)
+{
+  return -LDBL_MIN * LDBL_MIN;
+}
+# define minus_zero compute_minus_zero ()
+#else
+long double minus_zero = -0.0L;
+#endif
+
+static long double
+my_ldexp (long double x, int d)
+{
+  for (; d > 0; d--)
+    x *= 2.0L;
+  for (; d < 0; d++)
+    x *= 0.5L;
+  return x;
+}
+
+int
+main ()
+{
+  int i;
+  long double x;
+  DECL_LONG_DOUBLE_ROUNDING
+
+  BEGIN_LONG_DOUBLE_ROUNDING ();
+
+  { /* NaN.  */
+    int exp = -9999;
+    long double mantissa;
+    x = NaNl ();
+    mantissa = frexpl (x, &exp);
+    ASSERT (isnanl (mantissa));
+  }
+
+  { /* Positive infinity.  */
+    int exp = -9999;
+    long double mantissa;
+    x = 1.0L / 0.0L;
+    mantissa = frexpl (x, &exp);
+    ASSERT (mantissa == x);
+  }
+
+  { /* Negative infinity.  */
+    int exp = -9999;
+    long double mantissa;
+    x = -1.0L / 0.0L;
+    mantissa = frexpl (x, &exp);
+    ASSERT (mantissa == x);
+  }
+
+  { /* Positive zero.  */
+    int exp = -9999;
+    long double mantissa;
+    x = 0.0L;
+    mantissa = frexpl (x, &exp);
+    ASSERT (exp == 0);
+    ASSERT (mantissa == x);
+    ASSERT (!signbit (mantissa));
+  }
+
+  { /* Negative zero.  */
+    int exp = -9999;
+    long double mantissa;
+    x = minus_zero;
+    mantissa = frexpl (x, &exp);
+    ASSERT (exp == 0);
+    ASSERT (mantissa == x);
+    ASSERT (signbit (mantissa));
+  }
+
+  for (i = 1, x = 1.0L; i <= LDBL_MAX_EXP; i++, x *= 2.0L)
+    {
+      int exp = -9999;
+      long double mantissa = frexpl (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == 0.5L);
+    }
+  for (i = 1, x = 1.0L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L)
+    {
+      int exp = -9999;
+      long double mantissa = frexpl (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == 0.5L);
+    }
+  for (; i >= LDBL_MIN_EXP - 100 && x > 0.0L; i--, x *= 0.5L)
+    {
+      int exp = -9999;
+      long double mantissa = frexpl (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == 0.5L);
+    }
+
+  for (i = 1, x = -1.0L; i <= LDBL_MAX_EXP; i++, x *= 2.0L)
+    {
+      int exp = -9999;
+      long double mantissa = frexpl (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == -0.5L);
+    }
+  for (i = 1, x = -1.0L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L)
+    {
+      int exp = -9999;
+      long double mantissa = frexpl (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == -0.5L);
+    }
+  for (; i >= LDBL_MIN_EXP - 100 && x < 0.0L; i--, x *= 0.5L)
+    {
+      int exp = -9999;
+      long double mantissa = frexpl (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == -0.5L);
+    }
+
+  for (i = 1, x = 1.01L; i <= LDBL_MAX_EXP; i++, x *= 2.0L)
+    {
+      int exp = -9999;
+      long double mantissa = frexpl (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == 0.505L);
+    }
+  for (i = 1, x = 1.01L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L)
+    {
+      int exp = -9999;
+      long double mantissa = frexpl (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == 0.505L);
+    }
+  for (; i >= LDBL_MIN_EXP - 100 && x > 0.0L; i--, x *= 0.5L)
+    {
+      int exp = -9999;
+      long double mantissa = frexpl (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa >= 0.5L);
+      ASSERT (mantissa < 1.0L);
+      ASSERT (mantissa == my_ldexp (x, - exp));
+    }
+
+  for (i = 1, x = 1.73205L; i <= LDBL_MAX_EXP; i++, x *= 2.0L)
+    {
+      int exp = -9999;
+      long double mantissa = frexpl (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == 0.866025L);
+    }
+  for (i = 1, x = 1.73205L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L)
+    {
+      int exp = -9999;
+      long double mantissa = frexpl (x, &exp);
+      ASSERT (exp == i);
+      ASSERT (mantissa == 0.866025L);
+    }
+  for (; i >= LDBL_MIN_EXP - 100 && x > 0.0L; i--, x *= 0.5L)
+    {
+      int exp = -9999;
+      long double mantissa = frexpl (x, &exp);
+      ASSERT (exp == i || exp == i + 1);
+      ASSERT (mantissa >= 0.5L);
+      ASSERT (mantissa < 1.0L);
+      ASSERT (mantissa == my_ldexp (x, - exp));
+    }
+
+  return 0;
+}
diff --git a/libmissing/tests/test-getdelim.c b/libmissing/tests/test-getdelim.c
index df99664..a5df49f 100644
--- a/libmissing/tests/test-getdelim.c
+++ b/libmissing/tests/test-getdelim.c
@@ -33,13 +33,13 @@ int
 main (void)
 {
   FILE *f;
-  char *line = NULL;
-  size_t len = 0;
+  char *line;
+  size_t len;
   ssize_t result;
 
   /* Create test file.  */
   f = fopen ("test-getdelim.txt", "wb");
-  if (!f || fwrite ("anbcnd\0f", 1, 8, f) != 8 || fclose (f) != 0)
+  if (!f || fwrite ("anAnbcnd\0f", 1, 10, f) != 10 || fclose (f) != 0)
     {
       fputs ("Failed to create sample file.\n", stderr);
       remove ("test-getdelim.txt");
@@ -54,13 +54,24 @@ main (void)
     }
 
   /* Test initial allocation, which must include trailing NUL.  */
+  line = NULL;
+  len = 0;
   result = getdelim (&line, &len, 'n', f);
   ASSERT (result == 2);
   ASSERT (strcmp (line, "an") == 0);
   ASSERT (2 < len);
+  free (line);
 
-  /* Test growth of buffer.  */
+  /* Test initial allocation again, with line = NULL and len != 0.  */
+  line = NULL;
+  len = (size_t)(~0) / 4;
+  result = getdelim (&line, &len, 'n', f);
+  ASSERT (result == 2);
+  ASSERT (strcmp (line, "An") == 0);
+  ASSERT (2 < len);
   free (line);
+
+  /* Test growth of buffer.  */
   line = malloc (1);
   len = 1;
   result = getdelim (&line, &len, 'n', f);
diff --git a/libmissing/tests/test-getline.c b/libmissing/tests/test-getline.c
index 7112b52..6a661ce 100644
--- a/libmissing/tests/test-getline.c
+++ b/libmissing/tests/test-getline.c
@@ -33,13 +33,13 @@ int
 main (void)
 {
   FILE *f;
-  char *line = NULL;
-  size_t len = 0;
+  char *line;
+  size_t len;
   ssize_t result;
 
   /* Create test file.  */
   f = fopen ("test-getline.txt", "wb");
-  if (!f || fwrite ("a\nbc\nd\0f", 1, 8, f) != 8 || fclose (f) != 0)
+  if (!f || fwrite ("a\nA\nbc\nd\0f", 1, 10, f) != 10 || fclose (f) != 0)
     {
       fputs ("Failed to create sample file.\n", stderr);
       remove ("test-getline.txt");
@@ -54,13 +54,24 @@ main (void)
     }
 
   /* Test initial allocation, which must include trailing NUL.  */
+  line = NULL;
+  len = 0;
   result = getline (&line, &len, f);
   ASSERT (result == 2);
   ASSERT (strcmp (line, "a\n") == 0);
   ASSERT (2 < len);
+  free (line);
 
-  /* Test growth of buffer, must not leak.  */
+  /* Test initial allocation again, with line = NULL and len != 0.  */
+  line = NULL;
+  len = (size_t)(~0) / 4;
+  result = getline (&line, &len, f);
+  ASSERT (result == 2);
+  ASSERT (strcmp (line, "A\n") == 0);
+  ASSERT (2 < len);
   free (line);
+
+  /* Test growth of buffer, must not leak.  */
   line = malloc (1);
   len = 0;
   result = getline (&line, &len, f);
diff --git a/libmissing/tests/test-gettimeofday.c b/libmissing/tests/test-gettimeofday.c
index 2a07814..ff2bc72 100644
--- a/libmissing/tests/test-gettimeofday.c
+++ b/libmissing/tests/test-gettimeofday.c
@@ -20,7 +20,8 @@
 #include <sys/time.h>
 
 #include "signature.h"
-SIGNATURE_CHECK (gettimeofday, int, (struct timeval *, void *));
+SIGNATURE_CHECK (gettimeofday, int,
+                 (struct timeval *, GETTIMEOFDAY_TIMEZONE *));
 
 #include <time.h>
 
@@ -42,8 +43,5 @@ main (void)
       fprintf (stderr, "gettimeofday still clobbers the localtime buffer!\n");
       return 1;
     }
-  else
-    {
-      return 0;
-    }
+  return 0;
 }
diff --git a/libmissing/tests/test-isnand-nolibm.c b/libmissing/tests/test-isnand-nolibm.c
new file mode 100644
index 0000000..b0ac0ba
--- /dev/null
+++ b/libmissing/tests/test-isnand-nolibm.c
@@ -0,0 +1,22 @@
+/* Test of isnand() substitute.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include "isnand-nolibm.h"
+
+#include "test-isnand.h"
+
diff --git a/libmissing/tests/test-isnand.h b/libmissing/tests/test-isnand.h
new file mode 100644
index 0000000..f986621
--- /dev/null
+++ b/libmissing/tests/test-isnand.h
@@ -0,0 +1,65 @@
+/* Test of isnand() substitute.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2007.  */
+
+#include <limits.h>
+
+#include "nan.h"
+#include "macros.h"
+
+/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0.
+   So we use -zero instead.  */
+double zero = 0.0;
+
+int
+main ()
+{
+  /* Finite values.  */
+  ASSERT (!isnand (3.141));
+  ASSERT (!isnand (3.141e30));
+  ASSERT (!isnand (3.141e-30));
+  ASSERT (!isnand (-2.718));
+  ASSERT (!isnand (-2.718e30));
+  ASSERT (!isnand (-2.718e-30));
+  ASSERT (!isnand (0.0));
+  ASSERT (!isnand (-zero));
+  /* Infinite values.  */
+  ASSERT (!isnand (1.0 / 0.0));
+  ASSERT (!isnand (-1.0 / 0.0));
+  /* Quiet NaN.  */
+  ASSERT (isnand (NaNd ()));
+#if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT
+  /* Signalling NaN.  */
+  {
+    #define NWORDS \
+      ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+    typedef union { double value; unsigned int word[NWORDS]; } memory_double;
+    memory_double m;
+    m.value = NaNd ();
+# if DBL_EXPBIT0_BIT > 0
+    m.word[DBL_EXPBIT0_WORD] ^= (unsigned int) 1 << (DBL_EXPBIT0_BIT - 1);
+# else
+    m.word[DBL_EXPBIT0_WORD + (DBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
+      ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1);
+# endif
+    m.word[DBL_EXPBIT0_WORD + (DBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
+      |= (unsigned int) 1 << DBL_EXPBIT0_BIT;
+    ASSERT (isnand (m.value));
+  }
+#endif
+  return 0;
+}
diff --git a/libmissing/tests/test-isnanf-nolibm.c b/libmissing/tests/test-isnanf-nolibm.c
new file mode 100644
index 0000000..6ac69e0
--- /dev/null
+++ b/libmissing/tests/test-isnanf-nolibm.c
@@ -0,0 +1,21 @@
+/* Test of isnanf() substitute.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include "isnanf-nolibm.h"
+
+#include "test-isnanf.h"
diff --git a/libmissing/tests/test-isnanf.h b/libmissing/tests/test-isnanf.h
new file mode 100644
index 0000000..d071b2c
--- /dev/null
+++ b/libmissing/tests/test-isnanf.h
@@ -0,0 +1,67 @@
+/* Test of isnanf() substitute.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2007.  */
+
+#include <limits.h>
+
+#include "nan.h"
+#include "macros.h"
+
+/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0f.
+   So we use -zero instead.  */
+float zero = 0.0f;
+
+int
+main ()
+{
+  /* Finite values.  */
+  ASSERT (!isnanf (3.141f));
+  ASSERT (!isnanf (3.141e30f));
+  ASSERT (!isnanf (3.141e-30f));
+  ASSERT (!isnanf (-2.718f));
+  ASSERT (!isnanf (-2.718e30f));
+  ASSERT (!isnanf (-2.718e-30f));
+  ASSERT (!isnanf (0.0f));
+  ASSERT (!isnanf (-zero));
+  /* Infinite values.  */
+  ASSERT (!isnanf (1.0f / 0.0f));
+  ASSERT (!isnanf (-1.0f / 0.0f));
+  /* Quiet NaN.  */
+  ASSERT (isnanf (NaNf ()));
+#if defined FLT_EXPBIT0_WORD && defined FLT_EXPBIT0_BIT
+  /* Signalling NaN.  */
+  {
+    #define NWORDS \
+      ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+    typedef union { float value; unsigned int word[NWORDS]; } memory_float;
+    memory_float m;
+    m.value = NaNf ();
+# if FLT_EXPBIT0_BIT > 0
+    m.word[FLT_EXPBIT0_WORD] ^= (unsigned int) 1 << (FLT_EXPBIT0_BIT - 1);
+# else
+    m.word[FLT_EXPBIT0_WORD + (FLT_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
+      ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1);
+# endif
+    if (FLT_EXPBIT0_WORD < NWORDS / 2)
+      m.word[FLT_EXPBIT0_WORD + 1] |= (unsigned int) 1 << FLT_EXPBIT0_BIT;
+    else
+      m.word[0] |= (unsigned int) 1;
+    ASSERT (isnanf (m.value));
+  }
+#endif
+  return 0;
+}
diff --git a/libmissing/tests/test-isnanl-nolibm.c b/libmissing/tests/test-isnanl-nolibm.c
new file mode 100644
index 0000000..eeca6d8
--- /dev/null
+++ b/libmissing/tests/test-isnanl-nolibm.c
@@ -0,0 +1,23 @@
+/* Test of isnanl() substitute.
+   Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2007.  */
+
+#include <config.h>
+
+#include "isnanl-nolibm.h"
+
+#include "test-isnanl.h"
diff --git a/libmissing/tests/test-isnanl.h b/libmissing/tests/test-isnanl.h
new file mode 100644
index 0000000..1665cf4
--- /dev/null
+++ b/libmissing/tests/test-isnanl.h
@@ -0,0 +1,141 @@
+/* Test of isnanl() substitute.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2007.  */
+
+#include <float.h>
+#include <limits.h>
+
+#include "nan.h"
+#include "macros.h"
+
+/* On HP-UX 10.20, negating 0.0L does not yield -0.0L.
+   So we use minus_zero instead.
+   IRIX cc can't put -0.0L into .data, but can compute at runtime.
+   Note that the expression -LDBL_MIN * LDBL_MIN does not work on other
+   platforms, such as when cross-compiling to PowerPC on MacOS X 10.5.  */
+#if defined __hpux || defined __sgi
+static long double
+compute_minus_zero (void)
+{
+  return -LDBL_MIN * LDBL_MIN;
+}
+# define minus_zero compute_minus_zero ()
+#else
+long double minus_zero = -0.0L;
+#endif
+
+int
+main ()
+{
+  #define NWORDS \
+    ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+  typedef union { unsigned int word[NWORDS]; long double value; }
+          memory_long_double;
+
+  /* Finite values.  */
+  ASSERT (!isnanl (3.141L));
+  ASSERT (!isnanl (3.141e30L));
+  ASSERT (!isnanl (3.141e-30L));
+  ASSERT (!isnanl (-2.718L));
+  ASSERT (!isnanl (-2.718e30L));
+  ASSERT (!isnanl (-2.718e-30L));
+  ASSERT (!isnanl (0.0L));
+  ASSERT (!isnanl (minus_zero));
+  /* Infinite values.  */
+  ASSERT (!isnanl (1.0L / 0.0L));
+  ASSERT (!isnanl (-1.0L / 0.0L));
+  /* Quiet NaN.  */
+  ASSERT (isnanl (NaNl ()));
+
+#if defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT
+  /* A bit pattern that is different from a Quiet NaN.  With a bit of luck,
+     it's a Signalling NaN.  */
+  {
+    memory_long_double m;
+    m.value = NaNl ();
+# if LDBL_EXPBIT0_BIT > 0
+    m.word[LDBL_EXPBIT0_WORD] ^= (unsigned int) 1 << (LDBL_EXPBIT0_BIT - 1);
+# else
+    m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
+      ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1);
+# endif
+    m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
+      |= (unsigned int) 1 << LDBL_EXPBIT0_BIT;
+    ASSERT (isnanl (m.value));
+  }
+#endif
+
+#if ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_))
+/* Representation of an 80-bit 'long double' as an initializer for a sequence
+   of 'unsigned int' words.  */
+# ifdef WORDS_BIGENDIAN
+#  define LDBL80_WORDS(exponent,manthi,mantlo) \
+     { ((unsigned int) (exponent) << 16) | ((unsigned int) (manthi) >> 16), \
+       ((unsigned int) (manthi) << 16) | (unsigned int) (mantlo) >> 16),    \
+       (unsigned int) (mantlo) << 16                                        \
+     }
+# else
+#  define LDBL80_WORDS(exponent,manthi,mantlo) \
+     { mantlo, manthi, exponent }
+# endif
+  { /* Quiet NaN.  */
+    static memory_long_double x =
+      { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) };
+    ASSERT (isnanl (x.value));
+  }
+  {
+    /* Signalling NaN.  */
+    static memory_long_double x =
+      { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) };
+    ASSERT (isnanl (x.value));
+  }
+  /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities,
+     Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in
+       Intel IA-64 Architecture Software Developer's Manual, Volume 1:
+       Application Architecture.
+       Table 5-2 "Floating-Point Register Encodings"
+       Figure 5-6 "Memory to Floating-Point Register Data Translation"
+   */
+  { /* Pseudo-NaN.  */
+    static memory_long_double x =
+      { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) };
+    ASSERT (isnanl (x.value));
+  }
+  { /* Pseudo-Infinity.  */
+    static memory_long_double x =
+      { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) };
+    ASSERT (isnanl (x.value));
+  }
+  { /* Pseudo-Zero.  */
+    static memory_long_double x =
+      { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) };
+    ASSERT (isnanl (x.value));
+  }
+  { /* Unnormalized number.  */
+    static memory_long_double x =
+      { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) };
+    ASSERT (isnanl (x.value));
+  }
+  { /* Pseudo-Denormal.  */
+    static memory_long_double x =
+      { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) };
+    ASSERT (isnanl (x.value));
+  }
+#endif
+
+  return 0;
+}
diff --git a/libmissing/tests/test-lstat.c b/libmissing/tests/test-lstat.c
index 23ffec4..b8f9237 100644
--- a/libmissing/tests/test-lstat.c
+++ b/libmissing/tests/test-lstat.c
@@ -35,6 +35,7 @@ SIGNATURE_CHECK (lstat, int, (char const *, struct stat *));
 #include <unistd.h>
 
 #include "same-inode.h"
+#include "ignore-value.h"
 #include "macros.h"
 
 #define BASE "test-lstat.t"
@@ -53,7 +54,7 @@ int
 main (void)
 {
   /* Remove any leftovers from a previous partial run.  */
-  system ("rm -rf " BASE "*");
+  ignore_value (system ("rm -rf " BASE "*"));
 
   return test_lstat_func (do_lstat, true);
 }
diff --git a/libmissing/tests/test-math.c b/libmissing/tests/test-math.c
new file mode 100644
index 0000000..f940a24
--- /dev/null
+++ b/libmissing/tests/test-math.c
@@ -0,0 +1,53 @@
+/* Test of <math.h> substitute.
+   Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2007.  */
+
+#include <config.h>
+
+#include <math.h>
+
+#ifndef NAN
+# error NAN should be defined
+choke me
+#endif
+
+#if 0
+/* Check that NAN expands into a constant expression.  */
+static float n = NAN;
+#endif
+
+/* Compare two numbers with ==.
+   This is a separate function because IRIX 6.5 "cc -O" miscompiles an
+   'x == x' test.  */
+static int
+numeric_equal (double x, double y)
+{
+  return x == y;
+}
+
+int
+main (void)
+{
+  double d = NAN;
+  double zero = 0.0;
+  if (numeric_equal (d, d))
+    return 1;
+  d = HUGE_VAL;
+  if (!numeric_equal (d, 1.0 / zero))
+    return 1;
+  return 0;
+}
diff --git a/libmissing/tests/test-poll.c b/libmissing/tests/test-poll.c
index 1fb4c7b..7488090 100644
--- a/libmissing/tests/test-poll.c
+++ b/libmissing/tests/test-poll.c
@@ -371,7 +371,7 @@ main ()
   result = test (test_connect_first, "Unconnected socket test");
   result += test (test_socket_pair, "Connected sockets test");
   result += test (test_accept_first, "General socket test with fork");
-  //result += test (test_pipe, "Pipe test");
+  result += test (test_pipe, "Pipe test");
 
   exit (result);
 }
diff --git a/libmissing/tests/test-printf-frexp.c b/libmissing/tests/test-printf-frexp.c
new file mode 100644
index 0000000..13e1c30
--- /dev/null
+++ b/libmissing/tests/test-printf-frexp.c
@@ -0,0 +1,119 @@
+/* Test of splitting a double into fraction and mantissa.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2007.  */
+
+#include <config.h>
+
+#include "printf-frexp.h"
+
+#include <float.h>
+
+#include "macros.h"
+
+static double
+my_ldexp (double x, int d)
+{
+  for (; d > 0; d--)
+    x *= 2.0;
+  for (; d < 0; d++)
+    x *= 0.5;
+  return x;
+}
+
+int
+main ()
+{
+  int i;
+  /* The use of 'volatile' guarantees that excess precision bits are dropped
+     when dealing with denormalized numbers.  It is necessary on x86 systems
+     where double-floats are not IEEE compliant by default, to avoid that the
+     results become platform and compiler option dependent.  'volatile' is a
+     portable alternative to gcc's -ffloat-store option.  */
+  volatile double x;
+
+  for (i = 1, x = 1.0; i <= DBL_MAX_EXP; i++, x *= 2.0)
+    {
+      int exp = -9999;
+      double mantissa = printf_frexp (x, &exp);
+      ASSERT (exp == i - 1);
+      ASSERT (mantissa == 1.0);
+    }
+  for (i = 1, x = 1.0; i >= DBL_MIN_EXP; i--, x *= 0.5)
+    {
+      int exp = -9999;
+      double mantissa = printf_frexp (x, &exp);
+      ASSERT (exp == i - 1);
+      ASSERT (mantissa == 1.0);
+    }
+  for (; i >= DBL_MIN_EXP - 100 && x > 0.0; i--, x *= 0.5)
+    {
+      int exp = -9999;
+      double mantissa = printf_frexp (x, &exp);
+      ASSERT (exp == DBL_MIN_EXP - 1);
+      ASSERT (mantissa == my_ldexp (1.0, i - DBL_MIN_EXP));
+    }
+
+  for (i = 1, x = 1.01; i <= DBL_MAX_EXP; i++, x *= 2.0)
+    {
+      int exp = -9999;
+      double mantissa = printf_frexp (x, &exp);
+      ASSERT (exp == i - 1);
+      ASSERT (mantissa == 1.01);
+    }
+  for (i = 1, x = 1.01; i >= DBL_MIN_EXP; i--, x *= 0.5)
+    {
+      int exp = -9999;
+      double mantissa = printf_frexp (x, &exp);
+      ASSERT (exp == i - 1);
+      ASSERT (mantissa == 1.01);
+    }
+  for (; i >= DBL_MIN_EXP - 100 && x > 0.0; i--, x *= 0.5)
+    {
+      int exp = -9999;
+      double mantissa = printf_frexp (x, &exp);
+      ASSERT (exp == DBL_MIN_EXP - 1);
+      ASSERT (mantissa >= my_ldexp (1.0, i - DBL_MIN_EXP));
+      ASSERT (mantissa <= my_ldexp (2.0, i - DBL_MIN_EXP));
+      ASSERT (mantissa == my_ldexp (x, - exp));
+    }
+
+  for (i = 1, x = 1.73205; i <= DBL_MAX_EXP; i++, x *= 2.0)
+    {
+      int exp = -9999;
+      double mantissa = printf_frexp (x, &exp);
+      ASSERT (exp == i - 1);
+      ASSERT (mantissa == 1.73205);
+    }
+  for (i = 1, x = 1.73205; i >= DBL_MIN_EXP; i--, x *= 0.5)
+    {
+      int exp = -9999;
+      double mantissa = printf_frexp (x, &exp);
+      ASSERT (exp == i - 1);
+      ASSERT (mantissa == 1.73205);
+    }
+  for (; i >= DBL_MIN_EXP - 100 && x > 0.0; i--, x *= 0.5)
+    {
+      int exp = -9999;
+      double mantissa = printf_frexp (x, &exp);
+      ASSERT (exp == DBL_MIN_EXP - 1);
+      ASSERT (mantissa >= my_ldexp (1.0, i - DBL_MIN_EXP));
+      ASSERT (mantissa <= my_ldexp (2.0, i - DBL_MIN_EXP));
+      ASSERT (mantissa == my_ldexp (x, - exp));
+    }
+
+  return 0;
+}
diff --git a/libmissing/tests/test-printf-frexpl.c b/libmissing/tests/test-printf-frexpl.c
new file mode 100644
index 0000000..6f7e4f7
--- /dev/null
+++ b/libmissing/tests/test-printf-frexpl.c
@@ -0,0 +1,134 @@
+/* Test of splitting a 'long double' into fraction and mantissa.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2007.  */
+
+#include <config.h>
+
+#include "printf-frexpl.h"
+
+#include <float.h>
+
+#include "fpucw.h"
+#include "macros.h"
+
+/* On MIPS IRIX machines, LDBL_MIN_EXP is -1021, but the smallest reliable
+   exponent for 'long double' is -964.  Similarly, on PowerPC machines,
+   LDBL_MIN_EXP is -1021, but the smallest reliable exponent for 'long double'
+   is -968.  For exponents below that, the precision may be truncated to the
+   precision used for 'double'.  */
+#ifdef __sgi
+# define MIN_NORMAL_EXP (LDBL_MIN_EXP + 57)
+# define MIN_SUBNORMAL_EXP MIN_NORMAL_EXP
+#elif defined __ppc || defined __ppc__ || defined __powerpc || defined __powerpc__
+# define MIN_NORMAL_EXP (LDBL_MIN_EXP + 53)
+# define MIN_SUBNORMAL_EXP MIN_NORMAL_EXP
+#else
+# define MIN_NORMAL_EXP LDBL_MIN_EXP
+# define MIN_SUBNORMAL_EXP (LDBL_MIN_EXP - 100)
+#endif
+
+static long double
+my_ldexp (long double x, int d)
+{
+  for (; d > 0; d--)
+    x *= 2.0L;
+  for (; d < 0; d++)
+    x *= 0.5L;
+  return x;
+}
+
+int
+main ()
+{
+  int i;
+  long double x;
+  DECL_LONG_DOUBLE_ROUNDING
+
+  BEGIN_LONG_DOUBLE_ROUNDING ();
+
+  for (i = 1, x = 1.0L; i <= LDBL_MAX_EXP; i++, x *= 2.0L)
+    {
+      int exp = -9999;
+      long double mantissa = printf_frexpl (x, &exp);
+      ASSERT (exp == i - 1);
+      ASSERT (mantissa == 1.0L);
+    }
+  for (i = 1, x = 1.0L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L)
+    {
+      int exp = -9999;
+      long double mantissa = printf_frexpl (x, &exp);
+      ASSERT (exp == i - 1);
+      ASSERT (mantissa == 1.0L);
+    }
+  for (; i >= MIN_SUBNORMAL_EXP && x > 0.0L; i--, x *= 0.5L)
+    {
+      int exp = -9999;
+      long double mantissa = printf_frexpl (x, &exp);
+      ASSERT (exp == LDBL_MIN_EXP - 1);
+      ASSERT (mantissa == my_ldexp (1.0L, i - LDBL_MIN_EXP));
+    }
+
+  for (i = 1, x = 1.01L; i <= LDBL_MAX_EXP; i++, x *= 2.0L)
+    {
+      int exp = -9999;
+      long double mantissa = printf_frexpl (x, &exp);
+      ASSERT (exp == i - 1);
+      ASSERT (mantissa == 1.01L);
+    }
+  for (i = 1, x = 1.01L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L)
+    {
+      int exp = -9999;
+      long double mantissa = printf_frexpl (x, &exp);
+      ASSERT (exp == i - 1);
+      ASSERT (mantissa == 1.01L);
+    }
+  for (; i >= MIN_SUBNORMAL_EXP && x > 0.0L; i--, x *= 0.5L)
+    {
+      int exp = -9999;
+      long double mantissa = printf_frexpl (x, &exp);
+      ASSERT (exp == LDBL_MIN_EXP - 1);
+      ASSERT (mantissa >= my_ldexp (1.0L, i - LDBL_MIN_EXP));
+      ASSERT (mantissa <= my_ldexp (2.0L, i - LDBL_MIN_EXP));
+      ASSERT (mantissa == my_ldexp (x, - exp));
+    }
+
+  for (i = 1, x = 1.73205L; i <= LDBL_MAX_EXP; i++, x *= 2.0L)
+    {
+      int exp = -9999;
+      long double mantissa = printf_frexpl (x, &exp);
+      ASSERT (exp == i - 1);
+      ASSERT (mantissa == 1.73205L);
+    }
+  for (i = 1, x = 1.73205L; i >= MIN_NORMAL_EXP; i--, x *= 0.5L)
+    {
+      int exp = -9999;
+      long double mantissa = printf_frexpl (x, &exp);
+      ASSERT (exp == i - 1);
+      ASSERT (mantissa == 1.73205L);
+    }
+  for (; i >= MIN_SUBNORMAL_EXP && x > 0.0L; i--, x *= 0.5L)
+    {
+      int exp = -9999;
+      long double mantissa = printf_frexpl (x, &exp);
+      ASSERT (exp == LDBL_MIN_EXP - 1);
+      ASSERT (mantissa >= my_ldexp (1.0L, i - LDBL_MIN_EXP));
+      ASSERT (mantissa <= my_ldexp (2.0L, i - LDBL_MIN_EXP));
+      ASSERT (mantissa == my_ldexp (x, - exp));
+    }
+
+  return 0;
+}
diff --git a/libmissing/tests/test-signbit.c b/libmissing/tests/test-signbit.c
new file mode 100644
index 0000000..9581190
--- /dev/null
+++ b/libmissing/tests/test-signbit.c
@@ -0,0 +1,197 @@
+/* Test of signbit() substitute.
+   Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2007.  */
+
+#include <config.h>
+
+#include <math.h>
+
+/* signbit must be a macro.  */
+#ifndef signbit
+# error missing declaration
+#endif
+
+#include <float.h>
+#include <limits.h>
+
+#include "macros.h"
+
+float zerof = 0.0f;
+double zerod = 0.0;
+long double zerol = 0.0L;
+
+/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0f.
+   So we use -zerof instead.  */
+
+/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0.
+   So we use -zerod instead.  */
+
+/* On HP-UX 10.20, negating 0.0L does not yield -0.0L.
+   So we use minus_zerol instead.
+   IRIX cc can't put -0.0L into .data, but can compute at runtime.
+   Note that the expression -LDBL_MIN * LDBL_MIN does not work on other
+   platforms, such as when cross-compiling to PowerPC on MacOS X 10.5.  */
+#if defined __hpux || defined __sgi
+static long double
+compute_minus_zerol (void)
+{
+  return -LDBL_MIN * LDBL_MIN;
+}
+# define minus_zerol compute_minus_zerol ()
+#else
+long double minus_zerol = -0.0L;
+#endif
+
+static void
+test_signbitf ()
+{
+  /* Finite values.  */
+  ASSERT (!signbit (3.141f));
+  ASSERT (!signbit (3.141e30f));
+  ASSERT (!signbit (3.141e-30f));
+  ASSERT (signbit (-2.718f));
+  ASSERT (signbit (-2.718e30f));
+  ASSERT (signbit (-2.718e-30f));
+  /* Zeros.  */
+  ASSERT (!signbit (0.0f));
+  if (1.0f / -zerof < 0)
+    ASSERT (signbit (-zerof));
+  else
+    ASSERT (!signbit (-zerof));
+  /* Infinite values.  */
+  ASSERT (!signbit (1.0f / 0.0f));
+  ASSERT (signbit (-1.0f / 0.0f));
+  /* Quiet NaN.  */
+  (void) signbit (zerof / zerof);
+#if defined FLT_EXPBIT0_WORD && defined FLT_EXPBIT0_BIT
+  /* Signalling NaN.  */
+  {
+    #define NWORDS \
+      ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+    typedef union { float value; unsigned int word[NWORDS]; } memory_float;
+    memory_float m;
+    m.value = zerof / zerof;
+# if FLT_EXPBIT0_BIT > 0
+    m.word[FLT_EXPBIT0_WORD] ^= (unsigned int) 1 << (FLT_EXPBIT0_BIT - 1);
+# else
+    m.word[FLT_EXPBIT0_WORD + (FLT_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
+      ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1);
+# endif
+    if (FLT_EXPBIT0_WORD < NWORDS / 2)
+      m.word[FLT_EXPBIT0_WORD + 1] |= (unsigned int) 1 << FLT_EXPBIT0_BIT;
+    else
+      m.word[0] |= (unsigned int) 1;
+    (void) signbit (m.value);
+    #undef NWORDS
+  }
+#endif
+}
+
+static void
+test_signbitd ()
+{
+  /* Finite values.  */
+  ASSERT (!signbit (3.141));
+  ASSERT (!signbit (3.141e30));
+  ASSERT (!signbit (3.141e-30));
+  ASSERT (signbit (-2.718));
+  ASSERT (signbit (-2.718e30));
+  ASSERT (signbit (-2.718e-30));
+  /* Zeros.  */
+  ASSERT (!signbit (0.0));
+  if (1.0 / -zerod < 0)
+    ASSERT (signbit (-zerod));
+  else
+    ASSERT (!signbit (-zerod));
+  /* Infinite values.  */
+  ASSERT (!signbit (1.0 / 0.0));
+  ASSERT (signbit (-1.0 / 0.0));
+  /* Quiet NaN.  */
+  (void) signbit (zerod / zerod);
+#if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT
+  /* Signalling NaN.  */
+  {
+    #define NWORDS \
+      ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+    typedef union { double value; unsigned int word[NWORDS]; } memory_double;
+    memory_double m;
+    m.value = zerod / zerod;
+# if DBL_EXPBIT0_BIT > 0
+    m.word[DBL_EXPBIT0_WORD] ^= (unsigned int) 1 << (DBL_EXPBIT0_BIT - 1);
+# else
+    m.word[DBL_EXPBIT0_WORD + (DBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
+      ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1);
+# endif
+    m.word[DBL_EXPBIT0_WORD + (DBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
+      |= (unsigned int) 1 << DBL_EXPBIT0_BIT;
+    (void) signbit (m.value);
+    #undef NWORDS
+  }
+#endif
+}
+
+static void
+test_signbitl ()
+{
+  /* Finite values.  */
+  ASSERT (!signbit (3.141L));
+  ASSERT (!signbit (3.141e30L));
+  ASSERT (!signbit (3.141e-30L));
+  ASSERT (signbit (-2.718L));
+  ASSERT (signbit (-2.718e30L));
+  ASSERT (signbit (-2.718e-30L));
+  /* Zeros.  */
+  ASSERT (!signbit (0.0L));
+  if (1.0L / minus_zerol < 0)
+    ASSERT (signbit (minus_zerol));
+  else
+    ASSERT (!signbit (minus_zerol));
+  /* Infinite values.  */
+  ASSERT (!signbit (1.0L / 0.0L));
+  ASSERT (signbit (-1.0L / 0.0L));
+  /* Quiet NaN.  */
+  (void) signbit (zerol / zerol);
+#if defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT
+  /* Signalling NaN.  */
+  {
+    #define NWORDS \
+      ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+    typedef union { long double value; unsigned int word[NWORDS]; } memory_long_double;
+    memory_long_double m;
+    m.value = zerol / zerol;
+# if LDBL_EXPBIT0_BIT > 0
+    m.word[LDBL_EXPBIT0_WORD] ^= (unsigned int) 1 << (LDBL_EXPBIT0_BIT - 1);
+# else
+    m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
+      ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1);
+# endif
+    m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
+      |= (unsigned int) 1 << LDBL_EXPBIT0_BIT;
+    (void) signbit (m.value);
+    #undef NWORDS
+  }
+#endif
+}
+
+int
+main ()
+{
+  test_signbitf ();
+  test_signbitd ();
+  test_signbitl ();
+  return 0;
+}
diff --git a/libmissing/tests/test-snprintf-posix.c b/libmissing/tests/test-snprintf-posix.c
new file mode 100644
index 0000000..452e90c
--- /dev/null
+++ b/libmissing/tests/test-snprintf-posix.c
@@ -0,0 +1,38 @@
+/* Test of POSIX compatible snprintf() function.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2007.  */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <float.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "macros.h"
+
+#include "test-snprintf-posix.h"
+
+int
+main (int argc, char *argv[])
+{
+  test_function (snprintf);
+  return 0;
+}
diff --git a/libmissing/tests/test-snprintf-posix.h b/libmissing/tests/test-snprintf-posix.h
new file mode 100644
index 0000000..b796d5b
--- /dev/null
+++ b/libmissing/tests/test-snprintf-posix.h
@@ -0,0 +1,3113 @@
+/* Test of POSIX compatible vsnprintf() and snprintf() functions.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2007.  */
+
+#include "nan.h"
+
+/* The SGI MIPS floating-point format does not distinguish 0.0 and -0.0.  */
+static int
+have_minus_zero ()
+{
+  static double plus_zero = 0.0;
+  double minus_zero = - plus_zero;
+  return memcmp (&plus_zero, &minus_zero, sizeof (double)) != 0;
+}
+
+/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0.
+   So we use -zerod instead.  */
+double zerod = 0.0;
+
+/* On HP-UX 10.20, negating 0.0L does not yield -0.0L.
+   So we use minus_zerol instead.
+   IRIX cc can't put -0.0L into .data, but can compute at runtime.
+   Note that the expression -LDBL_MIN * LDBL_MIN does not work on other
+   platforms, such as when cross-compiling to PowerPC on MacOS X 10.5.  */
+#if defined __hpux || defined __sgi
+static long double
+compute_minus_zerol (void)
+{
+  return -LDBL_MIN * LDBL_MIN;
+}
+# define minus_zerol compute_minus_zerol ()
+#else
+long double minus_zerol = -0.0L;
+#endif
+
+/* Representation of an 80-bit 'long double' as an initializer for a sequence
+   of 'unsigned int' words.  */
+#ifdef WORDS_BIGENDIAN
+# define LDBL80_WORDS(exponent,manthi,mantlo) \
+    { ((unsigned int) (exponent) << 16) | ((unsigned int) (manthi) >> 16), \
+      ((unsigned int) (manthi) << 16) | (unsigned int) (mantlo) >> 16),    \
+      (unsigned int) (mantlo) << 16                                        \
+    }
+#else
+# define LDBL80_WORDS(exponent,manthi,mantlo) \
+    { mantlo, manthi, exponent }
+#endif
+
+static int
+strmatch (const char *pattern, const char *string)
+{
+  if (strlen (pattern) != strlen (string))
+    return 0;
+  for (; *pattern != '\0'; pattern++, string++)
+    if (*pattern != '*' && *string != *pattern)
+      return 0;
+  return 1;
+}
+
+/* Test whether string[start_index..end_index-1] is a valid textual
+   representation of NaN.  */
+static int
+strisnan (const char *string, size_t start_index, size_t end_index, int uppercase)
+{
+  if (start_index < end_index)
+    {
+      if (string[start_index] == '-')
+        start_index++;
+      if (start_index + 3 <= end_index
+          && memcmp (string + start_index, uppercase ? "NAN" : "nan", 3) == 0)
+        {
+          start_index += 3;
+          if (start_index == end_index
+              || (string[start_index] == '(' && string[end_index - 1] == ')'))
+            return 1;
+        }
+    }
+  return 0;
+}
+
+static void
+test_function (int (*my_snprintf) (char *, size_t, const char *, ...))
+{
+  char buf[8];
+  int size;
+
+  /* Test return value convention.  */
+
+  for (size = 0; size <= 8; size++)
+    {
+      int retval;
+
+      memcpy (buf, "DEADBEEF", 8);
+      retval = my_snprintf (buf, size, "%d", 12345);
+      ASSERT (retval == 5);
+      if (size < 6)
+        {
+          if (size > 0)
+            {
+              ASSERT (memcmp (buf, "12345", size - 1) == 0);
+              ASSERT (buf[size - 1] == '\0');
+            }
+          ASSERT (memcmp (buf + size, "DEADBEEF" + size, 8 - size) == 0);
+        }
+      else
+        {
+          ASSERT (memcmp (buf, "12345\0EF", 8) == 0);
+        }
+    }
+
+  /* Test support of size specifiers as in C99.  */
+
+  {
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%ju %d", (uintmax_t) 12345671, 33, 44, 55);
+    ASSERT (strcmp (result, "12345671 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  {
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%zu %d", (size_t) 12345672, 33, 44, 55);
+    ASSERT (strcmp (result, "12345672 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  {
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%tu %d", (ptrdiff_t) 12345673, 33, 44, 55);
+    ASSERT (strcmp (result, "12345673 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  {
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lg %d", (long double) 1.5, 33, 44, 55);
+    ASSERT (strcmp (result, "1.5 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  /* Test the support of the 'a' and 'A' conversion specifier for hexadecimal
+     output of floating-point numbers.  */
+
+  { /* A positive number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%a %d", 3.1416015625, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.922p+1 33") == 0
+            || strcmp (result, "0x3.244p+0 33") == 0
+            || strcmp (result, "0x6.488p-1 33") == 0
+            || strcmp (result, "0xc.91p-2 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* A negative number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%A %d", -3.1416015625, 33, 44, 55);
+    ASSERT (strcmp (result, "-0X1.922P+1 33") == 0
+            || strcmp (result, "-0X3.244P+0 33") == 0
+            || strcmp (result, "-0X6.488P-1 33") == 0
+            || strcmp (result, "-0XC.91P-2 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%a %d", 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "0x0p+0 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%a %d", -zerod, 33, 44, 55);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0x0p+0 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%a %d", 1.0 / 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "inf 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%a %d", -1.0 / 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "-inf 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* NaN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%a %d", NaNd (), 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Rounding near the decimal point.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.0a %d", 1.5, 33, 44, 55);
+    ASSERT (strcmp (result, "0x2p+0 33") == 0
+            || strcmp (result, "0x3p-1 33") == 0
+            || strcmp (result, "0x6p-2 33") == 0
+            || strcmp (result, "0xcp-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Rounding with precision 0.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.0a %d", 1.51, 33, 44, 55);
+    ASSERT (strcmp (result, "0x2p+0 33") == 0
+            || strcmp (result, "0x3p-1 33") == 0
+            || strcmp (result, "0x6p-2 33") == 0
+            || strcmp (result, "0xcp-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Rounding with precision 1.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.1a %d", 1.51, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.8p+0 33") == 0
+            || strcmp (result, "0x3.0p-1 33") == 0
+            || strcmp (result, "0x6.1p-2 33") == 0
+            || strcmp (result, "0xc.1p-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Rounding with precision 2.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.2a %d", 1.51, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.83p+0 33") == 0
+            || strcmp (result, "0x3.05p-1 33") == 0
+            || strcmp (result, "0x6.0ap-2 33") == 0
+            || strcmp (result, "0xc.14p-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Rounding with precision 3.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.3a %d", 1.51, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.829p+0 33") == 0
+            || strcmp (result, "0x3.052p-1 33") == 0
+            || strcmp (result, "0x6.0a4p-2 33") == 0
+            || strcmp (result, "0xc.148p-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Rounding can turn a ...FFF into a ...000.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.3a %d", 1.49999, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.800p+0 33") == 0
+            || strcmp (result, "0x3.000p-1 33") == 0
+            || strcmp (result, "0x6.000p-2 33") == 0
+            || strcmp (result, "0xc.000p-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Rounding can turn a ...FFF into a ...000.
+       This shows a MacOS X 10.3.9 (Darwin 7.9) bug.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.1a %d", 1.999, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.0p+1 33") == 0
+            || strcmp (result, "0x2.0p+0 33") == 0
+            || strcmp (result, "0x4.0p-1 33") == 0
+            || strcmp (result, "0x8.0p-2 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Width.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%10a %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "  0x1.cp+0 33") == 0
+            || strcmp (result, "  0x3.8p-1 33") == 0
+            || strcmp (result, "    0x7p-2 33") == 0
+            || strcmp (result, "    0xep-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Small precision.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.10a %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.c000000000p+0 33") == 0
+            || strcmp (result, "0x3.8000000000p-1 33") == 0
+            || strcmp (result, "0x7.0000000000p-2 33") == 0
+            || strcmp (result, "0xe.0000000000p-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Large precision.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.50a %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.c0000000000000000000000000000000000000000000000000p+0 33") == 0
+            || strcmp (result, "0x3.80000000000000000000000000000000000000000000000000p-1 33") == 0
+            || strcmp (result, "0x7.00000000000000000000000000000000000000000000000000p-2 33") == 0
+            || strcmp (result, "0xe.00000000000000000000000000000000000000000000000000p-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_LEFT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%-10a %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.cp+0   33") == 0
+            || strcmp (result, "0x3.8p-1   33") == 0
+            || strcmp (result, "0x7p-2     33") == 0
+            || strcmp (result, "0xep-3     33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_SHOWSIGN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%+a %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "+0x1.cp+0 33") == 0
+            || strcmp (result, "+0x3.8p-1 33") == 0
+            || strcmp (result, "+0x7p-2 33") == 0
+            || strcmp (result, "+0xep-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_SPACE.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "% a %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, " 0x1.cp+0 33") == 0
+            || strcmp (result, " 0x3.8p-1 33") == 0
+            || strcmp (result, " 0x7p-2 33") == 0
+            || strcmp (result, " 0xep-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#a %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.cp+0 33") == 0
+            || strcmp (result, "0x3.8p-1 33") == 0
+            || strcmp (result, "0x7.p-2 33") == 0
+            || strcmp (result, "0xe.p-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#a %d", 1.0, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.p+0 33") == 0
+            || strcmp (result, "0x2.p-1 33") == 0
+            || strcmp (result, "0x4.p-2 33") == 0
+            || strcmp (result, "0x8.p-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with finite number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%010a %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "0x001.cp+0 33") == 0
+            || strcmp (result, "0x003.8p-1 33") == 0
+            || strcmp (result, "0x00007p-2 33") == 0
+            || strcmp (result, "0x0000ep-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with infinite number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%010a %d", 1.0 / 0.0, 33, 44, 55);
+    /* "0000000inf 33" is not a valid result; see
+       <http://lists.gnu.org/archive/html/bug-gnulib/2007-04/msg00107.html> */
+    ASSERT (strcmp (result, "       inf 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with NaN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%050a %d", NaNd (), 33, 44, 55);
+    /* "0000000nan 33" is not a valid result; see
+       <http://lists.gnu.org/archive/html/bug-gnulib/2007-04/msg00107.html> */
+    ASSERT (strlen (result) == 50 + 3
+            && strisnan (result, strspn (result, " "), strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* A positive number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%La %d", 3.1416015625L, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.922p+1 33") == 0
+            || strcmp (result, "0x3.244p+0 33") == 0
+            || strcmp (result, "0x6.488p-1 33") == 0
+            || strcmp (result, "0xc.91p-2 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* A negative number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%LA %d", -3.1416015625L, 33, 44, 55);
+    ASSERT (strcmp (result, "-0X1.922P+1 33") == 0
+            || strcmp (result, "-0X3.244P+0 33") == 0
+            || strcmp (result, "-0X6.488P-1 33") == 0
+            || strcmp (result, "-0XC.91P-2 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%La %d", 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "0x0p+0 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%La %d", minus_zerol, 33, 44, 55);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0x0p+0 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%La %d", 1.0L / 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "inf 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%La %d", -1.0L / 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "-inf 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* NaN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%La %d", NaNl (), 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+#if CHECK_PRINTF_SAFE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_))
+  { /* Quiet NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%La %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  {
+    /* Signalling NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%La %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities,
+     Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in
+       Intel IA-64 Architecture Software Developer's Manual, Volume 1:
+       Application Architecture.
+       Table 5-2 "Floating-Point Register Encodings"
+       Figure 5-6 "Memory to Floating-Point Register Data Translation"
+   */
+  { /* Pseudo-NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%La %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  { /* Pseudo-Infinity.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%La %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  { /* Pseudo-Zero.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%La %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  { /* Unnormalized number.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%La %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  { /* Pseudo-Denormal.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%La %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+#endif
+
+  { /* Rounding near the decimal point.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.0La %d", 1.5L, 33, 44, 55);
+    ASSERT (strcmp (result, "0x2p+0 33") == 0
+            || strcmp (result, "0x3p-1 33") == 0
+            || strcmp (result, "0x6p-2 33") == 0
+            || strcmp (result, "0xcp-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Rounding with precision 0.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.0La %d", 1.51L, 33, 44, 55);
+    ASSERT (strcmp (result, "0x2p+0 33") == 0
+            || strcmp (result, "0x3p-1 33") == 0
+            || strcmp (result, "0x6p-2 33") == 0
+            || strcmp (result, "0xcp-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Rounding with precision 1.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.1La %d", 1.51L, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.8p+0 33") == 0
+            || strcmp (result, "0x3.0p-1 33") == 0
+            || strcmp (result, "0x6.1p-2 33") == 0
+            || strcmp (result, "0xc.1p-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Rounding with precision 2.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.2La %d", 1.51L, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.83p+0 33") == 0
+            || strcmp (result, "0x3.05p-1 33") == 0
+            || strcmp (result, "0x6.0ap-2 33") == 0
+            || strcmp (result, "0xc.14p-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Rounding with precision 3.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.3La %d", 1.51L, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.829p+0 33") == 0
+            || strcmp (result, "0x3.052p-1 33") == 0
+            || strcmp (result, "0x6.0a4p-2 33") == 0
+            || strcmp (result, "0xc.148p-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Rounding can turn a ...FFF into a ...000.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.3La %d", 1.49999L, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.800p+0 33") == 0
+            || strcmp (result, "0x3.000p-1 33") == 0
+            || strcmp (result, "0x6.000p-2 33") == 0
+            || strcmp (result, "0xc.000p-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Rounding can turn a ...FFF into a ...000.
+       This shows a MacOS X 10.3.9 (Darwin 7.9) bug and a
+       glibc 2.4 bug <http://sourceware.org/bugzilla/show_bug.cgi?id=2908>.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.1La %d", 1.999L, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.0p+1 33") == 0
+            || strcmp (result, "0x2.0p+0 33") == 0
+            || strcmp (result, "0x4.0p-1 33") == 0
+            || strcmp (result, "0x8.0p-2 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Width.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%10La %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "  0x1.cp+0 33") == 0
+            || strcmp (result, "  0x3.8p-1 33") == 0
+            || strcmp (result, "    0x7p-2 33") == 0
+            || strcmp (result, "    0xep-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Small precision.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.10La %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.c000000000p+0 33") == 0
+            || strcmp (result, "0x3.8000000000p-1 33") == 0
+            || strcmp (result, "0x7.0000000000p-2 33") == 0
+            || strcmp (result, "0xe.0000000000p-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Large precision.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.50La %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.c0000000000000000000000000000000000000000000000000p+0 33") == 0
+            || strcmp (result, "0x3.80000000000000000000000000000000000000000000000000p-1 33") == 0
+            || strcmp (result, "0x7.00000000000000000000000000000000000000000000000000p-2 33") == 0
+            || strcmp (result, "0xe.00000000000000000000000000000000000000000000000000p-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_LEFT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%-10La %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.cp+0   33") == 0
+            || strcmp (result, "0x3.8p-1   33") == 0
+            || strcmp (result, "0x7p-2     33") == 0
+            || strcmp (result, "0xep-3     33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_SHOWSIGN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%+La %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "+0x1.cp+0 33") == 0
+            || strcmp (result, "+0x3.8p-1 33") == 0
+            || strcmp (result, "+0x7p-2 33") == 0
+            || strcmp (result, "+0xep-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_SPACE.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "% La %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, " 0x1.cp+0 33") == 0
+            || strcmp (result, " 0x3.8p-1 33") == 0
+            || strcmp (result, " 0x7p-2 33") == 0
+            || strcmp (result, " 0xep-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#La %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.cp+0 33") == 0
+            || strcmp (result, "0x3.8p-1 33") == 0
+            || strcmp (result, "0x7.p-2 33") == 0
+            || strcmp (result, "0xe.p-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#La %d", 1.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "0x1.p+0 33") == 0
+            || strcmp (result, "0x2.p-1 33") == 0
+            || strcmp (result, "0x4.p-2 33") == 0
+            || strcmp (result, "0x8.p-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with finite number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%010La %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "0x001.cp+0 33") == 0
+            || strcmp (result, "0x003.8p-1 33") == 0
+            || strcmp (result, "0x00007p-2 33") == 0
+            || strcmp (result, "0x0000ep-3 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with infinite number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%010La %d", 1.0L / 0.0L, 33, 44, 55);
+    /* "0000000inf 33" is not a valid result; see
+       <http://lists.gnu.org/archive/html/bug-gnulib/2007-04/msg00107.html> */
+    ASSERT (strcmp (result, "       inf 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with NaN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%050La %d", NaNl (), 33, 44, 55);
+    /* "0000000nan 33" is not a valid result; see
+       <http://lists.gnu.org/archive/html/bug-gnulib/2007-04/msg00107.html> */
+    ASSERT (strlen (result) == 50 + 3
+            && strisnan (result, strspn (result, " "), strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  /* Test the support of the %f format directive.  */
+
+  { /* A positive number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%f %d", 12.75, 33, 44, 55);
+    ASSERT (strcmp (result, "12.750000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* A larger positive number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%f %d", 1234567.0, 33, 44, 55);
+    ASSERT (strcmp (result, "1234567.000000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Small and large positive numbers.  */
+    static struct { double value; const char *string; } data[] =
+      {
+        { 1.234321234321234e-37, "0.000000" },
+        { 1.234321234321234e-36, "0.000000" },
+        { 1.234321234321234e-35, "0.000000" },
+        { 1.234321234321234e-34, "0.000000" },
+        { 1.234321234321234e-33, "0.000000" },
+        { 1.234321234321234e-32, "0.000000" },
+        { 1.234321234321234e-31, "0.000000" },
+        { 1.234321234321234e-30, "0.000000" },
+        { 1.234321234321234e-29, "0.000000" },
+        { 1.234321234321234e-28, "0.000000" },
+        { 1.234321234321234e-27, "0.000000" },
+        { 1.234321234321234e-26, "0.000000" },
+        { 1.234321234321234e-25, "0.000000" },
+        { 1.234321234321234e-24, "0.000000" },
+        { 1.234321234321234e-23, "0.000000" },
+        { 1.234321234321234e-22, "0.000000" },
+        { 1.234321234321234e-21, "0.000000" },
+        { 1.234321234321234e-20, "0.000000" },
+        { 1.234321234321234e-19, "0.000000" },
+        { 1.234321234321234e-18, "0.000000" },
+        { 1.234321234321234e-17, "0.000000" },
+        { 1.234321234321234e-16, "0.000000" },
+        { 1.234321234321234e-15, "0.000000" },
+        { 1.234321234321234e-14, "0.000000" },
+        { 1.234321234321234e-13, "0.000000" },
+        { 1.234321234321234e-12, "0.000000" },
+        { 1.234321234321234e-11, "0.000000" },
+        { 1.234321234321234e-10, "0.000000" },
+        { 1.234321234321234e-9, "0.000000" },
+        { 1.234321234321234e-8, "0.000000" },
+        { 1.234321234321234e-7, "0.000000" },
+        { 1.234321234321234e-6, "0.000001" },
+        { 1.234321234321234e-5, "0.000012" },
+        { 1.234321234321234e-4, "0.000123" },
+        { 1.234321234321234e-3, "0.001234" },
+        { 1.234321234321234e-2, "0.012343" },
+        { 1.234321234321234e-1, "0.123432" },
+        { 1.234321234321234, "1.234321" },
+        { 1.234321234321234e1, "12.343212" },
+        { 1.234321234321234e2, "123.432123" },
+        { 1.234321234321234e3, "1234.321234" },
+        { 1.234321234321234e4, "12343.212343" },
+        { 1.234321234321234e5, "123432.123432" },
+        { 1.234321234321234e6, "1234321.234321" },
+        { 1.234321234321234e7, "12343212.343212" },
+        { 1.234321234321234e8, "123432123.432123" },
+        { 1.234321234321234e9, "1234321234.321234" },
+        { 1.234321234321234e10, "12343212343.2123**" },
+        { 1.234321234321234e11, "123432123432.123***" },
+        { 1.234321234321234e12, "1234321234321.23****" },
+        { 1.234321234321234e13, "12343212343212.3*****" },
+        { 1.234321234321234e14, "123432123432123.******" },
+        { 1.234321234321234e15, "1234321234321234.000000" },
+        { 1.234321234321234e16, "123432123432123**.000000" },
+        { 1.234321234321234e17, "123432123432123***.000000" },
+        { 1.234321234321234e18, "123432123432123****.000000" },
+        { 1.234321234321234e19, "123432123432123*****.000000" },
+        { 1.234321234321234e20, "123432123432123******.000000" },
+        { 1.234321234321234e21, "123432123432123*******.000000" },
+        { 1.234321234321234e22, "123432123432123********.000000" },
+        { 1.234321234321234e23, "123432123432123*********.000000" },
+        { 1.234321234321234e24, "123432123432123**********.000000" },
+        { 1.234321234321234e25, "123432123432123***********.000000" },
+        { 1.234321234321234e26, "123432123432123************.000000" },
+        { 1.234321234321234e27, "123432123432123*************.000000" },
+        { 1.234321234321234e28, "123432123432123**************.000000" },
+        { 1.234321234321234e29, "123432123432123***************.000000" },
+        { 1.234321234321234e30, "123432123432123****************.000000" },
+        { 1.234321234321234e31, "123432123432123*****************.000000" },
+        { 1.234321234321234e32, "123432123432123******************.000000" },
+        { 1.234321234321234e33, "123432123432123*******************.000000" },
+        { 1.234321234321234e34, "123432123432123********************.000000" },
+        { 1.234321234321234e35, "123432123432123*********************.000000" },
+        { 1.234321234321234e36, "123432123432123**********************.000000" }
+      };
+    size_t k;
+    for (k = 0; k < SIZEOF (data); k++)
+      {
+        char result[100];
+        int retval =
+          my_snprintf (result, sizeof (result), "%f", data[k].value);
+        ASSERT (strmatch (data[k].string, result));
+        ASSERT (retval == strlen (result));
+      }
+  }
+
+  { /* A negative number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%f %d", -0.03125, 33, 44, 55);
+    ASSERT (strcmp (result, "-0.031250 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%f %d", 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "0.000000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%f %d", -zerod, 33, 44, 55);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0.000000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%f %d", 1.0 / 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "inf 33") == 0
+            || strcmp (result, "infinity 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%f %d", -1.0 / 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "-inf 33") == 0
+            || strcmp (result, "-infinity 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* NaN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%f %d", NaNd (), 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Width.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%10f %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "  1.750000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_LEFT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%-10f %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "1.750000   33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_SHOWSIGN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%+f %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "+1.750000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_SPACE.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "% f %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, " 1.750000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#f %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "1.750000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#.f %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "2. 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with finite number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%015f %d", 1234.0, 33, 44, 55);
+    ASSERT (strcmp (result, "00001234.000000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with infinite number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%015f %d", -1.0 / 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "           -inf 33") == 0
+            || strcmp (result, "      -infinity 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with NaN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%050f %d", NaNd (), 33, 44, 55);
+    ASSERT (strlen (result) == 50 + 3
+            && strisnan (result, strspn (result, " "), strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.f %d", 1234.0, 33, 44, 55);
+    ASSERT (strcmp (result, "1234 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision with no rounding.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.2f %d", 999.951, 33, 44, 55);
+    ASSERT (strcmp (result, "999.95 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision with rounding.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.2f %d", 999.996, 33, 44, 55);
+    ASSERT (strcmp (result, "1000.00 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* A positive number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lf %d", 12.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "12.750000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* A larger positive number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lf %d", 1234567.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "1234567.000000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Small and large positive numbers.  */
+    static struct { long double value; const char *string; } data[] =
+      {
+        { 1.234321234321234e-37L, "0.000000" },
+        { 1.234321234321234e-36L, "0.000000" },
+        { 1.234321234321234e-35L, "0.000000" },
+        { 1.234321234321234e-34L, "0.000000" },
+        { 1.234321234321234e-33L, "0.000000" },
+        { 1.234321234321234e-32L, "0.000000" },
+        { 1.234321234321234e-31L, "0.000000" },
+        { 1.234321234321234e-30L, "0.000000" },
+        { 1.234321234321234e-29L, "0.000000" },
+        { 1.234321234321234e-28L, "0.000000" },
+        { 1.234321234321234e-27L, "0.000000" },
+        { 1.234321234321234e-26L, "0.000000" },
+        { 1.234321234321234e-25L, "0.000000" },
+        { 1.234321234321234e-24L, "0.000000" },
+        { 1.234321234321234e-23L, "0.000000" },
+        { 1.234321234321234e-22L, "0.000000" },
+        { 1.234321234321234e-21L, "0.000000" },
+        { 1.234321234321234e-20L, "0.000000" },
+        { 1.234321234321234e-19L, "0.000000" },
+        { 1.234321234321234e-18L, "0.000000" },
+        { 1.234321234321234e-17L, "0.000000" },
+        { 1.234321234321234e-16L, "0.000000" },
+        { 1.234321234321234e-15L, "0.000000" },
+        { 1.234321234321234e-14L, "0.000000" },
+        { 1.234321234321234e-13L, "0.000000" },
+        { 1.234321234321234e-12L, "0.000000" },
+        { 1.234321234321234e-11L, "0.000000" },
+        { 1.234321234321234e-10L, "0.000000" },
+        { 1.234321234321234e-9L, "0.000000" },
+        { 1.234321234321234e-8L, "0.000000" },
+        { 1.234321234321234e-7L, "0.000000" },
+        { 1.234321234321234e-6L, "0.000001" },
+        { 1.234321234321234e-5L, "0.000012" },
+        { 1.234321234321234e-4L, "0.000123" },
+        { 1.234321234321234e-3L, "0.001234" },
+        { 1.234321234321234e-2L, "0.012343" },
+        { 1.234321234321234e-1L, "0.123432" },
+        { 1.234321234321234L, "1.234321" },
+        { 1.234321234321234e1L, "12.343212" },
+        { 1.234321234321234e2L, "123.432123" },
+        { 1.234321234321234e3L, "1234.321234" },
+        { 1.234321234321234e4L, "12343.212343" },
+        { 1.234321234321234e5L, "123432.123432" },
+        { 1.234321234321234e6L, "1234321.234321" },
+        { 1.234321234321234e7L, "12343212.343212" },
+        { 1.234321234321234e8L, "123432123.432123" },
+        { 1.234321234321234e9L, "1234321234.321234" },
+        { 1.234321234321234e10L, "12343212343.2123**" },
+        { 1.234321234321234e11L, "123432123432.123***" },
+        { 1.234321234321234e12L, "1234321234321.23****" },
+        { 1.234321234321234e13L, "12343212343212.3*****" },
+        { 1.234321234321234e14L, "123432123432123.******" },
+        { 1.234321234321234e15L, "1234321234321234.000000" },
+        { 1.234321234321234e16L, "123432123432123**.000000" },
+        { 1.234321234321234e17L, "123432123432123***.000000" },
+        { 1.234321234321234e18L, "123432123432123****.000000" },
+        { 1.234321234321234e19L, "123432123432123*****.000000" },
+        { 1.234321234321234e20L, "123432123432123******.000000" },
+        { 1.234321234321234e21L, "123432123432123*******.000000" },
+        { 1.234321234321234e22L, "123432123432123********.000000" },
+        { 1.234321234321234e23L, "123432123432123*********.000000" },
+        { 1.234321234321234e24L, "123432123432123**********.000000" },
+        { 1.234321234321234e25L, "123432123432123***********.000000" },
+        { 1.234321234321234e26L, "123432123432123************.000000" },
+        { 1.234321234321234e27L, "123432123432123*************.000000" },
+        { 1.234321234321234e28L, "123432123432123**************.000000" },
+        { 1.234321234321234e29L, "123432123432123***************.000000" },
+        { 1.234321234321234e30L, "123432123432123****************.000000" },
+        { 1.234321234321234e31L, "123432123432123*****************.000000" },
+        { 1.234321234321234e32L, "123432123432123******************.000000" },
+        { 1.234321234321234e33L, "123432123432123*******************.000000" },
+        { 1.234321234321234e34L, "123432123432123********************.000000" },
+        { 1.234321234321234e35L, "123432123432123*********************.000000" },
+        { 1.234321234321234e36L, "123432123432123**********************.000000" }
+      };
+    size_t k;
+    for (k = 0; k < SIZEOF (data); k++)
+      {
+        char result[100];
+        int retval =
+          my_snprintf (result, sizeof (result), "%Lf", data[k].value);
+        ASSERT (strmatch (data[k].string, result));
+        ASSERT (retval == strlen (result));
+      }
+  }
+
+  { /* A negative number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lf %d", -0.03125L, 33, 44, 55);
+    ASSERT (strcmp (result, "-0.031250 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lf %d", 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "0.000000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lf %d", minus_zerol, 33, 44, 55);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0.000000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lf %d", 1.0L / 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "inf 33") == 0
+            || strcmp (result, "infinity 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lf %d", -1.0L / 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "-inf 33") == 0
+            || strcmp (result, "-infinity 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* NaN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lf %d", NaNl (), 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+#if CHECK_PRINTF_SAFE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_))
+  { /* Quiet NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lf %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  {
+    /* Signalling NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lf %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities,
+     Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in
+       Intel IA-64 Architecture Software Developer's Manual, Volume 1:
+       Application Architecture.
+       Table 5-2 "Floating-Point Register Encodings"
+       Figure 5-6 "Memory to Floating-Point Register Data Translation"
+   */
+  { /* Pseudo-NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lf %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  { /* Pseudo-Infinity.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lf %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  { /* Pseudo-Zero.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lf %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  { /* Unnormalized number.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lf %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  { /* Pseudo-Denormal.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lf %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+#endif
+
+  { /* Width.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%10Lf %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "  1.750000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_LEFT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%-10Lf %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "1.750000   33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_SHOWSIGN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%+Lf %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "+1.750000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_SPACE.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "% Lf %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, " 1.750000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#Lf %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "1.750000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#.Lf %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "2. 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with finite number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%015Lf %d", 1234.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "00001234.000000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with infinite number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%015Lf %d", -1.0L / 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "           -inf 33") == 0
+            || strcmp (result, "      -infinity 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with NaN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%050Lf %d", NaNl (), 33, 44, 55);
+    ASSERT (strlen (result) == 50 + 3
+            && strisnan (result, strspn (result, " "), strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.Lf %d", 1234.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "1234 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision with no rounding.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.2Lf %d", 999.951L, 33, 44, 55);
+    ASSERT (strcmp (result, "999.95 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision with rounding.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.2Lf %d", 999.996L, 33, 44, 55);
+    ASSERT (strcmp (result, "1000.00 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  /* Test the support of the %F format directive.  */
+
+  { /* A positive number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%F %d", 12.75, 33, 44, 55);
+    ASSERT (strcmp (result, "12.750000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* A larger positive number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%F %d", 1234567.0, 33, 44, 55);
+    ASSERT (strcmp (result, "1234567.000000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* A negative number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%F %d", -0.03125, 33, 44, 55);
+    ASSERT (strcmp (result, "-0.031250 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%F %d", 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "0.000000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%F %d", -zerod, 33, 44, 55);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0.000000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%F %d", 1.0 / 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "INF 33") == 0
+            || strcmp (result, "INFINITY 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%F %d", -1.0 / 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "-INF 33") == 0
+            || strcmp (result, "-INFINITY 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* NaN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%F %d", NaNd (), 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 1)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%015F %d", 1234.0, 33, 44, 55);
+    ASSERT (strcmp (result, "00001234.000000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with infinite number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%015F %d", -1.0 / 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "           -INF 33") == 0
+            || strcmp (result, "      -INFINITY 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.F %d", 1234.0, 33, 44, 55);
+    ASSERT (strcmp (result, "1234 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision with no rounding.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.2F %d", 999.951, 33, 44, 55);
+    ASSERT (strcmp (result, "999.95 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision with rounding.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.2F %d", 999.996, 33, 44, 55);
+    ASSERT (strcmp (result, "1000.00 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* A positive number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%LF %d", 12.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "12.750000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* A larger positive number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%LF %d", 1234567.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "1234567.000000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* A negative number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%LF %d", -0.03125L, 33, 44, 55);
+    ASSERT (strcmp (result, "-0.031250 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%LF %d", 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "0.000000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%LF %d", minus_zerol, 33, 44, 55);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0.000000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%LF %d", 1.0L / 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "INF 33") == 0
+            || strcmp (result, "INFINITY 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%LF %d", -1.0L / 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "-INF 33") == 0
+            || strcmp (result, "-INFINITY 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* NaN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%LF %d", NaNl (), 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 1)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%015LF %d", 1234.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "00001234.000000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with infinite number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%015LF %d", -1.0L / 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "           -INF 33") == 0
+            || strcmp (result, "      -INFINITY 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.LF %d", 1234.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "1234 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision with no rounding.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.2LF %d", 999.951L, 33, 44, 55);
+    ASSERT (strcmp (result, "999.95 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision with rounding.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.2LF %d", 999.996L, 33, 44, 55);
+    ASSERT (strcmp (result, "1000.00 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  /* Test the support of the %e format directive.  */
+
+  { /* A positive number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%e %d", 12.75, 33, 44, 55);
+    ASSERT (strcmp (result, "1.275000e+01 33") == 0
+            || strcmp (result, "1.275000e+001 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* A larger positive number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%e %d", 1234567.0, 33, 44, 55);
+    ASSERT (strcmp (result, "1.234567e+06 33") == 0
+            || strcmp (result, "1.234567e+006 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Small and large positive numbers.  */
+    static struct { double value; const char *string; } data[] =
+      {
+        { 1.234321234321234e-37, "1.234321e-37" },
+        { 1.234321234321234e-36, "1.234321e-36" },
+        { 1.234321234321234e-35, "1.234321e-35" },
+        { 1.234321234321234e-34, "1.234321e-34" },
+        { 1.234321234321234e-33, "1.234321e-33" },
+        { 1.234321234321234e-32, "1.234321e-32" },
+        { 1.234321234321234e-31, "1.234321e-31" },
+        { 1.234321234321234e-30, "1.234321e-30" },
+        { 1.234321234321234e-29, "1.234321e-29" },
+        { 1.234321234321234e-28, "1.234321e-28" },
+        { 1.234321234321234e-27, "1.234321e-27" },
+        { 1.234321234321234e-26, "1.234321e-26" },
+        { 1.234321234321234e-25, "1.234321e-25" },
+        { 1.234321234321234e-24, "1.234321e-24" },
+        { 1.234321234321234e-23, "1.234321e-23" },
+        { 1.234321234321234e-22, "1.234321e-22" },
+        { 1.234321234321234e-21, "1.234321e-21" },
+        { 1.234321234321234e-20, "1.234321e-20" },
+        { 1.234321234321234e-19, "1.234321e-19" },
+        { 1.234321234321234e-18, "1.234321e-18" },
+        { 1.234321234321234e-17, "1.234321e-17" },
+        { 1.234321234321234e-16, "1.234321e-16" },
+        { 1.234321234321234e-15, "1.234321e-15" },
+        { 1.234321234321234e-14, "1.234321e-14" },
+        { 1.234321234321234e-13, "1.234321e-13" },
+        { 1.234321234321234e-12, "1.234321e-12" },
+        { 1.234321234321234e-11, "1.234321e-11" },
+        { 1.234321234321234e-10, "1.234321e-10" },
+        { 1.234321234321234e-9, "1.234321e-09" },
+        { 1.234321234321234e-8, "1.234321e-08" },
+        { 1.234321234321234e-7, "1.234321e-07" },
+        { 1.234321234321234e-6, "1.234321e-06" },
+        { 1.234321234321234e-5, "1.234321e-05" },
+        { 1.234321234321234e-4, "1.234321e-04" },
+        { 1.234321234321234e-3, "1.234321e-03" },
+        { 1.234321234321234e-2, "1.234321e-02" },
+        { 1.234321234321234e-1, "1.234321e-01" },
+        { 1.234321234321234, "1.234321e+00" },
+        { 1.234321234321234e1, "1.234321e+01" },
+        { 1.234321234321234e2, "1.234321e+02" },
+        { 1.234321234321234e3, "1.234321e+03" },
+        { 1.234321234321234e4, "1.234321e+04" },
+        { 1.234321234321234e5, "1.234321e+05" },
+        { 1.234321234321234e6, "1.234321e+06" },
+        { 1.234321234321234e7, "1.234321e+07" },
+        { 1.234321234321234e8, "1.234321e+08" },
+        { 1.234321234321234e9, "1.234321e+09" },
+        { 1.234321234321234e10, "1.234321e+10" },
+        { 1.234321234321234e11, "1.234321e+11" },
+        { 1.234321234321234e12, "1.234321e+12" },
+        { 1.234321234321234e13, "1.234321e+13" },
+        { 1.234321234321234e14, "1.234321e+14" },
+        { 1.234321234321234e15, "1.234321e+15" },
+        { 1.234321234321234e16, "1.234321e+16" },
+        { 1.234321234321234e17, "1.234321e+17" },
+        { 1.234321234321234e18, "1.234321e+18" },
+        { 1.234321234321234e19, "1.234321e+19" },
+        { 1.234321234321234e20, "1.234321e+20" },
+        { 1.234321234321234e21, "1.234321e+21" },
+        { 1.234321234321234e22, "1.234321e+22" },
+        { 1.234321234321234e23, "1.234321e+23" },
+        { 1.234321234321234e24, "1.234321e+24" },
+        { 1.234321234321234e25, "1.234321e+25" },
+        { 1.234321234321234e26, "1.234321e+26" },
+        { 1.234321234321234e27, "1.234321e+27" },
+        { 1.234321234321234e28, "1.234321e+28" },
+        { 1.234321234321234e29, "1.234321e+29" },
+        { 1.234321234321234e30, "1.234321e+30" },
+        { 1.234321234321234e31, "1.234321e+31" },
+        { 1.234321234321234e32, "1.234321e+32" },
+        { 1.234321234321234e33, "1.234321e+33" },
+        { 1.234321234321234e34, "1.234321e+34" },
+        { 1.234321234321234e35, "1.234321e+35" },
+        { 1.234321234321234e36, "1.234321e+36" }
+      };
+    size_t k;
+    for (k = 0; k < SIZEOF (data); k++)
+      {
+        char result[100];
+        int retval =
+          my_snprintf (result, sizeof (result), "%e", data[k].value);
+        const char *expected = data[k].string;
+        ASSERT (strcmp (result, expected) == 0
+                /* Some implementations produce exponents with 3 digits.  */
+                || (strlen (result) == strlen (expected) + 1
+                    && memcmp (result, expected, strlen (expected) - 2) == 0
+                    && result[strlen (expected) - 2] == '0'
+                    && strcmp (result + strlen (expected) - 1,
+                               expected + strlen (expected) - 2)
+                       == 0));
+        ASSERT (retval == strlen (result));
+      }
+  }
+
+  { /* A negative number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%e %d", -0.03125, 33, 44, 55);
+    ASSERT (strcmp (result, "-3.125000e-02 33") == 0
+            || strcmp (result, "-3.125000e-002 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%e %d", 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "0.000000e+00 33") == 0
+            || strcmp (result, "0.000000e+000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%e %d", -zerod, 33, 44, 55);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0.000000e+00 33") == 0
+              || strcmp (result, "-0.000000e+000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%e %d", 1.0 / 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "inf 33") == 0
+            || strcmp (result, "infinity 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%e %d", -1.0 / 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "-inf 33") == 0
+            || strcmp (result, "-infinity 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* NaN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%e %d", NaNd (), 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Width.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%15e %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "   1.750000e+00 33") == 0
+            || strcmp (result, "  1.750000e+000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_LEFT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%-15e %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "1.750000e+00    33") == 0
+            || strcmp (result, "1.750000e+000   33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_SHOWSIGN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%+e %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "+1.750000e+00 33") == 0
+            || strcmp (result, "+1.750000e+000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_SPACE.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "% e %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, " 1.750000e+00 33") == 0
+            || strcmp (result, " 1.750000e+000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#e %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "1.750000e+00 33") == 0
+            || strcmp (result, "1.750000e+000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#.e %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "2.e+00 33") == 0
+            || strcmp (result, "2.e+000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#.e %d", 9.75, 33, 44, 55);
+    ASSERT (strcmp (result, "1.e+01 33") == 0
+            || strcmp (result, "1.e+001 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with finite number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%015e %d", 1234.0, 33, 44, 55);
+    ASSERT (strcmp (result, "0001.234000e+03 33") == 0
+            || strcmp (result, "001.234000e+003 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with infinite number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%015e %d", -1.0 / 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "           -inf 33") == 0
+            || strcmp (result, "      -infinity 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with NaN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%050e %d", NaNd (), 33, 44, 55);
+    ASSERT (strlen (result) == 50 + 3
+            && strisnan (result, strspn (result, " "), strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.e %d", 1234.0, 33, 44, 55);
+    ASSERT (strcmp (result, "1e+03 33") == 0
+            || strcmp (result, "1e+003 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision with no rounding.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.4e %d", 999.951, 33, 44, 55);
+    ASSERT (strcmp (result, "9.9995e+02 33") == 0
+            || strcmp (result, "9.9995e+002 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision with rounding.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.4e %d", 999.996, 33, 44, 55);
+    ASSERT (strcmp (result, "1.0000e+03 33") == 0
+            || strcmp (result, "1.0000e+003 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* A positive number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Le %d", 12.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "1.275000e+01 33") == 0
+            || strcmp (result, "1.275000e+001 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* A larger positive number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Le %d", 1234567.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "1.234567e+06 33") == 0
+            || strcmp (result, "1.234567e+006 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Small and large positive numbers.  */
+    static struct { long double value; const char *string; } data[] =
+      {
+        { 1.234321234321234e-37L, "1.234321e-37" },
+        { 1.234321234321234e-36L, "1.234321e-36" },
+        { 1.234321234321234e-35L, "1.234321e-35" },
+        { 1.234321234321234e-34L, "1.234321e-34" },
+        { 1.234321234321234e-33L, "1.234321e-33" },
+        { 1.234321234321234e-32L, "1.234321e-32" },
+        { 1.234321234321234e-31L, "1.234321e-31" },
+        { 1.234321234321234e-30L, "1.234321e-30" },
+        { 1.234321234321234e-29L, "1.234321e-29" },
+        { 1.234321234321234e-28L, "1.234321e-28" },
+        { 1.234321234321234e-27L, "1.234321e-27" },
+        { 1.234321234321234e-26L, "1.234321e-26" },
+        { 1.234321234321234e-25L, "1.234321e-25" },
+        { 1.234321234321234e-24L, "1.234321e-24" },
+        { 1.234321234321234e-23L, "1.234321e-23" },
+        { 1.234321234321234e-22L, "1.234321e-22" },
+        { 1.234321234321234e-21L, "1.234321e-21" },
+        { 1.234321234321234e-20L, "1.234321e-20" },
+        { 1.234321234321234e-19L, "1.234321e-19" },
+        { 1.234321234321234e-18L, "1.234321e-18" },
+        { 1.234321234321234e-17L, "1.234321e-17" },
+        { 1.234321234321234e-16L, "1.234321e-16" },
+        { 1.234321234321234e-15L, "1.234321e-15" },
+        { 1.234321234321234e-14L, "1.234321e-14" },
+        { 1.234321234321234e-13L, "1.234321e-13" },
+        { 1.234321234321234e-12L, "1.234321e-12" },
+        { 1.234321234321234e-11L, "1.234321e-11" },
+        { 1.234321234321234e-10L, "1.234321e-10" },
+        { 1.234321234321234e-9L, "1.234321e-09" },
+        { 1.234321234321234e-8L, "1.234321e-08" },
+        { 1.234321234321234e-7L, "1.234321e-07" },
+        { 1.234321234321234e-6L, "1.234321e-06" },
+        { 1.234321234321234e-5L, "1.234321e-05" },
+        { 1.234321234321234e-4L, "1.234321e-04" },
+        { 1.234321234321234e-3L, "1.234321e-03" },
+        { 1.234321234321234e-2L, "1.234321e-02" },
+        { 1.234321234321234e-1L, "1.234321e-01" },
+        { 1.234321234321234L, "1.234321e+00" },
+        { 1.234321234321234e1L, "1.234321e+01" },
+        { 1.234321234321234e2L, "1.234321e+02" },
+        { 1.234321234321234e3L, "1.234321e+03" },
+        { 1.234321234321234e4L, "1.234321e+04" },
+        { 1.234321234321234e5L, "1.234321e+05" },
+        { 1.234321234321234e6L, "1.234321e+06" },
+        { 1.234321234321234e7L, "1.234321e+07" },
+        { 1.234321234321234e8L, "1.234321e+08" },
+        { 1.234321234321234e9L, "1.234321e+09" },
+        { 1.234321234321234e10L, "1.234321e+10" },
+        { 1.234321234321234e11L, "1.234321e+11" },
+        { 1.234321234321234e12L, "1.234321e+12" },
+        { 1.234321234321234e13L, "1.234321e+13" },
+        { 1.234321234321234e14L, "1.234321e+14" },
+        { 1.234321234321234e15L, "1.234321e+15" },
+        { 1.234321234321234e16L, "1.234321e+16" },
+        { 1.234321234321234e17L, "1.234321e+17" },
+        { 1.234321234321234e18L, "1.234321e+18" },
+        { 1.234321234321234e19L, "1.234321e+19" },
+        { 1.234321234321234e20L, "1.234321e+20" },
+        { 1.234321234321234e21L, "1.234321e+21" },
+        { 1.234321234321234e22L, "1.234321e+22" },
+        { 1.234321234321234e23L, "1.234321e+23" },
+        { 1.234321234321234e24L, "1.234321e+24" },
+        { 1.234321234321234e25L, "1.234321e+25" },
+        { 1.234321234321234e26L, "1.234321e+26" },
+        { 1.234321234321234e27L, "1.234321e+27" },
+        { 1.234321234321234e28L, "1.234321e+28" },
+        { 1.234321234321234e29L, "1.234321e+29" },
+        { 1.234321234321234e30L, "1.234321e+30" },
+        { 1.234321234321234e31L, "1.234321e+31" },
+        { 1.234321234321234e32L, "1.234321e+32" },
+        { 1.234321234321234e33L, "1.234321e+33" },
+        { 1.234321234321234e34L, "1.234321e+34" },
+        { 1.234321234321234e35L, "1.234321e+35" },
+        { 1.234321234321234e36L, "1.234321e+36" }
+      };
+    size_t k;
+    for (k = 0; k < SIZEOF (data); k++)
+      {
+        char result[100];
+        int retval =
+          my_snprintf (result, sizeof (result), "%Le", data[k].value);
+        const char *expected = data[k].string;
+        ASSERT (strcmp (result, expected) == 0
+                /* Some implementations produce exponents with 3 digits.  */
+                || (strlen (result) == strlen (expected) + 1
+                    && memcmp (result, expected, strlen (expected) - 2) == 0
+                    && result[strlen (expected) - 2] == '0'
+                    && strcmp (result + strlen (expected) - 1,
+                               expected + strlen (expected) - 2)
+                       == 0));
+        ASSERT (retval == strlen (result));
+      }
+  }
+
+  { /* A negative number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Le %d", -0.03125L, 33, 44, 55);
+    ASSERT (strcmp (result, "-3.125000e-02 33") == 0
+            || strcmp (result, "-3.125000e-002 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Le %d", 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "0.000000e+00 33") == 0
+            || strcmp (result, "0.000000e+000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Le %d", minus_zerol, 33, 44, 55);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0.000000e+00 33") == 0
+              || strcmp (result, "-0.000000e+000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Le %d", 1.0L / 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "inf 33") == 0
+            || strcmp (result, "infinity 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Le %d", -1.0L / 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "-inf 33") == 0
+            || strcmp (result, "-infinity 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* NaN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Le %d", NaNl (), 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+#if CHECK_PRINTF_SAFE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_))
+  { /* Quiet NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Le %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  {
+    /* Signalling NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Le %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities,
+     Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in
+       Intel IA-64 Architecture Software Developer's Manual, Volume 1:
+       Application Architecture.
+       Table 5-2 "Floating-Point Register Encodings"
+       Figure 5-6 "Memory to Floating-Point Register Data Translation"
+   */
+  { /* Pseudo-NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Le %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  { /* Pseudo-Infinity.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Le %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  { /* Pseudo-Zero.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Le %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  { /* Unnormalized number.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Le %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  { /* Pseudo-Denormal.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Le %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+#endif
+
+  { /* Width.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%15Le %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "   1.750000e+00 33") == 0
+            || strcmp (result, "  1.750000e+000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_LEFT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%-15Le %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "1.750000e+00    33") == 0
+            || strcmp (result, "1.750000e+000   33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_SHOWSIGN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%+Le %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "+1.750000e+00 33") == 0
+            || strcmp (result, "+1.750000e+000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_SPACE.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "% Le %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, " 1.750000e+00 33") == 0
+            || strcmp (result, " 1.750000e+000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#Le %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "1.750000e+00 33") == 0
+            || strcmp (result, "1.750000e+000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#.Le %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "2.e+00 33") == 0
+            || strcmp (result, "2.e+000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#.Le %d", 9.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "1.e+01 33") == 0
+            || strcmp (result, "1.e+001 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with finite number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%015Le %d", 1234.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "0001.234000e+03 33") == 0
+            || strcmp (result, "001.234000e+003 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with infinite number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%015Le %d", -1.0L / 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "           -inf 33") == 0
+            || strcmp (result, "      -infinity 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with NaN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%050Le %d", NaNl (), 33, 44, 55);
+    ASSERT (strlen (result) == 50 + 3
+            && strisnan (result, strspn (result, " "), strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.Le %d", 1234.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "1e+03 33") == 0
+            || strcmp (result, "1e+003 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision with no rounding.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.4Le %d", 999.951L, 33, 44, 55);
+    ASSERT (strcmp (result, "9.9995e+02 33") == 0
+            || strcmp (result, "9.9995e+002 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision with rounding.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.4Le %d", 999.996L, 33, 44, 55);
+    ASSERT (strcmp (result, "1.0000e+03 33") == 0
+            || strcmp (result, "1.0000e+003 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  /* Test the support of the %g format directive.  */
+
+  { /* A positive number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%g %d", 12.75, 33, 44, 55);
+    ASSERT (strcmp (result, "12.75 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* A larger positive number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%g %d", 1234567.0, 33, 44, 55);
+    ASSERT (strcmp (result, "1.23457e+06 33") == 0
+            || strcmp (result, "1.23457e+006 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Small and large positive numbers.  */
+    static struct { double value; const char *string; } data[] =
+      {
+        { 1.234321234321234e-37, "1.23432e-37" },
+        { 1.234321234321234e-36, "1.23432e-36" },
+        { 1.234321234321234e-35, "1.23432e-35" },
+        { 1.234321234321234e-34, "1.23432e-34" },
+        { 1.234321234321234e-33, "1.23432e-33" },
+        { 1.234321234321234e-32, "1.23432e-32" },
+        { 1.234321234321234e-31, "1.23432e-31" },
+        { 1.234321234321234e-30, "1.23432e-30" },
+        { 1.234321234321234e-29, "1.23432e-29" },
+        { 1.234321234321234e-28, "1.23432e-28" },
+        { 1.234321234321234e-27, "1.23432e-27" },
+        { 1.234321234321234e-26, "1.23432e-26" },
+        { 1.234321234321234e-25, "1.23432e-25" },
+        { 1.234321234321234e-24, "1.23432e-24" },
+        { 1.234321234321234e-23, "1.23432e-23" },
+        { 1.234321234321234e-22, "1.23432e-22" },
+        { 1.234321234321234e-21, "1.23432e-21" },
+        { 1.234321234321234e-20, "1.23432e-20" },
+        { 1.234321234321234e-19, "1.23432e-19" },
+        { 1.234321234321234e-18, "1.23432e-18" },
+        { 1.234321234321234e-17, "1.23432e-17" },
+        { 1.234321234321234e-16, "1.23432e-16" },
+        { 1.234321234321234e-15, "1.23432e-15" },
+        { 1.234321234321234e-14, "1.23432e-14" },
+        { 1.234321234321234e-13, "1.23432e-13" },
+        { 1.234321234321234e-12, "1.23432e-12" },
+        { 1.234321234321234e-11, "1.23432e-11" },
+        { 1.234321234321234e-10, "1.23432e-10" },
+        { 1.234321234321234e-9, "1.23432e-09" },
+        { 1.234321234321234e-8, "1.23432e-08" },
+        { 1.234321234321234e-7, "1.23432e-07" },
+        { 1.234321234321234e-6, "1.23432e-06" },
+        { 1.234321234321234e-5, "1.23432e-05" },
+        { 1.234321234321234e-4, "0.000123432" },
+        { 1.234321234321234e-3, "0.00123432" },
+        { 1.234321234321234e-2, "0.0123432" },
+        { 1.234321234321234e-1, "0.123432" },
+        { 1.234321234321234, "1.23432" },
+        { 1.234321234321234e1, "12.3432" },
+        { 1.234321234321234e2, "123.432" },
+        { 1.234321234321234e3, "1234.32" },
+        { 1.234321234321234e4, "12343.2" },
+        { 1.234321234321234e5, "123432" },
+        { 1.234321234321234e6, "1.23432e+06" },
+        { 1.234321234321234e7, "1.23432e+07" },
+        { 1.234321234321234e8, "1.23432e+08" },
+        { 1.234321234321234e9, "1.23432e+09" },
+        { 1.234321234321234e10, "1.23432e+10" },
+        { 1.234321234321234e11, "1.23432e+11" },
+        { 1.234321234321234e12, "1.23432e+12" },
+        { 1.234321234321234e13, "1.23432e+13" },
+        { 1.234321234321234e14, "1.23432e+14" },
+        { 1.234321234321234e15, "1.23432e+15" },
+        { 1.234321234321234e16, "1.23432e+16" },
+        { 1.234321234321234e17, "1.23432e+17" },
+        { 1.234321234321234e18, "1.23432e+18" },
+        { 1.234321234321234e19, "1.23432e+19" },
+        { 1.234321234321234e20, "1.23432e+20" },
+        { 1.234321234321234e21, "1.23432e+21" },
+        { 1.234321234321234e22, "1.23432e+22" },
+        { 1.234321234321234e23, "1.23432e+23" },
+        { 1.234321234321234e24, "1.23432e+24" },
+        { 1.234321234321234e25, "1.23432e+25" },
+        { 1.234321234321234e26, "1.23432e+26" },
+        { 1.234321234321234e27, "1.23432e+27" },
+        { 1.234321234321234e28, "1.23432e+28" },
+        { 1.234321234321234e29, "1.23432e+29" },
+        { 1.234321234321234e30, "1.23432e+30" },
+        { 1.234321234321234e31, "1.23432e+31" },
+        { 1.234321234321234e32, "1.23432e+32" },
+        { 1.234321234321234e33, "1.23432e+33" },
+        { 1.234321234321234e34, "1.23432e+34" },
+        { 1.234321234321234e35, "1.23432e+35" },
+        { 1.234321234321234e36, "1.23432e+36" }
+      };
+    size_t k;
+    for (k = 0; k < SIZEOF (data); k++)
+      {
+        char result[100];
+        int retval =
+          my_snprintf (result, sizeof (result), "%g", data[k].value);
+        const char *expected = data[k].string;
+        ASSERT (strcmp (result, expected) == 0
+                /* Some implementations produce exponents with 3 digits.  */
+                || (expected[strlen (expected) - 4] == 'e'
+                    && strlen (result) == strlen (expected) + 1
+                    && memcmp (result, expected, strlen (expected) - 2) == 0
+                    && result[strlen (expected) - 2] == '0'
+                    && strcmp (result + strlen (expected) - 1,
+                               expected + strlen (expected) - 2)
+                       == 0));
+        ASSERT (retval == strlen (result));
+      }
+  }
+
+  { /* A negative number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%g %d", -0.03125, 33, 44, 55);
+    ASSERT (strcmp (result, "-0.03125 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%g %d", 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "0 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%g %d", -zerod, 33, 44, 55);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%g %d", 1.0 / 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "inf 33") == 0
+            || strcmp (result, "infinity 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%g %d", -1.0 / 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "-inf 33") == 0
+            || strcmp (result, "-infinity 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* NaN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%g %d", NaNd (), 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Width.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%10g %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "      1.75 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_LEFT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%-10g %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "1.75       33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_SHOWSIGN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%+g %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "+1.75 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_SPACE.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "% g %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, " 1.75 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#g %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "1.75000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#.g %d", 1.75, 33, 44, 55);
+    ASSERT (strcmp (result, "2. 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#.g %d", 9.75, 33, 44, 55);
+    ASSERT (strcmp (result, "1.e+01 33") == 0
+            || strcmp (result, "1.e+001 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with finite number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%010g %d", 1234.0, 33, 44, 55);
+    ASSERT (strcmp (result, "0000001234 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with infinite number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%015g %d", -1.0 / 0.0, 33, 44, 55);
+    ASSERT (strcmp (result, "           -inf 33") == 0
+            || strcmp (result, "      -infinity 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with NaN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%050g %d", NaNd (), 33, 44, 55);
+    ASSERT (strlen (result) == 50 + 3
+            && strisnan (result, strspn (result, " "), strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.g %d", 1234.0, 33, 44, 55);
+    ASSERT (strcmp (result, "1e+03 33") == 0
+            || strcmp (result, "1e+003 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision with no rounding.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.5g %d", 999.951, 33, 44, 55);
+    ASSERT (strcmp (result, "999.95 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision with rounding.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.5g %d", 999.996, 33, 44, 55);
+    ASSERT (strcmp (result, "1000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* A positive number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lg %d", 12.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "12.75 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* A larger positive number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lg %d", 1234567.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "1.23457e+06 33") == 0
+            || strcmp (result, "1.23457e+006 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Small and large positive numbers.  */
+    static struct { long double value; const char *string; } data[] =
+      {
+        { 1.234321234321234e-37L, "1.23432e-37" },
+        { 1.234321234321234e-36L, "1.23432e-36" },
+        { 1.234321234321234e-35L, "1.23432e-35" },
+        { 1.234321234321234e-34L, "1.23432e-34" },
+        { 1.234321234321234e-33L, "1.23432e-33" },
+        { 1.234321234321234e-32L, "1.23432e-32" },
+        { 1.234321234321234e-31L, "1.23432e-31" },
+        { 1.234321234321234e-30L, "1.23432e-30" },
+        { 1.234321234321234e-29L, "1.23432e-29" },
+        { 1.234321234321234e-28L, "1.23432e-28" },
+        { 1.234321234321234e-27L, "1.23432e-27" },
+        { 1.234321234321234e-26L, "1.23432e-26" },
+        { 1.234321234321234e-25L, "1.23432e-25" },
+        { 1.234321234321234e-24L, "1.23432e-24" },
+        { 1.234321234321234e-23L, "1.23432e-23" },
+        { 1.234321234321234e-22L, "1.23432e-22" },
+        { 1.234321234321234e-21L, "1.23432e-21" },
+        { 1.234321234321234e-20L, "1.23432e-20" },
+        { 1.234321234321234e-19L, "1.23432e-19" },
+        { 1.234321234321234e-18L, "1.23432e-18" },
+        { 1.234321234321234e-17L, "1.23432e-17" },
+        { 1.234321234321234e-16L, "1.23432e-16" },
+        { 1.234321234321234e-15L, "1.23432e-15" },
+        { 1.234321234321234e-14L, "1.23432e-14" },
+        { 1.234321234321234e-13L, "1.23432e-13" },
+        { 1.234321234321234e-12L, "1.23432e-12" },
+        { 1.234321234321234e-11L, "1.23432e-11" },
+        { 1.234321234321234e-10L, "1.23432e-10" },
+        { 1.234321234321234e-9L, "1.23432e-09" },
+        { 1.234321234321234e-8L, "1.23432e-08" },
+        { 1.234321234321234e-7L, "1.23432e-07" },
+        { 1.234321234321234e-6L, "1.23432e-06" },
+        { 1.234321234321234e-5L, "1.23432e-05" },
+        { 1.234321234321234e-4L, "0.000123432" },
+        { 1.234321234321234e-3L, "0.00123432" },
+        { 1.234321234321234e-2L, "0.0123432" },
+        { 1.234321234321234e-1L, "0.123432" },
+        { 1.234321234321234L, "1.23432" },
+        { 1.234321234321234e1L, "12.3432" },
+        { 1.234321234321234e2L, "123.432" },
+        { 1.234321234321234e3L, "1234.32" },
+        { 1.234321234321234e4L, "12343.2" },
+        { 1.234321234321234e5L, "123432" },
+        { 1.234321234321234e6L, "1.23432e+06" },
+        { 1.234321234321234e7L, "1.23432e+07" },
+        { 1.234321234321234e8L, "1.23432e+08" },
+        { 1.234321234321234e9L, "1.23432e+09" },
+        { 1.234321234321234e10L, "1.23432e+10" },
+        { 1.234321234321234e11L, "1.23432e+11" },
+        { 1.234321234321234e12L, "1.23432e+12" },
+        { 1.234321234321234e13L, "1.23432e+13" },
+        { 1.234321234321234e14L, "1.23432e+14" },
+        { 1.234321234321234e15L, "1.23432e+15" },
+        { 1.234321234321234e16L, "1.23432e+16" },
+        { 1.234321234321234e17L, "1.23432e+17" },
+        { 1.234321234321234e18L, "1.23432e+18" },
+        { 1.234321234321234e19L, "1.23432e+19" },
+        { 1.234321234321234e20L, "1.23432e+20" },
+        { 1.234321234321234e21L, "1.23432e+21" },
+        { 1.234321234321234e22L, "1.23432e+22" },
+        { 1.234321234321234e23L, "1.23432e+23" },
+        { 1.234321234321234e24L, "1.23432e+24" },
+        { 1.234321234321234e25L, "1.23432e+25" },
+        { 1.234321234321234e26L, "1.23432e+26" },
+        { 1.234321234321234e27L, "1.23432e+27" },
+        { 1.234321234321234e28L, "1.23432e+28" },
+        { 1.234321234321234e29L, "1.23432e+29" },
+        { 1.234321234321234e30L, "1.23432e+30" },
+        { 1.234321234321234e31L, "1.23432e+31" },
+        { 1.234321234321234e32L, "1.23432e+32" },
+        { 1.234321234321234e33L, "1.23432e+33" },
+        { 1.234321234321234e34L, "1.23432e+34" },
+        { 1.234321234321234e35L, "1.23432e+35" },
+        { 1.234321234321234e36L, "1.23432e+36" }
+      };
+    size_t k;
+    for (k = 0; k < SIZEOF (data); k++)
+      {
+        char result[100];
+        int retval =
+          my_snprintf (result, sizeof (result), "%Lg", data[k].value);
+        const char *expected = data[k].string;
+        ASSERT (strcmp (result, expected) == 0
+                /* Some implementations produce exponents with 3 digits.  */
+                || (expected[strlen (expected) - 4] == 'e'
+                    && strlen (result) == strlen (expected) + 1
+                    && memcmp (result, expected, strlen (expected) - 2) == 0
+                    && result[strlen (expected) - 2] == '0'
+                    && strcmp (result + strlen (expected) - 1,
+                               expected + strlen (expected) - 2)
+                       == 0));
+        ASSERT (retval == strlen (result));
+      }
+  }
+
+  { /* A negative number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lg %d", -0.03125L, 33, 44, 55);
+    ASSERT (strcmp (result, "-0.03125 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lg %d", 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "0 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative zero.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lg %d", minus_zerol, 33, 44, 55);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Positive infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lg %d", 1.0L / 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "inf 33") == 0
+            || strcmp (result, "infinity 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Negative infinity.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lg %d", -1.0L / 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "-inf 33") == 0
+            || strcmp (result, "-infinity 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* NaN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lg %d", NaNl (), 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+#if CHECK_PRINTF_SAFE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_))
+  { /* Quiet NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lg %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  {
+    /* Signalling NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lg %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities,
+     Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in
+       Intel IA-64 Architecture Software Developer's Manual, Volume 1:
+       Application Architecture.
+       Table 5-2 "Floating-Point Register Encodings"
+       Figure 5-6 "Memory to Floating-Point Register Data Translation"
+   */
+  { /* Pseudo-NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lg %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  { /* Pseudo-Infinity.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lg %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  { /* Pseudo-Zero.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lg %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  { /* Unnormalized number.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lg %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+  { /* Pseudo-Denormal.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) };
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%Lg %d", x.value, 33, 44, 55);
+    ASSERT (strlen (result) >= 3 + 3
+            && strisnan (result, 0, strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+#endif
+
+  { /* Width.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%10Lg %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "      1.75 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_LEFT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%-10Lg %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "1.75       33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_SHOWSIGN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%+Lg %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "+1.75 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_SPACE.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "% Lg %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, " 1.75 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#Lg %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "1.75000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#.Lg %d", 1.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "2. 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ALT.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#.Lg %d", 9.75L, 33, 44, 55);
+    ASSERT (strcmp (result, "1.e+01 33") == 0
+            || strcmp (result, "1.e+001 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with finite number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%010Lg %d", 1234.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "0000001234 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with infinite number.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%015Lg %d", -1.0L / 0.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "           -inf 33") == 0
+            || strcmp (result, "      -infinity 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* FLAG_ZERO with NaN.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%050Lg %d", NaNl (), 33, 44, 55);
+    ASSERT (strlen (result) == 50 + 3
+            && strisnan (result, strspn (result, " "), strlen (result) - 3, 0)
+            && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.Lg %d", 1234.0L, 33, 44, 55);
+    ASSERT (strcmp (result, "1e+03 33") == 0
+            || strcmp (result, "1e+003 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision with no rounding.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.5Lg %d", 999.951L, 33, 44, 55);
+    ASSERT (strcmp (result, "999.95 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  { /* Precision with rounding.  */
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.5Lg %d", 999.996L, 33, 44, 55);
+    ASSERT (strcmp (result, "1000 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  /* Test the support of the %n format directive.  */
+
+  {
+    int count = -1;
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%d %n", 123, &count, 33, 44, 55);
+    ASSERT (strcmp (result, "123 ") == 0);
+    ASSERT (retval == strlen (result));
+    ASSERT (count == 4);
+  }
+
+  /* Test the support of the POSIX/XSI format strings with positions.  */
+
+  {
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%2$d %1$d", 33, 55);
+    ASSERT (strcmp (result, "55 33") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  /* Test the support of the grouping flag.  */
+
+  {
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "%'d %d", 1234567, 99);
+    ASSERT (result[strlen (result) - 1] == '9');
+    ASSERT (retval == strlen (result));
+  }
+
+  /* Test the support of the left-adjust flag.  */
+
+  {
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "a%*sc", -3, "b");
+    ASSERT (strcmp (result, "ab  c") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  {
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "a%-*sc", 3, "b");
+    ASSERT (strcmp (result, "ab  c") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  {
+    char result[100];
+    int retval =
+      my_snprintf (result, sizeof (result), "a%-*sc", -3, "b");
+    ASSERT (strcmp (result, "ab  c") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  /* Test the support of large precision.  */
+
+  {
+    char result[5000];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.4000d %d", 1234567, 99);
+    size_t i;
+    for (i = 0; i < 4000 - 7; i++)
+      ASSERT (result[i] == '0');
+    ASSERT (strcmp (result + 4000 - 7, "1234567 99") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  {
+    char result[5000];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.*d %d", 4000, 1234567, 99);
+    size_t i;
+    for (i = 0; i < 4000 - 7; i++)
+      ASSERT (result[i] == '0');
+    ASSERT (strcmp (result + 4000 - 7, "1234567 99") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  {
+    char result[5000];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.4000d %d", -1234567, 99);
+    size_t i;
+    ASSERT (result[0] == '-');
+    for (i = 0; i < 4000 - 7; i++)
+      ASSERT (result[1 + i] == '0');
+    ASSERT (strcmp (result + 1 + 4000 - 7, "1234567 99") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  {
+    char result[5000];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.4000u %d", 1234567, 99);
+    size_t i;
+    for (i = 0; i < 4000 - 7; i++)
+      ASSERT (result[i] == '0');
+    ASSERT (strcmp (result + 4000 - 7, "1234567 99") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  {
+    char result[5000];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.4000o %d", 1234567, 99);
+    size_t i;
+    for (i = 0; i < 4000 - 7; i++)
+      ASSERT (result[i] == '0');
+    ASSERT (strcmp (result + 4000 - 7, "4553207 99") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  {
+    char result[5000];
+    int retval =
+      my_snprintf (result, sizeof (result), "%.4000x %d", 1234567, 99);
+    size_t i;
+    for (i = 0; i < 4000 - 6; i++)
+      ASSERT (result[i] == '0');
+    ASSERT (strcmp (result + 4000 - 6, "12d687 99") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  {
+    char result[5000];
+    int retval =
+      my_snprintf (result, sizeof (result), "%#.4000x %d", 1234567, 99);
+    size_t i;
+    ASSERT (result[0] == '0');
+    ASSERT (result[1] == 'x');
+    for (i = 0; i < 4000 - 6; i++)
+      ASSERT (result[2 + i] == '0');
+    ASSERT (strcmp (result + 2 + 4000 - 6, "12d687 99") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  {
+    char input[5000];
+    char result[5000];
+    int retval;
+    size_t i;
+
+    for (i = 0; i < sizeof (input) - 1; i++)
+      input[i] = 'a' + ((1000000 / (i + 1)) % 26);
+    input[i] = '\0';
+    retval = my_snprintf (result, sizeof (result), "%.4000s %d", input, 99);
+    ASSERT (memcmp (result, input, 4000) == 0);
+    ASSERT (strcmp (result + 4000, " 99") == 0);
+    ASSERT (retval == strlen (result));
+  }
+
+  /* Test the support of the %s format directive.  */
+
+  /* To verify that these tests succeed, it is necessary to run them under
+     a tool that checks against invalid memory accesses, such as ElectricFence
+     or "valgrind --tool=memcheck".  */
+  {
+    size_t i;
+
+    for (i = 1; i <= 8; i++)
+      {
+        char *block;
+        char result[5000];
+        int retval;
+
+        block = (char *) malloc (i);
+        memcpy (block, "abcdefgh", i);
+        retval = my_snprintf (result, sizeof (result), "%.*s", (int) i, block);
+        ASSERT (memcmp (result, block, i) == 0);
+        ASSERT (result[i] == '\0');
+        ASSERT (retval == strlen (result));
+        free (block);
+      }
+  }
+#if HAVE_WCHAR_T
+  {
+    size_t i;
+
+    for (i = 1; i <= 8; i++)
+      {
+        wchar_t *block;
+        size_t j;
+        char result[5000];
+        int retval;
+
+        block = (wchar_t *) malloc (i * sizeof (wchar_t));
+        for (j = 0; j < i; j++)
+          block[j] = "abcdefgh"[j];
+        retval = my_snprintf (result, sizeof (result), "%.*ls", (int) i, block);
+        ASSERT (memcmp (result, "abcdefgh", i) == 0);
+        ASSERT (result[i] == '\0');
+        ASSERT (retval == strlen (result));
+        free (block);
+      }
+  }
+#endif
+}
diff --git a/libmissing/tests/test-symlink.c b/libmissing/tests/test-symlink.c
index 2369773..d2df54c 100644
--- a/libmissing/tests/test-symlink.c
+++ b/libmissing/tests/test-symlink.c
@@ -30,6 +30,7 @@ SIGNATURE_CHECK (symlink, int, (char const *, char const *));
 #include <stdlib.h>
 #include <sys/stat.h>
 
+#include "ignore-value.h"
 #include "macros.h"
 
 #define BASE "test-symlink.t"
@@ -40,7 +41,7 @@ int
 main (void)
 {
   /* Remove any leftovers from a previous partial run.  */
-  system ("rm -rf " BASE "*");
+  ignore_value (system ("rm -rf " BASE "*"));
 
   return test_symlink (symlink, true);
 }
diff --git a/libmissing/tests/test-vsnprintf-posix.c b/libmissing/tests/test-vsnprintf-posix.c
new file mode 100644
index 0000000..8de5755
--- /dev/null
+++ b/libmissing/tests/test-vsnprintf-posix.c
@@ -0,0 +1,51 @@
+/* Test of POSIX compatible vsnprintf() function.
+   Copyright (C) 2007-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2007.  */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <float.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "macros.h"
+
+#include "test-snprintf-posix.h"
+
+static int
+my_snprintf (char *str, size_t size, const char *format, ...)
+{
+  va_list args;
+  int ret;
+
+  va_start (args, format);
+  ret = vsnprintf (str, size, format, args);
+  va_end (args);
+  return ret;
+}
+
+int
+main (int argc, char *argv[])
+{
+  test_function (my_snprintf);
+  return 0;
+}

--===============1472291964296053651==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
Prelude-cvslog site list
[email protected]
http://lists.prelude-technologies.com/mailman/listinfo/prelude-cvslog
--===============1472291964296053651==--