msvcr80+ has following wide-buffer swprintf like function symbols, none of
them is compatible with C95 (v)swprintf function, differences are:

  _(v)swprintf   - does not take buffer size argument, like non-wide C89
                   sprintf
  _(v)snwprintf  - does not fill nul-term wide char if there is not space
                   for it, like non-wide msvcr _(v)snprintf
  _(v)swprintf_c - clears the first wide character in buffer on error
                   (error means that there is no space for nul-term or
                   conversion error occurred)

Version before msvcr80 has following function symbols:

  _(v)snwprintf - same as in msvcrt80+
  (v)swprintf - same as _(v)swprintf in msvcrt80+

There is no (v)swprintf symbol in msvcr80+ (neither in UCRT) and there are
no _(v)swprintf_c/_(v)swprintf symbols before msvcr80.

Additionally msvcr80+ header files defines (v)swprintf() function as inline
wrapper function around _vswprintf_c_l() with NULL locale, which is same as
_vswprintf_c(). Therefore that msvcr80+ inline function (v)swprintf() is
not C95 compatible.

UCRT header files provides all those msvcr80+ swprintf family functions
defined as inline. But UCRT changed behavior of _(v)swprintf_c function,
on error it does not clear the first wide character in buffer, but instead
puts the nul wide character at current position. So with this change the
(v)swprintf() function definition in UCRT header file is C95 compatible.

mingw-w64 header files declares and defines (v)swprintf() without the
buffer size argument, matching the pre-msvcr80 (v)swprintf symbol. So
mingw-w64 has currently broken C95+ support for swprintf(), vswprintf(),
__ms_swprintf() and __ms_vswprintf() symbols, and for swprintf() and
vswprintf() functions provided by mingw-w64 header files when macro
__USE_MINGW_ANSI_STDIO is set to 0 (which is default for UCRT).

Fix this issue.

Ensure that swprintf and vswprintf symbols are always C95 compatible in
every CRT import library. Function symbols which do not take buffer size
are always under name with underscore prefix.

For non-UCRT import libraries provide mingw-w64 swprintf and vswprintf
implementations which calls _vsnwprintf and fill nul-term wide char. Original
pre-msvcr80 DLL symbols swprintf and vswprintf are renamed to _swprintf and
_vswprintf, for compatibility with msvcr80+ and UCRT.

Fix declarations of __ms_swprintf and __ms_vswprintf functions in header
files to include buffer size argument, to make them C95 compatible too.
crt-aliases.def.in file is updated to reflect this change (which completely
drops incompatible __ms_swprintf and __ms_vswprintf aliases and then also
unused PRE_C95_SWPRINTF macro).

With all these changes, functions swprintf() and vswprintf() when
__USE_MINGW_ANSI_STDIO is set to 0 are now compatible with ISO C95+.
---
 mingw-w64-crt/Makefile.am                    |  4 ++
 mingw-w64-crt/def-include/crt-aliases.def.in | 10 ----
 mingw-w64-crt/lib-common/msvcrt.def.in       |  9 ++--
 mingw-w64-crt/lib32/crtdll.def.in            |  5 +-
 mingw-w64-crt/lib32/msvcr40d.def.in          |  5 +-
 mingw-w64-crt/lib32/msvcr70.def.in           |  5 +-
 mingw-w64-crt/lib32/msvcr70d.def.in          |  5 +-
 mingw-w64-crt/lib32/msvcr71.def.in           |  5 +-
 mingw-w64-crt/lib32/msvcr71d.def.in          |  5 +-
 mingw-w64-crt/lib32/msvcrt10.def.in          |  5 +-
 mingw-w64-crt/lib32/msvcrt20.def.in          |  5 +-
 mingw-w64-crt/lib32/msvcrt40.def.in          |  5 +-
 mingw-w64-crt/lib32/msvcrtd.def.in           |  5 +-
 mingw-w64-crt/stdio/swprintf.c               | 18 +++++++
 mingw-w64-crt/stdio/swprintf_alias.c         | 26 +++++++++++
 mingw-w64-crt/stdio/vswprintf.c              | 32 +++++++++++++
 mingw-w64-crt/stdio/vswprintf_alias.c        | 20 ++++++++
 mingw-w64-headers/crt/stdio.h                | 49 ++++++++++++++++++--
 mingw-w64-headers/crt/swprintf.inl           | 34 ++------------
 mingw-w64-headers/crt/wchar.h                | 49 ++++++++++++++++++--
 20 files changed, 219 insertions(+), 82 deletions(-)
 create mode 100644 mingw-w64-crt/stdio/swprintf.c
 create mode 100644 mingw-w64-crt/stdio/swprintf_alias.c
 create mode 100644 mingw-w64-crt/stdio/vswprintf.c
 create mode 100644 mingw-w64-crt/stdio/vswprintf_alias.c

diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index 1864e35ae0b2..4959e04c7d9d 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -172,7 +172,11 @@ src_msvcrt_common=\
   stdio/acrt_iob_func.c \
   stdio/strtof.c \
   stdio/snprintf_alias.c \
