immutable: Add tests.
[gnulib.git] / m4 / mbrtoc32.m4
blob56f09c6d269df126e80ddbae0c2fac2677878270
1 # mbrtoc32.m4 serial 6
2 dnl Copyright (C) 2014-2021 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.
7 AC_DEFUN([gl_FUNC_MBRTOC32],
9   AC_REQUIRE([gl_UCHAR_H_DEFAULTS])
11   AC_REQUIRE([AC_TYPE_MBSTATE_T])
12   gl_MBSTATE_T_BROKEN
14   AC_REQUIRE([gl_TYPE_CHAR32_T])
15   AC_REQUIRE([gl_MBRTOC32_SANITYCHECK])
17   AC_REQUIRE([gl_CHECK_FUNC_MBRTOC32])
18   if test $gl_cv_func_mbrtoc32 = no; then
19     HAVE_MBRTOC32=0
20   else
21     if test $GNULIB_OVERRIDES_CHAR32_T = 1 || test $REPLACE_MBSTATE_T = 1; then
22       REPLACE_MBRTOC32=1
23     else
24       gl_MBRTOC32_EMPTY_INPUT
25       gl_MBRTOC32_C_LOCALE
26       case "$gl_cv_func_mbrtoc32_empty_input" in
27         *yes) ;;
28         *) AC_DEFINE([MBRTOC32_EMPTY_INPUT_BUG], [1],
29              [Define if the mbrtoc32 function does not return (size_t) -2 for empty input.])
30            REPLACE_MBRTOC32=1
31            ;;
32       esac
33       case "$gl_cv_func_mbrtoc32_C_locale_sans_EILSEQ" in
34         *yes) ;;
35         *) AC_DEFINE([MBRTOC32_IN_C_LOCALE_MAYBE_EILSEQ], [1],
36              [Define if the mbrtoc32 function may signal encoding errors in the C locale.])
37            REPLACE_MBRTOC32=1
38            ;;
39       esac
40     fi
41     if test $HAVE_WORKING_MBRTOC32 = 0; then
42       REPLACE_MBRTOC32=1
43     fi
44   fi
47 dnl We can't use AC_CHECK_FUNC here, because mbrtoc32() is defined as a
48 dnl static inline function on Haiku 2020.
49 AC_DEFUN([gl_CHECK_FUNC_MBRTOC32],
51   AC_CACHE_CHECK([for mbrtoc32], [gl_cv_func_mbrtoc32],
52     [AC_LINK_IFELSE(
53        [AC_LANG_PROGRAM(
54           [[#include <stdlib.h>
55             #include <uchar.h>
56           ]],
57           [[char32_t c;
58             return mbrtoc32 (&c, "", 1, NULL) == 0;
59           ]])
60        ],
61        [gl_cv_func_mbrtoc32=yes],
62        [gl_cv_func_mbrtoc32=no])
63     ])
66 AC_DEFUN([gl_MBRTOC32_EMPTY_INPUT],
68   AC_REQUIRE([AC_PROG_CC])
69   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
70   AC_CACHE_CHECK([whether mbrtoc32 works on empty input],
71     [gl_cv_func_mbrtoc32_empty_input],
72     [
73       dnl Initial guess, used when cross-compiling or when no suitable locale
74       dnl is present.
75 changequote(,)dnl
76       case "$host_os" in
77                        # Guess no on glibc systems.
78         *-gnu* | gnu*) gl_cv_func_mbrtoc32_empty_input="guessing no" ;;
79         *)             gl_cv_func_mbrtoc32_empty_input="guessing yes" ;;
80       esac
81 changequote([,])dnl
82       AC_RUN_IFELSE(
83         [AC_LANG_SOURCE([[
84            #include <uchar.h>
85            static char32_t wc;
86            static mbstate_t mbs;
87            int
88            main (void)
89            {
90              return mbrtoc32 (&wc, "", 0, &mbs) != (size_t) -2;
91            }]])],
92         [gl_cv_func_mbrtoc32_empty_input=yes],
93         [gl_cv_func_mbrtoc32_empty_input=no],
94         [:])
95     ])
98 AC_DEFUN([gl_MBRTOC32_C_LOCALE],
100   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
101   AC_CACHE_CHECK([whether the C locale is free of encoding errors],
102     [gl_cv_func_mbrtoc32_C_locale_sans_EILSEQ],
103     [
104      dnl Initial guess, used when cross-compiling or when no suitable locale
105      dnl is present.
106      gl_cv_func_mbrtoc32_C_locale_sans_EILSEQ="$gl_cross_guess_normal"
108      AC_RUN_IFELSE(
109        [AC_LANG_PROGRAM(
110           [[#include <limits.h>
111             #include <locale.h>
112             #include <uchar.h>
113           ]], [[
114             int i;
115             char *locale = setlocale (LC_ALL, "C");
116             if (! locale)
117               return 2;
118             for (i = CHAR_MIN; i <= CHAR_MAX; i++)
119               {
120                 char c = i;
121                 char32_t wc;
122                 mbstate_t mbs = { 0, };
123                 size_t ss = mbrtoc32 (&wc, &c, 1, &mbs);
124                 if (1 < ss)
125                   return 3;
126               }
127             return 0;
128           ]])],
129       [gl_cv_func_mbrtoc32_C_locale_sans_EILSEQ=yes],
130       [gl_cv_func_mbrtoc32_C_locale_sans_EILSEQ=no],
131       [case "$host_os" in
132                  # Guess yes on native Windows.
133          mingw*) gl_cv_func_mbrtoc32_C_locale_sans_EILSEQ="guessing yes" ;;
134        esac
135       ])
136     ])
139 dnl Test whether mbrtoc32 works not worse than mbrtowc.
140 dnl Result is HAVE_WORKING_MBRTOC32.
142 AC_DEFUN([gl_MBRTOC32_SANITYCHECK],
144   AC_REQUIRE([AC_PROG_CC])
145   AC_REQUIRE([gl_TYPE_CHAR32_T])
146   AC_REQUIRE([gl_CHECK_FUNC_MBRTOC32])
147   AC_REQUIRE([gt_LOCALE_FR])
148   AC_REQUIRE([gt_LOCALE_ZH_CN])
149   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
150   if test $GNULIB_OVERRIDES_CHAR32_T = 1 || test $gl_cv_func_mbrtoc32 = no; then
151     HAVE_WORKING_MBRTOC32=0
152   else
153     AC_CACHE_CHECK([whether mbrtoc32 works as well as mbrtowc],
154       [gl_cv_func_mbrtoc32_sanitycheck],
155       [
156         dnl Initial guess, used when cross-compiling or when no suitable locale
157         dnl is present.
158 changequote(,)dnl
159         case "$host_os" in
160           # Guess no on FreeBSD, Solaris, native Windows.
161           freebsd* | solaris* | mingw*)
162             gl_cv_func_mbrtoc32_sanitycheck="guessing no"
163             ;;
164           # Guess yes otherwise.
165           *)
166             gl_cv_func_mbrtoc32_sanitycheck="guessing yes"
167             ;;
168         esac
169 changequote([,])dnl
170         if test $LOCALE_FR != none || test $LOCALE_ZH_CN != none; then
171           AC_RUN_IFELSE(
172             [AC_LANG_SOURCE([[
173 #include <locale.h>
174 #include <stdlib.h>
175 #include <string.h>
176 #include <wchar.h>
177 #include <uchar.h>
178 int main ()
180   int result = 0;
181   /* This fails on native Windows:
182      mbrtoc32 returns (size_t)-1.
183      mbrtowc returns 1 (correct).  */
184   if (setlocale (LC_ALL, "$LOCALE_FR") != NULL)
185     {
186       mbstate_t state;
187       wchar_t wc = (wchar_t) 0xBADFACE;
188       memset (&state, '\0', sizeof (mbstate_t));
189       if (mbrtowc (&wc, "\374", 1, &state) == 1)
190         {
191           char32_t c32 = (wchar_t) 0xBADFACE;
192           memset (&state, '\0', sizeof (mbstate_t));
193           if (mbrtoc32 (&c32, "\374", 1, &state) != 1)
194             result |= 1;
195         }
196     }
197   /* This fails on FreeBSD 12 and Solaris 11.4:
198      mbrtoc32 returns (size_t)-2 or (size_t)-1.
199      mbrtowc returns 4 (correct).  */
200   if (setlocale (LC_ALL, "$LOCALE_ZH_CN") != NULL)
201     {
202       mbstate_t state;
203       wchar_t wc = (wchar_t) 0xBADFACE;
204       memset (&state, '\0', sizeof (mbstate_t));
205       if (mbrtowc (&wc, "\224\071\375\067", 4, &state) == 4)
206         {
207           char32_t c32 = (wchar_t) 0xBADFACE;
208           memset (&state, '\0', sizeof (mbstate_t));
209           if (mbrtoc32 (&c32, "\224\071\375\067", 4, &state) != 4)
210             result |= 2;
211         }
212     }
213   return result;
214 }]])],
215             [gl_cv_func_mbrtoc32_sanitycheck=yes],
216             [gl_cv_func_mbrtoc32_sanitycheck=no],
217             [:])
218         fi
219       ])
220     case "$gl_cv_func_mbrtoc32_sanitycheck" in
221       *yes)
222         HAVE_WORKING_MBRTOC32=1
223         AC_DEFINE([HAVE_WORKING_MBRTOC32], [1],
224           [Define if the mbrtoc32 function basically works.])
225         ;;
226       *) HAVE_WORKING_MBRTOC32=0 ;;
227     esac
228   fi
229   AC_SUBST([HAVE_WORKING_MBRTOC32])
232 # Prerequisites of lib/mbrtoc32.c and lib/lc-charset-dispatch.c.
233 AC_DEFUN([gl_PREREQ_MBRTOC32], [
234   :