mirror of
https://git.savannah.gnu.org/git/gnulib.git
synced 2026-10-24 00:48:56 +03:00
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 commit is contained in:
14
ChangeLog
14
ChangeLog
@@ -1,3 +1,17 @@
|
||||
2026-09-16 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
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.
|
||||
|
||||
2026-09-16 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
strerrorname_np: Ensure it handles EFTYPE.
|
||||
|
||||
@@ -32,11 +32,19 @@
|
||||
# include "lc-charset-unicode.h"
|
||||
#endif
|
||||
|
||||
#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)
|
||||
# include "hard-locale.h"
|
||||
# include <locale.h>
|
||||
#endif
|
||||
|
||||
size_t
|
||||
c32rtomb (char *s, char32_t wc, mbstate_t *ps)
|
||||
#undef c32rtomb
|
||||
{
|
||||
#if HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB
|
||||
#if !GNULIB_defined_mbstate_t && HAVE_WORKING_MBRTOC32 && HAVE_WORKING_C32RTOMB
|
||||
|
||||
# if C32RTOMB_RETVAL_BUG
|
||||
if (s == NULL)
|
||||
@@ -44,9 +52,30 @@ c32rtomb (char *s, char32_t wc, mbstate_t *ps)
|
||||
return 1;
|
||||
# endif
|
||||
|
||||
# if MBRTOC32_IN_C_LOCALE_MAYBE_LIKE_ISO_8859 /* OpenBSD */ \
|
||||
|| !_GL_WCHAR_T_IS_UCS4 /* NetBSD ≥ 11 */
|
||||
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;
|
||||
}
|
||||
# endif
|
||||
|
||||
# if MBRTOC32_IN_C_LOCALE_MAYBE_EILSEQ
|
||||
if ((wc >= 0x0080 && wc <= 0x00FF) && !hard_locale (LC_CTYPE))
|
||||
{
|
||||
/* In the "C" locale, map the code points U+0080..U+00FF back to the bytes
|
||||
0x80..0xFF, for consistency with the mbrtoc32 and btoc32 functions. */
|
||||
s[0] = (unsigned char) wc;
|
||||
return 1;
|
||||
}
|
||||
# endif
|
||||
|
||||
return c32rtomb (s, wc, ps);
|
||||
|
||||
#elif _GL_SMALL_WCHAR_T
|
||||
#elif !GNULIB_defined_mbstate_t && _GL_SMALL_WCHAR_T /* Cygwin, mingw, MSVC */
|
||||
|
||||
if (s == NULL)
|
||||
return wcrtomb (NULL, 0, ps);
|
||||
@@ -100,6 +129,27 @@ c32rtomb (char *s, char32_t wc, mbstate_t *ps)
|
||||
return count;
|
||||
}
|
||||
}
|
||||
else if (!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. */
|
||||
if (wc >= 0x00 && wc <= 0x7F)
|
||||
{
|
||||
s[0] = (unsigned char) wc;
|
||||
return 1;
|
||||
}
|
||||
else if (wc >= 0xDF80 && wc <= 0xDFFF)
|
||||
{
|
||||
s[0] = (unsigned char) (wc - 0xDF00);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
errno = EILSEQ;
|
||||
return (size_t)(-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((wchar_t) wc == wc)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# c32rtomb.m4
|
||||
# serial 10
|
||||
# serial 11
|
||||
dnl Copyright (C) 2020-2026 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
@@ -12,6 +12,8 @@ AC_DEFUN([gl_FUNC_C32RTOMB],
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
|
||||
AC_REQUIRE([gl_MBRTOC32_SANITYCHECK])
|
||||
AC_REQUIRE([gl_MBRTOC32_C_LOCALE])
|
||||
AC_REQUIRE([gl_MBRTOC32_C_LOCALE_LIKE_ISO_8859])
|
||||
AC_REQUIRE([gl_C32RTOMB_SANITYCHECK])
|
||||
|
||||
AC_REQUIRE([gl_CHECK_FUNC_C32RTOMB])
|
||||
@@ -23,6 +25,20 @@ AC_DEFUN([gl_FUNC_C32RTOMB],
|
||||
if test $HAVE_WORKING_MBRTOC32 = 0; then
|
||||
REPLACE_C32RTOMB=1
|
||||
fi
|
||||
dnl Likewise when we override it because of its behaviour in the C locale.
|
||||
case "$gl_cv_func_mbrtoc32_C_locale_sans_EILSEQ" in
|
||||
*yes)
|
||||
case "$gl_cv_func_mbrtoc32_C_locale_like_iso_8859" in
|
||||
*yes)
|
||||
case "$host_os" in
|
||||
solaris*) ;;
|
||||
*) REPLACE_C32RTOMB=1 ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*) REPLACE_C32RTOMB=1 ;;
|
||||
esac
|
||||
AC_CACHE_CHECK([whether c32rtomb return value is correct],
|
||||
[gl_cv_func_c32rtomb_retval],
|
||||
[
|
||||
|
||||
@@ -15,6 +15,7 @@ uchar-h
|
||||
attribute [test $HAVE_C32RTOMB = 0 || test $REPLACE_C32RTOMB = 1]
|
||||
wchar-h [test $HAVE_C32RTOMB = 0 || test $REPLACE_C32RTOMB = 1]
|
||||
wcrtomb [test $HAVE_C32RTOMB = 0 || test $REPLACE_C32RTOMB = 1]
|
||||
hard-locale [test $HAVE_C32RTOMB = 0 || test $REPLACE_C32RTOMB = 1]
|
||||
localcharset [{ test $HAVE_C32RTOMB = 0 || test $REPLACE_C32RTOMB = 1; } && test $SMALL_WCHAR_T = 1]
|
||||
streq-opt [{ test $HAVE_C32RTOMB = 0 || test $REPLACE_C32RTOMB = 1; } && test $SMALL_WCHAR_T = 1]
|
||||
|
||||
|
||||
@@ -116,6 +116,23 @@ main (int argc, char *argv[])
|
||||
{
|
||||
case '1':
|
||||
/* C locale; tested above. */
|
||||
#if !defined __ANDROID__
|
||||
/* On Android ≥ 5.0, the default locale is the "C.UTF-8" locale, not the
|
||||
"C" locale. Furthermore, when you attempt to set the "C" or "POSIX"
|
||||
locale via setlocale(), what you get is a "C" locale with UTF-8
|
||||
encoding, that is, effectively the "C.UTF-8" locale. */
|
||||
/* Check that c32rtomb does the inverse of mbrtoc32, in the C locale.
|
||||
Recall that POSIX:2024 says about mbrtoc32:
|
||||
"In the POSIX locale an [EILSEQ] error cannot occur since all
|
||||
byte values are valid characters."
|
||||
Above we have only tested the ISO C "basic character set". */
|
||||
for (int c = 0; c < 0x100; c++)
|
||||
{
|
||||
ret = c32rtomb (buf, btoc32 (c), NULL);
|
||||
ASSERT (ret == 1);
|
||||
ASSERT (buf[0] == (char) c);
|
||||
}
|
||||
#endif
|
||||
return test_exit_status;
|
||||
|
||||
case '2':
|
||||
|
||||
Reference in New Issue
Block a user