Bump to m4 1.4.19
[platform/upstream/m4.git] / m4 / mbrtowc.m4
1 # mbrtowc.m4 serial 38  -*- coding: utf-8 -*-
2 dnl Copyright (C) 2001-2002, 2004-2005, 2008-2021 Free Software Foundation,
3 dnl Inc.
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.
7
8 AC_DEFUN([gl_FUNC_MBRTOWC],
9 [
10   AC_REQUIRE([gl_WCHAR_H_DEFAULTS])
11   AC_REQUIRE([gl_PTHREADLIB])
12   AC_CHECK_HEADERS_ONCE([threads.h])
13
14   AC_REQUIRE([AC_TYPE_MBSTATE_T])
15   gl_MBSTATE_T_BROKEN
16
17   AC_CHECK_FUNCS_ONCE([mbrtowc])
18   if test $ac_cv_func_mbrtowc = no; then
19     HAVE_MBRTOWC=0
20     AC_CHECK_DECLS([mbrtowc],,, [[
21       #include <wchar.h>
22     ]])
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
26       dnl replacement.
27       REPLACE_MBRTOWC=1
28     fi
29   else
30     if test $REPLACE_MBSTATE_T = 1; then
31       REPLACE_MBRTOWC=1
32     else
33       gl_MBRTOWC_NULL_ARG1
34       gl_MBRTOWC_NULL_ARG2
35       gl_MBRTOWC_RETVAL
36       gl_MBRTOWC_NUL_RETVAL
37       gl_MBRTOWC_STORES_INCOMPLETE
38       gl_MBRTOWC_EMPTY_INPUT
39       gl_MBRTOWC_C_LOCALE
40       case "$gl_cv_func_mbrtowc_null_arg1" in
41         *yes) ;;
42         *) AC_DEFINE([MBRTOWC_NULL_ARG1_BUG], [1],
43              [Define if the mbrtowc function has the NULL pwc argument bug.])
44            REPLACE_MBRTOWC=1
45            ;;
46       esac
47       case "$gl_cv_func_mbrtowc_null_arg2" in
48         *yes) ;;
49         *) AC_DEFINE([MBRTOWC_NULL_ARG2_BUG], [1],
50              [Define if the mbrtowc function has the NULL string argument bug.])
51            REPLACE_MBRTOWC=1
52            ;;
53       esac
54       case "$gl_cv_func_mbrtowc_retval" in
55         *yes) ;;
56         *) AC_DEFINE([MBRTOWC_RETVAL_BUG], [1],
57              [Define if the mbrtowc function returns a wrong return value.])
58            REPLACE_MBRTOWC=1
59            ;;
60       esac
61       case "$gl_cv_func_mbrtowc_nul_retval" in
62         *yes) ;;
63         *) AC_DEFINE([MBRTOWC_NUL_RETVAL_BUG], [1],
64              [Define if the mbrtowc function does not return 0 for a NUL character.])
65            REPLACE_MBRTOWC=1
66            ;;
67       esac
68       case "$gl_cv_func_mbrtowc_stores_incomplete" in
69         *no) ;;
70         *) AC_DEFINE([MBRTOWC_STORES_INCOMPLETE_BUG], [1],
71              [Define if the mbrtowc function stores a wide character when reporting incomplete input.])
72            REPLACE_MBRTOWC=1
73            ;;
74       esac
75       case "$gl_cv_func_mbrtowc_empty_input" in
76         *yes) ;;
77         *) AC_DEFINE([MBRTOWC_EMPTY_INPUT_BUG], [1],
78              [Define if the mbrtowc function does not return (size_t) -2
79               for empty input.])
80            REPLACE_MBRTOWC=1
81            ;;
82       esac
83       case "$gl_cv_func_mbrtowc_C_locale_sans_EILSEQ" in
84         *yes) ;;
85         *) AC_DEFINE([MBRTOWC_IN_C_LOCALE_MAYBE_EILSEQ], [1],
86              [Define if the mbrtowc function may signal encoding errors in the C locale.])
87            REPLACE_MBRTOWC=1
88            ;;
89       esac
90     fi
91   fi
92   if test $REPLACE_MBSTATE_T = 1; then
93     case "$host_os" in
94       mingw*) LIB_MBRTOWC= ;;
95       *)
96         gl_WEAK_SYMBOLS
97         case "$gl_cv_have_weak" in
98           *yes) LIB_MBRTOWC= ;;
99           *)    LIB_MBRTOWC="$LIBPTHREAD" ;;
100         esac
101         ;;
102     esac
103   else
104     LIB_MBRTOWC=
105   fi
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])
109 ])
110
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.
116
117 AC_DEFUN([gl_MBSTATE_T_BROKEN],
118 [
119   AC_REQUIRE([gl_WCHAR_H_DEFAULTS])
120   AC_REQUIRE([AC_CANONICAL_HOST])
121
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
129        mingw*) true ;;
130        *) test $ac_cv_func_mbsinit = yes ;;
131      esac \
132     && test $ac_cv_func_mbrtowc = yes; then
133     gl_MBRTOWC_INCOMPLETE_STATE
134     gl_MBRTOWC_SANITYCHECK
135     REPLACE_MBSTATE_T=0
136     case "$gl_cv_func_mbrtowc_incomplete_state" in
137       *yes) ;;
138       *) REPLACE_MBSTATE_T=1 ;;
139     esac
140     case "$gl_cv_func_mbrtowc_sanitycheck" in
141       *yes) ;;
142       *) REPLACE_MBSTATE_T=1 ;;
143     esac
144   else
145     REPLACE_MBSTATE_T=1
146   fi
147 ])
148
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.
152
153 AC_DEFUN([gl_MBRTOWC_INCOMPLETE_STATE],
154 [
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],
161     [
162       dnl Initial guess, used when cross-compiling or when no suitable locale
163       dnl is present.
164 changequote(,)dnl
165       case "$host_os" in
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" ;;
170       esac
171 changequote([,])dnl
172       if test $LOCALE_JA != none; then
173         AC_RUN_IFELSE(
174           [AC_LANG_SOURCE([[
175 #include <locale.h>
176 #include <string.h>
177 #include <wchar.h>
178 int main ()
179 {
180   if (setlocale (LC_ALL, "$LOCALE_JA") != NULL)
181     {
182       const char input[] = "B\217\253\344\217\251\316er"; /* "Büßer" */
183       mbstate_t state;
184       wchar_t wc;
185
186       memset (&state, '\0', sizeof (mbstate_t));
187       if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
188         if (mbsinit (&state))
189           return 2;
190     }
191   return 0;
192 }]])],
193           [gl_cv_func_mbrtowc_incomplete_state=yes],
194           [gl_cv_func_mbrtowc_incomplete_state=no],
195           [:])
196       else
197         if test $LOCALE_FR_UTF8 != none; then
198           AC_RUN_IFELSE(
199             [AC_LANG_SOURCE([[
200 #include <locale.h>
201 #include <string.h>
202 #include <wchar.h>
203 int main ()
204 {
205   if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
206     {
207       const char input[] = "B\303\274\303\237er"; /* "Büßer" */
208       mbstate_t state;
209       wchar_t wc;
210
211       memset (&state, '\0', sizeof (mbstate_t));
212       if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
213         if (mbsinit (&state))
214           return 2;
215     }
216   return 0;
217 }]])],
218           [gl_cv_func_mbrtowc_incomplete_state=yes],
219           [gl_cv_func_mbrtowc_incomplete_state=no],
220           [:])
221         fi
222       fi
223     ])
224 ])
225
226 dnl Test whether mbrtowc works not worse than mbtowc.
227 dnl Result is gl_cv_func_mbrtowc_sanitycheck.
228
229 AC_DEFUN([gl_MBRTOWC_SANITYCHECK],
230 [
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],
236     [
237       dnl Initial guess, used when cross-compiling or when no suitable locale
238       dnl is present.
239 changequote(,)dnl
240       case "$host_os" in
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" ;;
245       esac
246 changequote([,])dnl
247       if test $LOCALE_ZH_CN != none; then
248         AC_RUN_IFELSE(
249           [AC_LANG_SOURCE([[
250 #include <locale.h>
251 #include <stdlib.h>
252 #include <string.h>
253 #include <wchar.h>
254 int main ()
255 {
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)
260     {
261       char input[] = "B\250\271\201\060\211\070er"; /* "Büßer" */
262       mbstate_t state;
263       wchar_t wc;
264
265       memset (&state, '\0', sizeof (mbstate_t));
266       if (mbrtowc (&wc, input + 3, 6, &state) != 4
267           && mbtowc (&wc, input + 3, 6) == 4)
268         return 2;
269     }
270   return 0;
271 }]])],
272           [gl_cv_func_mbrtowc_sanitycheck=yes],
273           [gl_cv_func_mbrtowc_sanitycheck=no],
274           [:])
275       fi
276     ])
277 ])
278
279 dnl Test whether mbrtowc supports a NULL pwc argument correctly.
280 dnl Result is gl_cv_func_mbrtowc_null_arg1.
281
282 AC_DEFUN([gl_MBRTOWC_NULL_ARG1],
283 [
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],
289     [
290       dnl Initial guess, used when cross-compiling or when no suitable locale
291       dnl is present.
292 changequote(,)dnl
293       case "$host_os" in
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" ;;
298       esac
299 changequote([,])dnl
300       if test $LOCALE_FR_UTF8 != none; then
301         AC_RUN_IFELSE(
302           [AC_LANG_SOURCE([[
303 #include <locale.h>
304 #include <stdlib.h>
305 #include <string.h>
306 #include <wchar.h>
307 int main ()
308 {
309   int result = 0;
310
311   if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
312     {
313       char input[] = "\303\237er";
314       mbstate_t state;
315       wchar_t wc;
316       size_t ret;
317
318       memset (&state, '\0', sizeof (mbstate_t));
319       wc = (wchar_t) 0xBADFACE;
320       ret = mbrtowc (&wc, input, 5, &state);
321       if (ret != 2)
322         result |= 1;
323       if (!mbsinit (&state))
324         result |= 2;
325
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.  */
329         result |= 4;
330       if (!mbsinit (&state))
331         result |= 8;
332     }
333   return result;
334 }]])],
335           [gl_cv_func_mbrtowc_null_arg1=yes],
336           [gl_cv_func_mbrtowc_null_arg1=no],
337           [:])
338       fi
339     ])
340 ])
341
342 dnl Test whether mbrtowc supports a NULL string argument correctly.
343 dnl Result is gl_cv_func_mbrtowc_null_arg2.
344
345 AC_DEFUN([gl_MBRTOWC_NULL_ARG2],
346 [
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],
352     [
353       dnl Initial guess, used when cross-compiling or when no suitable locale
354       dnl is present.
355 changequote(,)dnl
356       case "$host_os" in
357               # Guess no on OSF/1.
358         osf*) gl_cv_func_mbrtowc_null_arg2="guessing no" ;;
359               # Guess yes otherwise.
360         *)    gl_cv_func_mbrtowc_null_arg2="guessing yes" ;;
361       esac
362 changequote([,])dnl
363       if test $LOCALE_FR_UTF8 != none; then
364         AC_RUN_IFELSE(
365           [AC_LANG_SOURCE([[
366 #include <locale.h>
367 #include <string.h>
368 #include <wchar.h>
369 int main ()
370 {
371   if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
372     {
373       mbstate_t state;
374       wchar_t wc;
375       int ret;
376
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)
382         return 2;
383     }
384   return 0;
385 }]])],
386           [gl_cv_func_mbrtowc_null_arg2=yes],
387           [gl_cv_func_mbrtowc_null_arg2=no],
388           [:])
389       fi
390     ])
391 ])
392
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.
397
398 AC_DEFUN([gl_MBRTOWC_RETVAL],
399 [
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],
406     [
407       dnl Initial guess, used when cross-compiling or when no suitable locale
408       dnl is present.
409 changequote(,)dnl
410       case "$host_os" in
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" ;;
415       esac
416 changequote([,])dnl
417       if test $LOCALE_FR_UTF8 != none || test $LOCALE_JA != none \
418          || { case "$host_os" in mingw*) true;; *) false;; esac; }; then
419         AC_RUN_IFELSE(
420           [AC_LANG_SOURCE([[
421 #include <locale.h>
422 #include <string.h>
423 #include <wchar.h>
424 int main ()
425 {
426   int result = 0;
427   int found_some_locale = 0;
428   /* This fails on Solaris.  */
429   if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
430     {
431       char input[] = "B\303\274\303\237er"; /* "Büßer" */
432       mbstate_t state;
433       wchar_t wc;
434
435       memset (&state, '\0', sizeof (mbstate_t));
436       if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
437         {
438           input[1] = '\0';
439           if (mbrtowc (&wc, input + 2, 5, &state) != 1)
440             result |= 1;
441         }
442       found_some_locale = 1;
443     }
444   /* This fails on HP-UX 11.11.  */
445   if (setlocale (LC_ALL, "$LOCALE_JA") != NULL)
446     {
447       char input[] = "B\217\253\344\217\251\316er"; /* "Büßer" */
448       mbstate_t state;
449       wchar_t wc;
450
451       memset (&state, '\0', sizeof (mbstate_t));
452       if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
453         {
454           input[1] = '\0';
455           if (mbrtowc (&wc, input + 2, 5, &state) != 2)
456             result |= 2;
457         }
458       found_some_locale = 1;
459     }
460   /* This fails on native Windows.  */
461   if (setlocale (LC_ALL, "Japanese_Japan.932") != NULL)
462     {
463       char input[] = "<\223\372\226\173\214\352>"; /* "<日本語>" */
464       mbstate_t state;
465       wchar_t wc;
466
467       memset (&state, '\0', sizeof (mbstate_t));
468       if (mbrtowc (&wc, input + 3, 1, &state) == (size_t)(-2))
469         {
470           input[3] = '\0';
471           if (mbrtowc (&wc, input + 4, 4, &state) != 1)
472             result |= 4;
473         }
474       found_some_locale = 1;
475     }
476   if (setlocale (LC_ALL, "Chinese_Taiwan.950") != NULL)
477     {
478       char input[] = "<\244\351\245\273\273\171>"; /* "<日本語>" */
479       mbstate_t state;
480       wchar_t wc;
481
482       memset (&state, '\0', sizeof (mbstate_t));
483       if (mbrtowc (&wc, input + 3, 1, &state) == (size_t)(-2))
484         {
485           input[3] = '\0';
486           if (mbrtowc (&wc, input + 4, 4, &state) != 1)
487             result |= 8;
488         }
489       found_some_locale = 1;
490     }
491   if (setlocale (LC_ALL, "Chinese_China.936") != NULL)
492     {
493       char input[] = "<\310\325\261\276\325\132>"; /* "<日本語>" */
494       mbstate_t state;
495       wchar_t wc;
496
497       memset (&state, '\0', sizeof (mbstate_t));
498       if (mbrtowc (&wc, input + 3, 1, &state) == (size_t)(-2))
499         {
500           input[3] = '\0';
501           if (mbrtowc (&wc, input + 4, 4, &state) != 1)
502             result |= 16;
503         }
504       found_some_locale = 1;
505     }
506   return (found_some_locale ? result : 77);
507 }]])],
508           [gl_cv_func_mbrtowc_retval=yes],
509           [if test $? != 77; then
510              gl_cv_func_mbrtowc_retval=no
511            fi
512           ],
513           [:])
514       fi
515     ])
516 ])
517
518 dnl Test whether mbrtowc, when parsing a NUL character, correctly returns 0.
519 dnl Result is gl_cv_func_mbrtowc_nul_retval.
520
521 AC_DEFUN([gl_MBRTOWC_NUL_RETVAL],
522 [
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],
528     [
529       dnl Initial guess, used when cross-compiling or when no suitable locale
530       dnl is present.
531 changequote(,)dnl
532       case "$host_os" in
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" ;;
537       esac
538 changequote([,])dnl
539       if test $LOCALE_ZH_CN != none; then
540         AC_RUN_IFELSE(
541           [AC_LANG_SOURCE([[
542 #include <locale.h>
543 #include <string.h>
544 #include <wchar.h>
545 int main ()
546 {
547   /* This fails on Solaris 8 and 9.  */
548   if (setlocale (LC_ALL, "$LOCALE_ZH_CN") != NULL)
549     {
550       mbstate_t state;
551       wchar_t wc;
552
553       memset (&state, '\0', sizeof (mbstate_t));
554       if (mbrtowc (&wc, "", 1, &state) != 0)
555         return 2;
556     }
557   return 0;
558 }]])],
559           [gl_cv_func_mbrtowc_nul_retval=yes],
560           [gl_cv_func_mbrtowc_nul_retval=no],
561           [:])
562       fi
563     ])
564 ])
565
566 dnl Test whether mbrtowc stores a wide character when reporting incomplete
567 dnl input.
568
569 AC_DEFUN([gl_MBRTOWC_STORES_INCOMPLETE],
570 [
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],
575     [
576      dnl Initial guess, used when cross-compiling or when no suitable locale
577      dnl is present.
578 changequote(,)dnl
579      case "$host_os" in
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" ;;
583      esac
584 changequote([,])dnl
585      case "$host_os" in
586        mingw*)
587          AC_RUN_IFELSE(
588            [AC_LANG_SOURCE([[
589 #include <locale.h>
590 #include <string.h>
591 #include <wchar.h>
592 int main ()
593 {
594   int result = 0;
595   if (setlocale (LC_ALL, "French_France.65001") != NULL)
596     {
597       wchar_t wc = (wchar_t) 0xBADFACE;
598       mbstate_t state;
599
600       memset (&state, '\0', sizeof (mbstate_t));
601       if (mbrtowc (&wc, "\303", 1, &state) == (size_t)(-2)
602           && wc != (wchar_t) 0xBADFACE)
603         result |= 1;
604     }
605   if (setlocale (LC_ALL, "Japanese_Japan.932") != NULL)
606     {
607       wchar_t wc = (wchar_t) 0xBADFACE;
608       mbstate_t state;
609
610       memset (&state, '\0', sizeof (mbstate_t));
611       if (mbrtowc (&wc, "\226", 1, &state) == (size_t)(-2)
612           && wc != (wchar_t) 0xBADFACE)
613         result |= 2;
614     }
615   if (setlocale (LC_ALL, "Chinese_Taiwan.950") != NULL)
616     {
617       wchar_t wc = (wchar_t) 0xBADFACE;
618       mbstate_t state;
619
620       memset (&state, '\0', sizeof (mbstate_t));
621       if (mbrtowc (&wc, "\245", 1, &state) == (size_t)(-2)
622           && wc != (wchar_t) 0xBADFACE)
623         result |= 4;
624     }
625   if (setlocale (LC_ALL, "Chinese_China.936") != NULL)
626     {
627       wchar_t wc = (wchar_t) 0xBADFACE;
628       mbstate_t state;
629
630       memset (&state, '\0', sizeof (mbstate_t));
631       if (mbrtowc (&wc, "\261", 1, &state) == (size_t)(-2)
632           && wc != (wchar_t) 0xBADFACE)
633         result |= 8;
634     }
635   return result;
636 }]])],
637            [gl_cv_func_mbrtowc_stores_incomplete=no],
638            [gl_cv_func_mbrtowc_stores_incomplete=yes],
639            [:])
640          ;;
641        *)
642          AC_REQUIRE([gt_LOCALE_FR_UTF8])
643          if test $LOCALE_FR_UTF8 != none; then
644            AC_RUN_IFELSE(
645              [AC_LANG_SOURCE([[
646 #include <locale.h>
647 #include <string.h>
648 #include <wchar.h>
649 int main ()
650 {
651   if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
652     {
653       wchar_t wc = (wchar_t) 0xBADFACE;
654       mbstate_t state;
655
656       memset (&state, '\0', sizeof (mbstate_t));
657       if (mbrtowc (&wc, "\303", 1, &state) == (size_t)(-2)
658           && wc != (wchar_t) 0xBADFACE)
659         return 1;
660     }
661   return 0;
662 }]])],
663              [gl_cv_func_mbrtowc_stores_incomplete=no],
664              [gl_cv_func_mbrtowc_stores_incomplete=yes],
665              [:])
666          fi
667          ;;
668      esac
669     ])
670 ])
671
672 dnl Test whether mbrtowc returns the correct value on empty input.
673
674 AC_DEFUN([gl_MBRTOWC_EMPTY_INPUT],
675 [
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],
680     [
681       dnl Initial guess, used when cross-compiling or when no suitable locale
682       dnl is present.
683 changequote(,)dnl
684       case "$host_os" in
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" ;;
690       esac
691 changequote([,])dnl
692       AC_RUN_IFELSE(
693         [AC_LANG_SOURCE([[
694            #include <wchar.h>
695            static wchar_t wc;
696            static mbstate_t mbs;
697            int
698            main (void)
699            {
700              return mbrtowc (&wc, "", 0, &mbs) != (size_t) -2;
701            }]])],
702         [gl_cv_func_mbrtowc_empty_input=yes],
703         [gl_cv_func_mbrtowc_empty_input=no],
704         [:])
705     ])
706 ])
707
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
712
713 AC_DEFUN([gl_MBRTOWC_C_LOCALE],
714 [
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],
718     [
719      dnl Initial guess, used when cross-compiling or when no suitable locale
720      dnl is present.
721      gl_cv_func_mbrtowc_C_locale_sans_EILSEQ="$gl_cross_guess_normal"
722
723      AC_RUN_IFELSE(
724        [AC_LANG_PROGRAM(
725           [[#include <limits.h>
726             #include <locale.h>
727             #include <wchar.h>
728           ]], [[
729             int i;
730             char *locale = setlocale (LC_ALL, "C");
731             if (! locale)
732               return 2;
733             for (i = CHAR_MIN; i <= CHAR_MAX; i++)
734               {
735                 char c = i;
736                 wchar_t wc;
737                 mbstate_t mbs = { 0, };
738                 size_t ss = mbrtowc (&wc, &c, 1, &mbs);
739                 if (1 < ss)
740                   return 3;
741               }
742             return 0;
743           ]])],
744       [gl_cv_func_mbrtowc_C_locale_sans_EILSEQ=yes],
745       [gl_cv_func_mbrtowc_C_locale_sans_EILSEQ=no],
746       [case "$host_os" in
747                  # Guess yes on native Windows.
748          mingw*) gl_cv_func_mbrtowc_C_locale_sans_EILSEQ="guessing yes" ;;
749        esac
750       ])
751     ])
752 ])
753
754 # Prerequisites of lib/mbrtowc.c and lib/lc-charset-dispatch.c.
755 AC_DEFUN([gl_PREREQ_MBRTOWC], [
756   AC_REQUIRE([AC_C_INLINE])
757   :
758 ])
759
760 # Prerequisites of lib/mbtowc-lock.c.
761 AC_DEFUN([gl_PREREQ_MBTOWC_LOCK],
762 [
763   gl_VISIBILITY
764 ])
765
766
767 dnl From Paul Eggert
768
769 dnl This is an override of an autoconf macro.
770
771 AC_DEFUN([AC_FUNC_MBRTOWC],
772 [
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],
776     [AC_LINK_IFELSE(
777        [AC_LANG_PROGRAM(
778             [[#include <wchar.h>]],
779             [[wchar_t wc;
780               char const s[] = "";
781               size_t n = 1;
782               mbstate_t state;
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.])
789   fi
790 ])