1 1.15 spz /* $NetBSD: citrus_big5.c,v 1.15 2014/06/24 22:24:18 spz Exp $ */ 2 1.1 tshiozak 3 1.1 tshiozak /*- 4 1.10 tnozaki * Copyright (c)2002, 2006 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 29 1.1 tshiozak /*- 30 1.1 tshiozak * Copyright (c) 1993 31 1.1 tshiozak * The Regents of the University of California. All rights reserved. 32 1.1 tshiozak * 33 1.1 tshiozak * This code is derived from software contributed to Berkeley by 34 1.1 tshiozak * Paul Borman at Krystal Technologies. 35 1.1 tshiozak * 36 1.1 tshiozak * Redistribution and use in source and binary forms, with or without 37 1.1 tshiozak * modification, are permitted provided that the following conditions 38 1.1 tshiozak * are met: 39 1.1 tshiozak * 1. Redistributions of source code must retain the above copyright 40 1.1 tshiozak * notice, this list of conditions and the following disclaimer. 41 1.1 tshiozak * 2. Redistributions in binary form must reproduce the above copyright 42 1.1 tshiozak * notice, this list of conditions and the following disclaimer in the 43 1.1 tshiozak * documentation and/or other materials provided with the distribution. 44 1.8 agc * 3. Neither the name of the University nor the names of its contributors 45 1.1 tshiozak * may be used to endorse or promote products derived from this software 46 1.1 tshiozak * without specific prior written permission. 47 1.1 tshiozak * 48 1.1 tshiozak * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 1.1 tshiozak * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 1.1 tshiozak * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 1.1 tshiozak * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 1.1 tshiozak * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 1.1 tshiozak * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 1.1 tshiozak * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 1.1 tshiozak * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 1.1 tshiozak * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 1.1 tshiozak * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 1.1 tshiozak * SUCH DAMAGE. 59 1.1 tshiozak */ 60 1.1 tshiozak 61 1.1 tshiozak #include <sys/cdefs.h> 62 1.1 tshiozak #if defined(LIBC_SCCS) && !defined(lint) 63 1.15 spz __RCSID("$NetBSD: citrus_big5.c,v 1.15 2014/06/24 22:24:18 spz Exp $"); 64 1.1 tshiozak #endif /* LIBC_SCCS and not lint */ 65 1.1 tshiozak 66 1.10 tnozaki #include <sys/queue.h> 67 1.10 tnozaki #include <sys/types.h> 68 1.1 tshiozak #include <assert.h> 69 1.1 tshiozak #include <errno.h> 70 1.1 tshiozak #include <string.h> 71 1.10 tnozaki #include <stdint.h> 72 1.1 tshiozak #include <stdio.h> 73 1.1 tshiozak #include <stdlib.h> 74 1.1 tshiozak #include <stddef.h> 75 1.1 tshiozak #include <wchar.h> 76 1.1 tshiozak #include <limits.h> 77 1.6 tshiozak 78 1.6 tshiozak #include "citrus_namespace.h" 79 1.6 tshiozak #include "citrus_types.h" 80 1.10 tnozaki #include "citrus_bcs.h" 81 1.1 tshiozak #include "citrus_module.h" 82 1.1 tshiozak #include "citrus_ctype.h" 83 1.6 tshiozak #include "citrus_stdenc.h" 84 1.1 tshiozak #include "citrus_big5.h" 85 1.1 tshiozak 86 1.11 tnozaki #include "citrus_prop.h" 87 1.11 tnozaki 88 1.1 tshiozak /* ---------------------------------------------------------------------- 89 1.1 tshiozak * private stuffs used by templates 90 1.1 tshiozak */ 91 1.1 tshiozak 92 1.1 tshiozak typedef struct { 93 1.1 tshiozak char ch[2]; 94 1.1 tshiozak int chlen; 95 1.1 tshiozak } _BIG5State; 96 1.1 tshiozak 97 1.10 tnozaki typedef struct _BIG5Exclude { 98 1.10 tnozaki TAILQ_ENTRY(_BIG5Exclude) entry; 99 1.10 tnozaki wint_t start, end; 100 1.10 tnozaki } _BIG5Exclude; 101 1.10 tnozaki 102 1.10 tnozaki typedef TAILQ_HEAD(_BIG5ExcludeList, _BIG5Exclude) _BIG5ExcludeList; 103 1.10 tnozaki 104 1.1 tshiozak typedef struct { 105 1.10 tnozaki int cell[0x100]; 106 1.10 tnozaki _BIG5ExcludeList excludes; 107 1.1 tshiozak } _BIG5EncodingInfo; 108 1.1 tshiozak 109 1.1 tshiozak typedef struct { 110 1.1 tshiozak _BIG5EncodingInfo ei; 111 1.1 tshiozak struct { 112 1.1 tshiozak /* for future multi-locale facility */ 113 1.1 tshiozak _BIG5State s_mblen; 114 1.1 tshiozak _BIG5State s_mbrlen; 115 1.1 tshiozak _BIG5State s_mbrtowc; 116 1.1 tshiozak _BIG5State s_mbtowc; 117 1.1 tshiozak _BIG5State s_mbsrtowcs; 118 1.14 joerg _BIG5State s_mbsnrtowcs; 119 1.1 tshiozak _BIG5State s_wcrtomb; 120 1.1 tshiozak _BIG5State s_wcsrtombs; 121 1.14 joerg _BIG5State s_wcsnrtombs; 122 1.1 tshiozak _BIG5State s_wctomb; 123 1.1 tshiozak } states; 124 1.1 tshiozak } _BIG5CTypeInfo; 125 1.1 tshiozak 126 1.1 tshiozak #define _CEI_TO_EI(_cei_) (&(_cei_)->ei) 127 1.1 tshiozak #define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_ 128 1.1 tshiozak 129 1.1 tshiozak #define _FUNCNAME(m) _citrus_BIG5_##m 130 1.1 tshiozak #define _ENCODING_INFO _BIG5EncodingInfo 131 1.1 tshiozak #define _CTYPE_INFO _BIG5CTypeInfo 132 1.1 tshiozak #define _ENCODING_STATE _BIG5State 133 1.2 yamt #define _ENCODING_MB_CUR_MAX(_ei_) 2 134 1.1 tshiozak #define _ENCODING_IS_STATE_DEPENDENT 0 135 1.4 yamt #define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0 136 1.1 tshiozak 137 1.1 tshiozak 138 1.1 tshiozak static __inline void 139 1.1 tshiozak /*ARGSUSED*/ 140 1.1 tshiozak _citrus_BIG5_init_state(_BIG5EncodingInfo * __restrict ei, 141 1.1 tshiozak _BIG5State * __restrict s) 142 1.1 tshiozak { 143 1.1 tshiozak memset(s, 0, sizeof(*s)); 144 1.1 tshiozak } 145 1.1 tshiozak 146 1.1 tshiozak static __inline void 147 1.1 tshiozak /*ARGSUSED*/ 148 1.1 tshiozak _citrus_BIG5_pack_state(_BIG5EncodingInfo * __restrict ei, 149 1.1 tshiozak void * __restrict pspriv, 150 1.1 tshiozak const _BIG5State * __restrict s) 151 1.1 tshiozak { 152 1.1 tshiozak memcpy(pspriv, (const void *)s, sizeof(*s)); 153 1.1 tshiozak } 154 1.1 tshiozak 155 1.1 tshiozak static __inline void 156 1.1 tshiozak /*ARGSUSED*/ 157 1.1 tshiozak _citrus_BIG5_unpack_state(_BIG5EncodingInfo * __restrict ei, 158 1.1 tshiozak _BIG5State * __restrict s, 159 1.1 tshiozak const void * __restrict pspriv) 160 1.1 tshiozak { 161 1.1 tshiozak memcpy((void *)s, pspriv, sizeof(*s)); 162 1.1 tshiozak } 163 1.1 tshiozak 164 1.1 tshiozak static __inline int 165 1.10 tnozaki _citrus_BIG5_check(_BIG5EncodingInfo *ei, u_int c) 166 1.1 tshiozak { 167 1.10 tnozaki _DIAGASSERT(ei != NULL); 168 1.10 tnozaki 169 1.10 tnozaki return (ei->cell[c & 0xFF] & 0x1) ? 2 : 1; 170 1.1 tshiozak } 171 1.1 tshiozak 172 1.1 tshiozak static __inline int 173 1.10 tnozaki _citrus_BIG5_check2(_BIG5EncodingInfo *ei, u_int c) 174 1.10 tnozaki { 175 1.10 tnozaki _DIAGASSERT(ei != NULL); 176 1.10 tnozaki 177 1.10 tnozaki return (ei->cell[c & 0xFF] & 0x2) ? 1 : 0; 178 1.10 tnozaki } 179 1.10 tnozaki 180 1.10 tnozaki static __inline int 181 1.10 tnozaki _citrus_BIG5_check_excludes(_BIG5EncodingInfo *ei, wint_t c) 182 1.10 tnozaki { 183 1.10 tnozaki _BIG5Exclude *exclude; 184 1.10 tnozaki 185 1.10 tnozaki _DIAGASSERT(ei != NULL); 186 1.10 tnozaki 187 1.10 tnozaki TAILQ_FOREACH(exclude, &ei->excludes, entry) { 188 1.10 tnozaki if (c >= exclude->start && c <= exclude->end) 189 1.10 tnozaki return EILSEQ; 190 1.10 tnozaki } 191 1.10 tnozaki return 0; 192 1.10 tnozaki } 193 1.10 tnozaki 194 1.10 tnozaki static int 195 1.15 spz _citrus_BIG5_fill_rowcol(void * __restrict ctx, const char * __restrict s, 196 1.11 tnozaki uint64_t start, uint64_t end) 197 1.10 tnozaki { 198 1.10 tnozaki _BIG5EncodingInfo *ei; 199 1.10 tnozaki int i; 200 1.11 tnozaki uint64_t n; 201 1.10 tnozaki 202 1.15 spz _DIAGASSERT(ctx != NULL); 203 1.10 tnozaki 204 1.11 tnozaki if (start > 0xFF || end > 0xFF) 205 1.11 tnozaki return EINVAL; 206 1.15 spz ei = (_BIG5EncodingInfo *)ctx; 207 1.10 tnozaki i = strcmp("row", s) ? 1 : 0; 208 1.10 tnozaki i = 1 << i; 209 1.10 tnozaki for (n = start; n <= end; ++n) 210 1.10 tnozaki ei->cell[n & 0xFF] |= i; 211 1.10 tnozaki return 0; 212 1.1 tshiozak } 213 1.1 tshiozak 214 1.1 tshiozak static int 215 1.1 tshiozak /*ARGSUSED*/ 216 1.15 spz _citrus_BIG5_fill_excludes(void * __restrict ctx, const char * __restrict s, 217 1.11 tnozaki uint64_t start, uint64_t end) 218 1.1 tshiozak { 219 1.10 tnozaki _BIG5EncodingInfo *ei; 220 1.10 tnozaki _BIG5Exclude *exclude; 221 1.10 tnozaki 222 1.15 spz _DIAGASSERT(ctx != NULL); 223 1.1 tshiozak 224 1.11 tnozaki if (start > 0xFFFF || end > 0xFFFF) 225 1.11 tnozaki return EINVAL; 226 1.15 spz ei = (_BIG5EncodingInfo *)ctx; 227 1.10 tnozaki exclude = TAILQ_LAST(&ei->excludes, _BIG5ExcludeList); 228 1.10 tnozaki if (exclude != NULL && (wint_t)start <= exclude->end) 229 1.10 tnozaki return EINVAL; 230 1.10 tnozaki exclude = (void *)malloc(sizeof(*exclude)); 231 1.10 tnozaki if (exclude == NULL) 232 1.10 tnozaki return ENOMEM; 233 1.10 tnozaki exclude->start = (wint_t)start; 234 1.10 tnozaki exclude->end = (wint_t)end; 235 1.10 tnozaki TAILQ_INSERT_TAIL(&ei->excludes, exclude, entry); 236 1.1 tshiozak 237 1.10 tnozaki return 0; 238 1.1 tshiozak } 239 1.1 tshiozak 240 1.11 tnozaki static const _citrus_prop_hint_t root_hints[] = { 241 1.11 tnozaki _CITRUS_PROP_HINT_NUM("row", &_citrus_BIG5_fill_rowcol), 242 1.11 tnozaki _CITRUS_PROP_HINT_NUM("col", &_citrus_BIG5_fill_rowcol), 243 1.11 tnozaki _CITRUS_PROP_HINT_NUM("excludes", &_citrus_BIG5_fill_excludes), 244 1.11 tnozaki _CITRUS_PROP_HINT_END 245 1.10 tnozaki }; 246 1.10 tnozaki 247 1.1 tshiozak static void 248 1.1 tshiozak /*ARGSUSED*/ 249 1.6 tshiozak _citrus_BIG5_encoding_module_uninit(_BIG5EncodingInfo *ei) 250 1.1 tshiozak { 251 1.10 tnozaki _BIG5Exclude *exclude; 252 1.10 tnozaki 253 1.10 tnozaki _DIAGASSERT(ei != NULL); 254 1.10 tnozaki 255 1.10 tnozaki while ((exclude = TAILQ_FIRST(&ei->excludes)) != NULL) { 256 1.10 tnozaki TAILQ_REMOVE(&ei->excludes, exclude, entry); 257 1.10 tnozaki free(exclude); 258 1.10 tnozaki } 259 1.10 tnozaki } 260 1.10 tnozaki 261 1.10 tnozaki static int 262 1.10 tnozaki /*ARGSUSED*/ 263 1.10 tnozaki _citrus_BIG5_encoding_module_init(_BIG5EncodingInfo * __restrict ei, 264 1.10 tnozaki const void * __restrict var, size_t lenvar) 265 1.10 tnozaki { 266 1.10 tnozaki int err; 267 1.10 tnozaki const char *s; 268 1.10 tnozaki 269 1.10 tnozaki _DIAGASSERT(ei != NULL); 270 1.10 tnozaki 271 1.10 tnozaki memset((void *)ei, 0, sizeof(*ei)); 272 1.10 tnozaki TAILQ_INIT(&ei->excludes); 273 1.10 tnozaki 274 1.10 tnozaki if (lenvar > 0 && var != NULL) { 275 1.10 tnozaki s = _bcs_skip_ws_len((const char *)var, &lenvar); 276 1.10 tnozaki if (lenvar > 0 && *s != '\0') { 277 1.11 tnozaki err = _citrus_prop_parse_variable( 278 1.11 tnozaki root_hints, (void *)ei, s, lenvar); 279 1.10 tnozaki if (err == 0) 280 1.10 tnozaki return 0; 281 1.10 tnozaki 282 1.10 tnozaki _citrus_BIG5_encoding_module_uninit(ei); 283 1.10 tnozaki memset((void *)ei, 0, sizeof(*ei)); 284 1.10 tnozaki TAILQ_INIT(&ei->excludes); 285 1.10 tnozaki } 286 1.10 tnozaki } 287 1.10 tnozaki 288 1.10 tnozaki /* fallback Big5-1984, for backward compatibility. */ 289 1.15 spz _citrus_BIG5_fill_rowcol(ei, "row", 0xA1, 0xFE); 290 1.15 spz _citrus_BIG5_fill_rowcol(ei, "col", 0x40, 0x7E); 291 1.15 spz _citrus_BIG5_fill_rowcol(ei, "col", 0xA1, 0xFE); 292 1.10 tnozaki 293 1.10 tnozaki return 0; 294 1.1 tshiozak } 295 1.1 tshiozak 296 1.1 tshiozak static int 297 1.1 tshiozak /*ARGSUSED*/ 298 1.1 tshiozak _citrus_BIG5_mbrtowc_priv(_BIG5EncodingInfo * __restrict ei, 299 1.1 tshiozak wchar_t * __restrict pwc, 300 1.1 tshiozak const char ** __restrict s, size_t n, 301 1.1 tshiozak _BIG5State * __restrict psenc, 302 1.1 tshiozak size_t * __restrict nresult) 303 1.1 tshiozak { 304 1.1 tshiozak wchar_t wchar; 305 1.1 tshiozak int c; 306 1.1 tshiozak int chlenbak; 307 1.1 tshiozak const char *s0; 308 1.1 tshiozak 309 1.1 tshiozak _DIAGASSERT(nresult != 0); 310 1.1 tshiozak _DIAGASSERT(ei != NULL); 311 1.1 tshiozak _DIAGASSERT(psenc != NULL); 312 1.1 tshiozak _DIAGASSERT(s != NULL && *s != NULL); 313 1.1 tshiozak 314 1.1 tshiozak s0 = *s; 315 1.1 tshiozak 316 1.1 tshiozak if (s0 == NULL) { 317 1.1 tshiozak _citrus_BIG5_init_state(ei, psenc); 318 1.1 tshiozak *nresult = 0; 319 1.1 tshiozak return (0); 320 1.1 tshiozak } 321 1.1 tshiozak 322 1.1 tshiozak chlenbak = psenc->chlen; 323 1.1 tshiozak 324 1.1 tshiozak /* make sure we have the first byte in the buffer */ 325 1.1 tshiozak switch (psenc->chlen) { 326 1.1 tshiozak case 0: 327 1.1 tshiozak if (n < 1) 328 1.1 tshiozak goto restart; 329 1.1 tshiozak psenc->ch[0] = *s0++; 330 1.1 tshiozak psenc->chlen = 1; 331 1.1 tshiozak n--; 332 1.1 tshiozak break; 333 1.1 tshiozak case 1: 334 1.1 tshiozak break; 335 1.1 tshiozak default: 336 1.1 tshiozak /* illegal state */ 337 1.1 tshiozak goto ilseq; 338 1.1 tshiozak } 339 1.1 tshiozak 340 1.10 tnozaki c = _citrus_BIG5_check(ei, psenc->ch[0] & 0xff); 341 1.1 tshiozak if (c == 0) 342 1.1 tshiozak goto ilseq; 343 1.1 tshiozak while (psenc->chlen < c) { 344 1.1 tshiozak if (n < 1) { 345 1.1 tshiozak goto restart; 346 1.1 tshiozak } 347 1.1 tshiozak psenc->ch[psenc->chlen] = *s0++; 348 1.1 tshiozak psenc->chlen++; 349 1.1 tshiozak n--; 350 1.1 tshiozak } 351 1.1 tshiozak 352 1.1 tshiozak switch (c) { 353 1.1 tshiozak case 1: 354 1.1 tshiozak wchar = psenc->ch[0] & 0xff; 355 1.1 tshiozak break; 356 1.1 tshiozak case 2: 357 1.10 tnozaki if (!_citrus_BIG5_check2(ei, psenc->ch[1] & 0xff)) 358 1.1 tshiozak goto ilseq; 359 1.1 tshiozak wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff); 360 1.1 tshiozak break; 361 1.1 tshiozak default: 362 1.1 tshiozak /* illegal state */ 363 1.1 tshiozak goto ilseq; 364 1.1 tshiozak } 365 1.1 tshiozak 366 1.10 tnozaki if (_citrus_BIG5_check_excludes(ei, (wint_t)wchar) != 0) 367 1.10 tnozaki goto ilseq; 368 1.10 tnozaki 369 1.1 tshiozak *s = s0; 370 1.1 tshiozak psenc->chlen = 0; 371 1.1 tshiozak if (pwc) 372 1.1 tshiozak *pwc = wchar; 373 1.1 tshiozak if (!wchar) 374 1.1 tshiozak *nresult = 0; 375 1.1 tshiozak else 376 1.1 tshiozak *nresult = c - chlenbak; 377 1.1 tshiozak 378 1.1 tshiozak return (0); 379 1.1 tshiozak 380 1.1 tshiozak ilseq: 381 1.1 tshiozak psenc->chlen = 0; 382 1.1 tshiozak *nresult = (size_t)-1; 383 1.1 tshiozak return (EILSEQ); 384 1.1 tshiozak 385 1.1 tshiozak restart: 386 1.1 tshiozak *s = s0; 387 1.1 tshiozak *nresult = (size_t)-2; 388 1.1 tshiozak return (0); 389 1.1 tshiozak } 390 1.1 tshiozak 391 1.1 tshiozak static int 392 1.1 tshiozak /*ARGSUSED*/ 393 1.1 tshiozak _citrus_BIG5_wcrtomb_priv(_BIG5EncodingInfo * __restrict ei, 394 1.1 tshiozak char * __restrict s, 395 1.1 tshiozak size_t n, wchar_t wc, _BIG5State * __restrict psenc, 396 1.1 tshiozak size_t * __restrict nresult) 397 1.1 tshiozak { 398 1.13 joerg size_t l, ret; 399 1.1 tshiozak 400 1.1 tshiozak _DIAGASSERT(ei != NULL); 401 1.1 tshiozak _DIAGASSERT(nresult != 0); 402 1.1 tshiozak _DIAGASSERT(s != NULL); 403 1.6 tshiozak 404 1.1 tshiozak /* check invalid sequence */ 405 1.10 tnozaki if (wc & ~0xffff || 406 1.10 tnozaki _citrus_BIG5_check_excludes(ei, (wint_t)wc) != 0) { 407 1.6 tshiozak ret = EILSEQ; 408 1.6 tshiozak goto err; 409 1.6 tshiozak } 410 1.1 tshiozak 411 1.1 tshiozak if (wc & 0x8000) { 412 1.10 tnozaki if (_citrus_BIG5_check(ei, (wc >> 8) & 0xff) != 2 || 413 1.10 tnozaki !_citrus_BIG5_check2(ei, wc & 0xff)) { 414 1.6 tshiozak ret = EILSEQ; 415 1.6 tshiozak goto err; 416 1.6 tshiozak } 417 1.1 tshiozak l = 2; 418 1.1 tshiozak } else { 419 1.10 tnozaki if (wc & ~0xff || !_citrus_BIG5_check(ei, wc & 0xff)) { 420 1.6 tshiozak ret = EILSEQ; 421 1.6 tshiozak goto err; 422 1.6 tshiozak } 423 1.1 tshiozak l = 1; 424 1.1 tshiozak } 425 1.1 tshiozak 426 1.1 tshiozak if (n < l) { 427 1.1 tshiozak /* bound check failure */ 428 1.6 tshiozak ret = E2BIG; 429 1.6 tshiozak goto err; 430 1.1 tshiozak } 431 1.1 tshiozak 432 1.1 tshiozak if (l == 2) { 433 1.1 tshiozak s[0] = (wc >> 8) & 0xff; 434 1.1 tshiozak s[1] = wc & 0xff; 435 1.1 tshiozak } else 436 1.1 tshiozak s[0] = wc & 0xff; 437 1.1 tshiozak 438 1.1 tshiozak *nresult = l; 439 1.1 tshiozak 440 1.6 tshiozak return 0; 441 1.1 tshiozak 442 1.6 tshiozak err: 443 1.1 tshiozak *nresult = (size_t)-1; 444 1.6 tshiozak return ret; 445 1.6 tshiozak } 446 1.6 tshiozak 447 1.6 tshiozak static __inline int 448 1.6 tshiozak /*ARGSUSED*/ 449 1.6 tshiozak _citrus_BIG5_stdenc_wctocs(_BIG5EncodingInfo * __restrict ei, 450 1.6 tshiozak _csid_t * __restrict csid, 451 1.6 tshiozak _index_t * __restrict idx, wchar_t wc) 452 1.6 tshiozak { 453 1.6 tshiozak 454 1.6 tshiozak _DIAGASSERT(csid != NULL && idx != NULL); 455 1.6 tshiozak 456 1.10 tnozaki *csid = (wc < 0x100) ? 0 : 1; 457 1.6 tshiozak *idx = (_index_t)wc; 458 1.9 tshiozak 459 1.6 tshiozak return 0; 460 1.1 tshiozak } 461 1.1 tshiozak 462 1.6 tshiozak static __inline int 463 1.6 tshiozak /*ARGSUSED*/ 464 1.6 tshiozak _citrus_BIG5_stdenc_cstowc(_BIG5EncodingInfo * __restrict ei, 465 1.6 tshiozak wchar_t * __restrict wc, 466 1.6 tshiozak _csid_t csid, _index_t idx) 467 1.6 tshiozak { 468 1.6 tshiozak _DIAGASSERT(wc != NULL); 469 1.6 tshiozak 470 1.6 tshiozak switch (csid) { 471 1.6 tshiozak case 0: 472 1.6 tshiozak case 1: 473 1.6 tshiozak *wc = (wchar_t)idx; 474 1.6 tshiozak break; 475 1.6 tshiozak default: 476 1.6 tshiozak return EILSEQ; 477 1.6 tshiozak } 478 1.6 tshiozak 479 1.6 tshiozak return 0; 480 1.6 tshiozak } 481 1.1 tshiozak 482 1.9 tshiozak static __inline int 483 1.9 tshiozak /*ARGSUSED*/ 484 1.9 tshiozak _citrus_BIG5_stdenc_get_state_desc_generic(_BIG5EncodingInfo * __restrict ei, 485 1.9 tshiozak _BIG5State * __restrict psenc, 486 1.9 tshiozak int * __restrict rstate) 487 1.9 tshiozak { 488 1.9 tshiozak 489 1.9 tshiozak if (psenc->chlen == 0) 490 1.9 tshiozak *rstate = _STDENC_SDGEN_INITIAL; 491 1.9 tshiozak else 492 1.9 tshiozak *rstate = _STDENC_SDGEN_INCOMPLETE_CHAR; 493 1.9 tshiozak 494 1.9 tshiozak return 0; 495 1.9 tshiozak } 496 1.9 tshiozak 497 1.1 tshiozak /* ---------------------------------------------------------------------- 498 1.1 tshiozak * public interface for ctype 499 1.1 tshiozak */ 500 1.1 tshiozak 501 1.1 tshiozak _CITRUS_CTYPE_DECLS(BIG5); 502 1.1 tshiozak _CITRUS_CTYPE_DEF_OPS(BIG5); 503 1.1 tshiozak 504 1.1 tshiozak #include "citrus_ctype_template.h" 505 1.6 tshiozak 506 1.6 tshiozak 507 1.6 tshiozak /* ---------------------------------------------------------------------- 508 1.6 tshiozak * public interface for stdenc 509 1.6 tshiozak */ 510 1.6 tshiozak 511 1.6 tshiozak _CITRUS_STDENC_DECLS(BIG5); 512 1.6 tshiozak _CITRUS_STDENC_DEF_OPS(BIG5); 513 1.6 tshiozak 514 1.6 tshiozak #include "citrus_stdenc_template.h" 515