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