This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


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

Re: [PATCH v3 4/7] Add __v*printf_internal with flags arguments



On 15/11/2018 19:44, Gabriel F. T. Gomes wrote:
> From: Zack Weinberg <zackw@panix.com>
> 
> Changes since v2:
> 
>   - Expanded the comments about PRINTF_LDBL_IS_DBL and PRINTF_FORTIFY.
>   - Removed the parameter-less macros LDBL_IS_DBL and DO_FORTIFY.
>     Explicitly compare the flags.

LGTM, thanks.

> 
> Changes since v1:
> 
>   - Fixed white-space errors.
>   - In argp_fmtstream_printf, do not call __vsnprintf, instead call
>     __vsnprintf_internal passing 0 to mode_flags.  With this change,
>     there's no need to use libc_hidden_{proto,def} for __vsnprintf
>     (because it doesn't have other internal callers).  Also, it is no
>     longer necessary to '#undef __vsnprintf' and '#define __vsnprintf
>     vsnprintf' in argp-namefrob.h.
>   - In __argp_error and __argp_failure call __vasprintf_internal
>     directly, passing 0 (zero) to mode_flags, since these functions do
>     not currently have support for long double with the same format as
>     double (a subsequent patch in my personal branch provides that and
>     adjusts the call accordingly).
>     With this change, there's no need to use libc_hidden_{proto,def} for
>     __vasprintf.  It is also no longer required to '#undef __vasprintf'
>     and '#define __vasprintf vasprintf' in argp-namefrob.h.
>   - Declarations of _IO_vfprintf, _IO_vsprintf, __vfwprintf, and
>     __vswprintf removed from the internal headers: libio.h, iolibio.h,
>     and include/wchar.h, since they are no longer called from within
>     glibc.
>   - Added attribute_hidden to all new internal functions, since they are
>     all called from within libc.
>     Here are the objdumps of one such calls, before and after this
>     change, on a 32-bits powerpc machine:
>     Without attribute_hidden:
>       $ objdump -d --reloc INTERNAL-VISIBLE-glibc/libc.so | grep "<vprintf@@GLIBC_2.4>:" -A 21
>       000523a0 <vprintf@@GLIBC_2.4>:
>          523a0:       94 21 ff f0     stwu    r1,-16(r1)
>          523a4:       7c 85 23 78     mr      r5,r4
>          523a8:       7c 08 02 a6     mflr    r0
>          523ac:       42 9f 00 05     bcl     20,4*cr7+so,523b0 <vprintf@@GLIBC_2.4+0x10>
>          523b0:       7c 64 1b 78     mr      r4,r3
>          523b4:       38 c0 00 00     li      r6,0
>          523b8:       93 c1 00 08     stw     r30,8(r1)
>          523bc:       90 01 00 14     stw     r0,20(r1)
>          523c0:       7f c8 02 a6     mflr    r30
>          523c4:       3f de 00 15     addis   r30,r30,21
>          523c8:       3b de dc 44     addi    r30,r30,-9148
>          523cc:       81 3e fe 80     lwz     r9,-384(r30)
>          523d0:       80 69 00 00     lwz     r3,0(r9)
>          523d4:       48 01 52 bd     bl      67690 <__vfprintf_internal>
>          523d8:       80 01 00 14     lwz     r0,20(r1)
>          523dc:       83 c1 00 08     lwz     r30,8(r1)
>          523e0:       38 21 00 10     addi    r1,r1,16
>          523e4:       7c 08 03 a6     mtlr    r0
>          523e8:       4e 80 00 20     blr
>     With attribute_hidden:
>       $ objdump -d --reloc INTERNAL-HIDDEN-glibc/libc.so | grep "<vprintf@@GLIBC_2.4>:" -A 18
>       00052370 <vprintf@@GLIBC_2.4>:
>          52370:       94 21 ff f0     stwu    r1,-16(r1)
>          52374:       7c 85 23 78     mr      r5,r4
>          52378:       7d 88 02 a6     mflr    r12
>          5237c:       42 9f 00 05     bcl     20,4*cr7+so,52380 <vprintf@@GLIBC_2.4+0x10>
>          52380:       7c 64 1b 78     mr      r4,r3
>          52384:       38 c0 00 00     li      r6,0
>          52388:       93 c1 00 08     stw     r30,8(r1)
>          5238c:       7f c8 02 a6     mflr    r30
>          52390:       7d 88 03 a6     mtlr    r12
>          52394:       3f de 00 15     addis   r30,r30,21
>          52398:       3b de dc 74     addi    r30,r30,-9100
>          5239c:       81 3e fe 80     lwz     r9,-384(r30)
>          523a0:       83 c1 00 08     lwz     r30,8(r1)
>          523a4:       80 69 00 00     lwz     r3,0(r9)
>          523a8:       38 21 00 10     addi    r1,r1,16
>          523ac:       48 01 52 24     b       675d0 <__vfprintf_internal>
>     The branch-and-link instruction is gone.
> 
> Additional note for review:
> 
>   - Reviewing the changes from vfprintf.c to vfprintf-internal.c in the
>     original patch would be vey hard, because git doesn't detect the
>     filename change.  To make review a little easier, I did as Zack did
>     and manually edited the diff.  I'll reply to this thread and attach
>     the original patch if someone wants to apply it.
>     (ping me if I forget it)
> 
> -- 8< --
> There are a lot more printf variants than there are scanf variants,
> and the code for setting up and tearing down their custom FILE
> variants around the call to __vf(w)printf is more complicated and
> variable.  Therefore, I have added _internal versions of all the
> v*printf variants, rather than introducing helper routines so that
> they can all directly call __vf(w)printf_internal, as was done with
> scanf.
> 
> As with the scanf changes, in this patch the _internal functions still
> look at the environmental mode bits and all callers pass 0 for the
> flags parameter.
> 
> Several of the affected public functions had _IO_ name aliases that
> were not exported (but, in one case, appeared in libio.h anyway);
> I was originally planning to leave them as aliases to avoid having
> to touch internal callers, but it turns out ldbl_*_alias only work
> for exported symbols, so they've all been removed instead.  It also
> turns out there were hardly any internal callers.  _IO_vsprintf and
> _IO_vfprintf *are* exported, so those two stick around.
> 
> Summary for the changes to each of the affected symbols:
> 
>   _IO_vfprintf, _IO_vsprintf:
>     All internal calls removed, thus the internal declarations, as well
>     as uses of libc_hidden_proto and libc_hidden_def, were also removed.
>     The external symbol is now exposed via uses of ldbl_strong_alias
>     to __vfprintf_internal and __vsprintf_internal, respectively.
> 
>   _IO_vasprintf, _IO_vdprintf, _IO_vsnprintf,
>   _IO_vfwprintf, _IO_vswprintf,
>   _IO_obstack_vprintf, _IO_obstack_printf:
>     All internal calls removed, thus declaration in internal headers
>     were also removed.  They were never exported, so there are no
>     aliases tying them to the internal functions.  I.e.: entirely gone.
> 
>   __vsnprintf:
>     Internal calls were always preceded by macros such as
>       #define __vsnprintf _IO_vsnprintf, and
>       #define __vsnprintf vsnprintf
>     The macros were removed and their uses replaced with calls to the
>     new internal function __vsnprintf_internal.  Since there were no
>     internal calls, the internal declaration was also removed.  The
>     external symbol is preserved with ldbl_weak_alias to ___vsnprintf.
> 
>   __vfwprintf:
>     All internal calls converted into calls to __vfwprintf_internal,
>     thus the internal declaration was removed.  The function is now a
>     wrapper that calls __vfwprintf_internal.  The external symbol is
>     preserved.
> 
>   __vswprintf:
>     Similarly, but no external symbol.
> 
>   __vasprintf, __vdprintf, __vfprintf, __vsprintf:
>     New internal wrappers.  Not exported.
> 
>   vasprintf, vdprintf, vfprintf, vsprintf, vsnprintf,
>   vfwprintf, vswprintf,
>   obstack_vprintf, obstack_printf:
>     These functions used to be aliases to the respective _IO_* function,
>     they are now aliases to their respective __* functions.
> 
> Tested for powerpc and powerpc64le.
> 
> 2018-10-16  Zack Weinberg  <zackw@panix.com>
> 	    Gabriel F. T. Gomes  <gabriel@inconstante.eti.br>
> 
> 	* libio/libioP.h (__vfprintf_internal, __vfwprintf_internal)
> 	(__vasprintf_internal, __vdprintf_internal, __obstack_vprintf_internal)
> 	(__vsprintf_internal, __vsnprintf_internal, __vswprintf_internal):
> 	New functions.
> 	(PRINTF_LDBL_IS_DBL, PRINTF_FORTIFY): New constants.
> 	(_IO_vasprintf, _IO_vdprintf, _IO_vsnprintf): Remove prototypes.
> 
> 	* stdio-common/vfprintf-internal.c: Rename from vfprintf.c.
> 	Include wctype.h here if COMPILE_WPRINTF is defined.
> 	Define __vfprintf_internal or __vfwprintf_internal, depending
> 	on COMPILE_WPRINTF.
> 	Temporarily, on entry to this function, update mode_flags
> 	according to the environmental settings corresponding to
> 	PRINTF_LDBL_IS_DBL and PRINTF_FORTIFY.
> 	Throughout, check mode_flags instead of __ldbl_is_dbl and
> 	_IO_FLAGS2_FORTIFY on the destination FILE.
> 	* stdio-common/vfwprintf-internal.c: Rename from vfwprintf.c.
> 	Include vfprintf-internal.c.  Don't include wctype.h.
> 	* stdio-common/vfprintf.c: New file.  Just define __vfprintf
> 	as a wrapper around __vfprintf_internal, with aliases _IO_vfprintf
> 	and vfprintf.
> 	* stdio-common/vfwprintf.c: New file.  Just define __vfwprintf
> 	as a wrapper around __vfwprintf_internal, with aliases _IO_vfwprintf
> 	and vfwprintf.
> 	* stdio-common/Makefile: Add vfprintf-internal and vfwprintf-internal.
> 
> 	* libio/iovdprintf.c (_IO_vdprintf): Rename to __vdprintf_internal
> 	and add mode_flags argument; use __vfprintf_internal.
> 	(__vdprintf): New function.  Alias vdprintf to this.
> 	* libio/iovsprintf.c (_IO_vsprintf, __vsprintf): Similarly.
> 	* libio/vasprintf.c (_IO_vasprintf, __vasprintf): Similarly.
> 	* libio/obprintf.c (_IO_obstack_vprintf, __obstack_vprintf): Similarly.
> 	(__obstack_printf): Use __obstack_printf_internal.
> 	* libio/vsnprintf.c (_IO_vsnprintf, ___vsnprintf): Similarly, with
> 	public aliases __vsnprintf and vsnprintf.
> 	Remove use of ldbl_hidden_def, since __vsnprintf is no longer
> 	called internally.
> 	* libio/vswprintf (_IO_vswprintf, __vswprintf): Similarly, with
> 	public aliases _IO_vsprintf and vsprintf.
> 	* libio/swprintf.c (__swprintf): Use __vswprintf_internal.
> 	* stdio-common/asprintf.c (__asprintf): Use __vasprintf_internal.
> 	* stdio-common/dprintf.c (__dprintf): Use __vdprintf_internal.
> 	* stdio-common/snprintf.c (__snprintf): Use __vsprintf_internal.
> 	* stdio-common/sprintf.c (__sprintf): Use __vsprintf_internal.
> 
> 	* debug/obprintf_chk.c, debug/vasprintf_chk.c, debug/vdprintf_chk.c
> 	* debug/vsnprintf_chk.c, debug/vsprintf_chk.c, hurd/vpprintf.c
> 	* stdio-common/fprintf.c, stdio-common/fxprintf.c
> 	* stdio-common/printf.c: Use __vfprintf_internal.
> 
> 	* debug/fwprintf_chk.c, debug/vfwprintf_chk.c, debug/vswprintf_chk.c
> 	* debug/vwprintf_chk.c, debug/wprintf_chk.c, libio/fwprintf.c
> 	* libio/vwprintf.c, libio/wprintf.c: Use __vfwprintf_internal.
> 
> 	* sysdeps/ieee754/ldbl-opt/nldbl-compat.c: Use __vsprintf_internal,
> 	__obstack_vprintf_internal, __vasprintf_internal, __vdprintf_internal,
> 	__vsnprintf_internal, __vswprintf_internal, __vfprintf_internal, and
> 	__vfwprintf_internal.
> 
> 	* libio/libio.h: Remove libc_hidden_proto and declaration for
> 	_IO_vfprintf.
> 	Remove declaration of _IO_vfwprintf.
> 	* libio/iolibio.h: Remove libc_hidden_proto and declaration for
> 	_IO_vsprintf.
> 	Remove declarations of _IO_vswprintf, _IO_obstack_printf, and
> 	_IO_obstack_printf.
> 	* include/stdio.h: Add prototype for __vasprintf.
> 	(__vsnprintf): Remove declaration, because there are no more
> 	internal calls.
> 	* include/wchar.h (__vfwprintf, __vswprintf): Remove
> 	declaration, because there are no more internal calls.
> 
> 	* argp/argp-fmtstream.c (__argp_fmtstream_printf): Use
> 	__vsnprintf_internal, instead of _IO_vsnprintf.
> 	* argp/argp-help.c (__argp_error, __argp_failure): Use
> 	__vasprintf_internal, instead of _IO_vasprintf.
> 	* argp/argp-namefrob.h (__vsnprintf): Do not undefined then
> 	redefine, because there are no more internal calls.
> ---
>  argp/argp-fmtstream.c                            |    3 +-
>  argp/argp-help.c                                 |    4 +-
>  argp/argp-namefrob.h                             |    2 -
>  debug/fwprintf_chk.c                             |    2 +-
>  debug/obprintf_chk.c                             |    2 +-
>  debug/vasprintf_chk.c                            |    2 +-
>  debug/vdprintf_chk.c                             |    2 +-
>  debug/vfwprintf_chk.c                            |    2 +-
>  debug/vsnprintf_chk.c                            |    2 +-
>  debug/vsprintf_chk.c                             |    2 +-
>  debug/vswprintf_chk.c                            |    2 +-
>  debug/vwprintf_chk.c                             |    2 +-
>  debug/wprintf_chk.c                              |    2 +-
>  hurd/vpprintf.c                                  |    2 +-
>  include/stdio.h                                  |    3 -
>  include/wchar.h                                  |   10 -
>  libio/fwprintf.c                                 |    2 +-
>  libio/iolibio.h                                  |    8 -
>  libio/iovdprintf.c                               |   13 +-
>  libio/iovsprintf.c                               |   16 +-
>  libio/libio.h                                    |    5 -
>  libio/libioP.h                                   |   47 +-
>  libio/obprintf.c                                 |   19 +-
>  libio/swprintf.c                                 |    2 +-
>  libio/vasprintf.c                                |   20 +-
>  libio/vsnprintf.c                                |   16 +-
>  libio/vswprintf.c                                |   16 +-
>  libio/vwprintf.c                                 |    2 +-
>  libio/wprintf.c                                  |    2 +-
>  stdio-common/Makefile                            |    3 +-
>  stdio-common/asprintf.c                          |    6 +-
>  stdio-common/dprintf.c                           |    5 +-
>  stdio-common/fprintf.c                           |    2 +-
>  stdio-common/fxprintf.c                          |    4 +-
>  stdio-common/printf.c                            |    3 +-
>  stdio-common/snprintf.c                          |    4 +-
>  stdio-common/sprintf.c                           |    4 +-
>  stdio-common/{vfprintf.c => vfprintf-internal.c} |   66 +-
>  stdio-common/vfprintf.c                          | 2351 +---------------------
>  stdio-common/vfwprintf-internal.c                |    2 +
>  stdio-common/vfwprintf.c                         |   28 +-
>  stdio-common/vprintf.c                           |    4 +-
>  stdlib/strfrom-skeleton.c                        |    2 +-
>  sysdeps/ieee754/ldbl-opt/nldbl-compat.c          |   21 +-
>  44 files changed, 219 insertions(+), 2498 deletions(-)
>  copy stdio-common/{vfprintf.c => vfprintf-internal.c} (98%)
>  create mode 100644 stdio-common/vfwprintf-internal.c
> 
> diff --git a/argp/argp-fmtstream.c b/argp/argp-fmtstream.c
> index e43a0c7cf1..b9dcb2c9c7 100644
> --- a/argp/argp-fmtstream.c
> +++ b/argp/argp-fmtstream.c
> @@ -42,7 +42,6 @@
>  #ifdef _LIBC
>  # include <wchar.h>
>  # include <libio/libioP.h>
> -# define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a)
>  #endif
>  
>  #define INIT_BUF_SIZE 200
> @@ -409,7 +408,7 @@ __argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...)
>  
>        va_start (args, fmt);
>        avail = fs->end - fs->p;
> -      out = __vsnprintf (fs->p, avail, fmt, args);
> +      out = __vsnprintf_internal (fs->p, avail, fmt, args, 0);
>        va_end (args);
>        if ((size_t) out >= avail)
>  	size_guess = out + 1;

Ok.

