2 # serial 44 -*- coding: utf-8 -*-
3 dnl Copyright (C) 2001-2002, 2004-2005, 2008-2024 Free Software Foundation,
5 dnl This file is free software; the Free Software Foundation
6 dnl gives unlimited permission to copy and/or distribute it,
7 dnl with or without modifications, as long as this notice is preserved.
9 AC_DEFUN([gl_FUNC_MBRTOWC],
11 AC_REQUIRE([gl_WCHAR_H_DEFAULTS])
12 AC_REQUIRE([gl_PTHREADLIB])
13 AC_CHECK_HEADERS_ONCE([threads.h])
15 AC_REQUIRE([AC_TYPE_MBSTATE_T])
18 AC_CHECK_FUNCS_ONCE([mbrtowc])
19 if test $ac_cv_func_mbrtowc = no; then
21 AC_CHECK_DECLS([mbrtowc],,, [[
24 if test $ac_cv_have_decl_mbrtowc = yes; then
25 dnl On Minix 3.1.8, the system's <wchar.h> declares mbrtowc() although
26 dnl it does not have the function. Avoid a collision with gnulib's
31 if test $REPLACE_MBSTATE_T = 1; then
38 gl_MBRTOWC_STORES_INCOMPLETE
39 gl_MBRTOWC_EMPTY_INPUT
41 case "$gl_cv_func_mbrtowc_null_arg1" in
43 *) AC_DEFINE([MBRTOWC_NULL_ARG1_BUG], [1],
44 [Define if the mbrtowc function has the NULL pwc argument bug.])
48 case "$gl_cv_func_mbrtowc_null_arg2" in
50 *) AC_DEFINE([MBRTOWC_NULL_ARG2_BUG], [1],
51 [Define if the mbrtowc function has the NULL string argument bug.])
55 case "$gl_cv_func_mbrtowc_retval" in
57 *) AC_DEFINE([MBRTOWC_RETVAL_BUG], [1],
58 [Define if the mbrtowc function returns a wrong return value.])
62 case "$gl_cv_func_mbrtowc_nul_retval" in
64 *) AC_DEFINE([MBRTOWC_NUL_RETVAL_BUG], [1],
65 [Define if the mbrtowc function does not return 0 for a NUL character.])
69 case "$gl_cv_func_mbrtowc_stores_incomplete" in
71 *) AC_DEFINE([MBRTOWC_STORES_INCOMPLETE_BUG], [1],
72 [Define if the mbrtowc function stores a wide character when reporting incomplete input.])
76 case "$gl_cv_func_mbrtowc_empty_input" in
78 *) AC_DEFINE([MBRTOWC_EMPTY_INPUT_BUG], [1],
79 [Define if the mbrtowc function does not return (size_t) -2
84 case "$gl_cv_func_mbrtowc_C_locale_sans_EILSEQ" in
86 *) AC_DEFINE([MBRTOWC_IN_C_LOCALE_MAYBE_EILSEQ], [1],
87 [Define if the mbrtowc function may signal encoding errors in the C locale.])
93 if test $REPLACE_MBSTATE_T = 1; then
100 case "$gl_cv_have_weak" in
101 *yes) MBRTOWC_LIB= ;;
102 *) MBRTOWC_LIB="$LIBPTHREAD" ;;
109 dnl MBRTOWC_LIB is expected to be '-pthread' or '-lpthread' on AIX
110 dnl with gcc or xlc, and empty otherwise.
111 AC_SUBST([MBRTOWC_LIB])
112 dnl For backward compatibility.
113 LIB_MBRTOWC="$MBRTOWC_LIB"
114 AC_SUBST([LIB_MBRTOWC])
117 dnl Test whether mbsinit() and mbrtowc() need to be overridden in a way that
118 dnl redefines the semantics of the given mbstate_t type.
119 dnl Result is REPLACE_MBSTATE_T.
120 dnl When this is set to 1, we replace both mbsinit() and mbrtowc(), in order to
121 dnl avoid inconsistencies.
123 AC_DEFUN_ONCE([gl_MBSTATE_T_BROKEN],
125 AC_REQUIRE([gl_WCHAR_H_DEFAULTS])
126 AC_REQUIRE([AC_CANONICAL_HOST])
128 AC_REQUIRE([AC_TYPE_MBSTATE_T])
129 AC_CHECK_FUNCS_ONCE([mbsinit])
130 AC_CHECK_FUNCS_ONCE([mbrtowc])
131 dnl On native Windows, we know exactly how mbsinit() behaves and don't need
132 dnl to override it, even if - like on MSVC - mbsinit() is only defined as
133 dnl an inline function, not as a global function.
134 if case "$host_os" in
135 mingw* | windows*) true ;;
136 *) test $ac_cv_func_mbsinit = yes ;;
138 && test $ac_cv_func_mbrtowc = yes; then
139 gl_MBRTOWC_INCOMPLETE_STATE
140 gl_MBRTOWC_SANITYCHECK
142 case "$gl_cv_func_mbrtowc_incomplete_state" in
144 *) REPLACE_MBSTATE_T=1 ;;
146 case "$gl_cv_func_mbrtowc_sanitycheck" in
148 *) REPLACE_MBSTATE_T=1 ;;
155 dnl Test whether mbrtowc puts the state into non-initial state when parsing an
156 dnl incomplete multibyte character.
157 dnl Result is gl_cv_func_mbrtowc_incomplete_state.
159 AC_DEFUN([gl_MBRTOWC_INCOMPLETE_STATE],
161 AC_REQUIRE([AC_PROG_CC])
162 AC_REQUIRE([gt_LOCALE_JA])
163 AC_REQUIRE([gt_LOCALE_FR_UTF8])
164 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
165 AC_CACHE_CHECK([whether mbrtowc handles incomplete characters],
166 [gl_cv_func_mbrtowc_incomplete_state],
168 dnl Initial guess, used when cross-compiling or when no suitable locale
172 # Guess no on AIX and OSF/1.
173 aix* | osf*) gl_cv_func_mbrtowc_incomplete_state="guessing no" ;;
174 # Guess yes otherwise.
175 *) gl_cv_func_mbrtowc_incomplete_state="guessing yes" ;;
178 if test $LOCALE_JA != none; then
186 if (setlocale (LC_ALL, "$LOCALE_JA") != NULL)
188 const char input[] = "B\217\253\344\217\251\316er"; /* "Büßer" */
192 memset (&state, '\0', sizeof (mbstate_t));
193 if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
194 if (mbsinit (&state))
199 [gl_cv_func_mbrtowc_incomplete_state=yes],
200 [gl_cv_func_mbrtowc_incomplete_state=no],
203 if test $LOCALE_FR_UTF8 != none; then
211 if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
213 const char input[] = "B\303\274\303\237er"; /* "Büßer" */
217 memset (&state, '\0', sizeof (mbstate_t));
218 if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
219 if (mbsinit (&state))
224 [gl_cv_func_mbrtowc_incomplete_state=yes],
225 [gl_cv_func_mbrtowc_incomplete_state=no],
232 dnl Test whether mbrtowc works not worse than mbtowc.
233 dnl Result is gl_cv_func_mbrtowc_sanitycheck.
235 AC_DEFUN([gl_MBRTOWC_SANITYCHECK],
237 AC_REQUIRE([AC_PROG_CC])
238 AC_REQUIRE([gt_LOCALE_ZH_CN])
239 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
240 AC_CACHE_CHECK([whether mbrtowc works as well as mbtowc],
241 [gl_cv_func_mbrtowc_sanitycheck],
243 dnl Initial guess, used when cross-compiling or when no suitable locale
247 # Guess no on Solaris 8.
248 solaris2.8) gl_cv_func_mbrtowc_sanitycheck="guessing no" ;;
249 # Guess yes otherwise.
250 *) gl_cv_func_mbrtowc_sanitycheck="guessing yes" ;;
253 if test $LOCALE_ZH_CN != none; then
262 /* This fails on Solaris 8:
263 mbrtowc returns 2, and sets wc to 0x00F0.
264 mbtowc returns 4 (correct) and sets wc to 0x5EDC. */
265 if (setlocale (LC_ALL, "$LOCALE_ZH_CN") != NULL)
267 char input[] = "B\250\271\201\060\211\070er"; /* "Büßer" */
271 memset (&state, '\0', sizeof (mbstate_t));
272 if (mbrtowc (&wc, input + 3, 6, &state) != 4
273 && mbtowc (&wc, input + 3, 6) == 4)
278 [gl_cv_func_mbrtowc_sanitycheck=yes],
279 [gl_cv_func_mbrtowc_sanitycheck=no],
285 dnl Test whether mbrtowc supports a NULL pwc argument correctly.
286 dnl Result is gl_cv_func_mbrtowc_null_arg1.
288 AC_DEFUN([gl_MBRTOWC_NULL_ARG1],
290 AC_REQUIRE([AC_PROG_CC])
291 AC_REQUIRE([gt_LOCALE_FR_UTF8])
292 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
293 AC_CACHE_CHECK([whether mbrtowc handles a NULL pwc argument],
294 [gl_cv_func_mbrtowc_null_arg1],
296 dnl Initial guess, used when cross-compiling or when no suitable locale
300 # Guess no on Solaris.
301 solaris*) gl_cv_func_mbrtowc_null_arg1="guessing no" ;;
302 # Guess yes otherwise.
303 *) gl_cv_func_mbrtowc_null_arg1="guessing yes" ;;
306 if test $LOCALE_FR_UTF8 != none; then
317 if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
319 char input[] = "\303\237er";
324 memset (&state, '\0', sizeof (mbstate_t));
325 wc = (wchar_t) 0xBADFACE;
326 ret = mbrtowc (&wc, input, 5, &state);
329 if (!mbsinit (&state))
332 memset (&state, '\0', sizeof (mbstate_t));
333 ret = mbrtowc (NULL, input, 5, &state);
334 if (ret != 2) /* Solaris 7 fails here: ret is -1. */
336 if (!mbsinit (&state))
341 [gl_cv_func_mbrtowc_null_arg1=yes],
342 [gl_cv_func_mbrtowc_null_arg1=no],
348 dnl Test whether mbrtowc supports a NULL string argument correctly.
349 dnl Result is gl_cv_func_mbrtowc_null_arg2.
351 AC_DEFUN([gl_MBRTOWC_NULL_ARG2],
353 AC_REQUIRE([AC_PROG_CC])
354 AC_REQUIRE([gt_LOCALE_FR_UTF8])
355 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
356 AC_CACHE_CHECK([whether mbrtowc handles a NULL string argument],
357 [gl_cv_func_mbrtowc_null_arg2],
359 dnl Initial guess, used when cross-compiling or when no suitable locale
364 osf*) gl_cv_func_mbrtowc_null_arg2="guessing no" ;;
365 # Guess yes otherwise.
366 *) gl_cv_func_mbrtowc_null_arg2="guessing yes" ;;
369 if test $LOCALE_FR_UTF8 != none; then
377 if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
383 memset (&state, '\0', sizeof (mbstate_t));
384 wc = (wchar_t) 0xBADFACE;
385 mbrtowc (&wc, NULL, 5, &state);
386 /* Check that wc was not modified. */
387 if (wc != (wchar_t) 0xBADFACE)
392 [gl_cv_func_mbrtowc_null_arg2=yes],
393 [gl_cv_func_mbrtowc_null_arg2=no],
399 dnl Test whether mbrtowc, when parsing the end of a multibyte character,
400 dnl correctly returns the number of bytes that were needed to complete the
401 dnl character (not the total number of bytes of the multibyte character).
402 dnl Result is gl_cv_func_mbrtowc_retval.
404 AC_DEFUN([gl_MBRTOWC_RETVAL],
406 AC_REQUIRE([AC_PROG_CC])
407 AC_REQUIRE([gt_LOCALE_FR_UTF8])
408 AC_REQUIRE([gt_LOCALE_JA])
409 AC_REQUIRE([AC_CANONICAL_HOST])
410 AC_CACHE_CHECK([whether mbrtowc has a correct return value],
411 [gl_cv_func_mbrtowc_retval],
413 dnl Initial guess, used when cross-compiling or when no suitable locale
417 # Guess no on HP-UX, Solaris, native Windows.
418 hpux* | solaris* | mingw* | windows*)
419 gl_cv_func_mbrtowc_retval="guessing no" ;;
420 # Guess yes otherwise.
422 gl_cv_func_mbrtowc_retval="guessing yes" ;;
425 if test $LOCALE_FR_UTF8 != none || test $LOCALE_JA != none \
426 || { case "$host_os" in mingw* | windows*) true;; *) false;; esac; }; then
435 int found_some_locale = 0;
436 /* This fails on Solaris. */
437 if (strcmp ("$LOCALE_FR_UTF8", "none") != 0
438 && setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
440 char input[] = "B\303\274\303\237er"; /* "Büßer" */
444 memset (&state, '\0', sizeof (mbstate_t));
445 if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
448 if (mbrtowc (&wc, input + 2, 5, &state) != 1)
451 found_some_locale = 1;
453 /* This fails on HP-UX 11.11. */
454 if (strcmp ("$LOCALE_JA", "none") != 0
455 && setlocale (LC_ALL, "$LOCALE_JA") != NULL)
457 char input[] = "B\217\253\344\217\251\316er"; /* "Büßer" */
461 memset (&state, '\0', sizeof (mbstate_t));
462 if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
465 if (mbrtowc (&wc, input + 2, 5, &state) != 2)
468 found_some_locale = 1;
470 /* This fails on native Windows. */
471 if (setlocale (LC_ALL, "Japanese_Japan.932") != NULL)
473 char input[] = "<\223\372\226\173\214\352>"; /* "<日本語>" */
477 memset (&state, '\0', sizeof (mbstate_t));
478 if (mbrtowc (&wc, input + 3, 1, &state) == (size_t)(-2))
481 if (mbrtowc (&wc, input + 4, 4, &state) != 1)
484 found_some_locale = 1;
486 if (setlocale (LC_ALL, "Chinese_Taiwan.950") != NULL)
488 char input[] = "<\244\351\245\273\273\171>"; /* "<日本語>" */
492 memset (&state, '\0', sizeof (mbstate_t));
493 if (mbrtowc (&wc, input + 3, 1, &state) == (size_t)(-2))
496 if (mbrtowc (&wc, input + 4, 4, &state) != 1)
499 found_some_locale = 1;
501 if (setlocale (LC_ALL, "Chinese_China.936") != NULL)
503 char input[] = "<\310\325\261\276\325\132>"; /* "<日本語>" */
507 memset (&state, '\0', sizeof (mbstate_t));
508 if (mbrtowc (&wc, input + 3, 1, &state) == (size_t)(-2))
511 if (mbrtowc (&wc, input + 4, 4, &state) != 1)
514 found_some_locale = 1;
516 return (found_some_locale ? result : 77);
518 [gl_cv_func_mbrtowc_retval=yes],
519 [if test $? != 77; then
520 gl_cv_func_mbrtowc_retval=no
528 dnl Test whether mbrtowc, when parsing a NUL character, correctly returns 0.
529 dnl Result is gl_cv_func_mbrtowc_nul_retval.
531 AC_DEFUN([gl_MBRTOWC_NUL_RETVAL],
533 AC_REQUIRE([AC_PROG_CC])
534 AC_REQUIRE([gt_LOCALE_ZH_CN])
535 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
536 AC_CACHE_CHECK([whether mbrtowc returns 0 when parsing a NUL character],
537 [gl_cv_func_mbrtowc_nul_retval],
539 dnl Initial guess, used when cross-compiling or when no suitable locale
543 # Guess no on Solaris 8 and 9.
544 solaris2.[89]) gl_cv_func_mbrtowc_nul_retval="guessing no" ;;
545 # Guess yes otherwise.
546 *) gl_cv_func_mbrtowc_nul_retval="guessing yes" ;;
549 if test $LOCALE_ZH_CN != none; then
557 /* This fails on Solaris 8 and 9. */
558 if (setlocale (LC_ALL, "$LOCALE_ZH_CN") != NULL)
563 memset (&state, '\0', sizeof (mbstate_t));
564 if (mbrtowc (&wc, "", 1, &state) != 0)
569 [gl_cv_func_mbrtowc_nul_retval=yes],
570 [gl_cv_func_mbrtowc_nul_retval=no],
576 dnl Test whether mbrtowc stores a wide character when reporting incomplete
579 AC_DEFUN([gl_MBRTOWC_STORES_INCOMPLETE],
581 AC_REQUIRE([AC_PROG_CC])
582 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
583 AC_CACHE_CHECK([whether mbrtowc stores incomplete characters],
584 [gl_cv_func_mbrtowc_stores_incomplete],
586 dnl Initial guess, used when cross-compiling or when no suitable locale
590 # Guess yes on native Windows.
591 mingw* | windows*) gl_cv_func_mbrtowc_stores_incomplete="guessing yes" ;;
592 *) gl_cv_func_mbrtowc_stores_incomplete="guessing no" ;;
605 if (setlocale (LC_ALL, "French_France.65001") != NULL)
607 wchar_t wc = (wchar_t) 0xBADFACE;
610 memset (&state, '\0', sizeof (mbstate_t));
611 if (mbrtowc (&wc, "\303", 1, &state) == (size_t)(-2)
612 && wc != (wchar_t) 0xBADFACE)
615 if (setlocale (LC_ALL, "Japanese_Japan.932") != NULL)
617 wchar_t wc = (wchar_t) 0xBADFACE;
620 memset (&state, '\0', sizeof (mbstate_t));
621 if (mbrtowc (&wc, "\226", 1, &state) == (size_t)(-2)
622 && wc != (wchar_t) 0xBADFACE)
625 if (setlocale (LC_ALL, "Chinese_Taiwan.950") != NULL)
627 wchar_t wc = (wchar_t) 0xBADFACE;
630 memset (&state, '\0', sizeof (mbstate_t));
631 if (mbrtowc (&wc, "\245", 1, &state) == (size_t)(-2)
632 && wc != (wchar_t) 0xBADFACE)
635 if (setlocale (LC_ALL, "Chinese_China.936") != NULL)
637 wchar_t wc = (wchar_t) 0xBADFACE;
640 memset (&state, '\0', sizeof (mbstate_t));
641 if (mbrtowc (&wc, "\261", 1, &state) == (size_t)(-2)
642 && wc != (wchar_t) 0xBADFACE)
647 [gl_cv_func_mbrtowc_stores_incomplete=no],
648 [gl_cv_func_mbrtowc_stores_incomplete=yes],
652 AC_REQUIRE([gt_LOCALE_FR_UTF8])
653 if test $LOCALE_FR_UTF8 != none; then
661 if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
663 wchar_t wc = (wchar_t) 0xBADFACE;
666 memset (&state, '\0', sizeof (mbstate_t));
667 if (mbrtowc (&wc, "\303", 1, &state) == (size_t)(-2)
668 && wc != (wchar_t) 0xBADFACE)
673 [gl_cv_func_mbrtowc_stores_incomplete=no],
674 [gl_cv_func_mbrtowc_stores_incomplete=yes],
682 dnl Test whether mbrtowc returns the correct value on empty input.
684 AC_DEFUN([gl_MBRTOWC_EMPTY_INPUT],
686 AC_REQUIRE([AC_PROG_CC])
687 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
688 AC_CACHE_CHECK([whether mbrtowc works on empty input],
689 [gl_cv_func_mbrtowc_empty_input],
694 static mbstate_t mbs;
698 return mbrtowc (&wc, "", 0, &mbs) != (size_t) -2;
700 [gl_cv_func_mbrtowc_empty_input=yes],
701 [gl_cv_func_mbrtowc_empty_input=no],
703 # Guess no on AIX and glibc systems.
704 aix* | *-gnu* | gnu*) gl_cv_func_mbrtowc_empty_input="guessing no" ;;
705 # Guess no on Android.
706 linux*-android*) gl_cv_func_mbrtowc_empty_input="guessing no" ;;
707 # Guess no on native Windows.
708 mingw* | windows*) gl_cv_func_mbrtowc_empty_input="guessing no" ;;
709 *) gl_cv_func_mbrtowc_empty_input="guessing yes" ;;
715 dnl Test whether mbrtowc reports encoding errors in the C locale.
716 dnl Although POSIX was never intended to allow this, the GNU C Library
717 dnl and other implementations do it. See:
718 dnl https://sourceware.org/bugzilla/show_bug.cgi?id=19932
719 dnl POSIX has now clarified it:
720 dnl <https://pubs.opengroup.org/onlinepubs/9699919799/functions/mbrtowc.html>
721 dnl says: "In the POSIX locale an [EILSEQ] error cannot occur since all byte
722 dnl values are valid characters."
724 AC_DEFUN([gl_MBRTOWC_C_LOCALE],
726 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
727 AC_CACHE_CHECK([whether the C locale is free of encoding errors],
728 [gl_cv_func_mbrtowc_C_locale_sans_EILSEQ],
731 [[#include <limits.h>
736 char *locale = setlocale (LC_ALL, "C");
739 for (i = CHAR_MIN; i <= CHAR_MAX; i++)
743 mbstate_t mbs = { 0, };
744 size_t ss = mbrtowc (&wc, &c, 1, &mbs);
750 [gl_cv_func_mbrtowc_C_locale_sans_EILSEQ=yes],
751 [gl_cv_func_mbrtowc_C_locale_sans_EILSEQ=no],
753 # Guess yes on native Windows.
754 mingw* | windows*) gl_cv_func_mbrtowc_C_locale_sans_EILSEQ="guessing yes" ;;
755 *) gl_cv_func_mbrtowc_C_locale_sans_EILSEQ="$gl_cross_guess_normal" ;;
761 # Prerequisites of lib/mbrtowc.c and lib/lc-charset-dispatch.c.
762 AC_DEFUN([gl_PREREQ_MBRTOWC], [
763 AC_REQUIRE([AC_C_INLINE])
767 # Prerequisites of lib/mbtowc-lock.c.
768 AC_DEFUN([gl_PREREQ_MBTOWC_LOCK],
776 dnl This is an override of an autoconf macro.
778 AC_DEFUN([AC_FUNC_MBRTOWC],
780 dnl Same as AC_FUNC_MBRTOWC in autoconf-2.60.
781 AC_CACHE_CHECK([whether mbrtowc and mbstate_t are properly declared],
782 [gl_cv_func_mbrtowc],
785 [[#include <wchar.h>]],
790 return ! (sizeof state && (mbrtowc) (&wc, s, n, &state));]])],
791 [gl_cv_func_mbrtowc=yes],
792 [gl_cv_func_mbrtowc=no])])
793 if test $gl_cv_func_mbrtowc = yes; then
794 AC_DEFINE([HAVE_MBRTOWC], [1],
795 [Define to 1 if mbrtowc and mbstate_t are properly declared.])