]> git.ipfire.org Git - thirdparty/gnulib.git/commitdiff
stdio-h: Work around [v][f]printf bugs in mingw with msvcrt.
authorBruno Haible <bruno@clisp.org>
Wed, 17 Sep 2025 07:31:31 +0000 (09:31 +0200)
committerBruno Haible <bruno@clisp.org>
Wed, 17 Sep 2025 09:31:34 +0000 (11:31 +0200)
Reported by 松延 英樹 <maznobu@gmail.com> in
<https://github.com/mlocati/gettext-iconv-windows/issues/52>.

* lib/stdio.in.h (gl_consolesafe_fprintf, gl_consolesafe_printf,
gl_consolesafe_vfprintf, gl_consolesafe_vprintf): New declarations.
(fprintf): When msvcrt is in use, use gl_consolesafe_fprintf.
(printf): When msvcrt is in use, use gl_consolesafe_printf.
(vfprintf): When msvcrt is in use, use gl_consolesafe_vfprintf.
(vprintf): When msvcrt is in use, use gl_consolesafe_vprintf.
* lib/stdio-consolesafe.c: Include fseterr.h.
(gl_consolesafe_fprintf, gl_consolesafe_printf, gl_consolesafe_vfprintf,
gl_consolesafe_vprintf): New functions.
* lib/stdio-write.c (vfprintf): When msvcrt is in use, use
gl_consolesafe_vfprintf.
* modules/stdio-h (Depends-on): Add fseterr.
* doc/posix-functions/fprintf.texi: Document the mingw bug.
* doc/posix-functions/printf.texi: Likewise.
* doc/posix-functions/vfprintf.texi: Likewise.
* doc/posix-functions/vprintf.texi: Likewise.

ChangeLog
doc/posix-functions/fprintf.texi
doc/posix-functions/printf.texi
doc/posix-functions/vfprintf.texi
doc/posix-functions/vprintf.texi
lib/stdio-consolesafe.c
lib/stdio-write.c
lib/stdio.in.h
modules/stdio-h

index 03b2f5bc3be8e9ab975ee7d34d4e755932eae4e7..ab4794a80e018e9ae2e53cdbddd1a0a7a5391eb0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2025-09-17  Bruno Haible  <bruno@clisp.org>
+
+       stdio-h: Work around [v][f]printf bugs in mingw with msvcrt.
+       Reported by 松延 英樹 <maznobu@gmail.com> in
+       <https://github.com/mlocati/gettext-iconv-windows/issues/52>.
+       * lib/stdio.in.h (gl_consolesafe_fprintf, gl_consolesafe_printf,
+       gl_consolesafe_vfprintf, gl_consolesafe_vprintf): New declarations.
+       (fprintf): When msvcrt is in use, use gl_consolesafe_fprintf.
+       (printf): When msvcrt is in use, use gl_consolesafe_printf.
+       (vfprintf): When msvcrt is in use, use gl_consolesafe_vfprintf.
+       (vprintf): When msvcrt is in use, use gl_consolesafe_vprintf.
+       * lib/stdio-consolesafe.c: Include fseterr.h.
+       (gl_consolesafe_fprintf, gl_consolesafe_printf, gl_consolesafe_vfprintf,
+       gl_consolesafe_vprintf): New functions.
+       * lib/stdio-write.c (vfprintf): When msvcrt is in use, use
+       gl_consolesafe_vfprintf.
+       * modules/stdio-h (Depends-on): Add fseterr.
+       * doc/posix-functions/fprintf.texi: Document the mingw bug.
+       * doc/posix-functions/printf.texi: Likewise.
+       * doc/posix-functions/vfprintf.texi: Likewise.
+       * doc/posix-functions/vprintf.texi: Likewise.
+
 2025-09-17  Bruno Haible  <bruno@clisp.org>
 
        stdio-h: Work around fwrite bug in msvcrt.
index 4eebaafd8f043d5dc79324f65bb14425663a8a37..dbace97e180aafa9c6136a645533327a2b9eaea8 100644 (file)
@@ -11,6 +11,16 @@ Gnulib module: fprintf-posix or fprintf-gnu or stdio-h, nonblocking, sigpipe
 @mindex nonblocking
 @mindex sigpipe
 
+Portability problems fixed by either Gnulib module @code{stdio-h} or @code{fprintf-posix} or @code{fprintf-gnu}:
+@itemize
+@item
+This function does not support non-ASCII characters in double-byte encoding,
+corresponding to the locale, on some platforms:
+@c https://github.com/mlocati/gettext-iconv-windows/issues/52
+mingw with @code{__USE_MINGW_ANSI_STDIO} in combination with msvcrt,
+when the output goes to a Windows console.
+@end itemize
+
 Portability problems fixed by either Gnulib module @code{fprintf-posix} or @code{fprintf-gnu}:
 @itemize
 @item
