xref: /illumos-gate/usr/src/contrib/ast/src/lib/libast/comp/iconv.c (revision b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f)
1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman *                                                                      *
3*b30d1939SAndy Fiddaman *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2012 AT&T Intellectual Property          *
5*b30d1939SAndy Fiddaman *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*b30d1939SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*b30d1939SAndy Fiddaman *                                                                      *
9*b30d1939SAndy Fiddaman *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*b30d1939SAndy Fiddaman *                                                                      *
13*b30d1939SAndy Fiddaman *              Information and Software Systems Research               *
14*b30d1939SAndy Fiddaman *                            AT&T Research                             *
15*b30d1939SAndy Fiddaman *                           Florham Park NJ                            *
16*b30d1939SAndy Fiddaman *                                                                      *
17*b30d1939SAndy Fiddaman *                 Glenn Fowler <gsf@research.att.com>                  *
18*b30d1939SAndy Fiddaman *                  David Korn <dgk@research.att.com>                   *
19*b30d1939SAndy Fiddaman *                   Phong Vo <kpv@research.att.com>                    *
20*b30d1939SAndy Fiddaman *                                                                      *
21*b30d1939SAndy Fiddaman ***********************************************************************/
22*b30d1939SAndy Fiddaman #pragma prototyped
23*b30d1939SAndy Fiddaman 
24*b30d1939SAndy Fiddaman /*
25*b30d1939SAndy Fiddaman  * Glenn Fowler
26*b30d1939SAndy Fiddaman  * AT&T Research
27*b30d1939SAndy Fiddaman  *
28*b30d1939SAndy Fiddaman  * iconv intercept
29*b30d1939SAndy Fiddaman  * minimally provides { utf*<=>bin ascii<=>ebcdic* }
30*b30d1939SAndy Fiddaman  */
31*b30d1939SAndy Fiddaman 
32*b30d1939SAndy Fiddaman #include <ast.h>
33*b30d1939SAndy Fiddaman #include <dirent.h>
34*b30d1939SAndy Fiddaman 
35*b30d1939SAndy Fiddaman #define DEBUG_TRACE		0
36*b30d1939SAndy Fiddaman #define _ICONV_LIST_PRIVATE_
37*b30d1939SAndy Fiddaman 
38*b30d1939SAndy Fiddaman #include <ccode.h>
39*b30d1939SAndy Fiddaman #include <ctype.h>
40*b30d1939SAndy Fiddaman #include <iconv.h>
41*b30d1939SAndy Fiddaman 
42*b30d1939SAndy Fiddaman #include "lclib.h"
43*b30d1939SAndy Fiddaman 
44*b30d1939SAndy Fiddaman #if !_lib_iconv_open
45*b30d1939SAndy Fiddaman 
46*b30d1939SAndy Fiddaman #define _ast_iconv_t		iconv_t
47*b30d1939SAndy Fiddaman #define _ast_iconv_f		iconv_f
48*b30d1939SAndy Fiddaman #define _ast_iconv_list_t	iconv_list_t
49*b30d1939SAndy Fiddaman #define _ast_iconv_open		iconv_open
50*b30d1939SAndy Fiddaman #define _ast_iconv		iconv
51*b30d1939SAndy Fiddaman #define _ast_iconv_close	iconv_close
52*b30d1939SAndy Fiddaman #define _ast_iconv_list		iconv_list
53*b30d1939SAndy Fiddaman #define _ast_iconv_move		iconv_move
54*b30d1939SAndy Fiddaman #define _ast_iconv_name		iconv_name
55*b30d1939SAndy Fiddaman #define _ast_iconv_write	iconv_write
56*b30d1939SAndy Fiddaman 
57*b30d1939SAndy Fiddaman #endif
58*b30d1939SAndy Fiddaman 
59*b30d1939SAndy Fiddaman #ifndef E2BIG
60*b30d1939SAndy Fiddaman #define E2BIG			ENOMEM
61*b30d1939SAndy Fiddaman #endif
62*b30d1939SAndy Fiddaman #ifndef EILSEQ
63*b30d1939SAndy Fiddaman #define EILSEQ			EIO
64*b30d1939SAndy Fiddaman #endif
65*b30d1939SAndy Fiddaman 
66*b30d1939SAndy Fiddaman #define RETURN(e,n,fn) \
67*b30d1939SAndy Fiddaman 	if (*fn && !e) e = E2BIG; \
68*b30d1939SAndy Fiddaman 	if (e) { errno = e; return (size_t)(-1); } \
69*b30d1939SAndy Fiddaman 	return n;
70*b30d1939SAndy Fiddaman 
71*b30d1939SAndy Fiddaman typedef struct Map_s
72*b30d1939SAndy Fiddaman {
73*b30d1939SAndy Fiddaman 	char*			name;
74*b30d1939SAndy Fiddaman 	const unsigned char*	map;
75*b30d1939SAndy Fiddaman 	_ast_iconv_f		fun;
76*b30d1939SAndy Fiddaman 	int			index;
77*b30d1939SAndy Fiddaman } Map_t;
78*b30d1939SAndy Fiddaman 
79*b30d1939SAndy Fiddaman typedef struct Conv_s
80*b30d1939SAndy Fiddaman {
81*b30d1939SAndy Fiddaman 	iconv_t			cvt;
82*b30d1939SAndy Fiddaman 	char*			buf;
83*b30d1939SAndy Fiddaman 	size_t			size;
84*b30d1939SAndy Fiddaman 	Map_t			from;
85*b30d1939SAndy Fiddaman 	Map_t			to;
86*b30d1939SAndy Fiddaman } Conv_t;
87*b30d1939SAndy Fiddaman 
88*b30d1939SAndy Fiddaman static Conv_t*			freelist[4];
89*b30d1939SAndy Fiddaman static int			freeindex;
90*b30d1939SAndy Fiddaman 
91*b30d1939SAndy Fiddaman static const char		name_local[] = "local";
92*b30d1939SAndy Fiddaman static const char		name_native[] = "native";
93*b30d1939SAndy Fiddaman 
94*b30d1939SAndy Fiddaman static const _ast_iconv_list_t	codes[] =
95*b30d1939SAndy Fiddaman {
96*b30d1939SAndy Fiddaman 	{
97*b30d1939SAndy Fiddaman 	"utf",
98*b30d1939SAndy Fiddaman 	"un|unicode|utf",
99*b30d1939SAndy Fiddaman 	"multibyte 8-bit unicode",
100*b30d1939SAndy Fiddaman 	"UTF-%s",
101*b30d1939SAndy Fiddaman 	"8",
102*b30d1939SAndy Fiddaman 	CC_UTF,
103*b30d1939SAndy Fiddaman 	},
104*b30d1939SAndy Fiddaman 
105*b30d1939SAndy Fiddaman 	{
106*b30d1939SAndy Fiddaman 	"ume",
107*b30d1939SAndy Fiddaman 	"um|ume|utf?(-)7",
108*b30d1939SAndy Fiddaman 	"multibyte 7-bit unicode",
109*b30d1939SAndy Fiddaman 	"UTF-7",
110*b30d1939SAndy Fiddaman 	0,
111*b30d1939SAndy Fiddaman 	CC_UME,
112*b30d1939SAndy Fiddaman 	},
113*b30d1939SAndy Fiddaman 
114*b30d1939SAndy Fiddaman 	{
115*b30d1939SAndy Fiddaman 	"euc",
116*b30d1939SAndy Fiddaman 	"(big|euc)*",
117*b30d1939SAndy Fiddaman 	"euc family",
118*b30d1939SAndy Fiddaman 	0,
119*b30d1939SAndy Fiddaman 	0,
120*b30d1939SAndy Fiddaman 	CC_ICONV,
121*b30d1939SAndy Fiddaman 	},
122*b30d1939SAndy Fiddaman 
123*b30d1939SAndy Fiddaman 	{
124*b30d1939SAndy Fiddaman 	"dos",
125*b30d1939SAndy Fiddaman 	"dos?(-)?(855)",
126*b30d1939SAndy Fiddaman 	"dos code page",
127*b30d1939SAndy Fiddaman 	"DOS855",
128*b30d1939SAndy Fiddaman 	0,
129*b30d1939SAndy Fiddaman 	CC_ICONV,
130*b30d1939SAndy Fiddaman 	},
131*b30d1939SAndy Fiddaman 
132*b30d1939SAndy Fiddaman 	{
133*b30d1939SAndy Fiddaman 	"ucs",
134*b30d1939SAndy Fiddaman 	"ucs?(-)?(2)?(be)|utf-16?(be)",
135*b30d1939SAndy Fiddaman 	"unicode runes",
136*b30d1939SAndy Fiddaman 	"UCS-%s",
137*b30d1939SAndy Fiddaman 	"2",
138*b30d1939SAndy Fiddaman 	CC_UCS,
139*b30d1939SAndy Fiddaman 	},
140*b30d1939SAndy Fiddaman 
141*b30d1939SAndy Fiddaman 	{
142*b30d1939SAndy Fiddaman 	"ucs-le",
143*b30d1939SAndy Fiddaman 	"ucs?(-)?(2)le|utf-16le",
144*b30d1939SAndy Fiddaman 	"little endian unicode runes",
145*b30d1939SAndy Fiddaman 	"UCS-%sLE",
146*b30d1939SAndy Fiddaman 	"2",
147*b30d1939SAndy Fiddaman 	CC_SCU,
148*b30d1939SAndy Fiddaman 	},
149*b30d1939SAndy Fiddaman 
150*b30d1939SAndy Fiddaman 	{ 0 },
151*b30d1939SAndy Fiddaman };
152*b30d1939SAndy Fiddaman 
153*b30d1939SAndy Fiddaman #if _UWIN
154*b30d1939SAndy Fiddaman 
155*b30d1939SAndy Fiddaman #include <ast_windows.h>
156*b30d1939SAndy Fiddaman 
157*b30d1939SAndy Fiddaman #ifndef CP_UCS2
158*b30d1939SAndy Fiddaman #define CP_UCS2	0x0000
159*b30d1939SAndy Fiddaman #endif
160*b30d1939SAndy Fiddaman 
161*b30d1939SAndy Fiddaman static char	_win_maps[] = "/reg/local_machine/SOFTWARE/Classes/MIME/Database/Charset";
162*b30d1939SAndy Fiddaman 
163*b30d1939SAndy Fiddaman /*
164*b30d1939SAndy Fiddaman  * return the codeset index given its name or alias
165*b30d1939SAndy Fiddaman  * the map is in the what? oh, the registry
166*b30d1939SAndy Fiddaman  */
167*b30d1939SAndy Fiddaman 
168*b30d1939SAndy Fiddaman static int
_win_codeset(const char * name)169*b30d1939SAndy Fiddaman _win_codeset(const char* name)
170*b30d1939SAndy Fiddaman {
171*b30d1939SAndy Fiddaman 	register char*	s;
172*b30d1939SAndy Fiddaman 	char*		e;
173*b30d1939SAndy Fiddaman 	int		n;
174*b30d1939SAndy Fiddaman 	Sfio_t*		sp;
175*b30d1939SAndy Fiddaman 	char		aka[128];
176*b30d1939SAndy Fiddaman 	char		tmp[128];
177*b30d1939SAndy Fiddaman 
178*b30d1939SAndy Fiddaman #if DEBUG_TRACE
179*b30d1939SAndy Fiddaman error(DEBUG_TRACE, "AHA#%d _win_codeset name=%s", __LINE__, name);
180*b30d1939SAndy Fiddaman #endif
181*b30d1939SAndy Fiddaman 	if (name == name_native)
182*b30d1939SAndy Fiddaman 		return CP_ACP;
183*b30d1939SAndy Fiddaman 	if (!strcasecmp(name, "utf") || !strcasecmp(name, "utf8") || !strcasecmp(name, "utf-8"))
184*b30d1939SAndy Fiddaman 		return CP_UTF8;
185*b30d1939SAndy Fiddaman 	if (!strcasecmp(name, "ucs") || !strcasecmp(name, "ucs2") || !strcasecmp(name, "ucs-2"))
186*b30d1939SAndy Fiddaman 		return CP_UCS2;
187*b30d1939SAndy Fiddaman 	if (name[0] == '0' && name[1] == 'x' && (n = strtol(name, &e, 0)) > 0 && !*e)
188*b30d1939SAndy Fiddaman 		return n;
189*b30d1939SAndy Fiddaman 	for (;;)
190*b30d1939SAndy Fiddaman 	{
191*b30d1939SAndy Fiddaman 		sfsprintf(tmp, sizeof(tmp), "%s/%s", _win_maps, name);
192*b30d1939SAndy Fiddaman 		if (!(sp = sfopen(0, tmp, "r")))
193*b30d1939SAndy Fiddaman 		{
194*b30d1939SAndy Fiddaman 			s = (char*)name;
195*b30d1939SAndy Fiddaman 			if ((s[0] == 'c' || s[0] == 'C') && (s[1] == 'p' || s[1] == 'P'))
196*b30d1939SAndy Fiddaman 				s += 2;
197*b30d1939SAndy Fiddaman 			if (!isdigit(s[0]))
198*b30d1939SAndy Fiddaman 				break;
199*b30d1939SAndy Fiddaman 			sfsprintf(tmp, sizeof(tmp), "%s/windows-%s", _win_maps, s);
200*b30d1939SAndy Fiddaman 			if (!(sp = sfopen(0, tmp, "r")))
201*b30d1939SAndy Fiddaman 				break;
202*b30d1939SAndy Fiddaman 		}
203*b30d1939SAndy Fiddaman 		for (;;)
204*b30d1939SAndy Fiddaman 		{
205*b30d1939SAndy Fiddaman 			if (!(s = sfgetr(sp, '\n', 0)))
206*b30d1939SAndy Fiddaman 			{
207*b30d1939SAndy Fiddaman 				sfclose(sp);
208*b30d1939SAndy Fiddaman 				return -1;
209*b30d1939SAndy Fiddaman 			}
210*b30d1939SAndy Fiddaman 			if (!strncasecmp(s, "AliasForCharSet=", 16))
211*b30d1939SAndy Fiddaman 			{
212*b30d1939SAndy Fiddaman 				n = sfvalue(sp) - 17;
213*b30d1939SAndy Fiddaman 				s += 16;
214*b30d1939SAndy Fiddaman 				if (n >= sizeof(aka))
215*b30d1939SAndy Fiddaman 					n = sizeof(aka) - 1;
216*b30d1939SAndy Fiddaman 				memcpy(aka, s, n);
217*b30d1939SAndy Fiddaman 				aka[n] = 0;
218*b30d1939SAndy Fiddaman 				sfclose(sp);
219*b30d1939SAndy Fiddaman 				name = (const char*)aka;
220*b30d1939SAndy Fiddaman 				break;
221*b30d1939SAndy Fiddaman 			}
222*b30d1939SAndy Fiddaman 			if (!strncasecmp(s, "CodePage=", 9))
223*b30d1939SAndy Fiddaman 			{
224*b30d1939SAndy Fiddaman 				s += 9;
225*b30d1939SAndy Fiddaman 				n = strtol(s, 0, 0);
226*b30d1939SAndy Fiddaman 				sfclose(sp);
227*b30d1939SAndy Fiddaman 				return n;
228*b30d1939SAndy Fiddaman 			}
229*b30d1939SAndy Fiddaman 		}
230*b30d1939SAndy Fiddaman 	}
231*b30d1939SAndy Fiddaman 	return -1;
232*b30d1939SAndy Fiddaman }
233*b30d1939SAndy Fiddaman 
234*b30d1939SAndy Fiddaman /*
235*b30d1939SAndy Fiddaman  * get and check the codeset indices
236*b30d1939SAndy Fiddaman  */
237*b30d1939SAndy Fiddaman 
238*b30d1939SAndy Fiddaman static _ast_iconv_t
_win_iconv_open(register Conv_t * cc,const char * t,const char * f)239*b30d1939SAndy Fiddaman _win_iconv_open(register Conv_t* cc, const char* t, const char* f)
240*b30d1939SAndy Fiddaman {
241*b30d1939SAndy Fiddaman #if DEBUG_TRACE
242*b30d1939SAndy Fiddaman error(DEBUG_TRACE, "AHA#%d _win_iconv_open f=%s t=%s\n", __LINE__, f, t);
243*b30d1939SAndy Fiddaman #endif
244*b30d1939SAndy Fiddaman 	if ((cc->from.index = _win_codeset(f)) < 0)
245*b30d1939SAndy Fiddaman 		return (_ast_iconv_t)(-1);
246*b30d1939SAndy Fiddaman 	if ((cc->to.index = _win_codeset(t)) < 0)
247*b30d1939SAndy Fiddaman 		return (_ast_iconv_t)(-1);
248*b30d1939SAndy Fiddaman #if DEBUG_TRACE
249*b30d1939SAndy Fiddaman error(DEBUG_TRACE, "AHA#%d _win_iconv_open f=0x%04x t=0x%04x\n", __LINE__, cc->from.index, cc->to.index);
250*b30d1939SAndy Fiddaman #endif
251*b30d1939SAndy Fiddaman 	return (_ast_iconv_t)cc;
252*b30d1939SAndy Fiddaman }
253*b30d1939SAndy Fiddaman 
254*b30d1939SAndy Fiddaman /*
255*b30d1939SAndy Fiddaman  * even though the indices already check out
256*b30d1939SAndy Fiddaman  * they could still be rejected
257*b30d1939SAndy Fiddaman  */
258*b30d1939SAndy Fiddaman 
259*b30d1939SAndy Fiddaman static size_t
_win_iconv(_ast_iconv_t cd,char ** fb,size_t * fn,char ** tb,size_t * tn)260*b30d1939SAndy Fiddaman _win_iconv(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
261*b30d1939SAndy Fiddaman {
262*b30d1939SAndy Fiddaman 	Conv_t*	cc = (Conv_t*)cd;
263*b30d1939SAndy Fiddaman 	size_t	un;
264*b30d1939SAndy Fiddaman 	size_t	tz;
265*b30d1939SAndy Fiddaman 	size_t	fz;
266*b30d1939SAndy Fiddaman 	size_t	bz;
267*b30d1939SAndy Fiddaman 	size_t	pz;
268*b30d1939SAndy Fiddaman 	size_t	oz;
269*b30d1939SAndy Fiddaman 	LPWSTR	ub;
270*b30d1939SAndy Fiddaman 
271*b30d1939SAndy Fiddaman #if DEBUG_TRACE
272*b30d1939SAndy Fiddaman error(DEBUG_TRACE, "AHA#%d _win_iconv from=0x%04x to=0x%04x\n", __LINE__, cc->from.index, cc->to.index);
273*b30d1939SAndy Fiddaman #endif
274*b30d1939SAndy Fiddaman 	if (cc->from.index == cc->to.index || cc->from.index != CP_UCS2 && cc->to.index == 0)
275*b30d1939SAndy Fiddaman 	{
276*b30d1939SAndy Fiddaman 		/*
277*b30d1939SAndy Fiddaman 		 * easy
278*b30d1939SAndy Fiddaman 		 */
279*b30d1939SAndy Fiddaman 
280*b30d1939SAndy Fiddaman 		fz = tz = (*fn < *tn) ? *fn : *tn;
281*b30d1939SAndy Fiddaman 		memcpy(*tb, *fb, fz);
282*b30d1939SAndy Fiddaman 	}
283*b30d1939SAndy Fiddaman 	else
284*b30d1939SAndy Fiddaman 	{
285*b30d1939SAndy Fiddaman 		ub = 0;
286*b30d1939SAndy Fiddaman 		un = *fn;
287*b30d1939SAndy Fiddaman 
288*b30d1939SAndy Fiddaman 		/*
289*b30d1939SAndy Fiddaman 		 * from => ucs-2
290*b30d1939SAndy Fiddaman 		 */
291*b30d1939SAndy Fiddaman 
292*b30d1939SAndy Fiddaman 		if (cc->to.index == CP_UCS2)
293*b30d1939SAndy Fiddaman 		{
294*b30d1939SAndy Fiddaman 			if ((tz = MultiByteToWideChar(cc->from.index, 0, (LPCSTR)*fb, (int)*fn, (LPWSTR)*tb, *tn)) && tz <= *tn)
295*b30d1939SAndy Fiddaman 			{
296*b30d1939SAndy Fiddaman 				fz = *fn;
297*b30d1939SAndy Fiddaman 				tz *= sizeof(WCHAR);
298*b30d1939SAndy Fiddaman 			}
299*b30d1939SAndy Fiddaman 			else
300*b30d1939SAndy Fiddaman 			{
301*b30d1939SAndy Fiddaman 				/*
302*b30d1939SAndy Fiddaman 				 * target too small
303*b30d1939SAndy Fiddaman 				 * binary search on input size to make it fit
304*b30d1939SAndy Fiddaman 				 */
305*b30d1939SAndy Fiddaman 
306*b30d1939SAndy Fiddaman 				oz = 0;
307*b30d1939SAndy Fiddaman 				pz = *fn / 2;
308*b30d1939SAndy Fiddaman 				fz = *fn - pz;
309*b30d1939SAndy Fiddaman 				for (;;)
310*b30d1939SAndy Fiddaman 				{
311*b30d1939SAndy Fiddaman 					while (!(tz = MultiByteToWideChar(cc->from.index, 0, (LPCSTR)*fb, (int)fz, (LPWSTR)*tb, 0)))
312*b30d1939SAndy Fiddaman 						if (++fz >= *fn)
313*b30d1939SAndy Fiddaman 							goto nope;
314*b30d1939SAndy Fiddaman 					tz *= sizeof(WCHAR);
315*b30d1939SAndy Fiddaman 					if (tz == *tn)
316*b30d1939SAndy Fiddaman 						break;
317*b30d1939SAndy Fiddaman 					if (!(pz /= 2))
318*b30d1939SAndy Fiddaman 					{
319*b30d1939SAndy Fiddaman 						if (!(fz = oz))
320*b30d1939SAndy Fiddaman 							goto nope;
321*b30d1939SAndy Fiddaman 						break;
322*b30d1939SAndy Fiddaman 					}
323*b30d1939SAndy Fiddaman 					if (tz > *tn)
324*b30d1939SAndy Fiddaman 						fz -= pz;
325*b30d1939SAndy Fiddaman 					else
326*b30d1939SAndy Fiddaman 					{
327*b30d1939SAndy Fiddaman 						oz = fz;
328*b30d1939SAndy Fiddaman 						fz += pz;
329*b30d1939SAndy Fiddaman 					}
330*b30d1939SAndy Fiddaman 				}
331*b30d1939SAndy Fiddaman 			}
332*b30d1939SAndy Fiddaman 		}
333*b30d1939SAndy Fiddaman 		else
334*b30d1939SAndy Fiddaman 		{
335*b30d1939SAndy Fiddaman 			if (cc->from.index == CP_UCS2)
336*b30d1939SAndy Fiddaman 			{
337*b30d1939SAndy Fiddaman 				un = *fn / sizeof(WCHAR);
338*b30d1939SAndy Fiddaman 				ub = (LPWSTR)*fb;
339*b30d1939SAndy Fiddaman 			}
340*b30d1939SAndy Fiddaman 			else if (!(un = MultiByteToWideChar(cc->from.index, 0, (LPCSTR)*fb, (int)*fn, (LPWSTR)*tb, 0)))
341*b30d1939SAndy Fiddaman 				goto nope;
342*b30d1939SAndy Fiddaman 			else if (!(ub = (LPWSTR)malloc(un * sizeof(WCHAR))))
343*b30d1939SAndy Fiddaman 				goto nope;
344*b30d1939SAndy Fiddaman 			else if (!(un = MultiByteToWideChar(cc->from.index, 0, (LPCSTR)*fb, (int)*fn, (LPWSTR)ub, un)))
345*b30d1939SAndy Fiddaman 				goto nope;
346*b30d1939SAndy Fiddaman 
347*b30d1939SAndy Fiddaman 			/*
348*b30d1939SAndy Fiddaman 			 * ucs-2 => to
349*b30d1939SAndy Fiddaman 			 */
350*b30d1939SAndy Fiddaman 
351*b30d1939SAndy Fiddaman 			if (tz = WideCharToMultiByte(cc->to.index, 0, (LPCWSTR)ub, un, *tb, *tn, 0, 0))
352*b30d1939SAndy Fiddaman 				fz = *fn;
353*b30d1939SAndy Fiddaman 			else
354*b30d1939SAndy Fiddaman 			{
355*b30d1939SAndy Fiddaman 				/*
356*b30d1939SAndy Fiddaman 				 * target too small
357*b30d1939SAndy Fiddaman 				 * binary search on input size to make it fit
358*b30d1939SAndy Fiddaman 				 */
359*b30d1939SAndy Fiddaman 
360*b30d1939SAndy Fiddaman 				oz = 0;
361*b30d1939SAndy Fiddaman 				pz = *fn / 2;
362*b30d1939SAndy Fiddaman 				bz = *fn - pz;
363*b30d1939SAndy Fiddaman 				for (;;)
364*b30d1939SAndy Fiddaman 				{
365*b30d1939SAndy Fiddaman 					while (!(fz = MultiByteToWideChar(cc->from.index, 0, (LPCSTR)*fb, (int)bz, (LPWSTR)ub, un)))
366*b30d1939SAndy Fiddaman 						if (++bz > *fn)
367*b30d1939SAndy Fiddaman 							goto nope;
368*b30d1939SAndy Fiddaman 					if (!(tz = WideCharToMultiByte(cc->to.index, 0, (LPCWSTR)ub, fz, *tb, 0, 0, 0)))
369*b30d1939SAndy Fiddaman 						goto nope;
370*b30d1939SAndy Fiddaman 					if (tz == *tn)
371*b30d1939SAndy Fiddaman 						break;
372*b30d1939SAndy Fiddaman 					if (!(pz /= 2))
373*b30d1939SAndy Fiddaman 					{
374*b30d1939SAndy Fiddaman 						if (!(fz = oz))
375*b30d1939SAndy Fiddaman 							goto nope;
376*b30d1939SAndy Fiddaman 						break;
377*b30d1939SAndy Fiddaman 					}
378*b30d1939SAndy Fiddaman 					if (tz > *tn)
379*b30d1939SAndy Fiddaman 						bz -= pz;
380*b30d1939SAndy Fiddaman 					else
381*b30d1939SAndy Fiddaman 					{
382*b30d1939SAndy Fiddaman 						oz = bz;
383*b30d1939SAndy Fiddaman 						bz += pz;
384*b30d1939SAndy Fiddaman 					}
385*b30d1939SAndy Fiddaman 				}
386*b30d1939SAndy Fiddaman 				if (!(tz = WideCharToMultiByte(cc->to.index, 0, (LPCWSTR)ub, fz, *tb, tz, 0, 0)))
387*b30d1939SAndy Fiddaman 					goto nope;
388*b30d1939SAndy Fiddaman #if DEBUG_TRACE
389*b30d1939SAndy Fiddaman error(DEBUG_TRACE, "AHA#%d _win_iconv *fn=%u fz=%u[%u] *tn=%u tz=%u\n", __LINE__, *fn, fz, fz * sizeof(WCHAR), *tn, tz);
390*b30d1939SAndy Fiddaman #endif
391*b30d1939SAndy Fiddaman #if 0
392*b30d1939SAndy Fiddaman 				fz *= sizeof(WCHAR);
393*b30d1939SAndy Fiddaman #endif
394*b30d1939SAndy Fiddaman 			}
395*b30d1939SAndy Fiddaman 			if (ub != (LPWSTR)*fb)
396*b30d1939SAndy Fiddaman 				free(ub);
397*b30d1939SAndy Fiddaman 		}
398*b30d1939SAndy Fiddaman 	}
399*b30d1939SAndy Fiddaman 	*fb += fz;
400*b30d1939SAndy Fiddaman 	*fn -= fz;
401*b30d1939SAndy Fiddaman 	*tb += tz;
402*b30d1939SAndy Fiddaman 	*tn -= tz;
403*b30d1939SAndy Fiddaman 	return fz;
404*b30d1939SAndy Fiddaman  nope:
405*b30d1939SAndy Fiddaman 	if (ub && ub != (LPWSTR)*fb)
406*b30d1939SAndy Fiddaman 		free(ub);
407*b30d1939SAndy Fiddaman 	errno = EINVAL;
408*b30d1939SAndy Fiddaman 	return (size_t)(-1);
409*b30d1939SAndy Fiddaman }
410*b30d1939SAndy Fiddaman 
411*b30d1939SAndy Fiddaman #endif
412*b30d1939SAndy Fiddaman 
413*b30d1939SAndy Fiddaman /*
414*b30d1939SAndy Fiddaman  * return canonical character code set name for m
415*b30d1939SAndy Fiddaman  * if b!=0 then canonical name placed in b of size n
416*b30d1939SAndy Fiddaman  * <ccode.h> index returned
417*b30d1939SAndy Fiddaman  */
418*b30d1939SAndy Fiddaman 
419*b30d1939SAndy Fiddaman int
_ast_iconv_name(register const char * m,register char * b,size_t n)420*b30d1939SAndy Fiddaman _ast_iconv_name(register const char* m, register char* b, size_t n)
421*b30d1939SAndy Fiddaman {
422*b30d1939SAndy Fiddaman 	register const _ast_iconv_list_t*	cp;
423*b30d1939SAndy Fiddaman 	const _ast_iconv_list_t*		bp;
424*b30d1939SAndy Fiddaman 	register int				c;
425*b30d1939SAndy Fiddaman 	register char*				e;
426*b30d1939SAndy Fiddaman 	ssize_t					sub[2];
427*b30d1939SAndy Fiddaman 	char					buf[16];
428*b30d1939SAndy Fiddaman #if DEBUG_TRACE
429*b30d1939SAndy Fiddaman 	char*					o;
430*b30d1939SAndy Fiddaman #endif
431*b30d1939SAndy Fiddaman 
432*b30d1939SAndy Fiddaman 	if (!b)
433*b30d1939SAndy Fiddaman 	{
434*b30d1939SAndy Fiddaman 		b = buf;
435*b30d1939SAndy Fiddaman 		n = sizeof(buf);
436*b30d1939SAndy Fiddaman 	}
437*b30d1939SAndy Fiddaman #if DEBUG_TRACE
438*b30d1939SAndy Fiddaman 	o = b;
439*b30d1939SAndy Fiddaman #endif
440*b30d1939SAndy Fiddaman 	e = b + n - 1;
441*b30d1939SAndy Fiddaman 	bp = 0;
442*b30d1939SAndy Fiddaman 	n = 0;
443*b30d1939SAndy Fiddaman 	cp = ccmaplist(NiL);
444*b30d1939SAndy Fiddaman #if DEBUG_TRACE
445*b30d1939SAndy Fiddaman if (error_info.trace < DEBUG_TRACE) sfprintf(sfstderr, "%s: debug-%d: AHA%d _ast_iconv_name m=\"%s\"\n", error_info.id, error_info.trace, __LINE__, m);
446*b30d1939SAndy Fiddaman #endif
447*b30d1939SAndy Fiddaman 	for (;;)
448*b30d1939SAndy Fiddaman 	{
449*b30d1939SAndy Fiddaman #if DEBUG_TRACE
450*b30d1939SAndy Fiddaman if (error_info.trace < DEBUG_TRACE) sfprintf(sfstderr, "%s: debug-%d: AHA%d _ast_iconv_name n=%d bp=%p cp=%p ccode=%d name=\"%s\"\n", error_info.id, error_info.trace, __LINE__, n, bp, cp, cp->ccode, cp->name);
451*b30d1939SAndy Fiddaman #endif
452*b30d1939SAndy Fiddaman 		if (strgrpmatch(m, cp->match, sub, elementsof(sub) / 2, STR_MAXIMAL|STR_LEFT|STR_ICASE))
453*b30d1939SAndy Fiddaman 		{
454*b30d1939SAndy Fiddaman 			if (!(c = m[sub[1]]))
455*b30d1939SAndy Fiddaman 			{
456*b30d1939SAndy Fiddaman 				bp = cp;
457*b30d1939SAndy Fiddaman 				break;
458*b30d1939SAndy Fiddaman 			}
459*b30d1939SAndy Fiddaman 			if (sub[1] > n && !isalpha(c))
460*b30d1939SAndy Fiddaman 			{
461*b30d1939SAndy Fiddaman 				bp = cp;
462*b30d1939SAndy Fiddaman 				n = sub[1];
463*b30d1939SAndy Fiddaman 			}
464*b30d1939SAndy Fiddaman 		}
465*b30d1939SAndy Fiddaman 		if (cp->ccode < 0)
466*b30d1939SAndy Fiddaman 		{
467*b30d1939SAndy Fiddaman 			if (!(++cp)->name)
468*b30d1939SAndy Fiddaman 				break;
469*b30d1939SAndy Fiddaman 		}
470*b30d1939SAndy Fiddaman 		else if (!(cp = (const _ast_iconv_list_t*)ccmaplist((_ast_iconv_list_t*)cp)))
471*b30d1939SAndy Fiddaman 			cp = codes;
472*b30d1939SAndy Fiddaman 	}
473*b30d1939SAndy Fiddaman 	if (cp = bp)
474*b30d1939SAndy Fiddaman 	{
475*b30d1939SAndy Fiddaman 		if (cp->canon)
476*b30d1939SAndy Fiddaman 		{
477*b30d1939SAndy Fiddaman 			if (cp->index)
478*b30d1939SAndy Fiddaman 			{
479*b30d1939SAndy Fiddaman 				for (m += sub[1]; *m && !isalnum(*m); m++);
480*b30d1939SAndy Fiddaman 				if (!isdigit(*m))
481*b30d1939SAndy Fiddaman 					m = cp->index;
482*b30d1939SAndy Fiddaman 			}
483*b30d1939SAndy Fiddaman 			else
484*b30d1939SAndy Fiddaman 				m = "1";
485*b30d1939SAndy Fiddaman 			b += sfsprintf(b, e - b, cp->canon, m);
486*b30d1939SAndy Fiddaman 		}
487*b30d1939SAndy Fiddaman 		else if (cp->ccode == CC_NATIVE)
488*b30d1939SAndy Fiddaman 		{
489*b30d1939SAndy Fiddaman 			if ((locales[AST_LC_CTYPE]->flags & LC_default) || !locales[AST_LC_CTYPE]->charset || !(m = locales[AST_LC_CTYPE]->charset->code) || streq(m, "iso8859-1"))
490*b30d1939SAndy Fiddaman 				switch (CC_NATIVE)
491*b30d1939SAndy Fiddaman 				{
492*b30d1939SAndy Fiddaman 				case CC_EBCDIC:
493*b30d1939SAndy Fiddaman 					m = (const char*)"EBCDIC";
494*b30d1939SAndy Fiddaman 					break;
495*b30d1939SAndy Fiddaman 				case CC_EBCDIC_I:
496*b30d1939SAndy Fiddaman 					m = (const char*)"EBCDIC-I";
497*b30d1939SAndy Fiddaman 					break;
498*b30d1939SAndy Fiddaman 				case CC_EBCDIC_O:
499*b30d1939SAndy Fiddaman 					m = (const char*)"EBCDIC-O";
500*b30d1939SAndy Fiddaman 					break;
501*b30d1939SAndy Fiddaman 				default:
502*b30d1939SAndy Fiddaman 					m = (const char*)"ISO-8859-1";
503*b30d1939SAndy Fiddaman 					break;
504*b30d1939SAndy Fiddaman 				}
505*b30d1939SAndy Fiddaman 			b += sfsprintf(b, e - b, "%s", m);
506*b30d1939SAndy Fiddaman 		}
507*b30d1939SAndy Fiddaman 		*b = 0;
508*b30d1939SAndy Fiddaman #if DEBUG_TRACE
509*b30d1939SAndy Fiddaman if (error_info.trace < DEBUG_TRACE) sfprintf(sfstderr, "%s: debug-%d: AHA%d _ast_iconv_name ccode=%d canon=\"%s\"\n", error_info.id, error_info.trace, __LINE__, cp->ccode, o);
510*b30d1939SAndy Fiddaman #endif
511*b30d1939SAndy Fiddaman 		return cp->ccode;
512*b30d1939SAndy Fiddaman 	}
513*b30d1939SAndy Fiddaman 	while (b < e && (c = *m++))
514*b30d1939SAndy Fiddaman 	{
515*b30d1939SAndy Fiddaman 		if (islower(c))
516*b30d1939SAndy Fiddaman 			c = toupper(c);
517*b30d1939SAndy Fiddaman 		*b++ = c;
518*b30d1939SAndy Fiddaman 	}
519*b30d1939SAndy Fiddaman 	*b = 0;
520*b30d1939SAndy Fiddaman #if DEBUG_TRACE
521*b30d1939SAndy Fiddaman if (error_info.trace < DEBUG_TRACE) sfprintf(sfstderr, "%s: debug-%d: AHA%d _ast_iconv_name ccode=%d canon=\"%s\"\n", error_info.id, error_info.trace, __LINE__, CC_ICONV, o);
522*b30d1939SAndy Fiddaman #endif
523*b30d1939SAndy Fiddaman 	return CC_ICONV;
524*b30d1939SAndy Fiddaman }
525*b30d1939SAndy Fiddaman 
526*b30d1939SAndy Fiddaman /*
527*b30d1939SAndy Fiddaman  * convert utf-8 to bin
528*b30d1939SAndy Fiddaman  */
529*b30d1939SAndy Fiddaman 
530*b30d1939SAndy Fiddaman static size_t
utf2bin(_ast_iconv_t cd,char ** fb,size_t * fn,char ** tb,size_t * tn)531*b30d1939SAndy Fiddaman utf2bin(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
532*b30d1939SAndy Fiddaman {
533*b30d1939SAndy Fiddaman 	register unsigned char*		f;
534*b30d1939SAndy Fiddaman 	register unsigned char*		fe;
535*b30d1939SAndy Fiddaman 	register unsigned char*		t;
536*b30d1939SAndy Fiddaman 	register unsigned char*		te;
537*b30d1939SAndy Fiddaman 	register unsigned char*		p;
538*b30d1939SAndy Fiddaman 	register int			c;
539*b30d1939SAndy Fiddaman 	register int			w;
540*b30d1939SAndy Fiddaman 	size_t				n;
541*b30d1939SAndy Fiddaman 	int				e;
542*b30d1939SAndy Fiddaman 
543*b30d1939SAndy Fiddaman 	e = 0;
544*b30d1939SAndy Fiddaman 	f = (unsigned char*)(*fb);
545*b30d1939SAndy Fiddaman 	fe = f + (*fn);
546*b30d1939SAndy Fiddaman 	t = (unsigned char*)(*tb);
547*b30d1939SAndy Fiddaman 	te = t + (*tn);
548*b30d1939SAndy Fiddaman 	while (t < te && f < fe)
549*b30d1939SAndy Fiddaman 	{
550*b30d1939SAndy Fiddaman 		p = f;
551*b30d1939SAndy Fiddaman 		c = *f++;
552*b30d1939SAndy Fiddaman 		if (c & 0x80)
553*b30d1939SAndy Fiddaman 		{
554*b30d1939SAndy Fiddaman 			if (!(c & 0x40))
555*b30d1939SAndy Fiddaman 			{
556*b30d1939SAndy Fiddaman 				f = p;
557*b30d1939SAndy Fiddaman 				e = EILSEQ;
558*b30d1939SAndy Fiddaman 				break;
559*b30d1939SAndy Fiddaman 			}
560*b30d1939SAndy Fiddaman 			if (c & 0x20)
561*b30d1939SAndy Fiddaman 			{
562*b30d1939SAndy Fiddaman 				w = (c & 0x0F) << 12;
563*b30d1939SAndy Fiddaman 				if (f >= fe)
564*b30d1939SAndy Fiddaman 				{
565*b30d1939SAndy Fiddaman 					f = p;
566*b30d1939SAndy Fiddaman 					e = EINVAL;
567*b30d1939SAndy Fiddaman 					break;
568*b30d1939SAndy Fiddaman 				}
569*b30d1939SAndy Fiddaman 				c = *f++;
570*b30d1939SAndy Fiddaman 				if (c & 0x40)
571*b30d1939SAndy Fiddaman 				{
572*b30d1939SAndy Fiddaman 					f = p;
573*b30d1939SAndy Fiddaman 					e = EILSEQ;
574*b30d1939SAndy Fiddaman 					break;
575*b30d1939SAndy Fiddaman 				}
576*b30d1939SAndy Fiddaman 				w |= (c & 0x3F) << 6;
577*b30d1939SAndy Fiddaman 			}
578*b30d1939SAndy Fiddaman 			else
579*b30d1939SAndy Fiddaman 				w = (c & 0x1F) << 6;
580*b30d1939SAndy Fiddaman 			if (f >= fe)
581*b30d1939SAndy Fiddaman 			{
582*b30d1939SAndy Fiddaman 				f = p;
583*b30d1939SAndy Fiddaman 				e = EINVAL;
584*b30d1939SAndy Fiddaman 				break;
585*b30d1939SAndy Fiddaman 			}
586*b30d1939SAndy Fiddaman 			c = *f++;
587*b30d1939SAndy Fiddaman 			w |= (c & 0x3F);
588*b30d1939SAndy Fiddaman 		}
589*b30d1939SAndy Fiddaman 		else
590*b30d1939SAndy Fiddaman 			w = c;
591*b30d1939SAndy Fiddaman 		*t++ = w;
592*b30d1939SAndy Fiddaman 	}
593*b30d1939SAndy Fiddaman 	*fn -= (char*)f - (*fb);
594*b30d1939SAndy Fiddaman 	*fb = (char*)f;
595*b30d1939SAndy Fiddaman 	*tn -= (n = (char*)t - (*tb));
596*b30d1939SAndy Fiddaman 	*tb = (char*)t;
597*b30d1939SAndy Fiddaman 	RETURN(e, n, fn);
598*b30d1939SAndy Fiddaman }
599*b30d1939SAndy Fiddaman 
600*b30d1939SAndy Fiddaman /*
601*b30d1939SAndy Fiddaman  * convert bin to utf-8
602*b30d1939SAndy Fiddaman  */
603*b30d1939SAndy Fiddaman 
604*b30d1939SAndy Fiddaman static size_t
bin2utf(_ast_iconv_t cd,char ** fb,size_t * fn,char ** tb,size_t * tn)605*b30d1939SAndy Fiddaman bin2utf(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
606*b30d1939SAndy Fiddaman {
607*b30d1939SAndy Fiddaman 	register unsigned char*		f;
608*b30d1939SAndy Fiddaman 	register unsigned char*		fe;
609*b30d1939SAndy Fiddaman 	register unsigned char*		t;
610*b30d1939SAndy Fiddaman 	register unsigned char*		te;
611*b30d1939SAndy Fiddaman 	register int			c;
612*b30d1939SAndy Fiddaman 	wchar_t				w;
613*b30d1939SAndy Fiddaman 	size_t				n;
614*b30d1939SAndy Fiddaman 	int				e;
615*b30d1939SAndy Fiddaman 
616*b30d1939SAndy Fiddaman 	e = 0;
617*b30d1939SAndy Fiddaman 	f = (unsigned char*)(*fb);
618*b30d1939SAndy Fiddaman 	fe = f + (*fn);
619*b30d1939SAndy Fiddaman 	t = (unsigned char*)(*tb);
620*b30d1939SAndy Fiddaman 	te = t + (*tn);
621*b30d1939SAndy Fiddaman 	while (f < fe && t < te)
622*b30d1939SAndy Fiddaman 	{
623*b30d1939SAndy Fiddaman 		if (!mbwide())
624*b30d1939SAndy Fiddaman 		{
625*b30d1939SAndy Fiddaman 			c = 1;
626*b30d1939SAndy Fiddaman 			w = *f;
627*b30d1939SAndy Fiddaman 		}
628*b30d1939SAndy Fiddaman 		else if ((c = (*_ast_info.mb_towc)(&w, (char*)f, fe - f)) < 0)
629*b30d1939SAndy Fiddaman 		{
630*b30d1939SAndy Fiddaman 			e = EINVAL;
631*b30d1939SAndy Fiddaman 			break;
632*b30d1939SAndy Fiddaman 		}
633*b30d1939SAndy Fiddaman 		else if (!c)
634*b30d1939SAndy Fiddaman 			c = 1;
635*b30d1939SAndy Fiddaman 		if (!(w & ~0x7F))
636*b30d1939SAndy Fiddaman 			*t++ = w;
637*b30d1939SAndy Fiddaman 		else
638*b30d1939SAndy Fiddaman 		{
639*b30d1939SAndy Fiddaman 			if (!(w & ~0x7FF))
640*b30d1939SAndy Fiddaman 			{
641*b30d1939SAndy Fiddaman 				if (t >= (te - 2))
642*b30d1939SAndy Fiddaman 				{
643*b30d1939SAndy Fiddaman 					e = E2BIG;
644*b30d1939SAndy Fiddaman 					break;
645*b30d1939SAndy Fiddaman 				}
646*b30d1939SAndy Fiddaman 				*t++ = 0xC0 + (w >> 6);
647*b30d1939SAndy Fiddaman 			}
648*b30d1939SAndy Fiddaman 			else if (!(w & ~0xffff))
649*b30d1939SAndy Fiddaman 			{
650*b30d1939SAndy Fiddaman 				if (t >= (te - 3))
651*b30d1939SAndy Fiddaman 				{
652*b30d1939SAndy Fiddaman 					e = E2BIG;
653*b30d1939SAndy Fiddaman 					break;
654*b30d1939SAndy Fiddaman 				}
655*b30d1939SAndy Fiddaman 				*t++ = 0xE0 + (w >> 12);
656*b30d1939SAndy Fiddaman 				*t++ = 0x80 + ((w >> 6 ) & 0x3F);
657*b30d1939SAndy Fiddaman 			}
658*b30d1939SAndy Fiddaman 			else
659*b30d1939SAndy Fiddaman 			{
660*b30d1939SAndy Fiddaman 				e = EILSEQ;
661*b30d1939SAndy Fiddaman 				break;
662*b30d1939SAndy Fiddaman 			}
663*b30d1939SAndy Fiddaman 			*t++ = 0x80 + (w & 0x3F);
664*b30d1939SAndy Fiddaman 		}
665*b30d1939SAndy Fiddaman 		f += c;
666*b30d1939SAndy Fiddaman 	}
667*b30d1939SAndy Fiddaman 	*fn -= (n = (char*)f - (*fb));
668*b30d1939SAndy Fiddaman 	*fb = (char*)f;
669*b30d1939SAndy Fiddaman 	*tn -= (char*)t - (*tb);
670*b30d1939SAndy Fiddaman 	*tb = (char*)t;
671*b30d1939SAndy Fiddaman 	RETURN(e, n, fn);
672*b30d1939SAndy Fiddaman }
673*b30d1939SAndy Fiddaman 
674*b30d1939SAndy Fiddaman static const unsigned char	ume_D[] =
675*b30d1939SAndy Fiddaman "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'(),-./:?!\"#$%&*;<=>@[]^_`{|} \t\n";
676*b30d1939SAndy Fiddaman 
677*b30d1939SAndy Fiddaman static const unsigned char	ume_M[] =
678*b30d1939SAndy Fiddaman "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
679*b30d1939SAndy Fiddaman 
680*b30d1939SAndy Fiddaman static unsigned char		ume_d[UCHAR_MAX+1];
681*b30d1939SAndy Fiddaman 
682*b30d1939SAndy Fiddaman static unsigned char		ume_m[UCHAR_MAX+1];
683*b30d1939SAndy Fiddaman 
684*b30d1939SAndy Fiddaman #define NOE			0xFF
685*b30d1939SAndy Fiddaman #define UMEINIT()		(ume_d[ume_D[0]]?0:umeinit())
686*b30d1939SAndy Fiddaman 
687*b30d1939SAndy Fiddaman /*
688*b30d1939SAndy Fiddaman  * initialize the ume tables
689*b30d1939SAndy Fiddaman  */
690*b30d1939SAndy Fiddaman 
691*b30d1939SAndy Fiddaman static int
umeinit(void)692*b30d1939SAndy Fiddaman umeinit(void)
693*b30d1939SAndy Fiddaman {
694*b30d1939SAndy Fiddaman 	register const unsigned char*	s;
695*b30d1939SAndy Fiddaman 	register int			i;
696*b30d1939SAndy Fiddaman 	register int			c;
697*b30d1939SAndy Fiddaman 
698*b30d1939SAndy Fiddaman 	if (!ume_d[ume_D[0]])
699*b30d1939SAndy Fiddaman 	{
700*b30d1939SAndy Fiddaman 		s = ume_D;
701*b30d1939SAndy Fiddaman 		while (c = *s++)
702*b30d1939SAndy Fiddaman 			ume_d[c] = 1;
703*b30d1939SAndy Fiddaman 		memset(ume_m, NOE, sizeof(ume_m));
704*b30d1939SAndy Fiddaman 		for (i = 0; c = ume_M[i]; i++)
705*b30d1939SAndy Fiddaman 			ume_m[c] = i;
706*b30d1939SAndy Fiddaman 	}
707*b30d1939SAndy Fiddaman 	return 0;
708*b30d1939SAndy Fiddaman }
709*b30d1939SAndy Fiddaman 
710*b30d1939SAndy Fiddaman /*
711*b30d1939SAndy Fiddaman  * convert utf-7 to bin
712*b30d1939SAndy Fiddaman  */
713*b30d1939SAndy Fiddaman 
714*b30d1939SAndy Fiddaman static size_t
ume2bin(_ast_iconv_t cd,char ** fb,size_t * fn,char ** tb,size_t * tn)715*b30d1939SAndy Fiddaman ume2bin(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
716*b30d1939SAndy Fiddaman {
717*b30d1939SAndy Fiddaman 	register unsigned char*		f;
718*b30d1939SAndy Fiddaman 	register unsigned char*		fe;
719*b30d1939SAndy Fiddaman 	register unsigned char*		t;
720*b30d1939SAndy Fiddaman 	register unsigned char*		te;
721*b30d1939SAndy Fiddaman 	register unsigned char*		p;
722*b30d1939SAndy Fiddaman 	register int			s;
723*b30d1939SAndy Fiddaman 	register int			c;
724*b30d1939SAndy Fiddaman 	register int			w;
725*b30d1939SAndy Fiddaman 	size_t				n;
726*b30d1939SAndy Fiddaman 	int				e;
727*b30d1939SAndy Fiddaman 
728*b30d1939SAndy Fiddaman 	e = 0;
729*b30d1939SAndy Fiddaman 	UMEINIT();
730*b30d1939SAndy Fiddaman 	f = (unsigned char*)(*fb);
731*b30d1939SAndy Fiddaman 	fe = f + (*fn);
732*b30d1939SAndy Fiddaman 	t = (unsigned char*)(*tb);
733*b30d1939SAndy Fiddaman 	te = t + (*tn);
734*b30d1939SAndy Fiddaman 	s = 0;
735*b30d1939SAndy Fiddaman 	while (f < fe && t < te)
736*b30d1939SAndy Fiddaman 	{
737*b30d1939SAndy Fiddaman 		p = f;
738*b30d1939SAndy Fiddaman 		c = *f++;
739*b30d1939SAndy Fiddaman 		if (s)
740*b30d1939SAndy Fiddaman 		{
741*b30d1939SAndy Fiddaman 			if (c == '-' && s > 1)
742*b30d1939SAndy Fiddaman 				s = 0;
743*b30d1939SAndy Fiddaman 			else if ((w = ume_m[c]) == NOE)
744*b30d1939SAndy Fiddaman 			{
745*b30d1939SAndy Fiddaman 				s = 0;
746*b30d1939SAndy Fiddaman 				*t++ = c;
747*b30d1939SAndy Fiddaman 			}
748*b30d1939SAndy Fiddaman 			else if (f >= (fe - 2))
749*b30d1939SAndy Fiddaman 			{
750*b30d1939SAndy Fiddaman 				f = p;
751*b30d1939SAndy Fiddaman 				e = EINVAL;
752*b30d1939SAndy Fiddaman 				break;
753*b30d1939SAndy Fiddaman 			}
754*b30d1939SAndy Fiddaman 			else
755*b30d1939SAndy Fiddaman 			{
756*b30d1939SAndy Fiddaman 				s = 2;
757*b30d1939SAndy Fiddaman 				w = (w << 6) | ume_m[*f++];
758*b30d1939SAndy Fiddaman 				w = (w << 6) | ume_m[*f++];
759*b30d1939SAndy Fiddaman 				if (!(w & ~0xFF))
760*b30d1939SAndy Fiddaman 					*t++ = w;
761*b30d1939SAndy Fiddaman 				else if (t >= (te - 1))
762*b30d1939SAndy Fiddaman 				{
763*b30d1939SAndy Fiddaman 					f = p;
764*b30d1939SAndy Fiddaman 					e = E2BIG;
765*b30d1939SAndy Fiddaman 					break;
766*b30d1939SAndy Fiddaman 				}
767*b30d1939SAndy Fiddaman 				else
768*b30d1939SAndy Fiddaman 				{
769*b30d1939SAndy Fiddaman 					*t++ = (w >> 8) & 0xFF;
770*b30d1939SAndy Fiddaman 					*t++ = w & 0xFF;
771*b30d1939SAndy Fiddaman 				}
772*b30d1939SAndy Fiddaman 			}
773*b30d1939SAndy Fiddaman 		}
774*b30d1939SAndy Fiddaman 		else if (c == '+')
775*b30d1939SAndy Fiddaman 			s = 1;
776*b30d1939SAndy Fiddaman 		else
777*b30d1939SAndy Fiddaman 			*t++ = c;
778*b30d1939SAndy Fiddaman 	}
779*b30d1939SAndy Fiddaman 	*fn -= (char*)f - (*fb);
780*b30d1939SAndy Fiddaman 	*fb = (char*)f;
781*b30d1939SAndy Fiddaman 	*tn -= (n = (char*)t - (*tb));
782*b30d1939SAndy Fiddaman 	*tb = (char*)t;
783*b30d1939SAndy Fiddaman 	RETURN(e, n, fn);
784*b30d1939SAndy Fiddaman }
785*b30d1939SAndy Fiddaman 
786*b30d1939SAndy Fiddaman /*
787*b30d1939SAndy Fiddaman  * convert bin to utf-7
788*b30d1939SAndy Fiddaman  */
789*b30d1939SAndy Fiddaman 
790*b30d1939SAndy Fiddaman static size_t
bin2ume(_ast_iconv_t cd,char ** fb,size_t * fn,char ** tb,size_t * tn)791*b30d1939SAndy Fiddaman bin2ume(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
792*b30d1939SAndy Fiddaman {
793*b30d1939SAndy Fiddaman 	register unsigned char*		f;
794*b30d1939SAndy Fiddaman 	register unsigned char*		fe;
795*b30d1939SAndy Fiddaman 	register unsigned char*		t;
796*b30d1939SAndy Fiddaman 	register unsigned char*		te;
797*b30d1939SAndy Fiddaman 	register int			c;
798*b30d1939SAndy Fiddaman 	register int			s;
799*b30d1939SAndy Fiddaman 	wchar_t				w;
800*b30d1939SAndy Fiddaman 	size_t				n;
801*b30d1939SAndy Fiddaman 	int				e;
802*b30d1939SAndy Fiddaman 
803*b30d1939SAndy Fiddaman 	e = 0;
804*b30d1939SAndy Fiddaman 	UMEINIT();
805*b30d1939SAndy Fiddaman 	f = (unsigned char*)(*fb);
806*b30d1939SAndy Fiddaman 	fe = f + (*fn);
807*b30d1939SAndy Fiddaman 	t = (unsigned char*)(*tb);
808*b30d1939SAndy Fiddaman 	te = t + (*tn);
809*b30d1939SAndy Fiddaman 	s = 0;
810*b30d1939SAndy Fiddaman 	while (f < fe && t < (te - s))
811*b30d1939SAndy Fiddaman 	{
812*b30d1939SAndy Fiddaman 		if (!mbwide())
813*b30d1939SAndy Fiddaman 		{
814*b30d1939SAndy Fiddaman 			c = 1;
815*b30d1939SAndy Fiddaman 			w = *f;
816*b30d1939SAndy Fiddaman 		}
817*b30d1939SAndy Fiddaman 		else if ((c = (*_ast_info.mb_towc)(&w, (char*)f, fe - f)) < 0)
818*b30d1939SAndy Fiddaman 		{
819*b30d1939SAndy Fiddaman 			e = EINVAL;
820*b30d1939SAndy Fiddaman 			break;
821*b30d1939SAndy Fiddaman 		}
822*b30d1939SAndy Fiddaman 		else if (!c)
823*b30d1939SAndy Fiddaman 			c = 1;
824*b30d1939SAndy Fiddaman 		if (!(w & ~0x7F) && ume_d[w])
825*b30d1939SAndy Fiddaman 		{
826*b30d1939SAndy Fiddaman 			if (s)
827*b30d1939SAndy Fiddaman 			{
828*b30d1939SAndy Fiddaman 				s = 0;
829*b30d1939SAndy Fiddaman 				*t++ = '-';
830*b30d1939SAndy Fiddaman 			}
831*b30d1939SAndy Fiddaman 			*t++ = w;
832*b30d1939SAndy Fiddaman 		}
833*b30d1939SAndy Fiddaman 		else if (t >= (te - (4 + s)))
834*b30d1939SAndy Fiddaman 		{
835*b30d1939SAndy Fiddaman 			e = E2BIG;
836*b30d1939SAndy Fiddaman 			break;
837*b30d1939SAndy Fiddaman 		}
838*b30d1939SAndy Fiddaman 		else
839*b30d1939SAndy Fiddaman 		{
840*b30d1939SAndy Fiddaman 			if (!s)
841*b30d1939SAndy Fiddaman 			{
842*b30d1939SAndy Fiddaman 				s = 1;
843*b30d1939SAndy Fiddaman 				*t++ = '+';
844*b30d1939SAndy Fiddaman 			}
845*b30d1939SAndy Fiddaman 			*t++ = ume_M[(w >> 12) & 0x3F];
846*b30d1939SAndy Fiddaman 			*t++ = ume_M[(w >> 6) & 0x3F];
847*b30d1939SAndy Fiddaman 			*t++ = ume_M[w & 0x3F];
848*b30d1939SAndy Fiddaman 		}
849*b30d1939SAndy Fiddaman 		f += c;
850*b30d1939SAndy Fiddaman 	}
851*b30d1939SAndy Fiddaman 	if (s)
852*b30d1939SAndy Fiddaman 		*t++ = '-';
853*b30d1939SAndy Fiddaman 	*fn -= (n = (char*)f - (*fb));
854*b30d1939SAndy Fiddaman 	*fb = (char*)f;
855*b30d1939SAndy Fiddaman 	*tn -= (char*)t - (*tb);
856*b30d1939SAndy Fiddaman 	*tb = (char*)t;
857*b30d1939SAndy Fiddaman 	RETURN(e, n, fn);
858*b30d1939SAndy Fiddaman }
859*b30d1939SAndy Fiddaman 
860*b30d1939SAndy Fiddaman /*
861*b30d1939SAndy Fiddaman  * convert ucs-2 to bin with no byte swap
862*b30d1939SAndy Fiddaman  */
863*b30d1939SAndy Fiddaman 
864*b30d1939SAndy Fiddaman static size_t
ucs2bin(_ast_iconv_t cd,char ** fb,size_t * fn,char ** tb,size_t * tn)865*b30d1939SAndy Fiddaman ucs2bin(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
866*b30d1939SAndy Fiddaman {
867*b30d1939SAndy Fiddaman 	register unsigned char*		f;
868*b30d1939SAndy Fiddaman 	register unsigned char*		fe;
869*b30d1939SAndy Fiddaman 	register unsigned char*		t;
870*b30d1939SAndy Fiddaman 	register unsigned char*		te;
871*b30d1939SAndy Fiddaman 	register int			w;
872*b30d1939SAndy Fiddaman 	size_t				n;
873*b30d1939SAndy Fiddaman 	int				e;
874*b30d1939SAndy Fiddaman 
875*b30d1939SAndy Fiddaman 	e = 0;
876*b30d1939SAndy Fiddaman 	f = (unsigned char*)(*fb);
877*b30d1939SAndy Fiddaman 	fe = f + (*fn);
878*b30d1939SAndy Fiddaman 	t = (unsigned char*)(*tb);
879*b30d1939SAndy Fiddaman 	te = t + (*tn);
880*b30d1939SAndy Fiddaman 	while (f < (fe - 1) && t < te)
881*b30d1939SAndy Fiddaman 	{
882*b30d1939SAndy Fiddaman 		w = *f++;
883*b30d1939SAndy Fiddaman 		w = (w << 8) | *f++;
884*b30d1939SAndy Fiddaman 		if (!(w & ~0xFF))
885*b30d1939SAndy Fiddaman 			*t++ = w;
886*b30d1939SAndy Fiddaman 		else if (t >= (te - 1))
887*b30d1939SAndy Fiddaman 		{
888*b30d1939SAndy Fiddaman 			f -= 2;
889*b30d1939SAndy Fiddaman 			e = E2BIG;
890*b30d1939SAndy Fiddaman 			break;
891*b30d1939SAndy Fiddaman 		}
892*b30d1939SAndy Fiddaman 		else
893*b30d1939SAndy Fiddaman 		{
894*b30d1939SAndy Fiddaman 			*t++ = (w >> 8) & 0xFF;
895*b30d1939SAndy Fiddaman 			*t++ = w & 0xFF;
896*b30d1939SAndy Fiddaman 		}
897*b30d1939SAndy Fiddaman 	}
898*b30d1939SAndy Fiddaman 	*fn -= (char*)f - (*fb);
899*b30d1939SAndy Fiddaman 	*fb = (char*)f;
900*b30d1939SAndy Fiddaman 	*tn -= (n = (char*)t - (*tb));
901*b30d1939SAndy Fiddaman 	*tb = (char*)t;
902*b30d1939SAndy Fiddaman 	RETURN(e, n, fn);
903*b30d1939SAndy Fiddaman }
904*b30d1939SAndy Fiddaman 
905*b30d1939SAndy Fiddaman /*
906*b30d1939SAndy Fiddaman  * convert bin to ucs-2 with no byte swap
907*b30d1939SAndy Fiddaman  */
908*b30d1939SAndy Fiddaman 
909*b30d1939SAndy Fiddaman static size_t
bin2ucs(_ast_iconv_t cd,char ** fb,size_t * fn,char ** tb,size_t * tn)910*b30d1939SAndy Fiddaman bin2ucs(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
911*b30d1939SAndy Fiddaman {
912*b30d1939SAndy Fiddaman 	register unsigned char*		f;
913*b30d1939SAndy Fiddaman 	register unsigned char*		fe;
914*b30d1939SAndy Fiddaman 	register unsigned char*		t;
915*b30d1939SAndy Fiddaman 	register unsigned char*		te;
916*b30d1939SAndy Fiddaman 	register int			c;
917*b30d1939SAndy Fiddaman 	wchar_t				w;
918*b30d1939SAndy Fiddaman 	size_t				n;
919*b30d1939SAndy Fiddaman 	int				e;
920*b30d1939SAndy Fiddaman 
921*b30d1939SAndy Fiddaman 	e = 0;
922*b30d1939SAndy Fiddaman 	f = (unsigned char*)(*fb);
923*b30d1939SAndy Fiddaman 	fe = f + (*fn);
924*b30d1939SAndy Fiddaman 	t = (unsigned char*)(*tb);
925*b30d1939SAndy Fiddaman 	te = t + (*tn);
926*b30d1939SAndy Fiddaman 	while (f < fe && t < (te - 1))
927*b30d1939SAndy Fiddaman 	{
928*b30d1939SAndy Fiddaman 		if (!mbwide())
929*b30d1939SAndy Fiddaman 		{
930*b30d1939SAndy Fiddaman 			c = 1;
931*b30d1939SAndy Fiddaman 			w = *f;
932*b30d1939SAndy Fiddaman 		}
933*b30d1939SAndy Fiddaman 		if ((c = (*_ast_info.mb_towc)(&w, (char*)f, fe - f)) < 0)
934*b30d1939SAndy Fiddaman 		{
935*b30d1939SAndy Fiddaman 			e = EINVAL;
936*b30d1939SAndy Fiddaman 			break;
937*b30d1939SAndy Fiddaman 		}
938*b30d1939SAndy Fiddaman 		else if (!c)
939*b30d1939SAndy Fiddaman 			c = 1;
940*b30d1939SAndy Fiddaman 		*t++ = (w >> 8) & 0xFF;
941*b30d1939SAndy Fiddaman 		*t++ = w & 0xFF;
942*b30d1939SAndy Fiddaman 		f += c;
943*b30d1939SAndy Fiddaman 	}
944*b30d1939SAndy Fiddaman 	*fn -= (n = (char*)f - (*fb));
945*b30d1939SAndy Fiddaman 	*fb = (char*)f;
946*b30d1939SAndy Fiddaman 	*tn -= (char*)t - (*tb);
947*b30d1939SAndy Fiddaman 	*tb = (char*)t;
948*b30d1939SAndy Fiddaman 	RETURN(e, n, fn);
949*b30d1939SAndy Fiddaman }
950*b30d1939SAndy Fiddaman 
951*b30d1939SAndy Fiddaman /*
952*b30d1939SAndy Fiddaman  * convert ucs-2 to bin with byte swap
953*b30d1939SAndy Fiddaman  */
954*b30d1939SAndy Fiddaman 
955*b30d1939SAndy Fiddaman static size_t
scu2bin(_ast_iconv_t cd,char ** fb,size_t * fn,char ** tb,size_t * tn)956*b30d1939SAndy Fiddaman scu2bin(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
957*b30d1939SAndy Fiddaman {
958*b30d1939SAndy Fiddaman 	register unsigned char*		f;
959*b30d1939SAndy Fiddaman 	register unsigned char*		fe;
960*b30d1939SAndy Fiddaman 	register unsigned char*		t;
961*b30d1939SAndy Fiddaman 	register unsigned char*		te;
962*b30d1939SAndy Fiddaman 	register int			w;
963*b30d1939SAndy Fiddaman 	size_t				n;
964*b30d1939SAndy Fiddaman 	int				e;
965*b30d1939SAndy Fiddaman 
966*b30d1939SAndy Fiddaman 	e = 0;
967*b30d1939SAndy Fiddaman 	f = (unsigned char*)(*fb);
968*b30d1939SAndy Fiddaman 	fe = f + (*fn);
969*b30d1939SAndy Fiddaman 	t = (unsigned char*)(*tb);
970*b30d1939SAndy Fiddaman 	te = t + (*tn);
971*b30d1939SAndy Fiddaman 	while (f < (fe - 1) && t < te)
972*b30d1939SAndy Fiddaman 	{
973*b30d1939SAndy Fiddaman 		w = *f++;
974*b30d1939SAndy Fiddaman 		w = w | (*f++ << 8);
975*b30d1939SAndy Fiddaman 		if (!(w & ~0xFF))
976*b30d1939SAndy Fiddaman 			*t++ = w;
977*b30d1939SAndy Fiddaman 		else if (t >= (te - 1))
978*b30d1939SAndy Fiddaman 		{
979*b30d1939SAndy Fiddaman 			f -= 2;
980*b30d1939SAndy Fiddaman 			e = E2BIG;
981*b30d1939SAndy Fiddaman 			break;
982*b30d1939SAndy Fiddaman 		}
983*b30d1939SAndy Fiddaman 		else
984*b30d1939SAndy Fiddaman 		{
985*b30d1939SAndy Fiddaman 			*t++ = (w >> 8) & 0xFF;
986*b30d1939SAndy Fiddaman 			*t++ = w & 0xFF;
987*b30d1939SAndy Fiddaman 		}
988*b30d1939SAndy Fiddaman 	}
989*b30d1939SAndy Fiddaman 	*fn -= (char*)f - (*fb);
990*b30d1939SAndy Fiddaman 	*fb = (char*)f;
991*b30d1939SAndy Fiddaman 	*tn -= (n = (char*)t - (*tb));
992*b30d1939SAndy Fiddaman 	*tb = (char*)t;
993*b30d1939SAndy Fiddaman 	RETURN(e, n, fn);
994*b30d1939SAndy Fiddaman }
995*b30d1939SAndy Fiddaman 
996*b30d1939SAndy Fiddaman /*
997*b30d1939SAndy Fiddaman  * convert bin to ucs-2 with byte swap
998*b30d1939SAndy Fiddaman  */
999*b30d1939SAndy Fiddaman 
1000*b30d1939SAndy Fiddaman static size_t
bin2scu(_ast_iconv_t cd,char ** fb,size_t * fn,char ** tb,size_t * tn)1001*b30d1939SAndy Fiddaman bin2scu(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
1002*b30d1939SAndy Fiddaman {
1003*b30d1939SAndy Fiddaman 	register unsigned char*		f;
1004*b30d1939SAndy Fiddaman 	register unsigned char*		fe;
1005*b30d1939SAndy Fiddaman 	register unsigned char*		t;
1006*b30d1939SAndy Fiddaman 	register unsigned char*		te;
1007*b30d1939SAndy Fiddaman 	register int			c;
1008*b30d1939SAndy Fiddaman 	wchar_t				w;
1009*b30d1939SAndy Fiddaman 	size_t				n;
1010*b30d1939SAndy Fiddaman 	int				e;
1011*b30d1939SAndy Fiddaman 
1012*b30d1939SAndy Fiddaman 	e = 0;
1013*b30d1939SAndy Fiddaman 	f = (unsigned char*)(*fb);
1014*b30d1939SAndy Fiddaman 	fe = f + (*fn);
1015*b30d1939SAndy Fiddaman 	t = (unsigned char*)(*tb);
1016*b30d1939SAndy Fiddaman 	te = t + (*tn);
1017*b30d1939SAndy Fiddaman 	while (f < fe && t < (te - 1))
1018*b30d1939SAndy Fiddaman 	{
1019*b30d1939SAndy Fiddaman 		if (!mbwide())
1020*b30d1939SAndy Fiddaman 		{
1021*b30d1939SAndy Fiddaman 			c = 1;
1022*b30d1939SAndy Fiddaman 			w = *f;
1023*b30d1939SAndy Fiddaman 		}
1024*b30d1939SAndy Fiddaman 		else if ((c = (*_ast_info.mb_towc)(&w, (char*)f, fe - f)) < 0)
1025*b30d1939SAndy Fiddaman 		{
1026*b30d1939SAndy Fiddaman 			e = EINVAL;
1027*b30d1939SAndy Fiddaman 			break;
1028*b30d1939SAndy Fiddaman 		}
1029*b30d1939SAndy Fiddaman 		else if (!c)
1030*b30d1939SAndy Fiddaman 			c = 1;
1031*b30d1939SAndy Fiddaman 		*t++ = w & 0xFF;
1032*b30d1939SAndy Fiddaman 		*t++ = (w >> 8) & 0xFF;
1033*b30d1939SAndy Fiddaman 		f += c;
1034*b30d1939SAndy Fiddaman 	}
1035*b30d1939SAndy Fiddaman 	*fn -= (n = (char*)f - (*fb));
1036*b30d1939SAndy Fiddaman 	*fb = (char*)f;
1037*b30d1939SAndy Fiddaman 	*tn -= (char*)t - (*tb);
1038*b30d1939SAndy Fiddaman 	*tb = (char*)t;
1039*b30d1939SAndy Fiddaman 	RETURN(e, n, fn);
1040*b30d1939SAndy Fiddaman }
1041*b30d1939SAndy Fiddaman 
1042*b30d1939SAndy Fiddaman /*
1043*b30d1939SAndy Fiddaman  * open a character code conversion map from f to t
1044*b30d1939SAndy Fiddaman  */
1045*b30d1939SAndy Fiddaman 
1046*b30d1939SAndy Fiddaman _ast_iconv_t
_ast_iconv_open(const char * t,const char * f)1047*b30d1939SAndy Fiddaman _ast_iconv_open(const char* t, const char* f)
1048*b30d1939SAndy Fiddaman {
1049*b30d1939SAndy Fiddaman 	register Conv_t*	cc;
1050*b30d1939SAndy Fiddaman 	int			fc;
1051*b30d1939SAndy Fiddaman 	int			tc;
1052*b30d1939SAndy Fiddaman 	int			i;
1053*b30d1939SAndy Fiddaman 
1054*b30d1939SAndy Fiddaman 	char			fr[64];
1055*b30d1939SAndy Fiddaman 	char			to[64];
1056*b30d1939SAndy Fiddaman 
1057*b30d1939SAndy Fiddaman #if DEBUG_TRACE
1058*b30d1939SAndy Fiddaman error(DEBUG_TRACE, "AHA#%d _ast_iconv_open f=%s t=%s\n", __LINE__, f, t);
1059*b30d1939SAndy Fiddaman #endif
1060*b30d1939SAndy Fiddaman 	if (!t || !*t || *t == '-' && !*(t + 1) || !strcasecmp(t, name_local) || !strcasecmp(t, name_native))
1061*b30d1939SAndy Fiddaman 		t = name_native;
1062*b30d1939SAndy Fiddaman 	if (!f || !*f || *f == '-' && !*(f + 1) || !strcasecmp(t, name_local) || !strcasecmp(f, name_native))
1063*b30d1939SAndy Fiddaman 		f = name_native;
1064*b30d1939SAndy Fiddaman 
1065*b30d1939SAndy Fiddaman 	/*
1066*b30d1939SAndy Fiddaman 	 * the ast identify is always (iconv_t)(0)
1067*b30d1939SAndy Fiddaman 	 */
1068*b30d1939SAndy Fiddaman 
1069*b30d1939SAndy Fiddaman 	if (t == f)
1070*b30d1939SAndy Fiddaman 		return (iconv_t)(0);
1071*b30d1939SAndy Fiddaman 	fc = _ast_iconv_name(f, fr, sizeof(fr));
1072*b30d1939SAndy Fiddaman 	tc = _ast_iconv_name(t, to, sizeof(to));
1073*b30d1939SAndy Fiddaman #if DEBUG_TRACE
1074*b30d1939SAndy Fiddaman error(DEBUG_TRACE, "AHA#%d _ast_iconv_open f=%s:%s:%d t=%s:%s:%d\n", __LINE__, f, fr, fc, t, to, tc);
1075*b30d1939SAndy Fiddaman #endif
1076*b30d1939SAndy Fiddaman 	if (fc != CC_ICONV && fc == tc || streq(fr, to))
1077*b30d1939SAndy Fiddaman 		return (iconv_t)(0);
1078*b30d1939SAndy Fiddaman 
1079*b30d1939SAndy Fiddaman 	/*
1080*b30d1939SAndy Fiddaman 	 * first check the free list
1081*b30d1939SAndy Fiddaman 	 */
1082*b30d1939SAndy Fiddaman 
1083*b30d1939SAndy Fiddaman 	for (i = 0; i < elementsof(freelist); i++)
1084*b30d1939SAndy Fiddaman 		if ((cc = freelist[i]) && streq(to, cc->to.name) && streq(fr, cc->from.name))
1085*b30d1939SAndy Fiddaman 		{
1086*b30d1939SAndy Fiddaman 			freelist[i] = 0;
1087*b30d1939SAndy Fiddaman #if _lib_iconv_open
1088*b30d1939SAndy Fiddaman 			/*
1089*b30d1939SAndy Fiddaman 			 * reset the shift state if any
1090*b30d1939SAndy Fiddaman 			 */
1091*b30d1939SAndy Fiddaman 
1092*b30d1939SAndy Fiddaman 			if (cc->cvt != (iconv_t)(-1))
1093*b30d1939SAndy Fiddaman 				iconv(cc->cvt, NiL, NiL, NiL, NiL);
1094*b30d1939SAndy Fiddaman #endif
1095*b30d1939SAndy Fiddaman 			return cc;
1096*b30d1939SAndy Fiddaman 		}
1097*b30d1939SAndy Fiddaman 
1098*b30d1939SAndy Fiddaman 	/*
1099*b30d1939SAndy Fiddaman 	 * allocate a new one
1100*b30d1939SAndy Fiddaman 	 */
1101*b30d1939SAndy Fiddaman 
1102*b30d1939SAndy Fiddaman 	if (!(cc = newof(0, Conv_t, 1, strlen(to) + strlen(fr) + 2)))
1103*b30d1939SAndy Fiddaman 		return (iconv_t)(-1);
1104*b30d1939SAndy Fiddaman 	cc->to.name = (char*)(cc + 1);
1105*b30d1939SAndy Fiddaman 	cc->from.name = strcopy(cc->to.name, to) + 1;
1106*b30d1939SAndy Fiddaman 	strcpy(cc->from.name, fr);
1107*b30d1939SAndy Fiddaman 	cc->cvt = (iconv_t)(-1);
1108*b30d1939SAndy Fiddaman 
1109*b30d1939SAndy Fiddaman 	/*
1110*b30d1939SAndy Fiddaman 	 * 8 bit maps are the easiest
1111*b30d1939SAndy Fiddaman 	 */
1112*b30d1939SAndy Fiddaman 
1113*b30d1939SAndy Fiddaman 	if (fc >= 0 && tc >= 0)
1114*b30d1939SAndy Fiddaman 		cc->from.map = ccmap(fc, tc);
1115*b30d1939SAndy Fiddaman #if _lib_iconv_open
1116*b30d1939SAndy Fiddaman 	else if ((cc->cvt = iconv_open(t, f)) != (iconv_t)(-1) || (cc->cvt = iconv_open(to, fr)) != (iconv_t)(-1))
1117*b30d1939SAndy Fiddaman 		cc->from.fun = (_ast_iconv_f)iconv;
1118*b30d1939SAndy Fiddaman #endif
1119*b30d1939SAndy Fiddaman #if _UWIN
1120*b30d1939SAndy Fiddaman 	else if ((cc->cvt = _win_iconv_open(cc, t, f)) != (_ast_iconv_t)(-1) || (cc->cvt = _win_iconv_open(cc, to, fr)) != (_ast_iconv_t)(-1))
1121*b30d1939SAndy Fiddaman 		cc->from.fun = (_ast_iconv_f)_win_iconv;
1122*b30d1939SAndy Fiddaman #endif
1123*b30d1939SAndy Fiddaman 	else
1124*b30d1939SAndy Fiddaman 	{
1125*b30d1939SAndy Fiddaman 		switch (fc)
1126*b30d1939SAndy Fiddaman 		{
1127*b30d1939SAndy Fiddaman 		case CC_UTF:
1128*b30d1939SAndy Fiddaman 			cc->from.fun = utf2bin;
1129*b30d1939SAndy Fiddaman 			break;
1130*b30d1939SAndy Fiddaman 		case CC_UME:
1131*b30d1939SAndy Fiddaman 			cc->from.fun = ume2bin;
1132*b30d1939SAndy Fiddaman 			break;
1133*b30d1939SAndy Fiddaman 		case CC_UCS:
1134*b30d1939SAndy Fiddaman 			cc->from.fun = ucs2bin;
1135*b30d1939SAndy Fiddaman 			break;
1136*b30d1939SAndy Fiddaman 		case CC_SCU:
1137*b30d1939SAndy Fiddaman 			cc->from.fun = scu2bin;
1138*b30d1939SAndy Fiddaman 			break;
1139*b30d1939SAndy Fiddaman 		case CC_ASCII:
1140*b30d1939SAndy Fiddaman 			break;
1141*b30d1939SAndy Fiddaman 		default:
1142*b30d1939SAndy Fiddaman 			if (fc < 0)
1143*b30d1939SAndy Fiddaman 				goto nope;
1144*b30d1939SAndy Fiddaman 			cc->from.map = ccmap(fc, CC_ASCII);
1145*b30d1939SAndy Fiddaman 			break;
1146*b30d1939SAndy Fiddaman 		}
1147*b30d1939SAndy Fiddaman 		switch (tc)
1148*b30d1939SAndy Fiddaman 		{
1149*b30d1939SAndy Fiddaman 		case CC_UTF:
1150*b30d1939SAndy Fiddaman 			cc->to.fun = bin2utf;
1151*b30d1939SAndy Fiddaman 			break;
1152*b30d1939SAndy Fiddaman 		case CC_UME:
1153*b30d1939SAndy Fiddaman 			cc->to.fun = bin2ume;
1154*b30d1939SAndy Fiddaman 			break;
1155*b30d1939SAndy Fiddaman 		case CC_UCS:
1156*b30d1939SAndy Fiddaman 			cc->to.fun = bin2ucs;
1157*b30d1939SAndy Fiddaman 			break;
1158*b30d1939SAndy Fiddaman 		case CC_SCU:
1159*b30d1939SAndy Fiddaman 			cc->to.fun = bin2scu;
1160*b30d1939SAndy Fiddaman 			break;
1161*b30d1939SAndy Fiddaman 		case CC_ASCII:
1162*b30d1939SAndy Fiddaman 			break;
1163*b30d1939SAndy Fiddaman 		default:
1164*b30d1939SAndy Fiddaman 			if (tc < 0)
1165*b30d1939SAndy Fiddaman 				goto nope;
1166*b30d1939SAndy Fiddaman 			cc->to.map = ccmap(CC_ASCII, tc);
1167*b30d1939SAndy Fiddaman 			break;
1168*b30d1939SAndy Fiddaman 		}
1169*b30d1939SAndy Fiddaman 	}
1170*b30d1939SAndy Fiddaman 	return (iconv_t)cc;
1171*b30d1939SAndy Fiddaman  nope:
1172*b30d1939SAndy Fiddaman 	return (iconv_t)(-1);
1173*b30d1939SAndy Fiddaman }
1174*b30d1939SAndy Fiddaman 
1175*b30d1939SAndy Fiddaman /*
1176*b30d1939SAndy Fiddaman  * close a character code conversion map
1177*b30d1939SAndy Fiddaman  */
1178*b30d1939SAndy Fiddaman 
1179*b30d1939SAndy Fiddaman int
_ast_iconv_close(_ast_iconv_t cd)1180*b30d1939SAndy Fiddaman _ast_iconv_close(_ast_iconv_t cd)
1181*b30d1939SAndy Fiddaman {
1182*b30d1939SAndy Fiddaman 	Conv_t*	cc;
1183*b30d1939SAndy Fiddaman 	Conv_t*	oc;
1184*b30d1939SAndy Fiddaman 	int	i;
1185*b30d1939SAndy Fiddaman 	int	r = 0;
1186*b30d1939SAndy Fiddaman 
1187*b30d1939SAndy Fiddaman 	if (cd == (_ast_iconv_t)(-1))
1188*b30d1939SAndy Fiddaman 		return -1;
1189*b30d1939SAndy Fiddaman 	if (!(cc = (Conv_t*)cd))
1190*b30d1939SAndy Fiddaman 		return 0;
1191*b30d1939SAndy Fiddaman 
1192*b30d1939SAndy Fiddaman 	/*
1193*b30d1939SAndy Fiddaman 	 * add to the free list
1194*b30d1939SAndy Fiddaman 	 */
1195*b30d1939SAndy Fiddaman 
1196*b30d1939SAndy Fiddaman 	i = freeindex;
1197*b30d1939SAndy Fiddaman 	for (;;)
1198*b30d1939SAndy Fiddaman 	{
1199*b30d1939SAndy Fiddaman 		if (++ i >= elementsof(freelist))
1200*b30d1939SAndy Fiddaman 			i = 0;
1201*b30d1939SAndy Fiddaman 		if (!freelist[i])
1202*b30d1939SAndy Fiddaman 			break;
1203*b30d1939SAndy Fiddaman 		if (i == freeindex)
1204*b30d1939SAndy Fiddaman 		{
1205*b30d1939SAndy Fiddaman 			if (++ i >= elementsof(freelist))
1206*b30d1939SAndy Fiddaman 				i = 0;
1207*b30d1939SAndy Fiddaman 
1208*b30d1939SAndy Fiddaman 			/*
1209*b30d1939SAndy Fiddaman 			 * close the oldest
1210*b30d1939SAndy Fiddaman 			 */
1211*b30d1939SAndy Fiddaman 
1212*b30d1939SAndy Fiddaman 			if (oc = freelist[i])
1213*b30d1939SAndy Fiddaman 			{
1214*b30d1939SAndy Fiddaman #if _lib_iconv_open
1215*b30d1939SAndy Fiddaman 				if (oc->cvt != (iconv_t)(-1))
1216*b30d1939SAndy Fiddaman 					r = iconv_close(oc->cvt);
1217*b30d1939SAndy Fiddaman #endif
1218*b30d1939SAndy Fiddaman 				if (oc->buf)
1219*b30d1939SAndy Fiddaman 					free(oc->buf);
1220*b30d1939SAndy Fiddaman 				free(oc);
1221*b30d1939SAndy Fiddaman 			}
1222*b30d1939SAndy Fiddaman 			break;
1223*b30d1939SAndy Fiddaman 		}
1224*b30d1939SAndy Fiddaman 	}
1225*b30d1939SAndy Fiddaman 	freelist[freeindex = i] = cc;
1226*b30d1939SAndy Fiddaman 	return r;
1227*b30d1939SAndy Fiddaman }
1228*b30d1939SAndy Fiddaman 
1229*b30d1939SAndy Fiddaman /*
1230*b30d1939SAndy Fiddaman  * copy *fb size *fn to *tb size *tn
1231*b30d1939SAndy Fiddaman  * fb,fn tb,tn updated on return
1232*b30d1939SAndy Fiddaman  */
1233*b30d1939SAndy Fiddaman 
1234*b30d1939SAndy Fiddaman size_t
_ast_iconv(_ast_iconv_t cd,char ** fb,size_t * fn,char ** tb,size_t * tn)1235*b30d1939SAndy Fiddaman _ast_iconv(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
1236*b30d1939SAndy Fiddaman {
1237*b30d1939SAndy Fiddaman 	Conv_t*				cc = (Conv_t*)cd;
1238*b30d1939SAndy Fiddaman 	register unsigned char*		f;
1239*b30d1939SAndy Fiddaman 	register unsigned char*		t;
1240*b30d1939SAndy Fiddaman 	register unsigned char*		e;
1241*b30d1939SAndy Fiddaman 	register const unsigned char*	m;
1242*b30d1939SAndy Fiddaman 	register size_t			n;
1243*b30d1939SAndy Fiddaman 	char*				b;
1244*b30d1939SAndy Fiddaman 	char*				tfb;
1245*b30d1939SAndy Fiddaman 	size_t				tfn;
1246*b30d1939SAndy Fiddaman 	size_t				i;
1247*b30d1939SAndy Fiddaman 
1248*b30d1939SAndy Fiddaman 	if (!fb || !*fb)
1249*b30d1939SAndy Fiddaman 	{
1250*b30d1939SAndy Fiddaman 		/* TODO: reset to the initial state */
1251*b30d1939SAndy Fiddaman 		if (!tb || !*tb)
1252*b30d1939SAndy Fiddaman 			return 0;
1253*b30d1939SAndy Fiddaman 		/* TODO: write the initial state shift sequence */
1254*b30d1939SAndy Fiddaman 		return 0;
1255*b30d1939SAndy Fiddaman 	}
1256*b30d1939SAndy Fiddaman 	n = *tn;
1257*b30d1939SAndy Fiddaman 	if (cc)
1258*b30d1939SAndy Fiddaman 	{
1259*b30d1939SAndy Fiddaman 		if (cc->from.fun)
1260*b30d1939SAndy Fiddaman 		{
1261*b30d1939SAndy Fiddaman 			if (cc->to.fun)
1262*b30d1939SAndy Fiddaman 			{
1263*b30d1939SAndy Fiddaman 				if (!cc->buf && !(cc->buf = oldof(0, char, cc->size = SF_BUFSIZE, 0)))
1264*b30d1939SAndy Fiddaman 				{
1265*b30d1939SAndy Fiddaman 					errno = ENOMEM;
1266*b30d1939SAndy Fiddaman 					return -1;
1267*b30d1939SAndy Fiddaman 				}
1268*b30d1939SAndy Fiddaman 				b = cc->buf;
1269*b30d1939SAndy Fiddaman 				i = cc->size;
1270*b30d1939SAndy Fiddaman 				tfb = *fb;
1271*b30d1939SAndy Fiddaman 				tfn = *fn;
1272*b30d1939SAndy Fiddaman 				if ((*cc->from.fun)(cc->cvt, &tfb, &tfn, &b, &i) == (size_t)(-1))
1273*b30d1939SAndy Fiddaman 					return -1;
1274*b30d1939SAndy Fiddaman 				tfn = b - cc->buf;
1275*b30d1939SAndy Fiddaman 				tfb = cc->buf;
1276*b30d1939SAndy Fiddaman 				n = (*cc->to.fun)(cc->cvt, &tfb, &tfn, tb, tn);
1277*b30d1939SAndy Fiddaman 				i = tfb - cc->buf;
1278*b30d1939SAndy Fiddaman 				*fb += i;
1279*b30d1939SAndy Fiddaman 				*fn -= i;
1280*b30d1939SAndy Fiddaman 				return n;
1281*b30d1939SAndy Fiddaman 			}
1282*b30d1939SAndy Fiddaman 			if ((*cc->from.fun)(cc->cvt, fb, fn, tb, tn) == (size_t)(-1))
1283*b30d1939SAndy Fiddaman 				return -1;
1284*b30d1939SAndy Fiddaman 			n -= *tn;
1285*b30d1939SAndy Fiddaman 			if (m = cc->to.map)
1286*b30d1939SAndy Fiddaman 			{
1287*b30d1939SAndy Fiddaman 				e = (unsigned char*)(*tb);
1288*b30d1939SAndy Fiddaman 				for (t = e - n; t < e; t++)
1289*b30d1939SAndy Fiddaman 					*t = m[*t];
1290*b30d1939SAndy Fiddaman 			}
1291*b30d1939SAndy Fiddaman 			return n;
1292*b30d1939SAndy Fiddaman 		}
1293*b30d1939SAndy Fiddaman 		else if (cc->to.fun)
1294*b30d1939SAndy Fiddaman 		{
1295*b30d1939SAndy Fiddaman 			if (!(m = cc->from.map))
1296*b30d1939SAndy Fiddaman 				return (*cc->to.fun)(cc->cvt, fb, fn, tb, tn);
1297*b30d1939SAndy Fiddaman 			if (!cc->buf && !(cc->buf = oldof(0, char, cc->size = SF_BUFSIZE, 0)))
1298*b30d1939SAndy Fiddaman 			{
1299*b30d1939SAndy Fiddaman 				errno = ENOMEM;
1300*b30d1939SAndy Fiddaman 				return -1;
1301*b30d1939SAndy Fiddaman 			}
1302*b30d1939SAndy Fiddaman 			if ((n = *fn) > cc->size)
1303*b30d1939SAndy Fiddaman 				n = cc->size;
1304*b30d1939SAndy Fiddaman 			f = (unsigned char*)(*fb);
1305*b30d1939SAndy Fiddaman 			e = f + n;
1306*b30d1939SAndy Fiddaman 			t = (unsigned char*)(b = cc->buf);
1307*b30d1939SAndy Fiddaman 			while (f < e)
1308*b30d1939SAndy Fiddaman 				*t++ = m[*f++];
1309*b30d1939SAndy Fiddaman 			n = (*cc->to.fun)(cc->cvt, &b, fn, tb, tn);
1310*b30d1939SAndy Fiddaman 			*fb += b - cc->buf;
1311*b30d1939SAndy Fiddaman 			return n;
1312*b30d1939SAndy Fiddaman 		}
1313*b30d1939SAndy Fiddaman 	}
1314*b30d1939SAndy Fiddaman 	if (n > *fn)
1315*b30d1939SAndy Fiddaman 		n = *fn;
1316*b30d1939SAndy Fiddaman 	if (cc && (m = cc->from.map))
1317*b30d1939SAndy Fiddaman 	{
1318*b30d1939SAndy Fiddaman 		f = (unsigned char*)(*fb);
1319*b30d1939SAndy Fiddaman 		e = f + n;
1320*b30d1939SAndy Fiddaman 		t = (unsigned char*)(*tb);
1321*b30d1939SAndy Fiddaman 		while (f < e)
1322*b30d1939SAndy Fiddaman 			*t++ = m[*f++];
1323*b30d1939SAndy Fiddaman 	}
1324*b30d1939SAndy Fiddaman 	else
1325*b30d1939SAndy Fiddaman 		memcpy(*tb, *fb, n);
1326*b30d1939SAndy Fiddaman 	*fb += n;
1327*b30d1939SAndy Fiddaman 	*fn -= n;
1328*b30d1939SAndy Fiddaman 	*tb += n;
1329*b30d1939SAndy Fiddaman 	*tn -= n;
1330*b30d1939SAndy Fiddaman 	return n;
1331*b30d1939SAndy Fiddaman }
1332*b30d1939SAndy Fiddaman 
1333*b30d1939SAndy Fiddaman #define OK		((size_t)-1)
1334*b30d1939SAndy Fiddaman 
1335*b30d1939SAndy Fiddaman /*
1336*b30d1939SAndy Fiddaman  * write *fb size *fn to op
1337*b30d1939SAndy Fiddaman  * fb,fn updated on return
1338*b30d1939SAndy Fiddaman  * total bytes written to op returned
1339*b30d1939SAndy Fiddaman  */
1340*b30d1939SAndy Fiddaman 
1341*b30d1939SAndy Fiddaman ssize_t
_ast_iconv_write(_ast_iconv_t cd,Sfio_t * op,char ** fb,size_t * fn,Iconv_disc_t * disc)1342*b30d1939SAndy Fiddaman _ast_iconv_write(_ast_iconv_t cd, Sfio_t* op, char** fb, size_t* fn, Iconv_disc_t* disc)
1343*b30d1939SAndy Fiddaman {
1344*b30d1939SAndy Fiddaman 	char*		fo = *fb;
1345*b30d1939SAndy Fiddaman 	char*		tb;
1346*b30d1939SAndy Fiddaman 	char*		ts;
1347*b30d1939SAndy Fiddaman 	size_t*		e;
1348*b30d1939SAndy Fiddaman 	size_t		tn;
1349*b30d1939SAndy Fiddaman 	size_t		r;
1350*b30d1939SAndy Fiddaman 	int		ok;
1351*b30d1939SAndy Fiddaman 	Iconv_disc_t	compat;
1352*b30d1939SAndy Fiddaman 
1353*b30d1939SAndy Fiddaman 	/*
1354*b30d1939SAndy Fiddaman 	 * the old api had optional size_t* instead of Iconv_disc_t*
1355*b30d1939SAndy Fiddaman 	 */
1356*b30d1939SAndy Fiddaman 
1357*b30d1939SAndy Fiddaman 	if (!disc || disc->version < 20110101L || disc->version >= 30000101L)
1358*b30d1939SAndy Fiddaman 	{
1359*b30d1939SAndy Fiddaman 		e = (size_t*)disc;
1360*b30d1939SAndy Fiddaman 		disc = &compat;
1361*b30d1939SAndy Fiddaman 		iconv_init(disc, 0);
1362*b30d1939SAndy Fiddaman 	}
1363*b30d1939SAndy Fiddaman 	else
1364*b30d1939SAndy Fiddaman 		e = 0;
1365*b30d1939SAndy Fiddaman 	r = 0;
1366*b30d1939SAndy Fiddaman 	tn = 0;
1367*b30d1939SAndy Fiddaman 	ok = 1;
1368*b30d1939SAndy Fiddaman 	while (ok && *fn > 0)
1369*b30d1939SAndy Fiddaman 	{
1370*b30d1939SAndy Fiddaman 		if (!(tb = (char*)sfreserve(op, -(tn + 1), SF_WRITE|SF_LOCKR)) || !(tn = sfvalue(op)))
1371*b30d1939SAndy Fiddaman 		{
1372*b30d1939SAndy Fiddaman 			if (!r)
1373*b30d1939SAndy Fiddaman 				r = -1;
1374*b30d1939SAndy Fiddaman 			break;
1375*b30d1939SAndy Fiddaman 		}
1376*b30d1939SAndy Fiddaman 		ts = tb;
1377*b30d1939SAndy Fiddaman #if DEBUG_TRACE
1378*b30d1939SAndy Fiddaman error(DEBUG_TRACE, "AHA#%d iconv_write ts=%p tn=%d", __LINE__, ts, tn);
1379*b30d1939SAndy Fiddaman 		for (;;)
1380*b30d1939SAndy Fiddaman #else
1381*b30d1939SAndy Fiddaman 		while (*fn > 0 && _ast_iconv(cd, fb, fn, &ts, &tn) == (size_t)(-1))
1382*b30d1939SAndy Fiddaman #endif
1383*b30d1939SAndy Fiddaman 		{
1384*b30d1939SAndy Fiddaman #if DEBUG_TRACE
1385*b30d1939SAndy Fiddaman 			ssize_t	_r;
1386*b30d1939SAndy Fiddaman error(DEBUG_TRACE, "AHA#%d iconv_write %d => %d `%-.*s'", __LINE__, *fn, tn, *fn, *fb);
1387*b30d1939SAndy Fiddaman 			_r = _ast_iconv(cd, fb, fn, &ts, &tn);
1388*b30d1939SAndy Fiddaman error(DEBUG_TRACE, "AHA#%d iconv_write %d => %d [%d]", __LINE__, *fn, tn, _r);
1389*b30d1939SAndy Fiddaman 			if (_r != (size_t)(-1) || !fn)
1390*b30d1939SAndy Fiddaman 				break;
1391*b30d1939SAndy Fiddaman #endif
1392*b30d1939SAndy Fiddaman 			switch (errno)
1393*b30d1939SAndy Fiddaman 			{
1394*b30d1939SAndy Fiddaman 			case E2BIG:
1395*b30d1939SAndy Fiddaman 				break;
1396*b30d1939SAndy Fiddaman 			case EINVAL:
1397*b30d1939SAndy Fiddaman 				if (disc->errorf)
1398*b30d1939SAndy Fiddaman 					(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "incomplete multibyte sequence at offset %I*u", sizeof(fo), *fb - fo);
1399*b30d1939SAndy Fiddaman 				goto bad;
1400*b30d1939SAndy Fiddaman 			default:
1401*b30d1939SAndy Fiddaman 				if (disc->errorf)
1402*b30d1939SAndy Fiddaman 					(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "invalid multibyte sequence at offset %I*u", sizeof(fo), *fb - fo);
1403*b30d1939SAndy Fiddaman 			bad:
1404*b30d1939SAndy Fiddaman 				disc->errors++;
1405*b30d1939SAndy Fiddaman 				if (!(disc->flags & ICONV_FATAL))
1406*b30d1939SAndy Fiddaman 				{
1407*b30d1939SAndy Fiddaman 					if (!(disc->flags & ICONV_OMIT) && tn > 0)
1408*b30d1939SAndy Fiddaman 					{
1409*b30d1939SAndy Fiddaman 						*ts++ = (disc->fill >= 0) ? disc->fill : **fb;
1410*b30d1939SAndy Fiddaman 						tn--;
1411*b30d1939SAndy Fiddaman 					}
1412*b30d1939SAndy Fiddaman 					(*fb)++;
1413*b30d1939SAndy Fiddaman 					(*fn)--;
1414*b30d1939SAndy Fiddaman 					continue;
1415*b30d1939SAndy Fiddaman 				}
1416*b30d1939SAndy Fiddaman 				ok = 0;
1417*b30d1939SAndy Fiddaman 				break;
1418*b30d1939SAndy Fiddaman 			}
1419*b30d1939SAndy Fiddaman 			break;
1420*b30d1939SAndy Fiddaman 		}
1421*b30d1939SAndy Fiddaman #if DEBUG_TRACE
1422*b30d1939SAndy Fiddaman error(DEBUG_TRACE, "AHA#%d iconv_write %d", __LINE__, ts - tb);
1423*b30d1939SAndy Fiddaman #endif
1424*b30d1939SAndy Fiddaman 		sfwrite(op, tb, ts - tb);
1425*b30d1939SAndy Fiddaman 		r += ts - tb;
1426*b30d1939SAndy Fiddaman 	}
1427*b30d1939SAndy Fiddaman 	if (e)
1428*b30d1939SAndy Fiddaman 		*e = disc->errors;
1429*b30d1939SAndy Fiddaman 	return r;
1430*b30d1939SAndy Fiddaman }
1431*b30d1939SAndy Fiddaman 
1432*b30d1939SAndy Fiddaman /*
1433*b30d1939SAndy Fiddaman  * move n bytes from ip to op
1434*b30d1939SAndy Fiddaman  */
1435*b30d1939SAndy Fiddaman 
1436*b30d1939SAndy Fiddaman ssize_t
_ast_iconv_move(_ast_iconv_t cd,Sfio_t * ip,Sfio_t * op,size_t n,Iconv_disc_t * disc)1437*b30d1939SAndy Fiddaman _ast_iconv_move(_ast_iconv_t cd, Sfio_t* ip, Sfio_t* op, size_t n, Iconv_disc_t* disc)
1438*b30d1939SAndy Fiddaman {
1439*b30d1939SAndy Fiddaman 	char*		fb;
1440*b30d1939SAndy Fiddaman 	char*		fs;
1441*b30d1939SAndy Fiddaman 	char*		tb;
1442*b30d1939SAndy Fiddaman 	char*		ts;
1443*b30d1939SAndy Fiddaman 	size_t*		e;
1444*b30d1939SAndy Fiddaman 	size_t		fe;
1445*b30d1939SAndy Fiddaman 	size_t		fn;
1446*b30d1939SAndy Fiddaman 	size_t		fo;
1447*b30d1939SAndy Fiddaman 	size_t		ft;
1448*b30d1939SAndy Fiddaman 	size_t		tn;
1449*b30d1939SAndy Fiddaman 	size_t		i;
1450*b30d1939SAndy Fiddaman 	ssize_t		r = 0;
1451*b30d1939SAndy Fiddaman 	int		ok = 1;
1452*b30d1939SAndy Fiddaman 	int		locked;
1453*b30d1939SAndy Fiddaman 	Iconv_disc_t	compat;
1454*b30d1939SAndy Fiddaman 
1455*b30d1939SAndy Fiddaman 	/*
1456*b30d1939SAndy Fiddaman 	 * the old api had optional size_t* instead of Iconv_disc_t*
1457*b30d1939SAndy Fiddaman 	 */
1458*b30d1939SAndy Fiddaman 
1459*b30d1939SAndy Fiddaman 	if (!disc || disc->version < 20110101L || disc->version >= 30000101L)
1460*b30d1939SAndy Fiddaman 	{
1461*b30d1939SAndy Fiddaman 		e = (size_t*)disc;
1462*b30d1939SAndy Fiddaman 		disc = &compat;
1463*b30d1939SAndy Fiddaman 		iconv_init(disc, 0);
1464*b30d1939SAndy Fiddaman 	}
1465*b30d1939SAndy Fiddaman 	else
1466*b30d1939SAndy Fiddaman 		e = 0;
1467*b30d1939SAndy Fiddaman 	tb = 0;
1468*b30d1939SAndy Fiddaman 	fe = OK;
1469*b30d1939SAndy Fiddaman 	ft = 0;
1470*b30d1939SAndy Fiddaman 	fn = n;
1471*b30d1939SAndy Fiddaman 	do
1472*b30d1939SAndy Fiddaman 	{
1473*b30d1939SAndy Fiddaman 		if (n != SF_UNBOUND)
1474*b30d1939SAndy Fiddaman 			n = -((ssize_t)(n & (((size_t)(~0))>>1)));
1475*b30d1939SAndy Fiddaman 		if ((!(fb = (char*)sfreserve(ip, n, locked = SF_LOCKR)) || !(fo = sfvalue(ip))) &&
1476*b30d1939SAndy Fiddaman 		    (!(fb = (char*)sfreserve(ip, n, locked = 0)) || !(fo = sfvalue(ip))))
1477*b30d1939SAndy Fiddaman 			break;
1478*b30d1939SAndy Fiddaman 		fs = fb;
1479*b30d1939SAndy Fiddaman 		fn = fo;
1480*b30d1939SAndy Fiddaman 		if (!(tb = (char*)sfreserve(op, SF_UNBOUND, SF_WRITE|SF_LOCKR)))
1481*b30d1939SAndy Fiddaman 		{
1482*b30d1939SAndy Fiddaman 			if (!r)
1483*b30d1939SAndy Fiddaman 				r = -1;
1484*b30d1939SAndy Fiddaman 			break;
1485*b30d1939SAndy Fiddaman 		}
1486*b30d1939SAndy Fiddaman 		ts = tb;
1487*b30d1939SAndy Fiddaman 		tn = sfvalue(op);
1488*b30d1939SAndy Fiddaman 		while (fn > 0 && _ast_iconv(cd, &fs, &fn, &ts, &tn) == (size_t)(-1))
1489*b30d1939SAndy Fiddaman 		{
1490*b30d1939SAndy Fiddaman 			switch (errno)
1491*b30d1939SAndy Fiddaman 			{
1492*b30d1939SAndy Fiddaman 			case E2BIG:
1493*b30d1939SAndy Fiddaman 				break;
1494*b30d1939SAndy Fiddaman 			case EINVAL:
1495*b30d1939SAndy Fiddaman 				if (fe == ft + (fo - fn))
1496*b30d1939SAndy Fiddaman 				{
1497*b30d1939SAndy Fiddaman 					fe = OK;
1498*b30d1939SAndy Fiddaman 					if (disc->errorf)
1499*b30d1939SAndy Fiddaman 						(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "incomplete multibyte sequence at offset %I*u", sizeof(ft), ft + (fo - fn));
1500*b30d1939SAndy Fiddaman 					goto bad;
1501*b30d1939SAndy Fiddaman 				}
1502*b30d1939SAndy Fiddaman 				fe = ft;
1503*b30d1939SAndy Fiddaman 				break;
1504*b30d1939SAndy Fiddaman 			default:
1505*b30d1939SAndy Fiddaman 				if (disc->errorf)
1506*b30d1939SAndy Fiddaman 					(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "invalid multibyte sequence at offset %I*u", sizeof(ft), ft + (fo - fn));
1507*b30d1939SAndy Fiddaman 			bad:
1508*b30d1939SAndy Fiddaman 				disc->errors++;
1509*b30d1939SAndy Fiddaman 				if (!(disc->flags & ICONV_FATAL))
1510*b30d1939SAndy Fiddaman 				{
1511*b30d1939SAndy Fiddaman 					if (!(disc->flags & ICONV_OMIT) && tn > 0)
1512*b30d1939SAndy Fiddaman 					{
1513*b30d1939SAndy Fiddaman 						*ts++ = (disc->fill >= 0) ? disc->fill : *fs;
1514*b30d1939SAndy Fiddaman 						tn--;
1515*b30d1939SAndy Fiddaman 					}
1516*b30d1939SAndy Fiddaman 					fs++;
1517*b30d1939SAndy Fiddaman 					fn--;
1518*b30d1939SAndy Fiddaman 					continue;
1519*b30d1939SAndy Fiddaman 				}
1520*b30d1939SAndy Fiddaman 				ok = 0;
1521*b30d1939SAndy Fiddaman 				break;
1522*b30d1939SAndy Fiddaman 			}
1523*b30d1939SAndy Fiddaman 			break;
1524*b30d1939SAndy Fiddaman 		}
1525*b30d1939SAndy Fiddaman 		sfwrite(op, tb, ts - tb);
1526*b30d1939SAndy Fiddaman 		r += ts - tb;
1527*b30d1939SAndy Fiddaman 		ts = tb;
1528*b30d1939SAndy Fiddaman 		if (locked)
1529*b30d1939SAndy Fiddaman 			sfread(ip, fb, fs - fb);
1530*b30d1939SAndy Fiddaman 		else
1531*b30d1939SAndy Fiddaman 			for (i = fn; --i >= (fs - fb);)
1532*b30d1939SAndy Fiddaman 				sfungetc(ip, fb[i]);
1533*b30d1939SAndy Fiddaman 		if (n != SF_UNBOUND)
1534*b30d1939SAndy Fiddaman 		{
1535*b30d1939SAndy Fiddaman 			if (n <= (fs - fb))
1536*b30d1939SAndy Fiddaman 				break;
1537*b30d1939SAndy Fiddaman 			n -= fs - fb;
1538*b30d1939SAndy Fiddaman 		}
1539*b30d1939SAndy Fiddaman 		ft += (fs - fb);
1540*b30d1939SAndy Fiddaman 		if (fn == fo)
1541*b30d1939SAndy Fiddaman 			fn++;
1542*b30d1939SAndy Fiddaman 	} while (ok);
1543*b30d1939SAndy Fiddaman 	if (fb && locked)
1544*b30d1939SAndy Fiddaman 		sfread(ip, fb, 0);
1545*b30d1939SAndy Fiddaman 	if (tb)
1546*b30d1939SAndy Fiddaman 	{
1547*b30d1939SAndy Fiddaman 		sfwrite(op, tb, 0);
1548*b30d1939SAndy Fiddaman 		if (ts > tb)
1549*b30d1939SAndy Fiddaman 		{
1550*b30d1939SAndy Fiddaman 			sfwrite(op, tb, ts - tb);
1551*b30d1939SAndy Fiddaman 			r += ts - tb;
1552*b30d1939SAndy Fiddaman 		}
1553*b30d1939SAndy Fiddaman 	}
1554*b30d1939SAndy Fiddaman 	if (e)
1555*b30d1939SAndy Fiddaman 		*e = disc->errors;
1556*b30d1939SAndy Fiddaman 	return r;
1557*b30d1939SAndy Fiddaman }
1558*b30d1939SAndy Fiddaman 
1559*b30d1939SAndy Fiddaman /*
1560*b30d1939SAndy Fiddaman  * iconv_list_t iterator
1561*b30d1939SAndy Fiddaman  * call with arg 0 to start
1562*b30d1939SAndy Fiddaman  * prev return value is current arg
1563*b30d1939SAndy Fiddaman  */
1564*b30d1939SAndy Fiddaman 
1565*b30d1939SAndy Fiddaman _ast_iconv_list_t*
_ast_iconv_list(_ast_iconv_list_t * cp)1566*b30d1939SAndy Fiddaman _ast_iconv_list(_ast_iconv_list_t* cp)
1567*b30d1939SAndy Fiddaman {
1568*b30d1939SAndy Fiddaman #if _UWIN
1569*b30d1939SAndy Fiddaman 	struct dirent*	ent;
1570*b30d1939SAndy Fiddaman 
1571*b30d1939SAndy Fiddaman 	if (!cp)
1572*b30d1939SAndy Fiddaman 	{
1573*b30d1939SAndy Fiddaman 		if (!(cp = newof(0, _ast_iconv_list_t, 1, 0)))
1574*b30d1939SAndy Fiddaman 			return ccmaplist(NiL);
1575*b30d1939SAndy Fiddaman 		if (!(cp->data = opendir(_win_maps)))
1576*b30d1939SAndy Fiddaman 		{
1577*b30d1939SAndy Fiddaman 			free(cp);
1578*b30d1939SAndy Fiddaman 			return ccmaplist(NiL);
1579*b30d1939SAndy Fiddaman 		}
1580*b30d1939SAndy Fiddaman 	}
1581*b30d1939SAndy Fiddaman 	if (cp->data)
1582*b30d1939SAndy Fiddaman 	{
1583*b30d1939SAndy Fiddaman 		if (ent = readdir((DIR*)cp->data))
1584*b30d1939SAndy Fiddaman 		{
1585*b30d1939SAndy Fiddaman 			cp->name = cp->match = cp->desc = (const char*)ent->d_name;
1586*b30d1939SAndy Fiddaman 			return cp;
1587*b30d1939SAndy Fiddaman 		}
1588*b30d1939SAndy Fiddaman 		closedir((DIR*)cp->data);
1589*b30d1939SAndy Fiddaman 		free(cp);
1590*b30d1939SAndy Fiddaman 		return ccmaplist(NiL);
1591*b30d1939SAndy Fiddaman 	}
1592*b30d1939SAndy Fiddaman #else
1593*b30d1939SAndy Fiddaman 	if (!cp)
1594*b30d1939SAndy Fiddaman 		return ccmaplist(NiL);
1595*b30d1939SAndy Fiddaman #endif
1596*b30d1939SAndy Fiddaman 	if (cp->ccode >= 0)
1597*b30d1939SAndy Fiddaman 		return (cp = ccmaplist(cp)) ? cp : (_ast_iconv_list_t*)codes;
1598*b30d1939SAndy Fiddaman 	return (++cp)->name ? cp : (_ast_iconv_list_t*)0;
1599*b30d1939SAndy Fiddaman }
1600