Work around iconv_open problem on Solaris.
[gnulib.git] / m4 / iconv_open.m4
1 # iconv_open.m4 serial 6
2 dnl Copyright (C) 2007-2009 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_ICONV_OPEN],
8 [
9   AC_REQUIRE([AM_ICONV])
10   AC_REQUIRE([AC_CANONICAL_HOST])
11   AC_REQUIRE([gl_ICONV_H_DEFAULTS])
12   if test "$am_cv_func_iconv" = yes; then
13     dnl Test whether iconv_open accepts standardized encoding names.
14     dnl We know that GNU libiconv and GNU libc do.
15     AC_EGREP_CPP([gnu_iconv], [
16       #include <iconv.h>
17       #if defined _LIBICONV_VERSION || defined __GLIBC__
18        gnu_iconv
19       #endif
20       ], [gl_func_iconv_gnu=yes], [gl_func_iconv_gnu=no])
21     if test $gl_func_iconv_gnu = no; then
22       iconv_flavor=
23       case "$host_os" in
24         aix*)     iconv_flavor=ICONV_FLAVOR_AIX ;;
25         irix*)    iconv_flavor=ICONV_FLAVOR_IRIX ;;
26         hpux*)    iconv_flavor=ICONV_FLAVOR_HPUX ;;
27         osf*)     iconv_flavor=ICONV_FLAVOR_OSF ;;
28         solaris*) iconv_flavor=ICONV_FLAVOR_SOLARIS ;;
29       esac
30       if test -n "$iconv_flavor"; then
31         AC_DEFINE_UNQUOTED([ICONV_FLAVOR], [$iconv_flavor],
32           [Define to a symbolic name denoting the flavor of iconv_open()
33            implementation.])
34         gl_REPLACE_ICONV_OPEN
35       fi
36     fi
37   fi
38 ])
39
40 AC_DEFUN([gl_REPLACE_ICONV_OPEN],
41 [
42   gl_REPLACE_ICONV_H
43   REPLACE_ICONV_OPEN=1
44   AC_LIBOBJ([iconv_open])
45 ])
46
47 AC_DEFUN([gl_FUNC_ICONV_OPEN_UTF],
48 [
49   AC_REQUIRE([gl_FUNC_ICONV_OPEN])
50   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
51   AC_REQUIRE([gl_ICONV_H_DEFAULTS])
52   if test "$am_cv_func_iconv" = yes; then
53     if test -n "$am_cv_proto_iconv_arg1"; then
54       ICONV_CONST="const"
55     else
56       ICONV_CONST=
57     fi
58     AC_SUBST([ICONV_CONST])
59     AC_CACHE_CHECK([whether iconv supports conversion between UTF-8 and UTF-{16,32}{BE,LE}],
60       [gl_cv_func_iconv_supports_utf],
61       [
62         save_LIBS="$LIBS"
63         LIBS="$LIBS $LIBICONV"
64         AC_TRY_RUN([
65 #include <iconv.h>
66 #include <errno.h>
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #define ASSERT(expr) if (!(expr)) return 1;
71 int main ()
72 {
73   /* Test conversion from UTF-8 to UTF-16BE with no errors.  */
74   {
75     static const char input[] =
76       "Japanese (\346\227\245\346\234\254\350\252\236) [\360\235\224\215\360\235\224\236\360\235\224\255]";
77     static const char expected[] =
78       "\000J\000a\000p\000a\000n\000e\000s\000e\000 \000(\145\345\147\054\212\236\000)\000 \000[\330\065\335\015\330\065\335\036\330\065\335\055\000]";
79     iconv_t cd;
80     char buf[100];
81     const char *inptr;
82     size_t inbytesleft;
83     char *outptr;
84     size_t outbytesleft;
85     size_t res;
86     cd = iconv_open ("UTF-16BE", "UTF-8");
87     ASSERT (cd != (iconv_t)(-1));
88     inptr = input;
89     inbytesleft = sizeof (input) - 1;
90     outptr = buf;
91     outbytesleft = sizeof (buf);
92     res = iconv (cd,
93                  (ICONV_CONST char **) &inptr, &inbytesleft,
94                  &outptr, &outbytesleft);
95     ASSERT (res == 0 && inbytesleft == 0);
96     ASSERT (outptr == buf + (sizeof (expected) - 1));
97     ASSERT (memcmp (buf, expected, sizeof (expected) - 1) == 0);
98     ASSERT (iconv_close (cd) == 0);
99   }
100   /* Test conversion from UTF-8 to UTF-16LE with no errors.  */
101   {
102     static const char input[] =
103       "Japanese (\346\227\245\346\234\254\350\252\236) [\360\235\224\215\360\235\224\236\360\235\224\255]";
104     static const char expected[] =
105       "J\000a\000p\000a\000n\000e\000s\000e\000 \000(\000\345\145\054\147\236\212)\000 \000[\000\065\330\015\335\065\330\036\335\065\330\055\335]\000";
106     iconv_t cd;
107     char buf[100];
108     const char *inptr;
109     size_t inbytesleft;
110     char *outptr;
111     size_t outbytesleft;
112     size_t res;
113     cd = iconv_open ("UTF-16LE", "UTF-8");
114     ASSERT (cd != (iconv_t)(-1));
115     inptr = input;
116     inbytesleft = sizeof (input) - 1;
117     outptr = buf;
118     outbytesleft = sizeof (buf);
119     res = iconv (cd,
120                  (ICONV_CONST char **) &inptr, &inbytesleft,
121                  &outptr, &outbytesleft);
122     ASSERT (res == 0 && inbytesleft == 0);
123     ASSERT (outptr == buf + (sizeof (expected) - 1));
124     ASSERT (memcmp (buf, expected, sizeof (expected) - 1) == 0);
125     ASSERT (iconv_close (cd) == 0);
126   }
127   /* Test conversion from UTF-8 to UTF-32BE with no errors.  */
128   {
129     static const char input[] =
130       "Japanese (\346\227\245\346\234\254\350\252\236) [\360\235\224\215\360\235\224\236\360\235\224\255]";
131     static const char expected[] =
132       "\000\000\000J\000\000\000a\000\000\000p\000\000\000a\000\000\000n\000\000\000e\000\000\000s\000\000\000e\000\000\000 \000\000\000(\000\000\145\345\000\000\147\054\000\000\212\236\000\000\000)\000\000\000 \000\000\000[\000\001\325\015\000\001\325\036\000\001\325\055\000\000\000]";
133     iconv_t cd;
134     char buf[100];
135     const char *inptr;
136     size_t inbytesleft;
137     char *outptr;
138     size_t outbytesleft;
139     size_t res;
140     cd = iconv_open ("UTF-32BE", "UTF-8");
141     ASSERT (cd != (iconv_t)(-1));
142     inptr = input;
143     inbytesleft = sizeof (input) - 1;
144     outptr = buf;
145     outbytesleft = sizeof (buf);
146     res = iconv (cd,
147                  (ICONV_CONST char **) &inptr, &inbytesleft,
148                  &outptr, &outbytesleft);
149     ASSERT (res == 0 && inbytesleft == 0);
150     ASSERT (outptr == buf + (sizeof (expected) - 1));
151     ASSERT (memcmp (buf, expected, sizeof (expected) - 1) == 0);
152     ASSERT (iconv_close (cd) == 0);
153   }
154   /* Test conversion from UTF-8 to UTF-32LE with no errors.  */
155   {
156     static const char input[] =
157       "Japanese (\346\227\245\346\234\254\350\252\236) [\360\235\224\215\360\235\224\236\360\235\224\255]";
158     static const char expected[] =
159       "J\000\000\000a\000\000\000p\000\000\000a\000\000\000n\000\000\000e\000\000\000s\000\000\000e\000\000\000 \000\000\000(\000\000\000\345\145\000\000\054\147\000\000\236\212\000\000)\000\000\000 \000\000\000[\000\000\000\015\325\001\000\036\325\001\000\055\325\001\000]\000\000\000";
160     iconv_t cd;
161     char buf[100];
162     const char *inptr;
163     size_t inbytesleft;
164     char *outptr;
165     size_t outbytesleft;
166     size_t res;
167     cd = iconv_open ("UTF-32LE", "UTF-8");
168     ASSERT (cd != (iconv_t)(-1));
169     inptr = input;
170     inbytesleft = sizeof (input) - 1;
171     outptr = buf;
172     outbytesleft = sizeof (buf);
173     res = iconv (cd,
174                  (ICONV_CONST char **) &inptr, &inbytesleft,
175                  &outptr, &outbytesleft);
176     ASSERT (res == 0 && inbytesleft == 0);
177     ASSERT (outptr == buf + (sizeof (expected) - 1));
178     ASSERT (memcmp (buf, expected, sizeof (expected) - 1) == 0);
179     ASSERT (iconv_close (cd) == 0);
180   }
181   /* Test conversion from UTF-16BE to UTF-8 with no errors.
182      This test fails on NetBSD 3.0.  */
183   {
184     static const char input[] =
185       "\000J\000a\000p\000a\000n\000e\000s\000e\000 \000(\145\345\147\054\212\236\000)\000 \000[\330\065\335\015\330\065\335\036\330\065\335\055\000]";
186     static const char expected[] =
187       "Japanese (\346\227\245\346\234\254\350\252\236) [\360\235\224\215\360\235\224\236\360\235\224\255]";
188     iconv_t cd;
189     char buf[100];
190     const char *inptr;
191     size_t inbytesleft;
192     char *outptr;
193     size_t outbytesleft;
194     size_t res;
195     cd = iconv_open ("UTF-8", "UTF-16BE");
196     ASSERT (cd != (iconv_t)(-1));
197     inptr = input;
198     inbytesleft = sizeof (input) - 1;
199     outptr = buf;
200     outbytesleft = sizeof (buf);
201     res = iconv (cd,
202                  (ICONV_CONST char **) &inptr, &inbytesleft,
203                  &outptr, &outbytesleft);
204     ASSERT (res == 0 && inbytesleft == 0);
205     ASSERT (outptr == buf + (sizeof (expected) - 1));
206     ASSERT (memcmp (buf, expected, sizeof (expected) - 1) == 0);
207     ASSERT (iconv_close (cd) == 0);
208   }
209   return 0;
210 }], [gl_cv_func_iconv_supports_utf=yes], [gl_cv_func_iconv_supports_utf=no],
211           [
212            dnl We know that GNU libiconv, GNU libc, and Solaris >= 9 do.
213            dnl OSF/1 5.1 has these encodings, but inserts a BOM in the "to"
214            dnl direction.
215            gl_cv_func_iconv_supports_utf=no
216            if test $gl_func_iconv_gnu = yes; then
217              gl_cv_func_iconv_supports_utf=yes
218            else
219 changequote(,)dnl
220              case "$host_os" in
221                solaris2.9 | solaris2.1[0-9]) gl_cv_func_iconv_supports_utf=yes ;;
222              esac
223 changequote([,])dnl
224            fi
225           ])
226         LIBS="$save_LIBS"
227       ])
228     if test $gl_cv_func_iconv_supports_utf = no; then
229       REPLACE_ICONV_UTF=1
230       AC_DEFINE([REPLACE_ICONV_UTF], [1],
231         [Define if the iconv() functions are enhanced to handle the UTF-{16,32}{BE,LE} encodings.])
232       REPLACE_ICONV=1
233       gl_REPLACE_ICONV_OPEN
234       AC_LIBOBJ([iconv])
235       AC_LIBOBJ([iconv_close])
236     fi
237   fi
238 ])