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