__ms_vsnwprintf() function now calls _vscwprintf() funcion. _vscwprintf()
is not available in older msvcrt.dll version, so provide emulation of
_scwprintf() and _vscwprintf() functions.

This emulation is similar to existing _scprintf and _vscprintf emulation.
---
 mingw-w64-crt/Makefile.am              | 10 +++
 mingw-w64-crt/lib-common/msvcrt.def.in |  4 +-
 mingw-w64-crt/stdio/_scwprintf.c       | 67 ++++++++++++++++++++
 mingw-w64-crt/stdio/_vscwprintf.c      | 87 ++++++++++++++++++++++++++
 4 files changed, 166 insertions(+), 2 deletions(-)
 create mode 100644 mingw-w64-crt/stdio/_scwprintf.c
 create mode 100644 mingw-w64-crt/stdio/_vscwprintf.c

diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index fc547e668e3d..63d9f4befad8 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -487,7 +487,9 @@ src_msvcrt32=\
   misc/wctob.c \
   stdio/_fstat64i32.c \
   stdio/_scprintf.c \
+  stdio/_scwprintf.c \
   stdio/_vscprintf.c \
+  stdio/_vscwprintf.c \
   string/wcstok.c
 
 # Files included in libmsvcrt-os.a (for msvcrt.dll) on x86_64
@@ -745,7 +747,9 @@ src_crtdll=\
   misc/wctype.c \
   stdio/_filelengthi64.c \
   stdio/_scprintf.c \
+  stdio/_scwprintf.c \
   stdio/_vscprintf.c \
+  stdio/_vscwprintf.c \
   stdio/atoll.c \
   stdio/fgetpos.c \
   stdio/fsetpos.c \
@@ -812,7 +816,9 @@ src_msvcrt10=\
   misc/wctype.c \
   stdio/_filelengthi64.c \
   stdio/_scprintf.c \
+  stdio/_scwprintf.c \
   stdio/_vscprintf.c \
+  stdio/_vscwprintf.c \
   stdio/atoll.c \
   stdio/fgetpos.c \
   stdio/fsetpos.c \
@@ -860,7 +866,9 @@ src_msvcrt20=\
   misc/wctype.c \
   stdio/_filelengthi64.c \
   stdio/_scprintf.c \
+  stdio/_scwprintf.c \
   stdio/_vscprintf.c \
+  stdio/_vscwprintf.c \
   stdio/atoll.c \
   stdio/fgetpos.c \
   stdio/fsetpos.c \
@@ -902,7 +910,9 @@ src_msvcrt40=\
   misc/wctrans.c \
   misc/wctype.c \
   stdio/_scprintf.c \
+  stdio/_scwprintf.c \
   stdio/_vscprintf.c \
+  stdio/_vscwprintf.c \
   stdio/atoll.c \
   stdio/fseeki64.c \
   stdio/mingw_dummy__lock.c \
diff --git a/mingw-w64-crt/lib-common/msvcrt.def.in 
b/mingw-w64-crt/lib-common/msvcrt.def.in
index ab085571b498..e399f96ff12e 100644
--- a/mingw-w64-crt/lib-common/msvcrt.def.in
+++ b/mingw-w64-crt/lib-common/msvcrt.def.in
@@ -1214,7 +1214,7 @@ _getwche
 _putwch
 _resetstkoflw
 F_NON_I386(_scprintf) ; i386 _scprintf replaced by emu
-_scwprintf
+F_NON_I386(_scwprintf) ; i386 _scwprintf replaced by emu
 F_I386(_set_SSE2_enable)
 _snscanf
 _snwscanf
@@ -1222,7 +1222,7 @@ F_NON_I386(_strtoi64) ; i386 _strtoi64 replaced by emu
 F_NON_I386(_strtoui64) ; i386 _strtoui64 replaced by emu
 _ungetwch
 F_NON_I386(_vscprintf) ; i386 _vscprintf replaced by emu
-_vscwprintf
+F_NON_I386(_vscwprintf) ; i386 _vscwprintf replaced by emu
 _wcserror
 F_NON_I386(_wcstoi64) ; i386 _wcstoi64 replaced by emu
 F_NON_I386(_wcstoui64) ; i386 _wcstoui64 replaced by emu
