mbrtowc: Work around a Solaris 7 bug.
[gnulib.git] / m4 / mbrtowc.m4
1 # mbrtowc.m4 serial 21
2 dnl Copyright (C) 2001-2002, 2004-2005, 2008-2010 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]) dnl for cross-compiles
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 and Solaris.
360         hpux* | solaris*) 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; then
366         AC_RUN_IFELSE(
367           [AC_LANG_SOURCE([[
368 #include <locale.h>
369 #include <string.h>
370 /* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
371    <wchar.h>.
372    BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
373    included before <wchar.h>.  */
374 #include <stddef.h>
375 #include <stdio.h>
376 #include <time.h>
377 #include <wchar.h>
378 int main ()
379 {
380   int result = 0;
381   /* This fails on Solaris.  */
382   if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
383     {
384       char input[] = "B\303\274\303\237er"; /* "Büßer" */
385       mbstate_t state;
386       wchar_t wc;
387
388       memset (&state, '\0', sizeof (mbstate_t));
389       if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
390         {
391           input[1] = '\0';
392           if (mbrtowc (&wc, input + 2, 5, &state) != 1)
393             result |= 1;
394         }
395     }
396   /* This fails on HP-UX 11.11.  */
397   if (setlocale (LC_ALL, "$LOCALE_JA") != NULL)
398     {
399       char input[] = "B\217\253\344\217\251\316er"; /* "Büßer" */
400       mbstate_t state;
401       wchar_t wc;
402
403       memset (&state, '\0', sizeof (mbstate_t));
404       if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
405         {
406           input[1] = '\0';
407           if (mbrtowc (&wc, input + 2, 5, &state) != 2)
408             result |= 2;
409         }
410     }
411   return result;
412 }]])],
413           [gl_cv_func_mbrtowc_retval=yes],
414           [gl_cv_func_mbrtowc_retval=no],
415           [:])
416       fi
417     ])
418 ])
419
420 dnl Test whether mbrtowc, when parsing a NUL character, correctly returns 0.
421 dnl Result is gl_cv_func_mbrtowc_nul_retval.
422
423 AC_DEFUN([gl_MBRTOWC_NUL_RETVAL],
424 [
425   AC_REQUIRE([AC_PROG_CC])
426   AC_REQUIRE([gt_LOCALE_ZH_CN])
427   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
428   AC_CACHE_CHECK([whether mbrtowc returns 0 when parsing a NUL character],
429     [gl_cv_func_mbrtowc_nul_retval],
430     [
431       dnl Initial guess, used when cross-compiling or when no suitable locale
432       dnl is present.
433 changequote(,)dnl
434       case "$host_os" in
435                        # Guess no on Solaris 8 and 9.
436         solaris2.[89]) gl_cv_func_mbrtowc_nul_retval="guessing no" ;;
437                        # Guess yes otherwise.
438         *)             gl_cv_func_mbrtowc_nul_retval="guessing yes" ;;
439       esac
440 changequote([,])dnl
441       if test $LOCALE_ZH_CN != none; then
442         AC_RUN_IFELSE(
443           [AC_LANG_SOURCE([[
444 #include <locale.h>
445 #include <string.h>
446 /* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
447    <wchar.h>.
448    BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
449    included before <wchar.h>.  */
450 #include <stddef.h>
451 #include <stdio.h>
452 #include <time.h>
453 #include <wchar.h>
454 int main ()
455 {
456   /* This fails on Solaris 8 and 9.  */
457   if (setlocale (LC_ALL, "$LOCALE_ZH_CN") != NULL)
458     {
459       mbstate_t state;
460       wchar_t wc;
461
462       memset (&state, '\0', sizeof (mbstate_t));
463       if (mbrtowc (&wc, "", 1, &state) != 0)
464         return 1;
465     }
466   return 0;
467 }]])],
468           [gl_cv_func_mbrtowc_nul_retval=yes],
469           [gl_cv_func_mbrtowc_nul_retval=no],
470           [:])
471       fi
472     ])
473 ])
474
475 # Prerequisites of lib/mbrtowc.c.
476 AC_DEFUN([gl_PREREQ_MBRTOWC], [
477   :
478 ])
479
480
481 dnl From Paul Eggert
482
483 dnl This is an override of an autoconf macro.
484
485 AC_DEFUN([AC_FUNC_MBRTOWC],
486 [
487   dnl Same as AC_FUNC_MBRTOWC in autoconf-2.60.
488   AC_CACHE_CHECK([whether mbrtowc and mbstate_t are properly declared],
489     gl_cv_func_mbrtowc,
490     [AC_LINK_IFELSE(
491        [AC_LANG_PROGRAM(
492             [[/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be
493                  included before <wchar.h>.
494                  BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h>
495                  must be included before <wchar.h>.  */
496               #include <stddef.h>
497               #include <stdio.h>
498               #include <time.h>
499               #include <wchar.h>]],
500             [[wchar_t wc;
501               char const s[] = "";
502               size_t n = 1;
503               mbstate_t state;
504               return ! (sizeof state && (mbrtowc) (&wc, s, n, &state));]])],
505        gl_cv_func_mbrtowc=yes,
506        gl_cv_func_mbrtowc=no)])
507   if test $gl_cv_func_mbrtowc = yes; then
508     AC_DEFINE([HAVE_MBRTOWC], [1],
509       [Define to 1 if mbrtowc and mbstate_t are properly declared.])
510   fi
511 ])