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 (2^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 static __inline void 140 /*ARGSUSED*/ 141 _citrus_EUCTW_pack_state(_EUCTWEncodingInfo * __restrict ei __unused, 142 void * __restrict pspriv, const _EUCTWState * __restrict s) 143 { 144 145 memcpy(pspriv, (const void *)s, sizeof(*s)); 146 } 147 148 static __inline void 149 /*ARGSUSED*/ 150 _citrus_EUCTW_unpack_state(_EUCTWEncodingInfo * __restrict ei __unused, 151 _EUCTWState * __restrict s, const void * __restrict pspriv) 152 { 153 154 memcpy((void *)s, pspriv, sizeof(*s)); 155 } 156 157 static int 158 /*ARGSUSED*/ 159 _citrus_EUCTW_encoding_module_init(_EUCTWEncodingInfo * __restrict ei, 160 const void * __restrict var __unused, size_t lenvar __unused) 161 { 162 163 memset((void *)ei, 0, sizeof(*ei)); 164 165 return (0); 166 } 167 168 static void 169 /*ARGSUSED*/ 170 _citrus_EUCTW_encoding_module_uninit(_EUCTWEncodingInfo *ei __unused) 171 { 172 173 } 174 175 static int 176 _citrus_EUCTW_mbrtowc_priv(_EUCTWEncodingInfo * __restrict ei, 177 wchar_t * __restrict pwc, const char ** __restrict s, 178 size_t n, _EUCTWState * __restrict psenc, size_t * __restrict nresult) 179 { 180 const char *s0; 181 wchar_t wchar; 182 int c, chlenbak, cs; 183 184 s0 = *s; 185 186 if (s0 == NULL) { 187 _citrus_EUCTW_init_state(ei, psenc); 188 *nresult = 0; /* state independent */ 189 return (0); 190 } 191 192 chlenbak = psenc->chlen; 193 194 /* make sure we have the first byte in the buffer */ 195 switch (psenc->chlen) { 196 case 0: 197 if (n < 1) 198 goto restart; 199 psenc->ch[0] = *s0++; 200 psenc->chlen = 1; 201 n--; 202 break; 203 case 1: 204 case 2: 205 break; 206 default: 207 /* illgeal state */ 208 goto ilseq; 209 } 210 211 c = _citrus_EUCTW_count(cs = _citrus_EUCTW_cs(psenc->ch[0] & 0xff)); 212 if (c == 0) 213 goto ilseq; 214 while (psenc->chlen < c) { 215 if (n < 1) 216 goto ilseq; 217 psenc->ch[psenc->chlen] = *s0++; 218 psenc->chlen++; 219 n--; 220 } 221 222 wchar = 0; 223 switch (cs) { 224 case 0: 225 if (psenc->ch[0] & 0x80) 226 goto ilseq; 227 wchar = psenc->ch[0] & 0xff; 228 break; 229 case 1: 230 if (!(psenc->ch[0] & 0x80) || !(psenc->ch[1] & 0x80)) 231 goto ilseq; 232 wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff); 233 wchar |= 'G' << 24; 234 break; 235 case 2: 236 if ((unsigned char)psenc->ch[1] < 0xa1 || 237 0xa7 < (unsigned char)psenc->ch[1]) 238 goto ilseq; 239 if (!(psenc->ch[2] & 0x80) || !(psenc->ch[3] & 0x80)) 240 goto ilseq; 241 wchar = ((psenc->ch[2] & 0xff) << 8) | (psenc->ch[3] & 0xff); 242 wchar |= ('G' + psenc->ch[1] - 0xa1) << 24; 243 break; 244 default: 245 goto ilseq; 246 } 247 248 *s = s0; 249 psenc->chlen = 0; 250 251 if (pwc) 252 *pwc = wchar; 253 *nresult = wchar ? c - chlenbak : 0; 254 return (0); 255 256 ilseq: 257 psenc->chlen = 0; 258 *nresult = (size_t)-1; 259 return (EILSEQ); 260 261 restart: 262 *s = s0; 263 *nresult = (size_t)-1; 264 return (0); 265 } 266 267 static int 268 _citrus_EUCTW_wcrtomb_priv(_EUCTWEncodingInfo * __restrict ei __unused, 269 char * __restrict s, size_t n, wchar_t wc, 270 _EUCTWState * __restrict psenc __unused, size_t * __restrict nresult) 271 { 272 wchar_t cs, v; 273 int clen, i, ret; 274 size_t len; 275 276 cs = wc & 0x7f000080; 277 clen = 1; 278 if (wc & 0x00007f00) 279 clen = 2; 280 if ((wc & 0x007f0000) && !(wc & 0x00800000)) 281 clen = 3; 282 283 if (clen == 1 && cs == 0x00000000) { 284 /* ASCII */ 285 len = 1; 286 if (n < len) { 287 ret = E2BIG; 288 goto err; 289 } 290 v = wc & 0x0000007f; 291 } else if (clen == 2 && cs == ('G' << 24)) { 292 /* CNS-11643-1 */ 293 len = 2; 294 if (n < len) { 295 ret = E2BIG; 296 goto err; 297 } 298 v = wc & 0x00007f7f; 299 v |= 0x00008080; 300 } else if (clen == 2 && 'H' <= (cs >> 24) && (cs >> 24) <= 'M') { 301 /* CNS-11643-[2-7] */ 302 len = 4; 303 if (n < len) { 304 ret = E2BIG; 305 goto err; 306 } 307 *s++ = _SS2; 308 *s++ = (cs >> 24) - 'H' + 0xa2; 309 v = wc & 0x00007f7f; 310 v |= 0x00008080; 311 } else { 312 ret = EILSEQ; 313 goto err; 314 } 315 316 i = clen; 317 while (i-- > 0) 318 *s++ = (v >> (i << 3)) & 0xff; 319 320 *nresult = len; 321 return (0); 322 323 err: 324 *nresult = (size_t)-1; 325 return (ret); 326 } 327 328 static __inline int 329 /*ARGSUSED*/ 330 _citrus_EUCTW_stdenc_wctocs(_EUCTWEncodingInfo * __restrict ei __unused, 331 _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc) 332 { 333 334 *csid = (_csid_t)(wc >> 24) & 0xFF; 335 *idx = (_index_t)(wc & 0x7F7F); 336 337 return (0); 338 } 339 340 static __inline int 341 /*ARGSUSED*/ 342 _citrus_EUCTW_stdenc_cstowc(_EUCTWEncodingInfo * __restrict ei __unused, 343 wchar_t * __restrict wc, _csid_t csid, _index_t idx) 344 { 345 346 if (csid == 0) { 347 if ((idx & ~0x7F) != 0) 348 return (EINVAL); 349 *wc = (wchar_t)idx; 350 } else { 351 if (csid < 'G' || csid > 'M' || (idx & ~0x7F7F) != 0) 352 return (EINVAL); 353 *wc = (wchar_t)idx | ((wchar_t)csid << 24); 354 } 355 356 return (0); 357 } 358 359 static __inline int 360 /*ARGSUSED*/ 361 _citrus_EUCTW_stdenc_get_state_desc_generic(_EUCTWEncodingInfo * __restrict ei __unused, 362 _EUCTWState * __restrict psenc, int * __restrict rstate) 363 { 364 365 *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL : 366 _STDENC_SDGEN_INCOMPLETE_CHAR; 367 return (0); 368 } 369 370 /* ---------------------------------------------------------------------- 371 * public interface for stdenc 372 */ 373 374 _CITRUS_STDENC_DECLS(EUCTW); 375 _CITRUS_STDENC_DEF_OPS(EUCTW); 376 377 #include "citrus_stdenc_template.h" 378