xref: /minix3/lib/libc/citrus/modules/citrus_zw.c (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
1*84d9c625SLionel Sambuc /* $NetBSD: citrus_zw.c,v 1.5 2013/05/28 16:57:56 joerg Exp $ */
22fe8fb19SBen Gras 
32fe8fb19SBen Gras /*-
42fe8fb19SBen Gras  * Copyright (c)2004, 2006 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 
302fe8fb19SBen Gras #include <sys/cdefs.h>
312fe8fb19SBen Gras #if defined(LIB_SCCS) && !defined(lint)
32*84d9c625SLionel Sambuc __RCSID("$NetBSD: citrus_zw.c,v 1.5 2013/05/28 16:57:56 joerg Exp $");
332fe8fb19SBen Gras #endif /* LIB_SCCS and not lint */
342fe8fb19SBen Gras 
352fe8fb19SBen Gras #include <sys/types.h>
362fe8fb19SBen Gras #include <assert.h>
372fe8fb19SBen Gras #include <errno.h>
382fe8fb19SBen Gras #include <string.h>
392fe8fb19SBen Gras #include <stdio.h>
402fe8fb19SBen Gras #include <stdint.h>
412fe8fb19SBen Gras #include <stdlib.h>
422fe8fb19SBen Gras #include <stddef.h>
432fe8fb19SBen Gras #include <wchar.h>
442fe8fb19SBen Gras #include <limits.h>
452fe8fb19SBen Gras 
462fe8fb19SBen Gras #include "citrus_namespace.h"
472fe8fb19SBen Gras #include "citrus_types.h"
482fe8fb19SBen Gras #include "citrus_module.h"
492fe8fb19SBen Gras #include "citrus_ctype.h"
502fe8fb19SBen Gras #include "citrus_stdenc.h"
512fe8fb19SBen Gras #include "citrus_zw.h"
522fe8fb19SBen Gras 
532fe8fb19SBen Gras /* ----------------------------------------------------------------------
542fe8fb19SBen Gras  * private stuffs used by templates
552fe8fb19SBen Gras  */
562fe8fb19SBen Gras 
572fe8fb19SBen Gras typedef struct {
582fe8fb19SBen Gras 	int dummy;
592fe8fb19SBen Gras } _ZWEncodingInfo;
602fe8fb19SBen Gras 
612fe8fb19SBen Gras typedef enum {
622fe8fb19SBen Gras 	NONE, AMBIGIOUS, ASCII, GB2312
632fe8fb19SBen Gras } _ZWCharset;
642fe8fb19SBen Gras 
652fe8fb19SBen Gras typedef struct {
662fe8fb19SBen Gras 	int		chlen;
672fe8fb19SBen Gras 	char		ch[4];
682fe8fb19SBen Gras 	_ZWCharset	charset;
692fe8fb19SBen Gras } _ZWState;
702fe8fb19SBen Gras 
712fe8fb19SBen Gras typedef struct {
722fe8fb19SBen Gras 	_ZWEncodingInfo	ei;
732fe8fb19SBen Gras 	struct {
742fe8fb19SBen Gras 		/* for future multi-locale facility */
752fe8fb19SBen Gras 		_ZWState	s_mblen;
762fe8fb19SBen Gras 		_ZWState	s_mbrlen;
772fe8fb19SBen Gras 		_ZWState	s_mbrtowc;
782fe8fb19SBen Gras 		_ZWState	s_mbtowc;
792fe8fb19SBen Gras 		_ZWState	s_mbsrtowcs;
80*84d9c625SLionel Sambuc 		_ZWState	s_mbsnrtowcs;
812fe8fb19SBen Gras 		_ZWState	s_wcrtomb;
822fe8fb19SBen Gras 		_ZWState	s_wcsrtombs;
83*84d9c625SLionel Sambuc 		_ZWState	s_wcsnrtombs;
842fe8fb19SBen Gras 		_ZWState	s_wctomb;
852fe8fb19SBen Gras 	} states;
862fe8fb19SBen Gras } _ZWCTypeInfo;
872fe8fb19SBen Gras 
882fe8fb19SBen Gras #define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
892fe8fb19SBen Gras #define _CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.s_##_func_
902fe8fb19SBen Gras 
912fe8fb19SBen Gras #define _FUNCNAME(m)			_citrus_ZW_##m
922fe8fb19SBen Gras #define _ENCODING_INFO			_ZWEncodingInfo
932fe8fb19SBen Gras #define _CTYPE_INFO			_ZWCTypeInfo
942fe8fb19SBen Gras #define _ENCODING_STATE			_ZWState
952fe8fb19SBen Gras #define _ENCODING_MB_CUR_MAX(_ei_)	MB_LEN_MAX
962fe8fb19SBen Gras #define _ENCODING_IS_STATE_DEPENDENT		1
972fe8fb19SBen Gras #define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	((_ps_)->charset != NONE)
982fe8fb19SBen Gras 
992fe8fb19SBen Gras static __inline void
1002fe8fb19SBen Gras /*ARGSUSED*/
_citrus_ZW_init_state(_ZWEncodingInfo * __restrict ei,_ZWState * __restrict psenc)1012fe8fb19SBen Gras _citrus_ZW_init_state(_ZWEncodingInfo * __restrict ei,
1022fe8fb19SBen Gras 	_ZWState * __restrict psenc)
1032fe8fb19SBen Gras {
1042fe8fb19SBen Gras 	/* ei my be unused */
1052fe8fb19SBen Gras 	_DIAGASSERT(psenc != NULL);
1062fe8fb19SBen Gras 
1072fe8fb19SBen Gras 	psenc->chlen = 0;
1082fe8fb19SBen Gras 	psenc->charset = NONE;
1092fe8fb19SBen Gras }
1102fe8fb19SBen Gras 
1112fe8fb19SBen Gras static __inline void
1122fe8fb19SBen Gras /*ARGSUSED*/
_citrus_ZW_pack_state(_ZWEncodingInfo * __restrict ei,void * __restrict pspriv,const _ZWState * __restrict psenc)1132fe8fb19SBen Gras _citrus_ZW_pack_state(_ZWEncodingInfo * __restrict ei,
1142fe8fb19SBen Gras 	void *__restrict pspriv, const _ZWState * __restrict psenc)
1152fe8fb19SBen Gras {
1162fe8fb19SBen Gras 	/* ei may be unused */
1172fe8fb19SBen Gras 	_DIAGASSERT(pspriv != NULL);
1182fe8fb19SBen Gras 	_DIAGASSERT(psenc != NULL);
1192fe8fb19SBen Gras 
1202fe8fb19SBen Gras 	memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
1212fe8fb19SBen Gras }
1222fe8fb19SBen Gras 
1232fe8fb19SBen Gras static __inline void
1242fe8fb19SBen Gras /*ARGSUSED*/
_citrus_ZW_unpack_state(_ZWEncodingInfo * __restrict ei,_ZWState * __restrict psenc,const void * __restrict pspriv)1252fe8fb19SBen Gras _citrus_ZW_unpack_state(_ZWEncodingInfo * __restrict ei,
1262fe8fb19SBen Gras 	_ZWState * __restrict psenc, const void * __restrict pspriv)
1272fe8fb19SBen Gras {
1282fe8fb19SBen Gras 	/* ei may be unused */
1292fe8fb19SBen Gras 	_DIAGASSERT(psenc != NULL);
1302fe8fb19SBen Gras 	_DIAGASSERT(pspriv != NULL);
1312fe8fb19SBen Gras 
1322fe8fb19SBen Gras 	memcpy((void *)psenc, pspriv, sizeof(*psenc));
1332fe8fb19SBen Gras }
1342fe8fb19SBen Gras 
1352fe8fb19SBen Gras static int
_citrus_ZW_mbrtowc_priv(_ZWEncodingInfo * __restrict ei,wchar_t * __restrict pwc,const char ** __restrict s,size_t n,_ZWState * __restrict psenc,size_t * __restrict nresult)1362fe8fb19SBen Gras _citrus_ZW_mbrtowc_priv(_ZWEncodingInfo * __restrict ei,
1372fe8fb19SBen Gras 	wchar_t * __restrict pwc, const char **__restrict s, size_t n,
1382fe8fb19SBen Gras 	_ZWState * __restrict psenc, size_t * __restrict nresult)
1392fe8fb19SBen Gras {
1402fe8fb19SBen Gras 	const char *s0;
1412fe8fb19SBen Gras 	int ch, len;
1422fe8fb19SBen Gras 	wchar_t	 wc;
1432fe8fb19SBen Gras 
1442fe8fb19SBen Gras 	/* ei may be unused */
1452fe8fb19SBen Gras 	/* pwc may be null */
1462fe8fb19SBen Gras 	_DIAGASSERT(s != NULL);
1472fe8fb19SBen Gras 	_DIAGASSERT(psenc != NULL);
1482fe8fb19SBen Gras 	_DIAGASSERT(nresult != NULL);
1492fe8fb19SBen Gras 
1502fe8fb19SBen Gras 	if (*s == NULL) {
1512fe8fb19SBen Gras 		_citrus_ZW_init_state(ei, psenc);
1522fe8fb19SBen Gras 		*nresult = (size_t)_ENCODING_IS_STATE_DEPENDENT;
1532fe8fb19SBen Gras 		return 0;
1542fe8fb19SBen Gras 	}
1552fe8fb19SBen Gras 	s0 = *s;
1562fe8fb19SBen Gras 	len = 0;
1572fe8fb19SBen Gras 
1582fe8fb19SBen Gras #define	STORE				\
1592fe8fb19SBen Gras do {					\
1602fe8fb19SBen Gras 	if (n-- < 1) {			\
1612fe8fb19SBen Gras 		*nresult = (size_t)-2;	\
1622fe8fb19SBen Gras 		*s = s0;		\
1632fe8fb19SBen Gras 		return 0;		\
1642fe8fb19SBen Gras 	}				\
1652fe8fb19SBen Gras 	ch = (unsigned char)*s0++;	\
1662fe8fb19SBen Gras 	if (len++ > MB_LEN_MAX || ch > 0x7F)\
1672fe8fb19SBen Gras 		goto ilseq;		\
1682fe8fb19SBen Gras 	psenc->ch[psenc->chlen++] = ch;	\
1692fe8fb19SBen Gras } while (/*CONSTCOND*/0)
1702fe8fb19SBen Gras 
1712fe8fb19SBen Gras loop:
1722fe8fb19SBen Gras 	switch (psenc->charset) {
1732fe8fb19SBen Gras 	case ASCII:
1742fe8fb19SBen Gras 		switch (psenc->chlen) {
1752fe8fb19SBen Gras 		case 0:
1762fe8fb19SBen Gras 			STORE;
1772fe8fb19SBen Gras 			switch (psenc->ch[0]) {
1782fe8fb19SBen Gras 			case '\0': case '\n':
1792fe8fb19SBen Gras 				psenc->charset = NONE;
1802fe8fb19SBen Gras 			}
1812fe8fb19SBen Gras 		/*FALLTHROUGH*/
1822fe8fb19SBen Gras 		case 1:
1832fe8fb19SBen Gras 			break;
1842fe8fb19SBen Gras 		default:
1852fe8fb19SBen Gras 			return EINVAL;
1862fe8fb19SBen Gras 		}
1872fe8fb19SBen Gras 		ch = (unsigned char)psenc->ch[0];
1882fe8fb19SBen Gras 		if (ch > 0x7F)
1892fe8fb19SBen Gras 			goto ilseq;
1902fe8fb19SBen Gras 		wc = (wchar_t)ch;
1912fe8fb19SBen Gras 		psenc->chlen = 0;
1922fe8fb19SBen Gras 		break;
1932fe8fb19SBen Gras 	case NONE:
1942fe8fb19SBen Gras 		if (psenc->chlen != 0)
1952fe8fb19SBen Gras 			return EINVAL;
1962fe8fb19SBen Gras 		STORE;
1972fe8fb19SBen Gras 		ch = (unsigned char)psenc->ch[0];
1982fe8fb19SBen Gras 		if (ch != 'z') {
1992fe8fb19SBen Gras 			if (ch != '\n' && ch != '\0')
2002fe8fb19SBen Gras 				psenc->charset = ASCII;
2012fe8fb19SBen Gras 			wc = (wchar_t)ch;
2022fe8fb19SBen Gras 			psenc->chlen = 0;
2032fe8fb19SBen Gras 			break;
2042fe8fb19SBen Gras 		}
2052fe8fb19SBen Gras 		psenc->charset = AMBIGIOUS;
2062fe8fb19SBen Gras 		psenc->chlen = 0;
2072fe8fb19SBen Gras 	/* FALLTHROUGH */
2082fe8fb19SBen Gras 	case AMBIGIOUS:
2092fe8fb19SBen Gras 		if (psenc->chlen != 0)
2102fe8fb19SBen Gras 			return EINVAL;
2112fe8fb19SBen Gras 		STORE;
2122fe8fb19SBen Gras 		if (psenc->ch[0] != 'W') {
2132fe8fb19SBen Gras 			psenc->charset = ASCII;
2142fe8fb19SBen Gras 			wc = L'z';
2152fe8fb19SBen Gras 			break;
2162fe8fb19SBen Gras 		}
2172fe8fb19SBen Gras 		psenc->charset = GB2312;
2182fe8fb19SBen Gras 		psenc->chlen = 0;
2192fe8fb19SBen Gras 	/* FALLTHROUGH */
2202fe8fb19SBen Gras 	case GB2312:
2212fe8fb19SBen Gras 		switch (psenc->chlen) {
2222fe8fb19SBen Gras 		case 0:
2232fe8fb19SBen Gras 			STORE;
2242fe8fb19SBen Gras 			ch = (unsigned char)psenc->ch[0];
2252fe8fb19SBen Gras 			if (ch == '\0') {
2262fe8fb19SBen Gras 				psenc->charset = NONE;
2272fe8fb19SBen Gras 				wc = (wchar_t)ch;
2282fe8fb19SBen Gras 				psenc->chlen = 0;
2292fe8fb19SBen Gras 				break;
2302fe8fb19SBen Gras 			} else if (ch == '\n') {
2312fe8fb19SBen Gras 				psenc->charset = NONE;
2322fe8fb19SBen Gras 				psenc->chlen = 0;
2332fe8fb19SBen Gras 				goto loop;
2342fe8fb19SBen Gras 			}
2352fe8fb19SBen Gras 		/*FALLTHROUGH*/
2362fe8fb19SBen Gras 		case 1:
2372fe8fb19SBen Gras 			STORE;
2382fe8fb19SBen Gras 			if (psenc->ch[0] == ' ') {
2392fe8fb19SBen Gras 				ch = (unsigned char)psenc->ch[1];
2402fe8fb19SBen Gras 				wc = (wchar_t)ch;
2412fe8fb19SBen Gras 				psenc->chlen = 0;
2422fe8fb19SBen Gras 				break;
2432fe8fb19SBen Gras 			} else if (psenc->ch[0] == '#') {
2442fe8fb19SBen Gras 				ch = (unsigned char)psenc->ch[1];
2452fe8fb19SBen Gras 				if (ch == '\n') {
2462fe8fb19SBen Gras 					psenc->charset = NONE;
2472fe8fb19SBen Gras 					wc = (wchar_t)ch;
2482fe8fb19SBen Gras 					psenc->chlen = 0;
2492fe8fb19SBen Gras 					break;
2502fe8fb19SBen Gras 				} else if (ch == ' ') {
2512fe8fb19SBen Gras 					wc = (wchar_t)ch;
2522fe8fb19SBen Gras 					psenc->chlen = 0;
2532fe8fb19SBen Gras 					break;
2542fe8fb19SBen Gras 				}
2552fe8fb19SBen Gras 			}
2562fe8fb19SBen Gras 			ch = (unsigned char)psenc->ch[0];
2572fe8fb19SBen Gras 			if (ch < 0x21 || ch > 0x7E)
2582fe8fb19SBen Gras 				goto ilseq;
2592fe8fb19SBen Gras 			wc = (wchar_t)(ch << 8);
2602fe8fb19SBen Gras 			ch = (unsigned char)psenc->ch[1];
2612fe8fb19SBen Gras 			if (ch < 0x21 || ch > 0x7E) {
2622fe8fb19SBen Gras ilseq:
2632fe8fb19SBen Gras 				*nresult = (size_t)-1;
2642fe8fb19SBen Gras 				return EILSEQ;
2652fe8fb19SBen Gras 			}
2662fe8fb19SBen Gras 			wc |= (wchar_t)ch;
2672fe8fb19SBen Gras 			psenc->chlen = 0;
2682fe8fb19SBen Gras 			break;
2692fe8fb19SBen Gras 		default:
2702fe8fb19SBen Gras 			return EINVAL;
2712fe8fb19SBen Gras 		}
2722fe8fb19SBen Gras 		break;
2732fe8fb19SBen Gras 	default:
2742fe8fb19SBen Gras 		return EINVAL;
2752fe8fb19SBen Gras 	}
2762fe8fb19SBen Gras 	if (pwc != NULL)
2772fe8fb19SBen Gras 		*pwc = wc;
2782fe8fb19SBen Gras 
2792fe8fb19SBen Gras 	*nresult = (size_t)(wc == 0 ? 0 : len);
2802fe8fb19SBen Gras 	*s = s0;
2812fe8fb19SBen Gras 
2822fe8fb19SBen Gras 	return 0;
2832fe8fb19SBen Gras }
2842fe8fb19SBen Gras 
2852fe8fb19SBen Gras static int
2862fe8fb19SBen Gras /*ARGSUSED*/
_citrus_ZW_wcrtomb_priv(_ZWEncodingInfo * __restrict ei,char * __restrict s,size_t n,wchar_t wc,_ZWState * __restrict psenc,size_t * __restrict nresult)2872fe8fb19SBen Gras _citrus_ZW_wcrtomb_priv(_ZWEncodingInfo * __restrict ei,
2882fe8fb19SBen Gras 	char *__restrict s, size_t n, wchar_t wc,
2892fe8fb19SBen Gras 	_ZWState * __restrict psenc, size_t * __restrict nresult)
2902fe8fb19SBen Gras {
2912fe8fb19SBen Gras 	int ch;
2922fe8fb19SBen Gras 
2932fe8fb19SBen Gras 	/* ei may be null */
2942fe8fb19SBen Gras 	_DIAGASSERT(s != NULL);
2952fe8fb19SBen Gras 	_DIAGASSERT(psenc != NULL);
2962fe8fb19SBen Gras 	_DIAGASSERT(nresult != NULL);
2972fe8fb19SBen Gras 
2982fe8fb19SBen Gras 	if (psenc->chlen != 0)
2992fe8fb19SBen Gras 		return EINVAL;
3002fe8fb19SBen Gras 	if ((uint32_t)wc <= 0x7F) {
3012fe8fb19SBen Gras 		ch = (unsigned char)wc;
3022fe8fb19SBen Gras 		switch (psenc->charset) {
3032fe8fb19SBen Gras 		case NONE:
3042fe8fb19SBen Gras 			if (ch == '\0' || ch == '\n') {
3052fe8fb19SBen Gras 				psenc->ch[psenc->chlen++] = ch;
3062fe8fb19SBen Gras 			} else {
3072fe8fb19SBen Gras 				if (n < 4)
3082fe8fb19SBen Gras 					return E2BIG;
3092fe8fb19SBen Gras 				n -= 4;
3102fe8fb19SBen Gras 				psenc->ch[psenc->chlen++] = 'z';
3112fe8fb19SBen Gras 				psenc->ch[psenc->chlen++] = 'W';
3122fe8fb19SBen Gras 				psenc->ch[psenc->chlen++] = ' ';
3132fe8fb19SBen Gras 				psenc->ch[psenc->chlen++] = ch;
3142fe8fb19SBen Gras 				psenc->charset = GB2312;
3152fe8fb19SBen Gras 			}
3162fe8fb19SBen Gras 			break;
3172fe8fb19SBen Gras 		case GB2312:
3182fe8fb19SBen Gras 			if (n < 2)
3192fe8fb19SBen Gras 				return E2BIG;
3202fe8fb19SBen Gras 			n -= 2;
3212fe8fb19SBen Gras 			if (ch == '\0') {
3222fe8fb19SBen Gras 				psenc->ch[psenc->chlen++] = '\n';
3232fe8fb19SBen Gras 				psenc->ch[psenc->chlen++] = '\0';
3242fe8fb19SBen Gras 				psenc->charset = NONE;
3252fe8fb19SBen Gras 			} else if (ch == '\n') {
3262fe8fb19SBen Gras 				psenc->ch[psenc->chlen++] = '#';
3272fe8fb19SBen Gras 				psenc->ch[psenc->chlen++] = '\n';
3282fe8fb19SBen Gras 				psenc->charset = NONE;
3292fe8fb19SBen Gras 			} else {
3302fe8fb19SBen Gras 				psenc->ch[psenc->chlen++] = ' ';
3312fe8fb19SBen Gras 				psenc->ch[psenc->chlen++] = ch;
3322fe8fb19SBen Gras 			}
3332fe8fb19SBen Gras 			break;
3342fe8fb19SBen Gras 		default:
3352fe8fb19SBen Gras 			return EINVAL;
3362fe8fb19SBen Gras 		}
3372fe8fb19SBen Gras 	} else if ((uint32_t)wc <= 0x7E7E) {
3382fe8fb19SBen Gras 		switch (psenc->charset) {
3392fe8fb19SBen Gras 		case NONE:
3402fe8fb19SBen Gras 			if (n < 2)
3412fe8fb19SBen Gras 				return E2BIG;
3422fe8fb19SBen Gras 			n -= 2;
3432fe8fb19SBen Gras 			psenc->ch[psenc->chlen++] = 'z';
3442fe8fb19SBen Gras 			psenc->ch[psenc->chlen++] = 'W';
3452fe8fb19SBen Gras 			psenc->charset = GB2312;
3462fe8fb19SBen Gras 		/* FALLTHROUGH*/
3472fe8fb19SBen Gras 		case GB2312:
3482fe8fb19SBen Gras 			if (n < 2)
3492fe8fb19SBen Gras 				return E2BIG;
3502fe8fb19SBen Gras 			n -= 2;
3512fe8fb19SBen Gras 			ch = (wc >> 8) & 0xFF;
3522fe8fb19SBen Gras 			if (ch < 0x21 || ch > 0x7E)
3532fe8fb19SBen Gras 				goto ilseq;
3542fe8fb19SBen Gras 			psenc->ch[psenc->chlen++] = ch;
3552fe8fb19SBen Gras 			ch = wc & 0xFF;
3562fe8fb19SBen Gras 			if (ch < 0x21 || ch > 0x7E)
3572fe8fb19SBen Gras 				goto ilseq;
3582fe8fb19SBen Gras 			psenc->ch[psenc->chlen++] = ch;
3592fe8fb19SBen Gras 			break;
3602fe8fb19SBen Gras 		default:
3612fe8fb19SBen Gras 			return EINVAL;
3622fe8fb19SBen Gras 		}
3632fe8fb19SBen Gras 	} else {
3642fe8fb19SBen Gras ilseq:
3652fe8fb19SBen Gras 		*nresult = (size_t)-1;
3662fe8fb19SBen Gras 		return EILSEQ;
3672fe8fb19SBen Gras 	}
3682fe8fb19SBen Gras 	memcpy(s, psenc->ch, psenc->chlen);
3692fe8fb19SBen Gras 	*nresult = psenc->chlen;
3702fe8fb19SBen Gras 	psenc->chlen = 0;
3712fe8fb19SBen Gras 
3722fe8fb19SBen Gras 	return 0;
3732fe8fb19SBen Gras }
3742fe8fb19SBen Gras 
3752fe8fb19SBen Gras static int
3762fe8fb19SBen Gras /*ARGSUSED*/
_citrus_ZW_put_state_reset(_ZWEncodingInfo * __restrict ei,char * __restrict s,size_t n,_ZWState * __restrict psenc,size_t * __restrict nresult)3772fe8fb19SBen Gras _citrus_ZW_put_state_reset(_ZWEncodingInfo * __restrict ei,
3782fe8fb19SBen Gras 	char * __restrict s, size_t n,
3792fe8fb19SBen Gras 	_ZWState * __restrict psenc, size_t * __restrict nresult)
3802fe8fb19SBen Gras {
3812fe8fb19SBen Gras 	/* ei may be unused */
3822fe8fb19SBen Gras 	_DIAGASSERT(s != NULL);
3832fe8fb19SBen Gras 	_DIAGASSERT(psenc != NULL);
3842fe8fb19SBen Gras 	_DIAGASSERT(nresult != NULL);
3852fe8fb19SBen Gras 
3862fe8fb19SBen Gras 	if (psenc->chlen != 0)
3872fe8fb19SBen Gras 		return EINVAL;
3882fe8fb19SBen Gras 	switch (psenc->charset) {
3892fe8fb19SBen Gras 	case GB2312:
3902fe8fb19SBen Gras 		if (n-- < 1)
3912fe8fb19SBen Gras 			return E2BIG;
3922fe8fb19SBen Gras 		psenc->ch[psenc->chlen++] = '\n';
3932fe8fb19SBen Gras 		psenc->charset = NONE;
3942fe8fb19SBen Gras 	/*FALLTHROUGH*/
3952fe8fb19SBen Gras 	case NONE:
3962fe8fb19SBen Gras 		*nresult = psenc->chlen;
3972fe8fb19SBen Gras 		if (psenc->chlen > 0) {
3982fe8fb19SBen Gras 			memcpy(s, psenc->ch, psenc->chlen);
3992fe8fb19SBen Gras 			psenc->chlen = 0;
4002fe8fb19SBen Gras 		}
4012fe8fb19SBen Gras 		break;
4022fe8fb19SBen Gras 	default:
4032fe8fb19SBen Gras 		return EINVAL;
4042fe8fb19SBen Gras 	}
4052fe8fb19SBen Gras 
4062fe8fb19SBen Gras 	return 0;
4072fe8fb19SBen Gras }
4082fe8fb19SBen Gras 
4092fe8fb19SBen Gras static __inline int
4102fe8fb19SBen Gras /*ARGSUSED*/
_citrus_ZW_stdenc_get_state_desc_generic(_ZWEncodingInfo * __restrict ei,_ZWState * __restrict psenc,int * __restrict rstate)4112fe8fb19SBen Gras _citrus_ZW_stdenc_get_state_desc_generic(_ZWEncodingInfo * __restrict ei,
4122fe8fb19SBen Gras 	_ZWState * __restrict psenc, int * __restrict rstate)
4132fe8fb19SBen Gras {
4142fe8fb19SBen Gras 	/* ei may be unused */
4152fe8fb19SBen Gras 	_DIAGASSERT(psenc != NULL);
4162fe8fb19SBen Gras 	_DIAGASSERT(rstate != NULL);
4172fe8fb19SBen Gras 
4182fe8fb19SBen Gras 	switch (psenc->charset) {
4192fe8fb19SBen Gras 	case NONE:
4202fe8fb19SBen Gras 		if (psenc->chlen != 0)
4212fe8fb19SBen Gras 			return EINVAL;
4222fe8fb19SBen Gras 		*rstate = _STDENC_SDGEN_INITIAL;
4232fe8fb19SBen Gras 		break;
4242fe8fb19SBen Gras 	case AMBIGIOUS:
4252fe8fb19SBen Gras 		if (psenc->chlen != 0)
4262fe8fb19SBen Gras 			return EINVAL;
4272fe8fb19SBen Gras 		*rstate = _STDENC_SDGEN_INCOMPLETE_SHIFT;
4282fe8fb19SBen Gras 		break;
4292fe8fb19SBen Gras 	case ASCII:
4302fe8fb19SBen Gras 	case GB2312:
4312fe8fb19SBen Gras 		switch (psenc->chlen) {
4322fe8fb19SBen Gras 		case 0:
4332fe8fb19SBen Gras 			*rstate = _STDENC_SDGEN_STABLE;
4342fe8fb19SBen Gras 			break;
4352fe8fb19SBen Gras 		case 1:
4362fe8fb19SBen Gras 			*rstate = (psenc->ch[0] == '#')
4372fe8fb19SBen Gras 			    ? _STDENC_SDGEN_INCOMPLETE_SHIFT
4382fe8fb19SBen Gras 			    : _STDENC_SDGEN_INCOMPLETE_CHAR;
4392fe8fb19SBen Gras 			break;
4402fe8fb19SBen Gras 		default:
4412fe8fb19SBen Gras 			return EINVAL;
4422fe8fb19SBen Gras 		}
4432fe8fb19SBen Gras 		break;
4442fe8fb19SBen Gras 	default:
4452fe8fb19SBen Gras 		return EINVAL;
4462fe8fb19SBen Gras 	}
4472fe8fb19SBen Gras 	return 0;
4482fe8fb19SBen Gras }
4492fe8fb19SBen Gras 
4502fe8fb19SBen Gras static __inline int
4512fe8fb19SBen Gras /*ARGSUSED*/
_citrus_ZW_stdenc_wctocs(_ZWEncodingInfo * __restrict ei,_csid_t * __restrict csid,_index_t * __restrict idx,wchar_t wc)4522fe8fb19SBen Gras _citrus_ZW_stdenc_wctocs(_ZWEncodingInfo * __restrict ei,
4532fe8fb19SBen Gras 	_csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
4542fe8fb19SBen Gras {
4552fe8fb19SBen Gras 	/* ei seems to be unused */
4562fe8fb19SBen Gras 	_DIAGASSERT(csid != NULL);
4572fe8fb19SBen Gras 	_DIAGASSERT(idx != NULL);
4582fe8fb19SBen Gras 
4592fe8fb19SBen Gras 	*csid = (_csid_t)(wc <= 0x7FU) ? 0 : 1;
4602fe8fb19SBen Gras 	*idx = (_index_t)wc;
4612fe8fb19SBen Gras 
4622fe8fb19SBen Gras 	return 0;
4632fe8fb19SBen Gras }
4642fe8fb19SBen Gras 
4652fe8fb19SBen Gras static __inline int
4662fe8fb19SBen Gras /*ARGSUSED*/
_citrus_ZW_stdenc_cstowc(_ZWEncodingInfo * __restrict ei,wchar_t * __restrict wc,_csid_t csid,_index_t idx)4672fe8fb19SBen Gras _citrus_ZW_stdenc_cstowc(_ZWEncodingInfo * __restrict ei,
4682fe8fb19SBen Gras 	 wchar_t * __restrict wc, _csid_t csid, _index_t idx)
4692fe8fb19SBen Gras {
4702fe8fb19SBen Gras 	/* ei seems to be unused */
4712fe8fb19SBen Gras 	_DIAGASSERT(wc != NULL);
4722fe8fb19SBen Gras 
4732fe8fb19SBen Gras 	switch (csid) {
4742fe8fb19SBen Gras 	case 0: case 1:
4752fe8fb19SBen Gras 		break;
4762fe8fb19SBen Gras 	default:
4772fe8fb19SBen Gras 		return EINVAL;
4782fe8fb19SBen Gras 	}
4792fe8fb19SBen Gras 	*wc = (wchar_t)idx;
4802fe8fb19SBen Gras 
4812fe8fb19SBen Gras 	return 0;
4822fe8fb19SBen Gras }
4832fe8fb19SBen Gras 
4842fe8fb19SBen Gras static void
4852fe8fb19SBen Gras /*ARGSUSED*/
_citrus_ZW_encoding_module_uninit(_ZWEncodingInfo * ei)4862fe8fb19SBen Gras _citrus_ZW_encoding_module_uninit(_ZWEncodingInfo *ei)
4872fe8fb19SBen Gras {
4882fe8fb19SBen Gras }
4892fe8fb19SBen Gras 
4902fe8fb19SBen Gras static int
4912fe8fb19SBen Gras /*ARGSUSED*/
_citrus_ZW_encoding_module_init(_ZWEncodingInfo * __restrict ei,const void * __restrict var,size_t lenvar)4922fe8fb19SBen Gras _citrus_ZW_encoding_module_init(_ZWEncodingInfo * __restrict ei,
4932fe8fb19SBen Gras 	const void *__restrict var, size_t lenvar)
4942fe8fb19SBen Gras {
4952fe8fb19SBen Gras 	return 0;
4962fe8fb19SBen Gras }
4972fe8fb19SBen Gras 
4982fe8fb19SBen Gras /* ----------------------------------------------------------------------
4992fe8fb19SBen Gras  * public interface for ctype
5002fe8fb19SBen Gras  */
5012fe8fb19SBen Gras 
5022fe8fb19SBen Gras _CITRUS_CTYPE_DECLS(ZW);
5032fe8fb19SBen Gras _CITRUS_CTYPE_DEF_OPS(ZW);
5042fe8fb19SBen Gras 
5052fe8fb19SBen Gras #include "citrus_ctype_template.h"
5062fe8fb19SBen Gras 
5072fe8fb19SBen Gras /* ----------------------------------------------------------------------
5082fe8fb19SBen Gras  * public interface for stdenc
5092fe8fb19SBen Gras  */
5102fe8fb19SBen Gras 
5112fe8fb19SBen Gras _CITRUS_STDENC_DECLS(ZW);
5122fe8fb19SBen Gras _CITRUS_STDENC_DEF_OPS(ZW);
5132fe8fb19SBen Gras 
5142fe8fb19SBen Gras #include "citrus_stdenc_template.h"
515