Patchwork [5/9] Add __v*printf_internal with flags arguments.

login
register
mail settings
Submitter Zack Weinberg
Date March 7, 2018, 7:32 p.m.
Message ID <20180307193205.4751-6-zackw@panix.com>
Download mbox | patch
Permalink /patch/26233/
State New
Headers show

Comments

Zack Weinberg - March 7, 2018, 7:32 p.m.
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
*is* exported, so that one sticks around.

	* 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.
	* 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 for _IO_vfprintf.
	Remove declaration of _IO_vfwprintf.
	* libio/iolibio.h: Remove libc_hidden_proto for _IO_vsprintf.
	Remove declarations of _IO_vswprintf, _IO_obstack_printf, and
	_IO_obstack_printf.
	* include/stdio.h: Add libc_hidden_proto for __vsnprintf and
	prototype for __vasprintf.

	* argp/argp-fmtstream.c: Use __vsnprintf, not _IO_vsnprintf.
	* argp/argp-help.c: Use __vasprintf, not _IO_vasprintf.
	* argp/argp-namefrob.c: Update to match.
---
 argp/argp-fmtstream.c                              |    1 -
 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                                    |    4 +
 libio/fwprintf.c                                   |    2 +-
 libio/iolibio.h                                    |    7 -
 libio/iovdprintf.c                                 |   13 +-
 libio/iovsprintf.c                                 |   16 +-
 libio/libio.h                                      |    3 -
 libio/libioP.h                                     |   32 +-
 libio/obprintf.c                                   |   19 +-
 libio/swprintf.c                                   |    2 +-
 libio/vasprintf.c                                  |   20 +-
 libio/vsnprintf.c                                  |   17 +-
 libio/vswprintf.c                                  |   16 +-
 libio/vwprintf.c                                   |    2 +-
 libio/wprintf.c                                    |    2 +-
 stdio-common/Makefile                              |    3 +-
 stdio-common/asprintf.c                            |    7 +-
 stdio-common/dprintf.c                             |    5 +-
 stdio-common/fprintf.c                             |    2 +-
 stdio-common/fxprintf.c                            |    4 +-
 stdio-common/printf.c                              |    3 +-
 stdio-common/snprintf.c                            |    4 +-
 stdio-common/sprintf.c                             |    4 +-
 stdio-common/{vfprintf.c => vfprintf-internal.c}   |   68 +-
 stdio-common/vfprintf.c                            |   27 +
 stdio-common/{vfwprintf.c => vfwprintf-internal.c} |    3 +-
 stdio-common/vfwprintf.c                           |   25 +
 stdio-common/vprintf.c                             |    4 +-
 stdlib/strfrom-skeleton.c                          |    2 +-
 sysdeps/ieee754/ldbl-opt/nldbl-compat.c |   21 +-
 43 files changed, 210 insertions(+), 131 deletions(-)
 create mode 100644 stdio-common/vfprintf.c
 create mode 100644 stdio-common/vfwprintf.c
Gabriel F. T. Gomes - March 26, 2018, 3:40 p.m.
On Wed, 07 Mar 2018, Zack Weinberg wrote:

> 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)
  ~~~~~~~~~~~~~~~~
Spaces that could be converted to tabs.

> 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)
  ~~~~~~~~~~~~~~~~
Likewise.

>--- a/libio/libio.h
>+++ b/libio/libio.h
>@@ -298,8 +298,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);

In the second patch in this series, you mentioned that _IO_vfwscanf was
being kept because external callers could theoretically exist.  I don't
have the necessary background to understand why this doesn't apply to
_IO_vfwprintf, too.  Doesn't it?

