[: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