+  stdio/swprintf.c \
+  stdio/swprintf_alias.c \
   stdio/vsnprintf_alias.c \
+  stdio/vswprintf.c \
+  stdio/vswprintf_alias.c \
   math/cbrt.c math/cbrtf.c \
   math/copysign.c math/copysignf.c \
   math/coshf.c \
diff --git a/mingw-w64-crt/def-include/crt-aliases.def.in 
b/mingw-w64-crt/def-include/crt-aliases.def.in
index e9bfa8630c45..38e1f8436b92 100644
--- a/mingw-w64-crt/def-include/crt-aliases.def.in
+++ b/mingw-w64-crt/def-include/crt-aliases.def.in
@@ -545,21 +545,11 @@ __ms_printf == printf
 __ms_scanf == scanf
 __ms_sprintf == sprintf
 __ms_sscanf == sscanf
-#ifdef PRE_C95_SWPRINTF
-__ms_swprintf == swprintf
-#else
-__ms_swprintf == _swprintf
-#endif
 __ms_swscanf == swscanf
 __ms_vfprintf == vfprintf
 __ms_vfwprintf == vfwprintf
 __ms_vprintf == vprintf
 __ms_vsprintf == vsprintf
-#ifdef PRE_C95_SWPRINTF
-__ms_vswprintf == vswprintf
-#else
-__ms_vswprintf == _vswprintf
-#endif
 __ms_vwprintf == vwprintf
 __ms_wprintf == wprintf
 __ms_wscanf == wscanf
diff --git a/mingw-w64-crt/lib-common/msvcrt.def.in 
b/mingw-w64-crt/lib-common/msvcrt.def.in
index c30f27ba4d60..06174d347caf 100644
--- a/mingw-w64-crt/lib-common/msvcrt.def.in
+++ b/mingw-w64-crt/lib-common/msvcrt.def.in
@@ -1081,7 +1081,7 @@ strtok
 strtol
 strtoul
 strxfrm
-swprintf
+F_X86_ANY(_swprintf == swprintf) ; rename i386 and x64 swprintf to _swprintf 
(ARM already provided _swprintf) for compatibility with msvcr80+, real C95+ 
compatible swprintf provided by mingw-w64
 swscanf
 system
 tan
@@ -1099,7 +1099,7 @@ vfprintf
 vfwprintf
 vprintf
 vsprintf
-vswprintf
+F_X86_ANY(_vswprintf == vswprintf) ; rename i386 and x64 vswprintf to 
_vswprintf (ARM already provided _vswprintf) for compatibility with msvcr80+, 
real C95+ compatible vswprintf provided by mingw-w64
 vwprintf
 wcscat
 wcschr
@@ -1663,7 +1663,7 @@ _strupr_l
 _strupr_s
 _strupr_s_l
 _strxfrm_l
-_swprintf F_X86_ANY(== swprintf) ; i386 and x64 _swprintf replaced by alias
+F_ARM_ANY(_swprintf) ; i386 and x64 _swprintf replaced by renamed swprintf 
symbol
 _swprintf_c
 _swprintf_c_l
 _swprintf_p_l
@@ -1722,7 +1722,7 @@ _vsprintf_l
 _vsprintf_p
 _vsprintf_p_l
 _vsprintf_s_l
-_vswprintf F_X86_ANY(== vswprintf) ; i386 and x64 _vswprintf replaced by alias
+F_ARM_ANY(_vswprintf) ; i386 and x64 _vswprintf replaced by renamed vswprintf 
symbol
 _vswprintf_c
 _vswprintf_c_l
 _vswprintf_l
@@ -1903,7 +1903,6 @@ F_I386(_libm_sse2_tan_precise)
 
 
 ; This includes list of some symbol alises for compatibility with C99 and 
POSIX functions and symbols from other msvcr* libraries
-#define PRE_C95_SWPRINTF
 #define FIXED_SIZE_SYMBOLS
 #define NO_FIXED_SIZE_64_ALIAS
 #define NO_TIME_ALIAS
diff --git a/mingw-w64-crt/lib32/crtdll.def.in 
b/mingw-w64-crt/lib32/crtdll.def.in
index a41278ea7836..e086ab2a337a 100644
--- a/mingw-w64-crt/lib32/crtdll.def.in
+++ b/mingw-w64-crt/lib32/crtdll.def.in
@@ -571,7 +571,7 @@ strtok
 strtol
 strtoul
 strxfrm
-swprintf
+_swprintf == swprintf ; rename swprintf to _swprintf for compatibility with 
msvcr80+, real C95+ compatible swprintf provided by mingw-w64
 swscanf
 system
 tan
@@ -589,7 +589,7 @@ vfprintf
 vfwprintf
 vprintf
 vsprintf
-vswprintf
+_vswprintf == vswprintf ; rename vswprintf to _vswprintf for compatibility 
with msvcr80+, real C95+ compatible vswprintf provided by mingw-w64
 vwprintf
 wcscat
 wcschr
@@ -624,7 +624,6 @@ _ultow
 
 ; include symbol aliases for compatibility with msvcrt.dll
 #define CRTDLL