>+/* 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);
>+extern int __vfwprintf_internal (FILE *fp, const wchar_t *format, va_list ap,
>+                                 unsigned int mode_flags);
>+
>+extern int __vasprintf_internal (char **result_ptr, const char *format,
>+                                 va_list ap, unsigned int mode_flags);
>+extern int __vdprintf_internal (int d, const char *format, va_list ap,
>+                                unsigned int mode_flags);
>+extern int __obstack_vprintf_internal (struct obstack *ob, const char *fmt,
>+                                       va_list ap, unsigned int mode_flags);
>+
>+extern int __vsprintf_internal (char *string, const char *format, va_list ap,
>+                                unsigned int mode_flags);
>+extern int __vsnprintf_internal (char *string, size_t maxlen,
>+                                 const char *format, va_list ap,
>+                                 unsigned int mode_flags);
>+extern int __vswprintf_internal (wchar_t *string, size_t maxlen,
>+                                 const wchar_t *format, va_list ap,
>+                                 unsigned int mode_flags);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In this block of function prototypes, some spaces that could be converted
to tabs.

> 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)
  ~~~~~~~~~~~~~~~~~~~~~~~~
Likewise.

>-  result = _IO_vfprintf (&new_f.ofile.file.file, format, args);
>+  result = __vfprintf_internal (&new_f.ofile.file.file, format, args,
>+                                mode_flags);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Likewise.

> 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)
  ~~~~~~~~~~~~~~~~
Likewise.

> 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)
  ~~~~~~~~~~~~~~~~
Likewise.

>+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_hidden_def (___vsnprintf, __vsnprintf)
>+ldbl_weak_alias (___vsnprintf, vsnprintf)

OK.

> /* 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)
  ~~~~~~~~~~~~~~~~~~~~~~~~
Spaces instead of tabs.

>@@ -1223,7 +1230,9 @@ static int printf_positional (FILE *s,
> 			      va_list ap, va_list *ap_savep, int done,
> 			      int nspecs_done, const UCHAR_T *lead_str_end,
> 			      CHAR_T *work_buffer, int save_errno,
>-			      const char *grouping, THOUSANDS_SEP_T);
>+			      const char *grouping,
>+                              THOUSANDS_SEP_T thousands_sep,
>+                              unsigned int mode_flags);
  ~~~~~~~~~~~~~~~~~~~~~~~~
Likewise.

>@@ -1699,7 +1714,8 @@ printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
> 		   va_list ap, va_list *ap_savep, int done, int nspecs_done,
> 		   const UCHAR_T *lead_str_end,
> 		   CHAR_T *work_buffer, int save_errno,
>-		   const char *grouping, THOUSANDS_SEP_T thousands_sep)
>+		   const char *grouping, THOUSANDS_SEP_T thousands_sep,
>+                   unsigned int mode_flags)
  ~~~~~~~~~~~~~~~~
Likewise.

> 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)
  ~~~~~~~~~~~~~~~~
Likewise.

>   /* 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);

OK.

>--- 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 from libio.  */
                ~~~~~~~~~~~
It would be more precise to mention __vsnprint_internal.

Patch

diff --git a/argp/argp-fmtstream.c b/argp/argp-fmtstream.c
index e43a0c7cf1..2be2f521ad 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
diff --git a/argp/argp-help.c b/argp/argp-help.c
index 2b6b0775d6..9f25338ca0 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 (&buf, fmt, ap) < 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 (&buf, fmt, ap) < 0)
 		buf = NULL;
 
 	      __fxprintf (stream, ": %s", buf);
diff --git a/argp/argp-namefrob.h b/argp/argp-namefrob.h
index 5588fe172a..60381e7cd8 100644
--- a/argp/argp-namefrob.h
+++ b/argp/argp-namefrob.h
@@ -98,6 +98,8 @@ 
 #define __strerror_r strerror_r
 #undef __strndup
 #define __strndup strndup
