b9e01e7a0e95d43f7fe865c41e5de8ba4fd70711
[gnulib.git] / m4 / mbrtowc.m4
1 # mbrtowc.m4 serial 24
2 dnl Copyright (C) 2001-2002, 2004-2005, 2008-2011 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
12   AC_REQUIRE([AC_TYPE_MBSTATE_T])
13   gl_MBSTATE_T_BROKEN
14
15   AC_CHECK_FUNCS_ONCE([mbrtowc])
16   if test $ac_cv_func_mbrtowc = no; then
17     HAVE_MBRTOWC=0
18   else
19     if test $REPLACE_MBSTATE_T = 1; then
20       REPLACE_MBRTOWC=1
21     else
22       gl_MBRTOWC_NULL_ARG1
23       gl_MBRTOWC_NULL_ARG2
24       gl_MBRTOWC_RETVAL
25       gl_MBRTOWC_NUL_RETVAL
26       case "$gl_cv_func_mbrtowc_null_arg1" in
27         *yes) ;;
28         *) AC_DEFINE([MBRTOWC_NULL_ARG1_BUG], [1],
29              [Define if the mbrtowc function has the NULL pwc argument bug.])
30            REPLACE_MBRTOWC=1
31            ;;
32       esac
33       case "$gl_cv_func_mbrtowc_null_arg2" in
34         *yes) ;;
35         *) AC_DEFINE([MBRTOWC_NULL_ARG2_BUG], [1],
36              [Define if the mbrtowc function has the NULL string argument bug.])
37            REPLACE_MBRTOWC=1
38            ;;
39       esac
40       case "$gl_cv_func_mbrtowc_retval" in
41         *yes) ;;
42         *) AC_DEFINE([MBRTOWC_RETVAL_BUG], [1],
43              [Define if the mbrtowc function returns a wrong return value.])
44            REPLACE_MBRTOWC=1
45            ;;
46       esac
47       case "$gl_cv_func_mbrtowc_nul_retval" in
48         *yes) ;;
49         *) AC_DEFINE([MBRTOWC_NUL_RETVAL_BUG], [1],
50              [Define if the mbrtowc function does not return 0 for a NUL character.])
51            REPLACE_MBRTOWC=1
52            ;;
53       esac
54     fi
55   fi
56 ])
57
58 dnl Test whether mbsinit() and mbrtowc() need to be overridden in a way that
59 dnl redefines the semantics of the given mbstate_t type.
60 dnl Result is REPLACE_MBSTATE_T.
61 dnl When this is set to 1, we replace both mbsinit() and mbrtowc(), in order to
62 dnl avoid inconsistencies.
63
64 AC_DEFUN([gl_MBSTATE_T_BROKEN],
65 [
66   AC_REQUIRE([gl_WCHAR_H_DEFAULTS])
67
68   AC_REQUIRE([AC_TYPE_MBSTATE_T])
69   AC_CHECK_FUNCS_ONCE([mbsinit])
70   AC_CHECK_FUNCS_ONCE([mbrtowc])
71   if test $ac_cv_func_mbsinit = yes && test $ac_cv_func_mbrtowc = yes; then
72     gl_MBRTOWC_INCOMPLETE_STATE
73     gl_MBRTOWC_SANITYCHECK
74     REPLACE_MBSTATE_T=0
75     case "$gl_cv_func_mbrtowc_incomplete_state" in
76       *yes) ;;
77       *) REPLACE_MBSTATE_T=1 ;;
78     esac
79     case "$gl_cv_func_mbrtowc_sanitycheck" in
80       *yes) ;;
81       *) REPLACE_MBSTATE_T=1 ;;
82     esac
83   else
84     REPLACE_MBSTATE_T=1
85   fi
86 ])
87
88 dnl Test whether mbrtowc puts the state into non-initial state when parsing an
89 dnl incomplete multibyte character.
90 dnl Result is gl_cv_func_mbrtowc_incomplete_state.
91
92 AC_DEFUN([gl_MBRTOWC_INCOMPLETE_STATE],
93 [
94   AC_REQUIRE([AC_PROG_CC])
95   AC_REQUIRE([gt_LOCALE_JA])
96   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
97   AC_CACHE_CHECK([whether mbrtowc handles incomplete characters],
98     [gl_cv_func_mbrtowc_incomplete_state],
99     [
100       dnl Initial guess, used when cross-compiling or when no suitable locale
101       dnl is present.
102 changequote(,)dnl
103       case "$host_os" in
104                      # Guess no on AIX and OSF/1.
105         aix* | osf*) gl_cv_func_mbrtowc_incomplete_state="guessing no" ;;
106                      # Guess yes otherwise.
107         *)           gl_cv_func_mbrtowc_incomplete_state="guessing yes" ;;
108       esac
109 changequote([,])dnl
110       if test $LOCALE_JA != none; then
111         AC_RUN_IFELSE(
112           [AC_LANG_SOURCE([[
113 #include <locale.h>
114 #include <string.h>
115 /* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
116    <wchar.h>.
117    BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
118    included before <wchar.h>.  */
119 #include <stddef.h>
120 #include <stdio.h>
121 #include <time.h>
122 #include <wchar.h>
123 int main ()
124 {
125   if (setlocale (LC_ALL, "$LOCALE_JA") != NULL)
126     {
127       const char input[] = "B\217\253\344\217\251\316er"; /* "Büßer" */
128       mbstate_t state;
129       wchar_t wc;
130
131       memset (&state, '\0', sizeof (mbstate_t));
132       if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
133         if (mbsinit (&state))
134           return 1;
135     }
136   return 0;
137 }]])],
138           [gl_cv_func_mbrtowc_incomplete_state=yes],
139           [gl_cv_func_mbrtowc_incomplete_state=no],
140           [:])
141       fi
142     ])
143 ])
144
145 dnl Test whether mbrtowc works not worse than mbtowc.
146 dnl Result is gl_cv_func_mbrtowc_sanitycheck.
147
148 AC_DEFUN([gl_MBRTOWC_SANITYCHECK],
149 [
150   AC_REQUIRE([AC_PROG_CC])
151   AC_REQUIRE([gt_LOCALE_ZH_CN])
152   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
153   AC_CACHE_CHECK([whether mbrtowc works as well as mbtowc],
154     [gl_cv_func_mbrtowc_sanitycheck],
155     [
156       dnl Initial guess, used when cross-compiling or when no suitable locale
157       dnl is present.
158 changequote(,)dnl
159       case "$host_os" in
160                     # Guess no on Solaris 8.
161         solaris2.8) gl_cv_func_mbrtowc_sanitycheck="guessing no" ;;
162                     # Guess yes otherwise.
163         *)          gl_cv_func_mbrtowc_sanitycheck="guessing yes" ;;
164       esac
165 changequote([,])dnl
166       if test $LOCALE_ZH_CN != none; then
167         AC_RUN_IFELSE(
168           [AC_LANG_SOURCE([[
169 #include <locale.h>
170 #include <stdlib.h>
171 #include <string.h>
172 /* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
173    <wchar.h>.
174    BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
175    included before <wchar.h>.  */
176 #include <stddef.h>
177 #include <stdio.h>
178 #include <time.h>
179 #include <wchar.h>
180 int main ()
181 {
182   /* This fails on Solaris 8:
183      mbrtowc returns 2, and sets wc to 0x00F0.
184      mbtowc returns 4 (correct) and sets wc to 0x5EDC.  */
185   if (setlocale (LC_ALL, "$LOCALE_ZH_CN") != NULL)
186     {
187       char input[] = "B\250\271\201\060\211\070er"; /* "Büßer" */
188       mbstate_t state;
189       wchar_t wc;
190
191       memset (&state, '\0', sizeof (mbstate_t));
192       if (mbrtowc (&wc, input + 3, 6, &state) != 4
193           && mbtowc (&wc, input + 3, 6) == 4)
194         return 1;
195     }
196   return 0;
197 }]])],
198           [gl_cv_func_mbrtowc_sanitycheck=yes],
199           [gl_cv_func_mbrtowc_sanitycheck=no],
200           [:])
201       fi
202     ])
203 ])
204
205 dnl Test whether mbrtowc supports a NULL pwc argument correctly.
206 dnl Result is gl_cv_func_mbrtowc_null_arg1.
207
208 AC_DEFUN([gl_MBRTOWC_NULL_ARG1],
209 [
210   AC_REQUIRE([AC_PROG_CC])
211   AC_REQUIRE([gt_LOCALE_FR_UTF8])
212   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
213   AC_CACHE_CHECK([whether mbrtowc handles a NULL pwc argument],
214     [gl_cv_func_mbrtowc_null_arg1],
215     [
216       dnl Initial guess, used when cross-compiling or when no suitable locale
217       dnl is present.
218 changequote(,)dnl
219       case "$host_os" in
220                   # Guess no on Solaris.
221         solaris*) gl_cv_func_mbrtowc_null_arg1="guessing no" ;;
222                   # Guess yes otherwise.
223         *)        gl_cv_func_mbrtowc_null_arg1="guessing yes" ;;
224       esac
225 changequote([,])dnl
226       if test $LOCALE_FR_UTF8 != none; then
227         AC_RUN_IFELSE(
228           [AC_LANG_SOURCE([[
229 #include <locale.h>
230 #include <stdlib.h>
231 #include <string.h>
232 /* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
233    <wchar.h>.
234    BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
235    included before <wchar.h>.  */
236 #include <stddef.h>
237 #include <stdio.h>
238 #include <time.h>
239 #include <wchar.h>
240 int main ()
241 {
242   int result = 0;
243
244   if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
245     {
246       char input[] = "\303\237er";
247       mbstate_t state;
248       wchar_t wc;
249       size_t ret;
250
251       memset (&state, '\0', sizeof (mbstate_t));
252       wc = (wchar_t) 0xBADFACE;
253       ret = mbrtowc (&wc, input, 5, &state);
254       if (ret != 2)
255         result |= 1;
256       if (!mbsinit (&state))
257         result |= 2;
258
259       memset (&state, '\0', sizeof (mbstate_t));
260       ret = mbrtowc (NULL, input, 5, &state);
261       if (ret != 2) /* Solaris 7 fails here: ret is -1.  */
262         result |= 4;
263       if (!mbsinit (&state))
264         result |= 8;
265     }
266   return result;
267 }]])],
268           [gl_cv_func_mbrtowc_null_arg1=yes],
269           [gl_cv_func_mbrtowc_null_arg1=no],
270           [:])
271       fi
272     ])
273 ])
274
275 dnl Test whether mbrtowc supports a NULL string argument correctly.
276 dnl Result is gl_cv_func_mbrtowc_null_arg2.
277
278 AC_DEFUN([gl_MBRTOWC_NULL_ARG2],
279 [
280   AC_REQUIRE([AC_PROG_CC])
281   AC_REQUIRE([gt_LOCALE_FR_UTF8])
282   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
283   AC_CACHE_CHECK([whether mbrtowc handles a NULL string argument],
284     [gl_cv_func_mbrtowc_null_arg2],
285     [
286       dnl Initial guess, used when cross-compiling or when no suitable locale
287       dnl is present.
288 changequote(,)dnl
289       case "$host_os" in
290               # Guess no on OSF/1.
291         osf*) gl_cv_func_mbrtowc_null_arg2="guessing no" ;;
292               # Guess yes otherwise.
293         *)    gl_cv_func_mbrtowc_null_arg2="guessing yes" ;;
294       esac
295 changequote([,])dnl
296       if test $LOCALE_FR_UTF8 != none; then
297         AC_RUN_IFELSE(
298           [AC_LANG_SOURCE([[
299 #include <locale.h>
300 #include <string.h>
301 /* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
302    <wchar.h>.
303    BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
304    included before <wchar.h>.  */
305 #include <stddef.h>
306 #include <stdio.h>
307 #include <time.h>
308 #include <wchar.h>
309 int main ()
310 {
311   if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
312     {
313       mbstate_t state;
314       wchar_t wc;
315       int ret;
316
317       memset (&state, '\0', sizeof (mbstate_t));
318       wc = (wchar_t) 0xBADFACE;
319       mbrtowc (&wc, NULL, 5, &state);
320       /* Check that wc was not modified.  */
321       if (wc != (wchar_t) 0xBADFACE)
322         return 1;
323     }
324   return 0;
325 }]])],
326           [gl_cv_func_mbrtowc_null_arg2=yes],
327           [gl_cv_func_mbrtowc_null_arg2=no],
328           [:])
329       fi
330     ])
331 ])
332
333 dnl Test whether mbrtowc, when parsing the end of a multibyte character,
334 dnl correctly returns the number of bytes that were needed to complete the
335 dnl character (not the total number of bytes of the multibyte character).
336 dnl Result is gl_cv_func_mbrtowc_retval.
337
338 AC_DEFUN([gl_MBRTOWC_RETVAL],
339 [
340   AC_REQUIRE([AC_PROG_CC])
341   AC_REQUIRE([gt_LOCALE_FR_UTF8])
342   AC_REQUIRE([gt_LOCALE_JA])
343   AC_REQUIRE([AC_CANONICAL_HOST])
344   AC_CACHE_CHECK([whether mbrtowc has a correct return value],
345     [gl_cv_func_mbrtowc_retval],
346     [
347       dnl Initial guess, used when cross-compiling or when no suitable locale
348       dnl is present.
349 changequote(,)dnl
350       case "$host_os" in
351                                    # Guess no on HP-UX, Solaris, native Windows.
352         hpux* | solaris* | mingw*) gl_cv_func_mbrtowc_retval="guessing no" ;;
353                                    # Guess yes otherwise.
354         *)                         gl_cv_func_mbrtowc_retval="guessing yes" ;;
355       esac
356 changequote([,])dnl
357       if test $LOCALE_FR_UTF8 != none || test $LOCALE_JA != none \
358          || { case "$host_os" in mingw*) true;; *) false;; esac; }; then
359         AC_RUN_IFELSE(
360           [AC_LANG_SOURCE([[
361 #include <locale.h>
362 #include <string.h>
363 /* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
364    <wchar.h>.
365    BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
366    included before <wchar.h>.  */
367 #include <stddef.h>
368 #include <stdio.h>
369 #include <time.h>
370 #include <wchar.h>
371 int main ()
372 {
373   int result = 0;
374   int found_some_locale = 0;
375   /* This fails on Solaris.  */
376   if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
377     {
378       char input[] = "B\303\274\303\237er"; /* "Büßer" */
379       mbstate_t state;
380       wchar_t wc;
381
382       memset (&state, '\0', sizeof (mbstate_t));
383       if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
384         {
385           input[1] = '\0';
386           if (mbrtowc (&wc, input + 2, 5, &state) != 1)
387             result |= 1;
388         }
389       found_some_locale = 1;
390     }
391   /* This fails on HP-UX 11.11.  */
392   if (setlocale (LC_ALL, "$LOCALE_JA") != NULL)
393     {
394       char input[] = "B\217\253\344\217\251\316er"; /* "Büßer" */
395       mbstate_t state;
396       wchar_t wc;
397
398       memset (&state, '\0', sizeof (mbstate_t));
399       if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
400         {
401           input[1] = '\0';
402           if (mbrtowc (&wc, input + 2, 5, &state) != 2)
403             result |= 2;
404         }
405       found_some_locale = 1;
406     }
407   /* This fails on native Windows.  */
408   if (setlocale (LC_ALL, "Japanese_Japan.932") != NULL)
409     {
410       char input[] = "<\223\372\226\173\214\352>"; /* "<日本語>" */
411       mbstate_t state;
412       wchar_t wc;
413
414       memset (&state, '\0', sizeof (mbstate_t));
415       if (mbrtowc (&wc, input + 3, 1, &state) == (size_t)(-2))
416         {
417           input[3] = '\0';
418           if (mbrtowc (&wc, input + 4, 4, &state) != 1)
419             result |= 4;
420         }
421       found_some_locale = 1;
422     }
423   if (setlocale (LC_ALL, "Chinese_Taiwan.950") != NULL)
424     {
425       char input[] = "<\244\351\245\273\273\171>"; /* "<日本語>" */
426       mbstate_t state;
427       wchar_t wc;
428
429       memset (&state, '\0', sizeof (mbstate_t));
430       if (mbrtowc (&wc, input + 3, 1, &state) == (size_t)(-2))
431         {
432           input[3] = '\0';
433           if (mbrtowc (&wc, input + 4, 4, &state) != 1)
434             result |= 8;
435         }
436       found_some_locale = 1;
437     }
438   if (setlocale (LC_ALL, "Chinese_China.936") != NULL)
439     {
440       char input[] = "<\310\325\261\276\325\132>"; /* "<日本語>" */
441       mbstate_t state;
442       wchar_t wc;
443
444       memset (&state, '\0', sizeof (mbstate_t));
445       if (mbrtowc (&wc, input + 3, 1, &state) == (size_t)(-2))
446         {
447           input[3] = '\0';
448           if (mbrtowc (&wc, input + 4, 4, &state) != 1)
449             result |= 16;
450         }
451       found_some_locale = 1;
452     }
453   return (found_some_locale ? result : 77);
454 }]])],
455           [gl_cv_func_mbrtowc_retval=yes],
456           [if test $? != 77; then
457              gl_cv_func_mbrtowc_retval=no
458            fi
459           ],
460           [:])
461       fi
462     ])
463 ])
464
465 dnl Test whether mbrtowc, when parsing a NUL character, correctly returns 0.
466 dnl Result is gl_cv_func_mbrtowc_nul_retval.
467
468 AC_DEFUN([gl_MBRTOWC_NUL_RETVAL],
469 [
470   AC_REQUIRE([AC_PROG_CC])
471   AC_REQUIRE([gt_LOCALE_ZH_CN])
472   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
473   AC_CACHE_CHECK([whether mbrtowc returns 0 when parsing a NUL character],
474     [gl_cv_func_mbrtowc_nul_retval],
475     [
476       dnl Initial guess, used when cross-compiling or when no suitable locale
477       dnl is present.
478 changequote(,)dnl
479       case "$host_os" in
480                        # Guess no on Solaris 8 and 9.
481         solaris2.[89]) gl_cv_func_mbrtowc_nul_retval="guessing no" ;;
482                        # Guess yes otherwise.
483         *)             gl_cv_func_mbrtowc_nul_retval="guessing yes" ;;
484       esac
485 changequote([,])dnl
486       if test $LOCALE_ZH_CN != none; then
487         AC_RUN_IFELSE(
488           [AC_LANG_SOURCE([[
489 #include <locale.h>
490 #include <string.h>
491 /* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
492    <wchar.h>.
493    BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
494    included before <wchar.h>.  */
495 #include <stddef.h>
496 #include <stdio.h>
497 #include <time.h>
498 #include <wchar.h>
499 int main ()
500 {
501   /* This fails on Solaris 8 and 9.  */
502   if (setlocale (LC_ALL, "$LOCALE_ZH_CN") != NULL)
503     {
504       mbstate_t state;
505       wchar_t wc;
506
507       memset (&state, '\0', sizeof (mbstate_t));
508       if (mbrtowc (&wc, "", 1, &state) != 0)
509         return 1;
510     }
511   return 0;
512 }]])],
513           [gl_cv_func_mbrtowc_nul_retval=yes],
514           [gl_cv_func_mbrtowc_nul_retval=no],
515           [:])
516       fi
517     ])
518 ])
519
520 # Prerequisites of lib/mbrtowc.c.
521 AC_DEFUN([gl_PREREQ_MBRTOWC], [
522   :
523 ])
524
525
526 dnl From Paul Eggert
527
528 dnl This is an override of an autoconf macro.
529
530 AC_DEFUN([AC_FUNC_MBRTOWC],
531 [
532   dnl Same as AC_FUNC_MBRTOWC in autoconf-2.60.
533   AC_CACHE_CHECK([whether mbrtowc and mbstate_t are properly declared],
534     gl_cv_func_mbrtowc,
535     [AC_LINK_IFELSE(
536        [AC_LANG_PROGRAM(
537             [[/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be
538                  included before <wchar.h>.
539                  BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h>
540                  must be included before <wchar.h>.  */
541               #include <stddef.h>
542               #include <stdio.h>
543               #include <time.h>
544               #include <wchar.h>]],
545             [[wchar_t wc;
546               char const s[] = "";
547               size_t n = 1;
548               mbstate_t state;
549               return ! (sizeof state && (mbrtowc) (&wc, s, n, &state));]])],
550        gl_cv_func_mbrtowc=yes,
551        gl_cv_func_mbrtowc=no)])
552   if test $gl_cv_func_mbrtowc = yes; then
553     AC_DEFINE([HAVE_MBRTOWC], [1],
554       [Define to 1 if mbrtowc and mbstate_t are properly declared.])
555   fi
556 ])