1# mbrtowc.m4 serial 38  -*- coding: utf-8 -*-
2dnl Copyright (C) 2001-2002, 2004-2005, 2008-2022 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      #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
111dnl Test whether mbsinit() and mbrtowc() need to be overridden in a way that
112dnl redefines the semantics of the given mbstate_t type.
113dnl Result is REPLACE_MBSTATE_T.
114dnl When this is set to 1, we replace both mbsinit() and mbrtowc(), in order to
115dnl avoid inconsistencies.
116
117AC_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
149dnl Test whether mbrtowc puts the state into non-initial state when parsing an
150dnl incomplete multibyte character.
151dnl Result is gl_cv_func_mbrtowc_incomplete_state.
152
153AC_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.
164changequote(,)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
171changequote([,])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>
178int 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>
203int 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
226dnl Test whether mbrtowc works not worse than mbtowc.
227dnl Result is gl_cv_func_mbrtowc_sanitycheck.
228
229AC_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.
239changequote(,)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
246changequote([,])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>
254int 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
279dnl Test whether mbrtowc supports a NULL pwc argument correctly.
280dnl Result is gl_cv_func_mbrtowc_null_arg1.
281
282AC_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.
292changequote(,)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
299changequote([,])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>
307int 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
342dnl Test whether mbrtowc supports a NULL string argument correctly.
343dnl Result is gl_cv_func_mbrtowc_null_arg2.
344
345AC_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.
355changequote(,)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
362changequote([,])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>
369int 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
393dnl Test whether mbrtowc, when parsing the end of a multibyte character,
394dnl correctly returns the number of bytes that were needed to complete the
395dnl character (not the total number of bytes of the multibyte character).
396dnl Result is gl_cv_func_mbrtowc_retval.
397
398AC_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.
409changequote(,)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
416changequote([,])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>
424int 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
518dnl Test whether mbrtowc, when parsing a NUL character, correctly returns 0.
519dnl Result is gl_cv_func_mbrtowc_nul_retval.
520
521AC_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.
531changequote(,)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
538changequote([,])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>
545int 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
566dnl Test whether mbrtowc stores a wide character when reporting incomplete
567dnl input.
568
569AC_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.
578changequote(,)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
584changequote([,])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>
592int 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>
649int 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
672dnl Test whether mbrtowc returns the correct value on empty input.
673
674AC_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.
683changequote(,)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
691changequote([,])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
708dnl Test whether mbrtowc reports encoding errors in the C locale.
709dnl Although POSIX was never intended to allow this, the GNU C Library
710dnl and other implementations do it.  See:
711dnl https://sourceware.org/bugzilla/show_bug.cgi?id=19932
712
713AC_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.
755AC_DEFUN([gl_PREREQ_MBRTOWC], [
756  AC_REQUIRE([AC_C_INLINE])
757  :
758])
759
760# Prerequisites of lib/mbtowc-lock.c.
761AC_DEFUN([gl_PREREQ_MBTOWC_LOCK],
762[
763  gl_VISIBILITY
764])
765
766
767dnl From Paul Eggert
768
769dnl This is an override of an autoconf macro.
770
771AC_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])
791