1*abd1934eSrillig /* $NetBSD: citrus_zw.c,v 1.6 2022/04/19 20:32:14 rillig Exp $ */
28033a5b0Stnozaki
38033a5b0Stnozaki /*-
48033a5b0Stnozaki * Copyright (c)2004, 2006 Citrus Project,
58033a5b0Stnozaki * All rights reserved.
68033a5b0Stnozaki *
78033a5b0Stnozaki * Redistribution and use in source and binary forms, with or without
88033a5b0Stnozaki * modification, are permitted provided that the following conditions
98033a5b0Stnozaki * are met:
108033a5b0Stnozaki * 1. Redistributions of source code must retain the above copyright
118033a5b0Stnozaki * notice, this list of conditions and the following disclaimer.
128033a5b0Stnozaki * 2. Redistributions in binary form must reproduce the above copyright
138033a5b0Stnozaki * notice, this list of conditions and the following disclaimer in the
148033a5b0Stnozaki * documentation and/or other materials provided with the distribution.
158033a5b0Stnozaki *
168033a5b0Stnozaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
178033a5b0Stnozaki * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
188033a5b0Stnozaki * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
198033a5b0Stnozaki * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
208033a5b0Stnozaki * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
218033a5b0Stnozaki * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
228033a5b0Stnozaki * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
238033a5b0Stnozaki * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
248033a5b0Stnozaki * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
258033a5b0Stnozaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
268033a5b0Stnozaki * SUCH DAMAGE.
278033a5b0Stnozaki *
288033a5b0Stnozaki */
298033a5b0Stnozaki
308033a5b0Stnozaki #include <sys/cdefs.h>
318033a5b0Stnozaki #if defined(LIB_SCCS) && !defined(lint)
32*abd1934eSrillig __RCSID("$NetBSD: citrus_zw.c,v 1.6 2022/04/19 20:32:14 rillig Exp $");
338033a5b0Stnozaki #endif /* LIB_SCCS and not lint */
348033a5b0Stnozaki
358033a5b0Stnozaki #include <sys/types.h>
368033a5b0Stnozaki #include <assert.h>
378033a5b0Stnozaki #include <errno.h>
388033a5b0Stnozaki #include <string.h>
398033a5b0Stnozaki #include <stdio.h>
408033a5b0Stnozaki #include <stdint.h>
418033a5b0Stnozaki #include <stdlib.h>
428033a5b0Stnozaki #include <stddef.h>
438033a5b0Stnozaki #include <wchar.h>
448033a5b0Stnozaki #include <limits.h>
458033a5b0Stnozaki
468033a5b0Stnozaki #include "citrus_namespace.h"
478033a5b0Stnozaki #include "citrus_types.h"
488033a5b0Stnozaki #include "citrus_module.h"
498033a5b0Stnozaki #include "citrus_ctype.h"
508033a5b0Stnozaki #include "citrus_stdenc.h"
518033a5b0Stnozaki #include "citrus_zw.h"
528033a5b0Stnozaki
538033a5b0Stnozaki /* ----------------------------------------------------------------------
548033a5b0Stnozaki * private stuffs used by templates
558033a5b0Stnozaki */
568033a5b0Stnozaki
578033a5b0Stnozaki typedef struct {
588033a5b0Stnozaki int dummy;
598033a5b0Stnozaki } _ZWEncodingInfo;
608033a5b0Stnozaki
618033a5b0Stnozaki typedef enum {
628033a5b0Stnozaki NONE, AMBIGIOUS, ASCII, GB2312
638033a5b0Stnozaki } _ZWCharset;
648033a5b0Stnozaki
658033a5b0Stnozaki typedef struct {
668033a5b0Stnozaki int chlen;
678033a5b0Stnozaki char ch[4];
688033a5b0Stnozaki _ZWCharset charset;
698033a5b0Stnozaki } _ZWState;
708033a5b0Stnozaki
718033a5b0Stnozaki typedef struct {
728033a5b0Stnozaki _ZWEncodingInfo ei;
738033a5b0Stnozaki struct {
748033a5b0Stnozaki /* for future multi-locale facility */
758033a5b0Stnozaki _ZWState s_mblen;
768033a5b0Stnozaki _ZWState s_mbrlen;
778033a5b0Stnozaki _ZWState s_mbrtowc;
788033a5b0Stnozaki _ZWState s_mbtowc;
798033a5b0Stnozaki _ZWState s_mbsrtowcs;
80bf2f4b3eSjoerg _ZWState s_mbsnrtowcs;
818033a5b0Stnozaki _ZWState s_wcrtomb;
828033a5b0Stnozaki _ZWState s_wcsrtombs;
83bf2f4b3eSjoerg _ZWState s_wcsnrtombs;
848033a5b0Stnozaki _ZWState s_wctomb;
858033a5b0Stnozaki } states;
868033a5b0Stnozaki } _ZWCTypeInfo;
878033a5b0Stnozaki
888033a5b0Stnozaki #define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
898033a5b0Stnozaki #define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
908033a5b0Stnozaki
918033a5b0Stnozaki #define _FUNCNAME(m) _citrus_ZW_##m
928033a5b0Stnozaki #define _ENCODING_INFO _ZWEncodingInfo
938033a5b0Stnozaki #define _CTYPE_INFO _ZWCTypeInfo
948033a5b0Stnozaki #define _ENCODING_STATE _ZWState
958033a5b0Stnozaki #define _ENCODING_MB_CUR_MAX(_ei_) MB_LEN_MAX
968033a5b0Stnozaki #define _ENCODING_IS_STATE_DEPENDENT 1
978033a5b0Stnozaki #define _STATE_NEEDS_EXPLICIT_INIT(_ps_) ((_ps_)->charset != NONE)
988033a5b0Stnozaki
998033a5b0Stnozaki static __inline void
1008033a5b0Stnozaki /*ARGSUSED*/
_citrus_ZW_init_state(_ZWEncodingInfo * __restrict ei,_ZWState * __restrict psenc)1018033a5b0Stnozaki _citrus_ZW_init_state(_ZWEncodingInfo * __restrict ei,
1028033a5b0Stnozaki _ZWState * __restrict psenc)
1038033a5b0Stnozaki {
1048033a5b0Stnozaki /* ei my be unused */
1058033a5b0Stnozaki _DIAGASSERT(psenc != NULL);
1068033a5b0Stnozaki
1078033a5b0Stnozaki psenc->chlen = 0;
1088033a5b0Stnozaki psenc->charset = NONE;
1098033a5b0Stnozaki }
1108033a5b0Stnozaki
1118033a5b0Stnozaki static __inline void
1128033a5b0Stnozaki /*ARGSUSED*/
_citrus_ZW_pack_state(_ZWEncodingInfo * __restrict ei,void * __restrict pspriv,const _ZWState * __restrict psenc)1138033a5b0Stnozaki _citrus_ZW_pack_state(_ZWEncodingInfo * __restrict ei,
1148033a5b0Stnozaki void *__restrict pspriv, const _ZWState * __restrict psenc)
1158033a5b0Stnozaki {
1168033a5b0Stnozaki /* ei may be unused */
1178033a5b0Stnozaki _DIAGASSERT(pspriv != NULL);
1188033a5b0Stnozaki _DIAGASSERT(psenc != NULL);
1198033a5b0Stnozaki
1208033a5b0Stnozaki memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
1218033a5b0Stnozaki }
1228033a5b0Stnozaki
1238033a5b0Stnozaki static __inline void
1248033a5b0Stnozaki /*ARGSUSED*/
_citrus_ZW_unpack_state(_ZWEncodingInfo * __restrict ei,_ZWState * __restrict psenc,const void * __restrict pspriv)1258033a5b0Stnozaki _citrus_ZW_unpack_state(_ZWEncodingInfo * __restrict ei,
1268033a5b0Stnozaki _ZWState * __restrict psenc, const void * __restrict pspriv)
1278033a5b0Stnozaki {
1288033a5b0Stnozaki /* ei may be unused */
1298033a5b0Stnozaki _DIAGASSERT(psenc != NULL);
1308033a5b0Stnozaki _DIAGASSERT(pspriv != NULL);
1318033a5b0Stnozaki
1328033a5b0Stnozaki memcpy((void *)psenc, pspriv, sizeof(*psenc));
1338033a5b0Stnozaki }
1348033a5b0Stnozaki
1358033a5b0Stnozaki 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)1368033a5b0Stnozaki _citrus_ZW_mbrtowc_priv(_ZWEncodingInfo * __restrict ei,
1378033a5b0Stnozaki wchar_t * __restrict pwc, const char **__restrict s, size_t n,
1388033a5b0Stnozaki _ZWState * __restrict psenc, size_t * __restrict nresult)
1398033a5b0Stnozaki {
1408033a5b0Stnozaki const char *s0;
1413fb79e82Stnozaki int ch, len;
1428033a5b0Stnozaki wchar_t wc;
1438033a5b0Stnozaki
1448033a5b0Stnozaki /* ei may be unused */
1458033a5b0Stnozaki /* pwc may be null */
1468033a5b0Stnozaki _DIAGASSERT(s != NULL);
1478033a5b0Stnozaki _DIAGASSERT(psenc != NULL);
1488033a5b0Stnozaki _DIAGASSERT(nresult != NULL);
1498033a5b0Stnozaki
1508033a5b0Stnozaki if (*s == NULL) {
1518033a5b0Stnozaki _citrus_ZW_init_state(ei, psenc);
1528033a5b0Stnozaki *nresult = (size_t)_ENCODING_IS_STATE_DEPENDENT;
1538033a5b0Stnozaki return 0;
1548033a5b0Stnozaki }
1558033a5b0Stnozaki s0 = *s;
1563fb79e82Stnozaki len = 0;
1578033a5b0Stnozaki
1588033a5b0Stnozaki #define STORE \
1598033a5b0Stnozaki do { \
1608033a5b0Stnozaki if (n-- < 1) { \
1618033a5b0Stnozaki *nresult = (size_t)-2; \
1628033a5b0Stnozaki *s = s0; \
1638033a5b0Stnozaki return 0; \
1648033a5b0Stnozaki } \
1658033a5b0Stnozaki ch = (unsigned char)*s0++; \
1663fb79e82Stnozaki if (len++ > MB_LEN_MAX || ch > 0x7F)\
1678033a5b0Stnozaki goto ilseq; \
1688033a5b0Stnozaki psenc->ch[psenc->chlen++] = ch; \
169*abd1934eSrillig } while (0)
1708033a5b0Stnozaki
1718033a5b0Stnozaki loop:
1728033a5b0Stnozaki switch (psenc->charset) {
1738033a5b0Stnozaki case ASCII:
1748033a5b0Stnozaki switch (psenc->chlen) {
1758033a5b0Stnozaki case 0:
1768033a5b0Stnozaki STORE;
1778033a5b0Stnozaki switch (psenc->ch[0]) {
1788033a5b0Stnozaki case '\0': case '\n':
1798033a5b0Stnozaki psenc->charset = NONE;
1808033a5b0Stnozaki }
1818033a5b0Stnozaki /*FALLTHROUGH*/
1828033a5b0Stnozaki case 1:
1838033a5b0Stnozaki break;
1848033a5b0Stnozaki default:
1858033a5b0Stnozaki return EINVAL;
1868033a5b0Stnozaki }
1878033a5b0Stnozaki ch = (unsigned char)psenc->ch[0];
1888033a5b0Stnozaki if (ch > 0x7F)
1898033a5b0Stnozaki goto ilseq;
1908033a5b0Stnozaki wc = (wchar_t)ch;
1918033a5b0Stnozaki psenc->chlen = 0;
1928033a5b0Stnozaki break;
1938033a5b0Stnozaki case NONE:
1948033a5b0Stnozaki if (psenc->chlen != 0)
1958033a5b0Stnozaki return EINVAL;
1968033a5b0Stnozaki STORE;
1978033a5b0Stnozaki ch = (unsigned char)psenc->ch[0];
1988033a5b0Stnozaki if (ch != 'z') {
1998033a5b0Stnozaki if (ch != '\n' && ch != '\0')
2008033a5b0Stnozaki psenc->charset = ASCII;
2018033a5b0Stnozaki wc = (wchar_t)ch;
2028033a5b0Stnozaki psenc->chlen = 0;
2038033a5b0Stnozaki break;
2048033a5b0Stnozaki }
2058033a5b0Stnozaki psenc->charset = AMBIGIOUS;
2068033a5b0Stnozaki psenc->chlen = 0;
2078033a5b0Stnozaki /* FALLTHROUGH */
2088033a5b0Stnozaki case AMBIGIOUS:
2098033a5b0Stnozaki if (psenc->chlen != 0)
2108033a5b0Stnozaki return EINVAL;
2118033a5b0Stnozaki STORE;
2128033a5b0Stnozaki if (psenc->ch[0] != 'W') {
2138033a5b0Stnozaki psenc->charset = ASCII;
2148033a5b0Stnozaki wc = L'z';
2158033a5b0Stnozaki break;
2168033a5b0Stnozaki }
2178033a5b0Stnozaki psenc->charset = GB2312;
2188033a5b0Stnozaki psenc->chlen = 0;
2198033a5b0Stnozaki /* FALLTHROUGH */
2208033a5b0Stnozaki case GB2312:
2218033a5b0Stnozaki switch (psenc->chlen) {
2228033a5b0Stnozaki case 0:
2238033a5b0Stnozaki STORE;
2248033a5b0Stnozaki ch = (unsigned char)psenc->ch[0];
2258033a5b0Stnozaki if (ch == '\0') {
2268033a5b0Stnozaki psenc->charset = NONE;
2278033a5b0Stnozaki wc = (wchar_t)ch;
2288033a5b0Stnozaki psenc->chlen = 0;
2298033a5b0Stnozaki break;
2308033a5b0Stnozaki } else if (ch == '\n') {
2318033a5b0Stnozaki psenc->charset = NONE;
2328033a5b0Stnozaki psenc->chlen = 0;
2338033a5b0Stnozaki goto loop;
2348033a5b0Stnozaki }
2358033a5b0Stnozaki /*FALLTHROUGH*/
2368033a5b0Stnozaki case 1:
2378033a5b0Stnozaki STORE;
2388033a5b0Stnozaki if (psenc->ch[0] == ' ') {
2398033a5b0Stnozaki ch = (unsigned char)psenc->ch[1];
2408033a5b0Stnozaki wc = (wchar_t)ch;
2418033a5b0Stnozaki psenc->chlen = 0;
2428033a5b0Stnozaki break;
2438033a5b0Stnozaki } else if (psenc->ch[0] == '#') {
2448033a5b0Stnozaki ch = (unsigned char)psenc->ch[1];
2458033a5b0Stnozaki if (ch == '\n') {
2468033a5b0Stnozaki psenc->charset = NONE;
2478033a5b0Stnozaki wc = (wchar_t)ch;
2488033a5b0Stnozaki psenc->chlen = 0;
2498033a5b0Stnozaki break;
2508033a5b0Stnozaki } else if (ch == ' ') {
2518033a5b0Stnozaki wc = (wchar_t)ch;
2528033a5b0Stnozaki psenc->chlen = 0;
2538033a5b0Stnozaki break;
2548033a5b0Stnozaki }
2558033a5b0Stnozaki }
2568033a5b0Stnozaki ch = (unsigned char)psenc->ch[0];
2578033a5b0Stnozaki if (ch < 0x21 || ch > 0x7E)
2588033a5b0Stnozaki goto ilseq;
2598033a5b0Stnozaki wc = (wchar_t)(ch << 8);
2608033a5b0Stnozaki ch = (unsigned char)psenc->ch[1];
2618033a5b0Stnozaki if (ch < 0x21 || ch > 0x7E) {
2628033a5b0Stnozaki ilseq:
2638033a5b0Stnozaki *nresult = (size_t)-1;
2648033a5b0Stnozaki return EILSEQ;
2658033a5b0Stnozaki }
2668033a5b0Stnozaki wc |= (wchar_t)ch;
2678033a5b0Stnozaki psenc->chlen = 0;
2688033a5b0Stnozaki break;
2698033a5b0Stnozaki default:
2708033a5b0Stnozaki return EINVAL;
2718033a5b0Stnozaki }
2728033a5b0Stnozaki break;
2738033a5b0Stnozaki default:
2748033a5b0Stnozaki return EINVAL;
2758033a5b0Stnozaki }
2768033a5b0Stnozaki if (pwc != NULL)
2778033a5b0Stnozaki *pwc = wc;
2788033a5b0Stnozaki
2793fb79e82Stnozaki *nresult = (size_t)(wc == 0 ? 0 : len);
2808033a5b0Stnozaki *s = s0;
2818033a5b0Stnozaki
2828033a5b0Stnozaki return 0;
2838033a5b0Stnozaki }
2848033a5b0Stnozaki
2858033a5b0Stnozaki static int
2868033a5b0Stnozaki /*ARGSUSED*/
_citrus_ZW_wcrtomb_priv(_ZWEncodingInfo * __restrict ei,char * __restrict s,size_t n,wchar_t wc,_ZWState * __restrict psenc,size_t * __restrict nresult)2878033a5b0Stnozaki _citrus_ZW_wcrtomb_priv(_ZWEncodingInfo * __restrict ei,
2888033a5b0Stnozaki char *__restrict s, size_t n, wchar_t wc,
2898033a5b0Stnozaki _ZWState * __restrict psenc, size_t * __restrict nresult)
2908033a5b0Stnozaki {
2918033a5b0Stnozaki int ch;
2928033a5b0Stnozaki
2938033a5b0Stnozaki /* ei may be null */
2948033a5b0Stnozaki _DIAGASSERT(s != NULL);
2958033a5b0Stnozaki _DIAGASSERT(psenc != NULL);
2968033a5b0Stnozaki _DIAGASSERT(nresult != NULL);
2978033a5b0Stnozaki
2988033a5b0Stnozaki if (psenc->chlen != 0)
2998033a5b0Stnozaki return EINVAL;
3008033a5b0Stnozaki if ((uint32_t)wc <= 0x7F) {
3018033a5b0Stnozaki ch = (unsigned char)wc;
3028033a5b0Stnozaki switch (psenc->charset) {
3038033a5b0Stnozaki case NONE:
3048033a5b0Stnozaki if (ch == '\0' || ch == '\n') {
3058033a5b0Stnozaki psenc->ch[psenc->chlen++] = ch;
3068033a5b0Stnozaki } else {
3078033a5b0Stnozaki if (n < 4)
3088033a5b0Stnozaki return E2BIG;
3098033a5b0Stnozaki n -= 4;
3108033a5b0Stnozaki psenc->ch[psenc->chlen++] = 'z';
3118033a5b0Stnozaki psenc->ch[psenc->chlen++] = 'W';
3128033a5b0Stnozaki psenc->ch[psenc->chlen++] = ' ';
3138033a5b0Stnozaki psenc->ch[psenc->chlen++] = ch;
3148033a5b0Stnozaki psenc->charset = GB2312;
3158033a5b0Stnozaki }
3168033a5b0Stnozaki break;
3178033a5b0Stnozaki case GB2312:
3188033a5b0Stnozaki if (n < 2)
3198033a5b0Stnozaki return E2BIG;
3208033a5b0Stnozaki n -= 2;
3218033a5b0Stnozaki if (ch == '\0') {
3228033a5b0Stnozaki psenc->ch[psenc->chlen++] = '\n';
3238033a5b0Stnozaki psenc->ch[psenc->chlen++] = '\0';
3248033a5b0Stnozaki psenc->charset = NONE;
3258033a5b0Stnozaki } else if (ch == '\n') {
3268033a5b0Stnozaki psenc->ch[psenc->chlen++] = '#';
3278033a5b0Stnozaki psenc->ch[psenc->chlen++] = '\n';
3288033a5b0Stnozaki psenc->charset = NONE;
3298033a5b0Stnozaki } else {
3308033a5b0Stnozaki psenc->ch[psenc->chlen++] = ' ';
3318033a5b0Stnozaki psenc->ch[psenc->chlen++] = ch;
3328033a5b0Stnozaki }
3338033a5b0Stnozaki break;
3348033a5b0Stnozaki default:
3358033a5b0Stnozaki return EINVAL;
3368033a5b0Stnozaki }
3378033a5b0Stnozaki } else if ((uint32_t)wc <= 0x7E7E) {
3388033a5b0Stnozaki switch (psenc->charset) {
3398033a5b0Stnozaki case NONE:
3408033a5b0Stnozaki if (n < 2)
3418033a5b0Stnozaki return E2BIG;
3428033a5b0Stnozaki n -= 2;
3438033a5b0Stnozaki psenc->ch[psenc->chlen++] = 'z';
3448033a5b0Stnozaki psenc->ch[psenc->chlen++] = 'W';
3458033a5b0Stnozaki psenc->charset = GB2312;
3468033a5b0Stnozaki /* FALLTHROUGH*/
3478033a5b0Stnozaki case GB2312:
3488033a5b0Stnozaki if (n < 2)
3498033a5b0Stnozaki return E2BIG;
3508033a5b0Stnozaki n -= 2;
3518033a5b0Stnozaki ch = (wc >> 8) & 0xFF;
3528033a5b0Stnozaki if (ch < 0x21 || ch > 0x7E)
3538033a5b0Stnozaki goto ilseq;
3548033a5b0Stnozaki psenc->ch[psenc->chlen++] = ch;
3558033a5b0Stnozaki ch = wc & 0xFF;
3568033a5b0Stnozaki if (ch < 0x21 || ch > 0x7E)
3578033a5b0Stnozaki goto ilseq;
3588033a5b0Stnozaki psenc->ch[psenc->chlen++] = ch;
3598033a5b0Stnozaki break;
3608033a5b0Stnozaki default:
3618033a5b0Stnozaki return EINVAL;
3628033a5b0Stnozaki }
3638033a5b0Stnozaki } else {
3648033a5b0Stnozaki ilseq:
3658033a5b0Stnozaki *nresult = (size_t)-1;
3668033a5b0Stnozaki return EILSEQ;
3678033a5b0Stnozaki }
3688033a5b0Stnozaki memcpy(s, psenc->ch, psenc->chlen);
3698033a5b0Stnozaki *nresult = psenc->chlen;
3708033a5b0Stnozaki psenc->chlen = 0;
3718033a5b0Stnozaki
3728033a5b0Stnozaki return 0;
3738033a5b0Stnozaki }
3748033a5b0Stnozaki
3758033a5b0Stnozaki static int
3768033a5b0Stnozaki /*ARGSUSED*/
_citrus_ZW_put_state_reset(_ZWEncodingInfo * __restrict ei,char * __restrict s,size_t n,_ZWState * __restrict psenc,size_t * __restrict nresult)3778033a5b0Stnozaki _citrus_ZW_put_state_reset(_ZWEncodingInfo * __restrict ei,
3788033a5b0Stnozaki char * __restrict s, size_t n,
3798033a5b0Stnozaki _ZWState * __restrict psenc, size_t * __restrict nresult)
3808033a5b0Stnozaki {
3818033a5b0Stnozaki /* ei may be unused */
3828033a5b0Stnozaki _DIAGASSERT(s != NULL);
3838033a5b0Stnozaki _DIAGASSERT(psenc != NULL);
3848033a5b0Stnozaki _DIAGASSERT(nresult != NULL);
3858033a5b0Stnozaki
3868033a5b0Stnozaki if (psenc->chlen != 0)
3878033a5b0Stnozaki return EINVAL;
3888033a5b0Stnozaki switch (psenc->charset) {
3898033a5b0Stnozaki case GB2312:
3908033a5b0Stnozaki if (n-- < 1)
3918033a5b0Stnozaki return E2BIG;
3928033a5b0Stnozaki psenc->ch[psenc->chlen++] = '\n';
3938033a5b0Stnozaki psenc->charset = NONE;
3948033a5b0Stnozaki /*FALLTHROUGH*/
3958033a5b0Stnozaki case NONE:
3968033a5b0Stnozaki *nresult = psenc->chlen;
3978033a5b0Stnozaki if (psenc->chlen > 0) {
3988033a5b0Stnozaki memcpy(s, psenc->ch, psenc->chlen);
3998033a5b0Stnozaki psenc->chlen = 0;
4008033a5b0Stnozaki }
4018033a5b0Stnozaki break;
4028033a5b0Stnozaki default:
4038033a5b0Stnozaki return EINVAL;
4048033a5b0Stnozaki }
4058033a5b0Stnozaki
4068033a5b0Stnozaki return 0;
4078033a5b0Stnozaki }
4088033a5b0Stnozaki
4098033a5b0Stnozaki static __inline int
4108033a5b0Stnozaki /*ARGSUSED*/
_citrus_ZW_stdenc_get_state_desc_generic(_ZWEncodingInfo * __restrict ei,_ZWState * __restrict psenc,int * __restrict rstate)4118033a5b0Stnozaki _citrus_ZW_stdenc_get_state_desc_generic(_ZWEncodingInfo * __restrict ei,
4128033a5b0Stnozaki _ZWState * __restrict psenc, int * __restrict rstate)
4138033a5b0Stnozaki {
4148033a5b0Stnozaki /* ei may be unused */
4158033a5b0Stnozaki _DIAGASSERT(psenc != NULL);
4168033a5b0Stnozaki _DIAGASSERT(rstate != NULL);
4178033a5b0Stnozaki
4188033a5b0Stnozaki switch (psenc->charset) {
4198033a5b0Stnozaki case NONE:
4208033a5b0Stnozaki if (psenc->chlen != 0)
4218033a5b0Stnozaki return EINVAL;
4228033a5b0Stnozaki *rstate = _STDENC_SDGEN_INITIAL;
4238033a5b0Stnozaki break;
4248033a5b0Stnozaki case AMBIGIOUS:
4258033a5b0Stnozaki if (psenc->chlen != 0)
4268033a5b0Stnozaki return EINVAL;
4278033a5b0Stnozaki *rstate = _STDENC_SDGEN_INCOMPLETE_SHIFT;
4288033a5b0Stnozaki break;
4298033a5b0Stnozaki case ASCII:
4308033a5b0Stnozaki case GB2312:
4318033a5b0Stnozaki switch (psenc->chlen) {
4328033a5b0Stnozaki case 0:
4338033a5b0Stnozaki *rstate = _STDENC_SDGEN_STABLE;
4348033a5b0Stnozaki break;
4358033a5b0Stnozaki case 1:
4368033a5b0Stnozaki *rstate = (psenc->ch[0] == '#')
4378033a5b0Stnozaki ? _STDENC_SDGEN_INCOMPLETE_SHIFT
4388033a5b0Stnozaki : _STDENC_SDGEN_INCOMPLETE_CHAR;
4398033a5b0Stnozaki break;
4408033a5b0Stnozaki default:
4418033a5b0Stnozaki return EINVAL;
4428033a5b0Stnozaki }
4438033a5b0Stnozaki break;
4448033a5b0Stnozaki default:
4458033a5b0Stnozaki return EINVAL;
4468033a5b0Stnozaki }
4478033a5b0Stnozaki return 0;
4488033a5b0Stnozaki }
4498033a5b0Stnozaki
4508033a5b0Stnozaki static __inline int
4518033a5b0Stnozaki /*ARGSUSED*/
_citrus_ZW_stdenc_wctocs(_ZWEncodingInfo * __restrict ei,_csid_t * __restrict csid,_index_t * __restrict idx,wchar_t wc)4528033a5b0Stnozaki _citrus_ZW_stdenc_wctocs(_ZWEncodingInfo * __restrict ei,
4538033a5b0Stnozaki _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
4548033a5b0Stnozaki {
4558033a5b0Stnozaki /* ei seems to be unused */
4568033a5b0Stnozaki _DIAGASSERT(csid != NULL);
4578033a5b0Stnozaki _DIAGASSERT(idx != NULL);
4588033a5b0Stnozaki
4598033a5b0Stnozaki *csid = (_csid_t)(wc <= 0x7FU) ? 0 : 1;
4608033a5b0Stnozaki *idx = (_index_t)wc;
4618033a5b0Stnozaki
4628033a5b0Stnozaki return 0;
4638033a5b0Stnozaki }
4648033a5b0Stnozaki
4658033a5b0Stnozaki static __inline int
4668033a5b0Stnozaki /*ARGSUSED*/
_citrus_ZW_stdenc_cstowc(_ZWEncodingInfo * __restrict ei,wchar_t * __restrict wc,_csid_t csid,_index_t idx)4678033a5b0Stnozaki _citrus_ZW_stdenc_cstowc(_ZWEncodingInfo * __restrict ei,
4688033a5b0Stnozaki wchar_t * __restrict wc, _csid_t csid, _index_t idx)
4698033a5b0Stnozaki {
4708033a5b0Stnozaki /* ei seems to be unused */
4718033a5b0Stnozaki _DIAGASSERT(wc != NULL);
4728033a5b0Stnozaki
4738033a5b0Stnozaki switch (csid) {
4748033a5b0Stnozaki case 0: case 1:
4758033a5b0Stnozaki break;
4768033a5b0Stnozaki default:
4778033a5b0Stnozaki return EINVAL;
4788033a5b0Stnozaki }
4798033a5b0Stnozaki *wc = (wchar_t)idx;
4808033a5b0Stnozaki
4818033a5b0Stnozaki return 0;
4828033a5b0Stnozaki }
4838033a5b0Stnozaki
4848033a5b0Stnozaki static void
4858033a5b0Stnozaki /*ARGSUSED*/
_citrus_ZW_encoding_module_uninit(_ZWEncodingInfo * ei)4868033a5b0Stnozaki _citrus_ZW_encoding_module_uninit(_ZWEncodingInfo *ei)
4878033a5b0Stnozaki {
4888033a5b0Stnozaki }
4898033a5b0Stnozaki
4908033a5b0Stnozaki static int
4918033a5b0Stnozaki /*ARGSUSED*/
_citrus_ZW_encoding_module_init(_ZWEncodingInfo * __restrict ei,const void * __restrict var,size_t lenvar)4928033a5b0Stnozaki _citrus_ZW_encoding_module_init(_ZWEncodingInfo * __restrict ei,
4938033a5b0Stnozaki const void *__restrict var, size_t lenvar)
4948033a5b0Stnozaki {
4958033a5b0Stnozaki return 0;
4968033a5b0Stnozaki }
4978033a5b0Stnozaki
4988033a5b0Stnozaki /* ----------------------------------------------------------------------
4998033a5b0Stnozaki * public interface for ctype
5008033a5b0Stnozaki */
5018033a5b0Stnozaki
5028033a5b0Stnozaki _CITRUS_CTYPE_DECLS(ZW);
5038033a5b0Stnozaki _CITRUS_CTYPE_DEF_OPS(ZW);
5048033a5b0Stnozaki
5058033a5b0Stnozaki #include "citrus_ctype_template.h"
5068033a5b0Stnozaki
5078033a5b0Stnozaki /* ----------------------------------------------------------------------
5088033a5b0Stnozaki * public interface for stdenc
5098033a5b0Stnozaki */
5108033a5b0Stnozaki
5118033a5b0Stnozaki _CITRUS_STDENC_DECLS(ZW);
5128033a5b0Stnozaki _CITRUS_STDENC_DEF_OPS(ZW);
5138033a5b0Stnozaki
5148033a5b0Stnozaki #include "citrus_stdenc_template.h"
515