1# mbrtowc.m4 serial 37  -*- coding: utf-8 -*-
2dnl Copyright (C) 2001-2002, 2004-2005, 2008-2020 Free Software Foundation,
3dnl Inc.
4dnl This file is free software; the Free Software Foundation
5dnl gives unlimited permission to copy and/or distribute it,
6dnl with or without modifications, as long as this notice is preserved.
7
8AC_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/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
22   <wchar.h>.
23   BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
24   included before <wchar.h>.  */
25#include <stddef.h>
26#include <stdio.h>
27#include <time.h>
28#include <wchar.h>
29]])
30    if test $ac_cv_have_decl_mbrtowc = yes; then
31      dnl On Minix 3.1.8, the system's <wchar.h> declares mbrtowc() although
32      dnl it does not have the function. Avoid a collision with gnulib's
33      dnl replacement.
34      REPLACE_MBRTOWC=1
35    fi
36  else
37    if test $REPLACE_MBSTATE_T = 1; then
38      REPLACE_MBRTOWC=1
39    else
40      gl_MBRTOWC_NULL_ARG1
41      gl_MBRTOWC_NULL_ARG2
42      gl_MBRTOWC_RETVAL
43      gl_MBRTOWC_NUL_RETVAL
44      gl_MBRTOWC_STORES_INCOMPLETE
45      gl_MBRTOWC_EMPTY_INPUT
46      gl_MBRTOWC_C_LOCALE
47      case "$gl_cv_func_mbrtowc_null_arg1" in
48        *yes) ;;
49        *) AC_DEFINE([MBRTOWC_NULL_ARG1_BUG], [1],
50             [Define if the mbrtowc function has the NULL pwc argument bug.])
51           REPLACE_MBRTOWC=1
52           ;;
53      esac
54      case "$gl_cv_func_mbrtowc_null_arg2" in
55        *yes) ;;
56        *) AC_DEFINE([MBRTOWC_NULL_ARG2_BUG], [1],
57             [Define if the mbrtowc function has the NULL string argument bug.])
58           REPLACE_MBRTOWC=1
59           ;;
60      esac
61      case "$gl_cv_func_mbrtowc_retval" in
62        *yes) ;;
63        *) AC_DEFINE([MBRTOWC_RETVAL_BUG], [1],
64             [Define if the mbrtowc function returns a wrong return value.])
65           REPLACE_MBRTOWC=1
66           ;;
67      esac
68      case "$gl_cv_func_mbrtowc_nul_retval" in
69        *yes) ;;
70        *) AC_DEFINE([MBRTOWC_NUL_RETVAL_BUG], [1],
71             [Define if the mbrtowc function does not return 0 for a NUL character.])
72           REPLACE_MBRTOWC=1
73           ;;
74      esac
75      case "$gl_cv_func_mbrtowc_stores_incomplete" in
76        *no) ;;
77        *) AC_DEFINE([MBRTOWC_STORES_INCOMPLETE_BUG], [1],
78             [Define if the mbrtowc function stores a wide character when reporting incomplete input.])
79           REPLACE_MBRTOWC=1
80           ;;
81      esac
82      case "$gl_cv_func_mbrtowc_empty_input" in
83        *yes) ;;
84        *) AC_DEFINE([MBRTOWC_EMPTY_INPUT_BUG], [1],
85             [Define if the mbrtowc function does not return (size_t) -2
86              for empty input.])
87           REPLACE_MBRTOWC=1
88           ;;
89      esac
90      case "$gl_cv_func_mbrtowc_C_locale_sans_EILSEQ" in
91        *yes) ;;
92        *) AC_DEFINE([MBRTOWC_IN_C_LOCALE_MAYBE_EILSEQ], [1],
93             [Define if the mbrtowc function may signal encoding errors in the C locale.])
94           REPLACE_MBRTOWC=1
95           ;;
96      esac
97    fi
98  fi
99  if test $REPLACE_MBSTATE_T = 1; then
100    case "$host_os" in
101      mingw*) LIB_MBRTOWC= ;;
102      *)
103        gl_WEAK_SYMBOLS
104        case "$gl_cv_have_weak" in
105          *yes) LIB_MBRTOWC= ;;
106          *)    LIB_MBRTOWC="$LIBPTHREAD" ;;
107        esac
108        ;;
109    esac
110  else
111    LIB_MBRTOWC=
112  fi
113  dnl LIB_MBRTOWC is expected to be '-pthread' or '-lpthread' on AIX
114  dnl with gcc or xlc, and empty otherwise.
115  AC_SUBST([LIB_MBRTOWC])
116])
117
118dnl Test whether mbsinit() and mbrtowc() need to be overridden in a way that
119dnl redefines the semantics of the given mbstate_t type.
120dnl Result is REPLACE_MBSTATE_T.
121dnl When this is set to 1, we replace both mbsinit() and mbrtowc(), in order to
122dnl avoid inconsistencies.
123
124AC_DEFUN([gl_MBSTATE_T_BROKEN],
125[
126  AC_REQUIRE([gl_WCHAR_H_DEFAULTS])
127  AC_REQUIRE([AC_CANONICAL_HOST])
128
129  AC_REQUIRE([AC_TYPE_MBSTATE_T])
130  AC_CHECK_FUNCS_ONCE([mbsinit])
131  AC_CHECK_FUNCS_ONCE([mbrtowc])
132  dnl On native Windows, we know exactly how mbsinit() behaves and don't need
133  dnl to override it, even if - like on MSVC - mbsinit() is only defined as
134  dnl an inline function, not as a global function.
135  if case "$host_os" in
136       mingw*) true ;;
137       *) test $ac_cv_func_mbsinit = yes ;;
138     esac \
139    && test $ac_cv_func_mbrtowc = yes; then
140    gl_MBRTOWC_INCOMPLETE_STATE
141    gl_MBRTOWC_SANITYCHECK
142    REPLACE_MBSTATE_T=0
143    case "$gl_cv_func_mbrtowc_incomplete_state" in
144      *yes) ;;
145      *) REPLACE_MBSTATE_T=1 ;;
146    esac
147    case "$gl_cv_func_mbrtowc_sanitycheck" in
148      *yes) ;;
149      *) REPLACE_MBSTATE_T=1 ;;
150    esac
151  else
152    REPLACE_MBSTATE_T=1
153  fi
154])
155
156dnl Test whether mbrtowc puts the state into non-initial state when parsing an
157dnl incomplete multibyte character.
158dnl Result is gl_cv_func_mbrtowc_incomplete_state.
159
160AC_DEFUN([gl_MBRTOWC_INCOMPLETE_STATE],
161[
162  AC_REQUIRE([AC_PROG_CC])
163  AC_REQUIRE([gt_LOCALE_JA])
164  AC_REQUIRE([gt_LOCALE_FR_UTF8])
165  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
166  AC_CACHE_CHECK([whether mbrtowc handles incomplete characters],
167    [gl_cv_func_mbrtowc_incomplete_state],
168    [
169      dnl Initial guess, used when cross-compiling or when no suitable locale
170      dnl is present.
171changequote(,)dnl
172      case "$host_os" in
173                     # Guess no on AIX and OSF/1.
174        aix* | osf*) gl_cv_func_mbrtowc_incomplete_state="guessing no" ;;
175                     # Guess yes otherwise.
176        *)           gl_cv_func_mbrtowc_incomplete_state="guessing yes" ;;
177      esac
178changequote([,])dnl
179      if test $LOCALE_JA != none; then
180        AC_RUN_IFELSE(
181          [AC_LANG_SOURCE([[
182#include <locale.h>
183#include <string.h>
184/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
185   <wchar.h>.
186   BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
187   included before <wchar.h>.  */
188#include <stddef.h>
189#include <stdio.h>
190#include <time.h>
191#include <wchar.h>
192int main ()
193{
194  if (setlocale (LC_ALL, "$LOCALE_JA") != NULL)
195    {
196      const char input[] = "B\217\253\344\217\251\316er"; /* "Büßer" */
197      mbstate_t state;
198      wchar_t wc;
199
200      memset (&state, '\0', sizeof (mbstate_t));
201      if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
202        if (mbsinit (&state))
203          return 2;
204    }
205  return 0;
206}]])],
207          [gl_cv_func_mbrtowc_incomplete_state=yes],
208          [gl_cv_func_mbrtowc_incomplete_state=no],
209          [:])
210      else
211        if test $LOCALE_FR_UTF8 != none; then
212          AC_RUN_IFELSE(
213            [AC_LANG_SOURCE([[
214#include <locale.h>
215#include <string.h>
216/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
217   <wchar.h>.
218   BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
219   included before <wchar.h>.  */
220#include <stddef.h>
221#include <stdio.h>
222#include <time.h>
223#include <wchar.h>
224int main ()
225{
226  if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
227    {
228      const char input[] = "B\303\274\303\237er"; /* "Büßer" */
229      mbstate_t state;
230      wchar_t wc;
231
232      memset (&state, '\0', sizeof (mbstate_t));
233      if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
234        if (mbsinit (&state))
235          return 2;
236    }
237  return 0;
238}]])],
239          [gl_cv_func_mbrtowc_incomplete_state=yes],
240          [gl_cv_func_mbrtowc_incomplete_state=no],
241          [:])
242        fi
243      fi
244    ])
245])
246
247dnl Test whether mbrtowc works not worse than mbtowc.
248dnl Result is gl_cv_func_mbrtowc_sanitycheck.
249
250AC_DEFUN([gl_MBRTOWC_SANITYCHECK],
251[
252  AC_REQUIRE([AC_PROG_CC])
253  AC_REQUIRE([gt_LOCALE_ZH_CN])
254  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
255  AC_CACHE_CHECK([whether mbrtowc works as well as mbtowc],
256    [gl_cv_func_mbrtowc_sanitycheck],
257    [
258      dnl Initial guess, used when cross-compiling or when no suitable locale
259      dnl is present.
260changequote(,)dnl
261      case "$host_os" in
262                    # Guess no on Solaris 8.
263        solaris2.8) gl_cv_func_mbrtowc_sanitycheck="guessing no" ;;
264                    # Guess yes otherwise.
265        *)          gl_cv_func_mbrtowc_sanitycheck="guessing yes" ;;
266      esac
267changequote([,])dnl
268      if test $LOCALE_ZH_CN != none; then
269        AC_RUN_IFELSE(
270          [AC_LANG_SOURCE([[
271#include <locale.h>
272#include <stdlib.h>
273#include <string.h>
274/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
275   <wchar.h>.
276   BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
277   included before <wchar.h>.  */
278#include <stddef.h>
279#include <stdio.h>
280#include <time.h>
281#include <wchar.h>
282int main ()
283{
284  /* This fails on Solaris 8:
285     mbrtowc returns 2, and sets wc to 0x00F0.
286     mbtowc returns 4 (correct) and sets wc to 0x5EDC.  */
287  if (setlocale (LC_ALL, "$LOCALE_ZH_CN") != NULL)
288    {
289      char input[] = "B\250\271\201\060\211\070er"; /* "Büßer" */
290      mbstate_t state;
291      wchar_t wc;
292
293      memset (&state, '\0', sizeof (mbstate_t));
294      if (mbrtowc (&wc, input + 3, 6, &state) != 4
295          && mbtowc (&wc, input + 3, 6) == 4)
296        return 2;
297    }
298  return 0;
299}]])],
300          [gl_cv_func_mbrtowc_sanitycheck=yes],
301          [gl_cv_func_mbrtowc_sanitycheck=no],
302          [:])
303      fi
304    ])
305])
306
307dnl Test whether mbrtowc supports a NULL pwc argument correctly.
308dnl Result is gl_cv_func_mbrtowc_null_arg1.
309
310AC_DEFUN([gl_MBRTOWC_NULL_ARG1],
311[
312  AC_REQUIRE([AC_PROG_CC])
313  AC_REQUIRE([gt_LOCALE_FR_UTF8])
314  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
315  AC_CACHE_CHECK([whether mbrtowc handles a NULL pwc argument],
316    [gl_cv_func_mbrtowc_null_arg1],
317    [
318      dnl Initial guess, used when cross-compiling or when no suitable locale
319      dnl is present.
320changequote(,)dnl
321      case "$host_os" in
322                  # Guess no on Solaris.
323        solaris*) gl_cv_func_mbrtowc_null_arg1="guessing no" ;;
324                  # Guess yes otherwise.
325        *)        gl_cv_func_mbrtowc_null_arg1="guessing yes" ;;
326      esac
327changequote([,])dnl
328      if test $LOCALE_FR_UTF8 != none; then
329        AC_RUN_IFELSE(
330          [AC_LANG_SOURCE([[
331#include <locale.h>
332#include <stdlib.h>
333#include <string.h>
334/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
335   <wchar.h>.
336   BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
337   included before <wchar.h>.  */
338#include <stddef.h>
339#include <stdio.h>
340#include <time.h>
341#include <wchar.h>
342int main ()
343{
344  int result = 0;
345
346  if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
347    {
348      char input[] = "\303\237er";
349      mbstate_t state;
350      wchar_t wc;
351      size_t ret;
352
353      memset (&state, '\0', sizeof (mbstate_t));
354      wc = (wchar_t) 0xBADFACE;
355      ret = mbrtowc (&wc, input, 5, &state);
356      if (ret != 2)
357        result |= 1;
358      if (!mbsinit (&state))
359        result |= 2;
360
361      memset (&state, '\0', sizeof (mbstate_t));
362      ret = mbrtowc (NULL, input, 5, &state);
363      if (ret != 2) /* Solaris 7 fails here: ret is -1.  */
364        result |= 4;
365      if (!mbsinit (&state))
366        result |= 8;
367    }
368  return result;
369}]])],
370          [gl_cv_func_mbrtowc_null_arg1=yes],
371          [gl_cv_func_mbrtowc_null_arg1=no],
372          [:])
373      fi
374    ])
375])
376
377dnl Test whether mbrtowc supports a NULL string argument correctly.
378dnl Result is gl_cv_func_mbrtowc_null_arg2.
379
380AC_DEFUN([gl_MBRTOWC_NULL_ARG2],
381[
382  AC_REQUIRE([AC_PROG_CC])
383  AC_REQUIRE([gt_LOCALE_FR_UTF8])
384  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
385  AC_CACHE_CHECK([whether mbrtowc handles a NULL string argument],
386    [gl_cv_func_mbrtowc_null_arg2],
387    [
388      dnl Initial guess, used when cross-compiling or when no suitable locale
389      dnl is present.
390changequote(,)dnl
391      case "$host_os" in
392              # Guess no on OSF/1.
393        osf*) gl_cv_func_mbrtowc_null_arg2="guessing no" ;;
394              # Guess yes otherwise.
395        *)    gl_cv_func_mbrtowc_null_arg2="guessing yes" ;;
396      esac
397changequote([,])dnl
398      if test $LOCALE_FR_UTF8 != none; then
399        AC_RUN_IFELSE(
400          [AC_LANG_SOURCE([[
401#include <locale.h>
402#include <string.h>
403/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
404   <wchar.h>.
405   BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
406   included before <wchar.h>.  */
407#include <stddef.h>
408#include <stdio.h>
409#include <time.h>
410#include <wchar.h>
411int main ()
412{
413  if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
414    {
415      mbstate_t state;
416      wchar_t wc;
417      int ret;
418
419      memset (&state, '\0', sizeof (mbstate_t));
420      wc = (wchar_t) 0xBADFACE;
421      mbrtowc (&wc, NULL, 5, &state);
422      /* Check that wc was not modified.  */
423      if (wc != (wchar_t) 0xBADFACE)
424        return 2;
425    }
426  return 0;
427}]])],
428          [gl_cv_func_mbrtowc_null_arg2=yes],
429          [gl_cv_func_mbrtowc_null_arg2=no],
430          [:])
431      fi
432    ])
433])
434
435dnl Test whether mbrtowc, when parsing the end of a multibyte character,
436dnl correctly returns the number of bytes that were needed to complete the
437dnl character (not the total number of bytes of the multibyte character).
438dnl Result is gl_cv_func_mbrtowc_retval.
439
440AC_DEFUN([gl_MBRTOWC_RETVAL],
441[
442  AC_REQUIRE([AC_PROG_CC])
443  AC_REQUIRE([gt_LOCALE_FR_UTF8])
444  AC_REQUIRE([gt_LOCALE_JA])
445  AC_REQUIRE([AC_CANONICAL_HOST])
446  AC_CACHE_CHECK([whether mbrtowc has a correct return value],
447    [gl_cv_func_mbrtowc_retval],
448    [
449      dnl Initial guess, used when cross-compiling or when no suitable locale
450      dnl is present.
451changequote(,)dnl
452      case "$host_os" in
453                                   # Guess no on HP-UX, Solaris, native Windows.
454        hpux* | solaris* | mingw*) gl_cv_func_mbrtowc_retval="guessing no" ;;
455                                   # Guess yes otherwise.
456        *)                         gl_cv_func_mbrtowc_retval="guessing yes" ;;
457      esac
458changequote([,])dnl
459      if test $LOCALE_FR_UTF8 != none || test $LOCALE_JA != none \
460         || { case "$host_os" in mingw*) true;; *) false;; esac; }; then
461        AC_RUN_IFELSE(
462          [AC_LANG_SOURCE([[
463#include <locale.h>
464#include <string.h>
465/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
466   <wchar.h>.
467   BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
468   included before <wchar.h>.  */
469#include <stddef.h>
470#include <stdio.h>
471#include <time.h>
472#include <wchar.h>
473int main ()
474{
475  int result = 0;
476  int found_some_locale = 0;
477  /* This fails on Solaris.  */
478  if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
479    {
480      char input[] = "B\303\274\303\237er"; /* "Büßer" */
481      mbstate_t state;
482      wchar_t wc;
483
484      memset (&state, '\0', sizeof (mbstate_t));
485      if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
486        {
487          input[1] = '\0';
488          if (mbrtowc (&wc, input + 2, 5, &state) != 1)
489            result |= 1;
490        }
491      found_some_locale = 1;
492    }
493  /* This fails on HP-UX 11.11.  */
494  if (setlocale (LC_ALL, "$LOCALE_JA") != NULL)
495    {
496      char input[] = "B\217\253\344\217\251\316er"; /* "Büßer" */
497      mbstate_t state;
498      wchar_t wc;
499
500      memset (&state, '\0', sizeof (mbstate_t));
501      if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
502        {
503          input[1] = '\0';
504          if (mbrtowc (&wc, input + 2, 5, &state) != 2)
505            result |= 2;
506        }
507      found_some_locale = 1;
508    }
509  /* This fails on native Windows.  */
510  if (setlocale (LC_ALL, "Japanese_Japan.932") != NULL)
511    {
512      char input[] = "<\223\372\226\173\214\352>"; /* "<日本語>" */
513      mbstate_t state;
514      wchar_t wc;
515
516      memset (&state, '\0', sizeof (mbstate_t));
517      if (mbrtowc (&wc, input + 3, 1, &state) == (size_t)(-2))
518        {
519          input[3] = '\0';
520          if (mbrtowc (&wc, input + 4, 4, &state) != 1)
521            result |= 4;
522        }
523      found_some_locale = 1;
524    }
525  if (setlocale (LC_ALL, "Chinese_Taiwan.950") != NULL)
526    {
527      char input[] = "<\244\351\245\273\273\171>"; /* "<日本語>" */
528      mbstate_t state;
529      wchar_t wc;
530
531      memset (&state, '\0', sizeof (mbstate_t));
532      if (mbrtowc (&wc, input + 3, 1, &state) == (size_t)(-2))
533        {
534          input[3] = '\0';
535          if (mbrtowc (&wc, input + 4, 4, &state) != 1)
536            result |= 8;
537        }
538      found_some_locale = 1;
539    }
540  if (setlocale (LC_ALL, "Chinese_China.936") != NULL)
541    {
542      char input[] = "<\310\325\261\276\325\132>"; /* "<日本語>" */
543      mbstate_t state;
544      wchar_t wc;
545
546      memset (&state, '\0', sizeof (mbstate_t));
547      if (mbrtowc (&wc, input + 3, 1, &state) == (size_t)(-2))
548        {
549          input[3] = '\0';
550          if (mbrtowc (&wc, input + 4, 4, &state) != 1)
551            result |= 16;
552        }
553      found_some_locale = 1;
554    }
555  return (found_some_locale ? result : 77);
556}]])],
557          [gl_cv_func_mbrtowc_retval=yes],
558          [if test $? != 77; then
559             gl_cv_func_mbrtowc_retval=no
560           fi
561          ],
562          [:])
563      fi
564    ])
565])
566
567dnl Test whether mbrtowc, when parsing a NUL character, correctly returns 0.
568dnl Result is gl_cv_func_mbrtowc_nul_retval.
569
570AC_DEFUN([gl_MBRTOWC_NUL_RETVAL],
571[
572  AC_REQUIRE([AC_PROG_CC])
573  AC_REQUIRE([gt_LOCALE_ZH_CN])
574  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
575  AC_CACHE_CHECK([whether mbrtowc returns 0 when parsing a NUL character],
576    [gl_cv_func_mbrtowc_nul_retval],
577    [
578      dnl Initial guess, used when cross-compiling or when no suitable locale
579      dnl is present.
580changequote(,)dnl
581      case "$host_os" in
582                       # Guess no on Solaris 8 and 9.
583        solaris2.[89]) gl_cv_func_mbrtowc_nul_retval="guessing no" ;;
584                       # Guess yes otherwise.
585        *)             gl_cv_func_mbrtowc_nul_retval="guessing yes" ;;
586      esac
587changequote([,])dnl
588      if test $LOCALE_ZH_CN != none; then
589        AC_RUN_IFELSE(
590          [AC_LANG_SOURCE([[
591#include <locale.h>
592#include <string.h>
593/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
594   <wchar.h>.
595   BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
596   included before <wchar.h>.  */
597#include <stddef.h>
598#include <stdio.h>
599#include <time.h>
600#include <wchar.h>
601int main ()
602{
603  /* This fails on Solaris 8 and 9.  */
604  if (setlocale (LC_ALL, "$LOCALE_ZH_CN") != NULL)
605    {
606      mbstate_t state;
607      wchar_t wc;
608
609      memset (&state, '\0', sizeof (mbstate_t));
610      if (mbrtowc (&wc, "", 1, &state) != 0)
611        return 2;
612    }
613  return 0;
614}]])],
615          [gl_cv_func_mbrtowc_nul_retval=yes],
616          [gl_cv_func_mbrtowc_nul_retval=no],
617          [:])
618      fi
619    ])
620])
621
622dnl Test whether mbrtowc stores a wide character when reporting incomplete
623dnl input.
624
625AC_DEFUN([gl_MBRTOWC_STORES_INCOMPLETE],
626[
627  AC_REQUIRE([AC_PROG_CC])
628  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
629  AC_CACHE_CHECK([whether mbrtowc stores incomplete characters],
630    [gl_cv_func_mbrtowc_stores_incomplete],
631    [
632     dnl Initial guess, used when cross-compiling or when no suitable locale
633     dnl is present.
634changequote(,)dnl
635     case "$host_os" in
636               # Guess yes on native Windows.
637       mingw*) gl_cv_func_mbrtowc_stores_incomplete="guessing yes" ;;
638       *)      gl_cv_func_mbrtowc_stores_incomplete="guessing no" ;;
639     esac
640changequote([,])dnl
641     case "$host_os" in
642       mingw*)
643         AC_RUN_IFELSE(
644           [AC_LANG_SOURCE([[
645#include <locale.h>
646#include <string.h>
647/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
648   <wchar.h>.
649   BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
650   included before <wchar.h>.  */
651#include <stddef.h>
652#include <stdio.h>
653#include <time.h>
654#include <wchar.h>
655int main ()
656{
657  int result = 0;
658  if (setlocale (LC_ALL, "French_France.65001") != NULL)
659    {
660      wchar_t wc = (wchar_t) 0xBADFACE;
661      mbstate_t state;
662
663      memset (&state, '\0', sizeof (mbstate_t));
664      if (mbrtowc (&wc, "\303", 1, &state) == (size_t)(-2)
665          && wc != (wchar_t) 0xBADFACE)
666        result |= 1;
667    }
668  if (setlocale (LC_ALL, "Japanese_Japan.932") != NULL)
669    {
670      wchar_t wc = (wchar_t) 0xBADFACE;
671      mbstate_t state;
672
673      memset (&state, '\0', sizeof (mbstate_t));
674      if (mbrtowc (&wc, "\226", 1, &state) == (size_t)(-2)
675          && wc != (wchar_t) 0xBADFACE)
676        result |= 2;
677    }
678  if (setlocale (LC_ALL, "Chinese_Taiwan.950") != NULL)
679    {
680      wchar_t wc = (wchar_t) 0xBADFACE;
681      mbstate_t state;
682
683      memset (&state, '\0', sizeof (mbstate_t));
684      if (mbrtowc (&wc, "\245", 1, &state) == (size_t)(-2)
685          && wc != (wchar_t) 0xBADFACE)
686        result |= 4;
687    }
688  if (setlocale (LC_ALL, "Chinese_China.936") != NULL)
689    {
690      wchar_t wc = (wchar_t) 0xBADFACE;
691      mbstate_t state;
692
693      memset (&state, '\0', sizeof (mbstate_t));
694      if (mbrtowc (&wc, "\261", 1, &state) == (size_t)(-2)
695          && wc != (wchar_t) 0xBADFACE)
696        result |= 8;
697    }
698  return result;
699}]])],
700           [gl_cv_func_mbrtowc_stores_incomplete=no],
701           [gl_cv_func_mbrtowc_stores_incomplete=yes],
702           [:])
703         ;;
704       *)
705         AC_REQUIRE([gt_LOCALE_FR_UTF8])
706         if test $LOCALE_FR_UTF8 != none; then
707           AC_RUN_IFELSE(
708             [AC_LANG_SOURCE([[
709#include <locale.h>
710#include <string.h>
711/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
712   <wchar.h>.
713   BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
714   included before <wchar.h>.  */
715#include <stddef.h>
716#include <stdio.h>
717#include <time.h>
718#include <wchar.h>
719int main ()
720{
721  if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
722    {
723      wchar_t wc = (wchar_t) 0xBADFACE;
724      mbstate_t state;
725
726      memset (&state, '\0', sizeof (mbstate_t));
727      if (mbrtowc (&wc, "\303", 1, &state) == (size_t)(-2)
728          && wc != (wchar_t) 0xBADFACE)
729        return 1;
730    }
731  return 0;
732}]])],
733             [gl_cv_func_mbrtowc_stores_incomplete=no],
734             [gl_cv_func_mbrtowc_stores_incomplete=yes],
735             [:])
736         fi
737         ;;
738     esac
739    ])
740])
741
742dnl Test whether mbrtowc returns the correct value on empty input.
743
744AC_DEFUN([gl_MBRTOWC_EMPTY_INPUT],
745[
746  AC_REQUIRE([AC_PROG_CC])
747  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
748  AC_CACHE_CHECK([whether mbrtowc works on empty input],
749    [gl_cv_func_mbrtowc_empty_input],
750    [
751      dnl Initial guess, used when cross-compiling or when no suitable locale
752      dnl is present.
753changequote(,)dnl
754      case "$host_os" in
755                              # Guess no on AIX and glibc systems.
756        aix* | *-gnu* | gnu*) gl_cv_func_mbrtowc_empty_input="guessing no" ;;
757                              # Guess yes on native Windows.
758        mingw*)               gl_cv_func_mbrtowc_empty_input="guessing yes" ;;
759        *)                    gl_cv_func_mbrtowc_empty_input="guessing yes" ;;
760      esac
761changequote([,])dnl
762      AC_RUN_IFELSE(
763        [AC_LANG_SOURCE([[
764           #include <wchar.h>
765           static wchar_t wc;
766           static mbstate_t mbs;
767           int
768           main (void)
769           {
770             return mbrtowc (&wc, "", 0, &mbs) != (size_t) -2;
771           }]])],
772        [gl_cv_func_mbrtowc_empty_input=yes],
773        [gl_cv_func_mbrtowc_empty_input=no],
774        [:])
775    ])
776])
777
778dnl Test whether mbrtowc reports encoding errors in the C locale.
779dnl Although POSIX was never intended to allow this, the GNU C Library
780dnl and other implementations do it.  See:
781dnl https://sourceware.org/bugzilla/show_bug.cgi?id=19932
782
783AC_DEFUN([gl_MBRTOWC_C_LOCALE],
784[
785  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
786  AC_CACHE_CHECK([whether the C locale is free of encoding errors],
787    [gl_cv_func_mbrtowc_C_locale_sans_EILSEQ],
788    [
789     dnl Initial guess, used when cross-compiling or when no suitable locale
790     dnl is present.
791     gl_cv_func_mbrtowc_C_locale_sans_EILSEQ="$gl_cross_guess_normal"
792
793     AC_RUN_IFELSE(
794       [AC_LANG_PROGRAM(
795          [[#include <limits.h>
796            #include <locale.h>
797            #include <wchar.h>
798          ]], [[
799            int i;
800            char *locale = setlocale (LC_ALL, "C");
801            if (! locale)
802              return 2;
803            for (i = CHAR_MIN; i <= CHAR_MAX; i++)
804              {
805                char c = i;
806                wchar_t wc;
807                mbstate_t mbs = { 0, };
808                size_t ss = mbrtowc (&wc, &c, 1, &mbs);
809                if (1 < ss)
810                  return 3;
811              }
812            return 0;
813          ]])],
814      [gl_cv_func_mbrtowc_C_locale_sans_EILSEQ=yes],
815      [gl_cv_func_mbrtowc_C_locale_sans_EILSEQ=no],
816      [case "$host_os" in
817                 # Guess yes on native Windows.
818         mingw*) gl_cv_func_mbrtowc_C_locale_sans_EILSEQ="guessing yes" ;;
819       esac
820      ])
821    ])
822])
823
824# Prerequisites of lib/mbrtowc.c and lib/lc-charset-dispatch.c.
825AC_DEFUN([gl_PREREQ_MBRTOWC], [
826  AC_REQUIRE([AC_C_INLINE])
827  :
828])
829
830# Prerequisites of lib/mbtowc-lock.c.
831AC_DEFUN([gl_PREREQ_MBTOWC_LOCK],
832[
833  gl_VISIBILITY
834])
835
836
837dnl From Paul Eggert
838
839dnl This is an override of an autoconf macro.
840
841AC_DEFUN([AC_FUNC_MBRTOWC],
842[
843  dnl Same as AC_FUNC_MBRTOWC in autoconf-2.60.
844  AC_CACHE_CHECK([whether mbrtowc and mbstate_t are properly declared],
845    [gl_cv_func_mbrtowc],
846    [AC_LINK_IFELSE(
847       [AC_LANG_PROGRAM(
848            [[/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be
849                 included before <wchar.h>.
850                 BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h>
851                 must be included before <wchar.h>.  */
852              #include <stddef.h>
853              #include <stdio.h>
854              #include <time.h>
855              #include <wchar.h>]],
856            [[wchar_t wc;
857              char const s[] = "";
858              size_t n = 1;
859              mbstate_t state;
860              return ! (sizeof state && (mbrtowc) (&wc, s, n, &state));]])],
861       [gl_cv_func_mbrtowc=yes],
862       [gl_cv_func_mbrtowc=no])])
863  if test $gl_cv_func_mbrtowc = yes; then
864    AC_DEFINE([HAVE_MBRTOWC], [1],
865      [Define to 1 if mbrtowc and mbstate_t are properly declared.])
866  fi
867])
868