> diff --git a/argp/argp-help.c b/argp/argp-help.c
> index 2b6b0775d6..6857391ce2 100644
> --- a/argp/argp-help.c
> +++ b/argp/argp-help.c
> @@ -1769,7 +1769,7 @@ __argp_error (const struct argp_state *state, const char *fmt, ...)
>  #ifdef _LIBC
>  	  char *buf;
>  
> -	  if (_IO_vasprintf (&buf, fmt, ap) < 0)
> +	  if (__vasprintf_internal (&buf, fmt, ap, 0) < 0)
>  	    buf = NULL;
>  
>  	  __fxprintf (stream, "%s: %s\n",
> @@ -1839,7 +1839,7 @@ __argp_failure (const struct argp_state *state, int status, int errnum,
>  #ifdef _LIBC
>  	      char *buf;
>  
> -	      if (_IO_vasprintf (&buf, fmt, ap) < 0)
> +	      if (__vasprintf_internal (&buf, fmt, ap, 0) < 0)
>  		buf = NULL;
>  
>  	      __fxprintf (stream, ": %s", buf);

Ok.

> diff --git a/argp/argp-namefrob.h b/argp/argp-namefrob.h
> index 5588fe172a..5e48b5940d 100644
> --- a/argp/argp-namefrob.h
> +++ b/argp/argp-namefrob.h
> @@ -98,8 +98,6 @@
>  #define __strerror_r strerror_r
>  #undef __strndup
>  #define __strndup strndup
> -#undef __vsnprintf
> -#define __vsnprintf vsnprintf
>  
>  #if defined(HAVE_DECL_CLEARERR_UNLOCKED) && !HAVE_DECL_CLEARERR_UNLOCKED
>  # define clearerr_unlocked(x) clearerr (x)
> diff --git a/debug/fwprintf_chk.c b/debug/fwprintf_chk.c
> index aeb83077da..63167c1839 100644
> --- a/debug/fwprintf_chk.c
> +++ b/debug/fwprintf_chk.c
> @@ -32,7 +32,7 @@ __fwprintf_chk (FILE *fp, int flag, const wchar_t *format, ...)
>      fp->_flags2 |= _IO_FLAGS2_FORTIFY;
>  
>    va_start (ap, format);
> -  done = _IO_vfwprintf (fp, format, ap);
> +  done = __vfwprintf_internal (fp, format, ap, 0);
>    va_end (ap);
>  
>    if (flag > 0)

Ok.

> diff --git a/debug/obprintf_chk.c b/debug/obprintf_chk.c
> index 3ac5a3cd4f..41dd481c34 100644
> --- a/debug/obprintf_chk.c
> +++ b/debug/obprintf_chk.c
> @@ -91,7 +91,7 @@ __obstack_vprintf_chk (struct obstack *obstack, int flags, const char *format,
>    if (flags > 0)
>      new_f.ofile.file.file._flags2 |= _IO_FLAGS2_FORTIFY;
>  
> -  result = _IO_vfprintf (&new_f.ofile.file.file, format, args);
> +  result = __vfprintf_internal (&new_f.ofile.file.file, format, args, 0);
>  
>    /* Shrink the buffer to the space we really currently need.  */
>    obstack_blank_fast (obstack, (new_f.ofile.file.file._IO_write_ptr

Ok.

> diff --git a/debug/vasprintf_chk.c b/debug/vasprintf_chk.c
> index 48b4741651..dbfebff83f 100644
> --- a/debug/vasprintf_chk.c
> +++ b/debug/vasprintf_chk.c
> @@ -63,7 +63,7 @@ __vasprintf_chk (char **result_ptr, int flags, const char *format,
>    if (flags > 0)
>      sf._sbf._f._flags2 |= _IO_FLAGS2_FORTIFY;
>  
> -  ret = _IO_vfprintf (&sf._sbf._f, format, args);
> +  ret = __vfprintf_internal (&sf._sbf._f, format, args, 0);
>    if (ret < 0)
>      {
>        free (sf._sbf._f._IO_buf_base);

Ok.

> diff --git a/debug/vdprintf_chk.c b/debug/vdprintf_chk.c
> index bc713b4962..4386127cfe 100644
> --- a/debug/vdprintf_chk.c
> +++ b/debug/vdprintf_chk.c
> @@ -55,7 +55,7 @@ __vdprintf_chk (int d, int flags, const char *format, va_list arg)
>    if (flags > 0)
>      tmpfil.file._flags2 |= _IO_FLAGS2_FORTIFY;
>  
> -  done = _IO_vfprintf (&tmpfil.file, format, arg);
> +  done = __vfprintf_internal (&tmpfil.file, format, arg, 0);
>  
>    _IO_FINISH (&tmpfil.file);
>  

Ok.

> diff --git a/debug/vfwprintf_chk.c b/debug/vfwprintf_chk.c
> index 1ffd18cbd2..abf2bd6517 100644
> --- a/debug/vfwprintf_chk.c
> +++ b/debug/vfwprintf_chk.c
> @@ -30,7 +30,7 @@ __vfwprintf_chk (FILE *fp, int flag, const wchar_t *format, va_list ap)
>    if (flag > 0)
>      fp->_flags2 |= _IO_FLAGS2_FORTIFY;
>  
> -  done = _IO_vfwprintf (fp, format, ap);
> +  done = __vfwprintf_internal (fp, format, ap, 0);
>  
>    if (flag > 0)
>      fp->_flags2 &= ~_IO_FLAGS2_FORTIFY;

Ok.

> diff --git a/debug/vsnprintf_chk.c b/debug/vsnprintf_chk.c
> index d20d0fbd93..95d286f416 100644
> --- a/debug/vsnprintf_chk.c
> +++ b/debug/vsnprintf_chk.c
> @@ -60,7 +60,7 @@ ___vsnprintf_chk (char *s, size_t maxlen, int flags, size_t slen,
>      sf.f._sbf._f._flags2 |= _IO_FLAGS2_FORTIFY;
>  
>    _IO_str_init_static_internal (&sf.f, s, maxlen - 1, s);
> -  ret = _IO_vfprintf (&sf.f._sbf._f, format, args);
> +  ret = __vfprintf_internal (&sf.f._sbf._f, format, args, 0);
>  
>    if (sf.f._sbf._f._IO_buf_base != sf.overflow_buf)
>      *sf.f._sbf._f._IO_write_ptr = '\0';

Ok.

> diff --git a/debug/vsprintf_chk.c b/debug/vsprintf_chk.c
> index 9a443bb699..53f07236ae 100644
> --- a/debug/vsprintf_chk.c
> +++ b/debug/vsprintf_chk.c
> @@ -80,7 +80,7 @@ ___vsprintf_chk (char *s, int flags, size_t slen, const char *format,
>    if (flags > 0)
>      f._sbf._f._flags2 |= _IO_FLAGS2_FORTIFY;
>  
> -  ret = _IO_vfprintf (&f._sbf._f, format, args);
> +  ret = __vfprintf_internal (&f._sbf._f, format, args, 0);
>  
>    *f._sbf._f._IO_write_ptr = '\0';
>    return ret;

Ok.

> diff --git a/debug/vswprintf_chk.c b/debug/vswprintf_chk.c
> index c6a7edcacd..4d616f8835 100644
> --- a/debug/vswprintf_chk.c
> +++ b/debug/vswprintf_chk.c
> @@ -59,7 +59,7 @@ __vswprintf_chk (wchar_t *s, size_t maxlen, int flags, size_t slen,
>      sf.f._sbf._f._flags2 |= _IO_FLAGS2_FORTIFY;
>  
>    _IO_wstr_init_static (&sf.f._sbf._f, s, maxlen - 1, s);
> -  ret = _IO_vfwprintf ((FILE *) &sf.f._sbf, format, args);
> +  ret = __vfwprintf_internal ((FILE *) &sf.f._sbf, format, args, 0);
>  
>    if (sf.f._sbf._f._wide_data->_IO_buf_base == sf.overflow_buf)
>      /* ISO C99 requires swprintf/vswprintf to return an error if the

Ok.

> diff --git a/debug/vwprintf_chk.c b/debug/vwprintf_chk.c
> index 51b67c159d..fedc7a46bf 100644
> --- a/debug/vwprintf_chk.c
> +++ b/debug/vwprintf_chk.c
> @@ -31,7 +31,7 @@ __vwprintf_chk (int flag, const wchar_t *format, va_list ap)
>    if (flag > 0)
>      stdout->_flags2 |= _IO_FLAGS2_FORTIFY;
>  
> -  done = _IO_vfwprintf (stdout, format, ap);
> +  done = __vfwprintf_internal (stdout, format, ap, 0);
>  
>    if (flag > 0)
>      stdout->_flags2 &= ~_IO_FLAGS2_FORTIFY;

Ok.

> diff --git a/debug/wprintf_chk.c b/debug/wprintf_chk.c
> index 17023b6bb4..819050e5af 100644
> --- a/debug/wprintf_chk.c
> +++ b/debug/wprintf_chk.c
> @@ -33,7 +33,7 @@ __wprintf_chk (int flag, const wchar_t *format, ...)
>      stdout->_flags2 |= _IO_FLAGS2_FORTIFY;
>  
>    va_start (ap, format);
> -  done = _IO_vfwprintf (stdout, format, ap);
> +  done = __vfwprintf_internal (stdout, format, ap, 0);
>    va_end (ap);
>  
>    if (flag > 0)

Ok.

> diff --git a/hurd/vpprintf.c b/hurd/vpprintf.c
> index 76cd31f922..b9634afc2b 100644
> --- a/hurd/vpprintf.c
> +++ b/hurd/vpprintf.c
> @@ -53,7 +53,7 @@ vpprintf (io_t port, const char *format, va_list arg)
>    _IO_cookie_init (&temp_f.cfile, _IO_NO_READS,
>  		   (void *) port, (cookie_io_functions_t) { write: do_write });
>  
> -  done = _IO_vfprintf (&temp_f.cfile.__fp.file, format, arg);
> +  done = __vfprintf_internal (&temp_f.cfile.__fp.file, format, arg, 0);
>  
>    return done;
>  }



> diff --git a/include/stdio.h b/include/stdio.h
> index 51ada4a4c4..0856d729d9 100644
> --- a/include/stdio.h
> +++ b/include/stdio.h
> @@ -14,9 +14,6 @@ extern int __snprintf (char *__restrict __s, size_t __maxlen,
>  		       const char *__restrict __format, ...)
>       __attribute__ ((__format__ (__printf__, 3, 4)));
>  libc_hidden_proto (__snprintf)
> -extern int __vsnprintf (char *__restrict __s, size_t __maxlen,
> -			const char *__restrict __format, __gnuc_va_list __arg)
> -     __attribute__ ((__format__ (__printf__, 3, 0)));
>  extern int __vfscanf (FILE *__restrict __s,
>  		      const char *__restrict __format,
>  		      __gnuc_va_list __arg)
> diff --git a/include/wchar.h b/include/wchar.h
> index 1db0ac8278..d0fe45c3a6 100644
> --- a/include/wchar.h
> +++ b/include/wchar.h
> @@ -203,20 +203,10 @@ extern int __vfwscanf (__FILE *__restrict __s,
>  		       __gnuc_va_list __arg)
>       attribute_hidden
>       /* __attribute__ ((__format__ (__wscanf__, 2, 0)) */;
> -extern int __vswprintf (wchar_t *__restrict __s, size_t __n,
> -			const wchar_t *__restrict __format,
> -			__gnuc_va_list __arg)
> -     attribute_hidden
> -     /* __attribute__ ((__format__ (__wprintf__, 3, 0))) */;
>  extern int __fwprintf (__FILE *__restrict __s,
>  		       const wchar_t *__restrict __format, ...)
>       attribute_hidden
>       /* __attribute__ ((__format__ (__wprintf__, 2, 3))) */;
> -extern int __vfwprintf (__FILE *__restrict __s,
> -			const wchar_t *__restrict __format,
> -			__gnuc_va_list __arg)
> -     attribute_hidden
> -     /* __attribute__ ((__format__ (__wprintf__, 2, 0))) */;
>  extern int __vfwprintf_chk (FILE *__restrict __s, int __flag,
>  			    const wchar_t *__restrict __format,
>  			    __gnuc_va_list __arg)

Ok.

> diff --git a/libio/fwprintf.c b/libio/fwprintf.c
> index fab63a8716..9903f1f342 100644
> --- a/libio/fwprintf.c
> +++ b/libio/fwprintf.c
> @@ -30,7 +30,7 @@ __fwprintf (FILE *stream, const wchar_t *format, ...)
>    int done;
>  
>    va_start (arg, format);
> -  done = __vfwprintf (stream, format, arg);
> +  done = __vfwprintf_internal (stream, format, arg, 0);
>    va_end (arg);
>  
>    return done;

Ok.

> diff --git a/libio/iolibio.h b/libio/iolibio.h
> index 6c94fe6d62..2642d71e4f 100644
> --- a/libio/iolibio.h
> +++ b/libio/iolibio.h
> @@ -51,15 +51,7 @@ extern int _IO_sscanf (const char*, const char*, ...) __THROW;
>  extern int _IO_sprintf (char *, const char*, ...) __THROW;
>  extern int _IO_ungetc (int, FILE*) __THROW;
>  extern int _IO_vsscanf (const char *, const char *, __gnuc_va_list) __THROW;
> -extern int _IO_vsprintf (char*, const char*, __gnuc_va_list) __THROW;
> -libc_hidden_proto (_IO_vsprintf)
> -extern int _IO_vswprintf (wchar_t*, size_t, const wchar_t*, __gnuc_va_list)
> -       __THROW;
>  
> -struct obstack;
> -extern int _IO_obstack_vprintf (struct obstack *, const char *, __gnuc_va_list)
> -       __THROW;
> -extern int _IO_obstack_printf (struct obstack *, const char *, ...) __THROW;
>  #define _IO_clearerr(FP) ((FP)->_flags &= ~(_IO_ERR_SEEN|_IO_EOF_SEEN))
>  #define _IO_fseek(__fp, __offset, __whence) \
>    (_IO_seekoff_unlocked (__fp, __offset, __whence, _IOS_INPUT|_IOS_OUTPUT) \

Ok.

> diff --git a/libio/iovdprintf.c b/libio/iovdprintf.c
> index 78a3a2bd15..1d2ed0f9e7 100644
> --- a/libio/iovdprintf.c
> +++ b/libio/iovdprintf.c
> @@ -28,7 +28,8 @@
>  #include <stdio_ext.h>
>  
>  int
> -_IO_vdprintf (int d, const char *format, va_list arg)
> +__vdprintf_internal (int d, const char *format, va_list arg,
> +		     unsigned int mode_flags)
>  {
>    struct _IO_FILE_plus tmpfil;
>    struct _IO_wide_data wd;
> @@ -50,7 +51,7 @@ _IO_vdprintf (int d, const char *format, va_list arg)
>    _IO_mask_flags (&tmpfil.file, _IO_NO_READS,
>  		  _IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
>  
> -  done = _IO_vfprintf (&tmpfil.file, format, arg);
> +  done = __vfprintf_internal (&tmpfil.file, format, arg, mode_flags);
>  
>    if (done != EOF && _IO_do_flush (&tmpfil.file) == EOF)
>      done = EOF;
> @@ -59,4 +60,10 @@ _IO_vdprintf (int d, const char *format, va_list arg)
>  
>    return done;
>  }
> -ldbl_weak_alias (_IO_vdprintf, vdprintf)
> +
> +int
> +__vdprintf (int d, const char *format, va_list arg)
> +{
> +  return __vdprintf_internal (d, format, arg, 0);
> +}
> +ldbl_weak_alias (__vdprintf, vdprintf)

Ok.

> diff --git a/libio/iovsprintf.c b/libio/iovsprintf.c
> index 4def251701..3b1e8292b5 100644
> --- a/libio/iovsprintf.c
> +++ b/libio/iovsprintf.c
> @@ -28,7 +28,8 @@
>  #include "strfile.h"
>  
>  int
> -__IO_vsprintf (char *string, const char *format, va_list args)
> +__vsprintf_internal (char *string, const char *format, va_list args,
> +		     unsigned int mode_flags)
>  {
>    _IO_strfile sf;
>    int ret;
> @@ -39,11 +40,16 @@ __IO_vsprintf (char *string, const char *format, va_list args)
>    _IO_no_init (&sf._sbf._f, _IO_USER_LOCK, -1, NULL, NULL);
>    _IO_JUMPS (&sf._sbf) = &_IO_str_jumps;
>    _IO_str_init_static_internal (&sf, string, -1, string);
> -  ret = _IO_vfprintf (&sf._sbf._f, format, args);
> +  ret = __vfprintf_internal (&sf._sbf._f, format, args, mode_flags);
>    _IO_putc_unlocked ('\0', &sf._sbf._f);
>    return ret;
>  }
> -ldbl_hidden_def (__IO_vsprintf, _IO_vsprintf)
>  
> -ldbl_strong_alias (__IO_vsprintf, _IO_vsprintf)
> -ldbl_weak_alias (__IO_vsprintf, vsprintf)
> +int
> +__vsprintf (char *string, const char *format, va_list args)
> +{
> +  return __vsprintf_internal (string, format, args, 0);
> +}
> +
> +ldbl_strong_alias (__vsprintf, _IO_vsprintf)
> +ldbl_weak_alias (__vsprintf, vsprintf)

Ok.

> diff --git a/libio/libio.h b/libio/libio.h
> index 30cb7d784f..c188814ccc 100644
> --- a/libio/libio.h
> +++ b/libio/libio.h
> @@ -255,8 +255,6 @@ extern int _IO_ftrylockfile (FILE *) __THROW;
>  
>  extern int _IO_vfscanf (FILE * __restrict, const char * __restrict,
>  			__gnuc_va_list, int *__restrict);
> -extern int _IO_vfprintf (FILE *__restrict, const char *__restrict,
> -			 __gnuc_va_list);
>  extern __ssize_t _IO_padn (FILE *, int, __ssize_t);
>  extern size_t _IO_sgetn (FILE *, void *, size_t);
>  
> @@ -298,8 +296,6 @@ weak_extern (_IO_stdin_used);
>  
>  extern int _IO_vfwscanf (FILE * __restrict, const wchar_t * __restrict,
>  			 __gnuc_va_list, int *__restrict);
> -extern int _IO_vfwprintf (FILE *__restrict, const wchar_t *__restrict,
> -			  __gnuc_va_list);
>  extern __ssize_t _IO_wpadn (FILE *, wint_t, __ssize_t);
>  extern void _IO_free_wbackup_area (FILE *) __THROW;
>  
> @@ -319,7 +315,6 @@ libc_hidden_proto (_IO_free_wbackup_area)
>  libc_hidden_proto (_IO_padn)
>  libc_hidden_proto (_IO_putc)
>  libc_hidden_proto (_IO_sgetn)
> -libc_hidden_proto (_IO_vfprintf)
>  
>  #ifdef _IO_MTSAFE_IO
>  # undef _IO_peekc

Ok.

> diff --git a/libio/libioP.h b/libio/libioP.h
> index 9e971cb96b..fe52ef1752 100644
> --- a/libio/libioP.h
> +++ b/libio/libioP.h
> @@ -658,12 +658,49 @@ extern off64_t _IO_wstr_seekoff (FILE *, off64_t, int, int)
>  extern wint_t _IO_wstr_pbackfail (FILE *, wint_t) __THROW;
>  extern void _IO_wstr_finish (FILE *, int) __THROW;
>  
> -extern int _IO_vasprintf (char **result_ptr, const char *format,
> -			  va_list args) __THROW;
> -extern int _IO_vdprintf (int d, const char *format, va_list arg);
> -extern int _IO_vsnprintf (char *string, size_t maxlen,
> -			  const char *format, va_list args) __THROW;
> +/* Internal versions of v*printf that take an additional flags
> +   parameter.  */
> +extern int __vfprintf_internal (FILE *fp, const char *format, va_list ap,
> +				unsigned int mode_flags)
> +    attribute_hidden;
> +extern int __vfwprintf_internal (FILE *fp, const wchar_t *format, va_list ap,
> +				 unsigned int mode_flags)
> +    attribute_hidden;
> +
> +extern int __vasprintf_internal (char **result_ptr, const char *format,
> +				 va_list ap, unsigned int mode_flags)
> +    attribute_hidden;
> +extern int __vdprintf_internal (int d, const char *format, va_list ap,
> +				unsigned int mode_flags)
> +    attribute_hidden;
> +extern int __obstack_vprintf_internal (struct obstack *ob, const char *fmt,
> +				       va_list ap, unsigned int mode_flags)
> +    attribute_hidden;
> +
> +extern int __vsprintf_internal (char *string, const char *format, va_list ap,
> +				unsigned int mode_flags)
> +    attribute_hidden;
> +extern int __vsnprintf_internal (char *string, size_t maxlen,
> +				 const char *format, va_list ap,
> +				 unsigned int mode_flags)
> +    attribute_hidden;
> +extern int __vswprintf_internal (wchar_t *string, size_t maxlen,
> +				 const wchar_t *format, va_list ap,
> +				 unsigned int mode_flags)
> +    attribute_hidden;
> +
> +/* Flags for __v*printf_internal.
> +
> +   PRINTF_LDBL_IS_DBL indicates whether long double values are to be
> +   handled as having the same format as double, in which case the flag
> +   should be set to one, or as another format, otherwise.
>  
> +   PRINTF_FORTIFY, when set to one, indicates that fortification checks
> +   are to be performed in input parameters.  This is used by the
> +   __*printf_chk functions, which are used when _FORTIFY_SOURCE is
> +   defined to 1 or 2.  Otherwise, such checks are ignored.  */
> +#define PRINTF_LDBL_IS_DBL 0x0001
> +#define PRINTF_FORTIFY     0x0002
>  
>  extern size_t _IO_getline (FILE *,char *, size_t, int, int);
>  libc_hidden_proto (_IO_getline)

Ok.

> diff --git a/libio/obprintf.c b/libio/obprintf.c
> index a74f9467a2..10a4b5c10c 100644
> --- a/libio/obprintf.c
> +++ b/libio/obprintf.c
> @@ -117,7 +117,8 @@ const struct _IO_jump_t _IO_obstack_jumps libio_vtable attribute_hidden =
>  
>  
>  int
> -_IO_obstack_vprintf (struct obstack *obstack, const char *format, va_list args)
> +__obstack_vprintf_internal (struct obstack *obstack, const char *format,
> +			    va_list args, unsigned int mode_flags)
>  {
>    struct obstack_FILE
>      {
> @@ -164,7 +165,8 @@ _IO_obstack_vprintf (struct obstack *obstack, const char *format, va_list args)
>  
>    new_f.ofile.obstack = obstack;
>  
> -  result = _IO_vfprintf (&new_f.ofile.file.file, format, args);
> +  result = __vfprintf_internal (&new_f.ofile.file.file, format, args,
> +				mode_flags);
>  
>    /* Shrink the buffer to the space we really currently need.  */
>    obstack_blank_fast (obstack, (new_f.ofile.file.file._IO_write_ptr
> @@ -172,17 +174,22 @@ _IO_obstack_vprintf (struct obstack *obstack, const char *format, va_list args)
>  
>    return result;
>  }
> -ldbl_weak_alias (_IO_obstack_vprintf, obstack_vprintf)
>  
> +int
> +__obstack_vprintf (struct obstack *obstack, const char *format, va_list ap)
> +{
> +  return __obstack_vprintf_internal (obstack, format, ap, 0);
> +}
> +ldbl_weak_alias (__obstack_vprintf, obstack_vprintf)
>  
>  int
> -_IO_obstack_printf (struct obstack *obstack, const char *format, ...)
> +__obstack_printf (struct obstack *obstack, const char *format, ...)
>  {
>    int result;
>    va_list ap;
>    va_start (ap, format);
> -  result = _IO_obstack_vprintf (obstack, format, ap);
> +  result = __obstack_vprintf_internal (obstack, format, ap, 0);
>    va_end (ap);
>    return result;
>  }
> -ldbl_weak_alias (_IO_obstack_printf, obstack_printf)
> +ldbl_weak_alias (__obstack_printf, obstack_printf)

Ok.

> diff --git a/libio/swprintf.c b/libio/swprintf.c
> index 10f722d035..19b3f33198 100644
> --- a/libio/swprintf.c
> +++ b/libio/swprintf.c
> @@ -28,7 +28,7 @@ __swprintf (wchar_t *s, size_t n, const wchar_t *format, ...)
>    int done;
>  
>    va_start (arg, format);
> -  done = __vswprintf (s, n, format, arg);
> +  done = __vswprintf_internal (s, n, format, arg, 0);
>    va_end (arg);
>  
>    return done;

Ok.

> diff --git a/libio/vasprintf.c b/libio/vasprintf.c
> index 6c35d2b108..fabd84f403 100644
> --- a/libio/vasprintf.c
> +++ b/libio/vasprintf.c
> @@ -24,15 +24,13 @@
>     This exception applies to code released by its copyright holders
>     in files containing the exception.  */
>  
> -#include <malloc.h>
>  #include <string.h>
> -#include "libioP.h"
> -#include "stdio.h"
> -#include <stdio_ext.h>
> -#include "strfile.h"
> +#include <stdlib.h>
> +#include <strfile.h>
>  
>  int
> -_IO_vasprintf (char **result_ptr, const char *format, va_list args)
> +__vasprintf_internal (char **result_ptr, const char *format, va_list args,
> +		      unsigned int mode_flags)
>  {
>    /* Initial size of the buffer to be used.  Will be doubled each time an
>       overflow occurs.  */
> @@ -56,7 +54,7 @@ _IO_vasprintf (char **result_ptr, const char *format, va_list args)
>    sf._sbf._f._flags &= ~_IO_USER_BUF;
>    sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc;
>    sf._s._free_buffer_unused = (_IO_free_type) free;
> -  ret = _IO_vfprintf (&sf._sbf._f, format, args);
> +  ret = __vfprintf_internal (&sf._sbf._f, format, args, mode_flags);
>    if (ret < 0)
>      {
>        free (sf._sbf._f._IO_buf_base);
> @@ -85,4 +83,10 @@ _IO_vasprintf (char **result_ptr, const char *format, va_list args)
>    (*result_ptr)[needed - 1] = '\0';
>    return ret;
>  }
> -ldbl_weak_alias (_IO_vasprintf, vasprintf)
> +
> +int
> +__vasprintf (char **result_ptr, const char *format, va_list args)
> +{
> +  return __vasprintf_internal (result_ptr, format, args, 0);
> +}
> +ldbl_weak_alias (__vasprintf, vasprintf)

Ok.

> diff --git a/libio/vsnprintf.c b/libio/vsnprintf.c
> index 39b5500528..35b267abf8 100644
> --- a/libio/vsnprintf.c
> +++ b/libio/vsnprintf.c
> @@ -90,8 +90,8 @@ const struct _IO_jump_t _IO_strn_jumps libio_vtable attribute_hidden =
>  
>  
>  int
> -_IO_vsnprintf (char *string, size_t maxlen, const char *format,
> -	       va_list args)
> +__vsnprintf_internal (char *string, size_t maxlen, const char *format,
> +		      va_list args, unsigned int mode_flags)
>  {
>    _IO_strnfile sf;
>    int ret;
> @@ -111,11 +111,17 @@ _IO_vsnprintf (char *string, size_t maxlen, const char *format,
>    _IO_JUMPS (&sf.f._sbf) = &_IO_strn_jumps;
>    string[0] = '\0';
>    _IO_str_init_static_internal (&sf.f, string, maxlen - 1, string);
> -  ret = _IO_vfprintf (&sf.f._sbf._f, format, args);
> +  ret = __vfprintf_internal (&sf.f._sbf._f, format, args, mode_flags);
>  
>    if (sf.f._sbf._f._IO_buf_base != sf.overflow_buf)
>      *sf.f._sbf._f._IO_write_ptr = '\0';
>    return ret;
>  }
> -ldbl_weak_alias (_IO_vsnprintf, __vsnprintf)
> -ldbl_weak_alias (_IO_vsnprintf, vsnprintf)
> +
> +int
> +___vsnprintf (char *string, size_t maxlen, const char *format, va_list args)
> +{
> +  return __vsnprintf_internal (string, maxlen, format, args, 0);
> +}
> +ldbl_weak_alias (___vsnprintf, __vsnprintf)
> +ldbl_weak_alias (___vsnprintf, vsnprintf)

Ok.

> diff --git a/libio/vswprintf.c b/libio/vswprintf.c
> index bcc473d115..e415e39fc9 100644
> --- a/libio/vswprintf.c
> +++ b/libio/vswprintf.c
> @@ -89,8 +89,8 @@ const struct _IO_jump_t _IO_wstrn_jumps libio_vtable attribute_hidden =
>  
>  
>  int
> -_IO_vswprintf (wchar_t *string, size_t maxlen, const wchar_t *format,
> -	       va_list args)
> +__vswprintf_internal (wchar_t *string, size_t maxlen, const wchar_t *format,
> +		      va_list args, unsigned int mode_flags)
>  {
>    _IO_wstrnfile sf;
>    int ret;
> @@ -108,7 +108,7 @@ _IO_vswprintf (wchar_t *string, size_t maxlen, const wchar_t *format,
>    _IO_fwide (&sf.f._sbf._f, 1);
>    string[0] = L'\0';
>    _IO_wstr_init_static (&sf.f._sbf._f, string, maxlen - 1, string);
> -  ret = _IO_vfwprintf ((FILE *) &sf.f._sbf, format, args);
> +  ret = __vfwprintf_internal ((FILE *) &sf.f._sbf, format, args, mode_flags);
>  
>    if (sf.f._sbf._f._wide_data->_IO_buf_base == sf.overflow_buf)
>      /* ISO C99 requires swprintf/vswprintf to return an error if the
> @@ -120,5 +120,11 @@ _IO_vswprintf (wchar_t *string, size_t maxlen, const wchar_t *format,
>  
>    return ret;
>  }
> -weak_alias (_IO_vswprintf, __vswprintf)
> -ldbl_weak_alias (_IO_vswprintf, vswprintf)
> +
> +int
> +__vswprintf (wchar_t *string, size_t maxlen, const wchar_t *format,
> +	     va_list args)
> +{
> +  return __vswprintf_internal (string, maxlen, format, args, 0);
> +}
> +ldbl_weak_alias (__vswprintf, vswprintf)

Ok.

> diff --git a/libio/vwprintf.c b/libio/vwprintf.c
> index 72ebfec92d..e8a529afff 100644
> --- a/libio/vwprintf.c
> +++ b/libio/vwprintf.c
> @@ -25,6 +25,6 @@
>  int
>  __vwprintf (const wchar_t *format, __gnuc_va_list arg)
>  {
> -  return __vfwprintf (stdout, format, arg);
> +  return __vfwprintf_internal (stdout, format, arg, 0);
>  }
>  ldbl_strong_alias (__vwprintf, vwprintf)

Ok.

> diff --git a/libio/wprintf.c b/libio/wprintf.c
> index 5945f651fc..361cd40a1b 100644
> --- a/libio/wprintf.c
> +++ b/libio/wprintf.c
> @@ -29,7 +29,7 @@ __wprintf (const wchar_t *format, ...)
>    int done;
>  
>    va_start (arg, format);
> -  done = __vfwprintf (stdout, format, arg);
> +  done = __vfwprintf_internal (stdout, format, arg, 0);
>    va_end (arg);
>  
>    return done;

Ok.

> diff --git a/stdio-common/Makefile b/stdio-common/Makefile
> index f3b3ceddbd..84bad1fafe 100644
> --- a/stdio-common/Makefile
> +++ b/stdio-common/Makefile
> @@ -40,7 +40,8 @@ routines	:=							      \
>  	isoc99_scanf isoc99_vscanf isoc99_fscanf isoc99_vfscanf isoc99_sscanf \
>  	isoc99_vsscanf							      \
>  	psiginfo gentempfd						      \
> -	vfscanf-internal vfwscanf-internal iovfscanf iovfwscanf
> +	vfscanf-internal vfwscanf-internal iovfscanf iovfwscanf		      \
> +	vfprintf-internal vfwprintf-internal
>  
>  aux	:= errlist siglist printf-parsemb printf-parsewc fxprintf
>  

Ok.

> diff --git a/stdio-common/asprintf.c b/stdio-common/asprintf.c
> index bff858e657..8943ffcae1 100644
> --- a/stdio-common/asprintf.c
> +++ b/stdio-common/asprintf.c
> @@ -16,11 +16,7 @@
>     <http://www.gnu.org/licenses/>.  */
>  
>  #include <stdarg.h>
> -#include <stdio.h>
> -
>  #include <libioP.h>
> -#define vasprintf(s, f, a) _IO_vasprintf (s, f, a)
> -#undef __asprintf
>  
>  /* Write formatted output from FORMAT to a string which is
>     allocated with malloc and stored in *STRING_PTR.  */
> @@ -32,7 +28,7 @@ ___asprintf (char **string_ptr, const char *format, ...)
>    int done;
>  
>    va_start (arg, format);
> -  done = vasprintf (string_ptr, format, arg);
> +  done = __vasprintf_internal (string_ptr, format, arg, 0);
>    va_end (arg);
>  
>    return done;

Ok.

> diff --git a/stdio-common/dprintf.c b/stdio-common/dprintf.c
> index 11bd12b838..9adc8ae4c7 100644
> --- a/stdio-common/dprintf.c
> +++ b/stdio-common/dprintf.c
> @@ -16,10 +16,7 @@
>     <http://www.gnu.org/licenses/>.  */
>  
>  #include <stdarg.h>
> -#include <stdio.h>
> -
>  #include <libioP.h>
> -#define vdprintf(d, f, a) _IO_vdprintf (d, f, a)
>  
>  /* Write formatted output to D, according to the format string FORMAT.  */
>  /* VARARGS2 */
> @@ -30,7 +27,7 @@ __dprintf (int d, const char *format, ...)
>    int done;
>  
>    va_start (arg, format);
> -  done = vdprintf (d, format, arg);
> +  done = __vdprintf_internal (d, format, arg, 0);
>    va_end (arg);
>  
>    return done;

Ok.

> diff --git a/stdio-common/fprintf.c b/stdio-common/fprintf.c
> index 2bbf14bf5d..c8f8ac4faf 100644
> --- a/stdio-common/fprintf.c
> +++ b/stdio-common/fprintf.c
> @@ -29,7 +29,7 @@ __fprintf (FILE *stream, const char *format, ...)
>    int done;
>  
>    va_start (arg, format);
> -  done = vfprintf (stream, format, arg);
> +  done = __vfprintf_internal (stream, format, arg, 0);
>    va_end (arg);
>  
>    return done;

Ok.

> diff --git a/stdio-common/fxprintf.c b/stdio-common/fxprintf.c
> index 8d02b71f91..a028e8edd5 100644
> --- a/stdio-common/fxprintf.c
> +++ b/stdio-common/fxprintf.c
> @@ -27,7 +27,7 @@ static int
>  locked_vfxprintf (FILE *fp, const char *fmt, va_list ap)
>  {
>    if (_IO_fwide (fp, 0) <= 0)
> -    return _IO_vfprintf (fp, fmt, ap);
> +    return __vfprintf_internal (fp, fmt, ap, 0);
>  
>    /* We must convert the narrow format string to a wide one.
>       Each byte can produce at most one wide character.  */
> @@ -53,7 +53,7 @@ locked_vfxprintf (FILE *fp, const char *fmt, va_list ap)
>    res = __mbsrtowcs (wfmt, &fmt, len, &mbstate);
>  
>    if (res != -1)
> -    res = _IO_vfwprintf (fp, wfmt, ap);
> +    res = __vfwprintf_internal (fp, wfmt, ap, 0);
>  
>    if (used_malloc)
>      free (wfmt);

Ok.

> diff --git a/stdio-common/printf.c b/stdio-common/printf.c
> index 205b5e42df..ea41dd557c 100644
> --- a/stdio-common/printf.c
> +++ b/stdio-common/printf.c
> @@ -30,7 +30,7 @@ __printf (const char *format, ...)
>    int done;
>  
>    va_start (arg, format);
> -  done = vfprintf (stdout, format, arg);
> +  done = __vfprintf_internal (stdout, format, arg, 0);
>    va_end (arg);
>  
>    return done;
> @@ -38,5 +38,4 @@ __printf (const char *format, ...)
>  
>  #undef _IO_printf
>  ldbl_strong_alias (__printf, printf);
> -/* This is for libg++.  */
>  ldbl_strong_alias (__printf, _IO_printf);

Ok.

> diff --git a/stdio-common/snprintf.c b/stdio-common/snprintf.c
> index 29a169b08b..b75e160ea3 100644
> --- a/stdio-common/snprintf.c
> +++ b/stdio-common/snprintf.c
> @@ -16,9 +16,7 @@
>     <http://www.gnu.org/licenses/>.  */
>  
>  #include <stdarg.h>
> -#include <stdio.h>
>  #include <libioP.h>
> -#define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a)
>  
>  /* Write formatted output into S, according to the format
>     string FORMAT, writing no more than MAXLEN characters.  */
> @@ -30,7 +28,7 @@ __snprintf (char *s, size_t maxlen, const char *format, ...)
>    int done;
>  
>    va_start (arg, format);
> -  done = __vsnprintf (s, maxlen, format, arg);
> +  done = __vsnprintf_internal (s, maxlen, format, arg, 0);
>    va_end (arg);
>  
>    return done;

Ok.

> diff --git a/stdio-common/sprintf.c b/stdio-common/sprintf.c
> index bf5671dde9..77423b292f 100644
> --- a/stdio-common/sprintf.c
> +++ b/stdio-common/sprintf.c
> @@ -16,9 +16,7 @@
>     <http://www.gnu.org/licenses/>.  */
>  
>  #include <stdarg.h>
> -#include <stdio.h>
>  #include <libioP.h>
> -#define vsprintf(s, f, a) _IO_vsprintf (s, f, a)
>  
>  /* Write formatted output into S, according to the format string FORMAT.  */
>  /* VARARGS2 */
> @@ -29,7 +27,7 @@ __sprintf (char *s, const char *format, ...)
>    int done;
>  
>    va_start (arg, format);
> -  done = vsprintf (s, format, arg);
> +  done = __vsprintf_internal (s, format, arg, 0);
>    va_end (arg);
>  
>    return done;

Ok.

> diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf-internal.c
> similarity index 98%
> copy from stdio-common/vfprintf.c
> copy to stdio-common/vfprintf-internal.c
> index ae412e4b84..b0c86e99bd 100644
> --- a/stdio-common/vfprintf.c
> +++ b/stdio-common/vfprintf-internal.c
> @@ -41,6 +41,10 @@
>  
>  #include <libioP.h>
>  
> +#ifdef COMPILE_WPRINTF
> +#include <wctype.h>
> +#endif
> +
>  /* In some cases we need extra space for all the output which is not
>     counted in the width of the string. We assume 32 characters is
>     enough.  */
> @@ -78,7 +82,7 @@
>    } while (0)
>  
>  #ifndef COMPILE_WPRINTF
> -# define vfprintf	_IO_vfprintf_internal
> +# define vfprintf	__vfprintf_internal
>  # define CHAR_T		char
>  # define UCHAR_T	unsigned char
>  # define INT_T		int
> @@ -105,7 +109,7 @@ typedef const char *THOUSANDS_SEP_T;
>  # define ORIENT		if (_IO_vtable_offset (s) == 0 && _IO_fwide (s, -1) != -1)\
>  			  return -1
>  #else
> -# define vfprintf	_IO_vfwprintf
> +# define vfprintf	__vfwprintf_internal
>  # define CHAR_T		wchar_t
>  /* This is a hack!!!  There should be a type uwchar_t.  */
>  # define UCHAR_T	unsigned int /* uwchar_t */
> @@ -747,7 +751,7 @@ static const uint8_t jump_table[] =
>  									      \
>  	if (fspec == NULL)						      \
>  	  {								      \
> -	    if (__ldbl_is_dbl)						      \
> +	    if (__glibc_unlikely ((mode_flags & PRINTF_LDBL_IS_DBL) != 0))    \
>  	      is_long_double = 0;					      \
>  									      \
>  	    struct printf_info info = { .prec = prec,			      \
> @@ -778,7 +782,7 @@ static const uint8_t jump_table[] =
>  	else								      \
>  	  {								      \
>  	    ptr = (const void *) &args_value[fspec->data_arg];		      \
> -	    if (__ldbl_is_dbl)						      \
> +	    if (__glibc_unlikely ((mode_flags & PRINTF_LDBL_IS_DBL) != 0))    \
>  	      {								      \
>  		fspec->data_arg_type = PA_DOUBLE;			      \
>  		fspec->info.is_long_double = 0;				      \
> @@ -808,7 +812,7 @@ static const uint8_t jump_table[] =
>  									      \
>  	if (fspec == NULL)						      \
>  	  {								      \
> -	    if (__ldbl_is_dbl)						      \
> +	    if (__glibc_unlikely ((mode_flags & PRINTF_LDBL_IS_DBL) != 0))    \
>  	      is_long_double = 0;					      \
>  									      \
>  	    struct printf_info info = { .prec = prec,			      \
> @@ -838,7 +842,7 @@ static const uint8_t jump_table[] =
>  	else								      \
>  	  {								      \
>  	    ptr = (const void *) &args_value[fspec->data_arg];		      \
> -	    if (__ldbl_is_dbl)						      \
> +	    if (__glibc_unlikely ((mode_flags & PRINTF_LDBL_IS_DBL) != 0))    \
>  	      fspec->info.is_long_double = 0;				      \
>  	    /* Not supported by *printf functions.  */			      \
>  	    fspec->info.is_binary128 = 0;				      \
> @@ -891,7 +895,7 @@ static const uint8_t jump_table[] =
>        /* NOTREACHED */							      \
>  									      \
>      LABEL (form_number):						      \
> -      if (s->_flags2 & _IO_FLAGS2_FORTIFY)				      \
> +      if ((mode_flags & PRINTF_FORTIFY) != 0)				      \
>  	{								      \
>  	  if (! readonly_format)					      \
>  	    {								      \
> @@ -1214,7 +1218,8 @@ static const uint8_t jump_table[] =
>  #endif
>  
>  /* Helper function to provide temporary buffering for unbuffered streams.  */
> -static int buffered_vfprintf (FILE *stream, const CHAR_T *fmt, va_list)
> +static int buffered_vfprintf (FILE *stream, const CHAR_T *fmt, va_list,
> +			      unsigned int)
>       __THROW __attribute__ ((noinline));
>  
>  /* Handle positional format specifiers.  */
> @@ -1223,7 +1228,9 @@ static int printf_positional (FILE *s,
>  			      va_list ap, va_list *ap_savep, int done,
>  			      int nspecs_done, const UCHAR_T *lead_str_end,
>  			      CHAR_T *work_buffer, int save_errno,
> -			      const char *grouping, THOUSANDS_SEP_T);
> +			      const char *grouping,
> +			      THOUSANDS_SEP_T thousands_sep,
> +			      unsigned int mode_flags);
>  
>  /* Handle unknown format specifier.  */
>  static int printf_unknown (FILE *, const struct printf_info *,
> @@ -1235,7 +1242,7 @@ static CHAR_T *group_number (CHAR_T *, CHAR_T *, CHAR_T *, const char *,
>  
>  /* The function itself.  */
>  int
> -vfprintf (FILE *s, const CHAR_T *format, va_list ap)
> +vfprintf (FILE *s, const CHAR_T *format, va_list ap, unsigned int mode_flags)
>  {
>    /* The character used as thousands separator.  */
>    THOUSANDS_SEP_T thousands_sep = 0;
> @@ -1273,6 +1280,12 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
>       0 if unknown.  */
>    int readonly_format = 0;
>  
> +  /* Temporarily honor environmental settings.  */
> +  if (__ldbl_is_dbl)
> +    mode_flags |= PRINTF_LDBL_IS_DBL;
> +  if (s->_flags2 & _IO_FLAGS2_FORTIFY)
> +    mode_flags |= PRINTF_FORTIFY;
> +
>    /* Orient the stream.  */
>  #ifdef ORIENT
>    ORIENT;
> @@ -1293,7 +1306,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
>    if (UNBUFFERED_P (s))
>      /* Use a helper function which will allocate a local temporary buffer
>         for the stream and then call us again.  */
> -    return buffered_vfprintf (s, format, ap);
> +    return buffered_vfprintf (s, format, ap, mode_flags);
>  
>    /* Initialize local variables.  */
>    done = 0;
> @@ -1682,7 +1695,7 @@ do_positional:
>      }
>    done = printf_positional (s, format, readonly_format, ap, &ap_save,
>  			    done, nspecs_done, lead_str_end, work_buffer,
> -			    save_errno, grouping, thousands_sep);
> +			    save_errno, grouping, thousands_sep, mode_flags);
>  
>   all_done:
>    if (__glibc_unlikely (workstart != NULL))
> @@ -1699,7 +1712,8 @@ printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
>  		   va_list ap, va_list *ap_savep, int done, int nspecs_done,
>  		   const UCHAR_T *lead_str_end,
>  		   CHAR_T *work_buffer, int save_errno,
> -		   const char *grouping, THOUSANDS_SEP_T thousands_sep)
> +		   const char *grouping, THOUSANDS_SEP_T thousands_sep,
> +		   unsigned int mode_flags)
>  {
>    /* For positional argument handling.  */
>    struct scratch_buffer specsbuf;
> @@ -1789,7 +1803,7 @@ printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
>         now.  */
>      args_size = &args_value[nargs].pa_int;
>      args_type = &args_size[nargs];
> -    memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0',
> +    memset (args_type, (mode_flags & PRINTF_FORTIFY) != 0 ? '\xff' : '\0',
>  	    nargs * sizeof (*args_type));
>    }
>  
> @@ -1856,7 +1870,7 @@ printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
>        case PA_FLOAT:				/* Promoted.  */
>  	T (PA_DOUBLE, pa_double, double);
>        case PA_DOUBLE|PA_FLAG_LONG_DOUBLE:
> -	if (__ldbl_is_dbl)
> +	if (__glibc_unlikely ((mode_flags & PRINTF_LDBL_IS_DBL) != 0))
>  	  {
>  	    args_value[cnt].pa_double = va_arg (*ap_savep, double);
>  	    args_type[cnt] &= ~PA_FLAG_LONG_DOUBLE;
> @@ -1884,7 +1898,7 @@ printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
>        case -1:
>  	/* Error case.  Not all parameters appear in N$ format
>  	   strings.  We have no way to determine their type.  */
> -	assert (s->_flags2 & _IO_FLAGS2_FORTIFY);
> +	assert ((mode_flags & PRINTF_FORTIFY) != 0);
>  	__libc_fatal ("*** invalid %N$ use detected ***\n");
>        }
>  
> @@ -2285,7 +2299,8 @@ static const struct _IO_jump_t _IO_helper_jumps libio_vtable =
>  #endif
>  
>  static int
> -buffered_vfprintf (FILE *s, const CHAR_T *format, va_list args)
> +buffered_vfprintf (FILE *s, const CHAR_T *format, va_list args,
> +		   unsigned int mode_flags)
>  {
>    CHAR_T buf[BUFSIZ];
>    struct helper_file helper;
> @@ -2318,11 +2333,7 @@ buffered_vfprintf (FILE *s, const CHAR_T *format, va_list args)
>    _IO_JUMPS (&helper._f) = (struct _IO_jump_t *) &_IO_helper_jumps;
>  
>    /* Now print to helper instead.  */
> -#ifndef COMPILE_WPRINTF
> -  result = _IO_vfprintf (hp, format, args);
> -#else
> -  result = vfprintf (hp, format, args);
> -#endif
> +  result = vfprintf (hp, format, args, mode_flags);
>  
>    /* Lock stream.  */
>    __libc_cleanup_region_start (1, (void (*) (void *)) &_IO_funlockfile, s);
> @@ -2351,14 +2362,3 @@ buffered_vfprintf (FILE *s, const CHAR_T *format, va_list args)
>  
>    return result;
>  }
> -
> -#undef vfprintf
> -#ifdef COMPILE_WPRINTF
> -strong_alias (_IO_vfwprintf, __vfwprintf);
> -ldbl_weak_alias (_IO_vfwprintf, vfwprintf);
> -#else
> -ldbl_strong_alias (_IO_vfprintf_internal, vfprintf);
> -ldbl_hidden_def (_IO_vfprintf_internal, vfprintf)
> -ldbl_strong_alias (_IO_vfprintf_internal, _IO_vfprintf);
> -ldbl_hidden_def (_IO_vfprintf_internal, _IO_vfprintf)
> -#endif

Ok.

> diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
> index ae412e4b84..13a10db99b 100644
> --- a/stdio-common/vfprintf.c
> +++ b/stdio-common/vfprintf.c
> @@ -15,2350 +15,13 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> -#include <array_length.h>
> -#include <ctype.h>
> -#include <limits.h>
> -#include <printf.h>
> -#include <stdarg.h>
> -#include <stdint.h>
> -#include <stdlib.h>
> -#include <string.h>
> -#include <errno.h>
> -#include <wchar.h>
> -#include <libc-lock.h>
> -#include <sys/param.h>
> -#include <_itoa.h>
> -#include <locale/localeinfo.h>
> -#include <stdio.h>
> -#include <scratch_buffer.h>
> +#include <libio/libioP.h>
>  
> -/* This code is shared between the standard stdio implementation found
> -   in GNU C library and the libio implementation originally found in
> -   GNU libg++.
> -
> -   Beside this it is also shared between the normal and wide character
> -   implementation as defined in ISO/IEC 9899:1990/Amendment 1:1995.  */
> -
> -#include <libioP.h>
> -
> -/* In some cases we need extra space for all the output which is not
> -   counted in the width of the string. We assume 32 characters is
> -   enough.  */
> -#define EXTSIZ		32
> -#define ARGCHECK(S, Format) \
> -  do									      \
> -    {									      \
> -      /* Check file argument for consistence.  */			      \
> -      CHECK_FILE (S, -1);						      \
> -      if (S->_flags & _IO_NO_WRITES)					      \
> -	{								      \
> -	  S->_flags |= _IO_ERR_SEEN;					      \
> -	  __set_errno (EBADF);						      \
> -	  return -1;							      \
> -	}								      \
> -      if (Format == NULL)						      \
> -	{								      \
> -	  __set_errno (EINVAL);						      \
> -	  return -1;							      \
> -	}								      \
> -    } while (0)
> -#define UNBUFFERED_P(S) ((S)->_flags & _IO_UNBUFFERED)
> -
> -#define done_add(val) \
> -  do {									      \
> -    unsigned int _val = val;						      \
> -    assert ((unsigned int) done < (unsigned int) INT_MAX);		      \
> -    if (__glibc_unlikely (INT_MAX - done < _val))			      \
> -      {									      \
> -	done = -1;							      \
> -	 __set_errno (EOVERFLOW);					      \
> -	goto all_done;							      \
> -      }									      \
> -    done += _val;							      \
> -  } while (0)
> -
> -#ifndef COMPILE_WPRINTF
> -# define vfprintf	_IO_vfprintf_internal
> -# define CHAR_T		char
> -# define UCHAR_T	unsigned char
> -# define INT_T		int
> -typedef const char *THOUSANDS_SEP_T;
> -# define L_(Str)	Str
> -# define ISDIGIT(Ch)	((unsigned int) ((Ch) - '0') < 10)
> -# define STR_LEN(Str)	strlen (Str)
> -
> -# define PUT(F, S, N)	_IO_sputn ((F), (S), (N))
> -# define PAD(Padchar) \
> -  do {									      \
> -    if (width > 0)							      \
> -      {									      \
> -	ssize_t written = _IO_padn (s, (Padchar), width);		      \
> -	if (__glibc_unlikely (written != width))			      \
> -	  {								      \
> -	    done = -1;							      \
> -	    goto all_done;						      \
> -	  }								      \
> -	done_add (written);						      \
> -      }									      \
> -  } while (0)
> -# define PUTC(C, F)	_IO_putc_unlocked (C, F)
> -# define ORIENT		if (_IO_vtable_offset (s) == 0 && _IO_fwide (s, -1) != -1)\
> -			  return -1
> -#else
> -# define vfprintf	_IO_vfwprintf
> -# define CHAR_T		wchar_t
> -/* This is a hack!!!  There should be a type uwchar_t.  */
> -# define UCHAR_T	unsigned int /* uwchar_t */
> -# define INT_T		wint_t
> -typedef wchar_t THOUSANDS_SEP_T;
> -# define L_(Str)	L##Str
> -# define ISDIGIT(Ch)	((unsigned int) ((Ch) - L'0') < 10)
> -# define STR_LEN(Str)	__wcslen (Str)
> -
> -# include <_itowa.h>
> -
> -# define PUT(F, S, N)	_IO_sputn ((F), (S), (N))
> -# define PAD(Padchar) \
> -  do {									      \
> -    if (width > 0)							      \
> -      {									      \
> -	ssize_t written = _IO_wpadn (s, (Padchar), width);		      \
> -	if (__glibc_unlikely (written != width))			      \
> -	  {								      \
> -	    done = -1;							      \
> -	    goto all_done;						      \
> -	  }								      \
> -	done_add (written);						      \
> -      }									      \
> -  } while (0)
> -# define PUTC(C, F)	_IO_putwc_unlocked (C, F)
> -# define ORIENT		if (_IO_fwide (s, 1) != 1) return -1
> -
> -# undef _itoa
> -# define _itoa(Val, Buf, Base, Case) _itowa (Val, Buf, Base, Case)
> -# define _itoa_word(Val, Buf, Base, Case) _itowa_word (Val, Buf, Base, Case)
> -# undef EOF
> -# define EOF WEOF
> -#endif
> -
> -#include "_i18n_number.h"
> -
> -/* Include the shared code for parsing the format string.  */
> -#include "printf-parse.h"
> -
> -
> -#define	outchar(Ch)							      \
> -  do									      \
> -    {									      \
> -      const INT_T outc = (Ch);						      \
> -      if (PUTC (outc, s) == EOF || done == INT_MAX)			      \
> -	{								      \
> -	  done = -1;							      \
> -	  goto all_done;						      \
> -	}								      \
> -      ++done;								      \
> -    }									      \
> -  while (0)
> -
> -#define outstring(String, Len)						      \
> -  do									      \
> -    {									      \
> -      assert ((size_t) done <= (size_t) INT_MAX);			      \
> -      if ((size_t) PUT (s, (String), (Len)) != (size_t) (Len))		      \
> -	{								      \
> -	  done = -1;							      \
> -	  goto all_done;						      \
> -	}								      \
> -      if (__glibc_unlikely (INT_MAX - done < (Len)))			      \
> -      {									      \
> -	done = -1;							      \
> -	 __set_errno (EOVERFLOW);					      \
> -	goto all_done;							      \
> -      }									      \
> -      done += (Len);							      \
> -    }									      \
> -  while (0)
> -
> -/* For handling long_double and longlong we use the same flag.  If
> -   `long' and `long long' are effectively the same type define it to
> -   zero.  */
> -#if LONG_MAX == LONG_LONG_MAX
> -# define is_longlong 0
> -#else
> -# define is_longlong is_long_double
> -#endif
> -
> -/* If `long' and `int' is effectively the same type we don't have to
> -   handle `long separately.  */
> -#if INT_MAX == LONG_MAX
> -# define is_long_num	0
> -#else
> -# define is_long_num	is_long
> -#endif
> -
> -
> -/* Global constants.  */
> -static const CHAR_T null[] = L_("(null)");
> -
> -/* Size of the work_buffer variable (in characters, not bytes.  */
> -enum { WORK_BUFFER_SIZE = 1000 / sizeof (CHAR_T) };
> -
> -/* This table maps a character into a number representing a class.  In
> -   each step there is a destination label for each class.  */
> -static const uint8_t jump_table[] =
> -  {
> -    /* ' ' */  1,            0,            0, /* '#' */  4,
> -	       0, /* '%' */ 14,            0, /* '\''*/  6,
> -	       0,            0, /* '*' */  7, /* '+' */  2,
> -	       0, /* '-' */  3, /* '.' */  9,            0,
> -    /* '0' */  5, /* '1' */  8, /* '2' */  8, /* '3' */  8,
> -    /* '4' */  8, /* '5' */  8, /* '6' */  8, /* '7' */  8,
> -    /* '8' */  8, /* '9' */  8,            0,            0,
> -	       0,            0,            0,            0,
> -	       0, /* 'A' */ 26,            0, /* 'C' */ 25,
> -	       0, /* 'E' */ 19, /* F */   19, /* 'G' */ 19,
> -	       0, /* 'I' */ 29,            0,            0,
> -    /* 'L' */ 12,            0,            0,            0,
> -	       0,            0,            0, /* 'S' */ 21,
> -	       0,            0,            0,            0,
> -    /* 'X' */ 18,            0, /* 'Z' */ 13,            0,
> -	       0,            0,            0,            0,
> -	       0, /* 'a' */ 26,            0, /* 'c' */ 20,
> -    /* 'd' */ 15, /* 'e' */ 19, /* 'f' */ 19, /* 'g' */ 19,
> -    /* 'h' */ 10, /* 'i' */ 15, /* 'j' */ 28,            0,
> -    /* 'l' */ 11, /* 'm' */ 24, /* 'n' */ 23, /* 'o' */ 17,
> -    /* 'p' */ 22, /* 'q' */ 12,            0, /* 's' */ 21,
> -    /* 't' */ 27, /* 'u' */ 16,            0,            0,
> -    /* 'x' */ 18,            0, /* 'z' */ 13
> -  };
> -
> -#define NOT_IN_JUMP_RANGE(Ch) ((Ch) < L_(' ') || (Ch) > L_('z'))
> -#define CHAR_CLASS(Ch) (jump_table[(INT_T) (Ch) - L_(' ')])
> -#define LABEL(Name) do_##Name
> -#ifdef SHARED
> -  /* 'int' is enough and it saves some space on 64 bit systems.  */
> -# define JUMP_TABLE_TYPE const int
> -# define JUMP_TABLE_BASE_LABEL do_form_unknown
> -# define REF(Name) &&do_##Name - &&JUMP_TABLE_BASE_LABEL
> -# define JUMP(ChExpr, table)						      \
> -      do								      \
> -	{								      \
> -	  int offset;							      \
> -	  void *ptr;							      \
> -	  spec = (ChExpr);						      \
> -	  offset = NOT_IN_JUMP_RANGE (spec) ? REF (form_unknown)	      \
> -	    : table[CHAR_CLASS (spec)];					      \
> -	  ptr = &&JUMP_TABLE_BASE_LABEL + offset;			      \
> -	  goto *ptr;							      \
> -	}								      \
> -      while (0)
> -#else
> -# define JUMP_TABLE_TYPE const void *const
> -# define REF(Name) &&do_##Name
> -# define JUMP(ChExpr, table)						      \
> -      do								      \
> -	{								      \
> -	  const void *ptr;						      \
> -	  spec = (ChExpr);						      \
> -	  ptr = NOT_IN_JUMP_RANGE (spec) ? REF (form_unknown)		      \
> -	    : table[CHAR_CLASS (spec)];					      \
> -	  goto *ptr;							      \
> -	}								      \
> -      while (0)
> -#endif
> -
> -#define STEP0_3_TABLE							      \
> -    /* Step 0: at the beginning.  */					      \
> -    static JUMP_TABLE_TYPE step0_jumps[30] =				      \
> -    {									      \
> -      REF (form_unknown),						      \
> -      REF (flag_space),		/* for ' ' */				      \
> -      REF (flag_plus),		/* for '+' */				      \
> -      REF (flag_minus),		/* for '-' */				      \
> -      REF (flag_hash),		/* for '<hash>' */			      \
> -      REF (flag_zero),		/* for '0' */				      \
> -      REF (flag_quote),		/* for '\'' */				      \
> -      REF (width_asterics),	/* for '*' */				      \
> -      REF (width),		/* for '1'...'9' */			      \
> -      REF (precision),		/* for '.' */				      \
> -      REF (mod_half),		/* for 'h' */				      \
> -      REF (mod_long),		/* for 'l' */				      \
> -      REF (mod_longlong),	/* for 'L', 'q' */			      \
> -      REF (mod_size_t),		/* for 'z', 'Z' */			      \
> -      REF (form_percent),	/* for '%' */				      \
> -      REF (form_integer),	/* for 'd', 'i' */			      \
> -      REF (form_unsigned),	/* for 'u' */				      \
> -      REF (form_octal),		/* for 'o' */				      \
> -      REF (form_hexa),		/* for 'X', 'x' */			      \
> -      REF (form_float),		/* for 'E', 'e', 'F', 'f', 'G', 'g' */	      \
> -      REF (form_character),	/* for 'c' */				      \
> -      REF (form_string),	/* for 's', 'S' */			      \
> -      REF (form_pointer),	/* for 'p' */				      \
> -      REF (form_number),	/* for 'n' */				      \
> -      REF (form_strerror),	/* for 'm' */				      \
> -      REF (form_wcharacter),	/* for 'C' */				      \
> -      REF (form_floathex),	/* for 'A', 'a' */			      \
> -      REF (mod_ptrdiff_t),      /* for 't' */				      \
> -      REF (mod_intmax_t),       /* for 'j' */				      \
> -      REF (flag_i18n),		/* for 'I' */				      \
> -    };									      \
> -    /* Step 1: after processing width.  */				      \
> -    static JUMP_TABLE_TYPE step1_jumps[30] =				      \
> -    {									      \
> -      REF (form_unknown),						      \
> -      REF (form_unknown),	/* for ' ' */				      \
> -      REF (form_unknown),	/* for '+' */				      \
> -      REF (form_unknown),	/* for '-' */				      \
> -      REF (form_unknown),	/* for '<hash>' */			      \
> -      REF (form_unknown),	/* for '0' */				      \
> -      REF (form_unknown),	/* for '\'' */				      \
> -      REF (form_unknown),	/* for '*' */				      \
> -      REF (form_unknown),	/* for '1'...'9' */			      \
> -      REF (precision),		/* for '.' */				      \
> -      REF (mod_half),		/* for 'h' */				      \
> -      REF (mod_long),		/* for 'l' */				      \
> -      REF (mod_longlong),	/* for 'L', 'q' */			      \
> -      REF (mod_size_t),		/* for 'z', 'Z' */			      \
> -      REF (form_percent),	/* for '%' */				      \
> -      REF (form_integer),	/* for 'd', 'i' */			      \
> -      REF (form_unsigned),	/* for 'u' */				      \
> -      REF (form_octal),		/* for 'o' */				      \
> -      REF (form_hexa),		/* for 'X', 'x' */			      \
> -      REF (form_float),		/* for 'E', 'e', 'F', 'f', 'G', 'g' */	      \
> -      REF (form_character),	/* for 'c' */				      \
> -      REF (form_string),	/* for 's', 'S' */			      \
> -      REF (form_pointer),	/* for 'p' */				      \
> -      REF (form_number),	/* for 'n' */				      \
> -      REF (form_strerror),	/* for 'm' */				      \
> -      REF (form_wcharacter),	/* for 'C' */				      \
> -      REF (form_floathex),	/* for 'A', 'a' */			      \
> -      REF (mod_ptrdiff_t),      /* for 't' */				      \
> -      REF (mod_intmax_t),       /* for 'j' */				      \
> -      REF (form_unknown)        /* for 'I' */				      \
> -    };									      \
> -    /* Step 2: after processing precision.  */				      \
> -    static JUMP_TABLE_TYPE step2_jumps[30] =				      \
> -    {									      \
> -      REF (form_unknown),						      \
> -      REF (form_unknown),	/* for ' ' */				      \
> -      REF (form_unknown),	/* for '+' */				      \
> -      REF (form_unknown),	/* for '-' */				      \
> -      REF (form_unknown),	/* for '<hash>' */			      \
> -      REF (form_unknown),	/* for '0' */				      \
> -      REF (form_unknown),	/* for '\'' */				      \
> -      REF (form_unknown),	/* for '*' */				      \
> -      REF (form_unknown),	/* for '1'...'9' */			      \
> -      REF (form_unknown),	/* for '.' */				      \
> -      REF (mod_half),		/* for 'h' */				      \
> -      REF (mod_long),		/* for 'l' */				      \
> -      REF (mod_longlong),	/* for 'L', 'q' */			      \
> -      REF (mod_size_t),		/* for 'z', 'Z' */			      \
> -      REF (form_percent),	/* for '%' */				      \
> -      REF (form_integer),	/* for 'd', 'i' */			      \
> -      REF (form_unsigned),	/* for 'u' */				      \
> -      REF (form_octal),		/* for 'o' */				      \
> -      REF (form_hexa),		/* for 'X', 'x' */			      \
> -      REF (form_float),		/* for 'E', 'e', 'F', 'f', 'G', 'g' */	      \
> -      REF (form_character),	/* for 'c' */				      \
> -      REF (form_string),	/* for 's', 'S' */			      \
> -      REF (form_pointer),	/* for 'p' */				      \
> -      REF (form_number),	/* for 'n' */				      \
> -      REF (form_strerror),	/* for 'm' */				      \
> -      REF (form_wcharacter),	/* for 'C' */				      \
> -      REF (form_floathex),	/* for 'A', 'a' */			      \
> -      REF (mod_ptrdiff_t),      /* for 't' */				      \
> -      REF (mod_intmax_t),       /* for 'j' */				      \
> -      REF (form_unknown)        /* for 'I' */				      \
> -    };									      \
> -    /* Step 3a: after processing first 'h' modifier.  */		      \
> -    static JUMP_TABLE_TYPE step3a_jumps[30] =				      \
> -    {									      \
> -      REF (form_unknown),						      \
> -      REF (form_unknown),	/* for ' ' */				      \
> -      REF (form_unknown),	/* for '+' */				      \
> -      REF (form_unknown),	/* for '-' */				      \
> -      REF (form_unknown),	/* for '<hash>' */			      \
> -      REF (form_unknown),	/* for '0' */				      \
> -      REF (form_unknown),	/* for '\'' */				      \
> -      REF (form_unknown),	/* for '*' */				      \
> -      REF (form_unknown),	/* for '1'...'9' */			      \
> -      REF (form_unknown),	/* for '.' */				      \
> -      REF (mod_halfhalf),	/* for 'h' */				      \
> -      REF (form_unknown),	/* for 'l' */				      \
> -      REF (form_unknown),	/* for 'L', 'q' */			      \
> -      REF (form_unknown),	/* for 'z', 'Z' */			      \
> -      REF (form_percent),	/* for '%' */				      \
> -      REF (form_integer),	/* for 'd', 'i' */			      \
> -      REF (form_unsigned),	/* for 'u' */				      \
> -      REF (form_octal),		/* for 'o' */				      \
> -      REF (form_hexa),		/* for 'X', 'x' */			      \
> -      REF (form_unknown),	/* for 'E', 'e', 'F', 'f', 'G', 'g' */	      \
> -      REF (form_unknown),	/* for 'c' */				      \
> -      REF (form_unknown),	/* for 's', 'S' */			      \
> -      REF (form_unknown),	/* for 'p' */				      \
> -      REF (form_number),	/* for 'n' */				      \
> -      REF (form_unknown),	/* for 'm' */				      \
> -      REF (form_unknown),	/* for 'C' */				      \
> -      REF (form_unknown),	/* for 'A', 'a' */			      \
> -      REF (form_unknown),       /* for 't' */				      \
> -      REF (form_unknown),       /* for 'j' */				      \
> -      REF (form_unknown)        /* for 'I' */				      \
> -    };									      \
> -    /* Step 3b: after processing first 'l' modifier.  */		      \
> -    static JUMP_TABLE_TYPE step3b_jumps[30] =				      \
> -    {									      \
> -      REF (form_unknown),						      \
> -      REF (form_unknown),	/* for ' ' */				      \
> -      REF (form_unknown),	/* for '+' */				      \
> -      REF (form_unknown),	/* for '-' */				      \
> -      REF (form_unknown),	/* for '<hash>' */			      \
> -      REF (form_unknown),	/* for '0' */				      \
> -      REF (form_unknown),	/* for '\'' */				      \
> -      REF (form_unknown),	/* for '*' */				      \
> -      REF (form_unknown),	/* for '1'...'9' */			      \
> -      REF (form_unknown),	/* for '.' */				      \
> -      REF (form_unknown),	/* for 'h' */				      \
> -      REF (mod_longlong),	/* for 'l' */				      \
> -      REF (form_unknown),	/* for 'L', 'q' */			      \
> -      REF (form_unknown),	/* for 'z', 'Z' */			      \
> -      REF (form_percent),	/* for '%' */				      \
> -      REF (form_integer),	/* for 'd', 'i' */			      \
> -      REF (form_unsigned),	/* for 'u' */				      \
> -      REF (form_octal),		/* for 'o' */				      \
> -      REF (form_hexa),		/* for 'X', 'x' */			      \
> -      REF (form_float),		/* for 'E', 'e', 'F', 'f', 'G', 'g' */	      \
> -      REF (form_character),	/* for 'c' */				      \
> -      REF (form_string),	/* for 's', 'S' */			      \
> -      REF (form_pointer),	/* for 'p' */				      \
> -      REF (form_number),	/* for 'n' */				      \
> -      REF (form_strerror),	/* for 'm' */				      \
> -      REF (form_wcharacter),	/* for 'C' */				      \
> -      REF (form_floathex),	/* for 'A', 'a' */			      \
> -      REF (form_unknown),       /* for 't' */				      \
> -      REF (form_unknown),       /* for 'j' */				      \
> -      REF (form_unknown)        /* for 'I' */				      \
> -    }
> -
> -#define STEP4_TABLE							      \
> -    /* Step 4: processing format specifier.  */				      \
> -    static JUMP_TABLE_TYPE step4_jumps[30] =				      \
> -    {									      \
> -      REF (form_unknown),						      \
> -      REF (form_unknown),	/* for ' ' */				      \
> -      REF (form_unknown),	/* for '+' */				      \
> -      REF (form_unknown),	/* for '-' */				      \
> -      REF (form_unknown),	/* for '<hash>' */			      \
> -      REF (form_unknown),	/* for '0' */				      \
> -      REF (form_unknown),	/* for '\'' */				      \
> -      REF (form_unknown),	/* for '*' */				      \
> -      REF (form_unknown),	/* for '1'...'9' */			      \
> -      REF (form_unknown),	/* for '.' */				      \
> -      REF (form_unknown),	/* for 'h' */				      \
> -      REF (form_unknown),	/* for 'l' */				      \
> -      REF (form_unknown),	/* for 'L', 'q' */			      \
> -      REF (form_unknown),	/* for 'z', 'Z' */			      \
> -      REF (form_percent),	/* for '%' */				      \
> -      REF (form_integer),	/* for 'd', 'i' */			      \
> -      REF (form_unsigned),	/* for 'u' */				      \
> -      REF (form_octal),		/* for 'o' */				      \
> -      REF (form_hexa),		/* for 'X', 'x' */			      \
> -      REF (form_float),		/* for 'E', 'e', 'F', 'f', 'G', 'g' */	      \
> -      REF (form_character),	/* for 'c' */				      \
> -      REF (form_string),	/* for 's', 'S' */			      \
> -      REF (form_pointer),	/* for 'p' */				      \
> -      REF (form_number),	/* for 'n' */				      \
> -      REF (form_strerror),	/* for 'm' */				      \
> -      REF (form_wcharacter),	/* for 'C' */				      \
> -      REF (form_floathex),	/* for 'A', 'a' */			      \
> -      REF (form_unknown),       /* for 't' */				      \
> -      REF (form_unknown),       /* for 'j' */				      \
> -      REF (form_unknown)        /* for 'I' */				      \
> -    }
> -
> -
> -#define process_arg(fspec)						      \
> -      /* Start real work.  We know about all flags and modifiers and	      \
> -	 now process the wanted format specifier.  */			      \
> -    LABEL (form_percent):						      \
> -      /* Write a literal "%".  */					      \
> -      outchar (L_('%'));						      \
> -      break;								      \
> -									      \
> -    LABEL (form_integer):						      \
> -      /* Signed decimal integer.  */					      \
> -      base = 10;							      \
> -									      \
> -      if (is_longlong)							      \
> -	{								      \
> -	  long long int signed_number;					      \
> -									      \
> -	  if (fspec == NULL)						      \
> -	    signed_number = va_arg (ap, long long int);			      \
> -	  else								      \
> -	    signed_number = args_value[fspec->data_arg].pa_long_long_int;     \
> -									      \
> -	  is_negative = signed_number < 0;				      \
> -	  number.longlong = is_negative ? (- signed_number) : signed_number;  \
> -									      \
> -	  goto LABEL (longlong_number);					      \
> -	}								      \
> -      else								      \
> -	{								      \
> -	  long int signed_number;					      \
> -									      \
> -	  if (fspec == NULL)						      \
> -	    {								      \
> -	      if (is_long_num)						      \
> -		signed_number = va_arg (ap, long int);			      \
> -	      else if (is_char)						      \
> -		signed_number = (signed char) va_arg (ap, unsigned int);      \
> -	      else if (!is_short)					      \
> -		signed_number = va_arg (ap, int);			      \
> -	      else							      \
> -		signed_number = (short int) va_arg (ap, unsigned int);	      \
> -	    }								      \
> -	  else								      \
> -	    if (is_long_num)						      \
> -	      signed_number = args_value[fspec->data_arg].pa_long_int;	      \
> -	    else if (is_char)						      \
> -	      signed_number = (signed char)				      \
> -		args_value[fspec->data_arg].pa_u_int;			      \
> -	    else if (!is_short)						      \
> -	      signed_number = args_value[fspec->data_arg].pa_int;	      \
> -	    else							      \
> -	      signed_number = (short int)				      \
> -		args_value[fspec->data_arg].pa_u_int;			      \
> -									      \
> -	  is_negative = signed_number < 0;				      \
> -	  number.word = is_negative ? (- signed_number) : signed_number;      \
> -									      \
> -	  goto LABEL (number);						      \
> -	}								      \
> -      /* NOTREACHED */							      \
> -									      \
> -    LABEL (form_unsigned):						      \
> -      /* Unsigned decimal integer.  */					      \
> -      base = 10;							      \
> -      goto LABEL (unsigned_number);					      \
> -      /* NOTREACHED */							      \
> -									      \
> -    LABEL (form_octal):							      \
> -      /* Unsigned octal integer.  */					      \
> -      base = 8;								      \
> -      goto LABEL (unsigned_number);					      \
> -      /* NOTREACHED */							      \
> -									      \
> -    LABEL (form_hexa):							      \
> -      /* Unsigned hexadecimal integer.  */				      \
> -      base = 16;							      \
> -									      \
> -    LABEL (unsigned_number):	  /* Unsigned number of base BASE.  */	      \
> -									      \
> -      /* ISO specifies the `+' and ` ' flags only for signed		      \
> -	 conversions.  */						      \
> -      is_negative = 0;							      \
> -      showsign = 0;							      \
> -      space = 0;							      \
> -									      \
> -      if (is_longlong)							      \
> -	{								      \
> -	  if (fspec == NULL)						      \
> -	    number.longlong = va_arg (ap, unsigned long long int);	      \
> -	  else								      \
> -	    number.longlong = args_value[fspec->data_arg].pa_u_long_long_int; \
> -									      \
> -	LABEL (longlong_number):					      \
> -	  if (prec < 0)							      \
> -	    /* Supply a default precision if none was given.  */	      \
> -	    prec = 1;							      \
> -	  else								      \
> -	    /* We have to take care for the '0' flag.  If a precision	      \
> -	       is given it must be ignored.  */				      \
> -	    pad = L_(' ');						      \
> -									      \
> -	  /* If the precision is 0 and the number is 0 nothing has to	      \
> -	     be written for the number, except for the 'o' format in	      \
> -	     alternate form.  */					      \
> -	  if (prec == 0 && number.longlong == 0)			      \
> -	    {								      \
> -	      string = workend;						      \
> -	      if (base == 8 && alt)					      \
> -		*--string = L_('0');					      \
> -	    }								      \
> -	  else								      \
> -	    {								      \
> -	      /* Put the number in WORK.  */				      \
> -	      string = _itoa (number.longlong, workend, base,		      \
> -			      spec == L_('X'));				      \
> -	      if (group && grouping)					      \
> -		string = group_number (work_buffer, string, workend,	      \
> -				       grouping, thousands_sep);	      \
> -	      if (use_outdigits && base == 10)				      \
> -		string = _i18n_number_rewrite (string, workend, workend);     \
> -	    }								      \
> -	  /* Simplify further test for num != 0.  */			      \
> -	  number.word = number.longlong != 0;				      \
> -	}								      \
> -      else								      \
> -	{								      \
> -	  if (fspec == NULL)						      \
> -	    {								      \
> -	      if (is_long_num)						      \
> -		number.word = va_arg (ap, unsigned long int);		      \
> -	      else if (is_char)						      \
> -		number.word = (unsigned char) va_arg (ap, unsigned int);      \
> -	      else if (!is_short)					      \
> -		number.word = va_arg (ap, unsigned int);		      \
> -	      else							      \
> -		number.word = (unsigned short int) va_arg (ap, unsigned int); \
> -	    }								      \
> -	  else								      \
> -	    if (is_long_num)						      \
> -	      number.word = args_value[fspec->data_arg].pa_u_long_int;	      \
> -	    else if (is_char)						      \
> -	      number.word = (unsigned char)				      \
> -		args_value[fspec->data_arg].pa_u_int;			      \
> -	    else if (!is_short)						      \
> -	      number.word = args_value[fspec->data_arg].pa_u_int;	      \
> -	    else							      \
> -	      number.word = (unsigned short int)			      \
> -		args_value[fspec->data_arg].pa_u_int;			      \
> -									      \
> -	LABEL (number):							      \
> -	  if (prec < 0)							      \
> -	    /* Supply a default precision if none was given.  */	      \
> -	    prec = 1;							      \
> -	  else								      \
> -	    /* We have to take care for the '0' flag.  If a precision	      \
> -	       is given it must be ignored.  */				      \
> -	    pad = L_(' ');						      \
> -									      \
> -	  /* If the precision is 0 and the number is 0 nothing has to	      \
> -	     be written for the number, except for the 'o' format in	      \
> -	     alternate form.  */					      \
> -	  if (prec == 0 && number.word == 0)				      \
> -	    {								      \
> -	      string = workend;						      \
> -	      if (base == 8 && alt)					      \
> -		*--string = L_('0');					      \
> -	    }								      \
> -	  else								      \
> -	    {								      \
> -	      /* Put the number in WORK.  */				      \
> -	      string = _itoa_word (number.word, workend, base,		      \
> -				   spec == L_('X'));			      \
> -	      if (group && grouping)					      \
> -		string = group_number (work_buffer, string, workend,	      \
> -				       grouping, thousands_sep);	      \
> -	      if (use_outdigits && base == 10)				      \
> -		string = _i18n_number_rewrite (string, workend, workend);     \
> -	    }								      \
> -	}								      \
> -									      \
> -      if (prec <= workend - string && number.word != 0 && alt && base == 8)   \
> -	/* Add octal marker.  */					      \
> -	*--string = L_('0');						      \
> -									      \
> -      prec = MAX (0, prec - (workend - string));			      \
> -									      \
> -      if (!left)							      \
> -	{								      \
> -	  width -= workend - string + prec;				      \
> -									      \
> -	  if (number.word != 0 && alt && base == 16)			      \
> -	    /* Account for 0X hex marker.  */				      \
> -	    width -= 2;							      \
> -									      \
> -	  if (is_negative || showsign || space)				      \
> -	    --width;							      \
> -									      \
> -	  if (pad == L_(' '))						      \
> -	    {								      \
> -	      PAD (L_(' '));						      \
> -	      width = 0;						      \
> -	    }								      \
> -									      \
> -	  if (is_negative)						      \
> -	    outchar (L_('-'));						      \
> -	  else if (showsign)						      \
> -	    outchar (L_('+'));						      \
> -	  else if (space)						      \
> -	    outchar (L_(' '));						      \
> -									      \
> -	  if (number.word != 0 && alt && base == 16)			      \
> -	    {								      \
> -	      outchar (L_('0'));					      \
> -	      outchar (spec);						      \
> -	    }								      \
> -									      \
> -	  width += prec;						      \
> -	  PAD (L_('0'));						      \
> -									      \
> -	  outstring (string, workend - string);				      \
> -									      \
> -	  break;							      \
> -	}								      \
> -      else								      \
> -	{								      \
> -	  if (is_negative)						      \
> -	    {								      \
> -	      outchar (L_('-'));					      \
> -	      --width;							      \
> -	    }								      \
> -	  else if (showsign)						      \
> -	    {								      \
> -	      outchar (L_('+'));					      \
> -	      --width;							      \
> -	    }								      \
> -	  else if (space)						      \
> -	    {								      \
> -	      outchar (L_(' '));					      \
> -	      --width;							      \
> -	    }								      \
> -									      \
> -	  if (number.word != 0 && alt && base == 16)			      \
> -	    {								      \
> -	      outchar (L_('0'));					      \
> -	      outchar (spec);						      \
> -	      width -= 2;						      \
> -	    }								      \
> -									      \
> -	  width -= workend - string + prec;				      \
> -									      \
> -	  if (prec > 0)							      \
> -	    {								      \
> -	      int temp = width;						      \
> -	      width = prec;						      \
> -	      PAD (L_('0'));						      \
> -	      width = temp;						      \
> -	    }								      \
> -									      \
> -	  outstring (string, workend - string);				      \
> -									      \
> -	  PAD (L_(' '));						      \
> -	  break;							      \
> -	}								      \
> -									      \
> -    LABEL (form_float):							      \
> -      {									      \
> -	/* Floating-point number.  This is handled by printf_fp.c.  */	      \
> -	const void *ptr;						      \
> -	int function_done;						      \
> -									      \
> -	if (fspec == NULL)						      \
> -	  {								      \
> -	    if (__ldbl_is_dbl)						      \
> -	      is_long_double = 0;					      \
> -									      \
> -	    struct printf_info info = { .prec = prec,			      \
> -					.width = width,			      \
> -					.spec = spec,			      \
> -					.is_long_double = is_long_double,     \
> -					.is_short = is_short,		      \
> -					.is_long = is_long,		      \
> -					.alt = alt,			      \
> -					.space = space,			      \
> -					.left = left,			      \
> -					.showsign = showsign,		      \
> -					.group = group,			      \
> -					.pad = pad,			      \
> -					.extra = 0,			      \
> -					.i18n = use_outdigits,		      \
> -					.wide = sizeof (CHAR_T) != 1,	      \
> -					.is_binary128 = 0};		      \
> -									      \
> -	    if (is_long_double)						      \
> -	      the_arg.pa_long_double = va_arg (ap, long double);	      \
> -	    else							      \
> -	      the_arg.pa_double = va_arg (ap, double);			      \
> -	    ptr = (const void *) &the_arg;				      \
> -									      \
> -	    function_done = __printf_fp (s, &info, &ptr);		      \
> -	  }								      \
> -	else								      \
> -	  {								      \
> -	    ptr = (const void *) &args_value[fspec->data_arg];		      \
> -	    if (__ldbl_is_dbl)						      \
> -	      {								      \
> -		fspec->data_arg_type = PA_DOUBLE;			      \
> -		fspec->info.is_long_double = 0;				      \
> -	      }								      \
> -	    /* Not supported by *printf functions.  */			      \
> -	    fspec->info.is_binary128 = 0;				      \
> -									      \
> -	    function_done = __printf_fp (s, &fspec->info, &ptr);	      \
> -	  }								      \
> -									      \
> -	if (function_done < 0)						      \
> -	  {								      \
> -	    /* Error in print handler; up to handler to set errno.  */	      \
> -	    done = -1;							      \
> -	    goto all_done;						      \
> -	  }								      \
> -									      \
> -	done_add (function_done);					      \
> -      }									      \
> -      break;								      \
> -									      \
> -    LABEL (form_floathex):						      \
> -      {									      \
> -	/* Floating point number printed as hexadecimal number.  */	      \
> -	const void *ptr;						      \
> -	int function_done;						      \
> -									      \
> -	if (fspec == NULL)						      \
> -	  {								      \
> -	    if (__ldbl_is_dbl)						      \
> -	      is_long_double = 0;					      \
> -									      \
> -	    struct printf_info info = { .prec = prec,			      \
> -					.width = width,			      \
> -					.spec = spec,			      \
> -					.is_long_double = is_long_double,     \
> -					.is_short = is_short,		      \
> -					.is_long = is_long,		      \
> -					.alt = alt,			      \
> -					.space = space,			      \
> -					.left = left,			      \
> -					.showsign = showsign,		      \
> -					.group = group,			      \
> -					.pad = pad,			      \
> -					.extra = 0,			      \
> -					.wide = sizeof (CHAR_T) != 1,	      \
> -					.is_binary128 = 0};		      \
> -									      \
> -	    if (is_long_double)						      \
> -	      the_arg.pa_long_double = va_arg (ap, long double);	      \
> -	    else							      \
> -	      the_arg.pa_double = va_arg (ap, double);			      \
> -	    ptr = (const void *) &the_arg;				      \
> -									      \
> -	    function_done = __printf_fphex (s, &info, &ptr);		      \
> -	  }								      \
> -	else								      \
> -	  {								      \
> -	    ptr = (const void *) &args_value[fspec->data_arg];		      \
> -	    if (__ldbl_is_dbl)						      \
> -	      fspec->info.is_long_double = 0;				      \
> -	    /* Not supported by *printf functions.  */			      \
> -	    fspec->info.is_binary128 = 0;				      \
> -									      \
> -	    function_done = __printf_fphex (s, &fspec->info, &ptr);	      \
> -	  }								      \
> -									      \
> -	if (function_done < 0)						      \
> -	  {								      \
> -	    /* Error in print handler; up to handler to set errno.  */	      \
> -	    done = -1;							      \
> -	    goto all_done;						      \
> -	  }								      \
> -									      \
> -	done_add (function_done);					      \
> -      }									      \
> -      break;								      \
> -									      \
> -    LABEL (form_pointer):						      \
> -      /* Generic pointer.  */						      \
> -      {									      \
> -	const void *ptr;						      \
> -	if (fspec == NULL)						      \
> -	  ptr = va_arg (ap, void *);					      \
> -	else								      \
> -	  ptr = args_value[fspec->data_arg].pa_pointer;			      \
> -	if (ptr != NULL)						      \
> -	  {								      \
> -	    /* If the pointer is not NULL, write it as a %#x spec.  */	      \
> -	    base = 16;							      \
> -	    number.word = (unsigned long int) ptr;			      \
> -	    is_negative = 0;						      \
> -	    alt = 1;							      \
> -	    group = 0;							      \
> -	    spec = L_('x');						      \
> -	    goto LABEL (number);					      \
> -	  }								      \
> -	else								      \
> -	  {								      \
> -	    /* Write "(nil)" for a nil pointer.  */			      \
> -	    string = (CHAR_T *) L_("(nil)");				      \
> -	    /* Make sure the full string "(nil)" is printed.  */	      \
> -	    if (prec < 5)						      \
> -	      prec = 5;							      \
> -	    /* This is a wide string iff compiling wprintf.  */		      \
> -	    is_long = sizeof (CHAR_T) > 1;				      \
> -	    goto LABEL (print_string);					      \
> -	  }								      \
> -      }									      \
> -      /* NOTREACHED */							      \
> -									      \
> -    LABEL (form_number):						      \
> -      if (s->_flags2 & _IO_FLAGS2_FORTIFY)				      \
> -	{								      \
> -	  if (! readonly_format)					      \
> -	    {								      \
> -	      extern int __readonly_area (const void *, size_t)		      \
> -		attribute_hidden;					      \
> -	      readonly_format						      \
> -		= __readonly_area (format, ((STR_LEN (format) + 1)	      \
> -					    * sizeof (CHAR_T)));	      \
> -	    }								      \
> -	  if (readonly_format < 0)					      \
> -	    __libc_fatal ("*** %n in writable segment detected ***\n");	      \
> -	}								      \
> -      /* Answer the count of characters written.  */			      \
> -      if (fspec == NULL)						      \
> -	{								      \
> -	  if (is_longlong)						      \
> -	    *(long long int *) va_arg (ap, void *) = done;		      \
> -	  else if (is_long_num)						      \
> -	    *(long int *) va_arg (ap, void *) = done;			      \
> -	  else if (is_char)						      \
> -	    *(char *) va_arg (ap, void *) = done;			      \
> -	  else if (!is_short)						      \
> -	    *(int *) va_arg (ap, void *) = done;			      \
> -	  else								      \
> -	    *(short int *) va_arg (ap, void *) = done;			      \
> -	}								      \
> -      else								      \
> -	if (is_longlong)						      \
> -	  *(long long int *) args_value[fspec->data_arg].pa_pointer = done;   \
> -	else if (is_long_num)						      \
> -	  *(long int *) args_value[fspec->data_arg].pa_pointer = done;	      \
> -	else if (is_char)						      \
> -	  *(char *) args_value[fspec->data_arg].pa_pointer = done;	      \
> -	else if (!is_short)						      \
> -	  *(int *) args_value[fspec->data_arg].pa_pointer = done;	      \
> -	else								      \
> -	  *(short int *) args_value[fspec->data_arg].pa_pointer = done;	      \
> -      break;								      \
> -									      \
> -    LABEL (form_strerror):						      \
> -      /* Print description of error ERRNO.  */				      \
> -      string =								      \
> -	(CHAR_T *) __strerror_r (save_errno, (char *) work_buffer,	      \
> -				 WORK_BUFFER_SIZE * sizeof (CHAR_T));	      \
> -      is_long = 0;		/* This is no wide-char string.  */	      \
> -      goto LABEL (print_string)
> -
> -#ifdef COMPILE_WPRINTF
> -# define process_string_arg(fspec) \
> -    LABEL (form_character):						      \
> -      /* Character.  */							      \
> -      if (is_long)							      \
> -	goto LABEL (form_wcharacter);					      \
> -      --width;	/* Account for the character itself.  */		      \
> -      if (!left)							      \
> -	PAD (L' ');							      \
> -      if (fspec == NULL)						      \
> -	outchar (__btowc ((unsigned char) va_arg (ap, int))); /* Promoted. */ \
> -      else								      \
> -	outchar (__btowc ((unsigned char)				      \
> -			  args_value[fspec->data_arg].pa_int));		      \
> -      if (left)								      \
> -	PAD (L' ');							      \
> -      break;								      \
> -									      \
> -    LABEL (form_wcharacter):						      \
> -      {									      \
> -	/* Wide character.  */						      \
> -	--width;							      \
> -	if (!left)							      \
> -	  PAD (L' ');							      \
> -	if (fspec == NULL)						      \
> -	  outchar (va_arg (ap, wchar_t));				      \
> -	else								      \
> -	  outchar (args_value[fspec->data_arg].pa_wchar);		      \
> -	if (left)							      \
> -	  PAD (L' ');							      \
> -      }									      \
> -      break;								      \
> -									      \
> -    LABEL (form_string):						      \
> -      {									      \
> -	size_t len;							      \
> -	int string_malloced;						      \
> -									      \
> -	/* The string argument could in fact be `char *' or `wchar_t *'.      \
> -	   But this should not make a difference here.  */		      \
> -	if (fspec == NULL)						      \
> -	  string = (CHAR_T *) va_arg (ap, const wchar_t *);		      \
> -	else								      \
> -	  string = (CHAR_T *) args_value[fspec->data_arg].pa_wstring;	      \
> -									      \
> -	/* Entry point for printing other strings.  */			      \
> -      LABEL (print_string):						      \
> -									      \
> -	string_malloced = 0;						      \
> -	if (string == NULL)						      \
> -	  {								      \
> -	    /* Write "(null)" if there's space.  */			      \
> -	    if (prec == -1 || prec >= (int) array_length (null) - 1)          \
> -	      {								      \
> -		string = (CHAR_T *) null;				      \
> -		len = array_length (null) - 1;				      \
> -	      }								      \
> -	    else							      \
> -	      {								      \
> -		string = (CHAR_T *) L"";				      \
> -		len = 0;						      \
> -	      }								      \
> -	  }								      \
> -	else if (!is_long && spec != L_('S'))				      \
> -	  {								      \
> -	    /* This is complicated.  We have to transform the multibyte	      \
> -	       string into a wide character string.  */			      \
> -	    const char *mbs = (const char *) string;			      \
> -	    mbstate_t mbstate;						      \
> -									      \
> -	    len = prec != -1 ? __strnlen (mbs, (size_t) prec) : strlen (mbs); \
> -									      \
> -	    /* Allocate dynamically an array which definitely is long	      \
> -	       enough for the wide character version.  Each byte in the	      \
> -	       multi-byte string can produce at most one wide character.  */  \
> -	    if (__glibc_unlikely (len > SIZE_MAX / sizeof (wchar_t)))	      \
> -	      {								      \
> -		__set_errno (EOVERFLOW);				      \
> -		done = -1;						      \
> -		goto all_done;						      \
> -	      }								      \
> -	    else if (__libc_use_alloca (len * sizeof (wchar_t)))	      \
> -	      string = (CHAR_T *) alloca (len * sizeof (wchar_t));	      \
> -	    else if ((string = (CHAR_T *) malloc (len * sizeof (wchar_t)))    \
> -		     == NULL)						      \
> -	      {								      \
> -		done = -1;						      \
> -		goto all_done;						      \
> -	      }								      \
> -	    else							      \
> -	      string_malloced = 1;					      \
> -									      \
> -	    memset (&mbstate, '\0', sizeof (mbstate_t));		      \
> -	    len = __mbsrtowcs (string, &mbs, len, &mbstate);		      \
> -	    if (len == (size_t) -1)					      \
> -	      {								      \
> -		/* Illegal multibyte character.  */			      \
> -		done = -1;						      \
> -		goto all_done;						      \
> -	      }								      \
> -	  }								      \
> -	else								      \
> -	  {								      \
> -	    if (prec != -1)						      \
> -	      /* Search for the end of the string, but don't search past      \
> -		 the length specified by the precision.  */		      \
> -	      len = __wcsnlen (string, prec);				      \
> -	    else							      \
> -	      len = __wcslen (string);					      \
> -	  }								      \
> -									      \
> -	if ((width -= len) < 0)						      \
> -	  {								      \
> -	    outstring (string, len);					      \
> -	    break;							      \
> -	  }								      \
> -									      \
> -	if (!left)							      \
> -	  PAD (L' ');							      \
> -	outstring (string, len);					      \
> -	if (left)							      \
> -	  PAD (L' ');							      \
> -	if (__glibc_unlikely (string_malloced))				      \
> -	  free (string);						      \
> -      }									      \
> -      break;
> -#else
> -# define process_string_arg(fspec) \
> -    LABEL (form_character):						      \
> -      /* Character.  */							      \
> -      if (is_long)							      \
> -	goto LABEL (form_wcharacter);					      \
> -      --width;	/* Account for the character itself.  */		      \
> -      if (!left)							      \
> -	PAD (' ');							      \
> -      if (fspec == NULL)						      \
> -	outchar ((unsigned char) va_arg (ap, int)); /* Promoted.  */	      \
> -      else								      \
> -	outchar ((unsigned char) args_value[fspec->data_arg].pa_int);	      \
> -      if (left)								      \
> -	PAD (' ');							      \
> -      break;								      \
> -									      \
> -    LABEL (form_wcharacter):						      \
> -      {									      \
> -	/* Wide character.  */						      \
> -	char buf[MB_LEN_MAX];						      \
> -	mbstate_t mbstate;						      \
> -	size_t len;							      \
> -									      \
> -	memset (&mbstate, '\0', sizeof (mbstate_t));			      \
> -	len = __wcrtomb (buf, (fspec == NULL ? va_arg (ap, wchar_t)	      \
> -			       : args_value[fspec->data_arg].pa_wchar),	      \
> -			 &mbstate);					      \
> -	if (len == (size_t) -1)						      \
> -	  {								      \
> -	    /* Something went wrong during the conversion.  Bail out.  */     \
> -	    done = -1;							      \
> -	    goto all_done;						      \
> -	  }								      \
> -	width -= len;							      \
> -	if (!left)							      \
> -	  PAD (' ');							      \
> -	outstring (buf, len);						      \
> -	if (left)							      \
> -	  PAD (' ');							      \
> -      }									      \
> -      break;								      \
> -									      \
> -    LABEL (form_string):						      \
> -      {									      \
> -	size_t len;							      \
> -	int string_malloced;						      \
> -									      \
> -	/* The string argument could in fact be `char *' or `wchar_t *'.      \
> -	   But this should not make a difference here.  */		      \
> -	if (fspec == NULL)						      \
> -	  string = (char *) va_arg (ap, const char *);			      \
> -	else								      \
> -	  string = (char *) args_value[fspec->data_arg].pa_string;	      \
> -									      \
> -	/* Entry point for printing other strings.  */			      \
> -      LABEL (print_string):						      \
> -									      \
> -	string_malloced = 0;						      \
> -	if (string == NULL)						      \
> -	  {								      \
> -	    /* Write "(null)" if there's space.  */			      \
> -	    if (prec == -1 || prec >= (int) sizeof (null) - 1)		      \
> -	      {								      \
> -		string = (char *) null;					      \
> -		len = sizeof (null) - 1;				      \
> -	      }								      \
> -	    else							      \
> -	      {								      \
> -		string = (char *) "";					      \
> -		len = 0;						      \
> -	      }								      \
> -	  }								      \
> -	else if (!is_long && spec != L_('S'))				      \
> -	  {								      \
> -	    if (prec != -1)						      \
> -	      /* Search for the end of the string, but don't search past      \
> -		 the length (in bytes) specified by the precision.  */	      \
> -	      len = __strnlen (string, prec);				      \
> -	    else							      \
> -	      len = strlen (string);					      \
> -	  }								      \
> -	else								      \
> -	  {								      \
> -	    const wchar_t *s2 = (const wchar_t *) string;		      \
> -	    mbstate_t mbstate;						      \
> -									      \
> -	    memset (&mbstate, '\0', sizeof (mbstate_t));		      \
> -									      \
> -	    if (prec >= 0)						      \
> -	      {								      \
> -		/* The string `s2' might not be NUL terminated.  */	      \
> -		if (__libc_use_alloca (prec))				      \
> -		  string = (char *) alloca (prec);			      \
> -		else if ((string = (char *) malloc (prec)) == NULL)	      \
> -		  {							      \
> -		    done = -1;						      \
> -		    goto all_done;					      \
> -		  }							      \
> -		else							      \
> -		  string_malloced = 1;					      \
> -		len = __wcsrtombs (string, &s2, prec, &mbstate);	      \
> -	      }								      \
> -	    else							      \
> -	      {								      \
> -		len = __wcsrtombs (NULL, &s2, 0, &mbstate);		      \
> -		if (len != (size_t) -1)					      \
> -		  {							      \
> -		    assert (__mbsinit (&mbstate));			      \
> -		    s2 = (const wchar_t *) string;			      \
> -		    if (__libc_use_alloca (len + 1))			      \
> -		      string = (char *) alloca (len + 1);		      \
> -		    else if ((string = (char *) malloc (len + 1)) == NULL)    \
> -		      {							      \
> -			done = -1;					      \
> -			goto all_done;					      \
> -		      }							      \
> -		    else						      \
> -		      string_malloced = 1;				      \
> -		    (void) __wcsrtombs (string, &s2, len + 1, &mbstate);      \
> -		  }							      \
> -	      }								      \
> -									      \
> -	    if (len == (size_t) -1)					      \
> -	      {								      \
> -		/* Illegal wide-character string.  */			      \
> -		done = -1;						      \
> -		goto all_done;						      \
> -	      }								      \
> -	  }								      \
> -									      \
> -	if ((width -= len) < 0)						      \
> -	  {								      \
> -	    outstring (string, len);					      \
> -	    break;							      \
> -	  }								      \
> -									      \
> -	if (!left)							      \
> -	  PAD (' ');							      \
> -	outstring (string, len);					      \
> -	if (left)							      \
> -	  PAD (' ');							      \
> -	if (__glibc_unlikely (string_malloced))			              \
> -	  free (string);						      \
> -      }									      \
> -      break;
> -#endif
> -
> -/* Helper function to provide temporary buffering for unbuffered streams.  */
> -static int buffered_vfprintf (FILE *stream, const CHAR_T *fmt, va_list)
> -     __THROW __attribute__ ((noinline));
> -
> -/* Handle positional format specifiers.  */
> -static int printf_positional (FILE *s,
> -			      const CHAR_T *format, int readonly_format,
> -			      va_list ap, va_list *ap_savep, int done,
> -			      int nspecs_done, const UCHAR_T *lead_str_end,
> -			      CHAR_T *work_buffer, int save_errno,
> -			      const char *grouping, THOUSANDS_SEP_T);
> -
> -/* Handle unknown format specifier.  */
> -static int printf_unknown (FILE *, const struct printf_info *,
> -			   const void *const *) __THROW;
> -
> -/* Group digits of number string.  */
> -static CHAR_T *group_number (CHAR_T *, CHAR_T *, CHAR_T *, const char *,
> -			     THOUSANDS_SEP_T);
> -
> -/* The function itself.  */
> -int
> -vfprintf (FILE *s, const CHAR_T *format, va_list ap)
> +extern int
> +__vfprintf (FILE *fp, const char *format, va_list ap)
>  {
> -  /* The character used as thousands separator.  */
> -  THOUSANDS_SEP_T thousands_sep = 0;
> -
> -  /* The string describing the size of groups of digits.  */
> -  const char *grouping;
> -
> -  /* Place to accumulate the result.  */
> -  int done;
> -
> -  /* Current character in format string.  */
> -  const UCHAR_T *f;
> -
> -  /* End of leading constant string.  */
> -  const UCHAR_T *lead_str_end;
> -
> -  /* Points to next format specifier.  */
> -  const UCHAR_T *end_of_spec;
> -
> -  /* Buffer intermediate results.  */
> -  CHAR_T work_buffer[WORK_BUFFER_SIZE];
> -  CHAR_T *workstart = NULL;
> -  CHAR_T *workend;
> -
> -  /* We have to save the original argument pointer.  */
> -  va_list ap_save;
> -
> -  /* Count number of specifiers we already processed.  */
> -  int nspecs_done;
> -
> -  /* For the %m format we may need the current `errno' value.  */
> -  int save_errno = errno;
> -
> -  /* 1 if format is in read-only memory, -1 if it is in writable memory,
> -     0 if unknown.  */
> -  int readonly_format = 0;
> -
> -  /* Orient the stream.  */
> -#ifdef ORIENT
> -  ORIENT;
> -#endif
> -
> -  /* Sanity check of arguments.  */
> -  ARGCHECK (s, format);
> -
> -#ifdef ORIENT
> -  /* Check for correct orientation.  */
> -  if (_IO_vtable_offset (s) == 0 &&
> -      _IO_fwide (s, sizeof (CHAR_T) == 1 ? -1 : 1)
> -      != (sizeof (CHAR_T) == 1 ? -1 : 1))
> -    /* The stream is already oriented otherwise.  */
> -    return EOF;
> -#endif
> -
> -  if (UNBUFFERED_P (s))
> -    /* Use a helper function which will allocate a local temporary buffer
> -       for the stream and then call us again.  */
> -    return buffered_vfprintf (s, format, ap);
> -
> -  /* Initialize local variables.  */
> -  done = 0;
> -  grouping = (const char *) -1;
> -#ifdef __va_copy
> -  /* This macro will be available soon in gcc's <stdarg.h>.  We need it
> -     since on some systems `va_list' is not an integral type.  */
> -  __va_copy (ap_save, ap);
> -#else
> -  ap_save = ap;
> -#endif
> -  nspecs_done = 0;
> -
> -#ifdef COMPILE_WPRINTF
> -  /* Find the first format specifier.  */
> -  f = lead_str_end = __find_specwc ((const UCHAR_T *) format);
> -#else
> -  /* Find the first format specifier.  */
> -  f = lead_str_end = __find_specmb ((const UCHAR_T *) format);
> -#endif
> -
> -  /* Lock stream.  */
> -  _IO_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, s);
> -  _IO_flockfile (s);
> -
> -  /* Write the literal text before the first format.  */
> -  outstring ((const UCHAR_T *) format,
> -	     lead_str_end - (const UCHAR_T *) format);
> -
> -  /* If we only have to print a simple string, return now.  */
> -  if (*f == L_('\0'))
> -    goto all_done;
> -
> -  /* Use the slow path in case any printf handler is registered.  */
> -  if (__glibc_unlikely (__printf_function_table != NULL
> -			|| __printf_modifier_table != NULL
> -			|| __printf_va_arg_table != NULL))
> -    goto do_positional;
> -
> -  /* Process whole format string.  */
> -  do
> -    {
> -      STEP0_3_TABLE;
> -      STEP4_TABLE;
> -
> -      union printf_arg *args_value;	/* This is not used here but ... */
> -      int is_negative;	/* Flag for negative number.  */
> -      union
> -      {
> -	unsigned long long int longlong;
> -	unsigned long int word;
> -      } number;
> -      int base;
> -      union printf_arg the_arg;
> -      CHAR_T *string;	/* Pointer to argument string.  */
> -      int alt = 0;	/* Alternate format.  */
> -      int space = 0;	/* Use space prefix if no sign is needed.  */
> -      int left = 0;	/* Left-justify output.  */
> -      int showsign = 0;	/* Always begin with plus or minus sign.  */
> -      int group = 0;	/* Print numbers according grouping rules.  */
> -      int is_long_double = 0; /* Argument is long double/ long long int.  */
> -      int is_short = 0;	/* Argument is short int.  */
> -      int is_long = 0;	/* Argument is long int.  */
> -      int is_char = 0;	/* Argument is promoted (unsigned) char.  */
> -      int width = 0;	/* Width of output; 0 means none specified.  */
> -      int prec = -1;	/* Precision of output; -1 means none specified.  */
> -      /* This flag is set by the 'I' modifier and selects the use of the
> -	 `outdigits' as determined by the current locale.  */
> -      int use_outdigits = 0;
> -      UCHAR_T pad = L_(' ');/* Padding character.  */
> -      CHAR_T spec;
> -
> -      workstart = NULL;
> -      workend = work_buffer + WORK_BUFFER_SIZE;
> -
> -      /* Get current character in format string.  */
> -      JUMP (*++f, step0_jumps);
> -
> -      /* ' ' flag.  */
> -    LABEL (flag_space):
> -      space = 1;
> -      JUMP (*++f, step0_jumps);
> -
> -      /* '+' flag.  */
> -    LABEL (flag_plus):
> -      showsign = 1;
> -      JUMP (*++f, step0_jumps);
> -
> -      /* The '-' flag.  */
> -    LABEL (flag_minus):
> -      left = 1;
> -      pad = L_(' ');
> -      JUMP (*++f, step0_jumps);
> -
> -      /* The '#' flag.  */
> -    LABEL (flag_hash):
> -      alt = 1;
> -      JUMP (*++f, step0_jumps);
> -
> -      /* The '0' flag.  */
> -    LABEL (flag_zero):
> -      if (!left)
> -	pad = L_('0');
> -      JUMP (*++f, step0_jumps);
> -
> -      /* The '\'' flag.  */
> -    LABEL (flag_quote):
> -      group = 1;
> -
> -      if (grouping == (const char *) -1)
> -	{
> -#ifdef COMPILE_WPRINTF
> -	  thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC,
> -					    _NL_NUMERIC_THOUSANDS_SEP_WC);
> -#else
> -	  thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
> -#endif
> -
> -	  grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
> -	  if (*grouping == '\0' || *grouping == CHAR_MAX
> -#ifdef COMPILE_WPRINTF
> -	      || thousands_sep == L'\0'
> -#else
> -	      || *thousands_sep == '\0'
> -#endif
> -	      )
> -	    grouping = NULL;
> -	}
> -      JUMP (*++f, step0_jumps);
> -
> -    LABEL (flag_i18n):
> -      use_outdigits = 1;
> -      JUMP (*++f, step0_jumps);
> -
> -      /* Get width from argument.  */
> -    LABEL (width_asterics):
> -      {
> -	const UCHAR_T *tmp;	/* Temporary value.  */
> -
> -	tmp = ++f;
> -	if (ISDIGIT (*tmp))
> -	  {
> -	    int pos = read_int (&tmp);
> -
> -	    if (pos == -1)
> -	      {
> -		__set_errno (EOVERFLOW);
> -		done = -1;
> -		goto all_done;
> -	      }
> -
> -	    if (pos && *tmp == L_('$'))
> -	      /* The width comes from a positional parameter.  */
> -	      goto do_positional;
> -	  }
> -	width = va_arg (ap, int);
> -
> -	/* Negative width means left justified.  */
> -	if (width < 0)
> -	  {
> -	    width = -width;
> -	    pad = L_(' ');
> -	    left = 1;
> -	  }
> -
> -	if (__glibc_unlikely (width >= INT_MAX / sizeof (CHAR_T) - EXTSIZ))
> -	  {
> -	    __set_errno (EOVERFLOW);
> -	    done = -1;
> -	    goto all_done;
> -	  }
> -
> -	if (width >= WORK_BUFFER_SIZE - EXTSIZ)
> -	  {
> -	    /* We have to use a special buffer.  */
> -	    size_t needed = ((size_t) width + EXTSIZ) * sizeof (CHAR_T);
> -	    if (__libc_use_alloca (needed))
> -	      workend = (CHAR_T *) alloca (needed) + width + EXTSIZ;
> -	    else
> -	      {
> -		workstart = (CHAR_T *) malloc (needed);
> -		if (workstart == NULL)
> -		  {
> -		    done = -1;
> -		    goto all_done;
> -		  }
> -		workend = workstart + width + EXTSIZ;
> -	      }
> -	  }
> -      }
> -      JUMP (*f, step1_jumps);
> -
> -      /* Given width in format string.  */
> -    LABEL (width):
> -      width = read_int (&f);
> -
> -      if (__glibc_unlikely (width == -1
> -			    || width >= INT_MAX / sizeof (CHAR_T) - EXTSIZ))
> -	{
> -	  __set_errno (EOVERFLOW);
> -	  done = -1;
> -	  goto all_done;
> -	}
> -
> -      if (width >= WORK_BUFFER_SIZE - EXTSIZ)
> -	{
> -	  /* We have to use a special buffer.  */
> -	  size_t needed = ((size_t) width + EXTSIZ) * sizeof (CHAR_T);
> -	  if (__libc_use_alloca (needed))
> -	    workend = (CHAR_T *) alloca (needed) + width + EXTSIZ;
> -	  else
> -	    {
> -	      workstart = (CHAR_T *) malloc (needed);
> -	      if (workstart == NULL)
> -		{
> -		  done = -1;
> -		  goto all_done;
> -		}
> -	      workend = workstart + width + EXTSIZ;
> -	    }
> -	}
> -      if (*f == L_('$'))
> -	/* Oh, oh.  The argument comes from a positional parameter.  */
> -	goto do_positional;
> -      JUMP (*f, step1_jumps);
> -
> -    LABEL (precision):
> -      ++f;
> -      if (*f == L_('*'))
> -	{
> -	  const UCHAR_T *tmp;	/* Temporary value.  */
> -
> -	  tmp = ++f;
> -	  if (ISDIGIT (*tmp))
> -	    {
> -	      int pos = read_int (&tmp);
> -
> -	      if (pos == -1)
> -		{
> -		  __set_errno (EOVERFLOW);
> -		  done = -1;
> -		  goto all_done;
> -		}
> -
> -	      if (pos && *tmp == L_('$'))
> -		/* The precision comes from a positional parameter.  */
> -		goto do_positional;
> -	    }
> -	  prec = va_arg (ap, int);
> -
> -	  /* If the precision is negative the precision is omitted.  */
> -	  if (prec < 0)
> -	    prec = -1;
> -	}
> -      else if (ISDIGIT (*f))
> -	{
> -	  prec = read_int (&f);
> -
> -	  /* The precision was specified in this case as an extremely
> -	     large positive value.  */
> -	  if (prec == -1)
> -	    {
> -	      __set_errno (EOVERFLOW);
> -	      done = -1;
> -	      goto all_done;
> -	    }
> -	}
> -      else
> -	prec = 0;
> -      if (prec > width && prec > WORK_BUFFER_SIZE - EXTSIZ)
> -	{
> -	  /* Deallocate any previously allocated buffer because it is
> -	     too small.  */
> -	  if (__glibc_unlikely (workstart != NULL))
> -	    free (workstart);
> -	  workstart = NULL;
> -	  if (__glibc_unlikely (prec >= INT_MAX / sizeof (CHAR_T) - EXTSIZ))
> -	    {
> -	      __set_errno (EOVERFLOW);
> -	      done = -1;
> -	      goto all_done;
> -	    }
> -	  size_t needed = ((size_t) prec + EXTSIZ) * sizeof (CHAR_T);
> -
> -	  if (__libc_use_alloca (needed))
> -	    workend = (CHAR_T *) alloca (needed) + prec + EXTSIZ;
> -	  else
> -	    {
> -	      workstart = (CHAR_T *) malloc (needed);
> -	      if (workstart == NULL)
> -		{
> -		  done = -1;
> -		  goto all_done;
> -		}
> -	      workend = workstart + prec + EXTSIZ;
> -	    }
> -	}
> -      JUMP (*f, step2_jumps);
> -
> -      /* Process 'h' modifier.  There might another 'h' following.  */
> -    LABEL (mod_half):
> -      is_short = 1;
> -      JUMP (*++f, step3a_jumps);
> -
> -      /* Process 'hh' modifier.  */
> -    LABEL (mod_halfhalf):
> -      is_short = 0;
> -      is_char = 1;
> -      JUMP (*++f, step4_jumps);
> -
> -      /* Process 'l' modifier.  There might another 'l' following.  */
> -    LABEL (mod_long):
> -      is_long = 1;
> -      JUMP (*++f, step3b_jumps);
> -
> -      /* Process 'L', 'q', or 'll' modifier.  No other modifier is
> -	 allowed to follow.  */
> -    LABEL (mod_longlong):
> -      is_long_double = 1;
> -      is_long = 1;
> -      JUMP (*++f, step4_jumps);
> -
> -    LABEL (mod_size_t):
> -      is_long_double = sizeof (size_t) > sizeof (unsigned long int);
> -      is_long = sizeof (size_t) > sizeof (unsigned int);
> -      JUMP (*++f, step4_jumps);
> -
> -    LABEL (mod_ptrdiff_t):
> -      is_long_double = sizeof (ptrdiff_t) > sizeof (unsigned long int);
> -      is_long = sizeof (ptrdiff_t) > sizeof (unsigned int);
> -      JUMP (*++f, step4_jumps);
> -
> -    LABEL (mod_intmax_t):
> -      is_long_double = sizeof (intmax_t) > sizeof (unsigned long int);
> -      is_long = sizeof (intmax_t) > sizeof (unsigned int);
> -      JUMP (*++f, step4_jumps);
> -
> -      /* Process current format.  */
> -      while (1)
> -	{
> -	  process_arg (((struct printf_spec *) NULL));
> -	  process_string_arg (((struct printf_spec *) NULL));
> -
> -	LABEL (form_unknown):
> -	  if (spec == L_('\0'))
> -	    {
> -	      /* The format string ended before the specifier is complete.  */
> -	      __set_errno (EINVAL);
> -	      done = -1;
> -	      goto all_done;
> -	    }
> -
> -	  /* If we are in the fast loop force entering the complicated
> -	     one.  */
> -	  goto do_positional;
> -	}
> -
> -      /* The format is correctly handled.  */
> -      ++nspecs_done;
> -
> -      if (__glibc_unlikely (workstart != NULL))
> -	free (workstart);
> -      workstart = NULL;
> -
> -      /* Look for next format specifier.  */
> -#ifdef COMPILE_WPRINTF
> -      f = __find_specwc ((end_of_spec = ++f));
> -#else
> -      f = __find_specmb ((end_of_spec = ++f));
> -#endif
> -
> -      /* Write the following constant string.  */
> -      outstring (end_of_spec, f - end_of_spec);
> -    }
> -  while (*f != L_('\0'));
> -
> -  /* Unlock stream and return.  */
> -  goto all_done;
> -
> -  /* Hand off processing for positional parameters.  */
> -do_positional:
> -  if (__glibc_unlikely (workstart != NULL))
> -    {
> -      free (workstart);
> -      workstart = NULL;
> -    }
> -  done = printf_positional (s, format, readonly_format, ap, &ap_save,
> -			    done, nspecs_done, lead_str_end, work_buffer,
> -			    save_errno, grouping, thousands_sep);
> -
> - all_done:
> -  if (__glibc_unlikely (workstart != NULL))
> -    free (workstart);
> -  /* Unlock the stream.  */
> -  _IO_funlockfile (s);
> -  _IO_cleanup_region_end (0);
> -
> -  return done;
> -}
> -
> -static int
> -printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
> -		   va_list ap, va_list *ap_savep, int done, int nspecs_done,
> -		   const UCHAR_T *lead_str_end,
> -		   CHAR_T *work_buffer, int save_errno,
> -		   const char *grouping, THOUSANDS_SEP_T thousands_sep)
> -{
> -  /* For positional argument handling.  */
> -  struct scratch_buffer specsbuf;
> -  scratch_buffer_init (&specsbuf);
> -  struct printf_spec *specs = specsbuf.data;
> -  size_t specs_limit = specsbuf.length / sizeof (specs[0]);
> -
> -  /* Used as a backing store for args_value, args_size, args_type
> -     below.  */
> -  struct scratch_buffer argsbuf;
> -  scratch_buffer_init (&argsbuf);
> -
> -  /* Array with information about the needed arguments.  This has to
> -     be dynamically extensible.  */
> -  size_t nspecs = 0;
> -
> -  /* The number of arguments the format string requests.  This will
> -     determine the size of the array needed to store the argument
> -     attributes.  */
> -  size_t nargs = 0;
> -
> -  /* Positional parameters refer to arguments directly.  This could
> -     also determine the maximum number of arguments.  Track the
> -     maximum number.  */
> -  size_t max_ref_arg = 0;
> -
> -  /* Just a counter.  */
> -  size_t cnt;
> -
> -  CHAR_T *workstart = NULL;
> -
> -  if (grouping == (const char *) -1)
> -    {
> -#ifdef COMPILE_WPRINTF
> -      thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC,
> -					_NL_NUMERIC_THOUSANDS_SEP_WC);
> -#else
> -      thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
> -#endif
> -
> -      grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
> -      if (*grouping == '\0' || *grouping == CHAR_MAX)
> -	grouping = NULL;
> -    }
> -
> -  for (const UCHAR_T *f = lead_str_end; *f != L_('\0');
> -       f = specs[nspecs++].next_fmt)
> -    {
> -      if (nspecs == specs_limit)
> -	{
> -	  if (!scratch_buffer_grow_preserve (&specsbuf))
> -	    {
> -	      done = -1;
> -	      goto all_done;
> -	    }
> -	  specs = specsbuf.data;
> -	  specs_limit = specsbuf.length / sizeof (specs[0]);
> -	}
> -
> -      /* Parse the format specifier.  */
> -#ifdef COMPILE_WPRINTF
> -      nargs += __parse_one_specwc (f, nargs, &specs[nspecs], &max_ref_arg);
> -#else
> -      nargs += __parse_one_specmb (f, nargs, &specs[nspecs], &max_ref_arg);
> -#endif
> -    }
> -
> -  /* Determine the number of arguments the format string consumes.  */
> -  nargs = MAX (nargs, max_ref_arg);
> -
> -  union printf_arg *args_value;
> -  int *args_size;
> -  int *args_type;
> -  {
> -    /* Calculate total size needed to represent a single argument
> -       across all three argument-related arrays.  */
> -    size_t bytes_per_arg
> -      = sizeof (*args_value) + sizeof (*args_size) + sizeof (*args_type);
> -    if (!scratch_buffer_set_array_size (&argsbuf, nargs, bytes_per_arg))
> -      {
> -	done = -1;
> -	goto all_done;
> -      }
> -    args_value = argsbuf.data;
> -    /* Set up the remaining two arrays to each point past the end of
> -       the prior array, since space for all three has been allocated
> -       now.  */
> -    args_size = &args_value[nargs].pa_int;
> -    args_type = &args_size[nargs];
> -    memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0',
> -	    nargs * sizeof (*args_type));
> -  }
> -
> -  /* XXX Could do sanity check here: If any element in ARGS_TYPE is
> -     still zero after this loop, format is invalid.  For now we
> -     simply use 0 as the value.  */
> -
> -  /* Fill in the types of all the arguments.  */
> -  for (cnt = 0; cnt < nspecs; ++cnt)
> -    {
> -      /* If the width is determined by an argument this is an int.  */
> -      if (specs[cnt].width_arg != -1)
> -	args_type[specs[cnt].width_arg] = PA_INT;
> -
> -      /* If the precision is determined by an argument this is an int.  */
> -      if (specs[cnt].prec_arg != -1)
> -	args_type[specs[cnt].prec_arg] = PA_INT;
> -
> -      switch (specs[cnt].ndata_args)
> -	{
> -	case 0:		/* No arguments.  */
> -	  break;
> -	case 1:		/* One argument; we already have the
> -			   type and size.  */
> -	  args_type[specs[cnt].data_arg] = specs[cnt].data_arg_type;
> -	  args_size[specs[cnt].data_arg] = specs[cnt].size;
> -	  break;
> -	default:
> -	  /* We have more than one argument for this format spec.
> -	     We must call the arginfo function again to determine
> -	     all the types.  */
> -	  (void) (*__printf_arginfo_table[specs[cnt].info.spec])
> -	    (&specs[cnt].info,
> -	     specs[cnt].ndata_args, &args_type[specs[cnt].data_arg],
> -	     &args_size[specs[cnt].data_arg]);
> -	  break;
> -	}
> -    }
> -
> -  /* Now we know all the types and the order.  Fill in the argument
> -     values.  */
> -  for (cnt = 0; cnt < nargs; ++cnt)
> -    switch (args_type[cnt])
> -      {
> -#define T(tag, mem, type)				\
> -	case tag:					\
> -	  args_value[cnt].mem = va_arg (*ap_savep, type); \
> -	  break
> -
> -	T (PA_WCHAR, pa_wchar, wint_t);
> -      case PA_CHAR:				/* Promoted.  */
> -      case PA_INT|PA_FLAG_SHORT:		/* Promoted.  */
> -#if LONG_MAX == INT_MAX
> -      case PA_INT|PA_FLAG_LONG:
> -#endif
> -	T (PA_INT, pa_int, int);
> -#if LONG_MAX == LONG_LONG_MAX
> -      case PA_INT|PA_FLAG_LONG:
> -#endif
> -	T (PA_INT|PA_FLAG_LONG_LONG, pa_long_long_int, long long int);
> -#if LONG_MAX != INT_MAX && LONG_MAX != LONG_LONG_MAX
> -# error "he?"
> -#endif
> -      case PA_FLOAT:				/* Promoted.  */
> -	T (PA_DOUBLE, pa_double, double);
> -      case PA_DOUBLE|PA_FLAG_LONG_DOUBLE:
> -	if (__ldbl_is_dbl)
> -	  {
> -	    args_value[cnt].pa_double = va_arg (*ap_savep, double);
> -	    args_type[cnt] &= ~PA_FLAG_LONG_DOUBLE;
> -	  }
> -	else
> -	  args_value[cnt].pa_long_double = va_arg (*ap_savep, long double);
> -	break;
> -      case PA_STRING:				/* All pointers are the same */
> -      case PA_WSTRING:			/* All pointers are the same */
> -	T (PA_POINTER, pa_pointer, void *);
> -#undef T
> -      default:
> -	if ((args_type[cnt] & PA_FLAG_PTR) != 0)
> -	  args_value[cnt].pa_pointer = va_arg (*ap_savep, void *);
> -	else if (__glibc_unlikely (__printf_va_arg_table != NULL)
> -		 && __printf_va_arg_table[args_type[cnt] - PA_LAST] != NULL)
> -	  {
> -	    args_value[cnt].pa_user = alloca (args_size[cnt]);
> -	    (*__printf_va_arg_table[args_type[cnt] - PA_LAST])
> -	      (args_value[cnt].pa_user, ap_savep);
> -	  }
> -	else
> -	  args_value[cnt].pa_long_double = 0.0;
> -	break;
> -      case -1:
> -	/* Error case.  Not all parameters appear in N$ format
> -	   strings.  We have no way to determine their type.  */
> -	assert (s->_flags2 & _IO_FLAGS2_FORTIFY);
> -	__libc_fatal ("*** invalid %N$ use detected ***\n");
> -      }
> -
> -  /* Now walk through all format specifiers and process them.  */
> -  for (; (size_t) nspecs_done < nspecs; ++nspecs_done)
> -    {
> -      STEP4_TABLE;
> -
> -      int is_negative;
> -      union
> -      {
> -	unsigned long long int longlong;
> -	unsigned long int word;
> -      } number;
> -      int base;
> -      union printf_arg the_arg;
> -      CHAR_T *string;		/* Pointer to argument string.  */
> -
> -      /* Fill variables from values in struct.  */
> -      int alt = specs[nspecs_done].info.alt;
> -      int space = specs[nspecs_done].info.space;
> -      int left = specs[nspecs_done].info.left;
> -      int showsign = specs[nspecs_done].info.showsign;
> -      int group = specs[nspecs_done].info.group;
> -      int is_long_double = specs[nspecs_done].info.is_long_double;
> -      int is_short = specs[nspecs_done].info.is_short;
> -      int is_char = specs[nspecs_done].info.is_char;
> -      int is_long = specs[nspecs_done].info.is_long;
> -      int width = specs[nspecs_done].info.width;
> -      int prec = specs[nspecs_done].info.prec;
> -      int use_outdigits = specs[nspecs_done].info.i18n;
> -      char pad = specs[nspecs_done].info.pad;
> -      CHAR_T spec = specs[nspecs_done].info.spec;
> -
> -      workstart = NULL;
> -      CHAR_T *workend = work_buffer + WORK_BUFFER_SIZE;
> -
> -      /* Fill in last information.  */
> -      if (specs[nspecs_done].width_arg != -1)
> -	{
> -	  /* Extract the field width from an argument.  */
> -	  specs[nspecs_done].info.width =
> -	    args_value[specs[nspecs_done].width_arg].pa_int;
> -
> -	  if (specs[nspecs_done].info.width < 0)
> -	    /* If the width value is negative left justification is
> -	       selected and the value is taken as being positive.  */
> -	    {
> -	      specs[nspecs_done].info.width *= -1;
> -	      left = specs[nspecs_done].info.left = 1;
> -	    }
> -	  width = specs[nspecs_done].info.width;
> -	}
> -
> -      if (specs[nspecs_done].prec_arg != -1)
> -	{
> -	  /* Extract the precision from an argument.  */
> -	  specs[nspecs_done].info.prec =
> -	    args_value[specs[nspecs_done].prec_arg].pa_int;
> -
> -	  if (specs[nspecs_done].info.prec < 0)
> -	    /* If the precision is negative the precision is
> -	       omitted.  */
> -	    specs[nspecs_done].info.prec = -1;
> -
> -	  prec = specs[nspecs_done].info.prec;
> -	}
> -
> -      /* Maybe the buffer is too small.  */
> -      if (MAX (prec, width) + EXTSIZ > WORK_BUFFER_SIZE)
> -	{
> -	  if (__libc_use_alloca ((MAX (prec, width) + EXTSIZ)
> -				 * sizeof (CHAR_T)))
> -	    workend = ((CHAR_T *) alloca ((MAX (prec, width) + EXTSIZ)
> -					  * sizeof (CHAR_T))
> -		       + (MAX (prec, width) + EXTSIZ));
> -	  else
> -	    {
> -	      workstart = (CHAR_T *) malloc ((MAX (prec, width) + EXTSIZ)
> -					     * sizeof (CHAR_T));
> -	      if (workstart == NULL)
> -		{
> -		  done = -1;
> -		  goto all_done;
> -		}
> -	      workend = workstart + (MAX (prec, width) + EXTSIZ);
> -	    }
> -	}
> -
> -      /* Process format specifiers.  */
> -      while (1)
> -	{
> -	  extern printf_function **__printf_function_table;
> -	  int function_done;
> -
> -	  if (spec <= UCHAR_MAX
> -	      && __printf_function_table != NULL
> -	      && __printf_function_table[(size_t) spec] != NULL)
> -	    {
> -	      const void **ptr = alloca (specs[nspecs_done].ndata_args
> -					 * sizeof (const void *));
> -
> -	      /* Fill in an array of pointers to the argument values.  */
> -	      for (unsigned int i = 0; i < specs[nspecs_done].ndata_args;
> -		   ++i)
> -		ptr[i] = &args_value[specs[nspecs_done].data_arg + i];
> -
> -	      /* Call the function.  */
> -	      function_done = __printf_function_table[(size_t) spec]
> -		(s, &specs[nspecs_done].info, ptr);
> -
> -	      if (function_done != -2)
> -		{
> -		  /* If an error occurred we don't have information
> -		     about # of chars.  */
> -		  if (function_done < 0)
> -		    {
> -		      /* Function has set errno.  */
> -		      done = -1;
> -		      goto all_done;
> -		    }
> -
> -		  done_add (function_done);
> -		  break;
> -		}
> -	    }
> -
> -	  JUMP (spec, step4_jumps);
> -
> -	  process_arg ((&specs[nspecs_done]));
> -	  process_string_arg ((&specs[nspecs_done]));
> -
> -	  LABEL (form_unknown):
> -	  {
> -	    unsigned int i;
> -	    const void **ptr;
> -
> -	    ptr = alloca (specs[nspecs_done].ndata_args
> -			  * sizeof (const void *));
> -
> -	    /* Fill in an array of pointers to the argument values.  */
> -	    for (i = 0; i < specs[nspecs_done].ndata_args; ++i)
> -	      ptr[i] = &args_value[specs[nspecs_done].data_arg + i];
> -
> -	    /* Call the function.  */
> -	    function_done = printf_unknown (s, &specs[nspecs_done].info,
> -					    ptr);
> -
> -	    /* If an error occurred we don't have information about #
> -	       of chars.  */
> -	    if (function_done < 0)
> -	      {
> -		/* Function has set errno.  */
> -		done = -1;
> -		goto all_done;
> -	      }
> -
> -	    done_add (function_done);
> -	  }
> -	  break;
> -	}
> -
> -      if (__glibc_unlikely (workstart != NULL))
> -	free (workstart);
> -      workstart = NULL;
> -
> -      /* Write the following constant string.  */
> -      outstring (specs[nspecs_done].end_of_fmt,
> -		 specs[nspecs_done].next_fmt
> -		 - specs[nspecs_done].end_of_fmt);
> -    }
> - all_done:
> -  if (__glibc_unlikely (workstart != NULL))
> -    free (workstart);
> -  scratch_buffer_free (&argsbuf);
> -  scratch_buffer_free (&specsbuf);
> -  return done;
> +  return __vfprintf_internal (fp, format, ap, 0);
>  }
> -
> -/* Handle an unknown format specifier.  This prints out a canonicalized
> -   representation of the format spec itself.  */
> -static int
> -printf_unknown (FILE *s, const struct printf_info *info,
> -		const void *const *args)
> -
> -{
> -  int done = 0;
> -  CHAR_T work_buffer[MAX (sizeof (info->width), sizeof (info->prec)) * 3];
> -  CHAR_T *const workend
> -    = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T)];
> -  CHAR_T *w;
> -
> -  outchar (L_('%'));
> -
> -  if (info->alt)
> -    outchar (L_('#'));
> -  if (info->group)
> -    outchar (L_('\''));
> -  if (info->showsign)
> -    outchar (L_('+'));
> -  else if (info->space)
> -    outchar (L_(' '));
> -  if (info->left)
> -    outchar (L_('-'));
> -  if (info->pad == L_('0'))
> -    outchar (L_('0'));
> -  if (info->i18n)
> -    outchar (L_('I'));
> -
> -  if (info->width != 0)
> -    {
> -      w = _itoa_word (info->width, workend, 10, 0);
> -      while (w < workend)
> -	outchar (*w++);
> -    }
> -
> -  if (info->prec != -1)
> -    {
> -      outchar (L_('.'));
> -      w = _itoa_word (info->prec, workend, 10, 0);
> -      while (w < workend)
> -	outchar (*w++);
> -    }
> -
> -  if (info->spec != L_('\0'))
> -    outchar (info->spec);
> -
> - all_done:
> -  return done;
> -}
> -
> -/* Group the digits from W to REAR_PTR according to the grouping rules
> -   of the current locale.  The interpretation of GROUPING is as in
> -   `struct lconv' from <locale.h>.  The grouped number extends from
> -   the returned pointer until REAR_PTR.  FRONT_PTR to W is used as a
> -   scratch area.  */
> -static CHAR_T *
> -group_number (CHAR_T *front_ptr, CHAR_T *w, CHAR_T *rear_ptr,
> -	      const char *grouping, THOUSANDS_SEP_T thousands_sep)
> -{
> -  /* Length of the current group.  */
> -  int len;
> -#ifndef COMPILE_WPRINTF
> -  /* Length of the separator (in wide mode, the separator is always a
> -     single wide character).  */
> -  int tlen = strlen (thousands_sep);
> -#endif
> -
> -  /* We treat all negative values like CHAR_MAX.  */
> -
> -  if (*grouping == CHAR_MAX || *grouping <= 0)
> -    /* No grouping should be done.  */
> -    return w;
> -
> -  len = *grouping++;
> -
> -  /* Copy existing string so that nothing gets overwritten.  */
> -  memmove (front_ptr, w, (rear_ptr - w) * sizeof (CHAR_T));
> -  CHAR_T *s = front_ptr + (rear_ptr - w);
> -
> -  w = rear_ptr;
> -
> -  /* Process all characters in the string.  */
> -  while (s > front_ptr)
> -    {
> -      *--w = *--s;
> -
> -      if (--len == 0 && s > front_ptr)
> -	{
> -	  /* A new group begins.  */
> -#ifdef COMPILE_WPRINTF
> -	  if (w != s)
> -	    *--w = thousands_sep;
> -	  else
> -	    /* Not enough room for the separator.  */
> -	    goto copy_rest;
> -#else
> -	  int cnt = tlen;
> -	  if (tlen < w - s)
> -	    do
> -	      *--w = thousands_sep[--cnt];
> -	    while (cnt > 0);
> -	  else
> -	    /* Not enough room for the separator.  */
> -	    goto copy_rest;
> -#endif
> -
> -	  if (*grouping == CHAR_MAX
> -#if CHAR_MIN < 0
> -		   || *grouping < 0
> -#endif
> -		   )
> -	    {
> -	    copy_rest:
> -	      /* No further grouping to be done.  Copy the rest of the
> -		 number.  */
> -	      memmove (w, s, (front_ptr -s) * sizeof (CHAR_T));
> -	      break;
> -	    }
> -	  else if (*grouping != '\0')
> -	    len = *grouping++;
> -	  else
> -	    /* The previous grouping repeats ad infinitum.  */
> -	    len = grouping[-1];
> -	}
> -    }
> -  return w;
> -}
> -
> -/* Helper "class" for `fprintf to unbuffered': creates a temporary buffer.  */
> -struct helper_file
> -  {
> -    struct _IO_FILE_plus _f;
> -#ifdef COMPILE_WPRINTF
> -    struct _IO_wide_data _wide_data;
> -#endif
> -    FILE *_put_stream;
> -#ifdef _IO_MTSAFE_IO
> -    _IO_lock_t lock;
> -#endif
> -  };
> -
> -static int
> -_IO_helper_overflow (FILE *s, int c)
> -{
> -  FILE *target = ((struct helper_file*) s)->_put_stream;
> -#ifdef COMPILE_WPRINTF
> -  int used = s->_wide_data->_IO_write_ptr - s->_wide_data->_IO_write_base;
> -  if (used)
> -    {
> -      size_t written = _IO_sputn (target, s->_wide_data->_IO_write_base, used);
> -      if (written == 0 || written == WEOF)
> -	return WEOF;
> -      __wmemmove (s->_wide_data->_IO_write_base,
> -		  s->_wide_data->_IO_write_base + written,
> -		  used - written);
> -      s->_wide_data->_IO_write_ptr -= written;
> -    }
> -#else
> -  int used = s->_IO_write_ptr - s->_IO_write_base;
> -  if (used)
> -    {
> -      size_t written = _IO_sputn (target, s->_IO_write_base, used);
> -      if (written == 0 || written == EOF)
> -	return EOF;
> -      memmove (s->_IO_write_base, s->_IO_write_base + written,
> -	       used - written);
> -      s->_IO_write_ptr -= written;
> -    }
> -#endif
> -  return PUTC (c, s);
> -}
> -
> -#ifdef COMPILE_WPRINTF
> -static const struct _IO_jump_t _IO_helper_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT (finish, _IO_wdefault_finish),
> -  JUMP_INIT (overflow, _IO_helper_overflow),
> -  JUMP_INIT (underflow, _IO_default_underflow),
> -  JUMP_INIT (uflow, _IO_default_uflow),
> -  JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
> -  JUMP_INIT (xsputn, _IO_wdefault_xsputn),
> -  JUMP_INIT (xsgetn, _IO_wdefault_xsgetn),
> -  JUMP_INIT (seekoff, _IO_default_seekoff),
> -  JUMP_INIT (seekpos, _IO_default_seekpos),
> -  JUMP_INIT (setbuf, _IO_default_setbuf),
> -  JUMP_INIT (sync, _IO_default_sync),
> -  JUMP_INIT (doallocate, _IO_wdefault_doallocate),
> -  JUMP_INIT (read, _IO_default_read),
> -  JUMP_INIT (write, _IO_default_write),
> -  JUMP_INIT (seek, _IO_default_seek),
> -  JUMP_INIT (close, _IO_default_close),
> -  JUMP_INIT (stat, _IO_default_stat)
> -};
> -#else
> -static const struct _IO_jump_t _IO_helper_jumps libio_vtable =
> -{
> -  JUMP_INIT_DUMMY,
> -  JUMP_INIT (finish, _IO_default_finish),
> -  JUMP_INIT (overflow, _IO_helper_overflow),
> -  JUMP_INIT (underflow, _IO_default_underflow),
> -  JUMP_INIT (uflow, _IO_default_uflow),
> -  JUMP_INIT (pbackfail, _IO_default_pbackfail),
> -  JUMP_INIT (xsputn, _IO_default_xsputn),
> -  JUMP_INIT (xsgetn, _IO_default_xsgetn),
> -  JUMP_INIT (seekoff, _IO_default_seekoff),
> -  JUMP_INIT (seekpos, _IO_default_seekpos),
> -  JUMP_INIT (setbuf, _IO_default_setbuf),
> -  JUMP_INIT (sync, _IO_default_sync),
> -  JUMP_INIT (doallocate, _IO_default_doallocate),
> -  JUMP_INIT (read, _IO_default_read),
> -  JUMP_INIT (write, _IO_default_write),
> -  JUMP_INIT (seek, _IO_default_seek),
> -  JUMP_INIT (close, _IO_default_close),
> -  JUMP_INIT (stat, _IO_default_stat)
> -};
> -#endif
> -
> -static int
> -buffered_vfprintf (FILE *s, const CHAR_T *format, va_list args)
> -{
> -  CHAR_T buf[BUFSIZ];
> -  struct helper_file helper;
> -  FILE *hp = (FILE *) &helper._f;
> -  int result, to_flush;
> -
> -  /* Orient the stream.  */
> -#ifdef ORIENT
> -  ORIENT;
> -#endif
> -
> -  /* Initialize helper.  */
> -  helper._put_stream = s;
> -#ifdef COMPILE_WPRINTF
> -  hp->_wide_data = &helper._wide_data;
> -  _IO_wsetp (hp, buf, buf + sizeof buf / sizeof (CHAR_T));
> -  hp->_mode = 1;
> -#else
> -  _IO_setp (hp, buf, buf + sizeof buf);
> -  hp->_mode = -1;
> -#endif
> -  hp->_flags = _IO_MAGIC|_IO_NO_READS|_IO_USER_LOCK;
> -#if _IO_JUMPS_OFFSET
> -  hp->_vtable_offset = 0;
> -#endif
> -#ifdef _IO_MTSAFE_IO
> -  hp->_lock = NULL;
> -#endif
> -  hp->_flags2 = s->_flags2;
> -  _IO_JUMPS (&helper._f) = (struct _IO_jump_t *) &_IO_helper_jumps;
> -
> -  /* Now print to helper instead.  */
> -#ifndef COMPILE_WPRINTF
> -  result = _IO_vfprintf (hp, format, args);
> -#else
> -  result = vfprintf (hp, format, args);
> -#endif
> -
> -  /* Lock stream.  */
> -  __libc_cleanup_region_start (1, (void (*) (void *)) &_IO_funlockfile, s);
> -  _IO_flockfile (s);
> -
> -  /* Now flush anything from the helper to the S. */
> -#ifdef COMPILE_WPRINTF
> -  if ((to_flush = (hp->_wide_data->_IO_write_ptr
> -		   - hp->_wide_data->_IO_write_base)) > 0)
> -    {
> -      if ((int) _IO_sputn (s, hp->_wide_data->_IO_write_base, to_flush)
> -	  != to_flush)
> -	result = -1;
> -    }
> -#else
> -  if ((to_flush = hp->_IO_write_ptr - hp->_IO_write_base) > 0)
> -    {
> -      if ((int) _IO_sputn (s, hp->_IO_write_base, to_flush) != to_flush)
> -	result = -1;
> -    }
> -#endif
> -
> -  /* Unlock the stream.  */
> -  _IO_funlockfile (s);
> -  __libc_cleanup_region_end (0);
> -
> -  return result;
> -}
> -
> -#undef vfprintf
> -#ifdef COMPILE_WPRINTF
> -strong_alias (_IO_vfwprintf, __vfwprintf);
> -ldbl_weak_alias (_IO_vfwprintf, vfwprintf);
> -#else
> -ldbl_strong_alias (_IO_vfprintf_internal, vfprintf);
> -ldbl_hidden_def (_IO_vfprintf_internal, vfprintf)
> -ldbl_strong_alias (_IO_vfprintf_internal, _IO_vfprintf);
> -ldbl_hidden_def (_IO_vfprintf_internal, _IO_vfprintf)
> -#endif
> +ldbl_strong_alias (__vfprintf, _IO_vfprintf);
> +ldbl_strong_alias (__vfprintf, vfprintf);
> +ldbl_hidden_def (__vfprintf, vfprintf)

Ok.

> diff --git a/stdio-common/vfwprintf-internal.c b/stdio-common/vfwprintf-internal.c
> new file mode 100644
> index 0000000000..cefaf2fafe
> --- /dev/null
> +++ b/stdio-common/vfwprintf-internal.c
> @@ -0,0 +1,2 @@
> +#define COMPILE_WPRINTF	1
> +#include "vfprintf-internal.c"

Ok.

> diff --git a/stdio-common/vfwprintf.c b/stdio-common/vfwprintf.c
> index 2c3cd06fad..5d65eb7697 100644
> --- a/stdio-common/vfwprintf.c
> +++ b/stdio-common/vfwprintf.c
> @@ -1,3 +1,25 @@
> -#include <wctype.h>
> -#define COMPILE_WPRINTF	1
> -#include "vfprintf.c"
> +/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <libio/libioP.h>
> +
> +extern int
> +__vfwprintf (FILE *fp, const wchar_t *format, va_list ap)
> +{
> +  return __vfwprintf_internal (fp, format, ap, 0);
> +}
> +ldbl_weak_alias (__vfwprintf, vfwprintf);

Ok.

> diff --git a/stdio-common/vprintf.c b/stdio-common/vprintf.c
> index d459642dc8..0da8ba761e 100644
> --- a/stdio-common/vprintf.c
> +++ b/stdio-common/vprintf.c
> @@ -25,9 +25,9 @@
>  /* Write formatted output to stdout according to the
>     format string FORMAT, using the argument list in ARG.  */
>  int
> -__vprintf (const char *format, __gnuc_va_list arg)
> +__vprintf (const char *format, va_list ap)
>  {
> -  return vfprintf (stdout, format, arg);
> +  return __vfprintf_internal (stdout, format, ap, 0);
>  }
>  
>  ldbl_strong_alias (__vprintf, vprintf)

Ok.

> diff --git a/stdlib/strfrom-skeleton.c b/stdlib/strfrom-skeleton.c
> index 2840512cae..5b33604427 100644
> --- a/stdlib/strfrom-skeleton.c
> +++ b/stdlib/strfrom-skeleton.c
> @@ -106,7 +106,7 @@ STRFROM (char *dest, size_t size, const char *format, FLOAT f)
>      }
>  
>    /* The following code to prepare the virtual file has been adapted from the
> -     function _IO_vsnprintf from libio.  */
> +     function __vsnprintf_internal from libio.  */
>  
>    if (size == 0)
>      {

Ok.

> diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c
> index 468e23dec4..bda84af0bb 100644
> --- a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c
> +++ b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c
> @@ -166,7 +166,7 @@ __nldbl_vfprintf (FILE *s, const char *fmt, va_list ap)
>  {
>    int done;
>    set_no_long_double ();
> -  done = _IO_vfprintf (s, fmt, ap);
> +  done = __vfprintf_internal (s, fmt, ap, 0);
>    clear_no_long_double ();
>    return done;
>  }
> @@ -175,15 +175,16 @@ strong_alias (__nldbl_vfprintf, __nldbl__IO_vfprintf)
>  
>  int
>  attribute_compat_text_section
> -__nldbl__IO_vsprintf (char *string, const char *fmt, va_list ap)
> +__nldbl___vsprintf (char *string, const char *fmt, va_list ap)
>  {
>    int done;
>    __no_long_double = 1;
> -  done = _IO_vsprintf (string, fmt, ap);
> +  done = __vsprintf_internal (string, fmt, ap, 0);
>    __no_long_double = 0;
>    return done;
>  }
> -weak_alias (__nldbl__IO_vsprintf, __nldbl_vsprintf)
> +strong_alias (__nldbl___vsprintf, __nldbl__IO_vsprintf)
> +weak_alias (__nldbl___vsprintf, __nldbl_vsprintf)
>  libc_hidden_def (__nldbl_vsprintf)
>  
>  int
> @@ -193,7 +194,7 @@ __nldbl_obstack_vprintf (struct obstack *obstack, const char *fmt,
>  {
>    int done;
>    __no_long_double = 1;
> -  done = _IO_obstack_vprintf (obstack, fmt, ap);
> +  done = __obstack_vprintf_internal (obstack, fmt, ap, 0);
>    __no_long_double = 0;
>    return done;
>  }
> @@ -245,7 +246,7 @@ __nldbl_vasprintf (char **result_ptr, const char *fmt, va_list ap)
>  {
>    int res;
>    __no_long_double = 1;
> -  res = _IO_vasprintf (result_ptr, fmt, ap);
> +  res = __vasprintf_internal (result_ptr, fmt, ap, 0);
>    __no_long_double = 0;
>    return res;
>  }
> @@ -257,7 +258,7 @@ __nldbl_vdprintf (int d, const char *fmt, va_list arg)
>  {
>    int res;
>    set_no_long_double ();
> -  res = _IO_vdprintf (d, fmt, arg);
> +  res = __vdprintf_internal (d, fmt, arg, 0);
>    clear_no_long_double ();
>    return res;
>  }
> @@ -269,7 +270,7 @@ __nldbl_vfwprintf (FILE *s, const wchar_t *fmt, va_list ap)
>  {
>    int res;
>    set_no_long_double ();
> -  res = _IO_vfwprintf (s, fmt, ap);
> +  res = __vfwprintf_internal (s, fmt, ap, 0);
>    clear_no_long_double ();
>    return res;
>  }
> @@ -289,7 +290,7 @@ __nldbl_vsnprintf (char *string, size_t maxlen, const char *fmt,
>  {
>    int res;
>    __no_long_double = 1;
> -  res = _IO_vsnprintf (string, maxlen, fmt, ap);
> +  res = __vsnprintf_internal (string, maxlen, fmt, ap, 0);
>    __no_long_double = 0;
>    return res;
>  }
> @@ -303,7 +304,7 @@ __nldbl_vswprintf (wchar_t *string, size_t maxlen, const wchar_t *fmt,
>  {
>    int res;
>    __no_long_double = 1;
> -  res = _IO_vswprintf (string, maxlen, fmt, ap);
> +  res = __vswprintf_internal (string, maxlen, fmt, ap, 0);
>    __no_long_double = 0;
>    return res;
>  }
> 

Ok.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]