1 /* $NetBSD: citrus_euctw.c,v 1.12 2013/05/28 16:57:56 joerg Exp $ */ 2 3 /*- 4 * Copyright (c)2002 Citrus Project, 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /*- 30 * Copyright (c)1999 Citrus Project, 31 * All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions and the following disclaimer. 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 45 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 52 * SUCH DAMAGE. 53 * 54 * $Citrus: xpg4dl/FreeBSD/lib/libc/locale/euctw.c,v 1.13 2001/06/21 01:51:44 yamt Exp $ 55 */ 56 57 #include <sys/cdefs.h> 58 #if defined(LIBC_SCCS) && !defined(lint) 59 __RCSID("$NetBSD: citrus_euctw.c,v 1.12 2013/05/28 16:57:56 joerg Exp $"); 60 #endif /* LIBC_SCCS and not lint */ 61 62 #include <assert.h> 63 #include <errno.h> 64 #include <string.h> 65 #include <stdio.h> 66 #include <stdlib.h> 67 #include <stddef.h> 68 #include <wchar.h> 69 #include <sys/types.h> 70 #include <limits.h> 71 72 #include "citrus_namespace.h" 73 #include "citrus_types.h" 74 #include "citrus_module.h" 75 #include "citrus_ctype.h" 76 #include "citrus_stdenc.h" 77 #include "citrus_euctw.h" 78 79 80 /* ---------------------------------------------------------------------- 81 * private stuffs used by templates 82 */ 83 84 typedef struct { 85 char ch[4]; 86 int chlen; 87 } _EUCTWState; 88 89 typedef struct { 90 int dummy; 91 } _EUCTWEncodingInfo; 92 typedef struct { 93 _EUCTWEncodingInfo ei; 94 struct { 95 /* for future multi-locale facility */ 96 _EUCTWState s_mblen; 97 _EUCTWState s_mbrlen; 98 _EUCTWState s_mbrtowc; 99 _EUCTWState s_mbtowc; 100 _EUCTWState s_mbsrtowcs; 101 _EUCTWState s_mbsnrtowcs; 102 _EUCTWState s_wcrtomb; 103 _EUCTWState s_wcsrtombs; 104 _EUCTWState s_wcsnrtombs; 105 _EUCTWState s_wctomb; 106 } states; 107 } _EUCTWCTypeInfo; 108 109 #define _SS2 0x008e 110 #define _SS3 0x008f 111 112 #define _CEI_TO_EI(_cei_) (&(_cei_)->ei) 113 #define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_ 114 115 #define _FUNCNAME(m) _citrus_EUCTW_##m 116 #define _ENCODING_INFO _EUCTWEncodingInfo 117 #define _CTYPE_INFO _EUCTWCTypeInfo 118 #define _ENCODING_STATE _EUCTWState 119 #define _ENCODING_MB_CUR_MAX(_ei_) 4 120 #define _ENCODING_IS_STATE_DEPENDENT 0 121 #define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0 122 123 static __inline int 124 _citrus_EUCTW_cs(u_int c) 125 { 126 c &= 0xff; 127 128 return ((c & 0x80) ? (c == _SS2 ? 2 : 1) : 0); 129 } 130 131 static __inline int 132 _citrus_EUCTW_count(int cs) 133 { 134 switch (cs) { 135 case 0: 136 return 1; 137 case 1: 138 return 2; 139 case 2: 140 return 4; 141 case 3: 142 abort(); 143 /*NOTREACHED*/ 144 } 145 return 0; 146 } 147 148 static __inline void 149 /*ARGSUSED*/ 150 _citrus_EUCTW_init_state(_EUCTWEncodingInfo * __restrict ei, 151 _EUCTWState * __restrict s) 152 { 153 memset(s, 0, sizeof(*s)); 154 } 155 156 static __inline void 157 /*ARGSUSED*/ 158 _citrus_EUCTW_pack_state(_EUCTWEncodingInfo * __restrict ei, 159 void * __restrict pspriv, 160 const _EUCTWState * __restrict s) 161 { 162 memcpy(pspriv, (const void *)s, sizeof(*s)); 163 } 164 165 static __inline void 166 /*ARGSUSED*/ 167 _citrus_EUCTW_unpack_state(_EUCTWEncodingInfo * __restrict ei, 168 _EUCTWState * __restrict s, 169 const void * __restrict pspriv) 170 { 171 memcpy((void *)s, pspriv, sizeof(*s)); 172 } 173 174 static int 175 /*ARGSUSED*/ 176 _citrus_EUCTW_encoding_module_init(_EUCTWEncodingInfo * __restrict ei, 177 const void * __restrict var, size_t lenvar) 178 { 179 180 _DIAGASSERT(ei != NULL); 181 182 memset((void *)ei, 0, sizeof(*ei)); 183 184 return 0; 185 } 186 187 static void 188 /*ARGSUSED*/ 189 _citrus_EUCTW_encoding_module_uninit(_EUCTWEncodingInfo *ei) 190 { 191 } 192 193 static int 194 _citrus_EUCTW_mbrtowc_priv(_EUCTWEncodingInfo * __restrict ei, 195 wchar_t * __restrict pwc, 196 const char ** __restrict s, 197 size_t n, _EUCTWState * __restrict psenc, 198 size_t * __restrict nresult) 199 { 200 wchar_t wchar; 201 int c, cs; 202 int chlenbak; 203 const char *s0; 204 205 _DIAGASSERT(nresult != 0); 206 _DIAGASSERT(ei != NULL); 207 _DIAGASSERT(psenc != NULL); 208 _DIAGASSERT(s != NULL); 209 210 s0 = *s; 211 212 if (s0 == NULL) { 213 _citrus_EUCTW_init_state(ei, psenc); 214 *nresult = 0; /* state independent */ 215 return (0); 216 } 217 218 chlenbak = psenc->chlen; 219 220 /* make sure we have the first byte in the buffer */ 221 switch (psenc->chlen) { 222 case 0: 223 if (n < 1) 224 goto restart; 225 psenc->ch[0] = *s0++; 226 psenc->chlen = 1; 227 n--; 228 break; 229 case 1: 230 case 2: 231 break; 232 default: 233 /* illgeal state */ 234 goto ilseq; 235 } 236 237 c = _citrus_EUCTW_count(cs = _citrus_EUCTW_cs(psenc->ch[0] & 0xff)); 238 if (c == 0) 239 goto ilseq; 240 while (psenc->chlen < c) { 241 if (n < 1) 242 goto ilseq; 243 psenc->ch[psenc->chlen] = *s0++; 244 psenc->chlen++; 245 n--; 246 } 247 248 wchar = 0; 249 switch (cs) { 250 case 0: 251 if (psenc->ch[0] & 0x80) 252 goto ilseq; 253 wchar = psenc->ch[0] & 0xff; 254 break; 255 case 1: 256 if (!(psenc->ch[0] & 0x80) || !(psenc->ch[1] & 0x80)) 257 goto ilseq; 258 wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff); 259 wchar |= 'G' << 24; 260 break; 261 case 2: 262 if ((u_char)psenc->ch[1] < 0xa1 || 0xa7 < (u_char)psenc->ch[1]) 263 goto ilseq; 264 if (!(psenc->ch[2] & 0x80) || !(psenc->ch[3] & 0x80)) 265 goto ilseq; 266 wchar = ((psenc->ch[2] & 0xff) << 8) | (psenc->ch[3] & 0xff); 267 wchar |= ('G' + psenc->ch[1] - 0xa1) << 24; 268 break; 269 default: 270 goto ilseq; 271 } 272 273 *s = s0; 274 psenc->chlen = 0; 275 276 if (pwc) 277 *pwc = wchar; 278 279 if (!wchar) 280 *nresult = 0; 281 else 282 *nresult = c - chlenbak; 283 284 return (0); 285 286 ilseq: 287 psenc->chlen = 0; 288 *nresult = (size_t)-1; 289 return (EILSEQ); 290 291 restart: 292 *s = s0; 293 *nresult = (size_t)-1; 294 return (0); 295 } 296 297 static int 298 _citrus_EUCTW_wcrtomb_priv(_EUCTWEncodingInfo * __restrict ei, 299 char * __restrict s, size_t n, wchar_t wc, 300 _EUCTWState * __restrict psenc, 301 size_t * __restrict nresult) 302 { 303 wchar_t cs = wc & 0x7f000080; 304 wchar_t v; 305 int i, len, clen, ret; 306 307 _DIAGASSERT(ei != NULL); 308 _DIAGASSERT(nresult != 0); 309 _DIAGASSERT(s != NULL); 310 311 clen = 1; 312 if (wc & 0x00007f00) 313 clen = 2; 314 if ((wc & 0x007f0000) && !(wc & 0x00800000)) 315 clen = 3; 316 317 if (clen == 1 && cs == 0x00000000) { 318 /* ASCII */ 319 len = 1; 320 if (n < len) { 321 ret = E2BIG; 322 goto err; 323 } 324 v = wc & 0x0000007f; 325 } else if (clen == 2 && cs == ('G' << 24)) { 326 /* CNS-11643-1 */ 327 len = 2; 328 if (n < len) { 329 ret = E2BIG; 330 goto err; 331 } 332 v = wc & 0x00007f7f; 333 v |= 0x00008080; 334 } else if (clen == 2 && 'H' <= (cs >> 24) && (cs >> 24) <= 'M') { 335 /* CNS-11643-[2-7] */ 336 len = 4; 337 if (n < len) { 338 ret = E2BIG; 339 goto err; 340 } 341 *s++ = _SS2; 342 *s++ = (cs >> 24) - 'H' + 0xa2; 343 v = wc & 0x00007f7f; 344 v |= 0x00008080; 345 } else { 346 ret = EILSEQ; 347 goto err; 348 } 349 350 i = clen; 351 while (i-- > 0) 352 *s++ = (v >> (i << 3)) & 0xff; 353 354 *nresult = len; 355 return 0; 356 357 err: 358 *nresult = (size_t)-1; 359 return ret; 360 } 361 362 static __inline int 363 /*ARGSUSED*/ 364 _citrus_EUCTW_stdenc_wctocs(_EUCTWEncodingInfo * __restrict ei, 365 _csid_t * __restrict csid, 366 _index_t * __restrict idx, wchar_t wc) 367 { 368 369 _DIAGASSERT(ei != NULL && csid != NULL && idx != NULL); 370 371 *csid = (_csid_t)(wc >> 24) & 0xFF; 372 *idx = (_index_t)(wc & 0x7F7F); 373 374 return (0); 375 } 376 377 static __inline int 378 /*ARGSUSED*/ 379 _citrus_EUCTW_stdenc_cstowc(_EUCTWEncodingInfo * __restrict ei, 380 wchar_t * __restrict wc, 381 _csid_t csid, _index_t idx) 382 { 383 384 _DIAGASSERT(ei != NULL && wc != NULL); 385 386 if (csid==0) { 387 if ((idx & ~0x7F) != 0) 388 return (EINVAL); 389 *wc = (wchar_t)idx; 390 } else { 391 if (csid < 'G' || csid > 'M' || (idx & ~0x7F7F) != 0) 392 return (EINVAL); 393 *wc = (wchar_t)idx | ((wchar_t)csid<<24); 394 } 395 396 return (0); 397 } 398 399 static __inline int 400 /*ARGSUSED*/ 401 _citrus_EUCTW_stdenc_get_state_desc_generic(_EUCTWEncodingInfo * __restrict ei, 402 _EUCTWState * __restrict psenc, 403 int * __restrict rstate) 404 { 405 406 if (psenc->chlen == 0) 407 *rstate = _STDENC_SDGEN_INITIAL; 408 else 409 *rstate = _STDENC_SDGEN_INCOMPLETE_CHAR; 410 411 return 0; 412 } 413 414 /* ---------------------------------------------------------------------- 415 * public interface for ctype 416 */ 417 418 _CITRUS_CTYPE_DECLS(EUCTW); 419 _CITRUS_CTYPE_DEF_OPS(EUCTW); 420 421 #include "citrus_ctype_template.h" 422 423 /* ---------------------------------------------------------------------- 424 * public interface for stdenc 425 */ 426 427 _CITRUS_STDENC_DECLS(EUCTW); 428 _CITRUS_STDENC_DEF_OPS(EUCTW); 429 430 #include "citrus_stdenc_template.h" 431