prelude-lml/master: Various type sanitization

[email protected] Mon, 8 Feb 2010 11:24:49 +0100 (CET)
Newsgroups gmane.comp.security.ids.prelude.cvs
Message-ID <[email protected]>
--===============2523211104120890310==
Content-type: text

commit 84e5a4bbbef685af1bdffeb91fdaba18fe696a8b
Author: Yoann Vandoorselaere <[email protected]>
Date:   Mon Feb 8 11:04:22 2010 +0100

    Various type sanitization
    
    Type sanitization, simplify get_max_rotation_(time|size)(), use appropriate
    snprintf() facility to print off_t / time_t, use fseeko and ftello variant
    which directly handle off_t, and might fixes some problem with large file.
    
    Allow user to use K/M suffixes when specifying max-rotation-size-offset.


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

 libmissing/Makefile.am                 |  226 +++-
 libmissing/fpucw.h                     |  107 ++
 libmissing/frexp.c                     |  166 ++
 libmissing/frexpl.c                    |   18 +
 libmissing/imaxabs.c                   |   26 +
 libmissing/inttypes.in.h               | 1103 +++++++++++
 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/gnulib-cache.m4          |    4 +-
 libmissing/m4/gnulib-comp.m4           |   81 +
 libmissing/m4/imaxabs.m4               |   17 +
 libmissing/m4/inttypes-pri.m4          |   36 +
 libmissing/m4/inttypes.m4              |  302 +++
 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/signbit.m4               |  287 +++
 libmissing/m4/snprintf-posix.m4        |  126 ++
 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/signbitd.c                  |   64 +
 libmissing/signbitf.c                  |   64 +
 libmissing/signbitl.c                  |   64 +
 libmissing/tests/Makefile.am           |   95 +
 libmissing/tests/nan.h                 |   60 +
 libmissing/tests/test-frexp.c          |  199 ++
 libmissing/tests/test-frexpl.c         |  223 +++
 libmissing/tests/test-inttypes.c       |  121 ++
 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-math.c           |   53 +
 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 ++++++++++++++++++++++++++++++++
 prelude-lml.conf.in                    |    7 +-
 src/file-server.c                      |   94 +-
 src/include/file-server.h              |    8 +-
 src/lml-options.c                      |   32 +-
 63 files changed, 10304 insertions(+), 67 deletions(-)

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

diff --git a/libmissing/Makefile.am b/libmissing/Makefile.am
index fa93cc5..0f7a1e4 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 bind close fnmatch-gnu getaddrinfo glob iconv inet_ntop ioctl mktime nl_langinfo pathmax recvfrom servent sigaction sleep snprintf socket socklen strptime strsep sys_select
+# 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 bind close fnmatch-gnu getaddrinfo glob iconv imaxabs inet_ntop ioctl mktime nl_langinfo pathmax recvfrom servent sigaction sleep snprintf snprintf-posix socket socklen strptime strsep sys_select
 
 AUTOMAKE_OPTIONS = 1.5 gnits
 
@@ -337,6 +337,31 @@ EXTRA_libmissing_la_SOURCES += fnmatch.c fnmatch_loop.c
 
 ## end   gnulib module fnmatch
 
+## 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 getaddrinfo
 
 
@@ -399,6 +424,15 @@ EXTRA_DIST += $(top_srcdir)/./config.rpath
 
 ## end   gnulib module havelib
 
+## begin gnulib module imaxabs
+
+
+EXTRA_DIST += imaxabs.c
+
+EXTRA_libmissing_la_SOURCES += imaxabs.c
+
+## end   gnulib module imaxabs
+
 ## begin gnulib module inet_ntop
 
 
@@ -408,6 +442,47 @@ EXTRA_libmissing_la_SOURCES += inet_ntop.c
 
 ## end   gnulib module inet_ntop
 
+## begin gnulib module inttypes
+
+BUILT_SOURCES += inttypes.h
+
+# We need the following in order to create <inttypes.h> when the system
+# doesn't have one that works with the given compiler.
+inttypes.h: inttypes.in.h $(WARN_ON_USE_H) $(ARG_NONNULL_H)
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  sed -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''NEXT_INTTYPES_H''@|$(NEXT_INTTYPES_H)|g' \
+	      -e 's/@''PRI_MACROS_BROKEN''@/$(PRI_MACROS_BROKEN)/g' \
+	      -e 's/@''APPLE_UNIVERSAL_BUILD''@/$(APPLE_UNIVERSAL_BUILD)/g' \
+	      -e 's/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \
+	      -e 's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/g' \
+	      -e 's/@''PRIPTR_PREFIX''@/$(PRIPTR_PREFIX)/g' \
+	      -e 's/@''GNULIB_IMAXABS''@/$(GNULIB_IMAXABS)/g' \
+	      -e 's/@''GNULIB_IMAXDIV''@/$(GNULIB_IMAXDIV)/g' \
+	      -e 's/@''GNULIB_STRTOIMAX''@/$(GNULIB_STRTOIMAX)/g' \
+	      -e 's/@''GNULIB_STRTOUMAX''@/$(GNULIB_STRTOUMAX)/g' \
+	      -e 's/@''HAVE_DECL_IMAXABS''@/$(HAVE_DECL_IMAXABS)/g' \
+	      -e 's/@''HAVE_DECL_IMAXDIV''@/$(HAVE_DECL_IMAXDIV)/g' \
+	      -e 's/@''HAVE_DECL_STRTOIMAX''@/$(HAVE_DECL_STRTOIMAX)/g' \
+	      -e 's/@''HAVE_DECL_STRTOUMAX''@/$(HAVE_DECL_STRTOUMAX)/g' \
+	      -e 's/@''INT32_MAX_LT_INTMAX_MAX''@/$(INT32_MAX_LT_INTMAX_MAX)/g' \
+	      -e 's/@''INT64_MAX_EQ_LONG_MAX''@/$(INT64_MAX_EQ_LONG_MAX)/g' \
+	      -e 's/@''UINT32_MAX_LT_UINTMAX_MAX''@/$(UINT32_MAX_LT_UINTMAX_MAX)/g' \
+	      -e 's/@''UINT64_MAX_EQ_ULONG_MAX''@/$(UINT64_MAX_EQ_ULONG_MAX)/g' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+	      < $(srcdir)/inttypes.in.h; \
+	} > $@-t && \
+	mv $@-t $@
+MOSTLYCLEANFILES += inttypes.h inttypes.h-t
+
+EXTRA_DIST += inttypes.in.h
+
+## end   gnulib module inttypes
+
 ## begin gnulib module ioctl
 
 
@@ -417,6 +492,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
@@ -528,6 +630,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
 
 
@@ -651,6 +848,24 @@ EXTRA_DIST += pathmax.h
 
 ## end   gnulib module pathmax
 
