[v2,5/8] Add __v*printf_internal with flags arguments.

Message ID 20181029121650.24544-6-gabriel@inconstante.eti.br
State Superseded
Headers

Commit Message

Gabriel F. T. Gomes Oct. 29, 2018, 12:16 p.m. UTC
  From: Zack Weinberg <zackw@panix.com>

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.
	(LDBL_IS_DBL, DO_FORTIFY): New macros.	Throughout, use
	LDBL_IS_DBL instead of __ldbl_is_dbl, and DO_FORTIFY instead of
	checking _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.

Signed-off-by: Zack Weinberg <zackw@panix.com>
Signed-off-by: Gabriel F. T. Gomes <gabriel@inconstante.eti.br>
---
 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                          |   40 +-
 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-internal.c        | 2366 +++++++++++++++++++++++++++++++
 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, 2544 insertions(+), 2466 deletions(-)
 create mode 100644 stdio-common/vfprintf-internal.c
 create mode 100644 stdio-common/vfwprintf-internal.c
  

Comments

Adhemerval Zanella Nov. 7, 2018, 6:53 p.m. UTC | #1
On 29/10/2018 09:16, Gabriel F. T. Gomes wrote:
> From: Zack Weinberg <zackw@panix.com>
> 
> 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.

Look good in general with some nits below.

> 
> 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.
> 	(LDBL_IS_DBL, DO_FORTIFY): New macros.	Throughout, use
> 	LDBL_IS_DBL instead of __ldbl_is_dbl, and DO_FORTIFY instead of
> 	checking _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.
> 
> Signed-off-by: Zack Weinberg <zackw@panix.com>
> Signed-off-by: Gabriel F. T. Gomes <gabriel@inconstante.eti.br>

We don't use DCO, but copyright assignments.

> ---
>  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                          |   40 +-
>  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-internal.c        | 2366 +++++++++++++++++++++++++++++++
>  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, 2544 insertions(+), 2466 deletions(-)
>  create mode 100644 stdio-common/vfprintf-internal.c
>  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)

Ok.

> 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;
>  }

Ok.

> 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)

Ok.

> 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 f90fb2c050..c762cf9b67 100644
> --- a/libio/libioP.h
> +++ b/libio/libioP.h
> @@ -658,12 +658,40 @@ 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.  */
> +#define PRINTF_LDBL_IS_DBL 0x0001
> +#define PRINTF_FORTIFY     0x0002

Please extend the flags comment to describe what they do.

>  
>  extern size_t _IO_getline (FILE *,char *, size_t, int, int);
>  libc_hidden_proto (_IO_getline)
> 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;
> 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 -u stdio-common/vfprintf.c.old stdio-common/vfprintf-internal.c.new
> --- stdio-common/vfprintf.c.old	2018-10-26 11:09:08.538713613 -0300
> +++ stdio-common/vfprintf-internal.c.new	2018-10-26 11:08:45.130667960 -0300
> @@ -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.  */
> @@ -63,6 +67,8 @@
>  	}								      \
>      } while (0)
>  #define UNBUFFERED_P(S) ((S)->_flags & _IO_UNBUFFERED)
> +#define LDBL_IS_DBL (__glibc_unlikely ((mode_flags & PRINTF_LDBL_IS_DBL) != 0))
> +#define DO_FORTIFY  ((mode_flags & PRINTF_FORTIFY) != 0)

Do we really gain anything using these defines? I tend to frown on macros
that use internal named variables instead of set them as arguments. Also
this is quite short, I think it is more readable to just use the comparison
directly.

