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