On Sat, 14 Dec 2019, Martin Storsjö wrote:
On Sat, 14 Dec 2019, Liu Hao wrote:
在 2019/12/14 4:17, Martin Storsjö 写道:
For some reason, gnulib tries to provide its own function mbsinit (which
is used for checking if an mbstate_t is initialized or not), even if one
is provided. (I guess the reason for this misdetection, is that in UCRT
mode, mbsinit is purely available as an inline function, there's no
function available in the UCRT dll, and the gnulib check might only test
linking without using the right header.)
Perhaps we should provide a custom mbsinit function in the UCRT import
libraries - that should hopefully make gnulib realize the function
exists, and avoid trying to provide it.
Referring to the file 'mbsinit.m4' in GnuLib I get this:
```m4
if test $REPLACE_MBSTATE_T = 1; then
REPLACE_MBSINIT=1
else
dnl On mingw, mbsinit() always returns 1, which is inappropriate for
dnl states produced by mbrtowc() for an incomplete multibyte character
dnl in multibyte locales.
case "$host_os" in
mingw*) REPLACE_MBSINIT=1 ;;
esac
fi
```
Thus I presume that providing an out-of-line `mbsinit()` will not fix
the issue, as it is replaced unconditionally if the triplet matches
`*-*-mingw*`.
Ah, yes, indeed.
But there's another plot twist. If mbsinit is deemed to be missing (as it
is with ucrt right now), gnulib also replaces the definition of mbstate_t
like this:
typedef int rpl_mbstate_t;
#undef mbstate_t
#define mbstate_t rpl_mbstate_t
That's why the gnulib-provided mbsinit has built fine for me - but if
actually providing mbsinit, it breaks as gnulib still tries to build its
own mbsinit, but using the system's mbstate_t type.
So I'd guess that to reach the error Tom got, configure would have
detected an mbsinit function. Not sure how that happens though, unless
using a mixed set of headers and libs (headers for ucrt but libs targeting
msvcrt).
One potential workaround, not very pretty though, would be to change the
current
typedef struct _Mbstatet {
unsigned long _Wchar;
unsigned short _Byte, _State;
} _Mbstatet;
typedef _Mbstatet mbstate_t;
into this:
typedef uint64_t mbstate_t;
That should at least allocate an equally large state variable, and for
most cases (except mbsinit?) mbstate_t is used as an opaque storage, only
the crt-provided multibyte functions normally touch its internals.
That would of course break any code that actually wants to deal with the
UCRT mbstate_t though...
// Martin
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public