1 # mbrtowc.m4 serial 38 -*- coding: utf-8 -*-
2 dnl Copyright (C) 2001-2002, 2004-2005, 2008-2022 Free Software Foundation,
4 dnl This file is free software; the Free Software Foundation
5 dnl gives unlimited permission to copy and/or distribute it,
6 dnl with or without modifications, as long as this notice is preserved.
8 AC_DEFUN([gl_FUNC_MBRTOWC],
10 AC_REQUIRE([gl_WCHAR_H_DEFAULTS])
11 AC_REQUIRE([gl_PTHREADLIB])
12 AC_CHECK_HEADERS_ONCE([threads.h])
14 AC_REQUIRE([AC_TYPE_MBSTATE_T])
17 AC_CHECK_FUNCS_ONCE([mbrtowc])
18 if test $ac_cv_func_mbrtowc = no; then
20 AC_CHECK_DECLS([mbrtowc],,, [[
23 if test $ac_cv_have_decl_mbrtowc = yes; then
24 dnl On Minix 3.1.8, the system's <wchar.h> declares mbrtowc() although
25 dnl it does not have the function. Avoid a collision with gnulib's
30 if test $REPLACE_MBSTATE_T = 1; then
37 gl_MBRTOWC_STORES_INCOMPLETE
38 gl_MBRTOWC_EMPTY_INPUT
40 case "$gl_cv_func_mbrtowc_null_arg1" in
42 *) AC_DEFINE([MBRTOWC_NULL_ARG1_BUG], [1],
43 [Define if the mbrtowc function has the NULL pwc argument bug.])
47 case "$gl_cv_func_mbrtowc_null_arg2" in
49 *) AC_DEFINE([MBRTOWC_NULL_ARG2_BUG], [1],
50 [Define if the mbrtowc function has the NULL string argument bug.])
54 case "$gl_cv_func_mbrtowc_retval" in
56 *) AC_DEFINE([MBRTOWC_RETVAL_BUG], [1],
57 [Define if the mbrtowc function returns a wrong return value.])
61 case "$gl_cv_func_mbrtowc_nul_retval" in
63 *) AC_DEFINE([MBRTOWC_NUL_RETVAL_BUG], [1],
64 [Define if the mbrtowc function does not return 0 for a NUL character.])
68 case "$gl_cv_func_mbrtowc_stores_incomplete" in
70 *) AC_DEFINE([MBRTOWC_STORES_INCOMPLETE_BUG], [1],
71 [Define if the mbrtowc function stores a wide character when reporting incomplete input.])
75 case "$gl_cv_func_mbrtowc_empty_input" in
77 *) AC_DEFINE([MBRTOWC_EMPTY_INPUT_BUG], [1],
78 [Define if the mbrtowc function does not return (size_t) -2
83 case "$gl_cv_func_mbrtowc_C_locale_sans_EILSEQ" in
85 *) AC_DEFINE([MBRTOWC_IN_C_LOCALE_MAYBE_EILSEQ], [1],
86 [Define if the mbrtowc function may signal encoding errors in the C locale.])
92 if test $REPLACE_MBSTATE_T = 1; then
94 mingw*) LIB_MBRTOWC= ;;
97 case "$gl_cv_have_weak" in
99 *) LIB_MBRTOWC="$LIBPTHREAD" ;;
106 dnl LIB_MBRTOWC is expected to be '-pthread' or '-lpthread' on AIX
107 dnl with gcc or xlc, and empty otherwise.
108 AC_SUBST([LIB_MBRTOWC])
111 dnl Test whether mbsinit() and mbrtowc() need to be overridden in a way that
112 dnl redefines the semantics of the given mbstate_t type.
113 dnl Result is REPLACE_MBSTATE_T.
114 dnl When this is set to 1, we replace both mbsinit() and mbrtowc(), in order to
115 dnl avoid inconsistencies.
117 AC_DEFUN([gl_MBSTATE_T_BROKEN],
119 AC_REQUIRE([gl_WCHAR_H_DEFAULTS])
120 AC_REQUIRE([AC_CANONICAL_HOST])
122 AC_REQUIRE([AC_TYPE_MBSTATE_T])
123 AC_CHECK_FUNCS_ONCE([mbsinit])
124 AC_CHECK_FUNCS_ONCE([mbrtowc])
125 dnl On native Windows, we know exactly how mbsinit() behaves and don't need
126 dnl to override it, even if - like on MSVC - mbsinit() is only defined as
127 dnl an inline function, not as a global function.
128 if case "$host_os" in
130 *) test $ac_cv_func_mbsinit = yes ;;
132 && test $ac_cv_func_mbrtowc = yes; then
133 gl_MBRTOWC_INCOMPLETE_STATE
134 gl_MBRTOWC_SANITYCHECK
136 case "$gl_cv_func_mbrtowc_incomplete_state" in
138 *) REPLACE_MBSTATE_T=1 ;;
140 case "$gl_cv_func_mbrtowc_sanitycheck" in
142 *) REPLACE_MBSTATE_T=1 ;;
149 dnl Test whether mbrtowc puts the state into non-initial state when parsing an
150 dnl incomplete multibyte character.
151 dnl Result is gl_cv_func_mbrtowc_incomplete_state.
153 AC_DEFUN([gl_MBRTOWC_INCOMPLETE_STATE],
155 AC_REQUIRE([AC_PROG_CC])
156 AC_REQUIRE([gt_LOCALE_JA])
157 AC_REQUIRE([gt_LOCALE_FR_UTF8])
158 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
159 AC_CACHE_CHECK([whether mbrtowc handles incomplete characters],
160 [gl_cv_func_mbrtowc_incomplete_state],
162 dnl Initial guess, used when cross-compiling or when no suitable locale
166 # Guess no on AIX and OSF/1.
167 aix* | osf*) gl_cv_func_mbrtowc_incomplete_state="guessing no" ;;
168 # Guess yes otherwise.
169 *) gl_cv_func_mbrtowc_incomplete_state="guessing yes" ;;
172 if test $LOCALE_JA != none; then
180 if (setlocale (LC_ALL, "$LOCALE_JA") != NULL)
182 const char input[] = "B\217\253\344\217\251\316er"; /* "Büßer" */
186 memset (&state, '\0', sizeof (mbstate_t));
187 if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
188 if (mbsinit (&state))
193 [gl_cv_func_mbrtowc_incomplete_state=yes],
194 [gl_cv_func_mbrtowc_incomplete_state=no],
197 if test $LOCALE_FR_UTF8 != none; then
205 if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
207 const char input[] = "B\303\274\303\237er"; /* "Büßer" */
211 memset (&state, '\0', sizeof (mbstate_t));
212 if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
213 if (mbsinit (&state))
218 [gl_cv_func_mbrtowc_incomplete_state=yes],
219 [gl_cv_func_mbrtowc_incomplete_state=no],
226 dnl Test whether mbrtowc works not worse than mbtowc.
227 dnl Result is gl_cv_func_mbrtowc_sanitycheck.
229 AC_DEFUN([gl_MBRTOWC_SANITYCHECK],
231 AC_REQUIRE([AC_PROG_CC])
232 AC_REQUIRE([gt_LOCALE_ZH_CN])
233 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
234 AC_CACHE_CHECK([whether mbrtowc works as well as mbtowc],
235 [gl_cv_func_mbrtowc_sanitycheck],
237 dnl Initial guess, used when cross-compiling or when no suitable locale
241 # Guess no on Solaris 8.
242 solaris2.8) gl_cv_func_mbrtowc_sanitycheck="guessing no" ;;
243 # Guess yes otherwise.
244 *) gl_cv_func_mbrtowc_sanitycheck="guessing yes" ;;
247 if test $LOCALE_ZH_CN != none; then
256 /* This fails on Solaris 8:
257 mbrtowc returns 2, and sets wc to 0x00F0.
258 mbtowc returns 4 (correct) and sets wc to 0x5EDC. */
259 if (setlocale (LC_ALL, "$LOCALE_ZH_CN") != NULL)
261 char input[] = "B\250\271\201\060\211\070er"; /* "Büßer" */
265 memset (&state, '\0', sizeof (mbstate_t));
266 if (mbrtowc (&wc, input + 3, 6, &state) != 4
267 && mbtowc (&wc, input + 3, 6) == 4)
272 [gl_cv_func_mbrtowc_sanitycheck=yes],
273 [gl_cv_func_mbrtowc_sanitycheck=no],
279 dnl Test whether mbrtowc supports a NULL pwc argument correctly.
280 dnl Result is gl_cv_func_mbrtowc_null_arg1.
282 AC_DEFUN([gl_MBRTOWC_NULL_ARG1],
284 AC_REQUIRE([AC_PROG_CC])
285 AC_REQUIRE([gt_LOCALE_FR_UTF8])
286 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
287 AC_CACHE_CHECK([whether mbrtowc handles a NULL pwc argument],
288 [gl_cv_func_mbrtowc_null_arg1],
290 dnl Initial guess, used when cross-compiling or when no suitable locale
294 # Guess no on Solaris.
295 solaris*) gl_cv_func_mbrtowc_null_arg1="guessing no" ;;
296 # Guess yes otherwise.
297 *) gl_cv_func_mbrtowc_null_arg1="guessing yes" ;;
300 if test $LOCALE_FR_UTF8 != none; then
311 if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
313 char input[] = "\303\237er";
318 memset (&state, '\0', sizeof (mbstate_t));
319 wc = (wchar_t) 0xBADFACE;
320 ret = mbrtowc (&wc, input, 5, &state);
323 if (!mbsinit (&state))
326 memset (&state, '\0', sizeof (mbstate_t));
327 ret = mbrtowc (NULL, input, 5, &state);
328 if (ret != 2) /* Solaris 7 fails here: ret is -1. */
330 if (!mbsinit (&state))
335 [gl_cv_func_mbrtowc_null_arg1=yes],
336 [gl_cv_func_mbrtowc_null_arg1=no],
342 dnl Test whether mbrtowc supports a NULL string argument correctly.
343 dnl Result is gl_cv_func_mbrtowc_null_arg2.
345 AC_DEFUN([gl_MBRTOWC_NULL_ARG2],
347 AC_REQUIRE([AC_PROG_CC])
348 AC_REQUIRE([gt_LOCALE_FR_UTF8])
349 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
350 AC_CACHE_CHECK([whether mbrtowc handles a NULL string argument],
351 [gl_cv_func_mbrtowc_null_arg2],
353 dnl Initial guess, used when cross-compiling or when no suitable locale
358 osf*) gl_cv_func_mbrtowc_null_arg2="guessing no" ;;
359 # Guess yes otherwise.
360 *) gl_cv_func_mbrtowc_null_arg2="guessing yes" ;;
363 if test $LOCALE_FR_UTF8 != none; then
371 if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
377 memset (&state, '\0', sizeof (mbstate_t));
378 wc = (wchar_t) 0xBADFACE;
379 mbrtowc (&wc, NULL, 5, &state);
380 /* Check that wc was not modified. */
381 if (wc != (wchar_t) 0xBADFACE)
386 [gl_cv_func_mbrtowc_null_arg2=yes],
387 [gl_cv_func_mbrtowc_null_arg2=no],
393 dnl Test whether mbrtowc, when parsing the end of a multibyte character,
394 dnl correctly returns the number of bytes that were needed to complete the
395 dnl character (not the total number of bytes of the multibyte character).
396 dnl Result is gl_cv_func_mbrtowc_retval.
398 AC_DEFUN([gl_MBRTOWC_RETVAL],
400 AC_REQUIRE([AC_PROG_CC])
401 AC_REQUIRE([gt_LOCALE_FR_UTF8])
402 AC_REQUIRE([gt_LOCALE_JA])
403 AC_REQUIRE([AC_CANONICAL_HOST])
404 AC_CACHE_CHECK([whether mbrtowc has a correct return value],
405 [gl_cv_func_mbrtowc_retval],
407 dnl Initial guess, used when cross-compiling or when no suitable locale
411 # Guess no on HP-UX, Solaris, native Windows.
412 hpux* | solaris* | mingw*) gl_cv_func_mbrtowc_retval="guessing no" ;;
413 # Guess yes otherwise.
414 *) gl_cv_func_mbrtowc_retval="guessing yes" ;;
417 if test $LOCALE_FR_UTF8 != none || test $LOCALE_JA != none \
418 || { case "$host_os" in mingw*) true;; *) false;; esac; }; then
427 int found_some_locale = 0;
428 /* This fails on Solaris. */
429 if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
431 char input[] = "B\303\274\303\237er"; /* "Büßer" */
435 memset (&state, '\0', sizeof (mbstate_t));
436 if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
439 if (mbrtowc (&wc, input + 2, 5, &state) != 1)
442 found_some_locale = 1;
444 /* This fails on HP-UX 11.11. */
445 if (setlocale (LC_ALL, "$LOCALE_JA") != NULL)
447 char input[] = "B\217\253\344\217\251\316er"; /* "Büßer" */
451 memset (&state, '\0', sizeof (mbstate_t));
452 if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
455 if (mbrtowc (&wc, input + 2, 5, &state) != 2)
458 found_some_locale = 1;
460 /* This fails on native Windows. */
461 if (setlocale (LC_ALL, "Japanese_Japan.932") != NULL)
463 char input[] = "<\223\372\226\173\214\352>"; /* "<日本語>" */
467 memset (&state, '\0', sizeof (mbstate_t));
468 if (mbrtowc (&wc, input + 3, 1, &state) == (size_t)(-2))
471 if (mbrtowc (&wc, input + 4, 4, &state) != 1)
474 found_some_locale = 1;
476 if (setlocale (LC_ALL, "Chinese_Taiwan.950") != NULL)
478 char input[] = "<\244\351\245\273\273\171>"; /* "<日本語>" */
482 memset (&state, '\0', sizeof (mbstate_t));
483 if (mbrtowc (&wc, input + 3, 1, &state) == (size_t)(-2))
486 if (mbrtowc (&wc, input + 4, 4, &state) != 1)
489 found_some_locale = 1;
491 if (setlocale (LC_ALL, "Chinese_China.936") != NULL)
493 char input[] = "<\310\325\261\276\325\132>"; /* "<日本語>" */
497 memset (&state, '\0', sizeof (mbstate_t));
498 if (mbrtowc (&wc, input + 3, 1, &state) == (size_t)(-2))
501 if (mbrtowc (&wc, input + 4, 4, &state) != 1)
504 found_some_locale = 1;
506 return (found_some_locale ? result : 77);
508 [gl_cv_func_mbrtowc_retval=yes],
509 [if test $? != 77; then
510 gl_cv_func_mbrtowc_retval=no
518 dnl Test whether mbrtowc, when parsing a NUL character, correctly returns 0.
519 dnl Result is gl_cv_func_mbrtowc_nul_retval.
521 AC_DEFUN([gl_MBRTOWC_NUL_RETVAL],
523 AC_REQUIRE([AC_PROG_CC])
524 AC_REQUIRE([gt_LOCALE_ZH_CN])
525 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
526 AC_CACHE_CHECK([whether mbrtowc returns 0 when parsing a NUL character],
527 [gl_cv_func_mbrtowc_nul_retval],
529 dnl Initial guess, used when cross-compiling or when no suitable locale
533 # Guess no on Solaris 8 and 9.
534 solaris2.[89]) gl_cv_func_mbrtowc_nul_retval="guessing no" ;;
535 # Guess yes otherwise.
536 *) gl_cv_func_mbrtowc_nul_retval="guessing yes" ;;
539 if test $LOCALE_ZH_CN != none; then
547 /* This fails on Solaris 8 and 9. */
548 if (setlocale (LC_ALL, "$LOCALE_ZH_CN") != NULL)
553 memset (&state, '\0', sizeof (mbstate_t));
554 if (mbrtowc (&wc, "", 1, &state) != 0)
559 [gl_cv_func_mbrtowc_nul_retval=yes],
560 [gl_cv_func_mbrtowc_nul_retval=no],
566 dnl Test whether mbrtowc stores a wide character when reporting incomplete
569 AC_DEFUN([gl_MBRTOWC_STORES_INCOMPLETE],
571 AC_REQUIRE([AC_PROG_CC])
572 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
573 AC_CACHE_CHECK([whether mbrtowc stores incomplete characters],
574 [gl_cv_func_mbrtowc_stores_incomplete],
576 dnl Initial guess, used when cross-compiling or when no suitable locale
580 # Guess yes on native Windows.
581 mingw*) gl_cv_func_mbrtowc_stores_incomplete="guessing yes" ;;
582 *) gl_cv_func_mbrtowc_stores_incomplete="guessing no" ;;
595 if (setlocale (LC_ALL, "French_France.65001") != NULL)
597 wchar_t wc = (wchar_t) 0xBADFACE;
600 memset (&state, '\0', sizeof (mbstate_t));
601 if (mbrtowc (&wc, "\303", 1, &state) == (size_t)(-2)
602 && wc != (wchar_t) 0xBADFACE)
605 if (setlocale (LC_ALL, "Japanese_Japan.932") != NULL)
607 wchar_t wc = (wchar_t) 0xBADFACE;
610 memset (&state, '\0', sizeof (mbstate_t));
611 if (mbrtowc (&wc, "\226", 1, &state) == (size_t)(-2)
612 && wc != (wchar_t) 0xBADFACE)
615 if (setlocale (LC_ALL, "Chinese_Taiwan.950") != NULL)
617 wchar_t wc = (wchar_t) 0xBADFACE;
620 memset (&state, '\0', sizeof (mbstate_t));
621 if (mbrtowc (&wc, "\245", 1, &state) == (size_t)(-2)
622 && wc != (wchar_t) 0xBADFACE)
625 if (setlocale (LC_ALL, "Chinese_China.936") != NULL)
627 wchar_t wc = (wchar_t) 0xBADFACE;
630 memset (&state, '\0', sizeof (mbstate_t));
631 if (mbrtowc (&wc, "\261", 1, &state) == (size_t)(-2)
632 && wc != (wchar_t) 0xBADFACE)
637 [gl_cv_func_mbrtowc_stores_incomplete=no],
638 [gl_cv_func_mbrtowc_stores_incomplete=yes],
642 AC_REQUIRE([gt_LOCALE_FR_UTF8])
643 if test $LOCALE_FR_UTF8 != none; then
651 if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
653 wchar_t wc = (wchar_t) 0xBADFACE;
656 memset (&state, '\0', sizeof (mbstate_t));
657 if (mbrtowc (&wc, "\303", 1, &state) == (size_t)(-2)
658 && wc != (wchar_t) 0xBADFACE)
663 [gl_cv_func_mbrtowc_stores_incomplete=no],
664 [gl_cv_func_mbrtowc_stores_incomplete=yes],
672 dnl Test whether mbrtowc returns the correct value on empty input.
674 AC_DEFUN([gl_MBRTOWC_EMPTY_INPUT],
676 AC_REQUIRE([AC_PROG_CC])
677 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
678 AC_CACHE_CHECK([whether mbrtowc works on empty input],
679 [gl_cv_func_mbrtowc_empty_input],
681 dnl Initial guess, used when cross-compiling or when no suitable locale
685 # Guess no on AIX and glibc systems.
686 aix* | *-gnu* | gnu*) gl_cv_func_mbrtowc_empty_input="guessing no" ;;
687 # Guess yes on native Windows.
688 mingw*) gl_cv_func_mbrtowc_empty_input="guessing yes" ;;
689 *) gl_cv_func_mbrtowc_empty_input="guessing yes" ;;
696 static mbstate_t mbs;
700 return mbrtowc (&wc, "", 0, &mbs) != (size_t) -2;
702 [gl_cv_func_mbrtowc_empty_input=yes],
703 [gl_cv_func_mbrtowc_empty_input=no],
708 dnl Test whether mbrtowc reports encoding errors in the C locale.
709 dnl Although POSIX was never intended to allow this, the GNU C Library
710 dnl and other implementations do it. See:
711 dnl https://sourceware.org/bugzilla/show_bug.cgi?id=19932
713 AC_DEFUN([gl_MBRTOWC_C_LOCALE],
715 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
716 AC_CACHE_CHECK([whether the C locale is free of encoding errors],
717 [gl_cv_func_mbrtowc_C_locale_sans_EILSEQ],
719 dnl Initial guess, used when cross-compiling or when no suitable locale
721 gl_cv_func_mbrtowc_C_locale_sans_EILSEQ="$gl_cross_guess_normal"
725 [[#include <limits.h>
730 char *locale = setlocale (LC_ALL, "C");
733 for (i = CHAR_MIN; i <= CHAR_MAX; i++)
737 mbstate_t mbs = { 0, };
738 size_t ss = mbrtowc (&wc, &c, 1, &mbs);
744 [gl_cv_func_mbrtowc_C_locale_sans_EILSEQ=yes],
745 [gl_cv_func_mbrtowc_C_locale_sans_EILSEQ=no],
747 # Guess yes on native Windows.
748 mingw*) gl_cv_func_mbrtowc_C_locale_sans_EILSEQ="guessing yes" ;;
754 # Prerequisites of lib/mbrtowc.c and lib/lc-charset-dispatch.c.
755 AC_DEFUN([gl_PREREQ_MBRTOWC], [
756 AC_REQUIRE([AC_C_INLINE])
760 # Prerequisites of lib/mbtowc-lock.c.
761 AC_DEFUN([gl_PREREQ_MBTOWC_LOCK],
769 dnl This is an override of an autoconf macro.
771 AC_DEFUN([AC_FUNC_MBRTOWC],
773 dnl Same as AC_FUNC_MBRTOWC in autoconf-2.60.
774 AC_CACHE_CHECK([whether mbrtowc and mbstate_t are properly declared],
775 [gl_cv_func_mbrtowc],
778 [[#include <wchar.h>]],
783 return ! (sizeof state && (mbrtowc) (&wc, s, n, &state));]])],
784 [gl_cv_func_mbrtowc=yes],
785 [gl_cv_func_mbrtowc=no])])
786 if test $gl_cv_func_mbrtowc = yes; then
787 AC_DEFINE([HAVE_MBRTOWC], [1],
788 [Define to 1 if mbrtowc and mbstate_t are properly declared.])