1*85a67e61Sjoerg /* $NetBSD: citrus_iso2022.c,v 1.23 2013/05/28 16:57:56 joerg Exp $ */
2dc7d18ffStshiozak
3dc7d18ffStshiozak /*-
4dc7d18ffStshiozak * Copyright (c)1999, 2002 Citrus Project,
5dc7d18ffStshiozak * All rights reserved.
6dc7d18ffStshiozak *
7dc7d18ffStshiozak * Redistribution and use in source and binary forms, with or without
8dc7d18ffStshiozak * modification, are permitted provided that the following conditions
9dc7d18ffStshiozak * are met:
10dc7d18ffStshiozak * 1. Redistributions of source code must retain the above copyright
11dc7d18ffStshiozak * notice, this list of conditions and the following disclaimer.
12dc7d18ffStshiozak * 2. Redistributions in binary form must reproduce the above copyright
13dc7d18ffStshiozak * notice, this list of conditions and the following disclaimer in the
14dc7d18ffStshiozak * documentation and/or other materials provided with the distribution.
15dc7d18ffStshiozak *
16dc7d18ffStshiozak * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17dc7d18ffStshiozak * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18dc7d18ffStshiozak * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19dc7d18ffStshiozak * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20dc7d18ffStshiozak * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21dc7d18ffStshiozak * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22dc7d18ffStshiozak * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23dc7d18ffStshiozak * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24dc7d18ffStshiozak * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25dc7d18ffStshiozak * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26dc7d18ffStshiozak * SUCH DAMAGE.
27dc7d18ffStshiozak *
28dc7d18ffStshiozak * $Citrus: xpg4dl/FreeBSD/lib/libc/locale/iso2022.c,v 1.23 2001/06/21 01:51:44 yamt Exp $
29dc7d18ffStshiozak */
30dc7d18ffStshiozak
31dc7d18ffStshiozak #include <sys/cdefs.h>
32dc7d18ffStshiozak #if defined(LIBC_SCCS) && !defined(lint)
33*85a67e61Sjoerg __RCSID("$NetBSD: citrus_iso2022.c,v 1.23 2013/05/28 16:57:56 joerg Exp $");
34dc7d18ffStshiozak #endif /* LIBC_SCCS and not lint */
35dc7d18ffStshiozak
36dc7d18ffStshiozak #include <assert.h>
37dc7d18ffStshiozak #include <errno.h>
38dc7d18ffStshiozak #include <string.h>
39dc7d18ffStshiozak #include <stdio.h>
40dc7d18ffStshiozak #include <stdlib.h>
41dc7d18ffStshiozak #include <stddef.h>
42dc7d18ffStshiozak #include <wchar.h>
43dc7d18ffStshiozak #include <sys/types.h>
44dc7d18ffStshiozak #include <limits.h>
4504e58308Stshiozak
4604e58308Stshiozak #include "citrus_namespace.h"
4704e58308Stshiozak #include "citrus_types.h"
48dc7d18ffStshiozak #include "citrus_module.h"
49dc7d18ffStshiozak #include "citrus_ctype.h"
5004e58308Stshiozak #include "citrus_stdenc.h"
51dc7d18ffStshiozak #include "citrus_iso2022.h"
52dc7d18ffStshiozak
53dc7d18ffStshiozak
54dc7d18ffStshiozak /* ----------------------------------------------------------------------
55dc7d18ffStshiozak * private stuffs used by templates
56dc7d18ffStshiozak */
57dc7d18ffStshiozak
58dc7d18ffStshiozak
59dc7d18ffStshiozak /*
60dc7d18ffStshiozak * wchar_t mappings:
61dc7d18ffStshiozak * ASCII (ESC ( B) 00000000 00000000 00000000 0xxxxxxx
62dc7d18ffStshiozak * iso-8859-1 (ESC , A) 00000000 00000000 00000000 1xxxxxxx
63dc7d18ffStshiozak * 94 charset (ESC ( F) 0fffffff 00000000 00000000 0xxxxxxx
64dc7d18ffStshiozak * 94 charset (ESC ( M F) 0fffffff 1mmmmmmm 00000000 0xxxxxxx
65dc7d18ffStshiozak * 96 charset (ESC , F) 0fffffff 00000000 00000000 1xxxxxxx
66dc7d18ffStshiozak * 96 charset (ESC , M F) 0fffffff 1mmmmmmm 00000000 1xxxxxxx
67dc7d18ffStshiozak * 94x94 charset (ESC $ ( F) 0fffffff 00000000 0xxxxxxx 0xxxxxxx
68dc7d18ffStshiozak * 96x96 charset (ESC $ , F) 0fffffff 00000000 0xxxxxxx 1xxxxxxx
69dc7d18ffStshiozak * 94x94 charset (ESC & V ESC $ ( F)
70dc7d18ffStshiozak * 0fffffff 1vvvvvvv 0xxxxxxx 0xxxxxxx
71dc7d18ffStshiozak * 94x94x94 charset (ESC $ ( F) 0fffffff 0xxxxxxx 0xxxxxxx 0xxxxxxx
72dc7d18ffStshiozak * 96x96x96 charset (ESC $ , F) 0fffffff 0xxxxxxx 0xxxxxxx 1xxxxxxx
73855852a0Sitojun * reserved for UCS4 co-existence (UCS4 is 31bit encoding thanks to mohta bit)
74855852a0Sitojun * 1xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
75dc7d18ffStshiozak */
76dc7d18ffStshiozak
77dc7d18ffStshiozak typedef struct {
78dc7d18ffStshiozak u_char type;
79dc7d18ffStshiozak #define CS94 (0U)
80dc7d18ffStshiozak #define CS96 (1U)
81dc7d18ffStshiozak #define CS94MULTI (2U)
82dc7d18ffStshiozak #define CS96MULTI (3U)
83dc7d18ffStshiozak
84dc7d18ffStshiozak u_char final;
85dc7d18ffStshiozak u_char interm;
86dc7d18ffStshiozak u_char vers;
87dc7d18ffStshiozak } _ISO2022Charset;
88dc7d18ffStshiozak
89b29e60b3Stnozaki static const _ISO2022Charset ascii = { CS94, 'B', '\0', '\0' };
90b29e60b3Stnozaki static const _ISO2022Charset iso88591 = { CS96, 'A', '\0', '\0' };
91b29e60b3Stnozaki
92dc7d18ffStshiozak typedef struct {
93dc7d18ffStshiozak _ISO2022Charset g[4];
94dc7d18ffStshiozak /* need 3 bits to hold -1, 0, ..., 3 */
95dc7d18ffStshiozak int gl:3,
96dc7d18ffStshiozak gr:3,
97dc7d18ffStshiozak singlegl:3,
98dc7d18ffStshiozak singlegr:3;
99dc7d18ffStshiozak char ch[7]; /* longest escape sequence (ESC & V ESC $ ( F) */
100dc7d18ffStshiozak int chlen;
1013daba72aSyamt int flags;
1023daba72aSyamt #define _ISO2022STATE_FLAG_INITIALIZED 1
1036854a8c8Syamt } _ISO2022State;
104dc7d18ffStshiozak
105dc7d18ffStshiozak typedef struct {
106dc7d18ffStshiozak _ISO2022Charset *recommend[4];
107dc7d18ffStshiozak size_t recommendsize[4];
108dc7d18ffStshiozak _ISO2022Charset initg[4];
109dc7d18ffStshiozak int maxcharset;
110dc7d18ffStshiozak int flags;
111dc7d18ffStshiozak #define F_8BIT 0x0001
112dc7d18ffStshiozak #define F_NOOLD 0x0002
113dc7d18ffStshiozak #define F_SI 0x0010 /*0F*/
114dc7d18ffStshiozak #define F_SO 0x0020 /*0E*/
115dc7d18ffStshiozak #define F_LS0 0x0010 /*0F*/
116dc7d18ffStshiozak #define F_LS1 0x0020 /*0E*/
117dc7d18ffStshiozak #define F_LS2 0x0040 /*ESC n*/
118dc7d18ffStshiozak #define F_LS3 0x0080 /*ESC o*/
119dc7d18ffStshiozak #define F_LS1R 0x0100 /*ESC ~*/
120dc7d18ffStshiozak #define F_LS2R 0x0200 /*ESC }*/
121dc7d18ffStshiozak #define F_LS3R 0x0400 /*ESC |*/
122dc7d18ffStshiozak #define F_SS2 0x0800 /*ESC N*/
123dc7d18ffStshiozak #define F_SS3 0x1000 /*ESC O*/
124dc7d18ffStshiozak #define F_SS2R 0x2000 /*8E*/
125dc7d18ffStshiozak #define F_SS3R 0x4000 /*8F*/
126dc7d18ffStshiozak } _ISO2022EncodingInfo;
127dc7d18ffStshiozak typedef struct {
128dc7d18ffStshiozak _ISO2022EncodingInfo ei;
129dc7d18ffStshiozak struct {
130dc7d18ffStshiozak /* for future multi-locale facility */
131dc7d18ffStshiozak _ISO2022State s_mblen;
132dc7d18ffStshiozak _ISO2022State s_mbrlen;
133dc7d18ffStshiozak _ISO2022State s_mbrtowc;
134dc7d18ffStshiozak _ISO2022State s_mbtowc;
135dc7d18ffStshiozak _ISO2022State s_mbsrtowcs;
136*85a67e61Sjoerg _ISO2022State s_mbsnrtowcs;
137dc7d18ffStshiozak _ISO2022State s_wcrtomb;
138dc7d18ffStshiozak _ISO2022State s_wcsrtombs;
139*85a67e61Sjoerg _ISO2022State s_wcsnrtombs;
140dc7d18ffStshiozak _ISO2022State s_wctomb;
141dc7d18ffStshiozak } states;
142dc7d18ffStshiozak } _ISO2022CTypeInfo;
143dc7d18ffStshiozak
144dc7d18ffStshiozak #define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
145dc7d18ffStshiozak #define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
146dc7d18ffStshiozak
147dc7d18ffStshiozak #define _FUNCNAME(m) _citrus_ISO2022_##m
148dc7d18ffStshiozak #define _ENCODING_INFO _ISO2022EncodingInfo
149dc7d18ffStshiozak #define _CTYPE_INFO _ISO2022CTypeInfo
150dc7d18ffStshiozak #define _ENCODING_STATE _ISO2022State
151f0ab6c64Syamt #define _ENCODING_MB_CUR_MAX(_ei_) MB_LEN_MAX
152dc7d18ffStshiozak #define _ENCODING_IS_STATE_DEPENDENT 1
1533daba72aSyamt #define _STATE_NEEDS_EXPLICIT_INIT(_ps_) \
1543daba72aSyamt (!((_ps_)->flags & _ISO2022STATE_FLAG_INITIALIZED))
155dc7d18ffStshiozak
156dc7d18ffStshiozak
157dc7d18ffStshiozak #define _ISO2022INVALID (wchar_t)-1
158dc7d18ffStshiozak
isc0(__uint8_t x)159dc7d18ffStshiozak static __inline int isc0(__uint8_t x) { return ((x & 0x1f) == x); }
isc1(__uint8_t x)160dc7d18ffStshiozak static __inline int isc1(__uint8_t x) { return (0x80 <= x && x <= 0x9f); }
iscntl(__uint8_t x)161dc7d18ffStshiozak static __inline int iscntl(__uint8_t x) { return (isc0(x) || isc1(x) || x == 0x7f); }
is94(__uint8_t x)162dc7d18ffStshiozak static __inline int is94(__uint8_t x) { return (0x21 <= x && x <= 0x7e); }
is96(__uint8_t x)163dc7d18ffStshiozak static __inline int is96(__uint8_t x) { return (0x20 <= x && x <= 0x7f); }
isecma(__uint8_t x)164dc7d18ffStshiozak static __inline int isecma(__uint8_t x) { return (0x30 <= x && x <= 0x7f); }
isinterm(__uint8_t x)165dc7d18ffStshiozak static __inline int isinterm(__uint8_t x) { return (0x20 <= x && x <= 0x2f); }
isthree(__uint8_t x)166dc7d18ffStshiozak static __inline int isthree(__uint8_t x) { return (0x60 <= x && x <= 0x6f); }
167dc7d18ffStshiozak
168dc7d18ffStshiozak static __inline int
getcs(const char * __restrict p,_ISO2022Charset * __restrict cs)169dc7d18ffStshiozak getcs(const char * __restrict p, _ISO2022Charset * __restrict cs)
170dc7d18ffStshiozak {
171dc7d18ffStshiozak
172dc7d18ffStshiozak _DIAGASSERT(p != NULL);
173dc7d18ffStshiozak _DIAGASSERT(cs != NULL);
174dc7d18ffStshiozak
175dc7d18ffStshiozak if (!strncmp(p, "94$", 3) && p[3] && !p[4]) {
176dc7d18ffStshiozak cs->final = (u_char)(p[3] & 0xff);
177dc7d18ffStshiozak cs->interm = '\0';
178dc7d18ffStshiozak cs->vers = '\0';
179dc7d18ffStshiozak cs->type = CS94MULTI;
180dc7d18ffStshiozak } else if (!strncmp(p, "96$", 3) && p[3] && !p[4]) {
181dc7d18ffStshiozak cs->final = (u_char)(p[3] & 0xff);
182dc7d18ffStshiozak cs->interm = '\0';
183dc7d18ffStshiozak cs->vers = '\0';
184dc7d18ffStshiozak cs->type = CS96MULTI;
185dc7d18ffStshiozak } else if (!strncmp(p, "94", 2) && p[2] && !p[3]) {
186dc7d18ffStshiozak cs->final = (u_char)(p[2] & 0xff);
187dc7d18ffStshiozak cs->interm = '\0';
188dc7d18ffStshiozak cs->vers = '\0';
189dc7d18ffStshiozak cs->type = CS94;
190dc7d18ffStshiozak } else if (!strncmp(p, "96", 2) && p[2] && !p[3]) {
191dc7d18ffStshiozak cs->final = (u_char )(p[2] & 0xff);
192dc7d18ffStshiozak cs->interm = '\0';
193dc7d18ffStshiozak cs->vers = '\0';
194dc7d18ffStshiozak cs->type = CS96;
195dc7d18ffStshiozak } else {
196dc7d18ffStshiozak return 1;
197dc7d18ffStshiozak }
198dc7d18ffStshiozak
199dc7d18ffStshiozak return 0;
200dc7d18ffStshiozak }
201dc7d18ffStshiozak
202dc7d18ffStshiozak
203dc7d18ffStshiozak #define _NOTMATCH 0
204dc7d18ffStshiozak #define _MATCH 1
205dc7d18ffStshiozak #define _PARSEFAIL 2
206dc7d18ffStshiozak
207dc7d18ffStshiozak static __inline int
get_recommend(_ISO2022EncodingInfo * __restrict ei,const char * __restrict token)208dc7d18ffStshiozak get_recommend(_ISO2022EncodingInfo * __restrict ei,
209dc7d18ffStshiozak const char * __restrict token)
210dc7d18ffStshiozak {
211dc7d18ffStshiozak int i;
2125d489a8aSitojun _ISO2022Charset cs, *p;
213dc7d18ffStshiozak
214dc7d18ffStshiozak if (!strchr("0123", token[0]) || token[1] != '=')
215dc7d18ffStshiozak return (_NOTMATCH);
216dc7d18ffStshiozak
217dc7d18ffStshiozak if (getcs(&token[2], &cs) == 0)
218dc7d18ffStshiozak ;
219dc7d18ffStshiozak else if (!strcmp(&token[2], "94")) {
220dc7d18ffStshiozak cs.final = (u_char)(token[4]);
221dc7d18ffStshiozak cs.interm = '\0';
222dc7d18ffStshiozak cs.vers = '\0';
223dc7d18ffStshiozak cs.type = CS94;
224dc7d18ffStshiozak } else if (!strcmp(&token[2], "96")) {
225dc7d18ffStshiozak cs.final = (u_char)(token[4]);
226dc7d18ffStshiozak cs.interm = '\0';
227dc7d18ffStshiozak cs.vers = '\0';
228dc7d18ffStshiozak cs.type = CS96;
229dc7d18ffStshiozak } else if (!strcmp(&token[2], "94$")) {
230dc7d18ffStshiozak cs.final = (u_char)(token[5]);
231dc7d18ffStshiozak cs.interm = '\0';
232dc7d18ffStshiozak cs.vers = '\0';
233dc7d18ffStshiozak cs.type = CS94MULTI;
234dc7d18ffStshiozak } else if (!strcmp(&token[2], "96$")) {
235dc7d18ffStshiozak cs.final = (u_char)(token[5]);
236dc7d18ffStshiozak cs.interm = '\0';
237dc7d18ffStshiozak cs.vers = '\0';
238dc7d18ffStshiozak cs.type = CS96MULTI;
239dc7d18ffStshiozak } else {
240dc7d18ffStshiozak return (_PARSEFAIL);
241dc7d18ffStshiozak }
242dc7d18ffStshiozak
243dc7d18ffStshiozak i = token[0] - '0';
244dc7d18ffStshiozak if (!ei->recommend[i]) {
245dc7d18ffStshiozak ei->recommend[i] = malloc(sizeof(_ISO2022Charset));
246dc7d18ffStshiozak } else {
2475d489a8aSitojun p = realloc(ei->recommend[i],
2485d489a8aSitojun sizeof(_ISO2022Charset) * (ei->recommendsize[i] + 1));
2495d489a8aSitojun if (!p)
2505d489a8aSitojun return (_PARSEFAIL);
2515d489a8aSitojun ei->recommend[i] = p;
252dc7d18ffStshiozak }
253dc7d18ffStshiozak if (!ei->recommend[i])
254dc7d18ffStshiozak return (_PARSEFAIL);
2555d489a8aSitojun ei->recommendsize[i]++;
256dc7d18ffStshiozak
257dc7d18ffStshiozak (ei->recommend[i] + (ei->recommendsize[i] - 1))->final = cs.final;
258dc7d18ffStshiozak (ei->recommend[i] + (ei->recommendsize[i] - 1))->interm = cs.interm;
259dc7d18ffStshiozak (ei->recommend[i] + (ei->recommendsize[i] - 1))->vers = cs.vers;
260dc7d18ffStshiozak (ei->recommend[i] + (ei->recommendsize[i] - 1))->type = cs.type;
261dc7d18ffStshiozak
262dc7d18ffStshiozak return (_MATCH);
263dc7d18ffStshiozak }
264dc7d18ffStshiozak
265dc7d18ffStshiozak static __inline int
get_initg(_ISO2022EncodingInfo * __restrict ei,const char * __restrict token)266dc7d18ffStshiozak get_initg(_ISO2022EncodingInfo * __restrict ei,
267dc7d18ffStshiozak const char * __restrict token)
268dc7d18ffStshiozak {
269dc7d18ffStshiozak _ISO2022Charset cs;
270dc7d18ffStshiozak
271dc7d18ffStshiozak if (strncmp("INIT", &token[0], 4) ||
272dc7d18ffStshiozak !strchr("0123", token[4]) ||
273dc7d18ffStshiozak token[5] != '=')
274dc7d18ffStshiozak return (_NOTMATCH);
275dc7d18ffStshiozak
276dc7d18ffStshiozak if (getcs(&token[6], &cs) != 0)
277dc7d18ffStshiozak return (_PARSEFAIL);
278dc7d18ffStshiozak
279dc7d18ffStshiozak ei->initg[token[4] - '0'].type = cs.type;
280dc7d18ffStshiozak ei->initg[token[4] - '0'].final = cs.final;
281dc7d18ffStshiozak ei->initg[token[4] - '0'].interm = cs.interm;
282dc7d18ffStshiozak ei->initg[token[4] - '0'].vers = cs.vers;
283dc7d18ffStshiozak
284dc7d18ffStshiozak return (_MATCH);
285dc7d18ffStshiozak }
286dc7d18ffStshiozak
287dc7d18ffStshiozak static __inline int
get_max(_ISO2022EncodingInfo * __restrict ei,const char * __restrict token)288dc7d18ffStshiozak get_max(_ISO2022EncodingInfo * __restrict ei,
289dc7d18ffStshiozak const char * __restrict token)
290dc7d18ffStshiozak {
291dc7d18ffStshiozak if (!strcmp(token, "MAX1")) {
292dc7d18ffStshiozak ei->maxcharset = 1;
293dc7d18ffStshiozak } else if (!strcmp(token, "MAX2")) {
294dc7d18ffStshiozak ei->maxcharset = 2;
295dc7d18ffStshiozak } else if (!strcmp(token, "MAX3")) {
296dc7d18ffStshiozak ei->maxcharset = 3;
297dc7d18ffStshiozak } else
298dc7d18ffStshiozak return (_NOTMATCH);
299dc7d18ffStshiozak
300dc7d18ffStshiozak return (_MATCH);
301dc7d18ffStshiozak }
302dc7d18ffStshiozak
303dc7d18ffStshiozak
304dc7d18ffStshiozak static __inline int
get_flags(_ISO2022EncodingInfo * __restrict ei,const char * __restrict token)305dc7d18ffStshiozak get_flags(_ISO2022EncodingInfo * __restrict ei,
306dc7d18ffStshiozak const char * __restrict token)
307dc7d18ffStshiozak {
308dc7d18ffStshiozak int i;
309dc7d18ffStshiozak static struct {
310dc7d18ffStshiozak const char *tag;
311dc7d18ffStshiozak int flag;
312dc7d18ffStshiozak } const tags[] = {
313dc7d18ffStshiozak { "DUMMY", 0 },
314dc7d18ffStshiozak { "8BIT", F_8BIT },
315dc7d18ffStshiozak { "NOOLD", F_NOOLD },
316dc7d18ffStshiozak { "SI", F_SI },
317dc7d18ffStshiozak { "SO", F_SO },
318dc7d18ffStshiozak { "LS0", F_LS0 },
319dc7d18ffStshiozak { "LS1", F_LS1 },
320dc7d18ffStshiozak { "LS2", F_LS2 },
321dc7d18ffStshiozak { "LS3", F_LS3 },
322dc7d18ffStshiozak { "LS1R", F_LS1R },
323dc7d18ffStshiozak { "LS2R", F_LS2R },
324dc7d18ffStshiozak { "LS3R", F_LS3R },
325dc7d18ffStshiozak { "SS2", F_SS2 },
326dc7d18ffStshiozak { "SS3", F_SS3 },
327dc7d18ffStshiozak { "SS2R", F_SS2R },
328dc7d18ffStshiozak { "SS3R", F_SS3R },
329dc7d18ffStshiozak { NULL, 0 }
330dc7d18ffStshiozak };
331dc7d18ffStshiozak
332dc7d18ffStshiozak for (i = 0; tags[i].tag; i++) {
333dc7d18ffStshiozak if (!strcmp(token, tags[i].tag)) {
334dc7d18ffStshiozak ei->flags |= tags[i].flag;
335dc7d18ffStshiozak return (_MATCH);
336dc7d18ffStshiozak }
337dc7d18ffStshiozak }
338dc7d18ffStshiozak
339dc7d18ffStshiozak return (_NOTMATCH);
340dc7d18ffStshiozak }
341dc7d18ffStshiozak
342dc7d18ffStshiozak
343dc7d18ffStshiozak static __inline int
_citrus_ISO2022_parse_variable(_ISO2022EncodingInfo * __restrict ei,const void * __restrict var,size_t lenvar)344dc7d18ffStshiozak _citrus_ISO2022_parse_variable(_ISO2022EncodingInfo * __restrict ei,
345dc7d18ffStshiozak const void * __restrict var, size_t lenvar)
346dc7d18ffStshiozak {
347dc7d18ffStshiozak char const *v, *e;
348dc7d18ffStshiozak char buf[20];
349dc7d18ffStshiozak int i, len, ret;
350dc7d18ffStshiozak
351dc7d18ffStshiozak _DIAGASSERT(ei != NULL);
352dc7d18ffStshiozak
353dc7d18ffStshiozak
354dc7d18ffStshiozak /*
355dc7d18ffStshiozak * parse VARIABLE section.
356dc7d18ffStshiozak */
357dc7d18ffStshiozak
358dc7d18ffStshiozak if (!var)
359dc7d18ffStshiozak return (EFTYPE);
360dc7d18ffStshiozak
361dc7d18ffStshiozak v = (const char *) var;
362dc7d18ffStshiozak
363dc7d18ffStshiozak /* initialize structure */
364dc7d18ffStshiozak ei->maxcharset = 0;
365dc7d18ffStshiozak for (i = 0; i < 4; i++) {
366dc7d18ffStshiozak ei->recommend[i] = NULL;
367dc7d18ffStshiozak ei->recommendsize[i] = 0;
368dc7d18ffStshiozak }
369dc7d18ffStshiozak ei->flags = 0;
370dc7d18ffStshiozak
371dc7d18ffStshiozak while (*v) {
372dc7d18ffStshiozak while (*v == ' ' || *v == '\t')
373dc7d18ffStshiozak ++v;
374dc7d18ffStshiozak
375dc7d18ffStshiozak /* find the token */
376dc7d18ffStshiozak e = v;
377dc7d18ffStshiozak while (*e && *e != ' ' && *e != '\t')
378dc7d18ffStshiozak ++e;
37904e58308Stshiozak
380dc7d18ffStshiozak len = e-v;
38104e58308Stshiozak if (len == 0)
38204e58308Stshiozak break;
383dc7d18ffStshiozak if (len>=sizeof(buf))
384dc7d18ffStshiozak goto parsefail;
3852ec4a590Sitojun snprintf(buf, sizeof(buf), "%.*s", len, v);
386dc7d18ffStshiozak
387dc7d18ffStshiozak if ((ret = get_recommend(ei, buf)) != _NOTMATCH)
388dc7d18ffStshiozak ;
389dc7d18ffStshiozak else if ((ret = get_initg(ei, buf)) != _NOTMATCH)
390dc7d18ffStshiozak ;
391dc7d18ffStshiozak else if ((ret = get_max(ei, buf)) != _NOTMATCH)
392dc7d18ffStshiozak ;
393dc7d18ffStshiozak else if ((ret = get_flags(ei, buf)) != _NOTMATCH)
394dc7d18ffStshiozak ;
395dc7d18ffStshiozak else
396dc7d18ffStshiozak ret = _PARSEFAIL;
397dc7d18ffStshiozak if (ret==_PARSEFAIL)
398dc7d18ffStshiozak goto parsefail;
399dc7d18ffStshiozak v = e;
400dc7d18ffStshiozak
401dc7d18ffStshiozak }
402dc7d18ffStshiozak
403dc7d18ffStshiozak return (0);
404dc7d18ffStshiozak
405dc7d18ffStshiozak parsefail:
406dc7d18ffStshiozak free(ei->recommend[0]);
407dc7d18ffStshiozak free(ei->recommend[1]);
408dc7d18ffStshiozak free(ei->recommend[2]);
409dc7d18ffStshiozak free(ei->recommend[3]);
410dc7d18ffStshiozak
411dc7d18ffStshiozak return (EFTYPE);
412dc7d18ffStshiozak }
413dc7d18ffStshiozak
414dc7d18ffStshiozak static __inline void
415dc7d18ffStshiozak /*ARGSUSED*/
_citrus_ISO2022_init_state(_ISO2022EncodingInfo * __restrict ei,_ISO2022State * __restrict s)416dc7d18ffStshiozak _citrus_ISO2022_init_state(_ISO2022EncodingInfo * __restrict ei,
417dc7d18ffStshiozak _ISO2022State * __restrict s)
418dc7d18ffStshiozak {
419dc7d18ffStshiozak int i;
420dc7d18ffStshiozak
421dc7d18ffStshiozak memset(s, 0, sizeof(*s));
422dc7d18ffStshiozak s->gl = 0;
423dc7d18ffStshiozak s->gr = (ei->flags & F_8BIT) ? 1 : -1;
424dc7d18ffStshiozak
425dc7d18ffStshiozak for (i = 0; i < 4; i++) {
426dc7d18ffStshiozak if (ei->initg[i].final) {
427dc7d18ffStshiozak s->g[i].type = ei->initg[i].type;
428dc7d18ffStshiozak s->g[i].final = ei->initg[i].final;
429dc7d18ffStshiozak s->g[i].interm = ei->initg[i].interm;
430dc7d18ffStshiozak }
431dc7d18ffStshiozak }
432dc7d18ffStshiozak s->singlegl = s->singlegr = -1;
4333daba72aSyamt s->flags |= _ISO2022STATE_FLAG_INITIALIZED;
434dc7d18ffStshiozak }
435dc7d18ffStshiozak
436dc7d18ffStshiozak static __inline void
437dc7d18ffStshiozak /*ARGSUSED*/
_citrus_ISO2022_pack_state(_ISO2022EncodingInfo * __restrict ei,void * __restrict pspriv,const _ISO2022State * __restrict s)438dc7d18ffStshiozak _citrus_ISO2022_pack_state(_ISO2022EncodingInfo * __restrict ei,
439dc7d18ffStshiozak void * __restrict pspriv,
440dc7d18ffStshiozak const _ISO2022State * __restrict s)
441dc7d18ffStshiozak {
442dc7d18ffStshiozak memcpy(pspriv, (const void *)s, sizeof(*s));
443dc7d18ffStshiozak }
444dc7d18ffStshiozak
445dc7d18ffStshiozak static __inline void
446dc7d18ffStshiozak /*ARGSUSED*/
_citrus_ISO2022_unpack_state(_ISO2022EncodingInfo * __restrict ei,_ISO2022State * __restrict s,const void * __restrict pspriv)447dc7d18ffStshiozak _citrus_ISO2022_unpack_state(_ISO2022EncodingInfo * __restrict ei,
448dc7d18ffStshiozak _ISO2022State * __restrict s,
449dc7d18ffStshiozak const void * __restrict pspriv)
450dc7d18ffStshiozak {
451dc7d18ffStshiozak memcpy((void *)s, pspriv, sizeof(*s));
452dc7d18ffStshiozak }
453dc7d18ffStshiozak
454dc7d18ffStshiozak static int
455dc7d18ffStshiozak /*ARGSUSED*/
_citrus_ISO2022_encoding_module_init(_ISO2022EncodingInfo * __restrict ei,const void * __restrict var,size_t lenvar)45604e58308Stshiozak _citrus_ISO2022_encoding_module_init(_ISO2022EncodingInfo * __restrict ei,
45704e58308Stshiozak const void * __restrict var,
45804e58308Stshiozak size_t lenvar)
459dc7d18ffStshiozak {
460dc7d18ffStshiozak
461dc7d18ffStshiozak _DIAGASSERT(ei != NULL);
462dc7d18ffStshiozak
463dc7d18ffStshiozak return _citrus_ISO2022_parse_variable(ei, var, lenvar);
464dc7d18ffStshiozak }
465dc7d18ffStshiozak
466dc7d18ffStshiozak static void
467dc7d18ffStshiozak /*ARGSUSED*/
_citrus_ISO2022_encoding_module_uninit(_ISO2022EncodingInfo * ei)46804e58308Stshiozak _citrus_ISO2022_encoding_module_uninit(_ISO2022EncodingInfo *ei)
469dc7d18ffStshiozak {
470dc7d18ffStshiozak }
471dc7d18ffStshiozak
472dc7d18ffStshiozak #define ESC '\033'
473dc7d18ffStshiozak #define ECMA -1
474dc7d18ffStshiozak #define INTERM -2
475dc7d18ffStshiozak #define OECMA -3
4765b3d2342Syamt static const struct seqtable {
477dc7d18ffStshiozak int type;
478dc7d18ffStshiozak int csoff;
479dc7d18ffStshiozak int finaloff;
480dc7d18ffStshiozak int intermoff;
481dc7d18ffStshiozak int versoff;
482dc7d18ffStshiozak int len;
483dc7d18ffStshiozak int chars[10];
484dc7d18ffStshiozak } seqtable[] = {
485dc7d18ffStshiozak /* G0 94MULTI special */
486dc7d18ffStshiozak { CS94MULTI, -1, 2, -1, -1, 3, { ESC, '$', OECMA }, },
487dc7d18ffStshiozak /* G0 94MULTI special with version identification */
488dc7d18ffStshiozak { CS94MULTI, -1, 5, -1, 2, 6, { ESC, '&', ECMA, ESC, '$', OECMA }, },
489dc7d18ffStshiozak /* G? 94 */
490dc7d18ffStshiozak { CS94, 1, 2, -1, -1, 3, { ESC, CS94, ECMA, }, },
491dc7d18ffStshiozak /* G? 94 with 2nd intermediate char */
492dc7d18ffStshiozak { CS94, 1, 3, 2, -1, 4, { ESC, CS94, INTERM, ECMA, }, },
493dc7d18ffStshiozak /* G? 96 */
494dc7d18ffStshiozak { CS96, 1, 2, -1, -1, 3, { ESC, CS96, ECMA, }, },
495dc7d18ffStshiozak /* G? 96 with 2nd intermediate char */
496dc7d18ffStshiozak { CS96, 1, 3, 2, -1, 4, { ESC, CS96, INTERM, ECMA, }, },
497dc7d18ffStshiozak /* G? 94MULTI */
498dc7d18ffStshiozak { CS94MULTI, 2, 3, -1, -1, 4, { ESC, '$', CS94, ECMA, }, },
499dc7d18ffStshiozak /* G? 96MULTI */
500dc7d18ffStshiozak { CS96MULTI, 2, 3, -1, -1, 4, { ESC, '$', CS96, ECMA, }, },
501dc7d18ffStshiozak /* G? 94MULTI with version specification */
502dc7d18ffStshiozak { CS94MULTI, 5, 6, -1, 2, 7, { ESC, '&', ECMA, ESC, '$', CS94, ECMA, }, },
503dc7d18ffStshiozak /* LS2/3 */
504dc7d18ffStshiozak { -1, -1, -1, -1, -1, 2, { ESC, 'n', }, },
505dc7d18ffStshiozak { -1, -1, -1, -1, -1, 2, { ESC, 'o', }, },
506dc7d18ffStshiozak /* LS1/2/3R */
507dc7d18ffStshiozak { -1, -1, -1, -1, -1, 2, { ESC, '~', }, },
508dc7d18ffStshiozak { -1, -1, -1, -1, -1, 2, { ESC, /*{*/ '}', }, },
509dc7d18ffStshiozak { -1, -1, -1, -1, -1, 2, { ESC, '|', }, },
510dc7d18ffStshiozak /* SS2/3 */
511dc7d18ffStshiozak { -1, -1, -1, -1, -1, 2, { ESC, 'N', }, },
512dc7d18ffStshiozak { -1, -1, -1, -1, -1, 2, { ESC, 'O', }, },
513dc7d18ffStshiozak /* end of records */
514dc7d18ffStshiozak { 0, }
515dc7d18ffStshiozak };
516dc7d18ffStshiozak
517dc7d18ffStshiozak static int
seqmatch(const char * __restrict s,size_t n,const struct seqtable * __restrict sp)518dc7d18ffStshiozak seqmatch(const char * __restrict s, size_t n,
519dc7d18ffStshiozak const struct seqtable * __restrict sp)
520dc7d18ffStshiozak {
521dc7d18ffStshiozak const int *p;
522dc7d18ffStshiozak
523dc7d18ffStshiozak _DIAGASSERT(s != NULL);
524dc7d18ffStshiozak _DIAGASSERT(sp != NULL);
525dc7d18ffStshiozak
526dc7d18ffStshiozak p = sp->chars;
527dc7d18ffStshiozak while (p - sp->chars < n && p - sp->chars < sp->len) {
528dc7d18ffStshiozak switch (*p) {
529dc7d18ffStshiozak case ECMA:
530dc7d18ffStshiozak if (!isecma(*s))
531dc7d18ffStshiozak goto terminate;
532dc7d18ffStshiozak break;
533dc7d18ffStshiozak case OECMA:
534dc7d18ffStshiozak if (*s && strchr("@AB", *s))
535dc7d18ffStshiozak break;
536dc7d18ffStshiozak else
537dc7d18ffStshiozak goto terminate;
538dc7d18ffStshiozak case INTERM:
539dc7d18ffStshiozak if (!isinterm(*s))
540dc7d18ffStshiozak goto terminate;
541dc7d18ffStshiozak break;
542dc7d18ffStshiozak case CS94:
543dc7d18ffStshiozak if (*s && strchr("()*+", *s))
544dc7d18ffStshiozak break;
545dc7d18ffStshiozak else
546dc7d18ffStshiozak goto terminate;
547dc7d18ffStshiozak case CS96:
548dc7d18ffStshiozak if (*s && strchr(",-./", *s))
549dc7d18ffStshiozak break;
550dc7d18ffStshiozak else
551dc7d18ffStshiozak goto terminate;
552dc7d18ffStshiozak default:
553dc7d18ffStshiozak if (*s != *p)
554dc7d18ffStshiozak goto terminate;
555dc7d18ffStshiozak break;
556dc7d18ffStshiozak }
557dc7d18ffStshiozak
558dc7d18ffStshiozak p++;
559dc7d18ffStshiozak s++;
560dc7d18ffStshiozak }
561dc7d18ffStshiozak
562dc7d18ffStshiozak terminate:
563dc7d18ffStshiozak return p - sp->chars;
564dc7d18ffStshiozak }
565dc7d18ffStshiozak
566dc7d18ffStshiozak static wchar_t
_ISO2022_sgetwchar(_ISO2022EncodingInfo * __restrict ei,const char * __restrict string,size_t n,const char ** __restrict result,_ISO2022State * __restrict psenc)567dc7d18ffStshiozak _ISO2022_sgetwchar(_ISO2022EncodingInfo * __restrict ei,
568dc7d18ffStshiozak const char * __restrict string, size_t n,
569dc7d18ffStshiozak const char ** __restrict result,
570dc7d18ffStshiozak _ISO2022State * __restrict psenc)
571dc7d18ffStshiozak {
572dc7d18ffStshiozak wchar_t wchar = 0;
573dc7d18ffStshiozak int cur;
5745b3d2342Syamt const struct seqtable *sp;
575dc7d18ffStshiozak int nmatch;
576dc7d18ffStshiozak int i;
577dc7d18ffStshiozak
578dc7d18ffStshiozak _DIAGASSERT(ei != NULL);
579476f0d92Stnozaki _DIAGASSERT(psenc != NULL);
580dc7d18ffStshiozak _DIAGASSERT(string != NULL);
581dc7d18ffStshiozak /* result may be NULL */
582dc7d18ffStshiozak
583dc7d18ffStshiozak while (1) {
584dc7d18ffStshiozak /* SI/SO */
585dc7d18ffStshiozak if (1 <= n && string[0] == '\017') {
586dc7d18ffStshiozak psenc->gl = 0;
587dc7d18ffStshiozak string++;
588dc7d18ffStshiozak n--;
589dc7d18ffStshiozak continue;
590dc7d18ffStshiozak }
591dc7d18ffStshiozak if (1 <= n && string[0] == '\016') {
592dc7d18ffStshiozak psenc->gl = 1;
593dc7d18ffStshiozak string++;
594dc7d18ffStshiozak n--;
595dc7d18ffStshiozak continue;
596dc7d18ffStshiozak }
597dc7d18ffStshiozak
598dc7d18ffStshiozak /* SS2/3R */
599dc7d18ffStshiozak if (1 <= n && string[0] && strchr("\217\216", string[0])) {
600dc7d18ffStshiozak psenc->singlegl = psenc->singlegr =
601dc7d18ffStshiozak (string[0] - '\216') + 2;
602dc7d18ffStshiozak string++;
603dc7d18ffStshiozak n--;
604dc7d18ffStshiozak continue;
605dc7d18ffStshiozak }
606dc7d18ffStshiozak
607dc7d18ffStshiozak /* eat the letter if this is not ESC */
608dc7d18ffStshiozak if (1 <= n && string[0] != '\033')
609dc7d18ffStshiozak break;
610dc7d18ffStshiozak
611dc7d18ffStshiozak /* look for a perfect match from escape sequences */
612dc7d18ffStshiozak for (sp = &seqtable[0]; sp->len; sp++) {
613dc7d18ffStshiozak nmatch = seqmatch(string, n, sp);
614dc7d18ffStshiozak if (sp->len == nmatch && n >= sp->len)
615dc7d18ffStshiozak break;
616dc7d18ffStshiozak }
617dc7d18ffStshiozak
618dc7d18ffStshiozak if (!sp->len)
619dc7d18ffStshiozak goto notseq;
620dc7d18ffStshiozak
621dc7d18ffStshiozak if (sp->type != -1) {
622dc7d18ffStshiozak if (sp->csoff == -1)
623dc7d18ffStshiozak i = 0;
624dc7d18ffStshiozak else {
625dc7d18ffStshiozak switch (sp->type) {
626dc7d18ffStshiozak case CS94:
627dc7d18ffStshiozak case CS94MULTI:
628dc7d18ffStshiozak i = string[sp->csoff] - '(';
629dc7d18ffStshiozak break;
630dc7d18ffStshiozak case CS96:
631dc7d18ffStshiozak case CS96MULTI:
632dc7d18ffStshiozak i = string[sp->csoff] - ',';
633dc7d18ffStshiozak break;
6345bd7f658Schristos default:
6355bd7f658Schristos return (_ISO2022INVALID);
636dc7d18ffStshiozak }
637dc7d18ffStshiozak }
638dc7d18ffStshiozak psenc->g[i].type = sp->type;
639dc7d18ffStshiozak psenc->g[i].final = '\0';
640dc7d18ffStshiozak psenc->g[i].interm = '\0';
641dc7d18ffStshiozak psenc->g[i].vers = '\0';
642dc7d18ffStshiozak /* sp->finaloff must not be -1 */
643dc7d18ffStshiozak if (sp->finaloff != -1)
644dc7d18ffStshiozak psenc->g[i].final = string[sp->finaloff];
645dc7d18ffStshiozak if (sp->intermoff != -1)
646dc7d18ffStshiozak psenc->g[i].interm = string[sp->intermoff];
647dc7d18ffStshiozak if (sp->versoff != -1)
648dc7d18ffStshiozak psenc->g[i].vers = string[sp->versoff];
649dc7d18ffStshiozak
650dc7d18ffStshiozak string += sp->len;
651dc7d18ffStshiozak n -= sp->len;
652dc7d18ffStshiozak continue;
653dc7d18ffStshiozak }
654dc7d18ffStshiozak
655dc7d18ffStshiozak /* LS2/3 */
656dc7d18ffStshiozak if (2 <= n && string[0] == '\033'
657dc7d18ffStshiozak && string[1] && strchr("no", string[1])) {
658dc7d18ffStshiozak psenc->gl = string[1] - 'n' + 2;
659dc7d18ffStshiozak string += 2;
660dc7d18ffStshiozak n -= 2;
661dc7d18ffStshiozak continue;
662dc7d18ffStshiozak }
663dc7d18ffStshiozak
664dc7d18ffStshiozak /* LS1/2/3R */
665dc7d18ffStshiozak /* XXX: { for vi showmatch */
666dc7d18ffStshiozak if (2 <= n && string[0] == '\033'
667dc7d18ffStshiozak && string[1] && strchr("~}|", string[1])) {
668dc7d18ffStshiozak psenc->gr = 3 - (string[1] - '|');
669dc7d18ffStshiozak string += 2;
670dc7d18ffStshiozak n -= 2;
671dc7d18ffStshiozak continue;
672dc7d18ffStshiozak }
673dc7d18ffStshiozak
674dc7d18ffStshiozak /* SS2/3 */
675dc7d18ffStshiozak if (2 <= n && string[0] == '\033'
676dc7d18ffStshiozak && string[1] && strchr("NO", string[1])) {
677dc7d18ffStshiozak psenc->singlegl = (string[1] - 'N') + 2;
678dc7d18ffStshiozak string += 2;
679dc7d18ffStshiozak n -= 2;
680dc7d18ffStshiozak continue;
681dc7d18ffStshiozak }
682dc7d18ffStshiozak
683dc7d18ffStshiozak notseq:
684dc7d18ffStshiozak /*
685dc7d18ffStshiozak * if we've got an unknown escape sequence, eat the ESC at the
686dc7d18ffStshiozak * head. otherwise, wait till full escape sequence comes.
687dc7d18ffStshiozak */
688dc7d18ffStshiozak for (sp = &seqtable[0]; sp->len; sp++) {
689dc7d18ffStshiozak nmatch = seqmatch(string, n, sp);
690dc7d18ffStshiozak if (!nmatch)
691dc7d18ffStshiozak continue;
692dc7d18ffStshiozak
693dc7d18ffStshiozak /*
694dc7d18ffStshiozak * if we are in the middle of escape sequence,
695dc7d18ffStshiozak * we still need to wait for more characters to come
696dc7d18ffStshiozak */
697dc7d18ffStshiozak if (n < sp->len) {
698dc7d18ffStshiozak if (nmatch == n) {
699dc7d18ffStshiozak if (result)
7006b58a1b8Stnozaki *result = string;
701dc7d18ffStshiozak return (_ISO2022INVALID);
702dc7d18ffStshiozak }
703dc7d18ffStshiozak } else {
704dc7d18ffStshiozak if (nmatch == sp->len) {
705dc7d18ffStshiozak /* this case should not happen */
706dc7d18ffStshiozak goto eat;
707dc7d18ffStshiozak }
708dc7d18ffStshiozak }
709dc7d18ffStshiozak }
710dc7d18ffStshiozak
711dc7d18ffStshiozak break;
712dc7d18ffStshiozak }
713dc7d18ffStshiozak
714dc7d18ffStshiozak eat:
715dc7d18ffStshiozak /* no letter to eat */
716dc7d18ffStshiozak if (n < 1) {
717dc7d18ffStshiozak if (result)
718dc7d18ffStshiozak *result = string;
719dc7d18ffStshiozak return (_ISO2022INVALID);
720dc7d18ffStshiozak }
721dc7d18ffStshiozak
722dc7d18ffStshiozak /* normal chars. always eat C0/C1 as is. */
723dc7d18ffStshiozak if (iscntl(*string & 0xff))
724dc7d18ffStshiozak cur = -1;
725dc7d18ffStshiozak else if (*string & 0x80) {
726dc7d18ffStshiozak cur = (psenc->singlegr == -1)
727dc7d18ffStshiozak ? psenc->gr : psenc->singlegr;
728dc7d18ffStshiozak } else {
729dc7d18ffStshiozak cur = (psenc->singlegl == -1)
730dc7d18ffStshiozak ? psenc->gl : psenc->singlegl;
731dc7d18ffStshiozak }
732dc7d18ffStshiozak
733dc7d18ffStshiozak if (cur == -1) {
734dc7d18ffStshiozak asis:
735dc7d18ffStshiozak wchar = *string++ & 0xff;
736dc7d18ffStshiozak if (result)
737dc7d18ffStshiozak *result = string;
738dc7d18ffStshiozak /* reset single shift state */
739dc7d18ffStshiozak psenc->singlegr = psenc->singlegl = -1;
740dc7d18ffStshiozak return wchar;
741dc7d18ffStshiozak }
742dc7d18ffStshiozak
743dc7d18ffStshiozak /* length error check */
744dc7d18ffStshiozak switch (psenc->g[cur].type) {
745dc7d18ffStshiozak case CS94MULTI:
746dc7d18ffStshiozak case CS96MULTI:
747dc7d18ffStshiozak if (!isthree(psenc->g[cur].final)) {
748dc7d18ffStshiozak if (2 <= n
749dc7d18ffStshiozak && (string[0] & 0x80) == (string[1] & 0x80))
750dc7d18ffStshiozak break;
751dc7d18ffStshiozak } else {
752dc7d18ffStshiozak if (3 <= n
753dc7d18ffStshiozak && (string[0] & 0x80) == (string[1] & 0x80)
754dc7d18ffStshiozak && (string[0] & 0x80) == (string[2] & 0x80))
755dc7d18ffStshiozak break;
756dc7d18ffStshiozak }
757dc7d18ffStshiozak
758dc7d18ffStshiozak /* we still need to wait for more characters to come */
759dc7d18ffStshiozak if (result)
7606b58a1b8Stnozaki *result = string;
761dc7d18ffStshiozak return (_ISO2022INVALID);
762dc7d18ffStshiozak
763dc7d18ffStshiozak case CS94:
764dc7d18ffStshiozak case CS96:
765dc7d18ffStshiozak if (1 <= n)
766dc7d18ffStshiozak break;
767dc7d18ffStshiozak
768dc7d18ffStshiozak /* we still need to wait for more characters to come */
769dc7d18ffStshiozak if (result)
7706b58a1b8Stnozaki *result = string;
771dc7d18ffStshiozak return (_ISO2022INVALID);
772dc7d18ffStshiozak }
773dc7d18ffStshiozak
774dc7d18ffStshiozak /* range check */
775dc7d18ffStshiozak switch (psenc->g[cur].type) {
776dc7d18ffStshiozak case CS94:
777dc7d18ffStshiozak if (!(is94(string[0] & 0x7f)))
778dc7d18ffStshiozak goto asis;
779dc7d18ffStshiozak case CS96:
780dc7d18ffStshiozak if (!(is96(string[0] & 0x7f)))
781dc7d18ffStshiozak goto asis;
782dc7d18ffStshiozak break;
783dc7d18ffStshiozak case CS94MULTI:
784dc7d18ffStshiozak if (!(is94(string[0] & 0x7f) && is94(string[1] & 0x7f)))
785dc7d18ffStshiozak goto asis;
786dc7d18ffStshiozak break;
787dc7d18ffStshiozak case CS96MULTI:
788dc7d18ffStshiozak if (!(is96(string[0] & 0x7f) && is96(string[1] & 0x7f)))
789dc7d18ffStshiozak goto asis;
790dc7d18ffStshiozak break;
791dc7d18ffStshiozak }
792dc7d18ffStshiozak
793dc7d18ffStshiozak /* extract the character. */
794dc7d18ffStshiozak switch (psenc->g[cur].type) {
795dc7d18ffStshiozak case CS94:
796dc7d18ffStshiozak /* special case for ASCII. */
797dc7d18ffStshiozak if (psenc->g[cur].final == 'B' && !psenc->g[cur].interm) {
798dc7d18ffStshiozak wchar = *string++;
799dc7d18ffStshiozak wchar &= 0x7f;
800dc7d18ffStshiozak break;
801dc7d18ffStshiozak }
802dc7d18ffStshiozak wchar = psenc->g[cur].final;
803dc7d18ffStshiozak wchar = (wchar << 8);
804dc7d18ffStshiozak wchar |= (psenc->g[cur].interm ? (0x80 | psenc->g[cur].interm) : 0);
805dc7d18ffStshiozak wchar = (wchar << 8);
806dc7d18ffStshiozak wchar = (wchar << 8) | (*string++ & 0x7f);
807dc7d18ffStshiozak break;
808dc7d18ffStshiozak case CS96:
809dc7d18ffStshiozak /* special case for ISO-8859-1. */
810dc7d18ffStshiozak if (psenc->g[cur].final == 'A' && !psenc->g[cur].interm) {
811dc7d18ffStshiozak wchar = *string++;
812dc7d18ffStshiozak wchar &= 0x7f;
813dc7d18ffStshiozak wchar |= 0x80;
814dc7d18ffStshiozak break;
815dc7d18ffStshiozak }
816dc7d18ffStshiozak wchar = psenc->g[cur].final;
817dc7d18ffStshiozak wchar = (wchar << 8);
818dc7d18ffStshiozak wchar |= (psenc->g[cur].interm ? (0x80 | psenc->g[cur].interm) : 0);
819dc7d18ffStshiozak wchar = (wchar << 8);
820dc7d18ffStshiozak wchar = (wchar << 8) | (*string++ & 0x7f);
821dc7d18ffStshiozak wchar |= 0x80;
822dc7d18ffStshiozak break;
823dc7d18ffStshiozak case CS94MULTI:
824dc7d18ffStshiozak case CS96MULTI:
825dc7d18ffStshiozak wchar = psenc->g[cur].final;
826dc7d18ffStshiozak wchar = (wchar << 8);
827dc7d18ffStshiozak if (isthree(psenc->g[cur].final))
828dc7d18ffStshiozak wchar |= (*string++ & 0x7f);
829dc7d18ffStshiozak wchar = (wchar << 8) | (*string++ & 0x7f);
830dc7d18ffStshiozak wchar = (wchar << 8) | (*string++ & 0x7f);
831dc7d18ffStshiozak if (psenc->g[cur].type == CS96MULTI)
832dc7d18ffStshiozak wchar |= 0x80;
833dc7d18ffStshiozak break;
834dc7d18ffStshiozak }
835dc7d18ffStshiozak
836dc7d18ffStshiozak if (result)
837dc7d18ffStshiozak *result = string;
838dc7d18ffStshiozak /* reset single shift state */
839dc7d18ffStshiozak psenc->singlegr = psenc->singlegl = -1;
840dc7d18ffStshiozak return wchar;
841dc7d18ffStshiozak }
842dc7d18ffStshiozak
843dc7d18ffStshiozak
844dc7d18ffStshiozak
845dc7d18ffStshiozak 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)846dc7d18ffStshiozak _citrus_ISO2022_mbrtowc_priv(_ISO2022EncodingInfo * __restrict ei,
847dc7d18ffStshiozak wchar_t * __restrict pwc,
848dc7d18ffStshiozak const char ** __restrict s,
849dc7d18ffStshiozak size_t n, _ISO2022State * __restrict psenc,
850dc7d18ffStshiozak size_t * __restrict nresult)
851dc7d18ffStshiozak {
852dc7d18ffStshiozak wchar_t wchar;
853dc7d18ffStshiozak const char *s0, *p, *result;
854dc7d18ffStshiozak int c;
855dc7d18ffStshiozak int chlenbak;
856dc7d18ffStshiozak
857dc7d18ffStshiozak _DIAGASSERT(nresult != 0);
858dc7d18ffStshiozak _DIAGASSERT(ei != NULL);
859dc7d18ffStshiozak _DIAGASSERT(psenc != NULL);
860dc7d18ffStshiozak _DIAGASSERT(s != NULL);
861dc7d18ffStshiozak
8620941b12bStnozaki if (*s == NULL) {
8630941b12bStnozaki _citrus_ISO2022_init_state(ei, psenc);
8640941b12bStnozaki *nresult = _ENCODING_IS_STATE_DEPENDENT;
8650941b12bStnozaki return 0;
8660941b12bStnozaki }
867dc7d18ffStshiozak s0 = *s;
868dc7d18ffStshiozak c = 0;
869dc7d18ffStshiozak chlenbak = psenc->chlen;
870dc7d18ffStshiozak
871dc7d18ffStshiozak /*
872dc7d18ffStshiozak * if we have something in buffer, use that.
873dc7d18ffStshiozak * otherwise, skip here
874dc7d18ffStshiozak */
875dc7d18ffStshiozak if (psenc->chlen < 0 || psenc->chlen > sizeof(psenc->ch)) {
876dc7d18ffStshiozak /* illgeal state */
877dc7d18ffStshiozak _citrus_ISO2022_init_state(ei, psenc);
878dc7d18ffStshiozak goto encoding_error;
879dc7d18ffStshiozak }
880dc7d18ffStshiozak if (psenc->chlen == 0)
881dc7d18ffStshiozak goto emptybuf;
882dc7d18ffStshiozak
883dc7d18ffStshiozak /* buffer is not empty */
884dc7d18ffStshiozak p = psenc->ch;
885e325eedcSjoerg while (psenc->chlen < sizeof(psenc->ch)) {
886dc7d18ffStshiozak if (n > 0) {
887dc7d18ffStshiozak psenc->ch[psenc->chlen++] = *s0++;
888dc7d18ffStshiozak n--;
889dc7d18ffStshiozak }
890dc7d18ffStshiozak
891dc7d18ffStshiozak wchar = _ISO2022_sgetwchar(ei, p, psenc->chlen - (p-psenc->ch),
892dc7d18ffStshiozak &result, psenc);
893dc7d18ffStshiozak c += result - p;
8941beef8feStshiozak if (wchar != _ISO2022INVALID) {
895dc7d18ffStshiozak if (psenc->chlen > c)
896dc7d18ffStshiozak memmove(psenc->ch, result, psenc->chlen - c);
897dc7d18ffStshiozak if (psenc->chlen < c)
898dc7d18ffStshiozak psenc->chlen = 0;
899dc7d18ffStshiozak else
900dc7d18ffStshiozak psenc->chlen -= c;
901dc7d18ffStshiozak goto output;
902dc7d18ffStshiozak }
903dc7d18ffStshiozak
9041beef8feStshiozak if (n == 0) {
9051beef8feStshiozak if ((result - p) == psenc->chlen)
9061beef8feStshiozak /* complete shift sequence. */
9071beef8feStshiozak psenc->chlen = 0;
908dc7d18ffStshiozak goto restart;
909dc7d18ffStshiozak }
910dc7d18ffStshiozak
9111beef8feStshiozak p = result;
9121beef8feStshiozak }
9131beef8feStshiozak
914dc7d18ffStshiozak /* escape sequence too long? */
915dc7d18ffStshiozak goto encoding_error;
916dc7d18ffStshiozak
917dc7d18ffStshiozak emptybuf:
918dc7d18ffStshiozak wchar = _ISO2022_sgetwchar(ei, s0, n, &result, psenc);
919dc7d18ffStshiozak if (wchar != _ISO2022INVALID) {
920dc7d18ffStshiozak c += result - s0;
921dc7d18ffStshiozak psenc->chlen = 0;
922dc7d18ffStshiozak s0 = result;
923dc7d18ffStshiozak goto output;
924dc7d18ffStshiozak }
9251beef8feStshiozak if (result > s0) {
926dc7d18ffStshiozak c += (result - s0);
927dc7d18ffStshiozak n -= (result - s0);
928dc7d18ffStshiozak s0 = result;
9291beef8feStshiozak if (n>0)
930dc7d18ffStshiozak goto emptybuf;
9311beef8feStshiozak /* complete shift sequence. */
9321beef8feStshiozak goto restart;
933dc7d18ffStshiozak }
934dc7d18ffStshiozak n += c;
935dc7d18ffStshiozak if (n < sizeof(psenc->ch)) {
936dc7d18ffStshiozak memcpy(psenc->ch, s0 - c, n);
937dc7d18ffStshiozak psenc->chlen = n;
938dc7d18ffStshiozak s0 = result;
939dc7d18ffStshiozak goto restart;
940dc7d18ffStshiozak }
941dc7d18ffStshiozak
942dc7d18ffStshiozak /* escape sequence too long? */
943dc7d18ffStshiozak
944dc7d18ffStshiozak encoding_error:
945dc7d18ffStshiozak psenc->chlen = 0;
946dc7d18ffStshiozak *nresult = (size_t)-1;
947dc7d18ffStshiozak return (EILSEQ);
948dc7d18ffStshiozak
949dc7d18ffStshiozak output:
950dc7d18ffStshiozak *s = s0;
951dc7d18ffStshiozak if (pwc)
952dc7d18ffStshiozak *pwc = wchar;
953dc7d18ffStshiozak
954dc7d18ffStshiozak if (!wchar)
955dc7d18ffStshiozak *nresult = 0;
956dc7d18ffStshiozak else
957dc7d18ffStshiozak *nresult = c - chlenbak;
958dc7d18ffStshiozak
959dc7d18ffStshiozak return (0);
960dc7d18ffStshiozak
961dc7d18ffStshiozak restart:
962dc7d18ffStshiozak *s = s0;
963dc7d18ffStshiozak *nresult = (size_t)-2;
964dc7d18ffStshiozak
965dc7d18ffStshiozak return (0);
966dc7d18ffStshiozak }
967dc7d18ffStshiozak
968dc7d18ffStshiozak static int
recommendation(_ISO2022EncodingInfo * __restrict ei,_ISO2022Charset * __restrict cs)969dc7d18ffStshiozak recommendation(_ISO2022EncodingInfo * __restrict ei,
970dc7d18ffStshiozak _ISO2022Charset * __restrict cs)
971dc7d18ffStshiozak {
972dc7d18ffStshiozak int i, j;
973dc7d18ffStshiozak _ISO2022Charset *recommend;
974dc7d18ffStshiozak
975dc7d18ffStshiozak _DIAGASSERT(ei != NULL);
976dc7d18ffStshiozak _DIAGASSERT(cs != NULL);
977dc7d18ffStshiozak
978dc7d18ffStshiozak /* first, try a exact match. */
979dc7d18ffStshiozak for (i = 0; i < 4; i++) {
980dc7d18ffStshiozak recommend = ei->recommend[i];
981dc7d18ffStshiozak for (j = 0; j < ei->recommendsize[i]; j++) {
982dc7d18ffStshiozak if (cs->type != recommend[j].type)
983dc7d18ffStshiozak continue;
984dc7d18ffStshiozak if (cs->final != recommend[j].final)
985dc7d18ffStshiozak continue;
986dc7d18ffStshiozak if (cs->interm != recommend[j].interm)
987dc7d18ffStshiozak continue;
988dc7d18ffStshiozak
989dc7d18ffStshiozak return i;
990dc7d18ffStshiozak }
991dc7d18ffStshiozak }
992dc7d18ffStshiozak
993dc7d18ffStshiozak /* then, try a wildcard match over final char. */
994dc7d18ffStshiozak for (i = 0; i < 4; i++) {
995dc7d18ffStshiozak recommend = ei->recommend[i];
996dc7d18ffStshiozak for (j = 0; j < ei->recommendsize[i]; j++) {
997dc7d18ffStshiozak if (cs->type != recommend[j].type)
998dc7d18ffStshiozak continue;
999dc7d18ffStshiozak if (cs->final && (cs->final != recommend[j].final))
1000dc7d18ffStshiozak continue;
1001dc7d18ffStshiozak if (cs->interm && (cs->interm != recommend[j].interm))
1002dc7d18ffStshiozak continue;
1003dc7d18ffStshiozak
1004dc7d18ffStshiozak return i;
1005dc7d18ffStshiozak }
1006dc7d18ffStshiozak }
1007dc7d18ffStshiozak
1008dc7d18ffStshiozak /* there's no recommendation. make a guess. */
1009dc7d18ffStshiozak if (ei->maxcharset == 0) {
1010dc7d18ffStshiozak return 0;
1011dc7d18ffStshiozak } else {
1012dc7d18ffStshiozak switch (cs->type) {
1013dc7d18ffStshiozak case CS94:
1014dc7d18ffStshiozak case CS94MULTI:
1015dc7d18ffStshiozak return 0;
1016dc7d18ffStshiozak case CS96:
1017dc7d18ffStshiozak case CS96MULTI:
1018dc7d18ffStshiozak return 1;
1019dc7d18ffStshiozak }
1020dc7d18ffStshiozak }
1021dc7d18ffStshiozak return 0;
1022dc7d18ffStshiozak }
1023dc7d18ffStshiozak
1024dc7d18ffStshiozak 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)102504e58308Stshiozak _ISO2022_sputwchar(_ISO2022EncodingInfo * __restrict ei, wchar_t wc,
1026dc7d18ffStshiozak char * __restrict string, size_t n,
1027dc7d18ffStshiozak char ** __restrict result,
1028fca38949Stnozaki _ISO2022State * __restrict psenc,
1029fca38949Stnozaki size_t * __restrict nresult)
1030dc7d18ffStshiozak {
1031fca38949Stnozaki int i = 0;
1032fca38949Stnozaki size_t len;
1033dc7d18ffStshiozak _ISO2022Charset cs;
1034dc7d18ffStshiozak char *p;
1035dc7d18ffStshiozak char tmp[MB_LEN_MAX];
1036dc7d18ffStshiozak int target;
1037dc7d18ffStshiozak u_char mask;
1038dc7d18ffStshiozak int bit8;
1039dc7d18ffStshiozak
1040dc7d18ffStshiozak _DIAGASSERT(ei != NULL);
1041dc7d18ffStshiozak _DIAGASSERT(string != NULL);
1042dc7d18ffStshiozak /* result may be NULL */
1043fca38949Stnozaki _DIAGASSERT(psenc != NULL);
1044fca38949Stnozaki _DIAGASSERT(nresult != NULL);
1045dc7d18ffStshiozak
1046fca38949Stnozaki if (isc0(wc & 0xff)) {
1047b29e60b3Stnozaki /* go back to INIT0 or ASCII on control chars */
1048b29e60b3Stnozaki cs = ei->initg[0].final ? ei->initg[0] : ascii;
1049fca38949Stnozaki } else if (isc1(wc & 0xff)) {
1050fca38949Stnozaki /* go back to INIT1 or ISO-8859-1 on control chars */
1051fca38949Stnozaki cs = ei->initg[1].final ? ei->initg[1] : iso88591;
105204e58308Stshiozak } else if (!(wc & ~0xff)) {
105304e58308Stshiozak if (wc & 0x80) {
1054dc7d18ffStshiozak /* special treatment for ISO-8859-1 */
1055b29e60b3Stnozaki cs = iso88591;
1056dc7d18ffStshiozak } else {
1057dc7d18ffStshiozak /* special treatment for ASCII */
1058b29e60b3Stnozaki cs = ascii;
1059dc7d18ffStshiozak }
1060dc7d18ffStshiozak } else {
106104e58308Stshiozak cs.final = (wc >> 24) & 0x7f;
106204e58308Stshiozak if ((wc >> 16) & 0x80)
106304e58308Stshiozak cs.interm = (wc >> 16) & 0x7f;
1064dc7d18ffStshiozak else
1065dc7d18ffStshiozak cs.interm = '\0';
106604e58308Stshiozak if (wc & 0x80)
106704e58308Stshiozak cs.type = (wc & 0x00007f00) ? CS96MULTI : CS96;
1068dc7d18ffStshiozak else
106904e58308Stshiozak cs.type = (wc & 0x00007f00) ? CS94MULTI : CS94;
1070dc7d18ffStshiozak }
1071dc7d18ffStshiozak target = recommendation(ei, &cs);
1072dc7d18ffStshiozak p = tmp;
1073dc7d18ffStshiozak bit8 = ei->flags & F_8BIT;
1074dc7d18ffStshiozak
1075dc7d18ffStshiozak /* designate the charset onto the target plane(G0/1/2/3). */
1076dc7d18ffStshiozak if (psenc->g[target].type == cs.type
1077dc7d18ffStshiozak && psenc->g[target].final == cs.final
1078dc7d18ffStshiozak && psenc->g[target].interm == cs.interm)
1079dc7d18ffStshiozak goto planeok;
1080dc7d18ffStshiozak
1081dc7d18ffStshiozak *p++ = '\033';
1082dc7d18ffStshiozak if (cs.type == CS94MULTI || cs.type == CS96MULTI)
1083dc7d18ffStshiozak *p++ = '$';
1084dc7d18ffStshiozak if (target == 0 && cs.type == CS94MULTI && strchr("@AB", cs.final)
1085dc7d18ffStshiozak && !cs.interm && !(ei->flags & F_NOOLD))
1086dc7d18ffStshiozak ;
1087dc7d18ffStshiozak else if (cs.type == CS94 || cs.type == CS94MULTI)
1088dc7d18ffStshiozak *p++ = "()*+"[target];
1089dc7d18ffStshiozak else
1090dc7d18ffStshiozak *p++ = ",-./"[target];
1091dc7d18ffStshiozak if (cs.interm)
1092dc7d18ffStshiozak *p++ = cs.interm;
1093dc7d18ffStshiozak *p++ = cs.final;
1094dc7d18ffStshiozak
1095dc7d18ffStshiozak psenc->g[target].type = cs.type;
1096dc7d18ffStshiozak psenc->g[target].final = cs.final;
1097dc7d18ffStshiozak psenc->g[target].interm = cs.interm;
1098dc7d18ffStshiozak
1099dc7d18ffStshiozak planeok:
1100dc7d18ffStshiozak /* invoke the plane onto GL or GR. */
1101dc7d18ffStshiozak if (psenc->gl == target)
1102dc7d18ffStshiozak goto sideok;
1103dc7d18ffStshiozak if (bit8 && psenc->gr == target)
1104dc7d18ffStshiozak goto sideok;
1105dc7d18ffStshiozak
1106dc7d18ffStshiozak if (target == 0 && (ei->flags & F_LS0)) {
1107dc7d18ffStshiozak *p++ = '\017';
1108dc7d18ffStshiozak psenc->gl = 0;
1109dc7d18ffStshiozak } else if (target == 1 && (ei->flags & F_LS1)) {
1110dc7d18ffStshiozak *p++ = '\016';
1111dc7d18ffStshiozak psenc->gl = 1;
1112dc7d18ffStshiozak } else if (target == 2 && (ei->flags & F_LS2)) {
1113dc7d18ffStshiozak *p++ = '\033';
1114dc7d18ffStshiozak *p++ = 'n';
1115dc7d18ffStshiozak psenc->gl = 2;
1116dc7d18ffStshiozak } else if (target == 3 && (ei->flags & F_LS3)) {
1117dc7d18ffStshiozak *p++ = '\033';
1118dc7d18ffStshiozak *p++ = 'o';
1119dc7d18ffStshiozak psenc->gl = 3;
1120dc7d18ffStshiozak } else if (bit8 && target == 1 && (ei->flags & F_LS1R)) {
1121dc7d18ffStshiozak *p++ = '\033';
1122dc7d18ffStshiozak *p++ = '~';
1123dc7d18ffStshiozak psenc->gr = 1;
1124dc7d18ffStshiozak } else if (bit8 && target == 2 && (ei->flags & F_LS2R)) {
1125dc7d18ffStshiozak *p++ = '\033';
1126dc7d18ffStshiozak /*{*/
1127dc7d18ffStshiozak *p++ = '}';
1128dc7d18ffStshiozak psenc->gr = 2;
1129dc7d18ffStshiozak } else if (bit8 && target == 3 && (ei->flags & F_LS3R)) {
1130dc7d18ffStshiozak *p++ = '\033';
1131dc7d18ffStshiozak *p++ = '|';
1132dc7d18ffStshiozak psenc->gr = 3;
1133dc7d18ffStshiozak } else if (target == 2 && (ei->flags & F_SS2)) {
1134dc7d18ffStshiozak *p++ = '\033';
1135dc7d18ffStshiozak *p++ = 'N';
1136dc7d18ffStshiozak psenc->singlegl = 2;
1137dc7d18ffStshiozak } else if (target == 3 && (ei->flags & F_SS3)) {
1138dc7d18ffStshiozak *p++ = '\033';
1139dc7d18ffStshiozak *p++ = 'O';
1140dc7d18ffStshiozak psenc->singlegl = 3;
1141dc7d18ffStshiozak } else if (bit8 && target == 2 && (ei->flags & F_SS2R)) {
1142dc7d18ffStshiozak *p++ = '\216';
1143dc7d18ffStshiozak *p++ = 'N';
1144dc7d18ffStshiozak psenc->singlegl = psenc->singlegr = 2;
1145dc7d18ffStshiozak } else if (bit8 && target == 3 && (ei->flags & F_SS3R)) {
1146dc7d18ffStshiozak *p++ = '\217';
1147dc7d18ffStshiozak *p++ = 'O';
1148dc7d18ffStshiozak psenc->singlegl = psenc->singlegr = 3;
1149dc7d18ffStshiozak } else
1150fca38949Stnozaki goto ilseq;
1151dc7d18ffStshiozak
1152dc7d18ffStshiozak sideok:
1153dc7d18ffStshiozak if (psenc->singlegl == target)
1154dc7d18ffStshiozak mask = 0x00;
1155dc7d18ffStshiozak else if (psenc->singlegr == target)
1156dc7d18ffStshiozak mask = 0x80;
1157dc7d18ffStshiozak else if (psenc->gl == target)
1158dc7d18ffStshiozak mask = 0x00;
1159dc7d18ffStshiozak else if ((ei->flags & F_8BIT) && psenc->gr == target)
1160dc7d18ffStshiozak mask = 0x80;
1161dc7d18ffStshiozak else
1162fca38949Stnozaki goto ilseq;
1163dc7d18ffStshiozak
1164dc7d18ffStshiozak switch (cs.type) {
1165dc7d18ffStshiozak case CS94:
1166dc7d18ffStshiozak case CS96:
1167dc7d18ffStshiozak i = 1;
1168dc7d18ffStshiozak break;
1169dc7d18ffStshiozak case CS94MULTI:
1170dc7d18ffStshiozak case CS96MULTI:
1171b29e60b3Stnozaki i = !iscntl(wc & 0xff) ?
1172b29e60b3Stnozaki (isthree(cs.final) ? 3 : 2) : 1;
1173dc7d18ffStshiozak break;
1174dc7d18ffStshiozak }
1175dc7d18ffStshiozak while (i-- > 0)
117604e58308Stshiozak *p++ = ((wc >> (i << 3)) & 0x7f) | mask;
1177dc7d18ffStshiozak
1178dc7d18ffStshiozak /* reset single shift state */
1179dc7d18ffStshiozak psenc->singlegl = psenc->singlegr = -1;
1180dc7d18ffStshiozak
1181fca38949Stnozaki len = (size_t)(p - tmp);
1182dc7d18ffStshiozak if (n < len) {
1183dc7d18ffStshiozak if (result)
1184dc7d18ffStshiozak *result = (char *)0;
1185fca38949Stnozaki *nresult = (size_t)-1;
1186fca38949Stnozaki return E2BIG;
1187fca38949Stnozaki }
1188dc7d18ffStshiozak if (result)
1189dc7d18ffStshiozak *result = string + len;
1190dc7d18ffStshiozak memcpy(string, tmp, len);
1191fca38949Stnozaki *nresult = len;
1192fca38949Stnozaki
1193fca38949Stnozaki return 0;
1194fca38949Stnozaki
1195fca38949Stnozaki ilseq:
1196fca38949Stnozaki *nresult = (size_t)-1;
1197fca38949Stnozaki return EILSEQ;
1198dc7d18ffStshiozak }
1199dc7d18ffStshiozak
1200dc7d18ffStshiozak static int
_citrus_ISO2022_put_state_reset(_ISO2022EncodingInfo * __restrict ei,char * __restrict s,size_t n,_ISO2022State * __restrict psenc,size_t * __restrict nresult)1201f3995f1aStshiozak _citrus_ISO2022_put_state_reset(_ISO2022EncodingInfo * __restrict ei,
1202f3995f1aStshiozak char * __restrict s, size_t n,
1203f3995f1aStshiozak _ISO2022State * __restrict psenc,
1204f3995f1aStshiozak size_t * __restrict nresult)
1205f3995f1aStshiozak {
1206f3995f1aStshiozak char buf[MB_LEN_MAX];
1207f3995f1aStshiozak char *result;
1208fca38949Stnozaki int ret;
1209fca38949Stnozaki size_t len;
1210f3995f1aStshiozak
1211f3995f1aStshiozak _DIAGASSERT(ei != NULL);
1212f3995f1aStshiozak _DIAGASSERT(nresult != 0);
1213f3995f1aStshiozak _DIAGASSERT(s != NULL);
1214f3995f1aStshiozak
1215f3995f1aStshiozak /* XXX state will be modified after this operation... */
1216fca38949Stnozaki ret = _ISO2022_sputwchar(ei, L'\0', buf, sizeof(buf), &result, psenc,
1217fca38949Stnozaki &len);
1218fca38949Stnozaki if (ret) {
1219fca38949Stnozaki *nresult = len;
1220fca38949Stnozaki return ret;
1221f3995f1aStshiozak }
1222fca38949Stnozaki
1223f3995f1aStshiozak if (sizeof(buf) < len || n < len-1) {
1224f3995f1aStshiozak /* XXX should recover state? */
1225fca38949Stnozaki *nresult = (size_t)-1;
1226fca38949Stnozaki return E2BIG;
1227f3995f1aStshiozak }
1228f3995f1aStshiozak
1229f3995f1aStshiozak memcpy(s, buf, len-1);
1230fca38949Stnozaki *nresult = len-1;
1231f3995f1aStshiozak return (0);
1232f3995f1aStshiozak }
1233f3995f1aStshiozak
1234f3995f1aStshiozak 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)1235dc7d18ffStshiozak _citrus_ISO2022_wcrtomb_priv(_ISO2022EncodingInfo * __restrict ei,
1236dc7d18ffStshiozak char * __restrict s, size_t n, wchar_t wc,
1237dc7d18ffStshiozak _ISO2022State * __restrict psenc,
1238dc7d18ffStshiozak size_t * __restrict nresult)
1239dc7d18ffStshiozak {
1240dc7d18ffStshiozak char buf[MB_LEN_MAX];
1241dc7d18ffStshiozak char *result;
1242fca38949Stnozaki int ret;
1243fca38949Stnozaki size_t len;
1244dc7d18ffStshiozak
1245dc7d18ffStshiozak _DIAGASSERT(ei != NULL);
1246dc7d18ffStshiozak _DIAGASSERT(s != NULL);
1247fca38949Stnozaki _DIAGASSERT(psenc != NULL);
1248fca38949Stnozaki _DIAGASSERT(nresult != 0);
1249dc7d18ffStshiozak
1250dc7d18ffStshiozak /* XXX state will be modified after this operation... */
1251fca38949Stnozaki ret = _ISO2022_sputwchar(ei, wc, buf, sizeof(buf), &result, psenc,
1252fca38949Stnozaki &len);
1253fca38949Stnozaki if (ret) {
1254fca38949Stnozaki *nresult = len;
1255fca38949Stnozaki return ret;
1256fca38949Stnozaki }
1257fca38949Stnozaki
1258dc7d18ffStshiozak if (sizeof(buf) < len || n < len) {
1259dc7d18ffStshiozak /* XXX should recover state? */
1260fca38949Stnozaki *nresult = (size_t)-1;
1261fca38949Stnozaki return E2BIG;
1262dc7d18ffStshiozak }
1263dc7d18ffStshiozak
1264dc7d18ffStshiozak memcpy(s, buf, len);
1265fca38949Stnozaki *nresult = len;
1266dc7d18ffStshiozak return (0);
126704e58308Stshiozak }
126804e58308Stshiozak
126904e58308Stshiozak static __inline int
127004e58308Stshiozak /*ARGSUSED*/
_citrus_ISO2022_stdenc_wctocs(_ISO2022EncodingInfo * __restrict ei,_csid_t * __restrict csid,_index_t * __restrict idx,wchar_t wc)127104e58308Stshiozak _citrus_ISO2022_stdenc_wctocs(_ISO2022EncodingInfo * __restrict ei,
127204e58308Stshiozak _csid_t * __restrict csid,
127304e58308Stshiozak _index_t * __restrict idx, wchar_t wc)
127404e58308Stshiozak {
127504e58308Stshiozak wchar_t m, nm;
127604e58308Stshiozak
127704e58308Stshiozak _DIAGASSERT(csid != NULL && idx != NULL);
127804e58308Stshiozak
127904e58308Stshiozak m = wc & 0x7FFF8080;
128004e58308Stshiozak nm = wc & 0x007F7F7F;
128104e58308Stshiozak if (m & 0x00800000) {
128204e58308Stshiozak nm &= 0x00007F7F;
128304e58308Stshiozak } else {
128404e58308Stshiozak m &= 0x7F008080;
128504e58308Stshiozak }
128604e58308Stshiozak if (nm & 0x007F0000) {
128704e58308Stshiozak /* ^3 mark */
128804e58308Stshiozak m |= 0x007F0000;
128904e58308Stshiozak } else if (nm & 0x00007F00) {
129004e58308Stshiozak /* ^2 mark */
129104e58308Stshiozak m |= 0x00007F00;
129204e58308Stshiozak }
129304e58308Stshiozak *csid = (_csid_t)m;
129404e58308Stshiozak *idx = (_index_t)nm;
129504e58308Stshiozak
129604e58308Stshiozak return (0);
129704e58308Stshiozak }
129804e58308Stshiozak
129904e58308Stshiozak static __inline int
130004e58308Stshiozak /*ARGSUSED*/
_citrus_ISO2022_stdenc_cstowc(_ISO2022EncodingInfo * __restrict ei,wchar_t * __restrict wc,_csid_t csid,_index_t idx)130104e58308Stshiozak _citrus_ISO2022_stdenc_cstowc(_ISO2022EncodingInfo * __restrict ei,
130204e58308Stshiozak wchar_t * __restrict wc,
130304e58308Stshiozak _csid_t csid, _index_t idx)
130404e58308Stshiozak {
130504e58308Stshiozak
130604e58308Stshiozak _DIAGASSERT(ei != NULL && wc != NULL);
130704e58308Stshiozak
130804e58308Stshiozak *wc = (wchar_t)(csid & 0x7F808080) | (wchar_t)idx;
130904e58308Stshiozak
131004e58308Stshiozak return (0);
1311dc7d18ffStshiozak }
1312dc7d18ffStshiozak
13131beef8feStshiozak static __inline int
13141beef8feStshiozak /*ARGSUSED*/
_citrus_ISO2022_stdenc_get_state_desc_generic(_ISO2022EncodingInfo * __restrict ei,_ISO2022State * __restrict psenc,int * __restrict rstate)13151beef8feStshiozak _citrus_ISO2022_stdenc_get_state_desc_generic(_ISO2022EncodingInfo * __restrict ei,
13161beef8feStshiozak _ISO2022State * __restrict psenc,
13171beef8feStshiozak int * __restrict rstate)
13181beef8feStshiozak {
13191beef8feStshiozak
13201beef8feStshiozak if (psenc->chlen == 0) {
13211beef8feStshiozak /* XXX: it should distinguish initial and stable. */
13221beef8feStshiozak *rstate = _STDENC_SDGEN_STABLE;
13231beef8feStshiozak } else {
13241beef8feStshiozak if (psenc->ch[0] == '\033')
13251beef8feStshiozak *rstate = _STDENC_SDGEN_INCOMPLETE_SHIFT;
13261beef8feStshiozak else
13271beef8feStshiozak *rstate = _STDENC_SDGEN_INCOMPLETE_CHAR;
13281beef8feStshiozak }
13291beef8feStshiozak
13301beef8feStshiozak return 0;
13311beef8feStshiozak }
13321beef8feStshiozak
1333dc7d18ffStshiozak /* ----------------------------------------------------------------------
1334dc7d18ffStshiozak * public interface for ctype
1335dc7d18ffStshiozak */
1336dc7d18ffStshiozak
1337dc7d18ffStshiozak _CITRUS_CTYPE_DECLS(ISO2022);
1338dc7d18ffStshiozak _CITRUS_CTYPE_DEF_OPS(ISO2022);
1339dc7d18ffStshiozak
1340dc7d18ffStshiozak #include "citrus_ctype_template.h"
134104e58308Stshiozak
134204e58308Stshiozak /* ----------------------------------------------------------------------
134304e58308Stshiozak * public interface for stdenc
134404e58308Stshiozak */
134504e58308Stshiozak
134604e58308Stshiozak _CITRUS_STDENC_DECLS(ISO2022);
134704e58308Stshiozak _CITRUS_STDENC_DEF_OPS(ISO2022);
134804e58308Stshiozak
134904e58308Stshiozak #include "citrus_stdenc_template.h"
1350