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