+## 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 recvfrom
 
 
@@ -701,6 +916,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
 
 
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/imaxabs.c b/libmissing/imaxabs.c
new file mode 100644
index 0000000..f7139ee
--- /dev/null
+++ b/libmissing/imaxabs.c
@@ -0,0 +1,26 @@
+/* imaxabs() function: absolute value of 'intmax_t'.
+   Copyright (C) 2006, 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 <inttypes.h>
+
+intmax_t
+imaxabs (intmax_t x)
+{
+  return (x >= 0 ? x : - x);
+}
diff --git a/libmissing/inttypes.in.h b/libmissing/inttypes.in.h
new file mode 100644
index 0000000..2da9515
--- /dev/null
+++ b/libmissing/inttypes.in.h
@@ -0,0 +1,1103 @@
+/* Copyright (C) 2006-2010 Free Software Foundation, Inc.
+   Written by Paul Eggert, Bruno Haible, Derek Price.
+   This file is part of gnulib.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 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/>.  */
+
+/*
+ * ISO C 99 <inttypes.h> for platforms that lack it.
+ * <http://www.opengroup.org/susv3xbd/inttypes.h.html>
+ */
+
+/* Include the original <inttypes.h> if it exists, and if this file
+   has not been included yet or if this file includes gnulib stdint.h
+   which in turn includes this file.
+   The include_next requires a split double-inclusion guard.  */
+#if ! defined INTTYPES_H || defined _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H
+# if @HAVE_INTTYPES_H@
+#  if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#  endif
+#  @INCLUDE_NEXT@ @NEXT_INTTYPES_H@
+# endif
+#endif
+
+#if ! defined INTTYPES_H && ! defined _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H
+#define INTTYPES_H
+
+/* Include <stdint.h> or the gnulib replacement.
+   But avoid namespace pollution on glibc systems.  */
+#ifndef __GLIBC__
+# include <stdint.h>
+#endif
+/* Get CHAR_BIT.  */
+#include <limits.h>
+
+#if !(INT_MIN == INT32_MIN && INT_MAX == INT32_MAX)
+# error "This file assumes that 'int' has exactly 32 bits. Please report your platform and compiler to <[email protected]>."
+#endif
+
+/* The definition of _GL_ARG_NONNULL is copied here.  */
+
+/* The definition of _GL_WARN_ON_USE is copied here.  */
+
+/* 7.8.1 Macros for format specifiers */
+
+#if ! defined __cplusplus || defined __STDC_FORMAT_MACROS
+
+# if defined _TNS_R_TARGET
+   /* Tandem NonStop R series and compatible platforms released before
+      July 2005 support %Ld but not %lld.  */
+#  define _LONG_LONG_FORMAT_PREFIX "L"
+# else
+#  define _LONG_LONG_FORMAT_PREFIX "ll"
+# endif
+
+# if !defined PRId8 || @PRI_MACROS_BROKEN@
+#  undef PRId8
+#  ifdef INT8_MAX
+#   define PRId8 "d"
+#  endif
+# endif
+# if !defined PRIi8 || @PRI_MACROS_BROKEN@
+#  undef PRIi8
+#  ifdef INT8_MAX
+#   define PRIi8 "i"
+#  endif
+# endif
+# if !defined PRIo8 || @PRI_MACROS_BROKEN@
+#  undef PRIo8
+#  ifdef UINT8_MAX
+#   define PRIo8 "o"
+#  endif
+# endif
+# if !defined PRIu8 || @PRI_MACROS_BROKEN@
+#  undef PRIu8
+#  ifdef UINT8_MAX
+#   define PRIu8 "u"
+#  endif
+# endif
+# if !defined PRIx8 || @PRI_MACROS_BROKEN@
+#  undef PRIx8
+#  ifdef UINT8_MAX
+#   define PRIx8 "x"
+#  endif
+# endif
+# if !defined PRIX8 || @PRI_MACROS_BROKEN@
+#  undef PRIX8
+#  ifdef UINT8_MAX
+#   define PRIX8 "X"
+#  endif
+# endif
+# if !defined PRId16 || @PRI_MACROS_BROKEN@
+#  undef PRId16
+#  ifdef INT16_MAX
+#   define PRId16 "d"
+#  endif
+# endif
+# if !defined PRIi16 || @PRI_MACROS_BROKEN@
+#  undef PRIi16
+#  ifdef INT16_MAX
+#   define PRIi16 "i"
+#  endif
+# endif
+# if !defined PRIo16 || @PRI_MACROS_BROKEN@
+#  undef PRIo16
+#  ifdef UINT16_MAX
+#   define PRIo16 "o"
+#  endif
+# endif
+# if !defined PRIu16 || @PRI_MACROS_BROKEN@
+#  undef PRIu16
+#  ifdef UINT16_MAX
+#   define PRIu16 "u"
+#  endif
+# endif
+# if !defined PRIx16 || @PRI_MACROS_BROKEN@
+#  undef PRIx16
+#  ifdef UINT16_MAX
+#   define PRIx16 "x"
+#  endif
+# endif
+# if !defined PRIX16 || @PRI_MACROS_BROKEN@
+#  undef PRIX16
+#  ifdef UINT16_MAX
+#   define PRIX16 "X"
+#  endif
+# endif
+# if !defined PRId32 || @PRI_MACROS_BROKEN@
+#  undef PRId32
+#  ifdef INT32_MAX
+#   define PRId32 "d"
+#  endif
+# endif
+# if !defined PRIi32 || @PRI_MACROS_BROKEN@
+#  undef PRIi32
+#  ifdef INT32_MAX
+#   define PRIi32 "i"
+#  endif
+# endif
+# if !defined PRIo32 || @PRI_MACROS_BROKEN@
+#  undef PRIo32
+#  ifdef UINT32_MAX
+#   define PRIo32 "o"
+#  endif
+# endif
+# if !defined PRIu32 || @PRI_MACROS_BROKEN@
+#  undef PRIu32
+#  ifdef UINT32_MAX
+#   define PRIu32 "u"
+#  endif
+# endif
+# if !defined PRIx32 || @PRI_MACROS_BROKEN@
+#  undef PRIx32
+#  ifdef UINT32_MAX
+#   define PRIx32 "x"
+#  endif
+# endif
+# if !defined PRIX32 || @PRI_MACROS_BROKEN@
+#  undef PRIX32
+#  ifdef UINT32_MAX
+#   define PRIX32 "X"
+#  endif
+# endif
+# ifdef INT64_MAX
+#  if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @INT64_MAX_EQ_LONG_MAX@)
+#   define _PRI64_PREFIX "l"
+#  elif defined _MSC_VER || defined __MINGW32__
+#   define _PRI64_PREFIX "I64"
+#  elif @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1
+#   define _PRI64_PREFIX _LONG_LONG_FORMAT_PREFIX
+#  endif
+#  if !defined PRId64 || @PRI_MACROS_BROKEN@
+#   undef PRId64
+#   define PRId64 _PRI64_PREFIX "d"
+#  endif
+#  if !defined PRIi64 || @PRI_MACROS_BROKEN@
+#   undef PRIi64
+#   define PRIi64 _PRI64_PREFIX "i"
+#  endif
+# endif
+# ifdef UINT64_MAX
+#  if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @UINT64_MAX_EQ_ULONG_MAX@)
+#   define _PRIu64_PREFIX "l"
+#  elif defined _MSC_VER || defined __MINGW32__
+#   define _PRIu64_PREFIX "I64"
+#  elif @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1
+#   define _PRIu64_PREFIX _LONG_LONG_FORMAT_PREFIX
+#  endif
+#  if !defined PRIo64 || @PRI_MACROS_BROKEN@
+#   undef PRIo64
+#   define PRIo64 _PRIu64_PREFIX "o"
+#  endif
+#  if !defined PRIu64 || @PRI_MACROS_BROKEN@
+#   undef PRIu64
+#   define PRIu64 _PRIu64_PREFIX "u"
+#  endif
+#  if !defined PRIx64 || @PRI_MACROS_BROKEN@
+#   undef PRIx64
+#   define PRIx64 _PRIu64_PREFIX "x"
+#  endif
+#  if !defined PRIX64 || @PRI_MACROS_BROKEN@
+#   undef PRIX64
+#   define PRIX64 _PRIu64_PREFIX "X"
+#  endif
+# endif
+
+# if !defined PRIdLEAST8 || @PRI_MACROS_BROKEN@
+#  undef PRIdLEAST8
+#  define PRIdLEAST8 "d"
+# endif
+# if !defined PRIiLEAST8 || @PRI_MACROS_BROKEN@
+#  undef PRIiLEAST8
+#  define PRIiLEAST8 "i"
+# endif
+# if !defined PRIoLEAST8 || @PRI_MACROS_BROKEN@
+#  undef PRIoLEAST8
+#  define PRIoLEAST8 "o"
+# endif
+# if !defined PRIuLEAST8 || @PRI_MACROS_BROKEN@
+#  undef PRIuLEAST8
+#  define PRIuLEAST8 "u"
+# endif
+# if !defined PRIxLEAST8 || @PRI_MACROS_BROKEN@
+#  undef PRIxLEAST8
+#  define PRIxLEAST8 "x"
+# endif
+# if !defined PRIXLEAST8 || @PRI_MACROS_BROKEN@
+#  undef PRIXLEAST8
+#  define PRIXLEAST8 "X"
+# endif
+# if !defined PRIdLEAST16 || @PRI_MACROS_BROKEN@
+#  undef PRIdLEAST16
+#  define PRIdLEAST16 "d"
+# endif
+# if !defined PRIiLEAST16 || @PRI_MACROS_BROKEN@
+#  undef PRIiLEAST16
+#  define PRIiLEAST16 "i"
+# endif
+# if !defined PRIoLEAST16 || @PRI_MACROS_BROKEN@
+#  undef PRIoLEAST16
+#  define PRIoLEAST16 "o"
+# endif
+# if !defined PRIuLEAST16 || @PRI_MACROS_BROKEN@
+#  undef PRIuLEAST16
+#  define PRIuLEAST16 "u"
+# endif
+# if !defined PRIxLEAST16 || @PRI_MACROS_BROKEN@
+#  undef PRIxLEAST16
+#  define PRIxLEAST16 "x"
+# endif
+# if !defined PRIXLEAST16 || @PRI_MACROS_BROKEN@
+#  undef PRIXLEAST16
+#  define PRIXLEAST16 "X"
+# endif
+# if !defined PRIdLEAST32 || @PRI_MACROS_BROKEN@
+#  undef PRIdLEAST32
+#  define PRIdLEAST32 "d"
+# endif
+# if !defined PRIiLEAST32 || @PRI_MACROS_BROKEN@
+#  undef PRIiLEAST32
+#  define PRIiLEAST32 "i"
+# endif
+# if !defined PRIoLEAST32 || @PRI_MACROS_BROKEN@
+#  undef PRIoLEAST32
+#  define PRIoLEAST32 "o"
+# endif
+# if !defined PRIuLEAST32 || @PRI_MACROS_BROKEN@
+#  undef PRIuLEAST32
+#  define PRIuLEAST32 "u"
+# endif
+# if !defined PRIxLEAST32 || @PRI_MACROS_BROKEN@
+#  undef PRIxLEAST32
+#  define PRIxLEAST32 "x"
+# endif
+# if !defined PRIXLEAST32 || @PRI_MACROS_BROKEN@
+#  undef PRIXLEAST32
+#  define PRIXLEAST32 "X"
+# endif
+# ifdef INT64_MAX
+#  if !defined PRIdLEAST64 || @PRI_MACROS_BROKEN@
+#   undef PRIdLEAST64
+#   define PRIdLEAST64 PRId64
+#  endif
+#  if !defined PRIiLEAST64 || @PRI_MACROS_BROKEN@
+#   undef PRIiLEAST64
+#   define PRIiLEAST64 PRIi64
+#  endif
+# endif
+# ifdef UINT64_MAX
+#  if !defined PRIoLEAST64 || @PRI_MACROS_BROKEN@
+#   undef PRIoLEAST64
+#   define PRIoLEAST64 PRIo64
+#  endif
+#  if !defined PRIuLEAST64 || @PRI_MACROS_BROKEN@
+#   undef PRIuLEAST64
+#   define PRIuLEAST64 PRIu64
+#  endif
+#  if !defined PRIxLEAST64 || @PRI_MACROS_BROKEN@
+#   undef PRIxLEAST64
+#   define PRIxLEAST64 PRIx64
+#  endif
+#  if !defined PRIXLEAST64 || @PRI_MACROS_BROKEN@
+#   undef PRIXLEAST64
+#   define PRIXLEAST64 PRIX64
+#  endif
+# endif
+
+# if !defined PRIdFAST8 || @PRI_MACROS_BROKEN@
+#  undef PRIdFAST8
+#  if INT_FAST8_MAX > INT32_MAX
+#   define PRIdFAST8 PRId64
+#  else
+#   define PRIdFAST8 "d"
+#  endif
+# endif
+# if !defined PRIiFAST8 || @PRI_MACROS_BROKEN@
+#  undef PRIiFAST8
+#  if INT_FAST8_MAX > INT32_MAX
+#   define PRIiFAST8 PRIi64
+#  else
+#   define PRIiFAST8 "i"
+#  endif
+# endif
+# if !defined PRIoFAST8 || @PRI_MACROS_BROKEN@
+#  undef PRIoFAST8
+#  if UINT_FAST8_MAX > UINT32_MAX
+#   define PRIoFAST8 PRIo64
+#  else
+#   define PRIoFAST8 "o"
+#  endif
+# endif
+# if !defined PRIuFAST8 || @PRI_MACROS_BROKEN@
+#  undef PRIuFAST8
+#  if UINT_FAST8_MAX > UINT32_MAX
+#   define PRIuFAST8 PRIu64
+#  else
+#   define PRIuFAST8 "u"
+#  endif
+# endif
+# if !defined PRIxFAST8 || @PRI_MACROS_BROKEN@
+#  undef PRIxFAST8
+#  if UINT_FAST8_MAX > UINT32_MAX
+#   define PRIxFAST8 PRIx64
+#  else
+#   define PRIxFAST8 "x"
+#  endif
+# endif
+# if !defined PRIXFAST8 || @PRI_MACROS_BROKEN@
+#  undef PRIXFAST8
+#  if UINT_FAST8_MAX > UINT32_MAX
+#   define PRIXFAST8 PRIX64
+#  else
+#   define PRIXFAST8 "X"
+#  endif
+# endif
+# if !defined PRIdFAST16 || @PRI_MACROS_BROKEN@
+#  undef PRIdFAST16
+#  if INT_FAST16_MAX > INT32_MAX
+#   define PRIdFAST16 PRId64
+#  else
+#   define PRIdFAST16 "d"
+#  endif
+# endif
+# if !defined PRIiFAST16 || @PRI_MACROS_BROKEN@
+#  undef PRIiFAST16
+#  if INT_FAST16_MAX > INT32_MAX
+#   define PRIiFAST16 PRIi64
+#  else
+#   define PRIiFAST16 "i"
+#  endif
+# endif
+# if !defined PRIoFAST16 || @PRI_MACROS_BROKEN@
+#  undef PRIoFAST16
+#  if UINT_FAST16_MAX > UINT32_MAX
+#   define PRIoFAST16 PRIo64
+#  else
+#   define PRIoFAST16 "o"
+#  endif
+# endif
+# if !defined PRIuFAST16 || @PRI_MACROS_BROKEN@
+#  undef PRIuFAST16
+#  if UINT_FAST16_MAX > UINT32_MAX
+#   define PRIuFAST16 PRIu64
+#  else
+#   define PRIuFAST16 "u"
+#  endif
+# endif
+# if !defined PRIxFAST16 || @PRI_MACROS_BROKEN@
+#  undef PRIxFAST16
+#  if UINT_FAST16_MAX > UINT32_MAX
+#   define PRIxFAST16 PRIx64
+#  else
+#   define PRIxFAST16 "x"
+#  endif
+# endif
+# if !defined PRIXFAST16 || @PRI_MACROS_BROKEN@
+#  undef PRIXFAST16
+#  if UINT_FAST16_MAX > UINT32_MAX
+#   define PRIXFAST16 PRIX64
+#  else
+#   define PRIXFAST16 "X"
+#  endif
+# endif
+# if !defined PRIdFAST32 || @PRI_MACROS_BROKEN@
+#  undef PRIdFAST32
+#  if INT_FAST32_MAX > INT32_MAX
+#   define PRIdFAST32 PRId64
+#  else
+#   define PRIdFAST32 "d"
+#  endif
+# endif
+# if !defined PRIiFAST32 || @PRI_MACROS_BROKEN@
+#  undef PRIiFAST32
+#  if INT_FAST32_MAX > INT32_MAX
+#   define PRIiFAST32 PRIi64
+#  else
+#   define PRIiFAST32 "i"
+#  endif
+# endif
+# if !defined PRIoFAST32 || @PRI_MACROS_BROKEN@
+#  undef PRIoFAST32
+#  if UINT_FAST32_MAX > UINT32_MAX
+#   define PRIoFAST32 PRIo64
+#  else
+#   define PRIoFAST32 "o"
+#  endif
+# endif
+# if !defined PRIuFAST32 || @PRI_MACROS_BROKEN@
+#  undef PRIuFAST32
+#  if UINT_FAST32_MAX > UINT32_MAX
+#   define PRIuFAST32 PRIu64
+#  else
+#   define PRIuFAST32 "u"
+#  endif
+# endif
+# if !defined PRIxFAST32 || @PRI_MACROS_BROKEN@
+#  undef PRIxFAST32
+#  if UINT_FAST32_MAX > UINT32_MAX
+#   define PRIxFAST32 PRIx64
+#  else
+#   define PRIxFAST32 "x"
+#  endif
+# endif
+# if !defined PRIXFAST32 || @PRI_MACROS_BROKEN@
+#  undef PRIXFAST32
+#  if UINT_FAST32_MAX > UINT32_MAX
+#   define PRIXFAST32 PRIX64
+#  else
+#   define PRIXFAST32 "X"
+#  endif
+# endif
+# ifdef INT64_MAX
+#  if !defined PRIdFAST64 || @PRI_MACROS_BROKEN@
+#   undef PRIdFAST64
+#   define PRIdFAST64 PRId64
+#  endif
+#  if !defined PRIiFAST64 || @PRI_MACROS_BROKEN@
+#   undef PRIiFAST64
+#   define PRIiFAST64 PRIi64
+#  endif
+# endif
+# ifdef UINT64_MAX
+#  if !defined PRIoFAST64 || @PRI_MACROS_BROKEN@
+#   undef PRIoFAST64
+#   define PRIoFAST64 PRIo64
+#  endif
+#  if !defined PRIuFAST64 || @PRI_MACROS_BROKEN@
+#   undef PRIuFAST64
+#   define PRIuFAST64 PRIu64
+#  endif
+#  if !defined PRIxFAST64 || @PRI_MACROS_BROKEN@
+#   undef PRIxFAST64
+#   define PRIxFAST64 PRIx64
+#  endif
+#  if !defined PRIXFAST64 || @PRI_MACROS_BROKEN@
+#   undef PRIXFAST64
+#   define PRIXFAST64 PRIX64
+#  endif
+# endif
+
+# if !defined PRIdMAX || @PRI_MACROS_BROKEN@
+#  undef PRIdMAX
+#  if @INT32_MAX_LT_INTMAX_MAX@
+#   define PRIdMAX PRId64
+#  else
+#   define PRIdMAX "ld"
+#  endif
+# endif
+# if !defined PRIiMAX || @PRI_MACROS_BROKEN@
+#  undef PRIiMAX
+#  if @INT32_MAX_LT_INTMAX_MAX@
+#   define PRIiMAX PRIi64
+#  else
+#   define PRIiMAX "li"
+#  endif
+# endif
+# if !defined PRIoMAX || @PRI_MACROS_BROKEN@
+#  undef PRIoMAX
+#  if @UINT32_MAX_LT_UINTMAX_MAX@
+#   define PRIoMAX PRIo64
+#  else
+#   define PRIoMAX "lo"
+#  endif
+# endif
+# if !defined PRIuMAX || @PRI_MACROS_BROKEN@
+#  undef PRIuMAX
+#  if @UINT32_MAX_LT_UINTMAX_MAX@
+#   define PRIuMAX PRIu64
+#  else
+#   define PRIuMAX "lu"
+#  endif
+# endif
+# if !defined PRIxMAX || @PRI_MACROS_BROKEN@
+#  undef PRIxMAX
+#  if @UINT32_MAX_LT_UINTMAX_MAX@
+#   define PRIxMAX PRIx64
+#  else
+#   define PRIxMAX "lx"
+#  endif
+# endif
+# if !defined PRIXMAX || @PRI_MACROS_BROKEN@
+#  undef PRIXMAX
+#  if @UINT32_MAX_LT_UINTMAX_MAX@
+#   define PRIXMAX PRIX64
+#  else
+#   define PRIXMAX "lX"
+#  endif
+# endif
+
+# if !defined PRIdPTR || @PRI_MACROS_BROKEN@
+#  undef PRIdPTR
+#  ifdef INTPTR_MAX
+#   define PRIdPTR @PRIPTR_PREFIX@ "d"
+#  endif
+# endif
+# if !defined PRIiPTR || @PRI_MACROS_BROKEN@
+#  undef PRIiPTR
+#  ifdef INTPTR_MAX
+#   define PRIiPTR @PRIPTR_PREFIX@ "i"
+#  endif
+# endif
+# if !defined PRIoPTR || @PRI_MACROS_BROKEN@
+#  undef PRIoPTR
+#  ifdef UINTPTR_MAX
+#   define PRIoPTR @PRIPTR_PREFIX@ "o"
+#  endif
+# endif
+# if !defined PRIuPTR || @PRI_MACROS_BROKEN@
+#  undef PRIuPTR
+#  ifdef UINTPTR_MAX
+#   define PRIuPTR @PRIPTR_PREFIX@ "u"
+#  endif
+# endif
+# if !defined PRIxPTR || @PRI_MACROS_BROKEN@
+#  undef PRIxPTR
+#  ifdef UINTPTR_MAX
+#   define PRIxPTR @PRIPTR_PREFIX@ "x"
+#  endif
+# endif
+# if !defined PRIXPTR || @PRI_MACROS_BROKEN@
+#  undef PRIXPTR
+#  ifdef UINTPTR_MAX
+#   define PRIXPTR @PRIPTR_PREFIX@ "X"
+#  endif
+# endif
+
+# if !defined SCNd8 || @PRI_MACROS_BROKEN@
+#  undef SCNd8
+#  ifdef INT8_MAX
+#   define SCNd8 "hhd"
+#  endif
+# endif
+# if !defined SCNi8 || @PRI_MACROS_BROKEN@
+#  undef SCNi8
+#  ifdef INT8_MAX
+#   define SCNi8 "hhi"
+#  endif
+# endif
+# if !defined SCNo8 || @PRI_MACROS_BROKEN@
+#  undef SCNo8
+#  ifdef UINT8_MAX
+#   define SCNo8 "hho"
+#  endif
+# endif
+# if !defined SCNu8 || @PRI_MACROS_BROKEN@
+#  undef SCNu8
+#  ifdef UINT8_MAX
+#   define SCNu8 "hhu"
+#  endif
+# endif
+# if !defined SCNx8 || @PRI_MACROS_BROKEN@
+#  undef SCNx8
+#  ifdef UINT8_MAX
+#   define SCNx8 "hhx"
+#  endif
+# endif
+# if !defined SCNd16 || @PRI_MACROS_BROKEN@
+#  undef SCNd16
+#  ifdef INT16_MAX
+#   define SCNd16 "hd"
+#  endif
+# endif
+# if !defined SCNi16 || @PRI_MACROS_BROKEN@
+#  undef SCNi16
+#  ifdef INT16_MAX
+#   define SCNi16 "hi"
+#  endif
+# endif
+# if !defined SCNo16 || @PRI_MACROS_BROKEN@
+#  undef SCNo16
+#  ifdef UINT16_MAX
+#   define SCNo16 "ho"
+#  endif
+# endif
+# if !defined SCNu16 || @PRI_MACROS_BROKEN@
+#  undef SCNu16
+#  ifdef UINT16_MAX
+#   define SCNu16 "hu"
+#  endif
+# endif
+# if !defined SCNx16 || @PRI_MACROS_BROKEN@
+#  undef SCNx16
+#  ifdef UINT16_MAX
+#   define SCNx16 "hx"
+#  endif
+# endif
+# if !defined SCNd32 || @PRI_MACROS_BROKEN@
+#  undef SCNd32
+#  ifdef INT32_MAX
+#   define SCNd32 "d"
+#  endif
+# endif
+# if !defined SCNi32 || @PRI_MACROS_BROKEN@
+#  undef SCNi32
+#  ifdef INT32_MAX
+#   define SCNi32 "i"
+#  endif
+# endif
+# if !defined SCNo32 || @PRI_MACROS_BROKEN@
+#  undef SCNo32
+#  ifdef UINT32_MAX
+#   define SCNo32 "o"
+#  endif
+# endif
+# if !defined SCNu32 || @PRI_MACROS_BROKEN@
+#  undef SCNu32
+#  ifdef UINT32_MAX
+#   define SCNu32 "u"
+#  endif
+# endif
+# if !defined SCNx32 || @PRI_MACROS_BROKEN@
+#  undef SCNx32
+#  ifdef UINT32_MAX
+#   define SCNx32 "x"
+#  endif
+# endif
+# ifdef INT64_MAX
+#  if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @INT64_MAX_EQ_LONG_MAX@)
+#   define _SCN64_PREFIX "l"
+#  elif defined _MSC_VER || defined __MINGW32__
+#   define _SCN64_PREFIX "I64"
+#  elif @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1
+#   define _SCN64_PREFIX _LONG_LONG_FORMAT_PREFIX
+#  endif
+#  if !defined SCNd64 || @PRI_MACROS_BROKEN@
+#   undef SCNd64
+#   define SCNd64 _SCN64_PREFIX "d"
+#  endif
+#  if !defined SCNi64 || @PRI_MACROS_BROKEN@
+#   undef SCNi64
+#   define SCNi64 _SCN64_PREFIX "i"
+#  endif
+# endif
+# ifdef UINT64_MAX
+#  if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @UINT64_MAX_EQ_ULONG_MAX@)
+#   define _SCNu64_PREFIX "l"
+#  elif defined _MSC_VER || defined __MINGW32__
+#   define _SCNu64_PREFIX "I64"
+#  elif @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1
+#   define _SCNu64_PREFIX _LONG_LONG_FORMAT_PREFIX
+#  endif
+#  if !defined SCNo64 || @PRI_MACROS_BROKEN@
+#   undef SCNo64
+#   define SCNo64 _SCNu64_PREFIX "o"
+#  endif
+#  if !defined SCNu64 || @PRI_MACROS_BROKEN@
+#   undef SCNu64
+#   define SCNu64 _SCNu64_PREFIX "u"
+#  endif
+#  if !defined SCNx64 || @PRI_MACROS_BROKEN@
+#   undef SCNx64
+#   define SCNx64 _SCNu64_PREFIX "x"
+#  endif
+# endif
+
+# if !defined SCNdLEAST8 || @PRI_MACROS_BROKEN@
+#  undef SCNdLEAST8
+#  define SCNdLEAST8 "hhd"
+# endif
+# if !defined SCNiLEAST8 || @PRI_MACROS_BROKEN@
+#  undef SCNiLEAST8
+#  define SCNiLEAST8 "hhi"
+# endif
+# if !defined SCNoLEAST8 || @PRI_MACROS_BROKEN@
+#  undef SCNoLEAST8
+#  define SCNoLEAST8 "hho"
+# endif
+# if !defined SCNuLEAST8 || @PRI_MACROS_BROKEN@
+#  undef SCNuLEAST8
+#  define SCNuLEAST8 "hhu"
+# endif
+# if !defined SCNxLEAST8 || @PRI_MACROS_BROKEN@
+#  undef SCNxLEAST8
+#  define SCNxLEAST8 "hhx"
+# endif
+# if !defined SCNdLEAST16 || @PRI_MACROS_BROKEN@
+#  undef SCNdLEAST16
+#  define SCNdLEAST16 "hd"
+# endif
+# if !defined SCNiLEAST16 || @PRI_MACROS_BROKEN@
+#  undef SCNiLEAST16
+#  define SCNiLEAST16 "hi"
+# endif
+# if !defined SCNoLEAST16 || @PRI_MACROS_BROKEN@
+#  undef SCNoLEAST16
+#  define SCNoLEAST16 "ho"
+# endif
+# if !defined SCNuLEAST16 || @PRI_MACROS_BROKEN@
+#  undef SCNuLEAST16
+#  define SCNuLEAST16 "hu"
+# endif
+# if !defined SCNxLEAST16 || @PRI_MACROS_BROKEN@
+#  undef SCNxLEAST16
+#  define SCNxLEAST16 "hx"
+# endif
+# if !defined SCNdLEAST32 || @PRI_MACROS_BROKEN@
+#  undef SCNdLEAST32
+#  define SCNdLEAST32 "d"
+# endif
+# if !defined SCNiLEAST32 || @PRI_MACROS_BROKEN@
+#  undef SCNiLEAST32
+#  define SCNiLEAST32 "i"
+# endif
+# if !defined SCNoLEAST32 || @PRI_MACROS_BROKEN@
+#  undef SCNoLEAST32
+#  define SCNoLEAST32 "o"
+# endif
+# if !defined SCNuLEAST32 || @PRI_MACROS_BROKEN@
+#  undef SCNuLEAST32
+#  define SCNuLEAST32 "u"
+# endif
+# if !defined SCNxLEAST32 || @PRI_MACROS_BROKEN@
+#  undef SCNxLEAST32
+#  define SCNxLEAST32 "x"
+# endif
+# ifdef INT64_MAX
+#  if !defined SCNdLEAST64 || @PRI_MACROS_BROKEN@
+#   undef SCNdLEAST64
+#   define SCNdLEAST64 SCNd64
+#  endif
+#  if !defined SCNiLEAST64 || @PRI_MACROS_BROKEN@
+#   undef SCNiLEAST64
+#   define SCNiLEAST64 SCNi64
+#  endif
+# endif
+# ifdef UINT64_MAX
+#  if !defined SCNoLEAST64 || @PRI_MACROS_BROKEN@
+#   undef SCNoLEAST64
+#   define SCNoLEAST64 SCNo64
+#  endif
+#  if !defined SCNuLEAST64 || @PRI_MACROS_BROKEN@
+#   undef SCNuLEAST64
+#   define SCNuLEAST64 SCNu64
+#  endif
+#  if !defined SCNxLEAST64 || @PRI_MACROS_BROKEN@
+#   undef SCNxLEAST64
+#   define SCNxLEAST64 SCNx64
+#  endif
+# endif
+
+# if !defined SCNdFAST8 || @PRI_MACROS_BROKEN@
+#  undef SCNdFAST8
+#  if INT_FAST8_MAX > INT32_MAX
+#   define SCNdFAST8 SCNd64
+#  elif INT_FAST8_MAX == 0x7fff
+#   define SCNdFAST8 "hd"
+#  elif INT_FAST8_MAX == 0x7f
+#   define SCNdFAST8 "hhd"
+#  else
+#   define SCNdFAST8 "d"
+#  endif
+# endif
+# if !defined SCNiFAST8 || @PRI_MACROS_BROKEN@
+#  undef SCNiFAST8
+#  if INT_FAST8_MAX > INT32_MAX
+#   define SCNiFAST8 SCNi64
+#  elif INT_FAST8_MAX == 0x7fff
+#   define SCNiFAST8 "hi"
+#  elif INT_FAST8_MAX == 0x7f
+#   define SCNiFAST8 "hhi"
+#  else
+#   define SCNiFAST8 "i"
+#  endif
+# endif
+# if !defined SCNoFAST8 || @PRI_MACROS_BROKEN@
+#  undef SCNoFAST8
+#  if UINT_FAST8_MAX > UINT32_MAX
+#   define SCNoFAST8 SCNo64
+#  elif UINT_FAST8_MAX == 0xffff
+#   define SCNoFAST8 "ho"
+#  elif UINT_FAST8_MAX == 0xff
+#   define SCNoFAST8 "hho"
+#  else
+#   define SCNoFAST8 "o"
+#  endif
+# endif
+# if !defined SCNuFAST8 || @PRI_MACROS_BROKEN@
+#  undef SCNuFAST8
+#  if UINT_FAST8_MAX > UINT32_MAX
+#   define SCNuFAST8 SCNu64
+#  elif UINT_FAST8_MAX == 0xffff
+#   define SCNuFAST8 "hu"
+#  elif UINT_FAST8_MAX == 0xff
+#   define SCNuFAST8 "hhu"
+#  else
+#   define SCNuFAST8 "u"
+#  endif
+# endif
+# if !defined SCNxFAST8 || @PRI_MACROS_BROKEN@
+#  undef SCNxFAST8
+#  if UINT_FAST8_MAX > UINT32_MAX
+#   define SCNxFAST8 SCNx64
+#  elif UINT_FAST8_MAX == 0xffff
+#   define SCNxFAST8 "hx"
+#  elif UINT_FAST8_MAX == 0xff
+#   define SCNxFAST8 "hhx"
+#  else
+#   define SCNxFAST8 "x"
+#  endif
+# endif
+# if !defined SCNdFAST16 || @PRI_MACROS_BROKEN@
+#  undef SCNdFAST16
+#  if INT_FAST16_MAX > INT32_MAX
+#   define SCNdFAST16 SCNd64
+#  elif INT_FAST16_MAX == 0x7fff
+#   define SCNdFAST16 "hd"
+#  else
+#   define SCNdFAST16 "d"
+#  endif
+# endif
+# if !defined SCNiFAST16 || @PRI_MACROS_BROKEN@
+#  undef SCNiFAST16
+#  if INT_FAST16_MAX > INT32_MAX
+#   define SCNiFAST16 SCNi64
+#  elif INT_FAST16_MAX == 0x7fff
+#   define SCNiFAST16 "hi"
+#  else
+#   define SCNiFAST16 "i"
+#  endif
+# endif
+# if !defined SCNoFAST16 || @PRI_MACROS_BROKEN@
+#  undef SCNoFAST16
+#  if UINT_FAST16_MAX > UINT32_MAX
+#   define SCNoFAST16 SCNo64
+#  elif UINT_FAST16_MAX == 0xffff
+#   define SCNoFAST16 "ho"
+#  else
+#   define SCNoFAST16 "o"
+#  endif
+# endif
+# if !defined SCNuFAST16 || @PRI_MACROS_BROKEN@
+#  undef SCNuFAST16
+#  if UINT_FAST16_MAX > UINT32_MAX
+#   define SCNuFAST16 SCNu64
+#  elif UINT_FAST16_MAX == 0xffff
+#   define SCNuFAST16 "hu"
+#  else
+#   define SCNuFAST16 "u"
+#  endif
+# endif
+# if !defined SCNxFAST16 || @PRI_MACROS_BROKEN@
+#  undef SCNxFAST16
+#  if UINT_FAST16_MAX > UINT32_MAX
+#   define SCNxFAST16 SCNx64
+#  elif UINT_FAST16_MAX == 0xffff
+#   define SCNxFAST16 "hx"
+#  else
+#   define SCNxFAST16 "x"
+#  endif
+# endif
+# if !defined SCNdFAST32 || @PRI_MACROS_BROKEN@
+#  undef SCNdFAST32
+#  if INT_FAST32_MAX > INT32_MAX
+#   define SCNdFAST32 SCNd64
+#  else
+#   define SCNdFAST32 "d"
+#  endif
+# endif
+# if !defined SCNiFAST32 || @PRI_MACROS_BROKEN@
+#  undef SCNiFAST32
+#  if INT_FAST32_MAX > INT32_MAX
+#   define SCNiFAST32 SCNi64
+#  else
+#   define SCNiFAST32 "i"
+#  endif
+# endif
+# if !defined SCNoFAST32 || @PRI_MACROS_BROKEN@
+#  undef SCNoFAST32
+#  if UINT_FAST32_MAX > UINT32_MAX
+#   define SCNoFAST32 SCNo64
+#  else
+#   define SCNoFAST32 "o"
+#  endif
+# endif
+# if !defined SCNuFAST32 || @PRI_MACROS_BROKEN@
+#  undef SCNuFAST32
+#  if UINT_FAST32_MAX > UINT32_MAX
+#   define SCNuFAST32 SCNu64
+#  else
+#   define SCNuFAST32 "u"
+#  endif
+# endif
+# if !defined SCNxFAST32 || @PRI_MACROS_BROKEN@
+#  undef SCNxFAST32
+#  if UINT_FAST32_MAX > UINT32_MAX
+#   define SCNxFAST32 SCNx64
+#  else
+#   define SCNxFAST32 "x"
+#  endif
+# endif
+# ifdef INT64_MAX
+#  if !defined SCNdFAST64 || @PRI_MACROS_BROKEN@
+#   undef SCNdFAST64
+#   define SCNdFAST64 SCNd64
+#  endif
+#  if !defined SCNiFAST64 || @PRI_MACROS_BROKEN@
+#   undef SCNiFAST64
+#   define SCNiFAST64 SCNi64
+#  endif
+# endif
+# ifdef UINT64_MAX
+#  if !defined SCNoFAST64 || @PRI_MACROS_BROKEN@
+#   undef SCNoFAST64
+#   define SCNoFAST64 SCNo64
+#  endif
+#  if !defined SCNuFAST64 || @PRI_MACROS_BROKEN@
+#   undef SCNuFAST64
+#   define SCNuFAST64 SCNu64
+#  endif
+#  if !defined SCNxFAST64 || @PRI_MACROS_BROKEN@
+#   undef SCNxFAST64
+#   define SCNxFAST64 SCNx64
+#  endif
+# endif
+
+# if !defined SCNdMAX || @PRI_MACROS_BROKEN@
+#  undef SCNdMAX
+#  if @INT32_MAX_LT_INTMAX_MAX@
+#   define SCNdMAX SCNd64
+#  else
+#   define SCNdMAX "ld"
+#  endif
+# endif
+# if !defined SCNiMAX || @PRI_MACROS_BROKEN@
+#  undef SCNiMAX
+#  if @INT32_MAX_LT_INTMAX_MAX@
+#   define SCNiMAX SCNi64
+#  else
+#   define SCNiMAX "li"
+#  endif
+# endif
+# if !defined SCNoMAX || @PRI_MACROS_BROKEN@
+#  undef SCNoMAX
+#  if @UINT32_MAX_LT_UINTMAX_MAX@
+#   define SCNoMAX SCNo64
+#  else
+#   define SCNoMAX "lo"
+#  endif
+# endif
+# if !defined SCNuMAX || @PRI_MACROS_BROKEN@
+#  undef SCNuMAX
+#  if @UINT32_MAX_LT_UINTMAX_MAX@
+#   define SCNuMAX SCNu64
+#  else
+#   define SCNuMAX "lu"
+#  endif
+# endif
+# if !defined SCNxMAX || @PRI_MACROS_BROKEN@
+#  undef SCNxMAX
+#  if @UINT32_MAX_LT_UINTMAX_MAX@
+#   define SCNxMAX SCNx64
+#  else
+#   define SCNxMAX "lx"
+#  endif
+# endif
+
+# if !defined SCNdPTR || @PRI_MACROS_BROKEN@
+#  undef SCNdPTR
+#  ifdef INTPTR_MAX
+#   define SCNdPTR @PRIPTR_PREFIX@ "d"
+#  endif
+# endif
+# if !defined SCNiPTR || @PRI_MACROS_BROKEN@
+#  undef SCNiPTR
+#  ifdef INTPTR_MAX
+#   define SCNiPTR @PRIPTR_PREFIX@ "i"
+#  endif
+# endif
+# if !defined SCNoPTR || @PRI_MACROS_BROKEN@
+#  undef SCNoPTR
+#  ifdef UINTPTR_MAX
+#   define SCNoPTR @PRIPTR_PREFIX@ "o"
+#  endif
+# endif
+# if !defined SCNuPTR || @PRI_MACROS_BROKEN@
+#  undef SCNuPTR
+#  ifdef UINTPTR_MAX
+#   define SCNuPTR @PRIPTR_PREFIX@ "u"
+#  endif
+# endif
+# if !defined SCNxPTR || @PRI_MACROS_BROKEN@
+#  undef SCNxPTR
+#  ifdef UINTPTR_MAX
+#   define SCNxPTR @PRIPTR_PREFIX@ "x"
+#  endif
+# endif
+
+#endif
+
+/* 7.8.2 Functions for greatest-width integer types */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if @GNULIB_IMAXABS@
+# if !@HAVE_DECL_IMAXABS@
+extern intmax_t imaxabs (intmax_t);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef imaxabs
+# if HAVE_RAW_DECL_IMAXABS
+_GL_WARN_ON_USE (imaxabs, "imaxabs is unportable - "
+                 "use gnulib module imaxabs for portability");
+# endif
+#endif
+
+#if @GNULIB_IMAXDIV@
+# if !@HAVE_DECL_IMAXDIV@
+typedef struct { intmax_t quot; intmax_t rem; } imaxdiv_t;
+extern imaxdiv_t imaxdiv (intmax_t, intmax_t);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef imaxdiv
+# if HAVE_RAW_DECL_IMAXDIV
+_GL_WARN_ON_USE (imaxdiv, "imaxdiv is unportable - "
+                 "use gnulib module imaxdiv for portability");
+# endif
+#endif
+
+#if @GNULIB_STRTOIMAX@
+# if !@HAVE_DECL_STRTOIMAX@
+extern intmax_t strtoimax (const char *, char **, int) _GL_ARG_NONNULL ((1));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef strtoimax
+# if HAVE_RAW_DECL_STRTOIMAX
+_GL_WARN_ON_USE (strtoimax, "strtoimax is unportable - "
+                 "use gnulib module strtoimax for portability");
+# endif
+#endif
+
+#if @GNULIB_STRTOUMAX@
+# if !@HAVE_DECL_STRTOUMAX@
+extern uintmax_t strtoumax (const char *, char **, int) _GL_ARG_NONNULL ((1));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef strtoumax
+# if HAVE_RAW_DECL_STRTOUMAX
+_GL_WARN_ON_USE (strtoumax, "strtoumax is unportable - "
+                 "use gnulib module strtoumax for portability");
+# endif
+#endif
+
+/* Don't bother defining or declaring wcstoimax and wcstoumax, since
+   wide-character functions like this are hardly ever useful.  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined INTTYPES_H && !defined _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H */
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/gnulib-cache.m4 b/libmissing/m4/gnulib-cache.m4
index e5c9a79..a00e64d 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 bind close fnmatch-gnu getaddrinfo glob iconv inet_ntop ioctl mktime nl_langinfo pathmax recvfrom servent sigaction sleep snprintf socket socklen strptime strsep sys_select
+#   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 bind close fnmatch-gnu getaddrinfo glob iconv imaxabs inet_ntop ioctl mktime nl_langinfo pathmax recvfrom servent sigaction sleep snprintf snprintf-posix socket socklen strptime strsep sys_select
 
 # Specification in the form of a few gnulib-tool.m4 macro invocations:
 gl_LOCAL_DIR([])
