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