-#define PRE_C95_SWPRINTF
 #define FIXED_SIZE_SYMBOLS
 #define NO_WIDE_FIXED_SIZE
 #define NO_I64_FIXED_SIZE
diff --git a/mingw-w64-crt/lib32/msvcr40d.def.in 
b/mingw-w64-crt/lib32/msvcr40d.def.in
index b2408fbe5174..9a108cb06a6f 100644
--- a/mingw-w64-crt/lib32/msvcr40d.def.in
+++ b/mingw-w64-crt/lib32/msvcr40d.def.in
@@ -1605,7 +1605,7 @@ strtok
 strtol
 strtoul
 strxfrm
-swprintf
+_swprintf == swprintf ; rename swprintf to _swprintf for compatibility with 
msvcr80+, real C95+ compatible swprintf provided by mingw-w64
 swscanf
 system
 tan
@@ -1623,7 +1623,7 @@ vfprintf
 vfwprintf
 vprintf
 vsprintf
-vswprintf
+_vswprintf == vswprintf ; rename vswprintf to _vswprintf for compatibility 
with msvcr80+, real C95+ compatible vswprintf provided by mingw-w64
 vwprintf
 wcscat
 wcschr
@@ -1695,7 +1695,6 @@ _outpw
 _dstbias DATA
 
 ; Include symbol aliases for compatibility with msvcrt.dll
-#define PRE_C95_SWPRINTF
 #define FIXED_SIZE_SYMBOLS
 #define NO_STRCMPI_ALIAS
 #define WITH_NEXTAFTER_ALIAS
diff --git a/mingw-w64-crt/lib32/msvcr70.def.in 
b/mingw-w64-crt/lib32/msvcr70.def.in
index 12932e8b8bd9..d4726d199c57 100644
--- a/mingw-w64-crt/lib32/msvcr70.def.in
+++ b/mingw-w64-crt/lib32/msvcr70.def.in
@@ -855,7 +855,7 @@ strtok
 strtol
 strtoul
 strxfrm
-swprintf
+_swprintf == swprintf ; rename swprintf to _swprintf for compatibility with 
msvcr80+, real C95+ compatible swprintf provided by mingw-w64
 swscanf
 system
 tan
@@ -873,7 +873,7 @@ vfprintf
 vfwprintf
 vprintf
 vsprintf
-vswprintf
+_vswprintf == vswprintf ; rename vswprintf to _vswprintf for compatibility 
with msvcr80+, real C95+ compatible vswprintf provided by mingw-w64
 vwprintf
 wcscat
 wcschr
@@ -900,7 +900,6 @@ wctomb
 wprintf
 wscanf
 
-#define PRE_C95_SWPRINTF
 #define FIXED_SIZE_SYMBOLS
 #define NO_STRCMPI_ALIAS
 #define WITH_NEXTAFTER_ALIAS
diff --git a/mingw-w64-crt/lib32/msvcr70d.def.in 
b/mingw-w64-crt/lib32/msvcr70d.def.in
index a367799ec289..6ca476200152 100644
--- a/mingw-w64-crt/lib32/msvcr70d.def.in
+++ b/mingw-w64-crt/lib32/msvcr70d.def.in
@@ -899,7 +899,7 @@ strtok
 strtol
 strtoul
 strxfrm
-swprintf
+_swprintf == swprintf ; rename swprintf to _swprintf for compatibility with 
msvcr80+, real C95+ compatible swprintf provided by mingw-w64
 swscanf
 system
 tan
@@ -917,7 +917,7 @@ vfprintf
 vfwprintf
 vprintf
 vsprintf
-vswprintf
+_vswprintf == vswprintf ; rename vswprintf to _vswprintf for compatibility 
with msvcr80+, real C95+ compatible vswprintf provided by mingw-w64
 vwprintf
 wcscat
 wcschr
@@ -944,7 +944,6 @@ wctomb
 wprintf
 wscanf
 
-#define PRE_C95_SWPRINTF
 #define FIXED_SIZE_SYMBOLS
 #define NO_STRCMPI_ALIAS
 #define WITH_NEXTAFTER_ALIAS
diff --git a/mingw-w64-crt/lib32/msvcr71.def.in 
b/mingw-w64-crt/lib32/msvcr71.def.in
index 50fe1a2d87f4..6df695c4cfd7 100644
--- a/mingw-w64-crt/lib32/msvcr71.def.in
+++ b/mingw-w64-crt/lib32/msvcr71.def.in
@@ -849,7 +849,7 @@ strtok
 strtol
 strtoul
 strxfrm
-swprintf
+_swprintf == swprintf ; rename swprintf to _swprintf for compatibility with 
msvcr80+, real C95+ compatible swprintf provided by mingw-w64
 swscanf
 system
 tan
@@ -867,7 +867,7 @@ vfprintf
 vfwprintf
 vprintf
 vsprintf
-vswprintf
+_vswprintf == vswprintf ; rename vswprintf to _vswprintf for compatibility 
with msvcr80+, real C95+ compatible vswprintf provided by mingw-w64
 vwprintf
 wcscat
 wcschr
