diff options
author | Jeff Johnston <jjohnstn@redhat.com> | 2004-01-23 21:37:46 +0000 |
---|---|---|
committer | Jeff Johnston <jjohnstn@redhat.com> | 2004-01-23 21:37:46 +0000 |
commit | 786ab12ce20d68e4e5ace47ccf1c0d9b0129c875 (patch) | |
tree | bb9b930ea477a5e91dc4936a240b2685677174bd /newlib/libc/iconv/lib/ces_iso2022.c | |
parent | 35b7fc6c0035075cb75997e4f60f17337333c0bc (diff) | |
download | cygnal-786ab12ce20d68e4e5ace47ccf1c0d9b0129c875.tar.gz cygnal-786ab12ce20d68e4e5ace47ccf1c0d9b0129c875.tar.bz2 cygnal-786ab12ce20d68e4e5ace47ccf1c0d9b0129c875.zip |
2004-01-23 Artem B. Bityuckiy <abitytsky@softminecorp.com>
* acinclude.m4 (--enable-newlib-iconv): New configuration option.
(--enable-newlib-builtin-converters): Ditto.
* configure.in: Add code to set _ICONV_ENABLED flag.
Set _MB_LEN_MAX to 1 if not mb enabled.
* configure: Regenerated.
* aclocal.m4: Ditto.
* Makefile.in: Ditto.
* newlib.hin: Add _ICONV_ENABLED flag.
* libc/Makefile.am: Add support for iconv.
* libc/configure.in: Ditto.
* libc/Makefile.in: Regenerated.
* libc/aclocal.m4: Ditto.
* libc/configure: Ditto.
* libc/libc.texinfo: Add iconv documentation.
* libc/iconv/AUTHORS, libc/iconv/COPYING, libc/iconv/Makefile.am,
libc/iconv/Makefile.in, libc/iconv/README.ORIGINAL,
libc/iconv/README.TODO, libc/iconv/charset.aliases,
libc/iconv/iconv.tex, libc/iconv/ccs/Makefile.am,
libc/iconv/ccs/Makefile.in, libc/iconv/ccs/README.CCS.SOURCES,
libc/iconv/ccs/big5.c, libc/iconv/ccs/cns11643_plane1.c,
libc/iconv/ccs/cns11643_plane14.c, libc/iconv/ccs/cns11643_plane2.c,
libc/iconv/ccs/cp775.c, libc/iconv/ccs/cp850.c,
libc/iconv/ccs/cp852.c, libc/iconv/ccs/cp855.c,
libc/iconv/ccs/cp866.c, libc/iconv/ccs/gb_2312_80.c,
libc/iconv/ccs/iconv_mktbl, libc/iconv/ccs/iso_8859_1.c,
libc/iconv/ccs/iso_8859_15.c, libc/iconv/ccs/iso_8859_2.c,
libc/iconv/ccs/iso_8859_4.c, libc/iconv/ccs/iso_8859_5.c,
libc/iconv/ccs/jis_x0201.c, libc/iconv/ccs/jis_x0208_1983.c,
libc/iconv/ccs/jis_x0212_1990.c, libc/iconv/ccs/koi8_r.c,
libc/iconv/ccs/koi8_u.c, libc/iconv/ccs/ksx1001.c,
libc/iconv/ccs/shift_jis.c, libc/iconv/ccs/us_ascii.c,
libc/iconv/ccs/binary/Makefile.am, libc/iconv/ccs/binary/Makefile.in,
libc/iconv/ccs/binary/big5.cct,
libc/iconv/ccs/binary/cns11643_plane1.cct,
libc/iconv/ccs/binary/cns11643_plane14.cct,
libc/iconv/ccs/binary/cns11643_plane2.cct,
libc/iconv/ccs/binary/cp775.cct, libc/iconv/ccs/binary/cp850.cct,
libc/iconv/ccs/binary/cp852.cct, libc/iconv/ccs/binary/cp855.cct,
libc/iconv/ccs/binary/cp866.cct, libc/iconv/ccs/binary/gb_2312_80.cct,
libc/iconv/ccs/binary/iso_8859_1.cct,
libc/iconv/ccs/binary/iso_8859_15.cct,
libc/iconv/ccs/binary/iso_8859_2.cct,
libc/iconv/ccs/binary/iso_8859_4.cct,
libc/iconv/ccs/binary/iso_8859_5.cct,
libc/iconv/ccs/binary/jis_x0201.cct,
libc/iconv/ccs/binary/jis_x0208_1983.cct,
libc/iconv/ccs/binary/jis_x0212_1990.cct,
libc/iconv/ccs/binary/koi8_r.cct, libc/iconv/ccs/binary/koi8_u.cct,
libc/iconv/ccs/binary/ksx1001.cct,
libc/iconv/ccs/binary/shift_jis.cct,
libc/iconv/ccs/binary/us_ascii.cct,
libc/iconv/ces/Makefile.am, libc/iconv/ces/Makefile.in,
libc/iconv/ces/euc-jp.c, libc/iconv/ces/euc-kr.c,
libc/iconv/ces/euc-tw.c, libc/iconv/ces/gb2312.c,
libc/iconv/ces/iso-10646-ucs-2.c, libc/iconv/ces/iso-10646-ucs-4.c,
libc/iconv/ces/ucs-2-internal.c, libc/iconv/ces/ucs-4-internal.c,
libc/iconv/ces/utf-16.c, libc/iconv/ces/utf-8.c,
libc/iconv/lib/Makefile.am, libc/iconv/lib/Makefile.in,
libc/iconv/lib/aliases.c, libc/iconv/lib/bialiasesi.c,
libc/iconv/lib/biccs.c, libc/iconv/lib/bices.c,
libc/iconv/lib/ccs.c, libc/iconv/lib/ces.c,
libc/iconv/lib/ces_euc.c, libc/iconv/lib/ces_iso2022.c,
libc/iconv/lib/ces_table.c, libc/iconv/lib/converter.c,
libc/iconv/lib/deps.h, libc/iconv/lib/endian.h,
libc/iconv/lib/iconv.c, libc/iconv/lib/loaddata.c,
libc/iconv/lib/local.h, libc/include/iconv.h: New files.
* libc/sys/linux/include/iconv.h: Ditto.
* libc/include/sys/_types.h (_iconv_t): Added.
* doc/aclocal.m4: Regenerated.
* doc/configure: Ditto.
* doc/Makefile.in: Ditto.
* iconvdata/Makefile.in: Ditto.
* iconvdata/aclocal.m4: Ditto.
* iconvdata/configure: Ditto.
* libc/*aclocal.m4: Ditto.
* libc/*Makefile.in: Ditto.
* libc/*configure: Ditto.
* libm/*aclocal.m4: Ditto.
* libm/*Makefile.in: Ditto.
* libm/*configure: Ditto.
Diffstat (limited to 'newlib/libc/iconv/lib/ces_iso2022.c')
-rw-r--r-- | newlib/libc/iconv/lib/ces_iso2022.c | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/newlib/libc/iconv/lib/ces_iso2022.c b/newlib/libc/iconv/lib/ces_iso2022.c new file mode 100644 index 000000000..7753db56d --- /dev/null +++ b/newlib/libc/iconv/lib/ces_iso2022.c @@ -0,0 +1,332 @@ +/*- + * Copyright (c) 1999,2000 + * Konstantin Chuguev. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * iconv (Charset Conversion Library) v2.0 + */ +#ifdef ENABLE_ICONV + +#include <_ansi.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include "local.h" + +typedef struct { + _CONST char *sequence; + size_t length; + int prefix_type; +} iconv_ces_iso2022_shift; + +enum { ICONV_PREFIX_STATE = 0, ICONV_PREFIX_LINE, ICONV_PREFIX_CHAR }; + +static _CONST iconv_ces_iso2022_shift iso_shift[] = { + { "\x0f", 1, ICONV_PREFIX_STATE }, + { "\x0e", 1, ICONV_PREFIX_LINE }, + { "\x1bN", 2, ICONV_PREFIX_CHAR }, + { "\x1bO", 2, ICONV_PREFIX_CHAR } +}; + +#define shift_num (sizeof(iso_shift) / sizeof(iconv_ces_iso2022_shift)) + +typedef struct { + int nccs; + ucs_t previous_char; + int shift_index; + int shift_tab[shift_num]; + char prefix_cache[128]; + struct iconv_ccs ccs[1]; +} iconv_ces_iso2022_state; + +int +_DEFUN(iconv_iso2022_init, (rptr, data, desc_data, num), + struct _reent *rptr _AND + _VOID_PTR *data _AND + _CONST _VOID_PTR desc_data _AND + size_t num) +{ + size_t stsz = sizeof(iconv_ces_iso2022_state) + + sizeof(struct iconv_ccs) * (num - 1); + int i; + iconv_ces_iso2022_state *state + = (iconv_ces_iso2022_state *)_malloc_r(rptr, stsz); + + if (state == NULL) + return __errno_r(rptr); + bzero(state->prefix_cache, sizeof(state->prefix_cache)); + for (i = 0; i < num; i++) { + _CONST iconv_ces_iso2022_ccs *ccsattr = + &(((_CONST iconv_ces_iso2022_ccs *)desc_data)[i]); + int res = iconv_ccs_init(rptr, &(state->ccs[i]), ccsattr->name); + if (res) { + while (--i >= 0) + state->ccs[i].close(rptr, &(state->ccs[i])); + _free_r(rptr, state); + return res; + } + if (ccsattr->designatorlen) + state->prefix_cache[(int)ccsattr->designator[0]] = 1; + if (ccsattr->shift >= 0) + state->prefix_cache[(int)iso_shift[ccsattr->shift].sequence[0]] = 1; + } + state->nccs = num; + iconv_iso2022_reset(state); + (iconv_ces_iso2022_state *)*data = state; + return 0; +} + +#define state ((iconv_ces_iso2022_state *)data) + +int +_DEFUN(iconv_iso2022_close, (rptr, data), + struct _reent *rptr _AND + _VOID_PTR data) +{ + int i, res = 0; + + for (i = 0; i < state->nccs; i++) + res = state->ccs[i].close(rptr, &(state->ccs[i])) || res; + _free_r(rptr, data); + return res; +} + +_VOID +_DEFUN(iconv_iso2022_reset, (data), _VOID_PTR data) +{ + size_t i; + + state->shift_index = 0; + state->shift_tab[0] = 0; + for (i = 1; i < shift_num; i++) + state->shift_tab[i] = -1; + state->previous_char = UCS_CHAR_NONE; +} + +#undef state + +#define CES_STATE(ces) ((iconv_ces_iso2022_state *)((ces)->data)) +#define CES_CCSATTR(ces) ((_CONST iconv_ces_iso2022_ccs *) \ + (((struct iconv_ces_desc *)((ces)->desc))->data)) + +static _VOID +_DEFUN(update_shift_state, (ces, ch), + _CONST struct iconv_ces *ces _AND + ucs_t ch) +{ + iconv_ces_iso2022_state *iso_state = CES_STATE(ces); + size_t i; + + if (ch == '\n' && iso_state->previous_char == '\r') { + for (i = 0; i < shift_num; i ++) { + if (iso_shift[i].prefix_type != ICONV_PREFIX_STATE) + iso_state->shift_tab[i] = -1; + } + } + iso_state->previous_char = ch; +} + +#define is_7_14bit(ccs) ((ccs)->nbits & 7) + +static ssize_t +_DEFUN(cvt_ucs2iso, (ces, in, outbuf, outbytesleft, cs), + _CONST struct iconv_ces *ces _AND + ucs_t in _AND + unsigned char **outbuf _AND + size_t *outbytesleft _AND + int cs) +{ + iconv_ces_iso2022_state *iso_state = CES_STATE(ces); + _CONST iconv_ces_iso2022_ccs *ccsattr; + _CONST struct iconv_ccs *ccs; + ucs_t res; + size_t len = 0; + int need_designator, need_shift; + + ccs = &(iso_state->ccs[cs]); + res = (in == UCS_CHAR_NONE) ? + in : ICONV_CCS_CONVERT_FROM_UCS(ccs, in); + if (in != UCS_CHAR_NONE) { + if (iso_shift[cs].prefix_type == ICONV_PREFIX_CHAR && + !is_7_14bit(ccs)) { + if ((res & 0x8080) == 0) + return -1; + res &= 0x7F7F; + } else if (res & 0x8080) + return -1; /* Invalid/missing character in the output charset */ + } + ccsattr = &(CES_CCSATTR(ces)[cs]); + if ((need_shift = (ccsattr->shift != iso_state->shift_index))) + len += iso_shift[ccsattr->shift].length; + if ((need_designator = (cs != iso_state->shift_tab[ccsattr->shift]))) + len += ccsattr->designatorlen; + if (in != UCS_CHAR_NONE) + len += res & 0xFF00 ? 2 : 1; + if (len > *outbytesleft) + return 0; /* No space in output buffer */ + if (need_designator && (len = ccsattr->designatorlen)) { + memcpy(*outbuf, ccsattr->designator, len); + (*outbuf) += len; + (*outbytesleft) -= len; + iso_state->shift_tab[ccsattr->shift] = cs; + } + if (need_shift && (len = iso_shift[ccsattr->shift].length)) { + memcpy(*outbuf, iso_shift[ccsattr->shift].sequence, len); + (*outbuf) += len; + (*outbytesleft) -= len; + if (iso_shift[ccsattr->shift].prefix_type != ICONV_PREFIX_CHAR) + iso_state->shift_index = ccsattr->shift; + } + if (in == UCS_CHAR_NONE) + return 1; + if (res & 0xFF00) { + *(unsigned char *)(*outbuf) ++ = res >> 8; + (*outbytesleft)--; + } + *(unsigned char *)(*outbuf) ++ = res; + (*outbytesleft) --; + update_shift_state(ces, res); + return 1; +} + +ssize_t +_DEFUN(iconv_iso2022_convert_from_ucs, (ces, in, outbuf, outbytesleft), + struct iconv_ces *ces _AND + ucs_t in _AND + unsigned char **outbuf _AND + size_t *outbytesleft) +{ + iconv_ces_iso2022_state *iso_state = CES_STATE(ces); + ssize_t res; + int cs, i; + + if (in == UCS_CHAR_NONE) + return cvt_ucs2iso(ces, in, outbuf, outbytesleft, 0); + if (iconv_char32bit(in)) + return -1; + cs = iso_state->shift_tab[iso_state->shift_index]; + if ((res = cvt_ucs2iso(ces, in, outbuf, outbytesleft, cs)) >= 0) + return res; + for (i = 0; i < iso_state->nccs; i++) { + if (i == cs) + continue; + if ((res = cvt_ucs2iso(ces, in, outbuf, outbytesleft, i)) >= 0) + return res; + } + (*outbuf) ++; + (*outbytesleft) --; + return -1; /* No character in output charset */ +} + +static ucs_t +_DEFUN(cvt_iso2ucs, (ccs, inbuf, inbytesleft, prefix_type), + _CONST struct iconv_ccs *ccs _AND + _CONST unsigned char **inbuf _AND + size_t *inbytesleft _AND + int prefix_type) +{ + size_t bytes = ccs->nbits > 8 ? 2 : 1; + ucs_t ch = **inbuf; + + if (*inbytesleft < bytes) + return UCS_CHAR_NONE; /* Not enough bytes in the input buffer */ + if (bytes == 2) + ch = (ch << 8) | *(++(*inbuf)); + (*inbuf)++; + (*inbytesleft) -= bytes; + if (ch & 0x8080) + return UCS_CHAR_INVALID; + if (prefix_type == ICONV_PREFIX_CHAR && !is_7_14bit(ccs)) + ch |= (bytes == 2) ? 0x8080 : 0x80; + return ICONV_CCS_CONVERT_TO_UCS(ccs, ch); +} + +ucs_t +_DEFUN(iconv_iso2022_convert_to_ucs, (ces, inbuf, inbytesleft), + struct iconv_ces *ces _AND + _CONST unsigned char **inbuf _AND + size_t *inbytesleft) +{ + iconv_ces_iso2022_state *iso_state = CES_STATE(ces); + _CONST iconv_ces_iso2022_ccs *ccsattr; + ucs_t res; + _CONST unsigned char *ptr = *inbuf; + unsigned char byte; + size_t len, left = *inbytesleft; + int i; + + while (left) { + byte = *ptr; + if (byte & 0x80) { + (*inbuf)++; + (*inbytesleft) --; + return UCS_CHAR_INVALID; + } + if (!iso_state->prefix_cache[byte]) + break; + for (i = 0; i < iso_state->nccs; i++) { + ccsattr = &(CES_CCSATTR(ces)[i]); + len = ccsattr->designatorlen; + if (len) { + if (len + 1 > left) + return UCS_CHAR_NONE; + if (memcmp(ptr, ccsattr->designator, len) == 0) { + iso_state->shift_tab[ccsattr->shift] = i; + ptr += len; + left -= len; + break; + } + } + len = iso_shift[ccsattr->shift].length; + if (len) { + if (len + 1 > left) + return UCS_CHAR_NONE; + if (memcmp(ptr, + iso_shift[ccsattr->shift].sequence, len) == 0) { + if (iso_shift[ccsattr->shift].prefix_type != ICONV_PREFIX_CHAR) + iso_state->shift_index = ccsattr->shift; + ptr += len; + left -= len; + break; + } + } + } + } + i = iso_state->shift_tab[iso_state->shift_index]; + if (i < 0) { + (*inbuf) ++; + (*inbytesleft) --; + return UCS_CHAR_INVALID; + } + res = cvt_iso2ucs(&(iso_state->ccs[i]), &ptr, &left, + iso_shift[i].prefix_type); + if (res != UCS_CHAR_NONE) { + *inbuf = (_CONST char*)ptr; + *inbytesleft = left; + update_shift_state(ces, res); + } + return res; +} + +#endif /* #ifdef ENABLE_ICONV */ + |