guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] GNU Guile branch, string_abstraction2, updated. release_


From: Michael Gran
Subject: [Guile-commits] GNU Guile branch, string_abstraction2, updated. release_1-9-0-110-gcf91d49
Date: Wed, 15 Jul 2009 14:19:54 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Guile".

http://git.savannah.gnu.org/cgit/guile.git/commit/?id=cf91d49a872249c62de6e2d26dc1421e5fbf3e51

The branch, string_abstraction2 has been updated
       via  cf91d49a872249c62de6e2d26dc1421e5fbf3e51 (commit)
       via  5ff6f973ba5591dae9e112014aec71b061f7022a (commit)
       via  2b15091d4c112b4450da6a616762ea6c35a7cf83 (commit)
       via  c920260498a52aa624ea21f3d8c54969e0ae20ad (commit)
       via  7f1389344f07dab675a7860e9e807c6949e8afef (commit)
       via  a31d65e75504bc42ea1adc389d67e4368ac954fb (commit)
       via  c4fdba15e99bc355c6329e7d4d3346e3ab3d410e (commit)
       via  03fe05449482ac54f2cc6ceaf0737a67cde785b1 (commit)
       via  c4b681fdacc57de0b2a9584c1f6a195cf2629b32 (commit)
       via  5374ec9c281c2e77c283f60afd55e47d86e3b898 (commit)
       via  9120012f74a798064dd296d99afdc02608e305e5 (commit)
       via  345b17e911a136775a901c234b8cee95d490845c (commit)
       via  7c957b8657a510395fc451ae4a8e7e3fe5a643ad (commit)
       via  40f892156acba9cac990d2a53333fc41cefcd507 (commit)
       via  dd57ddd5ede6d3d9a736b2b48455fbd87da51e3a (commit)
       via  0a94eb002eba6539879f2cddf3e45fb25976af8d (commit)
       via  fb4e9fb1deb0494f46f4dfe360adee70a7deb4fa (commit)
       via  55720d50f140199f9d9cd2f65fd6841c6387ae64 (commit)
       via  39141c876b36431caa6bd0c84472de61fbc0a8e0 (commit)
       via  a98f422ed61d36d2a0feca3d662ddc64067466f3 (commit)
       via  d6f1ce3d1627e27c2262cb8da15828d515050fd6 (commit)
       via  e6eb2467164de264c313af92d488144d2cdae94c (commit)
       via  caa92f5e951528c1ea31b2eea8b388e9888fa19e (commit)
       via  5fa2deb3f715502866775a7e912dc66e3b6571ac (commit)
       via  e33779e3b84b4822b4d51562d7c4f1e65408151d (commit)
       via  f1ce9199335bebab1a62286ac965f33dc91ca97f (commit)
       via  376b6bd7a2d2484f5579645becc26c40a97c31a6 (commit)
       via  60ed31d28bd2d27efd98bf25556b7c785c46da52 (commit)
       via  a84673a68bfdb6f46235fc6aa1d60c418c28a2e5 (commit)
       via  0ebbcf43c45892afcec199bde0ca1ecaea0077da (commit)
       via  0d646345f477f0ffced6f602370fc8c607f7d32f (commit)
       via  b674d4716abe775e648445795f02bece8a3396e0 (commit)
       via  eb72179985966493f452c7be8b9b048341d2f9c5 (commit)
      from  beb7d5f249b1c20f5c75ab0a6ad7322dd48b1599 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit cf91d49a872249c62de6e2d26dc1421e5fbf3e51
Author: Michael Gran <address@hidden>
Date:   Wed Jul 15 07:18:14 2009 -0700

    Char-set off-by-1 error causes memory corruption
    
        * libguile/srfi-14.c (scm_i_charset_unset): off-by-1 error

commit 5ff6f973ba5591dae9e112014aec71b061f7022a
Author: Michael Gran <address@hidden>
Date:   Wed Jul 15 07:16:34 2009 -0700

    Character write format fixes
    
    This patch checks the unicode properties of a character to determine
    if it is a graphical character.  If it is, and if the character encoding
    will allow it, it is written unescaped.  Otherwise it is written
    as an octal escape.
    
        * libguile/print.c (iprin1): character writing tweaks

commit 2b15091d4c112b4450da6a616762ea6c35a7cf83
Author: Michael Gran <address@hidden>
Date:   Wed Jul 15 07:06:14 2009 -0700

    Limit amount of screen output when printing char-sets
    
    The Unicode char-sets can contain thousands of characters.
    This limits the default printing style of char-sets to
    a hundred character ranges.
    
        * libguile/srfi-14.c (charset_print): limit maximum output

commit c920260498a52aa624ea21f3d8c54969e0ae20ad
Author: Michael Gran <address@hidden>
Date:   Mon Jul 13 06:59:01 2009 -0700

    Var used before set in srfi-14.
    
        * libguile/srfi-14.c (charset_free): var used before set

commit 7f1389344f07dab675a7860e9e807c6949e8afef
Author: Michael Gran <address@hidden>
Date:   Mon Jul 13 06:56:52 2009 -0700

    Don't recompute charsets when locale changes.
    
            * libguile/posix.c (scm_setlocale): don't recompute charsets
            * libguile/posix.c (scm_setbinary): don't recompute charsets

commit a31d65e75504bc42ea1adc389d67e4368ac954fb
Merge: c4fdba15e99bc355c6329e7d4d3346e3ab3d410e 
c4b681fdacc57de0b2a9584c1f6a195cf2629b32
Author: Michael Gran <address@hidden>
Date:   Sat Jul 11 16:57:11 2009 -0700

    Merge branch 'master' into string_abstraction2
    
    Conflicts:
        libguile/numbers.c
        libguile/ports.h

commit c4fdba15e99bc355c6329e7d4d3346e3ab3d410e
Author: Michael Gran <address@hidden>
Date:   Sat Jul 11 15:35:22 2009 -0700

    Tests for srfi-14 implementation
    
            * test-suite/tests/srfi-14.test: new cases to test new srfi-14
            implementation

commit 03fe05449482ac54f2cc6ceaf0737a67cde785b1
Merge: fb4e9fb1deb0494f46f4dfe360adee70a7deb4fa 
0d646345f477f0ffced6f602370fc8c607f7d32f
Author: Michael Gran <address@hidden>
Date:   Tue Jul 7 21:07:24 2009 -0700

    Merge branch 'master' into string_abstraction2

commit fb4e9fb1deb0494f46f4dfe360adee70a7deb4fa
Author: Michael Gran <address@hidden>
Date:   Sun Jun 28 08:14:50 2009 -0700

    simplify string API
    
    Much of the string API can be reduced to a simple get/set pair.
    
        * strings.c (scm_i_string_ref): return scm_t_wchar instead of a
        Guile character.
        (scm_i_string_ref_to_char, scm_i_string_ref_to_wchar): removed
        (scm_i_string_ref_eq_char, scm_i_string_ref_eq_wchar): removed
        (scm_i_string_set_x): new function replacing scm_i_string_set_from_wchar
        (scm_i_string_set): removed
        (scm_i_symbol_ref): return scm_t_wchar instead of a Guile character
        (scm_i_symbol_ref_to_char, scm_i_symbol_ref_to_wchar): removed
        (scm_i_symbol_ref_eq_char): removed
    
        * hash.c:
        * goops.c:
        * gc-mark.c:
        * filesys.c:
        * numbers.c:
        * ports.c:
        * print.c:
        * rdelim.c:
        * read.c:
        * srfi-13.c:
        * srfi-14.c:
        * struct.c:
        * symbols.c:
        * unif.c: replace all calls to removed functions with
        scm_i_string_ref, scm_i_string_set_x, scm_i_symbol_ref

commit 55720d50f140199f9d9cd2f65fd6841c6387ae64
Author: Michael Gran <address@hidden>
Date:   Sun Jun 28 05:17:23 2009 -0700

    restore SCM_MAKE_CHAR as a pure macro
    
        * chars.h (SCM_MAKE_CHAR): no longer calls removed function
        scm_i_make_char
    
        * chars.c (scm_i_make_char): function removed

-----------------------------------------------------------------------

Summary of changes:
 FAQ                                           |   19 -
 Makefile.am                                   |    2 +-
 NEWS                                          |   14 +-
 THANKS                                        |    1 +
 configure.in                                  |   23 +-
 doc/ref/api-compound.texi                     |   28 +-
 doc/ref/api-data.texi                         |   34 +-
 doc/ref/api-io.texi                           |    4 +-
 doc/ref/posix.texi                            |    4 -
 guile-readline/configure.in                   |   71 -
 guile-readline/readline.c                     |   23 -
 lib/Makefile.am                               |  191 +-
 lib/{time_r.c => asnprintf.c}                 |   38 +-
 lib/errno.in.h                                |  160 +
 lib/float+.h                                  |  148 +
 lib/float.in.h                                |   62 +
 lib/{mbrlen.c => getpagesize.c}               |   29 +-
 lib/memchr.c                                  |  172 +
 lib/memchr.valgrind                           |   14 +
 lib/printf-args.c                             |  187 +
 lib/printf-args.h                             |  154 +
 lib/printf-parse.c                            |  627 +++
 lib/printf-parse.h                            |  179 +
 lib/size_max.h                                |   31 +
 lib/stdio-write.c                             |  148 +
 lib/stdio.in.h                                |  542 +++
 lib/vasnprintf.c                              | 5487 +++++++++++++++++++++++++
 lib/vasnprintf.h                              |   81 +
 lib/vsnprintf.c                               |   71 +
 lib/xsize.h                                   |  108 +
 libguile/_scm.h                               |   14 -
 libguile/bytevectors.c                        |   62 +-
 libguile/bytevectors.h                        |    3 +
 libguile/chars.c                              |   11 -
 libguile/chars.h                              |    7 +-
 libguile/discouraged.c                        |    2 +-
 libguile/filesys.c                            |   46 +-
 libguile/fports.c                             |   50 +-
 libguile/fports.h                             |    4 +-
 libguile/gc-mark.c                            |    6 +-
 libguile/gen-scmconfig.c                      |   18 +
 libguile/goops.c                              |    2 +-
 libguile/hash.c                               |    2 +-
 libguile/instructions.c                       |   11 +-
 libguile/instructions.h                       |    4 +-
 libguile/numbers.c                            |   61 +-
 libguile/objcodes.c                           |   30 +-
 libguile/ports.c                              |   31 +-
 libguile/ports.h                              |   20 +-
 libguile/posix.c                              |    8 -
 libguile/print.c                              |   63 +-
 libguile/r6rs-ports.c                         |   18 +-
 libguile/rdelim.c                             |    2 +-
 libguile/read.c                               |   16 +-
 libguile/rw.c                                 |    6 +-
 libguile/scmsigs.c                            |   36 +-
 libguile/srfi-13.c                            |  200 +-
 libguile/srfi-14.c                            |   17 +-
 libguile/strings.c                            |   92 +-
 libguile/strings.h                            |   13 +-
 libguile/strports.c                           |   14 +-
 libguile/struct.c                             |   45 +-
 libguile/symbols.c                            |    3 +-
 libguile/unif.c                               |    4 +-
 libguile/vm-engine.c                          |    8 +-
 libguile/vm-engine.h                          |   12 +-
 libguile/vm-i-scheme.c                        |  274 ++-
 m4/errno_h.m4                                 |  115 +
 m4/float_h.m4                                 |   19 +
 m4/getpagesize.m4                             |   29 +
 m4/gnulib-cache.m4                            |    3 +-
 m4/gnulib-comp.m4                             |   45 +
 m4/intmax_t.m4                                |   61 +
 m4/inttypes_h.m4                              |   26 +
 m4/lib-link.m4                                |    7 +-
 m4/mbrtowc.m4                                 |    3 +-
 m4/memchr.m4                                  |   86 +
 m4/mmap-anon.m4                               |   59 +
 m4/printf.m4                                  | 1416 +++++++
 m4/size_max.m4                                |   75 +
 m4/stdint_h.m4                                |   26 +
 m4/stdio_h.m4                                 |  136 +
 m4/vasnprintf.m4                              |  276 ++
 m4/vsnprintf.m4                               |   40 +
 m4/wchar_t.m4                                 |   20 +
 m4/xsize.m4                                   |   13 +
 module/language/brainfuck/compile-tree-il.scm |   44 +-
 module/language/tree-il/compile-glil.scm      |   67 +-
 module/language/tree-il/primitives.scm        |   31 +-
 module/system/repl/command.scm                |  157 +-
 module/system/repl/repl.scm                   |   41 +-
 test-suite/tests/bit-operations.test          |    7 +-
 test-suite/tests/bytevectors.test             |   34 +-
 test-suite/tests/numbers.test                 |    9 +-
 test-suite/tests/srfi-14.test                 |   26 +-
 95 files changed, 11879 insertions(+), 859 deletions(-)
 delete mode 100644 FAQ
 copy lib/{time_r.c => asnprintf.c} (57%)
 create mode 100644 lib/errno.in.h
 create mode 100644 lib/float+.h
 create mode 100644 lib/float.in.h
 copy lib/{mbrlen.c => getpagesize.c} (57%)
 create mode 100644 lib/memchr.c
 create mode 100644 lib/memchr.valgrind
 create mode 100644 lib/printf-args.c
 create mode 100644 lib/printf-args.h
 create mode 100644 lib/printf-parse.c
 create mode 100644 lib/printf-parse.h
 create mode 100644 lib/size_max.h
 create mode 100644 lib/stdio-write.c
 create mode 100644 lib/stdio.in.h
 create mode 100644 lib/vasnprintf.c
 create mode 100644 lib/vasnprintf.h
 create mode 100644 lib/vsnprintf.c
 create mode 100644 lib/xsize.h
 create mode 100644 m4/errno_h.m4
 create mode 100644 m4/float_h.m4
 create mode 100644 m4/getpagesize.m4
 create mode 100644 m4/intmax_t.m4
 create mode 100644 m4/inttypes_h.m4
 create mode 100644 m4/memchr.m4
 create mode 100644 m4/mmap-anon.m4
 create mode 100644 m4/printf.m4
 create mode 100644 m4/size_max.m4
 create mode 100644 m4/stdint_h.m4
 create mode 100644 m4/stdio_h.m4
 create mode 100644 m4/vasnprintf.m4
 create mode 100644 m4/vsnprintf.m4
 create mode 100644 m4/wchar_t.m4
 create mode 100644 m4/xsize.m4

diff --git a/FAQ b/FAQ
deleted file mode 100644
index 2ff6cad..0000000
--- a/FAQ
+++ /dev/null
@@ -1,19 +0,0 @@
-Guile FAQ                       -*- outline -*-
-
-* Build problems
-
-** readline.c: error: `rl_pending_input' undeclared
-
-This occurs if the Readline library detected by Guile's configure
-script is actually the BSD Editline project's supposedly
-Readline-compatible library.  The immediate fix is to uninstall
-Editline and install the real GNU Readline instead.  When you do this,
-please note that it probably won't work to keep Editline in /usr and
-install GNU Readline in /usr/local (or some similar arrangement),
-because the Editline library will then still be picked up at link and
-run time; it's best (subject to other constraints) to remove Editline
-completely.
-
-For the longer term, please also report this problem to the Editline
-project, to encourage them to fix it in the next release of their
-Readline compatibility library.
diff --git a/Makefile.am b/Makefile.am
index c0fd8c3..4562ddd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,7 +31,7 @@ SUBDIRS = lib meta libguile guile-readline emacs \
 include_HEADERS = libguile.h
 
 EXTRA_DIST = LICENSE HACKING GUILE-VERSION             \
-            m4/ChangeLog-2008 FAQ \
+            m4/ChangeLog-2008 \
             m4/autobuild.m4 ChangeLog-2008
 
 TESTS = check-guile
diff --git a/NEWS b/NEWS
index 5175a09..36d36cb 100644
--- a/NEWS
+++ b/NEWS
@@ -511,6 +511,11 @@ This procedure corresponds to Scheme's 
`module-public-interface'.
 ** `scm_stat' has an additional argument, `exception_on_error'
 ** `scm_primitive_load_path' has an additional argument 
`exception_on_not_found'
 
+** `scm_set_port_seek' and `scm_set_port_truncate' use the `scm_t_off' type
+
+Previously they would use the `off_t' type, which is fragile since its
+definition depends on the application's value for `_FILE_OFFSET_BITS'.
+
 * Changes to the distribution
 
 ** Guile's license is now LGPLv3+
@@ -552,9 +557,11 @@ Changes in 1.8.7 (since 1.8.6)
 ** Fix build problem when scm_t_timespec is different from struct timespec
 ** Fix build when compiled with -Wundef -Werror
 ** More build fixes for `alphaev56-dec-osf5.1b' (Tru64)
+** Build fixes for `powerpc-ibm-aix5.3.0.0' (AIX 5.3)
 ** With GCC, always compile with `-mieee' on `alpha*' and `sh*'
 ** Better diagnose broken `(strftime "%z" ...)' in `time.test' (bug #24130)
 ** Fix parsing of SRFI-88/postfix keywords longer than 128 characters
+** Fix reading of complex numbers where both parts are inexact decimals
 
 ** Allow @ macro to work with (ice-9 syncase)
 
@@ -683,13 +690,6 @@ lead to a stack overflow.
 ** Fixed shadowing of libc's <random.h> on Tru64, which broke compilation
 ** Make sure all tests honor `$TMPDIR'
 
-* Changes to the distribution
-
-** New FAQ
-
-We've started collecting Frequently Asked Questions (FAQ), and will
-distribute these (with answers!) in future Guile releases.
-
 
 Changes in 1.8.4 (since 1.8.3)
 
diff --git a/THANKS b/THANKS
index 90ccd87..47aa93c 100644
--- a/THANKS
+++ b/THANKS
@@ -24,6 +24,7 @@ For fixes or providing information which led to a fix:
           David Allouche
         Martin Baulig
         Fabrice Bauzac
+        Sylvain Beucler
           Carlo Bramini
             Rob Browning
          Adrian Bunk
diff --git a/configure.in b/configure.in
index d43de12..7235f6f 100644
--- a/configure.in
+++ b/configure.in
@@ -1059,18 +1059,6 @@ if test $guile_cv_localtime_cache = yes; then
   AC_DEFINE(LOCALTIME_CACHE, 1, [Define if localtime caches the TZ setting.])
 fi
 
-dnl Test whether system calls are restartable by default on the
-dnl current system.  If they are not, we put a loop around every system
-dnl call to check for EINTR (see SCM_SYSCALL) and do not attempt to
-dnl change from the default behaviour.  On the other hand, if signals
-dnl are restartable then the loop is not installed and when libguile
-dnl initialises it also resets the behaviour of each signal to cause a
-dnl restart (in case a different runtime had a different default
-dnl behaviour for some reason: e.g., different versions of linux seem
-dnl to behave differently.)
-
-AC_SYS_RESTARTABLE_SYSCALLS
-
 if test "$enable_regex" = yes; then
    if test "$ac_cv_header_regex_h" = yes ||
       test "$ac_cv_header_rxposix_h" = yes ||
@@ -1263,11 +1251,12 @@ case "$with_threads" in
 
     build_pthread_support="yes"
 
-    ACX_PTHREAD(CC="$PTHREAD_CC"
-      LIBS="$PTHREAD_LIBS $LIBS"
-      SCM_I_GSC_USE_PTHREAD_THREADS=1
-      with_threads="pthreads",
-      with_threads="null")
+    ACX_PTHREAD([CC="$PTHREAD_CC"
+       LIBS="$PTHREAD_LIBS $LIBS"
+       SCM_I_GSC_USE_PTHREAD_THREADS=1
+       with_threads="pthreads"],
+      [with_threads="null"
+       build_pthread_support="no"])
 
     old_CFLAGS="$CFLAGS"
     CFLAGS="$PTHREAD_CFLAGS $CFLAGS"
diff --git a/doc/ref/api-compound.texi b/doc/ref/api-compound.texi
index 8d0e02f..7eccb86 100644
--- a/doc/ref/api-compound.texi
+++ b/doc/ref/api-compound.texi
@@ -1651,16 +1651,16 @@ and writing.
 Guile has a number of data types that are generally vector-like:
 strings, uniform numeric vectors, bytevectors, bitvectors, and of course
 ordinary vectors of arbitrary Scheme values.  These types are disjoint:
-a Scheme value belongs to at most one of the four types listed above.
+a Scheme value belongs to at most one of the five types listed above.
 
 If you want to gloss over this distinction and want to treat all four
 types with common code, you can use the procedures in this section.
 They work with the @emph{generalized vector} type, which is the union
-of the four vector-like types.
+of the five vector-like types.
 
 @deffn {Scheme Procedure} generalized-vector? obj
 @deffnx {C Function} scm_generalized_vector_p (obj)
-Return @code{#t} if @var{obj} is a vector, string,
+Return @code{#t} if @var{obj} is a vector, bytevector, string,
 bitvector, or uniform numeric vector.
 @end deffn
 
@@ -2358,21 +2358,13 @@ the danger of a deadlock.  In a multi-threaded program, 
you will need
 additional synchronization to avoid modifying reserved arrays.)
 
 You must take care to always unreserve an array after reserving it,
-also in the presence of non-local exits.  To simplify this, reserving
-and unreserving work like a dynwind context (@pxref{Dynamic Wind}): a
-call to @code{scm_array_get_handle} can be thought of as beginning a
-dynwind context and @code{scm_array_handle_release} as ending it.
-When a non-local exit happens between these two calls, the array is
-implicitely unreserved.
-
-That is, you need to properly pair reserving and unreserving in your
-code, but you don't need to worry about non-local exits.
-
-These calls and other pairs of calls that establish dynwind contexts
-need to be properly nested.  If you begin a context prior to reserving
-an array, you need to unreserve the array before ending the context.
-Likewise, when reserving two or more arrays in a certain order, you
-need to unreserve them in the opposite order.
+even in the presence of non-local exits.  If a non-local exit can
+happen between these two calls, you should install a dynwind context
+that releases the array when it is left (@pxref{Dynamic Wind}).
+
+In addition, array reserving and unreserving must be properly
+paired.  For instance, when reserving two or more arrays in a certain
+order, you need to unreserve them in the opposite order.
 
 Once you have reserved an array and have retrieved the pointer to its
 elements, you must figure out the layout of the elements in memory.
diff --git a/doc/ref/api-data.texi b/doc/ref/api-data.texi
index 4401ef1..6e1a67a 100755
--- a/doc/ref/api-data.texi
+++ b/doc/ref/api-data.texi
@@ -3755,7 +3755,7 @@ stored and you probably need to try again with a larger 
buffer.
 
 A @dfn{bytevector} is a raw bit string.  The @code{(rnrs bytevector)}
 module provides the programming interface specified by the
address@hidden://www.r6rs.org/, Revised Report^6 on the Algorithmic Language
address@hidden://www.r6rs.org/, Revised^6 Report on the Algorithmic Language
 Scheme (R6RS)}.  It contains procedures to manipulate bytevectors and
 interpret their contents in a number of ways: bytevector contents can be
 accessed as signed or unsigned integer of various sizes and endianness,
@@ -3800,18 +3800,20 @@ R6RS (@pxref{R6RS I/O Ports}).
 @cindex word order
 
 Some of the following procedures take an @var{endianness} parameter.
-The @dfn{endianness} is defined is defined as the order of bytes in
-multi-byte numbers: numbers encoded in @dfn{big endian} have their most
-significant bytes written first, whereas numbers encoded in @dfn{little
-endian} have their least significant bytes address@hidden and little
-endian are the most common ``endiannesses'' but others exist.  For
-instance, the GNU MP library allows @dfn{word order} to be specified
-independently of @dfn{byte order} (@pxref{Integer Import and Export,,,
-gmp, The GNU Multiple Precision Arithmetic Library Manual}).}  Little
-endian is the native endianness of the IA32 architecture and its
-derivatives, while big endian is native to SPARC and PowerPC, among
-others.  The @code{native-endianness} procedure returns the native
-endianness of the machine it runs on.
+The @dfn{endianness} is defined as the order of bytes in multi-byte
+numbers: numbers encoded in @dfn{big endian} have their most
+significant bytes written first, whereas numbers encoded in
address@hidden endian} have their least significant bytes
address@hidden and little-endian are the most common
+``endiannesses'', but others do exist. For instance, the GNU MP
+library allows @dfn{word order} to be specified independently of
address@hidden order} (@pxref{Integer Import and Export,,, gmp, The GNU
+Multiple Precision Arithmetic Library Manual}).}.
+
+Little-endian is the native endianness of the IA32 architecture and
+its derivatives, while big-endian is native to SPARC and PowerPC,
+among others. The @code{native-endianness} procedure returns the
+native endianness of the machine it runs on.
 
 @deffn {Scheme Procedure} native-endianness
 @deffnx {C Function} scm_native_endianness ()
@@ -3820,13 +3822,13 @@ Return a value denoting the native endianness of the 
host machine.
 
 @deffn {Scheme Macro} endianness symbol
 Return an object denoting the endianness specified by @var{symbol}.  If
address@hidden is neither @code{big} nor @code{little} then a compile-time
-error is raised.
address@hidden is neither @code{big} nor @code{little} then an error is
+raised at expand-time.
 @end deffn
 
 @defvr {C Variable} scm_endianness_big
 @defvrx {C Variable} scm_endianness_little
-The objects denoting big (resp. little) endianness.
+The objects denoting big- and little-endianness, respectively.
 @end defvr
 
 
diff --git a/doc/ref/api-io.texi b/doc/ref/api-io.texi
index 12c19b7..b0b5741 100644
--- a/doc/ref/api-io.texi
+++ b/doc/ref/api-io.texi
@@ -1531,7 +1531,7 @@ implementations take care to avoid this problem.
 
 The procedure is set using
 
address@hidden void scm_set_port_seek (scm_t_bits tc, off_t (*seek) (SCM port, 
off_t offset, int whence))
address@hidden void scm_set_port_seek (scm_t_bits tc, scm_t_off (*seek) (SCM 
port, scm_t_off offset, int whence))
 @end deftypefun
 
 @item truncate
@@ -1539,7 +1539,7 @@ Truncate the port data to be specified length.  It can be 
assumed that the
 current state of @code{rw_active} is @code{SCM_PORT_NEITHER}.
 Set using
 
address@hidden void scm_set_port_truncate (scm_t_bits tc, void (*truncate) (SCM 
port, off_t length))
address@hidden void scm_set_port_truncate (scm_t_bits tc, void (*truncate) (SCM 
port, scm_t_off length))
 @end deftypefun
 
 @end table
diff --git a/doc/ref/posix.texi b/doc/ref/posix.texi
index cb19a7a..2d64919 100644
--- a/doc/ref/posix.texi
+++ b/doc/ref/posix.texi
@@ -1909,10 +1909,6 @@ for termination, not stopping.
 If a signal occurs while in a system call, deliver the signal then
 restart the system call (as opposed to returning an @code{EINTR} error
 from that call).
-
-Guile always enables this flag where available, no matter what
address@hidden are specified.  This avoids spurious error returns in low
-level operations.
 @end defvar
 
 The return value is a pair with information about the old handler as
diff --git a/guile-readline/configure.in b/guile-readline/configure.in
index d053566..f24fc94 100644
--- a/guile-readline/configure.in
+++ b/guile-readline/configure.in
@@ -54,77 +54,6 @@ dnl install paren matching on the Guile command line (when 
using
 dnl readline for input), so it's completely optional.
 AC_CHECK_FUNCS(rl_get_keymap)
 
-dnl Check for rl_pre_input_hook.  This is more complicated because on
-dnl some systems (HP/UX), the linker wont let us treat
-dnl rl_pre_input_hook as a function when it really is a function
-dnl pointer.
-
-AC_MSG_CHECKING([for rl_pre_input_hook])
-AC_CACHE_VAL(ac_cv_var_rl_pre_input_hook,
-[AC_TRY_LINK([
-#include <stdio.h>
-#include <readline/readline.h>
-], [
-rl_pre_input_hook = 0;
-],
-ac_cv_var_rl_pre_input_hook=yes,
-ac_cv_var_rl_pre_input_hook=no)])
-AC_MSG_RESULT($ac_cv_var_rl_pre_input_hook)
-if test $ac_cv_var_rl_pre_input_hook = yes; then
-  AC_DEFINE(HAVE_RL_PRE_INPUT_HOOK,1,
-            [Define if rl_pre_input_hook is available.])
-fi
-
-
-AC_MSG_CHECKING(if readline clears SA_RESTART flag for SIGWINCH)
-AC_CACHE_VAL(guile_cv_sigwinch_sa_restart_cleared,
-AC_TRY_RUN([#include <signal.h>
-#include <stdio.h>
-#include <readline/readline.h>
-
-int
-hook ()
-{
-  struct sigaction action;
-
-  sigaction (SIGWINCH, NULL, &action);
-  rl_cleanup_after_signal();
-
-  /* exit with 0 if readline disabled SA_RESTART */
-  exit (action.sa_flags & SA_RESTART);
-}
-
-int
-main ()
-{
-  struct sigaction action;
-
-  sigaction (SIGWINCH, NULL, &action);
-  action.sa_flags |= SA_RESTART;
-  sigaction (SIGWINCH, &action, NULL);
-
-  /* Give readline something to read.  Otherwise, it might hang, for
-     example when run as a background process with job control.
-  */
-  rl_instream = fopen ("/dev/null", "r");
-  if (rl_instream == NULL)
-    {
-      perror ("/dev/null");
-      exit (1);
-    }
-
-  rl_pre_input_hook = hook;
-  readline ("");
-}],
-guile_cv_sigwinch_sa_restart_cleared=yes,
-guile_cv_sigwinch_sa_restart_cleared=no,
-guile_cv_sigwinch_sa_restart_cleared=yes))
-AC_MSG_RESULT($guile_cv_sigwinch_sa_restart_cleared)
-if test $guile_cv_sigwinch_sa_restart_cleared = yes; then
-  AC_DEFINE(GUILE_SIGWINCH_SA_RESTART_CLEARED, 1,
-    [Define if readline disables SA_RESTART.])
-fi
-
 AC_CACHE_CHECK([for rl_getc_function pointer in readline],
                 ac_cv_var_rl_getc_function,
                 [AC_TRY_LINK([
diff --git a/guile-readline/readline.c b/guile-readline/readline.c
index ac44e26..a2cb2aa 100644
--- a/guile-readline/readline.c
+++ b/guile-readline/readline.c
@@ -537,26 +537,6 @@ match_paren (int x, int k)
 }
 #endif /* HAVE_RL_GET_KEYMAP */
 
-#if defined (HAVE_RL_PRE_INPUT_HOOK) && defined 
(GUILE_SIGWINCH_SA_RESTART_CLEARED)
-/* Readline disables SA_RESTART on SIGWINCH.
- * This code turns it back on.
- */
-static int
-sigwinch_enable_restart (void)
-{
-#ifdef HAVE_SIGINTERRUPT
-  siginterrupt (SIGWINCH, 0);
-#else
-  struct sigaction action;
-  
-  sigaction (SIGWINCH, NULL, &action);
-  action.sa_flags |= SA_RESTART;
-  sigaction (SIGWINCH, &action, NULL);
-#endif
-  return 0;
-}
-#endif
-
 #endif /* HAVE_RL_GETC_FUNCTION */
 
 void
@@ -576,9 +556,6 @@ scm_init_readline ()
 #endif
   rl_basic_word_break_characters = "\t\n\"'`;()";
   rl_readline_name = "Guile";
-#if defined (HAVE_RL_PRE_INPUT_HOOK) && defined 
(GUILE_SIGWINCH_SA_RESTART_CLEARED)
-  rl_pre_input_hook = sigwinch_enable_restart;
-#endif
 
   reentry_barrier_mutex = scm_permanent_object (scm_make_mutex ());
   scm_init_opts (scm_readline_options,
diff --git a/lib/Makefile.am b/lib/Makefile.am
index f488fa1..197320e 100644
--- a/lib/Makefile.am
+++ b/lib/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=libgnu --source-base=lib 
--m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --lgpl 
--libtool --macro-prefix=gl --no-vc-files alloca-opt autobuild byteswap 
canonicalize-lgpl count-one-bits environ extensions flock fpieee full-read 
full-write havelib iconv_open-utf lib-symbol-visibility libunistring putenv 
stdlib strcase strftime striconveh string
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib 
--m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --lgpl 
--libtool --macro-prefix=gl --no-vc-files alloca-opt autobuild byteswap 
canonicalize-lgpl count-one-bits environ extensions flock fpieee full-read 
full-write havelib iconv_open-utf lib-symbol-visibility libunistring putenv 
stdlib strcase strftime striconveh string vsnprintf
 
 AUTOMAKE_OPTIONS = 1.5 gnits subdir-objects
 
@@ -167,6 +167,54 @@ EXTRA_DIST += count-one-bits.h
 
 ## end   gnulib module count-one-bits
 
+## begin gnulib module errno
+
+BUILT_SOURCES += $(ERRNO_H)
+
+# We need the following in order to create <errno.h> when the system
+# doesn't have one that is POSIX compliant.
+errno.h: errno.in.h
+       rm -f address@hidden $@
+       { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+         sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+             -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+             -e 's|@''NEXT_ERRNO_H''@|$(NEXT_ERRNO_H)|g' \
+             -e 's|@''EMULTIHOP_HIDDEN''@|$(EMULTIHOP_HIDDEN)|g' \
+             -e 's|@''EMULTIHOP_VALUE''@|$(EMULTIHOP_VALUE)|g' \
+             -e 's|@''ENOLINK_HIDDEN''@|$(ENOLINK_HIDDEN)|g' \
+             -e 's|@''ENOLINK_VALUE''@|$(ENOLINK_VALUE)|g' \
+             -e 's|@''EOVERFLOW_HIDDEN''@|$(EOVERFLOW_HIDDEN)|g' \
+             -e 's|@''EOVERFLOW_VALUE''@|$(EOVERFLOW_VALUE)|g' \
+             < $(srcdir)/errno.in.h; \
+       } > address@hidden
+       mv address@hidden $@
+MOSTLYCLEANFILES += errno.h errno.h-t
+
+EXTRA_DIST += errno.in.h
+
+## end   gnulib module errno
+
+## begin gnulib module float
+
+BUILT_SOURCES += $(FLOAT_H)
+
+# We need the following in order to create <float.h> when the system
+# doesn't have one that works with the given compiler.
+float.h: float.in.h
+       rm -f address@hidden $@
+       { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+         sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+             -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+             -e 's|@''NEXT_FLOAT_H''@|$(NEXT_FLOAT_H)|g' \
+             < $(srcdir)/float.in.h; \
+       } > address@hidden
+       mv address@hidden $@
+MOSTLYCLEANFILES += float.h float.h-t
+
+EXTRA_DIST += float.in.h
+
+## end   gnulib module float
+
 ## begin gnulib module flock
 
 
@@ -188,6 +236,15 @@ libgnu_la_SOURCES += full-write.h full-write.c
 
 ## end   gnulib module full-write
 
+## begin gnulib module getpagesize
+
+
+EXTRA_DIST += getpagesize.c
+
+EXTRA_libgnu_la_SOURCES += getpagesize.c
+
+## end   gnulib module getpagesize
+
 ## begin gnulib module gperf
 
 GPERF = gperf
@@ -390,6 +447,15 @@ EXTRA_libgnu_la_SOURCES += mbsinit.c
 
 ## end   gnulib module mbsinit
 
+## begin gnulib module memchr
+
+
+EXTRA_DIST += memchr.c memchr.valgrind
+
+EXTRA_libgnu_la_SOURCES += memchr.c
+
+## end   gnulib module memchr
+
 ## begin gnulib module pathmax
 
 
@@ -433,6 +499,12 @@ EXTRA_libgnu_la_SOURCES += safe-write.c
 
 ## end   gnulib module safe-write
 
+## begin gnulib module size_max
+
+libgnu_la_SOURCES += size_max.h
+
+## end   gnulib module size_max
+
 ## begin gnulib module stdbool
 
 BUILT_SOURCES += $(STDBOOL_H)
@@ -493,6 +565,99 @@ EXTRA_DIST += stdint.in.h
 
 ## end   gnulib module stdint
 
+## begin gnulib module stdio
+
+BUILT_SOURCES += stdio.h
+
+# We need the following in order to create <stdio.h> when the system
+# doesn't have one that works with the given compiler.
+stdio.h: stdio.in.h
+       rm -f address@hidden $@
+       { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+         sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+             -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+             -e 's|@''NEXT_STDIO_H''@|$(NEXT_STDIO_H)|g' \
+             -e 's|@''GNULIB_FPRINTF''@|$(GNULIB_FPRINTF)|g' \
+             -e 's|@''GNULIB_FPRINTF_POSIX''@|$(GNULIB_FPRINTF_POSIX)|g' \
+             -e 's|@''GNULIB_PRINTF''@|$(GNULIB_PRINTF)|g' \
+             -e 's|@''GNULIB_PRINTF_POSIX''@|$(GNULIB_PRINTF_POSIX)|g' \
+             -e 's|@''GNULIB_SNPRINTF''@|$(GNULIB_SNPRINTF)|g' \
+             -e 's|@''GNULIB_SPRINTF_POSIX''@|$(GNULIB_SPRINTF_POSIX)|g' \
+             -e 's|@''GNULIB_VFPRINTF''@|$(GNULIB_VFPRINTF)|g' \
+             -e 's|@''GNULIB_VFPRINTF_POSIX''@|$(GNULIB_VFPRINTF_POSIX)|g' \
+             -e 's|@''GNULIB_VPRINTF''@|$(GNULIB_VPRINTF)|g' \
+             -e 's|@''GNULIB_VPRINTF_POSIX''@|$(GNULIB_VPRINTF_POSIX)|g' \
+             -e 's|@''GNULIB_VSNPRINTF''@|$(GNULIB_VSNPRINTF)|g' \
+             -e 's|@''GNULIB_VSPRINTF_POSIX''@|$(GNULIB_VSPRINTF_POSIX)|g' \
+             -e 's|@''GNULIB_DPRINTF''@|$(GNULIB_DPRINTF)|g' \
+             -e 's|@''GNULIB_VDPRINTF''@|$(GNULIB_VDPRINTF)|g' \
+             -e 's|@''GNULIB_VASPRINTF''@|$(GNULIB_VASPRINTF)|g' \
+             -e 's|@''GNULIB_OBSTACK_PRINTF''@|$(GNULIB_OBSTACK_PRINTF)|g' \
+             -e 
's|@''GNULIB_OBSTACK_PRINTF_POSIX''@|$(GNULIB_OBSTACK_PRINTF_POSIX)|g' \
+             -e 's|@''GNULIB_FOPEN''@|$(GNULIB_FOPEN)|g' \
+             -e 's|@''GNULIB_FREOPEN''@|$(GNULIB_FREOPEN)|g' \
+             -e 's|@''GNULIB_FSEEK''@|$(GNULIB_FSEEK)|g' \
+             -e 's|@''GNULIB_FSEEKO''@|$(GNULIB_FSEEKO)|g' \
+             -e 's|@''GNULIB_FTELL''@|$(GNULIB_FTELL)|g' \
+             -e 's|@''GNULIB_FTELLO''@|$(GNULIB_FTELLO)|g' \
+             -e 's|@''GNULIB_FFLUSH''@|$(GNULIB_FFLUSH)|g' \
+             -e 's|@''GNULIB_FPURGE''@|$(GNULIB_FPURGE)|g' \
+             -e 's|@''GNULIB_FCLOSE''@|$(GNULIB_FCLOSE)|g' \
+             -e 's|@''GNULIB_FPUTC''@|$(GNULIB_FPUTC)|g' \
+             -e 's|@''GNULIB_PUTC''@|$(GNULIB_PUTC)|g' \
+             -e 's|@''GNULIB_PUTCHAR''@|$(GNULIB_PUTCHAR)|g' \
+             -e 's|@''GNULIB_FPUTS''@|$(GNULIB_FPUTS)|g' \
+             -e 's|@''GNULIB_PUTS''@|$(GNULIB_PUTS)|g' \
+             -e 's|@''GNULIB_FWRITE''@|$(GNULIB_FWRITE)|g' \
+             -e 's|@''GNULIB_GETDELIM''@|$(GNULIB_GETDELIM)|g' \
+             -e 's|@''GNULIB_GETLINE''@|$(GNULIB_GETLINE)|g' \
+             -e 's|@''GNULIB_PERROR''@|$(GNULIB_PERROR)|g' \
+             -e 's|@''GNULIB_STDIO_H_SIGPIPE''@|$(GNULIB_STDIO_H_SIGPIPE)|g' \
+             -e 
's|@''REPLACE_STDIO_WRITE_FUNCS''@|$(REPLACE_STDIO_WRITE_FUNCS)|g' \
+             -e 's|@''REPLACE_FPRINTF''@|$(REPLACE_FPRINTF)|g' \
+             -e 's|@''REPLACE_VFPRINTF''@|$(REPLACE_VFPRINTF)|g' \
+             -e 's|@''REPLACE_PRINTF''@|$(REPLACE_PRINTF)|g' \
+             -e 's|@''REPLACE_VPRINTF''@|$(REPLACE_VPRINTF)|g' \
+             -e 's|@''REPLACE_SNPRINTF''@|$(REPLACE_SNPRINTF)|g' \
+             -e 's|@''HAVE_DECL_SNPRINTF''@|$(HAVE_DECL_SNPRINTF)|g' \
+             -e 's|@''REPLACE_VSNPRINTF''@|$(REPLACE_VSNPRINTF)|g' \
+             -e 's|@''HAVE_DECL_VSNPRINTF''@|$(HAVE_DECL_VSNPRINTF)|g' \
+             -e 's|@''REPLACE_SPRINTF''@|$(REPLACE_SPRINTF)|g' \
+             -e 's|@''REPLACE_VSPRINTF''@|$(REPLACE_VSPRINTF)|g' \
+             -e 's|@''HAVE_DPRINTF''@|$(HAVE_DPRINTF)|g' \
+             -e 's|@''REPLACE_DPRINTF''@|$(REPLACE_DPRINTF)|g' \
+             -e 's|@''HAVE_VDPRINTF''@|$(HAVE_VDPRINTF)|g' \
+             -e 's|@''REPLACE_VDPRINTF''@|$(REPLACE_VDPRINTF)|g' \
+             -e 's|@''HAVE_VASPRINTF''@|$(HAVE_VASPRINTF)|g' \
+             -e 's|@''REPLACE_VASPRINTF''@|$(REPLACE_VASPRINTF)|g' \
+             -e 
's|@''HAVE_DECL_OBSTACK_PRINTF''@|$(HAVE_DECL_OBSTACK_PRINTF)|g' \
+             -e 's|@''REPLACE_OBSTACK_PRINTF''@|$(REPLACE_OBSTACK_PRINTF)|g' \
+             -e 's|@''REPLACE_FOPEN''@|$(REPLACE_FOPEN)|g' \
+             -e 's|@''REPLACE_FREOPEN''@|$(REPLACE_FREOPEN)|g' \
+             -e 's|@''REPLACE_FSEEKO''@|$(REPLACE_FSEEKO)|g' \
+             -e 's|@''REPLACE_FSEEK''@|$(REPLACE_FSEEK)|g' \
+             -e 's|@''REPLACE_FTELLO''@|$(REPLACE_FTELLO)|g' \
+             -e 's|@''REPLACE_FTELL''@|$(REPLACE_FTELL)|g' \
+             -e 's|@''REPLACE_FFLUSH''@|$(REPLACE_FFLUSH)|g' \
+             -e 's|@''REPLACE_FPURGE''@|$(REPLACE_FPURGE)|g' \
+             -e 's|@''HAVE_DECL_FPURGE''@|$(HAVE_DECL_FPURGE)|g' \
+             -e 's|@''REPLACE_FCLOSE''@|$(REPLACE_FCLOSE)|g' \
+             -e 's|@''HAVE_DECL_GETDELIM''@|$(HAVE_DECL_GETDELIM)|g' \
+             -e 's|@''HAVE_DECL_GETLINE''@|$(HAVE_DECL_GETLINE)|g' \
+             -e 's|@''REPLACE_GETLINE''@|$(REPLACE_GETLINE)|g' \
+             -e 's|@''REPLACE_PERROR''@|$(REPLACE_PERROR)|g' \
+             -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \
+             < $(srcdir)/stdio.in.h; \
+       } > address@hidden
+       mv address@hidden $@
+MOSTLYCLEANFILES += stdio.h stdio.h-t
+
+EXTRA_DIST += stdio-write.c stdio.in.h
+
+EXTRA_libgnu_la_SOURCES += stdio-write.c
+
+## end   gnulib module stdio
+
 ## begin gnulib module stdlib
 
 BUILT_SOURCES += stdlib.h
@@ -868,12 +1033,30 @@ EXTRA_DIST += unitypes.h
 
 ## end   gnulib module unitypes
 
+## begin gnulib module vasnprintf
+
+
+EXTRA_DIST += asnprintf.c float+.h printf-args.c printf-args.h printf-parse.c 
printf-parse.h vasnprintf.c vasnprintf.h
+
+EXTRA_libgnu_la_SOURCES += asnprintf.c printf-args.c printf-parse.c 
vasnprintf.c
+
+## end   gnulib module vasnprintf
+
 ## begin gnulib module verify
 
 libgnu_la_SOURCES += verify.h
 
 ## end   gnulib module verify
 
+## begin gnulib module vsnprintf
+
+
+EXTRA_DIST += vsnprintf.c
+
+EXTRA_libgnu_la_SOURCES += vsnprintf.c
+
+## end   gnulib module vsnprintf
+
 ## begin gnulib module wchar
 
 BUILT_SOURCES += $(WCHAR_H)
@@ -941,6 +1124,12 @@ EXTRA_libgnu_la_SOURCES += write.c
 
 ## end   gnulib module write
 
+## begin gnulib module xsize
+
+libgnu_la_SOURCES += xsize.h
+
+## end   gnulib module xsize
+
 
 mostlyclean-local: mostlyclean-generic
        @for dir in '' $(MOSTLYCLEANDIRS); do \
diff --git a/lib/time_r.c b/lib/asnprintf.c
similarity index 57%
copy from lib/time_r.c
copy to lib/asnprintf.c
index 90dcf00..3b374a2 100644
--- a/lib/time_r.c
+++ b/lib/asnprintf.c
@@ -1,6 +1,5 @@
-/* Reentrant time functions like localtime_r.
-
-   Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc.
+/* Formatted output to strings.
+   Copyright (C) 1999, 2002, 2006 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
@@ -16,32 +15,21 @@
    with this program; if not, write to the Free Software Foundation,
    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
-/* Written by Paul Eggert.  */
-
 #include <config.h>
 
-#include <time.h>
-
-#include <string.h>
-
-static struct tm *
-copy_tm_result (struct tm *dest, struct tm const *src)
-{
-  if (! src)
-    return 0;
-  *dest = *src;
-  return dest;
-}
+/* Specification.  */
+#include "vasnprintf.h"
 
+#include <stdarg.h>
 
-struct tm *
-gmtime_r (time_t const * restrict t, struct tm * restrict tp)
+char *
+asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
 {
-  return copy_tm_result (tp, gmtime (t));
-}
+  va_list args;
+  char *result;
 
-struct tm *
-localtime_r (time_t const * restrict t, struct tm * restrict tp)
-{
-  return copy_tm_result (tp, localtime (t));
+  va_start (args, format);
+  result = vasnprintf (resultbuf, lengthp, format, args);
+  va_end (args);
+  return result;
 }
diff --git a/lib/errno.in.h b/lib/errno.in.h
new file mode 100644
index 0000000..a9b81d5
--- /dev/null
+++ b/lib/errno.in.h
@@ -0,0 +1,160 @@
+/* A POSIX-like <errno.h>.
+
+   Copyright (C) 2008-2009 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 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _GL_ERRNO_H
+
+#if __GNUC__ >= 3
address@hidden@
+#endif
+
+/* The include_next requires a split double-inclusion guard.  */
address@hidden@ @NEXT_ERRNO_H@
+
+#ifndef _GL_ERRNO_H
+#define _GL_ERRNO_H
+
+
+/* On native Windows platforms, many macros are not defined.  */
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+/* POSIX says that EAGAIN and EWOULDBLOCK may have the same value.  */
+#  define EWOULDBLOCK     EAGAIN
+
+/* Values >= 100 seem safe to use.  */
+#  define ETXTBSY   100
+#  define GNULIB_defined_ETXTBSY 1
+
+/* These are intentionally the same values as the WSA* error numbers, defined
+   in <winsock2.h>.  */
+#  define EINPROGRESS     10036
+#  define EALREADY        10037
+#  define ENOTSOCK        10038
+#  define EDESTADDRREQ    10039
+#  define EMSGSIZE        10040
+#  define EPROTOTYPE      10041
+#  define ENOPROTOOPT     10042
+#  define EPROTONOSUPPORT 10043
+#  define ESOCKTNOSUPPORT 10044  /* not required by POSIX */
+#  define EOPNOTSUPP      10045
+#  define EPFNOSUPPORT    10046  /* not required by POSIX */
+#  define EAFNOSUPPORT    10047
+#  define EADDRINUSE      10048
+#  define EADDRNOTAVAIL   10049
+#  define ENETDOWN        10050
+#  define ENETUNREACH     10051
+#  define ENETRESET       10052
+#  define ECONNABORTED    10053
+#  define ECONNRESET      10054
+#  define ENOBUFS         10055
+#  define EISCONN         10056
+#  define ENOTCONN        10057
+#  define ESHUTDOWN       10058  /* not required by POSIX */
+#  define ETOOMANYREFS    10059  /* not required by POSIX */
+#  define ETIMEDOUT       10060
+#  define ECONNREFUSED    10061
+#  define ELOOP           10062
+#  define EHOSTDOWN       10064  /* not required by POSIX */
+#  define EHOSTUNREACH    10065
+#  define EPROCLIM        10067  /* not required by POSIX */
+#  define EUSERS          10068  /* not required by POSIX */
+#  define EDQUOT          10069
+#  define ESTALE          10070
+#  define EREMOTE         10071  /* not required by POSIX */
+#  define GNULIB_defined_ESOCK 1
+
+# endif
+
+
+/* On OSF/1 5.1, when _XOPEN_SOURCE_EXTENDED is not defined, the macros
+   EMULTIHOP, ENOLINK, EOVERFLOW are not defined.  */
+# if @EMULTIHOP_HIDDEN@
+#  define EMULTIHOP @EMULTIHOP_VALUE@
+#  define GNULIB_defined_EMULTIHOP 1
+# endif
+# if @ENOLINK_HIDDEN@
+#  define ENOLINK   @ENOLINK_VALUE@
+#  define GNULIB_defined_ENOLINK 1
+# endif
+# if @EOVERFLOW_HIDDEN@
+#  define EOVERFLOW @EOVERFLOW_VALUE@
+#  define GNULIB_defined_EOVERFLOW 1
+# endif
+
+
+/* On OpenBSD 4.0 and on native Windows, the macros ENOMSG, EIDRM, ENOLINK,
+   EPROTO, EMULTIHOP, EBADMSG, EOVERFLOW, ENOTSUP, ECANCELED are not defined.
+   Define them here.  Values >= 2000 seem safe to use: Solaris ESTALE = 151,
+   HP-UX EWOULDBLOCK = 246, IRIX EDQUOT = 1133.
+
+   Note: When one of these systems defines some of these macros some day,
+   binaries will have to be recompiled so that they recognizes the new
+   errno values from the system.  */
+
+# ifndef ENOMSG
+#  define ENOMSG    2000
+#  define GNULIB_defined_ENOMSG 1
+# endif
+
+# ifndef EIDRM
+#  define EIDRM     2001
+#  define GNULIB_defined_EIDRM 1
+# endif
+
+# ifndef ENOLINK
+#  define ENOLINK   2002
+#  define GNULIB_defined_ENOLINK 1
+# endif
+
+# ifndef EPROTO
+#  define EPROTO    2003
+#  define GNULIB_defined_EPROTO 1
+# endif
+
+# ifndef EMULTIHOP
+#  define EMULTIHOP 2004
+#  define GNULIB_defined_EMULTIHOP 1
+# endif
+
+# ifndef EBADMSG
+#  define EBADMSG   2005
+#  define GNULIB_defined_EBADMSG 1
+# endif
+
+# ifndef EOVERFLOW
+#  define EOVERFLOW 2006
+#  define GNULIB_defined_EOVERFLOW 1
+# endif
+
+# ifndef ENOTSUP
+#  define ENOTSUP   2007
+#  define GNULIB_defined_ENOTSUP 1
+# endif
+
+# ifndef ESTALE
+#  define ESTALE    2009
+#  define GNULIB_defined_ESTALE 1
+# endif
+
+# ifndef ECANCELED
+#  define ECANCELED 2008
+#  define GNULIB_defined_ECANCELED 1
+# endif
+
+
+#endif /* _GL_ERRNO_H */
+#endif /* _GL_ERRNO_H */
diff --git a/lib/float+.h b/lib/float+.h
new file mode 100644
index 0000000..2288e3d
--- /dev/null
+++ b/lib/float+.h
@@ -0,0 +1,148 @@
+/* Supplemental information about the floating-point formats.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   Written by Bruno Haible <address@hidden>, 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 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _FLOATPLUS_H
+#define _FLOATPLUS_H
+
+#include <float.h>
+#include <limits.h>
+
+/* Number of bits in the mantissa of a floating-point number, including the
+   "hidden bit".  */
+#if FLT_RADIX == 2
+# define FLT_MANT_BIT FLT_MANT_DIG
+# define DBL_MANT_BIT DBL_MANT_DIG
+# define LDBL_MANT_BIT LDBL_MANT_DIG
+#elif FLT_RADIX == 4
+# define FLT_MANT_BIT (FLT_MANT_DIG * 2)
+# define DBL_MANT_BIT (DBL_MANT_DIG * 2)
+# define LDBL_MANT_BIT (LDBL_MANT_DIG * 2)
+#elif FLT_RADIX == 16
+# define FLT_MANT_BIT (FLT_MANT_DIG * 4)
+# define DBL_MANT_BIT (DBL_MANT_DIG * 4)
+# define LDBL_MANT_BIT (LDBL_MANT_DIG * 4)
+#endif
+
+/* Bit mask that can be used to mask the exponent, as an unsigned number.  */
+#define FLT_EXP_MASK ((FLT_MAX_EXP - FLT_MIN_EXP) | 7)
+#define DBL_EXP_MASK ((DBL_MAX_EXP - DBL_MIN_EXP) | 7)
+#define LDBL_EXP_MASK ((LDBL_MAX_EXP - LDBL_MIN_EXP) | 7)
+
+/* Number of bits used for the exponent of a floating-point number, including
+   the exponent's sign.  */
+#define FLT_EXP_BIT \
+  (FLT_EXP_MASK < 0x100 ? 8 : \
+   FLT_EXP_MASK < 0x200 ? 9 : \
+   FLT_EXP_MASK < 0x400 ? 10 : \
+   FLT_EXP_MASK < 0x800 ? 11 : \
+   FLT_EXP_MASK < 0x1000 ? 12 : \
+   FLT_EXP_MASK < 0x2000 ? 13 : \
+   FLT_EXP_MASK < 0x4000 ? 14 : \
+   FLT_EXP_MASK < 0x8000 ? 15 : \
+   FLT_EXP_MASK < 0x10000 ? 16 : \
+   FLT_EXP_MASK < 0x20000 ? 17 : \
+   FLT_EXP_MASK < 0x40000 ? 18 : \
+   FLT_EXP_MASK < 0x80000 ? 19 : \
+   FLT_EXP_MASK < 0x100000 ? 20 : \
+   FLT_EXP_MASK < 0x200000 ? 21 : \
+   FLT_EXP_MASK < 0x400000 ? 22 : \
+   FLT_EXP_MASK < 0x800000 ? 23 : \
+   FLT_EXP_MASK < 0x1000000 ? 24 : \
+   FLT_EXP_MASK < 0x2000000 ? 25 : \
+   FLT_EXP_MASK < 0x4000000 ? 26 : \
+   FLT_EXP_MASK < 0x8000000 ? 27 : \
+   FLT_EXP_MASK < 0x10000000 ? 28 : \
+   FLT_EXP_MASK < 0x20000000 ? 29 : \
+   FLT_EXP_MASK < 0x40000000 ? 30 : \
+   FLT_EXP_MASK <= 0x7fffffff ? 31 : \
+   32)
+#define DBL_EXP_BIT \
+  (DBL_EXP_MASK < 0x100 ? 8 : \
+   DBL_EXP_MASK < 0x200 ? 9 : \
+   DBL_EXP_MASK < 0x400 ? 10 : \
+   DBL_EXP_MASK < 0x800 ? 11 : \
+   DBL_EXP_MASK < 0x1000 ? 12 : \
+   DBL_EXP_MASK < 0x2000 ? 13 : \
+   DBL_EXP_MASK < 0x4000 ? 14 : \
+   DBL_EXP_MASK < 0x8000 ? 15 : \
+   DBL_EXP_MASK < 0x10000 ? 16 : \
+   DBL_EXP_MASK < 0x20000 ? 17 : \
+   DBL_EXP_MASK < 0x40000 ? 18 : \
+   DBL_EXP_MASK < 0x80000 ? 19 : \
+   DBL_EXP_MASK < 0x100000 ? 20 : \
+   DBL_EXP_MASK < 0x200000 ? 21 : \
+   DBL_EXP_MASK < 0x400000 ? 22 : \
+   DBL_EXP_MASK < 0x800000 ? 23 : \
+   DBL_EXP_MASK < 0x1000000 ? 24 : \
+   DBL_EXP_MASK < 0x2000000 ? 25 : \
+   DBL_EXP_MASK < 0x4000000 ? 26 : \
+   DBL_EXP_MASK < 0x8000000 ? 27 : \
+   DBL_EXP_MASK < 0x10000000 ? 28 : \
+   DBL_EXP_MASK < 0x20000000 ? 29 : \
+   DBL_EXP_MASK < 0x40000000 ? 30 : \
+   DBL_EXP_MASK <= 0x7fffffff ? 31 : \
+   32)
+#define LDBL_EXP_BIT \
+  (LDBL_EXP_MASK < 0x100 ? 8 : \
+   LDBL_EXP_MASK < 0x200 ? 9 : \
+   LDBL_EXP_MASK < 0x400 ? 10 : \
+   LDBL_EXP_MASK < 0x800 ? 11 : \
+   LDBL_EXP_MASK < 0x1000 ? 12 : \
+   LDBL_EXP_MASK < 0x2000 ? 13 : \
+   LDBL_EXP_MASK < 0x4000 ? 14 : \
+   LDBL_EXP_MASK < 0x8000 ? 15 : \
+   LDBL_EXP_MASK < 0x10000 ? 16 : \
+   LDBL_EXP_MASK < 0x20000 ? 17 : \
+   LDBL_EXP_MASK < 0x40000 ? 18 : \
+   LDBL_EXP_MASK < 0x80000 ? 19 : \
+   LDBL_EXP_MASK < 0x100000 ? 20 : \
+   LDBL_EXP_MASK < 0x200000 ? 21 : \
+   LDBL_EXP_MASK < 0x400000 ? 22 : \
+   LDBL_EXP_MASK < 0x800000 ? 23 : \
+   LDBL_EXP_MASK < 0x1000000 ? 24 : \
+   LDBL_EXP_MASK < 0x2000000 ? 25 : \
+   LDBL_EXP_MASK < 0x4000000 ? 26 : \
+   LDBL_EXP_MASK < 0x8000000 ? 27 : \
+   LDBL_EXP_MASK < 0x10000000 ? 28 : \
+   LDBL_EXP_MASK < 0x20000000 ? 29 : \
+   LDBL_EXP_MASK < 0x40000000 ? 30 : \
+   LDBL_EXP_MASK <= 0x7fffffff ? 31 : \
+   32)
+
+/* Number of bits used for a floating-point number: the mantissa (not
+   counting the "hidden bit", since it may or may not be explicit), the
+   exponent, and the sign.  */
+#define FLT_TOTAL_BIT ((FLT_MANT_BIT - 1) + FLT_EXP_BIT + 1)
+#define DBL_TOTAL_BIT ((DBL_MANT_BIT - 1) + DBL_EXP_BIT + 1)
+#define LDBL_TOTAL_BIT ((LDBL_MANT_BIT - 1) + LDBL_EXP_BIT + 1)
+
+/* Number of bytes used for a floating-point number.
+   This can be smaller than the 'sizeof'.  For example, on i386 systems,
+   'long double' most often have LDBL_MANT_BIT = 64, LDBL_EXP_BIT = 16, hence
+   LDBL_TOTAL_BIT = 80 bits, i.e. 10 bytes of consecutive memory, but
+   sizeof (long double) = 12 or = 16.  */
+#define SIZEOF_FLT ((FLT_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT)
+#define SIZEOF_DBL ((DBL_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT)
+#define SIZEOF_LDBL ((LDBL_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT)
+
+/* Verify that SIZEOF_FLT <= sizeof (float) etc.  */
+typedef int verify_sizeof_flt[2 * (SIZEOF_FLT <= sizeof (float)) - 1];
+typedef int verify_sizeof_dbl[2 * (SIZEOF_DBL <= sizeof (double)) - 1];
+typedef int verify_sizeof_ldbl[2 * (SIZEOF_LDBL <= sizeof (long double)) - 1];
+
+#endif /* _FLOATPLUS_H */
diff --git a/lib/float.in.h b/lib/float.in.h
new file mode 100644
index 0000000..63d55f8
--- /dev/null
+++ b/lib/float.in.h
@@ -0,0 +1,62 @@
+/* A correct <float.h>.
+
+   Copyright (C) 2007-2008 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_FLOAT_H
+
+#if __GNUC__ >= 3
address@hidden@
+#endif
+
+/* The include_next requires a split double-inclusion guard.  */
address@hidden@ @NEXT_FLOAT_H@
+
+#ifndef _GL_FLOAT_H
+#define _GL_FLOAT_H
+
+/* 'long double' properties.  */
+#if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__)
+/* Number of mantissa units, in base FLT_RADIX.  */
+# undef LDBL_MANT_DIG
+# define LDBL_MANT_DIG   64
+/* Number of decimal digits that is sufficient for representing a number.  */
+# undef LDBL_DIG
+# define LDBL_DIG        18
+/* x-1 where x is the smallest representable number > 1.  */
+# undef LDBL_EPSILON
+# define LDBL_EPSILON    1.0842021724855044340E-19L
+/* Minimum e such that FLT_RADIX^(e-1) is a normalized number.  */
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP    (-16381)
+/* Maximum e such that FLT_RADIX^(e-1) is a representable finite number.  */
+# undef LDBL_MAX_EXP
+# define LDBL_MAX_EXP    16384
+/* Minimum positive normalized number.  */
+# undef LDBL_MIN
+# define LDBL_MIN        3.3621031431120935063E-4932L
+/* Maximum representable finite number.  */
+# undef LDBL_MAX
+# define LDBL_MAX        1.1897314953572317650E+4932L
+/* Minimum e such that 10^e is in the range of normalized numbers.  */
+# undef LDBL_MIN_10_EXP
+# define LDBL_MIN_10_EXP (-4931)
+/* Maximum e such that 10^e is in the range of representable finite numbers.  
*/
+# undef LDBL_MAX_10_EXP
+# define LDBL_MAX_10_EXP 4932
+#endif
+
+#endif /* _GL_FLOAT_H */
+#endif /* _GL_FLOAT_H */
diff --git a/lib/mbrlen.c b/lib/getpagesize.c
similarity index 57%
copy from lib/mbrlen.c
copy to lib/getpagesize.c
index 94c66d6..82238df 100644
--- a/lib/mbrlen.c
+++ b/lib/getpagesize.c
@@ -1,6 +1,6 @@
-/* Recognize multibyte character.
-   Copyright (C) 1999-2000, 2008 Free Software Foundation, Inc.
-   Written by Bruno Haible <address@hidden>, 2008.
+/* getpagesize emulation for systems where it cannot be done in a C macro.
+
+   Copyright (C) 2007 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
@@ -15,18 +15,25 @@
    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 and Martin Lambers.  */
+
 #include <config.h>
 
-/* Specification.  */
-#include <wchar.h>
+/* Specification. */
+#include <unistd.h>
 
+/* This implementation is only for native Win32 systems.  */
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
 
-static mbstate_t internal_state;
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
 
-size_t
-mbrlen (const char *s, size_t n, mbstate_t *ps)
+int
+getpagesize (void)
 {
-  if (ps == NULL)
-    ps = &internal_state;
-  return mbrtowc (NULL, s, n, ps);
+  SYSTEM_INFO system_info;
+  GetSystemInfo (&system_info);
+  return system_info.dwPageSize;
 }
+
+#endif
diff --git a/lib/memchr.c b/lib/memchr.c
new file mode 100644
index 0000000..3ea1d5b
--- /dev/null
+++ b/lib/memchr.c
@@ -0,0 +1,172 @@
+/* Copyright (C) 1991, 1993, 1996, 1997, 1999, 2000, 2003, 2004, 2006, 2008
+   Free Software Foundation, Inc.
+
+   Based on strlen implementation by Torbjorn Granlund (address@hidden),
+   with help from Dan Sahlin (address@hidden) and
+   commentary by Jim Blandy (address@hidden);
+   adaptation to memchr suggested by Dick Karpinski (address@hidden),
+   and implemented by Roland McGrath (address@hidden).
+
+NOTE: The canonical source of this file is maintained with the GNU C Library.
+Bugs can be reported to address@hidden
+
+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 any
+later version.
+
+This program is distributed in the hope that 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 _LIBC
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <stddef.h>
+
+#if defined _LIBC
+# include <memcopy.h>
+#else
+# define reg_char char
+#endif
+
+#include <limits.h>
+
+#if HAVE_BP_SYM_H || defined _LIBC
+# include <bp-sym.h>
+#else
+# define BP_SYM(sym) sym
+#endif
+
+#undef __memchr
+#ifdef _LIBC
+# undef memchr
+#endif
+
+#ifndef weak_alias
+# define __memchr memchr
+#endif
+
+/* Search no more than N bytes of S for C.  */
+void *
+__memchr (void const *s, int c_in, size_t n)
+{
+  /* On 32-bit hardware, choosing longword to be a 32-bit unsigned
+     long instead of a 64-bit uintmax_t tends to give better
+     performance.  On 64-bit hardware, unsigned long is generally 64
+     bits already.  Change this typedef to experiment with
+     performance.  */
+  typedef unsigned long int longword;
+
+  const unsigned char *char_ptr;
+  const longword *longword_ptr;
+  longword repeated_one;
+  longword repeated_c;
+  unsigned reg_char c;
+
+  c = (unsigned char) c_in;
+
+  /* Handle the first few bytes by reading one byte at a time.
+     Do this until CHAR_PTR is aligned on a longword boundary.  */
+  for (char_ptr = (const unsigned char *) s;
+       n > 0 && (size_t) char_ptr % sizeof (longword) != 0;
+       --n, ++char_ptr)
+    if (*char_ptr == c)
+      return (void *) char_ptr;
+
+  longword_ptr = (const longword *) char_ptr;
+
+  /* All these elucidatory comments refer to 4-byte longwords,
+     but the theory applies equally well to any size longwords.  */
+
+  /* Compute auxiliary longword values:
+     repeated_one is a value which has a 1 in every byte.
+     repeated_c has c in every byte.  */
+  repeated_one = 0x01010101;
+  repeated_c = c | (c << 8);
+  repeated_c |= repeated_c << 16;
+  if (0xffffffffU < (longword) -1)
+    {
+      repeated_one |= repeated_one << 31 << 1;
+      repeated_c |= repeated_c << 31 << 1;
+      if (8 < sizeof (longword))
+       {
+         size_t i;
+
+         for (i = 64; i < sizeof (longword) * 8; i *= 2)
+           {
+             repeated_one |= repeated_one << i;
+             repeated_c |= repeated_c << i;
+           }
+       }
+    }
+
+  /* Instead of the traditional loop which tests each byte, we will test a
+     longword at a time.  The tricky part is testing if *any of the four*
+     bytes in the longword in question are equal to c.  We first use an xor
+     with repeated_c.  This reduces the task to testing whether *any of the
+     four* bytes in longword1 is zero.
+
+     We compute tmp =
+       ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7).
+     That is, we perform the following operations:
+       1. Subtract repeated_one.
+       2. & ~longword1.
+       3. & a mask consisting of 0x80 in every byte.
+     Consider what happens in each byte:
+       - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
+         and step 3 transforms it into 0x80.  A carry can also be propagated
+         to more significant bytes.
+       - If a byte of longword1 is nonzero, let its lowest 1 bit be at
+         position k (0 <= k <= 7); so the lowest k bits are 0.  After step 1,
+         the byte ends in a single bit of value 0 and k bits of value 1.
+         After step 2, the result is just k bits of value 1: 2^k - 1.  After
+         step 3, the result is 0.  And no carry is produced.
+     So, if longword1 has only non-zero bytes, tmp is zero.
+     Whereas if longword1 has a zero byte, call j the position of the least
+     significant zero byte.  Then the result has a zero at positions 0, ...,
+     j-1 and a 0x80 at position j.  We cannot predict the result at the more
+     significant bytes (positions j+1..3), but it does not matter since we
+     already have a non-zero bit at position 8*j+7.
+
+     So, the test whether any byte in longword1 is zero is equivalent to
+     testing whether tmp is nonzero.  */
+
+  while (n >= sizeof (longword))
+    {
+      longword longword1 = *longword_ptr ^ repeated_c;
+
+      if ((((longword1 - repeated_one) & ~longword1)
+          & (repeated_one << 7)) != 0)
+       break;
+      longword_ptr++;
+      n -= sizeof (longword);
+    }
+
+  char_ptr = (const unsigned char *) longword_ptr;
+
+  /* At this point, we know that either n < sizeof (longword), or one of the
+     sizeof (longword) bytes starting at char_ptr is == c.  On little-endian
+     machines, we could determine the first such byte without any further
+     memory accesses, just by looking at the tmp result from the last loop
+     iteration.  But this does not work on big-endian machines.  Choose code
+     that works in both cases.  */
+
+  for (; n > 0; --n, ++char_ptr)
+    {
+      if (*char_ptr == c)
+       return (void *) char_ptr;
+    }
+
+  return NULL;
+}
+#ifdef weak_alias
+weak_alias (__memchr, BP_SYM (memchr))
+#endif
diff --git a/lib/memchr.valgrind b/lib/memchr.valgrind
new file mode 100644
index 0000000..60f247e
--- /dev/null
+++ b/lib/memchr.valgrind
@@ -0,0 +1,14 @@
+# Suppress a valgrind message about use of uninitialized memory in memchr().
+# POSIX states that when the character is found, memchr must not read extra
+# bytes in an overestimated length (for example, where memchr is used to
+# implement strnlen).  However, we use a safe word read to provide a speedup.
+{
+    memchr-value4
+    Memcheck:Value4
+    fun:rpl_memchr
+}
+{
+    memchr-value8
+    Memcheck:Value8
+    fun:rpl_memchr
+}
diff --git a/lib/printf-args.c b/lib/printf-args.c
new file mode 100644
index 0000000..c31d204
--- /dev/null
+++ b/lib/printf-args.c
@@ -0,0 +1,187 @@
+/* Decomposed printf argument list.
+   Copyright (C) 1999, 2002-2003, 2005-2007 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* This file can be parametrized with the following macros:
+     ENABLE_UNISTDIO    Set to 1 to enable the unistdio extensions.
+     PRINTF_FETCHARGS   Name of the function to be defined.
+     STATIC             Set to 'static' to declare the function static.  */
+
+#ifndef PRINTF_FETCHARGS
+# include <config.h>
+#endif
+
+/* Specification.  */
+#ifndef PRINTF_FETCHARGS
+# include "printf-args.h"
+#endif
+
+#ifdef STATIC
+STATIC
+#endif
+int
+PRINTF_FETCHARGS (va_list args, arguments *a)
+{
+  size_t i;
+  argument *ap;
+
+  for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++)
+    switch (ap->type)
+      {
+      case TYPE_SCHAR:
+       ap->a.a_schar = va_arg (args, /*signed char*/ int);
+       break;
+      case TYPE_UCHAR:
+       ap->a.a_uchar = va_arg (args, /*unsigned char*/ int);
+       break;
+      case TYPE_SHORT:
+       ap->a.a_short = va_arg (args, /*short*/ int);
+       break;
+      case TYPE_USHORT:
+       ap->a.a_ushort = va_arg (args, /*unsigned short*/ int);
+       break;
+      case TYPE_INT:
+       ap->a.a_int = va_arg (args, int);
+       break;
+      case TYPE_UINT:
+       ap->a.a_uint = va_arg (args, unsigned int);
+       break;
+      case TYPE_LONGINT:
+       ap->a.a_longint = va_arg (args, long int);
+       break;
+      case TYPE_ULONGINT:
+       ap->a.a_ulongint = va_arg (args, unsigned long int);
+       break;
+#if HAVE_LONG_LONG_INT
+      case TYPE_LONGLONGINT:
+       ap->a.a_longlongint = va_arg (args, long long int);
+       break;
+      case TYPE_ULONGLONGINT:
+       ap->a.a_ulonglongint = va_arg (args, unsigned long long int);
+       break;
+#endif
+      case TYPE_DOUBLE:
+       ap->a.a_double = va_arg (args, double);
+       break;
+      case TYPE_LONGDOUBLE:
+       ap->a.a_longdouble = va_arg (args, long double);
+       break;
+      case TYPE_CHAR:
+       ap->a.a_char = va_arg (args, int);
+       break;
+#if HAVE_WINT_T
+      case TYPE_WIDE_CHAR:
+       /* Although ISO C 99 7.24.1.(2) says that wint_t is "unchanged by
+          default argument promotions", this is not the case in mingw32,
+          where wint_t is 'unsigned short'.  */
+       ap->a.a_wide_char =
+         (sizeof (wint_t) < sizeof (int)
+          ? va_arg (args, int)
+          : va_arg (args, wint_t));
+       break;
+#endif
+      case TYPE_STRING:
+       ap->a.a_string = va_arg (args, const char *);
+       /* A null pointer is an invalid argument for "%s", but in practice
+          it occurs quite frequently in printf statements that produce
+          debug output.  Use a fallback in this case.  */
+       if (ap->a.a_string == NULL)
+         ap->a.a_string = "(NULL)";
+       break;
+#if HAVE_WCHAR_T
+      case TYPE_WIDE_STRING:
+       ap->a.a_wide_string = va_arg (args, const wchar_t *);
+       /* A null pointer is an invalid argument for "%ls", but in practice
+          it occurs quite frequently in printf statements that produce
+          debug output.  Use a fallback in this case.  */
+       if (ap->a.a_wide_string == NULL)
+         {
+           static const wchar_t wide_null_string[] =
+             {
+               (wchar_t)'(',
+               (wchar_t)'N', (wchar_t)'U', (wchar_t)'L', (wchar_t)'L',
+               (wchar_t)')',
+               (wchar_t)0
+             };
+           ap->a.a_wide_string = wide_null_string;
+         }
+       break;
+#endif
+      case TYPE_POINTER:
+       ap->a.a_pointer = va_arg (args, void *);
+       break;
+      case TYPE_COUNT_SCHAR_POINTER:
+       ap->a.a_count_schar_pointer = va_arg (args, signed char *);
+       break;
+      case TYPE_COUNT_SHORT_POINTER:
+       ap->a.a_count_short_pointer = va_arg (args, short *);
+       break;
+      case TYPE_COUNT_INT_POINTER:
+       ap->a.a_count_int_pointer = va_arg (args, int *);
+       break;
+      case TYPE_COUNT_LONGINT_POINTER:
+       ap->a.a_count_longint_pointer = va_arg (args, long int *);
+       break;
+#if HAVE_LONG_LONG_INT
+      case TYPE_COUNT_LONGLONGINT_POINTER:
+       ap->a.a_count_longlongint_pointer = va_arg (args, long long int *);
+       break;
+#endif
+#if ENABLE_UNISTDIO
+      /* The unistdio extensions.  */
+      case TYPE_U8_STRING:
+       ap->a.a_u8_string = va_arg (args, const uint8_t *);
+       /* A null pointer is an invalid argument for "%U", but in practice
+          it occurs quite frequently in printf statements that produce
+          debug output.  Use a fallback in this case.  */
+       if (ap->a.a_u8_string == NULL)
+         {
+           static const uint8_t u8_null_string[] =
+             { '(', 'N', 'U', 'L', 'L', ')', 0 };
+           ap->a.a_u8_string = u8_null_string;
+         }
+       break;
+      case TYPE_U16_STRING:
+       ap->a.a_u16_string = va_arg (args, const uint16_t *);
+       /* A null pointer is an invalid argument for "%lU", but in practice
+          it occurs quite frequently in printf statements that produce
+          debug output.  Use a fallback in this case.  */
+       if (ap->a.a_u16_string == NULL)
+         {
+           static const uint16_t u16_null_string[] =
+             { '(', 'N', 'U', 'L', 'L', ')', 0 };
+           ap->a.a_u16_string = u16_null_string;
+         }
+       break;
+      case TYPE_U32_STRING:
+       ap->a.a_u32_string = va_arg (args, const uint32_t *);
+       /* A null pointer is an invalid argument for "%llU", but in practice
+          it occurs quite frequently in printf statements that produce
+          debug output.  Use a fallback in this case.  */
+       if (ap->a.a_u32_string == NULL)
+         {
+           static const uint32_t u32_null_string[] =
+             { '(', 'N', 'U', 'L', 'L', ')', 0 };
+           ap->a.a_u32_string = u32_null_string;
+         }
+       break;
+#endif
+      default:
+       /* Unknown type.  */
+       return -1;
+      }
+  return 0;
+}
diff --git a/lib/printf-args.h b/lib/printf-args.h
new file mode 100644
index 0000000..4c68f11
--- /dev/null
+++ b/lib/printf-args.h
@@ -0,0 +1,154 @@
+/* Decomposed printf argument list.
+   Copyright (C) 1999, 2002-2003, 2006-2007 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _PRINTF_ARGS_H
+#define _PRINTF_ARGS_H
+
+/* This file can be parametrized with the following macros:
+     ENABLE_UNISTDIO    Set to 1 to enable the unistdio extensions.
+     PRINTF_FETCHARGS   Name of the function to be declared.
+     STATIC             Set to 'static' to declare the function static.  */
+
+/* Default parameters.  */
+#ifndef PRINTF_FETCHARGS
+# define PRINTF_FETCHARGS printf_fetchargs
+#endif
+
+/* Get size_t.  */
+#include <stddef.h>
+
+/* Get wchar_t.  */
+#if HAVE_WCHAR_T
+# include <stddef.h>
+#endif
+
+/* Get wint_t.  */
+#if HAVE_WINT_T
+# include <wchar.h>
+#endif
+
+/* Get va_list.  */
+#include <stdarg.h>
+
+
+/* Argument types */
+typedef enum
+{
+  TYPE_NONE,
+  TYPE_SCHAR,
+  TYPE_UCHAR,
+  TYPE_SHORT,
+  TYPE_USHORT,
+  TYPE_INT,
+  TYPE_UINT,
+  TYPE_LONGINT,
+  TYPE_ULONGINT,
+#if HAVE_LONG_LONG_INT
+  TYPE_LONGLONGINT,
+  TYPE_ULONGLONGINT,
+#endif
+  TYPE_DOUBLE,
+  TYPE_LONGDOUBLE,
+  TYPE_CHAR,
+#if HAVE_WINT_T
+  TYPE_WIDE_CHAR,
+#endif
+  TYPE_STRING,
+#if HAVE_WCHAR_T
+  TYPE_WIDE_STRING,
+#endif
+  TYPE_POINTER,
+  TYPE_COUNT_SCHAR_POINTER,
+  TYPE_COUNT_SHORT_POINTER,
+  TYPE_COUNT_INT_POINTER,
+  TYPE_COUNT_LONGINT_POINTER
+#if HAVE_LONG_LONG_INT
+, TYPE_COUNT_LONGLONGINT_POINTER
+#endif
+#if ENABLE_UNISTDIO
+  /* The unistdio extensions.  */
+, TYPE_U8_STRING
+, TYPE_U16_STRING
+, TYPE_U32_STRING
+#endif
+} arg_type;
+
+/* Polymorphic argument */
+typedef struct
+{
+  arg_type type;
+  union
+  {
+    signed char                        a_schar;
+    unsigned char              a_uchar;
+    short                      a_short;
+    unsigned short             a_ushort;
+    int                                a_int;
+    unsigned int               a_uint;
+    long int                   a_longint;
+    unsigned long int          a_ulongint;
+#if HAVE_LONG_LONG_INT
+    long long int              a_longlongint;
+    unsigned long long int     a_ulonglongint;
+#endif
+    float                      a_float;
+    double                     a_double;
+    long double                        a_longdouble;
+    int                                a_char;
+#if HAVE_WINT_T
+    wint_t                     a_wide_char;
+#endif
+    const char*                        a_string;
+#if HAVE_WCHAR_T
+    const wchar_t*             a_wide_string;
+#endif
+    void*                      a_pointer;
+    signed char *              a_count_schar_pointer;
+    short *                    a_count_short_pointer;
+    int *                      a_count_int_pointer;
+    long int *                 a_count_longint_pointer;
+#if HAVE_LONG_LONG_INT
+    long long int *            a_count_longlongint_pointer;
+#endif
+#if ENABLE_UNISTDIO
+    /* The unistdio extensions.  */
+    const uint8_t *            a_u8_string;
+    const uint16_t *           a_u16_string;
+    const uint32_t *           a_u32_string;
+#endif
+  }
+  a;
+}
+argument;
+
+typedef struct
+{
+  size_t count;
+  argument *arg;
+}
+arguments;
+
+
+/* Fetch the arguments, putting them into a. */
+#ifdef STATIC
+STATIC
+#else
+extern
+#endif
+int PRINTF_FETCHARGS (va_list args, arguments *a);
+
+#endif /* _PRINTF_ARGS_H */
diff --git a/lib/printf-parse.c b/lib/printf-parse.c
new file mode 100644
index 0000000..85c454b
--- /dev/null
+++ b/lib/printf-parse.c
@@ -0,0 +1,627 @@
+/* Formatted output to strings.
+   Copyright (C) 1999-2000, 2002-2003, 2006-2008 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 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* This file can be parametrized with the following macros:
+     CHAR_T             The element type of the format string.
+     CHAR_T_ONLY_ASCII  Set to 1 to enable verification that all characters
+                        in the format string are ASCII.
+     DIRECTIVE          Structure denoting a format directive.
+                        Depends on CHAR_T.
+     DIRECTIVES         Structure denoting the set of format directives of a
+                        format string.  Depends on CHAR_T.
+     PRINTF_PARSE       Function that parses a format string.
+                        Depends on CHAR_T.
+     STATIC             Set to 'static' to declare the function static.
+     ENABLE_UNISTDIO    Set to 1 to enable the unistdio extensions.  */
+
+#ifndef PRINTF_PARSE
+# include <config.h>
+#endif
+
+/* Specification.  */
+#ifndef PRINTF_PARSE
+# include "printf-parse.h"
+#endif
+
+/* Default parameters.  */
+#ifndef PRINTF_PARSE
+# define PRINTF_PARSE printf_parse
+# define CHAR_T char
+# define DIRECTIVE char_directive
+# define DIRECTIVES char_directives
+#endif
+
+/* Get size_t, NULL.  */
+#include <stddef.h>
+
+/* Get intmax_t.  */
+#if defined IN_LIBINTL || defined IN_LIBASPRINTF
+# if HAVE_STDINT_H_WITH_UINTMAX
+#  include <stdint.h>
+# endif
+# if HAVE_INTTYPES_H_WITH_UINTMAX
+#  include <inttypes.h>
+# endif
+#else
+# include <stdint.h>
+#endif
+
+/* malloc(), realloc(), free().  */
+#include <stdlib.h>
+
+/* errno.  */
+#include <errno.h>
+
+/* Checked size_t computations.  */
+#include "xsize.h"
+
+#if CHAR_T_ONLY_ASCII
+/* c_isascii().  */
+# include "c-ctype.h"
+#endif
+
+#ifdef STATIC
+STATIC
+#endif
+int
+PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
+{
+  const CHAR_T *cp = format;           /* pointer into format */
+  size_t arg_posn = 0;         /* number of regular arguments consumed */
+  size_t d_allocated;                  /* allocated elements of d->dir */
+  size_t a_allocated;                  /* allocated elements of a->arg */
+  size_t max_width_length = 0;
+  size_t max_precision_length = 0;
+
+  d->count = 0;
+  d_allocated = 1;
+  d->dir = (DIRECTIVE *) malloc (d_allocated * sizeof (DIRECTIVE));
+  if (d->dir == NULL)
+    /* Out of memory.  */
+    goto out_of_memory_1;
+
+  a->count = 0;
+  a_allocated = 0;
+  a->arg = NULL;
+
+#define REGISTER_ARG(_index_,_type_) \
+  {                                                                    \
+    size_t n = (_index_);                                              \
+    if (n >= a_allocated)                                              \
+      {                                                                        
\
+       size_t memory_size;                                             \
+       argument *memory;                                               \
+                                                                       \
+       a_allocated = xtimes (a_allocated, 2);                          \
+       if (a_allocated <= n)                                           \
+         a_allocated = xsum (n, 1);                                    \
+       memory_size = xtimes (a_allocated, sizeof (argument));          \
+       if (size_overflow_p (memory_size))                              \
+         /* Overflow, would lead to out of memory.  */                 \
+         goto out_of_memory;                                           \
+       memory = (argument *) (a->arg                                   \
+                              ? realloc (a->arg, memory_size)          \
+                              : malloc (memory_size));                 \
+       if (memory == NULL)                                             \
+         /* Out of memory.  */                                         \
+         goto out_of_memory;                                           \
+       a->arg = memory;                                                \
+      }                                                                        
\
+    while (a->count <= n)                                              \
+      a->arg[a->count++].type = TYPE_NONE;                             \
+    if (a->arg[n].type == TYPE_NONE)                                   \
+      a->arg[n].type = (_type_);                                       \
+    else if (a->arg[n].type != (_type_))                               \
+      /* Ambiguous type for positional argument.  */                   \
+      goto error;                                                      \
+  }
+
+  while (*cp != '\0')
+    {
+      CHAR_T c = *cp++;
+      if (c == '%')
+       {
+         size_t arg_index = ARG_NONE;
+         DIRECTIVE *dp = &d->dir[d->count]; /* pointer to next directive */
+
+         /* Initialize the next directive.  */
+         dp->dir_start = cp - 1;
+         dp->flags = 0;
+         dp->width_start = NULL;
+         dp->width_end = NULL;
+         dp->width_arg_index = ARG_NONE;
+         dp->precision_start = NULL;
+         dp->precision_end = NULL;
+         dp->precision_arg_index = ARG_NONE;
+         dp->arg_index = ARG_NONE;
+
+         /* Test for positional argument.  */
+         if (*cp >= '0' && *cp <= '9')
+           {
+             const CHAR_T *np;
+
+             for (np = cp; *np >= '0' && *np <= '9'; np++)
+               ;
+             if (*np == '$')
+               {
+                 size_t n = 0;
+
+                 for (np = cp; *np >= '0' && *np <= '9'; np++)
+                   n = xsum (xtimes (n, 10), *np - '0');
+                 if (n == 0)
+                   /* Positional argument 0.  */
+                   goto error;
+                 if (size_overflow_p (n))
+                   /* n too large, would lead to out of memory later.  */
+                   goto error;
+                 arg_index = n - 1;
+                 cp = np + 1;
+               }
+           }
+
+         /* Read the flags.  */
+         for (;;)
+           {
+             if (*cp == '\'')
+               {
+                 dp->flags |= FLAG_GROUP;
+                 cp++;
+               }
+             else if (*cp == '-')
+               {
+                 dp->flags |= FLAG_LEFT;
+                 cp++;
+               }
+             else if (*cp == '+')
+               {
+                 dp->flags |= FLAG_SHOWSIGN;
+                 cp++;
+               }
+             else if (*cp == ' ')
+               {
+                 dp->flags |= FLAG_SPACE;
+                 cp++;
+               }
+             else if (*cp == '#')
+               {
+                 dp->flags |= FLAG_ALT;
+                 cp++;
+               }
+             else if (*cp == '0')
+               {
+                 dp->flags |= FLAG_ZERO;
+                 cp++;
+               }
+             else
+               break;
+           }
+
+         /* Parse the field width.  */
+         if (*cp == '*')
+           {
+             dp->width_start = cp;
+             cp++;
+             dp->width_end = cp;
+             if (max_width_length < 1)
+               max_width_length = 1;
+
+             /* Test for positional argument.  */
+             if (*cp >= '0' && *cp <= '9')
+               {
+                 const CHAR_T *np;
+
+                 for (np = cp; *np >= '0' && *np <= '9'; np++)
+                   ;
+                 if (*np == '$')
+                   {
+                     size_t n = 0;
+
+                     for (np = cp; *np >= '0' && *np <= '9'; np++)
+                       n = xsum (xtimes (n, 10), *np - '0');
+                     if (n == 0)
+                       /* Positional argument 0.  */
+                       goto error;
+                     if (size_overflow_p (n))
+                       /* n too large, would lead to out of memory later.  */
+                       goto error;
+                     dp->width_arg_index = n - 1;
+                     cp = np + 1;
+                   }
+               }
+             if (dp->width_arg_index == ARG_NONE)
+               {
+                 dp->width_arg_index = arg_posn++;
+                 if (dp->width_arg_index == ARG_NONE)
+                   /* arg_posn wrapped around.  */
+                   goto error;
+               }
+             REGISTER_ARG (dp->width_arg_index, TYPE_INT);
+           }
+         else if (*cp >= '0' && *cp <= '9')
+           {
+             size_t width_length;
+
+             dp->width_start = cp;
+             for (; *cp >= '0' && *cp <= '9'; cp++)
+               ;
+             dp->width_end = cp;
+             width_length = dp->width_end - dp->width_start;
+             if (max_width_length < width_length)
+               max_width_length = width_length;
+           }
+
+         /* Parse the precision.  */
+         if (*cp == '.')
+           {
+             cp++;
+             if (*cp == '*')
+               {
+                 dp->precision_start = cp - 1;
+                 cp++;
+                 dp->precision_end = cp;
+                 if (max_precision_length < 2)
+                   max_precision_length = 2;
+
+                 /* Test for positional argument.  */
+                 if (*cp >= '0' && *cp <= '9')
+                   {
+                     const CHAR_T *np;
+
+                     for (np = cp; *np >= '0' && *np <= '9'; np++)
+                       ;
+                     if (*np == '$')
+                       {
+                         size_t n = 0;
+
+                         for (np = cp; *np >= '0' && *np <= '9'; np++)
+                           n = xsum (xtimes (n, 10), *np - '0');
+                         if (n == 0)
+                           /* Positional argument 0.  */
+                           goto error;
+                         if (size_overflow_p (n))
+                           /* n too large, would lead to out of memory
+                              later.  */
+                           goto error;
+                         dp->precision_arg_index = n - 1;
+                         cp = np + 1;
+                       }
+                   }
+                 if (dp->precision_arg_index == ARG_NONE)
+                   {
+                     dp->precision_arg_index = arg_posn++;
+                     if (dp->precision_arg_index == ARG_NONE)
+                       /* arg_posn wrapped around.  */
+                       goto error;
+                   }
+                 REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
+               }
+             else
+               {
+                 size_t precision_length;
+
+                 dp->precision_start = cp - 1;
+                 for (; *cp >= '0' && *cp <= '9'; cp++)
+                   ;
+                 dp->precision_end = cp;
+                 precision_length = dp->precision_end - dp->precision_start;
+                 if (max_precision_length < precision_length)
+                   max_precision_length = precision_length;
+               }
+           }
+
+         {
+           arg_type type;
+
+           /* Parse argument type/size specifiers.  */
+           {
+             int flags = 0;
+
+             for (;;)
+               {
+                 if (*cp == 'h')
+                   {
+                     flags |= (1 << (flags & 1));
+                     cp++;
+                   }
+                 else if (*cp == 'L')
+                   {
+                     flags |= 4;
+                     cp++;
+                   }
+                 else if (*cp == 'l')
+                   {
+                     flags += 8;
+                     cp++;
+                   }
+                 else if (*cp == 'j')
+                   {
+                     if (sizeof (intmax_t) > sizeof (long))
+                       {
+                         /* intmax_t = long long */
+                         flags += 16;
+                       }
+                     else if (sizeof (intmax_t) > sizeof (int))
+                       {
+                         /* intmax_t = long */
+                         flags += 8;
+                       }
+                     cp++;
+                   }
+                 else if (*cp == 'z' || *cp == 'Z')
+                   {
+                     /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
+                        because the warning facility in gcc-2.95.2 understands
+                        only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784).  */
+                     if (sizeof (size_t) > sizeof (long))
+                       {
+                         /* size_t = long long */
+                         flags += 16;
+                       }
+                     else if (sizeof (size_t) > sizeof (int))
+                       {
+                         /* size_t = long */
+                         flags += 8;
+                       }
+                     cp++;
+                   }
+                 else if (*cp == 't')
+                   {
+                     if (sizeof (ptrdiff_t) > sizeof (long))
+                       {
+                         /* ptrdiff_t = long long */
+                         flags += 16;
+                       }
+                     else if (sizeof (ptrdiff_t) > sizeof (int))
+                       {
+                         /* ptrdiff_t = long */
+                         flags += 8;
+                       }
+                     cp++;
+                   }
+#if defined __APPLE__ && defined __MACH__
+                 /* On MacOS X 10.3, PRIdMAX is defined as "qd".
+                    We cannot change it to "lld" because PRIdMAX must also
+                    be understood by the system's printf routines.  */
+                 else if (*cp == 'q')
+                   {
+                     if (64 / 8 > sizeof (long))
+                       {
+                         /* int64_t = long long */
+                         flags += 16;
+                       }
+                     else
+                       {
+                         /* int64_t = long */
+                         flags += 8;
+                       }
+                     cp++;
+                   }
+#endif
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+                 /* On native Win32, PRIdMAX is defined as "I64d".
+                    We cannot change it to "lld" because PRIdMAX must also
+                    be understood by the system's printf routines.  */
+                 else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4')
+                   {
+                     if (64 / 8 > sizeof (long))
+                       {
+                         /* __int64 = long long */
+                         flags += 16;
+                       }
+                     else
+                       {
+                         /* __int64 = long */
+                         flags += 8;
+                       }
+                     cp += 3;
+                   }
+#endif
+                 else
+                   break;
+               }
+
+             /* Read the conversion character.  */
+             c = *cp++;
+             switch (c)
+               {
+               case 'd': case 'i':
+#if HAVE_LONG_LONG_INT
+                 /* If 'long long' exists and is larger than 'long':  */
+                 if (flags >= 16 || (flags & 4))
+                   type = TYPE_LONGLONGINT;
+                 else
+#endif
+                 /* If 'long long' exists and is the same as 'long', we parse
+                    "lld" into TYPE_LONGINT.  */
+                 if (flags >= 8)
+                   type = TYPE_LONGINT;
+                 else if (flags & 2)
+                   type = TYPE_SCHAR;
+                 else if (flags & 1)
+                   type = TYPE_SHORT;
+                 else
+                   type = TYPE_INT;
+                 break;
+               case 'o': case 'u': case 'x': case 'X':
+#if HAVE_LONG_LONG_INT
+                 /* If 'long long' exists and is larger than 'long':  */
+                 if (flags >= 16 || (flags & 4))
+                   type = TYPE_ULONGLONGINT;
+                 else
+#endif
+                 /* If 'unsigned long long' exists and is the same as
+                    'unsigned long', we parse "llu" into TYPE_ULONGINT.  */
+                 if (flags >= 8)
+                   type = TYPE_ULONGINT;
+                 else if (flags & 2)
+                   type = TYPE_UCHAR;
+                 else if (flags & 1)
+                   type = TYPE_USHORT;
+                 else
+                   type = TYPE_UINT;
+                 break;
+               case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
+               case 'a': case 'A':
+                 if (flags >= 16 || (flags & 4))
+                   type = TYPE_LONGDOUBLE;
+                 else
+                   type = TYPE_DOUBLE;
+                 break;
+               case 'c':
+                 if (flags >= 8)
+#if HAVE_WINT_T
+                   type = TYPE_WIDE_CHAR;
+#else
+                   goto error;
+#endif
+                 else
+                   type = TYPE_CHAR;
+                 break;
+#if HAVE_WINT_T
+               case 'C':
+                 type = TYPE_WIDE_CHAR;
+                 c = 'c';
+                 break;
+#endif
+               case 's':
+                 if (flags >= 8)
+#if HAVE_WCHAR_T
+                   type = TYPE_WIDE_STRING;
+#else
+                   goto error;
+#endif
+                 else
+                   type = TYPE_STRING;
+                 break;
+#if HAVE_WCHAR_T
+               case 'S':
+                 type = TYPE_WIDE_STRING;
+                 c = 's';
+                 break;
+#endif
+               case 'p':
+                 type = TYPE_POINTER;
+                 break;
+               case 'n':
+#if HAVE_LONG_LONG_INT
+                 /* If 'long long' exists and is larger than 'long':  */
+                 if (flags >= 16 || (flags & 4))
+                   type = TYPE_COUNT_LONGLONGINT_POINTER;
+                 else
+#endif
+                 /* If 'long long' exists and is the same as 'long', we parse
+                    "lln" into TYPE_COUNT_LONGINT_POINTER.  */
+                 if (flags >= 8)
+                   type = TYPE_COUNT_LONGINT_POINTER;
+                 else if (flags & 2)
+                   type = TYPE_COUNT_SCHAR_POINTER;
+                 else if (flags & 1)
+                   type = TYPE_COUNT_SHORT_POINTER;
+                 else
+                   type = TYPE_COUNT_INT_POINTER;
+                 break;
+#if ENABLE_UNISTDIO
+               /* The unistdio extensions.  */
+               case 'U':
+                 if (flags >= 16)
+                   type = TYPE_U32_STRING;
+                 else if (flags >= 8)
+                   type = TYPE_U16_STRING;
+                 else
+                   type = TYPE_U8_STRING;
+                 break;
+#endif
+               case '%':
+                 type = TYPE_NONE;
+                 break;
+               default:
+                 /* Unknown conversion character.  */
+                 goto error;
+               }
+           }
+
+           if (type != TYPE_NONE)
+             {
+               dp->arg_index = arg_index;
+               if (dp->arg_index == ARG_NONE)
+                 {
+                   dp->arg_index = arg_posn++;
+                   if (dp->arg_index == ARG_NONE)
+                     /* arg_posn wrapped around.  */
+                     goto error;
+                 }
+               REGISTER_ARG (dp->arg_index, type);
+             }
+           dp->conversion = c;
+           dp->dir_end = cp;
+         }
+
+         d->count++;
+         if (d->count >= d_allocated)
+           {
+             size_t memory_size;
+             DIRECTIVE *memory;
+
+             d_allocated = xtimes (d_allocated, 2);
+             memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
+             if (size_overflow_p (memory_size))
+               /* Overflow, would lead to out of memory.  */
+               goto out_of_memory;
+             memory = (DIRECTIVE *) realloc (d->dir, memory_size);
+             if (memory == NULL)
+               /* Out of memory.  */
+               goto out_of_memory;
+             d->dir = memory;
+           }
+       }
+#if CHAR_T_ONLY_ASCII
+      else if (!c_isascii (c))
+       {
+         /* Non-ASCII character.  Not supported.  */
+         goto error;
+       }
+#endif
+    }
+  d->dir[d->count].dir_start = cp;
+
+  d->max_width_length = max_width_length;
+  d->max_precision_length = max_precision_length;
+  return 0;
+
+error:
+  if (a->arg)
+    free (a->arg);
+  if (d->dir)
+    free (d->dir);
+  errno = EINVAL;
+  return -1;
+
+out_of_memory:
+  if (a->arg)
+    free (a->arg);
+  if (d->dir)
+    free (d->dir);
+out_of_memory_1:
+  errno = ENOMEM;
+  return -1;
+}
+
+#undef PRINTF_PARSE
+#undef DIRECTIVES
+#undef DIRECTIVE
+#undef CHAR_T_ONLY_ASCII
+#undef CHAR_T
diff --git a/lib/printf-parse.h b/lib/printf-parse.h
new file mode 100644
index 0000000..0a496cb
--- /dev/null
+++ b/lib/printf-parse.h
@@ -0,0 +1,179 @@
+/* Parse printf format string.
+   Copyright (C) 1999, 2002-2003, 2005, 2007 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _PRINTF_PARSE_H
+#define _PRINTF_PARSE_H
+
+/* This file can be parametrized with the following macros:
+     ENABLE_UNISTDIO    Set to 1 to enable the unistdio extensions.
+     STATIC             Set to 'static' to declare the function static.  */
+
+#include "printf-args.h"
+
+
+/* Flags */
+#define FLAG_GROUP      1      /* ' flag */
+#define FLAG_LEFT       2      /* - flag */
+#define FLAG_SHOWSIGN   4      /* + flag */
+#define FLAG_SPACE      8      /* space flag */
+#define FLAG_ALT       16      /* # flag */
+#define FLAG_ZERO      32
+
+/* arg_index value indicating that no argument is consumed.  */
+#define ARG_NONE       (~(size_t)0)
+
+/* xxx_directive: A parsed directive.
+   xxx_directives: A parsed format string.  */
+
+/* A parsed directive.  */
+typedef struct
+{
+  const char* dir_start;
+  const char* dir_end;
+  int flags;
+  const char* width_start;
+  const char* width_end;
+  size_t width_arg_index;
+  const char* precision_start;
+  const char* precision_end;
+  size_t precision_arg_index;
+  char conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S */
+  size_t arg_index;
+}
+char_directive;
+
+/* A parsed format string.  */
+typedef struct
+{
+  size_t count;
+  char_directive *dir;
+  size_t max_width_length;
+  size_t max_precision_length;
+}
+char_directives;
+
+#if ENABLE_UNISTDIO
+
+/* A parsed directive.  */
+typedef struct
+{
+  const uint8_t* dir_start;
+  const uint8_t* dir_end;
+  int flags;
+  const uint8_t* width_start;
+  const uint8_t* width_end;
+  size_t width_arg_index;
+  const uint8_t* precision_start;
+  const uint8_t* precision_end;
+  size_t precision_arg_index;
+  uint8_t conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S */
+  size_t arg_index;
+}
+u8_directive;
+
+/* A parsed format string.  */
+typedef struct
+{
+  size_t count;
+  u8_directive *dir;
+  size_t max_width_length;
+  size_t max_precision_length;
+}
+u8_directives;
+
+/* A parsed directive.  */
+typedef struct
+{
+  const uint16_t* dir_start;
+  const uint16_t* dir_end;
+  int flags;
+  const uint16_t* width_start;
+  const uint16_t* width_end;
+  size_t width_arg_index;
+  const uint16_t* precision_start;
+  const uint16_t* precision_end;
+  size_t precision_arg_index;
+  uint16_t conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S 
*/
+  size_t arg_index;
+}
+u16_directive;
+
+/* A parsed format string.  */
+typedef struct
+{
+  size_t count;
+  u16_directive *dir;
+  size_t max_width_length;
+  size_t max_precision_length;
+}
+u16_directives;
+
+/* A parsed directive.  */
+typedef struct
+{
+  const uint32_t* dir_start;
+  const uint32_t* dir_end;
+  int flags;
+  const uint32_t* width_start;
+  const uint32_t* width_end;
+  size_t width_arg_index;
+  const uint32_t* precision_start;
+  const uint32_t* precision_end;
+  size_t precision_arg_index;
+  uint32_t conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S 
*/
+  size_t arg_index;
+}
+u32_directive;
+
+/* A parsed format string.  */
+typedef struct
+{
+  size_t count;
+  u32_directive *dir;
+  size_t max_width_length;
+  size_t max_precision_length;
+}
+u32_directives;
+
+#endif
+
+
+/* Parses the format string.  Fills in the number N of directives, and fills
+   in directives[0], ..., directives[N-1], and sets directives[N].dir_start
+   to the end of the format string.  Also fills in the arg_type fields of the
+   arguments and the needed count of arguments.  */
+#if ENABLE_UNISTDIO
+extern int
+       ulc_printf_parse (const char *format, char_directives *d, arguments *a);
+extern int
+       u8_printf_parse (const uint8_t *format, u8_directives *d, arguments *a);
+extern int
+       u16_printf_parse (const uint16_t *format, u16_directives *d,
+                        arguments *a);
+extern int
+       u32_printf_parse (const uint32_t *format, u32_directives *d,
+                        arguments *a);
+#else
+# ifdef STATIC
+STATIC
+# else
+extern
+# endif
+int printf_parse (const char *format, char_directives *d, arguments *a);
+#endif
+
+#endif /* _PRINTF_PARSE_H */
diff --git a/lib/size_max.h b/lib/size_max.h
new file mode 100644
index 0000000..419d73a
--- /dev/null
+++ b/lib/size_max.h
@@ -0,0 +1,31 @@
+/* size_max.h -- declare SIZE_MAX through system headers
+   Copyright (C) 2005-2006 Free Software Foundation, Inc.
+   Written by Simon Josefsson.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef GNULIB_SIZE_MAX_H
+#define GNULIB_SIZE_MAX_H
+
+/* Get SIZE_MAX declaration on systems like Solaris 7/8/9.  */
+# include <limits.h>
+/* Get SIZE_MAX declaration on systems like glibc 2.  */
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+/* On systems where these include files don't define it, SIZE_MAX is defined
+   in config.h.  */
+
+#endif /* GNULIB_SIZE_MAX_H */
diff --git a/lib/stdio-write.c b/lib/stdio-write.c
new file mode 100644
index 0000000..8f275ff
--- /dev/null
+++ b/lib/stdio-write.c
@@ -0,0 +1,148 @@
+/* POSIX compatible FILE stream write function.
+   Copyright (C) 2008 Free Software Foundation, Inc.
+   Written by Bruno Haible <address@hidden>, 2008.
+
+   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 <stdio.h>
+
+/* Replace these functions only if module 'sigpipe' is requested.  */
+#if GNULIB_SIGPIPE
+
+/* On native Windows platforms, SIGPIPE does not exist.  When write() is
+   called on a pipe with no readers, WriteFile() fails with error
+   GetLastError() = ERROR_NO_DATA, and write() in consequence fails with
+   error EINVAL.  This write() function is at the basis of the function
+   which flushes the buffer of a FILE stream.  */
+
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+#  include <errno.h>
+#  include <signal.h>
+#  include <io.h>
+
+#  define WIN32_LEAN_AND_MEAN  /* avoid including junk */
+#  include <windows.h>
+
+#  define CALL_WITH_SIGPIPE_EMULATION(RETTYPE, EXPRESSION, FAILED) \
+  if (ferror (stream))                                                       \
+    return (EXPRESSION);                                                     \
+  else                                                                       \
+    {                                                                        \
+      RETTYPE ret;                                                           \
+      SetLastError (0);                                                        
      \
+      ret = (EXPRESSION);                                                    \
+      if (FAILED && GetLastError () == ERROR_NO_DATA && ferror (stream))      \
+       {                                                                     \
+         int fd = fileno (stream);                                           \
+         if (fd >= 0                                                         \
+             && GetFileType ((HANDLE) _get_osfhandle (fd)) == FILE_TYPE_PIPE)\
+           {                                                                 \
+             /* Try to raise signal SIGPIPE.  */                             \
+             raise (SIGPIPE);                                                \
+             /* If it is currently blocked or ignored, change errno from     \
+                EINVAL to EPIPE.  */                                         \
+             errno = EPIPE;                                                  \
+           }                                                                 \
+       }                                                                     \
+      return ret;                                                            \
+    }
+
+#  if !REPLACE_PRINTF_POSIX /* avoid collision with printf.c */
+int
+printf (const char *format, ...)
+{
+  int retval;
+  va_list args;
+
+  va_start (args, format);
+  retval = vfprintf (stdout, format, args);
+  va_end (args);
+
+  return retval;
+}
+#  endif
+
+#  if !REPLACE_FPRINTF_POSIX /* avoid collision with fprintf.c */
+int
+fprintf (FILE *stream, const char *format, ...)
+{
+  int retval;
+  va_list args;
+
+  va_start (args, format);
+  retval = vfprintf (stream, format, args);
+  va_end (args);
+
+  return retval;
+}
+#  endif
+
+#  if !REPLACE_VFPRINTF_POSIX /* avoid collision with vprintf.c */
+int
+vprintf (const char *format, va_list args)
+{
+  return vfprintf (stdout, format, args);
+}
+#  endif
+
+#  if !REPLACE_VPRINTF_POSIX /* avoid collision with vfprintf.c */
+int
+vfprintf (FILE *stream, const char *format, va_list args)
+#undef vfprintf
+{
+  CALL_WITH_SIGPIPE_EMULATION (int, vfprintf (stream, format, args), ret == 
EOF)
+}
+#  endif
+
+int
+putchar (int c)
+{
+  return fputc (c, stdout);
+}
+
+int
+fputc (int c, FILE *stream)
+#undef fputc
+{
+  CALL_WITH_SIGPIPE_EMULATION (int, fputc (c, stream), ret == EOF)
+}
+
+int
+fputs (const char *string, FILE *stream)
+#undef fputs
+{
+  CALL_WITH_SIGPIPE_EMULATION (int, fputs (string, stream), ret == EOF)
+}
+
+int
+puts (const char *string)
+#undef puts
+{
+  FILE *stream = stdout;
+  CALL_WITH_SIGPIPE_EMULATION (int, puts (string), ret == EOF)
+}
+
+size_t
+fwrite (const void *ptr, size_t s, size_t n, FILE *stream)
+#undef fwrite
+{
+  CALL_WITH_SIGPIPE_EMULATION (size_t, fwrite (ptr, s, n, stream), ret < n)
+}
+
+# endif
+#endif
diff --git a/lib/stdio.in.h b/lib/stdio.in.h
new file mode 100644
index 0000000..ae681fc
--- /dev/null
+++ b/lib/stdio.in.h
@@ -0,0 +1,542 @@
+/* A GNU-like <stdio.h>.
+
+   Copyright (C) 2004, 2007-2009 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 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#if __GNUC__ >= 3
address@hidden@
+#endif
+
+#if defined __need_FILE || defined __need___FILE
+/* Special invocation convention inside glibc header files.  */
+
address@hidden@ @NEXT_STDIO_H@
+
+#else
+/* Normal invocation convention.  */
+
+#ifndef _GL_STDIO_H
+
+/* The include_next requires a split double-inclusion guard.  */
address@hidden@ @NEXT_STDIO_H@
+
+#ifndef _GL_STDIO_H
+#define _GL_STDIO_H
+
+#include <stdarg.h>
+#include <stddef.h>
+
+#if (@GNULIB_FSEEKO@ && @REPLACE_FSEEKO@) \
+  || (@GNULIB_FTELLO@ && @REPLACE_FTELLO@) \
+  || (@GNULIB_GETDELIM@ && address@hidden@) \
+  || (@GNULIB_GETLINE@ && (address@hidden@ || @REPLACE_GETLINE@))
+/* Get off_t and ssize_t.  */
+# include <sys/types.h>
+#endif
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later.  */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
+#  define __attribute__(Spec) /* empty */
+# endif
+/* The __-protected variants of `format' and `printf' attributes
+   are accepted by gcc versions 2.6.4 (effectively 2.7) and later.  */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+#  define __format__ format
+#  define __printf__ printf
+# endif
+#endif
+
+
+/* The definition of GL_LINK_WARNING is copied here.  */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if @GNULIB_FPRINTF_POSIX@
+# if @REPLACE_FPRINTF@
+#  define fprintf rpl_fprintf
+extern int fprintf (FILE *fp, const char *format, ...)
+       __attribute__ ((__format__ (__printf__, 2, 3)));
+# endif
+#elif @GNULIB_FPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && 
@GNULIB_STDIO_H_SIGPIPE@
+# define fprintf rpl_fprintf
+extern int fprintf (FILE *fp, const char *format, ...)
+       __attribute__ ((__format__ (__printf__, 2, 3)));
+#elif defined GNULIB_POSIXCHECK
+# undef fprintf
+# define fprintf \
+    (GL_LINK_WARNING ("fprintf is not always POSIX compliant - " \
+                      "use gnulib module fprintf-posix for portable " \
+                      "POSIX compliance"), \
+     fprintf)
+#endif
+
+#if @GNULIB_VFPRINTF_POSIX@
+# if @REPLACE_VFPRINTF@
+#  define vfprintf rpl_vfprintf
+extern int vfprintf (FILE *fp, const char *format, va_list args)
+       __attribute__ ((__format__ (__printf__, 2, 0)));
+# endif
+#elif @GNULIB_VFPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && 
@GNULIB_STDIO_H_SIGPIPE@
+# define vfprintf rpl_vfprintf
+extern int vfprintf (FILE *fp, const char *format, va_list args)
+       __attribute__ ((__format__ (__printf__, 2, 0)));
+#elif defined GNULIB_POSIXCHECK
+# undef vfprintf
+# define vfprintf(s,f,a) \
+    (GL_LINK_WARNING ("vfprintf is not always POSIX compliant - " \
+                      "use gnulib module vfprintf-posix for portable " \
+                      "POSIX compliance"), \
+     vfprintf (s, f, a))
+#endif
+
+#if @GNULIB_PRINTF_POSIX@
+# if @REPLACE_PRINTF@
+/* Don't break __attribute__((format(printf,M,N))).  */
+#  define printf __printf__
+extern int printf (const char *format, ...)
+       __attribute__ ((__format__ (__printf__, 1, 2)));
+# endif
+#elif @GNULIB_PRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && 
@GNULIB_STDIO_H_SIGPIPE@
+/* Don't break __attribute__((format(printf,M,N))).  */
+# define printf __printf__
+extern int printf (const char *format, ...)
+       __attribute__ ((__format__ (__printf__, 1, 2)));
+#elif defined GNULIB_POSIXCHECK
+# undef printf
+# define printf \
+    (GL_LINK_WARNING ("printf is not always POSIX compliant - " \
+                      "use gnulib module printf-posix for portable " \
+                      "POSIX compliance"), \
+     printf)
+/* Don't break __attribute__((format(printf,M,N))).  */
+# define format(kind,m,n) format (__##kind##__, m, n)
+# define __format__(kind,m,n) __format__ (__##kind##__, m, n)
+# define ____printf____ __printf__
+# define ____scanf____ __scanf__
+# define ____strftime____ __strftime__
+# define ____strfmon____ __strfmon__
+#endif
+
+#if @GNULIB_VPRINTF_POSIX@
+# if @REPLACE_VPRINTF@
+#  define vprintf rpl_vprintf
+extern int vprintf (const char *format, va_list args)
+       __attribute__ ((__format__ (__printf__, 1, 0)));
+# endif
+#elif @GNULIB_VPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && 
@GNULIB_STDIO_H_SIGPIPE@
+# define vprintf rpl_vprintf
+extern int vprintf (const char *format, va_list args)
+       __attribute__ ((__format__ (__printf__, 1, 0)));
+#elif defined GNULIB_POSIXCHECK
+# undef vprintf
+# define vprintf(f,a) \
+    (GL_LINK_WARNING ("vprintf is not always POSIX compliant - " \
+                      "use gnulib module vprintf-posix for portable " \
+                      "POSIX compliance"), \
+     vprintf (f, a))
+#endif
+
+#if @GNULIB_SNPRINTF@
+# if @REPLACE_SNPRINTF@
+#  define snprintf rpl_snprintf
+# endif
+# if @REPLACE_SNPRINTF@ || address@hidden@
+extern int snprintf (char *str, size_t size, const char *format, ...)
+       __attribute__ ((__format__ (__printf__, 3, 4)));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef snprintf
+# define snprintf \
+    (GL_LINK_WARNING ("snprintf is unportable - " \
+                      "use gnulib module snprintf for portability"), \
+     snprintf)
+#endif
+
+#if @GNULIB_VSNPRINTF@
+# if @REPLACE_VSNPRINTF@
+#  define vsnprintf rpl_vsnprintf
+# endif
+# if @REPLACE_VSNPRINTF@ || address@hidden@
+extern int vsnprintf (char *str, size_t size, const char *format, va_list args)
+       __attribute__ ((__format__ (__printf__, 3, 0)));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef vsnprintf
+# define vsnprintf(b,s,f,a) \
+    (GL_LINK_WARNING ("vsnprintf is unportable - " \
+                      "use gnulib module vsnprintf for portability"), \
+     vsnprintf (b, s, f, a))
+#endif
+
+#if @GNULIB_SPRINTF_POSIX@
+# if @REPLACE_SPRINTF@
+#  define sprintf rpl_sprintf
+extern int sprintf (char *str, const char *format, ...)
+       __attribute__ ((__format__ (__printf__, 2, 3)));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef sprintf
+# define sprintf \
+    (GL_LINK_WARNING ("sprintf is not always POSIX compliant - " \
+                      "use gnulib module sprintf-posix for portable " \
+                      "POSIX compliance"), \
+     sprintf)
+#endif
+
+#if @GNULIB_VSPRINTF_POSIX@
+# if @REPLACE_VSPRINTF@
+#  define vsprintf rpl_vsprintf
+extern int vsprintf (char *str, const char *format, va_list args)
+       __attribute__ ((__format__ (__printf__, 2, 0)));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef vsprintf
+# define vsprintf(b,f,a) \
+    (GL_LINK_WARNING ("vsprintf is not always POSIX compliant - " \
+                      "use gnulib module vsprintf-posix for portable " \
+                      "POSIX compliance"), \
+     vsprintf (b, f, a))
+#endif
+
+#if @GNULIB_DPRINTF@
+# if @REPLACE_DPRINTF@
+#  define dprintf rpl_dprintf
+# endif
+# if @REPLACE_DPRINTF@ || address@hidden@
+extern int dprintf (int fd, const char *format, ...)
+       __attribute__ ((__format__ (__printf__, 2, 3)));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef dprintf
+# define dprintf(d,f,a) \
+    (GL_LINK_WARNING ("dprintf is unportable - " \
+                      "use gnulib module dprintf for portability"), \
+     dprintf (d, f, a))
+#endif
+
+#if @GNULIB_VDPRINTF@
+# if @REPLACE_VDPRINTF@
+#  define vdprintf rpl_vdprintf
+# endif
+# if @REPLACE_VDPRINTF@ || address@hidden@
+extern int vdprintf (int fd, const char *format, va_list args)
+       __attribute__ ((__format__ (__printf__, 2, 0)));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef vdprintf
+# define vdprintf(d,f,a) \
+    (GL_LINK_WARNING ("vdprintf is unportable - " \
+                      "use gnulib module vdprintf for portability"), \
+     vdprintf (d, f, a))
+#endif
+
+#if @GNULIB_VASPRINTF@
+# if @REPLACE_VASPRINTF@
+#  define asprintf rpl_asprintf
+#  define vasprintf rpl_vasprintf
+# endif
+# if @REPLACE_VASPRINTF@ || address@hidden@
+  /* Write formatted output to a string dynamically allocated with malloc().
+     If the memory allocation succeeds, store the address of the string in
+     *RESULT and return the number of resulting bytes, excluding the trailing
+     NUL.  Upon memory allocation error, or some other error, return -1.  */
+  extern int asprintf (char **result, const char *format, ...)
+    __attribute__ ((__format__ (__printf__, 2, 3)));
+  extern int vasprintf (char **result, const char *format, va_list args)
+    __attribute__ ((__format__ (__printf__, 2, 0)));
+# endif
+#endif
+
+#if @GNULIB_OBSTACK_PRINTF@
+# if @REPLACE_OBSTACK_PRINTF@
+#  define obstack_printf rpl_osbtack_printf
+#  define obstack_vprintf rpl_obstack_vprintf
+# endif
+# if @REPLACE_OBSTACK_PRINTF@ || address@hidden@
+  struct obstack;
+  /* Grow an obstack with formatted output.  Return the number of
+     bytes added to OBS.  No trailing nul byte is added, and the
+     object should be closed with obstack_finish before use.  Upon
+     memory allocation error, call obstack_alloc_failed_handler.  Upon
+     other error, return -1.  */
+  extern int obstack_printf (struct obstack *obs, const char *format, ...)
+    __attribute__ ((__format__ (__printf__, 2, 3)));
+  extern int obstack_vprintf (struct obstack *obs, const char *format,
+                             va_list args)
+    __attribute__ ((__format__ (__printf__, 2, 0)));
+# endif
+#endif
+
+#if @GNULIB_FOPEN@
+# if @REPLACE_FOPEN@
+#  undef fopen
+#  define fopen rpl_fopen
+extern FILE * fopen (const char *filename, const char *mode);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef fopen
+# define fopen(f,m) \
+   (GL_LINK_WARNING ("fopen on Win32 platforms is not POSIX compatible - " \
+                     "use gnulib module fopen for portability"), \
+    fopen (f, m))
+#endif
+
+#if @GNULIB_FREOPEN@
+# if @REPLACE_FREOPEN@
+#  undef freopen
+#  define freopen rpl_freopen
+extern FILE * freopen (const char *filename, const char *mode, FILE *stream);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef freopen
+# define freopen(f,m,s) \
+   (GL_LINK_WARNING ("freopen on Win32 platforms is not POSIX compatible - " \
+                     "use gnulib module freopen for portability"), \
+    freopen (f, m, s))
+#endif
+
+#if @GNULIB_FSEEKO@
+# if @REPLACE_FSEEKO@
+/* Provide fseek, fseeko functions that are aware of a preceding
+   fflush(), and which detect pipes.  */
+#  define fseeko rpl_fseeko
+extern int fseeko (FILE *fp, off_t offset, int whence);
+#  define fseek(fp, offset, whence) fseeko (fp, (off_t)(offset), whence)
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef fseeko
+# define fseeko(f,o,w) \
+   (GL_LINK_WARNING ("fseeko is unportable - " \
+                     "use gnulib module fseeko for portability"), \
+    fseeko (f, o, w))
+#endif
+
+#if @GNULIB_FSEEK@ && @REPLACE_FSEEK@
+extern int rpl_fseek (FILE *fp, long offset, int whence);
+# undef fseek
+# if defined GNULIB_POSIXCHECK
+#  define fseek(f,o,w) \
+     (GL_LINK_WARNING ("fseek cannot handle files larger than 4 GB " \
+                       "on 32-bit platforms - " \
+                       "use fseeko function for handling of large files"), \
+      rpl_fseek (f, o, w))
+# else
+#  define fseek rpl_fseek
+# endif
+#elif defined GNULIB_POSIXCHECK
+# ifndef fseek
+#  define fseek(f,o,w) \
+     (GL_LINK_WARNING ("fseek cannot handle files larger than 4 GB " \
+                       "on 32-bit platforms - " \
+                       "use fseeko function for handling of large files"), \
+      fseek (f, o, w))
+# endif
+#endif
+
+#if @GNULIB_FTELLO@
+# if @REPLACE_FTELLO@
+#  define ftello rpl_ftello
+extern off_t ftello (FILE *fp);
+#  define ftell(fp) ftello (fp)
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef ftello
+# define ftello(f) \
+   (GL_LINK_WARNING ("ftello is unportable - " \
+                     "use gnulib module ftello for portability"), \
+    ftello (f))
+#endif
+
+#if @GNULIB_FTELL@ && @REPLACE_FTELL@
+extern long rpl_ftell (FILE *fp);
+# undef ftell
+# if GNULIB_POSIXCHECK
+#  define ftell(f) \
+     (GL_LINK_WARNING ("ftell cannot handle files larger than 4 GB " \
+                       "on 32-bit platforms - " \
+                       "use ftello function for handling of large files"), \
+      rpl_ftell (f))
+# else
+#  define ftell rpl_ftell
+# endif
+#elif defined GNULIB_POSIXCHECK
+# ifndef ftell
+#  define ftell(f) \
+     (GL_LINK_WARNING ("ftell cannot handle files larger than 4 GB " \
+                       "on 32-bit platforms - " \
+                       "use ftello function for handling of large files"), \
+      ftell (f))
+# endif
+#endif
+
+#if @GNULIB_FFLUSH@
+# if @REPLACE_FFLUSH@
+#  define fflush rpl_fflush
+  /* Flush all pending data on STREAM according to POSIX rules.  Both
+     output and seekable input streams are supported.
+     Note! LOSS OF DATA can occur if fflush is applied on an input stream
+     that is _not_seekable_ or on an update stream that is _not_seekable_
+     and in which the most recent operation was input.  Seekability can
+     be tested with lseek(fileno(fp),0,SEEK_CUR).  */
+  extern int fflush (FILE *gl_stream);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef fflush
+# define fflush(f) \
+   (GL_LINK_WARNING ("fflush is not always POSIX compliant - " \
+                     "use gnulib module fflush for portable " \
+                     "POSIX compliance"), \
+    fflush (f))
+#endif
+
+#if @GNULIB_FPURGE@
+# if @REPLACE_FPURGE@
+#  define fpurge rpl_fpurge
+# endif
+# if @REPLACE_FPURGE@ || address@hidden@
+  /* Discard all pending buffered I/O data on STREAM.
+     STREAM must not be wide-character oriented.
+     Return 0 if successful.  Upon error, return -1 and set errno.  */
+  extern int fpurge (FILE *gl_stream);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef fpurge
+# define fpurge(f) \
+   (GL_LINK_WARNING ("fpurge is not always present - " \
+                     "use gnulib module fpurge for portability"), \
+    fpurge (f))
+#endif
+
+#if @GNULIB_FCLOSE@
+# if @REPLACE_FCLOSE@
+#  define fclose rpl_fclose
+  /* Close STREAM and its underlying file descriptor.  */
+extern int fclose (FILE *stream);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef fclose
+# define fclose(f) \
+   (GL_LINK_WARNING ("fclose is not always POSIX compliant - " \
+                     "use gnulib module fclose for portable " \
+                     "POSIX compliance"), \
+    fclose (f))
+#endif
+
+#if @GNULIB_FPUTC@ && @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@
+# undef fputc
+# define fputc rpl_fputc
+extern int fputc (int c, FILE *stream);
+#endif
+
+#if @GNULIB_PUTC@ && @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@
+# undef putc
+# define putc rpl_fputc
+extern int putc (int c, FILE *stream);
+#endif
+
+#if @GNULIB_PUTCHAR@ && @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@
+# undef putchar
+# define putchar rpl_putchar
+extern int putchar (int c);
+#endif
+
+#if @GNULIB_FPUTS@ && @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@
+# undef fputs
+# define fputs rpl_fputs
+extern int fputs (const char *string, FILE *stream);
+#endif
+
+#if @GNULIB_PUTS@ && @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@
+# undef puts
+# define puts rpl_puts
+extern int puts (const char *string);
+#endif
+
+#if @GNULIB_FWRITE@ && @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@
+# undef fwrite
+# define fwrite rpl_fwrite
+extern size_t fwrite (const void *ptr, size_t s, size_t n, FILE *stream);
+#endif
+
+#if @GNULIB_GETDELIM@
+# if address@hidden@
+/* Read input, up to (and including) the next occurrence of DELIMITER, from
+   STREAM, store it in *LINEPTR (and NUL-terminate it).
+   *LINEPTR is a pointer returned from malloc (or NULL), pointing to *LINESIZE
+   bytes of space.  It is realloc'd as necessary.
+   Return the number of bytes read and stored at *LINEPTR (not including the
+   NUL terminator), or -1 on error or EOF.  */
+extern ssize_t getdelim (char **lineptr, size_t *linesize, int delimiter,
+                        FILE *stream);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef getdelim
+# define getdelim(l, s, d, f)                                      \
+  (GL_LINK_WARNING ("getdelim is unportable - "                            \
+                   "use gnulib module getdelim for portability"),  \
+   getdelim (l, s, d, f))
+#endif
+
+#if @GNULIB_GETLINE@
+# if @REPLACE_GETLINE@
+#  undef getline
+#  define getline rpl_getline
+# endif
+# if address@hidden@ || @REPLACE_GETLINE@
+/* Read a line, up to (and including) the next newline, from STREAM, store it
+   in *LINEPTR (and NUL-terminate it).
+   *LINEPTR is a pointer returned from malloc (or NULL), pointing to *LINESIZE
+   bytes of space.  It is realloc'd as necessary.
+   Return the number of bytes read and stored at *LINEPTR (not including the
+   NUL terminator), or -1 on error or EOF.  */
+extern ssize_t getline (char **lineptr, size_t *linesize, FILE *stream);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef getline
+# define getline(l, s, f)                                              \
+  (GL_LINK_WARNING ("getline is unportable - "                         \
+                   "use gnulib module getline for portability"),       \
+   getline (l, s, f))
+#endif
+
+#if @GNULIB_PERROR@
+# if @REPLACE_PERROR@
+#  define perror rpl_perror
+/* Print a message to standard error, describing the value of ERRNO,
+   (if STRING is not NULL and not empty) prefixed with STRING and ": ",
+   and terminated with a newline.  */
+extern void perror (const char *string);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef perror
+# define perror(s) \
+    (GL_LINK_WARNING ("perror is not always POSIX compliant - " \
+                      "use gnulib module perror for portability"), \
+     perror (s))
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GL_STDIO_H */
+#endif /* _GL_STDIO_H */
+#endif
diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c
new file mode 100644
index 0000000..c620b4c
--- /dev/null
+++ b/lib/vasnprintf.c
@@ -0,0 +1,5487 @@
+/* vsprintf with automatic memory allocation.
+   Copyright (C) 1999, 2002-2009 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 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* This file can be parametrized with the following macros:
+     VASNPRINTF         The name of the function being defined.
+     FCHAR_T            The element type of the format string.
+     DCHAR_T            The element type of the destination (result) string.
+     FCHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters
+                        in the format string are ASCII. MUST be set if
+                        FCHAR_T and DCHAR_T are not the same type.
+     DIRECTIVE          Structure denoting a format directive.
+                        Depends on FCHAR_T.
+     DIRECTIVES         Structure denoting the set of format directives of a
+                        format string.  Depends on FCHAR_T.
+     PRINTF_PARSE       Function that parses a format string.
+                        Depends on FCHAR_T.
+     DCHAR_CPY          memcpy like function for DCHAR_T[] arrays.
+     DCHAR_SET          memset like function for DCHAR_T[] arrays.
+     DCHAR_MBSNLEN      mbsnlen like function for DCHAR_T[] arrays.
+     SNPRINTF           The system's snprintf (or similar) function.
+                        This may be either snprintf or swprintf.
+     TCHAR_T            The element type of the argument and result string
+                        of the said SNPRINTF function.  This may be either
+                        char or wchar_t.  The code exploits that
+                        sizeof (TCHAR_T) | sizeof (DCHAR_T) and
+                        alignof (TCHAR_T) <= alignof (DCHAR_T).
+     DCHAR_IS_TCHAR     Set to 1 if DCHAR_T and TCHAR_T are the same type.
+     DCHAR_CONV_FROM_ENCODING A function to convert from char[] to DCHAR[].
+     DCHAR_IS_UINT8_T   Set to 1 if DCHAR_T is uint8_t.
+     DCHAR_IS_UINT16_T  Set to 1 if DCHAR_T is uint16_t.
+     DCHAR_IS_UINT32_T  Set to 1 if DCHAR_T is uint32_t.  */
+
+/* Tell glibc's <stdio.h> to provide a prototype for snprintf().
+   This must come before <config.h> because <config.h> may include
+   <features.h>, and once <features.h> has been included, it's too late.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE    1
+#endif
+
+#ifndef VASNPRINTF
+# include <config.h>
+#endif
+#ifndef IN_LIBINTL
+# include <alloca.h>
+#endif
+
+/* Specification.  */
+#ifndef VASNPRINTF
+# if WIDE_CHAR_VERSION
+#  include "vasnwprintf.h"
+# else
+#  include "vasnprintf.h"
+# endif
+#endif
+
+#include <locale.h>    /* localeconv() */
+#include <stdio.h>     /* snprintf(), sprintf() */
+#include <stdlib.h>    /* abort(), malloc(), realloc(), free() */
+#include <string.h>    /* memcpy(), strlen() */
+#include <errno.h>     /* errno */
+#include <limits.h>    /* CHAR_BIT */
+#include <float.h>     /* DBL_MAX_EXP, LDBL_MAX_EXP */
+#if HAVE_NL_LANGINFO
+# include <langinfo.h>
+#endif
+#ifndef VASNPRINTF
+# if WIDE_CHAR_VERSION
+#  include "wprintf-parse.h"
+# else
+#  include "printf-parse.h"
+# endif
+#endif
+
+/* Checked size_t computations.  */
+#include "xsize.h"
+
+#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
+# include <math.h>
+# include "float+.h"
+#endif
+
+#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
+# include <math.h>
+# include "isnand-nolibm.h"
+#endif
+
+#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined 
IN_LIBINTL
+# include <math.h>
+# include "isnanl-nolibm.h"
+# include "fpucw.h"
+#endif
+
+#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
+# include <math.h>
+# include "isnand-nolibm.h"
+# include "printf-frexp.h"
+#endif
+
+#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
+# include <math.h>
+# include "isnanl-nolibm.h"
+# include "printf-frexpl.h"
+# include "fpucw.h"
+#endif
+
+/* Default parameters.  */
+#ifndef VASNPRINTF
+# if WIDE_CHAR_VERSION
+#  define VASNPRINTF vasnwprintf
+#  define FCHAR_T wchar_t
+#  define DCHAR_T wchar_t
+#  define TCHAR_T wchar_t
+#  define DCHAR_IS_TCHAR 1
+#  define DIRECTIVE wchar_t_directive
+#  define DIRECTIVES wchar_t_directives
+#  define PRINTF_PARSE wprintf_parse
+#  define DCHAR_CPY wmemcpy
+#  define DCHAR_SET wmemset
+# else
+#  define VASNPRINTF vasnprintf
+#  define FCHAR_T char
+#  define DCHAR_T char
+#  define TCHAR_T char
+#  define DCHAR_IS_TCHAR 1
+#  define DIRECTIVE char_directive
+#  define DIRECTIVES char_directives
+#  define PRINTF_PARSE printf_parse
+#  define DCHAR_CPY memcpy
+#  define DCHAR_SET memset
+# endif
+#endif
+#if WIDE_CHAR_VERSION
+  /* TCHAR_T is wchar_t.  */
+# define USE_SNPRINTF 1
+# if HAVE_DECL__SNWPRINTF
+   /* On Windows, the function swprintf() has a different signature than
+      on Unix; we use the _snwprintf() function instead.  */
+#  define SNPRINTF _snwprintf
+# else
+   /* Unix.  */
+#  define SNPRINTF swprintf
+# endif
+#else
+  /* TCHAR_T is char.  */
+  /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'.
+     But don't use it on BeOS, since BeOS snprintf produces no output if the
+     size argument is >= 0x3000000.
+     Also don't use it on Linux libc5, since there snprintf with size = 1
+     writes any output without bounds, like sprintf.  */
+# if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__ && 
!(__GNU_LIBRARY__ == 1)
+#  define USE_SNPRINTF 1
+# else
+#  define USE_SNPRINTF 0
+# endif
+# if HAVE_DECL__SNPRINTF
+   /* Windows.  */
+#  define SNPRINTF _snprintf
+# else
+   /* Unix.  */
+#  define SNPRINTF snprintf
+   /* Here we need to call the native snprintf, not rpl_snprintf.  */
+#  undef snprintf
+# endif
+#endif
+/* Here we need to call the native sprintf, not rpl_sprintf.  */
+#undef sprintf
+
+/* GCC >= 4.0 with -Wall emits unjustified "... may be used uninitialized"
+   warnings in this file.  Use -Dlint to suppress them.  */
+#ifdef lint
+# define IF_LINT(Code) Code
+#else
+# define IF_LINT(Code) /* empty */
+#endif
+
+/* Avoid some warnings from "gcc -Wshadow".
+   This file doesn't use the exp() and remainder() functions.  */
+#undef exp
+#define exp expo
+#undef remainder
+#define remainder rem
+
+#if !USE_SNPRINTF && !WIDE_CHAR_VERSION
+# if (HAVE_STRNLEN && !defined _AIX)
+#  define local_strnlen strnlen
+# else
+#  ifndef local_strnlen_defined
+#   define local_strnlen_defined 1
+static size_t
+local_strnlen (const char *string, size_t maxlen)
+{
+  const char *end = memchr (string, '\0', maxlen);
+  return end ? (size_t) (end - string) : maxlen;
+}
+#  endif
+# endif
+#endif
+
+#if (!USE_SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && 
HAVE_WCHAR_T && (WIDE_CHAR_VERSION || DCHAR_IS_TCHAR)
+# if HAVE_WCSLEN
+#  define local_wcslen wcslen
+# else
+   /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
+      a dependency towards this library, here is a local substitute.
+      Define this substitute only once, even if this file is included
+      twice in the same compilation unit.  */
+#  ifndef local_wcslen_defined
+#   define local_wcslen_defined 1
+static size_t
+local_wcslen (const wchar_t *s)
+{
+  const wchar_t *ptr;
+
+  for (ptr = s; *ptr != (wchar_t) 0; ptr++)
+    ;
+  return ptr - s;
+}
+#  endif
+# endif
+#endif
+
+#if !USE_SNPRINTF && HAVE_WCHAR_T && WIDE_CHAR_VERSION
+# if HAVE_WCSNLEN
+#  define local_wcsnlen wcsnlen
+# else
+#  ifndef local_wcsnlen_defined
+#   define local_wcsnlen_defined 1
+static size_t
+local_wcsnlen (const wchar_t *s, size_t maxlen)
+{
+  const wchar_t *ptr;
+
+  for (ptr = s; maxlen > 0 && *ptr != (wchar_t) 0; ptr++, maxlen--)
+    ;
+  return ptr - s;
+}
+#  endif
+# endif
+#endif
+
+#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || 
NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || 
NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
+/* Determine the decimal-point character according to the current locale.  */
+# ifndef decimal_point_char_defined
+#  define decimal_point_char_defined 1
+static char
+decimal_point_char ()
+{
+  const char *point;
+  /* Determine it in a multithread-safe way.  We know nl_langinfo is
+     multithread-safe on glibc systems, but is not required to be multithread-
+     safe by POSIX.  sprintf(), however, is multithread-safe.  localeconv()
+     is rarely multithread-safe.  */
+#  if HAVE_NL_LANGINFO && __GLIBC__
+  point = nl_langinfo (RADIXCHAR);
+#  elif 1
+  char pointbuf[5];
+  sprintf (pointbuf, "%#.0f", 1.0);
+  point = &pointbuf[1];
+#  else
+  point = localeconv () -> decimal_point;
+#  endif
+  /* The decimal point is always a single byte: either '.' or ','.  */
+  return (point[0] != '\0' ? point[0] : '.');
+}
+# endif
+#endif
+
+#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE && !defined IN_LIBINTL
+
+/* Equivalent to !isfinite(x) || x == 0, but does not require libm.  */
+static int
+is_infinite_or_zero (double x)
+{
+  return isnand (x) || x + x == x;
+}
+
+#endif
+
+#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined 
IN_LIBINTL
+
+/* Equivalent to !isfinite(x) || x == 0, but does not require libm.  */
+static int
+is_infinite_or_zerol (long double x)
+{
+  return isnanl (x) || x + x == x;
+}
+
+#endif
+
+#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
+
+/* Converting 'long double' to decimal without rare rounding bugs requires
+   real bignums.  We use the naming conventions of GNU gmp, but vastly simpler
+   (and slower) algorithms.  */
+
+typedef unsigned int mp_limb_t;
+# define GMP_LIMB_BITS 32
+typedef int mp_limb_verify[2 * (sizeof (mp_limb_t) * CHAR_BIT == 
GMP_LIMB_BITS) - 1];
+
+typedef unsigned long long mp_twolimb_t;
+# define GMP_TWOLIMB_BITS 64
+typedef int mp_twolimb_verify[2 * (sizeof (mp_twolimb_t) * CHAR_BIT == 
GMP_TWOLIMB_BITS) - 1];
+
+/* Representation of a bignum >= 0.  */
+typedef struct
+{
+  size_t nlimbs;
+  mp_limb_t *limbs; /* Bits in little-endian order, allocated with malloc().  
*/
+} mpn_t;
+
+/* Compute the product of two bignums >= 0.
+   Return the allocated memory in case of success, NULL in case of memory
+   allocation failure.  */
+static void *
+multiply (mpn_t src1, mpn_t src2, mpn_t *dest)
+{
+  const mp_limb_t *p1;
+  const mp_limb_t *p2;
+  size_t len1;
+  size_t len2;
+
+  if (src1.nlimbs <= src2.nlimbs)
+    {
+      len1 = src1.nlimbs;
+      p1 = src1.limbs;
+      len2 = src2.nlimbs;
+      p2 = src2.limbs;
+    }
+  else
+    {
+      len1 = src2.nlimbs;
+      p1 = src2.limbs;
+      len2 = src1.nlimbs;
+      p2 = src1.limbs;
+    }
+  /* Now 0 <= len1 <= len2.  */
+  if (len1 == 0)
+    {
+      /* src1 or src2 is zero.  */
+      dest->nlimbs = 0;
+      dest->limbs = (mp_limb_t *) malloc (1);
+    }
+  else
+    {
+      /* Here 1 <= len1 <= len2.  */
+      size_t dlen;
+      mp_limb_t *dp;
+      size_t k, i, j;
+
+      dlen = len1 + len2;
+      dp = (mp_limb_t *) malloc (dlen * sizeof (mp_limb_t));
+      if (dp == NULL)
+       return NULL;
+      for (k = len2; k > 0; )
+       dp[--k] = 0;
+      for (i = 0; i < len1; i++)
+       {
+         mp_limb_t digit1 = p1[i];
+         mp_twolimb_t carry = 0;
+         for (j = 0; j < len2; j++)
+           {
+             mp_limb_t digit2 = p2[j];
+             carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
+             carry += dp[i + j];
+             dp[i + j] = (mp_limb_t) carry;
+             carry = carry >> GMP_LIMB_BITS;
+           }
+         dp[i + len2] = (mp_limb_t) carry;
+       }
+      /* Normalise.  */
+      while (dlen > 0 && dp[dlen - 1] == 0)
+       dlen--;
+      dest->nlimbs = dlen;
+      dest->limbs = dp;
+    }
+  return dest->limbs;
+}
+
+/* Compute the quotient of a bignum a >= 0 and a bignum b > 0.
+   a is written as  a = q * b + r  with 0 <= r < b.  q is the quotient, r
+   the remainder.
+   Finally, round-to-even is performed: If r > b/2 or if r = b/2 and q is odd,
+   q is incremented.
+   Return the allocated memory in case of success, NULL in case of memory
+   allocation failure.  */
+static void *
+divide (mpn_t a, mpn_t b, mpn_t *q)
+{
+  /* Algorithm:
+     First normalise a and b: a=[a[m-1],...,a[0]], b=[b[n-1],...,b[0]]
+     with m>=0 and n>0 (in base beta = 2^GMP_LIMB_BITS).
+     If m<n, then q:=0 and r:=a.
+     If m>=n=1, perform a single-precision division:
+       r:=0, j:=m,
+       while j>0 do
+         {Here (q[m-1]*beta^(m-1)+...+q[j]*beta^j) * b[0] + r*beta^j =
+               = a[m-1]*beta^(m-1)+...+a[j]*beta^j und 0<=r<b[0]<beta}
+         j:=j-1, r:=r*beta+a[j], q[j]:=floor(r/b[0]), r:=r-b[0]*q[j].
+       Normalise [q[m-1],...,q[0]], yields q.
+     If m>=n>1, perform a multiple-precision division:
+       We have a/b < beta^(m-n+1).
+       s:=intDsize-1-(highest bit in b[n-1]), 0<=s<intDsize.
+       Shift a and b left by s bits, copying them. r:=a.
+       r=[r[m],...,r[0]], b=[b[n-1],...,b[0]] with b[n-1]>=beta/2.
+       For j=m-n,...,0: {Here 0 <= r < b*beta^(j+1).}
+         Compute q* :
+           q* := floor((r[j+n]*beta+r[j+n-1])/b[n-1]).
+           In case of overflow (q* >= beta) set q* := beta-1.
+           Compute c2 := ((r[j+n]*beta+r[j+n-1]) - q* * b[n-1])*beta + r[j+n-2]
+           and c3 := b[n-2] * q*.
+           {We have 0 <= c2 < 2*beta^2, even 0 <= c2 < beta^2 if no overflow
+            occurred.  Furthermore 0 <= c3 < beta^2.
+            If there was overflow and
+            r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta, i.e. c2 >= beta^2,
+            the next test can be skipped.}
+           While c3 > c2, {Here 0 <= c2 < c3 < beta^2}
+             Put q* := q* - 1, c2 := c2 + b[n-1]*beta, c3 := c3 - b[n-2].
+           If q* > 0:
+             Put r := r - b * q* * beta^j. In detail:
+               [r[n+j],...,r[j]] := [r[n+j],...,r[j]] - q* * [b[n-1],...,b[0]].
+               hence: u:=0, for i:=0 to n-1 do
+                              u := u + q* * b[i],
+                              r[j+i]:=r[j+i]-(u mod beta) (+ beta, if carry),
+                              u:=u div beta (+ 1, if carry in subtraction)
+                      r[n+j]:=r[n+j]-u.
+               {Since always u = (q* * [b[i-1],...,b[0]] div beta^i) + 1
+                               < q* + 1 <= beta,
+                the carry u does not overflow.}
+             If a negative carry occurs, put q* := q* - 1
+               and [r[n+j],...,r[j]] := [r[n+j],...,r[j]] + 
[0,b[n-1],...,b[0]].
+         Set q[j] := q*.
+       Normalise [q[m-n],..,q[0]]; this yields the quotient q.
+       Shift [r[n-1],...,r[0]] right by s bits and normalise; this yields the
+       rest r.
+       The room for q[j] can be allocated at the memory location of r[n+j].
+     Finally, round-to-even:
+       Shift r left by 1 bit.
+       If r > b or if r = b and q[0] is odd, q := q+1.
+   */
+  const mp_limb_t *a_ptr = a.limbs;
+  size_t a_len = a.nlimbs;
+  const mp_limb_t *b_ptr = b.limbs;
+  size_t b_len = b.nlimbs;
+  mp_limb_t *roomptr;
+  mp_limb_t *tmp_roomptr = NULL;
+  mp_limb_t *q_ptr;
+  size_t q_len;
+  mp_limb_t *r_ptr;
+  size_t r_len;
+
+  /* Allocate room for a_len+2 digits.
+     (Need a_len+1 digits for the real division and 1 more digit for the
+     final rounding of q.)  */
+  roomptr = (mp_limb_t *) malloc ((a_len + 2) * sizeof (mp_limb_t));
+  if (roomptr == NULL)
+    return NULL;
+
+  /* Normalise a.  */
+  while (a_len > 0 && a_ptr[a_len - 1] == 0)
+    a_len--;
+
+  /* Normalise b.  */
+  for (;;)
+    {
+      if (b_len == 0)
+       /* Division by zero.  */
+       abort ();
+      if (b_ptr[b_len - 1] == 0)
+       b_len--;
+      else
+       break;
+    }
+
+  /* Here m = a_len >= 0 and n = b_len > 0.  */
+
+  if (a_len < b_len)
+    {
+      /* m<n: trivial case.  q=0, r := copy of a.  */
+      r_ptr = roomptr;
+      r_len = a_len;
+      memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
+      q_ptr = roomptr + a_len;
+      q_len = 0;
+    }
+  else if (b_len == 1)
+    {
+      /* n=1: single precision division.
+        beta^(m-1) <= a < beta^m  ==>  beta^(m-2) <= a/b < beta^m  */
+      r_ptr = roomptr;
+      q_ptr = roomptr + 1;
+      {
+       mp_limb_t den = b_ptr[0];
+       mp_limb_t remainder = 0;
+       const mp_limb_t *sourceptr = a_ptr + a_len;
+       mp_limb_t *destptr = q_ptr + a_len;
+       size_t count;
+       for (count = a_len; count > 0; count--)
+         {
+           mp_twolimb_t num =
+             ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--sourceptr;
+           *--destptr = num / den;
+           remainder = num % den;
+         }
+       /* Normalise and store r.  */
+       if (remainder > 0)
+         {
+           r_ptr[0] = remainder;
+           r_len = 1;
+         }
+       else
+         r_len = 0;
+       /* Normalise q.  */
+       q_len = a_len;
+       if (q_ptr[q_len - 1] == 0)
+         q_len--;
+      }
+    }
+  else
+    {
+      /* n>1: multiple precision division.
+        beta^(m-1) <= a < beta^m, beta^(n-1) <= b < beta^n  ==>
+        beta^(m-n-1) <= a/b < beta^(m-n+1).  */
+      /* Determine s.  */
+      size_t s;
+      {
+       mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */
+       s = 31;
+       if (msd >= 0x10000)
+         {
+           msd = msd >> 16;
+           s -= 16;
+         }
+       if (msd >= 0x100)
+         {
+           msd = msd >> 8;
+           s -= 8;
+         }
+       if (msd >= 0x10)
+         {
+           msd = msd >> 4;
+           s -= 4;
+         }
+       if (msd >= 0x4)
+         {
+           msd = msd >> 2;
+           s -= 2;
+         }
+       if (msd >= 0x2)
+         {
+           msd = msd >> 1;
+           s -= 1;
+         }
+      }
+      /* 0 <= s < GMP_LIMB_BITS.
+        Copy b, shifting it left by s bits.  */
+      if (s > 0)
+       {
+         tmp_roomptr = (mp_limb_t *) malloc (b_len * sizeof (mp_limb_t));
+         if (tmp_roomptr == NULL)
+           {
+             free (roomptr);
+             return NULL;
+           }
+         {
+           const mp_limb_t *sourceptr = b_ptr;
+           mp_limb_t *destptr = tmp_roomptr;
+           mp_twolimb_t accu = 0;
+           size_t count;
+           for (count = b_len; count > 0; count--)
+             {
+               accu += (mp_twolimb_t) *sourceptr++ << s;
+               *destptr++ = (mp_limb_t) accu;
+               accu = accu >> GMP_LIMB_BITS;
+             }
+           /* accu must be zero, since that was how s was determined.  */
+           if (accu != 0)
+             abort ();
+         }
+         b_ptr = tmp_roomptr;
+       }
+      /* Copy a, shifting it left by s bits, yields r.
+        Memory layout:
+        At the beginning: r = roomptr[0..a_len],
+        at the end: r = roomptr[0..b_len-1], q = roomptr[b_len..a_len]  */
+      r_ptr = roomptr;
+      if (s == 0)
+       {
+         memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
+         r_ptr[a_len] = 0;
+       }
+      else
+       {
+         const mp_limb_t *sourceptr = a_ptr;
+         mp_limb_t *destptr = r_ptr;
+         mp_twolimb_t accu = 0;
+         size_t count;
+         for (count = a_len; count > 0; count--)
+           {
+             accu += (mp_twolimb_t) *sourceptr++ << s;
+             *destptr++ = (mp_limb_t) accu;
+             accu = accu >> GMP_LIMB_BITS;
+           }
+         *destptr++ = (mp_limb_t) accu;
+       }
+      q_ptr = roomptr + b_len;
+      q_len = a_len - b_len + 1; /* q will have m-n+1 limbs */
+      {
+       size_t j = a_len - b_len; /* m-n */
+       mp_limb_t b_msd = b_ptr[b_len - 1]; /* b[n-1] */
+       mp_limb_t b_2msd = b_ptr[b_len - 2]; /* b[n-2] */
+       mp_twolimb_t b_msdd = /* b[n-1]*beta+b[n-2] */
+         ((mp_twolimb_t) b_msd << GMP_LIMB_BITS) | b_2msd;
+       /* Division loop, traversed m-n+1 times.
+          j counts down, b is unchanged, beta/2 <= b[n-1] < beta.  */
+       for (;;)
+         {
+           mp_limb_t q_star;
+           mp_limb_t c1;
+           if (r_ptr[j + b_len] < b_msd) /* r[j+n] < b[n-1] ? */
+             {
+               /* Divide r[j+n]*beta+r[j+n-1] by b[n-1], no overflow.  */
+               mp_twolimb_t num =
+                 ((mp_twolimb_t) r_ptr[j + b_len] << GMP_LIMB_BITS)
+                 | r_ptr[j + b_len - 1];
+               q_star = num / b_msd;
+               c1 = num % b_msd;
+             }
+           else
+             {
+               /* Overflow, hence r[j+n]*beta+r[j+n-1] >= beta*b[n-1].  */
+               q_star = (mp_limb_t)~(mp_limb_t)0; /* q* = beta-1 */
+               /* Test whether r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] >= beta
+                  <==> r[j+n]*beta+r[j+n-1] + b[n-1] >= beta*b[n-1]+beta
+                  <==> b[n-1] < floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta)
+                       {<= beta !}.
+                  If yes, jump directly to the subtraction loop.
+                  (Otherwise, r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] < beta
+                   <==> floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) = b[n-1] ) */
+               if (r_ptr[j + b_len] > b_msd
+                   || (c1 = r_ptr[j + b_len - 1] + b_msd) < b_msd)
+                 /* r[j+n] >= b[n-1]+1 or
+                    r[j+n] = b[n-1] and the addition r[j+n-1]+b[n-1] gives a
+                    carry.  */
+                 goto subtract;
+             }
+           /* q_star = q*,
+              c1 = (r[j+n]*beta+r[j+n-1]) - q* * b[n-1] (>=0, <beta).  */
+           {
+             mp_twolimb_t c2 = /* c1*beta+r[j+n-2] */
+               ((mp_twolimb_t) c1 << GMP_LIMB_BITS) | r_ptr[j + b_len - 2];
+             mp_twolimb_t c3 = /* b[n-2] * q* */
+               (mp_twolimb_t) b_2msd * (mp_twolimb_t) q_star;
+             /* While c2 < c3, increase c2 and decrease c3.
+                Consider c3-c2.  While it is > 0, decrease it by
+                b[n-1]*beta+b[n-2].  Because of b[n-1]*beta+b[n-2] >= beta^2/2
+                this can happen only twice.  */
+             if (c3 > c2)
+               {
+                 q_star = q_star - 1; /* q* := q* - 1 */
+                 if (c3 - c2 > b_msdd)
+                   q_star = q_star - 1; /* q* := q* - 1 */
+               }
+           }
+           if (q_star > 0)
+             subtract:
+             {
+               /* Subtract r := r - b * q* * beta^j.  */
+               mp_limb_t cr;
+               {
+                 const mp_limb_t *sourceptr = b_ptr;
+                 mp_limb_t *destptr = r_ptr + j;
+                 mp_twolimb_t carry = 0;
+                 size_t count;
+                 for (count = b_len; count > 0; count--)
+                   {
+                     /* Here 0 <= carry <= q*.  */
+                     carry =
+                       carry
+                       + (mp_twolimb_t) q_star * (mp_twolimb_t) *sourceptr++
+                       + (mp_limb_t) ~(*destptr);
+                     /* Here 0 <= carry <= beta*q* + beta-1.  */
+                     *destptr++ = ~(mp_limb_t) carry;
+                     carry = carry >> GMP_LIMB_BITS; /* <= q* */
+                   }
+                 cr = (mp_limb_t) carry;
+               }
+               /* Subtract cr from r_ptr[j + b_len], then forget about
+                  r_ptr[j + b_len].  */
+               if (cr > r_ptr[j + b_len])
+                 {
+                   /* Subtraction gave a carry.  */
+                   q_star = q_star - 1; /* q* := q* - 1 */
+                   /* Add b back.  */
+                   {
+                     const mp_limb_t *sourceptr = b_ptr;
+                     mp_limb_t *destptr = r_ptr + j;
+                     mp_limb_t carry = 0;
+                     size_t count;
+                     for (count = b_len; count > 0; count--)
+                       {
+                         mp_limb_t source1 = *sourceptr++;
+                         mp_limb_t source2 = *destptr;
+                         *destptr++ = source1 + source2 + carry;
+                         carry =
+                           (carry
+                            ? source1 >= (mp_limb_t) ~source2
+                            : source1 > (mp_limb_t) ~source2);
+                       }
+                   }
+                   /* Forget about the carry and about r[j+n].  */
+                 }
+             }
+           /* q* is determined.  Store it as q[j].  */
+           q_ptr[j] = q_star;
+           if (j == 0)
+             break;
+           j--;
+         }
+      }
+      r_len = b_len;
+      /* Normalise q.  */
+      if (q_ptr[q_len - 1] == 0)
+       q_len--;
+# if 0 /* Not needed here, since we need r only to compare it with b/2, and
+         b is shifted left by s bits.  */
+      /* Shift r right by s bits.  */
+      if (s > 0)
+       {
+         mp_limb_t ptr = r_ptr + r_len;
+         mp_twolimb_t accu = 0;
+         size_t count;
+         for (count = r_len; count > 0; count--)
+           {
+             accu = (mp_twolimb_t) (mp_limb_t) accu << GMP_LIMB_BITS;
+             accu += (mp_twolimb_t) *--ptr << (GMP_LIMB_BITS - s);
+             *ptr = (mp_limb_t) (accu >> GMP_LIMB_BITS);
+           }
+       }
+# endif
+      /* Normalise r.  */
+      while (r_len > 0 && r_ptr[r_len - 1] == 0)
+       r_len--;
+    }
+  /* Compare r << 1 with b.  */
+  if (r_len > b_len)
+    goto increment_q;
+  {
+    size_t i;
+    for (i = b_len;;)
+      {
+       mp_limb_t r_i =
+         (i <= r_len && i > 0 ? r_ptr[i - 1] >> (GMP_LIMB_BITS - 1) : 0)
+         | (i < r_len ? r_ptr[i] << 1 : 0);
+       mp_limb_t b_i = (i < b_len ? b_ptr[i] : 0);
+       if (r_i > b_i)
+         goto increment_q;
+       if (r_i < b_i)
+         goto keep_q;
+       if (i == 0)
+         break;
+       i--;
+      }
+  }
+  if (q_len > 0 && ((q_ptr[0] & 1) != 0))
+    /* q is odd.  */
+    increment_q:
+    {
+      size_t i;
+      for (i = 0; i < q_len; i++)
+       if (++(q_ptr[i]) != 0)
+         goto keep_q;
+      q_ptr[q_len++] = 1;
+    }
+  keep_q:
+  if (tmp_roomptr != NULL)
+    free (tmp_roomptr);
+  q->limbs = q_ptr;
+  q->nlimbs = q_len;
+  return roomptr;
+}
+
+/* Convert a bignum a >= 0, multiplied with 10^extra_zeroes, to decimal
+   representation.
+   Destroys the contents of a.
+   Return the allocated memory - containing the decimal digits in low-to-high
+   order, terminated with a NUL character - in case of success, NULL in case
+   of memory allocation failure.  */
+static char *
+convert_to_decimal (mpn_t a, size_t extra_zeroes)
+{
+  mp_limb_t *a_ptr = a.limbs;
+  size_t a_len = a.nlimbs;
+  /* 0.03345 is slightly larger than log(2)/(9*log(10)).  */
+  size_t c_len = 9 * ((size_t)(a_len * (GMP_LIMB_BITS * 0.03345f)) + 1);
+  char *c_ptr = (char *) malloc (xsum (c_len, extra_zeroes));
+  if (c_ptr != NULL)
+    {
+      char *d_ptr = c_ptr;
+      for (; extra_zeroes > 0; extra_zeroes--)
+       *d_ptr++ = '0';
+      while (a_len > 0)
+       {
+         /* Divide a by 10^9, in-place.  */
+         mp_limb_t remainder = 0;
+         mp_limb_t *ptr = a_ptr + a_len;
+         size_t count;
+         for (count = a_len; count > 0; count--)
+           {
+             mp_twolimb_t num =
+               ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--ptr;
+             *ptr = num / 1000000000;
+             remainder = num % 1000000000;
+           }
+         /* Store the remainder as 9 decimal digits.  */
+         for (count = 9; count > 0; count--)
+           {
+             *d_ptr++ = '0' + (remainder % 10);
+             remainder = remainder / 10;
+           }
+         /* Normalize a.  */
+         if (a_ptr[a_len - 1] == 0)
+           a_len--;
+       }
+      /* Remove leading zeroes.  */
+      while (d_ptr > c_ptr && d_ptr[-1] == '0')
+       d_ptr--;
+      /* But keep at least one zero.  */
+      if (d_ptr == c_ptr)
+       *d_ptr++ = '0';
+      /* Terminate the string.  */
+      *d_ptr = '\0';
+    }
+  return c_ptr;
+}
+
+# if NEED_PRINTF_LONG_DOUBLE
+
+/* Assuming x is finite and >= 0:
+   write x as x = 2^e * m, where m is a bignum.
+   Return the allocated memory in case of success, NULL in case of memory
+   allocation failure.  */
+static void *
+decode_long_double (long double x, int *ep, mpn_t *mp)
+{
+  mpn_t m;
+  int exp;
+  long double y;
+  size_t i;
+
+  /* Allocate memory for result.  */
+  m.nlimbs = (LDBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
+  m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
+  if (m.limbs == NULL)
+    return NULL;
+  /* Split into exponential part and mantissa.  */
+  y = frexpl (x, &exp);
+  if (!(y >= 0.0L && y < 1.0L))
+    abort ();
+  /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * LDBL_MANT_BIT), and the
+     latter is an integer.  */
+  /* Convert the mantissa (y * LDBL_MANT_BIT) to a sequence of limbs.
+     I'm not sure whether it's safe to cast a 'long double' value between
+     2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
+     'long double' values between 0 and 2^16 (to 'unsigned int' or 'int',
+     doesn't matter).  */
+#  if (LDBL_MANT_BIT % GMP_LIMB_BITS) != 0
+#   if (LDBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
+    {
+      mp_limb_t hi, lo;
+      y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % (GMP_LIMB_BITS / 2));
+      hi = (int) y;
+      y -= hi;
+      if (!(y >= 0.0L && y < 1.0L))
+       abort ();
+      y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
+      lo = (int) y;
+      y -= lo;
+      if (!(y >= 0.0L && y < 1.0L))
+       abort ();
+      m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | 
lo;
+    }
+#   else
+    {
+      mp_limb_t d;
+      y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % GMP_LIMB_BITS);
+      d = (int) y;
+      y -= d;
+      if (!(y >= 0.0L && y < 1.0L))
+       abort ();
+      m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = d;
+    }
+#   endif
+#  endif
+  for (i = LDBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
+    {
+      mp_limb_t hi, lo;
+      y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
+      hi = (int) y;
+      y -= hi;
+      if (!(y >= 0.0L && y < 1.0L))
+       abort ();
+      y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
+      lo = (int) y;
+      y -= lo;
+      if (!(y >= 0.0L && y < 1.0L))
+       abort ();
+      m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
+    }
+#if 0 /* On FreeBSD 6.1/x86, 'long double' numbers sometimes have excess
+         precision.  */
+  if (!(y == 0.0L))
+    abort ();
+#endif
+  /* Normalise.  */
+  while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
+    m.nlimbs--;
+  *mp = m;
+  *ep = exp - LDBL_MANT_BIT;
+  return m.limbs;
+}
+
+# endif
+
+# if NEED_PRINTF_DOUBLE
+
+/* Assuming x is finite and >= 0:
+   write x as x = 2^e * m, where m is a bignum.
+   Return the allocated memory in case of success, NULL in case of memory
+   allocation failure.  */
+static void *
+decode_double (double x, int *ep, mpn_t *mp)
+{
+  mpn_t m;
+  int exp;
+  double y;
+  size_t i;
+
+  /* Allocate memory for result.  */
+  m.nlimbs = (DBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
+  m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
+  if (m.limbs == NULL)
+    return NULL;
+  /* Split into exponential part and mantissa.  */
+  y = frexp (x, &exp);
+  if (!(y >= 0.0 && y < 1.0))
+    abort ();
+  /* x = 2^exp * y = 2^(exp - DBL_MANT_BIT) * (y * DBL_MANT_BIT), and the
+     latter is an integer.  */
+  /* Convert the mantissa (y * DBL_MANT_BIT) to a sequence of limbs.
+     I'm not sure whether it's safe to cast a 'double' value between
+     2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
+     'double' values between 0 and 2^16 (to 'unsigned int' or 'int',
+     doesn't matter).  */
+#  if (DBL_MANT_BIT % GMP_LIMB_BITS) != 0
+#   if (DBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
+    {
+      mp_limb_t hi, lo;
+      y *= (mp_limb_t) 1 << (DBL_MANT_BIT % (GMP_LIMB_BITS / 2));
+      hi = (int) y;
+      y -= hi;
+      if (!(y >= 0.0 && y < 1.0))
+       abort ();
+      y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
+      lo = (int) y;
+      y -= lo;
+      if (!(y >= 0.0 && y < 1.0))
+       abort ();
+      m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
+    }
+#   else
+    {
+      mp_limb_t d;
+      y *= (mp_limb_t) 1 << (DBL_MANT_BIT % GMP_LIMB_BITS);
+      d = (int) y;
+      y -= d;
+      if (!(y >= 0.0 && y < 1.0))
+       abort ();
+      m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = d;
+    }
+#   endif
+#  endif
+  for (i = DBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
+    {
+      mp_limb_t hi, lo;
+      y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
+      hi = (int) y;
+      y -= hi;
+      if (!(y >= 0.0 && y < 1.0))
+       abort ();
+      y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
+      lo = (int) y;
+      y -= lo;
+      if (!(y >= 0.0 && y < 1.0))
+       abort ();
+      m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
+    }
+  if (!(y == 0.0))
+    abort ();
+  /* Normalise.  */
+  while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
+    m.nlimbs--;
+  *mp = m;
+  *ep = exp - DBL_MANT_BIT;
+  return m.limbs;
+}
+
+# endif
+
+/* Assuming x = 2^e * m is finite and >= 0, and n is an integer:
+   Returns the decimal representation of round (x * 10^n).
+   Return the allocated memory - containing the decimal digits in low-to-high
+   order, terminated with a NUL character - in case of success, NULL in case
+   of memory allocation failure.  */
+static char *
+scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
+{
+  int s;
+  size_t extra_zeroes;
+  unsigned int abs_n;
+  unsigned int abs_s;
+  mp_limb_t *pow5_ptr;
+  size_t pow5_len;
+  unsigned int s_limbs;
+  unsigned int s_bits;
+  mpn_t pow5;
+  mpn_t z;
+  void *z_memory;
+  char *digits;
+
+  if (memory == NULL)
+    return NULL;
+  /* x = 2^e * m, hence
+     y = round (2^e * 10^n * m) = round (2^(e+n) * 5^n * m)
+       = round (2^s * 5^n * m).  */
+  s = e + n;
+  extra_zeroes = 0;
+  /* Factor out a common power of 10 if possible.  */
+  if (s > 0 && n > 0)
+    {
+      extra_zeroes = (s < n ? s : n);
+      s -= extra_zeroes;
+      n -= extra_zeroes;
+    }
+  /* Here y = round (2^s * 5^n * m) * 10^extra_zeroes.
+     Before converting to decimal, we need to compute
+     z = round (2^s * 5^n * m).  */
+  /* Compute 5^|n|, possibly shifted by |s| bits if n and s have the same
+     sign.  2.322 is slightly larger than log(5)/log(2).  */
+  abs_n = (n >= 0 ? n : -n);
+  abs_s = (s >= 0 ? s : -s);
+  pow5_ptr = (mp_limb_t *) malloc (((int)(abs_n * (2.322f / GMP_LIMB_BITS)) + 1
+                                   + abs_s / GMP_LIMB_BITS + 1)
+                                  * sizeof (mp_limb_t));
+  if (pow5_ptr == NULL)
+    {
+      free (memory);
+      return NULL;
+    }
+  /* Initialize with 1.  */
+  pow5_ptr[0] = 1;
+  pow5_len = 1;
+  /* Multiply with 5^|n|.  */
+  if (abs_n > 0)
+    {
+      static mp_limb_t const small_pow5[13 + 1] =
+       {
+         1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625,
+         48828125, 244140625, 1220703125
+       };
+      unsigned int n13;
+      for (n13 = 0; n13 <= abs_n; n13 += 13)
+       {
+         mp_limb_t digit1 = small_pow5[n13 + 13 <= abs_n ? 13 : abs_n - n13];
+         size_t j;
+         mp_twolimb_t carry = 0;
+         for (j = 0; j < pow5_len; j++)
+           {
+             mp_limb_t digit2 = pow5_ptr[j];
+             carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
+             pow5_ptr[j] = (mp_limb_t) carry;
+             carry = carry >> GMP_LIMB_BITS;
+           }
+         if (carry > 0)
+           pow5_ptr[pow5_len++] = (mp_limb_t) carry;
+       }
+    }
+  s_limbs = abs_s / GMP_LIMB_BITS;
+  s_bits = abs_s % GMP_LIMB_BITS;
+  if (n >= 0 ? s >= 0 : s <= 0)
+    {
+      /* Multiply with 2^|s|.  */
+      if (s_bits > 0)
+       {
+         mp_limb_t *ptr = pow5_ptr;
+         mp_twolimb_t accu = 0;
+         size_t count;
+         for (count = pow5_len; count > 0; count--)
+           {
+             accu += (mp_twolimb_t) *ptr << s_bits;
+             *ptr++ = (mp_limb_t) accu;
+             accu = accu >> GMP_LIMB_BITS;
+           }
+         if (accu > 0)
+           {
+             *ptr = (mp_limb_t) accu;
+             pow5_len++;
+           }
+       }
+      if (s_limbs > 0)
+       {
+         size_t count;
+         for (count = pow5_len; count > 0;)
+           {
+             count--;
+             pow5_ptr[s_limbs + count] = pow5_ptr[count];
+           }
+         for (count = s_limbs; count > 0;)
+           {
+             count--;
+             pow5_ptr[count] = 0;
+           }
+         pow5_len += s_limbs;
+       }
+      pow5.limbs = pow5_ptr;
+      pow5.nlimbs = pow5_len;
+      if (n >= 0)
+       {
+         /* Multiply m with pow5.  No division needed.  */
+         z_memory = multiply (m, pow5, &z);
+       }
+      else
+       {
+         /* Divide m by pow5 and round.  */
+         z_memory = divide (m, pow5, &z);
+       }
+    }
+  else
+    {
+      pow5.limbs = pow5_ptr;
+      pow5.nlimbs = pow5_len;
+      if (n >= 0)
+       {
+         /* n >= 0, s < 0.
+            Multiply m with pow5, then divide by 2^|s|.  */
+         mpn_t numerator;
+         mpn_t denominator;
+         void *tmp_memory;
+         tmp_memory = multiply (m, pow5, &numerator);
+         if (tmp_memory == NULL)
+           {
+             free (pow5_ptr);
+             free (memory);
+             return NULL;
+           }
+         /* Construct 2^|s|.  */
+         {
+           mp_limb_t *ptr = pow5_ptr + pow5_len;
+           size_t i;
+           for (i = 0; i < s_limbs; i++)
+             ptr[i] = 0;
+           ptr[s_limbs] = (mp_limb_t) 1 << s_bits;
+           denominator.limbs = ptr;
+           denominator.nlimbs = s_limbs + 1;
+         }
+         z_memory = divide (numerator, denominator, &z);
+         free (tmp_memory);
+       }
+      else
+       {
+         /* n < 0, s > 0.
+            Multiply m with 2^s, then divide by pow5.  */
+         mpn_t numerator;
+         mp_limb_t *num_ptr;
+         num_ptr = (mp_limb_t *) malloc ((m.nlimbs + s_limbs + 1)
+                                         * sizeof (mp_limb_t));
+         if (num_ptr == NULL)
+           {
+             free (pow5_ptr);
+             free (memory);
+             return NULL;
+           }
+         {
+           mp_limb_t *destptr = num_ptr;
+           {
+             size_t i;
+             for (i = 0; i < s_limbs; i++)
+               *destptr++ = 0;
+           }
+           if (s_bits > 0)
+             {
+               const mp_limb_t *sourceptr = m.limbs;
+               mp_twolimb_t accu = 0;
+               size_t count;
+               for (count = m.nlimbs; count > 0; count--)
+                 {
+                   accu += (mp_twolimb_t) *sourceptr++ << s_bits;
+                   *destptr++ = (mp_limb_t) accu;
+                   accu = accu >> GMP_LIMB_BITS;
+                 }
+               if (accu > 0)
+                 *destptr++ = (mp_limb_t) accu;
+             }
+           else
+             {
+               const mp_limb_t *sourceptr = m.limbs;
+               size_t count;
+               for (count = m.nlimbs; count > 0; count--)
+                 *destptr++ = *sourceptr++;
+             }
+           numerator.limbs = num_ptr;
+           numerator.nlimbs = destptr - num_ptr;
+         }
+         z_memory = divide (numerator, pow5, &z);
+         free (num_ptr);
+       }
+    }
+  free (pow5_ptr);
+  free (memory);
+
+  /* Here y = round (x * 10^n) = z * 10^extra_zeroes.  */
+
+  if (z_memory == NULL)
+    return NULL;
+  digits = convert_to_decimal (z, extra_zeroes);
+  free (z_memory);
+  return digits;
+}
+
+# if NEED_PRINTF_LONG_DOUBLE
+
+/* Assuming x is finite and >= 0, and n is an integer:
+   Returns the decimal representation of round (x * 10^n).
+   Return the allocated memory - containing the decimal digits in low-to-high
+   order, terminated with a NUL character - in case of success, NULL in case
+   of memory allocation failure.  */
+static char *
+scale10_round_decimal_long_double (long double x, int n)
+{
+  int e IF_LINT(= 0);
+  mpn_t m;
+  void *memory = decode_long_double (x, &e, &m);
+  return scale10_round_decimal_decoded (e, m, memory, n);
+}
+
+# endif
+
+# if NEED_PRINTF_DOUBLE
+
+/* Assuming x is finite and >= 0, and n is an integer:
+   Returns the decimal representation of round (x * 10^n).
+   Return the allocated memory - containing the decimal digits in low-to-high
+   order, terminated with a NUL character - in case of success, NULL in case
+   of memory allocation failure.  */
+static char *
+scale10_round_decimal_double (double x, int n)
+{
+  int e IF_LINT(= 0);
+  mpn_t m;
+  void *memory = decode_double (x, &e, &m);
+  return scale10_round_decimal_decoded (e, m, memory, n);
+}
+
+# endif
+
+# if NEED_PRINTF_LONG_DOUBLE
+
+/* Assuming x is finite and > 0:
+   Return an approximation for n with 10^n <= x < 10^(n+1).
+   The approximation is usually the right n, but may be off by 1 sometimes.  */
+static int
+floorlog10l (long double x)
+{
+  int exp;
+  long double y;
+  double z;
+  double l;
+
+  /* Split into exponential part and mantissa.  */
+  y = frexpl (x, &exp);
+  if (!(y >= 0.0L && y < 1.0L))
+    abort ();
+  if (y == 0.0L)
+    return INT_MIN;
+  if (y < 0.5L)
+    {
+      while (y < (1.0L / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 
2))))
+       {
+         y *= 1.0L * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
+         exp -= GMP_LIMB_BITS;
+       }
+      if (y < (1.0L / (1 << 16)))
+       {
+         y *= 1.0L * (1 << 16);
+         exp -= 16;
+       }
+      if (y < (1.0L / (1 << 8)))
+       {
+         y *= 1.0L * (1 << 8);
+         exp -= 8;
+       }
+      if (y < (1.0L / (1 << 4)))
+       {
+         y *= 1.0L * (1 << 4);
+         exp -= 4;
+       }
+      if (y < (1.0L / (1 << 2)))
+       {
+         y *= 1.0L * (1 << 2);
+         exp -= 2;
+       }
+      if (y < (1.0L / (1 << 1)))
+       {
+         y *= 1.0L * (1 << 1);
+         exp -= 1;
+       }
+    }
+  if (!(y >= 0.5L && y < 1.0L))
+    abort ();
+  /* Compute an approximation for l = log2(x) = exp + log2(y).  */
+  l = exp;
+  z = y;
+  if (z < 0.70710678118654752444)
+    {
+      z *= 1.4142135623730950488;
+      l -= 0.5;
+    }
+  if (z < 0.8408964152537145431)
+    {
+      z *= 1.1892071150027210667;
+      l -= 0.25;
+    }
+  if (z < 0.91700404320467123175)
+    {
+      z *= 1.0905077326652576592;
+      l -= 0.125;
+    }
+  if (z < 0.9576032806985736469)
+    {
+      z *= 1.0442737824274138403;
+      l -= 0.0625;
+    }
+  /* Now 0.95 <= z <= 1.01.  */
+  z = 1 - z;
+  /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...)
+     Four terms are enough to get an approximation with error < 10^-7.  */
+  l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 
0.25)));
+  /* Finally multiply with log(2)/log(10), yields an approximation for
+     log10(x).  */
+  l *= 0.30102999566398119523;
+  /* Round down to the next integer.  */
+  return (int) l + (l < 0 ? -1 : 0);
+}
+
+# endif
+
+# if NEED_PRINTF_DOUBLE
+
+/* Assuming x is finite and > 0:
+   Return an approximation for n with 10^n <= x < 10^(n+1).
+   The approximation is usually the right n, but may be off by 1 sometimes.  */
+static int
+floorlog10 (double x)
+{
+  int exp;
+  double y;
+  double z;
+  double l;
+
+  /* Split into exponential part and mantissa.  */
+  y = frexp (x, &exp);
+  if (!(y >= 0.0 && y < 1.0))
+    abort ();
+  if (y == 0.0)
+    return INT_MIN;
+  if (y < 0.5)
+    {
+      while (y < (1.0 / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 
2))))
+       {
+         y *= 1.0 * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
+         exp -= GMP_LIMB_BITS;
+       }
+      if (y < (1.0 / (1 << 16)))
+       {
+         y *= 1.0 * (1 << 16);
+         exp -= 16;
+       }
+      if (y < (1.0 / (1 << 8)))
+       {
+         y *= 1.0 * (1 << 8);
+         exp -= 8;
+       }
+      if (y < (1.0 / (1 << 4)))
+       {
+         y *= 1.0 * (1 << 4);
+         exp -= 4;
+       }
+      if (y < (1.0 / (1 << 2)))
+       {
+         y *= 1.0 * (1 << 2);
+         exp -= 2;
+       }
+      if (y < (1.0 / (1 << 1)))
+       {
+         y *= 1.0 * (1 << 1);
+         exp -= 1;
+       }
+    }
+  if (!(y >= 0.5 && y < 1.0))
+    abort ();
+  /* Compute an approximation for l = log2(x) = exp + log2(y).  */
+  l = exp;
+  z = y;
+  if (z < 0.70710678118654752444)
+    {
+      z *= 1.4142135623730950488;
+      l -= 0.5;
+    }
+  if (z < 0.8408964152537145431)
+    {
+      z *= 1.1892071150027210667;
+      l -= 0.25;
+    }
+  if (z < 0.91700404320467123175)
+    {
+      z *= 1.0905077326652576592;
+      l -= 0.125;
+    }
+  if (z < 0.9576032806985736469)
+    {
+      z *= 1.0442737824274138403;
+      l -= 0.0625;
+    }
+  /* Now 0.95 <= z <= 1.01.  */
+  z = 1 - z;
+  /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...)
+     Four terms are enough to get an approximation with error < 10^-7.  */
+  l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 
0.25)));
+  /* Finally multiply with log(2)/log(10), yields an approximation for
+     log10(x).  */
+  l *= 0.30102999566398119523;
+  /* Round down to the next integer.  */
+  return (int) l + (l < 0 ? -1 : 0);
+}
+
+# endif
+
+/* Tests whether a string of digits consists of exactly PRECISION zeroes and
+   a single '1' digit.  */
+static int
+is_borderline (const char *digits, size_t precision)
+{
+  for (; precision > 0; precision--, digits++)
+    if (*digits != '0')
+      return 0;
+  if (*digits != '1')
+    return 0;
+  digits++;
+  return *digits == '\0';
+}
+
+#endif
+
+DCHAR_T *
+VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
+           const FCHAR_T *format, va_list args)
+{
+  DIRECTIVES d;
+  arguments a;
+
+  if (PRINTF_PARSE (format, &d, &a) < 0)
+    /* errno is already set.  */
+    return NULL;
+
+#define CLEANUP() \
+  free (d.dir);                                                                
\
+  if (a.arg)                                                           \
+    free (a.arg);
+
+  if (PRINTF_FETCHARGS (args, &a) < 0)
+    {
+      CLEANUP ();
+      errno = EINVAL;
+      return NULL;
+    }
+
+  {
+    size_t buf_neededlength;
+    TCHAR_T *buf;
+    TCHAR_T *buf_malloced;
+    const FCHAR_T *cp;
+    size_t i;
+    DIRECTIVE *dp;
+    /* Output string accumulator.  */
+    DCHAR_T *result;
+    size_t allocated;
+    size_t length;
+
+    /* Allocate a small buffer that will hold a directive passed to
+       sprintf or snprintf.  */
+    buf_neededlength =
+      xsum4 (7, d.max_width_length, d.max_precision_length, 6);
+#if HAVE_ALLOCA
+    if (buf_neededlength < 4000 / sizeof (TCHAR_T))
+      {
+       buf = (TCHAR_T *) alloca (buf_neededlength * sizeof (TCHAR_T));
+       buf_malloced = NULL;
+      }
+    else
+#endif
+      {
+       size_t buf_memsize = xtimes (buf_neededlength, sizeof (TCHAR_T));
+       if (size_overflow_p (buf_memsize))
+         goto out_of_memory_1;
+       buf = (TCHAR_T *) malloc (buf_memsize);
+       if (buf == NULL)
+         goto out_of_memory_1;
+       buf_malloced = buf;
+      }
+
+    if (resultbuf != NULL)
+      {
+       result = resultbuf;
+       allocated = *lengthp;
+      }
+    else
+      {
+       result = NULL;
+       allocated = 0;
+      }
+    length = 0;
+    /* Invariants:
+       result is either == resultbuf or == NULL or malloc-allocated.
+       If length > 0, then result != NULL.  */
+
+    /* Ensures that allocated >= needed.  Aborts through a jump to
+       out_of_memory if needed is SIZE_MAX or otherwise too big.  */
+#define ENSURE_ALLOCATION(needed) \
+    if ((needed) > allocated)                                               \
+      {                                                                        
     \
+       size_t memory_size;                                                  \
+       DCHAR_T *memory;                                                     \
+                                                                            \
+       allocated = (allocated > 0 ? xtimes (allocated, 2) : 12);            \
+       if ((needed) > allocated)                                            \
+         allocated = (needed);                                              \
+       memory_size = xtimes (allocated, sizeof (DCHAR_T));                  \
+       if (size_overflow_p (memory_size))                                   \
+         goto out_of_memory;                                                \
+       if (result == resultbuf || result == NULL)                           \
+         memory = (DCHAR_T *) malloc (memory_size);                         \
+       else                                                                 \
+         memory = (DCHAR_T *) realloc (result, memory_size);                \
+       if (memory == NULL)                                                  \
+         goto out_of_memory;                                                \
+       if (result == resultbuf && length > 0)                               \
+         DCHAR_CPY (memory, result, length);                                \
+       result = memory;                                                     \
+      }
+
+    for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
+      {
+       if (cp != dp->dir_start)
+         {
+           size_t n = dp->dir_start - cp;
+           size_t augmented_length = xsum (length, n);
+
+           ENSURE_ALLOCATION (augmented_length);
+           /* This copies a piece of FCHAR_T[] into a DCHAR_T[].  Here we
+              need that the format string contains only ASCII characters
+              if FCHAR_T and DCHAR_T are not the same type.  */
+           if (sizeof (FCHAR_T) == sizeof (DCHAR_T))
+             {
+               DCHAR_CPY (result + length, (const DCHAR_T *) cp, n);
+               length = augmented_length;
+             }
+           else
+             {
+               do
+                 result[length++] = (unsigned char) *cp++;
+               while (--n > 0);
+             }
+         }
+       if (i == d.count)
+         break;
+
+       /* Execute a single directive.  */
+       if (dp->conversion == '%')
+         {
+           size_t augmented_length;
+
+           if (!(dp->arg_index == ARG_NONE))
+             abort ();
+           augmented_length = xsum (length, 1);
+           ENSURE_ALLOCATION (augmented_length);
+           result[length] = '%';
+           length = augmented_length;
+         }
+       else
+         {
+           if (!(dp->arg_index != ARG_NONE))
+             abort ();
+
+           if (dp->conversion == 'n')
+             {
+               switch (a.arg[dp->arg_index].type)
+                 {
+                 case TYPE_COUNT_SCHAR_POINTER:
+                   *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
+                   break;
+                 case TYPE_COUNT_SHORT_POINTER:
+                   *a.arg[dp->arg_index].a.a_count_short_pointer = length;
+                   break;
+                 case TYPE_COUNT_INT_POINTER:
+                   *a.arg[dp->arg_index].a.a_count_int_pointer = length;
+                   break;
+                 case TYPE_COUNT_LONGINT_POINTER:
+                   *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
+                   break;
+#if HAVE_LONG_LONG_INT
+                 case TYPE_COUNT_LONGLONGINT_POINTER:
+                   *a.arg[dp->arg_index].a.a_count_longlongint_pointer = 
length;
+                   break;
+#endif
+                 default:
+                   abort ();
+                 }
+             }
+#if ENABLE_UNISTDIO
+           /* The unistdio extensions.  */
+           else if (dp->conversion == 'U')
+             {
+               arg_type type = a.arg[dp->arg_index].type;
+               int flags = dp->flags;
+               int has_width;
+               size_t width;
+               int has_precision;
+               size_t precision;
+
+               has_width = 0;
+               width = 0;
+               if (dp->width_start != dp->width_end)
+                 {
+                   if (dp->width_arg_index != ARG_NONE)
+                     {
+                       int arg;
+
+                       if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+                         abort ();
+                       arg = a.arg[dp->width_arg_index].a.a_int;
+                       if (arg < 0)
+                         {
+                           /* "A negative field width is taken as a '-' flag
+                               followed by a positive field width."  */
+                           flags |= FLAG_LEFT;
+                           width = (unsigned int) (-arg);
+                         }
+                       else
+                         width = arg;
+                     }
+                   else
+                     {
+                       const FCHAR_T *digitp = dp->width_start;
+
+                       do
+                         width = xsum (xtimes (width, 10), *digitp++ - '0');
+                       while (digitp != dp->width_end);
+                     }
+                   has_width = 1;
+                 }
+
+               has_precision = 0;
+               precision = 0;
+               if (dp->precision_start != dp->precision_end)
+                 {
+                   if (dp->precision_arg_index != ARG_NONE)
+                     {
+                       int arg;
+
+                       if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+                         abort ();
+                       arg = a.arg[dp->precision_arg_index].a.a_int;
+                       /* "A negative precision is taken as if the precision
+                           were omitted."  */
+                       if (arg >= 0)
+                         {
+                           precision = arg;
+                           has_precision = 1;
+                         }
+                     }
+                   else
+                     {
+                       const FCHAR_T *digitp = dp->precision_start + 1;
+
+                       precision = 0;
+                       while (digitp != dp->precision_end)
+                         precision = xsum (xtimes (precision, 10), *digitp++ - 
'0');
+                       has_precision = 1;
+                     }
+                 }
+
+               switch (type)
+                 {
+                 case TYPE_U8_STRING:
+                   {
+                     const uint8_t *arg = a.arg[dp->arg_index].a.a_u8_string;
+                     const uint8_t *arg_end;
+                     size_t characters;
+
+                     if (has_precision)
+                       {
+                         /* Use only PRECISION characters, from the left.  */
+                         arg_end = arg;
+                         characters = 0;
+                         for (; precision > 0; precision--)
+                           {
+                             int count = u8_strmblen (arg_end);
+                             if (count == 0)
+                               break;
+                             if (count < 0)
+                               {
+                                 if (!(result == resultbuf || result == NULL))
+                                   free (result);
+                                 if (buf_malloced != NULL)
+                                   free (buf_malloced);
+                                 CLEANUP ();
+                                 errno = EILSEQ;
+                                 return NULL;
+                               }
+                             arg_end += count;
+                             characters++;
+                           }
+                       }
+                     else if (has_width)
+                       {
+                         /* Use the entire string, and count the number of
+                            characters.  */
+                         arg_end = arg;
+                         characters = 0;
+                         for (;;)
+                           {
+                             int count = u8_strmblen (arg_end);
+                             if (count == 0)
+                               break;
+                             if (count < 0)
+                               {
+                                 if (!(result == resultbuf || result == NULL))
+                                   free (result);
+                                 if (buf_malloced != NULL)
+                                   free (buf_malloced);
+                                 CLEANUP ();
+                                 errno = EILSEQ;
+                                 return NULL;
+                               }
+                             arg_end += count;
+                             characters++;
+                           }
+                       }
+                     else
+                       {
+                         /* Use the entire string.  */
+                         arg_end = arg + u8_strlen (arg);
+                         /* The number of characters doesn't matter.  */
+                         characters = 0;
+                       }
+
+                     if (has_width && width > characters
+                         && !(dp->flags & FLAG_LEFT))
+                       {
+                         size_t n = width - characters;
+                         ENSURE_ALLOCATION (xsum (length, n));
+                         DCHAR_SET (result + length, ' ', n);
+                         length += n;
+                       }
+
+# if DCHAR_IS_UINT8_T
+                     {
+                       size_t n = arg_end - arg;
+                       ENSURE_ALLOCATION (xsum (length, n));
+                       DCHAR_CPY (result + length, arg, n);
+                       length += n;
+                     }
+# else
+                     { /* Convert.  */
+                       DCHAR_T *converted = result + length;
+                       size_t converted_len = allocated - length;
+#  if DCHAR_IS_TCHAR
+                       /* Convert from UTF-8 to locale encoding.  */
+                       converted =
+                         u8_conv_to_encoding (locale_charset (),
+                                              iconveh_question_mark,
+                                              arg, arg_end - arg, NULL,
+                                              converted, &converted_len);
+#  else
+                       /* Convert from UTF-8 to UTF-16/UTF-32.  */
+                       converted =
+                         U8_TO_DCHAR (arg, arg_end - arg,
+                                      converted, &converted_len);
+#  endif
+                       if (converted == NULL)
+                         {
+                           int saved_errno = errno;
+                           if (!(result == resultbuf || result == NULL))
+                             free (result);
+                           if (buf_malloced != NULL)
+                             free (buf_malloced);
+                           CLEANUP ();
+                           errno = saved_errno;
+                           return NULL;
+                         }
+                       if (converted != result + length)
+                         {
+                           ENSURE_ALLOCATION (xsum (length, converted_len));
+                           DCHAR_CPY (result + length, converted, 
converted_len);
+                           free (converted);
+                         }
+                       length += converted_len;
+                     }
+# endif
+
+                     if (has_width && width > characters
+                         && (dp->flags & FLAG_LEFT))
+                       {
+                         size_t n = width - characters;
+                         ENSURE_ALLOCATION (xsum (length, n));
+                         DCHAR_SET (result + length, ' ', n);
+                         length += n;
+                       }
+                   }
+                   break;
+
+                 case TYPE_U16_STRING:
+                   {
+                     const uint16_t *arg = a.arg[dp->arg_index].a.a_u16_string;
+                     const uint16_t *arg_end;
+                     size_t characters;
+
+                     if (has_precision)
+                       {
+                         /* Use only PRECISION characters, from the left.  */
+                         arg_end = arg;
+                         characters = 0;
+                         for (; precision > 0; precision--)
+                           {
+                             int count = u16_strmblen (arg_end);
+                             if (count == 0)
+                               break;
+                             if (count < 0)
+                               {
+                                 if (!(result == resultbuf || result == NULL))
+                                   free (result);
+                                 if (buf_malloced != NULL)
+                                   free (buf_malloced);
+                                 CLEANUP ();
+                                 errno = EILSEQ;
+                                 return NULL;
+                               }
+                             arg_end += count;
+                             characters++;
+                           }
+                       }
+                     else if (has_width)
+                       {
+                         /* Use the entire string, and count the number of
+                            characters.  */
+                         arg_end = arg;
+                         characters = 0;
+                         for (;;)
+                           {
+                             int count = u16_strmblen (arg_end);
+                             if (count == 0)
+                               break;
+                             if (count < 0)
+                               {
+                                 if (!(result == resultbuf || result == NULL))
+                                   free (result);
+                                 if (buf_malloced != NULL)
+                                   free (buf_malloced);
+                                 CLEANUP ();
+                                 errno = EILSEQ;
+                                 return NULL;
+                               }
+                             arg_end += count;
+                             characters++;
+                           }
+                       }
+                     else
+                       {
+                         /* Use the entire string.  */
+                         arg_end = arg + u16_strlen (arg);
+                         /* The number of characters doesn't matter.  */
+                         characters = 0;
+                       }
+
+                     if (has_width && width > characters
+                         && !(dp->flags & FLAG_LEFT))
+                       {
+                         size_t n = width - characters;
+                         ENSURE_ALLOCATION (xsum (length, n));
+                         DCHAR_SET (result + length, ' ', n);
+                         length += n;
+                       }
+
+# if DCHAR_IS_UINT16_T
+                     {
+                       size_t n = arg_end - arg;
+                       ENSURE_ALLOCATION (xsum (length, n));
+                       DCHAR_CPY (result + length, arg, n);
+                       length += n;
+                     }
+# else
+                     { /* Convert.  */
+                       DCHAR_T *converted = result + length;
+                       size_t converted_len = allocated - length;
+#  if DCHAR_IS_TCHAR
+                       /* Convert from UTF-16 to locale encoding.  */
+                       converted =
+                         u16_conv_to_encoding (locale_charset (),
+                                               iconveh_question_mark,
+                                               arg, arg_end - arg, NULL,
+                                               converted, &converted_len);
+#  else
+                       /* Convert from UTF-16 to UTF-8/UTF-32.  */
+                       converted =
+                         U16_TO_DCHAR (arg, arg_end - arg,
+                                       converted, &converted_len);
+#  endif
+                       if (converted == NULL)
+                         {
+                           int saved_errno = errno;
+                           if (!(result == resultbuf || result == NULL))
+                             free (result);
+                           if (buf_malloced != NULL)
+                             free (buf_malloced);
+                           CLEANUP ();
+                           errno = saved_errno;
+                           return NULL;
+                         }
+                       if (converted != result + length)
+                         {
+                           ENSURE_ALLOCATION (xsum (length, converted_len));
+                           DCHAR_CPY (result + length, converted, 
converted_len);
+                           free (converted);
+                         }
+                       length += converted_len;
+                     }
+# endif
+
+                     if (has_width && width > characters
+                         && (dp->flags & FLAG_LEFT))
+                       {
+                         size_t n = width - characters;
+                         ENSURE_ALLOCATION (xsum (length, n));
+                         DCHAR_SET (result + length, ' ', n);
+                         length += n;
+                       }
+                   }
+                   break;
+
+                 case TYPE_U32_STRING:
+                   {
+                     const uint32_t *arg = a.arg[dp->arg_index].a.a_u32_string;
+                     const uint32_t *arg_end;
+                     size_t characters;
+
+                     if (has_precision)
+                       {
+                         /* Use only PRECISION characters, from the left.  */
+                         arg_end = arg;
+                         characters = 0;
+                         for (; precision > 0; precision--)
+                           {
+                             int count = u32_strmblen (arg_end);
+                             if (count == 0)
+                               break;
+                             if (count < 0)
+                               {
+                                 if (!(result == resultbuf || result == NULL))
+                                   free (result);
+                                 if (buf_malloced != NULL)
+                                   free (buf_malloced);
+                                 CLEANUP ();
+                                 errno = EILSEQ;
+                                 return NULL;
+                               }
+                             arg_end += count;
+                             characters++;
+                           }
+                       }
+                     else if (has_width)
+                       {
+                         /* Use the entire string, and count the number of
+                            characters.  */
+                         arg_end = arg;
+                         characters = 0;
+                         for (;;)
+                           {
+                             int count = u32_strmblen (arg_end);
+                             if (count == 0)
+                               break;
+                             if (count < 0)
+                               {
+                                 if (!(result == resultbuf || result == NULL))
+                                   free (result);
+                                 if (buf_malloced != NULL)
+                                   free (buf_malloced);
+                                 CLEANUP ();
+                                 errno = EILSEQ;
+                                 return NULL;
+                               }
+                             arg_end += count;
+                             characters++;
+                           }
+                       }
+                     else
+                       {
+                         /* Use the entire string.  */
+                         arg_end = arg + u32_strlen (arg);
+                         /* The number of characters doesn't matter.  */
+                         characters = 0;
+                       }
+
+                     if (has_width && width > characters
+                         && !(dp->flags & FLAG_LEFT))
+                       {
+                         size_t n = width - characters;
+                         ENSURE_ALLOCATION (xsum (length, n));
+                         DCHAR_SET (result + length, ' ', n);
+                         length += n;
+                       }
+
+# if DCHAR_IS_UINT32_T
+                     {
+                       size_t n = arg_end - arg;
+                       ENSURE_ALLOCATION (xsum (length, n));
+                       DCHAR_CPY (result + length, arg, n);
+                       length += n;
+                     }
+# else
+                     { /* Convert.  */
+                       DCHAR_T *converted = result + length;
+                       size_t converted_len = allocated - length;
+#  if DCHAR_IS_TCHAR
+                       /* Convert from UTF-32 to locale encoding.  */
+                       converted =
+                         u32_conv_to_encoding (locale_charset (),
+                                               iconveh_question_mark,
+                                               arg, arg_end - arg, NULL,
+                                               converted, &converted_len);
+#  else
+                       /* Convert from UTF-32 to UTF-8/UTF-16.  */
+                       converted =
+                         U32_TO_DCHAR (arg, arg_end - arg,
+                                       converted, &converted_len);
+#  endif
+                       if (converted == NULL)
+                         {
+                           int saved_errno = errno;
+                           if (!(result == resultbuf || result == NULL))
+                             free (result);
+                           if (buf_malloced != NULL)
+                             free (buf_malloced);
+                           CLEANUP ();
+                           errno = saved_errno;
+                           return NULL;
+                         }
+                       if (converted != result + length)
+                         {
+                           ENSURE_ALLOCATION (xsum (length, converted_len));
+                           DCHAR_CPY (result + length, converted, 
converted_len);
+                           free (converted);
+                         }
+                       length += converted_len;
+                     }
+# endif
+
+                     if (has_width && width > characters
+                         && (dp->flags & FLAG_LEFT))
+                       {
+                         size_t n = width - characters;
+                         ENSURE_ALLOCATION (xsum (length, n));
+                         DCHAR_SET (result + length, ' ', n);
+                         length += n;
+                       }
+                   }
+                   break;
+
+                 default:
+                   abort ();
+                 }
+             }
+#endif
+#if (!USE_SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && 
HAVE_WCHAR_T
+           else if (dp->conversion == 's'
+# if WIDE_CHAR_VERSION
+                    && a.arg[dp->arg_index].type != TYPE_WIDE_STRING
+# else
+                    && a.arg[dp->arg_index].type == TYPE_WIDE_STRING
+# endif
+                   )
+             {
+               /* The normal handling of the 's' directive below requires
+                  allocating a temporary buffer.  The determination of its
+                  length (tmp_length), in the case when a precision is
+                  specified, below requires a conversion between a char[]
+                  string and a wchar_t[] wide string.  It could be done, but
+                  we have no guarantee that the implementation of sprintf will
+                  use the exactly same algorithm.  Without this guarantee, it
+                  is possible to have buffer overrun bugs.  In order to avoid
+                  such bugs, we implement the entire processing of the 's'
+                  directive ourselves.  */
+               int flags = dp->flags;
+               int has_width;
+               size_t width;
+               int has_precision;
+               size_t precision;
+
+               has_width = 0;
+               width = 0;
+               if (dp->width_start != dp->width_end)
+                 {
+                   if (dp->width_arg_index != ARG_NONE)
+                     {
+                       int arg;
+
+                       if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+                         abort ();
+                       arg = a.arg[dp->width_arg_index].a.a_int;
+                       if (arg < 0)
+                         {
+                           /* "A negative field width is taken as a '-' flag
+                               followed by a positive field width."  */
+                           flags |= FLAG_LEFT;
+                           width = (unsigned int) (-arg);
+                         }
+                       else
+                         width = arg;
+                     }
+                   else
+                     {
+                       const FCHAR_T *digitp = dp->width_start;
+
+                       do
+                         width = xsum (xtimes (width, 10), *digitp++ - '0');
+                       while (digitp != dp->width_end);
+                     }
+                   has_width = 1;
+                 }
+
+               has_precision = 0;
+               precision = 6;
+               if (dp->precision_start != dp->precision_end)
+                 {
+                   if (dp->precision_arg_index != ARG_NONE)
+                     {
+                       int arg;
+
+                       if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+                         abort ();
+                       arg = a.arg[dp->precision_arg_index].a.a_int;
+                       /* "A negative precision is taken as if the precision
+                           were omitted."  */
+                       if (arg >= 0)
+                         {
+                           precision = arg;
+                           has_precision = 1;
+                         }
+                     }
+                   else
+                     {
+                       const FCHAR_T *digitp = dp->precision_start + 1;
+
+                       precision = 0;
+                       while (digitp != dp->precision_end)
+                         precision = xsum (xtimes (precision, 10), *digitp++ - 
'0');
+                       has_precision = 1;
+                     }
+                 }
+
+# if WIDE_CHAR_VERSION
+               /* %s in vasnwprintf.  See the specification of fwprintf.  */
+               {
+                 const char *arg = a.arg[dp->arg_index].a.a_string;
+                 const char *arg_end;
+                 size_t characters;
+
+                 if (has_precision)
+                   {
+                     /* Use only as many bytes as needed to produce PRECISION
+                        wide characters, from the left.  */
+#  if HAVE_MBRTOWC
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#  endif
+                     arg_end = arg;
+                     characters = 0;
+                     for (; precision > 0; precision--)
+                       {
+                         int count;
+#  if HAVE_MBRTOWC
+                         count = mbrlen (arg_end, MB_CUR_MAX, &state);
+#  else
+                         count = mblen (arg_end, MB_CUR_MAX);
+#  endif
+                         if (count == 0)
+                           /* Found the terminating NUL.  */
+                           break;
+                         if (count < 0)
+                           {
+                             /* Invalid or incomplete multibyte character.  */
+                             if (!(result == resultbuf || result == NULL))
+                               free (result);
+                             if (buf_malloced != NULL)
+                               free (buf_malloced);
+                             CLEANUP ();
+                             errno = EILSEQ;
+                             return NULL;
+                           }
+                         arg_end += count;
+                         characters++;
+                       }
+                   }
+                 else if (has_width)
+                   {
+                     /* Use the entire string, and count the number of wide
+                        characters.  */
+#  if HAVE_MBRTOWC
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#  endif
+                     arg_end = arg;
+                     characters = 0;
+                     for (;;)
+                       {
+                         int count;
+#  if HAVE_MBRTOWC
+                         count = mbrlen (arg_end, MB_CUR_MAX, &state);
+#  else
+                         count = mblen (arg_end, MB_CUR_MAX);
+#  endif
+                         if (count == 0)
+                           /* Found the terminating NUL.  */
+                           break;
+                         if (count < 0)
+                           {
+                             /* Invalid or incomplete multibyte character.  */
+                             if (!(result == resultbuf || result == NULL))
+                               free (result);
+                             if (buf_malloced != NULL)
+                               free (buf_malloced);
+                             CLEANUP ();
+                             errno = EILSEQ;
+                             return NULL;
+                           }
+                         arg_end += count;
+                         characters++;
+                       }
+                   }
+                 else
+                   {
+                     /* Use the entire string.  */
+                     arg_end = arg + strlen (arg);
+                     /* The number of characters doesn't matter.  */
+                     characters = 0;
+                   }
+
+                 if (has_width && width > characters
+                     && !(dp->flags & FLAG_LEFT))
+                   {
+                     size_t n = width - characters;
+                     ENSURE_ALLOCATION (xsum (length, n));
+                     DCHAR_SET (result + length, ' ', n);
+                     length += n;
+                   }
+
+                 if (has_precision || has_width)
+                   {
+                     /* We know the number of wide characters in advance.  */
+                     size_t remaining;
+#  if HAVE_MBRTOWC
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#  endif
+                     ENSURE_ALLOCATION (xsum (length, characters));
+                     for (remaining = characters; remaining > 0; remaining--)
+                       {
+                         wchar_t wc;
+                         int count;
+#  if HAVE_MBRTOWC
+                         count = mbrtowc (&wc, arg, arg_end - arg, &state);
+#  else
+                         count = mbtowc (&wc, arg, arg_end - arg);
+#  endif
+                         if (count <= 0)
+                           /* mbrtowc not consistent with mbrlen, or mbtowc
+                              not consistent with mblen.  */
+                           abort ();
+                         result[length++] = wc;
+                         arg += count;
+                       }
+                     if (!(arg == arg_end))
+                       abort ();
+                   }
+                 else
+                   {
+#  if HAVE_MBRTOWC
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#  endif
+                     while (arg < arg_end)
+                       {
+                         wchar_t wc;
+                         int count;
+#  if HAVE_MBRTOWC
+                         count = mbrtowc (&wc, arg, arg_end - arg, &state);
+#  else
+                         count = mbtowc (&wc, arg, arg_end - arg);
+#  endif
+                         if (count <= 0)
+                           /* mbrtowc not consistent with mbrlen, or mbtowc
+                              not consistent with mblen.  */
+                           abort ();
+                         ENSURE_ALLOCATION (xsum (length, 1));
+                         result[length++] = wc;
+                         arg += count;
+                       }
+                   }
+
+                 if (has_width && width > characters
+                     && (dp->flags & FLAG_LEFT))
+                   {
+                     size_t n = width - characters;
+                     ENSURE_ALLOCATION (xsum (length, n));
+                     DCHAR_SET (result + length, ' ', n);
+                     length += n;
+                   }
+               }
+# else
+               /* %ls in vasnprintf.  See the specification of fprintf.  */
+               {
+                 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
+                 const wchar_t *arg_end;
+                 size_t characters;
+#  if !DCHAR_IS_TCHAR
+                 /* This code assumes that TCHAR_T is 'char'.  */
+                 typedef int TCHAR_T_verify[2 * (sizeof (TCHAR_T) == 1) - 1];
+                 TCHAR_T *tmpsrc;
+                 DCHAR_T *tmpdst;
+                 size_t tmpdst_len;
+#  endif
+                 size_t w;
+
+                 if (has_precision)
+                   {
+                     /* Use only as many wide characters as needed to produce
+                        at most PRECISION bytes, from the left.  */
+#  if HAVE_WCRTOMB
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#  endif
+                     arg_end = arg;
+                     characters = 0;
+                     while (precision > 0)
+                       {
+                         char buf[64]; /* Assume MB_CUR_MAX <= 64.  */
+                         int count;
+
+                         if (*arg_end == 0)
+                           /* Found the terminating null wide character.  */
+                           break;
+#  if HAVE_WCRTOMB
+                         count = wcrtomb (buf, *arg_end, &state);
+#  else
+                         count = wctomb (buf, *arg_end);
+#  endif
+                         if (count < 0)
+                           {
+                             /* Cannot convert.  */
+                             if (!(result == resultbuf || result == NULL))
+                               free (result);
+                             if (buf_malloced != NULL)
+                               free (buf_malloced);
+                             CLEANUP ();
+                             errno = EILSEQ;
+                             return NULL;
+                           }
+                         if (precision < count)
+                           break;
+                         arg_end++;
+                         characters += count;
+                         precision -= count;
+                       }
+                   }
+#  if DCHAR_IS_TCHAR
+                 else if (has_width)
+#  else
+                 else
+#  endif
+                   {
+                     /* Use the entire string, and count the number of
+                        bytes.  */
+#  if HAVE_WCRTOMB
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#  endif
+                     arg_end = arg;
+                     characters = 0;
+                     for (;;)
+                       {
+                         char buf[64]; /* Assume MB_CUR_MAX <= 64.  */
+                         int count;
+
+                         if (*arg_end == 0)
+                           /* Found the terminating null wide character.  */
+                           break;
+#  if HAVE_WCRTOMB
+                         count = wcrtomb (buf, *arg_end, &state);
+#  else
+                         count = wctomb (buf, *arg_end);
+#  endif
+                         if (count < 0)
+                           {
+                             /* Cannot convert.  */
+                             if (!(result == resultbuf || result == NULL))
+                               free (result);
+                             if (buf_malloced != NULL)
+                               free (buf_malloced);
+                             CLEANUP ();
+                             errno = EILSEQ;
+                             return NULL;
+                           }
+                         arg_end++;
+                         characters += count;
+                       }
+                   }
+#  if DCHAR_IS_TCHAR
+                 else
+                   {
+                     /* Use the entire string.  */
+                     arg_end = arg + local_wcslen (arg);
+                     /* The number of bytes doesn't matter.  */
+                     characters = 0;
+                   }
+#  endif
+
+#  if !DCHAR_IS_TCHAR
+                 /* Convert the string into a piece of temporary memory.  */
+                 tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T));
+                 if (tmpsrc == NULL)
+                   goto out_of_memory;
+                 {
+                   TCHAR_T *tmpptr = tmpsrc;
+                   size_t remaining;
+#   if HAVE_WCRTOMB
+                   mbstate_t state;
+                   memset (&state, '\0', sizeof (mbstate_t));
+#   endif
+                   for (remaining = characters; remaining > 0; )
+                     {
+                       char buf[64]; /* Assume MB_CUR_MAX <= 64.  */
+                       int count;
+
+                       if (*arg == 0)
+                         abort ();
+#   if HAVE_WCRTOMB
+                       count = wcrtomb (buf, *arg, &state);
+#   else
+                       count = wctomb (buf, *arg);
+#   endif
+                       if (count <= 0)
+                         /* Inconsistency.  */
+                         abort ();
+                       memcpy (tmpptr, buf, count);
+                       tmpptr += count;
+                       arg++;
+                       remaining -= count;
+                     }
+                   if (!(arg == arg_end))
+                     abort ();
+                 }
+
+                 /* Convert from TCHAR_T[] to DCHAR_T[].  */
+                 tmpdst =
+                   DCHAR_CONV_FROM_ENCODING (locale_charset (),
+                                             iconveh_question_mark,
+                                             tmpsrc, characters,
+                                             NULL,
+                                             NULL, &tmpdst_len);
+                 if (tmpdst == NULL)
+                   {
+                     int saved_errno = errno;
+                     free (tmpsrc);
+                     if (!(result == resultbuf || result == NULL))
+                       free (result);
+                     if (buf_malloced != NULL)
+                       free (buf_malloced);
+                     CLEANUP ();
+                     errno = saved_errno;
+                     return NULL;
+                   }
+                 free (tmpsrc);
+#  endif
+
+                 if (has_width)
+                   {
+#  if ENABLE_UNISTDIO
+                     /* Outside POSIX, it's preferrable to compare the width
+                        against the number of _characters_ of the converted
+                        value.  */
+                     w = DCHAR_MBSNLEN (result + length, characters);
+#  else
+                     /* The width is compared against the number of _bytes_
+                        of the converted value, says POSIX.  */
+                     w = characters;
+#  endif
+                   }
+                 else
+                   /* w doesn't matter.  */
+                   w = 0;
+
+                 if (has_width && width > w
+                     && !(dp->flags & FLAG_LEFT))
+                   {
+                     size_t n = width - w;
+                     ENSURE_ALLOCATION (xsum (length, n));
+                     DCHAR_SET (result + length, ' ', n);
+                     length += n;
+                   }
+
+#  if DCHAR_IS_TCHAR
+                 if (has_precision || has_width)
+                   {
+                     /* We know the number of bytes in advance.  */
+                     size_t remaining;
+#   if HAVE_WCRTOMB
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#   endif
+                     ENSURE_ALLOCATION (xsum (length, characters));
+                     for (remaining = characters; remaining > 0; )
+                       {
+                         char buf[64]; /* Assume MB_CUR_MAX <= 64.  */
+                         int count;
+
+                         if (*arg == 0)
+                           abort ();
+#   if HAVE_WCRTOMB
+                         count = wcrtomb (buf, *arg, &state);
+#   else
+                         count = wctomb (buf, *arg);
+#   endif
+                         if (count <= 0)
+                           /* Inconsistency.  */
+                           abort ();
+                         memcpy (result + length, buf, count);
+                         length += count;
+                         arg++;
+                         remaining -= count;
+                       }
+                     if (!(arg == arg_end))
+                       abort ();
+                   }
+                 else
+                   {
+#   if HAVE_WCRTOMB
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#   endif
+                     while (arg < arg_end)
+                       {
+                         char buf[64]; /* Assume MB_CUR_MAX <= 64.  */
+                         int count;
+
+                         if (*arg == 0)
+                           abort ();
+#   if HAVE_WCRTOMB
+                         count = wcrtomb (buf, *arg, &state);
+#   else
+                         count = wctomb (buf, *arg);
+#   endif
+                         if (count <= 0)
+                           /* Inconsistency.  */
+                           abort ();
+                         ENSURE_ALLOCATION (xsum (length, count));
+                         memcpy (result + length, buf, count);
+                         length += count;
+                         arg++;
+                       }
+                   }
+#  else
+                 ENSURE_ALLOCATION (xsum (length, tmpdst_len));
+                 DCHAR_CPY (result + length, tmpdst, tmpdst_len);
+                 free (tmpdst);
+                 length += tmpdst_len;
+#  endif
+
+                 if (has_width && width > w
+                     && (dp->flags & FLAG_LEFT))
+                   {
+                     size_t n = width - w;
+                     ENSURE_ALLOCATION (xsum (length, n));
+                     DCHAR_SET (result + length, ' ', n);
+                     length += n;
+                   }
+               }
+             }
+# endif
+#endif
+#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) 
&& !defined IN_LIBINTL
+           else if ((dp->conversion == 'a' || dp->conversion == 'A')
+# if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && 
NEED_PRINTF_DOUBLE))
+                    && (0
+#  if NEED_PRINTF_DOUBLE
+                        || a.arg[dp->arg_index].type == TYPE_DOUBLE
+#  endif
+#  if NEED_PRINTF_LONG_DOUBLE
+                        || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
+#  endif
+                       )
+# endif
+                   )
+             {
+               arg_type type = a.arg[dp->arg_index].type;
+               int flags = dp->flags;
+               int has_width;
+               size_t width;
+               int has_precision;
+               size_t precision;
+               size_t tmp_length;
+               DCHAR_T tmpbuf[700];
+               DCHAR_T *tmp;
+               DCHAR_T *pad_ptr;
+               DCHAR_T *p;
+
+               has_width = 0;
+               width = 0;
+               if (dp->width_start != dp->width_end)
+                 {
+                   if (dp->width_arg_index != ARG_NONE)
+                     {
+                       int arg;
+
+                       if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+                         abort ();
+                       arg = a.arg[dp->width_arg_index].a.a_int;
+                       if (arg < 0)
+                         {
+                           /* "A negative field width is taken as a '-' flag
+                               followed by a positive field width."  */
+                           flags |= FLAG_LEFT;
+                           width = (unsigned int) (-arg);
+                         }
+                       else
+                         width = arg;
+                     }
+                   else
+                     {
+                       const FCHAR_T *digitp = dp->width_start;
+
+                       do
+                         width = xsum (xtimes (width, 10), *digitp++ - '0');
+                       while (digitp != dp->width_end);
+                     }
+                   has_width = 1;
+                 }
+
+               has_precision = 0;
+               precision = 0;
+               if (dp->precision_start != dp->precision_end)
+                 {
+                   if (dp->precision_arg_index != ARG_NONE)
+                     {
+                       int arg;
+
+                       if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+                         abort ();
+                       arg = a.arg[dp->precision_arg_index].a.a_int;
+                       /* "A negative precision is taken as if the precision
+                           were omitted."  */
+                       if (arg >= 0)
+                         {
+                           precision = arg;
+                           has_precision = 1;
+                         }
+                     }
+                   else
+                     {
+                       const FCHAR_T *digitp = dp->precision_start + 1;
+
+                       precision = 0;
+                       while (digitp != dp->precision_end)
+                         precision = xsum (xtimes (precision, 10), *digitp++ - 
'0');
+                       has_precision = 1;
+                     }
+                 }
+
+               /* Allocate a temporary buffer of sufficient size.  */
+               if (type == TYPE_LONGDOUBLE)
+                 tmp_length =
+                   (unsigned int) ((LDBL_DIG + 1)
+                                   * 0.831 /* decimal -> hexadecimal */
+                                  )
+                   + 1; /* turn floor into ceil */
+               else
+                 tmp_length =
+                   (unsigned int) ((DBL_DIG + 1)
+                                   * 0.831 /* decimal -> hexadecimal */
+                                  )
+                   + 1; /* turn floor into ceil */
+               if (tmp_length < precision)
+                 tmp_length = precision;
+               /* Account for sign, decimal point etc. */
+               tmp_length = xsum (tmp_length, 12);
+
+               if (tmp_length < width)
+                 tmp_length = width;
+
+               tmp_length = xsum (tmp_length, 1); /* account for trailing NUL 
*/
+
+               if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
+                 tmp = tmpbuf;
+               else
+                 {
+                   size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
+
+                   if (size_overflow_p (tmp_memsize))
+                     /* Overflow, would lead to out of memory.  */
+                     goto out_of_memory;
+                   tmp = (DCHAR_T *) malloc (tmp_memsize);
+                   if (tmp == NULL)
+                     /* Out of memory.  */
+                     goto out_of_memory;
+                 }
+
+               pad_ptr = NULL;
+               p = tmp;
+               if (type == TYPE_LONGDOUBLE)
+                 {
+# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE
+                   long double arg = a.arg[dp->arg_index].a.a_longdouble;
+
+                   if (isnanl (arg))
+                     {
+                       if (dp->conversion == 'A')
+                         {
+                           *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
+                         }
+                       else
+                         {
+                           *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
+                         }
+                     }
+                   else
+                     {
+                       int sign = 0;
+                       DECL_LONG_DOUBLE_ROUNDING
+
+                       BEGIN_LONG_DOUBLE_ROUNDING ();
+
+                       if (signbit (arg)) /* arg < 0.0L or negative zero */
+                         {
+                           sign = -1;
+                           arg = -arg;
+                         }
+
+                       if (sign < 0)
+                         *p++ = '-';
+                       else if (flags & FLAG_SHOWSIGN)
+                         *p++ = '+';
+                       else if (flags & FLAG_SPACE)
+                         *p++ = ' ';
+
+                       if (arg > 0.0L && arg + arg == arg)
+                         {
+                           if (dp->conversion == 'A')
+                             {
+                               *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
+                             }
+                           else
+                             {
+                               *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
+                             }
+                         }
+                       else
+                         {
+                           int exponent;
+                           long double mantissa;
+
+                           if (arg > 0.0L)
+                             mantissa = printf_frexpl (arg, &exponent);
+                           else
+                             {
+                               exponent = 0;
+                               mantissa = 0.0L;
+                             }
+
+                           if (has_precision
+                               && precision < (unsigned int) ((LDBL_DIG + 1) * 
0.831) + 1)
+                             {
+                               /* Round the mantissa.  */
+                               long double tail = mantissa;
+                               size_t q;
+
+                               for (q = precision; ; q--)
+                                 {
+                                   int digit = (int) tail;
+                                   tail -= digit;
+                                   if (q == 0)
+                                     {
+                                       if (digit & 1 ? tail >= 0.5L : tail > 
0.5L)
+                                         tail = 1 - tail;
+                                       else
+                                         tail = - tail;
+                                       break;
+                                     }
+                                   tail *= 16.0L;
+                                 }
+                               if (tail != 0.0L)
+                                 for (q = precision; q > 0; q--)
+                                   tail *= 0.0625L;
+                               mantissa += tail;
+                             }
+
+                           *p++ = '0';
+                           *p++ = dp->conversion - 'A' + 'X';
+                           pad_ptr = p;
+                           {
+                             int digit;
+
+                             digit = (int) mantissa;
+                             mantissa -= digit;
+                             *p++ = '0' + digit;
+                             if ((flags & FLAG_ALT)
+                                 || mantissa > 0.0L || precision > 0)
+                               {
+                                 *p++ = decimal_point_char ();
+                                 /* This loop terminates because we assume
+                                    that FLT_RADIX is a power of 2.  */
+                                 while (mantissa > 0.0L)
+                                   {
+                                     mantissa *= 16.0L;
+                                     digit = (int) mantissa;
+                                     mantissa -= digit;
+                                     *p++ = digit
+                                            + (digit < 10
+                                               ? '0'
+                                               : dp->conversion - 10);
+                                     if (precision > 0)
+                                       precision--;
+                                   }
+                                 while (precision > 0)
+                                   {
+                                     *p++ = '0';
+                                     precision--;
+                                   }
+                               }
+                             }
+                             *p++ = dp->conversion - 'A' + 'P';
+#  if WIDE_CHAR_VERSION
+                             {
+                               static const wchar_t decimal_format[] =
+                                 { '%', '+', 'd', '\0' };
+                               SNPRINTF (p, 6 + 1, decimal_format, exponent);
+                             }
+                             while (*p != '\0')
+                               p++;
+#  else
+                             if (sizeof (DCHAR_T) == 1)
+                               {
+                                 sprintf ((char *) p, "%+d", exponent);
+                                 while (*p != '\0')
+                                   p++;
+                               }
+                             else
+                               {
+                                 char expbuf[6 + 1];
+                                 const char *ep;
+                                 sprintf (expbuf, "%+d", exponent);
+                                 for (ep = expbuf; (*p = *ep) != '\0'; ep++)
+                                   p++;
+                               }
+#  endif
+                         }
+
+                       END_LONG_DOUBLE_ROUNDING ();
+                     }
+# else
+                   abort ();
+# endif
+                 }
+               else
+                 {
+# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE
+                   double arg = a.arg[dp->arg_index].a.a_double;
+
+                   if (isnand (arg))
+                     {
+                       if (dp->conversion == 'A')
+                         {
+                           *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
+                         }
+                       else
+                         {
+                           *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
+                         }
+                     }
+                   else
+                     {
+                       int sign = 0;
+
+                       if (signbit (arg)) /* arg < 0.0 or negative zero */
+                         {
+                           sign = -1;
+                           arg = -arg;
+                         }
+
+                       if (sign < 0)
+                         *p++ = '-';
+                       else if (flags & FLAG_SHOWSIGN)
+                         *p++ = '+';
+                       else if (flags & FLAG_SPACE)
+                         *p++ = ' ';
+
+                       if (arg > 0.0 && arg + arg == arg)
+                         {
+                           if (dp->conversion == 'A')
+                             {
+                               *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
+                             }
+                           else
+                             {
+                               *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
+                             }
+                         }
+                       else
+                         {
+                           int exponent;
+                           double mantissa;
+
+                           if (arg > 0.0)
+                             mantissa = printf_frexp (arg, &exponent);
+                           else
+                             {
+                               exponent = 0;
+                               mantissa = 0.0;
+                             }
+
+                           if (has_precision
+                               && precision < (unsigned int) ((DBL_DIG + 1) * 
0.831) + 1)
+                             {
+                               /* Round the mantissa.  */
+                               double tail = mantissa;
+                               size_t q;
+
+                               for (q = precision; ; q--)
+                                 {
+                                   int digit = (int) tail;
+                                   tail -= digit;
+                                   if (q == 0)
+                                     {
+                                       if (digit & 1 ? tail >= 0.5 : tail > 
0.5)
+                                         tail = 1 - tail;
+                                       else
+                                         tail = - tail;
+                                       break;
+                                     }
+                                   tail *= 16.0;
+                                 }
+                               if (tail != 0.0)
+                                 for (q = precision; q > 0; q--)
+                                   tail *= 0.0625;
+                               mantissa += tail;
+                             }
+
+                           *p++ = '0';
+                           *p++ = dp->conversion - 'A' + 'X';
+                           pad_ptr = p;
+                           {
+                             int digit;
+
+                             digit = (int) mantissa;
+                             mantissa -= digit;
+                             *p++ = '0' + digit;
+                             if ((flags & FLAG_ALT)
+                                 || mantissa > 0.0 || precision > 0)
+                               {
+                                 *p++ = decimal_point_char ();
+                                 /* This loop terminates because we assume
+                                    that FLT_RADIX is a power of 2.  */
+                                 while (mantissa > 0.0)
+                                   {
+                                     mantissa *= 16.0;
+                                     digit = (int) mantissa;
+                                     mantissa -= digit;
+                                     *p++ = digit
+                                            + (digit < 10
+                                               ? '0'
+                                               : dp->conversion - 10);
+                                     if (precision > 0)
+                                       precision--;
+                                   }
+                                 while (precision > 0)
+                                   {
+                                     *p++ = '0';
+                                     precision--;
+                                   }
+                               }
+                             }
+                             *p++ = dp->conversion - 'A' + 'P';
+#  if WIDE_CHAR_VERSION
+                             {
+                               static const wchar_t decimal_format[] =
+                                 { '%', '+', 'd', '\0' };
+                               SNPRINTF (p, 6 + 1, decimal_format, exponent);
+                             }
+                             while (*p != '\0')
+                               p++;
+#  else
+                             if (sizeof (DCHAR_T) == 1)
+                               {
+                                 sprintf ((char *) p, "%+d", exponent);
+                                 while (*p != '\0')
+                                   p++;
+                               }
+                             else
+                               {
+                                 char expbuf[6 + 1];
+                                 const char *ep;
+                                 sprintf (expbuf, "%+d", exponent);
+                                 for (ep = expbuf; (*p = *ep) != '\0'; ep++)
+                                   p++;
+                               }
+#  endif
+                         }
+                     }
+# else
+                   abort ();
+# endif
+                 }
+               /* The generated string now extends from tmp to p, with the
+                  zero padding insertion point being at pad_ptr.  */
+               if (has_width && p - tmp < width)
+                 {
+                   size_t pad = width - (p - tmp);
+                   DCHAR_T *end = p + pad;
+
+                   if (flags & FLAG_LEFT)
+                     {
+                       /* Pad with spaces on the right.  */
+                       for (; pad > 0; pad--)
+                         *p++ = ' ';
+                     }
+                   else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
+                     {
+                       /* Pad with zeroes.  */
+                       DCHAR_T *q = end;
+
+                       while (p > pad_ptr)
+                         *--q = *--p;
+                       for (; pad > 0; pad--)
+                         *p++ = '0';
+                     }
+                   else
+                     {
+                       /* Pad with spaces on the left.  */
+                       DCHAR_T *q = end;
+
+                       while (p > tmp)
+                         *--q = *--p;
+                       for (; pad > 0; pad--)
+                         *p++ = ' ';
+                     }
+
+                   p = end;
+                 }
+
+               {
+                 size_t count = p - tmp;
+
+                 if (count >= tmp_length)
+                   /* tmp_length was incorrectly calculated - fix the
+                      code above!  */
+                   abort ();
+
+                 /* Make room for the result.  */
+                 if (count >= allocated - length)
+                   {
+                     size_t n = xsum (length, count);
+
+                     ENSURE_ALLOCATION (n);
+                   }
+
+                 /* Append the result.  */
+                 memcpy (result + length, tmp, count * sizeof (DCHAR_T));
+                 if (tmp != tmpbuf)
+                   free (tmp);
+                 length += count;
+               }
+             }
+#endif
+#if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_DOUBLE || 
NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined 
IN_LIBINTL
+           else if ((dp->conversion == 'f' || dp->conversion == 'F'
+                     || dp->conversion == 'e' || dp->conversion == 'E'
+                     || dp->conversion == 'g' || dp->conversion == 'G'
+                     || dp->conversion == 'a' || dp->conversion == 'A')
+                    && (0
+# if NEED_PRINTF_DOUBLE
+                        || a.arg[dp->arg_index].type == TYPE_DOUBLE
+# elif NEED_PRINTF_INFINITE_DOUBLE
+                        || (a.arg[dp->arg_index].type == TYPE_DOUBLE
+                            /* The systems (mingw) which produce wrong output
+                               for Inf, -Inf, and NaN also do so for -0.0.
+                               Therefore we treat this case here as well.  */
+                            && is_infinite_or_zero 
(a.arg[dp->arg_index].a.a_double))
+# endif
+# if NEED_PRINTF_LONG_DOUBLE
+                        || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
+# elif NEED_PRINTF_INFINITE_LONG_DOUBLE
+                        || (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
+                            /* Some systems produce wrong output for Inf,
+                               -Inf, and NaN.  Some systems in this category
+                               (IRIX 5.3) also do so for -0.0.  Therefore we
+                               treat this case here as well.  */
+                            && is_infinite_or_zerol 
(a.arg[dp->arg_index].a.a_longdouble))
+# endif
+                       ))
+             {
+# if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && 
(NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE)
+               arg_type type = a.arg[dp->arg_index].type;
+# endif
+               int flags = dp->flags;
+               int has_width;
+               size_t width;
+               int has_precision;
+               size_t precision;
+               size_t tmp_length;
+               DCHAR_T tmpbuf[700];
+               DCHAR_T *tmp;
+               DCHAR_T *pad_ptr;
+               DCHAR_T *p;
+
+               has_width = 0;
+               width = 0;
+               if (dp->width_start != dp->width_end)
+                 {
+                   if (dp->width_arg_index != ARG_NONE)
+                     {
+                       int arg;
+
+                       if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+                         abort ();
+                       arg = a.arg[dp->width_arg_index].a.a_int;
+                       if (arg < 0)
+                         {
+                           /* "A negative field width is taken as a '-' flag
+                               followed by a positive field width."  */
+                           flags |= FLAG_LEFT;
+                           width = (unsigned int) (-arg);
+                         }
+                       else
+                         width = arg;
+                     }
+                   else
+                     {
+                       const FCHAR_T *digitp = dp->width_start;
+
+                       do
+                         width = xsum (xtimes (width, 10), *digitp++ - '0');
+                       while (digitp != dp->width_end);
+                     }
+                   has_width = 1;
+                 }
+
+               has_precision = 0;
+               precision = 0;
+               if (dp->precision_start != dp->precision_end)
+                 {
+                   if (dp->precision_arg_index != ARG_NONE)
+                     {
+                       int arg;
+
+                       if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+                         abort ();
+                       arg = a.arg[dp->precision_arg_index].a.a_int;
+                       /* "A negative precision is taken as if the precision
+                           were omitted."  */
+                       if (arg >= 0)
+                         {
+                           precision = arg;
+                           has_precision = 1;
+                         }
+                     }
+                   else
+                     {
+                       const FCHAR_T *digitp = dp->precision_start + 1;
+
+                       precision = 0;
+                       while (digitp != dp->precision_end)
+                         precision = xsum (xtimes (precision, 10), *digitp++ - 
'0');
+                       has_precision = 1;
+                     }
+                 }
+
+               /* POSIX specifies the default precision to be 6 for %f, %F,
+                  %e, %E, but not for %g, %G.  Implementations appear to use
+                  the same default precision also for %g, %G.  But for %a, %A,
+                  the default precision is 0.  */
+               if (!has_precision)
+                 if (!(dp->conversion == 'a' || dp->conversion == 'A'))
+                   precision = 6;
+
+               /* Allocate a temporary buffer of sufficient size.  */
+# if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE
+               tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : DBL_DIG 
+ 1);
+# elif NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE
+               tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : 0);
+# elif NEED_PRINTF_LONG_DOUBLE
+               tmp_length = LDBL_DIG + 1;
+# elif NEED_PRINTF_DOUBLE
+               tmp_length = DBL_DIG + 1;
+# else
+               tmp_length = 0;
+# endif
+               if (tmp_length < precision)
+                 tmp_length = precision;
+# if NEED_PRINTF_LONG_DOUBLE
+#  if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
+               if (type == TYPE_LONGDOUBLE)
+#  endif
+                 if (dp->conversion == 'f' || dp->conversion == 'F')
+                   {
+                     long double arg = a.arg[dp->arg_index].a.a_longdouble;
+                     if (!(isnanl (arg) || arg + arg == arg))
+                       {
+                         /* arg is finite and nonzero.  */
+                         int exponent = floorlog10l (arg < 0 ? -arg : arg);
+                         if (exponent >= 0 && tmp_length < exponent + 
precision)
+                           tmp_length = exponent + precision;
+                       }
+                   }
+# endif
+# if NEED_PRINTF_DOUBLE
+#  if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
+               if (type == TYPE_DOUBLE)
+#  endif
+                 if (dp->conversion == 'f' || dp->conversion == 'F')
+                   {
+                     double arg = a.arg[dp->arg_index].a.a_double;
+                     if (!(isnand (arg) || arg + arg == arg))
+                       {
+                         /* arg is finite and nonzero.  */
+                         int exponent = floorlog10 (arg < 0 ? -arg : arg);
+                         if (exponent >= 0 && tmp_length < exponent + 
precision)
+                           tmp_length = exponent + precision;
+                       }
+                   }
+# endif
+               /* Account for sign, decimal point etc. */
+               tmp_length = xsum (tmp_length, 12);
+
+               if (tmp_length < width)
+                 tmp_length = width;
+
+               tmp_length = xsum (tmp_length, 1); /* account for trailing NUL 
*/
+
+               if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
+                 tmp = tmpbuf;
+               else
+                 {
+                   size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
+
+                   if (size_overflow_p (tmp_memsize))
+                     /* Overflow, would lead to out of memory.  */
+                     goto out_of_memory;
+                   tmp = (DCHAR_T *) malloc (tmp_memsize);
+                   if (tmp == NULL)
+                     /* Out of memory.  */
+                     goto out_of_memory;
+                 }
+
+               pad_ptr = NULL;
+               p = tmp;
+
+# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
+#  if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
+               if (type == TYPE_LONGDOUBLE)
+#  endif
+                 {
+                   long double arg = a.arg[dp->arg_index].a.a_longdouble;
+
+                   if (isnanl (arg))
+                     {
+                       if (dp->conversion >= 'A' && dp->conversion <= 'Z')
+                         {
+                           *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
+                         }
+                       else
+                         {
+                           *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
+                         }
+                     }
+                   else
+                     {
+                       int sign = 0;
+                       DECL_LONG_DOUBLE_ROUNDING
+
+                       BEGIN_LONG_DOUBLE_ROUNDING ();
+
+                       if (signbit (arg)) /* arg < 0.0L or negative zero */
+                         {
+                           sign = -1;
+                           arg = -arg;
+                         }
+
+                       if (sign < 0)
+                         *p++ = '-';
+                       else if (flags & FLAG_SHOWSIGN)
+                         *p++ = '+';
+                       else if (flags & FLAG_SPACE)
+                         *p++ = ' ';
+
+                       if (arg > 0.0L && arg + arg == arg)
+                         {
+                           if (dp->conversion >= 'A' && dp->conversion <= 'Z')
+                             {
+                               *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
+                             }
+                           else
+                             {
+                               *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
+                             }
+                         }
+                       else
+                         {
+#  if NEED_PRINTF_LONG_DOUBLE
+                           pad_ptr = p;
+
+                           if (dp->conversion == 'f' || dp->conversion == 'F')
+                             {
+                               char *digits;
+                               size_t ndigits;
+
+                               digits =
+                                 scale10_round_decimal_long_double (arg, 
precision);
+                               if (digits == NULL)
+                                 {
+                                   END_LONG_DOUBLE_ROUNDING ();
+                                   goto out_of_memory;
+                                 }
+                               ndigits = strlen (digits);
+
+                               if (ndigits > precision)
+                                 do
+                                   {
+                                     --ndigits;
+                                     *p++ = digits[ndigits];
+                                   }
+                                 while (ndigits > precision);
+                               else
+                                 *p++ = '0';
+                               /* Here ndigits <= precision.  */
+                               if ((flags & FLAG_ALT) || precision > 0)
+                                 {
+                                   *p++ = decimal_point_char ();
+                                   for (; precision > ndigits; precision--)
+                                     *p++ = '0';
+                                   while (ndigits > 0)
+                                     {
+                                       --ndigits;
+                                       *p++ = digits[ndigits];
+                                     }
+                                 }
+
+                               free (digits);
+                             }
+                           else if (dp->conversion == 'e' || dp->conversion == 
'E')
+                             {
+                               int exponent;
+
+                               if (arg == 0.0L)
+                                 {
+                                   exponent = 0;
+                                   *p++ = '0';
+                                   if ((flags & FLAG_ALT) || precision > 0)
+                                     {
+                                       *p++ = decimal_point_char ();
+                                       for (; precision > 0; precision--)
+                                         *p++ = '0';
+                                     }
+                                 }
+                               else
+                                 {
+                                   /* arg > 0.0L.  */
+                                   int adjusted;
+                                   char *digits;
+                                   size_t ndigits;
+
+                                   exponent = floorlog10l (arg);
+                                   adjusted = 0;
+                                   for (;;)
+                                     {
+                                       digits =
+                                         scale10_round_decimal_long_double 
(arg,
+                                                                            
(int)precision - exponent);
+                                       if (digits == NULL)
+                                         {
+                                           END_LONG_DOUBLE_ROUNDING ();
+                                           goto out_of_memory;
+                                         }
+                                       ndigits = strlen (digits);
+
+                                       if (ndigits == precision + 1)
+                                         break;
+                                       if (ndigits < precision
+                                           || ndigits > precision + 2)
+                                         /* The exponent was not guessed
+                                            precisely enough.  */
+                                         abort ();
+                                       if (adjusted)
+                                         /* None of two values of exponent is
+                                            the right one.  Prevent an endless
+                                            loop.  */
+                                         abort ();
+                                       free (digits);
+                                       if (ndigits == precision)
+                                         exponent -= 1;
+                                       else
+                                         exponent += 1;
+                                       adjusted = 1;
+                                     }
+                                   /* Here ndigits = precision+1.  */
+                                   if (is_borderline (digits, precision))
+                                     {
+                                       /* Maybe the exponent guess was too high
+                                          and a smaller exponent can be reached
+                                          by turning a 10...0 into 9...9x.  */
+                                       char *digits2 =
+                                         scale10_round_decimal_long_double 
(arg,
+                                                                            
(int)precision - exponent + 1);
+                                       if (digits2 == NULL)
+                                         {
+                                           free (digits);
+                                           END_LONG_DOUBLE_ROUNDING ();
+                                           goto out_of_memory;
+                                         }
+                                       if (strlen (digits2) == precision + 1)
+                                         {
+                                           free (digits);
+                                           digits = digits2;
+                                           exponent -= 1;
+                                         }
+                                       else
+                                         free (digits2);
+                                     }
+                                   /* Here ndigits = precision+1.  */
+
+                                   *p++ = digits[--ndigits];
+                                   if ((flags & FLAG_ALT) || precision > 0)
+                                     {
+                                       *p++ = decimal_point_char ();
+                                       while (ndigits > 0)
+                                         {
+                                           --ndigits;
+                                           *p++ = digits[ndigits];
+                                         }
+                                     }
+
+                                   free (digits);
+                                 }
+
+                               *p++ = dp->conversion; /* 'e' or 'E' */
+#   if WIDE_CHAR_VERSION
+                               {
+                                 static const wchar_t decimal_format[] =
+                                   { '%', '+', '.', '2', 'd', '\0' };
+                                 SNPRINTF (p, 6 + 1, decimal_format, exponent);
+                               }
+                               while (*p != '\0')
+                                 p++;
+#   else
+                               if (sizeof (DCHAR_T) == 1)
+                                 {
+                                   sprintf ((char *) p, "%+.2d", exponent);
+                                   while (*p != '\0')
+                                     p++;
+                                 }
+                               else
+                                 {
+                                   char expbuf[6 + 1];
+                                   const char *ep;
+                                   sprintf (expbuf, "%+.2d", exponent);
+                                   for (ep = expbuf; (*p = *ep) != '\0'; ep++)
+                                     p++;
+                                 }
+#   endif
+                             }
+                           else if (dp->conversion == 'g' || dp->conversion == 
'G')
+                             {
+                               if (precision == 0)
+                                 precision = 1;
+                               /* precision >= 1.  */
+
+                               if (arg == 0.0L)
+                                 /* The exponent is 0, >= -4, < precision.
+                                    Use fixed-point notation.  */
+                                 {
+                                   size_t ndigits = precision;
+                                   /* Number of trailing zeroes that have to be
+                                      dropped.  */
+                                   size_t nzeroes =
+                                     (flags & FLAG_ALT ? 0 : precision - 1);
+
+                                   --ndigits;
+                                   *p++ = '0';
+                                   if ((flags & FLAG_ALT) || ndigits > nzeroes)
+                                     {
+                                       *p++ = decimal_point_char ();
+                                       while (ndigits > nzeroes)
+                                         {
+                                           --ndigits;
+                                           *p++ = '0';
+                                         }
+                                     }
+                                 }
+                               else
+                                 {
+                                   /* arg > 0.0L.  */
+                                   int exponent;
+                                   int adjusted;
+                                   char *digits;
+                                   size_t ndigits;
+                                   size_t nzeroes;
+
+                                   exponent = floorlog10l (arg);
+                                   adjusted = 0;
+                                   for (;;)
+                                     {
+                                       digits =
+                                         scale10_round_decimal_long_double 
(arg,
+                                                                            
(int)(precision - 1) - exponent);
+                                       if (digits == NULL)
+                                         {
+                                           END_LONG_DOUBLE_ROUNDING ();
+                                           goto out_of_memory;
+                                         }
+                                       ndigits = strlen (digits);
+
+                                       if (ndigits == precision)
+                                         break;
+                                       if (ndigits < precision - 1
+                                           || ndigits > precision + 1)
+                                         /* The exponent was not guessed
+                                            precisely enough.  */
+                                         abort ();
+                                       if (adjusted)
+                                         /* None of two values of exponent is
+                                            the right one.  Prevent an endless
+                                            loop.  */
+                                         abort ();
+                                       free (digits);
+                                       if (ndigits < precision)
+                                         exponent -= 1;
+                                       else
+                                         exponent += 1;
+                                       adjusted = 1;
+                                     }
+                                   /* Here ndigits = precision.  */
+                                   if (is_borderline (digits, precision - 1))
+                                     {
+                                       /* Maybe the exponent guess was too high
+                                          and a smaller exponent can be reached
+                                          by turning a 10...0 into 9...9x.  */
+                                       char *digits2 =
+                                         scale10_round_decimal_long_double 
(arg,
+                                                                            
(int)(precision - 1) - exponent + 1);
+                                       if (digits2 == NULL)
+                                         {
+                                           free (digits);
+                                           END_LONG_DOUBLE_ROUNDING ();
+                                           goto out_of_memory;
+                                         }
+                                       if (strlen (digits2) == precision)
+                                         {
+                                           free (digits);
+                                           digits = digits2;
+                                           exponent -= 1;
+                                         }
+                                       else
+                                         free (digits2);
+                                     }
+                                   /* Here ndigits = precision.  */
+
+                                   /* Determine the number of trailing zeroes
+                                      that have to be dropped.  */
+                                   nzeroes = 0;
+                                   if ((flags & FLAG_ALT) == 0)
+                                     while (nzeroes < ndigits
+                                            && digits[nzeroes] == '0')
+                                       nzeroes++;
+
+                                   /* The exponent is now determined.  */
+                                   if (exponent >= -4
+                                       && exponent < (long)precision)
+                                     {
+                                       /* Fixed-point notation:
+                                          max(exponent,0)+1 digits, then the
+                                          decimal point, then the remaining
+                                          digits without trailing zeroes.  */
+                                       if (exponent >= 0)
+                                         {
+                                           size_t count = exponent + 1;
+                                           /* Note: count <= precision = 
ndigits.  */
+                                           for (; count > 0; count--)
+                                             *p++ = digits[--ndigits];
+                                           if ((flags & FLAG_ALT) || ndigits > 
nzeroes)
+                                             {
+                                               *p++ = decimal_point_char ();
+                                               while (ndigits > nzeroes)
+                                                 {
+                                                   --ndigits;
+                                                   *p++ = digits[ndigits];
+                                                 }
+                                             }
+                                         }
+                                       else
+                                         {
+                                           size_t count = -exponent - 1;
+                                           *p++ = '0';
+                                           *p++ = decimal_point_char ();
+                                           for (; count > 0; count--)
+                                             *p++ = '0';
+                                           while (ndigits > nzeroes)
+                                             {
+                                               --ndigits;
+                                               *p++ = digits[ndigits];
+                                             }
+                                         }
+                                     }
+                                   else
+                                     {
+                                       /* Exponential notation.  */
+                                       *p++ = digits[--ndigits];
+                                       if ((flags & FLAG_ALT) || ndigits > 
nzeroes)
+                                         {
+                                           *p++ = decimal_point_char ();
+                                           while (ndigits > nzeroes)
+                                             {
+                                               --ndigits;
+                                               *p++ = digits[ndigits];
+                                             }
+                                         }
+                                       *p++ = dp->conversion - 'G' + 'E'; /* 
'e' or 'E' */
+#   if WIDE_CHAR_VERSION
+                                       {
+                                         static const wchar_t decimal_format[] 
=
+                                           { '%', '+', '.', '2', 'd', '\0' };
+                                         SNPRINTF (p, 6 + 1, decimal_format, 
exponent);
+                                       }
+                                       while (*p != '\0')
+                                         p++;
+#   else
+                                       if (sizeof (DCHAR_T) == 1)
+                                         {
+                                           sprintf ((char *) p, "%+.2d", 
exponent);
+                                           while (*p != '\0')
+                                             p++;
+                                         }
+                                       else
+                                         {
+                                           char expbuf[6 + 1];
+                                           const char *ep;
+                                           sprintf (expbuf, "%+.2d", exponent);
+                                           for (ep = expbuf; (*p = *ep) != 
'\0'; ep++)
+                                             p++;
+                                         }
+#   endif
+                                     }
+
+                                   free (digits);
+                                 }
+                             }
+                           else
+                             abort ();
+#  else
+                           /* arg is finite.  */
+                           if (!(arg == 0.0L))
+                             abort ();
+
+                           pad_ptr = p;
+
+                           if (dp->conversion == 'f' || dp->conversion == 'F')
+                             {
+                               *p++ = '0';
+                               if ((flags & FLAG_ALT) || precision > 0)
+                                 {
+                                   *p++ = decimal_point_char ();
+                                   for (; precision > 0; precision--)
+                                     *p++ = '0';
+                                 }
+                             }
+                           else if (dp->conversion == 'e' || dp->conversion == 
'E')
+                             {
+                               *p++ = '0';
+                               if ((flags & FLAG_ALT) || precision > 0)
+                                 {
+                                   *p++ = decimal_point_char ();
+                                   for (; precision > 0; precision--)
+                                     *p++ = '0';
+                                 }
+                               *p++ = dp->conversion; /* 'e' or 'E' */
+                               *p++ = '+';
+                               *p++ = '0';
+                               *p++ = '0';
+                             }
+                           else if (dp->conversion == 'g' || dp->conversion == 
'G')
+                             {
+                               *p++ = '0';
+                               if (flags & FLAG_ALT)
+                                 {
+                                   size_t ndigits =
+                                     (precision > 0 ? precision - 1 : 0);
+                                   *p++ = decimal_point_char ();
+                                   for (; ndigits > 0; --ndigits)
+                                     *p++ = '0';
+                                 }
+                             }
+                           else if (dp->conversion == 'a' || dp->conversion == 
'A')
+                             {
+                               *p++ = '0';
+                               *p++ = dp->conversion - 'A' + 'X';
+                               pad_ptr = p;
+                               *p++ = '0';
+                               if ((flags & FLAG_ALT) || precision > 0)
+                                 {
+                                   *p++ = decimal_point_char ();
+                                   for (; precision > 0; precision--)
+                                     *p++ = '0';
+                                 }
+                               *p++ = dp->conversion - 'A' + 'P';
+                               *p++ = '+';
+                               *p++ = '0';
+                             }
+                           else
+                             abort ();
+#  endif
+                         }
+
+                       END_LONG_DOUBLE_ROUNDING ();
+                     }
+                 }
+#  if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
+               else
+#  endif
+# endif
+# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
+                 {
+                   double arg = a.arg[dp->arg_index].a.a_double;
+
+                   if (isnand (arg))
+                     {
+                       if (dp->conversion >= 'A' && dp->conversion <= 'Z')
+                         {
+                           *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
+                         }
+                       else
+                         {
+                           *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
+                         }
+                     }
+                   else
+                     {
+                       int sign = 0;
+
+                       if (signbit (arg)) /* arg < 0.0 or negative zero */
+                         {
+                           sign = -1;
+                           arg = -arg;
+                         }
+
+                       if (sign < 0)
+                         *p++ = '-';
+                       else if (flags & FLAG_SHOWSIGN)
+                         *p++ = '+';
+                       else if (flags & FLAG_SPACE)
+                         *p++ = ' ';
+
+                       if (arg > 0.0 && arg + arg == arg)
+                         {
+                           if (dp->conversion >= 'A' && dp->conversion <= 'Z')
+                             {
+                               *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
+                             }
+                           else
+                             {
+                               *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
+                             }
+                         }
+                       else
+                         {
+#  if NEED_PRINTF_DOUBLE
+                           pad_ptr = p;
+
+                           if (dp->conversion == 'f' || dp->conversion == 'F')
+                             {
+                               char *digits;
+                               size_t ndigits;
+
+                               digits =
+                                 scale10_round_decimal_double (arg, precision);
+                               if (digits == NULL)
+                                 goto out_of_memory;
+                               ndigits = strlen (digits);
+
+                               if (ndigits > precision)
+                                 do
+                                   {
+                                     --ndigits;
+                                     *p++ = digits[ndigits];
+                                   }
+                                 while (ndigits > precision);
+                               else
+                                 *p++ = '0';
+                               /* Here ndigits <= precision.  */
+                               if ((flags & FLAG_ALT) || precision > 0)
+                                 {
+                                   *p++ = decimal_point_char ();
+                                   for (; precision > ndigits; precision--)
+                                     *p++ = '0';
+                                   while (ndigits > 0)
+                                     {
+                                       --ndigits;
+                                       *p++ = digits[ndigits];
+                                     }
+                                 }
+
+                               free (digits);
+                             }
+                           else if (dp->conversion == 'e' || dp->conversion == 
'E')
+                             {
+                               int exponent;
+
+                               if (arg == 0.0)
+                                 {
+                                   exponent = 0;
+                                   *p++ = '0';
+                                   if ((flags & FLAG_ALT) || precision > 0)
+                                     {
+                                       *p++ = decimal_point_char ();
+                                       for (; precision > 0; precision--)
+                                         *p++ = '0';
+                                     }
+                                 }
+                               else
+                                 {
+                                   /* arg > 0.0.  */
+                                   int adjusted;
+                                   char *digits;
+                                   size_t ndigits;
+
+                                   exponent = floorlog10 (arg);
+                                   adjusted = 0;
+                                   for (;;)
+                                     {
+                                       digits =
+                                         scale10_round_decimal_double (arg,
+                                                                       
(int)precision - exponent);
+                                       if (digits == NULL)
+                                         goto out_of_memory;
+                                       ndigits = strlen (digits);
+
+                                       if (ndigits == precision + 1)
+                                         break;
+                                       if (ndigits < precision
+                                           || ndigits > precision + 2)
+                                         /* The exponent was not guessed
+                                            precisely enough.  */
+                                         abort ();
+                                       if (adjusted)
+                                         /* None of two values of exponent is
+                                            the right one.  Prevent an endless
+                                            loop.  */
+                                         abort ();
+                                       free (digits);
+                                       if (ndigits == precision)
+                                         exponent -= 1;
+                                       else
+                                         exponent += 1;
+                                       adjusted = 1;
+                                     }
+                                   /* Here ndigits = precision+1.  */
+                                   if (is_borderline (digits, precision))
+                                     {
+                                       /* Maybe the exponent guess was too high
+                                          and a smaller exponent can be reached
+                                          by turning a 10...0 into 9...9x.  */
+                                       char *digits2 =
+                                         scale10_round_decimal_double (arg,
+                                                                       
(int)precision - exponent + 1);
+                                       if (digits2 == NULL)
+                                         {
+                                           free (digits);
+                                           goto out_of_memory;
+                                         }
+                                       if (strlen (digits2) == precision + 1)
+                                         {
+                                           free (digits);
+                                           digits = digits2;
+                                           exponent -= 1;
+                                         }
+                                       else
+                                         free (digits2);
+                                     }
+                                   /* Here ndigits = precision+1.  */
+
+                                   *p++ = digits[--ndigits];
+                                   if ((flags & FLAG_ALT) || precision > 0)
+                                     {
+                                       *p++ = decimal_point_char ();
+                                       while (ndigits > 0)
+                                         {
+                                           --ndigits;
+                                           *p++ = digits[ndigits];
+                                         }
+                                     }
+
+                                   free (digits);
+                                 }
+
+                               *p++ = dp->conversion; /* 'e' or 'E' */
+#   if WIDE_CHAR_VERSION
+                               {
+                                 static const wchar_t decimal_format[] =
+                                   /* Produce the same number of exponent 
digits
+                                      as the native printf implementation.  */
+#    if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+                                   { '%', '+', '.', '3', 'd', '\0' };
+#    else
+                                   { '%', '+', '.', '2', 'd', '\0' };
+#    endif
+                                 SNPRINTF (p, 6 + 1, decimal_format, exponent);
+                               }
+                               while (*p != '\0')
+                                 p++;
+#   else
+                               {
+                                 static const char decimal_format[] =
+                                   /* Produce the same number of exponent 
digits
+                                      as the native printf implementation.  */
+#    if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+                                   "%+.3d";
+#    else
+                                   "%+.2d";
+#    endif
+                                 if (sizeof (DCHAR_T) == 1)
+                                   {
+                                     sprintf ((char *) p, decimal_format, 
exponent);
+                                     while (*p != '\0')
+                                       p++;
+                                   }
+                                 else
+                                   {
+                                     char expbuf[6 + 1];
+                                     const char *ep;
+                                     sprintf (expbuf, decimal_format, 
exponent);
+                                     for (ep = expbuf; (*p = *ep) != '\0'; 
ep++)
+                                       p++;
+                                   }
+                               }
+#   endif
+                             }
+                           else if (dp->conversion == 'g' || dp->conversion == 
'G')
+                             {
+                               if (precision == 0)
+                                 precision = 1;
+                               /* precision >= 1.  */
+
+                               if (arg == 0.0)
+                                 /* The exponent is 0, >= -4, < precision.
+                                    Use fixed-point notation.  */
+                                 {
+                                   size_t ndigits = precision;
+                                   /* Number of trailing zeroes that have to be
+                                      dropped.  */
+                                   size_t nzeroes =
+                                     (flags & FLAG_ALT ? 0 : precision - 1);
+
+                                   --ndigits;
+                                   *p++ = '0';
+                                   if ((flags & FLAG_ALT) || ndigits > nzeroes)
+                                     {
+                                       *p++ = decimal_point_char ();
+                                       while (ndigits > nzeroes)
+                                         {
+                                           --ndigits;
+                                           *p++ = '0';
+                                         }
+                                     }
+                                 }
+                               else
+                                 {
+                                   /* arg > 0.0.  */
+                                   int exponent;
+                                   int adjusted;
+                                   char *digits;
+                                   size_t ndigits;
+                                   size_t nzeroes;
+
+                                   exponent = floorlog10 (arg);
+                                   adjusted = 0;
+                                   for (;;)
+                                     {
+                                       digits =
+                                         scale10_round_decimal_double (arg,
+                                                                       
(int)(precision - 1) - exponent);
+                                       if (digits == NULL)
+                                         goto out_of_memory;
+                                       ndigits = strlen (digits);
+
+                                       if (ndigits == precision)
+                                         break;
+                                       if (ndigits < precision - 1
+                                           || ndigits > precision + 1)
+                                         /* The exponent was not guessed
+                                            precisely enough.  */
+                                         abort ();
+                                       if (adjusted)
+                                         /* None of two values of exponent is
+                                            the right one.  Prevent an endless
+                                            loop.  */
+                                         abort ();
+                                       free (digits);
+                                       if (ndigits < precision)
+                                         exponent -= 1;
+                                       else
+                                         exponent += 1;
+                                       adjusted = 1;
+                                     }
+                                   /* Here ndigits = precision.  */
+                                   if (is_borderline (digits, precision - 1))
+                                     {
+                                       /* Maybe the exponent guess was too high
+                                          and a smaller exponent can be reached
+                                          by turning a 10...0 into 9...9x.  */
+                                       char *digits2 =
+                                         scale10_round_decimal_double (arg,
+                                                                       
(int)(precision - 1) - exponent + 1);
+                                       if (digits2 == NULL)
+                                         {
+                                           free (digits);
+                                           goto out_of_memory;
+                                         }
+                                       if (strlen (digits2) == precision)
+                                         {
+                                           free (digits);
+                                           digits = digits2;
+                                           exponent -= 1;
+                                         }
+                                       else
+                                         free (digits2);
+                                     }
+                                   /* Here ndigits = precision.  */
+
+                                   /* Determine the number of trailing zeroes
+                                      that have to be dropped.  */
+                                   nzeroes = 0;
+                                   if ((flags & FLAG_ALT) == 0)
+                                     while (nzeroes < ndigits
+                                            && digits[nzeroes] == '0')
+                                       nzeroes++;
+
+                                   /* The exponent is now determined.  */
+                                   if (exponent >= -4
+                                       && exponent < (long)precision)
+                                     {
+                                       /* Fixed-point notation:
+                                          max(exponent,0)+1 digits, then the
+                                          decimal point, then the remaining
+                                          digits without trailing zeroes.  */
+                                       if (exponent >= 0)
+                                         {
+                                           size_t count = exponent + 1;
+                                           /* Note: count <= precision = 
ndigits.  */
+                                           for (; count > 0; count--)
+                                             *p++ = digits[--ndigits];
+                                           if ((flags & FLAG_ALT) || ndigits > 
nzeroes)
+                                             {
+                                               *p++ = decimal_point_char ();
+                                               while (ndigits > nzeroes)
+                                                 {
+                                                   --ndigits;
+                                                   *p++ = digits[ndigits];
+                                                 }
+                                             }
+                                         }
+                                       else
+                                         {
+                                           size_t count = -exponent - 1;
+                                           *p++ = '0';
+                                           *p++ = decimal_point_char ();
+                                           for (; count > 0; count--)
+                                             *p++ = '0';
+                                           while (ndigits > nzeroes)
+                                             {
+                                               --ndigits;
+                                               *p++ = digits[ndigits];
+                                             }
+                                         }
+                                     }
+                                   else
+                                     {
+                                       /* Exponential notation.  */
+                                       *p++ = digits[--ndigits];
+                                       if ((flags & FLAG_ALT) || ndigits > 
nzeroes)
+                                         {
+                                           *p++ = decimal_point_char ();
+                                           while (ndigits > nzeroes)
+                                             {
+                                               --ndigits;
+                                               *p++ = digits[ndigits];
+                                             }
+                                         }
+                                       *p++ = dp->conversion - 'G' + 'E'; /* 
'e' or 'E' */
+#   if WIDE_CHAR_VERSION
+                                       {
+                                         static const wchar_t decimal_format[] 
=
+                                           /* Produce the same number of 
exponent digits
+                                              as the native printf 
implementation.  */
+#    if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+                                           { '%', '+', '.', '3', 'd', '\0' };
+#    else
+                                           { '%', '+', '.', '2', 'd', '\0' };
+#    endif
+                                         SNPRINTF (p, 6 + 1, decimal_format, 
exponent);
+                                       }
+                                       while (*p != '\0')
+                                         p++;
+#   else
+                                       {
+                                         static const char decimal_format[] =
+                                           /* Produce the same number of 
exponent digits
+                                              as the native printf 
implementation.  */
+#    if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+                                           "%+.3d";
+#    else
+                                           "%+.2d";
+#    endif
+                                         if (sizeof (DCHAR_T) == 1)
+                                           {
+                                             sprintf ((char *) p, 
decimal_format, exponent);
+                                             while (*p != '\0')
+                                               p++;
+                                           }
+                                         else
+                                           {
+                                             char expbuf[6 + 1];
+                                             const char *ep;
+                                             sprintf (expbuf, decimal_format, 
exponent);
+                                             for (ep = expbuf; (*p = *ep) != 
'\0'; ep++)
+                                               p++;
+                                           }
+                                       }
+#   endif
+                                     }
+
+                                   free (digits);
+                                 }
+                             }
+                           else
+                             abort ();
+#  else
+                           /* arg is finite.  */
+                           if (!(arg == 0.0))
+                             abort ();
+
+                           pad_ptr = p;
+
+                           if (dp->conversion == 'f' || dp->conversion == 'F')
+                             {
+                               *p++ = '0';
+                               if ((flags & FLAG_ALT) || precision > 0)
+                                 {
+                                   *p++ = decimal_point_char ();
+                                   for (; precision > 0; precision--)
+                                     *p++ = '0';
+                                 }
+                             }
+                           else if (dp->conversion == 'e' || dp->conversion == 
'E')
+                             {
+                               *p++ = '0';
+                               if ((flags & FLAG_ALT) || precision > 0)
+                                 {
+                                   *p++ = decimal_point_char ();
+                                   for (; precision > 0; precision--)
+                                     *p++ = '0';
+                                 }
+                               *p++ = dp->conversion; /* 'e' or 'E' */
+                               *p++ = '+';
+                               /* Produce the same number of exponent digits as
+                                  the native printf implementation.  */
+#   if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+                               *p++ = '0';
+#   endif
+                               *p++ = '0';
+                               *p++ = '0';
+                             }
+                           else if (dp->conversion == 'g' || dp->conversion == 
'G')
+                             {
+                               *p++ = '0';
+                               if (flags & FLAG_ALT)
+                                 {
+                                   size_t ndigits =
+                                     (precision > 0 ? precision - 1 : 0);
+                                   *p++ = decimal_point_char ();
+                                   for (; ndigits > 0; --ndigits)
+                                     *p++ = '0';
+                                 }
+                             }
+                           else
+                             abort ();
+#  endif
+                         }
+                     }
+                 }
+# endif
+
+               /* The generated string now extends from tmp to p, with the
+                  zero padding insertion point being at pad_ptr.  */
+               if (has_width && p - tmp < width)
+                 {
+                   size_t pad = width - (p - tmp);
+                   DCHAR_T *end = p + pad;
+
+                   if (flags & FLAG_LEFT)
+                     {
+                       /* Pad with spaces on the right.  */
+                       for (; pad > 0; pad--)
+                         *p++ = ' ';
+                     }
+                   else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
+                     {
+                       /* Pad with zeroes.  */
+                       DCHAR_T *q = end;
+
+                       while (p > pad_ptr)
+                         *--q = *--p;
+                       for (; pad > 0; pad--)
+                         *p++ = '0';
+                     }
+                   else
+                     {
+                       /* Pad with spaces on the left.  */
+                       DCHAR_T *q = end;
+
+                       while (p > tmp)
+                         *--q = *--p;
+                       for (; pad > 0; pad--)
+                         *p++ = ' ';
+                     }
+
+                   p = end;
+                 }
+
+               {
+                 size_t count = p - tmp;
+
+                 if (count >= tmp_length)
+                   /* tmp_length was incorrectly calculated - fix the
+                      code above!  */
+                   abort ();
+
+                 /* Make room for the result.  */
+                 if (count >= allocated - length)
+                   {
+                     size_t n = xsum (length, count);
+
+                     ENSURE_ALLOCATION (n);
+                   }
+
+                 /* Append the result.  */
+                 memcpy (result + length, tmp, count * sizeof (DCHAR_T));
+                 if (tmp != tmpbuf)
+                   free (tmp);
+                 length += count;
+               }
+             }
+#endif
+           else
+             {
+               arg_type type = a.arg[dp->arg_index].type;
+               int flags = dp->flags;
+#if !USE_SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || 
NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || 
NEED_PRINTF_UNBOUNDED_PRECISION
+               int has_width;
+               size_t width;
+#endif
+#if !USE_SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION
+               int has_precision;
+               size_t precision;
+#endif
+#if NEED_PRINTF_UNBOUNDED_PRECISION
+               int prec_ourselves;
+#else
+#              define prec_ourselves 0
+#endif
+#if NEED_PRINTF_FLAG_LEFTADJUST
+#              define pad_ourselves 1
+#elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || 
NEED_PRINTF_UNBOUNDED_PRECISION
+               int pad_ourselves;
+#else
+#              define pad_ourselves 0
+#endif
+               TCHAR_T *fbp;
+               unsigned int prefix_count;
+               int prefixes[2] IF_LINT (= { 0 });
+#if !USE_SNPRINTF
+               size_t tmp_length;
+               TCHAR_T tmpbuf[700];
+               TCHAR_T *tmp;
+#endif
+
+#if !USE_SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || 
NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || 
NEED_PRINTF_UNBOUNDED_PRECISION
+               has_width = 0;
+               width = 0;
+               if (dp->width_start != dp->width_end)
+                 {
+                   if (dp->width_arg_index != ARG_NONE)
+                     {
+                       int arg;
+
+                       if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+                         abort ();
+                       arg = a.arg[dp->width_arg_index].a.a_int;
+                       if (arg < 0)
+                         {
+                           /* "A negative field width is taken as a '-' flag
+                               followed by a positive field width."  */
+                           flags |= FLAG_LEFT;
+                           width = (unsigned int) (-arg);
+                         }
+                       else
+                         width = arg;
+                     }
+                   else
+                     {
+                       const FCHAR_T *digitp = dp->width_start;
+
+                       do
+                         width = xsum (xtimes (width, 10), *digitp++ - '0');
+                       while (digitp != dp->width_end);
+                     }
+                   has_width = 1;
+                 }
+#endif
+
+#if !USE_SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION
+               has_precision = 0;
+               precision = 6;
+               if (dp->precision_start != dp->precision_end)
+                 {
+                   if (dp->precision_arg_index != ARG_NONE)
+                     {
+                       int arg;
+
+                       if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+                         abort ();
+                       arg = a.arg[dp->precision_arg_index].a.a_int;
+                       /* "A negative precision is taken as if the precision
+                           were omitted."  */
+                       if (arg >= 0)
+                         {
+                           precision = arg;
+                           has_precision = 1;
+                         }
+                     }
+                   else
+                     {
+                       const FCHAR_T *digitp = dp->precision_start + 1;
+
+                       precision = 0;
+                       while (digitp != dp->precision_end)
+                         precision = xsum (xtimes (precision, 10), *digitp++ - 
'0');
+                       has_precision = 1;
+                     }
+                 }
+#endif
+
+               /* Decide whether to handle the precision ourselves.  */
+#if NEED_PRINTF_UNBOUNDED_PRECISION
+               switch (dp->conversion)
+                 {
+                 case 'd': case 'i': case 'u':
+                 case 'o':
+                 case 'x': case 'X': case 'p':
+                   prec_ourselves = has_precision && (precision > 0);
+                   break;
+                 default:
+                   prec_ourselves = 0;
+                   break;
+                 }
+#endif
+
+               /* Decide whether to perform the padding ourselves.  */
+#if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || 
NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION)
+               switch (dp->conversion)
+                 {
+# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
+                 /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need
+                    to perform the padding after this conversion.  Functions
+                    with unistdio extensions perform the padding based on
+                    character count rather than element count.  */
+                 case 'c': case 's':
+# endif
+# if NEED_PRINTF_FLAG_ZERO
+                 case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
+                 case 'a': case 'A':
+# endif
+                   pad_ourselves = 1;
+                   break;
+                 default:
+                   pad_ourselves = prec_ourselves;
+                   break;
+                 }
+#endif
+
+#if !USE_SNPRINTF
+               /* Allocate a temporary buffer of sufficient size for calling
+                  sprintf.  */
+               {
+                 switch (dp->conversion)
+                   {
+
+                   case 'd': case 'i': case 'u':
+# if HAVE_LONG_LONG_INT
+                     if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+                       tmp_length =
+                         (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+                                         * 0.30103 /* binary -> decimal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     else
+# endif
+                     if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+                       tmp_length =
+                         (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+                                         * 0.30103 /* binary -> decimal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     else
+                       tmp_length =
+                         (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+                                         * 0.30103 /* binary -> decimal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     if (tmp_length < precision)
+                       tmp_length = precision;
+                     /* Multiply by 2, as an estimate for FLAG_GROUP.  */
+                     tmp_length = xsum (tmp_length, tmp_length);
+                     /* Add 1, to account for a leading sign.  */
+                     tmp_length = xsum (tmp_length, 1);
+                     break;
+
+                   case 'o':
+# if HAVE_LONG_LONG_INT
+                     if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+                       tmp_length =
+                         (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+                                         * 0.333334 /* binary -> octal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     else
+# endif
+                     if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+                       tmp_length =
+                         (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+                                         * 0.333334 /* binary -> octal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     else
+                       tmp_length =
+                         (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+                                         * 0.333334 /* binary -> octal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     if (tmp_length < precision)
+                       tmp_length = precision;
+                     /* Add 1, to account for a leading sign.  */
+                     tmp_length = xsum (tmp_length, 1);
+                     break;
+
+                   case 'x': case 'X':
+# if HAVE_LONG_LONG_INT
+                     if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+                       tmp_length =
+                         (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+                                         * 0.25 /* binary -> hexadecimal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     else
+# endif
+                     if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+                       tmp_length =
+                         (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+                                         * 0.25 /* binary -> hexadecimal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     else
+                       tmp_length =
+                         (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+                                         * 0.25 /* binary -> hexadecimal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     if (tmp_length < precision)
+                       tmp_length = precision;
+                     /* Add 2, to account for a leading sign or alternate 
form.  */
+                     tmp_length = xsum (tmp_length, 2);
+                     break;
+
+                   case 'f': case 'F':
+                     if (type == TYPE_LONGDOUBLE)
+                       tmp_length =
+                         (unsigned int) (LDBL_MAX_EXP
+                                         * 0.30103 /* binary -> decimal */
+                                         * 2 /* estimate for FLAG_GROUP */
+                                        )
+                         + 1 /* turn floor into ceil */
+                         + 10; /* sign, decimal point etc. */
+                     else
+                       tmp_length =
+                         (unsigned int) (DBL_MAX_EXP
+                                         * 0.30103 /* binary -> decimal */
+                                         * 2 /* estimate for FLAG_GROUP */
+                                        )
+                         + 1 /* turn floor into ceil */
+                         + 10; /* sign, decimal point etc. */
+                     tmp_length = xsum (tmp_length, precision);
+                     break;
+
+                   case 'e': case 'E': case 'g': case 'G':
+                     tmp_length =
+                       12; /* sign, decimal point, exponent etc. */
+                     tmp_length = xsum (tmp_length, precision);
+                     break;
+
+                   case 'a': case 'A':
+                     if (type == TYPE_LONGDOUBLE)
+                       tmp_length =
+                         (unsigned int) (LDBL_DIG
+                                         * 0.831 /* decimal -> hexadecimal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     else
+                       tmp_length =
+                         (unsigned int) (DBL_DIG
+                                         * 0.831 /* decimal -> hexadecimal */
+                                        )
+                         + 1; /* turn floor into ceil */
+                     if (tmp_length < precision)
+                       tmp_length = precision;
+                     /* Account for sign, decimal point etc. */
+                     tmp_length = xsum (tmp_length, 12);
+                     break;
+
+                   case 'c':
+# if HAVE_WINT_T && !WIDE_CHAR_VERSION
+                     if (type == TYPE_WIDE_CHAR)
+                       tmp_length = MB_CUR_MAX;
+                     else
+# endif
+                       tmp_length = 1;
+                     break;
+
+                   case 's':
+# if HAVE_WCHAR_T
+                     if (type == TYPE_WIDE_STRING)
+                       {
+#  if WIDE_CHAR_VERSION
+                         /* ISO C says about %ls in fwprintf:
+                              "If the precision is not specified or is greater
+                               than the size of the array, the array shall
+                               contain a null wide character."
+                            So if there is a precision, we must not use
+                            wcslen.  */
+                         const wchar_t *arg =
+                           a.arg[dp->arg_index].a.a_wide_string;
+
+                         if (has_precision)
+                           tmp_length = local_wcsnlen (arg, precision);
+                         else
+                           tmp_length = local_wcslen (arg);
+#  else
+                         /* ISO C says about %ls in fprintf:
+                              "If a precision is specified, no more than that
+                               many bytes are written (including shift
+                               sequences, if any), and the array shall contain
+                               a null wide character if, to equal the
+                               multibyte character sequence length given by
+                               the precision, the function would need to
+                               access a wide character one past the end of the
+                               array."
+                            So if there is a precision, we must not use
+                            wcslen.  */
+                         /* This case has already been handled above.  */
+                         abort ();
+#  endif
+                       }
+                     else
+# endif
+                       {
+# if WIDE_CHAR_VERSION
+                         /* ISO C says about %s in fwprintf:
+                              "If the precision is not specified or is greater
+                               than the size of the converted array, the
+                               converted array shall contain a null wide
+                               character."
+                            So if there is a precision, we must not use
+                            strlen.  */
+                         /* This case has already been handled above.  */
+                         abort ();
+# else
+                         /* ISO C says about %s in fprintf:
+                              "If the precision is not specified or greater
+                               than the size of the array, the array shall
+                               contain a null character."
+                            So if there is a precision, we must not use
+                            strlen.  */
+                         const char *arg = a.arg[dp->arg_index].a.a_string;
+
+                         if (has_precision)
+                           tmp_length = local_strnlen (arg, precision);
+                         else
+                           tmp_length = strlen (arg);
+# endif
+                       }
+                     break;
+
+                   case 'p':
+                     tmp_length =
+                       (unsigned int) (sizeof (void *) * CHAR_BIT
+                                       * 0.25 /* binary -> hexadecimal */
+                                      )
+                         + 1 /* turn floor into ceil */
+                         + 2; /* account for leading 0x */
+                     break;
+
+                   default:
+                     abort ();
+                   }
+
+                 if (!pad_ourselves)
+                   {
+# if ENABLE_UNISTDIO
+                     /* Padding considers the number of characters, therefore
+                        the number of elements after padding may be
+                          > max (tmp_length, width)
+                        but is certainly
+                          <= tmp_length + width.  */
+                     tmp_length = xsum (tmp_length, width);
+# else
+                     /* Padding considers the number of elements,
+                        says POSIX.  */
+                     if (tmp_length < width)
+                       tmp_length = width;
+# endif
+                   }
+
+                 tmp_length = xsum (tmp_length, 1); /* account for trailing 
NUL */
+               }
+
+               if (tmp_length <= sizeof (tmpbuf) / sizeof (TCHAR_T))
+                 tmp = tmpbuf;
+               else
+                 {
+                   size_t tmp_memsize = xtimes (tmp_length, sizeof (TCHAR_T));
+
+                   if (size_overflow_p (tmp_memsize))
+                     /* Overflow, would lead to out of memory.  */
+                     goto out_of_memory;
+                   tmp = (TCHAR_T *) malloc (tmp_memsize);
+                   if (tmp == NULL)
+                     /* Out of memory.  */
+                     goto out_of_memory;
+                 }
+#endif
+
+               /* Construct the format string for calling snprintf or
+                  sprintf.  */
+               fbp = buf;
+               *fbp++ = '%';
+#if NEED_PRINTF_FLAG_GROUPING
+               /* The underlying implementation doesn't support the ' flag.
+                  Produce no grouping characters in this case; this is
+                  acceptable because the grouping is locale dependent.  */
+#else
+               if (flags & FLAG_GROUP)
+                 *fbp++ = '\'';
+#endif
+               if (flags & FLAG_LEFT)
+                 *fbp++ = '-';
+               if (flags & FLAG_SHOWSIGN)
+                 *fbp++ = '+';
+               if (flags & FLAG_SPACE)
+                 *fbp++ = ' ';
+               if (flags & FLAG_ALT)
+                 *fbp++ = '#';
+               if (!pad_ourselves)
+                 {
+                   if (flags & FLAG_ZERO)
+                     *fbp++ = '0';
+                   if (dp->width_start != dp->width_end)
+                     {
+                       size_t n = dp->width_end - dp->width_start;
+                       /* The width specification is known to consist only
+                          of standard ASCII characters.  */
+                       if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
+                         {
+                           memcpy (fbp, dp->width_start, n * sizeof (TCHAR_T));
+                           fbp += n;
+                         }
+                       else
+                         {
+                           const FCHAR_T *mp = dp->width_start;
+                           do
+                             *fbp++ = (unsigned char) *mp++;
+                           while (--n > 0);
+                         }
+                     }
+                 }
+               if (!prec_ourselves)
+                 {
+                   if (dp->precision_start != dp->precision_end)
+                     {
+                       size_t n = dp->precision_end - dp->precision_start;
+                       /* The precision specification is known to consist only
+                          of standard ASCII characters.  */
+                       if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
+                         {
+                           memcpy (fbp, dp->precision_start, n * sizeof 
(TCHAR_T));
+                           fbp += n;
+                         }
+                       else
+                         {
+                           const FCHAR_T *mp = dp->precision_start;
+                           do
+                             *fbp++ = (unsigned char) *mp++;
+                           while (--n > 0);
+                         }
+                     }
+                 }
+
+               switch (type)
+                 {
+#if HAVE_LONG_LONG_INT
+                 case TYPE_LONGLONGINT:
+                 case TYPE_ULONGLONGINT:
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+                   *fbp++ = 'I';
+                   *fbp++ = '6';
+                   *fbp++ = '4';
+                   break;
+# else
+                   *fbp++ = 'l';
+                   /*FALLTHROUGH*/
+# endif
+#endif
+                 case TYPE_LONGINT:
+                 case TYPE_ULONGINT:
+#if HAVE_WINT_T
+                 case TYPE_WIDE_CHAR:
+#endif
+#if HAVE_WCHAR_T
+                 case TYPE_WIDE_STRING:
+#endif
+                   *fbp++ = 'l';
+                   break;
+                 case TYPE_LONGDOUBLE:
+                   *fbp++ = 'L';
+                   break;
+                 default:
+                   break;
+                 }
+#if NEED_PRINTF_DIRECTIVE_F
+               if (dp->conversion == 'F')
+                 *fbp = 'f';
+               else
+#endif
+                 *fbp = dp->conversion;
+#if USE_SNPRINTF
+# if !(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) || ((defined 
_WIN32 || defined __WIN32__) && ! defined __CYGWIN__))
+               fbp[1] = '%';
+               fbp[2] = 'n';
+               fbp[3] = '\0';
+# else
+               /* On glibc2 systems from glibc >= 2.3 - probably also older
+                  ones - we know that snprintf's returns value conforms to
+                  ISO C 99: the gl_SNPRINTF_DIRECTIVE_N test passes.
+                  Therefore we can avoid using %n in this situation.
+                  On glibc2 systems from 2004-10-18 or newer, the use of %n
+                  in format strings in writable memory may crash the program
+                  (if compiled with _FORTIFY_SOURCE=2), so we should avoid it
+                  in this situation.  */
+               /* On native Win32 systems (such as mingw), we can avoid using
+                  %n because:
+                    - Although the gl_SNPRINTF_TRUNCATION_C99 test fails,
+                      snprintf does not write more than the specified number
+                      of bytes. (snprintf (buf, 3, "%d %d", 4567, 89) writes
+                      '4', '5', '6' into buf, not '4', '5', '\0'.)
+                    - Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf
+                      allows us to recognize the case of an insufficient
+                      buffer size: it returns -1 in this case.
+                  On native Win32 systems (such as mingw) where the OS is
+                  Windows Vista, the use of %n in format strings by default
+                  crashes the program. See
+                    <http://gcc.gnu.org/ml/gcc/2007-06/msg00122.html> and
+                    
<http://msdn2.microsoft.com/en-us/library/ms175782(VS.80).aspx>
+                  So we should avoid %n in this situation.  */
+               fbp[1] = '\0';
+# endif
+#else
+               fbp[1] = '\0';
+#endif
+
+               /* Construct the arguments for calling snprintf or sprintf.  */
+               prefix_count = 0;
+               if (!pad_ourselves && dp->width_arg_index != ARG_NONE)
+                 {
+                   if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+                     abort ();
+                   prefixes[prefix_count++] = 
a.arg[dp->width_arg_index].a.a_int;
+                 }
+               if (!prec_ourselves && dp->precision_arg_index != ARG_NONE)
+                 {
+                   if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+                     abort ();
+                   prefixes[prefix_count++] = 
a.arg[dp->precision_arg_index].a.a_int;
+                 }
+
+#if USE_SNPRINTF
+               /* The SNPRINTF result is appended after result[0..length].
+                  The latter is an array of DCHAR_T; SNPRINTF appends an
+                  array of TCHAR_T to it.  This is possible because
+                  sizeof (TCHAR_T) divides sizeof (DCHAR_T) and
+                  alignof (TCHAR_T) <= alignof (DCHAR_T).  */
+# define TCHARS_PER_DCHAR (sizeof (DCHAR_T) / sizeof (TCHAR_T))
+               /* Ensure that maxlen below will be >= 2.  Needed on BeOS,
+                  where an snprintf() with maxlen==1 acts like sprintf().  */
+               ENSURE_ALLOCATION (xsum (length,
+                                        (2 + TCHARS_PER_DCHAR - 1)
+                                        / TCHARS_PER_DCHAR));
+               /* Prepare checking whether snprintf returns the count
+                  via %n.  */
+               *(TCHAR_T *) (result + length) = '\0';
+#endif
+
+               for (;;)
+                 {
+                   int count = -1;
+
+#if USE_SNPRINTF
+                   int retcount = 0;
+                   size_t maxlen = allocated - length;
+                   /* SNPRINTF can fail if its second argument is
+                      > INT_MAX.  */
+                   if (maxlen > INT_MAX / TCHARS_PER_DCHAR)
+                     maxlen = INT_MAX / TCHARS_PER_DCHAR;
+                   maxlen = maxlen * TCHARS_PER_DCHAR;
+# define SNPRINTF_BUF(arg) \
+                   switch (prefix_count)                                   \
+                     {                                                     \
+                     case 0:                                               \
+                       retcount = SNPRINTF ((TCHAR_T *) (result + length), \
+                                            maxlen, buf,                   \
+                                            arg, &count);                  \
+                       break;                                              \
+                     case 1:                                               \
+                       retcount = SNPRINTF ((TCHAR_T *) (result + length), \
+                                            maxlen, buf,                   \
+                                            prefixes[0], arg, &count);     \
+                       break;                                              \
+                     case 2:                                               \
+                       retcount = SNPRINTF ((TCHAR_T *) (result + length), \
+                                            maxlen, buf,                   \
+                                            prefixes[0], prefixes[1], arg, \
+                                            &count);                       \
+                       break;                                              \
+                     default:                                              \
+                       abort ();                                           \
+                     }
+#else
+# define SNPRINTF_BUF(arg) \
+                   switch (prefix_count)                                   \
+                     {                                                     \
+                     case 0:                                               \
+                       count = sprintf (tmp, buf, arg);                    \
+                       break;                                              \
+                     case 1:                                               \
+                       count = sprintf (tmp, buf, prefixes[0], arg);       \
+                       break;                                              \
+                     case 2:                                               \
+                       count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
+                                        arg);                              \
+                       break;                                              \
+                     default:                                              \
+                       abort ();                                           \
+                     }
+#endif
+
+                   switch (type)
+                     {
+                     case TYPE_SCHAR:
+                       {
+                         int arg = a.arg[dp->arg_index].a.a_schar;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     case TYPE_UCHAR:
+                       {
+                         unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     case TYPE_SHORT:
+                       {
+                         int arg = a.arg[dp->arg_index].a.a_short;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     case TYPE_USHORT:
+                       {
+                         unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     case TYPE_INT:
+                       {
+                         int arg = a.arg[dp->arg_index].a.a_int;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     case TYPE_UINT:
+                       {
+                         unsigned int arg = a.arg[dp->arg_index].a.a_uint;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     case TYPE_LONGINT:
+                       {
+                         long int arg = a.arg[dp->arg_index].a.a_longint;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     case TYPE_ULONGINT:
+                       {
+                         unsigned long int arg = 
a.arg[dp->arg_index].a.a_ulongint;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+#if HAVE_LONG_LONG_INT
+                     case TYPE_LONGLONGINT:
+                       {
+                         long long int arg = 
a.arg[dp->arg_index].a.a_longlongint;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     case TYPE_ULONGLONGINT:
+                       {
+                         unsigned long long int arg = 
a.arg[dp->arg_index].a.a_ulonglongint;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+#endif
+                     case TYPE_DOUBLE:
+                       {
+                         double arg = a.arg[dp->arg_index].a.a_double;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     case TYPE_LONGDOUBLE:
+                       {
+                         long double arg = a.arg[dp->arg_index].a.a_longdouble;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     case TYPE_CHAR:
+                       {
+                         int arg = a.arg[dp->arg_index].a.a_char;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+#if HAVE_WINT_T
+                     case TYPE_WIDE_CHAR:
+                       {
+                         wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+#endif
+                     case TYPE_STRING:
+                       {
+                         const char *arg = a.arg[dp->arg_index].a.a_string;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+#if HAVE_WCHAR_T
+                     case TYPE_WIDE_STRING:
+                       {
+                         const wchar_t *arg = 
a.arg[dp->arg_index].a.a_wide_string;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+#endif
+                     case TYPE_POINTER:
+                       {
+                         void *arg = a.arg[dp->arg_index].a.a_pointer;
+                         SNPRINTF_BUF (arg);
+                       }
+                       break;
+                     default:
+                       abort ();
+                     }
+
+#if USE_SNPRINTF
+                   /* Portability: Not all implementations of snprintf()
+                      are ISO C 99 compliant.  Determine the number of
+                      bytes that snprintf() has produced or would have
+                      produced.  */
+                   if (count >= 0)
+                     {
+                       /* Verify that snprintf() has NUL-terminated its
+                          result.  */
+                       if (count < maxlen
+                           && ((TCHAR_T *) (result + length)) [count] != '\0')
+                         abort ();
+                       /* Portability hack.  */
+                       if (retcount > count)
+                         count = retcount;
+                     }
+                   else
+                     {
+                       /* snprintf() doesn't understand the '%n'
+                          directive.  */
+                       if (fbp[1] != '\0')
+                         {
+                           /* Don't use the '%n' directive; instead, look
+                              at the snprintf() return value.  */
+                           fbp[1] = '\0';
+                           continue;
+                         }
+                       else
+                         {
+                           /* Look at the snprintf() return value.  */
+                           if (retcount < 0)
+                             {
+                               /* HP-UX 10.20 snprintf() is doubly deficient:
+                                  It doesn't understand the '%n' directive,
+                                  *and* it returns -1 (rather than the length
+                                  that would have been required) when the
+                                  buffer is too small.  */
+                               size_t bigger_need =
+                                 xsum (xtimes (allocated, 2), 12);
+                               ENSURE_ALLOCATION (bigger_need);
+                               continue;
+                             }
+                           else
+                             count = retcount;
+                         }
+                     }
+#endif
+
+                   /* Attempt to handle failure.  */
+                   if (count < 0)
+                     {
+                       if (!(result == resultbuf || result == NULL))
+                         free (result);
+                       if (buf_malloced != NULL)
+                         free (buf_malloced);
+                       CLEANUP ();
+                       errno = EINVAL;
+                       return NULL;
+                     }
+
+#if USE_SNPRINTF
+                   /* Handle overflow of the allocated buffer.
+                      If such an overflow occurs, a C99 compliant snprintf()
+                      returns a count >= maxlen.  However, a non-compliant
+                      snprintf() function returns only count = maxlen - 1.  To
+                      cover both cases, test whether count >= maxlen - 1.  */
+                   if ((unsigned int) count + 1 >= maxlen)
+                     {
+                       /* If maxlen already has attained its allowed maximum,
+                          allocating more memory will not increase maxlen.
+                          Instead of looping, bail out.  */
+                       if (maxlen == INT_MAX / TCHARS_PER_DCHAR)
+                         goto overflow;
+                       else
+                         {
+                           /* Need at least (count + 1) * sizeof (TCHAR_T)
+                              bytes.  (The +1 is for the trailing NUL.)
+                              But ask for (count + 2) * sizeof (TCHAR_T)
+                              bytes, so that in the next round, we likely get
+                                maxlen > (unsigned int) count + 1
+                              and so we don't get here again.
+                              And allocate proportionally, to avoid looping
+                              eternally if snprintf() reports a too small
+                              count.  */
+                           size_t n =
+                             xmax (xsum (length,
+                                         ((unsigned int) count + 2
+                                          + TCHARS_PER_DCHAR - 1)
+                                         / TCHARS_PER_DCHAR),
+                                   xtimes (allocated, 2));
+
+                           ENSURE_ALLOCATION (n);
+                           continue;
+                         }
+                     }
+#endif
+
+#if NEED_PRINTF_UNBOUNDED_PRECISION
+                   if (prec_ourselves)
+                     {
+                       /* Handle the precision.  */
+                       TCHAR_T *prec_ptr =
+# if USE_SNPRINTF
+                         (TCHAR_T *) (result + length);
+# else
+                         tmp;
+# endif
+                       size_t prefix_count;
+                       size_t move;
+
+                       prefix_count = 0;
+                       /* Put the additional zeroes after the sign.  */
+                       if (count >= 1
+                           && (*prec_ptr == '-' || *prec_ptr == '+'
+                               || *prec_ptr == ' '))
+                         prefix_count = 1;
+                       /* Put the additional zeroes after the 0x prefix if
+                          (flags & FLAG_ALT) || (dp->conversion == 'p').  */
+                       else if (count >= 2
+                                && prec_ptr[0] == '0'
+                                && (prec_ptr[1] == 'x' || prec_ptr[1] == 'X'))
+                         prefix_count = 2;
+
+                       move = count - prefix_count;
+                       if (precision > move)
+                         {
+                           /* Insert zeroes.  */
+                           size_t insert = precision - move;
+                           TCHAR_T *prec_end;
+
+# if USE_SNPRINTF
+                           size_t n =
+                             xsum (length,
+                                   (count + insert + TCHARS_PER_DCHAR - 1)
+                                   / TCHARS_PER_DCHAR);
+                           length += (count + TCHARS_PER_DCHAR - 1) / 
TCHARS_PER_DCHAR;
+                           ENSURE_ALLOCATION (n);
+                           length -= (count + TCHARS_PER_DCHAR - 1) / 
TCHARS_PER_DCHAR;
+                           prec_ptr = (TCHAR_T *) (result + length);
+# endif
+
+                           prec_end = prec_ptr + count;
+                           prec_ptr += prefix_count;
+
+                           while (prec_end > prec_ptr)
+                             {
+                               prec_end--;
+                               prec_end[insert] = prec_end[0];
+                             }
+
+                           prec_end += insert;
+                           do
+                             *--prec_end = '0';
+                           while (prec_end > prec_ptr);
+
+                           count += insert;
+                         }
+                     }
+#endif
+
+#if !USE_SNPRINTF
+                   if (count >= tmp_length)
+                     /* tmp_length was incorrectly calculated - fix the
+                        code above!  */
+                     abort ();
+#endif
+
+#if !DCHAR_IS_TCHAR
+                   /* Convert from TCHAR_T[] to DCHAR_T[].  */
+                   if (dp->conversion == 'c' || dp->conversion == 's')
+                     {
+                       /* type = TYPE_CHAR or TYPE_WIDE_CHAR or TYPE_STRING
+                          TYPE_WIDE_STRING.
+                          The result string is not certainly ASCII.  */
+                       const TCHAR_T *tmpsrc;
+                       DCHAR_T *tmpdst;
+                       size_t tmpdst_len;
+                       /* This code assumes that TCHAR_T is 'char'.  */
+                       typedef int TCHAR_T_verify
+                                   [2 * (sizeof (TCHAR_T) == 1) - 1];
+# if USE_SNPRINTF
+                       tmpsrc = (TCHAR_T *) (result + length);
+# else
+                       tmpsrc = tmp;
+# endif
+                       tmpdst =
+                         DCHAR_CONV_FROM_ENCODING (locale_charset (),
+                                                   iconveh_question_mark,
+                                                   tmpsrc, count,
+                                                   NULL,
+                                                   NULL, &tmpdst_len);
+                       if (tmpdst == NULL)
+                         {
+                           int saved_errno = errno;
+                           if (!(result == resultbuf || result == NULL))
+                             free (result);
+                           if (buf_malloced != NULL)
+                             free (buf_malloced);
+                           CLEANUP ();
+                           errno = saved_errno;
+                           return NULL;
+                         }
+                       ENSURE_ALLOCATION (xsum (length, tmpdst_len));
+                       DCHAR_CPY (result + length, tmpdst, tmpdst_len);
+                       free (tmpdst);
+                       count = tmpdst_len;
+                     }
+                   else
+                     {
+                       /* The result string is ASCII.
+                          Simple 1:1 conversion.  */
+# if USE_SNPRINTF
+                       /* If sizeof (DCHAR_T) == sizeof (TCHAR_T), it's a
+                          no-op conversion, in-place on the array starting
+                          at (result + length).  */
+                       if (sizeof (DCHAR_T) != sizeof (TCHAR_T))
+# endif
+                         {
+                           const TCHAR_T *tmpsrc;
+                           DCHAR_T *tmpdst;
+                           size_t n;
+
+# if USE_SNPRINTF
+                           if (result == resultbuf)
+                             {
+                               tmpsrc = (TCHAR_T *) (result + length);
+                               /* ENSURE_ALLOCATION will not move tmpsrc
+                                  (because it's part of resultbuf).  */
+                               ENSURE_ALLOCATION (xsum (length, count));
+                             }
+                           else
+                             {
+                               /* ENSURE_ALLOCATION will move the array
+                                  (because it uses realloc().  */
+                               ENSURE_ALLOCATION (xsum (length, count));
+                               tmpsrc = (TCHAR_T *) (result + length);
+                             }
+# else
+                           tmpsrc = tmp;
+                           ENSURE_ALLOCATION (xsum (length, count));
+# endif
+                           tmpdst = result + length;
+                           /* Copy backwards, because of overlapping.  */
+                           tmpsrc += count;
+                           tmpdst += count;
+                           for (n = count; n > 0; n--)
+                             *--tmpdst = (unsigned char) *--tmpsrc;
+                         }
+                     }
+#endif
+
+#if DCHAR_IS_TCHAR && !USE_SNPRINTF
+                   /* Make room for the result.  */
+                   if (count > allocated - length)
+                     {
+                       /* Need at least count elements.  But allocate
+                          proportionally.  */
+                       size_t n =
+                         xmax (xsum (length, count), xtimes (allocated, 2));
+
+                       ENSURE_ALLOCATION (n);
+                     }
+#endif
+
+                   /* Here count <= allocated - length.  */
+
+                   /* Perform padding.  */
+#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || 
NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
+                   if (pad_ourselves && has_width)
+                     {
+                       size_t w;
+# if ENABLE_UNISTDIO
+                       /* Outside POSIX, it's preferrable to compare the width
+                          against the number of _characters_ of the converted
+                          value.  */
+                       w = DCHAR_MBSNLEN (result + length, count);
+# else
+                       /* The width is compared against the number of _bytes_
+                          of the converted value, says POSIX.  */
+                       w = count;
+# endif
+                       if (w < width)
+                         {
+                           size_t pad = width - w;
+
+                           /* Make room for the result.  */
+                           if (xsum (count, pad) > allocated - length)
+                             {
+                               /* Need at least count + pad elements.  But
+                                  allocate proportionally.  */
+                               size_t n =
+                                 xmax (xsum3 (length, count, pad),
+                                       xtimes (allocated, 2));
+
+# if USE_SNPRINTF
+                               length += count;
+                               ENSURE_ALLOCATION (n);
+                               length -= count;
+# else
+                               ENSURE_ALLOCATION (n);
+# endif
+                             }
+                           /* Here count + pad <= allocated - length.  */
+
+                           {
+# if !DCHAR_IS_TCHAR || USE_SNPRINTF
+                             DCHAR_T * const rp = result + length;
+# else
+                             DCHAR_T * const rp = tmp;
+# endif
+                             DCHAR_T *p = rp + count;
+                             DCHAR_T *end = p + pad;
+                             DCHAR_T *pad_ptr;
+# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
+                             if (dp->conversion == 'c'
+                                 || dp->conversion == 's')
+                               /* No zero-padding for string directives.  */
+                               pad_ptr = NULL;
+                             else
+# endif
+                               {
+                                 pad_ptr = (*rp == '-' ? rp + 1 : rp);
+                                 /* No zero-padding of "inf" and "nan".  */
+                                 if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z')
+                                     || (*pad_ptr >= 'a' && *pad_ptr <= 'z'))
+                                   pad_ptr = NULL;
+                               }
+                             /* The generated string now extends from rp to p,
+                                with the zero padding insertion point being at
+                                pad_ptr.  */
+
+                             count = count + pad; /* = end - rp */
+
+                             if (flags & FLAG_LEFT)
+                               {
+                                 /* Pad with spaces on the right.  */
+                                 for (; pad > 0; pad--)
+                                   *p++ = ' ';
+                               }
+                             else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
+                               {
+                                 /* Pad with zeroes.  */
+                                 DCHAR_T *q = end;
+
+                                 while (p > pad_ptr)
+                                   *--q = *--p;
+                                 for (; pad > 0; pad--)
+                                   *p++ = '0';
+                               }
+                             else
+                               {
+                                 /* Pad with spaces on the left.  */
+                                 DCHAR_T *q = end;
+
+                                 while (p > rp)
+                                   *--q = *--p;
+                                 for (; pad > 0; pad--)
+                                   *p++ = ' ';
+                               }
+                           }
+                         }
+                     }
+#endif
+
+                   /* Here still count <= allocated - length.  */
+
+#if !DCHAR_IS_TCHAR || USE_SNPRINTF
+                   /* The snprintf() result did fit.  */
+#else
+                   /* Append the sprintf() result.  */
+                   memcpy (result + length, tmp, count * sizeof (DCHAR_T));
+#endif
+#if !USE_SNPRINTF
+                   if (tmp != tmpbuf)
+                     free (tmp);
+#endif
+
+#if NEED_PRINTF_DIRECTIVE_F
+                   if (dp->conversion == 'F')
+                     {
+                       /* Convert the %f result to upper case for %F.  */
+                       DCHAR_T *rp = result + length;
+                       size_t rc;
+                       for (rc = count; rc > 0; rc--, rp++)
+                         if (*rp >= 'a' && *rp <= 'z')
+                           *rp = *rp - 'a' + 'A';
+                     }
+#endif
+
+                   length += count;
+                   break;
+                 }
+             }
+         }
+      }
+
+    /* Add the final NUL.  */
+    ENSURE_ALLOCATION (xsum (length, 1));
+    result[length] = '\0';
+
+    if (result != resultbuf && length + 1 < allocated)
+      {
+       /* Shrink the allocated memory if possible.  */
+       DCHAR_T *memory;
+
+       memory = (DCHAR_T *) realloc (result, (length + 1) * sizeof (DCHAR_T));
+       if (memory != NULL)
+         result = memory;
+      }
+
+    if (buf_malloced != NULL)
+      free (buf_malloced);
+    CLEANUP ();
+    *lengthp = length;
+    /* Note that we can produce a big string of a length > INT_MAX.  POSIX
+       says that snprintf() fails with errno = EOVERFLOW in this case, but
+       that's only because snprintf() returns an 'int'.  This function does
+       not have this limitation.  */
+    return result;
+
+#if USE_SNPRINTF
+  overflow:
+    if (!(result == resultbuf || result == NULL))
+      free (result);
+    if (buf_malloced != NULL)
+      free (buf_malloced);
+    CLEANUP ();
+    errno = EOVERFLOW;
+    return NULL;
+#endif
+
+  out_of_memory:
+    if (!(result == resultbuf || result == NULL))
+      free (result);
+    if (buf_malloced != NULL)
+      free (buf_malloced);
+  out_of_memory_1:
+    CLEANUP ();
+    errno = ENOMEM;
+    return NULL;
+  }
+}
+
+#undef TCHARS_PER_DCHAR
+#undef SNPRINTF
+#undef USE_SNPRINTF
+#undef DCHAR_CPY
+#undef PRINTF_PARSE
+#undef DIRECTIVES
+#undef DIRECTIVE
+#undef DCHAR_IS_TCHAR
+#undef TCHAR_T
+#undef DCHAR_T
+#undef FCHAR_T
+#undef VASNPRINTF
diff --git a/lib/vasnprintf.h b/lib/vasnprintf.h
new file mode 100644
index 0000000..5ceab44
--- /dev/null
+++ b/lib/vasnprintf.h
@@ -0,0 +1,81 @@
+/* vsprintf with automatic memory allocation.
+   Copyright (C) 2002-2004, 2007-2008 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 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _VASNPRINTF_H
+#define _VASNPRINTF_H
+
+/* Get va_list.  */
+#include <stdarg.h>
+
+/* Get size_t.  */
+#include <stddef.h>
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later.  */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
+#  define __attribute__(Spec) /* empty */
+# endif
+/* The __-protected variants of `format' and `printf' attributes
+   are accepted by gcc versions 2.6.4 (effectively 2.7) and later.  */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+#  define __format__ format
+#  define __printf__ printf
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Write formatted output to a string dynamically allocated with malloc().
+   You can pass a preallocated buffer for the result in RESULTBUF and its
+   size in *LENGTHP; otherwise you pass RESULTBUF = NULL.
+   If successful, return the address of the string (this may be = RESULTBUF
+   if no dynamic memory allocation was necessary) and set *LENGTHP to the
+   number of resulting bytes, excluding the trailing NUL.  Upon error, set
+   errno and return NULL.
+
+   When dynamic memory allocation occurs, the preallocated buffer is left
+   alone (with possibly modified contents).  This makes it possible to use
+   a statically allocated or stack-allocated buffer, like this:
+
+          char buf[100];
+          size_t len = sizeof (buf);
+          char *output = vasnprintf (buf, &len, format, args);
+          if (output == NULL)
+            ... error handling ...;
+          else
+            {
+              ... use the output string ...;
+              if (output != buf)
+                free (output);
+            }
+  */
+#if REPLACE_VASNPRINTF
+# define asnprintf rpl_asnprintf
+# define vasnprintf rpl_vasnprintf
+#endif
+extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, 
...)
+       __attribute__ ((__format__ (__printf__, 3, 4)));
+extern char * vasnprintf (char *resultbuf, size_t *lengthp, const char 
*format, va_list args)
+       __attribute__ ((__format__ (__printf__, 3, 0)));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VASNPRINTF_H */
diff --git a/lib/vsnprintf.c b/lib/vsnprintf.c
new file mode 100644
index 0000000..1fdfb6b
--- /dev/null
+++ b/lib/vsnprintf.c
@@ -0,0 +1,71 @@
+/* Formatted output to strings.
+   Copyright (C) 2004, 2006-2008 Free Software Foundation, Inc.
+   Written by Simon Josefsson and Yoann Vandoorselaere <address@hidden>.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification.  */
+#include <stdio.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vasnprintf.h"
+
+/* Print formatted output to string STR.  Similar to vsprintf, but
+   additional length SIZE limit how much is written into STR.  Returns
+   string length of formatted string (which may be larger than SIZE).
+   STR may be NULL, in which case nothing will be written.  On error,
+   return a negative value.  */
+int
+vsnprintf (char *str, size_t size, const char *format, va_list args)
+{
+  char *output;
+  size_t len;
+  size_t lenbuf = size;
+
+  output = vasnprintf (str, &lenbuf, format, args);
+  len = lenbuf;
+
+  if (!output)
+    return -1;
+
+  if (output != str)
+    {
+      if (size)
+       {
+         size_t pruned_len = (len < size ? len : size - 1);
+         memcpy (str, output, pruned_len);
+         str[pruned_len] = '\0';
+       }
+
+      free (output);
+    }
+
+  if (len > INT_MAX)
+    {
+      errno = EOVERFLOW;
+      return -1;
+    }
+
+  return len;
+}
diff --git a/lib/xsize.h b/lib/xsize.h
new file mode 100644
index 0000000..0b30045
--- /dev/null
+++ b/lib/xsize.h
@@ -0,0 +1,108 @@
+/* xsize.h -- Checked size_t computations.
+
+   Copyright (C) 2003, 2008 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 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _XSIZE_H
+#define _XSIZE_H
+
+/* Get size_t.  */
+#include <stddef.h>
+
+/* Get SIZE_MAX.  */
+#include <limits.h>
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+/* The size of memory objects is often computed through expressions of
+   type size_t. Example:
+      void* p = malloc (header_size + n * element_size).
+   These computations can lead to overflow.  When this happens, malloc()
+   returns a piece of memory that is way too small, and the program then
+   crashes while attempting to fill the memory.
+   To avoid this, the functions and macros in this file check for overflow.
+   The convention is that SIZE_MAX represents overflow.
+   malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc
+   implementation that uses mmap --, it's recommended to use size_overflow_p()
+   or size_in_bounds_p() before invoking malloc().
+   The example thus becomes:
+      size_t size = xsum (header_size, xtimes (n, element_size));
+      void *p = (size_in_bounds_p (size) ? malloc (size) : NULL);
+*/
+
+/* Convert an arbitrary value >= 0 to type size_t.  */
+#define xcast_size_t(N) \
+  ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX)
+
+/* Sum of two sizes, with overflow check.  */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xsum (size_t size1, size_t size2)
+{
+  size_t sum = size1 + size2;
+  return (sum >= size1 ? sum : SIZE_MAX);
+}
+
+/* Sum of three sizes, with overflow check.  */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xsum3 (size_t size1, size_t size2, size_t size3)
+{
+  return xsum (xsum (size1, size2), size3);
+}
+
+/* Sum of four sizes, with overflow check.  */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xsum4 (size_t size1, size_t size2, size_t size3, size_t size4)
+{
+  return xsum (xsum (xsum (size1, size2), size3), size4);
+}
+
+/* Maximum of two sizes, with overflow check.  */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xmax (size_t size1, size_t size2)
+{
+  /* No explicit check is needed here, because for any n:
+     max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX.  */
+  return (size1 >= size2 ? size1 : size2);
+}
+
+/* Multiplication of a count with an element size, with overflow check.
+   The count must be >= 0 and the element size must be > 0.
+   This is a macro, not an inline function, so that it works correctly even
+   when N is of a wider type and N > SIZE_MAX.  */
+#define xtimes(N, ELSIZE) \
+  ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX)
+
+/* Check for overflow.  */
+#define size_overflow_p(SIZE) \
+  ((SIZE) == SIZE_MAX)
+/* Check against overflow.  */
+#define size_in_bounds_p(SIZE) \
+  ((SIZE) != SIZE_MAX)
+
+#endif /* _XSIZE_H */
diff --git a/libguile/_scm.h b/libguile/_scm.h
index 1a0a986..429e87b 100644
--- a/libguile/_scm.h
+++ b/libguile/_scm.h
@@ -79,20 +79,6 @@
 #include "libguile/modules.h"
 #include "libguile/inline.h"
 
-/* SCM_SYSCALL retries system calls that have been interrupted (EINTR).
-   However this can be avoided if the operating system can restart
-   system calls automatically.  We assume this is the case if
-   sigaction is available and SA_RESTART is defined; they will be used
-   when installing signal handlers.
-   */
-
-#ifdef HAVE_RESTARTABLE_SYSCALLS
-#if ! SCM_USE_PTHREAD_THREADS /* However, don't assume SA_RESTART 
-                                 works with pthreads... */
-#define SCM_SYSCALL(line) line
-#endif
-#endif
-
 #ifndef SCM_SYSCALL
 #ifdef vms
 # ifndef __GNUC__
diff --git a/libguile/bytevectors.c b/libguile/bytevectors.c
index fd9043a..24afd24 100644
--- a/libguile/bytevectors.c
+++ b/libguile/bytevectors.c
@@ -88,22 +88,22 @@
     scm_out_of_range (FUNC_NAME, index);
 
 /* Template for fixed-size integer access (only 8, 16 or 32-bit).  */
-#define INTEGER_REF(_len, _sign)                       \
-  SCM result;                                          \
-                                                       \
-  INTEGER_ACCESSOR_PROLOGUE (_len, _sign);             \
-  SCM_VALIDATE_SYMBOL (3, endianness);                 \
-                                                       \
-  {                                                    \
-    INT_TYPE (_len, _sign)  c_result;                  \
-                                                       \
-    memcpy (&c_result, &c_bv[c_index], (_len) / 8);    \
-    if (!scm_is_eq (endianness, native_endianness))    \
-      c_result = INT_SWAP (_len) (c_result);           \
-                                                       \
-    result = SCM_I_MAKINUM (c_result);                 \
-  }                                                    \
-                                                       \
+#define INTEGER_REF(_len, _sign)                                \
+  SCM result;                                                   \
+                                                                \
+  INTEGER_ACCESSOR_PROLOGUE (_len, _sign);                      \
+  SCM_VALIDATE_SYMBOL (3, endianness);                          \
+                                                                \
+  {                                                             \
+      INT_TYPE (_len, _sign)  c_result;                         \
+                                                                \
+    memcpy (&c_result, &c_bv[c_index], (_len) / 8);             \
+    if (!scm_is_eq (endianness, scm_i_native_endianness))       \
+      c_result = INT_SWAP (_len) (c_result);                    \
+                                                                \
+    result = SCM_I_MAKINUM (c_result);                          \
+  }                                                             \
+                                                                \
   return result;
 
 /* Template for fixed-size integer access using the native endianness.  */
@@ -138,7 +138,7 @@
       scm_out_of_range (FUNC_NAME, value);                     \
                                                                \
     c_value_short = (INT_TYPE (_len, _sign)) c_value;          \
-    if (!scm_is_eq (endianness, native_endianness))            \
+    if (!scm_is_eq (endianness, scm_i_native_endianness))       \
       c_value_short = INT_SWAP (_len) (c_value_short);         \
                                                                \
     memcpy (&c_bv[c_index], &c_value_short, (_len) / 8);       \
@@ -398,7 +398,7 @@ SCM_SYMBOL (scm_sym_little, "little");
 SCM scm_endianness_big, scm_endianness_little;
 
 /* Host endianness (a symbol).  */
-static SCM native_endianness = SCM_UNSPECIFIED;
+SCM scm_i_native_endianness = SCM_UNSPECIFIED;
 
 /* Byte-swapping.  */
 #ifndef bswap_24
@@ -414,7 +414,7 @@ SCM_DEFINE (scm_native_endianness, "native-endianness", 0, 
0, 0,
            "Return a symbol denoting the machine's native endianness.")
 #define FUNC_NAME s_scm_native_endianness
 {
-  return native_endianness;
+  return scm_i_native_endianness;
 }
 #undef FUNC_NAME
 
@@ -868,7 +868,7 @@ bytevector_large_set (char *c_bv, size_t c_size, int 
signed_p,
       int swap;                                                                
\
       _sign int value;                                                 \
                                                                        \
-      swap = !scm_is_eq (endianness, native_endianness);               \
+      swap = !scm_is_eq (endianness, scm_i_native_endianness);         \
       switch (c_size)                                                  \
        {                                                               \
        case 1:                                                         \
@@ -943,7 +943,7 @@ bytevector_unsigned_ref (const char *c_bv, size_t c_size, 
SCM endianness)
              int swap;                                                 \
              INT_TYPE (16, _sign)  c_value16;                          \
                                                                        \
-             swap = !scm_is_eq (endianness, native_endianness);        \
+             swap = !scm_is_eq (endianness, scm_i_native_endianness);  \
                                                                        \
              if (swap)                                                 \
                c_value16 = (INT_TYPE (16, _sign)) bswap_16 (c_value);  \
@@ -1293,7 +1293,7 @@ SCM_DEFINE (scm_bytevector_s16_native_set_x, 
"bytevector-s16-native-set!",
 #define LARGE_INTEGER_NATIVE_REF(_len, _sign)                           \
   INTEGER_ACCESSOR_PROLOGUE(_len, _sign);                               \
   return (bytevector_large_ref ((char *) c_bv + c_index, _len / 8,      \
-                               SIGNEDNESS (_sign), native_endianness));
+                               SIGNEDNESS (_sign), scm_i_native_endianness));
 
 #define LARGE_INTEGER_NATIVE_SET(_len, _sign)                          \
   int err;                                                             \
@@ -1301,7 +1301,7 @@ SCM_DEFINE (scm_bytevector_s16_native_set_x, 
"bytevector-s16-native-set!",
                                                                        \
   err = bytevector_large_set ((char *) c_bv + c_index, _len / 8,       \
                              SIGNEDNESS (_sign), value,                \
-                             native_endianness);                       \
+                             scm_i_native_endianness);                 \
   if (SCM_UNLIKELY (err))                                              \
      scm_out_of_range (FUNC_NAME, value);                              \
                                                                        \
@@ -1640,7 +1640,7 @@ double_from_foreign_endianness (const union 
scm_ieee754_double *source)
   IEEE754_ACCESSOR_PROLOGUE (_type);                           \
   SCM_VALIDATE_SYMBOL (3, endianness);                         \
                                                                \
-  if (scm_is_eq (endianness, native_endianness))               \
+  if (scm_is_eq (endianness, scm_i_native_endianness))         \
     memcpy (&c_result, &c_bv[c_index], sizeof (c_result));     \
   else                                                         \
     {                                                          \
@@ -1669,7 +1669,7 @@ double_from_foreign_endianness (const union 
scm_ieee754_double *source)
   SCM_VALIDATE_SYMBOL (4, endianness);                         \
   c_value = IEEE754_FROM_SCM (_type) (value);                  \
                                                                \
-  if (scm_is_eq (endianness, native_endianness))               \
+  if (scm_is_eq (endianness, scm_i_native_endianness))         \
     memcpy (&c_bv[c_index], &c_value, sizeof (c_value));       \
   else                                                         \
     {                                                          \
@@ -2075,6 +2075,12 @@ scm_bootstrap_bytevectors (void)
   scm_null_bytevector =
     scm_gc_protect_object (make_bytevector_from_buffer (0, NULL));
 
+#ifdef WORDS_BIGENDIAN
+  scm_i_native_endianness = scm_permanent_object (scm_from_locale_symbol 
("big"));
+#else
+  scm_i_native_endianness = scm_permanent_object (scm_from_locale_symbol 
("little"));
+#endif
+
   scm_c_register_extension ("libguile", "scm_init_bytevectors",
                            (scm_t_extension_init_func) scm_init_bytevectors,
                            NULL);
@@ -2085,12 +2091,6 @@ scm_init_bytevectors (void)
 {
 #include "libguile/bytevectors.x"
 
-#ifdef WORDS_BIGENDIAN
-  native_endianness = scm_sym_big;
-#else
-  native_endianness = scm_sym_little;
-#endif
-
   scm_endianness_big = scm_sym_big;
   scm_endianness_little = scm_sym_little;
 }
diff --git a/libguile/bytevectors.h b/libguile/bytevectors.h
index 903ce7a..cb27262 100644
--- a/libguile/bytevectors.h
+++ b/libguile/bytevectors.h
@@ -116,6 +116,8 @@ SCM_API SCM scm_utf32_to_string (SCM, SCM);
    i.e., without allocating memory beside the SMOB itself (a double cell).
    This optimization is necessary since small bytevectors are expected to be
    common.  */
+#define SCM_BYTEVECTOR_P(_bv)                  \
+  SCM_SMOB_PREDICATE (scm_tc16_bytevector, _bv)
 #define SCM_BYTEVECTOR_INLINE_THRESHOLD  (2 * sizeof (SCM))
 #define SCM_BYTEVECTOR_INLINEABLE_SIZE_P(_size)        \
   ((_size) <= SCM_BYTEVECTOR_INLINE_THRESHOLD)
@@ -129,6 +131,7 @@ SCM_INTERNAL void scm_bootstrap_bytevectors (void);
 SCM_INTERNAL void scm_init_bytevectors (void);
 
 SCM_INTERNAL scm_t_bits scm_tc16_bytevector;
+SCM_INTERNAL SCM scm_i_native_endianness;
 SCM_INTERNAL SCM scm_c_take_bytevector (signed char *, size_t);
 
 #define scm_c_shrink_bytevector(_bv, _len)             \
diff --git a/libguile/chars.c b/libguile/chars.c
index 94f2740..50a033f 100644
--- a/libguile/chars.c
+++ b/libguile/chars.c
@@ -34,17 +34,6 @@
 
 
 
-SCM
-scm_i_make_char (scm_t_int32 x)
-{
-  /* Negative numbers are the upper plane of 8-bit chars, or EOF (-1) */
-  if (x < 0)
-    return SCM_MAKE_ITAG8((scm_t_bits) (unsigned char) (x), scm_tc8_char);
-  else
-    return SCM_MAKE_ITAG8((scm_t_bits) (x), scm_tc8_char);
-}
-
-
 SCM_DEFINE (scm_char_p, "char?", 1, 0, 0, 
             (SCM x),
            "Return @code{#t} iff @var{x} is a character, else @code{#f}.")
diff --git a/libguile/chars.h b/libguile/chars.h
index ac1c294..bf9ae0f 100644
--- a/libguile/chars.h
+++ b/libguile/chars.h
@@ -36,7 +36,11 @@ typedef scm_t_int32 scm_t_wchar;
 
 #define SCM_CHARP(x) (SCM_ITAG8(x) == scm_tc8_char)
 #define SCM_CHAR(x) ((scm_t_wchar)SCM_ITAG8_DATA(x))
-#define SCM_MAKE_CHAR(x) (scm_i_make_char(x))
+
+#define SCM_MAKE_CHAR(x) ({scm_t_int32 _x = (x);                        \
+      _x < 0                                                            \
+        ? SCM_MAKE_ITAG8((scm_t_bits)(unsigned char)_x, scm_tc8_char)   \
+        : SCM_MAKE_ITAG8((scm_t_bits)_x, scm_tc8_char);})
 
 #define SCM_CODEPOINT_MAX (0x10ffff)
 #define SCM_IS_UNICODE_CHAR(c)                                          \
@@ -45,7 +49,6 @@ typedef scm_t_int32 scm_t_wchar;
 
 
 
-SCM_INTERNAL SCM scm_i_make_char (scm_t_int32 x);
 SCM_API SCM scm_char_p (SCM x);
 SCM_API SCM scm_char_eq_p (SCM x, SCM y);
 SCM_API SCM scm_char_less_p (SCM x, SCM y);
diff --git a/libguile/discouraged.c b/libguile/discouraged.c
index ff9ff90..2621428 100644
--- a/libguile/discouraged.c
+++ b/libguile/discouraged.c
@@ -265,7 +265,7 @@ SCM_DEFINE (scm_make_keyword_from_dash_symbol, 
"make-keyword-from-dash-symbol",
   SCM dash_string, non_dash_symbol;
 
   SCM_ASSERT (scm_is_symbol (symbol)
-             && (scm_i_symbol_ref_eq_char (symbol, 0, '-')),
+             && (scm_i_symbol_ref (symbol, 0) == '-'),
              symbol, SCM_ARG1, FUNC_NAME);
 
   dash_string = scm_symbol_to_string (symbol);
diff --git a/libguile/filesys.c b/libguile/filesys.c
index 76f65a2..1c87950 100644
--- a/libguile/filesys.c
+++ b/libguile/filesys.c
@@ -1583,24 +1583,24 @@ SCM_DEFINE (scm_dirname, "dirname", 1, 0, 0,
 
   i = len - 1;
 #ifdef __MINGW32__
-  while (i >= 0 && (scm_i_string_ref_eq_char (filename, i, '/') 
-                   || scm_i_string_ref_eq_char (filename, i, '\\'))) --i;
-  while (i >= 0 && (!scm_i_string_ref_eq_char (filename, i, '/') 
-                   && !scm_i_string_ref_eq_char (filename, i, '\\'))) --i;
-  while (i >= 0 && (scm_i_string_ref_eq_char (filename, i, '/') 
-                   || scm_i_string_ref_eq_char (filename, i, '\\'))) --i;
+  while (i >= 0 && (scm_i_string_ref (filename, i) == '/'
+                   || scm_i_string_ref (filename, i) == '\\')) --i;
+  while (i >= 0 && (scm_i_string_ref (filename, i) != '/'
+                   && scm_i_string_ref (filename, i) != '\\')) --i;
+  while (i >= 0 && (scm_i_string_ref (filename, i) == '/'
+                   || scm_i_string_ref (filename, i) == '\\')) --i;
 #else
-  while (i >= 0 && scm_i_string_ref_eq_char (filename, i, '/')) --i;
-  while (i >= 0 && !scm_i_string_ref_eq_char (filename, i, '/')) --i;
-  while (i >= 0 && scm_i_string_ref_eq_char (filename, i, '/')) --i;
+  while (i >= 0 && scm_i_string_ref (filename, i) == '/') --i;
+  while (i >= 0 && scm_i_string_ref (filename, i) != '/') --i;
+  while (i >= 0 && scm_i_string_ref (filename, i) == '/') --i;
 #endif /* ndef __MINGW32__ */
   if (i < 0)
     {
 #ifdef __MINGW32__
-      if (len > 0 && (scm_i_string_ref_eq_char (filename, 0, '/') 
-                     || scm_i_string_ref_eq_char (filename, 0, '\\')))
+      if (len > 0 && (scm_i_string_ref (filename, 0) == '/'
+                     || scm_i_string_ref (filename, 0) == '\\'))
 #else
-      if (len > 0 && scm_i_string_ref_eq_char (filename, 0, '/'))
+      if (len > 0 && scm_i_string_ref (filename, 0) == '/')
 #endif /* ndef __MINGW32__ */
        return scm_c_substring (filename, 0, 1);
       else
@@ -1633,17 +1633,17 @@ SCM_DEFINE (scm_basename, "basename", 1, 1, 0,
     }
   i = len - 1;
 #ifdef __MINGW32__
-  while (i >= 0 && (scm_i_string_ref_eq_char (filename, i, '/')
-                   || scm_i_string_ref_eq_char (filename, i, '\\')))
+  while (i >= 0 && (scm_i_string_ref (filename, i) == '/'
+                   || scm_i_string_ref (filename, i) ==  '\\'))
     --i;
 #else
-  while (i >= 0 && scm_i_string_ref_eq_char (filename, i, '/'))
+  while (i >= 0 && scm_i_string_ref (filename, i) == '/')
     --i;
 #endif /* ndef __MINGW32__ */
   end = i;
   while (i >= 0 && j >= 0 
-        && (scm_i_string_ref_to_wchar (filename, i)
-            == scm_i_string_ref_to_wchar (suffix, j)))
+        && (scm_i_string_ref (filename, i)
+            == scm_i_string_ref (suffix, j)))
     {
       --i;
       --j;
@@ -1651,20 +1651,20 @@ SCM_DEFINE (scm_basename, "basename", 1, 1, 0,
   if (j == -1)
     end = i;
 #ifdef __MINGW32__
-  while (i >= 0 && (!scm_i_string_ref_eq_char (filename, i, '/')
-                   && !scm_i_string_ref_eq_char (filename, i, '\\')))
+  while (i >= 0 && (scm_i_string_ref (filename, i) != '/'
+                   && scm_i_string_ref (filename, i) != '\\'))
     --i;
 #else
-  while (i >= 0 && !scm_i_string_ref_eq_char (filename, i, '/'))
+  while (i >= 0 && scm_i_string_ref (filename, i) != '/')
     --i;
 #endif /* ndef __MINGW32__ */
   if (i == end)
     {
 #ifdef __MINGW32__
-      if (len > 0 && (scm_i_string_ref_eq_char (filename, 0, '/')
-                     || scm_i_string_ref_eq_char (filename, 0, '\\'))
+      if (len > 0 && (scm_i_string_ref (filename, 0) ==  '/'
+                     || scm_i_string_ref (filename, 0) ==  '\\'))
 #else
-      if (len > 0 && scm_i_string_ref_eq_char (filename, 0, '/'))
+      if (len > 0 && scm_i_string_ref (filename, 0) == '/')
 #endif /* ndef __MINGW32__ */
        return scm_c_substring (filename, 0, 1);
       else
diff --git a/libguile/fports.c b/libguile/fports.c
index c6d1f1a..80e3228 100644
--- a/libguile/fports.c
+++ b/libguile/fports.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2004, 2006, 
2007, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2004, 2006, 
2007, 2008, 2009 Free Software Foundation, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -611,8 +611,8 @@ fport_fill_input (SCM port)
     }
 }
 
-static off_t_or_off64_t
-fport_seek_or_seek64 (SCM port, off_t_or_off64_t offset, int whence)
+static scm_t_off
+fport_seek (SCM port, scm_t_off offset, int whence)
 {
   scm_t_port *pt = SCM_PTAB_ENTRY (port);
   scm_t_fport *fp = SCM_FSTREAM (port);
@@ -663,41 +663,8 @@ fport_seek_or_seek64 (SCM port, off_t_or_off64_t offset, 
int whence)
   return result;
 }
 
-/* If we've got largefile and off_t isn't already off64_t then
-   fport_seek_or_seek64 needs a range checking wrapper to be fport_seek in
-   the port descriptor.
-
-   Otherwise if no largefile, or off_t is the same as off64_t (which is the
-   case on NetBSD apparently), then fport_seek_or_seek64 is right to be
-   fport_seek already.  */
-
-#if GUILE_USE_64_CALLS && HAVE_STAT64 && SIZEOF_OFF_T != SIZEOF_OFF64_T
-static off_t
-fport_seek (SCM port, off_t offset, int whence)
-{
-  off64_t rv = fport_seek_or_seek64 (port, (off64_t) offset, whence);
-  if (rv > OFF_T_MAX || rv < OFF_T_MIN)
-    {
-      errno = EOVERFLOW;
-      scm_syserror ("fport_seek");
-    }
-  return (off_t) rv;
-
-}
-#else
-#define fport_seek   fport_seek_or_seek64
-#endif
-
-/* `how' has been validated and is one of SEEK_SET, SEEK_CUR or SEEK_END */
-SCM
-scm_i_fport_seek (SCM port, SCM offset, int how)
-{
-  return scm_from_off_t_or_off64_t
-    (fport_seek_or_seek64 (port, scm_to_off_t_or_off64_t (offset), how));
-}
-
 static void
-fport_truncate (SCM port, off_t length)
+fport_truncate (SCM port, scm_t_off length)
 {
   scm_t_fport *fp = SCM_FSTREAM (port);
 
@@ -705,13 +672,6 @@ fport_truncate (SCM port, off_t length)
     scm_syserror ("ftruncate");
 }
 
-int
-scm_i_fport_truncate (SCM port, SCM length)
-{
-  scm_t_fport *fp = SCM_FSTREAM (port);
-  return ftruncate_or_ftruncate64 (fp->fdes, scm_to_off_t_or_off64_t (length));
-}
-
 /* helper for fport_write: try to write data, using multiple system
    calls if required.  */
 #define FUNC_NAME "write_all"
@@ -749,7 +709,7 @@ fport_write (SCM port, const void *data, size_t size)
     }
 
   {
-    off_t space = pt->write_end - pt->write_pos;
+    scm_t_off space = pt->write_end - pt->write_pos;
 
     if (size <= space)
       {
diff --git a/libguile/fports.h b/libguile/fports.h
index 2687504..cbef0f8 100644
--- a/libguile/fports.h
+++ b/libguile/fports.h
@@ -3,7 +3,7 @@
 #ifndef SCM_FPORTS_H
 #define SCM_FPORTS_H
 
-/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2006, 2008 Free Software 
Foundation, Inc.
+/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2006, 2008, 2009 Free 
Software Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -59,8 +59,6 @@ SCM_INTERNAL void scm_init_fports (void);
 /* internal functions */
 
 SCM_INTERNAL SCM scm_i_fdes_to_port (int fdes, long mode_bits, SCM name);
-SCM_INTERNAL int scm_i_fport_truncate (SCM, SCM);
-SCM_INTERNAL SCM scm_i_fport_seek (SCM, SCM, int);
 
 
 #endif  /* SCM_FPORTS_H */
diff --git a/libguile/gc-mark.c b/libguile/gc-mark.c
index c70d461..f16b7cb 100644
--- a/libguile/gc-mark.c
+++ b/libguile/gc-mark.c
@@ -260,11 +260,11 @@ scm_gc_mark_dependencies (SCM p)
            long x;
 
            for (x = 0; x < len - 2; x += 2, ++struct_data)
-             if (scm_i_symbol_ref_eq_char (layout, x, 'p'))
+             if (scm_i_symbol_ref (layout, x) ==  'p')
                scm_gc_mark (SCM_PACK (*struct_data));
-           if (scm_i_symbol_ref_eq_char (layout, x, 'p'))
+           if (scm_i_symbol_ref (layout, x) == 'p')
              {
-               char ch = scm_i_symbol_ref_to_char (layout, x+1, '\0');
+               scm_t_wchar ch = scm_i_symbol_ref (layout, x+1);
                if (SCM_LAYOUT_TAILP (ch))
                  for (x = *struct_data++; x; --x, ++struct_data)
                    scm_gc_mark (SCM_PACK (*struct_data));
diff --git a/libguile/gen-scmconfig.c b/libguile/gen-scmconfig.c
index 85ebfae..98fcc88 100644
--- a/libguile/gen-scmconfig.c
+++ b/libguile/gen-scmconfig.c
@@ -400,6 +400,24 @@ main (int argc, char *argv[])
   pf ("#define SCM_HAVE_READDIR64_R 0 /* 0 or 1 */\n");
 #endif
 
+  /* Arrange so that we have a file offset type that reflects the one
+     used when compiling Guile, regardless of what the application's
+     `_FILE_OFFSET_BITS' says.  See
+     http://lists.gnu.org/archive/html/bug-guile/2009-06/msg00018.html
+     for the original bug report.
+
+     Note that we can't define `scm_t_off' in terms of `off_t' or
+     `off64_t' because they may or may not be available depending on
+     how the application that uses Guile is compiled.  */
+
+#if defined GUILE_USE_64_CALLS && defined HAVE_STAT64
+  pf ("typedef scm_t_int64 scm_t_off;\n");
+#elif SIZEOF_OFF_T == SIZEOF_INT
+  pf ("typedef int scm_t_off;\n");
+#else
+  pf ("typedef long int scm_t_off;\n");
+#endif
+
 #if USE_DLL_IMPORT
   pf ("\n");
   pf ("/* Define some additional CPP macros on Win32 platforms. */\n");
diff --git a/libguile/goops.c b/libguile/goops.c
index d9fcc91..b701b0b 100644
--- a/libguile/goops.c
+++ b/libguile/goops.c
@@ -1534,7 +1534,7 @@ wrap_init (SCM class, SCM *m, long n)
 
   /* Set all SCM-holding slots to unbound */
   for (i = 0; i < n; i++)
-    if (scm_i_symbol_ref_eq_char (layout, i*2, 'p'))
+    if (scm_i_symbol_ref (layout, i*2) == 'p')
       m[i] = SCM_GOOPS_UNBOUND;
     else
       m[i] = 0;
diff --git a/libguile/hash.c b/libguile/hash.c
index 3e976cc..e6e38ba 100644
--- a/libguile/hash.c
+++ b/libguile/hash.c
@@ -58,7 +58,7 @@ scm_i_string_hash (SCM str)
 
   unsigned long h = 0;
   while (len-- > 0)
-    h = (unsigned long) scm_i_string_ref_to_wchar (str, i++) + h * 37;
+    h = (unsigned long) scm_i_string_ref (str, i++) + h * 37;
 
   scm_remember_upto_here_1 (str);
   return h;
diff --git a/libguile/instructions.c b/libguile/instructions.c
index a67684e..8e6d169 100644
--- a/libguile/instructions.c
+++ b/libguile/instructions.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2009 Free Software Foundation, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -109,10 +109,11 @@ SCM_DEFINE (scm_instruction_list, "instruction-list", 0, 
0, 0,
 #define FUNC_NAME s_scm_instruction_list
 {
   SCM list = SCM_EOL;
-  struct scm_instruction *ip;
-  for (ip = fetch_instruction_table (); ip->opcode != scm_op_last; ip++)
-    if (ip->name)
-      list = scm_cons (ip->symname, list);
+  int i;
+  struct scm_instruction *ip = fetch_instruction_table ();
+  for (i = 0; i < scm_op_last; i++)
+    if (ip[i].name)
+      list = scm_cons (ip[i].symname, list);
   return scm_reverse_x (list, SCM_EOL);
 }
 #undef FUNC_NAME
diff --git a/libguile/instructions.h b/libguile/instructions.h
index c9fe6e9..d081b3e 100644
--- a/libguile/instructions.h
+++ b/libguile/instructions.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2009 Free Software Foundation, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -21,7 +21,7 @@
 
 #include <libguile.h>
 
-#define SCM_VM_NUM_INSTRUCTIONS (1<<7)
+#define SCM_VM_NUM_INSTRUCTIONS (1<<8)
 #define SCM_VM_INSTRUCTION_MASK (SCM_VM_NUM_INSTRUCTIONS-1)
 
 enum scm_opcode {
diff --git a/libguile/numbers.c b/libguile/numbers.c
index 4dd0e1f..e74cc67 100644
--- a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ -2505,7 +2505,7 @@ mem2uinteger (SCM mem, unsigned int *p_idx,
   if (idx == len)
     return SCM_BOOL_F;
 
-  c = scm_i_string_ref_to_wchar (mem, idx);
+  c = scm_i_string_ref (mem, idx);
   if (!uc_is_property_ascii_hex_digit ((scm_t_uint32) c))
     return SCM_BOOL_F;
   digit_value = XDIGIT2UINT (c);
@@ -2516,7 +2516,7 @@ mem2uinteger (SCM mem, unsigned int *p_idx,
   result = SCM_I_MAKINUM (digit_value);
   while (idx != len)
     {
-      scm_t_wchar c = scm_i_string_ref_to_wchar (mem, idx);
+      scm_t_wchar c = scm_i_string_ref (mem, idx);
       if (uc_is_property_ascii_hex_digit ((scm_t_uint32) c))
        {
          if (hash_seen)
@@ -2583,7 +2583,7 @@ mem2decimal_from_point (SCM result, SCM mem,
   if (idx == len)
     return result;
 
-  if (scm_i_string_ref_eq_char (mem, idx, '.'))
+  if (scm_i_string_ref (mem, idx) == '.')
     {
       scm_t_bits shift = 1;
       scm_t_bits add = 0;
@@ -2593,7 +2593,7 @@ mem2decimal_from_point (SCM result, SCM mem,
       idx++;
       while (idx != len)
        {
-         scm_t_wchar c = scm_i_string_ref_to_wchar (mem, idx);
+         scm_t_wchar c = scm_i_string_ref (mem, idx);
          if (uc_is_property_decimal_digit ((scm_t_uint32) c))
            {
              if (x == INEXACT)
@@ -2650,7 +2650,7 @@ mem2decimal_from_point (SCM result, SCM mem,
 
       /* R5RS, section 7.1.1, lexical structure of numbers: <suffix> */
 
-      switch (scm_i_string_ref_to_wchar (mem, idx))
+      switch (scm_i_string_ref (mem, idx))
        {
        case 'd': case 'D':
        case 'e': case 'E':
@@ -2659,18 +2659,18 @@ mem2decimal_from_point (SCM result, SCM mem,
        case 's': case 'S':
          idx++;
          start = idx;
-         c = scm_i_string_ref_to_wchar (mem, idx);
+         c = scm_i_string_ref (mem, idx);
          if (c == '-')
            {
              idx++;
              sign = -1;
-             c = scm_i_string_ref_to_wchar (mem, idx);
+             c = scm_i_string_ref (mem, idx);
            }
          else if (c == '+')
            {
              idx++;
              sign = 1;
-             c = scm_i_string_ref_to_wchar (mem, idx);
+             c = scm_i_string_ref (mem, idx);
            }
          else
            sign = 1;
@@ -2682,7 +2682,7 @@ mem2decimal_from_point (SCM result, SCM mem,
          exponent = DIGIT2UINT (c);
          while (idx != len)
            {
-             scm_t_wchar c = scm_i_string_ref_to_wchar (mem, idx);
+             scm_t_wchar c = scm_i_string_ref (mem, idx);
              if (uc_is_property_decimal_digit ((scm_t_uint32) c))
                {
                  idx++;
@@ -2735,6 +2735,10 @@ mem2ureal (SCM mem, unsigned int *p_idx,
   SCM result;
   size_t len = scm_i_string_length (mem);
 
+  /* Start off believing that the number will be exact.  This changes
+     to INEXACT if we see a decimal point or a hash. */
+  enum t_exactness x = EXACT;
+
   if (idx == len)
     return SCM_BOOL_F;
 
@@ -2746,8 +2750,6 @@ mem2ureal (SCM mem, unsigned int *p_idx,
 
   if (idx+4 < len && !scm_i_string_strcmp (mem, idx, "nan."))
     {
-      enum t_exactness x = EXACT;
-
       /* Cobble up the fractional part.  We might want to set the
         NaN's mantissa from it. */
       idx += 4;
@@ -2756,21 +2758,20 @@ mem2ureal (SCM mem, unsigned int *p_idx,
       return scm_nan ();
     }
 
-  if (scm_i_string_ref_eq_char (mem, idx, '.'))
+  if (scm_i_string_ref (mem, idx) == '.')
     {
       if (radix != 10)
        return SCM_BOOL_F;
       else if (idx + 1 == len)
        return SCM_BOOL_F;
-      else if (!uc_is_property_decimal_digit ((scm_t_uint32) 
scm_i_string_ref_to_wchar (mem, idx+1)))
+      else if (!uc_is_property_decimal_digit ((scm_t_uint32) scm_i_string_ref 
(mem, idx+1)))
        return SCM_BOOL_F;
       else
        result = mem2decimal_from_point (SCM_I_MAKINUM (0), mem,
-                                        p_idx, p_exactness);
+                                        p_idx, &x);
     }
   else
     {
-      enum t_exactness x = EXACT;
       SCM uinteger;
 
       uinteger = mem2uinteger (mem, &idx, radix, &x);
@@ -2779,7 +2780,7 @@ mem2ureal (SCM mem, unsigned int *p_idx,
 
       if (idx == len)
        result = uinteger;
-      else if (scm_i_string_ref_eq_char (mem, idx, '/'))
+      else if (scm_i_string_ref (mem, idx) == '/')
        {
          SCM divisor;
 
@@ -2802,10 +2803,16 @@ mem2ureal (SCM mem, unsigned int *p_idx,
        result = uinteger;
 
       *p_idx = idx;
-      if (x == INEXACT)
-       *p_exactness = x;
     }
 
+  /* Update *p_exactness if the number just read was inexact.  This is
+     important for complex numbers, so that a complex number is
+     treated as inexact overall if either its real or imaginary part
+     is inexact.
+  */
+  if (x == INEXACT)
+    *p_exactness = x;
+
   /* When returning an inexact zero, make sure it is represented as a
      floating point value so that we can change its sign. 
   */
@@ -2830,7 +2837,7 @@ mem2complex (SCM mem, unsigned int idx,
   if (idx == len)
     return SCM_BOOL_F;
 
-  c = scm_i_string_ref_to_wchar (mem, idx);
+  c = scm_i_string_ref (mem, idx);
   if (c == '+')
     {
       idx++;
@@ -2853,8 +2860,8 @@ mem2complex (SCM mem, unsigned int idx,
       if (sign == 0)
        return SCM_BOOL_F;
 
-      if (scm_i_string_ref_eq_char (mem, idx, 'i') 
-         || scm_i_string_ref_eq_char (mem, idx, 'I'))
+      if (scm_i_string_ref (mem, idx) == 'i'
+         || scm_i_string_ref (mem, idx) == 'I')
        {
          idx++;
          if (idx != len)
@@ -2873,7 +2880,7 @@ mem2complex (SCM mem, unsigned int idx,
       if (idx == len)
        return ureal;
 
-      c = scm_i_string_ref_to_wchar (mem, idx);
+      c = scm_i_string_ref (mem, idx);
       switch (c)
        {
        case 'i': case 'I':
@@ -2898,7 +2905,7 @@ mem2complex (SCM mem, unsigned int idx,
              SCM angle;
              SCM result;
 
-             c = scm_i_string_ref_to_wchar (mem, idx);
+             c = scm_i_string_ref (mem, idx);
              if (c == '+')
                {
                  idx++;
@@ -2943,8 +2950,8 @@ mem2complex (SCM mem, unsigned int idx,
 
              if (idx == len)
                return SCM_BOOL_F;
-             if (!scm_i_string_ref_eq_char (mem, idx, 'i')
-                 && !scm_i_string_ref_eq_char (mem, idx, 'I'))
+             if (scm_i_string_ref (mem, idx) != 'i'
+                 && scm_i_string_ref (mem, idx) != 'I')
                return SCM_BOOL_F;
 
              idx++;
@@ -2975,9 +2982,9 @@ scm_i_string_to_number (SCM mem, unsigned int 
default_radix)
   size_t len = scm_i_string_length (mem);
 
   /* R5RS, section 7.1.1, lexical structure of numbers: <prefix R> */
-  while (idx + 2 < len && scm_i_string_ref_eq_char (mem, idx, '#'))
+  while (idx + 2 < len && scm_i_string_ref (mem, idx) == '#')
     {
-      switch (scm_i_string_ref_to_wchar (mem, idx + 1))
+      switch (scm_i_string_ref (mem, idx + 1))
        {
        case 'b': case 'B':
          if (radix != NO_RADIX)
diff --git a/libguile/objcodes.c b/libguile/objcodes.c
index 6b69fb7..4f21971 100644
--- a/libguile/objcodes.c
+++ b/libguile/objcodes.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2009 Free Software Foundation, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -34,7 +34,7 @@
 #include "objcodes.h"
 
 /* nb, the length of the header should be a multiple of 8 bytes */
-#define OBJCODE_COOKIE "GOOF-0.5"
+#define OBJCODE_COOKIE "GOOF-0.6"
 
 
 /*
@@ -63,19 +63,31 @@ make_objcode_by_mmap (int fd)
 
   addr = mmap (0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
   if (addr == MAP_FAILED)
-    SCM_SYSERROR;
+    {
+      (void) close (fd);
+      SCM_SYSERROR;
+    }
 
   if (memcmp (addr, OBJCODE_COOKIE, strlen (OBJCODE_COOKIE)))
-    scm_misc_error (FUNC_NAME, "bad header on object file: ~s",
-                   scm_list_1 (scm_from_locale_stringn
-                                (addr, strlen (OBJCODE_COOKIE))));
+    {
+      SCM args = scm_list_1 (scm_from_locale_stringn
+                             (addr, strlen (OBJCODE_COOKIE)));
+      (void) close (fd);
+      (void) munmap (addr, st.st_size);
+      scm_misc_error (FUNC_NAME, "bad header on object file: ~s", args);
+    }
 
   data = (struct scm_objcode*)(addr + strlen (OBJCODE_COOKIE));
 
   if (data->len + data->metalen != (st.st_size - sizeof (*data) - strlen 
(OBJCODE_COOKIE)))
-    scm_misc_error (FUNC_NAME, "bad length header (~a, ~a)",
-                   scm_list_2 (scm_from_size_t (st.st_size),
-                               scm_from_uint32 (sizeof (*data) + data->len + 
data->metalen)));
+    {
+      (void) close (fd);
+      (void) munmap (addr, st.st_size);
+      scm_misc_error (FUNC_NAME, "bad length header (~a, ~a)",
+                     scm_list_2 (scm_from_size_t (st.st_size),
+                                 scm_from_uint32 (sizeof (*data) + data->len
+                                                  + data->metalen)));
+    }
 
   SCM_NEWSMOB3 (sret, scm_tc16_objcode, addr + strlen (OBJCODE_COOKIE),
                 SCM_PACK (SCM_BOOL_F), fd);
diff --git a/libguile/ports.c b/libguile/ports.c
index b2d80fd..47c6900 100644
--- a/libguile/ports.c
+++ b/libguile/ports.c
@@ -226,15 +226,14 @@ scm_set_port_close (scm_t_bits tc, int (*close) (SCM))
 }
 
 void
-scm_set_port_seek (scm_t_bits tc, off_t (*seek) (SCM port,
-                                          off_t OFFSET,
-                                          int WHENCE))
+scm_set_port_seek (scm_t_bits tc,
+                  scm_t_off (*seek) (SCM, scm_t_off, int))
 {
   scm_ptobs[SCM_TC2PTOBNUM (tc)].seek = seek;
 }
 
 void
-scm_set_port_truncate (scm_t_bits tc, void (*truncate) (SCM port, off_t 
length))
+scm_set_port_truncate (scm_t_bits tc, void (*truncate) (SCM, scm_t_off))
 {
   scm_ptobs[SCM_TC2PTOBNUM (tc)].truncate = truncate;
 }
@@ -1188,7 +1187,7 @@ scm_lfwrite_substr (SCM str, size_t start, size_t end, 
SCM port)
 
   for (i = 0; i < size; i++) 
     {
-      p = scm_i_string_ref_to_wchar (str, i + start);
+      p = scm_i_string_ref (str, i + start);
       update_port_lf (p, port);
     }
 
@@ -1564,7 +1563,7 @@ SCM_DEFINE (scm_unread_string, "unread-string", 2, 0, 0,
   n = scm_i_string_length (str);
 
   while (n--)
-    scm_ungetc (scm_i_string_ref_to_wchar (str, n), port);
+    scm_ungetc (scm_i_string_ref (str, n), port);
   
   return str;
 }
@@ -1605,23 +1604,18 @@ SCM_DEFINE (scm_seek, "seek", 3, 0, 0,
   if (how != SEEK_SET && how != SEEK_CUR && how != SEEK_END)
     SCM_OUT_OF_RANGE (3, whence);
 
-  if (SCM_OPFPORTP (fd_port))
-    {
-      /* go direct to fport code to allow 64-bit offsets */
-      return scm_i_fport_seek (fd_port, offset, how);
-    }
-  else if (SCM_OPPORTP (fd_port))
+  if (SCM_OPPORTP (fd_port))
     {
       scm_t_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (fd_port);
-      off_t off = scm_to_off_t (offset);
-      off_t rv;
+      off_t_or_off64_t off = scm_to_off_t_or_off64_t (offset);
+      off_t_or_off64_t rv;
 
       if (!ptob->seek)
        SCM_MISC_ERROR ("port is not seekable", 
                         scm_cons (fd_port, SCM_EOL));
       else
        rv = ptob->seek (fd_port, off, how);
-      return scm_from_off_t (rv);
+      return scm_from_off_t_or_off64_t (rv);
     }
   else /* file descriptor?.  */
     {
@@ -1703,14 +1697,9 @@ SCM_DEFINE (scm_truncate_file, "truncate-file", 1, 1, 0,
       SCM_SYSCALL (rv = ftruncate_or_ftruncate64 (scm_to_int (object),
                                                   c_length));
     }
-  else if (SCM_OPOUTFPORTP (object))
-    {
-      /* go direct to fport code to allow 64-bit offsets */
-      rv = scm_i_fport_truncate (object, length);
-    }
   else if (SCM_OPOUTPORTP (object))
     {
-      off_t c_length = scm_to_off_t (length);
+      off_t_or_off64_t c_length = scm_to_off_t_or_off64_t (length);
       scm_t_port *pt = SCM_PTAB_ENTRY (object);
       scm_t_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
       
diff --git a/libguile/ports.h b/libguile/ports.h
index e8a1a87..93fd7f5 100644
--- a/libguile/ports.h
+++ b/libguile/ports.h
@@ -30,8 +30,6 @@
 #include "libguile/threads.h"
 #include "libguile/chars.h"
 
-/* Not sure if this is a good idea.  We need it for off_t.  */
-#include <sys/types.h>
 #include <uniconv.h>
 
 
@@ -77,7 +75,7 @@ typedef struct
   unsigned char *read_buf;     /* buffer start.  */
   const unsigned char *read_pos;/* the next unread char.  */
   unsigned char *read_end;      /* pointer to last buffered char + 1.  */
-  off_t read_buf_size;         /* size of the buffer.  */
+  scm_t_off read_buf_size;             /* size of the buffer.  */
 
   /* when chars are put back into the buffer, e.g., using peek-char or
      unread-string, the read-buffer pointers are switched to cbuf.
@@ -86,7 +84,7 @@ typedef struct
   unsigned char *saved_read_buf;
   const unsigned char *saved_read_pos;
   unsigned char *saved_read_end;
-  off_t saved_read_buf_size;
+  scm_t_off saved_read_buf_size;
 
   /* write requests are saved into this buffer at write_pos until it
      reaches write_buf + write_buf_size, then the ptob flush is
@@ -95,7 +93,7 @@ typedef struct
   unsigned char *write_buf;     /* buffer start.  */
   unsigned char *write_pos;     /* pointer to last buffered char + 1.  */
   unsigned char *write_end;     /* pointer to end of buffer + 1.  */
-  off_t write_buf_size;                /* size of the buffer.  */
+  scm_t_off write_buf_size;            /* size of the buffer.  */
 
   unsigned char shortbuf;       /* buffer for "unbuffered" streams.  */
 
@@ -192,8 +190,8 @@ typedef struct scm_t_ptob_descriptor
   int (*fill_input) (SCM port);
   int (*input_waiting) (SCM port);
 
-  off_t (*seek) (SCM port, off_t OFFSET, int WHENCE);
-  void (*truncate) (SCM port, off_t length);
+  scm_t_off (*seek) (SCM port, scm_t_off OFFSET, int WHENCE);
+  void (*truncate) (SCM port, scm_t_off length);
 
 } scm_t_ptob_descriptor;
 
@@ -231,12 +229,12 @@ SCM_API void scm_set_port_end_input (scm_t_bits tc,
                                     void (*end_input) (SCM port,
                                                        int offset));
 SCM_API void scm_set_port_seek (scm_t_bits tc,
-                               off_t (*seek) (SCM port,
-                                              off_t OFFSET,
-                                              int WHENCE));
+                               scm_t_off (*seek) (SCM port,
+                                                  scm_t_off OFFSET,
+                                                  int WHENCE));
 SCM_API void scm_set_port_truncate (scm_t_bits tc,
                                    void (*truncate) (SCM port,
-                                                     off_t length));
+                                                     scm_t_off length));
 SCM_API void scm_set_port_input_waiting (scm_t_bits tc, int (*input_waiting) 
(SCM));
 SCM_API SCM scm_char_ready_p (SCM port);
 size_t scm_take_from_input_buffers (SCM port, char *dest, size_t read_len);
diff --git a/libguile/posix.c b/libguile/posix.c
index 782178d..b92e464 100644
--- a/libguile/posix.c
+++ b/libguile/posix.c
@@ -1576,10 +1576,6 @@ SCM_DEFINE (scm_setlocale, "setlocale", 1, 1, 0,
   scm_i_set_port_encoding_x (scm_current_output_port (), enc);
   scm_i_set_port_encoding_x (scm_current_error_port (), enc);
 
-  /* Recompute the standard SRFI-14 character sets in a locale-dependent
-     (actually charset-dependent) way.  */
-  scm_srfi_14_compute_char_sets ();
-
   scm_dynwind_end ();
   return scm_from_locale_string (rv);
 }
@@ -1604,10 +1600,6 @@ SCM_DEFINE (scm_setbinary, "setbinary", 0, 0, 0,
   scm_i_set_port_encoding_x (scm_current_output_port (), enc);
   scm_i_set_port_encoding_x (scm_current_error_port (), enc);
 
-  /* Recompute the standard SRFI-14 character sets in a locale-dependent
-     (actually charset-dependent) way.  */
-  scm_srfi_14_compute_char_sets ();
-
   return SCM_UNSPECIFIED;
 }
 #undef FUNC_NAME
diff --git a/libguile/print.c b/libguile/print.c
index 1c20b85..7b82820 100644
--- a/libguile/print.c
+++ b/libguile/print.c
@@ -23,6 +23,7 @@
 #endif
 
 #include <errno.h>
+#include <unictype.h>
 
 #include "libguile/_scm.h"
 #include "libguile/chars.h"
@@ -296,8 +297,8 @@ quote_keywordish_symbol (SCM symbol)
 {
   SCM option;
 
-  if (!scm_i_symbol_ref_eq_char (symbol, 0, ':')
-      && !scm_i_symbol_ref_eq_char (symbol, scm_i_symbol_length (symbol) - 1, 
':'))
+  if (scm_i_symbol_ref (symbol, 0) != ':'
+      && scm_i_symbol_ref (symbol, scm_i_symbol_length (symbol) - 1) !=  ':')
     return 0;
 
   option = SCM_PRINT_KEYWORD_STYLE;
@@ -331,7 +332,7 @@ scm_i_print_symbol_name (SCM str, SCM port)
   int maybe_weird = 0;
   size_t mw_pos = 0;
   size_t len = scm_i_symbol_length (str);
-  scm_t_wchar str0 = scm_i_symbol_ref_to_wchar (str, 0);
+  scm_t_wchar str0 = scm_i_symbol_ref (str, 0);
 
   if (len == 0 || str0 == '\'' || str0 == '`' || str0 == ','
       || quote_keywordish_symbol (str) 
@@ -343,7 +344,7 @@ scm_i_print_symbol_name (SCM str, SCM port)
     }
 
   for (end = pos; end < len; ++end)
-    switch (scm_i_symbol_ref_to_wchar (str, end))
+    switch (scm_i_symbol_ref (str, end))
       {
 #ifdef BRACKETS_AS_PARENS
       case '[':
@@ -372,7 +373,7 @@ scm_i_print_symbol_name (SCM str, SCM port)
        {
          char buf[2];
          buf[0] = '\\';
-         buf[1] = (char) (unsigned char) scm_i_symbol_ref_to_wchar (str, end);
+         buf[1] = (char) (unsigned char) scm_i_symbol_ref (str, end);
          scm_lfwrite (buf, 2, port);
        }
        pos = end + 1;
@@ -453,10 +454,44 @@ iprin1 (SCM exp, SCM port, scm_print_state *pstate)
              name = scm_i_charname (exp);
              if (name != NULL)
                scm_puts (name, port);
-             else if (i < 0 || i > '\177')
-               scm_intprint (i, 8, port);
-             else
-               scm_charprint (i, port);
+             else if (uc_is_general_category_withtable (i, UC_CATEGORY_MASK_L
+                                                         | UC_CATEGORY_MASK_M 
+                                                         | UC_CATEGORY_MASK_N 
+                                                         | UC_CATEGORY_MASK_P 
+                                                         | UC_CATEGORY_MASK_S))
+                /* Print the character if is graphic character.  */
+                {
+                  scm_t_wchar *wbuf;
+                  SCM wstr = scm_i_make_wide_string (1, &wbuf);
+                  char *buf;
+                  size_t len;
+
+                  wbuf[0] = i;
+
+                  buf = u32_conv_to_encoding (scm_i_get_port_encoding (port), 
+                                              iconveh_error,
+                                              (scm_t_uint32 *) wbuf            
            , 
+                                              1   ,
+                                              NULL,
+                                              NULL, &len);
+                  if (buf != NULL)
+                    {
+                      /* Character is graphic.  Print it.  */
+                      scm_lfwrite_str (wstr, port);
+                      free (buf);
+                    }
+                  else
+                    {
+                      /* Character is graphic but unrepresentable in
+                         this port's encoding.  */
+                      scm_intprint (i, 8, port);
+                    }
+                }
+              else
+                {
+                  /* Character is a non-graphical character.  */
+                  scm_intprint (i, 8, port);
+                }
            }
          else
            scm_charprint (i, port);
@@ -564,7 +599,7 @@ iprin1 (SCM exp, SCM port, scm_print_state *pstate)
              len = scm_i_string_length (exp);
              for (i = 0, j = 0; i < len; ++i)
                {
-                 scm_t_wchar ch = scm_i_string_ref_to_wchar (exp, i);
+                 scm_t_wchar ch = scm_i_string_ref (exp, i);
 
                  if (ch == '"' || ch == '\\')
                    {
@@ -1025,12 +1060,12 @@ SCM_DEFINE (scm_simple_format, "simple-format", 2, 0, 1,
   start = 0;
   end = scm_i_string_length (message);
   for (p = start; p != end; ++p)
-    if (scm_i_string_ref_eq_char (message, p, '~'))
+    if (scm_i_string_ref (message, p) == '~')
       {
        if (++p == end)
          break;
 
-       switch (scm_i_string_ref_to_wchar (message, p)) 
+       switch (scm_i_string_ref (message, p)) 
          {
          case 'A': case 'a':
            writingp = 0;
@@ -1049,14 +1084,14 @@ SCM_DEFINE (scm_simple_format, "simple-format", 2, 0, 1,
            continue;
          default:
            SCM_MISC_ERROR ("FORMAT: Unsupported format option ~~~A - use 
(ice-9 format) instead",
-                           scm_list_1 (scm_i_string_ref (message, p)));
+                           scm_list_1 (SCM_MAKE_CHAR (scm_i_string_ref 
(message, p))));
            
          }
 
 
        if (!scm_is_pair (args))
          SCM_MISC_ERROR ("FORMAT: Missing argument for ~~~A",
-                         scm_list_1 (scm_i_string_ref (message, p)));
+                         scm_list_1 (SCM_MAKE_CHAR (scm_i_string_ref (message, 
p))));
                                        
        scm_lfwrite_substr (message, start, p - 1, port);
        /* we pass destination here */
diff --git a/libguile/r6rs-ports.c b/libguile/r6rs-ports.c
index d77c214..e3aa99e 100644
--- a/libguile/r6rs-ports.c
+++ b/libguile/r6rs-ports.c
@@ -125,11 +125,11 @@ bip_fill_input (SCM port)
   return result;
 }
 
-static off_t
-bip_seek (SCM port, off_t offset, int whence)
+static scm_t_off
+bip_seek (SCM port, scm_t_off offset, int whence)
 #define FUNC_NAME "bip_seek"
 {
-  off_t c_result = 0;
+  scm_t_off c_result = 0;
   scm_t_port *c_port = SCM_PTAB_ENTRY (port);
 
   switch (whence)
@@ -217,12 +217,12 @@ cbp_mark (SCM port)
     return SCM_BOOL_F;
 }
 
-static off_t
-cbp_seek (SCM port, off_t offset, int whence)
+static scm_t_off
+cbp_seek (SCM port, scm_t_off offset, int whence)
 #define FUNC_NAME "cbp_seek"
 {
   SCM result;
-  off_t c_result = 0;
+  scm_t_off c_result = 0;
 
   switch (whence)
     {
@@ -885,8 +885,8 @@ bop_write (SCM port, const void *data, size_t size)
   buf->len = (buf->len > buf->pos) ? buf->len : buf->pos;
 }
 
-static off_t
-bop_seek (SCM port, off_t offset, int whence)
+static scm_t_off
+bop_seek (SCM port, scm_t_off offset, int whence)
 #define FUNC_NAME "bop_seek"
 {
   scm_t_bop_buffer *buf;
@@ -895,7 +895,7 @@ bop_seek (SCM port, off_t offset, int whence)
   switch (whence)
     {
     case SEEK_CUR:
-      offset += (off_t) buf->pos;
+      offset += (scm_t_off) buf->pos;
       /* Fall through.  */
 
     case SEEK_SET:
diff --git a/libguile/rdelim.c b/libguile/rdelim.c
index 083c25b..1f46e5b 100644
--- a/libguile/rdelim.c
+++ b/libguile/rdelim.c
@@ -81,7 +81,7 @@ SCM_DEFINE (scm_read_delimited_x, "%read-delimited!", 3, 3, 0,
       c = scm_getc (port);
       for (k = 0; k < num_delims; k++)
        {
-         if (scm_i_string_ref_eq_wchar (delims, k, c))
+         if (scm_i_string_ref (delims, k) == c)
            {
              if (scm_is_false (gobble))
                scm_ungetc (c, port);
diff --git a/libguile/read.c b/libguile/read.c
index fe7d7f7..eb7332a 100644
--- a/libguile/read.c
+++ b/libguile/read.c
@@ -231,7 +231,7 @@ read_token (SCM port, SCM buf, size_t *read)
          return 0;
        }
 
-      scm_i_string_set_from_wchar (buf, *read, chr);
+      scm_i_string_set_x (buf, *read, chr);
       (*read)++;
     }
   scm_dynwind_end ();
@@ -554,7 +554,7 @@ scm_read_string (int chr, SCM port)
            }
        }
       str = scm_i_string_start_writing (str);
-      scm_i_string_set_from_wchar (str, c_str_len++, c);
+      scm_i_string_set_x (str, c_str_len++, c);
       scm_i_string_stop_writing ();
     }
   if (c_str_len > 0)
@@ -596,7 +596,7 @@ scm_read_mixed_case_symbol (int chr, SCM port)
   scm_ungetc (chr, port);
   buffer = read_complete_token (port, &read);
   if (read > 0)
-    ends_with_colon = scm_i_string_ref_eq_char (buffer, read - 1, ':');
+    ends_with_colon = scm_i_string_ref (buffer, read - 1) == ':';
 
   if (postfix && ends_with_colon && (read > 1))
     result = scm_symbol_to_keyword (scm_string_to_symbol (scm_i_substring 
(buffer, 0, read - 1)));
@@ -831,9 +831,9 @@ scm_read_character (scm_t_wchar chr, SCM port)
     }
 
   if (charname_len == 1)
-    return scm_i_string_ref (charname, 0);
+    return SCM_MAKE_CHAR (scm_i_string_ref (charname, 0));
 
-  cp = scm_i_string_ref_to_wchar (charname, 0);
+  cp = scm_i_string_ref (charname, 0);
   if (cp >= '0' && cp < '8')
     {
       /* Dirk:FIXME::  This type of character syntax is not R5RS
@@ -1010,14 +1010,14 @@ scm_read_extended_symbol (scm_t_wchar chr, SCM port)
          else
            {
              saw_brace = 0;
-             scm_i_string_set_from_wchar (buf, len++, '}');
-             scm_i_string_set_from_wchar (buf, len++, chr);
+             scm_i_string_set_x (buf, len++, '}');
+             scm_i_string_set_x (buf, len++, chr);
            }
        }
       else if (chr == '}')
        saw_brace = 1;
       else
-       scm_i_string_set_from_wchar (buf, len++, chr);
+       scm_i_string_set_x (buf, len++, chr);
 
       if (len >= scm_i_string_length (buf) - 2)
        {
diff --git a/libguile/rw.c b/libguile/rw.c
index 308f9eb..a9b4a32 100644
--- a/libguile/rw.c
+++ b/libguile/rw.c
@@ -1,4 +1,4 @@
-/*     Copyright (C) 2001, 2006 Free Software Foundation, Inc.
+/*     Copyright (C) 2001, 2006, 2009 Free Software Foundation, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -209,7 +209,7 @@ SCM_DEFINE (scm_write_string_partial, 
"write-string/partial", 1, 3, 0,
 #define FUNC_NAME s_scm_write_string_partial
 {
   const char *src;
-  long write_len;
+  scm_t_off write_len;
   int fdes;
 
   {
@@ -234,7 +234,7 @@ SCM_DEFINE (scm_write_string_partial, 
"write-string/partial", 1, 3, 0,
       SCM port = (SCM_UNBNDP (port_or_fdes)?
                  scm_current_output_port () : port_or_fdes);
       scm_t_port *pt;
-      off_t space;
+      scm_t_off space;
 
       SCM_VALIDATE_OPFPORT (2, port);
       SCM_VALIDATE_OUTPUT_PORT (2, port);
diff --git a/libguile/scmsigs.c b/libguile/scmsigs.c
index 258710e..f4772b7 100644
--- a/libguile/scmsigs.c
+++ b/libguile/scmsigs.c
@@ -306,10 +306,8 @@ SCM_DEFINE (scm_sigaction_for_thread, "sigaction", 1, 3, 0,
            "a scheme procedure has been specified, that procedure will run\n"
            "in the given @var{thread}.   When no thread has been given, the\n"
            "thread that made this call to @code{sigaction} is used.\n"
-           "Flags can "
-           "optionally be specified for the new handler (@code{SA_RESTART} 
will\n"
-           "always be added if it's available and the system is using 
restartable\n"
-           "system calls.)  The return value is a pair with information about 
the\n"
+           "Flags can optionally be specified for the new handler.\n"
+           "The return value is a pair with information about the\n"
            "old handler as described above.\n\n"
            "This interface does not provide access to the \"signal 
blocking\"\n"
            "facility.  Maybe this is not needed, since the thread support 
may\n"
@@ -333,14 +331,7 @@ SCM_DEFINE (scm_sigaction_for_thread, "sigaction", 1, 3, 0,
   csig = scm_to_signed_integer (signum, 0, NSIG-1);
 
 #if defined(HAVE_SIGACTION)
-#if defined(SA_RESTART) && defined(HAVE_RESTARTABLE_SYSCALLS)
-  /* don't allow SA_RESTART to be omitted if HAVE_RESTARTABLE_SYSCALLS
-     is defined, since libguile would be likely to produce spurious
-     EINTR errors.  */
-  action.sa_flags = SA_RESTART;
-#else
   action.sa_flags = 0;
-#endif
   if (!SCM_UNBNDP (flags))
     action.sa_flags |= scm_to_int (flags);
   sigemptyset (&action.sa_mask);
@@ -713,29 +704,6 @@ scm_init_scmsigs ()
 #else
       orig_handlers[i] = SIG_ERR;
 #endif
-
-#ifdef HAVE_RESTARTABLE_SYSCALLS
-      /* If HAVE_RESTARTABLE_SYSCALLS is defined, it's important that
-        signals really are restartable.  don't rely on the same
-        run-time that configure got: reset the default for every signal.
-      */
-#ifdef HAVE_SIGINTERRUPT
-      siginterrupt (i, 0);
-#elif defined(SA_RESTART)
-      {
-       struct sigaction action;
-
-       sigaction (i, NULL, &action);
-       if (!(action.sa_flags & SA_RESTART))
-         {
-           action.sa_flags |= SA_RESTART;
-           sigaction (i, &action, NULL);
-         }
-      }
-#endif
-      /* if neither siginterrupt nor SA_RESTART are available we may
-        as well assume that signals are always restartable.  */
-#endif
     }
 
   scm_c_define ("NSIG", scm_from_long (NSIG));
diff --git a/libguile/srfi-13.c b/libguile/srfi-13.c
index 9338b9d..4a0fb0e 100644
--- a/libguile/srfi-13.c
+++ b/libguile/srfi-13.c
@@ -52,11 +52,8 @@
                              start, &c_start, end, &c_end);  \
   } while (0)
 
-#define REF_EQ_CHAR(s, i, c)                                   \
-  (scm_is_true (scm_eqv_p (scm_i_string_ref ((s), (i)), (c))))
-
 #define REF_IN_CHARSET(s, i, cs)                                       \
-  (scm_is_true (scm_char_set_contains_p ((cs), scm_i_string_ref (s, i))))
+  (scm_is_true (scm_char_set_contains_p ((cs), SCM_MAKE_CHAR (scm_i_string_ref 
(s, i)))))
 
 /* Helper function for dynwind.  */
 static void stop_writing (void *x)
@@ -119,7 +116,7 @@ SCM_DEFINE (scm_string_any, "string-any-c-code", 2, 2, 0,
     {
       size_t i;
       for (i = cstart; i < cend; i ++)
-       if (REF_EQ_CHAR (s, i, char_pred))
+       if (scm_i_string_ref (s, i) == SCM_CHAR (char_pred))
          {
            res = SCM_BOOL_T;
            break;
@@ -142,7 +139,7 @@ SCM_DEFINE (scm_string_any, "string-any-c-code", 2, 2, 0,
 
       while (cstart < cend)
         {
-          res = pred_tramp (char_pred, scm_i_string_ref (s, cstart));
+          res = pred_tramp (char_pred, SCM_MAKE_CHAR (scm_i_string_ref (s, 
cstart)));
           if (scm_is_true (res))
             break;
           cstart++;
@@ -185,7 +182,7 @@ SCM_DEFINE (scm_string_every, "string-every-c-code", 2, 2, 
0,
     {
       size_t i;
       for (i = cstart; i < cend; i++)
-        if (!REF_EQ_CHAR (s, i, char_pred))
+        if (scm_i_string_ref (s, i) != SCM_CHAR (char_pred))
          {
            res = SCM_BOOL_F;
            break;
@@ -208,7 +205,7 @@ SCM_DEFINE (scm_string_every, "string-every-c-code", 2, 2, 
0,
 
       while (cstart < cend)
         {
-          res = pred_tramp (char_pred, scm_i_string_ref (s, cstart));
+          res = pred_tramp (char_pred, SCM_MAKE_CHAR (scm_i_string_ref (s, 
cstart)));
           if (scm_is_false (res))
             break;
           cstart++;
@@ -254,7 +251,7 @@ SCM_DEFINE (scm_string_tabulate, "string-tabulate", 2, 0, 0,
       ch = proc_tramp (proc, scm_from_size_t (i));
       if (!SCM_CHARP (ch))
        SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (proc));
-      scm_i_string_set (res, i, ch);
+      scm_i_string_set_x (res, i, SCM_CHAR (ch));
       i++;
     }
   scm_dynwind_end ();
@@ -277,7 +274,7 @@ SCM_DEFINE (scm_substring_to_list, "string->list", 1, 2, 0,
   while (cstart < cend)
     {
       cend--;
-      result = scm_cons (scm_i_string_ref (str, cend), result);
+      result = scm_cons (SCM_MAKE_CHAR (scm_i_string_ref (str, cend)), result);
     }
   scm_remember_upto_here_1 (str);
   return result;
@@ -320,7 +317,7 @@ SCM_DEFINE (scm_reverse_list_to_string, 
"reverse-list->string", 1, 0, 0,
       SCM elt = SCM_CAR (chrs);
       
       SCM_VALIDATE_CHAR (SCM_ARGn, elt);
-      scm_i_string_set (result, i-1, elt);
+      scm_i_string_set_x (result, i-1, SCM_CHAR (elt));
       chrs = SCM_CDR (chrs);
       i--;
     }
@@ -517,8 +514,8 @@ SCM_DEFINE (scm_string_copy_x, "string-copy!", 3, 2, 0,
   target = scm_i_string_start_writing (target);
   for (i = 0; i < cend - cstart; i++)
     {
-      scm_i_string_set (target, ctstart + i, 
-                       scm_i_string_ref (s, cstart + i));
+      scm_i_string_set_x (target, ctstart + i, 
+                          scm_i_string_ref (s, cstart + i));
     }
   scm_dynwind_end ();
   return SCM_UNSPECIFIED;
@@ -684,7 +681,7 @@ SCM_DEFINE (scm_string_trim, "string-trim", 1, 3, 0,
     {
       while (cstart < cend)
        {
-         if (!uc_is_c_whitespace (scm_i_string_ref_to_wchar (s, cstart)))
+         if (!uc_is_c_whitespace (scm_i_string_ref (s, cstart)))
            break;
          cstart++;
        }
@@ -693,7 +690,7 @@ SCM_DEFINE (scm_string_trim, "string-trim", 1, 3, 0,
     {
       while (cstart < cend)
        {
-         if (!REF_EQ_CHAR (s, cstart, char_pred))
+         if (scm_i_string_ref (s, cstart) != SCM_CHAR (char_pred))
            break;
          cstart++;
        }
@@ -716,7 +713,7 @@ SCM_DEFINE (scm_string_trim, "string-trim", 1, 3, 0,
        {
          SCM res;
 
-         res = pred_tramp (char_pred, scm_i_string_ref (s, cstart));
+         res = pred_tramp (char_pred, SCM_MAKE_CHAR (scm_i_string_ref (s, 
cstart)));
          if (scm_is_false (res))
            break;
          cstart++;
@@ -759,7 +756,7 @@ SCM_DEFINE (scm_string_trim_right, "string-trim-right", 1, 
3, 0,
     {
       while (cstart < cend)
        {
-         if (!uc_is_c_whitespace (scm_i_string_ref_to_wchar (s, cend - 1)))
+         if (!uc_is_c_whitespace (scm_i_string_ref (s, cend - 1)))
            break;
          cend--;
        }
@@ -768,7 +765,7 @@ SCM_DEFINE (scm_string_trim_right, "string-trim-right", 1, 
3, 0,
     {
       while (cstart < cend)
        {
-         if (!REF_EQ_CHAR (s, cend - 1, char_pred))
+         if (scm_i_string_ref (s, cend - 1) != SCM_CHAR (char_pred))
            break;
          cend--;
        }
@@ -791,7 +788,7 @@ SCM_DEFINE (scm_string_trim_right, "string-trim-right", 1, 
3, 0,
        {
          SCM res;
 
-         res = pred_tramp (char_pred, scm_i_string_ref (s, cend - 1));
+         res = pred_tramp (char_pred, SCM_MAKE_CHAR (scm_i_string_ref (s, cend 
- 1)));
          if (scm_is_false (res))
            break;
          cend--;
@@ -834,13 +831,13 @@ SCM_DEFINE (scm_string_trim_both, "string-trim-both", 1, 
3, 0,
     {
       while (cstart < cend)
        {
-         if (!uc_is_c_whitespace (scm_i_string_ref_to_wchar (s, cstart)))
+         if (!uc_is_c_whitespace (scm_i_string_ref (s, cstart)))
            break;
          cstart++;
        }
       while (cstart < cend)
        {
-         if (!uc_is_c_whitespace (scm_i_string_ref_to_wchar (s, cend - 1)))
+         if (!uc_is_c_whitespace (scm_i_string_ref (s, cend - 1)))
            break;
          cend--;
        }
@@ -849,13 +846,13 @@ SCM_DEFINE (scm_string_trim_both, "string-trim-both", 1, 
3, 0,
     {
       while (cstart < cend)
        {
-         if (!REF_EQ_CHAR (s, cstart, char_pred))
+         if (scm_i_string_ref (s, cstart) != SCM_CHAR(char_pred))
            break;
          cstart++;
        }
       while (cstart < cend)
        {
-         if (!REF_EQ_CHAR (s, cend - 1, char_pred))
+         if (scm_i_string_ref (s, cend - 1) != SCM_CHAR (char_pred))
            break;
          cend--;
        }
@@ -884,7 +881,7 @@ SCM_DEFINE (scm_string_trim_both, "string-trim-both", 1, 3, 
0,
        {
          SCM res;
 
-         res = pred_tramp (char_pred, scm_i_string_ref (s, cstart));
+         res = pred_tramp (char_pred, SCM_MAKE_CHAR (scm_i_string_ref (s, 
cstart)));
          if (scm_is_false (res))
            break;
          cstart++;
@@ -893,7 +890,7 @@ SCM_DEFINE (scm_string_trim_both, "string-trim-both", 1, 3, 
0,
        {
          SCM res;
 
-         res = pred_tramp (char_pred, scm_i_string_ref (s, cend - 1));
+         res = pred_tramp (char_pred, SCM_MAKE_CHAR (scm_i_string_ref (s, cend 
- 1)));
          if (scm_is_false (res))
            break;
          cend--;
@@ -937,7 +934,7 @@ SCM_DEFINE (scm_substring_fill_x, "string-fill!", 2, 2, 0,
 
   str = scm_i_string_start_writing (str);
   for (k = cstart; k < cend; k++)
-    scm_i_string_set (str, k, chr);
+    scm_i_string_set_x (str, k, SCM_CHAR (chr));
   scm_i_string_stop_writing ();
 
   return SCM_UNSPECIFIED;
@@ -975,14 +972,14 @@ SCM_DEFINE (scm_string_compare, "string-compare", 5, 4, 0,
 
   while (cstart1 < cend1 && cstart2 < cend2)
     {
-      if (scm_i_string_ref_to_wchar (s1, cstart1)
-         < scm_i_string_ref_to_wchar (s2, cstart2))
+      if (scm_i_string_ref (s1, cstart1)
+         < scm_i_string_ref (s2, cstart2))
        {
          proc = proc_lt;
          goto ret;
        }
-      else if (scm_i_string_ref_to_wchar (s1, cstart1) 
-              > scm_i_string_ref_to_wchar (s2, cstart2))
+      else if (scm_i_string_ref (s1, cstart1) 
+              > scm_i_string_ref (s2, cstart2))
        {
          proc = proc_gt;
          goto ret;
@@ -1035,14 +1032,14 @@ SCM_DEFINE (scm_string_compare_ci, "string-compare-ci", 
5, 4, 0,
 
   while (cstart1 < cend1 && cstart2 < cend2)
     {
-      if (uc_tolower (uc_toupper (scm_i_string_ref_to_wchar (s1, cstart1)))
-         < uc_tolower (uc_toupper (scm_i_string_ref_to_wchar (s2, cstart2))))
+      if (uc_tolower (uc_toupper (scm_i_string_ref (s1, cstart1)))
+         < uc_tolower (uc_toupper (scm_i_string_ref (s2, cstart2))))
        {
          proc = proc_lt;
          goto ret;
        }
-      else if (uc_tolower (uc_toupper (scm_i_string_ref_to_wchar (s1, 
cstart1)))
-              > uc_tolower (uc_toupper (scm_i_string_ref_to_wchar (s2, 
cstart2))))
+      else if (uc_tolower (uc_toupper (scm_i_string_ref (s1, cstart1)))
+              > uc_tolower (uc_toupper (scm_i_string_ref (s2, cstart2))))
        {
          proc = proc_gt;
          goto ret;
@@ -1084,13 +1081,13 @@ compare_strings (const char *fname, int 
case_insensitive,
     {
       if (case_insensitive)
        {
-         a = uc_tolower (uc_toupper (scm_i_string_ref_to_wchar (s1, cstart1)));
-         b = uc_tolower (uc_toupper (scm_i_string_ref_to_wchar (s2, cstart2)));
+         a = uc_tolower (uc_toupper (scm_i_string_ref (s1, cstart1)));
+         b = uc_tolower (uc_toupper (scm_i_string_ref (s2, cstart2)));
        }
       else
        {
-         a = scm_i_string_ref_to_wchar (s1, cstart1);
-         b = scm_i_string_ref_to_wchar (s2, cstart2);
+         a = scm_i_string_ref (s1, cstart1);
+         b = scm_i_string_ref (s2, cstart2);
        }
       if (a < b)
        {
@@ -1339,8 +1336,8 @@ SCM_DEFINE (scm_string_prefix_length, 
"string-prefix-length", 2, 4, 0,
   
   while (cstart1 < cend1 && cstart2 < cend2)
     {
-      scm_t_wchar a = scm_i_string_ref_to_wchar (s1, cstart1);
-      scm_t_wchar b = scm_i_string_ref_to_wchar (s2, cstart2);
+      scm_t_wchar a = scm_i_string_ref (s1, cstart1);
+      scm_t_wchar b = scm_i_string_ref (s2, cstart2);
       if (a != b)
        goto ret;
       len++;
@@ -1376,8 +1373,8 @@ SCM_DEFINE (scm_string_prefix_length_ci, 
"string-prefix-length-ci", 2, 4, 0,
                              6, end2, cend2);
   while (cstart1 < cend1 && cstart2 < cend2)
     {
-      if (uc_tolower (uc_toupper (scm_i_string_ref_to_wchar (s1, cstart1)))
-         != uc_tolower (uc_toupper (scm_i_string_ref_to_wchar (s2, cstart2))))
+      if (uc_tolower (uc_toupper (scm_i_string_ref (s1, cstart1)))
+         != uc_tolower (uc_toupper (scm_i_string_ref (s2, cstart2))))
        goto ret;
       len++;
       cstart1++;
@@ -1410,8 +1407,8 @@ SCM_DEFINE (scm_string_suffix_length, 
"string-suffix-length", 2, 4, 0,
     {
       cend1--;
       cend2--;
-      if (scm_i_string_ref_to_wchar (s1, cend1) 
-         != scm_i_string_ref_to_wchar (s2, cend2))
+      if (scm_i_string_ref (s1, cend1) 
+         != scm_i_string_ref (s2, cend2))
        goto ret;
       len++;
     }
@@ -1446,8 +1443,8 @@ SCM_DEFINE (scm_string_suffix_length_ci, 
"string-suffix-length-ci", 2, 4, 0,
     {
       cend1--;
       cend2--;
-      if (uc_tolower (uc_toupper (scm_i_string_ref_to_wchar (s1, cend1)))
-         != uc_tolower (uc_toupper (scm_i_string_ref_to_wchar (s2, cend2))))
+      if (uc_tolower (uc_toupper (scm_i_string_ref (s1, cend1)))
+         != uc_tolower (uc_toupper (scm_i_string_ref (s2, cend2))))
        goto ret;
       len++;
     }
@@ -1476,8 +1473,8 @@ SCM_DEFINE (scm_string_prefix_p, "string-prefix?", 2, 4, 
0,
   len1 = cend1 - cstart1;
   while (cstart1 < cend1 && cstart2 < cend2)
     {
-      scm_t_wchar a = scm_i_string_ref_to_wchar (s1, cstart1);
-      scm_t_wchar b = scm_i_string_ref_to_wchar (s2, cstart2);
+      scm_t_wchar a = scm_i_string_ref (s1, cstart1);
+      scm_t_wchar b = scm_i_string_ref (s2, cstart2);
       if (a != b)
        goto ret;
       len++;
@@ -1509,8 +1506,8 @@ SCM_DEFINE (scm_string_prefix_ci_p, "string-prefix-ci?", 
2, 4, 0,
   len1 = cend1 - cstart1;
   while (cstart1 < cend1 && cstart2 < cend2)
     {
-      scm_t_wchar a = uc_tolower (uc_toupper (scm_i_string_ref_to_wchar (s1, 
cstart1)));
-      scm_t_wchar b = uc_tolower (uc_toupper (scm_i_string_ref_to_wchar (s2, 
cstart2)));
+      scm_t_wchar a = uc_tolower (uc_toupper (scm_i_string_ref (s1, cstart1)));
+      scm_t_wchar b = uc_tolower (uc_toupper (scm_i_string_ref (s2, cstart2)));
       if (a != b)
        goto ret;
       len++;
@@ -1544,8 +1541,8 @@ SCM_DEFINE (scm_string_suffix_p, "string-suffix?", 2, 4, 
0,
     {
       cend1--;
       cend2--;
-      if (scm_i_string_ref_to_wchar (s1, cend1) 
-         != scm_i_string_ref_to_wchar (s2, cend2))
+      if (scm_i_string_ref (s1, cend1) 
+         != scm_i_string_ref (s2, cend2))
        goto ret;
       len++;
     }
@@ -1578,8 +1575,8 @@ SCM_DEFINE (scm_string_suffix_ci_p, "string-suffix-ci?", 
2, 4, 0,
     {
       cend1--;
       cend2--;
-      if (uc_tolower (uc_toupper (scm_i_string_ref_to_wchar (s1, cend1)))
-         != uc_tolower (uc_toupper (scm_i_string_ref_to_wchar (s2, cend2))))
+      if (uc_tolower (uc_toupper (scm_i_string_ref (s1, cend1)))
+         != uc_tolower (uc_toupper (scm_i_string_ref (s2, cend2))))
        goto ret;
       len++;
     }
@@ -1617,7 +1614,7 @@ SCM_DEFINE (scm_string_index, "string-index", 2, 2, 0,
     {
       while (cstart < cend)
        {
-         if (REF_EQ_CHAR (s, cstart, char_pred))
+         if (scm_i_string_ref (s, cstart) == SCM_CHAR (char_pred))
            goto found;
          cstart++;
        }
@@ -1639,7 +1636,7 @@ SCM_DEFINE (scm_string_index, "string-index", 2, 2, 0,
       while (cstart < cend)
        {
          SCM res;
-         res = pred_tramp (char_pred, scm_i_string_ref (s, cstart));
+         res = pred_tramp (char_pred, SCM_MAKE_CHAR (scm_i_string_ref (s, 
cstart)));
          if (scm_is_true (res))
            goto found;
          cstart++;
@@ -1682,7 +1679,7 @@ SCM_DEFINE (scm_string_index_right, "string-index-right", 
2, 2, 0,
       while (cstart < cend)
        {
          cend--;
-         if (REF_EQ_CHAR (s, cend, char_pred))
+         if (scm_i_string_ref (s, cend) == SCM_CHAR (char_pred))
            goto found;
        }
     }
@@ -1704,7 +1701,7 @@ SCM_DEFINE (scm_string_index_right, "string-index-right", 
2, 2, 0,
        {
          SCM res;
          cend--;
-         res = pred_tramp (char_pred, scm_i_string_ref (s, cend));
+         res = pred_tramp (char_pred, SCM_MAKE_CHAR (scm_i_string_ref (s, 
cend)));
          if (scm_is_true (res))
            goto found;
        }
@@ -1767,7 +1764,7 @@ SCM_DEFINE (scm_string_skip, "string-skip", 2, 2, 0,
     {
       while (cstart < cend)
        {
-         if (!REF_EQ_CHAR (s, cstart, char_pred))
+         if (scm_i_string_ref (s, cstart) !=  SCM_CHAR (char_pred))
            goto found;
          cstart++;
        }
@@ -1789,7 +1786,7 @@ SCM_DEFINE (scm_string_skip, "string-skip", 2, 2, 0,
       while (cstart < cend)
        {
          SCM res;
-         res = pred_tramp (char_pred, scm_i_string_ref (s, cstart));
+         res = pred_tramp (char_pred, SCM_MAKE_CHAR (scm_i_string_ref (s, 
cstart)));
          if (scm_is_false (res))
            goto found;
          cstart++;
@@ -1834,7 +1831,7 @@ SCM_DEFINE (scm_string_skip_right, "string-skip-right", 
2, 2, 0,
       while (cstart < cend)
        {
          cend--;
-         if (!REF_EQ_CHAR (s, cend, char_pred))
+         if (scm_i_string_ref (s, cend) != SCM_CHAR (char_pred))
            goto found;
        }
     }
@@ -1856,7 +1853,7 @@ SCM_DEFINE (scm_string_skip_right, "string-skip-right", 
2, 2, 0,
        {
          SCM res;
          cend--;
-         res = pred_tramp (char_pred, scm_i_string_ref (s, cend));
+         res = pred_tramp (char_pred, SCM_MAKE_CHAR (scm_i_string_ref (s, 
cend)));
          if (scm_is_false (res))
            goto found;
        }
@@ -1900,7 +1897,7 @@ SCM_DEFINE (scm_string_count, "string-count", 2, 2, 0,
     {
       while (cstart < cend)
        {
-         if (REF_EQ_CHAR (s, cstart, char_pred))
+         if (scm_i_string_ref (s, cstart) == SCM_CHAR(char_pred))
            count++;
          cstart++;
        }
@@ -1922,7 +1919,7 @@ SCM_DEFINE (scm_string_count, "string-count", 2, 2, 0,
       while (cstart < cend)
        {
          SCM res;
-         res = pred_tramp (char_pred, scm_i_string_ref (s, cstart));
+         res = pred_tramp (char_pred, SCM_MAKE_CHAR (scm_i_string_ref (s, 
cstart)));
          if (scm_is_true (res))
            count++;
          cstart++;
@@ -1963,8 +1960,8 @@ SCM_DEFINE (scm_string_contains, "string-contains", 2, 4, 
0,
        j = cstart2;
        while (i < cend1 
               && j < cend2 
-              && (scm_i_string_ref_to_wchar (s1, i)
-                  == scm_i_string_ref_to_wchar (s2, j)))
+              && (scm_i_string_ref (s1, i)
+                  == scm_i_string_ref (s2, j)))
          {
            i++;
            j++;
@@ -2014,8 +2011,8 @@ SCM_DEFINE (scm_string_contains_ci, "string-contains-ci", 
2, 4, 0,
        j = cstart2;
        while (i < cend1 
               && j < cend2 
-              && (uc_tolower (uc_toupper (scm_i_string_ref_to_wchar (s1, i)))
-                  == uc_tolower (uc_toupper (scm_i_string_ref_to_wchar (s2, 
j)))))
+              && (uc_tolower (uc_toupper (scm_i_string_ref (s1, i)))
+                  == uc_tolower (uc_toupper (scm_i_string_ref (s2, j)))))
          {
            i++;
            j++;
@@ -2042,7 +2039,7 @@ string_upcase_x (SCM v, size_t start, size_t end)
 
   v = scm_i_string_start_writing (v);
   for (k = start; k < end; ++k)
-    scm_i_string_set (v, k, SCM_MAKE_CHAR (uc_toupper 
(scm_i_string_ref_to_wchar (v, k))));
+    scm_i_string_set_x (v, k, uc_toupper (scm_i_string_ref (v, k)));
   scm_i_string_stop_writing ();
 
   scm_remember_upto_here_1 (v);
@@ -2106,7 +2103,7 @@ string_downcase_x (SCM v, size_t start, size_t end)
 
   v = scm_i_string_start_writing (v);
   for (k = start; k < end; ++k)
-    scm_i_string_set (v, k, SCM_MAKE_CHAR (uc_tolower 
(scm_i_string_ref_to_wchar (v, k))));
+    scm_i_string_set_x (v, k, uc_tolower (scm_i_string_ref (v, k)));
   scm_i_string_stop_writing ();
 
   scm_remember_upto_here_1 (v);
@@ -2175,21 +2172,21 @@ string_titlecase_x (SCM str, size_t start, size_t end)
   str = scm_i_string_start_writing (str);
   for(i = start; i < end;  i++)
     {
-      ch = scm_i_string_ref (str, i);
+      ch = SCM_MAKE_CHAR (scm_i_string_ref (str, i));
       if (scm_is_true (scm_char_alphabetic_p (ch)))
        {
          if (!in_word)
            {
              scm_t_wchar uch;
              uch = uc_toupper (SCM_CHAR (ch));
-             scm_i_string_set (str, i, SCM_MAKE_CHAR (uch));
+             scm_i_string_set_x (str, i, uch);
              in_word = 1;
            }
          else
            {
              scm_t_wchar dch;
              dch = uc_tolower (SCM_CHAR (ch));
-             scm_i_string_set (str, i, SCM_MAKE_CHAR (dch));
+             scm_i_string_set_x (str, i, dch);
            }
        }
       else
@@ -2274,9 +2271,9 @@ string_reverse_x (SCM str, size_t cstart, size_t cend)
       cend--;
       while (cstart < cend)
        {
-         tmp = scm_i_string_ref (str, cstart);
-         scm_i_string_set (str, cstart, scm_i_string_ref (str, cend));
-         scm_i_string_set (str, cend, tmp);
+         tmp = SCM_MAKE_CHAR (scm_i_string_ref (str, cstart));
+         scm_i_string_set_x (str, cstart, scm_i_string_ref (str, cend));
+         scm_i_string_set_x (str, cend, SCM_CHAR (tmp));
          cstart++;
          cend--;
        }
@@ -2454,7 +2451,7 @@ SCM_DEFINE (scm_string_map, "string-map", 2, 2, 0,
       if (!SCM_CHARP (ch))
        SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (proc));
       cstart++;
-      scm_i_string_set (result, p, ch);
+      scm_i_string_set_x (result, p, SCM_CHAR (ch));
       p++;
     }
   scm_dynwind_end ();
@@ -2487,7 +2484,7 @@ SCM_DEFINE (scm_string_map_x, "string-map!", 2, 2, 0,
       SCM ch = proc_tramp (proc, scm_c_string_ref (s, cstart));
       if (!SCM_CHARP (ch))
        SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (proc));
-      scm_i_string_set (s, cstart, ch);
+      scm_i_string_set_x (s, cstart, SCM_CHAR (ch));
       cstart++;
     }
   scm_dynwind_end ();
@@ -2514,7 +2511,7 @@ SCM_DEFINE (scm_string_fold, "string-fold", 3, 2, 0,
   result = knil;
   while (cstart < cend)
     {
-      result = scm_call_2 (kons, scm_i_string_ref (s, cstart), result);
+      result = scm_call_2 (kons, SCM_MAKE_CHAR (scm_i_string_ref (s, cstart)), 
result);
       cstart++;
     }
 
@@ -2542,7 +2539,7 @@ SCM_DEFINE (scm_string_fold_right, "string-fold-right", 
3, 2, 0,
   result = knil;
   while (cstart < cend)
     {
-      result = scm_call_2 (kons, scm_i_string_ref (s, cend-1), result);
+      result = scm_call_2 (kons, SCM_MAKE_CHAR (scm_i_string_ref (s, cend-1)), 
result);
       cend--;
     }
 
@@ -2599,7 +2596,7 @@ SCM_DEFINE (scm_string_unfold, "string-unfold", 4, 2, 0,
        SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (f));
       str = scm_i_make_string (1, NULL);
       str = scm_i_string_start_writing (str);
-      scm_i_string_set (str, i, ch);
+      scm_i_string_set_x (str, i, SCM_CHAR (ch));
       scm_i_string_stop_writing ();
       i++;
 
@@ -2665,7 +2662,7 @@ SCM_DEFINE (scm_string_unfold_right, 
"string-unfold-right", 4, 2, 0,
        SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (f));
       str = scm_i_make_string (1, NULL);
       str = scm_i_string_start_writing (str);
-      scm_i_string_set (str, i, ch);
+      scm_i_string_set_x (str, i, SCM_CHAR (ch));
       scm_i_string_stop_writing ();
       i++;
 
@@ -2699,7 +2696,7 @@ SCM_DEFINE (scm_string_for_each, "string-for-each", 2, 2, 
0,
                              4, end, cend);
   while (cstart < cend)
     {
-      proc_tramp (proc, scm_i_string_ref (s, cstart));
+      proc_tramp (proc, SCM_MAKE_CHAR (scm_i_string_ref (s, cstart)));
       cstart++;
     }
 
@@ -2786,9 +2783,10 @@ SCM_DEFINE (scm_xsubstring, "xsubstring", 2, 3, 0,
     {
       size_t t = ((cfrom < 0) ? -cfrom : cfrom) % (cend - cstart);
       if (cfrom < 0)
-       scm_i_string_set (result, p, scm_i_string_ref (s, (cend - cstart) - t));
+       scm_i_string_set_x (result, p, 
+                            scm_i_string_ref (s, (cend - cstart) - t));
       else
-       scm_i_string_set (result, p, scm_i_string_ref (s, t));
+       scm_i_string_set_x (result, p, scm_i_string_ref (s, t));
       cfrom++;
       p++;
     }
@@ -2837,9 +2835,9 @@ SCM_DEFINE (scm_string_xcopy_x, "string-xcopy!", 4, 3, 0,
     {
       size_t t = ((csfrom < 0) ? -csfrom : csfrom) % (cend - cstart);
       if (csfrom < 0)
-       scm_i_string_set (target, p + cstart, scm_i_string_ref (s, (cend - 
cstart) - t));
+       scm_i_string_set_x (target, p + cstart, scm_i_string_ref (s, (cend - 
cstart) - t));
       else
-       scm_i_string_set (target, p + cstart, scm_i_string_ref (s, t));
+       scm_i_string_set_x (target, p + cstart, scm_i_string_ref (s, t));
       csfrom++;
       p++;
     }
@@ -2961,7 +2959,7 @@ SCM_DEFINE (scm_string_split, "string-split", 2, 0, 0,
   while (idx >= 0)
     {
       last_idx = idx;
-      while (idx > 0 && !REF_EQ_CHAR (str, idx-1, chr))
+      while (idx > 0 && scm_i_string_ref (str, idx-1) != SCM_CHAR(chr))
        idx--;
       if (idx >= 0)
        {
@@ -3003,17 +3001,17 @@ SCM_DEFINE (scm_string_filter, "string-filter", 2, 2, 0,
       size_t count;
 
       /* strip leading non-matches by incrementing cstart */
-      while (cstart < cend && !REF_EQ_CHAR (s, cstart, char_pred))
+      while (cstart < cend && scm_i_string_ref (s, cstart) != SCM_CHAR 
(char_pred))
         cstart++;
 
       /* strip trailing non-matches by decrementing cend */
-      while (cend > cstart && !REF_EQ_CHAR (s, cend-1, char_pred))
+      while (cend > cstart && scm_i_string_ref (s, cend-1) != SCM_CHAR 
(char_pred))
         cend--;
 
       /* count chars to keep */
       count = 0;
       for (idx = cstart; idx < cend; idx++)
-        if (REF_EQ_CHAR (s, idx, char_pred))
+        if (scm_i_string_ref (s, idx) == SCM_CHAR (char_pred))
           count++;
 
       if (count == cend - cstart)
@@ -3060,7 +3058,7 @@ SCM_DEFINE (scm_string_filter, "string-filter", 2, 2, 0,
             {
               if (REF_IN_CHARSET (s, idx, char_pred))
                 {
-                 scm_i_string_set (result, dst, scm_i_string_ref (s, idx));
+                 scm_i_string_set_x (result, dst, scm_i_string_ref (s, idx));
                  dst ++;
                   count--;
                 }
@@ -3078,7 +3076,7 @@ SCM_DEFINE (scm_string_filter, "string-filter", 2, 2, 0,
       while (idx < cend)
        {
          SCM res, ch;
-         ch = scm_i_string_ref (s, idx);
+         ch = SCM_MAKE_CHAR (scm_i_string_ref (s, idx));
          res = pred_tramp (char_pred, ch);
          if (scm_is_true (res))
            ls = scm_cons (ch, ls);
@@ -3120,17 +3118,17 @@ SCM_DEFINE (scm_string_delete, "string-delete", 2, 2, 0,
       size_t count;
 
       /* strip leading matches by incrementing cstart */
-      while (cstart < cend && REF_EQ_CHAR (s, cstart, char_pred))
+      while (cstart < cend && scm_i_string_ref (s, cstart) == 
SCM_CHAR(char_pred))
         cstart++;
 
       /* strip trailing matches by decrementing cend */
-      while (cend > cstart && REF_EQ_CHAR (s, cend-1, char_pred))
+      while (cend > cstart && scm_i_string_ref (s, cend-1) == SCM_CHAR 
(char_pred))
         cend--;
 
       /* count chars to be kept */
       count = 0;
       for (idx = cstart; idx < cend; idx++)
-        if (!REF_EQ_CHAR (s, idx, char_pred))
+        if (scm_i_string_ref (s, idx) != SCM_CHAR (char_pred))
           count++;
 
       if (count == cend - cstart)
@@ -3151,10 +3149,10 @@ SCM_DEFINE (scm_string_delete, "string-delete", 2, 2, 0,
              it'll make us copy more than count characters */
           for (idx = cstart; idx < cend && count != 0; idx++)
             {
-             SCM c = scm_i_string_ref (s, idx);
-              if (scm_is_false (scm_eqv_p (c, char_pred)))
+             scm_t_wchar c = scm_i_string_ref (s, idx);
+              if (c != SCM_CHAR (char_pred))
                 {
-                  scm_i_string_set (result, i, c);
+                  scm_i_string_set_x (result, i, c);
                  i++;
                   count--;
                 }
@@ -3196,7 +3194,7 @@ SCM_DEFINE (scm_string_delete, "string-delete", 2, 2, 0,
             {
               if (! REF_IN_CHARSET (s, idx, char_pred))
                 {
-                 scm_i_string_set (result, i, scm_i_string_ref (s, idx));
+                 scm_i_string_set_x (result, i, scm_i_string_ref (s, idx));
                  i++;
                   count--;
                 }
@@ -3213,7 +3211,7 @@ SCM_DEFINE (scm_string_delete, "string-delete", 2, 2, 0,
       idx = cstart;
       while (idx < cend)
        {
-         SCM res, ch = scm_i_string_ref (s, idx);
+         SCM res, ch = SCM_MAKE_CHAR (scm_i_string_ref (s, idx));
          res = pred_tramp (char_pred, ch);
          if (scm_is_false (res))
            ls = scm_cons (ch, ls);
diff --git a/libguile/srfi-14.c b/libguile/srfi-14.c
index e2df1e2..1a8ca1e 100644
--- a/libguile/srfi-14.c
+++ b/libguile/srfi-14.c
@@ -236,7 +236,7 @@ scm_i_charset_unset (scm_t_char_set *cs, scm_t_wchar n)
                                        "character-set");
           if (i < len - 1)
             memmove (cs->ranges + (i+2), cs->ranges + (i+1), 
-                     sizeof (scm_t_char_range) * (len - i));
+                     sizeof (scm_t_char_range) * (len - i - 1));
           cs->ranges[i+1].hi = cs->ranges[i].hi;
           cs->ranges[i+1].lo = n + 1;
           cs->ranges[i].hi = n - 1;
@@ -474,6 +474,7 @@ charset_print (SCM charset, SCM port, scm_print_state 
*pstate SCM_UNUSED)
   size_t i;
   int first = 1;
   scm_t_char_set *p;
+  const size_t max_ranges_to_print = 100;
 
   p = SCM_CHARSET_DATA (charset);
 
@@ -490,6 +491,12 @@ charset_print (SCM charset, SCM port, scm_print_state 
*pstate SCM_UNUSED)
           scm_puts ("..", port);
           scm_write (SCM_MAKE_CHAR (p->ranges[i].hi), port);
         }
+      if (i >= max_ranges_to_print)
+        {
+          /* Too many to print here.  Quit early.  */
+          scm_puts (" ...", port);
+          break;
+        }
     }
   scm_puts ("}>", port);
   return 1;
@@ -501,7 +508,7 @@ static size_t
 charset_free (SCM charset)
 {
   scm_t_char_set *cs;
-  size_t len;
+  size_t len = 0;
 
   cs = SCM_CHARSET_DATA (charset);
   if (cs != NULL)
@@ -1105,7 +1112,7 @@ SCM_DEFINE (scm_string_to_char_set, "string->char-set", 
1, 1, 0,
   len = scm_i_string_length (str);
   while (k < len)
     {
-      scm_t_wchar c = scm_i_string_ref_to_wchar (str, k++);
+      scm_t_wchar c = scm_i_string_ref (str, k++);
       SCM_CHARSET_SET (cs, c);
     }
   scm_remember_upto_here_1 (str);
@@ -1128,7 +1135,7 @@ SCM_DEFINE (scm_string_to_char_set_x, 
"string->char-set!", 2, 0, 0,
   len = scm_i_string_length (str);
   while (k < len)
     {
-      scm_t_wchar c = scm_i_string_ref_to_wchar (str, k++);
+      scm_t_wchar c = scm_i_string_ref (str, k++);
       SCM_CHARSET_SET(base_cs, c);
     }
   scm_remember_upto_here_1 (str);
@@ -1930,7 +1937,7 @@ define_charset (const char *name)
 #define CSET_TITLE_PRED(c)       (uc_is_general_category_withtable (c, 
UC_CATEGORY_MASK_Lt))
 #define CSET_LETTER_PRED(c)      (uc_is_general_category_withtable (c, 
UC_CATEGORY_MASK_L))
 #define CSET_DIGIT_PRED(c)       (uc_is_general_category_withtable (c, 
UC_CATEGORY_MASK_Nd))
-#define CSET_WHITESPACE_PRED(c)  (uc_is_general_category_withtable (c, 
UC_CATEGORY_MASK_Zs))
+#define CSET_WHITESPACE_PRED(c)  (uc_is_property_white_space (c))
 #define CSET_CONTROL_PRED(c)     (uc_is_general_category_withtable (c, 
UC_CATEGORY_MASK_Cc))
 #define CSET_GRAPHIC_PRED(c)     (uc_is_general_category_withtable (c, 
UC_CATEGORY_MASK_L \
                                                                     | 
UC_CATEGORY_MASK_M \
diff --git a/libguile/strings.c b/libguile/strings.c
index 1958b20..becae10 100644
--- a/libguile/strings.c
+++ b/libguile/strings.c
@@ -542,17 +542,8 @@ scm_i_string_stop_writing (void)
 }
 
 /* Return the Xth character is C.  */
-SCM
-scm_i_string_ref(SCM str, size_t x)
-{
-  if (scm_i_is_narrow_string (str))
-    return SCM_MAKE_CHAR (scm_i_string_chars (str)[x]);
-  else
-    return SCM_MAKE_CHAR (scm_i_string_wide_chars (str)[x]);
-}
-
 scm_t_wchar
-scm_i_string_ref_to_wchar (SCM str, size_t x)
+scm_i_string_ref (SCM str, size_t x)
 {
   if (scm_i_is_narrow_string (str))
     return (scm_t_wchar) (unsigned char) (scm_i_string_chars (str)[x]);
@@ -560,24 +551,6 @@ scm_i_string_ref_to_wchar (SCM str, size_t x)
     return scm_i_string_wide_chars (str)[x];
 }
 
-int
-scm_i_string_ref_eq_char (SCM str, size_t x, char c)
-{
-  if (scm_i_is_narrow_string (str))
-    return (c == scm_i_string_chars (str)[x]);
-  else
-    return ((unsigned char) c == scm_i_string_wide_chars (str) [x]);
-}
-
-int
-scm_i_string_ref_eq_wchar (SCM str, size_t x, scm_t_wchar c)
-{
-  if (scm_i_is_narrow_string (str))
-    return (c == (scm_t_wchar) (unsigned char) scm_i_string_chars (str)[x]);
-  else
-    return (c == scm_i_string_wide_chars (str)[x]);
-}
-
 /* Returns the index of the first char in STR that matches C.  */
 int
 scm_i_string_contains_char (SCM str, char ch)
@@ -632,17 +605,7 @@ scm_i_string_strcmp (SCM sstr, size_t start_x, const char 
*cstr)
 }
 
 void
-scm_i_string_set (SCM str, size_t p, SCM chr)
-{
-  scm_t_wchar c;
-
-  c = SCM_CHAR (chr);
-
-  scm_i_string_set_from_wchar (str, p, c);
-}
-
-void
-scm_i_string_set_from_wchar (SCM str, size_t p, scm_t_wchar chr)
+scm_i_string_set_x (SCM str, size_t p, scm_t_wchar chr)
 {
   if (chr > 0xFF && scm_i_is_narrow_string (str))
     widen_stringbuf (STRING_STRINGBUF (str));
@@ -810,17 +773,8 @@ scm_i_symbol_substring (SCM sym, size_t start, size_t end)
                          (scm_t_bits)start, (scm_t_bits) end - start);
 }
 
-SCM
-scm_i_symbol_ref (SCM sym, size_t x)
-{
-  if (scm_i_is_narrow_symbol (sym))
-    return SCM_MAKE_CHAR (scm_i_symbol_chars (sym)[x]);
-  else
-    return SCM_MAKE_CHAR (scm_i_symbol_wide_chars (sym)[x]);
-}
-
 scm_t_wchar
-scm_i_symbol_ref_to_wchar (SCM sym, size_t x)
+scm_i_symbol_ref (SCM sym, size_t x)
 {
   if (scm_i_is_narrow_symbol (sym))
     return (scm_t_wchar) (unsigned char) (scm_i_symbol_chars (sym)[x]);
@@ -828,36 +782,6 @@ scm_i_symbol_ref_to_wchar (SCM sym, size_t x)
     return scm_i_symbol_wide_chars (sym)[x];
 }
 
-
-/* Return the Xth character of the name of SYM, or UNDEF if the Xth
-   character is not 8-bit. */
-char
-scm_i_symbol_ref_to_char (SCM sym, size_t x, char undef)
-{
-  scm_t_wchar ch;
-  if (scm_i_is_narrow_symbol (sym))
-    {
-      return scm_i_symbol_chars (sym)[x];
-    }
-  else
-    {
-      ch = scm_i_symbol_wide_chars (sym)[x];
-      if (ch < 0xFF)
-       return (char) (unsigned char) ch;
-      else
-       return undef;
-    }
-}
-
-int
-scm_i_symbol_ref_eq_char (SCM sym, size_t x, char c)
-{
-  if (scm_i_is_narrow_symbol (sym))
-    return (c == scm_i_symbol_chars (sym)[x]);
-  else
-    return ((unsigned char) c == scm_i_symbol_wide_chars (sym)[x]);
-}
-
 int
 scm_i_symbol_strcmp (SCM sym, char *str)
 {
@@ -1016,7 +940,7 @@ SCM_DEFINE (scm_string, "string", 0, 0, 1,
       SCM elt = SCM_CAR (chrs);
 
       SCM_VALIDATE_CHAR (SCM_ARGn, elt);
-      scm_i_string_set (result, p, elt);
+      scm_i_string_set_x (result, p, SCM_CHAR (elt));
       p++;
       chrs = SCM_CDR (chrs);
       len--;
@@ -1061,7 +985,7 @@ scm_c_make_string (size_t len, SCM chr)
     {
       SCM_VALIDATE_CHAR (0, chr);
       for (p = 0; p < len; p ++)
-       scm_i_string_set (res, p, chr);
+       scm_i_string_set_x (res, p, SCM_CHAR (chr));
     }
   scm_dynwind_end ();
 
@@ -1144,7 +1068,7 @@ SCM_DEFINE (scm_string_set_x, "string-set!", 3, 0, 0,
   SCM_VALIDATE_CHAR (3, chr);
 
   str = scm_i_string_start_writing (str);
-  scm_i_string_set (str, idx, chr);
+  scm_i_string_set_x (str, idx, SCM_CHAR (chr));
   scm_i_string_stop_writing ();
 
   return SCM_UNSPECIFIED;
@@ -1158,7 +1082,7 @@ scm_c_string_set_x (SCM str, size_t p, SCM chr)
     scm_out_of_range (NULL, scm_from_size_t (p));
 
   str = scm_i_string_start_writing (str);
-  scm_i_string_set (str, p, chr);
+  scm_i_string_set_x (str, p, SCM_CHAR (chr));
   scm_i_string_stop_writing ();
 }
 
@@ -1552,7 +1476,7 @@ scm_to_encoded_stringn (SCM str, size_t *lenp, const char 
*encoding,
        
   if (lenp == NULL)
     for (i = 0; i < ilen; i++)
-      if (scm_i_string_ref_eq_char (str, i, '\0'))
+      if (scm_i_string_ref (str, i) == '\0')
          scm_misc_error (NULL,
                          "string contains #\\nul character: ~S",
                          scm_list_1 (str));
diff --git a/libguile/strings.h b/libguile/strings.h
index 29ac8de..3efdb72 100644
--- a/libguile/strings.h
+++ b/libguile/strings.h
@@ -132,14 +132,10 @@ SCM_API /* FIXME: not internal */ char 
*scm_i_string_writable_chars (SCM str);
 SCM_INTERNAL SCM scm_i_string_start_writing (SCM str);
 SCM_INTERNAL void scm_i_string_stop_writing (void);
 SCM_INTERNAL int scm_i_is_narrow_string (SCM str);
-SCM_INTERNAL SCM scm_i_string_ref (SCM str, size_t x);
-SCM_INTERNAL scm_t_wchar scm_i_string_ref_to_wchar (SCM str, size_t x);
-SCM_INTERNAL int scm_i_string_ref_eq_char (SCM str, size_t x, char c);
-SCM_INTERNAL int scm_i_string_ref_eq_wchar (SCM str, size_t x, scm_t_wchar c);
+SCM_INTERNAL scm_t_wchar scm_i_string_ref (SCM str, size_t x);
 SCM_INTERNAL int scm_i_string_contains_char (SCM str, char c);
 SCM_INTERNAL int scm_i_string_strcmp (SCM sstr, size_t start_x, const char 
*cstr);
-SCM_INTERNAL void scm_i_string_set (SCM str, size_t x, SCM chr);
-SCM_INTERNAL void scm_i_string_set_from_wchar (SCM str, size_t p, scm_t_wchar 
chr);
+SCM_INTERNAL void scm_i_string_set_x (SCM str, size_t p, scm_t_wchar chr);
 
 /* internal functions related to symbols. */
 
@@ -156,10 +152,7 @@ SCM_INTERNAL const scm_t_wchar *scm_i_symbol_wide_chars 
(SCM sym);
 SCM_INTERNAL size_t scm_i_symbol_length (SCM sym);
 SCM_INTERNAL int scm_i_is_narrow_symbol (SCM str);
 SCM_INTERNAL SCM scm_i_symbol_substring (SCM sym, size_t start, size_t end);
-SCM_INTERNAL SCM scm_i_symbol_ref (SCM sym, size_t x);
-SCM_INTERNAL scm_t_wchar scm_i_symbol_ref_to_wchar (SCM sym, size_t x);
-SCM_INTERNAL char scm_i_symbol_ref_to_char (SCM sym, size_t x, char undef);
-SCM_INTERNAL int scm_i_symbol_ref_eq_char (SCM sym, size_t x, char c);
+SCM_INTERNAL scm_t_wchar scm_i_symbol_ref (SCM sym, size_t x);
 SCM_INTERNAL int scm_i_symbol_strcmp (SCM sym, char *str);
 
 
diff --git a/libguile/strports.c b/libguile/strports.c
index d1d238a..5065af6 100644
--- a/libguile/strports.c
+++ b/libguile/strports.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995,1996,1998,1999,2000,2001,2002, 2003, 2005, 2006 Free 
Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1998,1999,2000,2001,2002, 2003, 2005, 2006, 2009 
Free Software Foundation, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -109,7 +109,7 @@ stfill_buffer (SCM port)
 /* change the size of a port's string to new_size.  this doesn't
    change read_buf_size.  */
 static void 
-st_resize_port (scm_t_port *pt, off_t new_size)
+st_resize_port (scm_t_port *pt, scm_t_off new_size)
 {
   SCM old_stream = SCM_PACK (pt->stream);
   const char *src = scm_i_string_chars (old_stream);
@@ -119,7 +119,7 @@ st_resize_port (scm_t_port *pt, off_t new_size)
   unsigned long int min_size = min (old_size, new_size);
   unsigned long int i;
 
-  off_t index = pt->write_pos - pt->write_buf;
+  scm_t_off index = pt->write_pos - pt->write_buf;
 
   pt->write_buf_size = new_size;
 
@@ -200,11 +200,11 @@ st_end_input (SCM port, int offset)
   pt->rw_active = SCM_PORT_NEITHER;
 }
 
-static off_t
-st_seek (SCM port, off_t offset, int whence)
+static scm_t_off
+st_seek (SCM port, scm_t_off offset, int whence)
 {
   scm_t_port *pt = SCM_PTAB_ENTRY (port);
-  off_t target;
+  scm_t_off target;
 
   if (pt->rw_active == SCM_PORT_READ && offset == 0 && whence == SEEK_CUR)
     /* special case to avoid disturbing the unread-char buffer.  */
@@ -273,7 +273,7 @@ st_seek (SCM port, off_t offset, int whence)
 }
 
 static void
-st_truncate (SCM port, off_t length)
+st_truncate (SCM port, scm_t_off length)
 {
   scm_t_port *pt = SCM_PTAB_ENTRY (port);
 
diff --git a/libguile/struct.c b/libguile/struct.c
index 72e1457..a486896 100644
--- a/libguile/struct.c
+++ b/libguile/struct.c
@@ -74,7 +74,7 @@ SCM_DEFINE (scm_make_struct_layout, "make-struct-layout", 1, 
0, 0,
 
     for (x = 0; x < len; x += 2)
       {
-       switch (c = scm_i_string_ref_to_wchar (fields, x))
+       switch (c = scm_i_string_ref (fields, x))
          {
          case 'u':
          case 'p':
@@ -89,10 +89,10 @@ SCM_DEFINE (scm_make_struct_layout, "make-struct-layout", 
1, 0, 0,
                            scm_list_1 (SCM_MAKE_CHAR (c)));
          }
 
-       switch (c = scm_i_string_ref_to_wchar (fields, x + 1))
+       switch (c = scm_i_string_ref (fields, x + 1))
          {
          case 'w':
-           if (scm_i_string_ref_eq_char (fields, x, 's'))
+           if (scm_i_string_ref (fields, x) == 's')
              SCM_MISC_ERROR ("self fields not writable", SCM_EOL);
          case 'r':
          case 'o':
@@ -100,7 +100,7 @@ SCM_DEFINE (scm_make_struct_layout, "make-struct-layout", 
1, 0, 0,
          case 'R':
          case 'W':
          case 'O':
-           if (scm_i_string_ref_eq_char (fields, x, 's'))
+           if (scm_i_string_ref (fields, x) == 's')
              SCM_MISC_ERROR ("self fields not allowed in tail array", 
                              SCM_EOL);
            if (x != len - 2)
@@ -112,9 +112,9 @@ SCM_DEFINE (scm_make_struct_layout, "make-struct-layout", 
1, 0, 0,
                            scm_list_1 (SCM_MAKE_CHAR (c)));
          }
 #if 0
-       if (scm_i_string_ref_eq_char (fields, x, 'd'))
+       if (scm_i_string_ref (fields, x, 'd'))
          {
-           if (!scm_i_string_ref_eq_char (fields, x+2, '-'))
+           if (!scm_i_string_ref (fields, x+2, '-'))
              SCM_MISC_ERROR ("missing dash field at position ~A",
                              scm_list_1 (scm_from_int (x / 2)));
            x += 2;
@@ -147,7 +147,7 @@ scm_struct_init (SCM handle, SCM layout, scm_t_bits * mem, 
int tail_elts, SCM in
       if (!tailp)
        {
          i += 2;
-         prot = scm_i_symbol_ref_to_wchar (layout, i+1);
+         prot = scm_i_symbol_ref (layout, i+1);
          if (SCM_LAYOUT_TAILP (prot))
            {
              tailp = 1;
@@ -160,7 +160,7 @@ scm_struct_init (SCM handle, SCM layout, scm_t_bits * mem, 
int tail_elts, SCM in
            }
        }
 
-      switch (scm_i_symbol_ref_to_wchar (layout, i))
+      switch (scm_i_symbol_ref (layout, i))
        {
 #if 0
        case 'i':
@@ -649,7 +649,7 @@ SCM_DEFINE (scm_struct_ref, "struct-ref", 2, 0, 0,
   size_t layout_len;
   size_t p;
   scm_t_bits n_fields;
-  char field_type = 0;
+  scm_t_wchar field_type = 0;
   
 
   SCM_VALIDATE_STRUCT (1, handle);
@@ -669,9 +669,9 @@ SCM_DEFINE (scm_struct_ref, "struct-ref", 2, 0, 0,
 
   if (p * 2 < layout_len)
     {
-      char ref;
-      field_type = scm_i_symbol_ref_to_char (layout, p * 2, '?');
-      ref = scm_i_symbol_ref_to_char (layout, p * 2 + 1, '?');
+      scm_t_wchar ref;
+      field_type = scm_i_symbol_ref (layout, p * 2);
+      ref = scm_i_symbol_ref (layout, p * 2 + 1);
       if ((ref != 'r') && (ref != 'w'))
        {
          if ((ref == 'R') || (ref == 'W'))
@@ -680,8 +680,8 @@ SCM_DEFINE (scm_struct_ref, "struct-ref", 2, 0, 0,
            SCM_MISC_ERROR ("ref denied for field ~A", scm_list_1 (pos));
        }
     }
-  else if (!scm_i_symbol_ref_eq_char (layout, layout_len - 1, 'O'))
-    field_type = scm_i_symbol_ref_to_char(layout, layout_len - 2, '?');
+  else if (scm_i_symbol_ref (layout, layout_len - 1) != 'O')
+    field_type = scm_i_symbol_ref(layout, layout_len - 2);
   else
     SCM_MISC_ERROR ("ref denied for field ~A", scm_list_1 (pos));
   
@@ -709,7 +709,7 @@ SCM_DEFINE (scm_struct_ref, "struct-ref", 2, 0, 0,
 
     default:
       SCM_MISC_ERROR ("unrecognized field type: ~S",
-                     scm_list_1 (scm_i_symbol_ref (layout, layout_len - 2)));
+                     scm_list_1 (SCM_MAKE_CHAR (scm_i_symbol_ref (layout, 
layout_len - 2))));
     }
 
   return answer;
@@ -729,8 +729,7 @@ SCM_DEFINE (scm_struct_set_x, "struct-set!", 3, 0, 0,
   size_t layout_len;
   size_t p;
   int n_fields;
-  char field_type = 0;
-  SCM field_scm_type;
+  scm_t_wchar field_type = 0;
 
   SCM_VALIDATE_STRUCT (1, handle);
 
@@ -750,16 +749,14 @@ SCM_DEFINE (scm_struct_set_x, "struct-set!", 3, 0, 0,
   if (p * 2 < layout_len)
     {
       char set_x;
-      field_type = scm_i_symbol_ref_to_char (layout, p * 2, '?');
-      field_scm_type = scm_i_symbol_ref (layout, p * 2);
-      set_x = scm_i_symbol_ref_to_char (layout, p * 2 + 1, '?');
+      field_type = scm_i_symbol_ref (layout, p * 2);
+      set_x = scm_i_symbol_ref (layout, p * 2 + 1);
       if (set_x != 'w')
        SCM_MISC_ERROR ("set! denied for field ~A", scm_list_1 (pos));
     }
-  else if (scm_i_symbol_ref_eq_char (layout, layout_len - 1, 'W'))    
+  else if (scm_i_symbol_ref (layout, layout_len - 1) == 'W')    
     {
-      field_type = scm_i_symbol_ref_to_char (layout, layout_len - 2, '?');
-      field_scm_type = scm_i_symbol_ref (layout, layout_len - 2);
+      field_type = scm_i_symbol_ref (layout, layout_len - 2);
     }
   else
     SCM_MISC_ERROR ("set! denied for field ~A", scm_list_1 (pos));
@@ -789,7 +786,7 @@ SCM_DEFINE (scm_struct_set_x, "struct-set!", 3, 0, 0,
 
     default:
       SCM_MISC_ERROR ("unrecognized field type: ~S",
-                     scm_list_1 (field_scm_type));
+                     scm_list_1 (SCM_MAKE_CHAR (field_type)));
     }
 
   return val;
diff --git a/libguile/symbols.c b/libguile/symbols.c
index e93666b..aace16b 100644
--- a/libguile/symbols.c
+++ b/libguile/symbols.c
@@ -111,8 +111,7 @@ lookup_interned_symbol (SCM name, unsigned long raw_hash)
          while (i != 0)
            {
              --i;
-             if (scm_is_false (scm_eqv_p (scm_i_string_ref (name, i),
-                                          scm_i_symbol_ref (sym, i))))
+             if (scm_i_string_ref (name, i) != scm_i_symbol_ref (sym, i))
                goto next_symbol;
            }
 
diff --git a/libguile/unif.c b/libguile/unif.c
index 3a6790e..cf39d05 100644
--- a/libguile/unif.c
+++ b/libguile/unif.c
@@ -1198,7 +1198,7 @@ SCM_DEFINE (scm_enclose_array, "enclose-array", 1, 0, 1,
     }
   for (j = 0, k = 0; k < noutr; k++, j++)
     {
-      while (!scm_i_string_ref_eq_char (axv, j, '\0'))
+      while (!scm_i_string_ref (axv, j) == '\0')
        j++;
       SCM_I_ARRAY_DIMS (res)[k].lbnd = s[j].lbnd;
       SCM_I_ARRAY_DIMS (res)[k].ubnd = s[j].ubnd;
@@ -2340,7 +2340,7 @@ scm_istr2bve (SCM str)
       if (j > 32)
        j = 32;
       for (mask = 1L; j--; mask <<= 1)
-       switch (scm_i_string_ref_to_wchar (str, p++))
+       switch (scm_i_string_ref (str, p++))
          {
          case '0':
            break;
diff --git a/libguile/vm-engine.c b/libguile/vm-engine.c
index 978d407..90cf697 100644
--- a/libguile/vm-engine.c
+++ b/libguile/vm-engine.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2009 Free Software Foundation, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -203,6 +203,12 @@ VM_NAME (struct scm_vm *vp, SCM program, SCM *argv, int 
nargs)
     /* shouldn't get here */
     goto vm_error;
 
+  vm_error_not_a_bytevector:
+    SYNC_ALL ();
+    scm_wrong_type_arg_msg (FUNC_NAME, 1, finish_args, "bytevector");
+    /* shouldn't get here */
+    goto vm_error;
+
   vm_error_no_values:
     err_msg  = scm_from_locale_string ("VM: 0-valued return");
     finish_args = SCM_EOL;
diff --git a/libguile/vm-engine.h b/libguile/vm-engine.h
index c98dfdd..d684979 100644
--- a/libguile/vm-engine.h
+++ b/libguile/vm-engine.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2009 Free Software Foundation, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -54,13 +54,9 @@
 #endif
 #endif
 #ifdef __i386__
-/* gcc on lenny actually crashes if we allocate these variables in registers.
-   hopefully this is the only one of these. */
-#if !(__GNUC__==4 && __GNUC_MINOR__==1 && __GNUC_PATCHLEVEL__==2)
-#define IP_REG asm("%esi")
-#define SP_REG asm("%edi")
-#define FP_REG
-#endif
+/* too few registers! because of register allocation errors with various gcs,
+   just punt on explicit assignments on i386, hoping that the "register"
+   declaration will be sufficient. */
 #endif
 #if defined(PPC) || defined(_POWER) || defined(_IBMR2)
 #define IP_REG asm("26")
diff --git a/libguile/vm-i-scheme.c b/libguile/vm-i-scheme.c
index 02139c0..5de39a2 100644
--- a/libguile/vm-i-scheme.c
+++ b/libguile/vm-i-scheme.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2009 Free Software Foundation, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -131,20 +131,24 @@ VM_DEFINE_FUNCTION (92, cdr, "cdr", 1)
   RETURN (SCM_CDR (x));
 }
 
-VM_DEFINE_FUNCTION (93, set_car, "set-car!", 2)
+VM_DEFINE_INSTRUCTION (93, set_car, "set-car!", 0, 2, 0)
 {
-  ARGS2 (x, y);
+  SCM x, y;
+  POP (y);
+  POP (x);
   VM_VALIDATE_CONS (x);
   SCM_SETCAR (x, y);
-  RETURN (SCM_UNSPECIFIED);
+  NEXT;
 }
 
-VM_DEFINE_FUNCTION (94, set_cdr, "set-cdr!", 2)
+VM_DEFINE_INSTRUCTION (94, set_cdr, "set-cdr!", 0, 2, 0)
 {
-  ARGS2 (x, y);
+  SCM x, y;
+  POP (y);
+  POP (x);
   VM_VALIDATE_CONS (x);
   SCM_SETCDR (x, y);
-  RETURN (SCM_UNSPECIFIED);
+  NEXT;
 }
 
 
@@ -263,15 +267,265 @@ VM_DEFINE_FUNCTION (107, slot_ref, "slot-ref", 2)
   RETURN (SCM_PACK (SCM_STRUCT_DATA (instance) [slot]));
 }
 
-VM_DEFINE_FUNCTION (108, slot_set, "slot-set", 3)
+VM_DEFINE_INSTRUCTION (108, slot_set, "slot-set", 0, 3, 0)
 {
+  SCM instance, idx, val;
   size_t slot;
-  ARGS3 (instance, idx, val);
+  POP (val);
+  POP (idx);
+  POP (instance);
   slot = SCM_I_INUM (idx);
   SCM_STRUCT_DATA (instance) [slot] = SCM_UNPACK (val);
-  RETURN (SCM_UNSPECIFIED);
+  NEXT;
+}
+
+VM_DEFINE_FUNCTION (109, vector_ref, "vector-ref", 2)
+{
+  long i;
+  ARGS2 (vect, idx);
+  if (SCM_LIKELY (SCM_I_IS_VECTOR (vect)
+                  && SCM_I_INUMP (idx)
+                  && ((i = SCM_I_INUM (idx)) >= 0)
+                  && i < SCM_I_VECTOR_LENGTH (vect)))
+    RETURN (SCM_I_VECTOR_ELTS (vect)[i]);
+  else
+    RETURN (scm_vector_ref (vect, idx));
+}
+
+VM_DEFINE_INSTRUCTION (110, vector_set, "vector-set", 0, 3, 0)
+{
+  long i;
+  SCM vect, idx, val;
+  POP (val); POP (idx); POP (vect);
+  if (SCM_LIKELY (SCM_I_IS_VECTOR (vect)
+                  && SCM_I_INUMP (idx)
+                  && ((i = SCM_I_INUM (idx)) >= 0)
+                  && i < SCM_I_VECTOR_LENGTH (vect)))
+    SCM_I_VECTOR_WELTS (vect)[i] = val;
+  else
+    scm_vector_set_x (vect, idx, val);
+  NEXT;
+}
+
+#define VM_VALIDATE_BYTEVECTOR(x)               \
+  if (SCM_UNLIKELY (!SCM_BYTEVECTOR_P (x)))     \
+    { finish_args = x;                          \
+      goto vm_error_not_a_bytevector;           \
+    }
+
+#define BV_REF_WITH_ENDIANNESS(stem, fn_stem)                           \
+{                                                                       \
+  SCM endianness;                                                       \
+  POP (endianness);                                                     \
+  if (scm_is_eq (endianness, scm_i_native_endianness))                  \
+    goto VM_LABEL (bv_##stem##_native_ref);                             \
+  {                                                                     \
+    ARGS2 (bv, idx);                                                    \
+    RETURN (scm_bytevector_##fn_stem##_ref (bv, idx, endianness));      \
+  }                                                                     \
+}
+
+VM_DEFINE_FUNCTION (111, bv_u16_ref, "bv-u16-ref", 3)
+BV_REF_WITH_ENDIANNESS (u16, u16)
+VM_DEFINE_FUNCTION (112, bv_s16_ref, "bv-s16-ref", 3)
+BV_REF_WITH_ENDIANNESS (s16, s16)
+VM_DEFINE_FUNCTION (113, bv_u32_ref, "bv-u32-ref", 3)
+BV_REF_WITH_ENDIANNESS (u32, u32)
+VM_DEFINE_FUNCTION (114, bv_s32_ref, "bv-s32-ref", 3)
+BV_REF_WITH_ENDIANNESS (s32, s32)
+VM_DEFINE_FUNCTION (115, bv_u64_ref, "bv-u64-ref", 3)
+BV_REF_WITH_ENDIANNESS (u64, u64)
+VM_DEFINE_FUNCTION (116, bv_s64_ref, "bv-s64-ref", 3)
+BV_REF_WITH_ENDIANNESS (s64, s64)
+VM_DEFINE_FUNCTION (117, bv_f32_ref, "bv-f32-ref", 3)
+BV_REF_WITH_ENDIANNESS (f32, ieee_single)
+VM_DEFINE_FUNCTION (118, bv_f64_ref, "bv-f64-ref", 3)
+BV_REF_WITH_ENDIANNESS (f64, ieee_double)
+
+#undef BV_REF_WITH_ENDIANNESS
+
+#define BV_FIXABLE_INT_REF(stem, fn_stem, type, size)                   \
+{                                                                       \
+  long i;                                                               \
+  ARGS2 (bv, idx);                                                      \
+  VM_VALIDATE_BYTEVECTOR (bv);                                          \
+  if (SCM_LIKELY (SCM_I_INUMP (idx)                                     \
+                  && ((i = SCM_I_INUM (idx)) >= 0)                        \
+                  && (i < SCM_BYTEVECTOR_LENGTH (bv))                   \
+                  && (i % size == 0)))                                  \
+    RETURN (SCM_I_MAKINUM (*(scm_t_##type*)                             \
+                           (SCM_BYTEVECTOR_CONTENTS (bv) + i)));        \
+  else                                                                  \
+    RETURN (scm_bytevector_##fn_stem##_ref (bv, idx));                  \
+}
+
+#define BV_INT_REF(stem, type, size)                                    \
+{                                                                       \
+  long i;                                                               \
+  ARGS2 (bv, idx);                                                      \
+  VM_VALIDATE_BYTEVECTOR (bv);                                          \
+  if (SCM_LIKELY (SCM_I_INUMP (idx)                                     \
+                  && ((i = SCM_I_INUM (idx)) >= 0)                        \
+                  && (i < SCM_BYTEVECTOR_LENGTH (bv))                   \
+                  && (i % size == 0)))                                  \
+    { scm_t_##type x = (*(scm_t_##type*)(SCM_BYTEVECTOR_CONTENTS (bv) + i)); \
+      if (SCM_FIXABLE (x))                                              \
+        RETURN (SCM_I_MAKINUM (x));                                     \
+      else                                                              \
+        RETURN (scm_from_##type (x));                                   \
+    }                                                                   \
+  else                                                                  \
+    RETURN (scm_bytevector_##stem##_native_ref (bv, idx));              \
+}
+
+#define BV_FLOAT_REF(stem, fn_stem, type, size)                         \
+{                                                                       \
+  long i;                                                               \
+  ARGS2 (bv, idx);                                                      \
+  VM_VALIDATE_BYTEVECTOR (bv);                                          \
+  if (SCM_LIKELY (SCM_I_INUMP (idx)                                     \
+                  && ((i = SCM_I_INUM (idx)) >= 0)                        \
+                  && (i < SCM_BYTEVECTOR_LENGTH (bv))                   \
+                  && (i % size == 0)))                                  \
+    RETURN (scm_from_double ((*(type*)(SCM_BYTEVECTOR_CONTENTS (bv) + i)))); \
+  else                                                                  \
+    RETURN (scm_bytevector_##fn_stem##_native_ref (bv, idx));           \
+}
+
+VM_DEFINE_FUNCTION (119, bv_u8_ref, "bv-u8-ref", 2)
+BV_FIXABLE_INT_REF (u8, u8, uint8, 1)
+VM_DEFINE_FUNCTION (120, bv_s8_ref, "bv-s8-ref", 2)
+BV_FIXABLE_INT_REF (s8, s8, int8, 1)
+VM_DEFINE_FUNCTION (121, bv_u16_native_ref, "bv-u16-native-ref", 2)
+BV_FIXABLE_INT_REF (u16, u16_native, uint16, 2)
+VM_DEFINE_FUNCTION (122, bv_s16_native_ref, "bv-s16-native-ref", 2)
+BV_FIXABLE_INT_REF (s16, s16_native, int16, 2)
+VM_DEFINE_FUNCTION (123, bv_u32_native_ref, "bv-u32-native-ref", 2)
+/* FIXME: u32 is always a fixnum on 64-bit builds */
+BV_INT_REF (u32, uint32, 4)
+VM_DEFINE_FUNCTION (124, bv_s32_native_ref, "bv-s32-native-ref", 2)
+BV_INT_REF (s32, int32, 4)
+VM_DEFINE_FUNCTION (125, bv_u64_native_ref, "bv-u64-native-ref", 2)
+BV_INT_REF (u64, uint64, 8)
+VM_DEFINE_FUNCTION (126, bv_s64_native_ref, "bv-s64-native-ref", 2)
+BV_INT_REF (s64, int64, 8)
+VM_DEFINE_FUNCTION (127, bv_f32_native_ref, "bv-f32-native-ref", 2)
+BV_FLOAT_REF (f32, ieee_single, float, 4)
+VM_DEFINE_FUNCTION (128, bv_f64_native_ref, "bv-f64-native-ref", 2)
+BV_FLOAT_REF (f64, ieee_double, double, 8)
+
+#undef BV_FIXABLE_INT_REF
+#undef BV_INT_REF
+#undef BV_FLOAT_REF
+
+
+
+#define BV_SET_WITH_ENDIANNESS(stem, fn_stem)                           \
+{                                                                       \
+  SCM endianness;                                                       \
+  POP (endianness);                                                     \
+  if (scm_is_eq (endianness, scm_i_native_endianness))                  \
+    goto VM_LABEL (bv_##stem##_native_set);                             \
+  {                                                                     \
+    SCM bv, idx, val; POP (val); POP (idx); POP (bv);                   \
+    scm_bytevector_##fn_stem##_set_x (bv, idx, val, endianness);        \
+    NEXT;                                                               \
+  }                                                                     \
 }
 
+VM_DEFINE_INSTRUCTION (129, bv_u16_set, "bv-u16-set", 0, 4, 0)
+BV_SET_WITH_ENDIANNESS (u16, u16)
+VM_DEFINE_INSTRUCTION (130, bv_s16_set, "bv-s16-set", 0, 4, 0)
+BV_SET_WITH_ENDIANNESS (s16, s16)
+VM_DEFINE_INSTRUCTION (131, bv_u32_set, "bv-u32-set", 0, 4, 0)
+BV_SET_WITH_ENDIANNESS (u32, u32)
+VM_DEFINE_INSTRUCTION (132, bv_s32_set, "bv-s32-set", 0, 4, 0)
+BV_SET_WITH_ENDIANNESS (s32, s32)
+VM_DEFINE_INSTRUCTION (133, bv_u64_set, "bv-u64-set", 0, 4, 0)
+BV_SET_WITH_ENDIANNESS (u64, u64)
+VM_DEFINE_INSTRUCTION (134, bv_s64_set, "bv-s64-set", 0, 4, 0)
+BV_SET_WITH_ENDIANNESS (s64, s64)
+VM_DEFINE_INSTRUCTION (135, bv_f32_set, "bv-f32-set", 0, 4, 0)
+BV_SET_WITH_ENDIANNESS (f32, ieee_single)
+VM_DEFINE_INSTRUCTION (136, bv_f64_set, "bv-f64-set", 0, 4, 0)
+BV_SET_WITH_ENDIANNESS (f64, ieee_double)
+
+#undef BV_SET_WITH_ENDIANNESS
+
+#define BV_FIXABLE_INT_SET(stem, fn_stem, type, min, max, size)         \
+{                                                                       \
+  long i, j;                                                            \
+  SCM bv, idx, val; POP (val); POP (idx); POP (bv);                     \
+  VM_VALIDATE_BYTEVECTOR (bv);                                          \
+  if (SCM_LIKELY (SCM_I_INUMP (idx)                                     \
+                  && ((i = SCM_I_INUM (idx)) >= 0)                      \
+                  && (i < SCM_BYTEVECTOR_LENGTH (bv))                   \
+                  && (i % size == 0)                                    \
+                  && (SCM_I_INUMP (val))                                \
+                  && ((j = SCM_I_INUM (val)) >= min)                    \
+                  && (j <= max)))                                       \
+    *(scm_t_##type*) (SCM_BYTEVECTOR_CONTENTS (bv) + i) = (scm_t_##type)j; \
+  else                                                                  \
+    scm_bytevector_##fn_stem##_set_x (bv, idx, val);                    \
+  NEXT;                                                                 \
+}
+
+#define BV_INT_SET(stem, type, size)                                    \
+{                                                                       \
+  long i;                                                               \
+  SCM bv, idx, val; POP (val); POP (idx); POP (bv);                     \
+  VM_VALIDATE_BYTEVECTOR (bv);                                          \
+  if (SCM_LIKELY (SCM_I_INUMP (idx)                                     \
+                  && ((i = SCM_I_INUM (idx)) >= 0)                      \
+                  && (i < SCM_BYTEVECTOR_LENGTH (bv))                   \
+                  && (i % size == 0)))                                  \
+    *(scm_t_##type*) (SCM_BYTEVECTOR_CONTENTS (bv) + i) = scm_to_##type (val); 
\
+  else                                                                  \
+    scm_bytevector_##stem##_native_set_x (bv, idx, val);                \
+  NEXT;                                                                 \
+}
+
+#define BV_FLOAT_SET(stem, fn_stem, type, size)                         \
+{                                                                       \
+  long i;                                                               \
+  SCM bv, idx, val; POP (val); POP (idx); POP (bv);                     \
+  VM_VALIDATE_BYTEVECTOR (bv);                                          \
+  if (SCM_LIKELY (SCM_I_INUMP (idx)                                     \
+                  && ((i = SCM_I_INUM (idx)) >= 0)                      \
+                  && (i < SCM_BYTEVECTOR_LENGTH (bv))                   \
+                  && (i % size == 0)))                                  \
+    *(type*) (SCM_BYTEVECTOR_CONTENTS (bv) + i) = scm_to_double (val);  \
+  else                                                                  \
+    scm_bytevector_##fn_stem##_native_set_x (bv, idx, val);             \
+  NEXT;                                                                 \
+}
+
+VM_DEFINE_INSTRUCTION (137, bv_u8_set, "bv-u8-set", 0, 3, 0)
+BV_FIXABLE_INT_SET (u8, u8, uint8, 0, SCM_T_UINT8_MAX, 1)
+VM_DEFINE_INSTRUCTION (138, bv_s8_set, "bv-s8-set", 0, 3, 0)
+BV_FIXABLE_INT_SET (s8, s8, int8, SCM_T_INT8_MIN, SCM_T_INT8_MAX, 1)
+VM_DEFINE_INSTRUCTION (139, bv_u16_native_set, "bv-u16-native-set", 0, 3, 0)
+BV_FIXABLE_INT_SET (u16, u16_native, uint16, 0, SCM_T_UINT16_MAX, 2)
+VM_DEFINE_INSTRUCTION (140, bv_s16_native_set, "bv-s16-native-set", 0, 3, 0)
+BV_FIXABLE_INT_SET (s16, s16_native, int16, SCM_T_INT16_MIN, SCM_T_INT16_MAX, 
2)
+VM_DEFINE_INSTRUCTION (141, bv_u32_native_set, "bv-u32-native-set", 0, 3, 0)
+/* FIXME: u32 is always a fixnum on 64-bit builds */
+BV_INT_SET (u32, uint32, 4)
+VM_DEFINE_INSTRUCTION (142, bv_s32_native_set, "bv-s32-native-set", 0, 3, 0)
+BV_INT_SET (s32, int32, 4)
+VM_DEFINE_INSTRUCTION (143, bv_u64_native_set, "bv-u64-native-set", 0, 3, 0)
+BV_INT_SET (u64, uint64, 8)
+VM_DEFINE_INSTRUCTION (144, bv_s64_native_set, "bv-s64-native-set", 0, 3, 0)
+BV_INT_SET (s64, int64, 8)
+VM_DEFINE_INSTRUCTION (145, bv_f32_native_set, "bv-f32-native-set", 0, 3, 0)
+BV_FLOAT_SET (f32, ieee_single, float, 4)
+VM_DEFINE_INSTRUCTION (146, bv_f64_native_set, "bv-f64-native-set", 0, 3, 0)
+BV_FLOAT_SET (f64, ieee_double, double, 8)
+
+#undef BV_FIXABLE_INT_SET
+#undef BV_INT_SET
+#undef BV_FLOAT_SET
+
 /*
 (defun renumber-ops ()
   "start from top of buffer and renumber 'VM_DEFINE_FOO (\n' sequences"
diff --git a/m4/errno_h.m4 b/m4/errno_h.m4
new file mode 100644
index 0000000..4ce1ccb
--- /dev/null
+++ b/m4/errno_h.m4
@@ -0,0 +1,115 @@
+# errno_h.m4 serial 6
+dnl Copyright (C) 2004, 2006, 2008, 2009 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_ONCE([gl_HEADER_ERRNO_H],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_CACHE_CHECK([for complete errno.h], [gl_cv_header_errno_h_complete], [
+    AC_EGREP_CPP([booboo],[
+#include <errno.h>
+#if !defined ENOMSG
+booboo
+#endif
+#if !defined EIDRM
+booboo
+#endif
+#if !defined ENOLINK
+booboo
+#endif
+#if !defined EPROTO
+booboo
+#endif
+#if !defined EMULTIHOP
+booboo
+#endif
+#if !defined EBADMSG
+booboo
+#endif
+#if !defined EOVERFLOW
+booboo
+#endif
+#if !defined ENOTSUP
+booboo
+#endif
+#if !defined ESTALE
+booboo
+#endif
+#if !defined ECANCELED
+booboo
+#endif
+      ],
+      [gl_cv_header_errno_h_complete=no],
+      [gl_cv_header_errno_h_complete=yes])
+  ])
+  if test $gl_cv_header_errno_h_complete = yes; then
+    ERRNO_H=''
+  else
+    gl_CHECK_NEXT_HEADERS([errno.h])
+    ERRNO_H='errno.h'
+  fi
+  AC_SUBST([ERRNO_H])
+  gl_REPLACE_ERRNO_VALUE([EMULTIHOP])
+  gl_REPLACE_ERRNO_VALUE([ENOLINK])
+  gl_REPLACE_ERRNO_VALUE([EOVERFLOW])
+])
+
+# Assuming $1 = EOVERFLOW.
+# The EOVERFLOW errno value ought to be defined in <errno.h>, according to
+# POSIX.  But some systems (like OpenBSD 4.0 or AIX 3) don't define it, and
+# some systems (like OSF/1) define it when _XOPEN_SOURCE_EXTENDED is defined.
+# Check for the value of EOVERFLOW.
+# Set the variables EOVERFLOW_HIDDEN and EOVERFLOW_VALUE.
+AC_DEFUN([gl_REPLACE_ERRNO_VALUE],
+[
+  if test -n "$ERRNO_H"; then
+    AC_CACHE_CHECK([for ]$1[ value], [gl_cv_header_errno_h_]$1, [
+      AC_EGREP_CPP([yes],[
+#include <errno.h>
+#ifdef ]$1[
+yes
+#endif
+      ],
+      [gl_cv_header_errno_h_]$1[=yes],
+      [gl_cv_header_errno_h_]$1[=no])
+      if test $gl_cv_header_errno_h_]$1[ = no; then
+        AC_EGREP_CPP([yes],[
+#define _XOPEN_SOURCE_EXTENDED 1
+#include <errno.h>
+#ifdef ]$1[
+yes
+#endif
+          ], [gl_cv_header_errno_h_]$1[=hidden])
+        if test $gl_cv_header_errno_h_]$1[ = hidden; then
+          dnl The macro exists but is hidden.
+          dnl Define it to the same value.
+          AC_COMPUTE_INT([gl_cv_header_errno_h_]$1, $1, [
+#define _XOPEN_SOURCE_EXTENDED 1
+#include <errno.h>
+/* The following two lines are a workaround against an autoconf-2.52 bug.  */
+#include <stdio.h>
+#include <stdlib.h>
+])
+        fi
+      fi
+    ])
+    case $gl_cv_header_errno_h_]$1[ in
+      yes | no)
+        ]$1[_HIDDEN=0; ]$1[_VALUE=
+        ;;
+      *)
+        ]$1[_HIDDEN=1; ]$1[_VALUE="$gl_cv_header_errno_h_]$1["
+        ;;
+    esac
+    AC_SUBST($1[_HIDDEN])
+    AC_SUBST($1[_VALUE])
+  fi
+])
+
+dnl Autoconf >= 2.61 has AC_COMPUTE_INT built-in.
+dnl Remove this when we can assume autoconf >= 2.61.
+m4_ifdef([AC_COMPUTE_INT], [], [
+  AC_DEFUN([AC_COMPUTE_INT], [_AC_COMPUTE_INT([$2],[$1],[$3],[$4])])
+])
diff --git a/m4/float_h.m4 b/m4/float_h.m4
new file mode 100644
index 0000000..d36e3a4
--- /dev/null
+++ b/m4/float_h.m4
@@ -0,0 +1,19 @@
+# float_h.m4 serial 3
+dnl Copyright (C) 2007 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_H],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  FLOAT_H=
+  case "$host_os" in
+    beos* | openbsd*)
+      FLOAT_H=float.h
+      gl_CHECK_NEXT_HEADERS([float.h])
+      ;;
+  esac
+  AC_SUBST([FLOAT_H])
+])
diff --git a/m4/getpagesize.m4 b/m4/getpagesize.m4
new file mode 100644
index 0000000..0d07a3a
--- /dev/null
+++ b/m4/getpagesize.m4
@@ -0,0 +1,29 @@
+# getpagesize.m4 serial 7
+dnl Copyright (C) 2002, 2004-2005, 2007 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_GETPAGESIZE],
+[
+  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  AC_CHECK_FUNCS([getpagesize])
+  if test $ac_cv_func_getpagesize = no; then
+    HAVE_GETPAGESIZE=0
+    AC_CHECK_HEADERS([OS.h])
+    if test $ac_cv_header_OS_h = yes; then
+      HAVE_OS_H=1
+    fi
+    AC_CHECK_HEADERS([sys/param.h])
+    if test $ac_cv_header_sys_param_h = yes; then
+      HAVE_SYS_PARAM_H=1
+    fi
+  fi
+  case "$host_os" in
+    mingw*)
+      REPLACE_GETPAGESIZE=1
+      AC_LIBOBJ([getpagesize])
+      ;;
+  esac
+])
diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4
index e70283f..aad4999 100644
--- a/m4/gnulib-cache.m4
+++ b/m4/gnulib-cache.m4
@@ -15,7 +15,7 @@
 
 
 # Specification in the form of a command-line invocation:
-#   gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 
--doc-base=doc --tests-base=tests --aux-dir=build-aux --lgpl --libtool 
--macro-prefix=gl --no-vc-files alloca-opt autobuild byteswap canonicalize-lgpl 
count-one-bits environ extensions flock fpieee full-read full-write havelib 
iconv_open-utf lib-symbol-visibility libunistring putenv stdlib strcase 
strftime striconveh string
+#   gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 
--doc-base=doc --tests-base=tests --aux-dir=build-aux --lgpl --libtool 
--macro-prefix=gl --no-vc-files alloca-opt autobuild byteswap canonicalize-lgpl 
count-one-bits environ extensions flock fpieee full-read full-write havelib 
iconv_open-utf lib-symbol-visibility libunistring putenv stdlib strcase 
strftime striconveh string vsnprintf
 
 # Specification in the form of a few gnulib-tool.m4 macro invocations:
 gl_LOCAL_DIR([])
@@ -41,6 +41,7 @@ gl_MODULES([
   strftime
   striconveh
   string
+  vsnprintf
 ])
 gl_AVOID([])
 gl_SOURCE_BASE([lib])
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index ef0534e..0c2b968 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -51,8 +51,12 @@ AC_DEFUN([gl_INIT],
   gl_COUNT_ONE_BITS
   gl_ENVIRON
   gl_UNISTD_MODULE_INDICATOR([environ])
+  gl_HEADER_ERRNO_H
+  gl_FLOAT_H
   gl_FUNC_FLOCK
   gl_HEADER_SYS_FILE_MODULE_INDICATOR([flock])
+  gl_FUNC_GETPAGESIZE
+  gl_UNISTD_MODULE_INDICATOR([getpagesize])
   AM_ICONV
   gl_ICONV_H
   gl_FUNC_ICONV_OPEN
@@ -72,6 +76,8 @@ AC_DEFUN([gl_INIT],
   gl_WCHAR_MODULE_INDICATOR([mbrtowc])
   gl_FUNC_MBSINIT
   gl_WCHAR_MODULE_INDICATOR([mbsinit])
+  gl_FUNC_MEMCHR
+  gl_STRING_MODULE_INDICATOR([memchr])
   gl_MULTIARCH
   gl_PATHMAX
   gl_FUNC_PUTENV
@@ -80,9 +86,11 @@ AC_DEFUN([gl_INIT],
   gl_UNISTD_MODULE_INDICATOR([readlink])
   gl_SAFE_READ
   gl_SAFE_WRITE
+  gl_SIZE_MAX
   gt_TYPE_SSIZE_T
   AM_STDBOOL_H
   gl_STDINT_H
+  gl_STDIO_H
   gl_STDLIB_H
   gl_STRCASE
   gl_FUNC_GNU_STRFTIME
@@ -101,9 +109,13 @@ AC_DEFUN([gl_INIT],
   gl_MODULE_INDICATOR([unistr/u8-mbtouc-unsafe])
   gl_MODULE_INDICATOR([unistr/u8-mbtoucr])
   gl_MODULE_INDICATOR([unistr/u8-uctomb])
+  gl_FUNC_VASNPRINTF
+  gl_FUNC_VSNPRINTF
+  gl_STDIO_MODULE_INDICATOR([vsnprintf])
   gl_WCHAR_H
   gl_FUNC_WRITE
   gl_UNISTD_MODULE_INDICATOR([write])
+  gl_XSIZE
   m4_ifval(gl_LIBSOURCES_LIST, [
     m4_syscmd([test ! -d ]m4_defn([gl_LIBSOURCES_DIR])[ ||
       for gl_file in ]gl_LIBSOURCES_LIST[ ; do
@@ -235,6 +247,7 @@ AC_DEFUN([gl_FILE_LIST], [
   build-aux/config.rpath
   build-aux/link-warning.h
   lib/alloca.in.h
+  lib/asnprintf.c
   lib/byteswap.in.h
   lib/c-ctype.c
   lib/c-ctype.h
@@ -246,11 +259,15 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/canonicalize.h
   lib/config.charset
   lib/count-one-bits.h
+  lib/errno.in.h
+  lib/float+.h
+  lib/float.in.h
   lib/flock.c
   lib/full-read.c
   lib/full-read.h
   lib/full-write.c
   lib/full-write.h
+  lib/getpagesize.c
   lib/iconv.c
   lib/iconv.in.h
   lib/iconv_close.c
@@ -269,7 +286,13 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/mbrlen.c
   lib/mbrtowc.c
   lib/mbsinit.c
+  lib/memchr.c
+  lib/memchr.valgrind
   lib/pathmax.h
+  lib/printf-args.c
+  lib/printf-args.h
+  lib/printf-parse.c
+  lib/printf-parse.h
   lib/putenv.c
   lib/readlink.c
   lib/ref-add.sin
@@ -278,8 +301,11 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/safe-read.h
   lib/safe-write.c
   lib/safe-write.h
+  lib/size_max.h
   lib/stdbool.in.h
   lib/stdint.in.h
+  lib/stdio-write.c
+  lib/stdio.in.h
   lib/stdlib.in.h
   lib/strcasecmp.c
   lib/streq.h
@@ -304,9 +330,13 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/unistr/u8-uctomb-aux.c
   lib/unistr/u8-uctomb.c
   lib/unitypes.h
+  lib/vasnprintf.c
+  lib/vasnprintf.h
   lib/verify.h
+  lib/vsnprintf.c
   lib/wchar.in.h
   lib/write.c
+  lib/xsize.h
   m4/00gnulib.m4
   m4/alloca.m4
   m4/autobuild.m4
@@ -316,9 +346,12 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/count-one-bits.m4
   m4/eealloc.m4
   m4/environ.m4
+  m4/errno_h.m4
   m4/extensions.m4
+  m4/float_h.m4
   m4/flock.m4
   m4/fpieee.m4
+  m4/getpagesize.m4
   m4/glibc21.m4
   m4/gnulib-common.m4
   m4/iconv.m4
@@ -326,6 +359,8 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/iconv_open.m4
   m4/include_next.m4
   m4/inline.m4
+  m4/intmax_t.m4
+  m4/inttypes_h.m4
   m4/lib-ld.m4
   m4/lib-link.m4
   m4/lib-prefix.m4
@@ -341,15 +376,21 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/mbrtowc.m4
   m4/mbsinit.m4
   m4/mbstate_t.m4
+  m4/memchr.m4
+  m4/mmap-anon.m4
   m4/multiarch.m4
   m4/pathmax.m4
+  m4/printf.m4
   m4/putenv.m4
   m4/readlink.m4
   m4/safe-read.m4
   m4/safe-write.m4
+  m4/size_max.m4
   m4/ssize_t.m4
   m4/stdbool.m4
   m4/stdint.m4
+  m4/stdint_h.m4
+  m4/stdio_h.m4
   m4/stdlib_h.m4
   m4/strcase.m4
   m4/strftime.m4
@@ -360,8 +401,12 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/time_r.m4
   m4/tm_gmtoff.m4
   m4/unistd_h.m4
+  m4/vasnprintf.m4
   m4/visibility.m4
+  m4/vsnprintf.m4
   m4/wchar.m4
+  m4/wchar_t.m4
   m4/wint_t.m4
   m4/write.m4
+  m4/xsize.m4
 ])
diff --git a/m4/intmax_t.m4 b/m4/intmax_t.m4
new file mode 100644
index 0000000..264cb57
--- /dev/null
+++ b/m4/intmax_t.m4
@@ -0,0 +1,61 @@
+# intmax_t.m4 serial 7
+dnl Copyright (C) 1997-2004, 2006-2007, 2009 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 Paul Eggert.
+
+AC_PREREQ([2.13])
+
+# Define intmax_t to 'long' or 'long long'
+# if it is not already defined in <stdint.h> or <inttypes.h>.
+
+AC_DEFUN([gl_AC_TYPE_INTMAX_T],
+[
+  dnl For simplicity, we assume that a header file defines 'intmax_t' if and
+  dnl only if it defines 'uintmax_t'.
+  AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])
+  AC_REQUIRE([gl_AC_HEADER_STDINT_H])
+  if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; 
then
+    AC_REQUIRE([AC_TYPE_LONG_LONG_INT])
+    test $ac_cv_type_long_long_int = yes \
+      && ac_type='long long' \
+      || ac_type='long'
+    AC_DEFINE_UNQUOTED([intmax_t], [$ac_type],
+     [Define to long or long long if <inttypes.h> and <stdint.h> don't 
define.])
+  else
+    AC_DEFINE([HAVE_INTMAX_T], [1],
+      [Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>.])
+  fi
+])
+
+dnl An alternative would be to explicitly test for 'intmax_t'.
+
+AC_DEFUN([gt_AC_TYPE_INTMAX_T],
+[
+  AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])
+  AC_REQUIRE([gl_AC_HEADER_STDINT_H])
+  AC_CACHE_CHECK([for intmax_t], [gt_cv_c_intmax_t],
+    [AC_TRY_COMPILE([
+#include <stddef.h>
+#include <stdlib.h>
+#if HAVE_STDINT_H_WITH_UINTMAX
+#include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H_WITH_UINTMAX
+#include <inttypes.h>
+#endif
+], [intmax_t x = -1; return !x;], gt_cv_c_intmax_t=yes, gt_cv_c_intmax_t=no)])
+  if test $gt_cv_c_intmax_t = yes; then
+    AC_DEFINE([HAVE_INTMAX_T], [1],
+      [Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>.])
+  else
+    AC_REQUIRE([AC_TYPE_LONG_LONG_INT])
+    test $ac_cv_type_long_long_int = yes \
+      && ac_type='long long' \
+      || ac_type='long'
+    AC_DEFINE_UNQUOTED([intmax_t], [$ac_type],
+     [Define to long or long long if <stdint.h> and <inttypes.h> don't 
define.])
+  fi
+])
diff --git a/m4/inttypes_h.m4 b/m4/inttypes_h.m4
new file mode 100644
index 0000000..f4ca160
--- /dev/null
+++ b/m4/inttypes_h.m4
@@ -0,0 +1,26 @@
+# inttypes_h.m4 serial 9
+dnl Copyright (C) 1997-2004, 2006, 2008, 2009 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 Paul Eggert.
+
+# Define HAVE_INTTYPES_H_WITH_UINTMAX if <inttypes.h> exists,
+# doesn't clash with <sys/types.h>, and declares uintmax_t.
+
+AC_DEFUN([gl_AC_HEADER_INTTYPES_H],
+[
+  AC_CACHE_CHECK([for inttypes.h], [gl_cv_header_inttypes_h],
+  [AC_TRY_COMPILE(
+    [#include <sys/types.h>
+#include <inttypes.h>],
+    [uintmax_t i = (uintmax_t) -1; return !i;],
+    [gl_cv_header_inttypes_h=yes],
+    [gl_cv_header_inttypes_h=no])])
+  if test $gl_cv_header_inttypes_h = yes; then
+    AC_DEFINE_UNQUOTED([HAVE_INTTYPES_H_WITH_UINTMAX], [1],
+      [Define if <inttypes.h> exists, doesn't clash with <sys/types.h>,
+       and declares uintmax_t. ])
+  fi
+])
diff --git a/m4/lib-link.m4 b/m4/lib-link.m4
index 2144203..2f8b7ff 100644
--- a/m4/lib-link.m4
+++ b/m4/lib-link.m4
@@ -1,4 +1,4 @@
-# lib-link.m4 serial 19 (gettext-0.18)
+# lib-link.m4 serial 20 (gettext-0.18)
 dnl Copyright (C) 2001-2009 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -82,7 +82,7 @@ AC_DEFUN([AC_LIB_HAVE_LINKFLAGS],
   ])
   if test "$ac_cv_lib[]Name" = yes; then
     HAVE_LIB[]NAME=yes
-    AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the lib[]$1 library.])
+    AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the lib][$1 library.])
     AC_MSG_CHECKING([how to link with lib[]$1])
     AC_MSG_RESULT([$LIB[]NAME])
   else
@@ -210,6 +210,9 @@ AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
   LTLIB[]NAME=
   INC[]NAME=
   LIB[]NAME[]_PREFIX=
+  dnl HAVE_LIB${NAME} is an indicator that LIB${NAME}, LTLIB${NAME} have been
+  dnl computed. So it has to be reset here.
+  HAVE_LIB[]NAME=
   rpathdirs=
   ltrpathdirs=
   names_already_handled=
diff --git a/m4/mbrtowc.m4 b/m4/mbrtowc.m4
index 11d7d23..2fddcc8 100644
--- a/m4/mbrtowc.m4
+++ b/m4/mbrtowc.m4
@@ -1,4 +1,4 @@
-# mbrtowc.m4 serial 15
+# mbrtowc.m4 serial 16
 dnl Copyright (C) 2001-2002, 2004-2005, 2008, 2009 Free Software Foundation, 
Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -156,6 +156,7 @@ changequote([,])dnl
       if test $LOCALE_ZH_CN != none; then
         AC_TRY_RUN([
 #include <locale.h>
+#include <stdlib.h>
 #include <string.h>
 #include <wchar.h>
 int main ()
diff --git a/m4/memchr.m4 b/m4/memchr.m4
new file mode 100644
index 0000000..1194bac
--- /dev/null
+++ b/m4/memchr.m4
@@ -0,0 +1,86 @@
+# memchr.m4 serial 7
+dnl Copyright (C) 2002, 2003, 2004, 2009 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_ONCE([gl_FUNC_MEMCHR],
+[
+  dnl Check for prerequisites for memory fence checks.
+  gl_FUNC_MMAP_ANON
+  AC_CHECK_HEADERS_ONCE([sys/mman.h])
+  AC_CHECK_FUNCS_ONCE([mprotect])
+
+  dnl These days, we assume memchr is present.  But just in case...
+  AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS])
+  AC_REPLACE_FUNCS([memchr])
+  if test $ac_cv_func_memchr = no; then
+    gl_PREREQ_MEMCHR
+    REPLACE_MEMCHR=1
+  fi
+
+  if test $ac_cv_func_memchr = yes; then
+    # Detect platform-specific bugs in some versions of glibc:
+    # memchr should not dereference anything with length 0
+    #   http://bugzilla.redhat.com/499689
+    # memchr should not dereference overestimated length after a match
+    #   http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=521737
+    #   http://sourceware.org/bugzilla/show_bug.cgi?id=10162
+    # Assume that memchr works on platforms that lack mprotect.
+    AC_CACHE_CHECK([whether memchr works], [gl_cv_func_memchr_works],
+      [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
+#include <string.h>
+#if HAVE_SYS_MMAN_H
+# include <fcntl.h>
+# include <unistd.h>
+# include <sys/types.h>
+# include <sys/mman.h>
+# ifndef MAP_FILE
+#  define MAP_FILE 0
+# endif
+#endif
+]], [[
+  char *fence = NULL;
+#if HAVE_SYS_MMAN_H && HAVE_MPROTECT
+# if HAVE_MAP_ANONYMOUS
+  const int flags = MAP_ANONYMOUS | MAP_PRIVATE;
+  const int fd = -1;
+# else /* !HAVE_MAP_ANONYMOUS */
+  const int flags = MAP_FILE | MAP_PRIVATE;
+  int fd = open ("/dev/zero", O_RDONLY, 0666);
+  if (fd >= 0)
+# endif
+    {
+      int pagesize = getpagesize ();
+      char *two_pages =
+       (char *) mmap (NULL, 2 * pagesize, PROT_READ | PROT_WRITE,
+                      flags, fd, 0);
+      if (two_pages != (char *)(-1)
+         && mprotect (two_pages + pagesize, pagesize, PROT_NONE) == 0)
+       fence = two_pages + pagesize;
+    }
+#endif
+  if (fence)
+    {
+      if (memchr (fence, 0, 0))
+        return 1;
+      strcpy (fence - 9, "12345678");
+      if (memchr (fence - 9, 0, 79) != fence - 1)
+        return 2;
+    }
+  return 0;
+]])], [gl_cv_func_memchr_works=yes], [gl_cv_func_memchr_works=no],
+      [dnl Be pessimistic for now.
+       gl_cv_func_memchr_works="guessing no"])])
+    if test "$gl_cv_func_memchr_works" != yes; then
+      gl_PREREQ_MEMCHR
+      REPLACE_MEMCHR=1
+      AC_LIBOBJ([memchr])
+    fi
+  fi
+])
+
+# Prerequisites of lib/memchr.c.
+AC_DEFUN([gl_PREREQ_MEMCHR], [
+  AC_CHECK_HEADERS([bp-sym.h])
+])
diff --git a/m4/mmap-anon.m4 b/m4/mmap-anon.m4
new file mode 100644
index 0000000..14b6270
--- /dev/null
+++ b/m4/mmap-anon.m4
@@ -0,0 +1,59 @@
+# mmap-anon.m4 serial 8
+dnl Copyright (C) 2005, 2007, 2009 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.
+
+# Detect how mmap can be used to create anonymous (not file-backed) memory
+# mappings.
+# - On Linux, AIX, OSF/1, Solaris, Cygwin, Interix, Haiku, both MAP_ANONYMOUS
+#   and MAP_ANON exist and have the same value.
+# - On HP-UX, only MAP_ANONYMOUS exists.
+# - On MacOS X, FreeBSD, NetBSD, OpenBSD, only MAP_ANON exists.
+# - On IRIX, neither exists, and a file descriptor opened to /dev/zero must be
+#   used.
+
+AC_DEFUN([gl_FUNC_MMAP_ANON],
+[
+  dnl Work around a bug of AC_EGREP_CPP in autoconf-2.57.
+  AC_REQUIRE([AC_PROG_CPP])
+  AC_REQUIRE([AC_PROG_EGREP])
+
+  dnl Persuade glibc <sys/mman.h> to define MAP_ANONYMOUS.
+  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+
+  # Check for mmap(). Don't use AC_FUNC_MMAP, because it checks too much: it
+  # fails on HP-UX 11, because MAP_FIXED mappings do not work. But this is
+  # irrelevant for anonymous mappings.
+  AC_CHECK_FUNC([mmap], [gl_have_mmap=yes], [gl_have_mmap=no])
+
+  # Try to allow MAP_ANONYMOUS.
+  gl_have_mmap_anonymous=no
+  if test $gl_have_mmap = yes; then
+    AC_MSG_CHECKING([for MAP_ANONYMOUS])
+    AC_EGREP_CPP([I cant identify this map.], [
+#include <sys/mman.h>
+#ifdef MAP_ANONYMOUS
+    I cant identify this map.
+#endif
+],
+      [gl_have_mmap_anonymous=yes])
+    if test $gl_have_mmap_anonymous != yes; then
+      AC_EGREP_CPP([I cant identify this map.], [
+#include <sys/mman.h>
+#ifdef MAP_ANON
+    I cant identify this map.
+#endif
+],
+        [AC_DEFINE([MAP_ANONYMOUS], [MAP_ANON],
+          [Define to a substitute value for mmap()'s MAP_ANONYMOUS flag.])
+         gl_have_mmap_anonymous=yes])
+    fi
+    AC_MSG_RESULT([$gl_have_mmap_anonymous])
+    if test $gl_have_mmap_anonymous = yes; then
+      AC_DEFINE([HAVE_MAP_ANONYMOUS], [1],
+        [Define to 1 if mmap()'s MAP_ANONYMOUS flag is available after 
including
+         config.h and <sys/mman.h>.])
+    fi
+  fi
+])
diff --git a/m4/printf.m4 b/m4/printf.m4
new file mode 100644
index 0000000..87aa45c
--- /dev/null
+++ b/m4/printf.m4
@@ -0,0 +1,1416 @@
+# printf.m4 serial 33
+dnl Copyright (C) 2003, 2007-2009 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 Test whether the *printf family of functions supports the 'j', 'z', 't',
+dnl 'L' size specifiers. (ISO C99, POSIX:2001)
+dnl Result is gl_cv_func_printf_sizes_c99.
+
+AC_DEFUN([gl_PRINTF_SIZES_C99],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([gl_AC_HEADER_STDINT_H])
+  AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf supports size specifiers as in C99],
+    [gl_cv_func_printf_sizes_c99],
+    [
+      AC_TRY_RUN([
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#if HAVE_STDINT_H_WITH_UINTMAX
+# include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H_WITH_UINTMAX
+# include <inttypes.h>
+#endif
+static char buf[100];
+int main ()
+{
+#if HAVE_STDINT_H_WITH_UINTMAX || HAVE_INTTYPES_H_WITH_UINTMAX
+  buf[0] = '\0';
+  if (sprintf (buf, "%ju %d", (uintmax_t) 12345671, 33, 44, 55) < 0
+      || strcmp (buf, "12345671 33") != 0)
+    return 1;
+#endif
+  buf[0] = '\0';
+  if (sprintf (buf, "%zu %d", (size_t) 12345672, 33, 44, 55) < 0
+      || strcmp (buf, "12345672 33") != 0)
+    return 1;
+  buf[0] = '\0';
+  if (sprintf (buf, "%tu %d", (ptrdiff_t) 12345673, 33, 44, 55) < 0
+      || strcmp (buf, "12345673 33") != 0)
+    return 1;
+  buf[0] = '\0';
+  if (sprintf (buf, "%Lg %d", (long double) 1.5, 33, 44, 55) < 0
+      || strcmp (buf, "1.5 33") != 0)
+    return 1;
+  return 0;
+}], [gl_cv_func_printf_sizes_c99=yes], [gl_cv_func_printf_sizes_c99=no],
+      [
+changequote(,)dnl
+       case "$host_os" in
+                               # Guess yes on glibc systems.
+         *-gnu*)               gl_cv_func_printf_sizes_c99="guessing yes";;
+                               # Guess yes on FreeBSD >= 5.
+         freebsd[1-4]*)        gl_cv_func_printf_sizes_c99="guessing no";;
+         freebsd* | kfreebsd*) gl_cv_func_printf_sizes_c99="guessing yes";;
+                               # Guess yes on MacOS X >= 10.3.
+         darwin[1-6].*)        gl_cv_func_printf_sizes_c99="guessing no";;
+         darwin*)              gl_cv_func_printf_sizes_c99="guessing yes";;
+                               # Guess yes on OpenBSD >= 3.9.
+         openbsd[1-2].* | openbsd3.[0-8] | openbsd3.[0-8].*)
+                               gl_cv_func_printf_sizes_c99="guessing no";;
+         openbsd*)             gl_cv_func_printf_sizes_c99="guessing yes";;
+                               # Guess yes on Solaris >= 2.10.
+         solaris2.[0-9]*)      gl_cv_func_printf_sizes_c99="guessing no";;
+         solaris*)             gl_cv_func_printf_sizes_c99="guessing yes";;
+                               # Guess yes on NetBSD >= 3.
+         netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | netbsdcoff[1-2]*)
+                               gl_cv_func_printf_sizes_c99="guessing no";;
+         netbsd*)              gl_cv_func_printf_sizes_c99="guessing yes";;
+                               # If we don't know, assume the worst.
+         *)                    gl_cv_func_printf_sizes_c99="guessing no";;
+       esac
+changequote([,])dnl
+      ])
+    ])
+])
+
+dnl Test whether the *printf family of functions supports 'long double'
+dnl arguments together with the 'L' size specifier. (ISO C99, POSIX:2001)
+dnl Result is gl_cv_func_printf_long_double.
+
+AC_DEFUN([gl_PRINTF_LONG_DOUBLE],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf supports 'long double' arguments],
+    [gl_cv_func_printf_long_double],
+    [
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <string.h>
+static char buf[10000];
+int main ()
+{
+  buf[0] = '\0';
+  if (sprintf (buf, "%Lf %d", 1.75L, 33, 44, 55) < 0
+      || strcmp (buf, "1.750000 33") != 0)
+    return 1;
+  buf[0] = '\0';
+  if (sprintf (buf, "%Le %d", 1.75L, 33, 44, 55) < 0
+      || strcmp (buf, "1.750000e+00 33") != 0)
+    return 1;
+  buf[0] = '\0';
+  if (sprintf (buf, "%Lg %d", 1.75L, 33, 44, 55) < 0
+      || strcmp (buf, "1.75 33") != 0)
+    return 1;
+  return 0;
+}], [gl_cv_func_printf_long_double=yes], [gl_cv_func_printf_long_double=no],
+      [
+changequote(,)dnl
+       case "$host_os" in
+         beos*)        gl_cv_func_printf_long_double="guessing no";;
+         mingw* | pw*) gl_cv_func_printf_long_double="guessing no";;
+         *)            gl_cv_func_printf_long_double="guessing yes";;
+       esac
+changequote([,])dnl
+      ])
+    ])
+])
+
+dnl Test whether the *printf family of functions supports infinite and NaN
+dnl 'double' arguments and negative zero arguments in the %f, %e, %g
+dnl directives. (ISO C99, POSIX:2001)
+dnl Result is gl_cv_func_printf_infinite.
+
+AC_DEFUN([gl_PRINTF_INFINITE],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf supports infinite 'double' arguments],
+    [gl_cv_func_printf_infinite],
+    [
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <string.h>
+static int
+strisnan (const char *string, size_t start_index, size_t end_index)
+{
+  if (start_index < end_index)
+    {
+      if (string[start_index] == '-')
+        start_index++;
+      if (start_index + 3 <= end_index
+          && memcmp (string + start_index, "nan", 3) == 0)
+        {
+          start_index += 3;
+          if (start_index == end_index
+              || (string[start_index] == '(' && string[end_index - 1] == ')'))
+            return 1;
+        }
+    }
+  return 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;
+}
+static char buf[10000];
+static double zero = 0.0;
+int main ()
+{
+  if (sprintf (buf, "%f", 1.0 / 0.0) < 0
+      || (strcmp (buf, "inf") != 0 && strcmp (buf, "infinity") != 0))
+    return 1;
+  if (sprintf (buf, "%f", -1.0 / 0.0) < 0
+      || (strcmp (buf, "-inf") != 0 && strcmp (buf, "-infinity") != 0))
+    return 1;
+  if (sprintf (buf, "%f", zero / zero) < 0
+      || !strisnan (buf, 0, strlen (buf)))
+    return 1;
+  if (sprintf (buf, "%e", 1.0 / 0.0) < 0
+      || (strcmp (buf, "inf") != 0 && strcmp (buf, "infinity") != 0))
+    return 1;
+  if (sprintf (buf, "%e", -1.0 / 0.0) < 0
+      || (strcmp (buf, "-inf") != 0 && strcmp (buf, "-infinity") != 0))
+    return 1;
+  if (sprintf (buf, "%e", zero / zero) < 0
+      || !strisnan (buf, 0, strlen (buf)))
+    return 1;
+  if (sprintf (buf, "%g", 1.0 / 0.0) < 0
+      || (strcmp (buf, "inf") != 0 && strcmp (buf, "infinity") != 0))
+    return 1;
+  if (sprintf (buf, "%g", -1.0 / 0.0) < 0
+      || (strcmp (buf, "-inf") != 0 && strcmp (buf, "-infinity") != 0))
+    return 1;
+  if (sprintf (buf, "%g", zero / zero) < 0
+      || !strisnan (buf, 0, strlen (buf)))
+    return 1;
+  /* This test fails on HP-UX 10.20.  */
+  if (have_minus_zero ())
+    if (sprintf (buf, "%g", - zero) < 0
+        || strcmp (buf, "-0") != 0)
+    return 1;
+  return 0;
+}], [gl_cv_func_printf_infinite=yes], [gl_cv_func_printf_infinite=no],
+      [
+changequote(,)dnl
+       case "$host_os" in
+                               # Guess yes on glibc systems.
+         *-gnu*)               gl_cv_func_printf_infinite="guessing yes";;
+                               # Guess yes on FreeBSD >= 6.
+         freebsd[1-5]*)        gl_cv_func_printf_infinite="guessing no";;
+         freebsd* | kfreebsd*) gl_cv_func_printf_infinite="guessing yes";;
+                               # Guess yes on MacOS X >= 10.3.
+         darwin[1-6].*)        gl_cv_func_printf_infinite="guessing no";;
+         darwin*)              gl_cv_func_printf_infinite="guessing yes";;
+                               # Guess yes on HP-UX >= 11.
+         hpux[7-9]* | hpux10*) gl_cv_func_printf_infinite="guessing no";;
+         hpux*)                gl_cv_func_printf_infinite="guessing yes";;
+                               # Guess yes on NetBSD >= 3.
+         netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | netbsdcoff[1-2]*)
+                               gl_cv_func_printf_infinite="guessing no";;
+         netbsd*)              gl_cv_func_printf_infinite="guessing yes";;
+                               # Guess yes on BeOS.
+         beos*)                gl_cv_func_printf_infinite="guessing yes";;
+                               # If we don't know, assume the worst.
+         *)                    gl_cv_func_printf_infinite="guessing no";;
+       esac
+changequote([,])dnl
+      ])
+    ])
+])
+
+dnl Test whether the *printf family of functions supports infinite and NaN
+dnl 'long double' arguments in the %f, %e, %g directives. (ISO C99, POSIX:2001)
+dnl Result is gl_cv_func_printf_infinite_long_double.
+
+AC_DEFUN([gl_PRINTF_INFINITE_LONG_DOUBLE],
+[
+  AC_REQUIRE([gl_PRINTF_LONG_DOUBLE])
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([gl_BIGENDIAN])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  dnl The user can set or unset the variable gl_printf_safe to indicate
+  dnl that he wishes a safe handling of non-IEEE-754 'long double' values.
+  if test -n "$gl_printf_safe"; then
+    AC_DEFINE([CHECK_PRINTF_SAFE], [1],
+      [Define if you wish *printf() functions that have a safe handling of
+       non-IEEE-754 'long double' values.])
+  fi
+  case "$gl_cv_func_printf_long_double" in
+    *yes)
+      AC_CACHE_CHECK([whether printf supports infinite 'long double' 
arguments],
+        [gl_cv_func_printf_infinite_long_double],
+        [
+          AC_TRY_RUN([
+]GL_NOCRASH[
+#include <float.h>
+#include <stdio.h>
+#include <string.h>
+static int
+strisnan (const char *string, size_t start_index, size_t end_index)
+{
+  if (start_index < end_index)
+    {
+      if (string[start_index] == '-')
+        start_index++;
+      if (start_index + 3 <= end_index
+          && memcmp (string + start_index, "nan", 3) == 0)
+        {
+          start_index += 3;
+          if (start_index == end_index
+              || (string[start_index] == '(' && string[end_index - 1] == ')'))
+            return 1;
+        }
+    }
+  return 0;
+}
+static char buf[10000];
+static long double zeroL = 0.0L;
+int main ()
+{
+  nocrash_init();
+  if (sprintf (buf, "%Lf", 1.0L / 0.0L) < 0
+      || (strcmp (buf, "inf") != 0 && strcmp (buf, "infinity") != 0))
+    return 1;
+  if (sprintf (buf, "%Lf", -1.0L / 0.0L) < 0
+      || (strcmp (buf, "-inf") != 0 && strcmp (buf, "-infinity") != 0))
+    return 1;
+  if (sprintf (buf, "%Lf", zeroL / zeroL) < 0
+      || !strisnan (buf, 0, strlen (buf)))
+    return 1;
+  if (sprintf (buf, "%Le", 1.0L / 0.0L) < 0
+      || (strcmp (buf, "inf") != 0 && strcmp (buf, "infinity") != 0))
+    return 1;
+  if (sprintf (buf, "%Le", -1.0L / 0.0L) < 0
+      || (strcmp (buf, "-inf") != 0 && strcmp (buf, "-infinity") != 0))
+    return 1;
+  if (sprintf (buf, "%Le", zeroL / zeroL) < 0
+      || !strisnan (buf, 0, strlen (buf)))
+    return 1;
+  if (sprintf (buf, "%Lg", 1.0L / 0.0L) < 0
+      || (strcmp (buf, "inf") != 0 && strcmp (buf, "infinity") != 0))
+    return 1;
+  if (sprintf (buf, "%Lg", -1.0L / 0.0L) < 0
+      || (strcmp (buf, "-inf") != 0 && strcmp (buf, "-infinity") != 0))
+    return 1;
+  if (sprintf (buf, "%Lg", zeroL / zeroL) < 0
+      || !strisnan (buf, 0, strlen (buf)))
+    return 1;
+#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_))
+/* 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 union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) };
+    if (sprintf (buf, "%Lf", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+    if (sprintf (buf, "%Le", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+    if (sprintf (buf, "%Lg", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+  }
+  {
+    /* Signalling NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) };
+    if (sprintf (buf, "%Lf", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+    if (sprintf (buf, "%Le", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+    if (sprintf (buf, "%Lg", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+  }
+  { /* Pseudo-NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) };
+    if (sprintf (buf, "%Lf", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+    if (sprintf (buf, "%Le", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+    if (sprintf (buf, "%Lg", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+  }
+  { /* Pseudo-Infinity.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) };
+    if (sprintf (buf, "%Lf", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+    if (sprintf (buf, "%Le", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+    if (sprintf (buf, "%Lg", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+  }
+  { /* Pseudo-Zero.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) };
+    if (sprintf (buf, "%Lf", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+    if (sprintf (buf, "%Le", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+    if (sprintf (buf, "%Lg", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+  }
+  { /* Unnormalized number.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) };
+    if (sprintf (buf, "%Lf", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+    if (sprintf (buf, "%Le", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+    if (sprintf (buf, "%Lg", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+  }
+  { /* Pseudo-Denormal.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) };
+    if (sprintf (buf, "%Lf", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+    if (sprintf (buf, "%Le", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+    if (sprintf (buf, "%Lg", x.value) < 0
+        || !strisnan (buf, 0, strlen (buf)))
+      return 1;
+  }
+#endif
+  return 0;
+}],
+          [gl_cv_func_printf_infinite_long_double=yes],
+          [gl_cv_func_printf_infinite_long_double=no],
+          [
+changequote(,)dnl
+           case "$host_cpu" in
+                                   # Guess no on ia64, x86_64, i386.
+             ia64 | x86_64 | i*86) 
gl_cv_func_printf_infinite_long_double="guessing no";;
+             *)
+               case "$host_os" in
+                                       # Guess yes on glibc systems.
+                 *-gnu*)               
gl_cv_func_printf_infinite_long_double="guessing yes";;
+                                       # Guess yes on FreeBSD >= 6.
+                 freebsd[1-5]*)        
gl_cv_func_printf_infinite_long_double="guessing no";;
+                 freebsd* | kfreebsd*) 
gl_cv_func_printf_infinite_long_double="guessing yes";;
+                                       # Guess yes on MacOS X >= 10.3.
+                 darwin[1-6].*)        
gl_cv_func_printf_infinite_long_double="guessing no";;
+                 darwin*)              
gl_cv_func_printf_infinite_long_double="guessing yes";;
+                                       # Guess yes on HP-UX >= 11.
+                 hpux[7-9]* | hpux10*) 
gl_cv_func_printf_infinite_long_double="guessing no";;
+                 hpux*)                
gl_cv_func_printf_infinite_long_double="guessing yes";;
+                                       # Guess yes on NetBSD >= 3.
+                 netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | 
netbsdcoff[1-2]*)
+                                       
gl_cv_func_printf_infinite_long_double="guessing no";;
+                 netbsd*)              
gl_cv_func_printf_infinite_long_double="guessing yes";;
+                                       # If we don't know, assume the worst.
+                 *)                    
gl_cv_func_printf_infinite_long_double="guessing no";;
+               esac
+               ;;
+           esac
+changequote([,])dnl
+          ])
+        ])
+      ;;
+    *)
+      gl_cv_func_printf_infinite_long_double="irrelevant"
+      ;;
+  esac
+])
+
+dnl Test whether the *printf family of functions supports the 'a' and 'A'
+dnl conversion specifier for hexadecimal output of floating-point numbers.
+dnl (ISO C99, POSIX:2001)
+dnl Result is gl_cv_func_printf_directive_a.
+
+AC_DEFUN([gl_PRINTF_DIRECTIVE_A],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf supports the 'a' and 'A' directives],
+    [gl_cv_func_printf_directive_a],
+    [
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <string.h>
+static char buf[100];
+int main ()
+{
+  if (sprintf (buf, "%a %d", 3.1416015625, 33, 44, 55) < 0
+      || (strcmp (buf, "0x1.922p+1 33") != 0
+          && strcmp (buf, "0x3.244p+0 33") != 0
+          && strcmp (buf, "0x6.488p-1 33") != 0
+          && strcmp (buf, "0xc.91p-2 33") != 0))
+    return 1;
+  if (sprintf (buf, "%A %d", -3.1416015625, 33, 44, 55) < 0
+      || (strcmp (buf, "-0X1.922P+1 33") != 0
+          && strcmp (buf, "-0X3.244P+0 33") != 0
+          && strcmp (buf, "-0X6.488P-1 33") != 0
+          && strcmp (buf, "-0XC.91P-2 33") != 0))
+    return 1;
+  /* This catches a FreeBSD 6.1 bug: it doesn't round.  */
+  if (sprintf (buf, "%.2a %d", 1.51, 33, 44, 55) < 0
+      || (strcmp (buf, "0x1.83p+0 33") != 0
+          && strcmp (buf, "0x3.05p-1 33") != 0
+          && strcmp (buf, "0x6.0ap-2 33") != 0
+          && strcmp (buf, "0xc.14p-3 33") != 0))
+    return 1;
+  /* This catches a FreeBSD 6.1 bug.  See
+     <http://lists.gnu.org/archive/html/bug-gnulib/2007-04/msg00107.html> */
+  if (sprintf (buf, "%010a %d", 1.0 / 0.0, 33, 44, 55) < 0
+      || buf[0] == '0')
+    return 1;
+  /* This catches a MacOS X 10.3.9 (Darwin 7.9) bug.  */
+  if (sprintf (buf, "%.1a", 1.999) < 0
+      || (strcmp (buf, "0x1.0p+1") != 0
+          && strcmp (buf, "0x2.0p+0") != 0
+          && strcmp (buf, "0x4.0p-1") != 0
+          && strcmp (buf, "0x8.0p-2") != 0))
+    return 1;
+  /* This catches the same MacOS X 10.3.9 (Darwin 7.9) bug and also a
+     glibc 2.4 bug <http://sourceware.org/bugzilla/show_bug.cgi?id=2908>.  */
+  if (sprintf (buf, "%.1La", 1.999L) < 0
+      || (strcmp (buf, "0x1.0p+1") != 0
+          && strcmp (buf, "0x2.0p+0") != 0
+          && strcmp (buf, "0x4.0p-1") != 0
+          && strcmp (buf, "0x8.0p-2") != 0))
+    return 1;
+  return 0;
+}], [gl_cv_func_printf_directive_a=yes], [gl_cv_func_printf_directive_a=no],
+      [
+       case "$host_os" in
+                               # Guess yes on glibc >= 2.5 systems.
+         *-gnu*)
+           AC_EGREP_CPP([BZ2908], [
+             #include <features.h>
+             #ifdef __GNU_LIBRARY__
+              #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 5) || (__GLIBC__ > 2)
+               BZ2908
+              #endif
+             #endif
+             ],
+             [gl_cv_func_printf_directive_a="guessing yes"],
+             [gl_cv_func_printf_directive_a="guessing no"])
+           ;;
+                               # If we don't know, assume the worst.
+         *)                    gl_cv_func_printf_directive_a="guessing no";;
+       esac
+      ])
+    ])
+])
+
+dnl Test whether the *printf family of functions supports the %F format
+dnl directive. (ISO C99, POSIX:2001)
+dnl Result is gl_cv_func_printf_directive_f.
+
+AC_DEFUN([gl_PRINTF_DIRECTIVE_F],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf supports the 'F' directive],
+    [gl_cv_func_printf_directive_f],
+    [
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <string.h>
+static char buf[100];
+int main ()
+{
+  if (sprintf (buf, "%F %d", 1234567.0, 33, 44, 55) < 0
+      || strcmp (buf, "1234567.000000 33") != 0)
+    return 1;
+  if (sprintf (buf, "%F", 1.0 / 0.0) < 0
+      || (strcmp (buf, "INF") != 0 && strcmp (buf, "INFINITY") != 0))
+    return 1;
+  /* This catches a Cygwin 1.5.x bug.  */
+  if (sprintf (buf, "%.F", 1234.0) < 0
+      || strcmp (buf, "1234") != 0)
+    return 1;
+  return 0;
+}], [gl_cv_func_printf_directive_f=yes], [gl_cv_func_printf_directive_f=no],
+      [
+changequote(,)dnl
+       case "$host_os" in
+                               # Guess yes on glibc systems.
+         *-gnu*)               gl_cv_func_printf_directive_f="guessing yes";;
+                               # Guess yes on FreeBSD >= 6.
+         freebsd[1-5]*)        gl_cv_func_printf_directive_f="guessing no";;
+         freebsd* | kfreebsd*) gl_cv_func_printf_directive_f="guessing yes";;
+                               # Guess yes on MacOS X >= 10.3.
+         darwin[1-6].*)        gl_cv_func_printf_directive_f="guessing no";;
+         darwin*)              gl_cv_func_printf_directive_f="guessing yes";;
+                               # Guess yes on Solaris >= 2.10.
+         solaris2.[0-9]*)      gl_cv_func_printf_directive_f="guessing no";;
+         solaris*)             gl_cv_func_printf_directive_f="guessing yes";;
+                               # If we don't know, assume the worst.
+         *)                    gl_cv_func_printf_directive_f="guessing no";;
+       esac
+changequote([,])dnl
+      ])
+    ])
+])
+
+dnl Test whether the *printf family of functions supports the %n format
+dnl directive. (ISO C99, POSIX:2001)
+dnl Result is gl_cv_func_printf_directive_n.
+
+AC_DEFUN([gl_PRINTF_DIRECTIVE_N],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf supports the 'n' directive],
+    [gl_cv_func_printf_directive_n],
+    [
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <string.h>
+static char fmtstring[10];
+static char buf[100];
+int main ()
+{
+  int count = -1;
+  /* Copy the format string.  Some systems (glibc with _FORTIFY_SOURCE=2)
+     support %n in format strings in read-only memory but not in writable
+     memory.  */
+  strcpy (fmtstring, "%d %n");
+  if (sprintf (buf, fmtstring, 123, &count, 33, 44, 55) < 0
+      || strcmp (buf, "123 ") != 0
+      || count != 4)
+    return 1;
+  return 0;
+}], [gl_cv_func_printf_directive_n=yes], [gl_cv_func_printf_directive_n=no],
+      [
+changequote(,)dnl
+       case "$host_os" in
+         *)     gl_cv_func_printf_directive_n="guessing yes";;
+       esac
+changequote([,])dnl
+      ])
+    ])
+])
+
+dnl Test whether the *printf family of functions supports the %ls format
+dnl directive and in particular, when a precision is specified, whether
+dnl the functions stop converting the wide string argument when the number
+dnl of bytes that have been produced by this conversion equals or exceeds
+dnl the precision.
+dnl Result is gl_cv_func_printf_directive_ls.
+
+AC_DEFUN([gl_PRINTF_DIRECTIVE_LS],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf supports the 'ls' directive],
+    [gl_cv_func_printf_directive_ls],
+    [
+      AC_TRY_RUN([
+/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
+   <wchar.h>.
+   BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
+   included before <wchar.h>.  */
+#include <stddef.h>
+#include <stdio.h>
+#include <time.h>
+#include <wchar.h>
+#include <string.h>
+int main ()
+{
+  char buf[100];
+  /* Test whether %ls works at all.
+     This test fails on OpenBSD 4.0, IRIX 6.5, Solaris 2.6, Haiku, but not on
+     Cygwin 1.5.  */
+  {
+    static const wchar_t wstring[] = { 'a', 'b', 'c', 0 };
+    buf[0] = '\0';
+    if (sprintf (buf, "%ls", wstring) < 0
+        || strcmp (buf, "abc") != 0)
+      return 1;
+  }
+  /* This test fails on IRIX 6.5, Solaris 2.6, Cygwin 1.5, Haiku (with an
+     assertion failure inside libc), but not on OpenBSD 4.0.  */
+  {
+    static const wchar_t wstring[] = { 'a', 0 };
+    buf[0] = '\0';
+    if (sprintf (buf, "%ls", wstring) < 0
+        || strcmp (buf, "a") != 0)
+      return 1;
+  }
+  /* Test whether precisions in %ls are supported as specified in ISO C 99
+     section 7.19.6.1:
+       "If a precision is specified, no more than that many bytes are written
+        (including shift sequences, if any), and the array shall contain a
+        null wide character if, to equal the multibyte character sequence
+        length given by the precision, the function would need to access a
+        wide character one past the end of the array."
+     This test fails on Solaris 10.  */
+  {
+    static const wchar_t wstring[] = { 'a', 'b', (wchar_t) 0xfdfdfdfd, 0 };
+    buf[0] = '\0';
+    if (sprintf (buf, "%.2ls", wstring) < 0
+        || strcmp (buf, "ab") != 0)
+      return 1;
+  }
+  return 0;
+}], [gl_cv_func_printf_directive_ls=yes], [gl_cv_func_printf_directive_ls=no],
+      [
+changequote(,)dnl
+       case "$host_os" in
+         openbsd*)        gl_cv_func_printf_directive_ls="guessing no";;
+         irix*)           gl_cv_func_printf_directive_ls="guessing no";;
+         solaris*)        gl_cv_func_printf_directive_ls="guessing no";;
+         cygwin*)         gl_cv_func_printf_directive_ls="guessing no";;
+         beos* | haiku*)  gl_cv_func_printf_directive_ls="guessing no";;
+         *)               gl_cv_func_printf_directive_ls="guessing yes";;
+       esac
+changequote([,])dnl
+      ])
+    ])
+])
+
+dnl Test whether the *printf family of functions supports POSIX/XSI format
+dnl strings with positions. (POSIX:2001)
+dnl Result is gl_cv_func_printf_positions.
+
+AC_DEFUN([gl_PRINTF_POSITIONS],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf supports POSIX/XSI format strings with 
positions],
+    [gl_cv_func_printf_positions],
+    [
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <string.h>
+/* The string "%2$d %1$d", with dollar characters protected from the shell's
+   dollar expansion (possibly an autoconf bug).  */
+static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' };
+static char buf[100];
+int main ()
+{
+  sprintf (buf, format, 33, 55);
+  return (strcmp (buf, "55 33") != 0);
+}], [gl_cv_func_printf_positions=yes], [gl_cv_func_printf_positions=no],
+      [
+changequote(,)dnl
+       case "$host_os" in
+         netbsd[1-3]* | netbsdelf[1-3]* | netbsdaout[1-3]* | netbsdcoff[1-3]*)
+                       gl_cv_func_printf_positions="guessing no";;
+         beos*)        gl_cv_func_printf_positions="guessing no";;
+         mingw* | pw*) gl_cv_func_printf_positions="guessing no";;
+         *)            gl_cv_func_printf_positions="guessing yes";;
+       esac
+changequote([,])dnl
+      ])
+    ])
+])
+
+dnl Test whether the *printf family of functions supports POSIX/XSI format
+dnl strings with the ' flag for grouping of decimal digits. (POSIX:2001)
+dnl Result is gl_cv_func_printf_flag_grouping.
+
+AC_DEFUN([gl_PRINTF_FLAG_GROUPING],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf supports the grouping flag],
+    [gl_cv_func_printf_flag_grouping],
+    [
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <string.h>
+static char buf[100];
+int main ()
+{
+  if (sprintf (buf, "%'d %d", 1234567, 99) < 0
+      || buf[strlen (buf) - 1] != '9')
+    return 1;
+  return 0;
+}], [gl_cv_func_printf_flag_grouping=yes], 
[gl_cv_func_printf_flag_grouping=no],
+      [
+changequote(,)dnl
+       case "$host_os" in
+         cygwin*)      gl_cv_func_printf_flag_grouping="guessing no";;
+         netbsd*)      gl_cv_func_printf_flag_grouping="guessing no";;
+         mingw* | pw*) gl_cv_func_printf_flag_grouping="guessing no";;
+         *)            gl_cv_func_printf_flag_grouping="guessing yes";;
+       esac
+changequote([,])dnl
+      ])
+    ])
+])
+
+dnl Test whether the *printf family of functions supports the - flag correctly.
+dnl (ISO C99.) See
+dnl <http://lists.gnu.org/archive/html/bug-coreutils/2008-02/msg00035.html>
+dnl Result is gl_cv_func_printf_flag_leftadjust.
+
+AC_DEFUN([gl_PRINTF_FLAG_LEFTADJUST],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf supports the left-adjust flag correctly],
+    [gl_cv_func_printf_flag_leftadjust],
+    [
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <string.h>
+static char buf[100];
+int main ()
+{
+  /* Check that a '-' flag is not annihilated by a negative width.  */
+  if (sprintf (buf, "a%-*sc", -3, "b") < 0
+      || strcmp (buf, "ab  c") != 0)
+    return 1;
+  return 0;
+}],
+        [gl_cv_func_printf_flag_leftadjust=yes],
+        [gl_cv_func_printf_flag_leftadjust=no],
+        [
+changequote(,)dnl
+         case "$host_os" in
+                    # Guess yes on HP-UX 11.
+           hpux11*) gl_cv_func_printf_flag_leftadjust="guessing yes";;
+                    # Guess no on HP-UX 10 and older.
+           hpux*)   gl_cv_func_printf_flag_leftadjust="guessing no";;
+                    # Guess yes otherwise.
+           *)       gl_cv_func_printf_flag_leftadjust="guessing yes";;
+         esac
+changequote([,])dnl
+        ])
+    ])
+])
+
+dnl Test whether the *printf family of functions supports padding of non-finite
+dnl values with the 0 flag correctly. (ISO C99 + TC1 + TC2.) See
+dnl <http://lists.gnu.org/archive/html/bug-gnulib/2007-04/msg00107.html>
+dnl Result is gl_cv_func_printf_flag_zero.
+
+AC_DEFUN([gl_PRINTF_FLAG_ZERO],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf supports the zero flag correctly],
+    [gl_cv_func_printf_flag_zero],
+    [
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <string.h>
+static char buf[100];
+int main ()
+{
+  if (sprintf (buf, "%010f", 1.0 / 0.0, 33, 44, 55) < 0
+      || (strcmp (buf, "       inf") != 0
+          && strcmp (buf, "  infinity") != 0))
+    return 1;
+  return 0;
+}], [gl_cv_func_printf_flag_zero=yes], [gl_cv_func_printf_flag_zero=no],
+      [
+changequote(,)dnl
+       case "$host_os" in
+                 # Guess yes on glibc systems.
+         *-gnu*) gl_cv_func_printf_flag_zero="guessing yes";;
+                 # Guess yes on BeOS.
+         beos*)  gl_cv_func_printf_flag_zero="guessing yes";;
+                 # If we don't know, assume the worst.
+         *)      gl_cv_func_printf_flag_zero="guessing no";;
+       esac
+changequote([,])dnl
+      ])
+    ])
+])
+
+dnl Test whether the *printf family of functions supports large precisions.
+dnl On mingw, precisions larger than 512 are treated like 512, in integer,
+dnl floating-point or pointer output. On BeOS, precisions larger than 1044
+dnl crash the program.
+dnl Result is gl_cv_func_printf_precision.
+
+AC_DEFUN([gl_PRINTF_PRECISION],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf supports large precisions],
+    [gl_cv_func_printf_precision],
+    [
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <string.h>
+static char buf[5000];
+int main ()
+{
+#ifdef __BEOS__
+  /* On BeOS, this would crash and show a dialog box.  Avoid the crash.  */
+  return 1;
+#endif
+  if (sprintf (buf, "%.4000d %d", 1, 33, 44) < 4000 + 3)
+    return 1;
+  return 0;
+}], [gl_cv_func_printf_precision=yes], [gl_cv_func_printf_precision=no],
+      [
+changequote(,)dnl
+       case "$host_os" in
+         # Guess no only on native Win32 and BeOS systems.
+         mingw* | pw*) gl_cv_func_printf_precision="guessing no" ;;
+         beos*)        gl_cv_func_printf_precision="guessing no" ;;
+         *)            gl_cv_func_printf_precision="guessing yes" ;;
+       esac
+changequote([,])dnl
+      ])
+    ])
+])
+
+dnl Test whether the *printf family of functions recovers gracefully in case
+dnl of an out-of-memory condition, or whether it crashes the entire program.
+dnl Result is gl_cv_func_printf_enomem.
+
+AC_DEFUN([gl_PRINTF_ENOMEM],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([gl_MULTIARCH])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf survives out-of-memory conditions],
+    [gl_cv_func_printf_enomem],
+    [
+      gl_cv_func_printf_enomem="guessing no"
+      if test "$cross_compiling" = no; then
+        if test $APPLE_UNIVERSAL_BUILD = 0; then
+          AC_LANG_CONFTEST([AC_LANG_SOURCE([
+]GL_NOCRASH[
+changequote(,)dnl
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <errno.h>
+int main()
+{
+  struct rlimit limit;
+  int ret;
+  nocrash_init ();
+  /* Some printf implementations allocate temporary space with malloc.  */
+  /* On BSD systems, malloc() is limited by RLIMIT_DATA.  */
+#ifdef RLIMIT_DATA
+  if (getrlimit (RLIMIT_DATA, &limit) < 0)
+    return 77;
+  if (limit.rlim_max == RLIM_INFINITY || limit.rlim_max > 5000000)
+    limit.rlim_max = 5000000;
+  limit.rlim_cur = limit.rlim_max;
+  if (setrlimit (RLIMIT_DATA, &limit) < 0)
+    return 77;
+#endif
+  /* On Linux systems, malloc() is limited by RLIMIT_AS.  */
+#ifdef RLIMIT_AS
+  if (getrlimit (RLIMIT_AS, &limit) < 0)
+    return 77;
+  if (limit.rlim_max == RLIM_INFINITY || limit.rlim_max > 5000000)
+    limit.rlim_max = 5000000;
+  limit.rlim_cur = limit.rlim_max;
+  if (setrlimit (RLIMIT_AS, &limit) < 0)
+    return 77;
+#endif
+  /* Some printf implementations allocate temporary space on the stack.  */
+#ifdef RLIMIT_STACK
+  if (getrlimit (RLIMIT_STACK, &limit) < 0)
+    return 77;
+  if (limit.rlim_max == RLIM_INFINITY || limit.rlim_max > 5000000)
+    limit.rlim_max = 5000000;
+  limit.rlim_cur = limit.rlim_max;
+  if (setrlimit (RLIMIT_STACK, &limit) < 0)
+    return 77;
+#endif
+  ret = printf ("%.5000000f", 1.0);
+  return !(ret == 5000002 || (ret < 0 && errno == ENOMEM));
+}
+changequote([,])dnl
+          ])])
+          if AC_TRY_EVAL([ac_link]) && test -s conftest$ac_exeext; then
+            (./conftest
+             result=$?
+             if test $result != 0 && test $result != 77; then result=1; fi
+             exit $result
+            ) >/dev/null 2>/dev/null
+            case $? in
+              0) gl_cv_func_printf_enomem="yes" ;;
+              77) gl_cv_func_printf_enomem="guessing no" ;;
+              *) gl_cv_func_printf_enomem="no" ;;
+            esac
+          else
+            gl_cv_func_printf_enomem="guessing no"
+          fi
+          rm -fr conftest*
+        else
+          dnl A universal build on Apple MacOS X platforms.
+          dnl The result would be 'no' in 32-bit mode and 'yes' in 64-bit mode.
+          dnl But we need a configuration result that is valid in both modes.
+          gl_cv_func_printf_enomem="guessing no"
+        fi
+      fi
+      if test "$gl_cv_func_printf_enomem" = "guessing no"; then
+changequote(,)dnl
+        case "$host_os" in
+                    # Guess yes on glibc systems.
+          *-gnu*)   gl_cv_func_printf_enomem="guessing yes";;
+                    # Guess yes on Solaris.
+          solaris*) gl_cv_func_printf_enomem="guessing yes";;
+                    # Guess yes on AIX.
+          aix*)     gl_cv_func_printf_enomem="guessing yes";;
+                    # Guess yes on HP-UX/hppa.
+          hpux*)    case "$host_cpu" in
+                      hppa*) gl_cv_func_printf_enomem="guessing yes";;
+                      *)     gl_cv_func_printf_enomem="guessing no";;
+                    esac
+                    ;;
+                    # Guess yes on IRIX.
+          irix*)    gl_cv_func_printf_enomem="guessing yes";;
+                    # Guess yes on OSF/1.
+          osf*)     gl_cv_func_printf_enomem="guessing yes";;
+                    # Guess yes on BeOS.
+          beos*)    gl_cv_func_printf_enomem="guessing yes";;
+                    # Guess yes on Haiku.
+          haiku*)   gl_cv_func_printf_enomem="guessing yes";;
+                    # If we don't know, assume the worst.
+          *)        gl_cv_func_printf_enomem="guessing no";;
+        esac
+changequote([,])dnl
+      fi
+    ])
+])
+
+dnl Test whether the snprintf function exists. (ISO C99, POSIX:2001)
+dnl Result is ac_cv_func_snprintf.
+
+AC_DEFUN([gl_SNPRINTF_PRESENCE],
+[
+  AC_CHECK_FUNCS_ONCE([snprintf])
+])
+
+dnl Test whether the string produced by the snprintf function is always NUL
+dnl terminated. (ISO C99, POSIX:2001)
+dnl Result is gl_cv_func_snprintf_truncation_c99.
+
+AC_DEFUN([gl_SNPRINTF_TRUNCATION_C99],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether snprintf truncates the result as in C99],
+    [gl_cv_func_snprintf_truncation_c99],
+    [
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <string.h>
+static char buf[100];
+int main ()
+{
+  strcpy (buf, "ABCDEF");
+  snprintf (buf, 3, "%d %d", 4567, 89);
+  if (memcmp (buf, "45\0DEF", 6) != 0)
+    return 1;
+  return 0;
+}], [gl_cv_func_snprintf_truncation_c99=yes], 
[gl_cv_func_snprintf_truncation_c99=no],
+      [
+changequote(,)dnl
+       case "$host_os" in
+                               # Guess yes on glibc systems.
+         *-gnu*)               gl_cv_func_snprintf_truncation_c99="guessing 
yes";;
+                               # Guess yes on FreeBSD >= 5.
+         freebsd[1-4]*)        gl_cv_func_snprintf_truncation_c99="guessing 
no";;
+         freebsd* | kfreebsd*) gl_cv_func_snprintf_truncation_c99="guessing 
yes";;
+                               # Guess yes on MacOS X >= 10.3.
+         darwin[1-6].*)        gl_cv_func_snprintf_truncation_c99="guessing 
no";;
+         darwin*)              gl_cv_func_snprintf_truncation_c99="guessing 
yes";;
+                               # Guess yes on OpenBSD >= 3.9.
+         openbsd[1-2].* | openbsd3.[0-8] | openbsd3.[0-8].*)
+                               gl_cv_func_snprintf_truncation_c99="guessing 
no";;
+         openbsd*)             gl_cv_func_snprintf_truncation_c99="guessing 
yes";;
+                               # Guess yes on Solaris >= 2.6.
+         solaris2.[0-5]*)      gl_cv_func_snprintf_truncation_c99="guessing 
no";;
+         solaris*)             gl_cv_func_snprintf_truncation_c99="guessing 
yes";;
+                               # Guess yes on AIX >= 4.
+         aix[1-3]*)            gl_cv_func_snprintf_truncation_c99="guessing 
no";;
+         aix*)                 gl_cv_func_snprintf_truncation_c99="guessing 
yes";;
+                               # Guess yes on HP-UX >= 11.
+         hpux[7-9]* | hpux10*) gl_cv_func_snprintf_truncation_c99="guessing 
no";;
+         hpux*)                gl_cv_func_snprintf_truncation_c99="guessing 
yes";;
+                               # Guess yes on IRIX >= 6.5.
+         irix6.5)              gl_cv_func_snprintf_truncation_c99="guessing 
yes";;
+                               # Guess yes on OSF/1 >= 5.
+         osf[3-4]*)            gl_cv_func_snprintf_truncation_c99="guessing 
no";;
+         osf*)                 gl_cv_func_snprintf_truncation_c99="guessing 
yes";;
+                               # Guess yes on NetBSD >= 3.
+         netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | netbsdcoff[1-2]*)
+                               gl_cv_func_snprintf_truncation_c99="guessing 
no";;
+         netbsd*)              gl_cv_func_snprintf_truncation_c99="guessing 
yes";;
+                               # Guess yes on BeOS.
+         beos*)                gl_cv_func_snprintf_truncation_c99="guessing 
yes";;
+                               # If we don't know, assume the worst.
+         *)                    gl_cv_func_snprintf_truncation_c99="guessing 
no";;
+       esac
+changequote([,])dnl
+      ])
+    ])
+])
+
+dnl Test whether the return value of the snprintf function is the number
+dnl of bytes (excluding the terminating NUL) that would have been produced
+dnl if the buffer had been large enough. (ISO C99, POSIX:2001)
+dnl For example, this test program fails on IRIX 6.5:
+dnl     ---------------------------------------------------------------------
+dnl     #include <stdio.h>
+dnl     int main()
+dnl     {
+dnl       static char buf[8];
+dnl       int retval = snprintf (buf, 3, "%d", 12345);
+dnl       return retval >= 0 && retval < 3;
+dnl     }
+dnl     ---------------------------------------------------------------------
+dnl Result is gl_cv_func_snprintf_retval_c99.
+
+AC_DEFUN([gl_SNPRINTF_RETVAL_C99],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether snprintf returns a byte count as in C99],
+    [gl_cv_func_snprintf_retval_c99],
+    [
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <string.h>
+static char buf[100];
+int main ()
+{
+  strcpy (buf, "ABCDEF");
+  if (snprintf (buf, 3, "%d %d", 4567, 89) != 7)
+    return 1;
+  return 0;
+}], [gl_cv_func_snprintf_retval_c99=yes], [gl_cv_func_snprintf_retval_c99=no],
+      [
+changequote(,)dnl
+       case "$host_os" in
+                               # Guess yes on glibc systems.
+         *-gnu*)               gl_cv_func_snprintf_retval_c99="guessing yes";;
+                               # Guess yes on FreeBSD >= 5.
+         freebsd[1-4]*)        gl_cv_func_snprintf_retval_c99="guessing no";;
+         freebsd* | kfreebsd*) gl_cv_func_snprintf_retval_c99="guessing yes";;
+                               # Guess yes on MacOS X >= 10.3.
+         darwin[1-6].*)        gl_cv_func_snprintf_retval_c99="guessing no";;
+         darwin*)              gl_cv_func_snprintf_retval_c99="guessing yes";;
+                               # Guess yes on OpenBSD >= 3.9.
+         openbsd[1-2].* | openbsd3.[0-8] | openbsd3.[0-8].*)
+                               gl_cv_func_snprintf_retval_c99="guessing no";;
+         openbsd*)             gl_cv_func_snprintf_retval_c99="guessing yes";;
+                               # Guess yes on Solaris >= 2.6.
+         solaris2.[0-5]*)      gl_cv_func_snprintf_retval_c99="guessing no";;
+         solaris*)             gl_cv_func_snprintf_retval_c99="guessing yes";;
+                               # Guess yes on AIX >= 4.
+         aix[1-3]*)            gl_cv_func_snprintf_retval_c99="guessing no";;
+         aix*)                 gl_cv_func_snprintf_retval_c99="guessing yes";;
+                               # Guess yes on NetBSD >= 3.
+         netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | netbsdcoff[1-2]*)
+                               gl_cv_func_snprintf_retval_c99="guessing no";;
+         netbsd*)              gl_cv_func_snprintf_retval_c99="guessing yes";;
+                               # Guess yes on BeOS.
+         beos*)                gl_cv_func_snprintf_retval_c99="guessing yes";;
+                               # If we don't know, assume the worst.
+         *)                    gl_cv_func_snprintf_retval_c99="guessing no";;
+       esac
+changequote([,])dnl
+      ])
+    ])
+])
+
+dnl Test whether the snprintf function supports the %n format directive
+dnl also in truncated portions of the format string. (ISO C99, POSIX:2001)
+dnl Result is gl_cv_func_snprintf_directive_n.
+
+AC_DEFUN([gl_SNPRINTF_DIRECTIVE_N],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether snprintf fully supports the 'n' directive],
+    [gl_cv_func_snprintf_directive_n],
+    [
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <string.h>
+static char fmtstring[10];
+static char buf[100];
+int main ()
+{
+  int count = -1;
+  /* Copy the format string.  Some systems (glibc with _FORTIFY_SOURCE=2)
+     support %n in format strings in read-only memory but not in writable
+     memory.  */
+  strcpy (fmtstring, "%d %n");
+  snprintf (buf, 4, fmtstring, 12345, &count, 33, 44, 55);
+  if (count != 6)
+    return 1;
+  return 0;
+}], [gl_cv_func_snprintf_directive_n=yes], 
[gl_cv_func_snprintf_directive_n=no],
+      [
+changequote(,)dnl
+       case "$host_os" in
+                               # Guess yes on glibc systems.
+         *-gnu*)               gl_cv_func_snprintf_directive_n="guessing yes";;
+                               # Guess yes on FreeBSD >= 5.
+         freebsd[1-4]*)        gl_cv_func_snprintf_directive_n="guessing no";;
+         freebsd* | kfreebsd*) gl_cv_func_snprintf_directive_n="guessing yes";;
+                               # Guess yes on MacOS X >= 10.3.
+         darwin[1-6].*)        gl_cv_func_snprintf_directive_n="guessing no";;
+         darwin*)              gl_cv_func_snprintf_directive_n="guessing yes";;
+                               # Guess yes on Solaris >= 2.6.
+         solaris2.[0-5]*)      gl_cv_func_snprintf_directive_n="guessing no";;
+         solaris*)             gl_cv_func_snprintf_directive_n="guessing yes";;
+                               # Guess yes on AIX >= 4.
+         aix[1-3]*)            gl_cv_func_snprintf_directive_n="guessing no";;
+         aix*)                 gl_cv_func_snprintf_directive_n="guessing yes";;
+                               # Guess yes on IRIX >= 6.5.
+         irix6.5)              gl_cv_func_snprintf_directive_n="guessing yes";;
+                               # Guess yes on OSF/1 >= 5.
+         osf[3-4]*)            gl_cv_func_snprintf_directive_n="guessing no";;
+         osf*)                 gl_cv_func_snprintf_directive_n="guessing yes";;
+                               # Guess yes on NetBSD >= 3.
+         netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | netbsdcoff[1-2]*)
+                               gl_cv_func_snprintf_directive_n="guessing no";;
+         netbsd*)              gl_cv_func_snprintf_directive_n="guessing yes";;
+                               # Guess yes on BeOS.
+         beos*)                gl_cv_func_snprintf_directive_n="guessing yes";;
+                               # If we don't know, assume the worst.
+         *)                    gl_cv_func_snprintf_directive_n="guessing no";;
+       esac
+changequote([,])dnl
+      ])
+    ])
+])
+
+dnl Test whether the snprintf function, when passed a size = 1, writes any
+dnl output without bounds in this case, behaving like sprintf. This is the
+dnl case on Linux libc5.
+dnl Result is gl_cv_func_snprintf_size1.
+
+AC_DEFUN([gl_SNPRINTF_SIZE1],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_CACHE_CHECK([whether snprintf respects a size of 1],
+    [gl_cv_func_snprintf_size1],
+    [
+      AC_TRY_RUN([
+#include <stdio.h>
+int main()
+{
+  static char buf[8] = { 'D', 'E', 'A', 'D', 'B', 'E', 'E', 'F' };
+  snprintf (buf, 1, "%d", 12345);
+  return buf[1] != 'E';
+}],
+      [gl_cv_func_snprintf_size1=yes],
+      [gl_cv_func_snprintf_size1=no],
+      [gl_cv_func_snprintf_size1="guessing yes"])
+    ])
+])
+
+dnl Test whether the vsnprintf function, when passed a zero size, produces no
+dnl output. (ISO C99, POSIX:2001)
+dnl For example, snprintf nevertheless writes a NUL byte in this case
+dnl on OSF/1 5.1:
+dnl     ---------------------------------------------------------------------
+dnl     #include <stdio.h>
+dnl     int main()
+dnl     {
+dnl       static char buf[8] = { 'D', 'E', 'A', 'D', 'B', 'E', 'E', 'F' };
+dnl       snprintf (buf, 0, "%d", 12345);
+dnl       return buf[0] != 'D';
+dnl     }
+dnl     ---------------------------------------------------------------------
+dnl And vsnprintf writes any output without bounds in this case, behaving like
+dnl vsprintf, on HP-UX 11 and OSF/1 5.1:
+dnl     ---------------------------------------------------------------------
+dnl     #include <stdarg.h>
+dnl     #include <stdio.h>
+dnl     static int my_snprintf (char *buf, int size, const char *format, ...)
+dnl     {
+dnl       va_list args;
+dnl       int ret;
+dnl       va_start (args, format);
+dnl       ret = vsnprintf (buf, size, format, args);
+dnl       va_end (args);
+dnl       return ret;
+dnl     }
+dnl     int main()
+dnl     {
+dnl       static char buf[8] = { 'D', 'E', 'A', 'D', 'B', 'E', 'E', 'F' };
+dnl       my_snprintf (buf, 0, "%d", 12345);
+dnl       return buf[0] != 'D';
+dnl     }
+dnl     ---------------------------------------------------------------------
+dnl Result is gl_cv_func_vsnprintf_zerosize_c99.
+
+AC_DEFUN([gl_VSNPRINTF_ZEROSIZE_C99],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether vsnprintf respects a zero size as in C99],
+    [gl_cv_func_vsnprintf_zerosize_c99],
+    [
+      AC_TRY_RUN([
+#include <stdarg.h>
+#include <stdio.h>
+static int my_snprintf (char *buf, int size, const char *format, ...)
+{
+  va_list args;
+  int ret;
+  va_start (args, format);
+  ret = vsnprintf (buf, size, format, args);
+  va_end (args);
+  return ret;
+}
+int main()
+{
+  static char buf[8] = { 'D', 'E', 'A', 'D', 'B', 'E', 'E', 'F' };
+  my_snprintf (buf, 0, "%d", 12345);
+  return buf[0] != 'D';
+}],
+      [gl_cv_func_vsnprintf_zerosize_c99=yes],
+      [gl_cv_func_vsnprintf_zerosize_c99=no],
+      [
+changequote(,)dnl
+       case "$host_os" in
+                               # Guess yes on glibc systems.
+         *-gnu*)               gl_cv_func_vsnprintf_zerosize_c99="guessing 
yes";;
+                               # Guess yes on FreeBSD >= 5.
+         freebsd[1-4]*)        gl_cv_func_vsnprintf_zerosize_c99="guessing 
no";;
+         freebsd* | kfreebsd*) gl_cv_func_vsnprintf_zerosize_c99="guessing 
yes";;
+                               # Guess yes on MacOS X >= 10.3.
+         darwin[1-6].*)        gl_cv_func_vsnprintf_zerosize_c99="guessing 
no";;
+         darwin*)              gl_cv_func_vsnprintf_zerosize_c99="guessing 
yes";;
+                               # Guess yes on Cygwin.
+         cygwin*)              gl_cv_func_vsnprintf_zerosize_c99="guessing 
yes";;
+                               # Guess yes on Solaris >= 2.6.
+         solaris2.[0-5]*)      gl_cv_func_vsnprintf_zerosize_c99="guessing 
no";;
+         solaris*)             gl_cv_func_vsnprintf_zerosize_c99="guessing 
yes";;
+                               # Guess yes on AIX >= 4.
+         aix[1-3]*)            gl_cv_func_vsnprintf_zerosize_c99="guessing 
no";;
+         aix*)                 gl_cv_func_vsnprintf_zerosize_c99="guessing 
yes";;
+                               # Guess yes on IRIX >= 6.5.
+         irix6.5)              gl_cv_func_vsnprintf_zerosize_c99="guessing 
yes";;
+                               # Guess yes on NetBSD >= 3.
+         netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | netbsdcoff[1-2]*)
+                               gl_cv_func_vsnprintf_zerosize_c99="guessing 
no";;
+         netbsd*)              gl_cv_func_vsnprintf_zerosize_c99="guessing 
yes";;
+                               # Guess yes on BeOS.
+         beos*)                gl_cv_func_vsnprintf_zerosize_c99="guessing 
yes";;
+                               # Guess yes on mingw.
+         mingw* | pw*)         gl_cv_func_vsnprintf_zerosize_c99="guessing 
yes";;
+                               # If we don't know, assume the worst.
+         *)                    gl_cv_func_vsnprintf_zerosize_c99="guessing 
no";;
+       esac
+changequote([,])dnl
+      ])
+    ])
+])
+
+dnl The results of these tests on various platforms are:
+dnl
+dnl 1 = gl_PRINTF_SIZES_C99
+dnl 2 = gl_PRINTF_LONG_DOUBLE
+dnl 3 = gl_PRINTF_INFINITE
+dnl 4 = gl_PRINTF_INFINITE_LONG_DOUBLE
+dnl 5 = gl_PRINTF_DIRECTIVE_A
+dnl 6 = gl_PRINTF_DIRECTIVE_F
+dnl 7 = gl_PRINTF_DIRECTIVE_N
+dnl 8 = gl_PRINTF_DIRECTIVE_LS
+dnl 9 = gl_PRINTF_POSITIONS
+dnl 10 = gl_PRINTF_FLAG_GROUPING
+dnl 11 = gl_PRINTF_FLAG_LEFTADJUST
+dnl 12 = gl_PRINTF_FLAG_ZERO
+dnl 13 = gl_PRINTF_PRECISION
+dnl 14 = gl_PRINTF_ENOMEM
+dnl 15 = gl_SNPRINTF_PRESENCE
+dnl 16 = gl_SNPRINTF_TRUNCATION_C99
+dnl 17 = gl_SNPRINTF_RETVAL_C99
+dnl 18 = gl_SNPRINTF_DIRECTIVE_N
+dnl 19 = gl_SNPRINTF_SIZE1
+dnl 20 = gl_VSNPRINTF_ZEROSIZE_C99
+dnl
+dnl 1 = checking whether printf supports size specifiers as in C99...
+dnl 2 = checking whether printf supports 'long double' arguments...
+dnl 3 = checking whether printf supports infinite 'double' arguments...
+dnl 4 = checking whether printf supports infinite 'long double' arguments...
+dnl 5 = checking whether printf supports the 'a' and 'A' directives...
+dnl 6 = checking whether printf supports the 'F' directive...
+dnl 7 = checking whether printf supports the 'n' directive...
+dnl 8 = checking whether printf supports the 'ls' directive...
+dnl 9 = checking whether printf supports POSIX/XSI format strings with 
positions...
+dnl 10 = checking whether printf supports the grouping flag...
+dnl 11 = checking whether printf supports the left-adjust flag correctly...
+dnl 12 = checking whether printf supports the zero flag correctly...
+dnl 13 = checking whether printf supports large precisions...
+dnl 14 = checking whether printf survives out-of-memory conditions...
+dnl 15 = checking for snprintf...
+dnl 16 = checking whether snprintf truncates the result as in C99...
+dnl 17 = checking whether snprintf returns a byte count as in C99...
+dnl 18 = checking whether snprintf fully supports the 'n' directive...
+dnl 19 = checking whether snprintf respects a size of 1...
+dnl 20 = checking whether vsnprintf respects a zero size as in C99...
+dnl
+dnl . = yes, # = no.
+dnl
+dnl                                  1  2  3  4  5  6  7  8  9 10 11 12 13 14 
15 16 17 18 19 20
+dnl   glibc 2.5                      .  .  .  .  .  .  .  .  .  .  .  .  .  .  
.  .  .  .  .  .
+dnl   glibc 2.3.6                    .  .  .  .  #  .  .  .  .  .  .  .  .  .  
.  .  .  .  .  .
+dnl   FreeBSD 5.4, 6.1               .  .  .  .  #  .  .  .  .  .  .  #  .  #  
.  .  .  .  .  .
+dnl   MacOS X 10.3.9                 .  .  .  .  #  .  .  .  .  .  .  #  .  #  
.  .  .  .  .  .
+dnl   OpenBSD 3.9, 4.0               .  .  #  #  #  #  .  #  .  #  .  #  .  #  
.  .  .  .  .  .
+dnl   Cygwin 1.7.0 (2009)            .  .  .  #  .  .  .  ?  .  .  .  .  .  ?  
.  .  .  .  .  .
+dnl   Cygwin 1.5.25 (2008)           .  .  .  #  #  .  .  #  .  .  .  .  .  #  
.  .  .  .  .  .
+dnl   Cygwin 1.5.19 (2006)           #  .  .  #  #  #  .  #  .  #  .  #  #  #  
.  .  .  .  .  .
+dnl   Solaris 10                     .  .  #  #  #  .  .  #  .  .  .  #  .  .  
.  .  .  .  .  .
+dnl   Solaris 2.6 ... 9              #  .  #  #  #  #  .  #  .  .  .  #  .  .  
.  .  .  .  .  .
+dnl   Solaris 2.5.1                  #  .  #  #  #  #  .  #  .  .  .  #  .  .  
#  #  #  #  #  #
+dnl   AIX 5.2                        .  .  #  #  #  .  .  .  .  .  .  #  .  .  
.  .  .  .  .  .
+dnl   AIX 4.3.2, 5.1                 #  .  #  #  #  #  .  .  .  .  .  #  .  .  
.  .  .  .  .  .
+dnl   HP-UX 11.31                    .  .  .  .  #  .  .  .  .  .  .  #  .  .  
.  .  #  #  .  .
+dnl   HP-UX 11.{00,11,23}            #  .  .  .  #  #  .  .  .  .  .  #  .  .  
.  .  #  #  .  #
+dnl   HP-UX 10.20                    #  .  #  .  #  #  .  ?  .  .  #  #  .  .  
.  .  #  #  ?  #
+dnl   IRIX 6.5                       #  .  #  #  #  #  .  #  .  .  .  #  .  .  
.  .  #  .  .  .
+dnl   OSF/1 5.1                      #  .  #  #  #  #  .  .  .  .  .  #  .  .  
.  .  #  .  .  #
+dnl   OSF/1 4.0d                     #  .  #  #  #  #  .  .  .  .  .  #  .  .  
#  #  #  #  #  #
+dnl   NetBSD 4.0                     .  ?  ?  ?  ?  ?  .  ?  .  ?  ?  ?  ?  ?  
.  .  .  ?  ?  ?
+dnl   NetBSD 3.0                     .  .  .  .  #  #  .  ?  #  #  ?  #  .  #  
.  .  .  .  .  .
+dnl   Haiku                          .  .  .  #  #  #  .  #  .  .  .  .  .  ?  
.  .  .  .  .  .
+dnl   BeOS                           #  #  .  #  #  #  .  ?  #  .  ?  .  #  ?  
.  .  .  .  .  .
+dnl   mingw                          #  #  #  #  #  #  .  .  #  #  .  #  #  ?  
.  #  #  #  .  .
diff --git a/m4/size_max.m4 b/m4/size_max.m4
new file mode 100644
index 0000000..35bd3d6
--- /dev/null
+++ b/m4/size_max.m4
@@ -0,0 +1,75 @@
+# size_max.m4 serial 9
+dnl Copyright (C) 2003, 2005-2006, 2008-2009 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_DEFUN([gl_SIZE_MAX],
+[
+  AC_CHECK_HEADERS([stdint.h])
+  dnl First test whether the system already has SIZE_MAX.
+  AC_CACHE_CHECK([for SIZE_MAX], [gl_cv_size_max], [
+    gl_cv_size_max=
+    AC_EGREP_CPP([Found it], [
+#include <limits.h>
+#if HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef SIZE_MAX
+Found it
+#endif
+], [gl_cv_size_max=yes])
+    if test -z "$gl_cv_size_max"; then
+      dnl Define it ourselves. Here we assume that the type 'size_t' is not 
wider
+      dnl than the type 'unsigned long'. Try hard to find a definition that can
+      dnl be used in a preprocessor #if, i.e. doesn't contain a cast.
+      AC_COMPUTE_INT([size_t_bits_minus_1], [sizeof (size_t) * CHAR_BIT - 1],
+        [#include <stddef.h>
+#include <limits.h>], [size_t_bits_minus_1=])
+      AC_COMPUTE_INT([fits_in_uint], [sizeof (size_t) <= sizeof (unsigned 
int)],
+        [#include <stddef.h>], [fits_in_uint=])
+      if test -n "$size_t_bits_minus_1" && test -n "$fits_in_uint"; then
+        if test $fits_in_uint = 1; then
+          dnl Even though SIZE_MAX fits in an unsigned int, it must be of type
+          dnl 'unsigned long' if the type 'size_t' is the same as 'unsigned 
long'.
+          AC_TRY_COMPILE([#include <stddef.h>
+            extern size_t foo;
+            extern unsigned long foo;
+            ], [], [fits_in_uint=0])
+        fi
+        dnl We cannot use 'expr' to simplify this expression, because 'expr'
+        dnl works only with 'long' integers in the host environment, while we
+        dnl might be cross-compiling from a 32-bit platform to a 64-bit 
platform.
+        if test $fits_in_uint = 1; then
+          gl_cv_size_max="(((1U << $size_t_bits_minus_1) - 1) * 2 + 1)"
+        else
+          gl_cv_size_max="(((1UL << $size_t_bits_minus_1) - 1) * 2 + 1)"
+        fi
+      else
+        dnl Shouldn't happen, but who knows...
+        gl_cv_size_max='((size_t)~(size_t)0)'
+      fi
+    fi
+  ])
+  if test "$gl_cv_size_max" != yes; then
+    AC_DEFINE_UNQUOTED([SIZE_MAX], [$gl_cv_size_max],
+      [Define as the maximum value of type 'size_t', if the system doesn't 
define it.])
+  fi
+  dnl Don't redefine SIZE_MAX in config.h if config.h is re-included after
+  dnl <stdint.h>. Remember that the #undef in AH_VERBATIM gets replaced with
+  dnl #define by AC_DEFINE_UNQUOTED.
+  AH_VERBATIM([SIZE_MAX],
+[/* Define as the maximum value of type 'size_t', if the system doesn't define
+   it. */
+#ifndef SIZE_MAX
+# undef SIZE_MAX
+#endif])
+])
+
+dnl Autoconf >= 2.61 has AC_COMPUTE_INT built-in.
+dnl Remove this when we can assume autoconf >= 2.61.
+m4_ifdef([AC_COMPUTE_INT], [], [
+  AC_DEFUN([AC_COMPUTE_INT], [_AC_COMPUTE_INT([$2],[$1],[$3],[$4])])
+])
diff --git a/m4/stdint_h.m4 b/m4/stdint_h.m4
new file mode 100644
index 0000000..82f0c24
--- /dev/null
+++ b/m4/stdint_h.m4
@@ -0,0 +1,26 @@
+# stdint_h.m4 serial 8
+dnl Copyright (C) 1997-2004, 2006, 2008, 2009 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 Paul Eggert.
+
+# Define HAVE_STDINT_H_WITH_UINTMAX if <stdint.h> exists,
+# doesn't clash with <sys/types.h>, and declares uintmax_t.
+
+AC_DEFUN([gl_AC_HEADER_STDINT_H],
+[
+  AC_CACHE_CHECK([for stdint.h], [gl_cv_header_stdint_h],
+  [AC_TRY_COMPILE(
+    [#include <sys/types.h>
+#include <stdint.h>],
+    [uintmax_t i = (uintmax_t) -1; return !i;],
+    [gl_cv_header_stdint_h=yes],
+    [gl_cv_header_stdint_h=no])])
+  if test $gl_cv_header_stdint_h = yes; then
+    AC_DEFINE_UNQUOTED([HAVE_STDINT_H_WITH_UINTMAX], [1],
+      [Define if <stdint.h> exists, doesn't clash with <sys/types.h>,
+       and declares uintmax_t. ])
+  fi
+])
diff --git a/m4/stdio_h.m4 b/m4/stdio_h.m4
new file mode 100644
index 0000000..fcbe68f
--- /dev/null
+++ b/m4/stdio_h.m4
@@ -0,0 +1,136 @@
+# stdio_h.m4 serial 16
+dnl Copyright (C) 2007-2009 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_STDIO_H],
+[
+  AC_REQUIRE([gl_STDIO_H_DEFAULTS])
+  gl_CHECK_NEXT_HEADERS([stdio.h])
+  dnl No need to create extra modules for these functions. Everyone who uses
+  dnl <stdio.h> likely needs them.
+  GNULIB_FPRINTF=1
+  GNULIB_PRINTF=1
+  GNULIB_VFPRINTF=1
+  GNULIB_VPRINTF=1
+  GNULIB_FPUTC=1
+  GNULIB_PUTC=1
+  GNULIB_PUTCHAR=1
+  GNULIB_FPUTS=1
+  GNULIB_PUTS=1
+  GNULIB_FWRITE=1
+  dnl This ifdef is just an optimization, to avoid performing a configure
+  dnl check whose result is not used. It does not make the test of
+  dnl GNULIB_STDIO_H_SIGPIPE or GNULIB_SIGPIPE redundant.
+  m4_ifdef([gl_SIGNAL_SIGPIPE], [
+    gl_SIGNAL_SIGPIPE
+    if test $gl_cv_header_signal_h_SIGPIPE != yes; then
+      REPLACE_STDIO_WRITE_FUNCS=1
+      AC_LIBOBJ([stdio-write])
+    fi
+  ])
+])
+
+AC_DEFUN([gl_STDIO_MODULE_INDICATOR],
+[
+  dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
+  AC_REQUIRE([gl_STDIO_H_DEFAULTS])
+  
GNULIB_[]m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./-],[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])=1
+])
+
+AC_DEFUN([gl_STDIO_H_DEFAULTS],
+[
+  GNULIB_FPRINTF=0;              AC_SUBST([GNULIB_FPRINTF])
+  GNULIB_FPRINTF_POSIX=0;        AC_SUBST([GNULIB_FPRINTF_POSIX])
+  GNULIB_PRINTF=0;               AC_SUBST([GNULIB_PRINTF])
+  GNULIB_PRINTF_POSIX=0;         AC_SUBST([GNULIB_PRINTF_POSIX])
+  GNULIB_SNPRINTF=0;             AC_SUBST([GNULIB_SNPRINTF])
+  GNULIB_SPRINTF_POSIX=0;        AC_SUBST([GNULIB_SPRINTF_POSIX])
+  GNULIB_VFPRINTF=0;             AC_SUBST([GNULIB_VFPRINTF])
+  GNULIB_VFPRINTF_POSIX=0;       AC_SUBST([GNULIB_VFPRINTF_POSIX])
+  GNULIB_VPRINTF=0;              AC_SUBST([GNULIB_VPRINTF])
+  GNULIB_VPRINTF_POSIX=0;        AC_SUBST([GNULIB_VPRINTF_POSIX])
+  GNULIB_VSNPRINTF=0;            AC_SUBST([GNULIB_VSNPRINTF])
+  GNULIB_VSPRINTF_POSIX=0;       AC_SUBST([GNULIB_VSPRINTF_POSIX])
+  GNULIB_DPRINTF=0;              AC_SUBST([GNULIB_DPRINTF])
+  GNULIB_VDPRINTF=0;             AC_SUBST([GNULIB_VDPRINTF])
+  GNULIB_VASPRINTF=0;            AC_SUBST([GNULIB_VASPRINTF])
+  GNULIB_OBSTACK_PRINTF=0;       AC_SUBST([GNULIB_OBSTACK_PRINTF])
+  GNULIB_OBSTACK_PRINTF_POSIX=0; AC_SUBST([GNULIB_OBSTACK_PRINTF_POSIX])
+  GNULIB_FOPEN=0;                AC_SUBST([GNULIB_FOPEN])
+  GNULIB_FREOPEN=0;              AC_SUBST([GNULIB_FREOPEN])
+  GNULIB_FSEEK=0;                AC_SUBST([GNULIB_FSEEK])
+  GNULIB_FSEEKO=0;               AC_SUBST([GNULIB_FSEEKO])
+  GNULIB_FTELL=0;                AC_SUBST([GNULIB_FTELL])
+  GNULIB_FTELLO=0;               AC_SUBST([GNULIB_FTELLO])
+  GNULIB_FFLUSH=0;               AC_SUBST([GNULIB_FFLUSH])
+  GNULIB_FPURGE=0;               AC_SUBST([GNULIB_FPURGE])
+  GNULIB_FCLOSE=0;               AC_SUBST([GNULIB_FCLOSE])
+  GNULIB_FPUTC=0;                AC_SUBST([GNULIB_FPUTC])
+  GNULIB_PUTC=0;                 AC_SUBST([GNULIB_PUTC])
+  GNULIB_PUTCHAR=0;              AC_SUBST([GNULIB_PUTCHAR])
+  GNULIB_FPUTS=0;                AC_SUBST([GNULIB_FPUTS])
+  GNULIB_PUTS=0;                 AC_SUBST([GNULIB_PUTS])
+  GNULIB_FWRITE=0;               AC_SUBST([GNULIB_FWRITE])
+  GNULIB_GETDELIM=0;             AC_SUBST([GNULIB_GETDELIM])
+  GNULIB_GETLINE=0;              AC_SUBST([GNULIB_GETLINE])
+  GNULIB_PERROR=0;               AC_SUBST([GNULIB_PERROR])
+  GNULIB_STDIO_H_SIGPIPE=0;      AC_SUBST([GNULIB_STDIO_H_SIGPIPE])
+  dnl Assume proper GNU behavior unless another module says otherwise.
+  REPLACE_STDIO_WRITE_FUNCS=0;   AC_SUBST([REPLACE_STDIO_WRITE_FUNCS])
+  REPLACE_FPRINTF=0;             AC_SUBST([REPLACE_FPRINTF])
+  REPLACE_VFPRINTF=0;            AC_SUBST([REPLACE_VFPRINTF])
+  REPLACE_PRINTF=0;              AC_SUBST([REPLACE_PRINTF])
+  REPLACE_VPRINTF=0;             AC_SUBST([REPLACE_VPRINTF])
+  REPLACE_SNPRINTF=0;            AC_SUBST([REPLACE_SNPRINTF])
+  HAVE_DECL_SNPRINTF=1;          AC_SUBST([HAVE_DECL_SNPRINTF])
+  REPLACE_VSNPRINTF=0;           AC_SUBST([REPLACE_VSNPRINTF])
+  HAVE_DECL_VSNPRINTF=1;         AC_SUBST([HAVE_DECL_VSNPRINTF])
+  REPLACE_SPRINTF=0;             AC_SUBST([REPLACE_SPRINTF])
+  REPLACE_VSPRINTF=0;            AC_SUBST([REPLACE_VSPRINTF])
+  HAVE_DPRINTF=1;                AC_SUBST([HAVE_DPRINTF])
+  REPLACE_DPRINTF=0;             AC_SUBST([REPLACE_DPRINTF])
+  HAVE_VDPRINTF=1;               AC_SUBST([HAVE_VDPRINTF])
+  REPLACE_VDPRINTF=0;            AC_SUBST([REPLACE_VDPRINTF])
+  HAVE_VASPRINTF=1;              AC_SUBST([HAVE_VASPRINTF])
+  REPLACE_VASPRINTF=0;           AC_SUBST([REPLACE_VASPRINTF])
+  HAVE_DECL_OBSTACK_PRINTF=1;    AC_SUBST([HAVE_DECL_OBSTACK_PRINTF])
+  REPLACE_OBSTACK_PRINTF=0;      AC_SUBST([REPLACE_OBSTACK_PRINTF])
+  REPLACE_FOPEN=0;               AC_SUBST([REPLACE_FOPEN])
+  REPLACE_FREOPEN=0;             AC_SUBST([REPLACE_FREOPEN])
+  HAVE_FSEEKO=1;                 AC_SUBST([HAVE_FSEEKO])
+  REPLACE_FSEEKO=0;              AC_SUBST([REPLACE_FSEEKO])
+  REPLACE_FSEEK=0;               AC_SUBST([REPLACE_FSEEK])
+  HAVE_FTELLO=1;                 AC_SUBST([HAVE_FTELLO])
+  REPLACE_FTELLO=0;              AC_SUBST([REPLACE_FTELLO])
+  REPLACE_FTELL=0;               AC_SUBST([REPLACE_FTELL])
+  REPLACE_FFLUSH=0;              AC_SUBST([REPLACE_FFLUSH])
+  REPLACE_FPURGE=0;              AC_SUBST([REPLACE_FPURGE])
+  HAVE_DECL_FPURGE=1;            AC_SUBST([HAVE_DECL_FPURGE])
+  REPLACE_FCLOSE=0;              AC_SUBST([REPLACE_FCLOSE])
+  HAVE_DECL_GETDELIM=1;          AC_SUBST([HAVE_DECL_GETDELIM])
+  HAVE_DECL_GETLINE=1;           AC_SUBST([HAVE_DECL_GETLINE])
+  REPLACE_GETLINE=0;             AC_SUBST([REPLACE_GETLINE])
+  REPLACE_PERROR=0;              AC_SUBST([REPLACE_PERROR])
+])
+
+dnl Code shared by fseeko and ftello.  Determine if large files are supported,
+dnl but stdin does not start as a large file by default.
+AC_DEFUN([gl_STDIN_LARGE_OFFSET],
+  [
+    AC_CACHE_CHECK([whether stdin defaults to large file offsets],
+      [gl_cv_var_stdin_large_offset],
+      [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>]],
+[[#if defined __SL64 && defined __SCLE /* cygwin */
+  /* Cygwin 1.5.24 and earlier fail to put stdin in 64-bit mode, making
+     fseeko/ftello needlessly fail.  This bug was fixed in 1.5.25, and
+     it is easier to do a version check than building a runtime test.  */
+# include <cygwin/version.h>
+# if CYGWIN_VERSION_DLL_COMBINED < CYGWIN_VERSION_DLL_MAKE_COMBINED (1005, 25)
+  choke me
+# endif
+#endif]])],
+       [gl_cv_var_stdin_large_offset=yes],
+       [gl_cv_var_stdin_large_offset=no])])
+])
diff --git a/m4/vasnprintf.m4 b/m4/vasnprintf.m4
new file mode 100644
index 0000000..3a1d1e0
--- /dev/null
+++ b/m4/vasnprintf.m4
@@ -0,0 +1,276 @@
+# vasnprintf.m4 serial 29
+dnl Copyright (C) 2002-2004, 2006-2009 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_VASNPRINTF],
+[
+  AC_CHECK_FUNCS_ONCE([vasnprintf])
+  if test $ac_cv_func_vasnprintf = no; then
+    gl_REPLACE_VASNPRINTF
+  fi
+])
+
+AC_DEFUN([gl_REPLACE_VASNPRINTF],
+[
+  AC_CHECK_FUNCS_ONCE([vasnprintf])
+  AC_LIBOBJ([vasnprintf])
+  AC_LIBOBJ([printf-args])
+  AC_LIBOBJ([printf-parse])
+  AC_LIBOBJ([asnprintf])
+  if test $ac_cv_func_vasnprintf = yes; then
+    AC_DEFINE([REPLACE_VASNPRINTF], [1],
+      [Define if vasnprintf exists but is overridden by gnulib.])
+  fi
+  gl_PREREQ_PRINTF_ARGS
+  gl_PREREQ_PRINTF_PARSE
+  gl_PREREQ_VASNPRINTF
+  gl_PREREQ_ASNPRINTF
+])
+
+# Prequisites of lib/printf-args.h, lib/printf-args.c.
+AC_DEFUN([gl_PREREQ_PRINTF_ARGS],
+[
+  AC_REQUIRE([AC_TYPE_LONG_LONG_INT])
+  AC_REQUIRE([gt_TYPE_WCHAR_T])
+  AC_REQUIRE([gt_TYPE_WINT_T])
+])
+
+# Prequisites of lib/printf-parse.h, lib/printf-parse.c.
+AC_DEFUN([gl_PREREQ_PRINTF_PARSE],
+[
+  AC_REQUIRE([AC_TYPE_LONG_LONG_INT])
+  AC_REQUIRE([gt_TYPE_WCHAR_T])
+  AC_REQUIRE([gt_TYPE_WINT_T])
+  AC_REQUIRE([AC_TYPE_SIZE_T])
+  AC_CHECK_TYPE([ptrdiff_t], ,
+    [AC_DEFINE([ptrdiff_t], [long],
+       [Define as the type of the result of subtracting two pointers, if the 
system doesn't define it.])
+    ])
+  AC_REQUIRE([gt_AC_TYPE_INTMAX_T])
+])
+
+# Prerequisites of lib/vasnprintf.c.
+AC_DEFUN_ONCE([gl_PREREQ_VASNPRINTF],
+[
+  AC_REQUIRE([AC_FUNC_ALLOCA])
+  AC_REQUIRE([AC_TYPE_LONG_LONG_INT])
+  AC_REQUIRE([gt_TYPE_WCHAR_T])
+  AC_REQUIRE([gt_TYPE_WINT_T])
+  AC_CHECK_FUNCS([snprintf strnlen wcslen wcsnlen mbrtowc wcrtomb])
+  dnl Use the _snprintf function only if it is declared (because on NetBSD it
+  dnl is defined as a weak alias of snprintf; we prefer to use the latter).
+  AC_CHECK_DECLS([_snprintf], , , [#include <stdio.h>])
+])
+
+# Extra prerequisites of lib/vasnprintf.c for supporting 'long double'
+# arguments.
+AC_DEFUN_ONCE([gl_PREREQ_VASNPRINTF_LONG_DOUBLE],
+[
+  AC_REQUIRE([gl_PRINTF_LONG_DOUBLE])
+  case "$gl_cv_func_printf_long_double" in
+    *yes)
+      ;;
+    *)
+      AC_DEFINE([NEED_PRINTF_LONG_DOUBLE], [1],
+        [Define if the vasnprintf implementation needs special code for
+         'long double' arguments.])
+      ;;
+  esac
+])
+
+# Extra prerequisites of lib/vasnprintf.c for supporting infinite 'double'
+# arguments.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_INFINITE_DOUBLE],
+[
+  AC_REQUIRE([gl_PRINTF_INFINITE])
+  case "$gl_cv_func_printf_infinite" in
+    *yes)
+      ;;
+    *)
+      AC_DEFINE([NEED_PRINTF_INFINITE_DOUBLE], [1],
+        [Define if the vasnprintf implementation needs special code for
+         infinite 'double' arguments.])
+      ;;
+  esac
+])
+
+# Extra prerequisites of lib/vasnprintf.c for supporting infinite 'long double'
+# arguments.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_INFINITE_LONG_DOUBLE],
+[
+  AC_REQUIRE([gl_PRINTF_INFINITE_LONG_DOUBLE])
+  dnl There is no need to set NEED_PRINTF_INFINITE_LONG_DOUBLE if
+  dnl NEED_PRINTF_LONG_DOUBLE is already set.
+  AC_REQUIRE([gl_PREREQ_VASNPRINTF_LONG_DOUBLE])
+  case "$gl_cv_func_printf_long_double" in
+    *yes)
+      case "$gl_cv_func_printf_infinite_long_double" in
+        *yes)
+          ;;
+        *)
+          AC_DEFINE([NEED_PRINTF_INFINITE_LONG_DOUBLE], [1],
+            [Define if the vasnprintf implementation needs special code for
+             infinite 'long double' arguments.])
+          ;;
+      esac
+      ;;
+  esac
+])
+
+# Extra prerequisites of lib/vasnprintf.c for supporting the 'a' directive.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_DIRECTIVE_A],
+[
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_A])
+  case "$gl_cv_func_printf_directive_a" in
+    *yes)
+      ;;
+    *)
+      AC_DEFINE([NEED_PRINTF_DIRECTIVE_A], [1],
+        [Define if the vasnprintf implementation needs special code for
+         the 'a' and 'A' directives.])
+      AC_CHECK_FUNCS([nl_langinfo])
+      ;;
+  esac
+])
+
+# Extra prerequisites of lib/vasnprintf.c for supporting the 'F' directive.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_DIRECTIVE_F],
+[
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_F])
+  case "$gl_cv_func_printf_directive_f" in
+    *yes)
+      ;;
+    *)
+      AC_DEFINE([NEED_PRINTF_DIRECTIVE_F], [1],
+        [Define if the vasnprintf implementation needs special code for
+         the 'F' directive.])
+      ;;
+  esac
+])
+
+# Extra prerequisites of lib/vasnprintf.c for supporting the 'ls' directive.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_DIRECTIVE_LS],
+[
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_LS])
+  case "$gl_cv_func_printf_directive_ls" in
+    *yes)
+      ;;
+    *)
+      AC_DEFINE([NEED_PRINTF_DIRECTIVE_LS], [1],
+        [Define if the vasnprintf implementation needs special code for
+         the 'ls' directive.])
+      ;;
+  esac
+])
+
+# Extra prerequisites of lib/vasnprintf.c for supporting the ' flag.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_FLAG_GROUPING],
+[
+  AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
+  case "$gl_cv_func_printf_flag_grouping" in
+    *yes)
+      ;;
+    *)
+      AC_DEFINE([NEED_PRINTF_FLAG_GROUPING], [1],
+        [Define if the vasnprintf implementation needs special code for the
+         ' flag.])
+      ;;
+  esac
+])
+
+# Extra prerequisites of lib/vasnprintf.c for supporting the '-' flag.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_FLAG_LEFTADJUST],
+[
+  AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST])
+  case "$gl_cv_func_printf_flag_leftadjust" in
+    *yes)
+      ;;
+    *)
+      AC_DEFINE([NEED_PRINTF_FLAG_LEFTADJUST], [1],
+        [Define if the vasnprintf implementation needs special code for the
+         '-' flag.])
+      ;;
+  esac
+])
+
+# Extra prerequisites of lib/vasnprintf.c for supporting the 0 flag.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_FLAG_ZERO],
+[
+  AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
+  case "$gl_cv_func_printf_flag_zero" in
+    *yes)
+      ;;
+    *)
+      AC_DEFINE([NEED_PRINTF_FLAG_ZERO], [1],
+        [Define if the vasnprintf implementation needs special code for the
+         0 flag.])
+      ;;
+  esac
+])
+
+# Extra prerequisites of lib/vasnprintf.c for supporting large precisions.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_PRECISION],
+[
+  AC_REQUIRE([gl_PRINTF_PRECISION])
+  case "$gl_cv_func_printf_precision" in
+    *yes)
+      ;;
+    *)
+      AC_DEFINE([NEED_PRINTF_UNBOUNDED_PRECISION], [1],
+        [Define if the vasnprintf implementation needs special code for
+         supporting large precisions without arbitrary bounds.])
+      AC_DEFINE([NEED_PRINTF_DOUBLE], [1],
+        [Define if the vasnprintf implementation needs special code for
+         'double' arguments.])
+      AC_DEFINE([NEED_PRINTF_LONG_DOUBLE], [1],
+        [Define if the vasnprintf implementation needs special code for
+         'long double' arguments.])
+      ;;
+  esac
+])
+
+# Extra prerequisites of lib/vasnprintf.c for surviving out-of-memory
+# conditions.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_ENOMEM],
+[
+  AC_REQUIRE([gl_PRINTF_ENOMEM])
+  case "$gl_cv_func_printf_enomem" in
+    *yes)
+      ;;
+    *)
+      AC_DEFINE([NEED_PRINTF_ENOMEM], [1],
+        [Define if the vasnprintf implementation needs special code for
+         surviving out-of-memory conditions.])
+      AC_DEFINE([NEED_PRINTF_DOUBLE], [1],
+        [Define if the vasnprintf implementation needs special code for
+         'double' arguments.])
+      AC_DEFINE([NEED_PRINTF_LONG_DOUBLE], [1],
+        [Define if the vasnprintf implementation needs special code for
+         'long double' arguments.])
+      ;;
+  esac
+])
+
+# Prerequisites of lib/vasnprintf.c including all extras for POSIX compliance.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_WITH_EXTRAS],
+[
+  AC_REQUIRE([gl_PREREQ_VASNPRINTF])
+  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
+])
+
+# Prerequisites of lib/asnprintf.c.
+AC_DEFUN([gl_PREREQ_ASNPRINTF],
+[
+])
diff --git a/m4/vsnprintf.m4 b/m4/vsnprintf.m4
new file mode 100644
index 0000000..3b37d46
--- /dev/null
+++ b/m4/vsnprintf.m4
@@ -0,0 +1,40 @@
+# vsnprintf.m4 serial 5
+dnl Copyright (C) 2002-2004, 2007-2008 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_VSNPRINTF],
+[
+  AC_REQUIRE([gl_STDIO_H_DEFAULTS])
+  gl_cv_func_vsnprintf_usable=no
+  AC_CHECK_FUNCS([vsnprintf])
+  if test $ac_cv_func_vsnprintf = yes; then
+    gl_SNPRINTF_SIZE1
+    case "$gl_cv_func_snprintf_size1" in
+      *yes)
+        gl_cv_func_vsnprintf_usable=yes
+        ;;
+    esac
+  fi
+  if test $gl_cv_func_vsnprintf_usable = no; then
+    gl_REPLACE_VSNPRINTF
+  fi
+  AC_CHECK_DECLS_ONCE([vsnprintf])
+  if test $ac_cv_have_decl_vsnprintf = no; then
+    HAVE_DECL_VSNPRINTF=0
+  fi
+])
+
+AC_DEFUN([gl_REPLACE_VSNPRINTF],
+[
+  AC_REQUIRE([gl_STDIO_H_DEFAULTS])
+  AC_LIBOBJ([vsnprintf])
+  if test $ac_cv_func_vsnprintf = yes; then
+    REPLACE_VSNPRINTF=1
+  fi
+  gl_PREREQ_VSNPRINTF
+])
+
+# Prerequisites of lib/vsnprintf.c.
+AC_DEFUN([gl_PREREQ_VSNPRINTF], [:])
diff --git a/m4/wchar_t.m4 b/m4/wchar_t.m4
new file mode 100644
index 0000000..fb27a7f
--- /dev/null
+++ b/m4/wchar_t.m4
@@ -0,0 +1,20 @@
+# wchar_t.m4 serial 3 (gettext-0.18)
+dnl Copyright (C) 2002-2003, 2008, 2009 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.
+dnl Test whether <stddef.h> has the 'wchar_t' type.
+dnl Prerequisite: AC_PROG_CC
+
+AC_DEFUN([gt_TYPE_WCHAR_T],
+[
+  AC_CACHE_CHECK([for wchar_t], [gt_cv_c_wchar_t],
+    [AC_TRY_COMPILE([#include <stddef.h>
+       wchar_t foo = (wchar_t)'\0';], ,
+       [gt_cv_c_wchar_t=yes], [gt_cv_c_wchar_t=no])])
+  if test $gt_cv_c_wchar_t = yes; then
+    AC_DEFINE([HAVE_WCHAR_T], [1], [Define if you have the 'wchar_t' type.])
+  fi
+])
diff --git a/m4/xsize.m4 b/m4/xsize.m4
new file mode 100644
index 0000000..631893c
--- /dev/null
+++ b/m4/xsize.m4
@@ -0,0 +1,13 @@
+# xsize.m4 serial 4
+dnl Copyright (C) 2003-2004, 2008 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_XSIZE],
+[
+  dnl Prerequisites of lib/xsize.h.
+  AC_REQUIRE([gl_SIZE_MAX])
+  AC_REQUIRE([AC_C_INLINE])
+  AC_CHECK_HEADERS([stdint.h])
+])
diff --git a/module/language/brainfuck/compile-tree-il.scm 
b/module/language/brainfuck/compile-tree-il.scm
index c991631..0aaa112 100644
--- a/module/language/brainfuck/compile-tree-il.scm
+++ b/module/language/brainfuck/compile-tree-il.scm
@@ -49,24 +49,45 @@
 ;; This compiles a whole brainfuck program. This constructs a Tree-IL
 ;; code equivalent to Scheme code like this:
 ;;
-;; (let ((pointer 0)
-;;       (tape (make-vector tape-size 0)))
-;;   (begin
-;;     <body>
-;;     (write-char #\newline)))
+;;    (let ((pointer 0)
+;;          (tape (make-vector tape-size 0)))
+;;      (begin
+;;       <body>
+;;       (write-char #\newline)))
 ;;
 ;; So first the pointer and tape variables are set up correctly, then the
 ;; program's body is executed in this context, and finally we output an
 ;; additional newline character in case the program does not output one.
 ;;
+;; The fact that we are compiling to Guile primitives gives this
+;; implementation a number of interesting characteristics. First, the
+;; values of the tape cells do not underflow or overflow. We could make
+;; them do otherwise via compiling calls to "modulo" at certain points.
+;;
+;; In addition, tape overruns or underruns will be detected, and will
+;; throw an error, whereas a number of Brainfuck compilers do not detect
+;; this.
+;;
 ;; Note that we're generating the S-expression representation of
 ;; Tree-IL, then using parse-tree-il to turn it into the actual Tree-IL
 ;; data structures. This makes the compiler more pleasant to look at,
 ;; but we do lose is the ability to propagate source information. Since
 ;; Brainfuck is so obtuse anyway, this shouldn't matter ;-)
 ;;
-;; TODO: Find out and explain the details about env, the three return values 
and
-;; how to use the options.  Implement options to set the tape-size, maybe.
+;; `compile-tree-il' takes as its input the read expression, the
+;; environment, and some compile options. It returns the compiled
+;; expression, the environment appropriate for the next pass of the
+;; compiler -- in our case, just the environment unchanged -- and the
+;; continuation environment.
+;;
+;; The normal use of a continuation environment is if compiling one
+;; expression changes the environment, and that changed environment
+;; should be passed to the next compiled expression -- for example,
+;; changing the current module. But Brainfuck is incapable of that, so
+;; for us, the continuation environment is just the same environment we
+;; got in.
+;;
+;; FIXME: perhaps use options or the env to set the tape-size?
 
 (define (compile-tree-il exp env opts)
   (values
@@ -74,7 +95,7 @@
     `(let (pointer tape) (pointer tape)
           ((const 0)
            (apply (primitive make-vector) (const ,tape-size) (const 0)))
-       ,(compile-body exp)))
+          ,(compile-body exp)))
    env
    env))
 
@@ -137,6 +158,13 @@
         ;;         (begin
         ;;          <body>
         ;;          (iterate))))
+        ;;
+        ;; Indeed, letrec is the only way we have to loop in Tree-IL.
+        ;; Note that this does not mean that the closure must actually
+        ;; be created; later passes can compile tail-recursive letrec
+        ;; calls into inline code with gotos. Admittedly, that part of
+        ;; the compiler is not yet in place, but it will be, and in the
+        ;; meantime the code is still reasonably efficient.
         ((<bf-loop> . ,body)
          (let ((iterate (gensym)))
            (emit `(letrec (iterate) (,iterate)
diff --git a/module/language/tree-il/compile-glil.scm 
b/module/language/tree-il/compile-glil.scm
index 6dade35..e0df038 100644
--- a/module/language/tree-il/compile-glil.scm
+++ b/module/language/tree-il/compile-glil.scm
@@ -22,6 +22,7 @@
   #:use-module (system base syntax)
   #:use-module (ice-9 receive)
   #:use-module (language glil)
+  #:use-module (system vm instruction)
   #:use-module (language tree-il)
   #:use-module (language tree-il optimize)
   #:use-module (language tree-il analyze)
@@ -80,7 +81,53 @@
    (list . list)
    (vector . vector)
    ((@slot-ref . 2) . slot-ref)
-   ((@slot-set! . 3) . slot-set)))
+   ((@slot-set! . 3) . slot-set)
+   ((vector-ref . 2) . vector-ref)
+   ((vector-set! . 3) . vector-set)
+
+   ((bytevector-u8-ref . 2) . bv-u8-ref)
+   ((bytevector-u8-set! . 3) . bv-u8-set)
+   ((bytevector-s8-ref . 2) . bv-s8-ref)
+   ((bytevector-s8-set! . 3) . bv-s8-set)
+
+   ((bytevector-u16-ref . 3) . bv-u16-ref)
+   ((bytevector-u16-set! . 4) . bv-u16-set)
+   ((bytevector-u16-native-ref . 2) . bv-u16-native-ref)
+   ((bytevector-u16-native-set! . 3) . bv-u16-native-set)
+   ((bytevector-s16-ref . 3) . bv-s16-ref)
+   ((bytevector-s16-set! . 4) . bv-s16-set)
+   ((bytevector-s16-native-ref . 2) . bv-s16-native-ref)
+   ((bytevector-s16-native-set! . 3) . bv-s16-native-set)
+    
+   ((bytevector-u32-ref . 3) . bv-u32-ref)
+   ((bytevector-u32-set! . 4) . bv-u32-set)
+   ((bytevector-u32-native-ref . 2) . bv-u32-native-ref)
+   ((bytevector-u32-native-set! . 3) . bv-u32-native-set)
+   ((bytevector-s32-ref . 3) . bv-s32-ref)
+   ((bytevector-s32-set! . 4) . bv-s32-set)
+   ((bytevector-s32-native-ref . 2) . bv-s32-native-ref)
+   ((bytevector-s32-native-set! . 3) . bv-s32-native-set)
+    
+   ((bytevector-u64-ref . 3) . bv-u64-ref)
+   ((bytevector-u64-set! . 4) . bv-u64-set)
+   ((bytevector-u64-native-ref . 2) . bv-u64-native-ref)
+   ((bytevector-u64-native-set! . 3) . bv-u64-native-set)
+   ((bytevector-s64-ref . 3) . bv-s64-ref)
+   ((bytevector-s64-set! . 4) . bv-s64-set)
+   ((bytevector-s64-native-ref . 2) . bv-s64-native-ref)
+   ((bytevector-s64-native-set! . 3) . bv-s64-native-set)
+    
+   ((bytevector-ieee-single-ref . 3) . bv-f32-ref)
+   ((bytevector-ieee-single-set! . 4) . bv-f32-set)
+   ((bytevector-ieee-single-native-ref . 2) . bv-f32-native-ref)
+   ((bytevector-ieee-single-native-set! . 3) . bv-f32-native-set)
+   ((bytevector-ieee-double-ref . 3) . bv-f64-ref)
+   ((bytevector-ieee-double-set! . 4) . bv-f64-set)
+   ((bytevector-ieee-double-native-ref . 2) . bv-f64-native-ref)
+   ((bytevector-ieee-double-native-set! . 3) . bv-f64-native-set)))
+
+
+
 
 (define (make-label) (gensym ":L"))
 
@@ -305,10 +352,20 @@
          => (lambda (op)
               (for-each comp-push args)
               (emit-code src (make-glil-call op (length args)))
-              (case context
-                ((tail) (emit-code #f (make-glil-call 'return 1)))
-                ((drop) (emit-code #f (make-glil-call 'drop 1))))))
-
+              (case (instruction-pushes op)
+                ((0)
+                 (case context
+                   ((tail) (emit-code #f (make-glil-void))
+                           (emit-code #f (make-glil-call 'return 1)))
+                   ((push vals) (emit-code #f (make-glil-void)))))
+                ((1)
+                 (case context
+                   ((tail) (emit-code #f (make-glil-call 'return 1)))
+                   ((drop) (emit-code #f (make-glil-call 'drop 1)))))
+                (else
+                 (error "bad primitive op: too many pushes"
+                        op (instruction-pushes op))))))
+        
         (else
          (comp-push proc)
          (for-each comp-push args)
diff --git a/module/language/tree-il/primitives.scm 
b/module/language/tree-il/primitives.scm
index 7daae0c..9ccd272 100644
--- a/module/language/tree-il/primitives.scm
+++ b/module/language/tree-il/primitives.scm
@@ -19,6 +19,7 @@
 ;;; Code:
 
 (define-module (language tree-il primitives)
+  #:use-module (rnrs bytevector)
   #:use-module (system base syntax)
   #:use-module (language tree-il)
   #:use-module (srfi srfi-16)
@@ -47,11 +48,37 @@
     caaar caadr cadar caddr cdaar cdadr cddar cdddr
 
     caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr
-    cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr))
+    cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr
+
+    vector-ref vector-set!
+
+    bytevector-u8-ref bytevector-u8-set!
+    bytevector-s8-ref bytevector-s8-set!
+
+    bytevector-u16-ref bytevector-u16-set!
+    bytevector-u16-native-ref bytevector-u16-native-set!
+    bytevector-s16-ref bytevector-s16-set!
+    bytevector-s16-native-ref bytevector-s16-native-set!
+    
+    bytevector-u32-ref bytevector-u32-set!
+    bytevector-u32-native-ref bytevector-u32-native-set!
+    bytevector-s32-ref bytevector-s32-set!
+    bytevector-s32-native-ref bytevector-s32-native-set!
+    
+    bytevector-u64-ref bytevector-u64-set!
+    bytevector-u64-native-ref bytevector-u64-native-set!
+    bytevector-s64-ref bytevector-s64-set!
+    bytevector-s64-native-ref bytevector-s64-native-set!
+    
+    bytevector-ieee-single-ref bytevector-ieee-single-set!
+    bytevector-ieee-single-native-ref bytevector-ieee-single-native-set!
+    bytevector-ieee-double-ref bytevector-ieee-double-set!
+    bytevector-ieee-double-native-ref bytevector-ieee-double-native-set!))
 
 (define (add-interesting-primitive! name)
   (hashq-set! *interesting-primitive-vars*
-              (module-variable (current-module) name) name))
+              (module-variable (current-module) name)
+              name))
 
 (define *interesting-primitive-vars* (make-hash-table))
 
diff --git a/module/system/repl/command.scm b/module/system/repl/command.scm
index e6b4929..6f45bd7 100644
--- a/module/system/repl/command.scm
+++ b/module/system/repl/command.scm
@@ -1,21 +1,21 @@
 ;;; Repl commands
 
-;; Copyright (C) 2001 Free Software Foundation, Inc.
+;; Copyright (C) 2001, 2009 Free Software Foundation, Inc.
 
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
+;; This library 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,
+;; This library is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
+;; 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 General Public License
-;; along with this program; see the file COPYING.  If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; You should have received a copy of the GNU Lesser General Public
+;; License along with this library; if not, write to the Free Software
+;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+;; 02110-1301 USA
 
 ;;; Code:
 
@@ -27,7 +27,7 @@
   #:use-module (system vm objcode)
   #:use-module (system vm program)
   #:use-module (system vm vm)
-  #:autoload (system base language) (lookup-language)
+  #:autoload (system base language) (lookup-language language-reader)
   #:autoload (system vm debug) (vm-debugger vm-backtrace)
   #:autoload (system vm trace) (vm-trace vm-trace-on vm-trace-off)
   #:autoload (system vm profile) (vm-profile)
@@ -35,6 +35,7 @@
   #:use-module (ice-9 session)
   #:use-module (ice-9 documentation)
   #:use-module (ice-9 and-let-star)
+  #:use-module (ice-9 rdelim)
   #:export (meta-command))
 
 
@@ -109,33 +110,66 @@
   (let ((abbrev (if abbrev (format #f "[,~A]" abbrev) "")))
     (format #t " ,~24A address@hidden - ~A\n" usage abbrev summary)))
 
-(define (meta-command repl line)
-  (let ((input (call-with-input-string (string-append "(" line ")") read)))
-    (if (not (null? input))
-       (do ((key (car input))
-            (args (cdr input) (cdr args))
-            (opts '() (cons (make-keyword-from-dash-symbol (car args)) opts)))
-           ((or (null? args)
-                (not (symbol? (car args)))
-                (not (eq? (string-ref (symbol->string (car args)) 0) #\-)))
-            (let ((c (lookup-command key)))
-              (if c
-                  (cond ((memq #:h opts) (display-command c))
-                        (else (apply (command-procedure c)
-                                     repl (append! args (reverse! opts)))))
-                  (user-error "Unknown meta command: ~A" key))))))))
+(define (read-datum repl)
+  (read))
+
+(define read-line
+  (let ((orig-read-line read-line))
+    (lambda (repl)
+      (orig-read-line))))
+
+(define (meta-command repl)
+  (let ((command (read-datum repl)))
+    (if (not (symbol? command))
+        (user-error "Meta-command not a symbol: ~s" command))
+    (let ((c (lookup-command command)))
+      (if c
+          ((command-procedure c) repl)
+          (user-error "Unknown meta command: ~A" command)))))
+
+(define-syntax define-meta-command
+  (syntax-rules ()
+    ((_ (name repl (expression0 ...) . datums) docstring b0 b1 ...)
+     (define (name repl)
+       docstring
+       (let* ((expression0
+               (with-fluid* current-reader
+                            (language-reader (repl-language repl))
+                 (lambda () (repl-reader ""))))
+              ...)
+         (apply (lambda datums b0 b1 ...)
+                (let ((port (open-input-string (read-line repl))))
+                  (let lp ((out '()))
+                    (let ((x (read port)))
+                      (if (eof-object? x)
+                          (reverse out)
+                          (lp (cons x out))))))))))
+    ((_ (name repl . datums) docstring b0 b1 ...)
+     (define-meta-command (name repl () . datums)
+       docstring b0 b1 ...))))
+
 
 
 ;;;
 ;;; Help commands
 ;;;
 
-(define (help repl . args)
-  "help [GROUP]
-List available meta commands.
-A command group name can be given as an optional argument.
+(define-meta-command (help repl . args)
+  "help 
+help GROUP
+help [-c] COMMAND
+
+Gives help on the meta-commands available at the REPL.
+
+With one argument, tries to look up the argument as a group name, giving
+help on that group if successful. Otherwise tries to look up the
+argument as a command, giving help on the command.
+
+If there is a command whose name is also a group name, use the ,help
+-c COMMAND form to give help on the command instead of the group.
+
 Without any argument, a list of help commands and command groups
-are displayed, as you have already seen ;)"
+are displayed."
   (pmatch args
     (()
      (display-group (lookup-group 'help))
@@ -154,23 +188,30 @@ are displayed, as you have already seen ;)"
      (for-each display-group *command-table*))
     ((,group) (guard (lookup-group group))
      (display-group (lookup-group group)))
+    ((,command) (guard (lookup-command command))
+     (display-command (lookup-command command)))
+    ((-c ,command) (guard (lookup-command command))
+     (display-command (lookup-command command)))
+    ((,command)
+     (user-error "Unknown command or group: ~A" command))
+    ((-c ,command)
+     (user-error "Unknown command: ~A" command))
     (else
-     (user-error "Unknown command group: ~A" (car args)))))
+     (user-error "Bad arguments: ~A" args))))
 
 (define guile:apropos apropos)
-(define (apropos repl regexp)
+(define-meta-command (apropos repl regexp)
   "apropos REGEXP
 Find bindings/modules/packages."
   (guile:apropos (->string regexp)))
 
-(define (describe repl obj)
+(define-meta-command (describe repl (form))
   "describe OBJ
 Show description/documentation."
-  (display (object-documentation
-            (repl-eval repl (repl-parse repl obj))))
+  (display (object-documentation (repl-eval repl (repl-parse repl form))))
   (newline))
 
-(define (option repl . args)
+(define-meta-command (option repl . args)
   "option [KEY VALUE]
 List/show/set options."
   (pmatch args
@@ -190,7 +231,7 @@ List/show/set options."
               (apply vm-trace-on vm val)
               (vm-trace-off vm))))))))
 
-(define (quit repl)
+(define-meta-command (quit repl)
   "quit
 Quit this session."
   (throw 'quit))
@@ -200,7 +241,7 @@ Quit this session."
 ;;; Module commands
 ;;;
 
-(define (module repl . args)
+(define-meta-command (module repl . args)
   "module [MODULE]
 Change modules / Show current module."
   (pmatch args
@@ -209,7 +250,7 @@ Change modules / Show current module."
      (set-current-module (resolve-module mod-name)))
     (,mod-name (set-current-module (resolve-module mod-name)))))
 
-(define (import repl . args)
+(define-meta-command (import repl . args)
   "import [MODULE ...]
 Import modules / List those imported."
   (let ()
@@ -222,7 +263,7 @@ Import modules / List those imported."
         (for-each puts (map module-name (module-uses (current-module))))
         (for-each use args))))
 
-(define (load repl file . opts)
+(define-meta-command (load repl file . opts)
   "load FILE
 Load a file in the current module.
 
@@ -233,7 +274,7 @@ Load a file in the current module.
                      (apply load-file file opts))))
     (vm-load (repl-vm repl) objcode)))
 
-(define (binding repl . opts)
+(define-meta-command (binding repl)
   "binding
 List current bindings."
   (module-for-each (lambda (k v) (format #t "~23A ~A\n" k v))
@@ -244,7 +285,7 @@ List current bindings."
 ;;; Language commands
 ;;;
 
-(define (language repl name)
+(define-meta-command (language repl name)
   "language LANGUAGE
 Change languages."
   (set! (repl-language repl) (lookup-language name))
@@ -255,7 +296,7 @@ Change languages."
 ;;; Compile commands
 ;;;
 
-(define (compile repl form . opts)
+(define-meta-command (compile repl (form) . opts)
   "compile FORM
 Generate compiled code.
 
@@ -270,7 +311,7 @@ Generate compiled code.
           (else (repl-print repl x)))))
 
 (define guile:compile-file compile-file)
-(define (compile-file repl file . opts)
+(define-meta-command (compile-file repl file . opts)
   "compile-file FILE
 Compile a file."
   (guile:compile-file (->string file) #:opts opts))
@@ -278,12 +319,12 @@ Compile a file."
 (define (guile:disassemble x)
   ((@ (language assembly disassemble) disassemble) x))
 
-(define (disassemble repl prog)
+(define-meta-command (disassemble repl (form))
   "disassemble PROGRAM
 Disassemble a program."
-  (guile:disassemble (repl-eval repl (repl-parse repl prog))))
+  (guile:disassemble (repl-eval repl (repl-parse repl form))))
 
-(define (disassemble-file repl file)
+(define-meta-command (disassemble-file repl file)
   "disassemble-file FILE
 Disassemble a file."
   (guile:disassemble (load-objcode (->string file))))
@@ -293,7 +334,7 @@ Disassemble a file."
 ;;; Profile commands
 ;;;
 
-(define (time repl form)
+(define-meta-command (time repl (form))
   "time FORM
 Time execution."
   (let* ((vms-start (vm-stats (repl-vm repl)))
@@ -316,7 +357,7 @@ Time execution."
            (get identity gc-start gc-end))
     result))
 
-(define (profile repl form . opts)
+(define-meta-command (profile repl form . opts)
   "profile FORM
 Profile execution."
   (apply vm-profile
@@ -329,17 +370,17 @@ Profile execution."
 ;;; Debug commands
 ;;;
 
-(define (backtrace repl)
+(define-meta-command (backtrace repl)
   "backtrace
 Display backtrace."
   (vm-backtrace (repl-vm repl)))
 
-(define (debugger repl)
+(define-meta-command (debugger repl)
   "debugger
 Start debugger."
   (vm-debugger (repl-vm repl)))
 
-(define (trace repl form . opts)
+(define-meta-command (trace repl form . opts)
   "trace FORM
 Trace execution.
 
@@ -351,7 +392,7 @@ Trace execution.
          (repl-compile repl (repl-parse repl form))
          opts))
 
-(define (step repl)
+(define-meta-command (step repl)
   "step FORM
 Step execution."
   (display "Not implemented yet\n"))
@@ -362,12 +403,12 @@ Step execution."
 ;;;
 
 (define guile:gc gc)
-(define (gc repl)
+(define-meta-command (gc repl)
   "gc
 Garbage collection."
   (guile:gc))
 
-(define (statistics repl)
+(define-meta-command (statistics repl)
   "statistics
 Display statistics."
   (let ((this-tms (times))
diff --git a/module/system/repl/repl.scm b/module/system/repl/repl.scm
index 0a06e3d..2f4a378 100644
--- a/module/system/repl/repl.scm
+++ b/module/system/repl/repl.scm
@@ -1,21 +1,21 @@
 ;;; Read-Eval-Print Loop
 
-;; Copyright (C) 2001 Free Software Foundation, Inc.
+;; Copyright (C) 2001, 2009 Free Software Foundation, Inc.
 
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
+;; This library 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,
+;; This library is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
+;; 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 General Public License
-;; along with this program; see the file COPYING.  If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; You should have received a copy of the GNU Lesser General Public
+;; License along with this library; if not, write to the Free Software
+;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+;; 02110-1301 USA
 
 ;;; Code:
 
@@ -28,7 +28,6 @@
   #:use-module (system repl command)
   #:use-module (system vm vm)
   #:use-module (system vm debug)
-  #:use-module (ice-9 rdelim)
   #:export (start-repl call-with-backtrace))
 
 (define meta-command-token (cons 'meta 'command))
@@ -103,11 +102,14 @@
         (cond
          ((eqv? exp (if #f #f))) ; read error, pass
          ((eq? exp meta-command-token)
-          (with-backtrace (meta-command repl (read-line))))
+          (with-backtrace (meta-command repl)))
          ((eof-object? exp)
           (newline)
           (set! status '()))
          (else
+          ;; since the input port is line-buffered, consume up to the
+          ;; newline
+          (flush-to-newline)
           (with-backtrace
            (catch 'quit
                   (lambda ()
@@ -135,3 +137,14 @@
              ((char-whitespace? ch) (read-char) (next-char wait))
              (else ch)))
       #f))
+
+(define (flush-to-newline) 
+  (if (char-ready?)
+      (let ((ch (peek-char)))
+        (if (and (not (eof-object? ch)) (char-whitespace? ch))
+            (begin
+              (read-char)
+              (if (not (char=? ch #\newline))
+                  (flush-to-newline)))))))
+          
+          
\ No newline at end of file
diff --git a/test-suite/tests/bit-operations.test 
b/test-suite/tests/bit-operations.test
index 8815dc6..0e9df7d 100644
--- a/test-suite/tests/bit-operations.test
+++ b/test-suite/tests/bit-operations.test
@@ -1,5 +1,5 @@
 ;;;; bit-operations.test --- bitwise operations on numbers -*- scheme -*-
-;;;; Copyright (C) 2000, 2001, 2003, 2006 Free Software Foundation, Inc.
+;;;; Copyright (C) 2000, 2001, 2003, 2006, 2009 Free Software Foundation, Inc.
 ;;;;
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
@@ -15,8 +15,9 @@
 ;;;; License along with this library; if not, write to the Free Software
 ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
USA
 
-(use-modules (test-suite lib)
-            (ice-9 documentation))
+(define-module (test-bit-operations)
+  :use-module (test-suite lib)
+  :use-module (ice-9 documentation))
 
 
 ;;;
diff --git a/test-suite/tests/bytevectors.test 
b/test-suite/tests/bytevectors.test
index 45f11ec..8b336bb 100644
--- a/test-suite/tests/bytevectors.test
+++ b/test-suite/tests/bytevectors.test
@@ -19,13 +19,33 @@
 
 (define-module (test-bytevector)
   :use-module (test-suite lib)
+  :use-module (system base compile)
   :use-module (rnrs bytevector))
 
 ;;; Some of the tests in here are examples taken from the R6RS Standard
 ;;; Libraries document.
 
+(define-syntax c&e
+  (syntax-rules (pass-if pass-if-exception)
+    ((_ (pass-if test-name exp))
+     (begin (pass-if (string-append test-name " (eval)")
+                     (primitive-eval 'exp))
+            (pass-if (string-append test-name " (compile)")
+                     (compile 'exp #:to 'value))))
+    ((_ (pass-if-exception test-name exc exp))
+     (begin (pass-if-exception (string-append test-name " (eval)")
+                               exc (primitive-eval 'exp))
+            (pass-if-exception (string-append test-name " (compile)")
+                               exc (compile 'exp #:to 'value))))))
+
+(define-syntax with-test-prefix/c&e
+  (syntax-rules ()
+    ((_ section-name exp ...)
+     (with-test-prefix section-name (c&e exp) ...))))
+
+
 
-(with-test-prefix "2.2 General Operations"
+(with-test-prefix/c&e "2.2 General Operations"
 
   (pass-if "native-endianness"
     (not (not (memq (native-endianness) '(big little)))))
@@ -44,7 +64,7 @@
                             (make-bytevector 20 0))))))
 
 
-(with-test-prefix "2.3 Operations on Bytes and Octets"
+(with-test-prefix/c&e "2.3 Operations on Bytes and Octets"
 
   (pass-if "bytevector-{u8,s8}-ref"
     (equal? '(-127 129 -1 255)
@@ -131,7 +151,7 @@
       (equal? bv1 bv2))))
 
 
-(with-test-prefix "2.4 Operations on Integers of Arbitrary Size"
+(with-test-prefix/c&e "2.4 Operations on Integers of Arbitrary Size"
 
   (pass-if "bytevector->sint-list"
     (let ((b (u8-list->bytevector '(1 2 3 255 1 2 1 2))))
@@ -185,7 +205,7 @@
     (uint-list->bytevector '(0 -1) (endianness big) 2)))
 
 
-(with-test-prefix "2.5 Operations on 16-Bit Integers"
+(with-test-prefix/c&e "2.5 Operations on 16-Bit Integers"
 
   (pass-if "bytevector-u16-ref"
     (let ((b (u8-list->bytevector
@@ -233,7 +253,7 @@
              -77))))
 
 
-(with-test-prefix "2.6 Operations on 32-bit Integers"
+(with-test-prefix/c&e "2.6 Operations on 32-bit Integers"
 
   (pass-if "bytevector-u32-ref"
     (let ((b (u8-list->bytevector
@@ -270,7 +290,7 @@
                    (- 2222222222 (expt 2 32)))))))
 
 
-(with-test-prefix "2.7 Operations on 64-bit Integers"
+(with-test-prefix/c&e "2.7 Operations on 64-bit Integers"
 
   (pass-if "bytevector-u64-ref"
     (let ((b (u8-list->bytevector
@@ -315,7 +335,7 @@
        (= 0 (bytevector-u64-ref b 0 (endianness big))))))
 
 
-(with-test-prefix "2.8 Operations on IEEE-754 Representations"
+(with-test-prefix/c&e "2.8 Operations on IEEE-754 Representations"
 
   (pass-if "bytevector-ieee-single-native-{ref,set!}"
     (let ((b (make-bytevector 4))
diff --git a/test-suite/tests/numbers.test b/test-suite/tests/numbers.test
index 57e2f9b..4a9476a 100644
--- a/test-suite/tests/numbers.test
+++ b/test-suite/tests/numbers.test
@@ -1365,7 +1365,14 @@
                 ("address@hidden" 1.0) ("address@hidden" 1.0) 
("address@hidden" 1.0)
                 ("2+3i" ,(+ 2 (* 3 +i))) ("4-5i" ,(- 4 (* 5 +i)))
                 ("1+i" 1+1i) ("1-i" 1-1i) ("+1i" 0+1i) ("-1i" 0-1i)
-                ("+i" +1i) ("-i" -1i)))
+                ("+i" +1i) ("-i" -1i)
+               ("1.0+.1i" 1.0+0.1i)
+               ("1.0-.1i" 1.0-0.1i)
+               (".1+.0i" 0.1)
+               ("1.+.0i" 1.0)
+               (".1+.1i" 0.1+0.1i)
+               ("1e1+.1i" 10+0.1i)
+               ))
     #t)
 
   (pass-if-exception "exponent too big"
diff --git a/test-suite/tests/srfi-14.test b/test-suite/tests/srfi-14.test
index 8c678cd..853a15a 100644
--- a/test-suite/tests/srfi-14.test
+++ b/test-suite/tests/srfi-14.test
@@ -29,6 +29,30 @@
 (define exception:non-char-return
   (cons 'misc-error "returned non-char"))
 
+
+(with-test-prefix "char set contents"
+
+  (pass-if "empty set"
+    (list= eqv? 
+           (char-set->list (char-set))
+           '()))
+
+  (pass-if "single char"
+    (list= eqv?
+           (char-set->list (char-set #\a))
+           (list #\a)))
+
+  (pass-if "contiguous chars"
+    (list= eqv?
+           (char-set->list (char-set #\a #\b #\c))
+           (list #\a #\b #\c))) 
+
+  (pass-if "discontiguous chars"
+    (list= eqv?
+           (char-set->list (char-set #\a #\c #\e))
+           (list #\a #\c #\e))))
+          
+
 (with-test-prefix "char-set?"
 
   (pass-if "success on empty set"
@@ -113,7 +137,7 @@
 (with-test-prefix "char-set cursor"
 
   (pass-if-exception "invalid character cursor" 
-     exception:invalid-char-set-cursor
+     exception:wrong-type-arg
      (let* ((cs (char-set #\B #\r #\a #\z))
            (cc (char-set-cursor cs)))
        (char-set-ref cs 1000)))


hooks/post-receive
-- 
GNU Guile




reply via email to

[Prev in Thread] Current Thread [Next in Thread]