>  
>  #define done_add(val) \
>    do {									      \
> @@ -78,7 +84,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 +111,7 @@
>  # 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 +753,7 @@
>  									      \
>  	if (fspec == NULL)						      \
>  	  {								      \
> -	    if (__ldbl_is_dbl)						      \
> +	    if (LDBL_IS_DBL)						      \
>  	      is_long_double = 0;					      \
>  									      \
>  	    struct printf_info info = { .prec = prec,			      \
> @@ -778,7 +784,7 @@
>  	else								      \
>  	  {								      \
>  	    ptr = (const void *) &args_value[fspec->data_arg];		      \
> -	    if (__ldbl_is_dbl)						      \
> +	    if (LDBL_IS_DBL)						      \
>  	      {								      \
>  		fspec->data_arg_type = PA_DOUBLE;			      \
>  		fspec->info.is_long_double = 0;				      \
> @@ -808,7 +814,7 @@
>  									      \
>  	if (fspec == NULL)						      \
>  	  {								      \
> -	    if (__ldbl_is_dbl)						      \
> +	    if (LDBL_IS_DBL)						      \
>  	      is_long_double = 0;					      \
>  									      \
>  	    struct printf_info info = { .prec = prec,			      \
> @@ -838,7 +844,7 @@
>  	else								      \
>  	  {								      \
>  	    ptr = (const void *) &args_value[fspec->data_arg];		      \
> -	    if (__ldbl_is_dbl)						      \
> +	    if (LDBL_IS_DBL)						      \
>  	      fspec->info.is_long_double = 0;				      \
>  	    /* Not supported by *printf functions.  */			      \
>  	    fspec->info.is_binary128 = 0;				      \
> @@ -891,7 +897,7 @@
>        /* NOTREACHED */							      \
>  									      \
>      LABEL (form_number):						      \
> -      if (s->_flags2 & _IO_FLAGS2_FORTIFY)				      \
> +      if (DO_FORTIFY)							      \
>  	{								      \
>  	  if (! readonly_format)					      \
>  	    {								      \
> @@ -1214,7 +1220,8 @@
>  #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 +1230,9 @@
>  			      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 +1244,7 @@
>  
>  /* 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 +1282,12 @@
>       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 +1308,7 @@
>    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 +1697,7 @@
>      }
>    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 +1714,8 @@
>  		   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 +1805,7 @@
>         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, DO_FORTIFY ? '\xff' : '\0',
>  	    nargs * sizeof (*args_type));
>    }
>  
> @@ -1856,7 +1872,7 @@
>        case PA_FLOAT:				/* Promoted.  */
>  	T (PA_DOUBLE, pa_double, double);
>        case PA_DOUBLE|PA_FLAG_LONG_DOUBLE:
> -	if (__ldbl_is_dbl)
> +	if (LDBL_IS_DBL)
>  	  {
>  	    args_value[cnt].pa_double = va_arg (*ap_savep, double);
>  	    args_type[cnt] &= ~PA_FLAG_LONG_DOUBLE;
> @@ -1884,7 +1900,7 @@
>        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 (DO_FORTIFY);
>  	__libc_fatal ("*** invalid %N$ use detected ***\n");
>        }
>  
> @@ -2285,7 +2301,8 @@
>  #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 +2335,7 @@
>    _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 +2364,3 @@
>  
>    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 -u /dev/null stdio-common/vfprintf.c.new
> --- /dev/null	2018-10-15 19:30:16.914999855 -0300
> +++ stdio-common/vfprintf.c.new	2018-10-26 11:08:58.758694540 -0300
> @@ -0,0 +1,27 @@
> +/* 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
> +__vfprintf (FILE *fp, const char *format, va_list ap)
> +{
> +  return __vfprintf_internal (fp, format, ap, 0);
> +}
> +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.
  
Adhemerval Zanella Nov. 8, 2018, 5:24 p.m. UTC | #2
On 07/11/2018 16:53, Adhemerval Zanella wrote:
> 
> 
> On 29/10/2018 09:16, Gabriel F. T. Gomes wrote:
>> From: Zack Weinberg <zackw@panix.com>
>> [...]
>> 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.

Please add a note that it fixes BZ#11319 by unifing both fortified and 
non-fortified vdprintf initialization.
  
Gabriel F. T. Gomes Nov. 15, 2018, 4:27 p.m. UTC | #3
On Thu, 08 Nov 2018, Adhemerval Zanella wrote:

>Please add a note that it fixes BZ#11319 by unifing both fortified and 
>non-fortified vdprintf initialization.

I'll add this note to patch 7/8, since the fix is there.  Thanks for
checking and closing bug 20231, and for reopening 11319 and pointing it
out to me.
  

Patch

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;
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);
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)
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
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);
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);
 
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;
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';
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;
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
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;
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)
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)
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;
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) \
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)
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)
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
diff --git a/libio/libioP.h b/libio/libioP.h
index f90fb2c050..c762cf9b67 100644
--- a/libio/libioP.h
+++ b/libio/libioP.h
@@ -658,12 +658,40 @@  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.  */
+#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)
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)
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;
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)
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)
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)
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)
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;
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
 
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;
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;
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;
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);
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);
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;
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;
diff -u stdio-common/vfprintf.c.old stdio-common/vfprintf-internal.c.new
--- stdio-common/vfprintf.c.old	2018-10-26 11:09:08.538713613 -0300
+++ stdio-common/vfprintf-internal.c.new	2018-10-26 11:08:45.130667960 -0300
@@ -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.  */
@@ -63,6 +67,8 @@ 
 	}								      \
     } while (0)
 #define UNBUFFERED_P(S) ((S)->_flags & _IO_UNBUFFERED)
+#define LDBL_IS_DBL (__glibc_unlikely ((mode_flags & PRINTF_LDBL_IS_DBL) != 0))
+#define DO_FORTIFY  ((mode_flags & PRINTF_FORTIFY) != 0)
 
 #define done_add(val) \
   do {									      \
@@ -78,7 +84,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 +111,7 @@ 
 # 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 +753,7 @@ 
 									      \
 	if (fspec == NULL)						      \
 	  {								      \
-	    if (__ldbl_is_dbl)						      \
+	    if (LDBL_IS_DBL)						      \
 	      is_long_double = 0;					      \
 									      \
 	    struct printf_info info = { .prec = prec,			      \
@@ -778,7 +784,7 @@ 
 	else								      \
 	  {								      \
 	    ptr = (const void *) &args_value[fspec->data_arg];		      \
-	    if (__ldbl_is_dbl)						      \
+	    if (LDBL_IS_DBL)						      \
 	      {								      \
 		fspec->data_arg_type = PA_DOUBLE;			      \
 		fspec->info.is_long_double = 0;				      \
@@ -808,7 +814,7 @@ 
 									      \
 	if (fspec == NULL)						      \
 	  {								      \
-	    if (__ldbl_is_dbl)						      \
+	    if (LDBL_IS_DBL)						      \
 	      is_long_double = 0;					      \
 									      \
 	    struct printf_info info = { .prec = prec,			      \
@@ -838,7 +844,7 @@ 
 	else								      \
 	  {								      \
 	    ptr = (const void *) &args_value[fspec->data_arg];		      \
-	    if (__ldbl_is_dbl)						      \
+	    if (LDBL_IS_DBL)						      \
 	      fspec->info.is_long_double = 0;				      \
 	    /* Not supported by *printf functions.  */			      \
 	    fspec->info.is_binary128 = 0;				      \
@@ -891,7 +897,7 @@ 
       /* NOTREACHED */							      \
 									      \
     LABEL (form_number):						      \
-      if (s->_flags2 & _IO_FLAGS2_FORTIFY)				      \
+      if (DO_FORTIFY)							      \
 	{								      \
 	  if (! readonly_format)					      \
 	    {								      \
@@ -1214,7 +1220,8 @@ 
 #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 +1230,9 @@ 
 			      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 +1244,7 @@ 
 
 /* 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 +1282,12 @@ 
      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 +1308,7 @@ 
   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 +1697,7 @@ 
     }
   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 +1714,8 @@ 
 		   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 +1805,7 @@ 
        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, DO_FORTIFY ? '\xff' : '\0',
 	    nargs * sizeof (*args_type));
   }
 
@@ -1856,7 +1872,7 @@ 
       case PA_FLOAT:				/* Promoted.  */
 	T (PA_DOUBLE, pa_double, double);
       case PA_DOUBLE|PA_FLAG_LONG_DOUBLE:
-	if (__ldbl_is_dbl)
+	if (LDBL_IS_DBL)
 	  {
 	    args_value[cnt].pa_double = va_arg (*ap_savep, double);
 	    args_type[cnt] &= ~PA_FLAG_LONG_DOUBLE;
@@ -1884,7 +1900,7 @@ 
       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 (DO_FORTIFY);
 	__libc_fatal ("*** invalid %N$ use detected ***\n");
       }
 
@@ -2285,7 +2301,8 @@ 
 #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 +2335,7 @@ 
   _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 +2364,3 @@ 
 
   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
diff -u /dev/null stdio-common/vfprintf.c.new
--- /dev/null	2018-10-15 19:30:16.914999855 -0300
+++ stdio-common/vfprintf.c.new	2018-10-26 11:08:58.758694540 -0300
@@ -0,0 +1,27 @@ 
+/* 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
+__vfprintf (FILE *fp, const char *format, va_list ap)
+{
+  return __vfprintf_internal (fp, format, ap, 0);
+}
+ldbl_strong_alias (__vfprintf, _IO_vfprintf);
+ldbl_strong_alias (__vfprintf, vfprintf);
+ldbl_hidden_def (__vfprintf, vfprintf)
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"
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);
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)
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)
     {
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;
 }