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

Reply via email to