index 4cf38b5ba60b90e7891da916cd23c50d3af3390d..8b33702a83b6a6b5d955996c96194155e3432b42 100644 (file)
@@ -11,6 +11,16 @@ Gnulib module: printf-posix or printf-gnu or stdio-h, nonblocking, sigpipe
 @mindex nonblocking
 @mindex sigpipe
 
+Portability problems fixed by either Gnulib module @code{stdio-h} or @code{fprintf-posix} or @code{fprintf-gnu}:
+@itemize
+@item
+This function does not support non-ASCII characters in double-byte encoding,
+corresponding to the locale, on some platforms:
+@c https://github.com/mlocati/gettext-iconv-windows/issues/52
+mingw with @code{__USE_MINGW_ANSI_STDIO} in combination with msvcrt,
+when the output goes to a Windows console.
+@end itemize
+
 Portability problems fixed by either Gnulib module @code{printf-posix} or @code{printf-gnu}:
 @itemize
 @item
index 53516d374c6744b78a969be653b094b2d9467cd3..8cee58b3d8541dc033e6ae5d2eb4d40a0500fcd2 100644 (file)
@@ -11,6 +11,16 @@ Gnulib module: vfprintf-posix or vfprintf-gnu or stdio-h, nonblocking, sigpipe
 @mindex nonblocking
 @mindex sigpipe
 
+Portability problems fixed by either Gnulib module @code{stdio-h} or @code{fprintf-posix} or @code{fprintf-gnu}:
+@itemize
+@item
+This function does not support non-ASCII characters in double-byte encoding,
+corresponding to the locale, on some platforms:
+@c https://github.com/mlocati/gettext-iconv-windows/issues/52
+mingw with @code{__USE_MINGW_ANSI_STDIO} in combination with msvcrt,
+when the output goes to a Windows console.
+@end itemize
+
 Portability problems fixed by either Gnulib module @code{vfprintf-posix} or @code{vfprintf-gnu}:
 @itemize
 @item
index 8b84f2f91ed0c033d2ffb9a549f0236df4042e52..7a867172e7edc27bb67d68109a1598ae77b77b4c 100644 (file)
@@ -11,6 +11,16 @@ Gnulib module: vprintf-posix or vprintf-gnu or stdio-h, nonblocking, sigpipe
 @mindex nonblocking
 @mindex sigpipe
 
+Portability problems fixed by either Gnulib module @code{stdio-h} or @code{fprintf-posix} or @code{fprintf-gnu}:
+@itemize
+@item
+This function does not support non-ASCII characters in double-byte encoding,
+corresponding to the locale, on some platforms:
+@c https://github.com/mlocati/gettext-iconv-windows/issues/52
+mingw with @code{__USE_MINGW_ANSI_STDIO} in combination with msvcrt,
+when the output goes to a Windows console.
+@end itemize
+
 Portability problems fixed by either Gnulib module @code{vprintf-posix} or @code{vprintf-gnu}:
 @itemize
 @item
index 5cd0b12297e1a51fc864ac5d05da4b3e7b01ec25..fbea20be2242d7c63286279570b7907bdbd80d85 100644 (file)
@@ -70,3 +70,80 @@ gl_consolesafe_fwrite (const void *ptr, size_t size, size_t nmemb, FILE *fp)
   size_t written = workaround_fwrite0 (tmp, nbytes, fp);
   return written / size;
 }
+
+#if defined __MINGW32__ && __USE_MINGW_ANSI_STDIO
+
+# include "fseterr.h"
+
+/* Bypass the functions __mingw_[v][f]printf, that trigger a bug in msvcrt,
+   but without losing the support for modern format specifiers added by
+   __mingw_*printf.  */
+
+int
+gl_consolesafe_fprintf (FILE *restrict fp, const char *restrict format, ...)
+{
+  va_list args;
+  char *tmpstring;
+  va_start (args, format);
+  int result = vasprintf (&tmpstring, format, args);
+  va_end (args);
+  if (result >= 0)
+    {
+      if (workaround_fwrite0 (tmpstring, result, fp) < result)
+        result = -1;
+    }
+  else
+    fseterr (fp);
+  return result;
+}
+
+int
+gl_consolesafe_printf (const char *restrict format, ...)
+{
+  va_list args;
+  char *tmpstring;
+  va_start (args, format);
+  int result = vasprintf (&tmpstring, format, args);
+  va_end (args);
+  if (result >= 0)
+    {
+      if (workaround_fwrite0 (tmpstring, result, stdout) < result)
+        result = -1;
+    }
+  else
+    fseterr (stdout);
+  return result;
+}
+
+int
+gl_consolesafe_vfprintf (FILE *restrict fp,
+                         const char *restrict format, va_list args)
+{
+  char *tmpstring;
+  int result = vasprintf (&tmpstring, format, args);
+  if (result >= 0)
+    {
+      if (workaround_fwrite0 (tmpstring, result, fp) < result)
+        result = -1;
+    }
+  else
+    fseterr (fp);
+  return result;
+}
+
+int
+gl_consolesafe_vprintf (const char *restrict format, va_list args)
+{
+  char *tmpstring;
+  int result = vasprintf (&tmpstring, format, args);
+  if (result >= 0)
+    {
+      if (workaround_fwrite0 (tmpstring, result, stdout) < result)
+        result = -1;
+    }
+  else
+    fseterr (stdout);
+  return result;
+}
+
+#endif
index 1115111eda54de454943a7dab65ce15b53eba04e..59ba8fc4c348835e54ede7b363ef58ad7e674d24 100644 (file)
@@ -162,6 +162,9 @@ vprintf (const char *format, va_list args)
 int
 vfprintf (FILE *stream, const char *format, va_list args)
 #undef vfprintf