diff --git a/mingw-w64-crt/stdio/_scwprintf.c b/mingw-w64-crt/stdio/_scwprintf.c
new file mode 100644
index 000000000000..b132328ab7a1
--- /dev/null
+++ b/mingw-w64-crt/stdio/_scwprintf.c
@@ -0,0 +1,67 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+#include <windows.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
+
+/* mingw-w64 always provides _vscwprintf() implementation, so use it */
+static int __cdecl emu_scwprintf(const wchar_t * __restrict__ format, ...)
+{
+    va_list arglist;
+    int ret;
+
+    va_start(arglist, format);
+    ret = _vscwprintf(format, arglist);
+    va_end(arglist);
+    return ret;
+}
+
+#ifndef __LIBMSVCRT_OS__
+
+int __attribute__ ((alias ("emu_scwprintf"))) __cdecl _scwprintf (const 
wchar_t * __restrict__, ...);
+int (__cdecl *__MINGW_IMP_SYMBOL(_scwprintf))(const wchar_t * __restrict__, 
...) = _scwprintf;
+
+#else
+
+#include <msvcrt.h>
+
+static int __cdecl init_scwprintf(const wchar_t * __restrict__ format, ...);
+
+int (__cdecl *__MINGW_IMP_SYMBOL(_scwprintf))(const wchar_t * __restrict__, 
...) = init_scwprintf;
+
+__attribute__((used))
+static void resolve_scwprintf(void)
+{
+    HMODULE msvcrt = __mingw_get_msvcrt_handle();
+    int (__cdecl *func)(const wchar_t * __restrict__, ...) = NULL;
+
+    if (msvcrt)
+        func = (int (__cdecl *)(const wchar_t * __restrict__, 
...))GetProcAddress(msvcrt, "_scwprintf");
+
+    if (!func)
+        func = emu_scwprintf;
+
+    __MINGW_IMP_SYMBOL(_scwprintf) = func;
+}
+
+/* gcc does not provide an easy way to call another variadic function with 
reusing current arguments
+ * this source file is used only on i386, so do this function redirect via 
inline i386 assembly */
+#define ASM_SYM(sym) __MINGW64_STRINGIFY(__MINGW_USYMBOL(sym))
+asm (
+".def\t" ASM_SYM(init_scwprintf) ";\t.scl\t3;\t.type\t32;\t.endef\n"
+ASM_SYM(init_scwprintf) ":\n\t"
+    "pushal\n\t"
+    "call\t" ASM_SYM(resolve_scwprintf) "\n\t"
+    "popal\n\t"
+    /* fallthrough */
+".globl\t" ASM_SYM(_scwprintf) "\n\t"
+".def\t" ASM_SYM(_scwprintf) ";\t.scl\t2;\t.type\t32;\t.endef\n"
+ASM_SYM(_scwprintf) ":\n\t"
+    "jmp\t*" ASM_SYM(__MINGW_IMP_SYMBOL(_scwprintf))
+);
+
+#endif
diff --git a/mingw-w64-crt/stdio/_vscwprintf.c 
b/mingw-w64-crt/stdio/_vscwprintf.c
new file mode 100644
index 000000000000..0fae7a16ab6d
--- /dev/null
+++ b/mingw-w64-crt/stdio/_vscwprintf.c
@@ -0,0 +1,87 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+#include <windows.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <errno.h>
+
+/* emulation of _vscwprintf() via _vsnwprintf() */
+static int __cdecl emu_vscwprintf(const wchar_t * __restrict__ format, va_list 
arglist)
+{
+    wchar_t *buffer, *new_buffer;
+    size_t size;
+    int ret = -1;
+
+    /* if format is a null pointer, _vscwprintf() returns -1 and sets errno to 
EINVAL */
+    if (!format) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    /* size for _vsnwprintf() must be non-zero and buffer must have place for 
terminating null character */
+    size = (wcslen(format) * 2 + 1) * sizeof(wchar_t);
+    buffer = malloc(size);
+
+    if (!buffer) {
+        errno = ENOMEM;
+        return -1;
+    }
+
+    /* if the number of characters to write is greater than size, 
_vsnwprintf() returns -1 */
+    while (size < SIZE_MAX/2 && (ret = _vsnwprintf(buffer, size, format, 
arglist)) < 0) {
+        /* in this case try with larger buffer */
+        size *= 2;
+        new_buffer = realloc(buffer, size);
+        if (!new_buffer)
+            break;
+        buffer = new_buffer;
+    }
+
+    free(buffer);
+
+    if (ret < 0) {
+        errno = ENOMEM;
+        return -1;
+    }
+
+    return ret;
+}
+
+#ifndef __LIBMSVCRT_OS__
+
+int __attribute__ ((alias ("emu_vscwprintf"))) __cdecl _vscwprintf (const 
wchar_t * __restrict__, va_list);
+int (__cdecl *__MINGW_IMP_SYMBOL(_vscwprintf))(const wchar_t * __restrict__, 
va_list) = _vscwprintf;
+
+#else
+
+#include <msvcrt.h>
+
+static int __cdecl init_vscwprintf(const wchar_t * __restrict__ format, 
va_list arglist);
+
+int (__cdecl *__MINGW_IMP_SYMBOL(_vscwprintf))(const wchar_t * __restrict__, 
va_list) = init_vscwprintf;
+
+static int __cdecl init_vscwprintf(const wchar_t * __restrict__ format, 
va_list arglist)
+{
+    HMODULE msvcrt = __mingw_get_msvcrt_handle();
+    int (__cdecl *func)(const wchar_t * __restrict__, va_list) = NULL;
+
+    if (msvcrt)
+        func = (int (__cdecl *)(const wchar_t * __restrict__, 
va_list))GetProcAddress(msvcrt, "_vscwprintf");
+
+    if (!func)
+        func = emu_vscwprintf;
+
+    return (__MINGW_IMP_SYMBOL(_vscwprintf) = func)(format, arglist);
+}
+
+int __cdecl _vscwprintf(const wchar_t * __restrict__ format, va_list arglist)
+{
+    return __MINGW_IMP_SYMBOL(_vscwprintf)(format, arglist);
+}
+
+#endif
-- 
2.20.1



_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to