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