da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1985-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Glenn Fowler
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Research
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * iconv intercept
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * minimally provides { utf*<=>bin ascii<=>ebcdic* }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "un|unicode|utf",
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "multibyte 8-bit unicode",
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "um|ume|utf?(-)7",
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "multibyte 7-bit unicode",
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "(big|euc)*",
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "euc family",
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "dos?(-)?(855)",
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "dos code page",
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "ucs?(-)?(2)?(be)|utf-16?(be)",
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "unicode runes",
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "ucs?(-)?(2)le|utf-16le",
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "little endian unicode runes",
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "UCS-%sLE",
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char _win_maps[] = "/reg/local_machine/SOFTWARE/Classes/MIME/Database/Charset";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return the codeset index given its name or alias
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * the map is in the what? oh, the registry
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char* s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinerror(DEBUG_TRACE, "AHA#%d _win_codeset name=%s", __LINE__, name);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!strcasecmp(name, "utf") || !strcasecmp(name, "utf8") || !strcasecmp(name, "utf-8"))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!strcasecmp(name, "ucs") || !strcasecmp(name, "ucs2") || !strcasecmp(name, "ucs-2"))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (name[0] == '0' && name[1] == 'x' && (n = strtol(name, &e, 0)) > 0 && !*e)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s = (char*)name;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((s[0] == 'c' || s[0] == 'C') && (s[1] == 'p' || s[1] == 'P'))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!isdigit(s[0]))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsprintf(tmp, sizeof(tmp), "%s/windows-%s", _win_maps, s);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n >= sizeof(aka))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = strtol(s, 0, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * get and check the codeset indices
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin_win_iconv_open(register Conv_t* cc, const char* t, const char* f)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinerror(DEBUG_TRACE, "AHA#%d _win_iconv_open f=%s t=%s\n", __LINE__, f, t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinerror(DEBUG_TRACE, "AHA#%d _win_iconv_open f=0x%04x t=0x%04x\n", __LINE__, cc->from.index, cc->to.index);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * even though the indices already check out
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * they could still be rejected
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin_win_iconv(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinerror(DEBUG_TRACE, "AHA#%d _win_iconv from=0x%04x to=0x%04x\n", __LINE__, cc->from.index, cc->to.index);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * from => ucs-2
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((tz = MultiByteToWideChar(cc->from.index, 0, (LPCSTR)*fb, (int)*fn, (LPWSTR)*tb, *tn)) && tz <= *tn)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * target too small
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * binary search on input size to make it fit
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (!(tz = MultiByteToWideChar(cc->from.index, 0, (LPCSTR)*fb, (int)fz, (LPWSTR)*tb, 0)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!(un = MultiByteToWideChar(cc->from.index, 0, (LPCSTR)*fb, (int)*fn, (LPWSTR)*tb, 0)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!(un = MultiByteToWideChar(cc->from.index, 0, (LPCSTR)*fb, (int)*fn, (LPWSTR)ub, un)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * ucs-2 => to
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (tz = WideCharToMultiByte(cc->to.index, 0, (LPCWSTR)ub, un, *tb, *tn, 0, 0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * target too small
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * binary search on input size to make it fit
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (!(fz = MultiByteToWideChar(cc->from.index, 0, (LPCSTR)*fb, (int)bz, (LPWSTR)ub, un)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(tz = WideCharToMultiByte(cc->to.index, 0, (LPCWSTR)ub, fz, *tb, 0, 0, 0)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(tz = WideCharToMultiByte(cc->to.index, 0, (LPCWSTR)ub, fz, *tb, tz, 0, 0)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinerror(DEBUG_TRACE, "AHA#%d _win_iconv *fn=%u fz=%u[%u] *tn=%u tz=%u\n", __LINE__, *fn, fz, fz * sizeof(WCHAR), *tn, tz);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return canonical character code set name for m
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if b!=0 then canonical name placed in b of size n
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * <ccode.h> index returned
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin_ast_iconv_name(register const char* m, register char* b, size_t n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char* e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = sizeof(buf);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e = b + n - 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinif (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);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinif (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);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (strgrpmatch(m, cp->match, sub, elementsof(sub) / 2, STR_MAXIMAL|STR_LEFT|STR_ICASE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!(cp = (const _ast_iconv_list_t*)ccmaplist((_ast_iconv_list_t*)cp)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((locales[AST_LC_CTYPE]->flags & LC_default) || !locales[AST_LC_CTYPE]->charset || !(m = locales[AST_LC_CTYPE]->charset->code) || streq(m, "iso8859-1"))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m = (const char*)"EBCDIC";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m = (const char*)"EBCDIC-I";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m = (const char*)"EBCDIC-O";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m = (const char*)"ISO-8859-1";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinif (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);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (b < e && (c = *m++))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinif (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);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * convert utf-8 to bin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinutf2bin(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int w;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f = (unsigned char*)(*fb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t = (unsigned char*)(*tb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c & 0x80)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(c & 0x40))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c & 0x20)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c & 0x40)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin w |= (c & 0x3F);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *fb = (char*)f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *tb = (char*)t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * convert bin to utf-8
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinbin2utf(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f = (unsigned char*)(*fb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t = (unsigned char*)(*tb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if ((c = (*_ast_info.mb_towc)(&w, (char*)f, fe - f)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(w & ~0x7F))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(w & ~0x7FF))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!(w & ~0xffff))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *fb = (char*)f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *tb = (char*)t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'(),-./:?!\"#$%&*;<=>@[]^_`{|} \t\n";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * initialize the ume tables
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register const unsigned char* s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int i;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (c = *s++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; c = ume_M[i]; i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * convert utf-7 to bin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinume2bin(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int w;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f = (unsigned char*)(*fb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t = (unsigned char*)(*tb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(w & ~0xFF))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *t++ = w & 0xFF;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == '+')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *fb = (char*)f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *tb = (char*)t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * convert bin to utf-7
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinbin2ume(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f = (unsigned char*)(*fb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t = (unsigned char*)(*tb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if ((c = (*_ast_info.mb_towc)(&w, (char*)f, fe - f)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *t++ = '-';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *t++ = '+';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *t++ = '-';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *fb = (char*)f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *tb = (char*)t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * convert ucs-2 to bin with no byte swap
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinucs2bin(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int w;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f = (unsigned char*)(*fb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t = (unsigned char*)(*tb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin w = (w << 8) | *f++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(w & ~0xFF))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *t++ = w & 0xFF;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *fb = (char*)f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *tb = (char*)t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * convert bin to ucs-2 with no byte swap
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinbin2ucs(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f = (unsigned char*)(*fb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t = (unsigned char*)(*tb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((c = (*_ast_info.mb_towc)(&w, (char*)f, fe - f)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *t++ = w & 0xFF;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *fb = (char*)f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *tb = (char*)t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * convert ucs-2 to bin with byte swap
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinscu2bin(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int w;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f = (unsigned char*)(*fb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t = (unsigned char*)(*tb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin w = w | (*f++ << 8);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(w & ~0xFF))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *t++ = w & 0xFF;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *fb = (char*)f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *tb = (char*)t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * convert bin to ucs-2 with byte swap
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinbin2scu(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f = (unsigned char*)(*fb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t = (unsigned char*)(*tb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if ((c = (*_ast_info.mb_towc)(&w, (char*)f, fe - f)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *t++ = w & 0xFF;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *fb = (char*)f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *tb = (char*)t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * open a character code conversion map from f to t
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinerror(DEBUG_TRACE, "AHA#%d _ast_iconv_open f=%s t=%s\n", __LINE__, f, t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!t || !*t || *t == '-' && !*(t + 1) || !strcasecmp(t, name_local) || !strcasecmp(t, name_native))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!f || !*f || *f == '-' && !*(f + 1) || !strcasecmp(t, name_local) || !strcasecmp(f, name_native))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * the ast identify is always (iconv_t)(0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (t == f)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (iconv_t)(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinerror(DEBUG_TRACE, "AHA#%d _ast_iconv_open f=%s:%s:%d t=%s:%s:%d\n", __LINE__, f, fr, fc, t, to, tc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (iconv_t)(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * first check the free list
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((cc = freelist[i]) && streq(to, cc->to.name) && streq(fr, cc->from.name))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * reset the shift state if any
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * allocate a new one
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(cc = newof(0, Conv_t, 1, strlen(to) + strlen(fr) + 2)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * 8 bit maps are the easiest
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if ((cc->cvt = iconv_open(to, fr)) != (iconv_t)(-1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if ((cc->cvt = _win_iconv_open(cc, to, fr)) != (_ast_iconv_t)(-1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * close a character code conversion map
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int r = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * add to the free list
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * close the oldest
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * copy *fb size *fn to *tb size *tn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * fb,fn tb,tn updated on return
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin_ast_iconv(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register const unsigned char* m;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register size_t n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* TODO: reset to the initial state */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* TODO: write the initial state shift sequence */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!cc->buf && !(cc->buf = oldof(0, char, cc->size = SF_BUFSIZE, 0)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((*cc->from.fun)(cc->cvt, &tfb, &tfn, &b, &i) == (size_t)(-1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((*cc->from.fun)(cc->cvt, fb, fn, tb, tn) == (size_t)(-1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e = (unsigned char*)(*tb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (t = e - n; t < e; t++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *t = m[*t];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!cc->buf && !(cc->buf = oldof(0, char, cc->size = SF_BUFSIZE, 0)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f = (unsigned char*)(*fb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e = f + n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (f < e)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *t++ = m[*f++];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f = (unsigned char*)(*fb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e = f + n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t = (unsigned char*)(*tb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (f < e)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *t++ = m[*f++];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * write *fb size *fn to op
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * fb,fn updated on return
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * total bytes written to op returned
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin_ast_iconv_write(_ast_iconv_t cd, Sfio_t* op, char** fb, size_t* fn, size_t* e)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*fn > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(tb = (char*)sfreserve(op, -(tn + 1), SF_WRITE|SF_LOCKR)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return r ? r : -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinerror(DEBUG_TRACE, "AHA#%d iconv_write ts=%p tn=%d", __LINE__, ts, tn);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (_ast_iconv(cd, fb, fn, &ts, &tn) == (size_t)(-1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinerror(DEBUG_TRACE, "AHA#%d iconv_write %d => %d `%-.*s'", __LINE__, *fn, tn, *fn, *fb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinerror(DEBUG_TRACE, "AHA#%d iconv_write %d => %d [%d]", __LINE__, *fn, tn, _r);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinerror(DEBUG_TRACE, "AHA#%d iconv_write %d", __LINE__, ts - tb);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * move n bytes from ip to op
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin_ast_iconv_move(_ast_iconv_t cd, Sfio_t* ip, Sfio_t* op, size_t n, size_t* e)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(fb = (char*)sfreserve(ip, fn, locked = SF_LOCKR)) &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(tb = (char*)sfreserve(op, SF_UNBOUND, SF_WRITE|SF_LOCKR)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return r ? r : -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (_ast_iconv(cd, &fs, &fn, &ts, &tn) != (size_t)(-1) && fn > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * iconv_list_t iterator
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * call with arg 0 to start
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * prev return value is current arg
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp->name = cp->match = cp->desc = (const char*)ent->d_name;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (cp = ccmaplist(cp)) ? cp : (_ast_iconv_list_t*)codes;