@@ -894,7 +894,6 @@ wctomb
 wprintf
 wscanf
 
-#define PRE_C95_SWPRINTF
 #define FIXED_SIZE_SYMBOLS
 #define NO_STRCMPI_ALIAS
 #define WITH_NEXTAFTER_ALIAS
diff --git a/mingw-w64-crt/lib32/msvcr71d.def.in 
b/mingw-w64-crt/lib32/msvcr71d.def.in
index da5a56ee46c1..ba2a993ad04b 100644
--- a/mingw-w64-crt/lib32/msvcr71d.def.in
+++ b/mingw-w64-crt/lib32/msvcr71d.def.in
@@ -893,7 +893,7 @@ strtok
 strtol
 strtoul
 strxfrm
-swprintf
+_swprintf == swprintf ; rename swprintf to _swprintf for compatibility with 
msvcr80+, real C95+ compatible swprintf provided by mingw-w64
 swscanf
 system
 tan
@@ -911,7 +911,7 @@ vfprintf
 vfwprintf
 vprintf
 vsprintf
-vswprintf
+_vswprintf == vswprintf ; rename vswprintf to _vswprintf for compatibility 
with msvcr80+, real C95+ compatible vswprintf provided by mingw-w64
 vwprintf
 wcscat
 wcschr
@@ -938,7 +938,6 @@ wctomb
 wprintf
 wscanf
 
-#define PRE_C95_SWPRINTF
 #define FIXED_SIZE_SYMBOLS
 #define NO_STRCMPI_ALIAS
 #define WITH_NEXTAFTER_ALIAS
diff --git a/mingw-w64-crt/lib32/msvcrt10.def.in 
b/mingw-w64-crt/lib32/msvcrt10.def.in
index c11e1ac6e476..7d1db41ae8a4 100644
--- a/mingw-w64-crt/lib32/msvcrt10.def.in
+++ b/mingw-w64-crt/lib32/msvcrt10.def.in
@@ -1249,7 +1249,7 @@ strtok
 strtol
 strtoul
 strxfrm
-swprintf
+_swprintf == swprintf ; rename swprintf to _swprintf for compatibility with 
msvcr80+, real C95+ compatible swprintf provided by mingw-w64
 swscanf
 system
 tan
@@ -1267,7 +1267,7 @@ vfprintf
 vfwprintf
 vprintf
 vsprintf
-vswprintf
+_vswprintf == vswprintf ; rename vswprintf to _vswprintf for compatibility 
with msvcr80+, real C95+ compatible vswprintf provided by mingw-w64
 vwprintf
 wcscat
 wcschr
@@ -1294,7 +1294,6 @@ wctomb
 wprintf
 wscanf
 
-#define PRE_C95_SWPRINTF
 #define FIXED_SIZE_SYMBOLS
 #define NO_WIDE_FIXED_SIZE
 #define NO_I64_FIXED_SIZE
diff --git a/mingw-w64-crt/lib32/msvcrt20.def.in 
b/mingw-w64-crt/lib32/msvcrt20.def.in
index 76a3da398ba0..192cda00275d 100644
--- a/mingw-w64-crt/lib32/msvcrt20.def.in
+++ b/mingw-w64-crt/lib32/msvcrt20.def.in
@@ -1473,7 +1473,7 @@ strtok
 strtol
 strtoul
 strxfrm
-swprintf
+_swprintf == swprintf ; rename swprintf to _swprintf for compatibility with 
msvcr80+, real C95+ compatible swprintf provided by mingw-w64
 swscanf
 system
 tan
@@ -1491,7 +1491,7 @@ vfprintf
 vfwprintf
 vprintf
 vsprintf
-vswprintf
+_vswprintf == vswprintf ; rename vswprintf to _vswprintf for compatibility 
with msvcr80+, real C95+ compatible vswprintf provided by mingw-w64
 vwprintf
 wcscat
 wcschr
@@ -1576,7 +1576,6 @@ _safe_fprem
 _safe_fprem1
 
 ; Include symbol aliases for compatibility with msvcrt.dll
-#define PRE_C95_SWPRINTF
 #define FIXED_SIZE_SYMBOLS
 #define NO_I64_FIXED_SIZE
 #define NO_FPOS64_ALIASES
diff --git a/mingw-w64-crt/lib32/msvcrt40.def.in 
b/mingw-w64-crt/lib32/msvcrt40.def.in
index 1941bd99584e..88ae2bd2399f 100644
--- a/mingw-w64-crt/lib32/msvcrt40.def.in
+++ b/mingw-w64-crt/lib32/msvcrt40.def.in
@@ -1573,7 +1573,7 @@ strtok
 strtol
 strtoul
 strxfrm
-swprintf
+_swprintf == swprintf ; rename swprintf to _swprintf for compatibility with 
msvcr80+, real C95+ compatible swprintf provided by mingw-w64
 swscanf
 system
 tan
@@ -1591,7 +1591,7 @@ vfprintf
 vfwprintf
 vprintf
 vsprintf
