Currently, REPLACE_MBSTATE_T is set to 1 on MSVC, but not on mingw. Why? Because mbsinit is not declared as a global function on MSVC, only as an inline function. This has the effect of constraining the possible implementations of mbrtowc and mbrtoc32.
There is actually no need to set REPLACE_MBSTATE_T, because we know how the mbsinit function works on this platform, and it's fine. So let's set REPLACE_MBSTATE_T=0 on this platform. But we do need to override wcrtomb, otherwise the unit test fails. Here's a small standalone test program: ============================================================ #include <locale.h> #include <stdlib.h> #include <wchar.h> int main (int argc, char *argv[]) { if (setlocale (LC_ALL, "French_France.65001") == NULL) return 1; wchar_t wc; int iret; size_t ret; wc = (wchar_t) 0xBADFACE; iret = mbtowc (&wc, "\303\274", 2); if (iret != 2) return 2; ret = wcrtomb (NULL, wc, NULL); if (ret != 1) return 3; return 0; } ============================================================ 2020-01-02 Bruno Haible <br...@clisp.org> mbrtowc: Don't replace mbstate_t on MSVC. * m4/mbrtowc.m4 (gl_MBSTATE_T_BROKEN): Require AC_CANONICAL_HOST. Ignore a missing mbsinit function on native Windows. * m4/wcrtomb.m4 (gl_FUNC_WCRTOMB): Strengthen the test, to detect an MSVC bug. * doc/posix-functions/wcrtomb.texi: Mention the MSVC bug. diff --git a/m4/mbrtowc.m4 b/m4/mbrtowc.m4 index c747ea2..af4e25d 100644 --- a/m4/mbrtowc.m4 +++ b/m4/mbrtowc.m4 @@ -1,4 +1,4 @@ -# mbrtowc.m4 serial 34 -*- coding: utf-8 -*- +# mbrtowc.m4 serial 35 -*- coding: utf-8 -*- dnl Copyright (C) 2001-2002, 2004-2005, 2008-2020 Free Software Foundation, dnl Inc. dnl This file is free software; the Free Software Foundation @@ -97,11 +97,19 @@ dnl avoid inconsistencies. AC_DEFUN([gl_MBSTATE_T_BROKEN], [ AC_REQUIRE([gl_WCHAR_H_DEFAULTS]) + AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_TYPE_MBSTATE_T]) AC_CHECK_FUNCS_ONCE([mbsinit]) AC_CHECK_FUNCS_ONCE([mbrtowc]) - if test $ac_cv_func_mbsinit = yes && test $ac_cv_func_mbrtowc = yes; then + dnl On native Windows, we know exactly how mbsinit() behaves and don't need + dnl to override it, even if - like on MSVC - mbsinit() is only defined as + dnl an inline function, not as a global function. + if case "$host_os" in + mingw*) true ;; + *) test $ac_cv_func_mbsinit = yes ;; + esac \ + && test $ac_cv_func_mbrtowc = yes; then gl_MBRTOWC_INCOMPLETE_STATE gl_MBRTOWC_SANITYCHECK REPLACE_MBSTATE_T=0 diff --git a/m4/wcrtomb.m4 b/m4/wcrtomb.m4 index 73c551b..64e5110 100644 --- a/m4/wcrtomb.m4 +++ b/m4/wcrtomb.m4 @@ -1,4 +1,4 @@ -# wcrtomb.m4 serial 14 +# wcrtomb.m4 serial 15 dnl Copyright (C) 2008-2020 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -90,12 +90,10 @@ int main () dnl is present. changequote(,)dnl case "$host_os" in - # Guess no on AIX 4, OSF/1 and Solaris. - aix4* | osf* | solaris*) gl_cv_func_wcrtomb_retval="guessing no" ;; - # Guess yes on native Windows. - mingw*) gl_cv_func_wcrtomb_retval="guessing yes" ;; - # Guess yes otherwise. - *) gl_cv_func_wcrtomb_retval="guessing yes" ;; + # Guess no on AIX 4, OSF/1, Solaris, native Windows. + aix4* | osf* | solaris* | mingw*) gl_cv_func_wcrtomb_retval="guessing no" ;; + # Guess yes otherwise. + *) gl_cv_func_wcrtomb_retval="guessing yes" ;; esac changequote([,])dnl if test $LOCALE_FR != none || test $LOCALE_FR_UTF8 != none || test $LOCALE_JA != none || test $LOCALE_ZH_CN != none; then @@ -111,6 +109,7 @@ changequote([,])dnl #include <stdio.h> #include <time.h> #include <wchar.h> +#include <stdlib.h> int main () { int result = 0; @@ -123,6 +122,12 @@ int main () { if (wcrtomb (NULL, 0, NULL) != 1) result |= 2; + { + wchar_t wc = (wchar_t) 0xBADFACE; + if (mbtowc (&wc, "\303\274", 2) == 2) + if (wcrtomb (NULL, wc, NULL) != 1) + result |= 2; + } } if (setlocale (LC_ALL, "$LOCALE_JA") != NULL) { diff --git a/doc/posix-functions/wcrtomb.texi b/doc/posix-functions/wcrtomb.texi index 20902e9..232bea4 100644 --- a/doc/posix-functions/wcrtomb.texi +++ b/doc/posix-functions/wcrtomb.texi @@ -17,6 +17,9 @@ Android 4.3. @item This function returns 0 when the first argument is NULL in some locales on some platforms: Solaris 11.3. +@item +This function does not ignore the second argument when the first argument is NULL on some platforms: +MSVC 14. @end itemize Portability problems not fixed by Gnulib: