xref: /minix3/lib/libc/citrus/modules/citrus_gbk2k.c (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
1*84d9c625SLionel Sambuc /* $NetBSD: citrus_gbk2k.c,v 1.8 2013/05/28 16:57:56 joerg Exp $ */
22fe8fb19SBen Gras 
32fe8fb19SBen Gras /*-
42fe8fb19SBen Gras  * Copyright (c)2003 Citrus Project,
52fe8fb19SBen Gras  * All rights reserved.
62fe8fb19SBen Gras  *
72fe8fb19SBen Gras  * Redistribution and use in source and binary forms, with or without
82fe8fb19SBen Gras  * modification, are permitted provided that the following conditions
92fe8fb19SBen Gras  * are met:
102fe8fb19SBen Gras  * 1. Redistributions of source code must retain the above copyright
112fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer.
122fe8fb19SBen Gras  * 2. Redistributions in binary form must reproduce the above copyright
132fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer in the
142fe8fb19SBen Gras  *    documentation and/or other materials provided with the distribution.
152fe8fb19SBen Gras  *
162fe8fb19SBen Gras  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
172fe8fb19SBen Gras  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
182fe8fb19SBen Gras  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
192fe8fb19SBen Gras  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
202fe8fb19SBen Gras  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
212fe8fb19SBen Gras  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
222fe8fb19SBen Gras  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
232fe8fb19SBen Gras  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
242fe8fb19SBen Gras  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
252fe8fb19SBen Gras  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
262fe8fb19SBen Gras  * SUCH DAMAGE.
272fe8fb19SBen Gras  */
282fe8fb19SBen Gras 
292fe8fb19SBen Gras #include <sys/cdefs.h>
302fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
31*84d9c625SLionel Sambuc __RCSID("$NetBSD: citrus_gbk2k.c,v 1.8 2013/05/28 16:57:56 joerg Exp $");
322fe8fb19SBen Gras #endif /* LIBC_SCCS and not lint */
332fe8fb19SBen Gras 
342fe8fb19SBen Gras #include <assert.h>
352fe8fb19SBen Gras #include <errno.h>
362fe8fb19SBen Gras #include <string.h>
372fe8fb19SBen Gras #include <stdio.h>
382fe8fb19SBen Gras #include <stdlib.h>
392fe8fb19SBen Gras #include <stddef.h>
402fe8fb19SBen Gras #include <wchar.h>
412fe8fb19SBen Gras #include <sys/types.h>
422fe8fb19SBen Gras #include <limits.h>
432fe8fb19SBen Gras 
442fe8fb19SBen Gras #include "citrus_namespace.h"
452fe8fb19SBen Gras #include "citrus_types.h"
462fe8fb19SBen Gras #include "citrus_bcs.h"
472fe8fb19SBen Gras #include "citrus_module.h"
482fe8fb19SBen Gras #include "citrus_ctype.h"
492fe8fb19SBen Gras #include "citrus_stdenc.h"
502fe8fb19SBen Gras #include "citrus_gbk2k.h"
512fe8fb19SBen Gras 
522fe8fb19SBen Gras 
532fe8fb19SBen Gras /* ----------------------------------------------------------------------
542fe8fb19SBen Gras  * private stuffs used by templates
552fe8fb19SBen Gras  */
562fe8fb19SBen Gras 
572fe8fb19SBen Gras typedef struct _GBK2KState {
582fe8fb19SBen Gras 	char ch[4];
592fe8fb19SBen Gras 	int chlen;
602fe8fb19SBen Gras } _GBK2KState;
612fe8fb19SBen Gras 
622fe8fb19SBen Gras typedef struct {
632fe8fb19SBen Gras 	int mb_cur_max;
642fe8fb19SBen Gras } _GBK2KEncodingInfo;
652fe8fb19SBen Gras 
662fe8fb19SBen Gras typedef struct {
672fe8fb19SBen Gras 	_GBK2KEncodingInfo	ei;
682fe8fb19SBen Gras 	struct {
692fe8fb19SBen Gras 		/* for future multi-locale facility */
702fe8fb19SBen Gras 		_GBK2KState	s_mblen;
712fe8fb19SBen Gras 		_GBK2KState	s_mbrlen;
722fe8fb19SBen Gras 		_GBK2KState	s_mbrtowc;
732fe8fb19SBen Gras 		_GBK2KState	s_mbtowc;
742fe8fb19SBen Gras 		_GBK2KState	s_mbsrtowcs;
75*84d9c625SLionel Sambuc 		_GBK2KState	s_mbsnrtowcs;
762fe8fb19SBen Gras 		_GBK2KState	s_wcrtomb;
772fe8fb19SBen Gras 		_GBK2KState	s_wcsrtombs;
78*84d9c625SLionel Sambuc 		_GBK2KState	s_wcsnrtombs;
792fe8fb19SBen Gras 		_GBK2KState	s_wctomb;
802fe8fb19SBen Gras 	} states;
812fe8fb19SBen Gras } _GBK2KCTypeInfo;
822fe8fb19SBen Gras 
832fe8fb19SBen Gras #define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
842fe8fb19SBen Gras #define _CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.s_##_func_
852fe8fb19SBen Gras 
862fe8fb19SBen Gras #define _FUNCNAME(m)			_citrus_GBK2K_##m
872fe8fb19SBen Gras #define _ENCODING_INFO			_GBK2KEncodingInfo
882fe8fb19SBen Gras #define _CTYPE_INFO			_GBK2KCTypeInfo
892fe8fb19SBen Gras #define _ENCODING_STATE			_GBK2KState
902fe8fb19SBen Gras #define _ENCODING_MB_CUR_MAX(_ei_)	(_ei_)->mb_cur_max
912fe8fb19SBen Gras #define _ENCODING_IS_STATE_DEPENDENT	0
922fe8fb19SBen Gras #define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	0
932fe8fb19SBen Gras 
942fe8fb19SBen Gras static __inline void
952fe8fb19SBen Gras /*ARGSUSED*/
_citrus_GBK2K_init_state(_GBK2KEncodingInfo * __restrict ei,_GBK2KState * __restrict s)962fe8fb19SBen Gras _citrus_GBK2K_init_state(_GBK2KEncodingInfo * __restrict ei,
972fe8fb19SBen Gras 			 _GBK2KState * __restrict s)
982fe8fb19SBen Gras {
992fe8fb19SBen Gras 	memset(s, 0, sizeof(*s));
1002fe8fb19SBen Gras }
1012fe8fb19SBen Gras 
1022fe8fb19SBen Gras static __inline void
1032fe8fb19SBen Gras /*ARGSUSED*/
_citrus_GBK2K_pack_state(_GBK2KEncodingInfo * __restrict ei,void * __restrict pspriv,const _GBK2KState * __restrict s)1042fe8fb19SBen Gras _citrus_GBK2K_pack_state(_GBK2KEncodingInfo * __restrict ei,
1052fe8fb19SBen Gras 			 void * __restrict pspriv,
1062fe8fb19SBen Gras 			 const _GBK2KState * __restrict s)
1072fe8fb19SBen Gras {
1082fe8fb19SBen Gras 	memcpy(pspriv, (const void *)s, sizeof(*s));
1092fe8fb19SBen Gras }
1102fe8fb19SBen Gras 
1112fe8fb19SBen Gras static __inline void
1122fe8fb19SBen Gras /*ARGSUSED*/
_citrus_GBK2K_unpack_state(_GBK2KEncodingInfo * __restrict ei,_GBK2KState * __restrict s,const void * __restrict pspriv)1132fe8fb19SBen Gras _citrus_GBK2K_unpack_state(_GBK2KEncodingInfo * __restrict ei,
1142fe8fb19SBen Gras 			   _GBK2KState * __restrict s,
1152fe8fb19SBen Gras 			   const void * __restrict pspriv)
1162fe8fb19SBen Gras {
1172fe8fb19SBen Gras 	memcpy((void *)s, pspriv, sizeof(*s));
1182fe8fb19SBen Gras }
1192fe8fb19SBen Gras 
1202fe8fb19SBen Gras static  __inline int
_mb_singlebyte(int c)1212fe8fb19SBen Gras _mb_singlebyte(int c)
1222fe8fb19SBen Gras {
1232fe8fb19SBen Gras 	c &= 0xff;
1242fe8fb19SBen Gras 	return (c <= 0x7f);
1252fe8fb19SBen Gras }
1262fe8fb19SBen Gras 
1272fe8fb19SBen Gras static __inline int
_mb_leadbyte(int c)1282fe8fb19SBen Gras _mb_leadbyte(int c)
1292fe8fb19SBen Gras {
1302fe8fb19SBen Gras 	c &= 0xff;
1312fe8fb19SBen Gras 	return (0x81 <= c && c <= 0xfe);
1322fe8fb19SBen Gras }
1332fe8fb19SBen Gras 
1342fe8fb19SBen Gras static __inline int
_mb_trailbyte(int c)1352fe8fb19SBen Gras _mb_trailbyte(int c)
1362fe8fb19SBen Gras {
1372fe8fb19SBen Gras 	c &= 0xff;
1382fe8fb19SBen Gras 	return ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfe));
1392fe8fb19SBen Gras }
1402fe8fb19SBen Gras 
1412fe8fb19SBen Gras static __inline int
_mb_surrogate(int c)1422fe8fb19SBen Gras _mb_surrogate(int c)
1432fe8fb19SBen Gras {
1442fe8fb19SBen Gras 	c &= 0xff;
1452fe8fb19SBen Gras 	return (0x30 <= c && c <= 0x39);
1462fe8fb19SBen Gras }
1472fe8fb19SBen Gras 
1482fe8fb19SBen Gras static __inline int
_mb_count(wchar_t v)1492fe8fb19SBen Gras _mb_count(wchar_t v)
1502fe8fb19SBen Gras {
1512fe8fb19SBen Gras 	u_int32_t c;
1522fe8fb19SBen Gras 
1532fe8fb19SBen Gras 	c = (u_int32_t)v; /* XXX */
1542fe8fb19SBen Gras 	if (!(c & 0xffffff00))
1552fe8fb19SBen Gras 		return (1);
1562fe8fb19SBen Gras 	if (!(c & 0xffff0000))
1572fe8fb19SBen Gras 		return (2);
1582fe8fb19SBen Gras 	return (4);
1592fe8fb19SBen Gras }
1602fe8fb19SBen Gras 
1612fe8fb19SBen Gras #define	_PSENC		(psenc->ch[psenc->chlen - 1])
1622fe8fb19SBen Gras #define	_PUSH_PSENC(c)	(psenc->ch[psenc->chlen++] = (c))
1632fe8fb19SBen Gras 
1642fe8fb19SBen Gras static int
_citrus_GBK2K_mbrtowc_priv(_GBK2KEncodingInfo * __restrict ei,wchar_t * __restrict pwc,const char ** __restrict s,size_t n,_GBK2KState * __restrict psenc,size_t * __restrict nresult)1652fe8fb19SBen Gras _citrus_GBK2K_mbrtowc_priv(_GBK2KEncodingInfo * __restrict ei,
1662fe8fb19SBen Gras 			   wchar_t * __restrict pwc,
1672fe8fb19SBen Gras 			   const char ** __restrict s, size_t n,
1682fe8fb19SBen Gras 			   _GBK2KState * __restrict psenc,
1692fe8fb19SBen Gras 			   size_t * __restrict nresult)
1702fe8fb19SBen Gras {
1712fe8fb19SBen Gras 	int chlenbak, len;
1722fe8fb19SBen Gras 	const char *s0, *s1;
1732fe8fb19SBen Gras 	wchar_t wc;
1742fe8fb19SBen Gras 
1752fe8fb19SBen Gras 	_DIAGASSERT(ei != NULL);
1762fe8fb19SBen Gras 	/* pwc may be NULL */
1772fe8fb19SBen Gras 	_DIAGASSERT(s != NULL);
1782fe8fb19SBen Gras 	_DIAGASSERT(psenc != NULL);
1792fe8fb19SBen Gras 
1802fe8fb19SBen Gras 	s0 = *s;
1812fe8fb19SBen Gras 
1822fe8fb19SBen Gras 	if (s0 == NULL) {
1832fe8fb19SBen Gras 		/* _citrus_GBK2K_init_state(ei, psenc); */
1842fe8fb19SBen Gras 		psenc->chlen = 0;
1852fe8fb19SBen Gras 		*nresult = 0;
1862fe8fb19SBen Gras 		return (0);
1872fe8fb19SBen Gras 	}
1882fe8fb19SBen Gras 
1892fe8fb19SBen Gras 	chlenbak = psenc->chlen;
1902fe8fb19SBen Gras 
1912fe8fb19SBen Gras 	switch (psenc->chlen) {
1922fe8fb19SBen Gras 	case 3:
1932fe8fb19SBen Gras 		if (!_mb_leadbyte (_PSENC))
1942fe8fb19SBen Gras 			goto invalid;
1952fe8fb19SBen Gras 	/* FALLTHROUGH */
1962fe8fb19SBen Gras 	case 2:
1972fe8fb19SBen Gras 		if (!_mb_surrogate(_PSENC) || _mb_trailbyte(_PSENC))
1982fe8fb19SBen Gras 			goto invalid;
1992fe8fb19SBen Gras 	/* FALLTHROUGH */
2002fe8fb19SBen Gras 	case 1:
2012fe8fb19SBen Gras 		if (!_mb_leadbyte (_PSENC))
2022fe8fb19SBen Gras 			goto invalid;
2032fe8fb19SBen Gras 	/* FALLTHOROUGH */
2042fe8fb19SBen Gras 	case 0:
2052fe8fb19SBen Gras 		break;
2062fe8fb19SBen Gras 	default:
2072fe8fb19SBen Gras 		goto invalid;
2082fe8fb19SBen Gras 	}
2092fe8fb19SBen Gras 
2102fe8fb19SBen Gras 	for (;;) {
2112fe8fb19SBen Gras 		if (n-- < 1)
2122fe8fb19SBen Gras 			goto restart;
2132fe8fb19SBen Gras 
2142fe8fb19SBen Gras 		_PUSH_PSENC(*s0++);
2152fe8fb19SBen Gras 
2162fe8fb19SBen Gras 		switch (psenc->chlen) {
2172fe8fb19SBen Gras 		case 1:
2182fe8fb19SBen Gras 			if (_mb_singlebyte(_PSENC))
2192fe8fb19SBen Gras 				goto convert;
2202fe8fb19SBen Gras 			if (_mb_leadbyte  (_PSENC))
2212fe8fb19SBen Gras 				continue;
2222fe8fb19SBen Gras 			goto ilseq;
2232fe8fb19SBen Gras 		case 2:
2242fe8fb19SBen Gras 			if (_mb_trailbyte (_PSENC))
2252fe8fb19SBen Gras 				goto convert;
2262fe8fb19SBen Gras 			if (ei->mb_cur_max == 4 &&
2272fe8fb19SBen Gras 			    _mb_surrogate (_PSENC))
2282fe8fb19SBen Gras 				continue;
2292fe8fb19SBen Gras 			goto ilseq;
2302fe8fb19SBen Gras 		case 3:
2312fe8fb19SBen Gras 			if (_mb_leadbyte  (_PSENC))
2322fe8fb19SBen Gras 				continue;
2332fe8fb19SBen Gras 			goto ilseq;
2342fe8fb19SBen Gras 		case 4:
2352fe8fb19SBen Gras 			if (_mb_surrogate (_PSENC))
2362fe8fb19SBen Gras 				goto convert;
2372fe8fb19SBen Gras 			goto ilseq;
2382fe8fb19SBen Gras 		}
2392fe8fb19SBen Gras 	}
2402fe8fb19SBen Gras 
2412fe8fb19SBen Gras convert:
2422fe8fb19SBen Gras 	len = psenc->chlen;
2432fe8fb19SBen Gras 	s1  = &psenc->ch[0];
2442fe8fb19SBen Gras 	wc  = 0;
2452fe8fb19SBen Gras 	while (len-- > 0)
2462fe8fb19SBen Gras 		wc = (wc << 8) | (*s1++ & 0xff);
2472fe8fb19SBen Gras 
2482fe8fb19SBen Gras 	if (pwc != NULL)
2492fe8fb19SBen Gras 		*pwc = wc;
2502fe8fb19SBen Gras 	*s = s0;
2512fe8fb19SBen Gras 	*nresult = (wc == 0) ? 0 : psenc->chlen - chlenbak;
2522fe8fb19SBen Gras 	/* _citrus_GBK2K_init_state(ei, psenc); */
2532fe8fb19SBen Gras 	psenc->chlen = 0;
2542fe8fb19SBen Gras 
2552fe8fb19SBen Gras 	return (0);
2562fe8fb19SBen Gras 
2572fe8fb19SBen Gras restart:
2582fe8fb19SBen Gras 	*s = s0;
2592fe8fb19SBen Gras 	*nresult = (size_t)-2;
2602fe8fb19SBen Gras 
2612fe8fb19SBen Gras 	return (0);
2622fe8fb19SBen Gras 
2632fe8fb19SBen Gras invalid:
2642fe8fb19SBen Gras 	return (EINVAL);
2652fe8fb19SBen Gras 
2662fe8fb19SBen Gras ilseq:
2672fe8fb19SBen Gras 	*nresult = (size_t)-1;
2682fe8fb19SBen Gras 	return (EILSEQ);
2692fe8fb19SBen Gras }
2702fe8fb19SBen Gras 
2712fe8fb19SBen Gras 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)2722fe8fb19SBen Gras _citrus_GBK2K_wcrtomb_priv(_GBK2KEncodingInfo * __restrict ei,
2732fe8fb19SBen Gras 			   char * __restrict s, size_t n, wchar_t wc,
2742fe8fb19SBen Gras 			   _GBK2KState * __restrict psenc,
2752fe8fb19SBen Gras 			   size_t * __restrict nresult)
2762fe8fb19SBen Gras {
2772fe8fb19SBen Gras 	int len, ret;
2782fe8fb19SBen Gras 
2792fe8fb19SBen Gras 	_DIAGASSERT(ei != NULL);
2802fe8fb19SBen Gras 	_DIAGASSERT(s != NULL);
2812fe8fb19SBen Gras 	_DIAGASSERT(psenc != NULL);
2822fe8fb19SBen Gras 
2832fe8fb19SBen Gras 	if (psenc->chlen != 0) {
2842fe8fb19SBen Gras 		ret = EINVAL;
2852fe8fb19SBen Gras 		goto err;
2862fe8fb19SBen Gras 	}
2872fe8fb19SBen Gras 
2882fe8fb19SBen Gras 	len = _mb_count(wc);
2892fe8fb19SBen Gras 	if (n < len) {
2902fe8fb19SBen Gras 		ret = E2BIG;
2912fe8fb19SBen Gras 		goto err;
2922fe8fb19SBen Gras 	}
2932fe8fb19SBen Gras 
2942fe8fb19SBen Gras 	switch (len) {
2952fe8fb19SBen Gras 	case 1:
2962fe8fb19SBen Gras 		if (!_mb_singlebyte(_PUSH_PSENC(wc     ))) {
2972fe8fb19SBen Gras 			ret = EILSEQ;
2982fe8fb19SBen Gras 			goto err;
2992fe8fb19SBen Gras 		}
3002fe8fb19SBen Gras 		break;
3012fe8fb19SBen Gras 	case 2:
3022fe8fb19SBen Gras 		if (!_mb_leadbyte  (_PUSH_PSENC(wc >> 8)) ||
3032fe8fb19SBen Gras 		    !_mb_trailbyte (_PUSH_PSENC(wc     ))) {
3042fe8fb19SBen Gras 			ret = EILSEQ;
3052fe8fb19SBen Gras 			goto err;
3062fe8fb19SBen Gras 		}
3072fe8fb19SBen Gras 		break;
3082fe8fb19SBen Gras 	case 4:
3092fe8fb19SBen Gras 		if (ei->mb_cur_max != 4 ||
3102fe8fb19SBen Gras 		    !_mb_leadbyte  (_PUSH_PSENC(wc >> 24)) ||
3112fe8fb19SBen Gras 		    !_mb_surrogate (_PUSH_PSENC(wc >> 16)) ||
3122fe8fb19SBen Gras 		    !_mb_leadbyte  (_PUSH_PSENC(wc >>  8)) ||
3132fe8fb19SBen Gras 		    !_mb_surrogate (_PUSH_PSENC(wc      ))) {
3142fe8fb19SBen Gras 			ret = EILSEQ;
3152fe8fb19SBen Gras 			goto err;
3162fe8fb19SBen Gras 		}
3172fe8fb19SBen Gras 		break;
3182fe8fb19SBen Gras 	}
3192fe8fb19SBen Gras 
3202fe8fb19SBen Gras 	_DIAGASSERT(len == psenc->chlen);
3212fe8fb19SBen Gras 
3222fe8fb19SBen Gras 	memcpy(s, psenc->ch, psenc->chlen);
3232fe8fb19SBen Gras 	*nresult = psenc->chlen;
3242fe8fb19SBen Gras 	/* _citrus_GBK2K_init_state(ei, psenc); */
3252fe8fb19SBen Gras 	psenc->chlen = 0;
3262fe8fb19SBen Gras 
3272fe8fb19SBen Gras 	return (0);
3282fe8fb19SBen Gras 
3292fe8fb19SBen Gras err:
3302fe8fb19SBen Gras 	*nresult = (size_t)-1;
3312fe8fb19SBen Gras 	return ret;
3322fe8fb19SBen Gras }
3332fe8fb19SBen Gras 
3342fe8fb19SBen Gras static __inline int
3352fe8fb19SBen Gras /*ARGSUSED*/
_citrus_GBK2K_stdenc_wctocs(_GBK2KEncodingInfo * __restrict ei,_csid_t * __restrict csid,_index_t * __restrict idx,wchar_t wc)3362fe8fb19SBen Gras _citrus_GBK2K_stdenc_wctocs(_GBK2KEncodingInfo * __restrict ei,
3372fe8fb19SBen Gras 			    _csid_t * __restrict csid,
3382fe8fb19SBen Gras 			    _index_t * __restrict idx, wchar_t wc)
3392fe8fb19SBen Gras {
3402fe8fb19SBen Gras 	u_int8_t ch, cl;
3412fe8fb19SBen Gras 
3422fe8fb19SBen Gras 	_DIAGASSERT(csid != NULL && idx != NULL);
3432fe8fb19SBen Gras 
3442fe8fb19SBen Gras 	if ((u_int32_t)wc<0x80) {
3452fe8fb19SBen Gras 		/* ISO646 */
3462fe8fb19SBen Gras 		*csid = 0;
3472fe8fb19SBen Gras 		*idx = (_index_t)wc;
3482fe8fb19SBen Gras 	} else if ((u_int32_t)wc>=0x10000) {
3492fe8fb19SBen Gras 		/* GBKUCS : XXX */
3502fe8fb19SBen Gras 		*csid = 3;
3512fe8fb19SBen Gras 		*idx = (_index_t)wc;
3522fe8fb19SBen Gras 	} else {
3532fe8fb19SBen Gras 		ch = (u_int8_t)(wc >> 8);
3542fe8fb19SBen Gras 		cl = (u_int8_t)wc;
3552fe8fb19SBen Gras 		if (ch>=0xA1 && cl>=0xA1) {
3562fe8fb19SBen Gras 			/* EUC G1 */
3572fe8fb19SBen Gras 			*csid = 1;
3582fe8fb19SBen Gras 			*idx = (_index_t)wc & 0x7F7FU;
3592fe8fb19SBen Gras 		} else {
3602fe8fb19SBen Gras 			/* extended area (0x8140-) */
3612fe8fb19SBen Gras 			*csid = 2;
3622fe8fb19SBen Gras 			*idx = (_index_t)wc;
3632fe8fb19SBen Gras 		}
3642fe8fb19SBen Gras 	}
3652fe8fb19SBen Gras 
3662fe8fb19SBen Gras 	return 0;
3672fe8fb19SBen Gras }
3682fe8fb19SBen Gras 
3692fe8fb19SBen Gras static __inline int
3702fe8fb19SBen Gras /*ARGSUSED*/
_citrus_GBK2K_stdenc_cstowc(_GBK2KEncodingInfo * __restrict ei,wchar_t * __restrict wc,_csid_t csid,_index_t idx)3712fe8fb19SBen Gras _citrus_GBK2K_stdenc_cstowc(_GBK2KEncodingInfo * __restrict ei,
3722fe8fb19SBen Gras 			    wchar_t * __restrict wc,
3732fe8fb19SBen Gras 			    _csid_t csid, _index_t idx)
3742fe8fb19SBen Gras {
3752fe8fb19SBen Gras 
3762fe8fb19SBen Gras 	_DIAGASSERT(wc != NULL);
3772fe8fb19SBen Gras 
3782fe8fb19SBen Gras 	switch (csid) {
3792fe8fb19SBen Gras 	case 0:
3802fe8fb19SBen Gras 		/* ISO646 */
3812fe8fb19SBen Gras 		*wc = (wchar_t)idx;
3822fe8fb19SBen Gras 		break;
3832fe8fb19SBen Gras 	case 1:
3842fe8fb19SBen Gras 		/* EUC G1 */
3852fe8fb19SBen Gras 		*wc = (wchar_t)idx | 0x8080U;
3862fe8fb19SBen Gras 		break;
3872fe8fb19SBen Gras 	case 2:
3882fe8fb19SBen Gras 		/* extended area */
3892fe8fb19SBen Gras 		*wc = (wchar_t)idx;
3902fe8fb19SBen Gras 		break;
3912fe8fb19SBen Gras 	case 3:
3922fe8fb19SBen Gras 		/* GBKUCS : XXX */
3932fe8fb19SBen Gras 		if (ei->mb_cur_max != 4)
3942fe8fb19SBen Gras 			return EINVAL;
3952fe8fb19SBen Gras 		*wc = (wchar_t)idx;
3962fe8fb19SBen Gras 		break;
3972fe8fb19SBen Gras 	default:
3982fe8fb19SBen Gras 		return EILSEQ;
3992fe8fb19SBen Gras 	}
4002fe8fb19SBen Gras 
4012fe8fb19SBen Gras 	return 0;
4022fe8fb19SBen Gras }
4032fe8fb19SBen Gras 
4042fe8fb19SBen Gras static __inline int
4052fe8fb19SBen Gras /*ARGSUSED*/
_citrus_GBK2K_stdenc_get_state_desc_generic(_GBK2KEncodingInfo * __restrict ei,_GBK2KState * __restrict psenc,int * __restrict rstate)4062fe8fb19SBen Gras _citrus_GBK2K_stdenc_get_state_desc_generic(_GBK2KEncodingInfo * __restrict ei,
4072fe8fb19SBen Gras 					    _GBK2KState * __restrict psenc,
4082fe8fb19SBen Gras 					    int * __restrict rstate)
4092fe8fb19SBen Gras {
4102fe8fb19SBen Gras 
4112fe8fb19SBen Gras 	if (psenc->chlen == 0)
4122fe8fb19SBen Gras 		*rstate = _STDENC_SDGEN_INITIAL;
4132fe8fb19SBen Gras 	else
4142fe8fb19SBen Gras 		*rstate = _STDENC_SDGEN_INCOMPLETE_CHAR;
4152fe8fb19SBen Gras 
4162fe8fb19SBen Gras 	return 0;
4172fe8fb19SBen Gras }
4182fe8fb19SBen Gras 
4192fe8fb19SBen Gras static int
4202fe8fb19SBen Gras /*ARGSUSED*/
_citrus_GBK2K_encoding_module_init(_GBK2KEncodingInfo * __restrict ei,const void * __restrict var,size_t lenvar)4212fe8fb19SBen Gras _citrus_GBK2K_encoding_module_init(_GBK2KEncodingInfo * __restrict ei,
4222fe8fb19SBen Gras 				   const void * __restrict var, size_t lenvar)
4232fe8fb19SBen Gras {
4242fe8fb19SBen Gras 	const char *p;
4252fe8fb19SBen Gras 
4262fe8fb19SBen Gras 	_DIAGASSERT(ei != NULL);
4272fe8fb19SBen Gras 
4282fe8fb19SBen Gras 	p = var;
4292fe8fb19SBen Gras #define MATCH(x, act)                                           \
4302fe8fb19SBen Gras do {                                                            \
4312fe8fb19SBen Gras         if (lenvar >= (sizeof(#x)-1) &&                         \
4322fe8fb19SBen Gras             _bcs_strncasecmp(p, #x, sizeof(#x)-1) == 0) {       \
4332fe8fb19SBen Gras                 act;                                            \
4342fe8fb19SBen Gras                 lenvar -= sizeof(#x)-1;                         \
4352fe8fb19SBen Gras                 p += sizeof(#x)-1;                              \
4362fe8fb19SBen Gras         }                                                       \
4372fe8fb19SBen Gras } while (/*CONSTCOND*/0)
4382fe8fb19SBen Gras 	memset((void *)ei, 0, sizeof(*ei));
4392fe8fb19SBen Gras 	ei->mb_cur_max = 4;
4402fe8fb19SBen Gras 	while (lenvar>0) {
4412fe8fb19SBen Gras 		switch (_bcs_tolower(*p)) {
4422fe8fb19SBen Gras 		case '2':
4432fe8fb19SBen Gras 			MATCH("2byte", ei->mb_cur_max = 2);
4442fe8fb19SBen Gras 			break;
4452fe8fb19SBen Gras 		}
4462fe8fb19SBen Gras 		p++;
4472fe8fb19SBen Gras 		lenvar--;
4482fe8fb19SBen Gras 	}
4492fe8fb19SBen Gras 
4502fe8fb19SBen Gras 	return (0);
4512fe8fb19SBen Gras }
4522fe8fb19SBen Gras 
4532fe8fb19SBen Gras static void
4542fe8fb19SBen Gras /*ARGSUSED*/
_citrus_GBK2K_encoding_module_uninit(_GBK2KEncodingInfo * ei)4552fe8fb19SBen Gras _citrus_GBK2K_encoding_module_uninit(_GBK2KEncodingInfo *ei)
4562fe8fb19SBen Gras {
4572fe8fb19SBen Gras }
4582fe8fb19SBen Gras 
4592fe8fb19SBen Gras 
4602fe8fb19SBen Gras /* ----------------------------------------------------------------------
4612fe8fb19SBen Gras  * public interface for ctype
4622fe8fb19SBen Gras  */
4632fe8fb19SBen Gras 
4642fe8fb19SBen Gras _CITRUS_CTYPE_DECLS(GBK2K);
4652fe8fb19SBen Gras _CITRUS_CTYPE_DEF_OPS(GBK2K);
4662fe8fb19SBen Gras 
4672fe8fb19SBen Gras #include "citrus_ctype_template.h"
4682fe8fb19SBen Gras 
4692fe8fb19SBen Gras /* ----------------------------------------------------------------------
4702fe8fb19SBen Gras  * public interface for stdenc
4712fe8fb19SBen Gras  */
4722fe8fb19SBen Gras 
4732fe8fb19SBen Gras _CITRUS_STDENC_DECLS(GBK2K);
4742fe8fb19SBen Gras _CITRUS_STDENC_DEF_OPS(GBK2K);
4752fe8fb19SBen Gras 
4762fe8fb19SBen Gras #include "citrus_stdenc_template.h"
477