-vswprintf
+_vswprintf == vswprintf ; rename vswprintf to _vswprintf for compatibility 
with msvcr80+, real C95+ compatible vswprintf provided by mingw-w64
 vwprintf
 wcscat
 wcschr
@@ -1660,7 +1660,6 @@ _outpw
 _dstbias DATA
 
 ; Include symbol aliases for compatibility with msvcrt.dll
-#define PRE_C95_SWPRINTF
 #define FIXED_SIZE_SYMBOLS
 #define NO_STRCMPI_ALIAS
 #define WITH_NEXTAFTER_ALIAS
diff --git a/mingw-w64-crt/lib32/msvcrtd.def.in 
b/mingw-w64-crt/lib32/msvcrtd.def.in
index f725eeae4071..4313c797a179 100644
--- a/mingw-w64-crt/lib32/msvcrtd.def.in
+++ b/mingw-w64-crt/lib32/msvcrtd.def.in
@@ -799,7 +799,7 @@ strtok
 strtol
 strtoul
 strxfrm
-swprintf
+_swprintf == swprintf ; rename swprintf to _swprintf for compatibility with 
msvcr80+, real C95+ compatible swprintf provided by mingw-w64
 swscanf
 system
 tan
@@ -817,7 +817,7 @@ vfprintf
 vfwprintf
 vprintf
 vsprintf
-vswprintf
+_vswprintf == vswprintf ; rename vswprintf to _vswprintf for compatibility 
with msvcr80+, real C95+ compatible vswprintf provided by mingw-w64
 vwprintf
 wcscat
 wcschr
@@ -853,7 +853,6 @@ __lc_collate_cp DATA
 __unDNameEx
 _chkesp
 
-#define PRE_C95_SWPRINTF
 #define FIXED_SIZE_SYMBOLS
 #define NO_STRCMPI_ALIAS
 #define WITH_NEXTAFTER_ALIAS
