From 8f82486d838425aef2a4352c20a214e9789ca65c Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 23 May 2024 23:46:52 +0200 Subject: [PATCH] mbrtoc32: Work around bug in Cygwin 3.5.3. * m4/mbrtoc32.m4 (gl_MBRTOC32_UTF8_LOCALE): New macro. (gl_FUNC_MBRTOC32): Invoke it. If mbrtoc32 has this bug, define MBRTOC32_MULTIBYTE_LOCALE_BUG and reset LOCALE_ZH_CN to 'none'. * lib/mbrtoc32.c (mbrtoc32): Test MBRTOC32_MULTIBYTE_LOCALE_BUG. * doc/posix-functions/mbrtoc32.texi: Mention the Cygwin bug. --- ChangeLog | 9 +++++ doc/posix-functions/mbrtoc32.texi | 6 +++ lib/mbrtoc32.c | 4 +- m4/mbrtoc32.m4 | 61 ++++++++++++++++++++++++++++++- 4 files changed, 76 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index aefe54aa2c..ca996e5e03 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2024-05-23 Bruno Haible + + mbrtoc32: Work around bug in Cygwin 3.5.3. + * m4/mbrtoc32.m4 (gl_MBRTOC32_UTF8_LOCALE): New macro. + (gl_FUNC_MBRTOC32): Invoke it. If mbrtoc32 has this bug, define + MBRTOC32_MULTIBYTE_LOCALE_BUG and reset LOCALE_ZH_CN to 'none'. + * lib/mbrtoc32.c (mbrtoc32): Test MBRTOC32_MULTIBYTE_LOCALE_BUG. + * doc/posix-functions/mbrtoc32.texi: Mention the Cygwin bug. + 2024-05-23 Bruno Haible c32is*, c32toupper tests: Avoid test failures on Cygwin. diff --git a/doc/posix-functions/mbrtoc32.texi b/doc/posix-functions/mbrtoc32.texi index db7d6a0821..aae8d51ee8 100644 --- a/doc/posix-functions/mbrtoc32.texi +++ b/doc/posix-functions/mbrtoc32.texi @@ -33,6 +33,12 @@ FreeBSD 13.2, Solaris 11.4, mingw, MSVC 14. @c For MSVC this is because it assumes that the input is always UTF-8 encoded. @c See https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/mbrtoc16-mbrtoc323 +@item +This function does not work when it's fed the input bytes one-by-one +on some platforms: +@c https://cygwin.com/pipermail/cygwin/2024-May/255989.html +@c https://cygwin.com/pipermail/cygwin/2024-May/255990.html +Cygwin 3.5.3. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/mbrtoc32.c b/lib/mbrtoc32.c index b8d07ccb00..1eb5f85db2 100644 --- a/lib/mbrtoc32.c +++ b/lib/mbrtoc32.c @@ -1,5 +1,5 @@ /* Convert multibyte character to 32-bit wide character. - Copyright (C) 2020-2023 Free Software Foundation, Inc. + Copyright (C) 2020-2024 Free Software Foundation, Inc. This file is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as @@ -113,7 +113,7 @@ mbrtoc32 (char32_t *pwc, const char *s, size_t n, mbstate_t *ps) if (ps == NULL) ps = &internal_state; -# if HAVE_WORKING_MBRTOC32 +# if HAVE_WORKING_MBRTOC32 && !MBRTOC32_MULTIBYTE_LOCALE_BUG /* mbrtoc32() may produce different values for wc than mbrtowc(). Therefore use mbrtoc32(). */ diff --git a/m4/mbrtoc32.m4 b/m4/mbrtoc32.m4 index 25196039bb..f35d38db23 100644 --- a/m4/mbrtoc32.m4 +++ b/m4/mbrtoc32.m4 @@ -1,5 +1,5 @@ -# mbrtoc32.m4 serial 17 -dnl Copyright (C) 2014-2023 Free Software Foundation, Inc. +# mbrtoc32.m4 serial 17.1 +dnl Copyright (C) 2014-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. @@ -26,6 +26,7 @@ AC_DEFUN([gl_FUNC_MBRTOC32], else gl_MBRTOC32_EMPTY_INPUT gl_MBRTOC32_C_LOCALE + gl_MBRTOC32_UTF8_LOCALE case "$gl_cv_func_mbrtoc32_empty_input" in *yes) ;; *) AC_DEFINE([MBRTOC32_EMPTY_INPUT_BUG], [1], @@ -40,6 +41,15 @@ AC_DEFUN([gl_FUNC_MBRTOC32], REPLACE_MBRTOC32=1 ;; esac + case "$gl_cv_func_mbrtoc32_utf8_locale_works" in + *yes) ;; + *) AC_DEFINE([MBRTOC32_MULTIBYTE_LOCALE_BUG], [1], + [Define if the mbrtoc32 function does not accept the input bytes one-by-one.]) + REPLACE_MBRTOC32=1 + dnl Our replacement mbrtoc32 can handle UTF-8, but not GB18030. + LOCALE_ZH_CN=none + ;; + esac fi if test $HAVE_WORKING_MBRTOC32 = 0; then REPLACE_MBRTOC32=1 @@ -162,6 +172,53 @@ AC_DEFUN([gl_MBRTOC32_C_LOCALE], ]) ]) +dnl Test whether mbrtoc32 works when it's fed the bytes one-by-one in an UTF-8 +dnl locale. + +AC_DEFUN([gl_MBRTOC32_UTF8_LOCALE], +[ + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether mbrtoc32 works in an UTF-8 locale], + [gl_cv_func_mbrtoc32_utf8_locale_works], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #ifdef __HAIKU__ + #include + #endif + #include + ]], [[ + char *locale = setlocale (LC_ALL, "en_US.UTF-8"); + if (locale) + { + /* This test fails on Cygwin 3.5.3. */ + mbstate_t state = { 0, }; + char32_t uc = 0xDEADBEEF; + /* \360\237\220\203 = U+0001F403 */ + if (mbrtoc32 (&uc, "\360", 1, &state) != (size_t)-2) + return 1; + if (mbrtoc32 (&uc, "\237", 1, &state) != (size_t)-2) + return 2; + if (mbrtoc32 (&uc, "\220", 1, &state) != (size_t)-2) + return 3; + if (mbrtoc32 (&uc, "\203", 1, &state) != 1) + return 4; + if (uc != 0x0001F403) + return 5; + } + return 0; + ]])], + [gl_cv_func_mbrtoc32_utf8_locale_works=yes], + [gl_cv_func_mbrtoc32_utf8_locale_works=no], + [case "$host_os" in + # Guess no on Cygwin. + cygwin*) gl_cv_func_mbrtoc32_utf8_locale_works="guessing yes" ;; + *) gl_cv_func_mbrtoc32_utf8_locale_works="$gl_cross_guess_normal" ;; + esac + ]) + ]) +]) + dnl Test whether mbrtoc32 works not worse than mbrtowc. dnl Result is HAVE_WORKING_MBRTOC32. -- 2.39.5