Paul Eggert wrote: > > Currently it fails on: glibc, OpenBSD, Cygwin, mingw, MSVC. (Which is a > > little > > more than the platforms from > > <https://lists.gnu.org/archive/html/bug-gnulib/2026-08/msg00308.html>.) > The test also fails on NetBSD 11.0 because in the C locale its mbrtoc32 > treats bytes in the range 0x80-0xFF as encoding errors, like glibc does. It > seems that NetBSD 11.0 was the first NetBSD version to support mbrtoc32.
Good point. I've now replaced NetBSD 10 with NetBSD 11 in my CI, and while in a testdir of module 'c32rtomb' I see FAIL: test-c32rtomb.sh (like you say), in a testdir of module 'c32isprint' I see FAIL: test-c32isprint.sh FAIL: test-c32rtomb.sh So, the test-c32isprint failure needs to be fixed first. This patch does it. 2026-09-15 Bruno Haible <[email protected]> mbrtoc32: Fix test-c32isprint failure on NetBSD 11. * lib/mbrtoc32.c (mbrtoc32) [HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB && !_GL_WCHAR_T_IS_UCS4]: In the C locale, map 0x80..0xFF differently. * lib/btoc32.c (btoc32) [HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB && !_GL_WCHAR_T_IS_UCS4]: Likewise. * lib/c32is-impl.h (FUNC): Update comments. * lib/c32to-impl.h (FUNC): Likewise. * lib/c32width.c (c32width): Likewise. * doc/posix-functions/mbrtoc32.texi: Mention the NetBSD problem. diff --git a/doc/posix-functions/mbrtoc32.texi b/doc/posix-functions/mbrtoc32.texi index b64fb4b9ce..595848518d 100644 --- a/doc/posix-functions/mbrtoc32.texi +++ b/doc/posix-functions/mbrtoc32.texi @@ -25,7 +25,7 @@ In the C or POSIX locales, this function returns values like in ISO-8859-1 locales, which leads to @code{c32isprint} etc.@: being inconsistent with @code{isprint}: -OpenBSD 7.9. +NetBSD 11.0, OpenBSD 7.9. @item This function returns 0 instead of @code{(size_t) -2} when the input is empty: diff --git a/lib/btoc32.c b/lib/btoc32.c index c067efd943..9c028eb5c9 100644 --- a/lib/btoc32.c +++ b/lib/btoc32.c @@ -27,6 +27,8 @@ #include <wchar.h> #if MBRTOC32_IN_C_LOCALE_MAYBE_LIKE_ISO_8859 \ + || (!GNULIB_defined_mbstate_t && HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB \ + && !_GL_WCHAR_T_IS_UCS4) \ || (!GNULIB_defined_mbstate_t && _GL_SMALL_WCHAR_T) \ || ((!(HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB) && !_GL_SMALL_WCHAR_T) \ && GL_CHAR32_T_IS_UNICODE && GL_CHAR32_T_VS_WCHAR_T_NEEDS_CONVERSION) @@ -45,6 +47,8 @@ wint_t btoc32 (int c) { #if MBRTOC32_IN_C_LOCALE_MAYBE_LIKE_ISO_8859 /* OpenBSD */ \ + || (!GNULIB_defined_mbstate_t && HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB \ + && !_GL_WCHAR_T_IS_UCS4) /* NetBSD ≥ 11 */ \ || (!GNULIB_defined_mbstate_t && _GL_SMALL_WCHAR_T) /* Cygwin, mingw, MSVC */ \ || ((!(HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB) && !_GL_SMALL_WCHAR_T) \ && GL_CHAR32_T_IS_UNICODE && GL_CHAR32_T_VS_WCHAR_T_NEEDS_CONVERSION) diff --git a/lib/c32is-impl.h b/lib/c32is-impl.h index 2cd03dc4d2..8115217908 100644 --- a/lib/c32is-impl.h +++ b/lib/c32is-impl.h @@ -57,7 +57,7 @@ FUNC (wint_t wc) else return 0; -#elif HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB /* glibc, Android */ +#elif HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB /* glibc, NetBSD ≥ 11, Android */ /* mbrtoc32() is essentially defined by the system libc. */ # if _GL_WCHAR_T_IS_UCS4 @@ -92,7 +92,7 @@ FUNC (wint_t wc) return UCS_FUNC (wc); # endif -#else /* macOS, FreeBSD, NetBSD, OpenBSD, HP-UX, Solaris, Minix, Android */ +#else /* macOS, FreeBSD, NetBSD < 11, OpenBSD, HP-UX, Solaris, Minix, Android */ /* char32_t and wchar_t are equivalent. */ static_assert (sizeof (char32_t) == sizeof (wchar_t)); diff --git a/lib/c32to-impl.h b/lib/c32to-impl.h index b89cc98e2d..1c8dc1beb0 100644 --- a/lib/c32to-impl.h +++ b/lib/c32to-impl.h @@ -74,7 +74,7 @@ FUNC (wint_t wc) return UCS_FUNC (wc); # endif -#elif HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB /* glibc, Android */ +#elif HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB /* glibc, NetBSD ≥ 11, Android */ /* mbrtoc32() is essentially defined by the system libc. */ # if _GL_WCHAR_T_IS_UCS4 @@ -90,7 +90,7 @@ FUNC (wint_t wc) return wc; # endif -#else /* macOS, FreeBSD, NetBSD, OpenBSD, HP-UX, Solaris, Minix, Android */ +#else /* macOS, FreeBSD, NetBSD < 11, OpenBSD, HP-UX, Solaris, Minix, Android */ /* char32_t and wchar_t are equivalent. */ static_assert (sizeof (char32_t) == sizeof (wchar_t)); diff --git a/lib/c32width.c b/lib/c32width.c index da944cfe74..807fb0cacb 100644 --- a/lib/c32width.c +++ b/lib/c32width.c @@ -58,7 +58,7 @@ c32width (char32_t wc) else return wcwidth (wc); -#elif HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB /* glibc, Android */ +#elif HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB /* glibc, NetBSD ≥ 11, Android */ /* mbrtoc32() is essentially defined by the system libc. */ # if _GL_WCHAR_T_IS_UCS4 @@ -90,7 +90,7 @@ c32width (char32_t wc) return uc_width (wc, locale_charset ()); # endif -#else /* macOS, FreeBSD, NetBSD, OpenBSD, HP-UX, Solaris, Minix, Android */ +#else /* macOS, FreeBSD, NetBSD < 11, OpenBSD, HP-UX, Solaris, Minix, Android */ /* char32_t and wchar_t are equivalent. */ static_assert (sizeof (char32_t) == sizeof (wchar_t)); diff --git a/lib/mbrtoc32.c b/lib/mbrtoc32.c index 34ac7b8348..00de09a258 100644 --- a/lib/mbrtoc32.c +++ b/lib/mbrtoc32.c @@ -94,6 +94,7 @@ mbrtoc32 (char32_t *pwc, const char *s, size_t n, mbstate_t *ps) # 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 \ || ((!(HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB) && !_GL_SMALL_WCHAR_T) \ && GL_CHAR32_T_IS_UNICODE && GL_CHAR32_T_VS_WCHAR_T_NEEDS_CONVERSION)) @@ -141,6 +142,7 @@ mbrtoc32 (char32_t *pwc, const char *s, size_t n, mbstate_t *ps) # if (MBRTOC32_EMPTY_INPUT_BUG \ || (GNULIB_WCHAR_SINGLE_LOCALE && __GLIBC__ >= 2 && !__UCLIBC__) \ || MBRTOC32_IN_C_LOCALE_MAYBE_LIKE_ISO_8859 \ + || (HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB && !_GL_WCHAR_T_IS_UCS4) \ || _GL_SMALL_WCHAR_T \ || ((!(HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB) && !_GL_SMALL_WCHAR_T) \ && GL_CHAR32_T_IS_UNICODE && GL_CHAR32_T_VS_WCHAR_T_NEEDS_CONVERSION)) @@ -270,7 +272,8 @@ mbrtoc32 (char32_t *pwc, const char *s, size_t n, mbstate_t *ps) /* mbrtoc32() may produce different values for wc than mbrtowc(). Therefore use mbrtoc32(). */ -# if MBRTOC32_IN_C_LOCALE_MAYBE_LIKE_ISO_8859 /* OpenBSD */ +# if MBRTOC32_IN_C_LOCALE_MAYBE_LIKE_ISO_8859 /* OpenBSD */ \ + || !_GL_WCHAR_T_IS_UCS4 /* NetBSD ≥ 11 */ if (!hard_locale (LC_CTYPE)) { /* In the "C" locale, map the bytes 0x80..0xFF to U+DF80..U+DFFF, so that