diff --git a/mingw-w64-crt/stdio/swprintf.c b/mingw-w64-crt/stdio/swprintf.c
new file mode 100644
index 000000000000..68483dd991b9
--- /dev/null
+++ b/mingw-w64-crt/stdio/swprintf.c
@@ -0,0 +1,18 @@
+/**
+ * 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 <stdarg.h>
+#include <stdio.h>
+
+int __cdecl __ms_swprintf(wchar_t *__restrict__ ws, size_t n, const wchar_t 
*__restrict__ format, ...)
+{
+    int retval;
+    va_list argptr;
+
+    va_start(argptr, format);
+    retval = __ms_vswprintf(ws, n, format, argptr);
+    va_end(argptr);
+    return retval;
+}
diff --git a/mingw-w64-crt/stdio/swprintf_alias.c 
b/mingw-w64-crt/stdio/swprintf_alias.c
new file mode 100644
index 000000000000..3db9ee050de0
--- /dev/null
+++ b/mingw-w64-crt/stdio/swprintf_alias.c
@@ -0,0 +1,26 @@
+/**
+ * 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 <stdarg.h>
+#include <stddef.h>
+
+/* Intentionally not including stdio.h, as it unconditionally defines the
+ * swprintf inline, and it can't be renamed with "#define swprintf othername"
+ * either, as stdio.h contains "#undef swprintf". */
+
+int __cdecl __ms_vswprintf(wchar_t *ws, size_t n, const wchar_t *format, 
va_list arg);
+
+int __cdecl swprintf(wchar_t* ws, size_t n, const wchar_t *format, ...);
+int __cdecl swprintf(wchar_t* ws, size_t n, const wchar_t *format, ...)
+{
+  int retval;
+  va_list argptr;
+
+  va_start(argptr, format);
+  retval = __ms_vswprintf(ws, n, format, argptr);
+  va_end(argptr);
+  return retval;
+}
diff --git a/mingw-w64-crt/stdio/vswprintf.c b/mingw-w64-crt/stdio/vswprintf.c
new file mode 100644
index 000000000000..66028659325e
--- /dev/null
+++ b/mingw-w64-crt/stdio/vswprintf.c
@@ -0,0 +1,32 @@
+/**
+ * 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.
+ */
+#define __CRT__NO_INLINE
+#include <stdarg.h>
+#include <stdio.h>
+
+int __cdecl __ms_vswprintf(wchar_t *__restrict__ ws, size_t n, const wchar_t 
*__restrict__ format, va_list arg)
+{
+    int retval;
+
+    /* ISO C95+ vswprintf() returns negative value if buffer has zero size */
+    if (n == 0)
+        return -1;
+
+    /*
+     * _vsnwprintf() returns number of filled wide chars up to the N or -1 
otherwise.
+     * ISO C95+ vswprintf() returns number of filled wide chars excluding the
+     * trailing nul (therefore up to the N-1) or -1 otherwise.
+     * So call _vsnwprintf() with n-1 to have correct return value (-1) when 
more
+     * wide chars (inc nul) were requested to write into the output buffer 
than N.
+     */
+    retval = _vsnwprintf(ws, n-1, format, arg);
+
+    /* _vsnwprintf() does not fill trailing nul wide char if there is not 
place for it */
+    if (retval < 0 || (size_t)retval == n-1)
+        ws[n-1] = L'\0';
+
+    return retval;
+}
diff --git a/mingw-w64-crt/stdio/vswprintf_alias.c 
b/mingw-w64-crt/stdio/vswprintf_alias.c
new file mode 100644
index 000000000000..199b8a81b21d
--- /dev/null
+++ b/mingw-w64-crt/stdio/vswprintf_alias.c
@@ -0,0 +1,20 @@
+/**
+ * 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 <stdarg.h>
+#include <stddef.h>
+
+/* Intentionally not including stdio.h, as it unconditionally defines the
+ * vswprintf inline, and it can't be renamed with "#define vswprintf othername"
+ * either, as stdio.h contains "#undef vswprintf". */
+
+int __cdecl __ms_vswprintf(wchar_t *ws, size_t n, const wchar_t *format, 
va_list arg);
+
+int __cdecl vswprintf(wchar_t *ws, size_t n, const wchar_t *format, va_list 
arg);
+int __cdecl vswprintf(wchar_t *ws, size_t n, const wchar_t *format, va_list 
arg)
+{
+  return __ms_vswprintf(ws, n, format, arg);
+}
diff --git a/mingw-w64-headers/crt/stdio.h b/mingw-w64-headers/crt/stdio.h
index a8f5c978000e..bb998db1dad1 100644
--- a/mingw-w64-headers/crt/stdio.h
+++ b/mingw-w64-headers/crt/stdio.h
@@ -935,10 +935,10 @@ int vsprintf (char * __restrict__ __stream, const char * 
__restrict__ __format,
   int __cdecl __ms_vfwprintf(FILE * __restrict__ _File,const wchar_t * 
__restrict__ _Format,va_list _ArgList);
 /*__attribute__((__format__ (ms_wprintf, 1, 0))) */ __MINGW_ATTRIB_NONNULL(1)
   int __cdecl __ms_vwprintf(const wchar_t * __restrict__ _Format,va_list 
_ArgList);
-/* __attribute__((__format__ (ms_wprintf, 2, 3))) */ __MINGW_ATTRIB_NONNULL(2)
-  int __cdecl __ms_swprintf(wchar_t * __restrict__ , const wchar_t * 
__restrict__ , ...);
-/* __attribute__((__format__ (ms_wprintf, 2, 0))) */ __MINGW_ATTRIB_NONNULL(2)
-  int __cdecl __ms_vswprintf(wchar_t * __restrict__ , const wchar_t * 
__restrict__ ,va_list);
+/* __attribute__((__format__ (ms_wprintf, 3, 4))) */ __MINGW_ATTRIB_NONNULL(3)
+  int __cdecl __ms_swprintf(wchar_t * __restrict__ , size_t, const wchar_t * 
__restrict__ , ...);
+/* __attribute__((__format__ (ms_wprintf, 3, 0))) */ __MINGW_ATTRIB_NONNULL(3)
+  int __cdecl __ms_vswprintf(wchar_t * __restrict__ , size_t, const wchar_t * 
__restrict__ ,va_list);
 
 #ifdef _UCRT
   int __cdecl __stdio_common_vswprintf(unsigned __int64 options, wchar_t *str, 
size_t len, const wchar_t *format, _locale_t locale, va_list valist);
@@ -1169,6 +1169,44 @@ int vsnwprintf (wchar_t *__stream, size_t __n, const 
wchar_t *__format, __builti
   int __cdecl _vsnwprintf(wchar_t * __restrict__ _Dest,size_t _Count,const 
wchar_t * __restrict__ _Format,va_list _Args) 
__MINGW_ATTRIB_DEPRECATED_SEC_WARN;
 
 #if __USE_MINGW_ANSI_STDIO == 0
+  __mingw_ovr
+  int __cdecl swprintf(wchar_t * __restrict__ _Dest,size_t _Count,const 
wchar_t * __restrict__ _Format,...)
+  {
+    __builtin_va_list __ap;
+    int __ret;
+    /*
+     * __stdio_common_vswprintf() for case _Dest == NULL and _Count == 0 and
+     * without _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR option, is
+     * executed in "standard snprintf behavior" and returns number of (wide)
+     * chars required to allocate. For all other cases it is executed in a way
+     * that returns negative value on error. But C95+ compliant swprintf() for
+     * case _Count == 0 returns negative value, so handle this case specially.
+     */
+    if (_Dest == NULL && _Count == 0)
+      return -1;
+    __builtin_va_start(__ap, _Format);
+    __ret = __stdio_common_vswprintf(_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS, 
_Dest, _Count, _Format, NULL, __ap);
+    __builtin_va_end(__ap);
+    return __ret < 0 ? -1 : __ret;
+  }
+  __mingw_ovr
+  int __cdecl vswprintf(wchar_t * __restrict__ _Dest,size_t _Count,const 
wchar_t * __restrict__ _Format,va_list _Args)
+  {
+    int __ret;
+    /*
+     * __stdio_common_vswprintf() for case _Dest == NULL and _Count == 0 and
+     * without _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR option, is
+     * executed in "standard snprintf behavior" and returns number of (wide)
+     * chars required to allocate. For all other cases it is executed in a way
+     * that returns negative value on error. But C95+ compliant vswprintf() for
+     * case _Count == 0 returns negative value, so handle this case specially.
+     */
+    if (_Dest == NULL && _Count == 0)
+      return -1;
+    __ret = __stdio_common_vswprintf(_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS, 
_Dest, _Count, _Format, NULL, _Args);
+    return __ret < 0 ? -1 : __ret;
+  }
+
   __mingw_ovr
   int snwprintf (wchar_t * __restrict__ s, size_t n, const wchar_t * 
__restrict__ format, ...)
   {
@@ -1242,6 +1280,9 @@ int vsnwprintf (wchar_t *__stream, size_t __n, const 
wchar_t *__format, __builti
 #endif /* ! __NO_ISOCEXT */
   _CRTIMP int __cdecl _swprintf(wchar_t * __restrict__ _Dest,const wchar_t * 
__restrict__ _Format,...);
   _CRTIMP int __cdecl _vswprintf(wchar_t * __restrict__ _Dest,const wchar_t * 
__restrict__ _Format,va_list _Args);
+
+  int __cdecl swprintf(wchar_t * __restrict__ _Dest,size_t _Count,const 
wchar_t * __restrict__ _Format,...);
+  int __cdecl vswprintf(wchar_t * __restrict__ _Dest,size_t _Count,const 
wchar_t * __restrict__ _Format,va_list _Args);
 #endif /* _UCRT */
 
 #ifndef RC_INVOKED
diff --git a/mingw-w64-headers/crt/swprintf.inl 
b/mingw-w64-headers/crt/swprintf.inl
index d990d428c5a1..3fe7712c0c61 100644
--- a/mingw-w64-headers/crt/swprintf.inl
+++ b/mingw-w64-headers/crt/swprintf.inl
@@ -9,26 +9,6 @@
 
 #include <vadefs.h>
 
-__mingw_ovr
-/* __attribute__((__format__ (gnu_wprintf, 3, 0))) */ __MINGW_ATTRIB_NONNULL(3)
-int vswprintf (wchar_t *__stream, size_t __count, const wchar_t *__format, 
__builtin_va_list __local_argv)
-{
-  return vsnwprintf( __stream, __count, __format, __local_argv );
-}
-
-__mingw_ovr
-/* __attribute__((__format__ (gnu_wprintf, 3, 4))) */ __MINGW_ATTRIB_NONNULL(3)
-int swprintf (wchar_t *__stream, size_t __count, const wchar_t *__format, ...)
-{
-  int __retval;
-  __builtin_va_list __local_argv;
-
-  __builtin_va_start( __local_argv, __format );
-  __retval = vswprintf( __stream, __count, __format, __local_argv );
-  __builtin_va_end( __local_argv );
-  return __retval;
-}
-
 #ifdef __cplusplus
 
 extern "C++" {
@@ -37,17 +17,15 @@ __mingw_ovr
 /* __attribute__((__format__ (gnu_wprintf, 2, 0))) */ __MINGW_ATTRIB_NONNULL(2)
 int vswprintf (wchar_t *__stream, const wchar_t *__format, __builtin_va_list 
__local_argv)
 {
-#if __USE_MINGW_ANSI_STDIO
-  return __mingw_vswprintf( __stream, __format, __local_argv );
-#else
   return _vswprintf( __stream, __format, __local_argv );
-#endif
 }
 
 __mingw_ovr
 /* __attribute__((__format__ (gnu_wprintf, 2, 3))) */ __MINGW_ATTRIB_NONNULL(2)
 int swprintf (wchar_t *__stream, const wchar_t *__format, ...)
 {
+#ifdef __clang__
+  /* clang does not support __builtin_va_arg_pack(), so forward swprintf() to 
vswprintf() */
   int __retval;
   __builtin_va_list __local_argv;
 
@@ -55,19 +33,17 @@ int swprintf (wchar_t *__stream, const wchar_t *__format, 
...)
   __retval = vswprintf( __stream, __format, __local_argv );
   __builtin_va_end( __local_argv );
   return __retval;
+#else
+  return _swprintf( __stream, __format, __builtin_va_arg_pack() );
+#endif
 }
 
 }
 
 #elif defined(_CRT_NON_CONFORMING_SWPRINTFS)
 
-#if __USE_MINGW_ANSI_STDIO
-#define swprintf __mingw_swprintf
-#define vswprintf __mingw_vswprintf
-#else
 #define swprintf _swprintf
 #define vswprintf _vswprintf
-#endif
 
 #endif /* __cplusplus */
 
diff --git a/mingw-w64-headers/crt/wchar.h b/mingw-w64-headers/crt/wchar.h
index 6aa1daf995d2..8ef48e97f612 100644
--- a/mingw-w64-headers/crt/wchar.h
+++ b/mingw-w64-headers/crt/wchar.h
@@ -472,10 +472,10 @@ _CRTIMP FILE *__cdecl __acrt_iob_func(unsigned index);
   int __cdecl __ms_vfwprintf(FILE * __restrict__ _File,const wchar_t * 
__restrict__ _Format,va_list _ArgList);
 /*__attribute__((__format__ (ms_wprintf, 1, 0))) */ __MINGW_ATTRIB_NONNULL(1)
   int __cdecl __ms_vwprintf(const wchar_t * __restrict__ _Format,va_list 
_ArgList);
-/* __attribute__((__format__ (ms_wprintf, 2, 3))) */ __MINGW_ATTRIB_NONNULL(2)
-  int __cdecl __ms_swprintf(wchar_t * __restrict__ , const wchar_t * 
__restrict__ , ...);
-/* __attribute__((__format__ (ms_wprintf, 2, 0))) */ __MINGW_ATTRIB_NONNULL(2)
-  int __cdecl __ms_vswprintf(wchar_t * __restrict__ , const wchar_t * 
__restrict__ ,va_list);
+/* __attribute__((__format__ (ms_wprintf, 3, 4))) */ __MINGW_ATTRIB_NONNULL(3)
+  int __cdecl __ms_swprintf(wchar_t * __restrict__ , size_t, const wchar_t * 
__restrict__ , ...);
+/* __attribute__((__format__ (ms_wprintf, 3, 0))) */ __MINGW_ATTRIB_NONNULL(3)
+  int __cdecl __ms_vswprintf(wchar_t * __restrict__ , size_t, const wchar_t * 
__restrict__ ,va_list);
 
 #ifdef _UCRT
   int __cdecl __stdio_common_vswprintf(unsigned __int64 options, wchar_t *str, 
size_t len, const wchar_t *format, _locale_t locale, va_list valist);
@@ -616,6 +616,44 @@ __MINGW_ASM_CALL(__mingw_vsnwprintf);
   {
     return __stdio_common_vfwprintf(_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS, 
stdout, _Format, NULL, _ArgList);
   }
+
+  __mingw_ovr
+  int __cdecl swprintf(wchar_t * __restrict__ _Dest,size_t _Count,const 
wchar_t * __restrict__ _Format,...)
+  {
+    __builtin_va_list __ap;
+    int __ret;
+    /*
+     * __stdio_common_vswprintf() for case _Dest == NULL and _Count == 0 and
+     * without _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR option, is
+     * executed in "standard snprintf behavior" and returns number of (wide)
+     * chars required to allocate. For all other cases it is executed in a way
+     * that returns negative value on error. But C95+ compliant swprintf() for
+     * case _Count == 0 returns negative value, so handle this case specially.
+     */
+    if (_Dest == NULL && _Count == 0)
+      return -1;
+    __builtin_va_start(__ap, _Format);
+    __ret = __stdio_common_vswprintf(_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS, 
_Dest, _Count, _Format, NULL, __ap);
+    __builtin_va_end(__ap);
+    return __ret < 0 ? -1 : __ret;
+  }
+  __mingw_ovr
+  int __cdecl vswprintf(wchar_t * __restrict__ _Dest,size_t _Count,const 
wchar_t * __restrict__ _Format,va_list _Args)
+  {
+    int __ret;
+    /*
+     * __stdio_common_vswprintf() for case _Dest == NULL and _Count == 0 and
+     * without _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR option, is
+     * executed in "standard snprintf behavior" and returns number of (wide)
+     * chars required to allocate. For all other cases it is executed in a way
+     * that returns negative value on error. But C95+ compliant vswprintf() for
+     * case _Count == 0 returns negative value, so handle this case specially.
+     */
+    if (_Dest == NULL && _Count == 0)
+      return -1;
+    __ret = __stdio_common_vswprintf(_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS, 
_Dest, _Count, _Format, NULL, _Args);
+    return __ret < 0 ? -1 : __ret;
+  }
 #else
 
   int __cdecl fwscanf(FILE * __restrict__ _File,const wchar_t * __restrict__ 
_Format,...) __MINGW_ATTRIB_DEPRECATED_SEC_WARN;
@@ -652,6 +690,9 @@ __MINGW_ASM_CALL(__mingw_vsnwprintf);
   int __cdecl wprintf(const wchar_t * __restrict__ _Format,...);
   int __cdecl vfwprintf(FILE * __restrict__ _File,const wchar_t * __restrict__ 
_Format,va_list _ArgList);
   int __cdecl vwprintf(const wchar_t * __restrict__ _Format,va_list _ArgList);
+
+  int __cdecl swprintf(wchar_t * __restrict__ _Dest,size_t _Count,const 
wchar_t * __restrict__ _Format,...);
+  int __cdecl vswprintf(wchar_t * __restrict__ _Dest,size_t _Count,const 
wchar_t * __restrict__ _Format,va_list _Args);
 #endif /* _UCRT */
 #endif /* __USE_MINGW_ANSI_STDIO */
 
-- 
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