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