1# mbrtowc.m4 serial 17
2dnl Copyright (C) 2001-2002, 2004-2005, 2008-2010 Free Software Foundation,
3dnl Inc.
4dnl This file is free software; the Free Software Foundation
5dnl gives unlimited permission to copy and/or distribute it,
6dnl with or without modifications, as long as this notice is preserved.
7
8AC_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
55dnl Test whether mbsinit() and mbrtowc() need to be overridden in a way that
56dnl redefines the semantics of the given mbstate_t type.
57dnl Result is REPLACE_MBSTATE_T.
58dnl When this is set to 1, we replace both mbsinit() and mbrtowc(), in order to
59dnl avoid inconsistencies.
60
61AC_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
88dnl Test whether mbrtowc puts the state into non-initial state when parsing an
89dnl incomplete multibyte character.
90dnl Result is gl_cv_func_mbrtowc_incomplete_state.
91
92AC_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.
102changequote(,)dnl
103      case "$host_os" in
104              # Guess no on AIX and OSF/1.
105        osf*) gl_cv_func_mbrtowc_incomplete_state="guessing no" ;;
106              # Guess yes otherwise.
107        *)    gl_cv_func_mbrtowc_incomplete_state="guessing yes" ;;
108      esac
109changequote([,])dnl
110      if test $LOCALE_JA != none; then
111        AC_TRY_RUN([
112#include <locale.h>
113#include <string.h>
114#include <wchar.h>
115int main ()
116{
117  if (setlocale (LC_ALL, "$LOCALE_JA") != NULL)
118    {
119      const char input[] = "B\217\253\344\217\251\316er"; /* "B����er" */
120      mbstate_t state;
121      wchar_t wc;
122
123      memset (&state, '\0', sizeof (mbstate_t));
124      if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
125        if (mbsinit (&state))
126          return 1;
127    }
128  return 0;
129}],
130          [gl_cv_func_mbrtowc_incomplete_state=yes],
131          [gl_cv_func_mbrtowc_incomplete_state=no],
132          [:])
133      fi
134    ])
135])
136
137dnl Test whether mbrtowc works not worse than mbtowc.
138dnl Result is gl_cv_func_mbrtowc_sanitycheck.
139
140AC_DEFUN([gl_MBRTOWC_SANITYCHECK],
141[
142  AC_REQUIRE([AC_PROG_CC])
143  AC_REQUIRE([gt_LOCALE_ZH_CN])
144  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
145  AC_CACHE_CHECK([whether mbrtowc works as well as mbtowc],
146    [gl_cv_func_mbrtowc_sanitycheck],
147    [
148      dnl Initial guess, used when cross-compiling or when no suitable locale
149      dnl is present.
150changequote(,)dnl
151      case "$host_os" in
152                    # Guess no on Solaris 8.
153        solaris2.8) gl_cv_func_mbrtowc_sanitycheck="guessing no" ;;
154                    # Guess yes otherwise.
155        *)          gl_cv_func_mbrtowc_sanitycheck="guessing yes" ;;
156      esac
157changequote([,])dnl
158      if test $LOCALE_ZH_CN != none; then
159        AC_TRY_RUN([
160#include <locale.h>
161#include <stdlib.h>
162#include <string.h>
163#include <wchar.h>
164int main ()
165{
166  /* This fails on Solaris 8:
167     mbrtowc returns 2, and sets wc to 0x00F0.
168     mbtowc returns 4 (correct) and sets wc to 0x5EDC.  */
169  if (setlocale (LC_ALL, "$LOCALE_ZH_CN") != NULL)
170    {
171      char input[] = "B\250\271\201\060\211\070er"; /* "B����er" */
172      mbstate_t state;
173      wchar_t wc;
174
175      memset (&state, '\0', sizeof (mbstate_t));
176      if (mbrtowc (&wc, input + 3, 6, &state) != 4
177          && mbtowc (&wc, input + 3, 6) == 4)
178        return 1;
179    }
180  return 0;
181}],
182          [gl_cv_func_mbrtowc_sanitycheck=yes],
183          [gl_cv_func_mbrtowc_sanitycheck=no],
184          [:])
185      fi
186    ])
187])
188
189dnl Test whether mbrtowc supports a NULL string argument correctly.
190dnl Result is gl_cv_func_mbrtowc_null_arg.
191
192AC_DEFUN([gl_MBRTOWC_NULL_ARG],
193[
194  AC_REQUIRE([AC_PROG_CC])
195  AC_REQUIRE([gt_LOCALE_FR_UTF8])
196  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
197  AC_CACHE_CHECK([whether mbrtowc handles a NULL string argument],
198    [gl_cv_func_mbrtowc_null_arg],
199    [
200      dnl Initial guess, used when cross-compiling or when no suitable locale
201      dnl is present.
202changequote(,)dnl
203      case "$host_os" in
204              # Guess no on OSF/1.
205        osf*) gl_cv_func_mbrtowc_null_arg="guessing no" ;;
206              # Guess yes otherwise.
207        *)    gl_cv_func_mbrtowc_null_arg="guessing yes" ;;
208      esac
209changequote([,])dnl
210      if test $LOCALE_FR_UTF8 != none; then
211        AC_TRY_RUN([
212#include <locale.h>
213#include <string.h>
214#include <wchar.h>
215int main ()
216{
217  if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
218    {
219      mbstate_t state;
220      wchar_t wc;
221      int ret;
222
223      memset (&state, '\0', sizeof (mbstate_t));
224      wc = (wchar_t) 0xBADFACE;
225      mbrtowc (&wc, NULL, 5, &state);
226      /* Check that wc was not modified.  */
227      if (wc != (wchar_t) 0xBADFACE)
228        return 1;
229    }
230  return 0;
231}], [gl_cv_func_mbrtowc_null_arg=yes], [gl_cv_func_mbrtowc_null_arg=no], [:])
232      fi
233    ])
234])
235
236dnl Test whether mbrtowc, when parsing the end of a multibyte character,
237dnl correctly returns the number of bytes that were needed to complete the
238dnl character (not the total number of bytes of the multibyte character).
239dnl Result is gl_cv_func_mbrtowc_retval.
240
241AC_DEFUN([gl_MBRTOWC_RETVAL],
242[
243  AC_REQUIRE([AC_PROG_CC])
244  AC_REQUIRE([gt_LOCALE_FR_UTF8])
245  AC_REQUIRE([gt_LOCALE_JA])
246  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
247  AC_CACHE_CHECK([whether mbrtowc has a correct return value],
248    [gl_cv_func_mbrtowc_retval],
249    [
250      dnl Initial guess, used when cross-compiling or when no suitable locale
251      dnl is present.
252changequote(,)dnl
253      case "$host_os" in
254                          # Guess no on HP-UX and Solaris.
255        hpux* | solaris*) gl_cv_func_mbrtowc_retval="guessing no" ;;
256                          # Guess yes otherwise.
257        *)                gl_cv_func_mbrtowc_retval="guessing yes" ;;
258      esac
259changequote([,])dnl
260      if test $LOCALE_FR_UTF8 != none || test $LOCALE_JA != none; then
261        AC_TRY_RUN([
262#include <locale.h>
263#include <string.h>
264#include <wchar.h>
265int main ()
266{
267  /* This fails on Solaris.  */
268  if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL)
269    {
270      char input[] = "B\303\274\303\237er"; /* "B����er" */
271      mbstate_t state;
272      wchar_t wc;
273
274      memset (&state, '\0', sizeof (mbstate_t));
275      if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
276        {
277          input[1] = '\0';
278          if (mbrtowc (&wc, input + 2, 5, &state) != 1)
279            return 1;
280        }
281    }
282  /* This fails on HP-UX 11.11.  */
283  if (setlocale (LC_ALL, "$LOCALE_JA") != NULL)
284    {
285      char input[] = "B\217\253\344\217\251\316er"; /* "B����er" */
286      mbstate_t state;
287      wchar_t wc;
288
289      memset (&state, '\0', sizeof (mbstate_t));
290      if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2))
291        {
292          input[1] = '\0';
293          if (mbrtowc (&wc, input + 2, 5, &state) != 2)
294            return 1;
295        }
296    }
297  return 0;
298}],
299          [gl_cv_func_mbrtowc_retval=yes],
300          [gl_cv_func_mbrtowc_retval=no],
301          [:])
302      fi
303    ])
304])
305
306dnl Test whether mbrtowc, when parsing a NUL character, correctly returns 0.
307dnl Result is gl_cv_func_mbrtowc_nul_retval.
308
309AC_DEFUN([gl_MBRTOWC_NUL_RETVAL],
310[
311  AC_REQUIRE([AC_PROG_CC])
312  AC_REQUIRE([gt_LOCALE_ZH_CN])
313  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
314  AC_CACHE_CHECK([whether mbrtowc returns 0 when parsing a NUL character],
315    [gl_cv_func_mbrtowc_nul_retval],
316    [
317      dnl Initial guess, used when cross-compiling or when no suitable locale
318      dnl is present.
319changequote(,)dnl
320      case "$host_os" in
321                       # Guess no on Solaris 8 and 9.
322        solaris2.[89]) gl_cv_func_mbrtowc_nul_retval="guessing no" ;;
323                       # Guess yes otherwise.
324        *)             gl_cv_func_mbrtowc_nul_retval="guessing yes" ;;
325      esac
326changequote([,])dnl
327      if test $LOCALE_ZH_CN != none; then
328        AC_TRY_RUN([
329#include <locale.h>
330#include <string.h>
331#include <wchar.h>
332int main ()
333{
334  /* This fails on Solaris 8 and 9.  */
335  if (setlocale (LC_ALL, "$LOCALE_ZH_CN") != NULL)
336    {
337      mbstate_t state;
338      wchar_t wc;
339
340      memset (&state, '\0', sizeof (mbstate_t));
341      if (mbrtowc (&wc, "", 1, &state) != 0)
342        return 1;
343    }
344  return 0;
345}],
346          [gl_cv_func_mbrtowc_nul_retval=yes],
347          [gl_cv_func_mbrtowc_nul_retval=no],
348          [:])
349      fi
350    ])
351])
352
353# Prerequisites of lib/mbrtowc.c.
354AC_DEFUN([gl_PREREQ_MBRTOWC], [
355  :
356])
357
358
359dnl From Paul Eggert
360
361dnl This override of an autoconf macro can be removed when autoconf 2.60 or
362dnl newer can be assumed everywhere.
363
364m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.60]),[-1],[
365AC_DEFUN([AC_FUNC_MBRTOWC],
366[
367  dnl Same as AC_FUNC_MBRTOWC in autoconf-2.60.
368  AC_CACHE_CHECK([whether mbrtowc and mbstate_t are properly declared],
369    gl_cv_func_mbrtowc,
370    [AC_LINK_IFELSE(
371       [AC_LANG_PROGRAM(
372            [[#include <wchar.h>]],
373            [[wchar_t wc;
374              char const s[] = "";
375              size_t n = 1;
376              mbstate_t state;
377              return ! (sizeof state && (mbrtowc) (&wc, s, n, &state));]])],
378       gl_cv_func_mbrtowc=yes,
379       gl_cv_func_mbrtowc=no)])
380  if test $gl_cv_func_mbrtowc = yes; then
381    AC_DEFINE([HAVE_MBRTOWC], [1],
382      [Define to 1 if mbrtowc and mbstate_t are properly declared.])
383  fi
384])
385])
386