diff options
Diffstat (limited to 'lib/libiconv_modules')
72 files changed, 10787 insertions, 0 deletions
diff --git a/lib/libiconv_modules/BIG5/Makefile b/lib/libiconv_modules/BIG5/Makefile new file mode 100644 index 000000000000..0f755fcd582e --- /dev/null +++ b/lib/libiconv_modules/BIG5/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +SHLIB= BIG5 +SRCS+= citrus_big5.c +CFLAGS+= --param max-inline-insns-single=32 + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/BIG5/citrus_big5.c b/lib/libiconv_modules/BIG5/citrus_big5.c new file mode 100644 index 000000000000..b6ece4622012 --- /dev/null +++ b/lib/libiconv_modules/BIG5/citrus_big5.c @@ -0,0 +1,457 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_big5.c,v 1.12 2008/06/14 16:01:07 tnozaki Exp $ */ + +/*- + * Copyright (c)2002, 2006 Citrus Project, + * 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. + */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Paul Borman at Krystal Technologies. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#include <sys/cdefs.h> +#include <sys/queue.h> +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include "citrus_namespace.h" +#include "citrus_prop.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_module.h" +#include "citrus_stdenc.h" +#include "citrus_big5.h" + +/* ---------------------------------------------------------------------- + * private stuffs used by templates + */ + +typedef struct { + int chlen; + char ch[2]; +} _BIG5State; + +typedef struct _BIG5Exclude { + TAILQ_ENTRY(_BIG5Exclude) entry; + wint_t end; + wint_t start; +} _BIG5Exclude; + +typedef TAILQ_HEAD(_BIG5ExcludeList, _BIG5Exclude) _BIG5ExcludeList; + +typedef struct { + _BIG5ExcludeList excludes; + int cell[0x100]; +} _BIG5EncodingInfo; + +#define _CEI_TO_EI(_cei_) (&(_cei_)->ei) +#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_ + +#define _FUNCNAME(m) _citrus_BIG5_##m +#define _ENCODING_INFO _BIG5EncodingInfo +#define _ENCODING_STATE _BIG5State +#define _ENCODING_MB_CUR_MAX(_ei_) 2 +#define _ENCODING_IS_STATE_DEPENDENT 0 +#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0 + + +static __inline void +/*ARGSUSED*/ +_citrus_BIG5_init_state(_BIG5EncodingInfo * __restrict ei __unused, + _BIG5State * __restrict s) +{ + + memset(s, 0, sizeof(*s)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_BIG5_pack_state(_BIG5EncodingInfo * __restrict ei __unused, + void * __restrict pspriv, + const _BIG5State * __restrict s) +{ + + memcpy(pspriv, (const void *)s, sizeof(*s)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_BIG5_unpack_state(_BIG5EncodingInfo * __restrict ei __unused, + _BIG5State * __restrict s, + const void * __restrict pspriv) +{ + + memcpy((void *)s, pspriv, sizeof(*s)); +} + +static __inline int +_citrus_BIG5_check(_BIG5EncodingInfo *ei, unsigned int c) +{ + + return ((ei->cell[c & 0xFF] & 0x1) ? 2 : 1); +} + +static __inline int +_citrus_BIG5_check2(_BIG5EncodingInfo *ei, unsigned int c) +{ + + return ((ei->cell[c & 0xFF] & 0x2) ? 1 : 0); +} + +static __inline int +_citrus_BIG5_check_excludes(_BIG5EncodingInfo *ei, wint_t c) +{ + _BIG5Exclude *exclude; + + TAILQ_FOREACH(exclude, &ei->excludes, entry) { + if (c >= exclude->start && c <= exclude->end) + return (EILSEQ); + } + return (0); +} + +static int +_citrus_BIG5_fill_rowcol(void ** __restrict ctx, const char * __restrict s, + uint64_t start, uint64_t end) +{ + _BIG5EncodingInfo *ei; + uint64_t n; + int i; + + if (start > 0xFF || end > 0xFF) + return (EINVAL); + ei = (_BIG5EncodingInfo *)ctx; + i = strcmp("row", s) ? 1 : 0; + i = 1 << i; + for (n = start; n <= end; ++n) + ei->cell[n & 0xFF] |= i; + return (0); +} + +static int +/*ARGSUSED*/ +_citrus_BIG5_fill_excludes(void ** __restrict ctx, + const char * __restrict s __unused, uint64_t start, uint64_t end) +{ + _BIG5EncodingInfo *ei; + _BIG5Exclude *exclude; + + if (start > 0xFFFF || end > 0xFFFF) + return (EINVAL); + ei = (_BIG5EncodingInfo *)ctx; + exclude = TAILQ_LAST(&ei->excludes, _BIG5ExcludeList); + if (exclude != NULL && (wint_t)start <= exclude->end) + return (EINVAL); + exclude = (void *)malloc(sizeof(*exclude)); + if (exclude == NULL) + return (ENOMEM); + exclude->start = (wint_t)start; + exclude->end = (wint_t)end; + TAILQ_INSERT_TAIL(&ei->excludes, exclude, entry); + + return (0); +} + +static const _citrus_prop_hint_t root_hints[] = { + _CITRUS_PROP_HINT_NUM("row", &_citrus_BIG5_fill_rowcol), + _CITRUS_PROP_HINT_NUM("col", &_citrus_BIG5_fill_rowcol), + _CITRUS_PROP_HINT_NUM("excludes", &_citrus_BIG5_fill_excludes), + _CITRUS_PROP_HINT_END +}; + +static void +/*ARGSUSED*/ +_citrus_BIG5_encoding_module_uninit(_BIG5EncodingInfo *ei) +{ + _BIG5Exclude *exclude; + + while ((exclude = TAILQ_FIRST(&ei->excludes)) != NULL) { + TAILQ_REMOVE(&ei->excludes, exclude, entry); + free(exclude); + } +} + +static int +/*ARGSUSED*/ +_citrus_BIG5_encoding_module_init(_BIG5EncodingInfo * __restrict ei, + const void * __restrict var, size_t lenvar) +{ + void *ctx = (void *)ei; + const char *s; + int err; + + memset((void *)ei, 0, sizeof(*ei)); + TAILQ_INIT(&ei->excludes); + + if (lenvar > 0 && var != NULL) { + s = _bcs_skip_ws_len((const char *)var, &lenvar); + if (lenvar > 0 && *s != '\0') { + err = _citrus_prop_parse_variable( + root_hints, (void *)ei, s, lenvar); + if (err == 0) + return (0); + + _citrus_BIG5_encoding_module_uninit(ei); + memset((void *)ei, 0, sizeof(*ei)); + TAILQ_INIT(&ei->excludes); + } + } + + /* fallback Big5-1984, for backward compatibility. */ + _citrus_BIG5_fill_rowcol((void **)&ctx, "row", 0xA1, 0xFE); + _citrus_BIG5_fill_rowcol((void **)&ctx, "col", 0x40, 0x7E); + _citrus_BIG5_fill_rowcol((void **)&ctx, "col", 0xA1, 0xFE); + + return (0); +} + +static int +/*ARGSUSED*/ +_citrus_BIG5_mbrtowc_priv(_BIG5EncodingInfo * __restrict ei, + wchar_t * __restrict pwc, + char ** __restrict s, size_t n, + _BIG5State * __restrict psenc, + size_t * __restrict nresult) +{ + wchar_t wchar; + char *s0; + int c, chlenbak; + + s0 = *s; + + if (s0 == NULL) { + _citrus_BIG5_init_state(ei, psenc); + *nresult = 0; + return (0); + } + + chlenbak = psenc->chlen; + + /* make sure we have the first byte in the buffer */ + switch (psenc->chlen) { + case 0: + if (n < 1) + goto restart; + psenc->ch[0] = *s0++; + psenc->chlen = 1; + n--; + break; + case 1: + break; + default: + /* illegal state */ + goto ilseq; + } + + c = _citrus_BIG5_check(ei, psenc->ch[0] & 0xff); + if (c == 0) + goto ilseq; + while (psenc->chlen < c) { + if (n < 1) { + goto restart; + } + psenc->ch[psenc->chlen] = *s0++; + psenc->chlen++; + n--; + } + + switch (c) { + case 1: + wchar = psenc->ch[0] & 0xff; + break; + case 2: + if (!_citrus_BIG5_check2(ei, psenc->ch[1] & 0xff)) + goto ilseq; + wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff); + break; + default: + /* illegal state */ + goto ilseq; + } + + if (_citrus_BIG5_check_excludes(ei, (wint_t)wchar) != 0) + goto ilseq; + + *s = s0; + psenc->chlen = 0; + if (pwc) + *pwc = wchar; + *nresult = wchar ? c - chlenbak : 0; + + return (0); + +ilseq: + psenc->chlen = 0; + *nresult = (size_t)-1; + return (EILSEQ); + +restart: + *s = s0; + *nresult = (size_t)-2; + return (0); +} + +static int +/*ARGSUSED*/ +_citrus_BIG5_wcrtomb_priv(_BIG5EncodingInfo * __restrict ei, + char * __restrict s, + size_t n, wchar_t wc, _BIG5State * __restrict psenc __unused, + size_t * __restrict nresult) +{ + unsigned char l; + int ret; + + /* check invalid sequence */ + if (wc & ~0xffff || + _citrus_BIG5_check_excludes(ei, (wint_t)wc) != 0) { + ret = EILSEQ; + goto err; + } + + if (wc & 0x8000) { + if (_citrus_BIG5_check(ei, (wc >> 8) & 0xff) != 2 || + !_citrus_BIG5_check2(ei, wc & 0xff)) { + ret = EILSEQ; + goto err; + } + l = 2; + } else { + if (wc & ~0xff || !_citrus_BIG5_check(ei, wc & 0xff)) { + ret = EILSEQ; + goto err; + } + l = 1; + } + + if (n < l) { + /* bound check failure */ + ret = E2BIG; + goto err; + } + + if (l == 2) { + s[0] = (wc >> 8) & 0xff; + s[1] = wc & 0xff; + } else + s[0] = wc & 0xff; + + *nresult = l; + + return (0); + +err: + *nresult = (size_t)-1; + return (ret); +} + +static __inline int +/*ARGSUSED*/ +_citrus_BIG5_stdenc_wctocs(_BIG5EncodingInfo * __restrict ei __unused, + _csid_t * __restrict csid, + _index_t * __restrict idx, wchar_t wc) +{ + + *csid = (wc < 0x100) ? 0 : 1; + *idx = (_index_t)wc; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_BIG5_stdenc_cstowc(_BIG5EncodingInfo * __restrict ei __unused, + wchar_t * __restrict wc, + _csid_t csid, _index_t idx) +{ + + switch (csid) { + case 0: + case 1: + *wc = (wchar_t)idx; + break; + default: + return (EILSEQ); + } + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_BIG5_stdenc_get_state_desc_generic(_BIG5EncodingInfo * __restrict ei __unused, + _BIG5State * __restrict psenc, + int * __restrict rstate) +{ + + *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL : + _STDENC_SDGEN_INCOMPLETE_CHAR; + return (0); +} + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(BIG5); +_CITRUS_STDENC_DEF_OPS(BIG5); + +#include "citrus_stdenc_template.h" diff --git a/lib/libiconv_modules/BIG5/citrus_big5.h b/lib/libiconv_modules/BIG5/citrus_big5.h new file mode 100644 index 000000000000..e653ac6c1261 --- /dev/null +++ b/lib/libiconv_modules/BIG5/citrus_big5.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_big5.h,v 1.2 2003/06/25 09:51:41 tshiozak Exp $ */ + +/*- + * Copyright (c)2002 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_BIG5_H_ +#define _CITRUS_BIG5_H_ + +__BEGIN_DECLS +_CITRUS_STDENC_GETOPS_FUNC(BIG5); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/DECHanyu/Makefile b/lib/libiconv_modules/DECHanyu/Makefile new file mode 100644 index 000000000000..c14e123b02c4 --- /dev/null +++ b/lib/libiconv_modules/DECHanyu/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +SHLIB= DECHanyu +SRCS+= citrus_dechanyu.c + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/DECHanyu/citrus_dechanyu.c b/lib/libiconv_modules/DECHanyu/citrus_dechanyu.c new file mode 100644 index 000000000000..0801ac97bf83 --- /dev/null +++ b/lib/libiconv_modules/DECHanyu/citrus_dechanyu.c @@ -0,0 +1,392 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_dechanyu.c,v 1.3 2008/06/14 16:01:07 tnozaki Exp $ */ + +/*- + * Copyright (c)2007 Citrus Project, + * 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. + */ +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_module.h" +#include "citrus_stdenc.h" +#include "citrus_dechanyu.h" + +/* ---------------------------------------------------------------------- + * private stuffs used by templates + */ + +typedef struct { + size_t chlen; + char ch[4]; +} _DECHanyuState; + +typedef struct { + int dummy; +} _DECHanyuEncodingInfo; + +#define _CEI_TO_EI(_cei_) (&(_cei_)->ei) +#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.__CONCAT(s_,_func_) + +#define _FUNCNAME(m) __CONCAT(_citrus_DECHanyu_,m) +#define _ENCODING_INFO _DECHanyuEncodingInfo +#define _ENCODING_STATE _DECHanyuState +#define _ENCODING_MB_CUR_MAX(_ei_) 4 +#define _ENCODING_IS_STATE_DEPENDENT 0 +#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0 + +static __inline void +/*ARGSUSED*/ +_citrus_DECHanyu_init_state(_DECHanyuEncodingInfo * __restrict ei __unused, + _DECHanyuState * __restrict psenc) +{ + + psenc->chlen = 0; +} + +static __inline void +/*ARGSUSED*/ +_citrus_DECHanyu_pack_state(_DECHanyuEncodingInfo * __restrict ei __unused, + void * __restrict pspriv, const _DECHanyuState * __restrict psenc) +{ + + memcpy(pspriv, (const void *)psenc, sizeof(*psenc)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_DECHanyu_unpack_state(_DECHanyuEncodingInfo * __restrict ei __unused, + _DECHanyuState * __restrict psenc, + const void * __restrict pspriv) +{ + + memcpy((void *)psenc, pspriv, sizeof(*psenc)); +} + +static void +/*ARGSUSED*/ +_citrus_DECHanyu_encoding_module_uninit(_DECHanyuEncodingInfo *ei __unused) +{ + + /* ei may be null */ +} + +static int +/*ARGSUSED*/ +_citrus_DECHanyu_encoding_module_init(_DECHanyuEncodingInfo * __restrict ei __unused, + const void * __restrict var __unused, size_t lenvar __unused) +{ + + /* ei may be null */ + return (0); +} + +static __inline bool +is_singlebyte(int c) +{ + + return (c <= 0x7F); +} + +static __inline bool +is_leadbyte(int c) +{ + + return (c >= 0xA1 && c <= 0xFE); +} + +static __inline bool +is_trailbyte(int c) +{ + + c &= ~0x80; + return (c >= 0x21 && c <= 0x7E); +} + +static __inline bool +is_hanyu1(int c) +{ + + return (c == 0xC2); +} + +static __inline bool +is_hanyu2(int c) +{ + + return (c == 0xCB); +} + +#define HANYUBIT 0xC2CB0000 + +static __inline bool +is_94charset(int c) +{ + + return (c >= 0x21 && c <= 0x7E); +} + +static int +/*ARGSUSED*/ +_citrus_DECHanyu_mbrtowc_priv(_DECHanyuEncodingInfo * __restrict ei, + wchar_t * __restrict pwc, char ** __restrict s, size_t n, + _DECHanyuState * __restrict psenc, size_t * __restrict nresult) +{ + char *s0; + wchar_t wc; + int ch; + + if (*s == NULL) { + _citrus_DECHanyu_init_state(ei, psenc); + *nresult = _ENCODING_IS_STATE_DEPENDENT; + return (0); + } + s0 = *s; + + wc = (wchar_t)0; + switch (psenc->chlen) { + case 0: + if (n-- < 1) + goto restart; + ch = *s0++ & 0xFF; + if (is_singlebyte(ch)) { + if (pwc != NULL) + *pwc = (wchar_t)ch; + *nresult = (size_t)((ch == 0) ? 0 : 1); + *s = s0; + return (0); + } + if (!is_leadbyte(ch)) + goto ilseq; + psenc->ch[psenc->chlen++] = ch; + break; + case 1: + ch = psenc->ch[0] & 0xFF; + if (!is_leadbyte(ch)) + return (EINVAL); + break; + case 2: case 3: + ch = psenc->ch[0] & 0xFF; + if (is_hanyu1(ch)) { + ch = psenc->ch[1] & 0xFF; + if (is_hanyu2(ch)) { + wc |= (wchar_t)HANYUBIT; + break; + } + } + /*FALLTHROUGH*/ + default: + return (EINVAL); + } + + switch (psenc->chlen) { + case 1: + if (is_hanyu1(ch)) { + if (n-- < 1) + goto restart; + ch = *s0++ & 0xFF; + if (!is_hanyu2(ch)) + goto ilseq; + psenc->ch[psenc->chlen++] = ch; + wc |= (wchar_t)HANYUBIT; + if (n-- < 1) + goto restart; + ch = *s0++ & 0xFF; + if (!is_leadbyte(ch)) + goto ilseq; + psenc->ch[psenc->chlen++] = ch; + } + break; + case 2: + if (n-- < 1) + goto restart; + ch = *s0++ & 0xFF; + if (!is_leadbyte(ch)) + goto ilseq; + psenc->ch[psenc->chlen++] = ch; + break; + case 3: + ch = psenc->ch[2] & 0xFF; + if (!is_leadbyte(ch)) + return (EINVAL); + } + if (n-- < 1) + goto restart; + wc |= (wchar_t)(ch << 8); + ch = *s0++ & 0xFF; + if (!is_trailbyte(ch)) + goto ilseq; + wc |= (wchar_t)ch; + if (pwc != NULL) + *pwc = wc; + *nresult = (size_t)(s0 - *s); + *s = s0; + psenc->chlen = 0; + + return (0); + +restart: + *nresult = (size_t)-2; + *s = s0; + return (0); + +ilseq: + *nresult = (size_t)-1; + return (EILSEQ); +} + +static int +/*ARGSUSED*/ +_citrus_DECHanyu_wcrtomb_priv(_DECHanyuEncodingInfo * __restrict ei __unused, + char * __restrict s, size_t n, wchar_t wc, + _DECHanyuState * __restrict psenc, size_t * __restrict nresult) +{ + int ch; + + if (psenc->chlen != 0) + return (EINVAL); + + /* XXX: assume wchar_t as int */ + if ((uint32_t)wc <= 0x7F) { + ch = wc & 0xFF; + } else { + if ((uint32_t)wc > 0xFFFF) { + if ((wc & ~0xFFFF) != (wchar_t)HANYUBIT) + goto ilseq; + psenc->ch[psenc->chlen++] = (wc >> 24) & 0xFF; + psenc->ch[psenc->chlen++] = (wc >> 16) & 0xFF; + wc &= 0xFFFF; + } + ch = (wc >> 8) & 0xFF; + if (!is_leadbyte(ch)) + goto ilseq; + psenc->ch[psenc->chlen++] = ch; + ch = wc & 0xFF; + if (!is_trailbyte(ch)) + goto ilseq; + } + psenc->ch[psenc->chlen++] = ch; + if (n < psenc->chlen) { + *nresult = (size_t)-1; + return (E2BIG); + } + memcpy(s, psenc->ch, psenc->chlen); + *nresult = psenc->chlen; + psenc->chlen = 0; + + return (0); + +ilseq: + *nresult = (size_t)-1; + return (EILSEQ); +} + +static __inline int +/*ARGSUSED*/ +_citrus_DECHanyu_stdenc_wctocs(_DECHanyuEncodingInfo * __restrict ei __unused, + _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc) +{ + wchar_t mask; + int plane; + + plane = 0; + mask = 0x7F; + /* XXX: assume wchar_t as int */ + if ((uint32_t)wc > 0x7F) { + if ((uint32_t)wc > 0xFFFF) { + if ((wc & ~0xFFFF) != (wchar_t)HANYUBIT) + return (EILSEQ); + plane += 2; + } + if (!is_leadbyte((wc >> 8) & 0xFF) || + !is_trailbyte(wc & 0xFF)) + return (EILSEQ); + plane += (wc & 0x80) ? 1 : 2; + mask |= 0x7F00; + } + *csid = plane; + *idx = (_index_t)(wc & mask); + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_DECHanyu_stdenc_cstowc(_DECHanyuEncodingInfo * __restrict ei __unused, + wchar_t * __restrict wc, _csid_t csid, _index_t idx) +{ + + if (csid == 0) { + if (idx > 0x7F) + return (EILSEQ); + } else if (csid <= 4) { + if (!is_94charset(idx >> 8)) + return (EILSEQ); + if (!is_94charset(idx & 0xFF)) + return (EILSEQ); + if (csid % 2) + idx |= 0x80; + idx |= 0x8000; + if (csid > 2) + idx |= HANYUBIT; + } else + return (EILSEQ); + *wc = (wchar_t)idx; + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_DECHanyu_stdenc_get_state_desc_generic( + _DECHanyuEncodingInfo * __restrict ei __unused, + _DECHanyuState * __restrict psenc, int * __restrict rstate) +{ + + *rstate = (psenc->chlen == 0) + ? _STDENC_SDGEN_INITIAL + : _STDENC_SDGEN_INCOMPLETE_CHAR; + return (0); +} + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(DECHanyu); +_CITRUS_STDENC_DEF_OPS(DECHanyu); + +#include "citrus_stdenc_template.h" diff --git a/lib/libiconv_modules/DECHanyu/citrus_dechanyu.h b/lib/libiconv_modules/DECHanyu/citrus_dechanyu.h new file mode 100644 index 000000000000..5f8873cf7f54 --- /dev/null +++ b/lib/libiconv_modules/DECHanyu/citrus_dechanyu.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_dechanyu.h,v 1.1 2007/04/01 18:52:32 tnozaki Exp $ */ + +/*- + * Copyright (c)2006 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_DECHANYU_H_ +#define _CITRUS_DECHANYU_H_ + +__BEGIN_DECLS +_CITRUS_STDENC_GETOPS_FUNC(DECHanyu); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/EUC/Makefile b/lib/libiconv_modules/EUC/Makefile new file mode 100644 index 000000000000..422aab398388 --- /dev/null +++ b/lib/libiconv_modules/EUC/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +SHLIB= EUC +SRCS+= citrus_euc.c +CFLAGS+= --param max-inline-insns-single=32 + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/EUC/citrus_euc.c b/lib/libiconv_modules/EUC/citrus_euc.c new file mode 100644 index 000000000000..708473bf7641 --- /dev/null +++ b/lib/libiconv_modules/EUC/citrus_euc.c @@ -0,0 +1,385 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_euc.c,v 1.14 2009/01/11 02:46:24 christos Exp $ */ + +/*- + * Copyright (c)2002 Citrus Project, + * 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. + */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Paul Borman at Krystal Technologies. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include "citrus_namespace.h" +#include "citrus_bcs.h" +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_stdenc.h" +#include "citrus_euc.h" + + +/* ---------------------------------------------------------------------- + * private stuffs used by templates + */ + +typedef struct { + int chlen; + char ch[3]; +} _EUCState; + +typedef struct { + wchar_t bits[4]; + wchar_t mask; + unsigned count[4]; + unsigned mb_cur_max; +} _EUCEncodingInfo; + +#define _SS2 0x008e +#define _SS3 0x008f + +#define _CEI_TO_EI(_cei_) (&(_cei_)->ei) +#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_ + +#define _FUNCNAME(m) _citrus_EUC_##m +#define _ENCODING_INFO _EUCEncodingInfo +#define _ENCODING_STATE _EUCState +#define _ENCODING_MB_CUR_MAX(_ei_) (_ei_)->mb_cur_max +#define _ENCODING_IS_STATE_DEPENDENT 0 +#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0 + + +static __inline int +_citrus_EUC_cs(unsigned int c) +{ + + c &= 0xff; + + return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0); +} + +static __inline int +_citrus_EUC_parse_variable(_EUCEncodingInfo *ei, const void *var, + size_t lenvar __unused) +{ + char *e; + const char *v; + int x; + + /* parse variable string */ + if (!var) + return (EFTYPE); + + v = (const char *)var; + + while (*v == ' ' || *v == '\t') + ++v; + + ei->mb_cur_max = 1; + for (x = 0; x < 4; ++x) { + ei->count[x] = (int)_bcs_strtol(v, (char **)&e, 0); + if (v == e || !(v = e) || ei->count[x] < 1 || ei->count[x] > 4) { + return (EFTYPE); + } + if (ei->mb_cur_max < ei->count[x]) + ei->mb_cur_max = ei->count[x]; + while (*v == ' ' || *v == '\t') + ++v; + ei->bits[x] = (int)_bcs_strtol(v, (char **)&e, 0); + if (v == e || !(v = e)) { + return (EFTYPE); + } + while (*v == ' ' || *v == '\t') + ++v; + } + ei->mask = (int)_bcs_strtol(v, (char **)&e, 0); + if (v == e || !(v = e)) { + return (EFTYPE); + } + + return (0); +} + + +static __inline void +/*ARGSUSED*/ +_citrus_EUC_init_state(_EUCEncodingInfo *ei __unused, _EUCState *s) +{ + + memset(s, 0, sizeof(*s)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_EUC_pack_state(_EUCEncodingInfo *ei __unused, void *pspriv, + const _EUCState *s) +{ + + memcpy(pspriv, (const void *)s, sizeof(*s)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_EUC_unpack_state(_EUCEncodingInfo *ei __unused, _EUCState *s, + const void *pspriv) +{ + + memcpy((void *)s, pspriv, sizeof(*s)); +} + +static int +_citrus_EUC_mbrtowc_priv(_EUCEncodingInfo *ei, wchar_t *pwc, char **s, + size_t n, _EUCState *psenc, size_t *nresult) +{ + wchar_t wchar; + int c, chlenbak, cs, len; + char *s0, *s1 = NULL; + + s0 = *s; + + if (s0 == NULL) { + _citrus_EUC_init_state(ei, psenc); + *nresult = 0; /* state independent */ + return (0); + } + + chlenbak = psenc->chlen; + + /* make sure we have the first byte in the buffer */ + switch (psenc->chlen) { + case 0: + if (n < 1) + goto restart; + psenc->ch[0] = *s0++; + psenc->chlen = 1; + n--; + break; + case 1: + case 2: + break; + default: + /* illgeal state */ + goto encoding_error; + } + + c = ei->count[cs = _citrus_EUC_cs(psenc->ch[0] & 0xff)]; + if (c == 0) + goto encoding_error; + while (psenc->chlen < c) { + if (n < 1) + goto restart; + psenc->ch[psenc->chlen] = *s0++; + psenc->chlen++; + n--; + } + *s = s0; + + switch (cs) { + case 3: + case 2: + /* skip SS2/SS3 */ + len = c - 1; + s1 = &psenc->ch[1]; + break; + case 1: + case 0: + len = c; + s1 = &psenc->ch[0]; + break; + default: + goto encoding_error; + } + wchar = 0; + while (len-- > 0) + wchar = (wchar << 8) | (*s1++ & 0xff); + wchar = (wchar & ~ei->mask) | ei->bits[cs]; + + psenc->chlen = 0; + if (pwc) + *pwc = wchar; + *nresult = wchar ? (size_t)(c - chlenbak) : 0; + return (0); + +encoding_error: + psenc->chlen = 0; + *nresult = (size_t)-1; + return (EILSEQ); + +restart: + *nresult = (size_t)-2; + *s = s0; + return (0); +} + +static int +_citrus_EUC_wcrtomb_priv(_EUCEncodingInfo *ei, char *s, size_t n, wchar_t wc, + _EUCState *psenc __unused, size_t *nresult) +{ + wchar_t m, nm; + unsigned int cs; + int ret; + short i; + + m = wc & ei->mask; + nm = wc & ~m; + + for (cs = 0; cs < sizeof(ei->count) / sizeof(ei->count[0]); cs++) + if (m == ei->bits[cs]) + break; + /* fallback case - not sure if it is necessary */ + if (cs == sizeof(ei->count) / sizeof(ei->count[0])) + cs = 1; + + i = ei->count[cs]; + if (n < (unsigned)i) { + ret = E2BIG; + goto err; + } + m = (cs) ? 0x80 : 0x00; + switch (cs) { + case 2: + *s++ = _SS2; + i--; + break; + case 3: + *s++ = _SS3; + i--; + break; + } + + while (i-- > 0) + *s++ = ((nm >> (i << 3)) & 0xff) | m; + + *nresult = (size_t)ei->count[cs]; + return (0); + +err: + *nresult = (size_t)-1; + return (ret); +} + +static __inline int +/*ARGSUSED*/ +_citrus_EUC_stdenc_wctocs(_EUCEncodingInfo * __restrict ei, + _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc) +{ + wchar_t m, nm; + + m = wc & ei->mask; + nm = wc & ~m; + + *csid = (_citrus_csid_t)m; + *idx = (_citrus_index_t)nm; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_EUC_stdenc_cstowc(_EUCEncodingInfo * __restrict ei, + wchar_t * __restrict wc, _csid_t csid, _index_t idx) +{ + + if ((csid & ~ei->mask) != 0 || (idx & ei->mask) != 0) + return (EINVAL); + + *wc = (wchar_t)csid | (wchar_t)idx; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_EUC_stdenc_get_state_desc_generic(_EUCEncodingInfo * __restrict ei __unused, + _EUCState * __restrict psenc, int * __restrict rstate) +{ + + *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL : + _STDENC_SDGEN_INCOMPLETE_CHAR; + return (0); +} + +static int +/*ARGSUSED*/ +_citrus_EUC_encoding_module_init(_EUCEncodingInfo * __restrict ei, + const void * __restrict var, size_t lenvar) +{ + + return (_citrus_EUC_parse_variable(ei, var, lenvar)); +} + +static void +/*ARGSUSED*/ +_citrus_EUC_encoding_module_uninit(_EUCEncodingInfo * __restrict ei __unused) +{ + +} + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(EUC); +_CITRUS_STDENC_DEF_OPS(EUC); + +#include "citrus_stdenc_template.h" diff --git a/lib/libiconv_modules/EUC/citrus_euc.h b/lib/libiconv_modules/EUC/citrus_euc.h new file mode 100644 index 000000000000..e9bab9f70753 --- /dev/null +++ b/lib/libiconv_modules/EUC/citrus_euc.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_euc.h,v 1.2 2003/06/25 09:51:42 tshiozak Exp $ */ + +/*- + * Copyright (c)2002 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_EUC_H_ +#define _CITRUS_EUC_H_ + +__BEGIN_DECLS +_CITRUS_STDENC_GETOPS_FUNC(EUC); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/EUCTW/Makefile b/lib/libiconv_modules/EUCTW/Makefile new file mode 100644 index 000000000000..b85c0359171c --- /dev/null +++ b/lib/libiconv_modules/EUCTW/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +SHLIB= EUCTW +SRCS+= citrus_euctw.c +CFLAGS+= --param max-inline-insns-single=32 + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/EUCTW/citrus_euctw.c b/lib/libiconv_modules/EUCTW/citrus_euctw.c new file mode 100644 index 000000000000..79aa9fa90d30 --- /dev/null +++ b/lib/libiconv_modules/EUCTW/citrus_euctw.c @@ -0,0 +1,377 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_euctw.c,v 1.11 2008/06/14 16:01:07 tnozaki Exp $ */ + +/*- + * Copyright (c)2002 Citrus Project, + * 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. + */ + +/*- + * Copyright (c)1999 Citrus Project, + * 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. + * + * $Citrus: xpg4dl/FreeBSD/lib/libc/locale/euctw.c,v 1.13 2001/06/21 01:51:44 yamt Exp $ + */ + +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_stdenc.h" +#include "citrus_euctw.h" + + +/* ---------------------------------------------------------------------- + * private stuffs used by templates + */ + +typedef struct { + int chlen; + char ch[4]; +} _EUCTWState; + +typedef struct { + int dummy; +} _EUCTWEncodingInfo; + +#define _SS2 0x008e +#define _SS3 0x008f + +#define _CEI_TO_EI(_cei_) (&(_cei_)->ei) +#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_ + +#define _FUNCNAME(m) _citrus_EUCTW_##m +#define _ENCODING_INFO _EUCTWEncodingInfo +#define _ENCODING_STATE _EUCTWState +#define _ENCODING_MB_CUR_MAX(_ei_) 4 +#define _ENCODING_IS_STATE_DEPENDENT 0 +#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0 + +static __inline int +_citrus_EUCTW_cs(unsigned int c) +{ + + c &= 0xff; + + return ((c & 0x80) ? (c == _SS2 ? 2 : 1) : 0); +} + +static __inline int +_citrus_EUCTW_count(int cs) +{ + + switch (cs) { + case 0: + /*FALLTHROUGH*/ + case 1: + /*FALLTHROUGH*/ + case 2: + return (2^cs); + case 3: + abort(); + /*NOTREACHED*/ + } + return (0); +} + +static __inline void +/*ARGSUSED*/ +_citrus_EUCTW_init_state(_EUCTWEncodingInfo * __restrict ei __unused, + _EUCTWState * __restrict s) +{ + + memset(s, 0, sizeof(*s)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_EUCTW_pack_state(_EUCTWEncodingInfo * __restrict ei __unused, + void * __restrict pspriv, const _EUCTWState * __restrict s) +{ + + memcpy(pspriv, (const void *)s, sizeof(*s)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_EUCTW_unpack_state(_EUCTWEncodingInfo * __restrict ei __unused, + _EUCTWState * __restrict s, const void * __restrict pspriv) +{ + + memcpy((void *)s, pspriv, sizeof(*s)); +} + +static int +/*ARGSUSED*/ +_citrus_EUCTW_encoding_module_init(_EUCTWEncodingInfo * __restrict ei, + const void * __restrict var __unused, size_t lenvar __unused) +{ + + memset((void *)ei, 0, sizeof(*ei)); + + return (0); +} + +static void +/*ARGSUSED*/ +_citrus_EUCTW_encoding_module_uninit(_EUCTWEncodingInfo *ei __unused) +{ + +} + +static int +_citrus_EUCTW_mbrtowc_priv(_EUCTWEncodingInfo * __restrict ei, + wchar_t * __restrict pwc, char ** __restrict s, + size_t n, _EUCTWState * __restrict psenc, size_t * __restrict nresult) +{ + char *s0; + wchar_t wchar; + int c, chlenbak, cs; + + s0 = *s; + + if (s0 == NULL) { + _citrus_EUCTW_init_state(ei, psenc); + *nresult = 0; /* state independent */ + return (0); + } + + chlenbak = psenc->chlen; + + /* make sure we have the first byte in the buffer */ + switch (psenc->chlen) { + case 0: + if (n < 1) + goto restart; + psenc->ch[0] = *s0++; + psenc->chlen = 1; + n--; + break; + case 1: + case 2: + break; + default: + /* illgeal state */ + goto ilseq; + } + + c = _citrus_EUCTW_count(cs = _citrus_EUCTW_cs(psenc->ch[0] & 0xff)); + if (c == 0) + goto ilseq; + while (psenc->chlen < c) { + if (n < 1) + goto ilseq; + psenc->ch[psenc->chlen] = *s0++; + psenc->chlen++; + n--; + } + + wchar = 0; + switch (cs) { + case 0: + if (psenc->ch[0] & 0x80) + goto ilseq; + wchar = psenc->ch[0] & 0xff; + break; + case 1: + if (!(psenc->ch[0] & 0x80) || !(psenc->ch[1] & 0x80)) + goto ilseq; + wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff); + wchar |= 'G' << 24; + break; + case 2: + if ((unsigned char)psenc->ch[1] < 0xa1 || + 0xa7 < (unsigned char)psenc->ch[1]) + goto ilseq; + if (!(psenc->ch[2] & 0x80) || !(psenc->ch[3] & 0x80)) + goto ilseq; + wchar = ((psenc->ch[2] & 0xff) << 8) | (psenc->ch[3] & 0xff); + wchar |= ('G' + psenc->ch[1] - 0xa1) << 24; + break; + default: + goto ilseq; + } + + *s = s0; + psenc->chlen = 0; + + if (pwc) + *pwc = wchar; + *nresult = wchar ? c - chlenbak : 0; + return (0); + +ilseq: + psenc->chlen = 0; + *nresult = (size_t)-1; + return (EILSEQ); + +restart: + *s = s0; + *nresult = (size_t)-1; + return (0); +} + +static int +_citrus_EUCTW_wcrtomb_priv(_EUCTWEncodingInfo * __restrict ei __unused, + char * __restrict s, size_t n, wchar_t wc, + _EUCTWState * __restrict psenc __unused, size_t * __restrict nresult) +{ + wchar_t cs, v; + int clen, i, ret; + size_t len; + + cs = wc & 0x7f000080; + clen = 1; + if (wc & 0x00007f00) + clen = 2; + if ((wc & 0x007f0000) && !(wc & 0x00800000)) + clen = 3; + + if (clen == 1 && cs == 0x00000000) { + /* ASCII */ + len = 1; + if (n < len) { + ret = E2BIG; + goto err; + } + v = wc & 0x0000007f; + } else if (clen == 2 && cs == ('G' << 24)) { + /* CNS-11643-1 */ + len = 2; + if (n < len) { + ret = E2BIG; + goto err; + } + v = wc & 0x00007f7f; + v |= 0x00008080; + } else if (clen == 2 && 'H' <= (cs >> 24) && (cs >> 24) <= 'M') { + /* CNS-11643-[2-7] */ + len = 4; + if (n < len) { + ret = E2BIG; + goto err; + } + *s++ = _SS2; + *s++ = (cs >> 24) - 'H' + 0xa2; + v = wc & 0x00007f7f; + v |= 0x00008080; + } else { + ret = EILSEQ; + goto err; + } + + i = clen; + while (i-- > 0) + *s++ = (v >> (i << 3)) & 0xff; + + *nresult = len; + return (0); + +err: + *nresult = (size_t)-1; + return (ret); +} + +static __inline int +/*ARGSUSED*/ +_citrus_EUCTW_stdenc_wctocs(_EUCTWEncodingInfo * __restrict ei __unused, + _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc) +{ + + *csid = (_csid_t)(wc >> 24) & 0xFF; + *idx = (_index_t)(wc & 0x7F7F); + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_EUCTW_stdenc_cstowc(_EUCTWEncodingInfo * __restrict ei __unused, + wchar_t * __restrict wc, _csid_t csid, _index_t idx) +{ + + if (csid == 0) { + if ((idx & ~0x7F) != 0) + return (EINVAL); + *wc = (wchar_t)idx; + } else { + if (csid < 'G' || csid > 'M' || (idx & ~0x7F7F) != 0) + return (EINVAL); + *wc = (wchar_t)idx | ((wchar_t)csid << 24); + } + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_EUCTW_stdenc_get_state_desc_generic(_EUCTWEncodingInfo * __restrict ei __unused, + _EUCTWState * __restrict psenc, int * __restrict rstate) +{ + + *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL : + _STDENC_SDGEN_INCOMPLETE_CHAR; + return (0); +} + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(EUCTW); +_CITRUS_STDENC_DEF_OPS(EUCTW); + +#include "citrus_stdenc_template.h" diff --git a/lib/libiconv_modules/EUCTW/citrus_euctw.h b/lib/libiconv_modules/EUCTW/citrus_euctw.h new file mode 100644 index 000000000000..5dde3421e3d7 --- /dev/null +++ b/lib/libiconv_modules/EUCTW/citrus_euctw.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_euctw.h,v 1.2 2003/06/25 09:51:42 tshiozak Exp $ */ + +/*- + * Copyright (c)2002 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_EUCTW_H_ +#define _CITRUS_EUCTW_H_ + +__BEGIN_DECLS +_CITRUS_STDENC_GETOPS_FUNC(EUCTW); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/GBK2K/Makefile b/lib/libiconv_modules/GBK2K/Makefile new file mode 100644 index 000000000000..28dc79603d07 --- /dev/null +++ b/lib/libiconv_modules/GBK2K/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +SHLIB= GBK2K +SRCS+= citrus_gbk2k.c +CFLAGS+= --param max-inline-insns-single=16 + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/GBK2K/citrus_gbk2k.c b/lib/libiconv_modules/GBK2K/citrus_gbk2k.c new file mode 100644 index 000000000000..ff31725d110a --- /dev/null +++ b/lib/libiconv_modules/GBK2K/citrus_gbk2k.c @@ -0,0 +1,417 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_gbk2k.c,v 1.7 2008/06/14 16:01:07 tnozaki Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * 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. + */ + +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_module.h" +#include "citrus_stdenc.h" +#include "citrus_gbk2k.h" + + +/* ---------------------------------------------------------------------- + * private stuffs used by templates + */ + +typedef struct _GBK2KState { + int chlen; + char ch[4]; +} _GBK2KState; + +typedef struct { + int mb_cur_max; +} _GBK2KEncodingInfo; + +#define _CEI_TO_EI(_cei_) (&(_cei_)->ei) +#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_ + +#define _FUNCNAME(m) _citrus_GBK2K_##m +#define _ENCODING_INFO _GBK2KEncodingInfo +#define _ENCODING_STATE _GBK2KState +#define _ENCODING_MB_CUR_MAX(_ei_) (_ei_)->mb_cur_max +#define _ENCODING_IS_STATE_DEPENDENT 0 +#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0 + +static __inline void +/*ARGSUSED*/ +_citrus_GBK2K_init_state(_GBK2KEncodingInfo * __restrict ei __unused, + _GBK2KState * __restrict s) +{ + + memset(s, 0, sizeof(*s)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_GBK2K_pack_state(_GBK2KEncodingInfo * __restrict ei __unused, + void * __restrict pspriv, const _GBK2KState * __restrict s) +{ + + memcpy(pspriv, (const void *)s, sizeof(*s)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_GBK2K_unpack_state(_GBK2KEncodingInfo * __restrict ei __unused, + _GBK2KState * __restrict s, const void * __restrict pspriv) +{ + + memcpy((void *)s, pspriv, sizeof(*s)); +} + +static __inline bool +_mb_singlebyte(int c) +{ + + return ((c & 0xff) <= 0x7f); +} + +static __inline bool +_mb_leadbyte(int c) +{ + + c &= 0xff; + return (0x81 <= c && c <= 0xfe); +} + +static __inline bool +_mb_trailbyte(int c) +{ + + c &= 0xff; + return ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfe)); +} + +static __inline bool +_mb_surrogate(int c) +{ + + c &= 0xff; + return (0x30 <= c && c <= 0x39); +} + +static __inline int +_mb_count(wchar_t v) +{ + uint32_t c; + + c = (uint32_t)v; /* XXX */ + if (!(c & 0xffffff00)) + return (1); + if (!(c & 0xffff0000)) + return (2); + return (4); +} + +#define _PSENC (psenc->ch[psenc->chlen - 1]) +#define _PUSH_PSENC(c) (psenc->ch[psenc->chlen++] = (c)) + +static int +_citrus_GBK2K_mbrtowc_priv(_GBK2KEncodingInfo * __restrict ei, + wchar_t * __restrict pwc, char ** __restrict s, size_t n, + _GBK2KState * __restrict psenc, size_t * __restrict nresult) +{ + char *s0, *s1; + wchar_t wc; + int chlenbak, len; + + s0 = *s; + + if (s0 == NULL) { + /* _citrus_GBK2K_init_state(ei, psenc); */ + psenc->chlen = 0; + *nresult = 0; + return (0); + } + + chlenbak = psenc->chlen; + + switch (psenc->chlen) { + case 3: + if (!_mb_leadbyte (_PSENC)) + goto invalid; + /* FALLTHROUGH */ + case 2: + if (!_mb_surrogate(_PSENC) || _mb_trailbyte(_PSENC)) + goto invalid; + /* FALLTHROUGH */ + case 1: + if (!_mb_leadbyte (_PSENC)) + goto invalid; + /* FALLTHOROUGH */ + case 0: + break; + default: + goto invalid; + } + + for (;;) { + if (n-- < 1) + goto restart; + + _PUSH_PSENC(*s0++); + + switch (psenc->chlen) { + case 1: + if (_mb_singlebyte(_PSENC)) + goto convert; + if (_mb_leadbyte (_PSENC)) + continue; + goto ilseq; + case 2: + if (_mb_trailbyte (_PSENC)) + goto convert; + if (ei->mb_cur_max == 4 && + _mb_surrogate (_PSENC)) + continue; + goto ilseq; + case 3: + if (_mb_leadbyte (_PSENC)) + continue; + goto ilseq; + case 4: + if (_mb_surrogate (_PSENC)) + goto convert; + goto ilseq; + } + } + +convert: + len = psenc->chlen; + s1 = &psenc->ch[0]; + wc = 0; + while (len-- > 0) + wc = (wc << 8) | (*s1++ & 0xff); + + if (pwc != NULL) + *pwc = wc; + *s = s0; + *nresult = (wc == 0) ? 0 : psenc->chlen - chlenbak; + /* _citrus_GBK2K_init_state(ei, psenc); */ + psenc->chlen = 0; + + return (0); + +restart: + *s = s0; + *nresult = (size_t)-2; + + return (0); + +invalid: + return (EINVAL); + +ilseq: + *nresult = (size_t)-1; + return (EILSEQ); +} + +static int +_citrus_GBK2K_wcrtomb_priv(_GBK2KEncodingInfo * __restrict ei, + char * __restrict s, size_t n, wchar_t wc, _GBK2KState * __restrict psenc, + size_t * __restrict nresult) +{ + size_t len; + int ret; + + if (psenc->chlen != 0) { + ret = EINVAL; + goto err; + } + + len = _mb_count(wc); + if (n < len) { + ret = E2BIG; + goto err; + } + + switch (len) { + case 1: + if (!_mb_singlebyte(_PUSH_PSENC(wc ))) { + ret = EILSEQ; + goto err; + } + break; + case 2: + if (!_mb_leadbyte (_PUSH_PSENC(wc >> 8)) || + !_mb_trailbyte (_PUSH_PSENC(wc))) { + ret = EILSEQ; + goto err; + } + break; + case 4: + if (ei->mb_cur_max != 4 || + !_mb_leadbyte (_PUSH_PSENC(wc >> 24)) || + !_mb_surrogate (_PUSH_PSENC(wc >> 16)) || + !_mb_leadbyte (_PUSH_PSENC(wc >> 8)) || + !_mb_surrogate (_PUSH_PSENC(wc))) { + ret = EILSEQ; + goto err; + } + break; + } + + memcpy(s, psenc->ch, psenc->chlen); + *nresult = psenc->chlen; + /* _citrus_GBK2K_init_state(ei, psenc); */ + psenc->chlen = 0; + + return (0); + +err: + *nresult = (size_t)-1; + return (ret); +} + +static __inline int +/*ARGSUSED*/ +_citrus_GBK2K_stdenc_wctocs(_GBK2KEncodingInfo * __restrict ei __unused, + _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc) +{ + uint8_t ch, cl; + + if ((uint32_t)wc < 0x80) { + /* ISO646 */ + *csid = 0; + *idx = (_index_t)wc; + } else if ((uint32_t)wc >= 0x10000) { + /* GBKUCS : XXX */ + *csid = 3; + *idx = (_index_t)wc; + } else { + ch = (uint8_t)(wc >> 8); + cl = (uint8_t)wc; + if (ch >= 0xA1 && cl >= 0xA1) { + /* EUC G1 */ + *csid = 1; + *idx = (_index_t)wc & 0x7F7FU; + } else { + /* extended area (0x8140-) */ + *csid = 2; + *idx = (_index_t)wc; + } + } + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_GBK2K_stdenc_cstowc(_GBK2KEncodingInfo * __restrict ei, + wchar_t * __restrict wc, _csid_t csid, _index_t idx) +{ + + switch (csid) { + case 0: + /* ISO646 */ + *wc = (wchar_t)idx; + break; + case 1: + /* EUC G1 */ + *wc = (wchar_t)idx | 0x8080U; + break; + case 2: + /* extended area */ + *wc = (wchar_t)idx; + break; + case 3: + /* GBKUCS : XXX */ + if (ei->mb_cur_max != 4) + return (EINVAL); + *wc = (wchar_t)idx; + break; + default: + return (EILSEQ); + } + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_GBK2K_stdenc_get_state_desc_generic(_GBK2KEncodingInfo * __restrict ei __unused, + _GBK2KState * __restrict psenc, int * __restrict rstate) +{ + + *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL : + _STDENC_SDGEN_INCOMPLETE_CHAR; + return (0); +} + +static int +/*ARGSUSED*/ +_citrus_GBK2K_encoding_module_init(_GBK2KEncodingInfo * __restrict ei, + const void * __restrict var, size_t lenvar) +{ + const char *p; + + p = var; + memset((void *)ei, 0, sizeof(*ei)); + ei->mb_cur_max = 4; + while (lenvar > 0) { + switch (_bcs_tolower(*p)) { + case '2': + MATCH("2byte", ei->mb_cur_max = 2); + break; + } + p++; + lenvar--; + } + + return (0); +} + +static void +/*ARGSUSED*/ +_citrus_GBK2K_encoding_module_uninit(_GBK2KEncodingInfo *ei __unused) +{ + +} + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(GBK2K); +_CITRUS_STDENC_DEF_OPS(GBK2K); + +#include "citrus_stdenc_template.h" diff --git a/lib/libiconv_modules/GBK2K/citrus_gbk2k.h b/lib/libiconv_modules/GBK2K/citrus_gbk2k.h new file mode 100644 index 000000000000..174a19e95055 --- /dev/null +++ b/lib/libiconv_modules/GBK2K/citrus_gbk2k.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_gbk2k.h,v 1.2 2003/06/25 09:51:43 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_GBK2K_H_ +#define _CITRUS_GBK2K_H_ + +__BEGIN_DECLS +_CITRUS_STDENC_GETOPS_FUNC(GBK2K); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/HZ/Makefile b/lib/libiconv_modules/HZ/Makefile new file mode 100644 index 000000000000..a501187c2f1c --- /dev/null +++ b/lib/libiconv_modules/HZ/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +SHLIB= HZ +SRCS+= citrus_hz.c + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/HZ/citrus_hz.c b/lib/libiconv_modules/HZ/citrus_hz.c new file mode 100644 index 000000000000..3775ea626279 --- /dev/null +++ b/lib/libiconv_modules/HZ/citrus_hz.c @@ -0,0 +1,648 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_hz.c,v 1.2 2008/06/14 16:01:07 tnozaki Exp $ */ + +/*- + * Copyright (c)2004, 2006 Citrus Project, + * 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. + * + */ + +#include <sys/cdefs.h> +#include <sys/queue.h> +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_module.h" +#include "citrus_stdenc.h" + +#include "citrus_hz.h" +#include "citrus_prop.h" + +/* + * wchar_t mapping: + * + * CTRL/ASCII 00000000 00000000 00000000 gxxxxxxx + * GB2312 00000000 00000000 0xxxxxxx gxxxxxxx + * 94/96*n (~M) 0mmmmmmm 0xxxxxxx 0xxxxxxx gxxxxxxx + */ + +#define ESCAPE_CHAR '~' + +typedef enum { + CTRL = 0, ASCII = 1, GB2312 = 2, CS94 = 3, CS96 = 4 +} charset_t; + +typedef struct { + int end; + int start; + int width; +} range_t; + +static const range_t ranges[] = { +#define RANGE(start, end) { start, end, (end - start) + 1 } +/* CTRL */ RANGE(0x00, 0x1F), +/* ASCII */ RANGE(0x20, 0x7F), +/* GB2312 */ RANGE(0x21, 0x7E), +/* CS94 */ RANGE(0x21, 0x7E), +/* CS96 */ RANGE(0x20, 0x7F), +#undef RANGE +}; + +typedef struct escape_t escape_t; +typedef struct { + charset_t charset; + escape_t *escape; + ssize_t length; +#define ROWCOL_MAX 3 +} graphic_t; + +typedef TAILQ_HEAD(escape_list, escape_t) escape_list; +struct escape_t { + TAILQ_ENTRY(escape_t) entry; + escape_list *set; + graphic_t *left; + graphic_t *right; + int ch; +}; + +#define GL(escape) ((escape)->left) +#define GR(escape) ((escape)->right) +#define SET(escape) ((escape)->set) +#define ESC(escape) ((escape)->ch) +#define INIT(escape) (TAILQ_FIRST(SET(escape))) + +static __inline escape_t * +find_escape(escape_list *set, int ch) +{ + escape_t *escape; + + TAILQ_FOREACH(escape, set, entry) { + if (ESC(escape) == ch) + break; + } + + return (escape); +} + +typedef struct { + escape_list e0; + escape_list e1; + graphic_t *ascii; + graphic_t *gb2312; +} _HZEncodingInfo; + +#define E0SET(ei) (&(ei)->e0) +#define E1SET(ei) (&(ei)->e1) +#define INIT0(ei) (TAILQ_FIRST(E0SET(ei))) +#define INIT1(ei) (TAILQ_FIRST(E1SET(ei))) + +typedef struct { + escape_t *inuse; + int chlen; + char ch[ROWCOL_MAX]; +} _HZState; + +#define _CEI_TO_EI(_cei_) (&(_cei_)->ei) +#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_ + +#define _FUNCNAME(m) _citrus_HZ_##m +#define _ENCODING_INFO _HZEncodingInfo +#define _ENCODING_STATE _HZState +#define _ENCODING_MB_CUR_MAX(_ei_) MB_LEN_MAX +#define _ENCODING_IS_STATE_DEPENDENT 1 +#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) ((_ps_)->inuse == NULL) + +static __inline void +_citrus_HZ_init_state(_HZEncodingInfo * __restrict ei, + _HZState * __restrict psenc) +{ + + psenc->chlen = 0; + psenc->inuse = INIT0(ei); +} + +static __inline void +/*ARGSUSED*/ +_citrus_HZ_pack_state(_HZEncodingInfo * __restrict ei __unused, + void *__restrict pspriv, const _HZState * __restrict psenc) +{ + + memcpy(pspriv, (const void *)psenc, sizeof(*psenc)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_HZ_unpack_state(_HZEncodingInfo * __restrict ei __unused, + _HZState * __restrict psenc, const void * __restrict pspriv) +{ + + memcpy((void *)psenc, pspriv, sizeof(*psenc)); +} + +static int +_citrus_HZ_mbrtowc_priv(_HZEncodingInfo * __restrict ei, + wchar_t * __restrict pwc, char ** __restrict s, size_t n, + _HZState * __restrict psenc, size_t * __restrict nresult) +{ + escape_t *candidate, *init; + graphic_t *graphic; + const range_t *range; + char *s0; + wchar_t wc; + int bit, ch, head, len, tail; + + if (*s == NULL) { + _citrus_HZ_init_state(ei, psenc); + *nresult = 1; + return (0); + } + s0 = *s; + if (psenc->chlen < 0 || psenc->inuse == NULL) + return (EINVAL); + + wc = (wchar_t)0; + bit = head = tail = 0; + graphic = NULL; + for (len = 0; len <= MB_LEN_MAX;) { + if (psenc->chlen == tail) { + if (n-- < 1) { + *s = s0; + *nresult = (size_t)-2; + return (0); + } + psenc->ch[psenc->chlen++] = *s0++; + ++len; + } + ch = (unsigned char)psenc->ch[tail++]; + if (tail == 1) { + if ((ch & ~0x80) <= 0x1F) { + if (psenc->inuse != INIT0(ei)) + break; + wc = (wchar_t)ch; + goto done; + } + if (ch & 0x80) { + graphic = GR(psenc->inuse); + bit = 0x80; + ch &= ~0x80; + } else { + graphic = GL(psenc->inuse); + if (ch == ESCAPE_CHAR) + continue; + bit = 0x0; + } + if (graphic == NULL) + break; + } else if (tail == 2 && psenc->ch[0] == ESCAPE_CHAR) { + if (tail < psenc->chlen) + return (EINVAL); + if (ch == ESCAPE_CHAR) { + ++head; + } else if (ch == '\n') { + if (psenc->inuse != INIT0(ei)) + break; + tail = psenc->chlen = 0; + continue; + } else { + candidate = NULL; + init = INIT0(ei); + if (psenc->inuse == init) { + init = INIT1(ei); + } else if (INIT(psenc->inuse) == init) { + if (ESC(init) != ch) + break; + candidate = init; + } + if (candidate == NULL) { + candidate = find_escape( + SET(psenc->inuse), ch); + if (candidate == NULL) { + if (init == NULL || + ESC(init) != ch) + break; + candidate = init; + } + } + psenc->inuse = candidate; + tail = psenc->chlen = 0; + continue; + } + } else if (ch & 0x80) { + if (graphic != GR(psenc->inuse)) + break; + ch &= ~0x80; + } else { + if (graphic != GL(psenc->inuse)) + break; + } + range = &ranges[(size_t)graphic->charset]; + if (range->start > ch || range->end < ch) + break; + wc <<= 8; + wc |= ch; + if (graphic->length == (tail - head)) { + if (graphic->charset > GB2312) + bit |= ESC(psenc->inuse) << 24; + wc |= bit; + goto done; + } + } + *nresult = (size_t)-1; + return (EILSEQ); +done: + if (tail < psenc->chlen) + return (EINVAL); + *s = s0; + if (pwc != NULL) + *pwc = wc; + psenc->chlen = 0; + *nresult = (wc == 0) ? 0 : len; + + return (0); +} + +static int +_citrus_HZ_wcrtomb_priv(_HZEncodingInfo * __restrict ei, + char * __restrict s, size_t n, wchar_t wc, + _HZState * __restrict psenc, size_t * __restrict nresult) +{ + escape_t *candidate, *init; + graphic_t *graphic; + const range_t *range; + size_t len; + int bit, ch; + + if (psenc->chlen != 0 || psenc->inuse == NULL) + return (EINVAL); + if (wc & 0x80) { + bit = 0x80; + wc &= ~0x80; + } else { + bit = 0x0; + } + if ((uint32_t)wc <= 0x1F) { + candidate = INIT0(ei); + graphic = (bit == 0) ? candidate->left : candidate->right; + if (graphic == NULL) + goto ilseq; + range = &ranges[(size_t)CTRL]; + len = 1; + } else if ((uint32_t)wc <= 0x7F) { + graphic = ei->ascii; + if (graphic == NULL) + goto ilseq; + candidate = graphic->escape; + range = &ranges[(size_t)graphic->charset]; + len = graphic->length; + } else if ((uint32_t)wc <= 0x7F7F) { + graphic = ei->gb2312; + if (graphic == NULL) + goto ilseq; + candidate = graphic->escape; + range = &ranges[(size_t)graphic->charset]; + len = graphic->length; + } else { + ch = (wc >> 24) & 0xFF; + candidate = find_escape(E0SET(ei), ch); + if (candidate == NULL) { + candidate = find_escape(E1SET(ei), ch); + if (candidate == NULL) + goto ilseq; + } + wc &= ~0xFF000000; + graphic = (bit == 0) ? candidate->left : candidate->right; + if (graphic == NULL) + goto ilseq; + range = &ranges[(size_t)graphic->charset]; + len = graphic->length; + } + if (psenc->inuse != candidate) { + init = INIT0(ei); + if (SET(psenc->inuse) == SET(candidate)) { + if (INIT(psenc->inuse) != init || + psenc->inuse == init || candidate == init) + init = NULL; + } else if (candidate == (init = INIT(candidate))) { + init = NULL; + } + if (init != NULL) { + if (n < 2) + return (E2BIG); + n -= 2; + psenc->ch[psenc->chlen++] = ESCAPE_CHAR; + psenc->ch[psenc->chlen++] = ESC(init); + } + if (n < 2) + return (E2BIG); + n -= 2; + psenc->ch[psenc->chlen++] = ESCAPE_CHAR; + psenc->ch[psenc->chlen++] = ESC(candidate); + psenc->inuse = candidate; + } + if (n < len) + return (E2BIG); + while (len-- > 0) { + ch = (wc >> (len * 8)) & 0xFF; + if (range->start > ch || range->end < ch) + goto ilseq; + psenc->ch[psenc->chlen++] = ch | bit; + } + memcpy(s, psenc->ch, psenc->chlen); + *nresult = psenc->chlen; + psenc->chlen = 0; + + return (0); + +ilseq: + *nresult = (size_t)-1; + return (EILSEQ); +} + +static __inline int +_citrus_HZ_put_state_reset(_HZEncodingInfo * __restrict ei, + char * __restrict s, size_t n, _HZState * __restrict psenc, + size_t * __restrict nresult) +{ + escape_t *candidate; + + if (psenc->chlen != 0 || psenc->inuse == NULL) + return (EINVAL); + candidate = INIT0(ei); + if (psenc->inuse != candidate) { + if (n < 2) + return (E2BIG); + n -= 2; + psenc->ch[psenc->chlen++] = ESCAPE_CHAR; + psenc->ch[psenc->chlen++] = ESC(candidate); + } + if (n < 1) + return (E2BIG); + if (psenc->chlen > 0) + memcpy(s, psenc->ch, psenc->chlen); + *nresult = psenc->chlen; + _citrus_HZ_init_state(ei, psenc); + + return (0); +} + +static __inline int +_citrus_HZ_stdenc_get_state_desc_generic(_HZEncodingInfo * __restrict ei, + _HZState * __restrict psenc, int * __restrict rstate) +{ + + if (psenc->chlen < 0 || psenc->inuse == NULL) + return (EINVAL); + *rstate = (psenc->chlen == 0) + ? ((psenc->inuse == INIT0(ei)) + ? _STDENC_SDGEN_INITIAL + : _STDENC_SDGEN_STABLE) + : ((psenc->ch[0] == ESCAPE_CHAR) + ? _STDENC_SDGEN_INCOMPLETE_SHIFT + : _STDENC_SDGEN_INCOMPLETE_CHAR); + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_HZ_stdenc_wctocs(_HZEncodingInfo * __restrict ei __unused, + _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc) +{ + int bit; + + if (wc & 0x80) { + bit = 0x80; + wc &= ~0x80; + } else + bit = 0x0; + if ((uint32_t)wc <= 0x7F) { + *csid = (_csid_t)bit; + *idx = (_index_t)wc; + } else if ((uint32_t)wc <= 0x7F7F) { + *csid = (_csid_t)(bit | 0x8000); + *idx = (_index_t)wc; + } else { + *csid = (_index_t)(wc & ~0x00FFFF7F); + *idx = (_csid_t)(wc & 0x00FFFF7F); + } + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_HZ_stdenc_cstowc(_HZEncodingInfo * __restrict ei __unused, + wchar_t * __restrict wc, _csid_t csid, _index_t idx) +{ + + *wc = (wchar_t)idx; + switch (csid) { + case 0x80: + case 0x8080: + *wc |= (wchar_t)0x80; + /*FALLTHROUGH*/ + case 0x0: + case 0x8000: + break; + default: + *wc |= (wchar_t)csid; + } + + return (0); +} + +static void +_citrus_HZ_encoding_module_uninit(_HZEncodingInfo *ei) +{ + escape_t *escape; + + while ((escape = TAILQ_FIRST(E0SET(ei))) != NULL) { + TAILQ_REMOVE(E0SET(ei), escape, entry); + free(GL(escape)); + free(GR(escape)); + free(escape); + } + while ((escape = TAILQ_FIRST(E1SET(ei))) != NULL) { + TAILQ_REMOVE(E1SET(ei), escape, entry); + free(GL(escape)); + free(GR(escape)); + free(escape); + } +} + +static int +_citrus_HZ_parse_char(void **context, const char *name __unused, const char *s) +{ + escape_t *escape; + void **p; + + p = (void **)*context; + escape = (escape_t *)p[0]; + if (escape->ch != '\0') + return (EINVAL); + escape->ch = *s++; + if (escape->ch == ESCAPE_CHAR || *s != '\0') + return (EINVAL); + + return (0); +} + +static int +_citrus_HZ_parse_graphic(void **context, const char *name, const char *s) +{ + _HZEncodingInfo *ei; + escape_t *escape; + graphic_t *graphic; + void **p; + + p = (void **)*context; + escape = (escape_t *)p[0]; + ei = (_HZEncodingInfo *)p[1]; + graphic = malloc(sizeof(*graphic)); + if (graphic == NULL) + return (ENOMEM); + memset(graphic, 0, sizeof(*graphic)); + if (strcmp("GL", name) == 0) { + if (GL(escape) != NULL) + goto release; + GL(escape) = graphic; + } else if (strcmp("GR", name) == 0) { + if (GR(escape) != NULL) + goto release; + GR(escape) = graphic; + } else { +release: + free(graphic); + return (EINVAL); + } + graphic->escape = escape; + if (_bcs_strncasecmp("ASCII", s, 5) == 0) { + if (s[5] != '\0') + return (EINVAL); + graphic->charset = ASCII; + graphic->length = 1; + ei->ascii = graphic; + return (0); + } else if (_bcs_strncasecmp("GB2312", s, 6) == 0) { + if (s[6] != '\0') + return (EINVAL); + graphic->charset = GB2312; + graphic->length = 2; + ei->gb2312 = graphic; + return (0); + } else if (strncmp("94*", s, 3) == 0) + graphic->charset = CS94; + else if (strncmp("96*", s, 3) == 0) + graphic->charset = CS96; + else + return (EINVAL); + s += 3; + switch(*s) { + case '1': case '2': case '3': + graphic->length = (size_t)(*s - '0'); + if (*++s == '\0') + break; + /*FALLTHROUGH*/ + default: + return (EINVAL); + } + return (0); +} + +static const _citrus_prop_hint_t escape_hints[] = { +_CITRUS_PROP_HINT_STR("CH", &_citrus_HZ_parse_char), +_CITRUS_PROP_HINT_STR("GL", &_citrus_HZ_parse_graphic), +_CITRUS_PROP_HINT_STR("GR", &_citrus_HZ_parse_graphic), +_CITRUS_PROP_HINT_END +}; + +static int +_citrus_HZ_parse_escape(void **context, const char *name, const char *s) +{ + _HZEncodingInfo *ei; + escape_t *escape; + void *p[2]; + + ei = (_HZEncodingInfo *)*context; + escape = malloc(sizeof(*escape)); + if (escape == NULL) + return (EINVAL); + memset(escape, 0, sizeof(*escape)); + if (strcmp("0", name) == 0) { + escape->set = E0SET(ei); + TAILQ_INSERT_TAIL(E0SET(ei), escape, entry); + } else if (strcmp("1", name) == 0) { + escape->set = E1SET(ei); + TAILQ_INSERT_TAIL(E1SET(ei), escape, entry); + } else { + free(escape); + return (EINVAL); + } + p[0] = (void *)escape; + p[1] = (void *)ei; + return (_citrus_prop_parse_variable( + escape_hints, (void *)&p[0], s, strlen(s))); +} + +static const _citrus_prop_hint_t root_hints[] = { +_CITRUS_PROP_HINT_STR("0", &_citrus_HZ_parse_escape), +_CITRUS_PROP_HINT_STR("1", &_citrus_HZ_parse_escape), +_CITRUS_PROP_HINT_END +}; + +static int +_citrus_HZ_encoding_module_init(_HZEncodingInfo * __restrict ei, + const void * __restrict var, size_t lenvar) +{ + int errnum; + + memset(ei, 0, sizeof(*ei)); + TAILQ_INIT(E0SET(ei)); + TAILQ_INIT(E1SET(ei)); + errnum = _citrus_prop_parse_variable( + root_hints, (void *)ei, var, lenvar); + if (errnum != 0) + _citrus_HZ_encoding_module_uninit(ei); + return (errnum); +} + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(HZ); +_CITRUS_STDENC_DEF_OPS(HZ); + +#include "citrus_stdenc_template.h" diff --git a/lib/libiconv_modules/HZ/citrus_hz.h b/lib/libiconv_modules/HZ/citrus_hz.h new file mode 100644 index 000000000000..9737b7b34338 --- /dev/null +++ b/lib/libiconv_modules/HZ/citrus_hz.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_hz.h,v 1.1 2006/11/22 23:38:27 tnozaki Exp $ */ + +/*- + * Copyright (c)2004, 2006 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_HZ_H_ +#define _CITRUS_HZ_H_ + +__BEGIN_DECLS +_CITRUS_STDENC_GETOPS_FUNC(HZ); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/ISO2022/Makefile b/lib/libiconv_modules/ISO2022/Makefile new file mode 100644 index 000000000000..1e865ac74134 --- /dev/null +++ b/lib/libiconv_modules/ISO2022/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +SHLIB= ISO2022 +SRCS+= citrus_iso2022.c +CFLAGS+= --param max-inline-insns-single=128 + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/ISO2022/citrus_iso2022.c b/lib/libiconv_modules/ISO2022/citrus_iso2022.c new file mode 100644 index 000000000000..82ad7c365eec --- /dev/null +++ b/lib/libiconv_modules/ISO2022/citrus_iso2022.c @@ -0,0 +1,1289 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_iso2022.c,v 1.19 2008/06/14 16:01:07 tnozaki Exp $ */ + +/*- + * Copyright (c)1999, 2002 Citrus Project, + * 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. + * + * $Citrus: xpg4dl/FreeBSD/lib/libc/locale/iso2022.c,v 1.23 2001/06/21 01:51:44 yamt Exp $ + */ + +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_stdenc.h" +#include "citrus_iso2022.h" + + +/* ---------------------------------------------------------------------- + * private stuffs used by templates + */ + + +/* + * wchar_t mappings: + * ASCII (ESC ( B) 00000000 00000000 00000000 0xxxxxxx + * iso-8859-1 (ESC , A) 00000000 00000000 00000000 1xxxxxxx + * 94 charset (ESC ( F) 0fffffff 00000000 00000000 0xxxxxxx + * 94 charset (ESC ( M F) 0fffffff 1mmmmmmm 00000000 0xxxxxxx + * 96 charset (ESC , F) 0fffffff 00000000 00000000 1xxxxxxx + * 96 charset (ESC , M F) 0fffffff 1mmmmmmm 00000000 1xxxxxxx + * 94x94 charset (ESC $ ( F) 0fffffff 00000000 0xxxxxxx 0xxxxxxx + * 96x96 charset (ESC $ , F) 0fffffff 00000000 0xxxxxxx 1xxxxxxx + * 94x94 charset (ESC & V ESC $ ( F) + * 0fffffff 1vvvvvvv 0xxxxxxx 0xxxxxxx + * 94x94x94 charset (ESC $ ( F) 0fffffff 0xxxxxxx 0xxxxxxx 0xxxxxxx + * 96x96x96 charset (ESC $ , F) 0fffffff 0xxxxxxx 0xxxxxxx 1xxxxxxx + * reserved for UCS4 co-existence (UCS4 is 31bit encoding thanks to mohta bit) + * 1xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx + */ + +#define CS94 (0U) +#define CS96 (1U) +#define CS94MULTI (2U) +#define CS96MULTI (3U) + +typedef struct { + unsigned char interm; + unsigned char final; + unsigned char type; + unsigned char vers; +} _ISO2022Charset; + +static const _ISO2022Charset ascii = { CS94, 'B', '\0', '\0' }; +static const _ISO2022Charset iso88591 = { CS96, 'A', '\0', '\0' }; + +typedef struct { + _ISO2022Charset g[4]; + /* need 3 bits to hold -1, 0, ..., 3 */ + int gl:3, + gr:3, + singlegl:3, + singlegr:3; + char ch[7]; /* longest escape sequence (ESC & V ESC $ ( F) */ + size_t chlen; + int flags; +#define _ISO2022STATE_FLAG_INITIALIZED 1 +} _ISO2022State; + +typedef struct { + _ISO2022Charset *recommend[4]; + size_t recommendsize[4]; + _ISO2022Charset initg[4]; + int maxcharset; + int flags; +#define F_8BIT 0x0001 +#define F_NOOLD 0x0002 +#define F_SI 0x0010 /*0F*/ +#define F_SO 0x0020 /*0E*/ +#define F_LS0 0x0010 /*0F*/ +#define F_LS1 0x0020 /*0E*/ +#define F_LS2 0x0040 /*ESC n*/ +#define F_LS3 0x0080 /*ESC o*/ +#define F_LS1R 0x0100 /*ESC ~*/ +#define F_LS2R 0x0200 /*ESC }*/ +#define F_LS3R 0x0400 /*ESC |*/ +#define F_SS2 0x0800 /*ESC N*/ +#define F_SS3 0x1000 /*ESC O*/ +#define F_SS2R 0x2000 /*8E*/ +#define F_SS3R 0x4000 /*8F*/ +} _ISO2022EncodingInfo; + +#define _CEI_TO_EI(_cei_) (&(_cei_)->ei) +#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_ + +#define _FUNCNAME(m) _citrus_ISO2022_##m +#define _ENCODING_INFO _ISO2022EncodingInfo +#define _ENCODING_STATE _ISO2022State +#define _ENCODING_MB_CUR_MAX(_ei_) MB_LEN_MAX +#define _ENCODING_IS_STATE_DEPENDENT 1 +#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) \ + (!((_ps_)->flags & _ISO2022STATE_FLAG_INITIALIZED)) + + +#define _ISO2022INVALID (wchar_t)-1 + +static __inline bool isc0(__uint8_t x) +{ + + return ((x & 0x1f) == x); +} + +static __inline bool isc1(__uint8_t x) +{ + + return (0x80 <= x && x <= 0x9f); +} + +static __inline bool iscntl(__uint8_t x) +{ + + return (isc0(x) || isc1(x) || x == 0x7f); +} + +static __inline bool is94(__uint8_t x) +{ + + return (0x21 <= x && x <= 0x7e); +} + +static __inline bool is96(__uint8_t x) +{ + + return (0x20 <= x && x <= 0x7f); +} + +static __inline bool isecma(__uint8_t x) +{ + + return (0x30 <= x && x <= 0x7f); +} + +static __inline bool isinterm(__uint8_t x) +{ + + return (0x20 <= x && x <= 0x2f); +} + +static __inline bool isthree(__uint8_t x) +{ + + return (0x60 <= x && x <= 0x6f); +} + +static __inline int +getcs(const char * __restrict p, _ISO2022Charset * __restrict cs) +{ + + if (!strncmp(p, "94$", 3) && p[3] && !p[4]) { + cs->final = (unsigned char)(p[3] & 0xff); + cs->interm = '\0'; + cs->vers = '\0'; + cs->type = CS94MULTI; + } else if (!strncmp(p, "96$", 3) && p[3] && !p[4]) { + cs->final = (unsigned char)(p[3] & 0xff); + cs->interm = '\0'; + cs->vers = '\0'; + cs->type = CS96MULTI; + } else if (!strncmp(p, "94", 2) && p[2] && !p[3]) { + cs->final = (unsigned char)(p[2] & 0xff); + cs->interm = '\0'; + cs->vers = '\0'; + cs->type = CS94; + } else if (!strncmp(p, "96", 2) && p[2] && !p[3]) { + cs->final = (unsigned char )(p[2] & 0xff); + cs->interm = '\0'; + cs->vers = '\0'; + cs->type = CS96; + } else + return (1); + + return (0); +} + + +#define _NOTMATCH 0 +#define _MATCH 1 +#define _PARSEFAIL 2 + +static __inline int +get_recommend(_ISO2022EncodingInfo * __restrict ei, + const char * __restrict token) +{ + _ISO2022Charset cs, *p; + int i; + + if (!strchr("0123", token[0]) || token[1] != '=') + return (_NOTMATCH); + + if (getcs(&token[2], &cs) == 0) + ; + else if (!strcmp(&token[2], "94")) { + cs.final = (unsigned char)(token[4]); + cs.interm = '\0'; + cs.vers = '\0'; + cs.type = CS94; + } else if (!strcmp(&token[2], "96")) { + cs.final = (unsigned char)(token[4]); + cs.interm = '\0'; + cs.vers = '\0'; + cs.type = CS96; + } else if (!strcmp(&token[2], "94$")) { + cs.final = (unsigned char)(token[5]); + cs.interm = '\0'; + cs.vers = '\0'; + cs.type = CS94MULTI; + } else if (!strcmp(&token[2], "96$")) { + cs.final = (unsigned char)(token[5]); + cs.interm = '\0'; + cs.vers = '\0'; + cs.type = CS96MULTI; + } else + return (_PARSEFAIL); + + i = token[0] - '0'; + if (!ei->recommend[i]) + ei->recommend[i] = malloc(sizeof(_ISO2022Charset)); + else { + p = realloc(ei->recommend[i], + sizeof(_ISO2022Charset) * (ei->recommendsize[i] + 1)); + if (!p) + return (_PARSEFAIL); + ei->recommend[i] = p; + } + if (!ei->recommend[i]) + return (_PARSEFAIL); + ei->recommendsize[i]++; + + (ei->recommend[i] + (ei->recommendsize[i] - 1))->final = cs.final; + (ei->recommend[i] + (ei->recommendsize[i] - 1))->interm = cs.interm; + (ei->recommend[i] + (ei->recommendsize[i] - 1))->vers = cs.vers; + (ei->recommend[i] + (ei->recommendsize[i] - 1))->type = cs.type; + + return (_MATCH); +} + +static __inline int +get_initg(_ISO2022EncodingInfo * __restrict ei, + const char * __restrict token) +{ + _ISO2022Charset cs; + + if (strncmp("INIT", &token[0], 4) || + !strchr("0123", token[4]) || + token[5] != '=') + return (_NOTMATCH); + + if (getcs(&token[6], &cs) != 0) + return (_PARSEFAIL); + + ei->initg[token[4] - '0'].type = cs.type; + ei->initg[token[4] - '0'].final = cs.final; + ei->initg[token[4] - '0'].interm = cs.interm; + ei->initg[token[4] - '0'].vers = cs.vers; + + return (_MATCH); +} + +static __inline int +get_max(_ISO2022EncodingInfo * __restrict ei, + const char * __restrict token) +{ + if (!strcmp(token, "MAX1")) + ei->maxcharset = 1; + else if (!strcmp(token, "MAX2")) + ei->maxcharset = 2; + else if (!strcmp(token, "MAX3")) + ei->maxcharset = 3; + else + return (_NOTMATCH); + + return (_MATCH); +} + + +static __inline int +get_flags(_ISO2022EncodingInfo * __restrict ei, + const char * __restrict token) +{ + static struct { + const char *tag; + int flag; + } const tags[] = { + { "DUMMY", 0 }, + { "8BIT", F_8BIT }, + { "NOOLD", F_NOOLD }, + { "SI", F_SI }, + { "SO", F_SO }, + { "LS0", F_LS0 }, + { "LS1", F_LS1 }, + { "LS2", F_LS2 }, + { "LS3", F_LS3 }, + { "LS1R", F_LS1R }, + { "LS2R", F_LS2R }, + { "LS3R", F_LS3R }, + { "SS2", F_SS2 }, + { "SS3", F_SS3 }, + { "SS2R", F_SS2R }, + { "SS3R", F_SS3R }, + { NULL, 0 } + }; + int i; + + for (i = 0; tags[i].tag; i++) + if (!strcmp(token, tags[i].tag)) { + ei->flags |= tags[i].flag; + return (_MATCH); + } + + return (_NOTMATCH); +} + + +static __inline int +_citrus_ISO2022_parse_variable(_ISO2022EncodingInfo * __restrict ei, + const void * __restrict var, size_t lenvar __unused) +{ + char const *e, *v; + char buf[20]; + size_t len; + int i, ret; + + /* + * parse VARIABLE section. + */ + + if (!var) + return (EFTYPE); + + v = (const char *) var; + + /* initialize structure */ + ei->maxcharset = 0; + for (i = 0; i < 4; i++) { + ei->recommend[i] = NULL; + ei->recommendsize[i] = 0; + } + ei->flags = 0; + + while (*v) { + while (*v == ' ' || *v == '\t') + ++v; + + /* find the token */ + e = v; + while (*e && *e != ' ' && *e != '\t') + ++e; + + len = e - v; + if (len == 0) + break; + if (len >= sizeof(buf)) + goto parsefail; + snprintf(buf, sizeof(buf), "%.*s", (int)len, v); + + if ((ret = get_recommend(ei, buf)) != _NOTMATCH) + ; + else if ((ret = get_initg(ei, buf)) != _NOTMATCH) + ; + else if ((ret = get_max(ei, buf)) != _NOTMATCH) + ; + else if ((ret = get_flags(ei, buf)) != _NOTMATCH) + ; + else + ret = _PARSEFAIL; + if (ret == _PARSEFAIL) + goto parsefail; + v = e; + + } + + return (0); + +parsefail: + free(ei->recommend[0]); + free(ei->recommend[1]); + free(ei->recommend[2]); + free(ei->recommend[3]); + + return (EFTYPE); +} + +static __inline void +/*ARGSUSED*/ +_citrus_ISO2022_init_state(_ISO2022EncodingInfo * __restrict ei, + _ISO2022State * __restrict s) +{ + int i; + + memset(s, 0, sizeof(*s)); + s->gl = 0; + s->gr = (ei->flags & F_8BIT) ? 1 : -1; + + for (i = 0; i < 4; i++) + if (ei->initg[i].final) { + s->g[i].type = ei->initg[i].type; + s->g[i].final = ei->initg[i].final; + s->g[i].interm = ei->initg[i].interm; + } + s->singlegl = s->singlegr = -1; + s->flags |= _ISO2022STATE_FLAG_INITIALIZED; +} + +static __inline void +/*ARGSUSED*/ +_citrus_ISO2022_pack_state(_ISO2022EncodingInfo * __restrict ei __unused, + void * __restrict pspriv, const _ISO2022State * __restrict s) +{ + + memcpy(pspriv, (const void *)s, sizeof(*s)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_ISO2022_unpack_state(_ISO2022EncodingInfo * __restrict ei __unused, + _ISO2022State * __restrict s, const void * __restrict pspriv) +{ + + memcpy((void *)s, pspriv, sizeof(*s)); +} + +static int +/*ARGSUSED*/ +_citrus_ISO2022_encoding_module_init(_ISO2022EncodingInfo * __restrict ei, + const void * __restrict var, size_t lenvar) +{ + + return (_citrus_ISO2022_parse_variable(ei, var, lenvar)); +} + +static void +/*ARGSUSED*/ +_citrus_ISO2022_encoding_module_uninit(_ISO2022EncodingInfo *ei __unused) +{ + +} + +#define ESC '\033' +#define ECMA -1 +#define INTERM -2 +#define OECMA -3 +static const struct seqtable { + int type; + int csoff; + int finaloff; + int intermoff; + int versoff; + int len; + int chars[10]; +} seqtable[] = { + /* G0 94MULTI special */ + { CS94MULTI, -1, 2, -1, -1, 3, { ESC, '$', OECMA }, }, + /* G0 94MULTI special with version identification */ + { CS94MULTI, -1, 5, -1, 2, 6, { ESC, '&', ECMA, ESC, '$', OECMA }, }, + /* G? 94 */ + { CS94, 1, 2, -1, -1, 3, { ESC, CS94, ECMA, }, }, + /* G? 94 with 2nd intermediate char */ + { CS94, 1, 3, 2, -1, 4, { ESC, CS94, INTERM, ECMA, }, }, + /* G? 96 */ + { CS96, 1, 2, -1, -1, 3, { ESC, CS96, ECMA, }, }, + /* G? 96 with 2nd intermediate char */ + { CS96, 1, 3, 2, -1, 4, { ESC, CS96, INTERM, ECMA, }, }, + /* G? 94MULTI */ + { CS94MULTI, 2, 3, -1, -1, 4, { ESC, '$', CS94, ECMA, }, }, + /* G? 96MULTI */ + { CS96MULTI, 2, 3, -1, -1, 4, { ESC, '$', CS96, ECMA, }, }, + /* G? 94MULTI with version specification */ + { CS94MULTI, 5, 6, -1, 2, 7, { ESC, '&', ECMA, ESC, '$', CS94, ECMA, }, }, + /* LS2/3 */ + { -1, -1, -1, -1, -1, 2, { ESC, 'n', }, }, + { -1, -1, -1, -1, -1, 2, { ESC, 'o', }, }, + /* LS1/2/3R */ + { -1, -1, -1, -1, -1, 2, { ESC, '~', }, }, + { -1, -1, -1, -1, -1, 2, { ESC, /*{*/ '}', }, }, + { -1, -1, -1, -1, -1, 2, { ESC, '|', }, }, + /* SS2/3 */ + { -1, -1, -1, -1, -1, 2, { ESC, 'N', }, }, + { -1, -1, -1, -1, -1, 2, { ESC, 'O', }, }, + /* end of records */ +// { 0, } + { 0, 0, 0, 0, 0, 0, { ESC, 0, }, } +}; + +static int +seqmatch(const char * __restrict s, size_t n, + const struct seqtable * __restrict sp) +{ + const int *p; + + p = sp->chars; + while ((size_t)(p - sp->chars) < n && p - sp->chars < sp->len) { + switch (*p) { + case ECMA: + if (!isecma(*s)) + goto terminate; + break; + case OECMA: + if (*s && strchr("@AB", *s)) + break; + else + goto terminate; + case INTERM: + if (!isinterm(*s)) + goto terminate; + break; + case CS94: + if (*s && strchr("()*+", *s)) + break; + else + goto terminate; + case CS96: + if (*s && strchr(",-./", *s)) + break; + else + goto terminate; + default: + if (*s != *p) + goto terminate; + break; + } + + p++; + s++; + } + +terminate: + return (p - sp->chars); +} + +static wchar_t +_ISO2022_sgetwchar(_ISO2022EncodingInfo * __restrict ei __unused, + char * __restrict string, size_t n, char ** __restrict result, + _ISO2022State * __restrict psenc) +{ + const struct seqtable *sp; + wchar_t wchar = 0; + int i, cur, nmatch; + + while (1) { + /* SI/SO */ + if (1 <= n && string[0] == '\017') { + psenc->gl = 0; + string++; + n--; + continue; + } + if (1 <= n && string[0] == '\016') { + psenc->gl = 1; + string++; + n--; + continue; + } + + /* SS2/3R */ + if (1 <= n && string[0] && strchr("\217\216", string[0])) { + psenc->singlegl = psenc->singlegr = + (string[0] - '\216') + 2; + string++; + n--; + continue; + } + + /* eat the letter if this is not ESC */ + if (1 <= n && string[0] != '\033') + break; + + /* look for a perfect match from escape sequences */ + for (sp = &seqtable[0]; sp->len; sp++) { + nmatch = seqmatch(string, n, sp); + if (sp->len == nmatch && n >= (size_t)(sp->len)) + break; + } + + if (!sp->len) + goto notseq; + + if (sp->type != -1) { + if (sp->csoff == -1) + i = 0; + else { + switch (sp->type) { + case CS94: + case CS94MULTI: + i = string[sp->csoff] - '('; + break; + case CS96: + case CS96MULTI: + i = string[sp->csoff] - ','; + break; + default: + return (_ISO2022INVALID); + } + } + psenc->g[i].type = sp->type; + psenc->g[i].final = '\0'; + psenc->g[i].interm = '\0'; + psenc->g[i].vers = '\0'; + /* sp->finaloff must not be -1 */ + if (sp->finaloff != -1) + psenc->g[i].final = string[sp->finaloff]; + if (sp->intermoff != -1) + psenc->g[i].interm = string[sp->intermoff]; + if (sp->versoff != -1) + psenc->g[i].vers = string[sp->versoff]; + + string += sp->len; + n -= sp->len; + continue; + } + + /* LS2/3 */ + if (2 <= n && string[0] == '\033' && + string[1] && strchr("no", string[1])) { + psenc->gl = string[1] - 'n' + 2; + string += 2; + n -= 2; + continue; + } + + /* LS1/2/3R */ + /* XXX: { for vi showmatch */ + if (2 <= n && string[0] == '\033' && + string[1] && strchr("~}|", string[1])) { + psenc->gr = 3 - (string[1] - '|'); + string += 2; + n -= 2; + continue; + } + + /* SS2/3 */ + if (2 <= n && string[0] == '\033' && string[1] && + strchr("NO", string[1])) { + psenc->singlegl = (string[1] - 'N') + 2; + string += 2; + n -= 2; + continue; + } + + notseq: + /* + * if we've got an unknown escape sequence, eat the ESC at the + * head. otherwise, wait till full escape sequence comes. + */ + for (sp = &seqtable[0]; sp->len; sp++) { + nmatch = seqmatch(string, n, sp); + if (!nmatch) + continue; + + /* + * if we are in the middle of escape sequence, + * we still need to wait for more characters to come + */ + if (n < (size_t)(sp->len)) { + if ((size_t)(nmatch) == n) { + if (result) + *result = string; + return (_ISO2022INVALID); + } + } else { + if (nmatch == sp->len) { + /* this case should not happen */ + goto eat; + } + } + } + + break; + } + +eat: + /* no letter to eat */ + if (n < 1) { + if (result) + *result = string; + return (_ISO2022INVALID); + } + + /* normal chars. always eat C0/C1 as is. */ + if (iscntl(*string & 0xff)) + cur = -1; + else if (*string & 0x80) + cur = (psenc->singlegr == -1) ? psenc->gr : psenc->singlegr; + else + cur = (psenc->singlegl == -1) ? psenc->gl : psenc->singlegl; + + if (cur == -1) { +asis: + wchar = *string++ & 0xff; + if (result) + *result = string; + /* reset single shift state */ + psenc->singlegr = psenc->singlegl = -1; + return (wchar); + } + + /* length error check */ + switch (psenc->g[cur].type) { + case CS94MULTI: + case CS96MULTI: + if (!isthree(psenc->g[cur].final)) { + if (2 <= n && + (string[0] & 0x80) == (string[1] & 0x80)) + break; + } else { + if (3 <= n && + (string[0] & 0x80) == (string[1] & 0x80) && + (string[0] & 0x80) == (string[2] & 0x80)) + break; + } + + /* we still need to wait for more characters to come */ + if (result) + *result = string; + return (_ISO2022INVALID); + + case CS94: + case CS96: + if (1 <= n) + break; + + /* we still need to wait for more characters to come */ + if (result) + *result = string; + return (_ISO2022INVALID); + } + + /* range check */ + switch (psenc->g[cur].type) { + case CS94: + if (!(is94(string[0] & 0x7f))) + goto asis; + case CS96: + if (!(is96(string[0] & 0x7f))) + goto asis; + break; + case CS94MULTI: + if (!(is94(string[0] & 0x7f) && is94(string[1] & 0x7f))) + goto asis; + break; + case CS96MULTI: + if (!(is96(string[0] & 0x7f) && is96(string[1] & 0x7f))) + goto asis; + break; + } + + /* extract the character. */ + switch (psenc->g[cur].type) { + case CS94: + /* special case for ASCII. */ + if (psenc->g[cur].final == 'B' && !psenc->g[cur].interm) { + wchar = *string++; + wchar &= 0x7f; + break; + } + wchar = psenc->g[cur].final; + wchar = (wchar << 8); + wchar |= (psenc->g[cur].interm ? (0x80 | psenc->g[cur].interm) : 0); + wchar = (wchar << 8); + wchar = (wchar << 8) | (*string++ & 0x7f); + break; + case CS96: + /* special case for ISO-8859-1. */ + if (psenc->g[cur].final == 'A' && !psenc->g[cur].interm) { + wchar = *string++; + wchar &= 0x7f; + wchar |= 0x80; + break; + } + wchar = psenc->g[cur].final; + wchar = (wchar << 8); + wchar |= (psenc->g[cur].interm ? (0x80 | psenc->g[cur].interm) : 0); + wchar = (wchar << 8); + wchar = (wchar << 8) | (*string++ & 0x7f); + wchar |= 0x80; + break; + case CS94MULTI: + case CS96MULTI: + wchar = psenc->g[cur].final; + wchar = (wchar << 8); + if (isthree(psenc->g[cur].final)) + wchar |= (*string++ & 0x7f); + wchar = (wchar << 8) | (*string++ & 0x7f); + wchar = (wchar << 8) | (*string++ & 0x7f); + if (psenc->g[cur].type == CS96MULTI) + wchar |= 0x80; + break; + } + + if (result) + *result = string; + /* reset single shift state */ + psenc->singlegr = psenc->singlegl = -1; + return (wchar); +} + + + +static int +_citrus_ISO2022_mbrtowc_priv(_ISO2022EncodingInfo * __restrict ei, + wchar_t * __restrict pwc, char ** __restrict s, + size_t n, _ISO2022State * __restrict psenc, size_t * __restrict nresult) +{ + char *p, *result, *s0; + wchar_t wchar; + int c, chlenbak; + + if (*s == NULL) { + _citrus_ISO2022_init_state(ei, psenc); + *nresult = _ENCODING_IS_STATE_DEPENDENT; + return (0); + } + s0 = *s; + c = 0; + chlenbak = psenc->chlen; + + /* + * if we have something in buffer, use that. + * otherwise, skip here + */ + if (psenc->chlen > sizeof(psenc->ch)) { + /* illgeal state */ + _citrus_ISO2022_init_state(ei, psenc); + goto encoding_error; + } + if (psenc->chlen == 0) + goto emptybuf; + + /* buffer is not empty */ + p = psenc->ch; + while (psenc->chlen < sizeof(psenc->ch)) { + if (n > 0) { + psenc->ch[psenc->chlen++] = *s0++; + n--; + } + + wchar = _ISO2022_sgetwchar(ei, p, psenc->chlen - (p-psenc->ch), + &result, psenc); + c += result - p; + if (wchar != _ISO2022INVALID) { + if (psenc->chlen > (size_t)c) + memmove(psenc->ch, result, psenc->chlen - c); + if (psenc->chlen < (size_t)c) + psenc->chlen = 0; + else + psenc->chlen -= c; + goto output; + } + + if (n == 0) { + if ((size_t)(result - p) == psenc->chlen) + /* complete shift sequence. */ + psenc->chlen = 0; + goto restart; + } + + p = result; + } + + /* escape sequence too long? */ + goto encoding_error; + +emptybuf: + wchar = _ISO2022_sgetwchar(ei, s0, n, &result, psenc); + if (wchar != _ISO2022INVALID) { + c += result - s0; + psenc->chlen = 0; + s0 = result; + goto output; + } + if (result > s0) { + c += (result - s0); + n -= (result - s0); + s0 = result; + if (n > 0) + goto emptybuf; + /* complete shift sequence. */ + goto restart; + } + n += c; + if (n < sizeof(psenc->ch)) { + memcpy(psenc->ch, s0 - c, n); + psenc->chlen = n; + s0 = result; + goto restart; + } + + /* escape sequence too long? */ + +encoding_error: + psenc->chlen = 0; + *nresult = (size_t)-1; + return (EILSEQ); + +output: + *s = s0; + if (pwc) + *pwc = wchar; + *nresult = wchar ? c - chlenbak : 0; + return (0); + +restart: + *s = s0; + *nresult = (size_t)-2; + + return (0); +} + +static int +recommendation(_ISO2022EncodingInfo * __restrict ei, + _ISO2022Charset * __restrict cs) +{ + _ISO2022Charset *recommend; + size_t j; + int i; + + /* first, try a exact match. */ + for (i = 0; i < 4; i++) { + recommend = ei->recommend[i]; + for (j = 0; j < ei->recommendsize[i]; j++) { + if (cs->type != recommend[j].type) + continue; + if (cs->final != recommend[j].final) + continue; + if (cs->interm != recommend[j].interm) + continue; + + return (i); + } + } + + /* then, try a wildcard match over final char. */ + for (i = 0; i < 4; i++) { + recommend = ei->recommend[i]; + for (j = 0; j < ei->recommendsize[i]; j++) { + if (cs->type != recommend[j].type) + continue; + if (cs->final && (cs->final != recommend[j].final)) + continue; + if (cs->interm && (cs->interm != recommend[j].interm)) + continue; + + return (i); + } + } + + /* there's no recommendation. make a guess. */ + if (ei->maxcharset == 0) { + return (0); + } else { + switch (cs->type) { + case CS94: + case CS94MULTI: + return (0); + case CS96: + case CS96MULTI: + return (1); + } + } + return (0); +} + +static int +_ISO2022_sputwchar(_ISO2022EncodingInfo * __restrict ei, wchar_t wc, + char * __restrict string, size_t n, char ** __restrict result, + _ISO2022State * __restrict psenc, size_t * __restrict nresult) +{ + _ISO2022Charset cs; + char *p; + char tmp[MB_LEN_MAX]; + size_t len; + int bit8, i = 0, target; + unsigned char mask; + + if (isc0(wc & 0xff)) { + /* go back to INIT0 or ASCII on control chars */ + cs = ei->initg[0].final ? ei->initg[0] : ascii; + } else if (isc1(wc & 0xff)) { + /* go back to INIT1 or ISO-8859-1 on control chars */ + cs = ei->initg[1].final ? ei->initg[1] : iso88591; + } else if (!(wc & ~0xff)) { + if (wc & 0x80) { + /* special treatment for ISO-8859-1 */ + cs = iso88591; + } else { + /* special treatment for ASCII */ + cs = ascii; + } + } else { + cs.final = (wc >> 24) & 0x7f; + if ((wc >> 16) & 0x80) + cs.interm = (wc >> 16) & 0x7f; + else + cs.interm = '\0'; + if (wc & 0x80) + cs.type = (wc & 0x00007f00) ? CS96MULTI : CS96; + else + cs.type = (wc & 0x00007f00) ? CS94MULTI : CS94; + } + target = recommendation(ei, &cs); + p = tmp; + bit8 = ei->flags & F_8BIT; + + /* designate the charset onto the target plane(G0/1/2/3). */ + if (psenc->g[target].type == cs.type && + psenc->g[target].final == cs.final && + psenc->g[target].interm == cs.interm) + goto planeok; + + *p++ = '\033'; + if (cs.type == CS94MULTI || cs.type == CS96MULTI) + *p++ = '$'; + if (target == 0 && cs.type == CS94MULTI && strchr("@AB", cs.final) && + !cs.interm && !(ei->flags & F_NOOLD)) + ; + else if (cs.type == CS94 || cs.type == CS94MULTI) + *p++ = "()*+"[target]; + else + *p++ = ",-./"[target]; + if (cs.interm) + *p++ = cs.interm; + *p++ = cs.final; + + psenc->g[target].type = cs.type; + psenc->g[target].final = cs.final; + psenc->g[target].interm = cs.interm; + +planeok: + /* invoke the plane onto GL or GR. */ + if (psenc->gl == target) + goto sideok; + if (bit8 && psenc->gr == target) + goto sideok; + + if (target == 0 && (ei->flags & F_LS0)) { + *p++ = '\017'; + psenc->gl = 0; + } else if (target == 1 && (ei->flags & F_LS1)) { + *p++ = '\016'; + psenc->gl = 1; + } else if (target == 2 && (ei->flags & F_LS2)) { + *p++ = '\033'; + *p++ = 'n'; + psenc->gl = 2; + } else if (target == 3 && (ei->flags & F_LS3)) { + *p++ = '\033'; + *p++ = 'o'; + psenc->gl = 3; + } else if (bit8 && target == 1 && (ei->flags & F_LS1R)) { + *p++ = '\033'; + *p++ = '~'; + psenc->gr = 1; + } else if (bit8 && target == 2 && (ei->flags & F_LS2R)) { + *p++ = '\033'; + /*{*/ + *p++ = '}'; + psenc->gr = 2; + } else if (bit8 && target == 3 && (ei->flags & F_LS3R)) { + *p++ = '\033'; + *p++ = '|'; + psenc->gr = 3; + } else if (target == 2 && (ei->flags & F_SS2)) { + *p++ = '\033'; + *p++ = 'N'; + psenc->singlegl = 2; + } else if (target == 3 && (ei->flags & F_SS3)) { + *p++ = '\033'; + *p++ = 'O'; + psenc->singlegl = 3; + } else if (bit8 && target == 2 && (ei->flags & F_SS2R)) { + *p++ = '\216'; + *p++ = 'N'; + psenc->singlegl = psenc->singlegr = 2; + } else if (bit8 && target == 3 && (ei->flags & F_SS3R)) { + *p++ = '\217'; + *p++ = 'O'; + psenc->singlegl = psenc->singlegr = 3; + } else + goto ilseq; + +sideok: + if (psenc->singlegl == target) + mask = 0x00; + else if (psenc->singlegr == target) + mask = 0x80; + else if (psenc->gl == target) + mask = 0x00; + else if ((ei->flags & F_8BIT) && psenc->gr == target) + mask = 0x80; + else + goto ilseq; + + switch (cs.type) { + case CS94: + case CS96: + i = 1; + break; + case CS94MULTI: + case CS96MULTI: + i = !iscntl(wc & 0xff) ? + (isthree(cs.final) ? 3 : 2) : 1; + break; + } + while (i-- > 0) + *p++ = ((wc >> (i << 3)) & 0x7f) | mask; + + /* reset single shift state */ + psenc->singlegl = psenc->singlegr = -1; + + len = (size_t)(p - tmp); + if (n < len) { + if (result) + *result = (char *)0; + *nresult = (size_t)-1; + return (E2BIG); + } + if (result) + *result = string + len; + memcpy(string, tmp, len); + *nresult = len; + + return (0); + +ilseq: + *nresult = (size_t)-1; + return (EILSEQ); +} + +static int +_citrus_ISO2022_put_state_reset(_ISO2022EncodingInfo * __restrict ei, + char * __restrict s, size_t n, _ISO2022State * __restrict psenc, + size_t * __restrict nresult) +{ + char *result; + char buf[MB_LEN_MAX]; + size_t len; + int ret; + + /* XXX state will be modified after this operation... */ + ret = _ISO2022_sputwchar(ei, L'\0', buf, sizeof(buf), &result, psenc, + &len); + if (ret) { + *nresult = len; + return (ret); + } + + if (sizeof(buf) < len || n < len-1) { + /* XXX should recover state? */ + *nresult = (size_t)-1; + return (E2BIG); + } + + memcpy(s, buf, len - 1); + *nresult = len - 1; + return (0); +} + +static int +_citrus_ISO2022_wcrtomb_priv(_ISO2022EncodingInfo * __restrict ei, + char * __restrict s, size_t n, wchar_t wc, + _ISO2022State * __restrict psenc, size_t * __restrict nresult) +{ + char *result; + char buf[MB_LEN_MAX]; + size_t len; + int ret; + + /* XXX state will be modified after this operation... */ + ret = _ISO2022_sputwchar(ei, wc, buf, sizeof(buf), &result, psenc, + &len); + if (ret) { + *nresult = len; + return (ret); + } + + if (sizeof(buf) < len || n < len) { + /* XXX should recover state? */ + *nresult = (size_t)-1; + return (E2BIG); + } + + memcpy(s, buf, len); + *nresult = len; + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_ISO2022_stdenc_wctocs(_ISO2022EncodingInfo * __restrict ei __unused, + _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc) +{ + wchar_t m, nm; + + m = wc & 0x7FFF8080; + nm = wc & 0x007F7F7F; + if (m & 0x00800000) + nm &= 0x00007F7F; + else + m &= 0x7F008080; + if (nm & 0x007F0000) { + /* ^3 mark */ + m |= 0x007F0000; + } else if (nm & 0x00007F00) { + /* ^2 mark */ + m |= 0x00007F00; + } + *csid = (_csid_t)m; + *idx = (_index_t)nm; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_ISO2022_stdenc_cstowc(_ISO2022EncodingInfo * __restrict ei __unused, + wchar_t * __restrict wc, _csid_t csid, _index_t idx) +{ + + *wc = (wchar_t)(csid & 0x7F808080) | (wchar_t)idx; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_ISO2022_stdenc_get_state_desc_generic(_ISO2022EncodingInfo * __restrict ei __unused, + _ISO2022State * __restrict psenc, int * __restrict rstate) +{ + + if (psenc->chlen == 0) { + /* XXX: it should distinguish initial and stable. */ + *rstate = _STDENC_SDGEN_STABLE; + } else + *rstate = (psenc->ch[0] == '\033') ? + _STDENC_SDGEN_INCOMPLETE_SHIFT : + _STDENC_SDGEN_INCOMPLETE_CHAR; + return (0); +} + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(ISO2022); +_CITRUS_STDENC_DEF_OPS(ISO2022); + +#include "citrus_stdenc_template.h" diff --git a/lib/libiconv_modules/ISO2022/citrus_iso2022.h b/lib/libiconv_modules/ISO2022/citrus_iso2022.h new file mode 100644 index 000000000000..c5bbc40c9111 --- /dev/null +++ b/lib/libiconv_modules/ISO2022/citrus_iso2022.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_iso2022.h,v 1.2 2003/06/25 09:51:44 tshiozak Exp $ */ + +/*- + * Copyright (c)2002 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_ISO2022_H_ +#define _CITRUS_ISO2022_H_ + +__BEGIN_DECLS +_CITRUS_STDENC_GETOPS_FUNC(ISO2022); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/JOHAB/Makefile b/lib/libiconv_modules/JOHAB/Makefile new file mode 100644 index 000000000000..b94544521665 --- /dev/null +++ b/lib/libiconv_modules/JOHAB/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +SHLIB= JOHAB +SRCS+= citrus_johab.c +CFLAGS+= --param max-inline-insns-single=16 + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/JOHAB/citrus_johab.c b/lib/libiconv_modules/JOHAB/citrus_johab.c new file mode 100644 index 000000000000..35c35f3384b9 --- /dev/null +++ b/lib/libiconv_modules/JOHAB/citrus_johab.c @@ -0,0 +1,333 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_johab.c,v 1.4 2008/06/14 16:01:07 tnozaki Exp $ */ + +/*- + * Copyright (c)2006 Citrus Project, + * 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. + */ +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_module.h" +#include "citrus_stdenc.h" +#include "citrus_johab.h" + +/* ---------------------------------------------------------------------- + * private stuffs used by templates + */ + +typedef struct { + int chlen; + char ch[2]; +} _JOHABState; + +typedef struct { + int dummy; +} _JOHABEncodingInfo; + +#define _CEI_TO_EI(_cei_) (&(_cei_)->ei) +#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_ + +#define _FUNCNAME(m) _citrus_JOHAB_##m +#define _ENCODING_INFO _JOHABEncodingInfo +#define _ENCODING_STATE _JOHABState +#define _ENCODING_MB_CUR_MAX(_ei_) 2 +#define _ENCODING_IS_STATE_DEPENDENT 0 +#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0 + + +static __inline void +/*ARGSUSED*/ +_citrus_JOHAB_init_state(_JOHABEncodingInfo * __restrict ei __unused, + _JOHABState * __restrict psenc) +{ + + psenc->chlen = 0; +} + +static __inline void +/*ARGSUSED*/ +_citrus_JOHAB_pack_state(_JOHABEncodingInfo * __restrict ei __unused, + void * __restrict pspriv, const _JOHABState * __restrict psenc) +{ + + memcpy(pspriv, (const void *)psenc, sizeof(*psenc)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_JOHAB_unpack_state(_JOHABEncodingInfo * __restrict ei __unused, + _JOHABState * __restrict psenc, const void * __restrict pspriv) +{ + + memcpy((void *)psenc, pspriv, sizeof(*psenc)); +} + +static void +/*ARGSUSED*/ +_citrus_JOHAB_encoding_module_uninit(_JOHABEncodingInfo *ei __unused) +{ + + /* ei may be null */ +} + +static int +/*ARGSUSED*/ +_citrus_JOHAB_encoding_module_init(_JOHABEncodingInfo * __restrict ei __unused, + const void * __restrict var __unused, size_t lenvar __unused) +{ + + /* ei may be null */ + return (0); +} + +static __inline bool +ishangul(int l, int t) +{ + + return ((l >= 0x84 && l <= 0xD3) && + ((t >= 0x41 && t <= 0x7E) || (t >= 0x81 && t <= 0xFE))); +} + +static __inline bool +isuda(int l, int t) +{ + + return ((l == 0xD8) && + ((t >= 0x31 && t <= 0x7E) || (t >= 0x91 && t <= 0xFE))); +} + +static __inline bool +ishanja(int l, int t) +{ + + return (((l >= 0xD9 && l <= 0xDE) || (l >= 0xE0 && l <= 0xF9)) && + ((t >= 0x31 && t <= 0x7E) || (t >= 0x91 && t <= 0xFE))); +} + +static int +/*ARGSUSED*/ +_citrus_JOHAB_mbrtowc_priv(_JOHABEncodingInfo * __restrict ei, + wchar_t * __restrict pwc, char ** __restrict s, size_t n, + _JOHABState * __restrict psenc, size_t * __restrict nresult) +{ + char *s0; + int l, t; + + if (*s == NULL) { + _citrus_JOHAB_init_state(ei, psenc); + *nresult = _ENCODING_IS_STATE_DEPENDENT; + return (0); + } + s0 = *s; + + switch (psenc->chlen) { + case 0: + if (n-- < 1) + goto restart; + l = *s0++ & 0xFF; + if (l <= 0x7F) { + if (pwc != NULL) + *pwc = (wchar_t)l; + *nresult = (l == 0) ? 0 : 1; + *s = s0; + return (0); + } + psenc->ch[psenc->chlen++] = l; + break; + case 1: + l = psenc->ch[0] & 0xFF; + break; + default: + return (EINVAL); + } + if (n-- < 1) { +restart: + *nresult = (size_t)-2; + *s = s0; + return (0); + } + t = *s0++ & 0xFF; + if (!ishangul(l, t) && !isuda(l, t) && !ishanja(l, t)) { + *nresult = (size_t)-1; + return (EILSEQ); + } + if (pwc != NULL) + *pwc = (wchar_t)(l << 8 | t); + *nresult = s0 - *s; + *s = s0; + psenc->chlen = 0; + + return (0); +} + +static int +/*ARGSUSED*/ +_citrus_JOHAB_wcrtomb_priv(_JOHABEncodingInfo * __restrict ei __unused, + char * __restrict s, size_t n, wchar_t wc, + _JOHABState * __restrict psenc, size_t * __restrict nresult) +{ + int l, t; + + if (psenc->chlen != 0) + return (EINVAL); + + /* XXX assume wchar_t as int */ + if ((uint32_t)wc <= 0x7F) { + if (n < 1) + goto e2big; + *s = wc & 0xFF; + *nresult = 1; + } else if ((uint32_t)wc <= 0xFFFF) { + if (n < 2) { +e2big: + *nresult = (size_t)-1; + return (E2BIG); + } + l = (wc >> 8) & 0xFF; + t = wc & 0xFF; + if (!ishangul(l, t) && !isuda(l, t) && !ishanja(l, t)) + goto ilseq; + *s++ = l; + *s = t; + *nresult = 2; + } else { +ilseq: + *nresult = (size_t)-1; + return (EILSEQ); + } + return (0); + +} + +static __inline int +/*ARGSUSED*/ +_citrus_JOHAB_stdenc_wctocs(_JOHABEncodingInfo * __restrict ei __unused, + _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc) +{ + int m, l, linear, t; + + /* XXX assume wchar_t as int */ + if ((uint32_t)wc <= 0x7F) { + *idx = (_index_t)wc; + *csid = 0; + } else if ((uint32_t)wc <= 0xFFFF) { + l = (wc >> 8) & 0xFF; + t = wc & 0xFF; + if (ishangul(l, t) || isuda(l, t)) { + *idx = (_index_t)wc; + *csid = 1; + } else { + if (l >= 0xD9 && l <= 0xDE) { + linear = l - 0xD9; + m = 0x21; + } else if (l >= 0xE0 && l <= 0xF9) { + linear = l - 0xE0; + m = 0x4A; + } else + return (EILSEQ); + linear *= 188; + if (t >= 0x31 && t <= 0x7E) + linear += t - 0x31; + else if (t >= 0x91 && t <= 0xFE) + linear += t - 0x43; + else + return (EILSEQ); + l = (linear / 94) + m; + t = (linear % 94) + 0x21; + *idx = (_index_t)((l << 8) | t); + *csid = 2; + } + } else + return (EILSEQ); + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_JOHAB_stdenc_cstowc(_JOHABEncodingInfo * __restrict ei __unused, + wchar_t * __restrict wc, _csid_t csid, _index_t idx) +{ + int m, n, l, linear, t; + + switch (csid) { + case 0: + case 1: + *wc = (wchar_t)idx; + break; + case 2: + if (idx >= 0x2121 && idx <= 0x2C71) { + m = 0xD9; + n = 0x21; + } else if (idx >= 0x4A21 && idx <= 0x7D7E) { + m = 0xE0; + n = 0x4A; + } else + return (EILSEQ); + l = ((idx >> 8) & 0xFF) - n; + t = (idx & 0xFF) - 0x21; + linear = (l * 94) + t; + l = (linear / 188) + m; + t = linear % 188; + t += (t <= 0x4D) ? 0x31 : 0x43; + break; + default: + return (EILSEQ); + } + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_JOHAB_stdenc_get_state_desc_generic(_JOHABEncodingInfo * __restrict ei __unused, + _JOHABState * __restrict psenc, int * __restrict rstate) +{ + + *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL : + _STDENC_SDGEN_INCOMPLETE_CHAR; + return (0); +} + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(JOHAB); +_CITRUS_STDENC_DEF_OPS(JOHAB); + +#include "citrus_stdenc_template.h" diff --git a/lib/libiconv_modules/JOHAB/citrus_johab.h b/lib/libiconv_modules/JOHAB/citrus_johab.h new file mode 100644 index 000000000000..f11fb4e5009c --- /dev/null +++ b/lib/libiconv_modules/JOHAB/citrus_johab.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_johab.h,v 1.1 2006/10/18 17:54:55 tnozaki Exp $ */ + +/*- + * Copyright (c)2006 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_JOHAB_H_ +#define _CITRUS_JOHAB_H_ + +__BEGIN_DECLS +_CITRUS_STDENC_GETOPS_FUNC(JOHAB); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/MSKanji/Makefile b/lib/libiconv_modules/MSKanji/Makefile new file mode 100644 index 000000000000..d4703eb456f2 --- /dev/null +++ b/lib/libiconv_modules/MSKanji/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +SHLIB= MSKanji +SRCS+= citrus_mskanji.c + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/MSKanji/citrus_mskanji.c b/lib/libiconv_modules/MSKanji/citrus_mskanji.c new file mode 100644 index 000000000000..e6554484d991 --- /dev/null +++ b/lib/libiconv_modules/MSKanji/citrus_mskanji.c @@ -0,0 +1,473 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_mskanji.c,v 1.13 2008/06/14 16:01:08 tnozaki Exp $ */ + +/*- + * Copyright (c)2002 Citrus Project, + * 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. + */ + +/* + * ja_JP.SJIS locale table for BSD4.4/rune + * version 1.0 + * (C) Sin'ichiro MIYATANI / Phase One, Inc + * May 12, 1995 + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Phase One, Inc. + * 4. The name of Phase One, Inc. may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + + +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_module.h" +#include "citrus_stdenc.h" +#include "citrus_mskanji.h" + + +/* ---------------------------------------------------------------------- + * private stuffs used by templates + */ + +typedef struct _MSKanjiState { + int chlen; + char ch[2]; +} _MSKanjiState; + +typedef struct { + int mode; +#define MODE_JIS2004 1 +} _MSKanjiEncodingInfo; + +#define _CEI_TO_EI(_cei_) (&(_cei_)->ei) +#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_ + +#define _FUNCNAME(m) _citrus_MSKanji_##m +#define _ENCODING_INFO _MSKanjiEncodingInfo +#define _ENCODING_STATE _MSKanjiState +#define _ENCODING_MB_CUR_MAX(_ei_) 2 +#define _ENCODING_IS_STATE_DEPENDENT 0 +#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0 + + +static bool +_mskanji1(int c) +{ + + return ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xfc)); +} + +static bool +_mskanji2(int c) +{ + + return ((c >= 0x40 && c <= 0x7e) || (c >= 0x80 && c <= 0xfc)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_MSKanji_init_state(_MSKanjiEncodingInfo * __restrict ei __unused, + _MSKanjiState * __restrict s) +{ + + s->chlen = 0; +} + +static __inline void +/*ARGSUSED*/ +_citrus_MSKanji_pack_state(_MSKanjiEncodingInfo * __restrict ei __unused, + void * __restrict pspriv, const _MSKanjiState * __restrict s) +{ + + memcpy(pspriv, (const void *)s, sizeof(*s)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_MSKanji_unpack_state(_MSKanjiEncodingInfo * __restrict ei __unused, + _MSKanjiState * __restrict s, const void * __restrict pspriv) +{ + + memcpy((void *)s, pspriv, sizeof(*s)); +} + +static int +/*ARGSUSED*/ +_citrus_MSKanji_mbrtowc_priv(_MSKanjiEncodingInfo * __restrict ei, + wchar_t * __restrict pwc, char ** __restrict s, size_t n, + _MSKanjiState * __restrict psenc, size_t * __restrict nresult) +{ + char *s0; + wchar_t wchar; + int chlenbak, len; + + s0 = *s; + + if (s0 == NULL) { + _citrus_MSKanji_init_state(ei, psenc); + *nresult = 0; /* state independent */ + return (0); + } + + chlenbak = psenc->chlen; + + /* make sure we have the first byte in the buffer */ + switch (psenc->chlen) { + case 0: + if (n < 1) + goto restart; + psenc->ch[0] = *s0++; + psenc->chlen = 1; + n--; + break; + case 1: + break; + default: + /* illegal state */ + goto encoding_error; + } + + len = _mskanji1(psenc->ch[0] & 0xff) ? 2 : 1; + while (psenc->chlen < len) { + if (n < 1) + goto restart; + psenc->ch[psenc->chlen] = *s0++; + psenc->chlen++; + n--; + } + + *s = s0; + + switch (len) { + case 1: + wchar = psenc->ch[0] & 0xff; + break; + case 2: + if (!_mskanji2(psenc->ch[1] & 0xff)) + goto encoding_error; + wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff); + break; + default: + /* illegal state */ + goto encoding_error; + } + + psenc->chlen = 0; + + if (pwc) + *pwc = wchar; + *nresult = wchar ? len - chlenbak : 0; + return (0); + +encoding_error: + psenc->chlen = 0; + *nresult = (size_t)-1; + return (EILSEQ); + +restart: + *nresult = (size_t)-2; + *s = s0; + return (0); +} + + +static int +_citrus_MSKanji_wcrtomb_priv(_MSKanjiEncodingInfo * __restrict ei __unused, + char * __restrict s, size_t n, wchar_t wc, + _MSKanjiState * __restrict psenc __unused, size_t * __restrict nresult) +{ + int ret; + + /* check invalid sequence */ + if (wc & ~0xffff) { + ret = EILSEQ; + goto err; + } + + if (wc & 0xff00) { + if (n < 2) { + ret = E2BIG; + goto err; + } + + s[0] = (wc >> 8) & 0xff; + s[1] = wc & 0xff; + if (!_mskanji1(s[0] & 0xff) || !_mskanji2(s[1] & 0xff)) { + ret = EILSEQ; + goto err; + } + + *nresult = 2; + return (0); + } else { + if (n < 1) { + ret = E2BIG; + goto err; + } + + s[0] = wc & 0xff; + if (_mskanji1(s[0] & 0xff)) { + ret = EILSEQ; + goto err; + } + + *nresult = 1; + return (0); + } + +err: + *nresult = (size_t)-1; + return (ret); +} + + +static __inline int +/*ARGSUSED*/ +_citrus_MSKanji_stdenc_wctocs(_MSKanjiEncodingInfo * __restrict ei, + _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc) +{ + _index_t col, row; + int offset; + + if ((_wc_t)wc < 0x80) { + /* ISO-646 */ + *csid = 0; + *idx = (_index_t)wc; + } else if ((_wc_t)wc < 0x100) { + /* KANA */ + *csid = 1; + *idx = (_index_t)wc & 0x7F; + } else { + /* Kanji (containing Gaiji zone) */ + /* + * 94^2 zone (contains a part of Gaiji (0xED40 - 0xEEFC)): + * 0x8140 - 0x817E -> 0x2121 - 0x215F + * 0x8180 - 0x819E -> 0x2160 - 0x217E + * 0x819F - 0x81FC -> 0x2221 - 0x227E + * + * 0x8240 - 0x827E -> 0x2321 - 0x235F + * ... + * 0x9F9F - 0x9FFc -> 0x5E21 - 0x5E7E + * + * 0xE040 - 0xE07E -> 0x5F21 - 0x5F5F + * ... + * 0xEF9F - 0xEFFC -> 0x7E21 - 0x7E7E + * + * extended Gaiji zone: + * 0xF040 - 0xFCFC + * + * JIS X0213-plane2: + * 0xF040 - 0xF09E -> 0x2121 - 0x217E + * 0xF140 - 0xF19E -> 0x2321 - 0x237E + * ... + * 0xF240 - 0xF29E -> 0x2521 - 0x257E + * + * 0xF09F - 0xF0FC -> 0x2821 - 0x287E + * 0xF29F - 0xF2FC -> 0x2C21 - 0x2C7E + * ... + * 0xF44F - 0xF49E -> 0x2F21 - 0x2F7E + * + * 0xF49F - 0xF4FC -> 0x6E21 - 0x6E7E + * ... + * 0xFC9F - 0xFCFC -> 0x7E21 - 0x7E7E + */ + row = ((_wc_t)wc >> 8) & 0xFF; + col = (_wc_t)wc & 0xFF; + if (!_mskanji1(row) || !_mskanji2(col)) + return (EILSEQ); + if ((ei->mode & MODE_JIS2004) == 0 || row < 0xF0) { + *csid = 2; + offset = 0x81; + } else { + *csid = 3; + if ((_wc_t)wc <= 0xF49E) { + offset = (_wc_t)wc >= 0xF29F || + ((_wc_t)wc >= 0xF09F && + (_wc_t)wc <= 0xF0FC) ? 0xED : 0xF0; + } else + offset = 0xCE; + } + row -= offset; + if (row >= 0x5F) + row -= 0x40; + row = row * 2 + 0x21; + col -= 0x1F; + if (col >= 0x61) + col -= 1; + if (col > 0x7E) { + row += 1; + col -= 0x5E; + } + *idx = ((_index_t)row << 8) | col; + } + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_MSKanji_stdenc_cstowc(_MSKanjiEncodingInfo * __restrict ei, + wchar_t * __restrict wc, _csid_t csid, _index_t idx) +{ + uint32_t col, row; + int offset; + + switch (csid) { + case 0: + /* ISO-646 */ + if (idx >= 0x80) + return (EILSEQ); + *wc = (wchar_t)idx; + break; + case 1: + /* kana */ + if (idx >= 0x80) + return (EILSEQ); + *wc = (wchar_t)idx + 0x80; + break; + case 3: + if ((ei->mode & MODE_JIS2004) == 0) + return (EILSEQ); + /*FALLTHROUGH*/ + case 2: + /* kanji */ + row = (idx >> 8); + if (row < 0x21) + return (EILSEQ); + if (csid == 3) { + if (row <= 0x2F) + offset = (row == 0x22 || row >= 0x26) ? + 0xED : 0xF0; + else if (row >= 0x4D && row <= 0x7E) + offset = 0xCE; + else + return (EILSEQ); + } else { + if (row > 0x97) + return (EILSEQ); + offset = (row < 0x5F) ? 0x81 : 0xC1; + } + col = idx & 0xFF; + if (col < 0x21 || col > 0x7E) + return (EILSEQ); + row -= 0x21; col -= 0x21; + if ((row & 1) == 0) { + col += 0x40; + if (col >= 0x7F) + col += 1; + } else + col += 0x9F; + row = row / 2 + offset; + *wc = ((wchar_t)row << 8) | col; + break; + default: + return (EILSEQ); + } + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_MSKanji_stdenc_get_state_desc_generic(_MSKanjiEncodingInfo * __restrict ei __unused, + _MSKanjiState * __restrict psenc, int * __restrict rstate) +{ + + *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL : + _STDENC_SDGEN_INCOMPLETE_CHAR; + return (0); +} + +static int +/*ARGSUSED*/ +_citrus_MSKanji_encoding_module_init(_MSKanjiEncodingInfo * __restrict ei, + const void * __restrict var, size_t lenvar) +{ + const char *p; + + p = var; + memset((void *)ei, 0, sizeof(*ei)); + while (lenvar > 0) { + switch (_bcs_toupper(*p)) { + case 'J': + MATCH(JIS2004, ei->mode |= MODE_JIS2004); + break; + } + ++p; + --lenvar; + } + + return (0); +} + +static void +_citrus_MSKanji_encoding_module_uninit(_MSKanjiEncodingInfo *ei __unused) +{ + +} + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(MSKanji); +_CITRUS_STDENC_DEF_OPS(MSKanji); + +#include "citrus_stdenc_template.h" diff --git a/lib/libiconv_modules/MSKanji/citrus_mskanji.h b/lib/libiconv_modules/MSKanji/citrus_mskanji.h new file mode 100644 index 000000000000..3dc385243910 --- /dev/null +++ b/lib/libiconv_modules/MSKanji/citrus_mskanji.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_mskanji.h,v 1.2 2003/06/25 09:51:48 tshiozak Exp $ */ + +/*- + * Copyright (c)2002 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_MSKANJI_H_ +#define _CITRUS_MSKANJI_H_ + +__BEGIN_DECLS +_CITRUS_STDENC_GETOPS_FUNC(MSKanji); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/Makefile b/lib/libiconv_modules/Makefile new file mode 100644 index 000000000000..1a7213612b8f --- /dev/null +++ b/lib/libiconv_modules/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +.include <bsd.own.mk> + +SUBDIR= BIG5 DECHanyu EUC EUCTW GBK2K HZ ISO2022 JOHAB MSKanji UES UTF1632 \ + UTF7 UTF8 VIQR ZW iconv_none iconv_std mapper_646 mapper_none \ + mapper_parallel mapper_serial mapper_std mapper_zone + +.include <bsd.subdir.mk> diff --git a/lib/libiconv_modules/Makefile.inc b/lib/libiconv_modules/Makefile.inc new file mode 100644 index 000000000000..994939008ab5 --- /dev/null +++ b/lib/libiconv_modules/Makefile.inc @@ -0,0 +1,14 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../libc/iconv + +SHLIB_MAJOR= 4 +WARNS?= 6 +CFLAGS+= -I${.CURDIR}/../../libc/iconv +.if !defined(COMPAT_32BIT) +SHLIBDIR= /usr/lib/i18n +.else +SHLIBDIR= /usr/lib32/i18n +.endif +LIBDIR= ${SHLIBDIR} +NO_PROFILE= diff --git a/lib/libiconv_modules/UES/Makefile b/lib/libiconv_modules/UES/Makefile new file mode 100644 index 000000000000..972e496e1a3b --- /dev/null +++ b/lib/libiconv_modules/UES/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +SHLIB= UES +SRCS+= citrus_ues.c +CFLAGS+= --param max-inline-insns-single=64 + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/UES/citrus_ues.c b/lib/libiconv_modules/UES/citrus_ues.c new file mode 100644 index 000000000000..1c4bc83a3c50 --- /dev/null +++ b/lib/libiconv_modules/UES/citrus_ues.c @@ -0,0 +1,412 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_ues.c,v 1.1 2006/11/13 15:16:31 tnozaki Exp $ */ + +/*- + * Copyright (c)2006 Citrus Project, + * 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. + */ + +#include <sys/cdefs.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_module.h" +#include "citrus_stdenc.h" +#include "citrus_ues.h" + +typedef struct { + size_t mb_cur_max; + int mode; +#define MODE_C99 1 +} _UESEncodingInfo; + +typedef struct { + int chlen; + char ch[12]; +} _UESState; + +#define _CEI_TO_EI(_cei_) (&(_cei_)->ei) +#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_ + +#define _FUNCNAME(m) _citrus_UES_##m +#define _ENCODING_INFO _UESEncodingInfo +#define _ENCODING_STATE _UESState +#define _ENCODING_MB_CUR_MAX(_ei_) (_ei_)->mb_cur_max +#define _ENCODING_IS_STATE_DEPENDENT 0 +#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0 + +static __inline void +/*ARGSUSED*/ +_citrus_UES_init_state(_UESEncodingInfo * __restrict ei __unused, + _UESState * __restrict psenc) +{ + + psenc->chlen = 0; +} + +static __inline void +/*ARGSUSED*/ +_citrus_UES_pack_state(_UESEncodingInfo * __restrict ei __unused, + void *__restrict pspriv, const _UESState * __restrict psenc) +{ + + memcpy(pspriv, (const void *)psenc, sizeof(*psenc)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_UES_unpack_state(_UESEncodingInfo * __restrict ei __unused, + _UESState * __restrict psenc, const void * __restrict pspriv) +{ + + memcpy((void *)psenc, pspriv, sizeof(*psenc)); +} + +static __inline int +to_int(int ch) +{ + + if (ch >= '0' && ch <= '9') + return (ch - '0'); + else if (ch >= 'A' && ch <= 'F') + return ((ch - 'A') + 10); + else if (ch >= 'a' && ch <= 'f') + return ((ch - 'a') + 10); + return (-1); +} + +#define ESCAPE '\\' +#define UCS2_ESC 'u' +#define UCS4_ESC 'U' + +#define UCS2_BIT 16 +#define UCS4_BIT 32 +#define BMP_MAX UINT32_C(0xFFFF) +#define UCS2_MAX UINT32_C(0x10FFFF) +#define UCS4_MAX UINT32_C(0x7FFFFFFF) + +static const char *xdig = "0123456789abcdef"; + +static __inline int +to_str(char *s, wchar_t wc, int bit) +{ + char *p; + + p = s; + *p++ = ESCAPE; + switch (bit) { + case UCS2_BIT: + *p++ = UCS2_ESC; + break; + case UCS4_BIT: + *p++ = UCS4_ESC; + break; + default: + abort(); + } + do { + *p++ = xdig[(wc >> (bit -= 4)) & 0xF]; + } while (bit > 0); + return (p - s); +} + +static __inline bool +is_hi_surrogate(wchar_t wc) +{ + + return (wc >= 0xD800 && wc <= 0xDBFF); +} + +static __inline bool +is_lo_surrogate(wchar_t wc) +{ + + return (wc >= 0xDC00 && wc <= 0xDFFF); +} + +static __inline wchar_t +surrogate_to_ucs(wchar_t hi, wchar_t lo) +{ + + hi -= 0xD800; + lo -= 0xDC00; + return ((hi << 10 | lo) + 0x10000); +} + +static __inline void +ucs_to_surrogate(wchar_t wc, wchar_t * __restrict hi, wchar_t * __restrict lo) +{ + + wc -= 0x10000; + *hi = (wc >> 10) + 0xD800; + *lo = (wc & 0x3FF) + 0xDC00; +} + +static __inline bool +is_basic(wchar_t wc) +{ + + return ((uint32_t)wc <= 0x9F && wc != 0x24 && wc != 0x40 && + wc != 0x60); +} + +static int +_citrus_UES_mbrtowc_priv(_UESEncodingInfo * __restrict ei, + wchar_t * __restrict pwc, char ** __restrict s, size_t n, + _UESState * __restrict psenc, size_t * __restrict nresult) +{ + char *s0; + int ch, head, num, tail; + wchar_t hi, wc; + + if (*s == NULL) { + _citrus_UES_init_state(ei, psenc); + *nresult = 0; + return (0); + } + s0 = *s; + + hi = (wchar_t)0; + tail = 0; + +surrogate: + wc = (wchar_t)0; + head = tail; + if (psenc->chlen == head) { + if (n-- < 1) + goto restart; + psenc->ch[psenc->chlen++] = *s0++; + } + ch = (unsigned char)psenc->ch[head++]; + if (ch == ESCAPE) { + if (psenc->chlen == head) { + if (n-- < 1) + goto restart; + psenc->ch[psenc->chlen++] = *s0++; + } + switch (psenc->ch[head]) { + case UCS2_ESC: + tail += 6; + break; + case UCS4_ESC: + if (ei->mode & MODE_C99) { + tail = 10; + break; + } + /*FALLTHROUGH*/ + default: + tail = 0; + } + ++head; + } + for (; head < tail; ++head) { + if (psenc->chlen == head) { + if (n-- < 1) { +restart: + *s = s0; + *nresult = (size_t)-2; + return (0); + } + psenc->ch[psenc->chlen++] = *s0++; + } + num = to_int((int)(unsigned char)psenc->ch[head]); + if (num < 0) { + tail = 0; + break; + } + wc = (wc << 4) | num; + } + head = 0; + switch (tail) { + case 0: + break; + case 6: + if (hi != (wchar_t)0) + break; + if ((ei->mode & MODE_C99) == 0) { + if (is_hi_surrogate(wc) != 0) { + hi = wc; + goto surrogate; + } + if ((uint32_t)wc <= 0x7F /* XXX */ || + is_lo_surrogate(wc) != 0) + break; + goto done; + } + /*FALLTHROUGH*/ + case 10: + if (is_basic(wc) == 0 && (uint32_t)wc <= UCS4_MAX && + is_hi_surrogate(wc) == 0 && is_lo_surrogate(wc) == 0) + goto done; + *nresult = (size_t)-1; + return (EILSEQ); + case 12: + if (is_lo_surrogate(wc) == 0) + break; + wc = surrogate_to_ucs(hi, wc); + goto done; + } + ch = (unsigned char)psenc->ch[0]; + head = psenc->chlen; + if (--head > 0) + memmove(&psenc->ch[0], &psenc->ch[1], head); + wc = (wchar_t)ch; +done: + psenc->chlen = head; + if (pwc != NULL) + *pwc = wc; + *nresult = (size_t)((wc == 0) ? 0 : (s0 - *s)); + *s = s0; + + return (0); +} + +static int +_citrus_UES_wcrtomb_priv(_UESEncodingInfo * __restrict ei, + char * __restrict s, size_t n, wchar_t wc, + _UESState * __restrict psenc, size_t * __restrict nresult) +{ + wchar_t hi, lo; + + if (psenc->chlen != 0) + return (EINVAL); + + if ((ei->mode & MODE_C99) ? is_basic(wc) : (uint32_t)wc <= 0x7F) { + if (n-- < 1) + goto e2big; + psenc->ch[psenc->chlen++] = (char)wc; + } else if ((uint32_t)wc <= BMP_MAX) { + if (n < 6) + goto e2big; + psenc->chlen = to_str(&psenc->ch[0], wc, UCS2_BIT); + } else if ((ei->mode & MODE_C99) == 0 && (uint32_t)wc <= UCS2_MAX) { + if (n < 12) + goto e2big; + ucs_to_surrogate(wc, &hi, &lo); + psenc->chlen += to_str(&psenc->ch[0], hi, UCS2_BIT); + psenc->chlen += to_str(&psenc->ch[6], lo, UCS2_BIT); + } else if ((ei->mode & MODE_C99) && (uint32_t)wc <= UCS4_MAX) { + if (n < 10) + goto e2big; + psenc->chlen = to_str(&psenc->ch[0], wc, UCS4_BIT); + } else { + *nresult = (size_t)-1; + return (EILSEQ); + } + memcpy(s, psenc->ch, psenc->chlen); + *nresult = psenc->chlen; + psenc->chlen = 0; + + return (0); + +e2big: + *nresult = (size_t)-1; + return (E2BIG); +} + +/*ARGSUSED*/ +static int +_citrus_UES_stdenc_wctocs(_UESEncodingInfo * __restrict ei __unused, + _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc) +{ + + *csid = 0; + *idx = (_index_t)wc; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_UES_stdenc_cstowc(_UESEncodingInfo * __restrict ei __unused, + wchar_t * __restrict wc, _csid_t csid, _index_t idx) +{ + + if (csid != 0) + return (EILSEQ); + *wc = (wchar_t)idx; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_UES_stdenc_get_state_desc_generic(_UESEncodingInfo * __restrict ei __unused, + _UESState * __restrict psenc, int * __restrict rstate) +{ + + *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL : + _STDENC_SDGEN_INCOMPLETE_CHAR; + return (0); +} + +static void +/*ARGSUSED*/ +_citrus_UES_encoding_module_uninit(_UESEncodingInfo *ei __unused) +{ + + /* ei seems to be unused */ +} + +static int +/*ARGSUSED*/ +_citrus_UES_encoding_module_init(_UESEncodingInfo * __restrict ei, + const void * __restrict var, size_t lenvar) +{ + const char *p; + + p = var; + memset((void *)ei, 0, sizeof(*ei)); + while (lenvar > 0) { + switch (_bcs_toupper(*p)) { + case 'C': + MATCH(C99, ei->mode |= MODE_C99); + break; + } + ++p; + --lenvar; + } + ei->mb_cur_max = (ei->mode & MODE_C99) ? 10 : 12; + + return (0); +} + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(UES); +_CITRUS_STDENC_DEF_OPS(UES); + +#include "citrus_stdenc_template.h" diff --git a/lib/libiconv_modules/UES/citrus_ues.h b/lib/libiconv_modules/UES/citrus_ues.h new file mode 100644 index 000000000000..7198cdfca5a5 --- /dev/null +++ b/lib/libiconv_modules/UES/citrus_ues.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_ues.h,v 1.1 2006/11/13 15:16:31 tnozaki Exp $ */ + +/*- + * Copyright (c)2004, 2006 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_UES_H_ +#define _CITRUS_UES_H_ + +__BEGIN_DECLS +_CITRUS_STDENC_GETOPS_FUNC(UES); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/UTF1632/Makefile b/lib/libiconv_modules/UTF1632/Makefile new file mode 100644 index 000000000000..71e9f881b1ae --- /dev/null +++ b/lib/libiconv_modules/UTF1632/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +SHLIB= UTF1632 +SRCS+= citrus_utf1632.c +CFLAGS+= --param max-inline-insns-single=32 + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/UTF1632/citrus_utf1632.c b/lib/libiconv_modules/UTF1632/citrus_utf1632.c new file mode 100644 index 000000000000..6682ab279692 --- /dev/null +++ b/lib/libiconv_modules/UTF1632/citrus_utf1632.c @@ -0,0 +1,453 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_utf1632.c,v 1.9 2008/06/14 16:01:08 tnozaki Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * 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. + */ + +#include <sys/cdefs.h> +#include <sys/endian.h> +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_stdenc.h" +#include "citrus_bcs.h" + +#include "citrus_utf1632.h" + + +/* ---------------------------------------------------------------------- + * private stuffs used by templates + */ + +typedef struct { + int chlen; + int current_endian; + uint8_t ch[4]; +} _UTF1632State; + +#define _ENDIAN_UNKNOWN 0 +#define _ENDIAN_BIG 1 +#define _ENDIAN_LITTLE 2 +#if BYTE_ORDER == BIG_ENDIAN +#define _ENDIAN_INTERNAL _ENDIAN_BIG +#define _ENDIAN_SWAPPED _ENDIAN_LITTLE +#else +#define _ENDIAN_INTERNAL _ENDIAN_LITTLE +#define _ENDIAN_SWAPPED _ENDIAN_BIG +#endif +#define _MODE_UTF32 0x00000001U +#define _MODE_FORCE_ENDIAN 0x00000002U + +typedef struct { + int preffered_endian; + unsigned int cur_max; + uint32_t mode; +} _UTF1632EncodingInfo; + +#define _FUNCNAME(m) _citrus_UTF1632_##m +#define _ENCODING_INFO _UTF1632EncodingInfo +#define _ENCODING_STATE _UTF1632State +#define _ENCODING_MB_CUR_MAX(_ei_) ((_ei_)->cur_max) +#define _ENCODING_IS_STATE_DEPENDENT 0 +#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0 + + +static __inline void +/*ARGSUSED*/ +_citrus_UTF1632_init_state(_UTF1632EncodingInfo *ei __unused, + _UTF1632State *s) +{ + + memset(s, 0, sizeof(*s)); +} + +static int +_citrus_UTF1632_mbrtowc_priv(_UTF1632EncodingInfo *ei, wchar_t *pwc, + char **s, size_t n, _UTF1632State *psenc, size_t *nresult) +{ + char *s0; + size_t result; + wchar_t wc = L'\0'; + int chlenbak, endian, needlen; + + s0 = *s; + + if (s0 == NULL) { + _citrus_UTF1632_init_state(ei, psenc); + *nresult = 0; /* state independent */ + return (0); + } + + result = 0; + chlenbak = psenc->chlen; + +refetch: + needlen = ((ei->mode & _MODE_UTF32) != 0 || chlenbak >= 2) ? 4 : 2; + + while (chlenbak < needlen) { + if (n == 0) + goto restart; + psenc->ch[chlenbak++] = *s0++; + n--; + result++; + } + + /* judge endian marker */ + if ((ei->mode & _MODE_UTF32) == 0) { + /* UTF16 */ + if (psenc->ch[0] == 0xFE && psenc->ch[1] == 0xFF) { + psenc->current_endian = _ENDIAN_BIG; + chlenbak = 0; + goto refetch; + } else if (psenc->ch[0] == 0xFF && psenc->ch[1] == 0xFE) { + psenc->current_endian = _ENDIAN_LITTLE; + chlenbak = 0; + goto refetch; + } + } else { + /* UTF32 */ + if (psenc->ch[0] == 0x00 && psenc->ch[1] == 0x00 && + psenc->ch[2] == 0xFE && psenc->ch[3] == 0xFF) { + psenc->current_endian = _ENDIAN_BIG; + chlenbak = 0; + goto refetch; + } else if (psenc->ch[0] == 0xFF && psenc->ch[1] == 0xFE && + psenc->ch[2] == 0x00 && psenc->ch[3] == 0x00) { + psenc->current_endian = _ENDIAN_LITTLE; + chlenbak = 0; + goto refetch; + } + } + endian = ((ei->mode & _MODE_FORCE_ENDIAN) != 0 || + psenc->current_endian == _ENDIAN_UNKNOWN) ? ei->preffered_endian : + psenc->current_endian; + + /* get wc */ + if ((ei->mode & _MODE_UTF32) == 0) { + /* UTF16 */ + if (needlen == 2) { + switch (endian) { + case _ENDIAN_LITTLE: + wc = (psenc->ch[0] | + ((wchar_t)psenc->ch[1] << 8)); + break; + case _ENDIAN_BIG: + wc = (psenc->ch[1] | + ((wchar_t)psenc->ch[0] << 8)); + break; + default: + goto ilseq; + } + if (wc >= 0xD800 && wc <= 0xDBFF) { + /* surrogate high */ + needlen = 4; + goto refetch; + } + } else { + /* surrogate low */ + wc -= 0xD800; /* wc : surrogate high (see above) */ + wc <<= 10; + switch (endian) { + case _ENDIAN_LITTLE: + if (psenc->ch[3] < 0xDC || psenc->ch[3] > 0xDF) + goto ilseq; + wc |= psenc->ch[2]; + wc |= (wchar_t)(psenc->ch[3] & 3) << 8; + break; + case _ENDIAN_BIG: + if (psenc->ch[2]<0xDC || psenc->ch[2]>0xDF) + goto ilseq; + wc |= psenc->ch[3]; + wc |= (wchar_t)(psenc->ch[2] & 3) << 8; + break; + default: + goto ilseq; + } + wc += 0x10000; + } + } else { + /* UTF32 */ + switch (endian) { + case _ENDIAN_LITTLE: + wc = (psenc->ch[0] | + ((wchar_t)psenc->ch[1] << 8) | + ((wchar_t)psenc->ch[2] << 16) | + ((wchar_t)psenc->ch[3] << 24)); + break; + case _ENDIAN_BIG: + wc = (psenc->ch[3] | + ((wchar_t)psenc->ch[2] << 8) | + ((wchar_t)psenc->ch[1] << 16) | + ((wchar_t)psenc->ch[0] << 24)); + break; + default: + goto ilseq; + } + if (wc >= 0xD800 && wc <= 0xDFFF) + goto ilseq; + } + + + *pwc = wc; + psenc->chlen = 0; + *nresult = result; + *s = s0; + + return (0); + +ilseq: + *nresult = (size_t)-1; + psenc->chlen = 0; + return (EILSEQ); + +restart: + *nresult = (size_t)-2; + psenc->chlen = chlenbak; + *s = s0; + return (0); +} + +static int +_citrus_UTF1632_wcrtomb_priv(_UTF1632EncodingInfo *ei, char *s, size_t n, + wchar_t wc, _UTF1632State *psenc, size_t *nresult) +{ + wchar_t wc2; + static const char _bom[4] = { + 0x00, 0x00, 0xFE, 0xFF, + }; + const char *bom = &_bom[0]; + size_t cnt; + + cnt = (size_t)0; + if (psenc->current_endian == _ENDIAN_UNKNOWN) { + if ((ei->mode & _MODE_FORCE_ENDIAN) == 0) { + if (ei->mode & _MODE_UTF32) + cnt = 4; + else { + cnt = 2; + bom += 2; + } + if (n < cnt) + goto e2big; + memcpy(s, bom, cnt); + s += cnt, n -= cnt; + } + psenc->current_endian = ei->preffered_endian; + } + + wc2 = 0; + if ((ei->mode & _MODE_UTF32)==0) { + /* UTF16 */ + if (wc > 0xFFFF) { + /* surrogate */ + if (wc > 0x10FFFF) + goto ilseq; + if (n < 4) + goto e2big; + cnt += 4; + wc -= 0x10000; + wc2 = (wc & 0x3FF) | 0xDC00; + wc = (wc>>10) | 0xD800; + } else { + if (n < 2) + goto e2big; + cnt += 2; + } + +surrogate: + switch (psenc->current_endian) { + case _ENDIAN_BIG: + s[1] = wc; + s[0] = (wc >>= 8); + break; + case _ENDIAN_LITTLE: + s[0] = wc; + s[1] = (wc >>= 8); + break; + } + if (wc2 != 0) { + wc = wc2; + wc2 = 0; + s += 2; + goto surrogate; + } + } else { + /* UTF32 */ + if (wc >= 0xD800 && wc <= 0xDFFF) + goto ilseq; + if (n < 4) + goto e2big; + cnt += 4; + switch (psenc->current_endian) { + case _ENDIAN_BIG: + s[3] = wc; + s[2] = (wc >>= 8); + s[1] = (wc >>= 8); + s[0] = (wc >>= 8); + break; + case _ENDIAN_LITTLE: + s[0] = wc; + s[1] = (wc >>= 8); + s[2] = (wc >>= 8); + s[3] = (wc >>= 8); + break; + } + } + *nresult = cnt; + + return (0); + +ilseq: + *nresult = (size_t)-1; + return (EILSEQ); +e2big: + *nresult = (size_t)-1; + return (E2BIG); +} + +static void +parse_variable(_UTF1632EncodingInfo * __restrict ei, + const void * __restrict var, size_t lenvar) +{ + const char *p; + + p = var; + while (lenvar > 0) { + switch (*p) { + case 'B': + case 'b': + MATCH(big, ei->preffered_endian = _ENDIAN_BIG); + break; + case 'L': + case 'l': + MATCH(little, ei->preffered_endian = _ENDIAN_LITTLE); + break; + case 'i': + case 'I': + MATCH(internal, ei->preffered_endian = _ENDIAN_INTERNAL); + break; + case 's': + case 'S': + MATCH(swapped, ei->preffered_endian = _ENDIAN_SWAPPED); + break; + case 'F': + case 'f': + MATCH(force, ei->mode |= _MODE_FORCE_ENDIAN); + break; + case 'U': + case 'u': + MATCH(utf32, ei->mode |= _MODE_UTF32); + break; + } + p++; + lenvar--; + } +} + +static int +/*ARGSUSED*/ +_citrus_UTF1632_encoding_module_init(_UTF1632EncodingInfo * __restrict ei, + const void * __restrict var, size_t lenvar) +{ + + memset((void *)ei, 0, sizeof(*ei)); + + parse_variable(ei, var, lenvar); + + ei->cur_max = ((ei->mode&_MODE_UTF32) == 0) ? 6 : 8; + /* 6: endian + surrogate */ + /* 8: endian + normal */ + + if (ei->preffered_endian == _ENDIAN_UNKNOWN) { + ei->preffered_endian = _ENDIAN_BIG; + } + + return (0); +} + +static void +/*ARGSUSED*/ +_citrus_UTF1632_encoding_module_uninit(_UTF1632EncodingInfo *ei __unused) +{ + +} + +static __inline int +/*ARGSUSED*/ +_citrus_UTF1632_stdenc_wctocs(_UTF1632EncodingInfo * __restrict ei __unused, + _csid_t * __restrict csid, _index_t * __restrict idx, _wc_t wc) +{ + + *csid = 0; + *idx = (_index_t)wc; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_UTF1632_stdenc_cstowc(_UTF1632EncodingInfo * __restrict ei __unused, + _wc_t * __restrict wc, _csid_t csid, _index_t idx) +{ + + if (csid != 0) + return (EILSEQ); + + *wc = (_wc_t)idx; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_UTF1632_stdenc_get_state_desc_generic(_UTF1632EncodingInfo * __restrict ei __unused, + _UTF1632State * __restrict psenc, int * __restrict rstate) +{ + + *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL : + _STDENC_SDGEN_INCOMPLETE_CHAR; + return (0); +} + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(UTF1632); +_CITRUS_STDENC_DEF_OPS(UTF1632); + +#include "citrus_stdenc_template.h" diff --git a/lib/libiconv_modules/UTF1632/citrus_utf1632.h b/lib/libiconv_modules/UTF1632/citrus_utf1632.h new file mode 100644 index 000000000000..8ee7ada23dae --- /dev/null +++ b/lib/libiconv_modules/UTF1632/citrus_utf1632.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_utf1632.h,v 1.1 2003/06/25 09:51:49 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_UTF1632_H_ +#define _CITRUS_UTF1632_H_ + +__BEGIN_DECLS +_CITRUS_STDENC_GETOPS_FUNC(UTF1632); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/UTF7/Makefile b/lib/libiconv_modules/UTF7/Makefile new file mode 100644 index 000000000000..8bedb73ec61b --- /dev/null +++ b/lib/libiconv_modules/UTF7/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +SHLIB= UTF7 +SRCS+= citrus_utf7.c +CFLAGS+= --param max-inline-insns-single=32 + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/UTF7/citrus_utf7.c b/lib/libiconv_modules/UTF7/citrus_utf7.c new file mode 100644 index 000000000000..e99f980c321c --- /dev/null +++ b/lib/libiconv_modules/UTF7/citrus_utf7.c @@ -0,0 +1,499 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_utf7.c,v 1.5 2006/08/23 12:57:24 tnozaki Exp $ */ + +/*- + * Copyright (c)2004, 2005 Citrus Project, + * 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. + * + */ + +#include <sys/cdefs.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_stdenc.h" +#include "citrus_utf7.h" + +/* ---------------------------------------------------------------------- + * private stuffs used by templates + */ + +#define EI_MASK UINT16_C(0xff) +#define EI_DIRECT UINT16_C(0x100) +#define EI_OPTION UINT16_C(0x200) +#define EI_SPACE UINT16_C(0x400) + +typedef struct { + uint16_t cell[0x80]; +} _UTF7EncodingInfo; + +typedef struct { + unsigned int + mode: 1, /* whether base64 mode */ + bits: 4, /* need to hold 0 - 15 */ + cache: 22, /* 22 = BASE64_BIT + UTF16_BIT */ + surrogate: 1; /* whether surrogate pair or not */ + int chlen; + char ch[4]; /* BASE64_IN, 3 * 6 = 18, most closed to UTF16_BIT */ +} _UTF7State; + +#define _CEI_TO_EI(_cei_) (&(_cei_)->ei) +#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_ + +#define _FUNCNAME(m) _citrus_UTF7_##m +#define _ENCODING_INFO _UTF7EncodingInfo +#define _ENCODING_STATE _UTF7State +#define _ENCODING_MB_CUR_MAX(_ei_) 4 +#define _ENCODING_IS_STATE_DEPENDENT 1 +#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0 + +static __inline void +/*ARGSUSED*/ +_citrus_UTF7_init_state(_UTF7EncodingInfo * __restrict ei __unused, + _UTF7State * __restrict s) +{ + + memset((void *)s, 0, sizeof(*s)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_UTF7_pack_state(_UTF7EncodingInfo * __restrict ei __unused, + void *__restrict pspriv, const _UTF7State * __restrict s) +{ + + memcpy(pspriv, (const void *)s, sizeof(*s)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_UTF7_unpack_state(_UTF7EncodingInfo * __restrict ei __unused, + _UTF7State * __restrict s, const void * __restrict pspriv) +{ + + memcpy((void *)s, pspriv, sizeof(*s)); +} + +static const char base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +static const char direct[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789(),-./:?"; + +static const char option[] = "!\"#$%&';<=>@[]^_`{|}"; +static const char spaces[] = " \t\r\n"; + +#define BASE64_BIT 6 +#define UTF16_BIT 16 + +#define BASE64_MAX 0x3f +#define UTF16_MAX UINT16_C(0xffff) +#define UTF32_MAX UINT32_C(0x10ffff) + +#define BASE64_IN '+' +#define BASE64_OUT '-' + +#define SHIFT7BIT(c) ((c) >> 7) +#define ISSPECIAL(c) ((c) == '\0' || (c) == BASE64_IN) + +#define FINDLEN(ei, c) \ + (SHIFT7BIT((c)) ? -1 : (((ei)->cell[(c)] & EI_MASK) - 1)) + +#define ISDIRECT(ei, c) (!SHIFT7BIT((c)) && (ISSPECIAL((c)) || \ + ei->cell[(c)] & (EI_DIRECT | EI_OPTION | EI_SPACE))) + +#define ISSAFE(ei, c) (!SHIFT7BIT((c)) && (ISSPECIAL((c)) || \ + (c < 0x80 && ei->cell[(c)] & (EI_DIRECT | EI_SPACE)))) + +/* surrogate pair */ +#define SRG_BASE UINT32_C(0x10000) +#define HISRG_MIN UINT16_C(0xd800) +#define HISRG_MAX UINT16_C(0xdbff) +#define LOSRG_MIN UINT16_C(0xdc00) +#define LOSRG_MAX UINT16_C(0xdfff) + +static int +_citrus_UTF7_mbtoutf16(_UTF7EncodingInfo * __restrict ei, + uint16_t * __restrict u16, char ** __restrict s, size_t n, + _UTF7State * __restrict psenc, size_t * __restrict nresult) +{ + _UTF7State sv; + char *s0; + int done, i, len; + + s0 = *s; + sv = *psenc; + + for (i = 0, done = 0; done == 0; i++) { + if (i == psenc->chlen) { + if (n-- < 1) { + *nresult = (size_t)-2; + *s = s0; + sv.chlen = psenc->chlen; + *psenc = sv; + return (0); + } + psenc->ch[psenc->chlen++] = *s0++; + } + if (SHIFT7BIT((int)psenc->ch[i])) + goto ilseq; + if (!psenc->mode) { + if (psenc->bits > 0 || psenc->cache > 0) + return (EINVAL); + if (psenc->ch[i] == BASE64_IN) + psenc->mode = 1; + else { + if (!ISDIRECT(ei, (int)psenc->ch[i])) + goto ilseq; + *u16 = (uint16_t)psenc->ch[i]; + done = 1; + continue; + } + } else { + if (psenc->ch[i] == BASE64_OUT && psenc->cache == 0) { + psenc->mode = 0; + *u16 = (uint16_t)BASE64_IN; + done = 1; + continue; + } + len = FINDLEN(ei, (int)psenc->ch[i]); + if (len < 0) { + if (psenc->bits >= BASE64_BIT) + return (EINVAL); + psenc->mode = 0; + psenc->bits = psenc->cache = 0; + if (psenc->ch[i] != BASE64_OUT) { + if (!ISDIRECT(ei, (int)psenc->ch[i])) + goto ilseq; + *u16 = (uint16_t)psenc->ch[i]; + done = 1; + } + } else { + psenc->cache = + (psenc->cache << BASE64_BIT) | len; + switch (psenc->bits) { + case 0: case 2: case 4: case 6: case 8: + psenc->bits += BASE64_BIT; + break; + case 10: case 12: case 14: + psenc->bits -= (UTF16_BIT - BASE64_BIT); + *u16 = (psenc->cache >> psenc->bits) & + UTF16_MAX; + done = 1; + break; + default: + return (EINVAL); + } + } + } + } + + if (psenc->chlen > i) + return (EINVAL); + psenc->chlen = 0; + *nresult = (size_t)((*u16 == 0) ? 0 : s0 - *s); + *s = s0; + + return (0); + +ilseq: + *nresult = (size_t)-1; + return (EILSEQ); +} + +static int +_citrus_UTF7_mbrtowc_priv(_UTF7EncodingInfo * __restrict ei, + wchar_t * __restrict pwc, char ** __restrict s, size_t n, + _UTF7State * __restrict psenc, size_t * __restrict nresult) +{ + char *s0; + uint32_t u32; + uint16_t hi, lo; + size_t nr, siz; + int err; + + if (*s == NULL) { + _citrus_UTF7_init_state(ei, psenc); + *nresult = (size_t)_ENCODING_IS_STATE_DEPENDENT; + return (0); + } + s0 = *s; + if (psenc->surrogate) { + hi = (psenc->cache >> 2) & UTF16_MAX; + if (hi < HISRG_MIN || hi > HISRG_MAX) + return (EINVAL); + siz = 0; + } else { + err = _citrus_UTF7_mbtoutf16(ei, &hi, &s0, n, psenc, &nr); + if (nr == (size_t)-1 || nr == (size_t)-2) { + *nresult = nr; + return (err); + } + if (err != 0) + return (err); + n -= nr; + siz = nr; + if (hi < HISRG_MIN || hi > HISRG_MAX) { + u32 = (uint32_t)hi; + goto done; + } + psenc->surrogate = 1; + } + err = _citrus_UTF7_mbtoutf16(ei, &lo, &s0, n, psenc, &nr); + if (nr == (size_t)-1 || nr == (size_t)-2) { + *nresult = nr; + return (err); + } + if (err != 0) + return (err); + hi -= HISRG_MIN; + lo -= LOSRG_MIN; + u32 = (hi << 10 | lo) + SRG_BASE; + siz += nr; +done: + *s = s0; + if (pwc != NULL) + *pwc = (wchar_t)u32; + if (u32 == (uint32_t)0) { + *nresult = (size_t)0; + _citrus_UTF7_init_state(ei, psenc); + } else { + *nresult = siz; + psenc->surrogate = 0; + } + return (err); +} + +static int +_citrus_UTF7_utf16tomb(_UTF7EncodingInfo * __restrict ei, + char * __restrict s, size_t n __unused, uint16_t u16, + _UTF7State * __restrict psenc, size_t * __restrict nresult) +{ + int bits, i; + + if (psenc->chlen != 0 || psenc->bits > BASE64_BIT) + return (EINVAL); + + if (ISSAFE(ei, u16)) { + if (psenc->mode) { + if (psenc->bits > 0) { + bits = BASE64_BIT - psenc->bits; + i = (psenc->cache << bits) & BASE64_MAX; + psenc->ch[psenc->chlen++] = base64[i]; + psenc->bits = psenc->cache = 0; + } + if (u16 == BASE64_OUT || FINDLEN(ei, u16) >= 0) + psenc->ch[psenc->chlen++] = BASE64_OUT; + psenc->mode = 0; + } + if (psenc->bits != 0) + return (EINVAL); + psenc->ch[psenc->chlen++] = (char)u16; + if (u16 == BASE64_IN) + psenc->ch[psenc->chlen++] = BASE64_OUT; + } else { + if (!psenc->mode) { + if (psenc->bits > 0) + return (EINVAL); + psenc->ch[psenc->chlen++] = BASE64_IN; + psenc->mode = 1; + } + psenc->cache = (psenc->cache << UTF16_BIT) | u16; + bits = UTF16_BIT + psenc->bits; + psenc->bits = bits % BASE64_BIT; + while ((bits -= BASE64_BIT) >= 0) { + i = (psenc->cache >> bits) & BASE64_MAX; + psenc->ch[psenc->chlen++] = base64[i]; + } + } + memcpy(s, psenc->ch, psenc->chlen); + *nresult = psenc->chlen; + psenc->chlen = 0; + + return (0); +} + +static int +_citrus_UTF7_wcrtomb_priv(_UTF7EncodingInfo * __restrict ei, + char * __restrict s, size_t n, wchar_t wchar, + _UTF7State * __restrict psenc, size_t * __restrict nresult) +{ + uint32_t u32; + uint16_t u16[2]; + int err, i, len; + size_t nr, siz; + + u32 = (uint32_t)wchar; + if (u32 <= UTF16_MAX) { + u16[0] = (uint16_t)u32; + len = 1; + } else if (u32 <= UTF32_MAX) { + u32 -= SRG_BASE; + u16[0] = (u32 >> 10) + HISRG_MIN; + u16[1] = ((uint16_t)(u32 & UINT32_C(0x3ff))) + LOSRG_MIN; + len = 2; + } else { + *nresult = (size_t)-1; + return (EILSEQ); + } + siz = 0; + for (i = 0; i < len; ++i) { + err = _citrus_UTF7_utf16tomb(ei, s, n, u16[i], psenc, &nr); + if (err != 0) + return (err); /* XXX: state has been modified */ + s += nr; + n -= nr; + siz += nr; + } + *nresult = siz; + + return (0); +} + +static int +/* ARGSUSED */ +_citrus_UTF7_put_state_reset(_UTF7EncodingInfo * __restrict ei __unused, + char * __restrict s, size_t n, _UTF7State * __restrict psenc, + size_t * __restrict nresult) +{ + int bits, pos; + + if (psenc->chlen != 0 || psenc->bits > BASE64_BIT || psenc->surrogate) + return (EINVAL); + + if (psenc->mode) { + if (psenc->bits > 0) { + if (n-- < 1) + return (E2BIG); + bits = BASE64_BIT - psenc->bits; + pos = (psenc->cache << bits) & BASE64_MAX; + psenc->ch[psenc->chlen++] = base64[pos]; + psenc->ch[psenc->chlen++] = BASE64_OUT; + psenc->bits = psenc->cache = 0; + } + psenc->mode = 0; + } + if (psenc->bits != 0) + return (EINVAL); + if (n-- < 1) + return (E2BIG); + + *nresult = (size_t)psenc->chlen; + if (psenc->chlen > 0) { + memcpy(s, psenc->ch, psenc->chlen); + psenc->chlen = 0; + } + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_UTF7_stdenc_wctocs(_UTF7EncodingInfo * __restrict ei __unused, + _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc) +{ + + *csid = 0; + *idx = (_index_t)wc; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_UTF7_stdenc_cstowc(_UTF7EncodingInfo * __restrict ei __unused, + wchar_t * __restrict wc, _csid_t csid, _index_t idx) +{ + + if (csid != 0) + return (EILSEQ); + *wc = (wchar_t)idx; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_UTF7_stdenc_get_state_desc_generic(_UTF7EncodingInfo * __restrict ei __unused, + _UTF7State * __restrict psenc, int * __restrict rstate) +{ + + *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL : + _STDENC_SDGEN_INCOMPLETE_CHAR; + return (0); +} + +static void +/*ARGSUSED*/ +_citrus_UTF7_encoding_module_uninit(_UTF7EncodingInfo *ei __unused) +{ + + /* ei seems to be unused */ +} + +static int +/*ARGSUSED*/ +_citrus_UTF7_encoding_module_init(_UTF7EncodingInfo * __restrict ei, + const void * __restrict var __unused, size_t lenvar __unused) +{ + const char *s; + + memset(ei, 0, sizeof(*ei)); + +#define FILL(str, flag) \ +do { \ + for (s = str; *s != '\0'; s++) \ + ei->cell[*s & 0x7f] |= flag; \ +} while (/*CONSTCOND*/0) + + FILL(base64, (s - base64) + 1); + FILL(direct, EI_DIRECT); + FILL(option, EI_OPTION); + FILL(spaces, EI_SPACE); + + return (0); +} + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(UTF7); +_CITRUS_STDENC_DEF_OPS(UTF7); + +#include "citrus_stdenc_template.h" diff --git a/lib/libiconv_modules/UTF7/citrus_utf7.h b/lib/libiconv_modules/UTF7/citrus_utf7.h new file mode 100644 index 000000000000..96ca478e0216 --- /dev/null +++ b/lib/libiconv_modules/UTF7/citrus_utf7.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_utf7.h,v 1.1 2005/03/05 18:05:15 tnozaki Exp $ */ + +/*- + * Copyright (c)2004,2005 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_UTF7_H_ +#define _CITRUS_UTF7_H_ + +__BEGIN_DECLS +_CITRUS_STDENC_GETOPS_FUNC(UTF7); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/UTF8/Makefile b/lib/libiconv_modules/UTF8/Makefile new file mode 100644 index 000000000000..223a12630952 --- /dev/null +++ b/lib/libiconv_modules/UTF8/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +SHLIB= UTF8 +SRCS+= citrus_utf8.c + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/UTF8/citrus_utf8.c b/lib/libiconv_modules/UTF8/citrus_utf8.c new file mode 100644 index 000000000000..2bd8d81847a0 --- /dev/null +++ b/lib/libiconv_modules/UTF8/citrus_utf8.c @@ -0,0 +1,349 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_utf8.c,v 1.17 2008/06/14 16:01:08 tnozaki Exp $ */ + +/*- + * Copyright (c)2002 Citrus Project, + * 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. + */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Paul Borman at Krystal Technologies. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_stdenc.h" +#include "citrus_utf8.h" + + +/* ---------------------------------------------------------------------- + * private stuffs used by templates + */ + +static uint8_t _UTF8_count_array[256] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70 - 7F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* C0 - CF */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* D0 - DF */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* E0 - EF */ + 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0 /* F0 - FF */ +}; + +static uint8_t const *_UTF8_count = _UTF8_count_array; + +static const uint32_t _UTF8_range[] = { + 0, /*dummy*/ + 0x00000000, 0x00000080, 0x00000800, 0x00010000, + 0x00200000, 0x04000000, 0x80000000, +}; + +typedef struct { + int chlen; + char ch[6]; +} _UTF8State; + +typedef void *_UTF8EncodingInfo; + +#define _CEI_TO_EI(_cei_) (&(_cei_)->ei) +#define _CEI_TO_STATE(_ei_, _func_) (_ei_)->states.s_##_func_ + +#define _FUNCNAME(m) _citrus_UTF8_##m +#define _ENCODING_INFO _UTF8EncodingInfo +#define _ENCODING_STATE _UTF8State +#define _ENCODING_MB_CUR_MAX(_ei_) 6 +#define _ENCODING_IS_STATE_DEPENDENT 0 +#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0 + +static size_t +_UTF8_findlen(wchar_t v) +{ + size_t i; + uint32_t c; + + c = (uint32_t)v; /*XXX*/ + for (i = 1; i < sizeof(_UTF8_range) / sizeof(_UTF8_range[0]) - 1; i++) + if (c >= _UTF8_range[i] && c < _UTF8_range[i + 1]) + return (i); + + return (-1); /*out of range*/ +} + +static __inline bool +_UTF8_surrogate(wchar_t wc) +{ + + return (wc >= 0xd800 && wc <= 0xdfff); +} + +static __inline void +/*ARGSUSED*/ +_citrus_UTF8_init_state(_UTF8EncodingInfo *ei __unused, _UTF8State *s) +{ + + s->chlen = 0; +} + +static __inline void +/*ARGSUSED*/ +_citrus_UTF8_pack_state(_UTF8EncodingInfo *ei __unused, void *pspriv, + const _UTF8State *s) +{ + + memcpy(pspriv, (const void *)s, sizeof(*s)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_UTF8_unpack_state(_UTF8EncodingInfo *ei __unused, _UTF8State *s, + const void *pspriv) +{ + + memcpy((void *)s, pspriv, sizeof(*s)); +} + +static int +_citrus_UTF8_mbrtowc_priv(_UTF8EncodingInfo *ei, wchar_t *pwc, char **s, + size_t n, _UTF8State *psenc, size_t *nresult) +{ + char *s0; + wchar_t wchar; + int i; + uint8_t c; + + s0 = *s; + + if (s0 == NULL) { + _citrus_UTF8_init_state(ei, psenc); + *nresult = 0; /* state independent */ + return (0); + } + + /* make sure we have the first byte in the buffer */ + if (psenc->chlen == 0) { + if (n-- < 1) + goto restart; + psenc->ch[psenc->chlen++] = *s0++; + } + + c = _UTF8_count[psenc->ch[0] & 0xff]; + if (c < 1 || c < psenc->chlen) + goto ilseq; + + if (c == 1) + wchar = psenc->ch[0] & 0xff; + else { + while (psenc->chlen < c) { + if (n-- < 1) + goto restart; + psenc->ch[psenc->chlen++] = *s0++; + } + wchar = psenc->ch[0] & (0x7f >> c); + for (i = 1; i < c; i++) { + if ((psenc->ch[i] & 0xc0) != 0x80) + goto ilseq; + wchar <<= 6; + wchar |= (psenc->ch[i] & 0x3f); + } + if (_UTF8_surrogate(wchar) || _UTF8_findlen(wchar) != c) + goto ilseq; + } + if (pwc != NULL) + *pwc = wchar; + *nresult = (wchar == 0) ? 0 : s0 - *s; + *s = s0; + psenc->chlen = 0; + + return (0); + +ilseq: + *nresult = (size_t)-1; + return (EILSEQ); + +restart: + *s = s0; + *nresult = (size_t)-2; + return (0); +} + +static int +_citrus_UTF8_wcrtomb_priv(_UTF8EncodingInfo *ei __unused, char *s, size_t n, + wchar_t wc, _UTF8State *psenc __unused, size_t *nresult) +{ + wchar_t c; + size_t cnt; + int i, ret; + + if (_UTF8_surrogate(wc)) { + ret = EILSEQ; + goto err; + } + cnt = _UTF8_findlen(wc); + if (cnt <= 0 || cnt > 6) { + /* invalid UCS4 value */ + ret = EILSEQ; + goto err; + } + if (n < cnt) { + /* bound check failure */ + ret = E2BIG; + goto err; + } + + c = wc; + if (s) { + for (i = cnt - 1; i > 0; i--) { + s[i] = 0x80 | (c & 0x3f); + c >>= 6; + } + s[0] = c; + if (cnt == 1) + s[0] &= 0x7f; + else { + s[0] &= (0x7f >> cnt); + s[0] |= ((0xff00 >> cnt) & 0xff); + } + } + + *nresult = (size_t)cnt; + return (0); + +err: + *nresult = (size_t)-1; + return (ret); +} + +static __inline int +/*ARGSUSED*/ +_citrus_UTF8_stdenc_wctocs(_UTF8EncodingInfo * __restrict ei __unused, + _csid_t * __restrict csid, _index_t * __restrict idx, + wchar_t wc) +{ + + *csid = 0; + *idx = (_citrus_index_t)wc; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_UTF8_stdenc_cstowc(_UTF8EncodingInfo * __restrict ei __unused, + wchar_t * __restrict wc, _csid_t csid, _index_t idx) +{ + + if (csid != 0) + return (EILSEQ); + + *wc = (wchar_t)idx; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_UTF8_stdenc_get_state_desc_generic(_UTF8EncodingInfo * __restrict ei __unused, + _UTF8State * __restrict psenc, int * __restrict rstate) +{ + + *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL : + _STDENC_SDGEN_INCOMPLETE_CHAR; + return (0); +} + +static int +/*ARGSUSED*/ +_citrus_UTF8_encoding_module_init(_UTF8EncodingInfo * __restrict ei __unused, + const void * __restrict var __unused, size_t lenvar __unused) +{ + + return (0); +} + +static void +/*ARGSUSED*/ +_citrus_UTF8_encoding_module_uninit(_UTF8EncodingInfo *ei __unused) +{ + +} + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(UTF8); +_CITRUS_STDENC_DEF_OPS(UTF8); + +#include "citrus_stdenc_template.h" diff --git a/lib/libiconv_modules/UTF8/citrus_utf8.h b/lib/libiconv_modules/UTF8/citrus_utf8.h new file mode 100644 index 000000000000..fa412b7ba1aa --- /dev/null +++ b/lib/libiconv_modules/UTF8/citrus_utf8.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_utf8.h,v 1.2 2003/06/25 09:51:49 tshiozak Exp $ */ + +/*- + * Copyright (c)2002 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_UTF8_H_ +#define _CITRUS_UTF8_H_ + +__BEGIN_DECLS +_CITRUS_STDENC_GETOPS_FUNC(UTF8); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/VIQR/Makefile b/lib/libiconv_modules/VIQR/Makefile new file mode 100644 index 000000000000..67e367ab9b36 --- /dev/null +++ b/lib/libiconv_modules/VIQR/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +SHLIB= VIQR +SRCS+= citrus_viqr.c + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/VIQR/citrus_viqr.c b/lib/libiconv_modules/VIQR/citrus_viqr.c new file mode 100644 index 000000000000..bd26749865f2 --- /dev/null +++ b/lib/libiconv_modules/VIQR/citrus_viqr.c @@ -0,0 +1,494 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_viqr.c,v 1.4 2008/06/14 16:01:08 tnozaki Exp $ */ + +/*- + * Copyright (c)2006 Citrus Project, + * 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. + * + */ + +#include <sys/cdefs.h> +#include <sys/queue.h> +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_module.h" +#include "citrus_stdenc.h" +#include "citrus_viqr.h" + +#define ESCAPE '\\' + +/* + * this table generated from RFC 1456. + */ +static const char *mnemonic_rfc1456[0x100] = { + NULL , NULL , "A(?", NULL , NULL , "A(~", "A^~", NULL , + NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , + NULL , NULL , NULL , NULL , "Y?" , NULL , NULL , NULL , + NULL , "Y~" , NULL , NULL , NULL , NULL , "Y." , NULL , + NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , + NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , + NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , + NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , + NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , + NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , + NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , + NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , + NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , + NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , + NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , + NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , + "A." , "A('", "A(`", "A(.", "A^'", "A^`", "A^?", "A^.", + "E~" , "E." , "E^'", "E^`", "E^?", "E^~", "E^.", "O^'", + "O^`", "O^?", "O^~", "O^.", "O+.", "O+'", "O+`", "O+?", + "I." , "O?" , "O." , "I?" , "U?" , "U~" , "U." , "Y`" , + "O~" , "a('", "a(`", "a(.", "a^'", "a^`", "a^?", "a^.", + "e~" , "e." , "e^'", "e^`", "e^?", "e^~", "e^.", "o^'", + "o^`", "o^?", "o^~", "O+~", "O+" , "o^.", "o+`", "o+?", + "i." , "U+.", "U+'", "U+`", "U+?", "o+" , "o+'", "U+" , + "A`" , "A'" , "A^" , "A~" , "A?" , "A(" , "a(?", "a(~", + "E`" , "E'" , "E^" , "E?" , "I`" , "I'" , "I~" , "y`" , + "DD" , "u+'", "O`" , "O'" , "O^" , "a." , "y?" , "u+`", + "u+?", "U`" , "U'" , "y~" , "y." , "Y'" , "o+~", "u+" , + "a`" , "a'" , "a^" , "a~" , "a?" , "a(" , "u+~", "a^~", + "e`" , "e'" , "e^" , "e?" , "i`" , "i'" , "i~" , "i?" , + "dd" , "u+.", "o`" , "o'" , "o^" , "o~" , "o?" , "o." , + "u." , "u`" , "u'" , "u~" , "u?" , "y'" , "o+.", "U+~", +}; + +typedef struct { + const char *name; + wchar_t value; +} mnemonic_def_t; + +static const mnemonic_def_t mnemonic_ext[] = { +/* add extra mnemonic here (should be sorted by wchar_t order). */ +}; +static const size_t mnemonic_ext_size = + sizeof(mnemonic_ext) / sizeof(mnemonic_def_t); + +static const char * +mnemonic_ext_find(wchar_t wc, const mnemonic_def_t *head, size_t n) +{ + const mnemonic_def_t *mid; + + for (; n > 0; n >>= 1) { + mid = head + (n >> 1); + if (mid->value == wc) + return (mid->name); + else if (mid->value < wc) { + head = mid + 1; + --n; + } + } + return (NULL); +} + +struct mnemonic_t; +typedef TAILQ_HEAD(mnemonic_list_t, mnemonic_t) mnemonic_list_t; +typedef struct mnemonic_t { + TAILQ_ENTRY(mnemonic_t) entry; + struct mnemonic_t *parent; + mnemonic_list_t child; + wchar_t value; + int ascii; +} mnemonic_t; + +static mnemonic_t * +mnemonic_list_find(mnemonic_list_t *ml, int ch) +{ + mnemonic_t *m; + + TAILQ_FOREACH(m, ml, entry) { + if (m->ascii == ch) + return (m); + } + + return (NULL); +} + +static mnemonic_t * +mnemonic_create(mnemonic_t *parent, int ascii, wchar_t value) +{ + mnemonic_t *m; + + m = malloc(sizeof(*m)); + if (m != NULL) { + m->parent = parent; + m->ascii = ascii; + m->value = value; + TAILQ_INIT(&m->child); + } + + return (m); +} + +static int +mnemonic_append_child(mnemonic_t *m, const char *s, + wchar_t value, wchar_t invalid) +{ + mnemonic_t *m0; + int ch; + + ch = (unsigned char)*s++; + if (ch == '\0') + return (EINVAL); + m0 = mnemonic_list_find(&m->child, ch); + if (m0 == NULL) { + m0 = mnemonic_create(m, ch, (wchar_t)ch); + if (m0 == NULL) + return (ENOMEM); + TAILQ_INSERT_TAIL(&m->child, m0, entry); + } + m = m0; + for (m0 = NULL; (ch = (unsigned char)*s) != '\0'; ++s) { + m0 = mnemonic_list_find(&m->child, ch); + if (m0 == NULL) { + m0 = mnemonic_create(m, ch, invalid); + if (m0 == NULL) + return (ENOMEM); + TAILQ_INSERT_TAIL(&m->child, m0, entry); + } + m = m0; + } + if (m0 == NULL) + return (EINVAL); + m0->value = value; + + return (0); +} + +static void +mnemonic_destroy(mnemonic_t *m) +{ + mnemonic_t *m0; + + TAILQ_FOREACH(m0, &m->child, entry) + mnemonic_destroy(m0); + free(m); +} + +typedef struct { + mnemonic_t *mroot; + wchar_t invalid; + size_t mb_cur_max; +} _VIQREncodingInfo; + +typedef struct { + int chlen; + char ch[MB_LEN_MAX]; +} _VIQRState; + +#define _CEI_TO_EI(_cei_) (&(_cei_)->ei) +#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_ + +#define _FUNCNAME(m) _citrus_VIQR_##m +#define _ENCODING_INFO _VIQREncodingInfo +#define _ENCODING_STATE _VIQRState +#define _ENCODING_MB_CUR_MAX(_ei_) (_ei_)->mb_cur_max +#define _ENCODING_IS_STATE_DEPENDENT 1 +#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0 + +static __inline void +/*ARGSUSED*/ +_citrus_VIQR_init_state(_VIQREncodingInfo * __restrict ei __unused, + _VIQRState * __restrict psenc) +{ + + psenc->chlen = 0; +} + +static __inline void +/*ARGSUSED*/ +_citrus_VIQR_pack_state(_VIQREncodingInfo * __restrict ei __unused, + void *__restrict pspriv, const _VIQRState * __restrict psenc) +{ + + memcpy(pspriv, (const void *)psenc, sizeof(*psenc)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_VIQR_unpack_state(_VIQREncodingInfo * __restrict ei __unused, + _VIQRState * __restrict psenc, const void * __restrict pspriv) +{ + + memcpy((void *)psenc, pspriv, sizeof(*psenc)); +} + +static int +_citrus_VIQR_mbrtowc_priv(_VIQREncodingInfo * __restrict ei, + wchar_t * __restrict pwc, char ** __restrict s, size_t n, + _VIQRState * __restrict psenc, size_t * __restrict nresult) +{ + mnemonic_t *m, *m0; + char *s0; + wchar_t wc; + ssize_t i; + int ch, escape; + + if (*s == NULL) { + _citrus_VIQR_init_state(ei, psenc); + *nresult = (size_t)_ENCODING_IS_STATE_DEPENDENT; + return (0); + } + s0 = *s; + + i = 0; + m = ei->mroot; + for (escape = 0;;) { + if (psenc->chlen == i) { + if (n-- < 1) { + *s = s0; + *nresult = (size_t)-2; + return (0); + } + psenc->ch[psenc->chlen++] = *s0++; + } + ch = (unsigned char)psenc->ch[i++]; + if (ch == ESCAPE) { + if (m != ei->mroot) + break; + escape = 1; + continue; + } + if (escape != 0) + break; + m0 = mnemonic_list_find(&m->child, ch); + if (m0 == NULL) + break; + m = m0; + } + while (m != ei->mroot) { + --i; + if (m->value != ei->invalid) + break; + m = m->parent; + } + if (ch == ESCAPE && m != ei->mroot) + ++i; + psenc->chlen -= i; + memmove(&psenc->ch[0], &psenc->ch[i], psenc->chlen); + wc = (m == ei->mroot) ? (wchar_t)ch : m->value; + if (pwc != NULL) + *pwc = wc; + *nresult = (size_t)(wc == 0 ? 0 : s0 - *s); + *s = s0; + + return (0); +} + +static int +_citrus_VIQR_wcrtomb_priv(_VIQREncodingInfo * __restrict ei, + char * __restrict s, size_t n, wchar_t wc, + _VIQRState * __restrict psenc, size_t * __restrict nresult) +{ + mnemonic_t *m; + const char *p; + int ch = 0; + + switch (psenc->chlen) { + case 0: case 1: + break; + default: + return (EINVAL); + } + m = NULL; + if ((uint32_t)wc <= 0xFF) { + p = mnemonic_rfc1456[wc & 0xFF]; + if (p != NULL) + goto mnemonic_found; + if (n-- < 1) + goto e2big; + ch = (unsigned int)wc; + m = ei->mroot; + if (psenc->chlen > 0) { + m = mnemonic_list_find(&m->child, psenc->ch[0]); + if (m == NULL) + return (EINVAL); + psenc->ch[0] = ESCAPE; + } + if (mnemonic_list_find(&m->child, ch) == NULL) { + psenc->chlen = 0; + m = NULL; + } + psenc->ch[psenc->chlen++] = ch; + } else { + p = mnemonic_ext_find(wc, &mnemonic_ext[0], mnemonic_ext_size); + if (p == NULL) { + *nresult = (size_t)-1; + return (EILSEQ); + } else { +mnemonic_found: + psenc->chlen = 0; + while (*p != '\0') { + if (n-- < 1) + goto e2big; + psenc->ch[psenc->chlen++] = *p++; + } + } + } + memcpy(s, psenc->ch, psenc->chlen); + *nresult = psenc->chlen; + if (m == ei->mroot) { + psenc->ch[0] = ch; + psenc->chlen = 1; + } else + psenc->chlen = 0; + + return (0); + +e2big: + *nresult = (size_t)-1; + return (E2BIG); +} + +static int +/* ARGSUSED */ +_citrus_VIQR_put_state_reset(_VIQREncodingInfo * __restrict ei __unused, + char * __restrict s __unused, size_t n __unused, + _VIQRState * __restrict psenc, size_t * __restrict nresult) +{ + + switch (psenc->chlen) { + case 0: case 1: + break; + default: + return (EINVAL); + } + *nresult = 0; + psenc->chlen = 0; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_VIQR_stdenc_wctocs(_VIQREncodingInfo * __restrict ei __unused, + _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc) +{ + + *csid = 0; + *idx = (_index_t)wc; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_VIQR_stdenc_cstowc(_VIQREncodingInfo * __restrict ei __unused, + wchar_t * __restrict pwc, _csid_t csid, _index_t idx) +{ + + if (csid != 0) + return (EILSEQ); + *pwc = (wchar_t)idx; + + return (0); +} + +static void +_citrus_VIQR_encoding_module_uninit(_VIQREncodingInfo *ei) +{ + + mnemonic_destroy(ei->mroot); +} + +static int +/*ARGSUSED*/ +_citrus_VIQR_encoding_module_init(_VIQREncodingInfo * __restrict ei, + const void * __restrict var __unused, size_t lenvar __unused) +{ + const mnemonic_def_t *p; + const char *s; + size_t i, n; + int errnum; + + ei->mb_cur_max = 1; + ei->invalid = (wchar_t)-1; + ei->mroot = mnemonic_create(NULL, '\0', ei->invalid); + if (ei->mroot == NULL) + return (ENOMEM); + for (i = 0; i < sizeof(mnemonic_rfc1456) / sizeof(const char *); ++i) { + s = mnemonic_rfc1456[i]; + if (s == NULL) + continue; + n = strlen(s); + if (ei->mb_cur_max < n) + ei->mb_cur_max = n; + errnum = mnemonic_append_child(ei->mroot, + s, (wchar_t)i, ei->invalid); + if (errnum != 0) { + _citrus_VIQR_encoding_module_uninit(ei); + return (errnum); + } + } + for (i = 0;; ++i) { + p = &mnemonic_ext[i]; + n = strlen(p->name); + if (ei->mb_cur_max < n) + ei->mb_cur_max = n; + errnum = mnemonic_append_child(ei->mroot, + p->name, p->value, ei->invalid); + if (errnum != 0) { + _citrus_VIQR_encoding_module_uninit(ei); + return (errnum); + } + } + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_VIQR_stdenc_get_state_desc_generic(_VIQREncodingInfo * __restrict ei __unused, + _VIQRState * __restrict psenc, int * __restrict rstate) +{ + + *rstate = (psenc->chlen == 0) ? + _STDENC_SDGEN_INITIAL : + _STDENC_SDGEN_INCOMPLETE_CHAR; + + return (0); +} + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(VIQR); +_CITRUS_STDENC_DEF_OPS(VIQR); + +#include "citrus_stdenc_template.h" diff --git a/lib/libiconv_modules/VIQR/citrus_viqr.h b/lib/libiconv_modules/VIQR/citrus_viqr.h new file mode 100644 index 000000000000..a6d943c2656c --- /dev/null +++ b/lib/libiconv_modules/VIQR/citrus_viqr.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_viqr.h,v 1.1 2006/11/13 15:16:31 tnozaki Exp $ */ + +/*- + * Copyright (c)2006 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_VIQR_H_ +#define _CITRUS_VIQR_H_ + +__BEGIN_DECLS +_CITRUS_STDENC_GETOPS_FUNC(VIQR); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/ZW/Makefile b/lib/libiconv_modules/ZW/Makefile new file mode 100644 index 000000000000..42ecd9f4d651 --- /dev/null +++ b/lib/libiconv_modules/ZW/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +SHLIB= ZW +SRCS+= citrus_zw.c + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/ZW/citrus_zw.c b/lib/libiconv_modules/ZW/citrus_zw.c new file mode 100644 index 000000000000..d57661f1649c --- /dev/null +++ b/lib/libiconv_modules/ZW/citrus_zw.c @@ -0,0 +1,455 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_zw.c,v 1.4 2008/06/14 16:01:08 tnozaki Exp $ */ + +/*- + * Copyright (c)2004, 2006 Citrus Project, + * 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. + * + */ + +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stddef.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_stdenc.h" +#include "citrus_zw.h" + +/* ---------------------------------------------------------------------- + * private stuffs used by templates + */ + +typedef struct { + int dummy; +} _ZWEncodingInfo; + +typedef enum { + NONE, AMBIGIOUS, ASCII, GB2312 +} _ZWCharset; + +typedef struct { + _ZWCharset charset; + int chlen; + char ch[4]; +} _ZWState; + +#define _CEI_TO_EI(_cei_) (&(_cei_)->ei) +#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_ + +#define _FUNCNAME(m) _citrus_ZW_##m +#define _ENCODING_INFO _ZWEncodingInfo +#define _ENCODING_STATE _ZWState +#define _ENCODING_MB_CUR_MAX(_ei_) MB_LEN_MAX +#define _ENCODING_IS_STATE_DEPENDENT 1 +#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) ((_ps_)->charset != NONE) + +static __inline void +/*ARGSUSED*/ +_citrus_ZW_init_state(_ZWEncodingInfo * __restrict ei __unused, + _ZWState * __restrict psenc) +{ + + psenc->chlen = 0; + psenc->charset = NONE; +} + +static __inline void +/*ARGSUSED*/ +_citrus_ZW_pack_state(_ZWEncodingInfo * __restrict ei __unused, + void *__restrict pspriv, const _ZWState * __restrict psenc) +{ + + memcpy(pspriv, (const void *)psenc, sizeof(*psenc)); +} + +static __inline void +/*ARGSUSED*/ +_citrus_ZW_unpack_state(_ZWEncodingInfo * __restrict ei __unused, + _ZWState * __restrict psenc, const void * __restrict pspriv) +{ + + memcpy((void *)psenc, pspriv, sizeof(*psenc)); +} + +static int +_citrus_ZW_mbrtowc_priv(_ZWEncodingInfo * __restrict ei, + wchar_t * __restrict pwc, char **__restrict s, size_t n, + _ZWState * __restrict psenc, size_t * __restrict nresult) +{ + char *s0; + wchar_t wc; + int ch, len; + + if (*s == NULL) { + _citrus_ZW_init_state(ei, psenc); + *nresult = (size_t)_ENCODING_IS_STATE_DEPENDENT; + return (0); + } + s0 = *s; + len = 0; + +#define STORE \ +do { \ + if (n-- < 1) { \ + *nresult = (size_t)-2; \ + *s = s0; \ + return (0); \ + } \ + ch = (unsigned char)*s0++; \ + if (len++ > MB_LEN_MAX || ch > 0x7F)\ + goto ilseq; \ + psenc->ch[psenc->chlen++] = ch; \ +} while (/*CONSTCOND*/0) + +loop: + switch (psenc->charset) { + case ASCII: + switch (psenc->chlen) { + case 0: + STORE; + switch (psenc->ch[0]) { + case '\0': case '\n': + psenc->charset = NONE; + } + /*FALLTHROUGH*/ + case 1: + break; + default: + return (EINVAL); + } + ch = (unsigned char)psenc->ch[0]; + if (ch > 0x7F) + goto ilseq; + wc = (wchar_t)ch; + psenc->chlen = 0; + break; + case NONE: + if (psenc->chlen != 0) + return (EINVAL); + STORE; + ch = (unsigned char)psenc->ch[0]; + if (ch != 'z') { + if (ch != '\n' && ch != '\0') + psenc->charset = ASCII; + wc = (wchar_t)ch; + psenc->chlen = 0; + break; + } + psenc->charset = AMBIGIOUS; + psenc->chlen = 0; + /* FALLTHROUGH */ + case AMBIGIOUS: + if (psenc->chlen != 0) + return (EINVAL); + STORE; + if (psenc->ch[0] != 'W') { + psenc->charset = ASCII; + wc = L'z'; + break; + } + psenc->charset = GB2312; + psenc->chlen = 0; + /* FALLTHROUGH */ + case GB2312: + switch (psenc->chlen) { + case 0: + STORE; + ch = (unsigned char)psenc->ch[0]; + if (ch == '\0') { + psenc->charset = NONE; + wc = (wchar_t)ch; + psenc->chlen = 0; + break; + } else if (ch == '\n') { + psenc->charset = NONE; + psenc->chlen = 0; + goto loop; + } + /*FALLTHROUGH*/ + case 1: + STORE; + if (psenc->ch[0] == ' ') { + ch = (unsigned char)psenc->ch[1]; + wc = (wchar_t)ch; + psenc->chlen = 0; + break; + } else if (psenc->ch[0] == '#') { + ch = (unsigned char)psenc->ch[1]; + if (ch == '\n') { + psenc->charset = NONE; + wc = (wchar_t)ch; + psenc->chlen = 0; + break; + } else if (ch == ' ') { + wc = (wchar_t)ch; + psenc->chlen = 0; + break; + } + } + ch = (unsigned char)psenc->ch[0]; + if (ch < 0x21 || ch > 0x7E) + goto ilseq; + wc = (wchar_t)(ch << 8); + ch = (unsigned char)psenc->ch[1]; + if (ch < 0x21 || ch > 0x7E) { +ilseq: + *nresult = (size_t)-1; + return (EILSEQ); + } + wc |= (wchar_t)ch; + psenc->chlen = 0; + break; + default: + return (EINVAL); + } + break; + default: + return (EINVAL); + } + if (pwc != NULL) + *pwc = wc; + + *nresult = (size_t)(wc == 0 ? 0 : len); + *s = s0; + + return (0); +} + +static int +/*ARGSUSED*/ +_citrus_ZW_wcrtomb_priv(_ZWEncodingInfo * __restrict ei __unused, + char *__restrict s, size_t n, wchar_t wc, + _ZWState * __restrict psenc, size_t * __restrict nresult) +{ + int ch; + + if (psenc->chlen != 0) + return (EINVAL); + if ((uint32_t)wc <= 0x7F) { + ch = (unsigned char)wc; + switch (psenc->charset) { + case NONE: + if (ch == '\0' || ch == '\n') + psenc->ch[psenc->chlen++] = ch; + else { + if (n < 4) + return (E2BIG); + n -= 4; + psenc->ch[psenc->chlen++] = 'z'; + psenc->ch[psenc->chlen++] = 'W'; + psenc->ch[psenc->chlen++] = ' '; + psenc->ch[psenc->chlen++] = ch; + psenc->charset = GB2312; + } + break; + case GB2312: + if (n < 2) + return (E2BIG); + n -= 2; + if (ch == '\0') { + psenc->ch[psenc->chlen++] = '\n'; + psenc->ch[psenc->chlen++] = '\0'; + psenc->charset = NONE; + } else if (ch == '\n') { + psenc->ch[psenc->chlen++] = '#'; + psenc->ch[psenc->chlen++] = '\n'; + psenc->charset = NONE; + } else { + psenc->ch[psenc->chlen++] = ' '; + psenc->ch[psenc->chlen++] = ch; + } + break; + default: + return (EINVAL); + } + } else if ((uint32_t)wc <= 0x7E7E) { + switch (psenc->charset) { + case NONE: + if (n < 2) + return (E2BIG); + n -= 2; + psenc->ch[psenc->chlen++] = 'z'; + psenc->ch[psenc->chlen++] = 'W'; + psenc->charset = GB2312; + /* FALLTHROUGH*/ + case GB2312: + if (n < 2) + return (E2BIG); + n -= 2; + ch = (wc >> 8) & 0xFF; + if (ch < 0x21 || ch > 0x7E) + goto ilseq; + psenc->ch[psenc->chlen++] = ch; + ch = wc & 0xFF; + if (ch < 0x21 || ch > 0x7E) + goto ilseq; + psenc->ch[psenc->chlen++] = ch; + break; + default: + return (EINVAL); + } + } else { +ilseq: + *nresult = (size_t)-1; + return (EILSEQ); + } + memcpy(s, psenc->ch, psenc->chlen); + *nresult = psenc->chlen; + psenc->chlen = 0; + + return (0); +} + +static int +/*ARGSUSED*/ +_citrus_ZW_put_state_reset(_ZWEncodingInfo * __restrict ei __unused, + char * __restrict s, size_t n, _ZWState * __restrict psenc, + size_t * __restrict nresult) +{ + + if (psenc->chlen != 0) + return (EINVAL); + switch (psenc->charset) { + case GB2312: + if (n-- < 1) + return (E2BIG); + psenc->ch[psenc->chlen++] = '\n'; + psenc->charset = NONE; + /*FALLTHROUGH*/ + case NONE: + *nresult = psenc->chlen; + if (psenc->chlen > 0) { + memcpy(s, psenc->ch, psenc->chlen); + psenc->chlen = 0; + } + break; + default: + return (EINVAL); + } + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_ZW_stdenc_get_state_desc_generic(_ZWEncodingInfo * __restrict ei __unused, + _ZWState * __restrict psenc, int * __restrict rstate) +{ + + switch (psenc->charset) { + case NONE: + if (psenc->chlen != 0) + return (EINVAL); + *rstate = _STDENC_SDGEN_INITIAL; + break; + case AMBIGIOUS: + if (psenc->chlen != 0) + return (EINVAL); + *rstate = _STDENC_SDGEN_INCOMPLETE_SHIFT; + break; + case ASCII: + case GB2312: + switch (psenc->chlen) { + case 0: + *rstate = _STDENC_SDGEN_STABLE; + break; + case 1: + *rstate = (psenc->ch[0] == '#') ? + _STDENC_SDGEN_INCOMPLETE_SHIFT : + _STDENC_SDGEN_INCOMPLETE_CHAR; + break; + default: + return (EINVAL); + } + break; + default: + return (EINVAL); + } + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_ZW_stdenc_wctocs(_ZWEncodingInfo * __restrict ei __unused, + _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc) +{ + + *csid = (_csid_t)(wc <= (wchar_t)0x7FU) ? 0 : 1; + *idx = (_index_t)wc; + + return (0); +} + +static __inline int +/*ARGSUSED*/ +_citrus_ZW_stdenc_cstowc(_ZWEncodingInfo * __restrict ei __unused, + wchar_t * __restrict wc, _csid_t csid, _index_t idx) +{ + + switch (csid) { + case 0: case 1: + break; + default: + return (EINVAL); + } + *wc = (wchar_t)idx; + + return (0); +} + +static void +/*ARGSUSED*/ +_citrus_ZW_encoding_module_uninit(_ZWEncodingInfo *ei __unused) +{ + +} + +static int +/*ARGSUSED*/ +_citrus_ZW_encoding_module_init(_ZWEncodingInfo * __restrict ei __unused, + const void *__restrict var __unused, size_t lenvar __unused) +{ + + return (0); +} + +/* ---------------------------------------------------------------------- + * public interface for stdenc + */ + +_CITRUS_STDENC_DECLS(ZW); +_CITRUS_STDENC_DEF_OPS(ZW); + +#include "citrus_stdenc_template.h" diff --git a/lib/libiconv_modules/ZW/citrus_zw.h b/lib/libiconv_modules/ZW/citrus_zw.h new file mode 100644 index 000000000000..b24485b5e852 --- /dev/null +++ b/lib/libiconv_modules/ZW/citrus_zw.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_zw.h,v 1.1 2006/11/22 23:38:27 tnozaki Exp $ */ + +/*- + * Copyright (c)2004,2006 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_ZW_H_ +#define _CITRUS_ZW_H_ + +__BEGIN_DECLS +_CITRUS_STDENC_GETOPS_FUNC(ZW); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/iconv_none/Makefile b/lib/libiconv_modules/iconv_none/Makefile new file mode 100644 index 000000000000..d6cbd0268b13 --- /dev/null +++ b/lib/libiconv_modules/iconv_none/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +SHLIB= iconv_none +SRCS+= citrus_iconv_none.c + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/iconv_none/citrus_iconv_none.c b/lib/libiconv_modules/iconv_none/citrus_iconv_none.c new file mode 100644 index 000000000000..d9230cb26f3e --- /dev/null +++ b/lib/libiconv_modules/iconv_none/citrus_iconv_none.c @@ -0,0 +1,127 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_iconv_none.c,v 1.2 2003/07/01 09:42:16 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * 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. + */ + +#include <sys/cdefs.h> +#include <sys/queue.h> + +#include <assert.h> +#include <errno.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_hash.h" +#include "citrus_iconv.h" +#include "citrus_iconv_none.h" + +/* ---------------------------------------------------------------------- */ + +_CITRUS_ICONV_DECLS(iconv_none); +_CITRUS_ICONV_DEF_OPS(iconv_none); + + +/* ---------------------------------------------------------------------- */ + +int +_citrus_iconv_none_iconv_getops(struct _citrus_iconv_ops *ops) +{ + + memcpy(ops, &_citrus_iconv_none_iconv_ops, + sizeof(_citrus_iconv_none_iconv_ops)); + + return (0); +} + +static int +/*ARGSUSED*/ +_citrus_iconv_none_iconv_init_shared( + struct _citrus_iconv_shared * __restrict ci, + const char * __restrict in __unused, const char * __restrict out __unused) +{ + + ci->ci_closure = NULL; + return (0); +} + +static void +/*ARGSUSED*/ +_citrus_iconv_none_iconv_uninit_shared(struct _citrus_iconv_shared *ci __unused) +{ + +} + +static int +/*ARGSUSED*/ +_citrus_iconv_none_iconv_init_context(struct _citrus_iconv *cv) +{ + + cv->cv_closure = NULL; + return (0); +} + +static void +/*ARGSUSED*/ +_citrus_iconv_none_iconv_uninit_context(struct _citrus_iconv *cv __unused) +{ + +} + +static int +/*ARGSUSED*/ +_citrus_iconv_none_iconv_convert(struct _citrus_iconv * __restrict ci __unused, + char * __restrict * __restrict in, size_t * __restrict inbytes, + char * __restrict * __restrict out, size_t * __restrict outbytes, + uint32_t flags __unused, size_t * __restrict invalids) +{ + size_t len; + int e2big; + + if ((in == NULL) || (out == NULL) || (inbytes == NULL)) + return (0); + if ((*in == NULL) || (*out == NULL) || (*inbytes == 0) || (*outbytes == 0)) + return (0); + len = *inbytes; + e2big = 0; + if (*outbytes<len) { + e2big = 1; + len = *outbytes; + } + memcpy(*out, *in, len); + in += len; + *inbytes -= len; + out += len; + *outbytes -= len; + *invalids = 0; + if (e2big) + return (E2BIG); + + return (0); +} diff --git a/lib/libiconv_modules/iconv_none/citrus_iconv_none.h b/lib/libiconv_modules/iconv_none/citrus_iconv_none.h new file mode 100644 index 000000000000..392af412c6ab --- /dev/null +++ b/lib/libiconv_modules/iconv_none/citrus_iconv_none.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_iconv_none.h,v 1.1 2003/06/25 09:51:43 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_ICONV_NONE_H_ +#define _CITRUS_ICONV_NONE_H_ + +__BEGIN_DECLS +_CITRUS_ICONV_GETOPS_FUNC(iconv_none); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/iconv_std/Makefile b/lib/libiconv_modules/iconv_std/Makefile new file mode 100644 index 000000000000..a873cfad5d65 --- /dev/null +++ b/lib/libiconv_modules/iconv_std/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +SHLIB= iconv_std +SRCS+= citrus_iconv_std.c +CFLAGS+= --param max-inline-insns-single=32 + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/iconv_std/citrus_iconv_std.c b/lib/libiconv_modules/iconv_std/citrus_iconv_std.c new file mode 100644 index 000000000000..8349c46819c6 --- /dev/null +++ b/lib/libiconv_modules/iconv_std/citrus_iconv_std.c @@ -0,0 +1,583 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_iconv_std.c,v 1.15 2006/11/13 19:08:19 tnozaki Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * 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. + */ + +#include <sys/cdefs.h> +#include <sys/endian.h> +#include <sys/queue.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_region.h" +#include "citrus_mmap.h" +#include "citrus_hash.h" +#include "citrus_iconv.h" +#include "citrus_stdenc.h" +#include "citrus_mapper.h" +#include "citrus_csmapper.h" +#include "citrus_memstream.h" +#include "citrus_iconv_std.h" +#include "citrus_esdb.h" + +/* ---------------------------------------------------------------------- */ + +_CITRUS_ICONV_DECLS(iconv_std); +_CITRUS_ICONV_DEF_OPS(iconv_std); + + +/* ---------------------------------------------------------------------- */ + +int +_citrus_iconv_std_iconv_getops(struct _citrus_iconv_ops *ops) +{ + + memcpy(ops, &_citrus_iconv_std_iconv_ops, + sizeof(_citrus_iconv_std_iconv_ops)); + + return (0); +} + +/* ---------------------------------------------------------------------- */ + +/* + * convenience routines for stdenc. + */ +static __inline void +save_encoding_state(struct _citrus_iconv_std_encoding *se) +{ + + if (se->se_ps) + memcpy(se->se_pssaved, se->se_ps, + _stdenc_get_state_size(se->se_handle)); +} + +static __inline void +restore_encoding_state(struct _citrus_iconv_std_encoding *se) +{ + + if (se->se_ps) + memcpy(se->se_ps, se->se_pssaved, + _stdenc_get_state_size(se->se_handle)); +} + +static __inline void +init_encoding_state(struct _citrus_iconv_std_encoding *se) +{ + + if (se->se_ps) + _stdenc_init_state(se->se_handle, se->se_ps); +} + +static __inline int +mbtocsx(struct _citrus_iconv_std_encoding *se, + _csid_t *csid, _index_t *idx, char **s, size_t n, size_t *nresult, + struct iconv_hooks *hooks) +{ + + return (_stdenc_mbtocs(se->se_handle, csid, idx, s, n, se->se_ps, + nresult, hooks)); +} + +static __inline int +cstombx(struct _citrus_iconv_std_encoding *se, + char *s, size_t n, _csid_t csid, _index_t idx, size_t *nresult, + struct iconv_hooks *hooks) +{ + + return (_stdenc_cstomb(se->se_handle, s, n, csid, idx, se->se_ps, + nresult, hooks)); +} + +static __inline int +wctombx(struct _citrus_iconv_std_encoding *se, + char *s, size_t n, _wc_t wc, size_t *nresult, + struct iconv_hooks *hooks) +{ + + return (_stdenc_wctomb(se->se_handle, s, n, wc, se->se_ps, nresult, + hooks)); +} + +static __inline int +put_state_resetx(struct _citrus_iconv_std_encoding *se, char *s, size_t n, + size_t *nresult) +{ + + return (_stdenc_put_state_reset(se->se_handle, s, n, se->se_ps, nresult)); +} + +static __inline int +get_state_desc_gen(struct _citrus_iconv_std_encoding *se, int *rstate) +{ + struct _stdenc_state_desc ssd; + int ret; + + ret = _stdenc_get_state_desc(se->se_handle, se->se_ps, + _STDENC_SDID_GENERIC, &ssd); + if (!ret) + *rstate = ssd.u.generic.state; + + return (ret); +} + +/* + * init encoding context + */ +static int +init_encoding(struct _citrus_iconv_std_encoding *se, struct _stdenc *cs, + void *ps1, void *ps2) +{ + int ret = -1; + + se->se_handle = cs; + se->se_ps = ps1; + se->se_pssaved = ps2; + + if (se->se_ps) + ret = _stdenc_init_state(cs, se->se_ps); + if (!ret && se->se_pssaved) + ret = _stdenc_init_state(cs, se->se_pssaved); + + return (ret); +} + +static int +open_csmapper(struct _csmapper **rcm, const char *src, const char *dst, + unsigned long *rnorm) +{ + struct _csmapper *cm; + int ret; + + ret = _csmapper_open(&cm, src, dst, 0, rnorm); + if (ret) + return (ret); + if (_csmapper_get_src_max(cm) != 1 || _csmapper_get_dst_max(cm) != 1 || + _csmapper_get_state_size(cm) != 0) { + _csmapper_close(cm); + return (EINVAL); + } + + *rcm = cm; + + return (0); +} + +static void +close_dsts(struct _citrus_iconv_std_dst_list *dl) +{ + struct _citrus_iconv_std_dst *sd; + + while ((sd = TAILQ_FIRST(dl)) != NULL) { + TAILQ_REMOVE(dl, sd, sd_entry); + _csmapper_close(sd->sd_mapper); + free(sd); + } +} + +static int +open_dsts(struct _citrus_iconv_std_dst_list *dl, + const struct _esdb_charset *ec, const struct _esdb *dbdst) +{ + struct _citrus_iconv_std_dst *sd, *sdtmp; + unsigned long norm; + int i, ret; + + sd = malloc(sizeof(*sd)); + if (sd == NULL) + return (errno); + + for (i = 0; i < dbdst->db_num_charsets; i++) { + ret = open_csmapper(&sd->sd_mapper, ec->ec_csname, + dbdst->db_charsets[i].ec_csname, &norm); + if (ret == 0) { + sd->sd_csid = dbdst->db_charsets[i].ec_csid; + sd->sd_norm = norm; + /* insert this mapper by sorted order. */ + TAILQ_FOREACH(sdtmp, dl, sd_entry) { + if (sdtmp->sd_norm > norm) { + TAILQ_INSERT_BEFORE(sdtmp, sd, + sd_entry); + sd = NULL; + break; + } + } + if (sd) + TAILQ_INSERT_TAIL(dl, sd, sd_entry); + sd = malloc(sizeof(*sd)); + if (sd == NULL) { + ret = errno; + close_dsts(dl); + return (ret); + } + } else if (ret != ENOENT) { + close_dsts(dl); + free(sd); + return (ret); + } + } + free(sd); + return (0); +} + +static void +close_srcs(struct _citrus_iconv_std_src_list *sl) +{ + struct _citrus_iconv_std_src *ss; + + while ((ss = TAILQ_FIRST(sl)) != NULL) { + TAILQ_REMOVE(sl, ss, ss_entry); + close_dsts(&ss->ss_dsts); + free(ss); + } +} + +static int +open_srcs(struct _citrus_iconv_std_src_list *sl, + const struct _esdb *dbsrc, const struct _esdb *dbdst) +{ + struct _citrus_iconv_std_src *ss; + int count = 0, i, ret; + + ss = malloc(sizeof(*ss)); + if (ss == NULL) + return (errno); + + TAILQ_INIT(&ss->ss_dsts); + + for (i = 0; i < dbsrc->db_num_charsets; i++) { + ret = open_dsts(&ss->ss_dsts, &dbsrc->db_charsets[i], dbdst); + if (ret) + goto err; + if (!TAILQ_EMPTY(&ss->ss_dsts)) { + ss->ss_csid = dbsrc->db_charsets[i].ec_csid; + TAILQ_INSERT_TAIL(sl, ss, ss_entry); + ss = malloc(sizeof(*ss)); + if (ss == NULL) { + ret = errno; + goto err; + } + count++; + TAILQ_INIT(&ss->ss_dsts); + } + } + free(ss); + + return (count ? 0 : ENOENT); + +err: + free(ss); + close_srcs(sl); + return (ret); +} + +/* do convert a character */ +#define E_NO_CORRESPONDING_CHAR ENOENT /* XXX */ +static int +/*ARGSUSED*/ +do_conv(const struct _citrus_iconv_std_shared *is, + _csid_t *csid, _index_t *idx) +{ + struct _citrus_iconv_std_dst *sd; + struct _citrus_iconv_std_src *ss; + _index_t tmpidx; + int ret; + + TAILQ_FOREACH(ss, &is->is_srcs, ss_entry) { + if (ss->ss_csid == *csid) { + TAILQ_FOREACH(sd, &ss->ss_dsts, sd_entry) { + ret = _csmapper_convert(sd->sd_mapper, + &tmpidx, *idx, NULL); + switch (ret) { + case _MAPPER_CONVERT_SUCCESS: + *csid = sd->sd_csid; + *idx = tmpidx; + return (0); + case _MAPPER_CONVERT_NONIDENTICAL: + break; + case _MAPPER_CONVERT_SRC_MORE: + /*FALLTHROUGH*/ + case _MAPPER_CONVERT_DST_MORE: + /*FALLTHROUGH*/ + case _MAPPER_CONVERT_ILSEQ: + return (EILSEQ); + case _MAPPER_CONVERT_FATAL: + return (EINVAL); + } + } + break; + } + } + + return (E_NO_CORRESPONDING_CHAR); +} +/* ---------------------------------------------------------------------- */ + +static int +/*ARGSUSED*/ +_citrus_iconv_std_iconv_init_shared(struct _citrus_iconv_shared *ci, + const char * __restrict src, const char * __restrict dst) +{ + struct _citrus_esdb esdbdst, esdbsrc; + struct _citrus_iconv_std_shared *is; + int ret; + + is = malloc(sizeof(*is)); + if (is == NULL) { + ret = errno; + goto err0; + } + ret = _citrus_esdb_open(&esdbsrc, src); + if (ret) + goto err1; + ret = _citrus_esdb_open(&esdbdst, dst); + if (ret) + goto err2; + ret = _stdenc_open(&is->is_src_encoding, esdbsrc.db_encname, + esdbsrc.db_variable, esdbsrc.db_len_variable); + if (ret) + goto err3; + ret = _stdenc_open(&is->is_dst_encoding, esdbdst.db_encname, + esdbdst.db_variable, esdbdst.db_len_variable); + if (ret) + goto err4; + is->is_use_invalid = esdbdst.db_use_invalid; + is->is_invalid = esdbdst.db_invalid; + + TAILQ_INIT(&is->is_srcs); + ret = open_srcs(&is->is_srcs, &esdbsrc, &esdbdst); + if (ret) + goto err5; + + _esdb_close(&esdbsrc); + _esdb_close(&esdbdst); + ci->ci_closure = is; + + return (0); + +err5: + _stdenc_close(is->is_dst_encoding); +err4: + _stdenc_close(is->is_src_encoding); +err3: + _esdb_close(&esdbdst); +err2: + _esdb_close(&esdbsrc); +err1: + free(is); +err0: + return (ret); +} + +static void +_citrus_iconv_std_iconv_uninit_shared(struct _citrus_iconv_shared *ci) +{ + struct _citrus_iconv_std_shared *is = ci->ci_closure; + + if (is == NULL) + return; + + _stdenc_close(is->is_src_encoding); + _stdenc_close(is->is_dst_encoding); + close_srcs(&is->is_srcs); + free(is); +} + +static int +_citrus_iconv_std_iconv_init_context(struct _citrus_iconv *cv) +{ + const struct _citrus_iconv_std_shared *is = cv->cv_shared->ci_closure; + struct _citrus_iconv_std_context *sc; + char *ptr; + size_t sz, szpsdst, szpssrc; + + szpssrc = _stdenc_get_state_size(is->is_src_encoding); + szpsdst = _stdenc_get_state_size(is->is_dst_encoding); + + sz = (szpssrc + szpsdst)*2 + sizeof(struct _citrus_iconv_std_context); + sc = malloc(sz); + if (sc == NULL) + return (errno); + + ptr = (char *)&sc[1]; + if (szpssrc > 0) + init_encoding(&sc->sc_src_encoding, is->is_src_encoding, + ptr, ptr+szpssrc); + else + init_encoding(&sc->sc_src_encoding, is->is_src_encoding, + NULL, NULL); + ptr += szpssrc*2; + if (szpsdst > 0) + init_encoding(&sc->sc_dst_encoding, is->is_dst_encoding, + ptr, ptr+szpsdst); + else + init_encoding(&sc->sc_dst_encoding, is->is_dst_encoding, + NULL, NULL); + + cv->cv_closure = (void *)sc; + + return (0); +} + +static void +_citrus_iconv_std_iconv_uninit_context(struct _citrus_iconv *cv) +{ + + free(cv->cv_closure); +} + +static int +_citrus_iconv_std_iconv_convert(struct _citrus_iconv * __restrict cv, + char * __restrict * __restrict in, size_t * __restrict inbytes, + char * __restrict * __restrict out, size_t * __restrict outbytes, + uint32_t flags, size_t * __restrict invalids) +{ + const struct _citrus_iconv_std_shared *is = cv->cv_shared->ci_closure; + struct _citrus_iconv_std_context *sc = cv->cv_closure; + _csid_t csid; + _index_t idx; + char *tmpin; + size_t inval, szrin, szrout; + int ret, state = 0; + + inval = 0; + if (in == NULL || *in == NULL) { + /* special cases */ + if (out != NULL && *out != NULL) { + /* init output state and store the shift sequence */ + save_encoding_state(&sc->sc_src_encoding); + save_encoding_state(&sc->sc_dst_encoding); + szrout = 0; + + ret = put_state_resetx(&sc->sc_dst_encoding, + *out, *outbytes, &szrout); + if (ret) + goto err; + + if (szrout == (size_t)-2) { + /* too small to store the character */ + ret = EINVAL; + goto err; + } + *out += szrout; + *outbytes -= szrout; + } else + /* otherwise, discard the shift sequence */ + init_encoding_state(&sc->sc_dst_encoding); + init_encoding_state(&sc->sc_src_encoding); + *invalids = 0; + return (0); + } + + /* normal case */ + for (;;) { + if (*inbytes == 0) { + ret = get_state_desc_gen(&sc->sc_src_encoding, &state); + if (state == _STDENC_SDGEN_INITIAL || + state == _STDENC_SDGEN_STABLE) + break; + } + + /* save the encoding states for the error recovery */ + save_encoding_state(&sc->sc_src_encoding); + save_encoding_state(&sc->sc_dst_encoding); + + /* mb -> csid/index */ + tmpin = *in; + szrin = szrout = 0; + ret = mbtocsx(&sc->sc_src_encoding, &csid, &idx, &tmpin, + *inbytes, &szrin, cv->cv_shared->ci_hooks); + if (ret) + goto err; + + if (szrin == (size_t)-2) { + /* incompleted character */ + ret = get_state_desc_gen(&sc->sc_src_encoding, &state); + if (ret) { + ret = EINVAL; + goto err; + } + switch (state) { + case _STDENC_SDGEN_INITIAL: + case _STDENC_SDGEN_STABLE: + /* fetch shift sequences only. */ + goto next; + } + ret = EINVAL; + goto err; + } + /* convert the character */ + ret = do_conv(is, &csid, &idx); + if (ret) { + if (ret == E_NO_CORRESPONDING_CHAR) { + inval++; + szrout = 0; + if ((((flags & _CITRUS_ICONV_F_HIDE_INVALID) == 0) && + !cv->cv_shared->ci_discard_ilseq) && + is->is_use_invalid) { + ret = wctombx(&sc->sc_dst_encoding, + *out, *outbytes, is->is_invalid, + &szrout, cv->cv_shared->ci_hooks); + if (ret) + goto err; + } + goto next; + } else + goto err; + } + /* csid/index -> mb */ + ret = cstombx(&sc->sc_dst_encoding, + *out, *outbytes, csid, idx, &szrout, + cv->cv_shared->ci_hooks); + if (ret) + goto err; +next: + *inbytes -= tmpin-*in; /* szrin is insufficient on \0. */ + *in = tmpin; + *outbytes -= szrout; + *out += szrout; + } + *invalids = inval; + + return (0); + +err: + restore_encoding_state(&sc->sc_src_encoding); + restore_encoding_state(&sc->sc_dst_encoding); + *invalids = inval; + + return (ret); +} diff --git a/lib/libiconv_modules/iconv_std/citrus_iconv_std.h b/lib/libiconv_modules/iconv_std/citrus_iconv_std.h new file mode 100644 index 000000000000..3aef79ee549c --- /dev/null +++ b/lib/libiconv_modules/iconv_std/citrus_iconv_std.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_iconv_std.h,v 1.1 2003/06/25 09:51:44 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_ICONV_STD_H_ +#define _CITRUS_ICONV_STD_H_ + +#include "citrus_iconv_std_local.h" + +_CITRUS_ICONV_GETOPS_FUNC(iconv_std); + +#endif diff --git a/lib/libiconv_modules/iconv_std/citrus_iconv_std_local.h b/lib/libiconv_modules/iconv_std/citrus_iconv_std_local.h new file mode 100644 index 000000000000..6e83730eb333 --- /dev/null +++ b/lib/libiconv_modules/iconv_std/citrus_iconv_std_local.h @@ -0,0 +1,82 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_iconv_std_local.h,v 1.2 2003/07/01 09:42:16 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_ICONV_STD_LOCAL_H_ +#define _CITRUS_ICONV_STD_LOCAL_H_ + +/* + * encoding + */ +struct _citrus_iconv_std_encoding { + struct _citrus_stdenc *se_handle; + void *se_ps; + void *se_pssaved; +}; + +/* + * dst + */ +struct _citrus_iconv_std_dst { + TAILQ_ENTRY(_citrus_iconv_std_dst) sd_entry; + struct _citrus_csmapper *sd_mapper; + _citrus_csid_t sd_csid; + unsigned long sd_norm; +}; +TAILQ_HEAD(_citrus_iconv_std_dst_list, _citrus_iconv_std_dst); + +/* + * src + */ +struct _citrus_iconv_std_src { + TAILQ_ENTRY(_citrus_iconv_std_src) ss_entry; + struct _citrus_iconv_std_dst_list ss_dsts; + _citrus_csid_t ss_csid; +}; +TAILQ_HEAD(_citrus_iconv_std_src_list, _citrus_iconv_std_src); + +/* + * iconv_std handle + */ +struct _citrus_iconv_std_shared { + struct _citrus_stdenc *is_dst_encoding; + struct _citrus_stdenc *is_src_encoding; + struct _citrus_iconv_std_src_list is_srcs; + _citrus_wc_t is_invalid; + int is_use_invalid; +}; + +/* + * iconv_std context + */ +struct _citrus_iconv_std_context { + struct _citrus_iconv_std_encoding sc_dst_encoding; + struct _citrus_iconv_std_encoding sc_src_encoding; +}; + +#endif diff --git a/lib/libiconv_modules/mapper_646/Makefile b/lib/libiconv_modules/mapper_646/Makefile new file mode 100644 index 000000000000..7a524f480b19 --- /dev/null +++ b/lib/libiconv_modules/mapper_646/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +SHLIB= mapper_646 +SRCS= citrus_mapper_646.c + +WARNS?= 2 + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/mapper_646/citrus_mapper_646.c b/lib/libiconv_modules/mapper_646/citrus_mapper_646.c new file mode 100644 index 000000000000..b2775492a259 --- /dev/null +++ b/lib/libiconv_modules/mapper_646/citrus_mapper_646.c @@ -0,0 +1,249 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_mapper_646.c,v 1.4 2003/07/14 11:37:49 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * 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. + */ + +#include <sys/cdefs.h> +#include <sys/queue.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_module.h" +#include "citrus_region.h" +#include "citrus_memstream.h" +#include "citrus_mmap.h" +#include "citrus_hash.h" +#include "citrus_mapper.h" +#include "citrus_mapper_646.h" + +/* ---------------------------------------------------------------------- */ + +_CITRUS_MAPPER_DECLS(mapper_646); +_CITRUS_MAPPER_DEF_OPS(mapper_646); + +/* ---------------------------------------------------------------------- */ + +#define ILSEQ 0xFFFFFFFE +#define INVALID 0xFFFFFFFF +#define SPECIALS(x) \ + x(0x23) \ + x(0x24) \ + x(0x40) \ + x(0x5B) \ + x(0x5C) \ + x(0x5D) \ + x(0x5E) \ + x(0x60) \ + x(0x7B) \ + x(0x7C) \ + x(0x7D) \ + x(0x7E) + +#define INDEX(x) INDEX_##x, + +enum { + SPECIALS(INDEX) + NUM_OF_SPECIALS +}; +struct _citrus_mapper_646 { + _index_t m6_map[NUM_OF_SPECIALS]; + int m6_forward; +}; + +int +_citrus_mapper_646_mapper_getops(struct _citrus_mapper_ops *ops) +{ + + memcpy(ops, &_citrus_mapper_646_mapper_ops, + sizeof(_citrus_mapper_646_mapper_ops)); + + return (0); +} + +#define T_COMM '#' +static int +parse_file(struct _citrus_mapper_646 *m6, const char *path) +{ + struct _memstream ms; + struct _region r; + const char *p; + char *pp; + size_t len; + char buf[PATH_MAX]; + int i, ret; + + ret = _map_file(&r, path); + if (ret) + return (ret); + _memstream_bind(&ms, &r); + for (i = 0; i < NUM_OF_SPECIALS; i++) { +retry: + p = _memstream_getln(&ms, &len); + if (p == NULL) { + ret = EINVAL; + break; + } + p = _bcs_skip_ws_len(p, &len); + if (*p == T_COMM || len==0) + goto retry; + if (!_bcs_isdigit(*p)) { + ret = EINVAL; + break; + } + snprintf(buf, sizeof(buf), "%.*s", (int)len, p); + pp = __DECONST(void *, p); + m6->m6_map[i] = strtoul(buf, (char **)&pp, 0); + p = _bcs_skip_ws(buf); + if (*p != T_COMM && !*p) { + ret = EINVAL; + break; + } + } + _unmap_file(&r); + + return (ret); +}; + +static int +parse_var(struct _citrus_mapper_646 *m6, struct _memstream *ms, + const char *dir) +{ + struct _region r; + char path[PATH_MAX]; + + m6->m6_forward = 1; + _memstream_skip_ws(ms); + /* whether backward */ + if (_memstream_peek(ms) == '!') { + _memstream_getc(ms); + m6->m6_forward = 0; + } + /* get description file path */ + _memstream_getregion(ms, &r, _memstream_remainder(ms)); + snprintf(path, sizeof(path), "%s/%.*s", + dir, (int)_region_size(&r), (char *)_region_head(&r)); + /* remove trailing white spaces */ + path[_bcs_skip_nonws(path)-path] = '\0'; + return (parse_file(m6, path)); +} + +static int +/*ARGSUSED*/ +_citrus_mapper_646_mapper_init(struct _citrus_mapper_area *__restrict ma __unused, + struct _citrus_mapper * __restrict cm, const char * __restrict dir, + const void * __restrict var, size_t lenvar, + struct _citrus_mapper_traits * __restrict mt, size_t lenmt) +{ + struct _citrus_mapper_646 *m6; + struct _memstream ms; + struct _region r; + int ret; + + if (lenmt < sizeof(*mt)) + return (EINVAL); + + m6 = malloc(sizeof(*m6)); + if (m6 == NULL) + return (errno); + + _region_init(&r, __DECONST(void *, var), lenvar); + _memstream_bind(&ms, &r); + ret = parse_var(m6, &ms, dir); + if (ret) { + free(m6); + return (ret); + } + + cm->cm_closure = m6; + mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */ + mt->mt_state_size = 0; /* stateless */ + + return (0); +} + +static void +/*ARGSUSED*/ +_citrus_mapper_646_mapper_uninit(struct _citrus_mapper *cm) +{ + + if (cm && cm->cm_closure) + free(cm->cm_closure); +} + +static int +/*ARGSUSED*/ +_citrus_mapper_646_mapper_convert(struct _citrus_mapper * __restrict cm, + _index_t * __restrict dst, _index_t src, void * __restrict ps __unused) +{ + struct _citrus_mapper_646 *m6; + + m6 = cm->cm_closure; + if (m6->m6_forward) { + /* forward */ + if (src >= 0x80) + return (_MAPPER_CONVERT_ILSEQ); +#define FORWARD(x) \ +if (src == (x)) { \ + if (m6->m6_map[INDEX_##x]==INVALID) \ + return (_MAPPER_CONVERT_NONIDENTICAL); \ + *dst = m6->m6_map[INDEX_##x]; \ + return (0); \ +} else + SPECIALS(FORWARD); + *dst = src; + } else { + /* backward */ +#define BACKWARD(x) \ +if (m6->m6_map[INDEX_##x] != INVALID && src == m6->m6_map[INDEX_##x]) { \ + *dst = (x); \ + return (0); \ +} else if (src == (x)) \ + return (_MAPPER_CONVERT_ILSEQ); \ +else + SPECIALS(BACKWARD); + if (src >= 0x80) + return (_MAPPER_CONVERT_NONIDENTICAL); + *dst = src; + } + + return (_MAPPER_CONVERT_SUCCESS); +} + +static void +/*ARGSUSED*/ +_citrus_mapper_646_mapper_init_state(void) +{ + +} diff --git a/lib/libiconv_modules/mapper_646/citrus_mapper_646.h b/lib/libiconv_modules/mapper_646/citrus_mapper_646.h new file mode 100644 index 000000000000..2fd9170cbeb0 --- /dev/null +++ b/lib/libiconv_modules/mapper_646/citrus_mapper_646.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_mapper_646.h,v 1.1 2003/06/25 09:51:45 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_MAPPER_646_H_ +#define _CITRUS_MAPPER_646_H_ + +__BEGIN_DECLS +_CITRUS_MAPPER_GETOPS_FUNC(mapper_646); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/mapper_none/Makefile b/lib/libiconv_modules/mapper_none/Makefile new file mode 100644 index 000000000000..4261fe7214d4 --- /dev/null +++ b/lib/libiconv_modules/mapper_none/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +SHLIB= mapper_none +SRCS+= citrus_mapper_none.c + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/mapper_none/citrus_mapper_none.c b/lib/libiconv_modules/mapper_none/citrus_mapper_none.c new file mode 100644 index 000000000000..b3d2bda96b82 --- /dev/null +++ b/lib/libiconv_modules/mapper_none/citrus_mapper_none.c @@ -0,0 +1,104 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_mapper_none.c,v 1.2 2003/06/27 17:53:31 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * 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. + */ + +#include <sys/cdefs.h> +#include <sys/queue.h> + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_module.h" +#include "citrus_hash.h" +#include "citrus_mapper.h" +#include "citrus_mapper_none.h" + +/* ---------------------------------------------------------------------- */ + +_CITRUS_MAPPER_DECLS(mapper_none); +_CITRUS_MAPPER_DEF_OPS(mapper_none); + + +/* ---------------------------------------------------------------------- */ + +int +_citrus_mapper_none_mapper_getops(struct _citrus_mapper_ops *ops) +{ + + memcpy(ops, &_citrus_mapper_none_mapper_ops, + sizeof(_citrus_mapper_none_mapper_ops)); + + return (0); +} + +static int +/*ARGSUSED*/ +_citrus_mapper_none_mapper_init(struct _citrus_mapper_area *__restrict ma __unused, + struct _citrus_mapper * __restrict cm, const char * __restrict dir __unused, + const void * __restrict var __unused, size_t lenvar __unused, + struct _citrus_mapper_traits * __restrict mt, size_t lenmt) +{ + + if (lenmt < sizeof(*mt)) + return (EINVAL); + + cm->cm_closure = NULL; + mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */ + mt->mt_state_size = 0; /* stateless */ + + return (0); +} + +static void +/*ARGSUSED*/ +_citrus_mapper_none_mapper_uninit(struct _citrus_mapper *cm __unused) +{ + +} + +static int +/*ARGSUSED*/ +_citrus_mapper_none_mapper_convert(struct _citrus_mapper * __restrict cm __unused, + _citrus_index_t * __restrict dst, _citrus_index_t src, + void * __restrict ps __unused) +{ + + *dst = src; + return (_CITRUS_MAPPER_CONVERT_SUCCESS); +} + +static void +/*ARGSUSED*/ +_citrus_mapper_none_mapper_init_state(void) +{ + +} diff --git a/lib/libiconv_modules/mapper_none/citrus_mapper_none.h b/lib/libiconv_modules/mapper_none/citrus_mapper_none.h new file mode 100644 index 000000000000..9b4e07d5cb58 --- /dev/null +++ b/lib/libiconv_modules/mapper_none/citrus_mapper_none.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_mapper_none.h,v 1.1 2003/06/25 09:51:45 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_MAPPER_NONE_H_ +#define _CITRUS_MAPPER_NONE_H_ + +__BEGIN_DECLS +_CITRUS_MAPPER_GETOPS_FUNC(mapper_none); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/mapper_parallel/Makefile b/lib/libiconv_modules/mapper_parallel/Makefile new file mode 100644 index 000000000000..000c1cdd6997 --- /dev/null +++ b/lib/libiconv_modules/mapper_parallel/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../mapper_serial + +SHLIB= mapper_parallel +SRCS+= citrus_mapper_serial.c +CFLAGS+= --param max-inline-insns-single=32 + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/mapper_serial/Makefile b/lib/libiconv_modules/mapper_serial/Makefile new file mode 100644 index 000000000000..67d4bb0cbfbf --- /dev/null +++ b/lib/libiconv_modules/mapper_serial/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +SHLIB= mapper_serial +SRCS+= citrus_mapper_serial.c +CFLAGS+= --param max-inline-insns-single=32 + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/mapper_serial/citrus_mapper_serial.c b/lib/libiconv_modules/mapper_serial/citrus_mapper_serial.c new file mode 100644 index 000000000000..87f362a7ef8f --- /dev/null +++ b/lib/libiconv_modules/mapper_serial/citrus_mapper_serial.c @@ -0,0 +1,246 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_mapper_serial.c,v 1.2 2003/07/12 15:39:20 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * 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. + */ + +#include <sys/cdefs.h> +#include <sys/queue.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_module.h" +#include "citrus_region.h" +#include "citrus_memstream.h" +#include "citrus_mmap.h" +#include "citrus_hash.h" +#include "citrus_mapper.h" +#include "citrus_mapper_serial.h" + +/* ---------------------------------------------------------------------- */ + +_CITRUS_MAPPER_DECLS(mapper_serial); +_CITRUS_MAPPER_DEF_OPS(mapper_serial); + +#define _citrus_mapper_parallel_mapper_init \ + _citrus_mapper_serial_mapper_init +#define _citrus_mapper_parallel_mapper_uninit \ + _citrus_mapper_serial_mapper_uninit +#define _citrus_mapper_parallel_mapper_init_state \ + _citrus_mapper_serial_mapper_init_state +static int _citrus_mapper_parallel_mapper_convert( + struct _citrus_mapper * __restrict, _index_t * __restrict, + _index_t, void * __restrict); +_CITRUS_MAPPER_DEF_OPS(mapper_parallel); +#undef _citrus_mapper_parallel_mapper_init +#undef _citrus_mapper_parallel_mapper_uninit +#undef _citrus_mapper_parallel_mapper_init_state + + +/* ---------------------------------------------------------------------- */ + +struct maplink { + STAILQ_ENTRY(maplink) ml_entry; + struct _mapper *ml_mapper; +}; +STAILQ_HEAD(maplist, maplink); + +struct _citrus_mapper_serial { + struct maplist sr_mappers; +}; + +int +_citrus_mapper_serial_mapper_getops(struct _citrus_mapper_ops *ops) +{ + + memcpy(ops, &_citrus_mapper_serial_mapper_ops, + sizeof(_citrus_mapper_serial_mapper_ops)); + + return (0); +} + +int +_citrus_mapper_parallel_mapper_getops(struct _citrus_mapper_ops *ops) +{ + + memcpy(ops, &_citrus_mapper_parallel_mapper_ops, + sizeof(_citrus_mapper_parallel_mapper_ops)); + + return (0); +} + +static void +uninit(struct _citrus_mapper_serial *sr) +{ + struct maplink *ml; + + while ((ml = STAILQ_FIRST(&sr->sr_mappers)) != NULL) { + STAILQ_REMOVE_HEAD(&sr->sr_mappers, ml_entry); + _mapper_close(ml->ml_mapper); + free(ml); + } +} + +static int +parse_var(struct _citrus_mapper_area *__restrict ma, + struct _citrus_mapper_serial *sr, struct _memstream *ms) +{ + struct _region r; + struct maplink *ml; + char mapname[PATH_MAX]; + int ret; + + STAILQ_INIT(&sr->sr_mappers); + while (1) { + /* remove beginning white spaces */ + _memstream_skip_ws(ms); + if (_memstream_iseof(ms)) + break; + /* cut down a mapper name */ + _memstream_chr(ms, &r, ','); + snprintf(mapname, sizeof(mapname), "%.*s", + (int)_region_size(&r), (char *)_region_head(&r)); + /* remove trailing white spaces */ + mapname[_bcs_skip_nonws(mapname)-mapname] = '\0'; + /* create a new mapper record */ + ml = malloc(sizeof(*ml)); + if (ml == NULL) + return (errno); + ret = _mapper_open(ma, &ml->ml_mapper, mapname); + if (ret) { + free(ml); + return (ret); + } + /* support only 1:1 and stateless converter */ + if (_mapper_get_src_max(ml->ml_mapper) != 1 || + _mapper_get_dst_max(ml->ml_mapper) != 1 || + _mapper_get_state_size(ml->ml_mapper) != 0) { + free(ml); + return (EINVAL); + } + STAILQ_INSERT_TAIL(&sr->sr_mappers, ml, ml_entry); + } + return (0); +} + +static int +/*ARGSUSED*/ +_citrus_mapper_serial_mapper_init(struct _citrus_mapper_area *__restrict ma __unused, + struct _citrus_mapper * __restrict cm, const char * __restrict dir __unused, + const void * __restrict var, size_t lenvar, + struct _citrus_mapper_traits * __restrict mt, size_t lenmt) +{ + struct _citrus_mapper_serial *sr; + struct _memstream ms; + struct _region r; + + if (lenmt < sizeof(*mt)) + return (EINVAL); + + sr = malloc(sizeof(*sr)); + if (sr == NULL) + return (errno); + + _region_init(&r, __DECONST(void *, var), lenvar); + _memstream_bind(&ms, &r); + if (parse_var(ma, sr, &ms)) { + uninit(sr); + free(sr); + return (EINVAL); + } + cm->cm_closure = sr; + mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */ + mt->mt_state_size = 0; /* stateless */ + + return (0); +} + +static void +/*ARGSUSED*/ +_citrus_mapper_serial_mapper_uninit(struct _citrus_mapper *cm) +{ + + if (cm && cm->cm_closure) { + uninit(cm->cm_closure); + free(cm->cm_closure); + } +} + +static int +/*ARGSUSED*/ +_citrus_mapper_serial_mapper_convert(struct _citrus_mapper * __restrict cm, + _index_t * __restrict dst, _index_t src, void * __restrict ps __unused) +{ + struct _citrus_mapper_serial *sr; + struct maplink *ml; + int ret; + + sr = cm->cm_closure; + STAILQ_FOREACH(ml, &sr->sr_mappers, ml_entry) { + ret = _mapper_convert(ml->ml_mapper, &src, src, NULL); + if (ret != _MAPPER_CONVERT_SUCCESS) + return (ret); + } + *dst = src; + return (_MAPPER_CONVERT_SUCCESS); +} + +static int +/*ARGSUSED*/ +_citrus_mapper_parallel_mapper_convert(struct _citrus_mapper * __restrict cm, + _index_t * __restrict dst, _index_t src, void * __restrict ps __unused) +{ + struct _citrus_mapper_serial *sr; + struct maplink *ml; + _index_t tmp; + int ret; + + sr = cm->cm_closure; + STAILQ_FOREACH(ml, &sr->sr_mappers, ml_entry) { + ret = _mapper_convert(ml->ml_mapper, &tmp, src, NULL); + if (ret == _MAPPER_CONVERT_SUCCESS) { + *dst = tmp; + return (_MAPPER_CONVERT_SUCCESS); + } else if (ret == _MAPPER_CONVERT_ILSEQ) + return (_MAPPER_CONVERT_ILSEQ); + } + return (_MAPPER_CONVERT_NONIDENTICAL); +} + +static void +/*ARGSUSED*/ +_citrus_mapper_serial_mapper_init_state(void) +{ + +} diff --git a/lib/libiconv_modules/mapper_serial/citrus_mapper_serial.h b/lib/libiconv_modules/mapper_serial/citrus_mapper_serial.h new file mode 100644 index 000000000000..02cb9b1c8e50 --- /dev/null +++ b/lib/libiconv_modules/mapper_serial/citrus_mapper_serial.h @@ -0,0 +1,38 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_mapper_serial.h,v 1.1 2003/06/25 09:51:46 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_MAPPER_SERIAL_H_ +#define _CITRUS_MAPPER_SERIAL_H_ + +__BEGIN_DECLS +_CITRUS_MAPPER_GETOPS_FUNC(mapper_serial); +_CITRUS_MAPPER_GETOPS_FUNC(mapper_parallel); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/mapper_std/Makefile b/lib/libiconv_modules/mapper_std/Makefile new file mode 100644 index 000000000000..0d35e90d788e --- /dev/null +++ b/lib/libiconv_modules/mapper_std/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +SHLIB= mapper_std +SRCS+= citrus_mapper_std.c +CFLAGS+= --param max-inline-insns-single=8 + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/mapper_std/citrus_mapper_std.c b/lib/libiconv_modules/mapper_std/citrus_mapper_std.c new file mode 100644 index 000000000000..bc756435bb81 --- /dev/null +++ b/lib/libiconv_modules/mapper_std/citrus_mapper_std.c @@ -0,0 +1,435 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_mapper_std.c,v 1.8 2006/09/11 13:06:33 tnozaki Exp $ */ + +/*- + * Copyright (c)2003, 2006 Citrus Project, + * 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. + */ + +#include <sys/cdefs.h> +#include <sys/endian.h> +#include <sys/queue.h> + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_region.h" +#include "citrus_mmap.h" +#include "citrus_module.h" +#include "citrus_hash.h" +#include "citrus_mapper.h" +#include "citrus_db.h" +#include "citrus_db_hash.h" + +#include "citrus_mapper_std.h" +#include "citrus_mapper_std_file.h" + +/* ---------------------------------------------------------------------- */ + +_CITRUS_MAPPER_DECLS(mapper_std); +_CITRUS_MAPPER_DEF_OPS(mapper_std); + + +/* ---------------------------------------------------------------------- */ + +int +_citrus_mapper_std_mapper_getops(struct _citrus_mapper_ops *ops) +{ + + memcpy(ops, &_citrus_mapper_std_mapper_ops, + sizeof(_citrus_mapper_std_mapper_ops)); + + return (0); +} + +/* ---------------------------------------------------------------------- */ + +static int +/*ARGSUSED*/ +rowcol_convert(struct _citrus_mapper_std * __restrict ms, + _index_t * __restrict dst, _index_t src, void * __restrict ps __unused) +{ + struct _citrus_mapper_std_linear_zone *lz; + struct _citrus_mapper_std_rowcol *rc; + _index_t idx = 0, n; + size_t i; + uint32_t conv; + + /* ps may be unused */ + rc = &ms->ms_rowcol; + + for (i = rc->rc_src_rowcol_len * rc->rc_src_rowcol_bits, + lz = &rc->rc_src_rowcol[0]; i > 0; ++lz) { + i -= rc->rc_src_rowcol_bits; + n = (src >> i) & rc->rc_src_rowcol_mask; + if (n < lz->begin || n > lz->end) { + switch (rc->rc_oob_mode) { + case _CITRUS_MAPPER_STD_OOB_NONIDENTICAL: + *dst = rc->rc_dst_invalid; + return (_MAPPER_CONVERT_NONIDENTICAL); + case _CITRUS_MAPPER_STD_OOB_ILSEQ: + return (_MAPPER_CONVERT_ILSEQ); + default: + return (_MAPPER_CONVERT_FATAL); + } + } + idx = idx * lz->width + n - lz->begin; + } + switch (rc->rc_dst_unit_bits) { + case 8: + conv = _region_peek8(&rc->rc_table, idx); + break; + case 16: + conv = be16toh(_region_peek16(&rc->rc_table, idx*2)); + break; + case 32: + conv = be32toh(_region_peek32(&rc->rc_table, idx*4)); + break; + default: + return (_MAPPER_CONVERT_FATAL); + } + + if (conv == rc->rc_dst_invalid) { + *dst = rc->rc_dst_invalid; + return (_MAPPER_CONVERT_NONIDENTICAL); + } + if (conv == rc->rc_dst_ilseq) + return (_MAPPER_CONVERT_ILSEQ); + + *dst = conv; + + return (_MAPPER_CONVERT_SUCCESS); +} + +static __inline int +set_linear_zone(struct _citrus_mapper_std_linear_zone *lz, + uint32_t begin, uint32_t end) +{ + + if (begin > end) + return (EFTYPE); + + lz->begin = begin; + lz->end = end; + lz->width= end - begin + 1; + + return (0); +} + +static __inline int +rowcol_parse_variable_compat(struct _citrus_mapper_std_rowcol *rc, + struct _region *r) +{ + const struct _citrus_mapper_std_rowcol_info_compat_x *rcx; + struct _citrus_mapper_std_linear_zone *lz; + uint32_t m, n; + int ret; + + rcx = _region_head(r); + + rc->rc_dst_invalid = be32toh(rcx->rcx_dst_invalid); + rc->rc_dst_unit_bits = be32toh(rcx->rcx_dst_unit_bits); + m = be32toh(rcx->rcx_src_col_bits); + n = 1 << (m - 1); + n |= n - 1; + rc->rc_src_rowcol_bits = m; + rc->rc_src_rowcol_mask = n; + + rc->rc_src_rowcol = malloc(2 * + sizeof(*rc->rc_src_rowcol)); + if (rc->rc_src_rowcol == NULL) + return (ENOMEM); + lz = rc->rc_src_rowcol; + rc->rc_src_rowcol_len = 1; + m = be32toh(rcx->rcx_src_row_begin); + n = be32toh(rcx->rcx_src_row_end); + if (m + n > 0) { + ret = set_linear_zone(lz, m, n); + if (ret != 0) + return (ret); + ++rc->rc_src_rowcol_len, ++lz; + } + m = be32toh(rcx->rcx_src_col_begin); + n = be32toh(rcx->rcx_src_col_end); + + return (set_linear_zone(lz, m, n)); +} + +static __inline int +rowcol_parse_variable(struct _citrus_mapper_std_rowcol *rc, + struct _region *r) +{ + const struct _citrus_mapper_std_rowcol_info_x *rcx; + struct _citrus_mapper_std_linear_zone *lz; + size_t i; + uint32_t m, n; + int ret; + + rcx = _region_head(r); + + rc->rc_dst_invalid = be32toh(rcx->rcx_dst_invalid); + rc->rc_dst_unit_bits = be32toh(rcx->rcx_dst_unit_bits); + + m = be32toh(rcx->rcx_src_rowcol_bits); + n = 1 << (m - 1); + n |= n - 1; + rc->rc_src_rowcol_bits = m; + rc->rc_src_rowcol_mask = n; + + rc->rc_src_rowcol_len = be32toh(rcx->rcx_src_rowcol_len); + if (rc->rc_src_rowcol_len > _CITRUS_MAPPER_STD_ROWCOL_MAX) + return (EFTYPE); + rc->rc_src_rowcol = malloc(rc->rc_src_rowcol_len * + sizeof(*rc->rc_src_rowcol)); + if (rc->rc_src_rowcol == NULL) + return (ENOMEM); + for (i = 0, lz = rc->rc_src_rowcol; + i < rc->rc_src_rowcol_len; ++i, ++lz) { + m = be32toh(rcx->rcx_src_rowcol[i].begin), + n = be32toh(rcx->rcx_src_rowcol[i].end); + ret = set_linear_zone(lz, m, n); + if (ret != 0) { + free(rc->rc_src_rowcol); + rc->rc_src_rowcol = NULL; + return (ret); + } + } + return (0); +} + +static void +rowcol_uninit(struct _citrus_mapper_std *ms) +{ + struct _citrus_mapper_std_rowcol *rc; + + rc = &ms->ms_rowcol; + free(rc->rc_src_rowcol); +} + +static int +rowcol_init(struct _citrus_mapper_std *ms) +{ + struct _citrus_mapper_std_linear_zone *lz; + struct _citrus_mapper_std_rowcol *rc; + const struct _citrus_mapper_std_rowcol_ext_ilseq_info_x *eix; + struct _region r; + uint64_t table_size; + size_t i; + int ret; + + ms->ms_convert = &rowcol_convert; + ms->ms_uninit = &rowcol_uninit; + rc = &ms->ms_rowcol; + + /* get table region */ + ret = _db_lookup_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_TABLE, + &rc->rc_table, NULL); + if (ret) { + if (ret == ENOENT) + ret = EFTYPE; + return (ret); + } + + /* get table information */ + ret = _db_lookup_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_INFO, &r, NULL); + if (ret) { + if (ret == ENOENT) + ret = EFTYPE; + return (ret); + } + switch (_region_size(&r)) { + case _CITRUS_MAPPER_STD_ROWCOL_INFO_COMPAT_SIZE: + ret = rowcol_parse_variable_compat(rc, &r); + break; + case _CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE: + ret = rowcol_parse_variable(rc, &r); + break; + default: + return (EFTYPE); + } + if (ret != 0) + return (ret); + /* sanity check */ + switch (rc->rc_src_rowcol_bits) { + case 8: case 16: case 32: + if (rc->rc_src_rowcol_len <= 32 / rc->rc_src_rowcol_bits) + break; + /*FALLTHROUGH*/ + default: + return (EFTYPE); + } + + /* ilseq extension */ + rc->rc_oob_mode = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL; + rc->rc_dst_ilseq = rc->rc_dst_invalid; + ret = _db_lookup_by_s(ms->ms_db, + _CITRUS_MAPPER_STD_SYM_ROWCOL_EXT_ILSEQ, &r, NULL); + if (ret && ret != ENOENT) + return (ret); + if (_region_size(&r) < sizeof(*eix)) + return (EFTYPE); + if (ret == 0) { + eix = _region_head(&r); + rc->rc_oob_mode = be32toh(eix->eix_oob_mode); + rc->rc_dst_ilseq = be32toh(eix->eix_dst_ilseq); + } + + /* calcurate expected table size */ + i = rc->rc_src_rowcol_len; + lz = &rc->rc_src_rowcol[--i]; + table_size = lz->width; + while (i > 0) { + lz = &rc->rc_src_rowcol[--i]; + table_size *= lz->width; + } + table_size *= rc->rc_dst_unit_bits/8; + + if (table_size > UINT32_MAX || + _region_size(&rc->rc_table) < table_size) + return (EFTYPE); + + return (0); +} + +typedef int (*initfunc_t)(struct _citrus_mapper_std *); +static const struct { + initfunc_t t_init; + const char *t_name; +} types[] = { + { &rowcol_init, _CITRUS_MAPPER_STD_TYPE_ROWCOL }, +}; +#define NUM_OF_TYPES ((int)(sizeof(types)/sizeof(types[0]))) + +static int +/*ARGSUSED*/ +_citrus_mapper_std_mapper_init(struct _citrus_mapper_area *__restrict ma __unused, + struct _citrus_mapper * __restrict cm, const char * __restrict curdir, + const void * __restrict var, size_t lenvar, + struct _citrus_mapper_traits * __restrict mt, size_t lenmt) +{ + struct _citrus_mapper_std *ms; + char path[PATH_MAX]; + const char *type; + int id, ret; + + /* set traits */ + if (lenmt < sizeof(*mt)) { + ret = EINVAL; + goto err0; + } + mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */ + mt->mt_state_size = 0; /* stateless */ + + /* alloc mapper std structure */ + ms = malloc(sizeof(*ms)); + if (ms == NULL) { + ret = errno; + goto err0; + } + + /* open mapper file */ + snprintf(path, sizeof(path), "%s/%.*s", curdir, (int)lenvar, + (const char *)var); + ret = _map_file(&ms->ms_file, path); + if (ret) + goto err1; + + ret = _db_open(&ms->ms_db, &ms->ms_file, _CITRUS_MAPPER_STD_MAGIC, + &_db_hash_std, NULL); + if (ret) + goto err2; + + /* get mapper type */ + ret = _db_lookupstr_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_TYPE, + &type, NULL); + if (ret) { + if (ret == ENOENT) + ret = EFTYPE; + goto err3; + } + for (id = 0; id < NUM_OF_TYPES; id++) + if (_bcs_strcasecmp(type, types[id].t_name) == 0) + break; + + if (id == NUM_OF_TYPES) + goto err3; + + /* init the per-type structure */ + ret = (*types[id].t_init)(ms); + if (ret) + goto err3; + + cm->cm_closure = ms; + + return (0); + +err3: + _db_close(ms->ms_db); +err2: + _unmap_file(&ms->ms_file); +err1: + free(ms); +err0: + return (ret); +} + +static void +/*ARGSUSED*/ +_citrus_mapper_std_mapper_uninit(struct _citrus_mapper *cm) +{ + struct _citrus_mapper_std *ms; + + ms = cm->cm_closure; + if (ms->ms_uninit) + (*ms->ms_uninit)(ms); + _db_close(ms->ms_db); + _unmap_file(&ms->ms_file); + free(ms); +} + +static void +/*ARGSUSED*/ +_citrus_mapper_std_mapper_init_state(void) +{ + +} + +static int +/*ARGSUSED*/ +_citrus_mapper_std_mapper_convert(struct _citrus_mapper * __restrict cm, + _index_t * __restrict dst, _index_t src, void * __restrict ps) +{ + struct _citrus_mapper_std *ms; + + ms = cm->cm_closure; + return ((*ms->ms_convert)(ms, dst, src, ps)); +} diff --git a/lib/libiconv_modules/mapper_std/citrus_mapper_std.h b/lib/libiconv_modules/mapper_std/citrus_mapper_std.h new file mode 100644 index 000000000000..d6a0b62d3f58 --- /dev/null +++ b/lib/libiconv_modules/mapper_std/citrus_mapper_std.h @@ -0,0 +1,39 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_mapper_std.h,v 1.1 2003/06/25 09:51:47 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_MAPPER_STD_H_ +#define _CITRUS_MAPPER_STD_H_ + +#include "citrus_mapper_std_local.h" + +__BEGIN_DECLS +_CITRUS_MAPPER_GETOPS_FUNC(mapper_std); +__END_DECLS + +#endif diff --git a/lib/libiconv_modules/mapper_std/citrus_mapper_std_file.h b/lib/libiconv_modules/mapper_std/citrus_mapper_std_file.h new file mode 100644 index 000000000000..d433c74eb3a1 --- /dev/null +++ b/lib/libiconv_modules/mapper_std/citrus_mapper_std_file.h @@ -0,0 +1,76 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_mapper_std_file.h,v 1.3 2006/09/09 14:35:17 tnozaki Exp $ */ + +/*- + * Copyright (c)2003, 2006 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_MAPPER_STD_FILE_H_ +#define _CITRUS_MAPPER_STD_FILE_H_ + +#define _CITRUS_MAPPER_STD_MAGIC "MAPPER\0\0" + +#define _CITRUS_MAPPER_STD_SYM_TYPE "type" +#define _CITRUS_MAPPER_STD_SYM_INFO "info" +#define _CITRUS_MAPPER_STD_SYM_TABLE "table" + +#define _CITRUS_MAPPER_STD_TYPE_ROWCOL "rowcol" +struct _citrus_mapper_std_rowcol_info_x { + uint32_t rcx_src_rowcol_bits; + uint32_t rcx_dst_invalid; +#define _CITRUS_MAPPER_STD_ROWCOL_MAX 4 + struct { + uint32_t begin; + uint32_t end; + } __packed rcx_src_rowcol[_CITRUS_MAPPER_STD_ROWCOL_MAX]; + uint32_t rcx_dst_unit_bits; + uint32_t rcx_src_rowcol_len; +} __packed; +#define _CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE 48 + +/* old file layout */ +struct _citrus_mapper_std_rowcol_info_compat_x { + uint32_t rcx_src_col_bits; + uint32_t rcx_dst_invalid; + uint32_t rcx_src_row_begin; + uint32_t rcx_src_row_end; + uint32_t rcx_src_col_begin; + uint32_t rcx_src_col_end; + uint32_t rcx_dst_unit_bits; + uint32_t rcx_pad; +} __packed; +#define _CITRUS_MAPPER_STD_ROWCOL_INFO_COMPAT_SIZE 32 + +/* rowcol oob extension info */ +#define _CITRUS_MAPPER_STD_SYM_ROWCOL_EXT_ILSEQ "rowcol_ext_ilseq" +struct _citrus_mapper_std_rowcol_ext_ilseq_info_x { +#define _CITRUS_MAPPER_STD_OOB_NONIDENTICAL 0 +#define _CITRUS_MAPPER_STD_OOB_ILSEQ 1 + uint32_t eix_oob_mode; + uint32_t eix_dst_ilseq; +} __packed; +#define _CITRUS_MAPPER_STD_ROWCOL_EXT_ILSEQ_SIZE 8 + +#endif diff --git a/lib/libiconv_modules/mapper_std/citrus_mapper_std_local.h b/lib/libiconv_modules/mapper_std/citrus_mapper_std_local.h new file mode 100644 index 000000000000..f76f606a2d52 --- /dev/null +++ b/lib/libiconv_modules/mapper_std/citrus_mapper_std_local.h @@ -0,0 +1,71 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_mapper_std_local.h,v 1.3 2006/09/09 14:35:17 tnozaki Exp $ */ + +/*- + * Copyright (c)2003, 2006 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_MAPPER_STD_LOCAL_H_ +#define _CITRUS_MAPPER_STD_LOCAL_H_ + +typedef uint32_t (*_citrus_mapper_std_getvalfunc_t)(const void *, uint32_t); + +struct _citrus_mapper_std_linear_zone { + _citrus_index_t begin; + _citrus_index_t end; + _citrus_index_t width; +}; +struct _citrus_mapper_std_rowcol { + struct _citrus_region rc_table; + size_t rc_src_rowcol_len; + struct _citrus_mapper_std_linear_zone + *rc_src_rowcol; + _citrus_index_t rc_src_rowcol_bits; + _citrus_index_t rc_src_rowcol_mask; + _citrus_index_t rc_dst_invalid; + _citrus_index_t rc_dst_unit_bits; + int rc_oob_mode; + _citrus_index_t rc_dst_ilseq; +}; + +struct _citrus_mapper_std; + +typedef int (*_citrus_mapper_std_convert_t)( + struct _citrus_mapper_std *__restrict, + _index_t *__restrict, _index_t, void *__restrict); +typedef void (*_citrus_mapper_std_uninit_t)(struct _citrus_mapper_std *); + +struct _citrus_mapper_std { + struct _citrus_region ms_file; + struct _citrus_db *ms_db; + _citrus_mapper_std_convert_t ms_convert; + _citrus_mapper_std_uninit_t ms_uninit; + union { + struct _citrus_mapper_std_rowcol rowcol; + } u; +#define ms_rowcol u.rowcol +}; + +#endif diff --git a/lib/libiconv_modules/mapper_zone/Makefile b/lib/libiconv_modules/mapper_zone/Makefile new file mode 100644 index 000000000000..287bc24e0072 --- /dev/null +++ b/lib/libiconv_modules/mapper_zone/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +SHLIB= mapper_zone +SRCS+= citrus_mapper_zone.c +CFLAGS+= --param max-inline-insns-single=8 + +.include <bsd.lib.mk> diff --git a/lib/libiconv_modules/mapper_zone/citrus_mapper_zone.c b/lib/libiconv_modules/mapper_zone/citrus_mapper_zone.c new file mode 100644 index 000000000000..f1117f423af4 --- /dev/null +++ b/lib/libiconv_modules/mapper_zone/citrus_mapper_zone.c @@ -0,0 +1,385 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_mapper_zone.c,v 1.4 2003/07/12 15:39:21 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * 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. + */ + +#include <sys/cdefs.h> +#include <sys/queue.h> + +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "citrus_namespace.h" +#include "citrus_types.h" +#include "citrus_bcs.h" +#include "citrus_module.h" +#include "citrus_region.h" +#include "citrus_memstream.h" +#include "citrus_mmap.h" +#include "citrus_hash.h" +#include "citrus_mapper.h" +#include "citrus_mapper_zone.h" + +/* ---------------------------------------------------------------------- */ + +_CITRUS_MAPPER_DECLS(mapper_zone); +_CITRUS_MAPPER_DEF_OPS(mapper_zone); + + +/* ---------------------------------------------------------------------- */ + +struct _zone { + uint32_t z_begin; + uint32_t z_end; +}; + +struct _citrus_mapper_zone { + struct _zone mz_col; + struct _zone mz_row; + int32_t mz_col_offset; + int32_t mz_row_offset; + int mz_col_bits; +}; + +struct _parse_state { + enum { S_BEGIN, S_OFFSET } ps_state; + union { + uint32_t u_imm; + int32_t s_imm; + struct _zone zone; + } u; +#define ps_u_imm u.u_imm +#define ps_s_imm u.s_imm +#define ps_zone u.zone + int ps_top; +}; + +int +_citrus_mapper_zone_mapper_getops(struct _citrus_mapper_ops *ops) +{ + + memcpy(ops, &_citrus_mapper_zone_mapper_ops, + sizeof(_citrus_mapper_zone_mapper_ops)); + + return (0); +} + +#define BUFSIZE 20 +#define T_ERR 0x100 +#define T_IMM 0x101 + +static int +get_imm(struct _memstream *ms, struct _parse_state *ps) +{ + int c, i, sign = 0; + char buf[BUFSIZE + 1]; + char *p; + + for (i = 0; i < BUFSIZE; i++) { +retry: + c = _memstream_peek(ms); + if (i == 0) { + if (sign == 0 && (c == '+' || c == '-')) { + sign = c; + _memstream_getc(ms); + goto retry; + } else if (!_bcs_isdigit(c)) + break; + } else if (!_bcs_isxdigit(c)) + if (!(i == 1 && c == 'x')) + break; + buf[i] = _memstream_getc(ms); + } + buf[i] = '\0'; + ps->ps_u_imm = strtoul(buf, &p, 0); + if ((p - buf) != i) + return (T_ERR); + if (sign == '-') + ps->ps_u_imm = (unsigned long)-(long)ps->ps_u_imm; + return (T_IMM); +} + +static int +get_tok(struct _memstream *ms, struct _parse_state *ps) +{ + int c; + +loop: + c = _memstream_peek(ms); + if (c == 0x00) + return (EOF); + if (_bcs_isspace(c)) { + _memstream_getc(ms); + goto loop; + } + + switch (ps->ps_state) { + case S_BEGIN: + switch (c) { + case ':': + case '-': + case '/': + _memstream_getc(ms); + return (c); + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return (get_imm(ms, ps)); + } + break; + case S_OFFSET: + switch (c) { + case '/': + _memstream_getc(ms); + return (c); + case '+': + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return (get_imm(ms, ps)); + } + break; + } + return (T_ERR); +} + +static int +parse_zone(struct _memstream *ms, struct _parse_state *ps, struct _zone *z) +{ + + if (get_tok(ms, ps) != T_IMM) + return (-1); + z->z_begin = ps->ps_u_imm; + if (get_tok(ms, ps) != '-') + return (-1); + if (get_tok(ms, ps) != T_IMM) + return (-1); + z->z_end = ps->ps_u_imm; + + if (z->z_begin > z->z_end) + return (-1); + + return (0); +} + +static int +check_rowcol(struct _zone *z, int32_t ofs, uint32_t maxval) +{ + uint32_t remain; + + if (maxval != 0 && z->z_end >= maxval) + return (-1); + + if (ofs > 0) { + if (maxval == 0) + /* this should 0x100000000 - z->z_end */ + remain = (z->z_end == 0) ? 0xFFFFFFFF : + 0xFFFFFFFF - z->z_end + 1; + else + remain = maxval - z->z_end; + if ((uint32_t)ofs > remain) + return (-1); + } else if (ofs < 0) { + if (z->z_begin < (uint32_t)-ofs) + return (-1); + } + + return (0); +} + +static int +parse_var(struct _citrus_mapper_zone *mz, struct _memstream *ms) +{ + struct _parse_state ps; + uint32_t colmax, rowmax; + int isrc, ret; + + ps.ps_state = S_BEGIN; + + if (parse_zone(ms, &ps, &mz->mz_col)) + return (-1); + + ret = get_tok(ms, &ps); + if (ret == '/') { + /* rowzone / colzone / bits */ + isrc = 1; + mz->mz_row = mz->mz_col; + + if (parse_zone(ms, &ps, &mz->mz_col)) + return (-1); + if (get_tok(ms, &ps) != '/') + return (-1); + if (get_tok(ms, &ps) != T_IMM) + return (-1); + mz->mz_col_bits = ps.ps_u_imm; + if (mz->mz_col_bits < 0 || mz->mz_col_bits > 32) + return (-1); + ret = get_tok(ms, &ps); + } else { + /* colzone */ + isrc = 0; + mz->mz_col_bits = 32; + mz->mz_row.z_begin = mz->mz_row.z_end = 0; + } + if (ret == ':') { + /* offset */ + ps.ps_state = S_OFFSET; + if (get_tok(ms, &ps) != T_IMM) + return (-1); + mz->mz_col_offset = ps.ps_s_imm; + if (isrc) { + /* row/col */ + mz->mz_row_offset = mz->mz_col_offset; + if (get_tok(ms, &ps) != '/') + return (-1); + if (get_tok(ms, &ps) != T_IMM) + return (-1); + mz->mz_col_offset = ps.ps_s_imm; + } else + mz->mz_row_offset = 0; + ret = get_tok(ms, &ps); + } + if (ret != EOF) + return (-1); + + /* sanity check */ + colmax = (mz->mz_col_bits == 32) ? 0 : 1 << mz->mz_col_bits; + rowmax = (mz->mz_col_bits == 0) ? 0 : 1 << (32-mz->mz_col_bits); + if (check_rowcol(&mz->mz_col, mz->mz_col_offset, colmax)) + return (-1); + if (check_rowcol(&mz->mz_row, mz->mz_row_offset, rowmax)) + return (-1); + + return (0); +} + +static int +/*ARGSUSED*/ +_citrus_mapper_zone_mapper_init(struct _citrus_mapper_area *__restrict ma __unused, + struct _citrus_mapper * __restrict cm, const char * __restrict dir __unused, + const void * __restrict var, size_t lenvar, + struct _citrus_mapper_traits * __restrict mt, size_t lenmt) +{ + struct _citrus_mapper_zone *mz; + struct _memstream ms; + struct _region r; + + if (lenmt < sizeof(*mt)) + return (EINVAL); + + mz = malloc(sizeof(*mz)); + if (mz == NULL) + return (errno); + + mz->mz_col.z_begin = mz->mz_col.z_end = 0; + mz->mz_row.z_begin = mz->mz_row.z_end = 0; + mz->mz_col_bits = 0; + mz->mz_row_offset = 0; + mz->mz_col_offset = 0; + + _region_init(&r, __DECONST(void *, var), lenvar); + _memstream_bind(&ms, &r); + if (parse_var(mz, &ms)) { + free(mz); + return (EINVAL); + } + cm->cm_closure = mz; + mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */ + mt->mt_state_size = 0; /* stateless */ + + return (0); +} + +static void +/*ARGSUSED*/ +_citrus_mapper_zone_mapper_uninit(struct _citrus_mapper *cm __unused) +{ + +} + +static int +/*ARGSUSED*/ +_citrus_mapper_zone_mapper_convert(struct _citrus_mapper * __restrict cm, + _citrus_index_t * __restrict dst, _citrus_index_t src, + void * __restrict ps __unused) +{ + struct _citrus_mapper_zone *mz = cm->cm_closure; + uint32_t col, row; + + if (mz->mz_col_bits == 32) { + col = src; + row = 0; + if (col < mz->mz_col.z_begin || col > mz->mz_col.z_end) + return (_CITRUS_MAPPER_CONVERT_NONIDENTICAL); + if (mz->mz_col_offset > 0) + col += (uint32_t)mz->mz_col_offset; + else + col -= (uint32_t)-mz->mz_col_offset; + *dst = col; + } else { + col = src & (((uint32_t)1 << mz->mz_col_bits) - 1); + row = src >> mz->mz_col_bits; + if (row < mz->mz_row.z_begin || row > mz->mz_row.z_end || + col < mz->mz_col.z_begin || col > mz->mz_col.z_end) + return (_CITRUS_MAPPER_CONVERT_NONIDENTICAL); + if (mz->mz_col_offset > 0) + col += (uint32_t)mz->mz_col_offset; + else + col -= (uint32_t)-mz->mz_col_offset; + if (mz->mz_row_offset > 0) + row += (uint32_t)mz->mz_row_offset; + else + row -= (uint32_t)-mz->mz_row_offset; + *dst = col | (row << mz->mz_col_bits); + } + return (_CITRUS_MAPPER_CONVERT_SUCCESS); +} + +static void +/*ARGSUSED*/ +_citrus_mapper_zone_mapper_init_state(void) +{ + +} diff --git a/lib/libiconv_modules/mapper_zone/citrus_mapper_zone.h b/lib/libiconv_modules/mapper_zone/citrus_mapper_zone.h new file mode 100644 index 000000000000..590cee6bb26b --- /dev/null +++ b/lib/libiconv_modules/mapper_zone/citrus_mapper_zone.h @@ -0,0 +1,37 @@ +/* $FreeBSD$ */ +/* $NetBSD: citrus_mapper_zone.h,v 1.1 2003/06/25 09:51:48 tshiozak Exp $ */ + +/*- + * Copyright (c)2003 Citrus Project, + * 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. + */ + +#ifndef _CITRUS_MAPPER_ZONE_H_ +#define _CITRUS_MAPPER_ZONE_H_ + +__BEGIN_DECLS +_CITRUS_MAPPER_GETOPS_FUNC(mapper_zone); +__END_DECLS + +#endif |