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