Eli Zaretskii wrote:
> > The code in stdio-consolesafe.c is conditionalized with
> > __USE_MINGW_ANSI_STDIO.
> 
> mingw.org's MinGW defines that by default for a long time.
> 
> > Does your old mingw have the functions __mingw_[v][f]printf?
> 
> Yes.
> 
> > Do these functions in your old mingw output double-byte characters
> > one byte at a time?
> 
> I believe so, because they use fputc to output characters (bytes) one
> by one.
> 
> > Does your old mingw enable these functions under a different
> > condition than __USE_MINGW_ANSI_STDIO?
> 
> They can _also_ be enabled under a different condition, yes.  But I
> don't see how this is relevant.
> 
> > Does your old mingw have the vasprintf() function?
> 
> No, it doesn't.

OK, so I'm adding a vasprintf() replacement just for that use in
stdio-consolesafe.c and for mingw with __USE_MINGW_ANSI_STDIO.

Caveat: This code is not tested, and will not be tested in Gnulib's
usual test environments. So, feel welcome to review it and to report
issues if there are some.

>From 19de62ef025bc39cf759ebd20c6b4733c7e27f27 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Thu, 6 Nov 2025 20:16:45 +0100
Subject: [PATCH] stdio-windows: Add fallback code for very old mingw without
 vasprintf.

Reported by Eli Zaretskii <[email protected]> in
<https://lists.gnu.org/archive/html/emacs-devel/2025-11/msg00194.html>.

* lib/stdio-consolesafe.c (vasprintf) [!HAVE_VASPRINTF]: New function.
* modules/stdio-windows (configure.ac): Test whether vasprintf exists.
---
 ChangeLog               |  8 +++++++
 lib/stdio-consolesafe.c | 50 +++++++++++++++++++++++++++++++++++++++++
 modules/stdio-windows   |  1 +
 3 files changed, 59 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index ab93d83349..551a7acae0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2025-11-06  Bruno Haible  <[email protected]>
+
+	stdio-windows: Add fallback code for very old mingw without vasprintf.
+	Reported by Eli Zaretskii <[email protected]> in
+	<https://lists.gnu.org/archive/html/emacs-devel/2025-11/msg00194.html>.
+	* lib/stdio-consolesafe.c (vasprintf) [!HAVE_VASPRINTF]: New function.
+	* modules/stdio-windows (configure.ac): Test whether vasprintf exists.
+
 2025-11-06  Bruno Haible  <[email protected]>
 
 	stdio-windows: New module.
diff --git a/lib/stdio-consolesafe.c b/lib/stdio-consolesafe.c
index fbea20be22..b5ca8cc012 100644
--- a/lib/stdio-consolesafe.c
+++ b/lib/stdio-consolesafe.c
@@ -75,6 +75,56 @@ gl_consolesafe_fwrite (const void *ptr, size_t size, size_t nmemb, FILE *fp)
 
 # include "fseterr.h"
 
+# if !HAVE_VASPRINTF
+
+#  include <errno.h>
+#  include <stdarg.h>
+
+/* The old mingw (before mingw-w64) does not have the vasprintf function.
+   Define a suitable replacement here, that supports the same format
+   specifiers as the mingw *printf functions.  */
+
+static int
+vasprintf (char **resultp, const char *format, va_list args)
+{
+  /* First try: Use a stack-allocated buffer.  */
+  char buf[2048];
+  size_t bufsize = sizeof (buf);
+  int ret = __mingw_vsnprintf (buf, bufsize, format, args);
+  if (ret < 0)
+    return -1;
+  size_t nbytes = ret;
+  char *mem = (char *) malloc (nbytes + 1);
+  if (mem == NULL)
+    {
+      errno = ENOMEM;
+      return -1;
+    }
+  if (ret < bufsize)
+    {
+      /* The buffer was sufficiently large.  */
+      memcpy (mem, buf, nbytes + 1);
+    }
+  else
+    {
+      /* Second try: Use the heap-allocated memory.  */
+      ret = __mingw_vsnprintf (mem, nbytes + 1, format, args);
+      if (ret < 0)
+        {
+          int saved_errno = errno;
+          free (mem);
+          errno = saved_errno;
+          return -1;
+        }
+      if (ret != nbytes)
+        abort ();
+    }
+  *resultp = mem;
+  return nbytes;
+}
+
+# endif
+
 /* 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.  */
diff --git a/modules/stdio-windows b/modules/stdio-windows
index d9489e3e7c..8cbca1be1b 100644
--- a/modules/stdio-windows
+++ b/modules/stdio-windows
@@ -23,6 +23,7 @@ case "$host_os" in
     ;;
 esac
 gl_CONDITIONAL([GL_COND_OBJ_STDIO_CONSOLESAFE], [test $USES_MSVCRT = 1])
+AC_CHECK_FUNCS([vasprintf])
 
 Makefile.am:
 if GL_COND_OBJ_STDIO_CONSOLESAFE
-- 
2.51.0

Reply via email to