@@ -26,6 +26,7 @@ gl_MODULES([
   getaddrinfo
   glob
   iconv
+  imaxabs
   inet_ntop
   ioctl
   mktime
@@ -36,6 +37,7 @@ gl_MODULES([
   sigaction
   sleep
   snprintf
+  snprintf-posix
   socket
   socklen
   strptime
diff --git a/libmissing/m4/gnulib-comp.m4 b/libmissing/m4/gnulib-comp.m4
index 1001f6a..570e577 100644
--- a/libmissing/m4/gnulib-comp.m4
+++ b/libmissing/m4/gnulib-comp.m4
@@ -26,6 +26,7 @@ AC_DEFUN([gl_EARLY],
   m4_pattern_allow([^gl_LTLIBOBJS$])dnl a variable
   AC_REQUIRE([AC_PROG_RANLIB])
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+  AC_REQUIRE([gl_FP_IEEE])
 ])
 
 # This macro should be invoked from ./configure.in, in the section
@@ -65,6 +66,10 @@ AC_SUBST([LTALLOCA])
   gl_FLOAT_H
   gl_FUNC_FNMATCH_POSIX
   gl_FUNC_FNMATCH_GNU
+  gl_FUNC_FREXP_NO_LIBM
+  gl_MATH_MODULE_INDICATOR([frexp])
+  gl_FUNC_FREXPL_NO_LIBM
+  gl_MATH_MODULE_INDICATOR([frexpl])
   gl_GETADDRINFO
   gl_NETDB_MODULE_INDICATOR([getaddrinfo])
   gl_GETLOGIN_R
@@ -79,8 +84,11 @@ AC_SUBST([LTALLOCA])
   gl_GLOB
   gl_HOSTENT
   AM_ICONV
+  gl_FUNC_IMAXABS
+  gl_INTTYPES_MODULE_INDICATOR([imaxabs])
   gl_INET_NTOP
   gl_ARPA_INET_MODULE_INDICATOR([inet_ntop])
+  gl_INTTYPES_H
   AC_REQUIRE([gl_HEADER_SYS_SOCKET])
   if test "$ac_cv_header_winsock2_h" = yes; then
     dnl Even if the 'socket' module is not used here, another part of the
@@ -91,12 +99,16 @@ 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
   gl_LOCALCHARSET
   LOCALCHARSET_TESTS_ENVIRONMENT="CHARSETALIASDIR=\"\$(top_builddir)/$gl_source_base\""
   AC_SUBST([LOCALCHARSET_TESTS_ENVIRONMENT])
   gl_FUNC_MALLOC_POSIX
   gl_STDLIB_MODULE_INDICATOR([malloc-posix])
+  gl_MATH_H
   gl_FUNC_MBRTOWC
   gl_WCHAR_MODULE_INDICATOR([mbrtowc])
   gl_FUNC_MBSINIT
@@ -115,6 +127,9 @@ AC_SUBST([LTALLOCA])
   gl_FUNC_NL_LANGINFO
   gl_LANGINFO_MODULE_INDICATOR([nl_langinfo])
   gl_PATHMAX
+  gl_FUNC_PRINTF_FREXP
+  gl_FUNC_PRINTF_FREXPL
+  m4_divert_text([INIT_PREPARE], [gl_printf_safe=yes])
   AC_REQUIRE([gl_HEADER_SYS_SOCKET])
   if test "$ac_cv_header_winsock2_h" = yes; then
     AC_LIBOBJ([recvfrom])
@@ -124,6 +139,8 @@ AC_SUBST([LTALLOCA])
   gl_SIGACTION
   gl_SIGNAL_MODULE_INDICATOR([sigaction])
   gl_SIGNAL_H
+  gl_SIGNBIT
+  gl_MATH_MODULE_INDICATOR([signbit])
   gl_SIGNALBLOCKING
   gl_SIGNAL_MODULE_INDICATOR([sigprocmask])
   gl_SIZE_MAX
@@ -131,6 +148,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])
@@ -217,6 +235,9 @@ AC_SUBST([LTALLOCA])
   gt_LOCALE_FR
   gt_LOCALE_TR_UTF8
   AC_C_BIGENDIAN
+  gl_DOUBLE_EXPONENT_LOCATION
+  gl_FLOAT_EXPONENT_LOCATION
+  gl_LONG_DOUBLE_EXPONENT_LOCATION
   gt_LOCALE_FR
   gt_LOCALE_FR_UTF8
   gt_LOCALE_JA
@@ -228,7 +249,12 @@ AC_SUBST([LTALLOCA])
   gt_LOCALE_ZH_CN
   gt_LOCALE_FR
   gt_LOCALE_FR_UTF8
+  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
   gl_FUNC_STRERROR
@@ -349,6 +375,9 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/fnmatch.c
   lib/fnmatch.in.h
   lib/fnmatch_loop.c
+  lib/fpucw.h
+  lib/frexp.c
+  lib/frexpl.c
   lib/gai_strerror.c
   lib/getaddrinfo.c
   lib/getlogin_r.c
@@ -357,12 +386,22 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/glob-libc.h
   lib/glob.c
   lib/glob.in.h
+  lib/imaxabs.c
   lib/inet_ntop.c
+  lib/inttypes.in.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/localcharset.c
   lib/localcharset.h
   lib/malloc.c
+  lib/math.in.h
   lib/mbrtowc.c
   lib/mbsinit.c
   lib/mbsrtowcs-state.c
@@ -378,6 +417,10 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/pathmax.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/recvfrom.c
@@ -386,6 +429,9 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/sig-handler.h
   lib/sigaction.c
   lib/signal.in.h
+  lib/signbitd.c
+  lib/signbitf.c
+  lib/signbitl.c
   lib/sigprocmask.c
   lib/size_max.h
   lib/sleep.c
@@ -432,11 +478,17 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/dirent_h.m4
   m4/dirfd.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/float_h.m4
   m4/fnmatch.m4
+  m4/fpieee.m4
+  m4/frexp.m4
+  m4/frexpl.m4
   m4/getaddrinfo.m4
   m4/getlogin_r.m4
   m4/glibc21.m4
@@ -444,11 +496,18 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/gnulib-common.m4
   m4/hostent.m4
   m4/iconv.m4
+  m4/imaxabs.m4
   m4/include_next.m4
   m4/inet_ntop.m4
   m4/intmax_t.m4
+  m4/inttypes-pri.m4
+  m4/inttypes.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
@@ -459,6 +518,7 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/locale-zh.m4
   m4/longlong.m4
   m4/malloc.m4
+  m4/math_h.m4
   m4/mbrtowc.m4
   m4/mbsinit.m4
   m4/mbsrtowcs.m4
@@ -471,15 +531,20 @@ 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/pathmax.m4
+  m4/printf-frexp.m4
+  m4/printf-frexpl.m4
   m4/printf.m4
   m4/servent.m4
   m4/sigaction.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
@@ -514,6 +579,7 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/wint_t.m4
   m4/xsize.m4
   tests/macros.h
+  tests/nan.h
   tests/signature.h
   tests/test-alignof.c
   tests/test-alloca-opt.c
@@ -525,12 +591,22 @@ AC_DEFUN([gl_FILE_LIST], [
   tests/test-dirent.c
   tests/test-errno.c
   tests/test-fnmatch.c
+  tests/test-frexp.c
+  tests/test-frexpl.c
   tests/test-getaddrinfo.c
   tests/test-getlogin_r.c
   tests/test-glob.c
   tests/test-iconv.c
   tests/test-inet_ntop.c
+  tests/test-inttypes.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-math.c
   tests/test-mbrtowc.c
   tests/test-mbrtowc1.sh
   tests/test-mbrtowc2.sh
@@ -548,9 +624,14 @@ AC_DEFUN([gl_FILE_LIST], [
   tests/test-netinet_in.c
   tests/test-nl_langinfo.c
   tests/test-nl_langinfo.sh
+  tests/test-printf-frexp.c
+  tests/test-printf-frexpl.c
   tests/test-sigaction.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-stdbool.c
diff --git a/libmissing/m4/imaxabs.m4 b/libmissing/m4/imaxabs.m4
new file mode 100644
index 0000000..fa1331e
--- /dev/null
+++ b/libmissing/m4/imaxabs.m4
@@ -0,0 +1,17 @@
+# imaxabs.m4 serial 1
+dnl Copyright (C) 2006, 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_IMAXABS],
+[
+  AC_REQUIRE([gl_INTTYPES_H])
+  if test "$ac_cv_have_decl_imaxabs" != yes; then
+    AC_LIBOBJ([imaxabs])
+    gl_PREREQ_IMAXABS
+  fi
+])
+
+# Prerequisites of lib/imaxabs.c.
+AC_DEFUN([gl_PREREQ_IMAXABS], [:])
diff --git a/libmissing/m4/inttypes-pri.m4 b/libmissing/m4/inttypes-pri.m4
new file mode 100644
index 0000000..718a4f4
--- /dev/null
+++ b/libmissing/m4/inttypes-pri.m4
@@ -0,0 +1,36 @@
+# inttypes-pri.m4 serial 6 (gettext-0.18)
+dnl Copyright (C) 1997-2002, 2006, 2008-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 From Bruno Haible.
+
+AC_PREREQ([2.52])
+
+# Define PRI_MACROS_BROKEN if <inttypes.h> exists and defines the PRI*
+# macros to non-string values.  This is the case on AIX 4.3.3.
+
+AC_DEFUN([gt_INTTYPES_PRI],
+[
+  AC_CHECK_HEADERS([inttypes.h])
+  if test $ac_cv_header_inttypes_h = yes; then
+    AC_CACHE_CHECK([whether the inttypes.h PRIxNN macros are broken],
+      [gt_cv_inttypes_pri_broken],
+      [
+        AC_TRY_COMPILE([#include <inttypes.h>
+#ifdef PRId32
+char *p = PRId32;
+#endif
+], [], [gt_cv_inttypes_pri_broken=no], [gt_cv_inttypes_pri_broken=yes])
+      ])
+  fi
+  if test "$gt_cv_inttypes_pri_broken" = yes; then
+    AC_DEFINE_UNQUOTED([PRI_MACROS_BROKEN], [1],
+      [Define if <inttypes.h> exists and defines unusable PRI* macros.])
+    PRI_MACROS_BROKEN=1
+  else
+    PRI_MACROS_BROKEN=0
+  fi
+  AC_SUBST([PRI_MACROS_BROKEN])
+])
diff --git a/libmissing/m4/inttypes.m4 b/libmissing/m4/inttypes.m4
new file mode 100644
index 0000000..3ee174d
--- /dev/null
+++ b/libmissing/m4/inttypes.m4
@@ -0,0 +1,302 @@
+# inttypes.m4 serial 17
+dnl Copyright (C) 2006-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 From Derek Price, Bruno Haible.
+dnl Test whether <inttypes.h> is supported or must be substituted.
+
+AC_DEFUN([gl_INTTYPES_H],
+[
+  AC_REQUIRE([gl_STDINT_H])
+  AC_REQUIRE([gt_INTTYPES_PRI])
+  AC_CHECK_HEADERS_ONCE([inttypes.h])
+  AC_CHECK_DECLS_ONCE([imaxabs])
+  AC_CHECK_DECLS_ONCE([imaxdiv])
+  AC_CHECK_DECLS_ONCE([strtoimax])
+  AC_CHECK_DECLS_ONCE([strtoumax])
+
+  dnl Now see if we need a substitute <inttypes.h>.
+  dnl A complete <inttypes.h> requires
+  dnl   - a complete <stdint.h>,
+  dnl   - the existence of an <inttypes.h>,
+  dnl   - that imaxabs, imaxdiv, strtoimax, strtoumax are declared,
+  dnl   - some additional tests.
+  AC_CACHE_CHECK([whether inttypes.h conforms to C99],
+    [gl_cv_header_working_inttypes_h],
+    [gl_cv_header_working_inttypes_h=no
+     if test "$gl_cv_header_working_stdint_h" = yes \
+        && test $ac_cv_header_inttypes_h = yes \
+        && test "$ac_cv_have_decl_imaxabs" = yes \
+        && test "$ac_cv_have_decl_imaxdiv" = yes \
+        && test "$ac_cv_have_decl_strtoimax" = yes \
+        && test "$ac_cv_have_decl_strtoumax" = yes; then
+       AC_COMPILE_IFELSE([
+         AC_LANG_PROGRAM([[
+#include <stddef.h>
+#define __STDC_LIMIT_MACROS 1 /* to make it work also in C++ mode */
+#define __STDC_CONSTANT_MACROS 1 /* to make it work also in C++ mode */
+#define __STDC_FORMAT_MACROS 1 /* to make it work also in C++ mode */
+#define _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H /* work if build isn't clean */
+#include <inttypes.h>
+
+/* No need to duplicate the tests of stdint.m4; they are subsumed by
+   $gl_cv_header_working_stdint_h = yes.  */
+
+/* Tests for macros supposed to be defined in inttypes.h.  */
+
+const char *k = /* implicit string concatenation */
+#ifdef INT8_MAX
+  PRId8 PRIi8
+#endif
+#ifdef UINT8_MAX
+  PRIo8 PRIu8 PRIx8 PRIX8
+#endif
+#ifdef INT16_MAX
+  PRId16 PRIi16
+#endif
+#ifdef UINT16_MAX
+  PRIo16 PRIu16 PRIx16 PRIX16
+#endif
+#ifdef INT32_MAX
+  PRId32 PRIi32
+#endif
+#ifdef UINT32_MAX
+  PRIo32 PRIu32 PRIx32 PRIX32
+#endif
+#ifdef INT64_MAX
+  PRId64 PRIi64
+#endif
+#ifdef UINT64_MAX
+  PRIo64 PRIu64 PRIx64 PRIX64
+#endif
+  PRIdLEAST8 PRIiLEAST8 PRIoLEAST8 PRIuLEAST8 PRIxLEAST8 PRIXLEAST8
+  PRIdLEAST16 PRIiLEAST16 PRIoLEAST16 PRIuLEAST16 PRIxLEAST16 PRIXLEAST16
+  PRIdLEAST32 PRIiLEAST32 PRIoLEAST32 PRIuLEAST32 PRIxLEAST32 PRIXLEAST32
+  PRIdLEAST64 PRIiLEAST64
+  PRIoLEAST64 PRIuLEAST64 PRIxLEAST64 PRIXLEAST64
+  PRIdFAST8 PRIiFAST8 PRIoFAST8 PRIuFAST8 PRIxFAST8 PRIXFAST8
+  PRIdFAST16 PRIiFAST16 PRIoFAST16 PRIuFAST16 PRIxFAST16 PRIXFAST16
+  PRIdFAST32 PRIiFAST32 PRIoFAST32 PRIuFAST32 PRIxFAST32 PRIXFAST32
+  PRIdFAST64 PRIiFAST64
+  PRIoFAST64 PRIuFAST64 PRIxFAST64 PRIXFAST64
+  PRIdMAX PRIiMAX PRIoMAX PRIuMAX PRIxMAX PRIXMAX
+#ifdef INTPTR_MAX
+  PRIdPTR PRIiPTR
+#endif
+#ifdef UINTPTR_MAX
+  PRIoPTR PRIuPTR PRIxPTR PRIXPTR
+#endif
+  ;
+const char *l = /* implicit string concatenation */
+#ifdef INT8_MAX
+  SCNd8 SCNi8
+#endif
+#ifdef UINT8_MAX
+  SCNo8 SCNu8 SCNx8
+#endif
+#ifdef INT16_MAX
+  SCNd16 SCNi16
+#endif
+#ifdef UINT16_MAX
+  SCNo16 SCNu16 SCNx16
+#endif
+#ifdef INT32_MAX
+  SCNd32 SCNi32
+#endif
+#ifdef UINT32_MAX
+  SCNo32 SCNu32 SCNx32
+#endif
+#ifdef INT64_MAX
+  SCNd64 SCNi64
+#endif
+#ifdef UINT64_MAX
+  SCNo64 SCNu64 SCNx64
+#endif
+  SCNdLEAST8 SCNiLEAST8 SCNoLEAST8 SCNuLEAST8 SCNxLEAST8
+  SCNdLEAST16 SCNiLEAST16 SCNoLEAST16 SCNuLEAST16 SCNxLEAST16
+  SCNdLEAST32 SCNiLEAST32 SCNoLEAST32 SCNuLEAST32 SCNxLEAST32
+  SCNdLEAST64 SCNiLEAST64
+  SCNoLEAST64 SCNuLEAST64 SCNxLEAST64
+  SCNdFAST8 SCNiFAST8 SCNoFAST8 SCNuFAST8 SCNxFAST8
+  SCNdFAST16 SCNiFAST16 SCNoFAST16 SCNuFAST16 SCNxFAST16
+  SCNdFAST32 SCNiFAST32 SCNoFAST32 SCNuFAST32 SCNxFAST32
+  SCNdFAST64 SCNiFAST64
+  SCNoFAST64 SCNuFAST64 SCNxFAST64
+  SCNdMAX SCNiMAX SCNoMAX SCNuMAX SCNxMAX
+#ifdef INTPTR_MAX
+  SCNdPTR SCNiPTR
+#endif
+#ifdef UINTPTR_MAX
+  SCNoPTR SCNuPTR SCNxPTR
+#endif
+  ;
+         ]])],
+         [gl_cv_header_working_inttypes_h=yes])
+     fi])
+
+  dnl Override <inttypes.h> always, so that the portability warnings work.
+  AC_REQUIRE([gl_INTTYPES_H_DEFAULTS])
+  gl_CHECK_NEXT_HEADERS([inttypes.h])
+
+  AC_REQUIRE([gl_MULTIARCH])
+
+  dnl Ensure that <stdint.h> defines the limit macros, since gnulib's
+  dnl <inttypes.h> relies on them.  This macro is only needed when a
+  dnl C++ compiler is in use; it has no effect for a C compiler.
+  dnl Also be careful to define __STDC_LIMIT_MACROS only when gnulib's
+  dnl <inttypes.h> is going to be created, and to avoid redefinition warnings
+  dnl if the __STDC_LIMIT_MACROS is already defined through the CPPFLAGS.
+  AC_DEFINE([GL_TRIGGER_STDC_LIMIT_MACROS], [1],
+    [Define to make the limit macros in <stdint.h> visible.])
+  AH_VERBATIM([__STDC_LIMIT_MACROS_ZZZ],
+[/* Ensure that <stdint.h> defines the limit macros, since gnulib's
+   <inttypes.h> relies on them.  */
+#if defined __cplusplus && !defined __STDC_LIMIT_MACROS && GL_TRIGGER_STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS 1
+#endif
+])
+
+  PRIPTR_PREFIX=
+  if test -n "$STDINT_H"; then
+    dnl Using the gnulib <stdint.h>. It always defines intptr_t to 'long'.
+    PRIPTR_PREFIX='"l"'
+  else
+    dnl Using the system's <stdint.h>.
+    for glpfx in '' l ll I64; do
+      case $glpfx in
+        '')  gltype1='int';;
+        l)   gltype1='long int';;
+        ll)  gltype1='long long int';;
+        I64) gltype1='__int64';;
+      esac
+      AC_COMPILE_IFELSE(
+        [AC_LANG_PROGRAM([[#include <stdint.h>
+           extern intptr_t foo;
+           extern $gltype1 foo;]])],
+        [PRIPTR_PREFIX='"'$glpfx'"'])
+      test -n "$PRIPTR_PREFIX" && break
+    done
+  fi
+  AC_SUBST([PRIPTR_PREFIX])
+
+  if test "$ac_cv_have_decl_imaxabs" = yes; then
+    HAVE_DECL_IMAXABS=1
+  else
+    HAVE_DECL_IMAXABS=0
+  fi
+
+  if test "$ac_cv_have_decl_imaxdiv" = yes; then
+    HAVE_DECL_IMAXDIV=1
+  else
+    HAVE_DECL_IMAXDIV=0
+  fi
+
+  if test "$ac_cv_have_decl_strtoimax" = yes; then
+    HAVE_DECL_STRTOIMAX=1
+  else
+    HAVE_DECL_STRTOIMAX=0
+  fi
+
+  if test "$ac_cv_have_decl_strtoumax" = yes; then
+    HAVE_DECL_STRTOUMAX=1
+  else
+    HAVE_DECL_STRTOUMAX=0
+  fi
+
+  gl_INTTYPES_CHECK_LONG_LONG_INT_CONDITION(
+    [INT32_MAX_LT_INTMAX_MAX],
+    [defined INT32_MAX && defined INTMAX_MAX],
+    [INT32_MAX < INTMAX_MAX],
+    [sizeof (int) < sizeof (long long int)])
+  if test $APPLE_UNIVERSAL_BUILD = 0; then
+    gl_INTTYPES_CHECK_LONG_LONG_INT_CONDITION(
+      [INT64_MAX_EQ_LONG_MAX],
+      [defined INT64_MAX],
+      [INT64_MAX == LONG_MAX],
+      [sizeof (long long int) == sizeof (long int)])
+  else
+    INT64_MAX_EQ_LONG_MAX=-1
+  fi
+  gl_INTTYPES_CHECK_LONG_LONG_INT_CONDITION(
+    [UINT32_MAX_LT_UINTMAX_MAX],
+    [defined UINT32_MAX && defined UINTMAX_MAX],
+    [UINT32_MAX < UINTMAX_MAX],
+    [sizeof (unsigned int) < sizeof (unsigned long long int)])
+  if test $APPLE_UNIVERSAL_BUILD = 0; then
+    gl_INTTYPES_CHECK_LONG_LONG_INT_CONDITION(
+      [UINT64_MAX_EQ_ULONG_MAX],
+      [defined UINT64_MAX],
+      [UINT64_MAX == ULONG_MAX],
+      [sizeof (unsigned long long int) == sizeof (unsigned long int)])
+  else
+    UINT64_MAX_EQ_ULONG_MAX=-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 <inttypes.h>
+    ]], [imaxabs imaxdiv strtoimax strtoumax])
+])
+
+# Define the symbol $1 to be 1 if the condition is true, 0 otherwise.
+# If $2 is true, the condition is $3; otherwise if long long int is supported
+# approximate the condition with $4; otherwise, assume the condition is false.
+# The condition should work on all C99 platforms; the approximations should be
+# good enough to work on all practical pre-C99 platforms.
+# $2 is evaluated by the C preprocessor, $3 and $4 as compile-time constants.
+AC_DEFUN([gl_INTTYPES_CHECK_LONG_LONG_INT_CONDITION],
+[
+  AC_CACHE_CHECK([whether $3],
+    [gl_cv_test_$1],
+    [AC_COMPILE_IFELSE(
+       [AC_LANG_PROGRAM(
+          [[/* Work also in C++ mode.  */
+            #define __STDC_LIMIT_MACROS 1
+
+            /* Work if build is not clean.  */
+            #define _GL_JUST_INCLUDE_SYSTEM_STDINT_H
+
+            #include <limits.h>
+            #if HAVE_STDINT_H
+             #include <stdint.h>
+            #endif
+
+            #if $2
+             #define CONDITION ($3)
+            #elif HAVE_LONG_LONG_INT
+             #define CONDITION ($4)
+            #else
+             #define CONDITION 0
+            #endif
+            int test[CONDITION ? 1 : -1];]])],
+       [gl_cv_test_$1=yes],
+       [gl_cv_test_$1=no])])
+  if test $gl_cv_test_$1 = yes; then
+    $1=1;
+  else
+    $1=0;
+  fi
+  AC_SUBST([$1])
+])
+
+AC_DEFUN([gl_INTTYPES_MODULE_INDICATOR],
+[
+  dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
+  AC_REQUIRE([gl_INTTYPES_H_DEFAULTS])
+  GNULIB_[]m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./-],[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])=1
+])
+
+AC_DEFUN([gl_INTTYPES_H_DEFAULTS],
+[
+  GNULIB_IMAXABS=0;      AC_SUBST([GNULIB_IMAXABS])
+  GNULIB_IMAXDIV=0;      AC_SUBST([GNULIB_IMAXDIV])
+  GNULIB_STRTOIMAX=0;    AC_SUBST([GNULIB_STRTOIMAX])
+  GNULIB_STRTOUMAX=0;    AC_SUBST([GNULIB_STRTOUMAX])
+  dnl Assume proper GNU behavior unless another module says otherwise.
+  HAVE_DECL_IMAXABS=1;   AC_SUBST([HAVE_DECL_IMAXABS])
+  HAVE_DECL_IMAXDIV=1;   AC_SUBST([HAVE_DECL_IMAXDIV])
+  HAVE_DECL_STRTOIMAX=1; AC_SUBST([HAVE_DECL_STRTOIMAX])
+  HAVE_DECL_STRTOUMAX=1; AC_SUBST([HAVE_DECL_STRTOUMAX])
+])
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/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/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/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/tests/Makefile.am b/libmissing/tests/Makefile.am
index 4da05ba..3ca03e7 100644
--- a/libmissing/tests/Makefile.am
+++ b/libmissing/tests/Makefile.am
@@ -150,6 +150,24 @@ EXTRA_DIST += test-fnmatch.c signature.h macros.h
 
 ## end   gnulib module fnmatch-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 getaddrinfo-tests
 
 TESTS += test-getaddrinfo
