[:xdigit:] does not work with std::wstring in a Cygwin environment

Hans-Bernhard Bröker HBBroeker@t-online.de
Tue Feb 15 01:36:08 GMT 2022


Am 13.02.2022 um 19:25 schrieb Achim Gratz:
> Gans, Markus writes:
>> This seems to be an internal Cygwin error:
>> 
>> https://www.reddit.com/r/cpp_questions/comments/sp52gq/xdigit_does_not_work_with_stdwstring_in_a_cygwin/
>
>> 
[…]
>> Question: Why does Cygwin not detect the letters a, b, c, d, e, and
>> f as hexadecimal digits in a wide string?

[...]

> There is no OS specific configuration for Cygwin explicitly, instead
> there is one for newlib that actually gets used.

This piqued my curiosity, so I had a look at how libstdc++ is built.  I
found that at least for one crucial source file, called
ctype_members.cc, cygwin builds do _not_ use the newlib edition, but
rather the "generic" one.  And that may very well be the problem here.

The superficial cause of the problem is that member function
_M_initialize_ctype() in
libstdc++-v3/config/locale/generic/ctype_member.cc fills most of its
array _M_wmask[] with zeroes instead of meaningful character class 
identifiers.

The slightly deeper reason is that the companion array _M_bit[] is also
suspiciously full of zeroes.

But the real problem, IMHO, is that the type ctype<wchar_t>::mask is
just a plain char.  That overflows the looped shift used to fill
_M_bit[], which in turn leads to nonsense in _M_wmask[].

I didn't manage to find where this ctype<wchar_t>::mask is defined, but 
the way it's used here cannot work if it's defined as plain char.  The
newlib edition of ctype_members.cc loops over just 8 bits instead of
16, which would allow this to work.

So we either have to pick up a different type definition of 
ctype<wchar_t>::mask, or a different edition of ctype_members.cc --- I 
guess it should be the newlib one.


More information about the Cygwin mailing list