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