1*84d9c625SLionel Sambuc /* $NetBSD: citrus_iso2022.c,v 1.23 2013/05/28 16:57:56 joerg Exp $ */
22fe8fb19SBen Gras
32fe8fb19SBen Gras /*-
42fe8fb19SBen Gras * Copyright (c)1999, 2002 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 * $Citrus: xpg4dl/FreeBSD/lib/libc/locale/iso2022.c,v 1.23 2001/06/21 01:51:44 yamt Exp $
292fe8fb19SBen Gras */
302fe8fb19SBen Gras
312fe8fb19SBen Gras #include <sys/cdefs.h>
322fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
33*84d9c625SLionel Sambuc __RCSID("$NetBSD: citrus_iso2022.c,v 1.23 2013/05/28 16:57:56 joerg Exp $");
342fe8fb19SBen Gras #endif /* LIBC_SCCS and not lint */
352fe8fb19SBen Gras
362fe8fb19SBen Gras #include <assert.h>
372fe8fb19SBen Gras #include <errno.h>
382fe8fb19SBen Gras #include <string.h>
392fe8fb19SBen Gras #include <stdio.h>
402fe8fb19SBen Gras #include <stdlib.h>
412fe8fb19SBen Gras #include <stddef.h>
422fe8fb19SBen Gras #include <wchar.h>
432fe8fb19SBen Gras #include <sys/types.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_iso2022.h"
522fe8fb19SBen Gras
532fe8fb19SBen Gras
542fe8fb19SBen Gras /* ----------------------------------------------------------------------
552fe8fb19SBen Gras * private stuffs used by templates
562fe8fb19SBen Gras */
572fe8fb19SBen Gras
582fe8fb19SBen Gras
592fe8fb19SBen Gras /*
602fe8fb19SBen Gras * wchar_t mappings:
612fe8fb19SBen Gras * ASCII (ESC ( B) 00000000 00000000 00000000 0xxxxxxx
622fe8fb19SBen Gras * iso-8859-1 (ESC , A) 00000000 00000000 00000000 1xxxxxxx
632fe8fb19SBen Gras * 94 charset (ESC ( F) 0fffffff 00000000 00000000 0xxxxxxx
642fe8fb19SBen Gras * 94 charset (ESC ( M F) 0fffffff 1mmmmmmm 00000000 0xxxxxxx
652fe8fb19SBen Gras * 96 charset (ESC , F) 0fffffff 00000000 00000000 1xxxxxxx
662fe8fb19SBen Gras * 96 charset (ESC , M F) 0fffffff 1mmmmmmm 00000000 1xxxxxxx
672fe8fb19SBen Gras * 94x94 charset (ESC $ ( F) 0fffffff 00000000 0xxxxxxx 0xxxxxxx
682fe8fb19SBen Gras * 96x96 charset (ESC $ , F) 0fffffff 00000000 0xxxxxxx 1xxxxxxx
692fe8fb19SBen Gras * 94x94 charset (ESC & V ESC $ ( F)
702fe8fb19SBen Gras * 0fffffff 1vvvvvvv 0xxxxxxx 0xxxxxxx
712fe8fb19SBen Gras * 94x94x94 charset (ESC $ ( F) 0fffffff 0xxxxxxx 0xxxxxxx 0xxxxxxx
722fe8fb19SBen Gras * 96x96x96 charset (ESC $ , F) 0fffffff 0xxxxxxx 0xxxxxxx 1xxxxxxx
732fe8fb19SBen Gras * reserved for UCS4 co-existence (UCS4 is 31bit encoding thanks to mohta bit)
742fe8fb19SBen Gras * 1xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
752fe8fb19SBen Gras */
762fe8fb19SBen Gras
772fe8fb19SBen Gras typedef struct {
782fe8fb19SBen Gras u_char type;
792fe8fb19SBen Gras #define CS94 (0U)
802fe8fb19SBen Gras #define CS96 (1U)
812fe8fb19SBen Gras #define CS94MULTI (2U)
822fe8fb19SBen Gras #define CS96MULTI (3U)
832fe8fb19SBen Gras
842fe8fb19SBen Gras u_char final;
852fe8fb19SBen Gras u_char interm;
862fe8fb19SBen Gras u_char vers;
872fe8fb19SBen Gras } _ISO2022Charset;
882fe8fb19SBen Gras
892fe8fb19SBen Gras static const _ISO2022Charset ascii = { CS94, 'B', '\0', '\0' };
902fe8fb19SBen Gras static const _ISO2022Charset iso88591 = { CS96, 'A', '\0', '\0' };
912fe8fb19SBen Gras
922fe8fb19SBen Gras typedef struct {
932fe8fb19SBen Gras _ISO2022Charset g[4];
942fe8fb19SBen Gras /* need 3 bits to hold -1, 0, ..., 3 */
952fe8fb19SBen Gras int gl:3,
962fe8fb19SBen Gras gr:3,
972fe8fb19SBen Gras singlegl:3,
982fe8fb19SBen Gras singlegr:3;
992fe8fb19SBen Gras char ch[7]; /* longest escape sequence (ESC & V ESC $ ( F) */
1002fe8fb19SBen Gras int chlen;
1012fe8fb19SBen Gras int flags;
1022fe8fb19SBen Gras #define _ISO2022STATE_FLAG_INITIALIZED 1
1032fe8fb19SBen Gras } _ISO2022State;
1042fe8fb19SBen Gras
1052fe8fb19SBen Gras typedef struct {
1062fe8fb19SBen Gras _ISO2022Charset *recommend[4];
1072fe8fb19SBen Gras size_t recommendsize[4];
1082fe8fb19SBen Gras _ISO2022Charset initg[4];
1092fe8fb19SBen Gras int maxcharset;
1102fe8fb19SBen Gras int flags;
1112fe8fb19SBen Gras #define F_8BIT 0x0001
1122fe8fb19SBen Gras #define F_NOOLD 0x0002
1132fe8fb19SBen Gras #define F_SI 0x0010 /*0F*/
1142fe8fb19SBen Gras #define F_SO 0x0020 /*0E*/
1152fe8fb19SBen Gras #define F_LS0 0x0010 /*0F*/
1162fe8fb19SBen Gras #define F_LS1 0x0020 /*0E*/
1172fe8fb19SBen Gras #define F_LS2 0x0040 /*ESC n*/
1182fe8fb19SBen Gras #define F_LS3 0x0080 /*ESC o*/
1192fe8fb19SBen Gras #define F_LS1R 0x0100 /*ESC ~*/
1202fe8fb19SBen Gras #define F_LS2R 0x0200 /*ESC }*/
1212fe8fb19SBen Gras #define F_LS3R 0x0400 /*ESC |*/
1222fe8fb19SBen Gras #define F_SS2 0x0800 /*ESC N*/
1232fe8fb19SBen Gras #define F_SS3 0x1000 /*ESC O*/
1242fe8fb19SBen Gras #define F_SS2R 0x2000 /*8E*/
1252fe8fb19SBen Gras #define F_SS3R 0x4000 /*8F*/
1262fe8fb19SBen Gras } _ISO2022EncodingInfo;
1272fe8fb19SBen Gras typedef struct {
1282fe8fb19SBen Gras _ISO2022EncodingInfo ei;
1292fe8fb19SBen Gras struct {
1302fe8fb19SBen Gras /* for future multi-locale facility */
1312fe8fb19SBen Gras _ISO2022State s_mblen;
1322fe8fb19SBen Gras _ISO2022State s_mbrlen;
1332fe8fb19SBen Gras _ISO2022State s_mbrtowc;
1342fe8fb19SBen Gras _ISO2022State s_mbtowc;
1352fe8fb19SBen Gras _ISO2022State s_mbsrtowcs;
136*84d9c625SLionel Sambuc _ISO2022State s_mbsnrtowcs;
1372fe8fb19SBen Gras _ISO2022State s_wcrtomb;
1382fe8fb19SBen Gras _ISO2022State s_wcsrtombs;
139*84d9c625SLionel Sambuc _ISO2022State s_wcsnrtombs;
1402fe8fb19SBen Gras _ISO2022State s_wctomb;
1412fe8fb19SBen Gras } states;
1422fe8fb19SBen Gras } _ISO2022CTypeInfo;
1432fe8fb19SBen Gras
1442fe8fb19SBen Gras #define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
1452fe8fb19SBen Gras #define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
1462fe8fb19SBen Gras
1472fe8fb19SBen Gras #define _FUNCNAME(m) _citrus_ISO2022_##m
1482fe8fb19SBen Gras #define _ENCODING_INFO _ISO2022EncodingInfo
1492fe8fb19SBen Gras #define _CTYPE_INFO _ISO2022CTypeInfo
1502fe8fb19SBen Gras #define _ENCODING_STATE _ISO2022State
1512fe8fb19SBen Gras #define _ENCODING_MB_CUR_MAX(_ei_) MB_LEN_MAX
1522fe8fb19SBen Gras #define _ENCODING_IS_STATE_DEPENDENT 1
1532fe8fb19SBen Gras #define _STATE_NEEDS_EXPLICIT_INIT(_ps_) \
1542fe8fb19SBen Gras (!((_ps_)->flags & _ISO2022STATE_FLAG_INITIALIZED))
1552fe8fb19SBen Gras
1562fe8fb19SBen Gras
1572fe8fb19SBen Gras #define _ISO2022INVALID (wchar_t)-1
1582fe8fb19SBen Gras
isc0(__uint8_t x)1592fe8fb19SBen Gras static __inline int isc0(__uint8_t x) { return ((x & 0x1f) == x); }
isc1(__uint8_t x)1602fe8fb19SBen Gras static __inline int isc1(__uint8_t x) { return (0x80 <= x && x <= 0x9f); }
iscntl(__uint8_t x)1612fe8fb19SBen Gras static __inline int iscntl(__uint8_t x) { return (isc0(x) || isc1(x) || x == 0x7f); }
is94(__uint8_t x)1622fe8fb19SBen Gras static __inline int is94(__uint8_t x) { return (0x21 <= x && x <= 0x7e); }
is96(__uint8_t x)1632fe8fb19SBen Gras static __inline int is96(__uint8_t x) { return (0x20 <= x && x <= 0x7f); }
isecma(__uint8_t x)1642fe8fb19SBen Gras static __inline int isecma(__uint8_t x) { return (0x30 <= x && x <= 0x7f); }
isinterm(__uint8_t x)1652fe8fb19SBen Gras static __inline int isinterm(__uint8_t x) { return (0x20 <= x && x <= 0x2f); }
isthree(__uint8_t x)1662fe8fb19SBen Gras static __inline int isthree(__uint8_t x) { return (0x60 <= x && x <= 0x6f); }
1672fe8fb19SBen Gras
1682fe8fb19SBen Gras static __inline int
getcs(const char * __restrict p,_ISO2022Charset * __restrict cs)1692fe8fb19SBen Gras getcs(const char * __restrict p, _ISO2022Charset * __restrict cs)
1702fe8fb19SBen Gras {
1712fe8fb19SBen Gras
1722fe8fb19SBen Gras _DIAGASSERT(p != NULL);
1732fe8fb19SBen Gras _DIAGASSERT(cs != NULL);
1742fe8fb19SBen Gras
1752fe8fb19SBen Gras if (!strncmp(p, "94$", 3) && p[3] && !p[4]) {
1762fe8fb19SBen Gras cs->final = (u_char)(p[3] & 0xff);
1772fe8fb19SBen Gras cs->interm = '\0';
1782fe8fb19SBen Gras cs->vers = '\0';
1792fe8fb19SBen Gras cs->type = CS94MULTI;
1802fe8fb19SBen Gras } else if (!strncmp(p, "96$", 3) && p[3] && !p[4]) {
1812fe8fb19SBen Gras cs->final = (u_char)(p[3] & 0xff);
1822fe8fb19SBen Gras cs->interm = '\0';
1832fe8fb19SBen Gras cs->vers = '\0';
1842fe8fb19SBen Gras cs->type = CS96MULTI;
1852fe8fb19SBen Gras } else if (!strncmp(p, "94", 2) && p[2] && !p[3]) {
1862fe8fb19SBen Gras cs->final = (u_char)(p[2] & 0xff);
1872fe8fb19SBen Gras cs->interm = '\0';
1882fe8fb19SBen Gras cs->vers = '\0';
1892fe8fb19SBen Gras cs->type = CS94;
1902fe8fb19SBen Gras } else if (!strncmp(p, "96", 2) && p[2] && !p[3]) {
1912fe8fb19SBen Gras cs->final = (u_char )(p[2] & 0xff);
1922fe8fb19SBen Gras cs->interm = '\0';
1932fe8fb19SBen Gras cs->vers = '\0';
1942fe8fb19SBen Gras cs->type = CS96;
1952fe8fb19SBen Gras } else {
1962fe8fb19SBen Gras return 1;
1972fe8fb19SBen Gras }
1982fe8fb19SBen Gras
1992fe8fb19SBen Gras return 0;
2002fe8fb19SBen Gras }
2012fe8fb19SBen Gras
2022fe8fb19SBen Gras
2032fe8fb19SBen Gras #define _NOTMATCH 0
2042fe8fb19SBen Gras #define _MATCH 1
2052fe8fb19SBen Gras #define _PARSEFAIL 2
2062fe8fb19SBen Gras
2072fe8fb19SBen Gras static __inline int
get_recommend(_ISO2022EncodingInfo * __restrict ei,const char * __restrict token)2082fe8fb19SBen Gras get_recommend(_ISO2022EncodingInfo * __restrict ei,
2092fe8fb19SBen Gras const char * __restrict token)
2102fe8fb19SBen Gras {
2112fe8fb19SBen Gras int i;
2122fe8fb19SBen Gras _ISO2022Charset cs, *p;
2132fe8fb19SBen Gras
2142fe8fb19SBen Gras if (!strchr("0123", token[0]) || token[1] != '=')
2152fe8fb19SBen Gras return (_NOTMATCH);
2162fe8fb19SBen Gras
2172fe8fb19SBen Gras if (getcs(&token[2], &cs) == 0)
2182fe8fb19SBen Gras ;
2192fe8fb19SBen Gras else if (!strcmp(&token[2], "94")) {
2202fe8fb19SBen Gras cs.final = (u_char)(token[4]);
2212fe8fb19SBen Gras cs.interm = '\0';
2222fe8fb19SBen Gras cs.vers = '\0';
2232fe8fb19SBen Gras cs.type = CS94;
2242fe8fb19SBen Gras } else if (!strcmp(&token[2], "96")) {
2252fe8fb19SBen Gras cs.final = (u_char)(token[4]);
2262fe8fb19SBen Gras cs.interm = '\0';
2272fe8fb19SBen Gras cs.vers = '\0';
2282fe8fb19SBen Gras cs.type = CS96;
2292fe8fb19SBen Gras } else if (!strcmp(&token[2], "94$")) {
2302fe8fb19SBen Gras cs.final = (u_char)(token[5]);
2312fe8fb19SBen Gras cs.interm = '\0';
2322fe8fb19SBen Gras cs.vers = '\0';
2332fe8fb19SBen Gras cs.type = CS94MULTI;
2342fe8fb19SBen Gras } else if (!strcmp(&token[2], "96$")) {
2352fe8fb19SBen Gras cs.final = (u_char)(token[5]);
2362fe8fb19SBen Gras cs.interm = '\0';
2372fe8fb19SBen Gras cs.vers = '\0';
2382fe8fb19SBen Gras cs.type = CS96MULTI;
2392fe8fb19SBen Gras } else {
2402fe8fb19SBen Gras return (_PARSEFAIL);
2412fe8fb19SBen Gras }
2422fe8fb19SBen Gras
2432fe8fb19SBen Gras i = token[0] - '0';
2442fe8fb19SBen Gras if (!ei->recommend[i]) {
2452fe8fb19SBen Gras ei->recommend[i] = malloc(sizeof(_ISO2022Charset));
2462fe8fb19SBen Gras } else {
2472fe8fb19SBen Gras p = realloc(ei->recommend[i],
2482fe8fb19SBen Gras sizeof(_ISO2022Charset) * (ei->recommendsize[i] + 1));
2492fe8fb19SBen Gras if (!p)
2502fe8fb19SBen Gras return (_PARSEFAIL);
2512fe8fb19SBen Gras ei->recommend[i] = p;
2522fe8fb19SBen Gras }
2532fe8fb19SBen Gras if (!ei->recommend[i])
2542fe8fb19SBen Gras return (_PARSEFAIL);
2552fe8fb19SBen Gras ei->recommendsize[i]++;
2562fe8fb19SBen Gras
2572fe8fb19SBen Gras (ei->recommend[i] + (ei->recommendsize[i] - 1))->final = cs.final;
2582fe8fb19SBen Gras (ei->recommend[i] + (ei->recommendsize[i] - 1))->interm = cs.interm;
2592fe8fb19SBen Gras (ei->recommend[i] + (ei->recommendsize[i] - 1))->vers = cs.vers;
2602fe8fb19SBen Gras (ei->recommend[i] + (ei->recommendsize[i] - 1))->type = cs.type;
2612fe8fb19SBen Gras
2622fe8fb19SBen Gras return (_MATCH);
2632fe8fb19SBen Gras }
2642fe8fb19SBen Gras
2652fe8fb19SBen Gras static __inline int
get_initg(_ISO2022EncodingInfo * __restrict ei,const char * __restrict token)2662fe8fb19SBen Gras get_initg(_ISO2022EncodingInfo * __restrict ei,
2672fe8fb19SBen Gras const char * __restrict token)
2682fe8fb19SBen Gras {
2692fe8fb19SBen Gras _ISO2022Charset cs;
2702fe8fb19SBen Gras
2712fe8fb19SBen Gras if (strncmp("INIT", &token[0], 4) ||
2722fe8fb19SBen Gras !strchr("0123", token[4]) ||
2732fe8fb19SBen Gras token[5] != '=')
2742fe8fb19SBen Gras return (_NOTMATCH);
2752fe8fb19SBen Gras
2762fe8fb19SBen Gras if (getcs(&token[6], &cs) != 0)
2772fe8fb19SBen Gras return (_PARSEFAIL);
2782fe8fb19SBen Gras
2792fe8fb19SBen Gras ei->initg[token[4] - '0'].type = cs.type;
2802fe8fb19SBen Gras ei->initg[token[4] - '0'].final = cs.final;
2812fe8fb19SBen Gras ei->initg[token[4] - '0'].interm = cs.interm;
2822fe8fb19SBen Gras ei->initg[token[4] - '0'].vers = cs.vers;
2832fe8fb19SBen Gras
2842fe8fb19SBen Gras return (_MATCH);
2852fe8fb19SBen Gras }
2862fe8fb19SBen Gras
2872fe8fb19SBen Gras static __inline int
get_max(_ISO2022EncodingInfo * __restrict ei,const char * __restrict token)2882fe8fb19SBen Gras get_max(_ISO2022EncodingInfo * __restrict ei,
2892fe8fb19SBen Gras const char * __restrict token)
2902fe8fb19SBen Gras {
2912fe8fb19SBen Gras if (!strcmp(token, "MAX1")) {
2922fe8fb19SBen Gras ei->maxcharset = 1;
2932fe8fb19SBen Gras } else if (!strcmp(token, "MAX2")) {
2942fe8fb19SBen Gras ei->maxcharset = 2;
2952fe8fb19SBen Gras } else if (!strcmp(token, "MAX3")) {
2962fe8fb19SBen Gras ei->maxcharset = 3;
2972fe8fb19SBen Gras } else
2982fe8fb19SBen Gras return (_NOTMATCH);
2992fe8fb19SBen Gras
3002fe8fb19SBen Gras return (_MATCH);
3012fe8fb19SBen Gras }
3022fe8fb19SBen Gras
3032fe8fb19SBen Gras
3042fe8fb19SBen Gras static __inline int
get_flags(_ISO2022EncodingInfo * __restrict ei,const char * __restrict token)3052fe8fb19SBen Gras get_flags(_ISO2022EncodingInfo * __restrict ei,
3062fe8fb19SBen Gras const char * __restrict token)
3072fe8fb19SBen Gras {
3082fe8fb19SBen Gras int i;
3092fe8fb19SBen Gras static struct {
3102fe8fb19SBen Gras const char *tag;
3112fe8fb19SBen Gras int flag;
3122fe8fb19SBen Gras } const tags[] = {
3132fe8fb19SBen Gras { "DUMMY", 0 },
3142fe8fb19SBen Gras { "8BIT", F_8BIT },
3152fe8fb19SBen Gras { "NOOLD", F_NOOLD },
3162fe8fb19SBen Gras { "SI", F_SI },
3172fe8fb19SBen Gras { "SO", F_SO },
3182fe8fb19SBen Gras { "LS0", F_LS0 },
3192fe8fb19SBen Gras { "LS1", F_LS1 },
3202fe8fb19SBen Gras { "LS2", F_LS2 },
3212fe8fb19SBen Gras { "LS3", F_LS3 },
3222fe8fb19SBen Gras { "LS1R", F_LS1R },
3232fe8fb19SBen Gras { "LS2R", F_LS2R },
3242fe8fb19SBen Gras { "LS3R", F_LS3R },
3252fe8fb19SBen Gras { "SS2", F_SS2 },
3262fe8fb19SBen Gras { "SS3", F_SS3 },
3272fe8fb19SBen Gras { "SS2R", F_SS2R },
3282fe8fb19SBen Gras { "SS3R", F_SS3R },
3292fe8fb19SBen Gras { NULL, 0 }
3302fe8fb19SBen Gras };
3312fe8fb19SBen Gras
3322fe8fb19SBen Gras for (i = 0; tags[i].tag; i++) {
3332fe8fb19SBen Gras if (!strcmp(token, tags[i].tag)) {
3342fe8fb19SBen Gras ei->flags |= tags[i].flag;
3352fe8fb19SBen Gras return (_MATCH);
3362fe8fb19SBen Gras }
3372fe8fb19SBen Gras }
3382fe8fb19SBen Gras
3392fe8fb19SBen Gras return (_NOTMATCH);
3402fe8fb19SBen Gras }
3412fe8fb19SBen Gras
3422fe8fb19SBen Gras
3432fe8fb19SBen Gras static __inline int
_citrus_ISO2022_parse_variable(_ISO2022EncodingInfo * __restrict ei,const void * __restrict var,size_t lenvar)3442fe8fb19SBen Gras _citrus_ISO2022_parse_variable(_ISO2022EncodingInfo * __restrict ei,
3452fe8fb19SBen Gras const void * __restrict var, size_t lenvar)
3462fe8fb19SBen Gras {
3472fe8fb19SBen Gras char const *v, *e;
3482fe8fb19SBen Gras char buf[20];
3492fe8fb19SBen Gras int i, len, ret;
3502fe8fb19SBen Gras
3512fe8fb19SBen Gras _DIAGASSERT(ei != NULL);
3522fe8fb19SBen Gras
3532fe8fb19SBen Gras
3542fe8fb19SBen Gras /*
3552fe8fb19SBen Gras * parse VARIABLE section.
3562fe8fb19SBen Gras */
3572fe8fb19SBen Gras
3582fe8fb19SBen Gras if (!var)
3592fe8fb19SBen Gras return (EFTYPE);
3602fe8fb19SBen Gras
3612fe8fb19SBen Gras v = (const char *) var;
3622fe8fb19SBen Gras
3632fe8fb19SBen Gras /* initialize structure */
3642fe8fb19SBen Gras ei->maxcharset = 0;
3652fe8fb19SBen Gras for (i = 0; i < 4; i++) {
3662fe8fb19SBen Gras ei->recommend[i] = NULL;
3672fe8fb19SBen Gras ei->recommendsize[i] = 0;
3682fe8fb19SBen Gras }
3692fe8fb19SBen Gras ei->flags = 0;
3702fe8fb19SBen Gras
3712fe8fb19SBen Gras while (*v) {
3722fe8fb19SBen Gras while (*v == ' ' || *v == '\t')
3732fe8fb19SBen Gras ++v;
3742fe8fb19SBen Gras
3752fe8fb19SBen Gras /* find the token */
3762fe8fb19SBen Gras e = v;
3772fe8fb19SBen Gras while (*e && *e != ' ' && *e != '\t')
3782fe8fb19SBen Gras ++e;
3792fe8fb19SBen Gras
3802fe8fb19SBen Gras len = e-v;
3812fe8fb19SBen Gras if (len == 0)
3822fe8fb19SBen Gras break;
3832fe8fb19SBen Gras if (len>=sizeof(buf))
3842fe8fb19SBen Gras goto parsefail;
3852fe8fb19SBen Gras snprintf(buf, sizeof(buf), "%.*s", len, v);
3862fe8fb19SBen Gras
3872fe8fb19SBen Gras if ((ret = get_recommend(ei, buf)) != _NOTMATCH)
3882fe8fb19SBen Gras ;
3892fe8fb19SBen Gras else if ((ret = get_initg(ei, buf)) != _NOTMATCH)
3902fe8fb19SBen Gras ;
3912fe8fb19SBen Gras else if ((ret = get_max(ei, buf)) != _NOTMATCH)
3922fe8fb19SBen Gras ;
3932fe8fb19SBen Gras else if ((ret = get_flags(ei, buf)) != _NOTMATCH)
3942fe8fb19SBen Gras ;
3952fe8fb19SBen Gras else
3962fe8fb19SBen Gras ret = _PARSEFAIL;
3972fe8fb19SBen Gras if (ret==_PARSEFAIL)
3982fe8fb19SBen Gras goto parsefail;
3992fe8fb19SBen Gras v = e;
4002fe8fb19SBen Gras
4012fe8fb19SBen Gras }
4022fe8fb19SBen Gras
4032fe8fb19SBen Gras return (0);
4042fe8fb19SBen Gras
4052fe8fb19SBen Gras parsefail:
4062fe8fb19SBen Gras free(ei->recommend[0]);
4072fe8fb19SBen Gras free(ei->recommend[1]);
4082fe8fb19SBen Gras free(ei->recommend[2]);
4092fe8fb19SBen Gras free(ei->recommend[3]);
4102fe8fb19SBen Gras
4112fe8fb19SBen Gras return (EFTYPE);
4122fe8fb19SBen Gras }
4132fe8fb19SBen Gras
4142fe8fb19SBen Gras static __inline void
4152fe8fb19SBen Gras /*ARGSUSED*/
_citrus_ISO2022_init_state(_ISO2022EncodingInfo * __restrict ei,_ISO2022State * __restrict s)4162fe8fb19SBen Gras _citrus_ISO2022_init_state(_ISO2022EncodingInfo * __restrict ei,
4172fe8fb19SBen Gras _ISO2022State * __restrict s)
4182fe8fb19SBen Gras {
4192fe8fb19SBen Gras int i;
4202fe8fb19SBen Gras
4212fe8fb19SBen Gras memset(s, 0, sizeof(*s));
4222fe8fb19SBen Gras s->gl = 0;
4232fe8fb19SBen Gras s->gr = (ei->flags & F_8BIT) ? 1 : -1;
4242fe8fb19SBen Gras
4252fe8fb19SBen Gras for (i = 0; i < 4; i++) {
4262fe8fb19SBen Gras if (ei->initg[i].final) {
4272fe8fb19SBen Gras s->g[i].type = ei->initg[i].type;
4282fe8fb19SBen Gras s->g[i].final = ei->initg[i].final;
4292fe8fb19SBen Gras s->g[i].interm = ei->initg[i].interm;
4302fe8fb19SBen Gras }
4312fe8fb19SBen Gras }
4322fe8fb19SBen Gras s->singlegl = s->singlegr = -1;
4332fe8fb19SBen Gras s->flags |= _ISO2022STATE_FLAG_INITIALIZED;
4342fe8fb19SBen Gras }
4352fe8fb19SBen Gras
4362fe8fb19SBen Gras static __inline void
4372fe8fb19SBen Gras /*ARGSUSED*/
_citrus_ISO2022_pack_state(_ISO2022EncodingInfo * __restrict ei,void * __restrict pspriv,const _ISO2022State * __restrict s)4382fe8fb19SBen Gras _citrus_ISO2022_pack_state(_ISO2022EncodingInfo * __restrict ei,
4392fe8fb19SBen Gras void * __restrict pspriv,
4402fe8fb19SBen Gras const _ISO2022State * __restrict s)
4412fe8fb19SBen Gras {
4422fe8fb19SBen Gras memcpy(pspriv, (const void *)s, sizeof(*s));
4432fe8fb19SBen Gras }
4442fe8fb19SBen Gras
4452fe8fb19SBen Gras static __inline void
4462fe8fb19SBen Gras /*ARGSUSED*/
_citrus_ISO2022_unpack_state(_ISO2022EncodingInfo * __restrict ei,_ISO2022State * __restrict s,const void * __restrict pspriv)4472fe8fb19SBen Gras _citrus_ISO2022_unpack_state(_ISO2022EncodingInfo * __restrict ei,
4482fe8fb19SBen Gras _ISO2022State * __restrict s,
4492fe8fb19SBen Gras const void * __restrict pspriv)
4502fe8fb19SBen Gras {
4512fe8fb19SBen Gras memcpy((void *)s, pspriv, sizeof(*s));
4522fe8fb19SBen Gras }
4532fe8fb19SBen Gras
4542fe8fb19SBen Gras static int
4552fe8fb19SBen Gras /*ARGSUSED*/
_citrus_ISO2022_encoding_module_init(_ISO2022EncodingInfo * __restrict ei,const void * __restrict var,size_t lenvar)4562fe8fb19SBen Gras _citrus_ISO2022_encoding_module_init(_ISO2022EncodingInfo * __restrict ei,
4572fe8fb19SBen Gras const void * __restrict var,
4582fe8fb19SBen Gras size_t lenvar)
4592fe8fb19SBen Gras {
4602fe8fb19SBen Gras
4612fe8fb19SBen Gras _DIAGASSERT(ei != NULL);
4622fe8fb19SBen Gras
4632fe8fb19SBen Gras return _citrus_ISO2022_parse_variable(ei, var, lenvar);
4642fe8fb19SBen Gras }
4652fe8fb19SBen Gras
4662fe8fb19SBen Gras static void
4672fe8fb19SBen Gras /*ARGSUSED*/
_citrus_ISO2022_encoding_module_uninit(_ISO2022EncodingInfo * ei)4682fe8fb19SBen Gras _citrus_ISO2022_encoding_module_uninit(_ISO2022EncodingInfo *ei)
4692fe8fb19SBen Gras {
4702fe8fb19SBen Gras }
4712fe8fb19SBen Gras
4722fe8fb19SBen Gras #define ESC '\033'
4732fe8fb19SBen Gras #define ECMA -1
4742fe8fb19SBen Gras #define INTERM -2
4752fe8fb19SBen Gras #define OECMA -3
4762fe8fb19SBen Gras static const struct seqtable {
4772fe8fb19SBen Gras int type;
4782fe8fb19SBen Gras int csoff;
4792fe8fb19SBen Gras int finaloff;
4802fe8fb19SBen Gras int intermoff;
4812fe8fb19SBen Gras int versoff;
4822fe8fb19SBen Gras int len;
4832fe8fb19SBen Gras int chars[10];
4842fe8fb19SBen Gras } seqtable[] = {
4852fe8fb19SBen Gras /* G0 94MULTI special */
4862fe8fb19SBen Gras { CS94MULTI, -1, 2, -1, -1, 3, { ESC, '$', OECMA }, },
4872fe8fb19SBen Gras /* G0 94MULTI special with version identification */
4882fe8fb19SBen Gras { CS94MULTI, -1, 5, -1, 2, 6, { ESC, '&', ECMA, ESC, '$', OECMA }, },
4892fe8fb19SBen Gras /* G? 94 */
4902fe8fb19SBen Gras { CS94, 1, 2, -1, -1, 3, { ESC, CS94, ECMA, }, },
4912fe8fb19SBen Gras /* G? 94 with 2nd intermediate char */
4922fe8fb19SBen Gras { CS94, 1, 3, 2, -1, 4, { ESC, CS94, INTERM, ECMA, }, },
4932fe8fb19SBen Gras /* G? 96 */
4942fe8fb19SBen Gras { CS96, 1, 2, -1, -1, 3, { ESC, CS96, ECMA, }, },
4952fe8fb19SBen Gras /* G? 96 with 2nd intermediate char */
4962fe8fb19SBen Gras { CS96, 1, 3, 2, -1, 4, { ESC, CS96, INTERM, ECMA, }, },
4972fe8fb19SBen Gras /* G? 94MULTI */
4982fe8fb19SBen Gras { CS94MULTI, 2, 3, -1, -1, 4, { ESC, '$', CS94, ECMA, }, },
4992fe8fb19SBen Gras /* G? 96MULTI */
5002fe8fb19SBen Gras { CS96MULTI, 2, 3, -1, -1, 4, { ESC, '$', CS96, ECMA, }, },
5012fe8fb19SBen Gras /* G? 94MULTI with version specification */
5022fe8fb19SBen Gras { CS94MULTI, 5, 6, -1, 2, 7, { ESC, '&', ECMA, ESC, '$', CS94, ECMA, }, },
5032fe8fb19SBen Gras /* LS2/3 */
5042fe8fb19SBen Gras { -1, -1, -1, -1, -1, 2, { ESC, 'n', }, },
5052fe8fb19SBen Gras { -1, -1, -1, -1, -1, 2, { ESC, 'o', }, },
5062fe8fb19SBen Gras /* LS1/2/3R */
5072fe8fb19SBen Gras { -1, -1, -1, -1, -1, 2, { ESC, '~', }, },
5082fe8fb19SBen Gras { -1, -1, -1, -1, -1, 2, { ESC, /*{*/ '}', }, },
5092fe8fb19SBen Gras { -1, -1, -1, -1, -1, 2, { ESC, '|', }, },
5102fe8fb19SBen Gras /* SS2/3 */
5112fe8fb19SBen Gras { -1, -1, -1, -1, -1, 2, { ESC, 'N', }, },
5122fe8fb19SBen Gras { -1, -1, -1, -1, -1, 2, { ESC, 'O', }, },
5132fe8fb19SBen Gras /* end of records */
5142fe8fb19SBen Gras { 0, }
5152fe8fb19SBen Gras };
5162fe8fb19SBen Gras
5172fe8fb19SBen Gras static int
seqmatch(const char * __restrict s,size_t n,const struct seqtable * __restrict sp)5182fe8fb19SBen Gras seqmatch(const char * __restrict s, size_t n,
5192fe8fb19SBen Gras const struct seqtable * __restrict sp)
5202fe8fb19SBen Gras {
5212fe8fb19SBen Gras const int *p;
5222fe8fb19SBen Gras
5232fe8fb19SBen Gras _DIAGASSERT(s != NULL);
5242fe8fb19SBen Gras _DIAGASSERT(sp != NULL);
5252fe8fb19SBen Gras
5262fe8fb19SBen Gras p = sp->chars;
5272fe8fb19SBen Gras while (p - sp->chars < n && p - sp->chars < sp->len) {
5282fe8fb19SBen Gras switch (*p) {
5292fe8fb19SBen Gras case ECMA:
5302fe8fb19SBen Gras if (!isecma(*s))
5312fe8fb19SBen Gras goto terminate;
5322fe8fb19SBen Gras break;
5332fe8fb19SBen Gras case OECMA:
5342fe8fb19SBen Gras if (*s && strchr("@AB", *s))
5352fe8fb19SBen Gras break;
5362fe8fb19SBen Gras else
5372fe8fb19SBen Gras goto terminate;
5382fe8fb19SBen Gras case INTERM:
5392fe8fb19SBen Gras if (!isinterm(*s))
5402fe8fb19SBen Gras goto terminate;
5412fe8fb19SBen Gras break;
5422fe8fb19SBen Gras case CS94:
5432fe8fb19SBen Gras if (*s && strchr("()*+", *s))
5442fe8fb19SBen Gras break;
5452fe8fb19SBen Gras else
5462fe8fb19SBen Gras goto terminate;
5472fe8fb19SBen Gras case CS96:
5482fe8fb19SBen Gras if (*s && strchr(",-./", *s))
5492fe8fb19SBen Gras break;
5502fe8fb19SBen Gras else
5512fe8fb19SBen Gras goto terminate;
5522fe8fb19SBen Gras default:
5532fe8fb19SBen Gras if (*s != *p)
5542fe8fb19SBen Gras goto terminate;
5552fe8fb19SBen Gras break;
5562fe8fb19SBen Gras }
5572fe8fb19SBen Gras
5582fe8fb19SBen Gras p++;
5592fe8fb19SBen Gras s++;
5602fe8fb19SBen Gras }
5612fe8fb19SBen Gras
5622fe8fb19SBen Gras terminate:
5632fe8fb19SBen Gras return p - sp->chars;
5642fe8fb19SBen Gras }
5652fe8fb19SBen Gras
5662fe8fb19SBen Gras static wchar_t
_ISO2022_sgetwchar(_ISO2022EncodingInfo * __restrict ei,const char * __restrict string,size_t n,const char ** __restrict result,_ISO2022State * __restrict psenc)5672fe8fb19SBen Gras _ISO2022_sgetwchar(_ISO2022EncodingInfo * __restrict ei,
5682fe8fb19SBen Gras const char * __restrict string, size_t n,
5692fe8fb19SBen Gras const char ** __restrict result,
5702fe8fb19SBen Gras _ISO2022State * __restrict psenc)
5712fe8fb19SBen Gras {
5722fe8fb19SBen Gras wchar_t wchar = 0;
5732fe8fb19SBen Gras int cur;
5742fe8fb19SBen Gras const struct seqtable *sp;
5752fe8fb19SBen Gras int nmatch;
5762fe8fb19SBen Gras int i;
5772fe8fb19SBen Gras
5782fe8fb19SBen Gras _DIAGASSERT(ei != NULL);
5792fe8fb19SBen Gras _DIAGASSERT(psenc != NULL);
5802fe8fb19SBen Gras _DIAGASSERT(string != NULL);
5812fe8fb19SBen Gras /* result may be NULL */
5822fe8fb19SBen Gras
5832fe8fb19SBen Gras while (1) {
5842fe8fb19SBen Gras /* SI/SO */
5852fe8fb19SBen Gras if (1 <= n && string[0] == '\017') {
5862fe8fb19SBen Gras psenc->gl = 0;
5872fe8fb19SBen Gras string++;
5882fe8fb19SBen Gras n--;
5892fe8fb19SBen Gras continue;
5902fe8fb19SBen Gras }
5912fe8fb19SBen Gras if (1 <= n && string[0] == '\016') {
5922fe8fb19SBen Gras psenc->gl = 1;
5932fe8fb19SBen Gras string++;
5942fe8fb19SBen Gras n--;
5952fe8fb19SBen Gras continue;
5962fe8fb19SBen Gras }
5972fe8fb19SBen Gras
5982fe8fb19SBen Gras /* SS2/3R */
5992fe8fb19SBen Gras if (1 <= n && string[0] && strchr("\217\216", string[0])) {
6002fe8fb19SBen Gras psenc->singlegl = psenc->singlegr =
6012fe8fb19SBen Gras (string[0] - '\216') + 2;
6022fe8fb19SBen Gras string++;
6032fe8fb19SBen Gras n--;
6042fe8fb19SBen Gras continue;
6052fe8fb19SBen Gras }
6062fe8fb19SBen Gras
6072fe8fb19SBen Gras /* eat the letter if this is not ESC */
6082fe8fb19SBen Gras if (1 <= n && string[0] != '\033')
6092fe8fb19SBen Gras break;
6102fe8fb19SBen Gras
6112fe8fb19SBen Gras /* look for a perfect match from escape sequences */
6122fe8fb19SBen Gras for (sp = &seqtable[0]; sp->len; sp++) {
6132fe8fb19SBen Gras nmatch = seqmatch(string, n, sp);
6142fe8fb19SBen Gras if (sp->len == nmatch && n >= sp->len)
6152fe8fb19SBen Gras break;
6162fe8fb19SBen Gras }
6172fe8fb19SBen Gras
6182fe8fb19SBen Gras if (!sp->len)
6192fe8fb19SBen Gras goto notseq;
6202fe8fb19SBen Gras
6212fe8fb19SBen Gras if (sp->type != -1) {
6222fe8fb19SBen Gras if (sp->csoff == -1)
6232fe8fb19SBen Gras i = 0;
6242fe8fb19SBen Gras else {
6252fe8fb19SBen Gras switch (sp->type) {
6262fe8fb19SBen Gras case CS94:
6272fe8fb19SBen Gras case CS94MULTI:
6282fe8fb19SBen Gras i = string[sp->csoff] - '(';
6292fe8fb19SBen Gras break;
6302fe8fb19SBen Gras case CS96:
6312fe8fb19SBen Gras case CS96MULTI:
6322fe8fb19SBen Gras i = string[sp->csoff] - ',';
6332fe8fb19SBen Gras break;
6342fe8fb19SBen Gras default:
6352fe8fb19SBen Gras return (_ISO2022INVALID);
6362fe8fb19SBen Gras }
6372fe8fb19SBen Gras }
6382fe8fb19SBen Gras psenc->g[i].type = sp->type;
6392fe8fb19SBen Gras psenc->g[i].final = '\0';
6402fe8fb19SBen Gras psenc->g[i].interm = '\0';
6412fe8fb19SBen Gras psenc->g[i].vers = '\0';
6422fe8fb19SBen Gras /* sp->finaloff must not be -1 */
6432fe8fb19SBen Gras if (sp->finaloff != -1)
6442fe8fb19SBen Gras psenc->g[i].final = string[sp->finaloff];
6452fe8fb19SBen Gras if (sp->intermoff != -1)
6462fe8fb19SBen Gras psenc->g[i].interm = string[sp->intermoff];
6472fe8fb19SBen Gras if (sp->versoff != -1)
6482fe8fb19SBen Gras psenc->g[i].vers = string[sp->versoff];
6492fe8fb19SBen Gras
6502fe8fb19SBen Gras string += sp->len;
6512fe8fb19SBen Gras n -= sp->len;
6522fe8fb19SBen Gras continue;
6532fe8fb19SBen Gras }
6542fe8fb19SBen Gras
6552fe8fb19SBen Gras /* LS2/3 */
6562fe8fb19SBen Gras if (2 <= n && string[0] == '\033'
6572fe8fb19SBen Gras && string[1] && strchr("no", string[1])) {
6582fe8fb19SBen Gras psenc->gl = string[1] - 'n' + 2;
6592fe8fb19SBen Gras string += 2;
6602fe8fb19SBen Gras n -= 2;
6612fe8fb19SBen Gras continue;
6622fe8fb19SBen Gras }
6632fe8fb19SBen Gras
6642fe8fb19SBen Gras /* LS1/2/3R */
6652fe8fb19SBen Gras /* XXX: { for vi showmatch */
6662fe8fb19SBen Gras if (2 <= n && string[0] == '\033'
6672fe8fb19SBen Gras && string[1] && strchr("~}|", string[1])) {
6682fe8fb19SBen Gras psenc->gr = 3 - (string[1] - '|');
6692fe8fb19SBen Gras string += 2;
6702fe8fb19SBen Gras n -= 2;
6712fe8fb19SBen Gras continue;
6722fe8fb19SBen Gras }
6732fe8fb19SBen Gras
6742fe8fb19SBen Gras /* SS2/3 */
6752fe8fb19SBen Gras if (2 <= n && string[0] == '\033'
6762fe8fb19SBen Gras && string[1] && strchr("NO", string[1])) {
6772fe8fb19SBen Gras psenc->singlegl = (string[1] - 'N') + 2;
6782fe8fb19SBen Gras string += 2;
6792fe8fb19SBen Gras n -= 2;
6802fe8fb19SBen Gras continue;
6812fe8fb19SBen Gras }
6822fe8fb19SBen Gras
6832fe8fb19SBen Gras notseq:
6842fe8fb19SBen Gras /*
6852fe8fb19SBen Gras * if we've got an unknown escape sequence, eat the ESC at the
6862fe8fb19SBen Gras * head. otherwise, wait till full escape sequence comes.
6872fe8fb19SBen Gras */
6882fe8fb19SBen Gras for (sp = &seqtable[0]; sp->len; sp++) {
6892fe8fb19SBen Gras nmatch = seqmatch(string, n, sp);
6902fe8fb19SBen Gras if (!nmatch)
6912fe8fb19SBen Gras continue;
6922fe8fb19SBen Gras
6932fe8fb19SBen Gras /*
6942fe8fb19SBen Gras * if we are in the middle of escape sequence,
6952fe8fb19SBen Gras * we still need to wait for more characters to come
6962fe8fb19SBen Gras */
6972fe8fb19SBen Gras if (n < sp->len) {
6982fe8fb19SBen Gras if (nmatch == n) {
6992fe8fb19SBen Gras if (result)
7002fe8fb19SBen Gras *result = string;
7012fe8fb19SBen Gras return (_ISO2022INVALID);
7022fe8fb19SBen Gras }
7032fe8fb19SBen Gras } else {
7042fe8fb19SBen Gras if (nmatch == sp->len) {
7052fe8fb19SBen Gras /* this case should not happen */
7062fe8fb19SBen Gras goto eat;
7072fe8fb19SBen Gras }
7082fe8fb19SBen Gras }
7092fe8fb19SBen Gras }
7102fe8fb19SBen Gras
7112fe8fb19SBen Gras break;
7122fe8fb19SBen Gras }
7132fe8fb19SBen Gras
7142fe8fb19SBen Gras eat:
7152fe8fb19SBen Gras /* no letter to eat */
7162fe8fb19SBen Gras if (n < 1) {
7172fe8fb19SBen Gras if (result)
7182fe8fb19SBen Gras *result = string;
7192fe8fb19SBen Gras return (_ISO2022INVALID);
7202fe8fb19SBen Gras }
7212fe8fb19SBen Gras
7222fe8fb19SBen Gras /* normal chars. always eat C0/C1 as is. */
7232fe8fb19SBen Gras if (iscntl(*string & 0xff))
7242fe8fb19SBen Gras cur = -1;
7252fe8fb19SBen Gras else if (*string & 0x80) {
7262fe8fb19SBen Gras cur = (psenc->singlegr == -1)
7272fe8fb19SBen Gras ? psenc->gr : psenc->singlegr;
7282fe8fb19SBen Gras } else {
7292fe8fb19SBen Gras cur = (psenc->singlegl == -1)
7302fe8fb19SBen Gras ? psenc->gl : psenc->singlegl;
7312fe8fb19SBen Gras }
7322fe8fb19SBen Gras
7332fe8fb19SBen Gras if (cur == -1) {
7342fe8fb19SBen Gras asis:
7352fe8fb19SBen Gras wchar = *string++ & 0xff;
7362fe8fb19SBen Gras if (result)
7372fe8fb19SBen Gras *result = string;
7382fe8fb19SBen Gras /* reset single shift state */
7392fe8fb19SBen Gras psenc->singlegr = psenc->singlegl = -1;
7402fe8fb19SBen Gras return wchar;
7412fe8fb19SBen Gras }
7422fe8fb19SBen Gras
7432fe8fb19SBen Gras /* length error check */
7442fe8fb19SBen Gras switch (psenc->g[cur].type) {
7452fe8fb19SBen Gras case CS94MULTI:
7462fe8fb19SBen Gras case CS96MULTI:
7472fe8fb19SBen Gras if (!isthree(psenc->g[cur].final)) {
7482fe8fb19SBen Gras if (2 <= n
7492fe8fb19SBen Gras && (string[0] & 0x80) == (string[1] & 0x80))
7502fe8fb19SBen Gras break;
7512fe8fb19SBen Gras } else {
7522fe8fb19SBen Gras if (3 <= n
7532fe8fb19SBen Gras && (string[0] & 0x80) == (string[1] & 0x80)
7542fe8fb19SBen Gras && (string[0] & 0x80) == (string[2] & 0x80))
7552fe8fb19SBen Gras break;
7562fe8fb19SBen Gras }
7572fe8fb19SBen Gras
7582fe8fb19SBen Gras /* we still need to wait for more characters to come */
7592fe8fb19SBen Gras if (result)
7602fe8fb19SBen Gras *result = string;
7612fe8fb19SBen Gras return (_ISO2022INVALID);
7622fe8fb19SBen Gras
7632fe8fb19SBen Gras case CS94:
7642fe8fb19SBen Gras case CS96:
7652fe8fb19SBen Gras if (1 <= n)
7662fe8fb19SBen Gras break;
7672fe8fb19SBen Gras
7682fe8fb19SBen Gras /* we still need to wait for more characters to come */
7692fe8fb19SBen Gras if (result)
7702fe8fb19SBen Gras *result = string;
7712fe8fb19SBen Gras return (_ISO2022INVALID);
7722fe8fb19SBen Gras }
7732fe8fb19SBen Gras
7742fe8fb19SBen Gras /* range check */
7752fe8fb19SBen Gras switch (psenc->g[cur].type) {
7762fe8fb19SBen Gras case CS94:
7772fe8fb19SBen Gras if (!(is94(string[0] & 0x7f)))
7782fe8fb19SBen Gras goto asis;
7792fe8fb19SBen Gras case CS96:
7802fe8fb19SBen Gras if (!(is96(string[0] & 0x7f)))
7812fe8fb19SBen Gras goto asis;
7822fe8fb19SBen Gras break;
7832fe8fb19SBen Gras case CS94MULTI:
7842fe8fb19SBen Gras if (!(is94(string[0] & 0x7f) && is94(string[1] & 0x7f)))
7852fe8fb19SBen Gras goto asis;
7862fe8fb19SBen Gras break;
7872fe8fb19SBen Gras case CS96MULTI:
7882fe8fb19SBen Gras if (!(is96(string[0] & 0x7f) && is96(string[1] & 0x7f)))
7892fe8fb19SBen Gras goto asis;
7902fe8fb19SBen Gras break;
7912fe8fb19SBen Gras }
7922fe8fb19SBen Gras
7932fe8fb19SBen Gras /* extract the character. */
7942fe8fb19SBen Gras switch (psenc->g[cur].type) {
7952fe8fb19SBen Gras case CS94:
7962fe8fb19SBen Gras /* special case for ASCII. */
7972fe8fb19SBen Gras if (psenc->g[cur].final == 'B' && !psenc->g[cur].interm) {
7982fe8fb19SBen Gras wchar = *string++;
7992fe8fb19SBen Gras wchar &= 0x7f;
8002fe8fb19SBen Gras break;
8012fe8fb19SBen Gras }
8022fe8fb19SBen Gras wchar = psenc->g[cur].final;
8032fe8fb19SBen Gras wchar = (wchar << 8);
8042fe8fb19SBen Gras wchar |= (psenc->g[cur].interm ? (0x80 | psenc->g[cur].interm) : 0);
8052fe8fb19SBen Gras wchar = (wchar << 8);
8062fe8fb19SBen Gras wchar = (wchar << 8) | (*string++ & 0x7f);
8072fe8fb19SBen Gras break;
8082fe8fb19SBen Gras case CS96:
8092fe8fb19SBen Gras /* special case for ISO-8859-1. */
8102fe8fb19SBen Gras if (psenc->g[cur].final == 'A' && !psenc->g[cur].interm) {
8112fe8fb19SBen Gras wchar = *string++;
8122fe8fb19SBen Gras wchar &= 0x7f;
8132fe8fb19SBen Gras wchar |= 0x80;
8142fe8fb19SBen Gras break;
8152fe8fb19SBen Gras }
8162fe8fb19SBen Gras wchar = psenc->g[cur].final;
8172fe8fb19SBen Gras wchar = (wchar << 8);
8182fe8fb19SBen Gras wchar |= (psenc->g[cur].interm ? (0x80 | psenc->g[cur].interm) : 0);
8192fe8fb19SBen Gras wchar = (wchar << 8);
8202fe8fb19SBen Gras wchar = (wchar << 8) | (*string++ & 0x7f);
8212fe8fb19SBen Gras wchar |= 0x80;
8222fe8fb19SBen Gras break;
8232fe8fb19SBen Gras case CS94MULTI:
8242fe8fb19SBen Gras case CS96MULTI:
8252fe8fb19SBen Gras wchar = psenc->g[cur].final;
8262fe8fb19SBen Gras wchar = (wchar << 8);
8272fe8fb19SBen Gras if (isthree(psenc->g[cur].final))
8282fe8fb19SBen Gras wchar |= (*string++ & 0x7f);
8292fe8fb19SBen Gras wchar = (wchar << 8) | (*string++ & 0x7f);
8302fe8fb19SBen Gras wchar = (wchar << 8) | (*string++ & 0x7f);
8312fe8fb19SBen Gras if (psenc->g[cur].type == CS96MULTI)
8322fe8fb19SBen Gras wchar |= 0x80;
8332fe8fb19SBen Gras break;
8342fe8fb19SBen Gras }
8352fe8fb19SBen Gras
8362fe8fb19SBen Gras if (result)
8372fe8fb19SBen Gras *result = string;
8382fe8fb19SBen Gras /* reset single shift state */
8392fe8fb19SBen Gras psenc->singlegr = psenc->singlegl = -1;
8402fe8fb19SBen Gras return wchar;
8412fe8fb19SBen Gras }
8422fe8fb19SBen Gras
8432fe8fb19SBen Gras
8442fe8fb19SBen Gras
8452fe8fb19SBen Gras static int
_citrus_ISO2022_mbrtowc_priv(_ISO2022EncodingInfo * __restrict ei,wchar_t * __restrict pwc,const char ** __restrict s,size_t n,_ISO2022State * __restrict psenc,size_t * __restrict nresult)8462fe8fb19SBen Gras _citrus_ISO2022_mbrtowc_priv(_ISO2022EncodingInfo * __restrict ei,
8472fe8fb19SBen Gras wchar_t * __restrict pwc,
8482fe8fb19SBen Gras const char ** __restrict s,
8492fe8fb19SBen Gras size_t n, _ISO2022State * __restrict psenc,
8502fe8fb19SBen Gras size_t * __restrict nresult)
8512fe8fb19SBen Gras {
8522fe8fb19SBen Gras wchar_t wchar;
8532fe8fb19SBen Gras const char *s0, *p, *result;
8542fe8fb19SBen Gras int c;
8552fe8fb19SBen Gras int chlenbak;
8562fe8fb19SBen Gras
8572fe8fb19SBen Gras _DIAGASSERT(nresult != 0);
8582fe8fb19SBen Gras _DIAGASSERT(ei != NULL);
8592fe8fb19SBen Gras _DIAGASSERT(psenc != NULL);
8602fe8fb19SBen Gras _DIAGASSERT(s != NULL);
8612fe8fb19SBen Gras
8622fe8fb19SBen Gras if (*s == NULL) {
8632fe8fb19SBen Gras _citrus_ISO2022_init_state(ei, psenc);
8642fe8fb19SBen Gras *nresult = _ENCODING_IS_STATE_DEPENDENT;
8652fe8fb19SBen Gras return 0;
8662fe8fb19SBen Gras }
8672fe8fb19SBen Gras s0 = *s;
8682fe8fb19SBen Gras c = 0;
8692fe8fb19SBen Gras chlenbak = psenc->chlen;
8702fe8fb19SBen Gras
8712fe8fb19SBen Gras /*
8722fe8fb19SBen Gras * if we have something in buffer, use that.
8732fe8fb19SBen Gras * otherwise, skip here
8742fe8fb19SBen Gras */
8752fe8fb19SBen Gras if (psenc->chlen < 0 || psenc->chlen > sizeof(psenc->ch)) {
8762fe8fb19SBen Gras /* illgeal state */
8772fe8fb19SBen Gras _citrus_ISO2022_init_state(ei, psenc);
8782fe8fb19SBen Gras goto encoding_error;
8792fe8fb19SBen Gras }
8802fe8fb19SBen Gras if (psenc->chlen == 0)
8812fe8fb19SBen Gras goto emptybuf;
8822fe8fb19SBen Gras
8832fe8fb19SBen Gras /* buffer is not empty */
8842fe8fb19SBen Gras p = psenc->ch;
8852fe8fb19SBen Gras while (psenc->chlen < sizeof(psenc->ch)) {
8862fe8fb19SBen Gras if (n > 0) {
8872fe8fb19SBen Gras psenc->ch[psenc->chlen++] = *s0++;
8882fe8fb19SBen Gras n--;
8892fe8fb19SBen Gras }
8902fe8fb19SBen Gras
8912fe8fb19SBen Gras wchar = _ISO2022_sgetwchar(ei, p, psenc->chlen - (p-psenc->ch),
8922fe8fb19SBen Gras &result, psenc);
8932fe8fb19SBen Gras c += result - p;
8942fe8fb19SBen Gras if (wchar != _ISO2022INVALID) {
8952fe8fb19SBen Gras if (psenc->chlen > c)
8962fe8fb19SBen Gras memmove(psenc->ch, result, psenc->chlen - c);
8972fe8fb19SBen Gras if (psenc->chlen < c)
8982fe8fb19SBen Gras psenc->chlen = 0;
8992fe8fb19SBen Gras else
9002fe8fb19SBen Gras psenc->chlen -= c;
9012fe8fb19SBen Gras goto output;
9022fe8fb19SBen Gras }
9032fe8fb19SBen Gras
9042fe8fb19SBen Gras if (n == 0) {
9052fe8fb19SBen Gras if ((result - p) == psenc->chlen)
9062fe8fb19SBen Gras /* complete shift sequence. */
9072fe8fb19SBen Gras psenc->chlen = 0;
9082fe8fb19SBen Gras goto restart;
9092fe8fb19SBen Gras }
9102fe8fb19SBen Gras
9112fe8fb19SBen Gras p = result;
9122fe8fb19SBen Gras }
9132fe8fb19SBen Gras
9142fe8fb19SBen Gras /* escape sequence too long? */
9152fe8fb19SBen Gras goto encoding_error;
9162fe8fb19SBen Gras
9172fe8fb19SBen Gras emptybuf:
9182fe8fb19SBen Gras wchar = _ISO2022_sgetwchar(ei, s0, n, &result, psenc);
9192fe8fb19SBen Gras if (wchar != _ISO2022INVALID) {
9202fe8fb19SBen Gras c += result - s0;
9212fe8fb19SBen Gras psenc->chlen = 0;
9222fe8fb19SBen Gras s0 = result;
9232fe8fb19SBen Gras goto output;
9242fe8fb19SBen Gras }
9252fe8fb19SBen Gras if (result > s0) {
9262fe8fb19SBen Gras c += (result - s0);
9272fe8fb19SBen Gras n -= (result - s0);
9282fe8fb19SBen Gras s0 = result;
9292fe8fb19SBen Gras if (n>0)
9302fe8fb19SBen Gras goto emptybuf;
9312fe8fb19SBen Gras /* complete shift sequence. */
9322fe8fb19SBen Gras goto restart;
9332fe8fb19SBen Gras }
9342fe8fb19SBen Gras n += c;
9352fe8fb19SBen Gras if (n < sizeof(psenc->ch)) {
9362fe8fb19SBen Gras memcpy(psenc->ch, s0 - c, n);
9372fe8fb19SBen Gras psenc->chlen = n;
9382fe8fb19SBen Gras s0 = result;
9392fe8fb19SBen Gras goto restart;
9402fe8fb19SBen Gras }
9412fe8fb19SBen Gras
9422fe8fb19SBen Gras /* escape sequence too long? */
9432fe8fb19SBen Gras
9442fe8fb19SBen Gras encoding_error:
9452fe8fb19SBen Gras psenc->chlen = 0;
9462fe8fb19SBen Gras *nresult = (size_t)-1;
9472fe8fb19SBen Gras return (EILSEQ);
9482fe8fb19SBen Gras
9492fe8fb19SBen Gras output:
9502fe8fb19SBen Gras *s = s0;
9512fe8fb19SBen Gras if (pwc)
9522fe8fb19SBen Gras *pwc = wchar;
9532fe8fb19SBen Gras
9542fe8fb19SBen Gras if (!wchar)
9552fe8fb19SBen Gras *nresult = 0;
9562fe8fb19SBen Gras else
9572fe8fb19SBen Gras *nresult = c - chlenbak;
9582fe8fb19SBen Gras
9592fe8fb19SBen Gras return (0);
9602fe8fb19SBen Gras
9612fe8fb19SBen Gras restart:
9622fe8fb19SBen Gras *s = s0;
9632fe8fb19SBen Gras *nresult = (size_t)-2;
9642fe8fb19SBen Gras
9652fe8fb19SBen Gras return (0);
9662fe8fb19SBen Gras }
9672fe8fb19SBen Gras
9682fe8fb19SBen Gras static int
recommendation(_ISO2022EncodingInfo * __restrict ei,_ISO2022Charset * __restrict cs)9692fe8fb19SBen Gras recommendation(_ISO2022EncodingInfo * __restrict ei,
9702fe8fb19SBen Gras _ISO2022Charset * __restrict cs)
9712fe8fb19SBen Gras {
9722fe8fb19SBen Gras int i, j;
9732fe8fb19SBen Gras _ISO2022Charset *recommend;
9742fe8fb19SBen Gras
9752fe8fb19SBen Gras _DIAGASSERT(ei != NULL);
9762fe8fb19SBen Gras _DIAGASSERT(cs != NULL);
9772fe8fb19SBen Gras
9782fe8fb19SBen Gras /* first, try a exact match. */
9792fe8fb19SBen Gras for (i = 0; i < 4; i++) {
9802fe8fb19SBen Gras recommend = ei->recommend[i];
9812fe8fb19SBen Gras for (j = 0; j < ei->recommendsize[i]; j++) {
9822fe8fb19SBen Gras if (cs->type != recommend[j].type)
9832fe8fb19SBen Gras continue;
9842fe8fb19SBen Gras if (cs->final != recommend[j].final)
9852fe8fb19SBen Gras continue;
9862fe8fb19SBen Gras if (cs->interm != recommend[j].interm)
9872fe8fb19SBen Gras continue;
9882fe8fb19SBen Gras
9892fe8fb19SBen Gras return i;
9902fe8fb19SBen Gras }
9912fe8fb19SBen Gras }
9922fe8fb19SBen Gras
9932fe8fb19SBen Gras /* then, try a wildcard match over final char. */
9942fe8fb19SBen Gras for (i = 0; i < 4; i++) {
9952fe8fb19SBen Gras recommend = ei->recommend[i];
9962fe8fb19SBen Gras for (j = 0; j < ei->recommendsize[i]; j++) {
9972fe8fb19SBen Gras if (cs->type != recommend[j].type)
9982fe8fb19SBen Gras continue;
9992fe8fb19SBen Gras if (cs->final && (cs->final != recommend[j].final))
10002fe8fb19SBen Gras continue;
10012fe8fb19SBen Gras if (cs->interm && (cs->interm != recommend[j].interm))
10022fe8fb19SBen Gras continue;
10032fe8fb19SBen Gras
10042fe8fb19SBen Gras return i;
10052fe8fb19SBen Gras }
10062fe8fb19SBen Gras }
10072fe8fb19SBen Gras
10082fe8fb19SBen Gras /* there's no recommendation. make a guess. */
10092fe8fb19SBen Gras if (ei->maxcharset == 0) {
10102fe8fb19SBen Gras return 0;
10112fe8fb19SBen Gras } else {
10122fe8fb19SBen Gras switch (cs->type) {
10132fe8fb19SBen Gras case CS94:
10142fe8fb19SBen Gras case CS94MULTI:
10152fe8fb19SBen Gras return 0;
10162fe8fb19SBen Gras case CS96:
10172fe8fb19SBen Gras case CS96MULTI:
10182fe8fb19SBen Gras return 1;
10192fe8fb19SBen Gras }
10202fe8fb19SBen Gras }
10212fe8fb19SBen Gras return 0;
10222fe8fb19SBen Gras }
10232fe8fb19SBen Gras
10242fe8fb19SBen Gras 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)10252fe8fb19SBen Gras _ISO2022_sputwchar(_ISO2022EncodingInfo * __restrict ei, wchar_t wc,
10262fe8fb19SBen Gras char * __restrict string, size_t n,
10272fe8fb19SBen Gras char ** __restrict result,
10282fe8fb19SBen Gras _ISO2022State * __restrict psenc,
10292fe8fb19SBen Gras size_t * __restrict nresult)
10302fe8fb19SBen Gras {
10312fe8fb19SBen Gras int i = 0;
10322fe8fb19SBen Gras size_t len;
10332fe8fb19SBen Gras _ISO2022Charset cs;
10342fe8fb19SBen Gras char *p;
10352fe8fb19SBen Gras char tmp[MB_LEN_MAX];
10362fe8fb19SBen Gras int target;
10372fe8fb19SBen Gras u_char mask;
10382fe8fb19SBen Gras int bit8;
10392fe8fb19SBen Gras
10402fe8fb19SBen Gras _DIAGASSERT(ei != NULL);
10412fe8fb19SBen Gras _DIAGASSERT(string != NULL);
10422fe8fb19SBen Gras /* result may be NULL */
10432fe8fb19SBen Gras _DIAGASSERT(psenc != NULL);
10442fe8fb19SBen Gras _DIAGASSERT(nresult != NULL);
10452fe8fb19SBen Gras
10462fe8fb19SBen Gras if (isc0(wc & 0xff)) {
10472fe8fb19SBen Gras /* go back to INIT0 or ASCII on control chars */
10482fe8fb19SBen Gras cs = ei->initg[0].final ? ei->initg[0] : ascii;
10492fe8fb19SBen Gras } else if (isc1(wc & 0xff)) {
10502fe8fb19SBen Gras /* go back to INIT1 or ISO-8859-1 on control chars */
10512fe8fb19SBen Gras cs = ei->initg[1].final ? ei->initg[1] : iso88591;
10522fe8fb19SBen Gras } else if (!(wc & ~0xff)) {
10532fe8fb19SBen Gras if (wc & 0x80) {
10542fe8fb19SBen Gras /* special treatment for ISO-8859-1 */
10552fe8fb19SBen Gras cs = iso88591;
10562fe8fb19SBen Gras } else {
10572fe8fb19SBen Gras /* special treatment for ASCII */
10582fe8fb19SBen Gras cs = ascii;
10592fe8fb19SBen Gras }
10602fe8fb19SBen Gras } else {
10612fe8fb19SBen Gras cs.final = (wc >> 24) & 0x7f;
10622fe8fb19SBen Gras if ((wc >> 16) & 0x80)
10632fe8fb19SBen Gras cs.interm = (wc >> 16) & 0x7f;
10642fe8fb19SBen Gras else
10652fe8fb19SBen Gras cs.interm = '\0';
10662fe8fb19SBen Gras if (wc & 0x80)
10672fe8fb19SBen Gras cs.type = (wc & 0x00007f00) ? CS96MULTI : CS96;
10682fe8fb19SBen Gras else
10692fe8fb19SBen Gras cs.type = (wc & 0x00007f00) ? CS94MULTI : CS94;
10702fe8fb19SBen Gras }
10712fe8fb19SBen Gras target = recommendation(ei, &cs);
10722fe8fb19SBen Gras p = tmp;
10732fe8fb19SBen Gras bit8 = ei->flags & F_8BIT;
10742fe8fb19SBen Gras
10752fe8fb19SBen Gras /* designate the charset onto the target plane(G0/1/2/3). */
10762fe8fb19SBen Gras if (psenc->g[target].type == cs.type
10772fe8fb19SBen Gras && psenc->g[target].final == cs.final
10782fe8fb19SBen Gras && psenc->g[target].interm == cs.interm)
10792fe8fb19SBen Gras goto planeok;
10802fe8fb19SBen Gras
10812fe8fb19SBen Gras *p++ = '\033';
10822fe8fb19SBen Gras if (cs.type == CS94MULTI || cs.type == CS96MULTI)
10832fe8fb19SBen Gras *p++ = '$';
10842fe8fb19SBen Gras if (target == 0 && cs.type == CS94MULTI && strchr("@AB", cs.final)
10852fe8fb19SBen Gras && !cs.interm && !(ei->flags & F_NOOLD))
10862fe8fb19SBen Gras ;
10872fe8fb19SBen Gras else if (cs.type == CS94 || cs.type == CS94MULTI)
10882fe8fb19SBen Gras *p++ = "()*+"[target];
10892fe8fb19SBen Gras else
10902fe8fb19SBen Gras *p++ = ",-./"[target];
10912fe8fb19SBen Gras if (cs.interm)
10922fe8fb19SBen Gras *p++ = cs.interm;
10932fe8fb19SBen Gras *p++ = cs.final;
10942fe8fb19SBen Gras
10952fe8fb19SBen Gras psenc->g[target].type = cs.type;
10962fe8fb19SBen Gras psenc->g[target].final = cs.final;
10972fe8fb19SBen Gras psenc->g[target].interm = cs.interm;
10982fe8fb19SBen Gras
10992fe8fb19SBen Gras planeok:
11002fe8fb19SBen Gras /* invoke the plane onto GL or GR. */
11012fe8fb19SBen Gras if (psenc->gl == target)
11022fe8fb19SBen Gras goto sideok;
11032fe8fb19SBen Gras if (bit8 && psenc->gr == target)
11042fe8fb19SBen Gras goto sideok;
11052fe8fb19SBen Gras
11062fe8fb19SBen Gras if (target == 0 && (ei->flags & F_LS0)) {
11072fe8fb19SBen Gras *p++ = '\017';
11082fe8fb19SBen Gras psenc->gl = 0;
11092fe8fb19SBen Gras } else if (target == 1 && (ei->flags & F_LS1)) {
11102fe8fb19SBen Gras *p++ = '\016';
11112fe8fb19SBen Gras psenc->gl = 1;
11122fe8fb19SBen Gras } else if (target == 2 && (ei->flags & F_LS2)) {
11132fe8fb19SBen Gras *p++ = '\033';
11142fe8fb19SBen Gras *p++ = 'n';
11152fe8fb19SBen Gras psenc->gl = 2;
11162fe8fb19SBen Gras } else if (target == 3 && (ei->flags & F_LS3)) {
11172fe8fb19SBen Gras *p++ = '\033';
11182fe8fb19SBen Gras *p++ = 'o';
11192fe8fb19SBen Gras psenc->gl = 3;
11202fe8fb19SBen Gras } else if (bit8 && target == 1 && (ei->flags & F_LS1R)) {
11212fe8fb19SBen Gras *p++ = '\033';
11222fe8fb19SBen Gras *p++ = '~';
11232fe8fb19SBen Gras psenc->gr = 1;
11242fe8fb19SBen Gras } else if (bit8 && target == 2 && (ei->flags & F_LS2R)) {
11252fe8fb19SBen Gras *p++ = '\033';
11262fe8fb19SBen Gras /*{*/
11272fe8fb19SBen Gras *p++ = '}';
11282fe8fb19SBen Gras psenc->gr = 2;
11292fe8fb19SBen Gras } else if (bit8 && target == 3 && (ei->flags & F_LS3R)) {
11302fe8fb19SBen Gras *p++ = '\033';
11312fe8fb19SBen Gras *p++ = '|';
11322fe8fb19SBen Gras psenc->gr = 3;
11332fe8fb19SBen Gras } else if (target == 2 && (ei->flags & F_SS2)) {
11342fe8fb19SBen Gras *p++ = '\033';
11352fe8fb19SBen Gras *p++ = 'N';
11362fe8fb19SBen Gras psenc->singlegl = 2;
11372fe8fb19SBen Gras } else if (target == 3 && (ei->flags & F_SS3)) {
11382fe8fb19SBen Gras *p++ = '\033';
11392fe8fb19SBen Gras *p++ = 'O';
11402fe8fb19SBen Gras psenc->singlegl = 3;
11412fe8fb19SBen Gras } else if (bit8 && target == 2 && (ei->flags & F_SS2R)) {
11422fe8fb19SBen Gras *p++ = '\216';
11432fe8fb19SBen Gras *p++ = 'N';
11442fe8fb19SBen Gras psenc->singlegl = psenc->singlegr = 2;
11452fe8fb19SBen Gras } else if (bit8 && target == 3 && (ei->flags & F_SS3R)) {
11462fe8fb19SBen Gras *p++ = '\217';
11472fe8fb19SBen Gras *p++ = 'O';
11482fe8fb19SBen Gras psenc->singlegl = psenc->singlegr = 3;
11492fe8fb19SBen Gras } else
11502fe8fb19SBen Gras goto ilseq;
11512fe8fb19SBen Gras
11522fe8fb19SBen Gras sideok:
11532fe8fb19SBen Gras if (psenc->singlegl == target)
11542fe8fb19SBen Gras mask = 0x00;
11552fe8fb19SBen Gras else if (psenc->singlegr == target)
11562fe8fb19SBen Gras mask = 0x80;
11572fe8fb19SBen Gras else if (psenc->gl == target)
11582fe8fb19SBen Gras mask = 0x00;
11592fe8fb19SBen Gras else if ((ei->flags & F_8BIT) && psenc->gr == target)
11602fe8fb19SBen Gras mask = 0x80;
11612fe8fb19SBen Gras else
11622fe8fb19SBen Gras goto ilseq;
11632fe8fb19SBen Gras
11642fe8fb19SBen Gras switch (cs.type) {
11652fe8fb19SBen Gras case CS94:
11662fe8fb19SBen Gras case CS96:
11672fe8fb19SBen Gras i = 1;
11682fe8fb19SBen Gras break;
11692fe8fb19SBen Gras case CS94MULTI:
11702fe8fb19SBen Gras case CS96MULTI:
11712fe8fb19SBen Gras i = !iscntl(wc & 0xff) ?
11722fe8fb19SBen Gras (isthree(cs.final) ? 3 : 2) : 1;
11732fe8fb19SBen Gras break;
11742fe8fb19SBen Gras }
11752fe8fb19SBen Gras while (i-- > 0)
11762fe8fb19SBen Gras *p++ = ((wc >> (i << 3)) & 0x7f) | mask;
11772fe8fb19SBen Gras
11782fe8fb19SBen Gras /* reset single shift state */
11792fe8fb19SBen Gras psenc->singlegl = psenc->singlegr = -1;
11802fe8fb19SBen Gras
11812fe8fb19SBen Gras len = (size_t)(p - tmp);
11822fe8fb19SBen Gras if (n < len) {
11832fe8fb19SBen Gras if (result)
11842fe8fb19SBen Gras *result = (char *)0;
11852fe8fb19SBen Gras *nresult = (size_t)-1;
11862fe8fb19SBen Gras return E2BIG;
11872fe8fb19SBen Gras }
11882fe8fb19SBen Gras if (result)
11892fe8fb19SBen Gras *result = string + len;
11902fe8fb19SBen Gras memcpy(string, tmp, len);
11912fe8fb19SBen Gras *nresult = len;
11922fe8fb19SBen Gras
11932fe8fb19SBen Gras return 0;
11942fe8fb19SBen Gras
11952fe8fb19SBen Gras ilseq:
11962fe8fb19SBen Gras *nresult = (size_t)-1;
11972fe8fb19SBen Gras return EILSEQ;
11982fe8fb19SBen Gras }
11992fe8fb19SBen Gras
12002fe8fb19SBen Gras static int
_citrus_ISO2022_put_state_reset(_ISO2022EncodingInfo * __restrict ei,char * __restrict s,size_t n,_ISO2022State * __restrict psenc,size_t * __restrict nresult)12012fe8fb19SBen Gras _citrus_ISO2022_put_state_reset(_ISO2022EncodingInfo * __restrict ei,
12022fe8fb19SBen Gras char * __restrict s, size_t n,
12032fe8fb19SBen Gras _ISO2022State * __restrict psenc,
12042fe8fb19SBen Gras size_t * __restrict nresult)
12052fe8fb19SBen Gras {
12062fe8fb19SBen Gras char buf[MB_LEN_MAX];
12072fe8fb19SBen Gras char *result;
12082fe8fb19SBen Gras int ret;
12092fe8fb19SBen Gras size_t len;
12102fe8fb19SBen Gras
12112fe8fb19SBen Gras _DIAGASSERT(ei != NULL);
12122fe8fb19SBen Gras _DIAGASSERT(nresult != 0);
12132fe8fb19SBen Gras _DIAGASSERT(s != NULL);
12142fe8fb19SBen Gras
12152fe8fb19SBen Gras /* XXX state will be modified after this operation... */
12162fe8fb19SBen Gras ret = _ISO2022_sputwchar(ei, L'\0', buf, sizeof(buf), &result, psenc,
12172fe8fb19SBen Gras &len);
12182fe8fb19SBen Gras if (ret) {
12192fe8fb19SBen Gras *nresult = len;
12202fe8fb19SBen Gras return ret;
12212fe8fb19SBen Gras }
12222fe8fb19SBen Gras
12232fe8fb19SBen Gras if (sizeof(buf) < len || n < len-1) {
12242fe8fb19SBen Gras /* XXX should recover state? */
12252fe8fb19SBen Gras *nresult = (size_t)-1;
12262fe8fb19SBen Gras return E2BIG;
12272fe8fb19SBen Gras }
12282fe8fb19SBen Gras
12292fe8fb19SBen Gras memcpy(s, buf, len-1);
12302fe8fb19SBen Gras *nresult = len-1;
12312fe8fb19SBen Gras return (0);
12322fe8fb19SBen Gras }
12332fe8fb19SBen Gras
12342fe8fb19SBen Gras 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)12352fe8fb19SBen Gras _citrus_ISO2022_wcrtomb_priv(_ISO2022EncodingInfo * __restrict ei,
12362fe8fb19SBen Gras char * __restrict s, size_t n, wchar_t wc,
12372fe8fb19SBen Gras _ISO2022State * __restrict psenc,
12382fe8fb19SBen Gras size_t * __restrict nresult)
12392fe8fb19SBen Gras {
12402fe8fb19SBen Gras char buf[MB_LEN_MAX];
12412fe8fb19SBen Gras char *result;
12422fe8fb19SBen Gras int ret;
12432fe8fb19SBen Gras size_t len;
12442fe8fb19SBen Gras
12452fe8fb19SBen Gras _DIAGASSERT(ei != NULL);
12462fe8fb19SBen Gras _DIAGASSERT(s != NULL);
12472fe8fb19SBen Gras _DIAGASSERT(psenc != NULL);
12482fe8fb19SBen Gras _DIAGASSERT(nresult != 0);
12492fe8fb19SBen Gras
12502fe8fb19SBen Gras /* XXX state will be modified after this operation... */
12512fe8fb19SBen Gras ret = _ISO2022_sputwchar(ei, wc, buf, sizeof(buf), &result, psenc,
12522fe8fb19SBen Gras &len);
12532fe8fb19SBen Gras if (ret) {
12542fe8fb19SBen Gras *nresult = len;
12552fe8fb19SBen Gras return ret;
12562fe8fb19SBen Gras }
12572fe8fb19SBen Gras
12582fe8fb19SBen Gras if (sizeof(buf) < len || n < len) {
12592fe8fb19SBen Gras /* XXX should recover state? */
12602fe8fb19SBen Gras *nresult = (size_t)-1;
12612fe8fb19SBen Gras return E2BIG;
12622fe8fb19SBen Gras }
12632fe8fb19SBen Gras
12642fe8fb19SBen Gras memcpy(s, buf, len);
12652fe8fb19SBen Gras *nresult = len;
12662fe8fb19SBen Gras return (0);
12672fe8fb19SBen Gras }
12682fe8fb19SBen Gras
12692fe8fb19SBen Gras static __inline int
12702fe8fb19SBen Gras /*ARGSUSED*/
_citrus_ISO2022_stdenc_wctocs(_ISO2022EncodingInfo * __restrict ei,_csid_t * __restrict csid,_index_t * __restrict idx,wchar_t wc)12712fe8fb19SBen Gras _citrus_ISO2022_stdenc_wctocs(_ISO2022EncodingInfo * __restrict ei,
12722fe8fb19SBen Gras _csid_t * __restrict csid,
12732fe8fb19SBen Gras _index_t * __restrict idx, wchar_t wc)
12742fe8fb19SBen Gras {
12752fe8fb19SBen Gras wchar_t m, nm;
12762fe8fb19SBen Gras
12772fe8fb19SBen Gras _DIAGASSERT(csid != NULL && idx != NULL);
12782fe8fb19SBen Gras
12792fe8fb19SBen Gras m = wc & 0x7FFF8080;
12802fe8fb19SBen Gras nm = wc & 0x007F7F7F;
12812fe8fb19SBen Gras if (m & 0x00800000) {
12822fe8fb19SBen Gras nm &= 0x00007F7F;
12832fe8fb19SBen Gras } else {
12842fe8fb19SBen Gras m &= 0x7F008080;
12852fe8fb19SBen Gras }
12862fe8fb19SBen Gras if (nm & 0x007F0000) {
12872fe8fb19SBen Gras /* ^3 mark */
12882fe8fb19SBen Gras m |= 0x007F0000;
12892fe8fb19SBen Gras } else if (nm & 0x00007F00) {
12902fe8fb19SBen Gras /* ^2 mark */
12912fe8fb19SBen Gras m |= 0x00007F00;
12922fe8fb19SBen Gras }
12932fe8fb19SBen Gras *csid = (_csid_t)m;
12942fe8fb19SBen Gras *idx = (_index_t)nm;
12952fe8fb19SBen Gras
12962fe8fb19SBen Gras return (0);
12972fe8fb19SBen Gras }
12982fe8fb19SBen Gras
12992fe8fb19SBen Gras static __inline int
13002fe8fb19SBen Gras /*ARGSUSED*/
_citrus_ISO2022_stdenc_cstowc(_ISO2022EncodingInfo * __restrict ei,wchar_t * __restrict wc,_csid_t csid,_index_t idx)13012fe8fb19SBen Gras _citrus_ISO2022_stdenc_cstowc(_ISO2022EncodingInfo * __restrict ei,
13022fe8fb19SBen Gras wchar_t * __restrict wc,
13032fe8fb19SBen Gras _csid_t csid, _index_t idx)
13042fe8fb19SBen Gras {
13052fe8fb19SBen Gras
13062fe8fb19SBen Gras _DIAGASSERT(ei != NULL && wc != NULL);
13072fe8fb19SBen Gras
13082fe8fb19SBen Gras *wc = (wchar_t)(csid & 0x7F808080) | (wchar_t)idx;
13092fe8fb19SBen Gras
13102fe8fb19SBen Gras return (0);
13112fe8fb19SBen Gras }
13122fe8fb19SBen Gras
13132fe8fb19SBen Gras static __inline int
13142fe8fb19SBen Gras /*ARGSUSED*/
_citrus_ISO2022_stdenc_get_state_desc_generic(_ISO2022EncodingInfo * __restrict ei,_ISO2022State * __restrict psenc,int * __restrict rstate)13152fe8fb19SBen Gras _citrus_ISO2022_stdenc_get_state_desc_generic(_ISO2022EncodingInfo * __restrict ei,
13162fe8fb19SBen Gras _ISO2022State * __restrict psenc,
13172fe8fb19SBen Gras int * __restrict rstate)
13182fe8fb19SBen Gras {
13192fe8fb19SBen Gras
13202fe8fb19SBen Gras if (psenc->chlen == 0) {
13212fe8fb19SBen Gras /* XXX: it should distinguish initial and stable. */
13222fe8fb19SBen Gras *rstate = _STDENC_SDGEN_STABLE;
13232fe8fb19SBen Gras } else {
13242fe8fb19SBen Gras if (psenc->ch[0] == '\033')
13252fe8fb19SBen Gras *rstate = _STDENC_SDGEN_INCOMPLETE_SHIFT;
13262fe8fb19SBen Gras else
13272fe8fb19SBen Gras *rstate = _STDENC_SDGEN_INCOMPLETE_CHAR;
13282fe8fb19SBen Gras }
13292fe8fb19SBen Gras
13302fe8fb19SBen Gras return 0;
13312fe8fb19SBen Gras }
13322fe8fb19SBen Gras
13332fe8fb19SBen Gras /* ----------------------------------------------------------------------
13342fe8fb19SBen Gras * public interface for ctype
13352fe8fb19SBen Gras */
13362fe8fb19SBen Gras
13372fe8fb19SBen Gras _CITRUS_CTYPE_DECLS(ISO2022);
13382fe8fb19SBen Gras _CITRUS_CTYPE_DEF_OPS(ISO2022);
13392fe8fb19SBen Gras
13402fe8fb19SBen Gras #include "citrus_ctype_template.h"
13412fe8fb19SBen Gras
13422fe8fb19SBen Gras /* ----------------------------------------------------------------------
13432fe8fb19SBen Gras * public interface for stdenc
13442fe8fb19SBen Gras */
13452fe8fb19SBen Gras
13462fe8fb19SBen Gras _CITRUS_STDENC_DECLS(ISO2022);
13472fe8fb19SBen Gras _CITRUS_STDENC_DEF_OPS(ISO2022);
13482fe8fb19SBen Gras
13492fe8fb19SBen Gras #include "citrus_stdenc_template.h"
1350