diff options
author | Bruno Haible <bruno@clisp.org> | 2020-01-09 01:47:17 +0100 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2020-01-09 01:47:17 +0100 |
commit | 9be236d67f3d78235c5cbe4381c5dd7b3cddb179 (patch) | |
tree | 09bcc0427c1bd58585080336ebed1fe1bfde6898 /lib/mbrtoc32.c | |
parent | 877b0c46019d34e722c94248edbfaf5bfbaa17ec (diff) | |
download | gnulib-9be236d67f3d78235c5cbe4381c5dd7b3cddb179.tar.gz |
mbrtoc32: Use the system's mbrtoc32 if it exists and basically works.
* m4/mbrtoc32.m4 (gl_MBRTOC32_SANITYCHECK): New macro.
(gl_FUNC_MBRTOC32): Require it. Set REPLACE_MBRTOC32 if mbrtoc32 exists
but is not working.
* lib/mbrtoc32.c: Include hard-locale.h, <locale.h>.
(mbrtoc32): If the char32_t encoding and the wchar_t encoding may
differ, use the system's mbrtoc32, adding workarounds.
* modules/mbrtoc32 (Depends-on): Add hard-locale.
* doc/posix-functions/mbrtoc32.texi: Mention the Solaris and native
Windows problem.
* lib/btoc32.c: Include <stdio.h>, <string.h>.
(btoc32): If the char32_t encoding and the wchar_t encoding may differ,
use mbrtoc32, not btowc.
* modules/btoc32 (Depends-on): Add mbrtoc32.
* lib/mbsrtoc32s.c (mbsrtoc32s): If the char32_t encoding and the
wchar_t encoding may differ, use mbrtoc32, not mbsrtowcs.
* modules/mbsrtoc32s (Depends-on): Update conditions.
(configure.ac): Compile mbsrtoc32s-state.c unconditionally.
* lib/mbsnrtoc32s.c (mbsnrtoc32s): If the char32_t encoding and the
wchar_t encoding may differ, use mbrtoc32, not mbsnrtowcs.
* modules/mbsnrtoc32s (Depends-on): Update conditions.
(configure.ac): Compile mbsrtoc32s-state.c unconditionally.
Diffstat (limited to 'lib/mbrtoc32.c')
-rw-r--r-- | lib/mbrtoc32.c | 53 |
1 files changed, 39 insertions, 14 deletions
diff --git a/lib/mbrtoc32.c b/lib/mbrtoc32.c index f2cf71ec11..facf28bc54 100644 --- a/lib/mbrtoc32.c +++ b/lib/mbrtoc32.c @@ -24,13 +24,13 @@ #include <errno.h> #include <stdlib.h> -# ifndef FALLTHROUGH -# if __GNUC__ < 7 -# define FALLTHROUGH ((void) 0) -# else -# define FALLTHROUGH __attribute__ ((__fallthrough__)) -# endif +#ifndef FALLTHROUGH +# if __GNUC__ < 7 +# define FALLTHROUGH ((void) 0) +# else +# define FALLTHROUGH __attribute__ ((__fallthrough__)) # endif +#endif #if GNULIB_defined_mbstate_t /* AIX, IRIX */ /* Implement mbrtoc32() on top of mbtowc() for the non-UTF-8 locales @@ -74,17 +74,23 @@ mbrtoc32 (char32_t *pwc, const char *s, size_t n, mbstate_t *ps) #else /* glibc, macOS, FreeBSD, NetBSD, OpenBSD, HP-UX, Solaris, Cygwin, mingw, MSVC, Minix, Android */ -/* Implement mbrtoc32() based on mbrtowc(). */ +/* Implement mbrtoc32() based on the original mbrtoc32() or on mbrtowc(). */ # include <wchar.h> # include "localcharset.h" # include "streq.h" +# if MBRTOC32_IN_C_LOCALE_MAYBE_EILSEQ +# include "hard-locale.h" +# include <locale.h> +# endif + static mbstate_t internal_state; size_t mbrtoc32 (char32_t *pwc, const char *s, size_t n, mbstate_t *ps) +# undef mbrtoc32 { /* It's simpler to handle the case s == NULL upfront, than to worry about this case later, before every test of pwc and n. */ @@ -103,7 +109,31 @@ mbrtoc32 (char32_t *pwc, const char *s, size_t n, mbstate_t *ps) if (ps == NULL) ps = &internal_state; -# if _GL_LARGE_CHAR32_T +# if HAVE_WORKING_MBRTOC32 + /* mbrtoc32() may produce different values for wc than mbrtowc(). Therefore + use mbrtoc32(). */ + +# if defined _WIN32 && !defined __CYGWIN__ + char32_t wc; + size_t ret = mbrtoc32 (&wc, s, n, ps); + if (ret < (size_t) -2 && pwc != NULL) + *pwc = wc; +# else + size_t ret = mbrtoc32 (pwc, s, n, ps); +# endif + +# if MBRTOC32_IN_C_LOCALE_MAYBE_EILSEQ + if ((size_t) -2 <= ret && n != 0 && ! hard_locale (LC_CTYPE)) + { + if (pwc != NULL) + *pwc = (unsigned char) *s; + return 1; + } +# endif + + return ret; + +# elif _GL_LARGE_CHAR32_T /* Special-case all encodings that may produce wide character values > WCHAR_MAX. */ @@ -209,12 +239,7 @@ mbrtoc32 (char32_t *pwc, const char *s, size_t n, mbstate_t *ps) # else - /* char32_t and wchar_t are equivalent. - Two implementations are possible: - - We can call the original mbrtoc32 (if it exists) and handle - MBRTOC32_IN_C_LOCALE_MAYBE_EILSEQ. - - We can call mbrtowc. - The latter is simpler. */ + /* char32_t and wchar_t are equivalent. Use mbrtowc(). */ wchar_t wc; size_t ret = mbrtowc (&wc, s, n, ps); if (ret < (size_t) -2 && pwc != NULL) |