xref: /freebsd/tools/test/iconv/gnu/gnu.c (revision 1d386b48a555f61cb7325543adbbb5c3f3407a66)
1ad30f8e7SGabor Kovesdan /*-
2ad30f8e7SGabor Kovesdan  * Copyright (C) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
3ad30f8e7SGabor Kovesdan  * All rights reserved.
4ad30f8e7SGabor Kovesdan  *
5ad30f8e7SGabor Kovesdan  * Redistribution and use in source and binary forms, with or without
6ad30f8e7SGabor Kovesdan  * modification, are permitted provided that the following conditions
7ad30f8e7SGabor Kovesdan  * are met:
8ad30f8e7SGabor Kovesdan  * 1. Redistributions of source code must retain the above copyright
9ad30f8e7SGabor Kovesdan  *    notice, this list of conditions and the following disclaimer.
10ad30f8e7SGabor Kovesdan  * 2. Redistributions in binary form must reproduce the above copyright
11ad30f8e7SGabor Kovesdan  *    notice, this list of conditions and the following disclaimer in the
12ad30f8e7SGabor Kovesdan  *    documentation and/or other materials provided with the distribution.
13ad30f8e7SGabor Kovesdan  *
14ad30f8e7SGabor Kovesdan  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15ad30f8e7SGabor Kovesdan  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16ad30f8e7SGabor Kovesdan  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17ad30f8e7SGabor Kovesdan  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18ad30f8e7SGabor Kovesdan  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19ad30f8e7SGabor Kovesdan  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20ad30f8e7SGabor Kovesdan  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21ad30f8e7SGabor Kovesdan  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22ad30f8e7SGabor Kovesdan  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23ad30f8e7SGabor Kovesdan  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24ad30f8e7SGabor Kovesdan  * SUCH DAMAGE.
25ad30f8e7SGabor Kovesdan  */
26ad30f8e7SGabor Kovesdan 
27ad30f8e7SGabor Kovesdan #include <sys/cdefs.h>
28ad30f8e7SGabor Kovesdan #include <sys/endian.h>
29ad30f8e7SGabor Kovesdan #include <sys/types.h>
30ad30f8e7SGabor Kovesdan 
31ad30f8e7SGabor Kovesdan #include <err.h>
32ad30f8e7SGabor Kovesdan #include <errno.h>
33ad30f8e7SGabor Kovesdan #include <iconv.h>
34ad30f8e7SGabor Kovesdan #include <stdbool.h>
35ad30f8e7SGabor Kovesdan #include <stdio.h>
36ad30f8e7SGabor Kovesdan #include <stdlib.h>
37ad30f8e7SGabor Kovesdan #include <string.h>
38ad30f8e7SGabor Kovesdan 
39ad30f8e7SGabor Kovesdan static bool uc_hook = false;
40ad30f8e7SGabor Kovesdan static bool wc_hook = false;
41ad30f8e7SGabor Kovesdan static bool mb_uc_fb = false;
42ad30f8e7SGabor Kovesdan 
43ad30f8e7SGabor Kovesdan void	 unicode_hook(unsigned int mbr, void *data);
44ad30f8e7SGabor Kovesdan void	 wchar_hook(wchar_t wc, void *data);
45ad30f8e7SGabor Kovesdan 
46ad30f8e7SGabor Kovesdan void    mb_to_uc_fb(const char *, size_t,
47ad30f8e7SGabor Kovesdan             void (*write_replacement) (const unsigned int *, size_t, void *),
48ad30f8e7SGabor Kovesdan             void *, void *);
49ad30f8e7SGabor Kovesdan 
50ad30f8e7SGabor Kovesdan static int
ctl_get_translit1(void)51ad30f8e7SGabor Kovesdan ctl_get_translit1(void)
52ad30f8e7SGabor Kovesdan {
53ad30f8e7SGabor Kovesdan 	iconv_t cd;
54ad30f8e7SGabor Kovesdan 	int arg, ret;
55ad30f8e7SGabor Kovesdan 
56ad30f8e7SGabor Kovesdan 	cd = iconv_open("ASCII//TRANSLIT", "UTF-8");
57ad30f8e7SGabor Kovesdan 	if (cd == (iconv_t)-1)
58ad30f8e7SGabor Kovesdan 		return (-1);
59ad30f8e7SGabor Kovesdan 	if (iconvctl(cd, ICONV_GET_TRANSLITERATE, &arg) == 0)
60ad30f8e7SGabor Kovesdan 		ret = (arg == 1) ? 0 : -1;
61ad30f8e7SGabor Kovesdan 	else
62ad30f8e7SGabor Kovesdan 		ret = -1;
63ad30f8e7SGabor Kovesdan 	if (iconv_close(cd) == -1)
64ad30f8e7SGabor Kovesdan 		return (-1);
65ad30f8e7SGabor Kovesdan 	return (ret);
66ad30f8e7SGabor Kovesdan }
67ad30f8e7SGabor Kovesdan 
68ad30f8e7SGabor Kovesdan static int
ctl_get_translit2(void)69ad30f8e7SGabor Kovesdan ctl_get_translit2(void)
70ad30f8e7SGabor Kovesdan {
71ad30f8e7SGabor Kovesdan 	iconv_t cd;
72ad30f8e7SGabor Kovesdan 	int arg, ret;
73ad30f8e7SGabor Kovesdan 
74ad30f8e7SGabor Kovesdan 	cd = iconv_open("ASCII", "UTF-8");
75ad30f8e7SGabor Kovesdan 	if (cd == (iconv_t)-1)
76ad30f8e7SGabor Kovesdan 		return (-1);
77ad30f8e7SGabor Kovesdan 	if (iconvctl(cd, ICONV_GET_TRANSLITERATE, &arg) == 0)
78ad30f8e7SGabor Kovesdan 		ret = (arg == 0) ? 0 : -1;
79ad30f8e7SGabor Kovesdan 	else
80ad30f8e7SGabor Kovesdan 		ret = -1;
81ad30f8e7SGabor Kovesdan 	if (iconv_close(cd) == -1)
82ad30f8e7SGabor Kovesdan 		return (-1);
83ad30f8e7SGabor Kovesdan 	return (ret);
84ad30f8e7SGabor Kovesdan }
85ad30f8e7SGabor Kovesdan 
86ad30f8e7SGabor Kovesdan static int
ctl_set_translit1(void)87ad30f8e7SGabor Kovesdan ctl_set_translit1(void)
88ad30f8e7SGabor Kovesdan {
89ad30f8e7SGabor Kovesdan 	iconv_t cd;
90ad30f8e7SGabor Kovesdan 	int arg = 1, ret;
91ad30f8e7SGabor Kovesdan 
92ad30f8e7SGabor Kovesdan 	cd = iconv_open("ASCII", "UTF-8");
93ad30f8e7SGabor Kovesdan 	if (cd == (iconv_t)-1)
94ad30f8e7SGabor Kovesdan 		return (-1);
95ad30f8e7SGabor Kovesdan 	ret = iconvctl(cd, ICONV_SET_TRANSLITERATE, &arg) == 0 ? 0 : -1;
96ad30f8e7SGabor Kovesdan 	if (iconv_close(cd) == -1)
97ad30f8e7SGabor Kovesdan 		return (-1);
98ad30f8e7SGabor Kovesdan 	return (ret);
99ad30f8e7SGabor Kovesdan }
100ad30f8e7SGabor Kovesdan 
101ad30f8e7SGabor Kovesdan static int
ctl_set_translit2(void)102ad30f8e7SGabor Kovesdan ctl_set_translit2(void)
103ad30f8e7SGabor Kovesdan {
104ad30f8e7SGabor Kovesdan 	iconv_t cd;
105ad30f8e7SGabor Kovesdan 	int arg = 0, ret;
106ad30f8e7SGabor Kovesdan 
107ad30f8e7SGabor Kovesdan 	cd = iconv_open("ASCII//TRANSLIT", "UTF-8");
108ad30f8e7SGabor Kovesdan 	if (cd == (iconv_t)-1)
109ad30f8e7SGabor Kovesdan 		return (-1);
110ad30f8e7SGabor Kovesdan 	ret = iconvctl(cd, ICONV_SET_TRANSLITERATE, &arg) == 0 ? 0 : -1;
111ad30f8e7SGabor Kovesdan 	if (iconv_close(cd) == -1)
112ad30f8e7SGabor Kovesdan 		return (-1);
113ad30f8e7SGabor Kovesdan 	return (ret);
114ad30f8e7SGabor Kovesdan }
115ad30f8e7SGabor Kovesdan 
116ad30f8e7SGabor Kovesdan static int
ctl_get_discard_ilseq1(void)117ad30f8e7SGabor Kovesdan ctl_get_discard_ilseq1(void)
118ad30f8e7SGabor Kovesdan {
119ad30f8e7SGabor Kovesdan 	iconv_t cd;
120ad30f8e7SGabor Kovesdan         int arg, ret;
121ad30f8e7SGabor Kovesdan 
122ad30f8e7SGabor Kovesdan 	cd = iconv_open("ASCII", "UTF-8");
123ad30f8e7SGabor Kovesdan 	if (cd == (iconv_t)-1)
124ad30f8e7SGabor Kovesdan 		return (-1);
125ad30f8e7SGabor Kovesdan 	if (iconvctl(cd, ICONV_GET_DISCARD_ILSEQ, &arg) == 0)
126ad30f8e7SGabor Kovesdan 		ret = arg == 0 ? 0 : -1;
127ad30f8e7SGabor Kovesdan 	else
128ad30f8e7SGabor Kovesdan 		ret = -1;
129ad30f8e7SGabor Kovesdan 	if (iconv_close(cd) == -1)
130ad30f8e7SGabor Kovesdan 		return (-1);
131ad30f8e7SGabor Kovesdan 	return (ret);
132ad30f8e7SGabor Kovesdan }
133ad30f8e7SGabor Kovesdan 
134ad30f8e7SGabor Kovesdan static int
ctl_get_discard_ilseq2(void)135ad30f8e7SGabor Kovesdan ctl_get_discard_ilseq2(void)
136ad30f8e7SGabor Kovesdan {
137ad30f8e7SGabor Kovesdan 	iconv_t cd;
138ad30f8e7SGabor Kovesdan 	int arg, ret;
139ad30f8e7SGabor Kovesdan 
140ad30f8e7SGabor Kovesdan 	cd = iconv_open("ASCII//IGNORE", "UTF-8");
141ad30f8e7SGabor Kovesdan 	if (cd == (iconv_t)-1)
142ad30f8e7SGabor Kovesdan 		return (-1);
143ad30f8e7SGabor Kovesdan 	if (iconvctl(cd, ICONV_GET_DISCARD_ILSEQ, &arg) == 0)
144ad30f8e7SGabor Kovesdan 		ret = arg == 1 ? 0 : -1;
145ad30f8e7SGabor Kovesdan 	else
146ad30f8e7SGabor Kovesdan 		ret = -1;
147ad30f8e7SGabor Kovesdan 	if (iconv_close(cd) == -1)
148ad30f8e7SGabor Kovesdan 		return (-1);
149ad30f8e7SGabor Kovesdan 	return (ret);
150ad30f8e7SGabor Kovesdan }
151ad30f8e7SGabor Kovesdan 
152ad30f8e7SGabor Kovesdan static int
ctl_set_discard_ilseq1(void)153ad30f8e7SGabor Kovesdan ctl_set_discard_ilseq1(void)
154ad30f8e7SGabor Kovesdan {
155ad30f8e7SGabor Kovesdan 	iconv_t cd;
156ad30f8e7SGabor Kovesdan 	int arg = 1, ret;
157ad30f8e7SGabor Kovesdan 
158ad30f8e7SGabor Kovesdan 	cd = iconv_open("ASCII", "UTF-8");
159ad30f8e7SGabor Kovesdan 	if (cd == (iconv_t)-1)
160ad30f8e7SGabor Kovesdan 		return (-1);
161ad30f8e7SGabor Kovesdan 	ret = iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, &arg) == 0 ? 0 : -1;
162ad30f8e7SGabor Kovesdan 	if (iconv_close(cd) == -1)
163ad30f8e7SGabor Kovesdan 		return (-1);
164ad30f8e7SGabor Kovesdan 	return (ret);
165ad30f8e7SGabor Kovesdan }
166ad30f8e7SGabor Kovesdan 
167ad30f8e7SGabor Kovesdan static int
ctl_set_discard_ilseq2(void)168ad30f8e7SGabor Kovesdan ctl_set_discard_ilseq2(void)
169ad30f8e7SGabor Kovesdan {
170ad30f8e7SGabor Kovesdan 	iconv_t cd;
171ad30f8e7SGabor Kovesdan         int arg = 0, ret;
172ad30f8e7SGabor Kovesdan 
173ad30f8e7SGabor Kovesdan 	cd = iconv_open("ASCII//IGNORE", "UTF-8");
174ad30f8e7SGabor Kovesdan 	if (cd == (iconv_t)-1)
175ad30f8e7SGabor Kovesdan 	return (-1);
176ad30f8e7SGabor Kovesdan 	ret = iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, &arg) == 0 ? 0 : -1;
177ad30f8e7SGabor Kovesdan 	if (iconv_close(cd) == -1)
178ad30f8e7SGabor Kovesdan 		return (-1);
179ad30f8e7SGabor Kovesdan 	return (ret);
180ad30f8e7SGabor Kovesdan }
181ad30f8e7SGabor Kovesdan 
182ad30f8e7SGabor Kovesdan static int
ctl_trivialp1(void)183ad30f8e7SGabor Kovesdan ctl_trivialp1(void)
184ad30f8e7SGabor Kovesdan {
185ad30f8e7SGabor Kovesdan 	iconv_t cd;
186ad30f8e7SGabor Kovesdan         int arg, ret;
187ad30f8e7SGabor Kovesdan 
188ad30f8e7SGabor Kovesdan 	cd = iconv_open("latin2", "latin2");
189ad30f8e7SGabor Kovesdan 	if (cd == (iconv_t)-1)
190ad30f8e7SGabor Kovesdan 		return (-1);
191ad30f8e7SGabor Kovesdan 	if (iconvctl(cd, ICONV_TRIVIALP, &arg) == 0) {
192ad30f8e7SGabor Kovesdan 		ret = (arg == 1) ? 0 : -1;
193ad30f8e7SGabor Kovesdan         } else
194ad30f8e7SGabor Kovesdan                 ret = -1;
195ad30f8e7SGabor Kovesdan 	if (iconv_close(cd) == -1)
196ad30f8e7SGabor Kovesdan 		return (-1);
197ad30f8e7SGabor Kovesdan 	return (ret);
198ad30f8e7SGabor Kovesdan }
199ad30f8e7SGabor Kovesdan 
200ad30f8e7SGabor Kovesdan static int
ctl_trivialp2(void)201ad30f8e7SGabor Kovesdan ctl_trivialp2(void)
202ad30f8e7SGabor Kovesdan {
203ad30f8e7SGabor Kovesdan 	iconv_t cd;
204ad30f8e7SGabor Kovesdan 	int arg, ret;
205ad30f8e7SGabor Kovesdan 
206ad30f8e7SGabor Kovesdan 	cd = iconv_open("ASCII", "KOI8-R");
207ad30f8e7SGabor Kovesdan 	if (cd == (iconv_t)-1)
208ad30f8e7SGabor Kovesdan 		return (-1);
209ad30f8e7SGabor Kovesdan 	if (iconvctl(cd, ICONV_TRIVIALP, &arg) == 0) {
210ad30f8e7SGabor Kovesdan 		ret = (arg == 0) ? 0 : -1;
211ad30f8e7SGabor Kovesdan 	} else
212ad30f8e7SGabor Kovesdan 		ret = -1;
213ad30f8e7SGabor Kovesdan 	if (iconv_close(cd) == -1)
214ad30f8e7SGabor Kovesdan 		return (-1);
215ad30f8e7SGabor Kovesdan 	return (ret);
216ad30f8e7SGabor Kovesdan }
217ad30f8e7SGabor Kovesdan 
218ad30f8e7SGabor Kovesdan void
unicode_hook(unsigned int mbr,void * data)219ad30f8e7SGabor Kovesdan unicode_hook(unsigned int mbr, void *data)
220ad30f8e7SGabor Kovesdan {
221ad30f8e7SGabor Kovesdan 
222ad30f8e7SGabor Kovesdan #ifdef VERBOSE
223ad30f8e7SGabor Kovesdan 	printf("Unicode hook: %u\n", mbr);
224ad30f8e7SGabor Kovesdan #endif
225ad30f8e7SGabor Kovesdan 	uc_hook = true;
226ad30f8e7SGabor Kovesdan }
227ad30f8e7SGabor Kovesdan 
228ad30f8e7SGabor Kovesdan void
wchar_hook(wchar_t wc,void * data)229ad30f8e7SGabor Kovesdan wchar_hook(wchar_t wc, void *data)
230ad30f8e7SGabor Kovesdan {
231ad30f8e7SGabor Kovesdan 
232ad30f8e7SGabor Kovesdan #ifdef VERBOSE
233ad30f8e7SGabor Kovesdan 	printf("Wchar hook: %ull\n", wc);
234ad30f8e7SGabor Kovesdan #endif
235ad30f8e7SGabor Kovesdan 	wc_hook = true;
236ad30f8e7SGabor Kovesdan }
237ad30f8e7SGabor Kovesdan 
238ad30f8e7SGabor Kovesdan static int
ctl_uc_hook(void)239ad30f8e7SGabor Kovesdan ctl_uc_hook(void)
240ad30f8e7SGabor Kovesdan {
241ad30f8e7SGabor Kovesdan 	struct iconv_hooks hooks;
242ad30f8e7SGabor Kovesdan 	iconv_t cd;
243ad30f8e7SGabor Kovesdan 	size_t inbytesleft = 15, outbytesleft = 40;
244*efe014e6SEdward Tomasz Napierala 	char **inptr;
245*efe014e6SEdward Tomasz Napierala 	char *s = "Hello World!";
246ad30f8e7SGabor Kovesdan 	char **outptr;
247ad30f8e7SGabor Kovesdan 	char *outbuf;
248ad30f8e7SGabor Kovesdan 
249ad30f8e7SGabor Kovesdan 	inptr = &s;
250ad30f8e7SGabor Kovesdan 	hooks.uc_hook = unicode_hook;
251ad30f8e7SGabor Kovesdan 	hooks.wc_hook = NULL;
252ad30f8e7SGabor Kovesdan 
253ad30f8e7SGabor Kovesdan 	outbuf = malloc(40);
254ad30f8e7SGabor Kovesdan 	outptr = &outbuf;
255ad30f8e7SGabor Kovesdan 
256ad30f8e7SGabor Kovesdan 	cd = iconv_open("UTF-8", "ASCII");
257ad30f8e7SGabor Kovesdan 	if (cd == (iconv_t)-1)
258ad30f8e7SGabor Kovesdan 		return (-1);
259ad30f8e7SGabor Kovesdan 	if (iconvctl(cd, ICONV_SET_HOOKS, (void *)&hooks) != 0)
260ad30f8e7SGabor Kovesdan 		return (-1);
261ad30f8e7SGabor Kovesdan 	if (iconv(cd, inptr, &inbytesleft, outptr, &outbytesleft) == (size_t)-1)
262ad30f8e7SGabor Kovesdan 		return (-1);
263ad30f8e7SGabor Kovesdan 	if (iconv_close(cd) == -1)
264ad30f8e7SGabor Kovesdan 		return (-1);
265ad30f8e7SGabor Kovesdan 	return (uc_hook ? 0 : 1);
266ad30f8e7SGabor Kovesdan }
267ad30f8e7SGabor Kovesdan 
268ad30f8e7SGabor Kovesdan static int
ctl_wc_hook(void)269ad30f8e7SGabor Kovesdan ctl_wc_hook(void)
270ad30f8e7SGabor Kovesdan {
271ad30f8e7SGabor Kovesdan 	struct iconv_hooks hooks;
272ad30f8e7SGabor Kovesdan 	iconv_t cd;
273ad30f8e7SGabor Kovesdan 	size_t inbytesleft, outbytesleft = 40;
274*efe014e6SEdward Tomasz Napierala 	char **inptr;
275*efe014e6SEdward Tomasz Napierala 	char *s = "Hello World!";
276ad30f8e7SGabor Kovesdan 	char **outptr;
277ad30f8e7SGabor Kovesdan 	char *outbuf;
278ad30f8e7SGabor Kovesdan 
279ad30f8e7SGabor Kovesdan 	inptr = &s;
280ad30f8e7SGabor Kovesdan 	hooks.wc_hook = wchar_hook;
281ad30f8e7SGabor Kovesdan 	hooks.uc_hook = NULL;
282ad30f8e7SGabor Kovesdan 
283ad30f8e7SGabor Kovesdan 	outbuf = malloc(40);
284ad30f8e7SGabor Kovesdan 	outptr = &outbuf;
285ad30f8e7SGabor Kovesdan 	inbytesleft = sizeof(s);
286ad30f8e7SGabor Kovesdan 
287ad30f8e7SGabor Kovesdan 	cd = iconv_open("SHIFT_JIS", "ASCII");
288ad30f8e7SGabor Kovesdan 	if (cd == (iconv_t)-1)
289ad30f8e7SGabor Kovesdan 		return (-1);
290ad30f8e7SGabor Kovesdan 	if (iconvctl(cd, ICONV_SET_HOOKS, (void *)&hooks) != 0)
291ad30f8e7SGabor Kovesdan 		return (-1);
292ad30f8e7SGabor Kovesdan 	if (iconv(cd, inptr, &inbytesleft, outptr, &outbytesleft) == (size_t)-1)
293ad30f8e7SGabor Kovesdan 		return (-1);
294ad30f8e7SGabor Kovesdan 	if (iconv_close(cd) == -1)
295ad30f8e7SGabor Kovesdan 		return (-1);
296ad30f8e7SGabor Kovesdan 	return (wc_hook ? 0 : 1);
297ad30f8e7SGabor Kovesdan }
298ad30f8e7SGabor Kovesdan 
299ad30f8e7SGabor Kovesdan 
300ad30f8e7SGabor Kovesdan 
301ad30f8e7SGabor Kovesdan static int
gnu_canonicalize1(void)302ad30f8e7SGabor Kovesdan gnu_canonicalize1(void)
303ad30f8e7SGabor Kovesdan {
304ad30f8e7SGabor Kovesdan 
305ad30f8e7SGabor Kovesdan 	return (strcmp(iconv_canonicalize("latin2"), "ISO-8859-2"));
306ad30f8e7SGabor Kovesdan }
307ad30f8e7SGabor Kovesdan 
308ad30f8e7SGabor Kovesdan static int
gnu_canonicalize2(void)309ad30f8e7SGabor Kovesdan gnu_canonicalize2(void)
310ad30f8e7SGabor Kovesdan {
311ad30f8e7SGabor Kovesdan 
312ad30f8e7SGabor Kovesdan 	return (!strcmp(iconv_canonicalize("ASCII"), iconv_canonicalize("latin2")));
313ad30f8e7SGabor Kovesdan }
314ad30f8e7SGabor Kovesdan 
315ad30f8e7SGabor Kovesdan 
316ad30f8e7SGabor Kovesdan static int
iconvlist_cb(unsigned int count,const char * const * names,void * data)317ad30f8e7SGabor Kovesdan iconvlist_cb(unsigned int count, const char * const *names, void *data)
318ad30f8e7SGabor Kovesdan {
319ad30f8e7SGabor Kovesdan 
320ad30f8e7SGabor Kovesdan 	return (*(int *)data = ((names == NULL) && (count > 0)) ? -1 : 0);
321ad30f8e7SGabor Kovesdan }
322ad30f8e7SGabor Kovesdan 
323ad30f8e7SGabor Kovesdan static int
gnu_iconvlist(void)324ad30f8e7SGabor Kovesdan gnu_iconvlist(void)
325ad30f8e7SGabor Kovesdan {
326ad30f8e7SGabor Kovesdan 	int i;
327ad30f8e7SGabor Kovesdan 
328ad30f8e7SGabor Kovesdan 	iconvlist(iconvlist_cb, (void *)&i);
329ad30f8e7SGabor Kovesdan 	return (i);
330ad30f8e7SGabor Kovesdan }
331ad30f8e7SGabor Kovesdan 
332ad30f8e7SGabor Kovesdan void
mb_to_uc_fb(const char * inbuf,size_t inbufsize,void (* write_replacement)(const unsigned int * buf,size_t buflen,void * callback_arg),void * callback_arg,void * data)333ad30f8e7SGabor Kovesdan mb_to_uc_fb(const char* inbuf, size_t inbufsize,
334ad30f8e7SGabor Kovesdan     void (*write_replacement)(const unsigned int *buf, size_t buflen,
335ad30f8e7SGabor Kovesdan        void* callback_arg), void* callback_arg, void* data)
336ad30f8e7SGabor Kovesdan {
337ad30f8e7SGabor Kovesdan 	unsigned int c = 0x3F;
338ad30f8e7SGabor Kovesdan 
339ad30f8e7SGabor Kovesdan 	mb_uc_fb = true;
340ad30f8e7SGabor Kovesdan 	write_replacement((const unsigned int *)&c, 1, NULL);
341ad30f8e7SGabor Kovesdan }
342ad30f8e7SGabor Kovesdan 
343ad30f8e7SGabor Kovesdan static int __unused
ctl_mb_to_uc_fb(void)344ad30f8e7SGabor Kovesdan ctl_mb_to_uc_fb(void)
345ad30f8e7SGabor Kovesdan {
346ad30f8e7SGabor Kovesdan 	struct iconv_fallbacks fb;
347ad30f8e7SGabor Kovesdan 	iconv_t cd;
348ad30f8e7SGabor Kovesdan 	size_t inbytesleft, outbytesleft;
349ad30f8e7SGabor Kovesdan 	uint16_t inbuf[1] = { 0xF187 };
350ad30f8e7SGabor Kovesdan 	uint8_t outbuf[4] = { 0x00, 0x00, 0x00, 0x00 };
351*efe014e6SEdward Tomasz Napierala 	char *inptr;
352ad30f8e7SGabor Kovesdan 	char *outptr;
353ad30f8e7SGabor Kovesdan 	int ret;
354ad30f8e7SGabor Kovesdan 
355ad30f8e7SGabor Kovesdan 	if ((cd = iconv_open("UTF-32", "UTF-8")) == (iconv_t)-1)
356ad30f8e7SGabor Kovesdan 		return (1);
357ad30f8e7SGabor Kovesdan 
358ad30f8e7SGabor Kovesdan 	fb.uc_to_mb_fallback = NULL;
359ad30f8e7SGabor Kovesdan 	fb.mb_to_wc_fallback = NULL;
360ad30f8e7SGabor Kovesdan 	fb.wc_to_mb_fallback = NULL;
361ad30f8e7SGabor Kovesdan 	fb.mb_to_uc_fallback = mb_to_uc_fb;
362ad30f8e7SGabor Kovesdan 	fb.data = NULL;
363ad30f8e7SGabor Kovesdan 
364ad30f8e7SGabor Kovesdan 	if (iconvctl(cd, ICONV_SET_FALLBACKS, (void *)&fb) != 0)
365ad30f8e7SGabor Kovesdan 		return (1);
366ad30f8e7SGabor Kovesdan 
367*efe014e6SEdward Tomasz Napierala 	inptr = (char *)inbuf;
368ad30f8e7SGabor Kovesdan 	outptr = (char *)outbuf;
369ad30f8e7SGabor Kovesdan 	inbytesleft = 2;
370ad30f8e7SGabor Kovesdan 	outbytesleft = 4;
371ad30f8e7SGabor Kovesdan 
372ad30f8e7SGabor Kovesdan 	errno = 0;
373ad30f8e7SGabor Kovesdan 	ret = iconv(cd, &inptr, &inbytesleft, &outptr, &outbytesleft);
374ad30f8e7SGabor Kovesdan 
375ad30f8e7SGabor Kovesdan #ifdef VERBOSE
376ad30f8e7SGabor Kovesdan 	printf("mb_uc fallback: %c\n", outbuf[0]);
377ad30f8e7SGabor Kovesdan #endif
378ad30f8e7SGabor Kovesdan 
379ad30f8e7SGabor Kovesdan 	if (mb_uc_fb && (outbuf[0] == 0x3F))
380ad30f8e7SGabor Kovesdan 		return (0);
381ad30f8e7SGabor Kovesdan 	else
382ad30f8e7SGabor Kovesdan 		return (1);
383ad30f8e7SGabor Kovesdan }
384ad30f8e7SGabor Kovesdan 
385ad30f8e7SGabor Kovesdan static int
gnu_openinto(void)386ad30f8e7SGabor Kovesdan gnu_openinto(void)
387ad30f8e7SGabor Kovesdan {
388ad30f8e7SGabor Kovesdan 	iconv_allocation_t *myspace;
389ad30f8e7SGabor Kovesdan 	size_t inbytesleft, outbytesleft;
390*efe014e6SEdward Tomasz Napierala 	char *inptr;
391ad30f8e7SGabor Kovesdan 	char *inbuf = "works!", *outptr;
392ad30f8e7SGabor Kovesdan 	char outbuf[6];
393ad30f8e7SGabor Kovesdan 
394ad30f8e7SGabor Kovesdan 	if ((myspace = (iconv_allocation_t *)malloc(sizeof(iconv_allocation_t))) == NULL)
395ad30f8e7SGabor Kovesdan 		return (1);
396ad30f8e7SGabor Kovesdan 	if (iconv_open_into("ASCII", "ASCII", myspace) == -1)
397ad30f8e7SGabor Kovesdan 		return (1);
398ad30f8e7SGabor Kovesdan 
399*efe014e6SEdward Tomasz Napierala 	inptr = (char *)inbuf;
400ad30f8e7SGabor Kovesdan 	outptr = (char *)outbuf;
401ad30f8e7SGabor Kovesdan 	inbytesleft = 6;
402ad30f8e7SGabor Kovesdan 	outbytesleft = 6;
403ad30f8e7SGabor Kovesdan 
404ad30f8e7SGabor Kovesdan 	iconv((iconv_t)myspace, &inptr, &inbytesleft, &outptr, &outbytesleft);
405ad30f8e7SGabor Kovesdan 
406ad30f8e7SGabor Kovesdan 	return ((memcmp(inbuf, outbuf, 6) == 0)	? 0 : 1);
407ad30f8e7SGabor Kovesdan }
408ad30f8e7SGabor Kovesdan 
409ad30f8e7SGabor Kovesdan static void
test(int (tester)(void),const char * label)410ad30f8e7SGabor Kovesdan test(int (tester) (void), const char * label)
411ad30f8e7SGabor Kovesdan {
412ad30f8e7SGabor Kovesdan 	int ret;
413ad30f8e7SGabor Kovesdan 
414ad30f8e7SGabor Kovesdan 	if ((ret = tester()))
415ad30f8e7SGabor Kovesdan 		printf("%s failed (%d)\n", label, ret);
416ad30f8e7SGabor Kovesdan 	else
417ad30f8e7SGabor Kovesdan 		printf("%s succeeded\n", label);
418ad30f8e7SGabor Kovesdan }
419ad30f8e7SGabor Kovesdan 
420ad30f8e7SGabor Kovesdan int
main(void)421ad30f8e7SGabor Kovesdan main(void)
422ad30f8e7SGabor Kovesdan {
423ad30f8e7SGabor Kovesdan 	test(ctl_get_translit1, "ctl_get_translit1");
424ad30f8e7SGabor Kovesdan 	test(ctl_get_translit2, "ctl_get_translit2");
425ad30f8e7SGabor Kovesdan 	test(ctl_set_translit1, "ctl_set_translit1");
426ad30f8e7SGabor Kovesdan 	test(ctl_set_translit2, "ctl_set_translit2");
427ad30f8e7SGabor Kovesdan 	test(ctl_get_discard_ilseq1, "ctl_get_discard_ilseq1");
428ad30f8e7SGabor Kovesdan 	test(ctl_get_discard_ilseq2, "ctl_get_discard_ilseq2");
429ad30f8e7SGabor Kovesdan 	test(ctl_set_discard_ilseq1, "ctl_set_discard_ilseq1");
430ad30f8e7SGabor Kovesdan 	test(ctl_set_discard_ilseq2, "ctl_set_discard_ilseq2");
431ad30f8e7SGabor Kovesdan 	test(ctl_trivialp1, "ctl_trivialp1");
432ad30f8e7SGabor Kovesdan 	test(ctl_trivialp2, "ctl_trivialp2");
433ad30f8e7SGabor Kovesdan 	test(ctl_uc_hook, "ctl_uc_hook");
434ad30f8e7SGabor Kovesdan 	test(ctl_wc_hook, "ctl_wc_hook");
435ad30f8e7SGabor Kovesdan //	test(ctl_mb_to_uc_fb, "ctl_mb_to_uc_fb");
436ad30f8e7SGabor Kovesdan 	test(gnu_openinto, "gnu_openinto");
437ad30f8e7SGabor Kovesdan 	test(gnu_canonicalize1, "gnu_canonicalize1");
438ad30f8e7SGabor Kovesdan 	test(gnu_canonicalize2, "gnu_canonicalize2");
439ad30f8e7SGabor Kovesdan 	test(gnu_iconvlist, "gnu_iconvlist");
440ad30f8e7SGabor Kovesdan }
441