+#undef __vasprintf
+#define __vasprintf vasprintf
 #undef __vsnprintf
 #define __vsnprintf vsnprintf
 
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 46603d9538..6136694431 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 f140813ad6..93b9385524 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -17,6 +17,10 @@  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)));
+libc_hidden_proto (__vsnprintf)
+extern int __vasprintf (char **__result_ptr, const char *__restrict __format,
+			va_list args)
+     __attribute__ ((__format__ (__printf__, 2, 0)));
 extern int __vfscanf (FILE *__restrict __s,
 		      const char *__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 69e1c0e699..3a6a27a58c 100644
--- a/libio/iolibio.h
+++ b/libio/iolibio.h
@@ -51,14 +51,7 @@  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..afdeff056d 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..cf4b9973a7 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..1025f3343e 100644
--- a/libio/libio.h
+++ b/libio/libio.h
@@ -298,8 +298,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 +317,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 0772fb1431..17eda383d3 100644
--- a/libio/libioP.h
+++ b/libio/libioP.h
@@ -658,12 +658,32 @@  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);
+extern int __vfwprintf_internal (FILE *fp, const wchar_t *format, va_list ap,
+                                 unsigned int mode_flags);
+
+extern int __vasprintf_internal (char **result_ptr, const char *format,
+                                 va_list ap, unsigned int mode_flags);
+extern int __vdprintf_internal (int d, const char *format, va_list ap,
+                                unsigned int mode_flags);
+extern int __obstack_vprintf_internal (struct obstack *ob, const char *fmt,
+                                       va_list ap, unsigned int mode_flags);
+
+extern int __vsprintf_internal (char *string, const char *format, va_list ap,
+                                unsigned int mode_flags);
+extern int __vsnprintf_internal (char *string, size_t maxlen,
+                                 const char *format, va_list ap,
+                                 unsigned int mode_flags);
+extern int __vswprintf_internal (wchar_t *string, size_t maxlen,
+                                 const wchar_t *format, va_list ap,
+                                 unsigned int mode_flags);
+
+/* 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..6bb51a411a 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 08218ddbe7..5307f95fd5 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 = (_IO_alloc_type) malloc;
   sf._s._free_buffer = (_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..8a5d0bacf3 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,18 @@  _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_hidden_def (___vsnprintf, __vsnprintf)
+ldbl_weak_alias (___vsnprintf, vsnprintf)
diff --git a/libio/vswprintf.c b/libio/vswprintf.c
index bcc473d115..71d4e6ccd4 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 b7b1f01bdd..1c657efa86 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..5f5ca6c4a6 100644
--- a/stdio-common/asprintf.c
+++ b/stdio-common/asprintf.c
@@ -16,11 +16,8 @@ 
    <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 +29,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 c4a1146b20..d74364c7f5 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 --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf-internal.c
similarity index 98%
rename from stdio-common/vfprintf.c
rename to stdio-common/vfprintf-internal.c
index ae412e4b84..d8716f4f07 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf-internal.c
@@ -41,6 +41,10 @@ 
 
 #include <libioP.h>
 
+#ifdef COMPILE_WPRINTF
+#include <wctype.h>
+#endif
+
 /* In some cases we need extra space for all the output which is not
    counted in the width of the string. We assume 32 characters is
    enough.  */
@@ -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 @@  typedef const char *THOUSANDS_SEP_T;
 # define ORIENT		if (_IO_vtable_offset (s) == 0 && _IO_fwide (s, -1) != -1)\
 			  return -1
 #else
-# define vfprintf	_IO_vfwprintf
+# define vfprintf	__vfwprintf_internal
 # define CHAR_T		wchar_t
 /* This is a hack!!!  There should be a type uwchar_t.  */
 # define UCHAR_T	unsigned int /* uwchar_t */
@@ -747,7 +753,7 @@  static const uint8_t jump_table[] =
 									      \
 	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 @@  static const uint8_t jump_table[] =
 	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 @@  static const uint8_t jump_table[] =
 									      \
 	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 @@  static const uint8_t jump_table[] =
 	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 @@  static const uint8_t jump_table[] =
       /* NOTREACHED */							      \
 									      \
     LABEL (form_number):						      \