@@ -201,6 +219,41 @@ EXTRA_DIST += intprops.h
 
 ## end   gnulib module intprops
 
+## begin gnulib module inttypes-tests
+
+TESTS += test-inttypes
+check_PROGRAMS += test-inttypes
+EXTRA_DIST += test-inttypes.c
+
+## end   gnulib module inttypes-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
@@ -209,6 +262,14 @@ EXTRA_DIST += test-langinfo.c
 
 ## end   gnulib module langinfo-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
@@ -280,6 +341,22 @@ EXTRA_DIST += test-nl_langinfo.sh test-nl_langinfo.c signature.h macros.h
 
 ## end   gnulib module nl_langinfo-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 sigaction-tests
 
 TESTS += test-sigaction
@@ -296,6 +373,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
@@ -304,6 +390,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
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-inttypes.c b/libmissing/tests/test-inttypes.c
new file mode 100644
index 0000000..f055a4e
--- /dev/null
+++ b/libmissing/tests/test-inttypes.c
@@ -0,0 +1,121 @@
+/* Test of <inttypes.h> substitute.
+   Copyright (C) 2006-2007, 2009-2010 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 2007.  */
+
+#include <config.h>
+
+#define __STDC_LIMIT_MACROS 1 /* to make it work also in C++ mode */
+#define __STDC_CONSTANT_MACROS 1 /* to make it work also in C++ mode */
+#define __STDC_FORMAT_MACROS 1 /* to make it work also in C++ mode */
+#include <inttypes.h>
+
+#include <stddef.h>
+
+/* Tests for macros supposed to be defined in inttypes.h.  */
+
+const char *k = /* implicit string concatenation */
+#ifdef INT8_MAX
+  PRId8 PRIi8
+#endif
+#ifdef UINT8_MAX
+  PRIo8 PRIu8 PRIx8 PRIX8
+#endif
+#ifdef INT16_MAX
+  PRId16 PRIi16
+#endif
+#ifdef UINT16_MAX
+  PRIo16 PRIu16 PRIx16 PRIX16
+#endif
+#ifdef INT32_MAX
+  PRId32 PRIi32
+#endif
+#ifdef UINT32_MAX
+  PRIo32 PRIu32 PRIx32 PRIX32
+#endif
+#ifdef INT64_MAX
+  PRId64 PRIi64
+#endif
+#ifdef UINT64_MAX
+  PRIo64 PRIu64 PRIx64 PRIX64
+#endif
+  PRIdLEAST8 PRIiLEAST8 PRIoLEAST8 PRIuLEAST8 PRIxLEAST8 PRIXLEAST8
+  PRIdLEAST16 PRIiLEAST16 PRIoLEAST16 PRIuLEAST16 PRIxLEAST16 PRIXLEAST16
+  PRIdLEAST32 PRIiLEAST32 PRIoLEAST32 PRIuLEAST32 PRIxLEAST32 PRIXLEAST32
+  PRIdLEAST64 PRIiLEAST64
+  PRIoLEAST64 PRIuLEAST64 PRIxLEAST64 PRIXLEAST64
+  PRIdFAST8 PRIiFAST8 PRIoFAST8 PRIuFAST8 PRIxFAST8 PRIXFAST8
+  PRIdFAST16 PRIiFAST16 PRIoFAST16 PRIuFAST16 PRIxFAST16 PRIXFAST16
+  PRIdFAST32 PRIiFAST32 PRIoFAST32 PRIuFAST32 PRIxFAST32 PRIXFAST32
+  PRIdFAST64 PRIiFAST64
+  PRIoFAST64 PRIuFAST64 PRIxFAST64 PRIXFAST64
+  PRIdMAX PRIiMAX PRIoMAX PRIuMAX PRIxMAX PRIXMAX
+#ifdef INTPTR_MAX
+  PRIdPTR PRIiPTR
+#endif
+#ifdef UINTPTR_MAX
+  PRIoPTR PRIuPTR PRIxPTR PRIXPTR
+#endif
+  ;
+const char *l = /* implicit string concatenation */
+#ifdef INT8_MAX
+  SCNd8 SCNi8
+#endif
+#ifdef UINT8_MAX
+  SCNo8 SCNu8 SCNx8
+#endif
+#ifdef INT16_MAX
+  SCNd16 SCNi16
+#endif
+#ifdef UINT16_MAX
+  SCNo16 SCNu16 SCNx16
+#endif
+#ifdef INT32_MAX
+  SCNd32 SCNi32
+#endif
+#ifdef UINT32_MAX
+  SCNo32 SCNu32 SCNx32
+#endif
+#ifdef INT64_MAX
+  SCNd64 SCNi64
+#endif
+#ifdef UINT64_MAX
+  SCNo64 SCNu64 SCNx64
+#endif
+  SCNdLEAST8 SCNiLEAST8 SCNoLEAST8 SCNuLEAST8 SCNxLEAST8
+  SCNdLEAST16 SCNiLEAST16 SCNoLEAST16 SCNuLEAST16 SCNxLEAST16
+  SCNdLEAST32 SCNiLEAST32 SCNoLEAST32 SCNuLEAST32 SCNxLEAST32
+  SCNdLEAST64 SCNiLEAST64
+  SCNoLEAST64 SCNuLEAST64 SCNxLEAST64
+  SCNdFAST8 SCNiFAST8 SCNoFAST8 SCNuFAST8 SCNxFAST8
+  SCNdFAST16 SCNiFAST16 SCNoFAST16 SCNuFAST16 SCNxFAST16
+  SCNdFAST32 SCNiFAST32 SCNoFAST32 SCNuFAST32 SCNxFAST32
+  SCNdFAST64 SCNiFAST64
+  SCNoFAST64 SCNuFAST64 SCNxFAST64
+  SCNdMAX SCNiMAX SCNoMAX SCNuMAX SCNxMAX
+#ifdef INTPTR_MAX
+  SCNdPTR SCNiPTR
+#endif
+#ifdef UINTPTR_MAX
+  SCNoPTR SCNuPTR SCNxPTR
+#endif
+  ;
+
+int
+main (void)
+{
+  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-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-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/prelude-lml.conf.in b/prelude-lml.conf.in
index 7ae30d9..25b3266 100644
--- a/prelude-lml.conf.in
+++ b/prelude-lml.conf.in
@@ -133,9 +133,10 @@ file = /var/log/apache2/error_log
 
 
 #
-# Specifies the maximum difference, in seconds, between
-# the interval of two logfiles' rotation. If this difference
-# is reached, a high severity alert will be emited
+# Specifies the maximum difference, in seconds and/or size, between
+# the interval of two logfiles' rotation. If this difference is reached,
+# a high severity alert will be emited. The K (kbytes) or M (mbytes)
+# suffix might be used for size definition.
 #
 #max-rotation-size-offset = 1024
 #max-rotation-time-offset = 300
diff --git a/src/file-server.c b/src/file-server.c
index 253dffb..4eef647 100644
--- a/src/file-server.c
+++ b/src/file-server.c
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <inttypes.h>
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
@@ -91,8 +92,8 @@
 /*
  * Logfile metadata stuff.
  */
-#define METADATA_SIZE 12
 #define METADATA_CHECKSUM_SIZE 4
+#define METADATA_SIZE (sizeof(off_t) + METADATA_CHECKSUM_SIZE)
 #define METADATA_CHECKSUM_TYPE GCRY_MD_CRC32
 
 #define LOG_LINE_MAXSIZE 65535
@@ -116,14 +117,14 @@ typedef struct {
         FILE *metadata_fd;
         prelude_bool_t need_position;
 
-        uint64_t last_rotation_size;
+        off_t last_rotation_size;
         time_t last_rotation_time;
         time_t last_rotation_time_interval;
 
         prelude_string_t *buf;
 
-        uint64_t need_more_read;
-        uint64_t last_size;
+        off_t need_more_read;
+        off_t last_size;
         size_t current_line_len;
 
         union {
@@ -144,8 +145,8 @@ extern lml_config_t config;
 
 static PRELUDE_LIST(active_fd_list);
 static PRELUDE_LIST(inactive_fd_list);
-static unsigned int max_rotation_size_offset = DEFAULT_MAX_ROTATION_SIZE_OFFSET;
 static unsigned int max_rotation_time_offset = DEFAULT_MAX_ROTATION_TIME_OFFSET;
+static unsigned int max_rotation_size_offset = DEFAULT_MAX_ROTATION_SIZE_OFFSET;
 static file_server_metadata_flags_t metadata_flags = FILE_SERVER_METADATA_FLAGS_LAST;
 
 
@@ -305,7 +306,7 @@ static void logfile_modified_alert(monitor_fd_t *monitor, ev_statdata *st_old, s
 static off_t read_logfile(monitor_fd_t *fd, off_t *available)
 {
         int ret;
-        size_t i = 0;
+        off_t i = 0;
 
         while ( 1 ) {
                 ret = getc(fd->fd);
@@ -342,7 +343,7 @@ static off_t read_logfile(monitor_fd_t *fd, off_t *available)
 
 
 
-static int file_metadata_read(monitor_fd_t *monitor, uint64_t *start, unsigned char **buf)
+static int file_metadata_read(monitor_fd_t *monitor, off_t *start, unsigned char **buf)
 {
         ssize_t ret;
         struct stat st;
@@ -364,14 +365,14 @@ static int file_metadata_read(monitor_fd_t *monitor, uint64_t *start, unsigned c
         if ( ret != METADATA_SIZE )
                 return -1;
 
-        *start = prelude_align_uint64(*buf);
-        *buf = *buf + sizeof(uint64_t);
+        memcpy(start, *buf, sizeof(*start));
+        *buf = *buf + sizeof(off_t);
 
         return 0;
 }
 
 
-static int file_metadata_save(monitor_fd_t *monitor, uint64_t offset)
+static int file_metadata_save(monitor_fd_t *monitor, off_t offset)
 {
         int ret;
         unsigned char buf[METADATA_SIZE];
@@ -411,11 +412,10 @@ static int verify_metadata_checksum(prelude_string_t *log, unsigned char *metada
 
 static int file_metadata_get_position(monitor_fd_t *monitor)
 {
-        uint64_t offset = 0;
         struct stat st;
         const char *filename;
         int ret, have_metadata = 0;
-        off_t available = LOG_LINE_MAXSIZE;
+        off_t offset = 0, available = LOG_LINE_MAXSIZE;
         unsigned char msum[METADATA_SIZE], *sumptr = msum;
 
         filename = lml_log_source_get_name(monitor->source);
@@ -434,7 +434,7 @@ static int file_metadata_get_position(monitor_fd_t *monitor)
 
         if ( ! have_metadata ) {
                 prelude_log(PRELUDE_LOG_INFO, "%s: No metadata available, starting from tail.\n", filename);
-                return fseek(monitor->fd, st.st_size, SEEK_SET);
+                return fseeko(monitor->fd, st.st_size, SEEK_SET);
         }
 
         if ( st.st_size < offset ) {
@@ -443,7 +443,7 @@ static int file_metadata_get_position(monitor_fd_t *monitor)
                 return 0;
         }
 
-        ret = fseek(monitor->fd, offset, SEEK_SET);
+        ret = fseeko(monitor->fd, offset, SEEK_SET);
         if ( ret < 0 ) {
                 prelude_log(PRELUDE_LOG_ERR, "%s: error seeking to offset %" PRELUDE_PRIu64 ": %s.\n",
                             filename, offset, strerror(errno));
@@ -622,7 +622,7 @@ static monitor_fd_t *monitor_new(lml_log_source_t *ls)
 
 
 
-static int monitor_set_position(monitor_fd_t *monitor, const char *filename, int fd)
+static int monitor_set_position(monitor_fd_t *monitor, const char *filename)
 {
         int ret = 0;
 
@@ -691,7 +691,7 @@ static int monitor_open(monitor_fd_t *monitor)
                 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
 #endif
 
-                ret = monitor_set_position(monitor, filename, fd);
+                ret = monitor_set_position(monitor, filename);
                 if ( ret < 0 ) {
                         prelude_string_destroy(monitor->buf);
                         return -1;
@@ -762,51 +762,42 @@ static void check_modification_time(monitor_fd_t *monitor, ev_statdata *prev, st
 }
 
 
-static int get_rotation_size_offset(monitor_fd_t *monitor, ev_statdata *st)
+static off_t get_rotation_size_offset(monitor_fd_t *monitor, ev_statdata *st)
 {
-        off_t diff;
-        int prev = 0;
-
-        diff = MAX(monitor->last_rotation_size, st->st_size) -
-               MIN(monitor->last_rotation_size, st->st_size);
+        off_t diff = 0;
 
         if ( monitor->last_rotation_size )
-                prev = 1;
+                diff = (off_t) imaxabs((intmax_t) monitor->last_rotation_size - st->st_size);
 
         monitor->last_rotation_size = st->st_size;
 
-        return prev ? diff : 0;
+        return diff;
 }
 
 
-static int get_rotation_time_offset(monitor_fd_t *monitor, ev_statdata *st)
+static time_t get_rotation_time_offset(monitor_fd_t *monitor)
 {
-        int prev = 0;
-        time_t interval, now, offset;
-
-        now = time(NULL);
-        interval = now - monitor->last_rotation_time;
+        time_t interval = 0, diff = 0, now = time(NULL);
 
-        offset = MAX(monitor->last_rotation_time_interval, interval) -
-                 MIN(monitor->last_rotation_time_interval, interval);
+        if ( monitor->last_rotation_time )
+                interval = now - monitor->last_rotation_time;
 
-        if ( monitor->last_rotation_time ) {
-                prev = 1;
-                monitor->last_rotation_time_interval = interval;
-        }
+        if ( interval && monitor->last_rotation_time_interval )
+                diff = (time_t) imaxabs((intmax_t) monitor->last_rotation_time_interval - interval);
 
         monitor->last_rotation_time = now;
+        monitor->last_rotation_time_interval = interval;
 
-        return prev ? offset : 0;
+        return diff;
 }
 
 
-
 static int is_file_already_used(monitor_fd_t *monitor, ev_statdata *st_prev, ev_statdata *st_cur, struct stat *st_now)
 {
         int ret;
         char buf[1024];
-        int toff, soff;
+        off_t soff;
+        time_t toff;
         const char *filename, *ctxt;
         idmef_impact_t *impact;
         idmef_classification_t *classification;
@@ -867,20 +858,25 @@ static int is_file_already_used(monitor_fd_t *monitor, ev_statdata *st_prev, ev_
         idmef_impact_set_completion(impact, IDMEF_IMPACT_COMPLETION_SUCCEEDED);
 
         soff = get_rotation_size_offset(monitor, st_now);
-        toff = get_rotation_time_offset(monitor, st_now);
+        toff = get_rotation_time_offset(monitor);
 
-        if ( toff <= max_rotation_time_offset|| soff <= max_rotation_size_offset ) {
+        if ( toff <= max_rotation_time_offset || soff <= max_rotation_size_offset ) {
                 idmef_impact_set_severity(impact, IDMEF_IMPACT_SEVERITY_INFO);
                 ret = idmef_impact_new_description(impact, &str);
+                if ( ret < 0 )
+                        return ret;
                 prelude_string_set_constant(str, LOGFILE_DELETION_IMPACT);
         } else {
                 idmef_impact_set_severity(impact, IDMEF_IMPACT_SEVERITY_HIGH);
                 ret = idmef_impact_new_description(impact, &str);
+                if ( ret < 0 )
+                        return ret;
                 snprintf(buf, sizeof(buf), "An inconsistency has been observed in file rotation: "
-                        "The differences between the previously observed rotation time and size are higher "
-                        "than the allowed limits: size difference=%u bytes allowed=%u bytes, time "
-                        "difference=%u seconds allowed=%u seconds", soff, max_rotation_size_offset,
-                         toff, max_rotation_time_offset);
+                        "the differences between the previously observed rotation size and time are higher "
+                        "than allowed limits: %" PRELUDE_PRIu64 " bytes difference (%" PRELUDE_PRIu64" allowed), "
+                        "%" PRELUDE_PRIu64 " seconds difference (%" PRELUDE_PRIu64" allowed)",
+                         (intmax_t) soff, (intmax_t) max_rotation_size_offset,
+                         (intmax_t) toff, (intmax_t) max_rotation_time_offset);
                 prelude_string_set_ref(str, buf);
         }
 
@@ -985,27 +981,27 @@ int file_server_read_once(void)
 
 
 
-void file_server_set_max_rotation_time_offset(unsigned int val)
+void file_server_set_max_rotation_time_offset(time_t val)
 {
         max_rotation_time_offset = val;
 }
 
 
 
-unsigned int file_server_get_max_rotation_time_offset(void)
+time_t file_server_get_max_rotation_time_offset(void)
 {
         return max_rotation_time_offset;
 }
 
 
 
-void file_server_set_max_rotation_size_offset(unsigned int val)
+void file_server_set_max_rotation_size_offset(off_t val)
 {
         max_rotation_size_offset = val;
 }
 
 
-unsigned int file_server_get_max_rotation_size_offset(void)
+off_t file_server_get_max_rotation_size_offset(void)
 {
         return max_rotation_size_offset;
 }
diff --git a/src/include/file-server.h b/src/include/file-server.h
index 7edf672..aff8438 100644
--- a/src/include/file-server.h
+++ b/src/include/file-server.h
@@ -38,10 +38,10 @@ int file_server_monitor_file(lml_log_source_t *ls);
 
 int file_server_start_monitoring(void);
 
-unsigned int file_server_get_max_rotation_time_offset(void);
+time_t file_server_get_max_rotation_time_offset(void);
 
-void file_server_set_max_rotation_time_offset(unsigned int val);
+void file_server_set_max_rotation_time_offset(time_t val);
 
-unsigned int file_server_get_max_rotation_size_offset(void);
+off_t file_server_get_max_rotation_size_offset(void);
 
-void file_server_set_max_rotation_size_offset(unsigned int val);
+void file_server_set_max_rotation_size_offset(off_t val);
diff --git a/src/lml-options.c b/src/lml-options.c
index a4063bf..9b16db4 100644
--- a/src/lml-options.c
+++ b/src/lml-options.c
@@ -203,22 +203,36 @@ static int set_rotation_time_offset(prelude_option_t *opt, const char *optarg, p
 
 static int get_rotation_time_offset(prelude_option_t *opt, prelude_string_t *out, void *context)
 {
-        return prelude_string_sprintf(out, "%u", file_server_get_max_rotation_time_offset());
+        return prelude_string_sprintf(out, "%jd", (intmax_t) file_server_get_max_rotation_time_offset());
 }
 
 
 static int set_rotation_size_offset(prelude_option_t *opt, const char *arg, prelude_string_t *err, void *context)
 {
-        char *endptr;
-        unsigned long int off;
+        char *eptr = NULL;
+        unsigned long long int value;
 
-        off = strtoul(arg, &endptr, 10);
-        if ( *endptr != '\0' ) {
-                prelude_string_sprintf(err, "Invalid max rotation size offset specified: %s", arg);
+        value = strtoull(arg, &eptr, 10);
+        if ( value == ULLONG_MAX || eptr == arg ) {
+                prelude_log(PRELUDE_LOG_ERR, "Invalid buffer size specified: '%s'.\n", arg);
+                return -1;
+        }
+
+        if ( *eptr == 'K' || *eptr == 'k' )
+                value = value * 1024;
+
+        else if ( *eptr == 'M' || *eptr == 'm' )
+                value = value * 1024 * 1024;
+
+        else if ( *eptr == 'G' || *eptr == 'g' )
+                value = value * 1024 * 1024 * 1024;
+
+        else if ( eptr != arg ) {
+                prelude_string_sprintf(err, "Invalid max rotation size offset specified: %s.", arg);
                 return -1;
         }
 
-        file_server_set_max_rotation_size_offset(off);
+        file_server_set_max_rotation_size_offset((off_t) value);
         return 0;
 }
 
@@ -226,7 +240,7 @@ static int set_rotation_size_offset(prelude_option_t *opt, const char *arg, prel
 
 static int get_rotation_size_offset(prelude_option_t *opt, prelude_string_t *out, void *context)
 {
-        return prelude_string_sprintf(out, "%u", file_server_get_max_rotation_size_offset());
+        return prelude_string_sprintf(out, "%jd", (intmax_t) file_server_get_max_rotation_size_offset());
 }
 
 
@@ -692,7 +706,7 @@ int lml_options_init(prelude_option_t *ropt, int argc, char **argv)
                            set_rotation_time_offset, get_rotation_time_offset);
 
         prelude_option_add(ropt, NULL, all_hook, 0, "max-rotation-size-offset",
-                           "Specifies the maximum difference, in bytes, between two logfile "
+                           "Specifies the maximum size difference between two logfile "
                            "rotation. If this difference is reached, a high severity alert "
                            "will be emited", PRELUDE_OPTION_ARGUMENT_REQUIRED, set_rotation_size_offset,
                            get_rotation_size_offset);

--===============2523211104120890310==
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
--===============2523211104120890310==--