+#if defined __MINGW32__ && !defined _UCRT && __USE_MINGW_ANSI_STDIO
+# define vfprintf gl_consolesafe_vfprintf
+#endif
 {
   CALL_WITH_SIGPIPE_EMULATION (int, vfprintf (stream, format, args), ret == EOF)
 }
index 08db0290cda9942094ebb97a9448fe3b745dd9ca..f3ab7969d198006d2bd9da52dc7d437c5ae26370 100644 (file)
 _GL_FUNCDECL_SYS (gl_consolesafe_fwrite, size_t,
                   (const void *ptr, size_t size, size_t nmemb, FILE *fp),
                   _GL_ARG_NONNULL ((1, 4)));
+# if defined __MINGW32__
+_GL_FUNCDECL_SYS (gl_consolesafe_fprintf, int,
+                  (FILE *restrict fp, const char *restrict format, ...),
+                  _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
+                  _GL_ARG_NONNULL ((1, 2)));
+_GL_FUNCDECL_SYS (gl_consolesafe_printf, int,
+                  (const char *restrict format, ...),
+                  _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 2)
+                  _GL_ARG_NONNULL ((1)));
+_GL_FUNCDECL_SYS (gl_consolesafe_vfprintf, int,
+                  (FILE *restrict fp,
+                   const char *restrict format, va_list args),
+                  _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
+                  _GL_ARG_NONNULL ((1, 2)));
+_GL_FUNCDECL_SYS (gl_consolesafe_vprintf, int,
+                  (const char *restrict format, va_list args),
+                  _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 0)
+                  _GL_ARG_NONNULL ((1)));
+# endif
 #endif
 
 
@@ -615,6 +634,11 @@ _GL_CXXALIAS_SYS (fprintf, int,
 # if __GLIBC__ >= 2
 _GL_CXXALIASWARN (fprintf);
 # endif
+#elif defined __MINGW32__ && !defined _UCRT && __USE_MINGW_ANSI_STDIO
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#  undef fprintf
+#  define fprintf gl_consolesafe_fprintf
+# endif
 #endif
 #if !@GNULIB_FPRINTF_POSIX@ && defined GNULIB_POSIXCHECK
 # if !GNULIB_overrides_fprintf
@@ -1337,6 +1361,11 @@ _GL_CXXALIAS_SYS (printf, int, (const char *restrict format, ...));
 # if __GLIBC__ >= 2
 _GL_CXXALIASWARN (printf);
 # endif
+#elif defined __MINGW32__ && !defined _UCRT && __USE_MINGW_ANSI_STDIO
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#  undef printf
+#  define printf gl_consolesafe_printf
+# endif
 #endif
 #if !@GNULIB_PRINTF_POSIX@ && defined GNULIB_POSIXCHECK
 # if !GNULIB_overrides_printf
@@ -1889,6 +1918,11 @@ _GL_CXXALIAS_SYS_CAST (vfprintf, int,
 # if __GLIBC__ >= 2
 _GL_CXXALIASWARN (vfprintf);
 # endif
+#elif defined __MINGW32__ && !defined _UCRT && __USE_MINGW_ANSI_STDIO
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#  undef vfprintf
+#  define vfprintf gl_consolesafe_vfprintf
+# endif
 #endif
 #if !@GNULIB_VFPRINTF_POSIX@ && defined GNULIB_POSIXCHECK
 # if !GNULIB_overrides_vfprintf
@@ -1970,6 +2004,11 @@ _GL_CXXALIAS_SYS_CAST (vprintf, int,
 # if __GLIBC__ >= 2
 _GL_CXXALIASWARN (vprintf);
 # endif
+#elif defined __MINGW32__ && !defined _UCRT && __USE_MINGW_ANSI_STDIO
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#  undef vprintf
+#  define vprintf gl_consolesafe_vprintf
+# endif
 #endif
 #if !@GNULIB_VPRINTF_POSIX@ && defined GNULIB_POSIXCHECK
 # if !GNULIB_overrides_vprintf
index 02a08688ec6577e6744cd22a4aff783908cd85d4..619d8684301e8399451344f5e1e68e549deef613 100644 (file)
@@ -20,6 +20,7 @@ ssize_t
 stddef-h
 sys_types-h
 stdckdint-h
+fseterr
 
 configure.ac-early:
 gl_STDIO_H_EARLY