-      if (s->_flags2 & _IO_FLAGS2_FORTIFY)				      \
+      if (DO_FORTIFY)							      \
 	{								      \
 	  if (! readonly_format)					      \
 	    {								      \
@@ -1214,7 +1220,8 @@  static const uint8_t jump_table[] =
 #endif
 
 /* Helper function to provide temporary buffering for unbuffered streams.  */
-static int buffered_vfprintf (FILE *stream, const CHAR_T *fmt, va_list)
+static int buffered_vfprintf (FILE *stream, const CHAR_T *fmt, va_list,
+                              unsigned int)
      __THROW __attribute__ ((noinline));
 
 /* Handle positional format specifiers.  */
@@ -1223,7 +1230,9 @@  static int printf_positional (FILE *s,
 			      va_list ap, va_list *ap_savep, int done,
 			      int nspecs_done, const UCHAR_T *lead_str_end,
 			      CHAR_T *work_buffer, int save_errno,
-			      const char *grouping, THOUSANDS_SEP_T);
+			      const char *grouping,
+                              THOUSANDS_SEP_T thousands_sep,
+                              unsigned int mode_flags);
 
 /* Handle unknown format specifier.  */
 static int printf_unknown (FILE *, const struct printf_info *,
@@ -1235,7 +1244,7 @@  static CHAR_T *group_number (CHAR_T *, CHAR_T *, CHAR_T *, const char *,
 
 /* The function itself.  */
 int
-vfprintf (FILE *s, const CHAR_T *format, va_list ap)
+vfprintf (FILE *s, const CHAR_T *format, va_list ap, unsigned int mode_flags)
 {
   /* The character used as thousands separator.  */
   THOUSANDS_SEP_T thousands_sep = 0;
@@ -1273,6 +1282,12 @@  vfprintf (FILE *s, const CHAR_T *format, va_list ap)
      0 if unknown.  */
   int readonly_format = 0;
 
+  /* Temporarily honor environmental settings.  */
+  if (__ldbl_is_dbl)
+    mode_flags |= PRINTF_LDBL_IS_DBL;
+  if (s->_flags2 & _IO_FLAGS2_FORTIFY)
+    mode_flags |= PRINTF_FORTIFY;
+
   /* Orient the stream.  */
 #ifdef ORIENT
   ORIENT;
@@ -1293,7 +1308,7 @@  vfprintf (FILE *s, const CHAR_T *format, va_list ap)
   if (UNBUFFERED_P (s))
     /* Use a helper function which will allocate a local temporary buffer
        for the stream and then call us again.  */
-    return buffered_vfprintf (s, format, ap);
+    return buffered_vfprintf (s, format, ap, mode_flags);
 
   /* Initialize local variables.  */
   done = 0;
@@ -1682,7 +1697,7 @@  do_positional:
     }
   done = printf_positional (s, format, readonly_format, ap, &ap_save,
 			    done, nspecs_done, lead_str_end, work_buffer,
-			    save_errno, grouping, thousands_sep);
+			    save_errno, grouping, thousands_sep, mode_flags);
 
  all_done:
   if (__glibc_unlikely (workstart != NULL))
@@ -1699,7 +1714,8 @@  printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
 		   va_list ap, va_list *ap_savep, int done, int nspecs_done,
 		   const UCHAR_T *lead_str_end,
 		   CHAR_T *work_buffer, int save_errno,
-		   const char *grouping, THOUSANDS_SEP_T thousands_sep)
+		   const char *grouping, THOUSANDS_SEP_T thousands_sep,
+                   unsigned int mode_flags)
 {
   /* For positional argument handling.  */
   struct scratch_buffer specsbuf;
@@ -1789,7 +1805,7 @@  printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
        now.  */
     args_size = &args_value[nargs].pa_int;
     args_type = &args_size[nargs];
-    memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0',
+    memset (args_type, DO_FORTIFY ? '\xff' : '\0',
 	    nargs * sizeof (*args_type));
   }
 
@@ -1856,7 +1872,7 @@  printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
       case PA_FLOAT:				/* Promoted.  */
 	T (PA_DOUBLE, pa_double, double);
       case PA_DOUBLE|PA_FLAG_LONG_DOUBLE:
