I wrote: > 2026-09-16 Bruno Haible <[email protected]> > > c32rtomb: Make consistent with mbrtoc32 in the C locale. > Suggested by Paul Eggert. > * m4/c32rtomb.m4 (gl_FUNC_C32RTOMB): Require gl_MBRTOC32_C_LOCALE, > gl_MBRTOC32_C_LOCALE_LIKE_ISO_8859. When mbrtoc32 gets overridden due to > the C locale, set also REPLACE_C32RTOMB to 1. > * lib/c32rtomb.c: Include hard-locale.h, <locale.h>. > (c32rtomb): On OpenBSD, NetBSD ≥ 11, glibc, Cygwin, mingw, MSVC, do > special handling of non-ASCII characters in the C locale. > * modules/c32rtomb (Depends-on): Add hard-locale. > * tests/test-c32rtomb.c (main): Check that c32rtomb does the inverse of > mbrtoc32 in the C locale.
This patch was tested through a testdir of 'c32isprint', which depends on c32rtomb. But in a testdir of 'c32isprint uchar-h-c23', I still see a test failure on macOS, FreeBSD, NetBSD 10, Solaris 11: FAIL: test-c32rtomb.sh ====================== ../../gltests/test-c32rtomb.c:132: assertion 'ret == 1' failed This patch fixes it. 2026-09-18 Bruno Haible <[email protected]> c32rtomb + uchar-h-c23: Make consistent with mbrtoc32 in the C locale. * lib/c32rtomb.c (c32rtomb) [GL_CHAR32_T_VS_WCHAR_T_NEEDS_CONVERSION]: Do special handling of non-ASCII characters in the C locale. diff --git a/lib/c32rtomb.c b/lib/c32rtomb.c index cb8274f14a..9da0abb6be 100644 --- a/lib/c32rtomb.c +++ b/lib/c32rtomb.c @@ -35,7 +35,8 @@ #if (MBRTOC32_IN_C_LOCALE_MAYBE_LIKE_ISO_8859 \ || MBRTOC32_IN_C_LOCALE_MAYBE_EILSEQ \ || (HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB && !_GL_WCHAR_T_IS_UCS4) \ - || _GL_SMALL_WCHAR_T) + || _GL_SMALL_WCHAR_T \ + || (GL_CHAR32_T_IS_UNICODE && GL_CHAR32_T_VS_WCHAR_T_NEEDS_CONVERSION)) # include "hard-locale.h" # include <locale.h> #endif @@ -166,6 +167,13 @@ c32rtomb (char *s, char32_t wc, mbstate_t *ps) /* char32_t and wchar_t are equivalent. */ # if GL_CHAR32_T_IS_UNICODE && GL_CHAR32_T_VS_WCHAR_T_NEEDS_CONVERSION + if ((wc >= 0xDF80 && wc <= 0xDFFF) && !hard_locale (LC_CTYPE)) + { + /* In the "C" locale, map the code points U+DF80..U+DFFF back to the bytes + 0x80..0xFF, for consistency with the mbrtoc32 and btoc32 functions. */ + s[0] = (unsigned char) (wc - 0xDF00); + return 1; + } if (wc != 0) { wc = unicode_to_locale_encoding (wc);
