Work around mbrtowc bugs on AIX, HP-UX, OSF/1, Solaris.
[gnulib.git] / m4 / mbrtowc.m4
1 # mbrtowc.m4 serial 11
2 dnl Copyright (C) 2001-2002, 2004-2005, 2008 Free Software Foundation, Inc.
3 dnl This file is free software; the Free Software Foundation
4 dnl gives unlimited permission to copy and/or distribute it,
5 dnl with or without modifications, as long as this notice is preserved.
6
7 AC_DEFUN([gl_FUNC_MBRTOWC],
8 [
9   AC_REQUIRE([gl_WCHAR_H_DEFAULTS])
10
11   AC_REQUIRE([AC_TYPE_MBSTATE_T])
12   gl_MBSTATE_T_BROKEN
13   if test $REPLACE_MBSTATE_T = 1; then
14     REPLACE_MBRTOWC=1
15   fi
16   AC_CHECK_FUNCS_ONCE([mbrtowc])
17   if test $ac_cv_func_mbrtowc = no; then
18     HAVE_MBRTOWC=0
19   fi
20   if test $HAVE_MBRTOWC != 0 && test $REPLACE_MBRTOWC != 1; then
21     gl_MBRTOWC_NULL_ARG
22     gl_MBRTOWC_RETVAL
23     gl_MBRTOWC_NUL_RETVAL
24     case "$gl_cv_func_mbrtowc_null_arg" in
25       *yes) ;;
26       *) AC_DEFINE([MBRTOWC_NULL_ARG_BUG], [1],
27            [Define if the mbrtowc function has the NULL string argument bug.])
28          REPLACE_MBRTOWC=1
29          ;;
30     esac
31     case "$gl_cv_func_mbrtowc_retval" in
32       *yes) ;;
33       *) AC_DEFINE([MBRTOWC_RETVAL_BUG], [1],
34            [Define if the mbrtowc function returns a wrong return value.])
35          REPLACE_MBRTOWC=1
36          ;;
37     esac
38     case "$gl_cv_func_mbrtowc_nul_retval" in
39       *yes) ;;
40       *) AC_DEFINE([MBRTOWC_NUL_RETVAL_BUG], [1],
41            [Define if the mbrtowc function does not return 0 for a NUL character.])
42          REPLACE_MBRTOWC=1
43          ;;
44     esac
45   fi
46   if test $HAVE_MBRTOWC = 0 || test $REPLACE_MBRTOWC = 1; then
47     gl_REPLACE_WCHAR_H
48     AC_LIBOBJ([mbrtowc])
49     gl_PREREQ_MBRTOWC
50   fi
51 ])
52
53 dnl Test whether mbsinit() and mbrtowc() need to be overridden in a way that
54 dnl redefines the semantics of the given mbstate_t type.
55 dnl Result is REPLACE_MBSTATE_T.
56 dnl When this is set to 1, we replace both mbsinit() and mbrtowc(), in order to
57 dnl avoid inconsistencies.
58
59 AC_DEFUN([gl_MBSTATE_T_BROKEN],
60 [
61   AC_REQUIRE([gl_WCHAR_H_DEFAULTS])
62
63   AC_REQUIRE([AC_TYPE_MBSTATE_T])
64   AC_CHECK_FUNCS_ONCE([mbsinit])
65   AC_CHECK_FUNCS_ONCE([mbrtowc])
66   if test $ac_cv_func_mbsinit = yes && test $ac_cv_func_mbrtowc = yes; then
67     gl_MBRTOWC_INCOMPLETE_STATE
68     case "$gl_cv_func_mbrtowc_incomplete_state" in
69       *yes) REPLACE_MBSTATE_T=0 ;;
70       *)    REPLACE_MBSTATE_T=1 ;;
71     esac
72   else
73     REPLACE_MBSTATE_T=1
74   fi
75   if test $REPLACE_MBSTATE_T = 1; then
76     gl_REPLACE_WCHAR_H
77   fi
78 ])
79
80 dnl Test whether mbrtowc puts the state into non-initial state when parsing an
81 dnl incomplete multibyte character.
82 dnl Result is gl_cv_func_mbrtowc_incomplete_state.
83
84 AC_DEFUN([gl_MBRTOWC_INCOMPLETE_STATE],
85 [
86   AC_REQUIRE([AC_PROG_CC])
87   AC_REQUIRE([gt_LOCALE_JA])
88   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
89   AC_CACHE_CHECK([whether mbrtowc handles incomplete characters],
90     [gl_cv_func_mbrtowc_incomplete_state],
91     [
92       dnl Initial guess, used when cross-compiling or when no suitable locale
93       dnl is present.
94 changequote(,)dnl
95       case "$host_os" in
96               # Guess no on AIX and OSF/1.
97         osf*) gl_cv_func_mbrtowc_incomplete_state="guessing no" ;;
98               # Guess yes otherwise.
99         *)    gl_cv_func_mbrtowc_incomplete_state="guessing yes" ;;
100       esac
101 changequote([,])dnl
102       if test $LOCALE_JA != none; then
103         AC_TRY_RUN([
104 #include <locale.h>
105 #include <string.h>
106 #include <wchar.h>
107 int main ()
108 {
109   if (setlocale (LC_ALL, "$LOCALE_JA") != NULL)
110     {
111       const char input[] = "B\217\253\344\217\251\316er"; /* "Büßer" */
112       mbstate_t state;
113       wchar_t wc;
114       int ret;
115
116       memset (&state, '\0', sizeof (mbstate_t));
117       if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
118         if (mbsinit (&state))
119           return 1;
120     }
121   return 0;
122 }],
123           [gl_cv_func_mbrtowc_incomplete_state=yes],
124           [gl_cv_func_mbrtowc_incomplete_state=no],
125           [])
126       fi
127     ])
128 ])
129
130 dnl Test whether mbrtowc supports a NULL string argument correctly.
131 dnl Result is gl_cv_func_mbrtowc_null_arg.
132
133 AC_DEFUN([gl_MBRTOWC_NULL_ARG],
134 [
135   AC_REQUIRE([AC_PROG_CC])
136   AC_REQUIRE([gt_LOCALE_FR_UTF8])
137   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
138   AC_CACHE_CHECK([whether mbrtowc handles a NULL string argument],
139     [gl_cv_func_mbrtowc_null_arg],
140     [
141       dnl Initial guess, used when cross-compiling or when no suitable locale
142       dnl is present.
143 changequote(,)dnl
144       case "$host_os" in
145               # Guess no on OSF/1.
146         osf*) gl_cv_func_mbrtowc_null_arg="guessing no" ;;
147               # Guess yes otherwise.
148         *)    gl_cv_func_mbrtowc_null_arg="guessing yes" ;;
149       esac
150 changequote([,])dnl
151       if test $LOCALE_FR_UTF8 != none; then
152         AC_TRY_RUN([
153 #include <locale.h>
154 #include <string.h>
155 #include <wchar.h>
156 int main ()
157 {
158   if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
159     {
160       mbstate_t state;
161       wchar_t wc;
162       int ret;
163
164       memset (&state, '\0', sizeof (mbstate_t));
165       wc = (wchar_t) 0xBADFACE;
166       mbrtowc (&wc, NULL, 5, &state);
167       /* Check that wc was not modified.  */
168       if (wc != (wchar_t) 0xBADFACE)
169         return 1;
170     }
171   return 0;
172 }], [gl_cv_func_mbrtowc_null_arg=yes], [gl_cv_func_mbrtowc_null_arg=no], [])
173       fi
174     ])
175 ])
176
177 dnl Test whether mbrtowc, when parsing the end of a multibyte character,
178 dnl correctly returns the number of bytes that were needed to complete the
179 dnl character (not the total number of bytes of the multibyte character).
180 dnl Result is gl_cv_func_mbrtowc_retval.
181
182 AC_DEFUN([gl_MBRTOWC_RETVAL],
183 [
184   AC_REQUIRE([AC_PROG_CC])
185   AC_REQUIRE([gt_LOCALE_FR_UTF8])
186   AC_REQUIRE([gt_LOCALE_JA])
187   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
188   AC_CACHE_CHECK([whether mbrtowc has a correct return value],
189     [gl_cv_func_mbrtowc_retval],
190     [
191       dnl Initial guess, used when cross-compiling or when no suitable locale
192       dnl is present.
193 changequote(,)dnl
194       case "$host_os" in
195                           # Guess no on HP-UX and Solaris.
196         hpux* | solaris*) gl_cv_func_mbrtowc_retval="guessing no" ;;
197                           # Guess yes otherwise.
198         *)                gl_cv_func_mbrtowc_retval="guessing yes" ;;
199       esac
200 changequote([,])dnl
201       if test $LOCALE_FR_UTF8 != none || test $LOCALE_JA != none; then
202         AC_TRY_RUN([
203 #include <locale.h>
204 #include <string.h>
205 #include <wchar.h>
206 int main ()
207 {
208   /* This fails on Solaris.  */
209   if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
210     {
211       char input[] = "B\303\274\303\237er"; /* "Büßer" */
212       mbstate_t state;
213       wchar_t wc;
214
215       memset (&state, '\0', sizeof (mbstate_t));
216       if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
217         {
218           input[1] = '\0';
219           if (mbrtowc (&wc, input + 2, 5, &state) != 1)
220             return 1;
221         }
222     }
223   /* This fails on HP-UX 11.11.  */
224   if (setlocale (LC_ALL, "$LOCALE_JA") != NULL)
225     {
226       char input[] = "B\217\253\344\217\251\316er"; /* "Büßer" */
227       mbstate_t state;
228       wchar_t wc;
229
230       memset (&state, '\0', sizeof (mbstate_t));
231       if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
232         {
233           input[1] = '\0';
234           if (mbrtowc (&wc, input + 2, 5, &state) != 2)
235             return 1;
236         }
237     }
238   return 0;
239 }],
240           [gl_cv_func_mbrtowc_retval=yes],
241           [gl_cv_func_mbrtowc_retval=no],
242           [])
243       fi
244     ])
245 ])
246
247 dnl Test whether mbrtowc, when parsing a NUL character, correctly returns 0.
248 dnl Result is gl_cv_func_mbrtowc_nul_retval.
249
250 AC_DEFUN([gl_MBRTOWC_NUL_RETVAL],
251 [
252   AC_REQUIRE([AC_PROG_CC])
253   AC_REQUIRE([gt_LOCALE_ZH_CN])
254   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
255   AC_CACHE_CHECK([whether mbrtowc returns 0 when parsing a NUL character],
256     [gl_cv_func_mbrtowc_nul_retval],
257     [
258       dnl Initial guess, used when cross-compiling or when no suitable locale
259       dnl is present.
260 changequote(,)dnl
261       case "$host_os" in
262                     # Guess no on Solaris 9.
263         solaris2.9) gl_cv_func_mbrtowc_nul_retval="guessing no" ;;
264                     # Guess yes otherwise.
265         *)          gl_cv_func_mbrtowc_nul_retval="guessing yes" ;;
266       esac
267 changequote([,])dnl
268       if test $LOCALE_ZH_CN != none; then
269         AC_TRY_RUN([
270 #include <locale.h>
271 #include <string.h>
272 #include <wchar.h>
273 int main ()
274 {
275   /* This fails on Solaris 9.  */
276   if (setlocale (LC_ALL, "$LOCALE_ZH_CN") != NULL)
277     {
278       mbstate_t state;
279       wchar_t wc;
280
281       memset (&state, '\0', sizeof (mbstate_t));
282       if (mbrtowc (&wc, "", 1, &state) != 0)
283         return 1;
284     }
285   return 0;
286 }],
287           [gl_cv_func_mbrtowc_nul_retval=yes],
288           [gl_cv_func_mbrtowc_nul_retval=no],
289           [])
290       fi
291     ])
292 ])
293
294 # Prerequisites of lib/mbrtowc.c.
295 AC_DEFUN([gl_PREREQ_MBRTOWC], [
296   :
297 ])
298
299
300 dnl From Paul Eggert
301
302 dnl This override of an autoconf macro can be removed when autoconf 2.60 or
303 dnl newer can be assumed everywhere.
304
305 m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.60]),[-1],[
306 AC_DEFUN([AC_FUNC_MBRTOWC],
307 [
308   dnl Same as AC_FUNC_MBRTOWC in autoconf-2.60.
309   AC_CACHE_CHECK([whether mbrtowc and mbstate_t are properly declared],
310     gl_cv_func_mbrtowc,
311     [AC_LINK_IFELSE(
312        [AC_LANG_PROGRAM(
313             [[#include <wchar.h>]],
314             [[wchar_t wc;
315               char const s[] = "";
316               size_t n = 1;
317               mbstate_t state;
318               return ! (sizeof state && (mbrtowc) (&wc, s, n, &state));]])],
319        gl_cv_func_mbrtowc=yes,
320        gl_cv_func_mbrtowc=no)])
321   if test $gl_cv_func_mbrtowc = yes; then
322     AC_DEFINE([HAVE_MBRTOWC], 1,
323       [Define to 1 if mbrtowc and mbstate_t are properly declared.])
324   fi
325 ])
326 ])