-	if (__ldbl_is_dbl)
+	if (LDBL_IS_DBL)
 	  {
 	    args_value[cnt].pa_double = va_arg (*ap_savep, double);
 	    args_type[cnt] &= ~PA_FLAG_LONG_DOUBLE;
@@ -1884,7 +1900,7 @@  printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
       case -1:
 	/* Error case.  Not all parameters appear in N$ format
 	   strings.  We have no way to determine their type.  */
-	assert (s->_flags2 & _IO_FLAGS2_FORTIFY);
+	assert (DO_FORTIFY);
 	__libc_fatal ("*** invalid %N$ use detected ***\n");
       }
 
@@ -2285,7 +2301,8 @@  static const struct _IO_jump_t _IO_helper_jumps libio_vtable =
 #endif
 
 static int
-buffered_vfprintf (FILE *s, const CHAR_T *format, va_list args)
+buffered_vfprintf (FILE *s, const CHAR_T *format, va_list args,
+                   unsigned int mode_flags)
 {
   CHAR_T buf[BUFSIZ];
   struct helper_file helper;
@@ -2318,11 +2335,7 @@  buffered_vfprintf (FILE *s, const CHAR_T *format, va_list args)
   _IO_JUMPS (&helper._f) = (struct _IO_jump_t *) &_IO_helper_jumps;
 
   /* Now print to helper instead.  */
-#ifndef COMPILE_WPRINTF
-  result = _IO_vfprintf (hp, format, args);
-#else
-  result = vfprintf (hp, format, args);
-#endif
+  result = vfprintf (hp, format, args, mode_flags);
 
   /* Lock stream.  */
   __libc_cleanup_region_start (1, (void (*) (void *)) &_IO_funlockfile, s);
@@ -2351,14 +2364,3 @@  buffered_vfprintf (FILE *s, const CHAR_T *format, va_list args)
 
   return result;
 }
-
-#undef vfprintf
-#ifdef COMPILE_WPRINTF
-strong_alias (_IO_vfwprintf, __vfwprintf);
-ldbl_weak_alias (_IO_vfwprintf, vfwprintf);
-#else
-ldbl_strong_alias (_IO_vfprintf_internal, vfprintf);
-ldbl_hidden_def (_IO_vfprintf_internal, vfprintf)
-ldbl_strong_alias (_IO_vfprintf_internal, _IO_vfprintf);
-ldbl_hidden_def (_IO_vfprintf_internal, _IO_vfprintf)
-#endif
diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
new file mode 100644
index 0000000000..13a10db99b
--- /dev/null
+++ b/stdio-common/vfprintf.c
@@ -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.c b/stdio-common/vfwprintf-internal.c
similarity index 33%
rename from stdio-common/vfwprintf.c
rename to stdio-common/vfwprintf-internal.c
index 2c3cd06fad..cefaf2fafe 100644
--- /dev/null
+++ b/stdio-common/vfwprintf-internal.c
@@ -1,3 +1,2 @@ 
-#include <wctype.h>
 #define COMPILE_WPRINTF	1
-#include "vfprintf.c"
+#include "vfprintf-internal.c"
diff --git a/stdio-common/vfwprintf.c b/stdio-common/vfwprintf.c
new file mode 100644
index 0000000000..5d65eb7697
--- /dev/null
+++ b/stdio-common/vfwprintf.c
@@ -0,0 +1,25 @@ 
+/* 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..c178780f08 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 from libio.  */
 
   if (size == 0)
     {
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c
index 15f212ffce..7e8af80d63 100644
--- a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c
@@ -165,7 +165,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;
 }
@@ -174,15 +174,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
@@ -192,7 +193,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;
 }
@@ -244,7 +245,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;
 }
@@ -256,7 +257,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;
 }
@@ -268,7 +269,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;
 }
@@ -288,7 +289,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;
 }
@@ -302,7 +303,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;
 }