1 /* $NetBSD: citrus_hz.c,v 1.1 2006/11/22 23:38:27 tnozaki Exp $ */ 2 3 /*- 4 * Copyright (c)2004, 2006 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 #include <sys/cdefs.h> 31 #if defined(LIBC_SCCS) && !defined(lint) 32 __RCSID("$NetBSD: citrus_hz.c,v 1.1 2006/11/22 23:38:27 tnozaki Exp $"); 33 #endif /* LIBC_SCCS and not lint */ 34 35 #include <sys/queue.h> 36 #include <sys/types.h> 37 #include <assert.h> 38 #include <errno.h> 39 #include <string.h> 40 #include <stdint.h> 41 #include <stdlib.h> 42 #include <stddef.h> 43 #include <locale.h> 44 #include <limits.h> 45 #include <wchar.h> 46 47 #include "citrus_namespace.h" 48 #include "citrus_types.h" 49 #include "citrus_bcs.h" 50 #include "citrus_module.h" 51 #include "citrus_ctype.h" 52 #include "citrus_stdenc.h" 53 54 #include "citrus_hz.h" 55 #include "citrus_prop.h" 56 57 /* 58 * wchar_t mapping: 59 * 60 * CTRL/ASCII 00000000 00000000 00000000 gxxxxxxx 61 * GB2312 00000000 00000000 0xxxxxxx gxxxxxxx 62 * 94/96*n (~M) 0mmmmmmm 0xxxxxxx 0xxxxxxx gxxxxxxx 63 */ 64 65 #define ESCAPE_CHAR '~' 66 67 typedef enum { 68 CTRL = 0, ASCII = 1, GB2312 = 2, CS94 = 3, CS96 = 4 69 } charset_t; 70 71 typedef struct { 72 int start, end, width; 73 } range_t; 74 75 static const range_t ranges[] = { 76 #define RANGE(start, end) { start, end, (end - start) + 1 } 77 /* CTRL */ RANGE(0x00, 0x1F), 78 /* ASCII */ RANGE(0x20, 0x7F), 79 /* GB2312 */ RANGE(0x21, 0x7E), 80 /* CS94 */ RANGE(0x21, 0x7E), 81 /* CS96 */ RANGE(0x20, 0x7F), 82 #undef RANGE 83 }; 84 85 typedef struct escape_t escape_t; 86 typedef struct { 87 charset_t charset; 88 size_t length; 89 #define ROWCOL_MAX 3 90 escape_t *escape; 91 } graphic_t; 92 93 typedef TAILQ_HEAD(escape_list, escape_t) escape_list; 94 struct escape_t { 95 TAILQ_ENTRY(escape_t) entry; 96 int ch; 97 graphic_t *left, *right; 98 escape_list *set; 99 }; 100 101 #define GL(escape) ((escape)->left) 102 #define GR(escape) ((escape)->right) 103 #define SET(escape) ((escape)->set) 104 #define ESC(escape) ((escape)->ch) 105 #define INIT(escape) (TAILQ_FIRST(SET(escape))) 106 107 static __inline escape_t * 108 find_escape(escape_list *set, int ch) 109 { 110 escape_t *escape; 111 112 _DIAGASSERT(set != NULL); 113 114 TAILQ_FOREACH(escape, set, entry) { 115 if (ESC(escape) == ch) 116 break; 117 } 118 119 return escape; 120 } 121 122 typedef struct { 123 escape_list e0, e1; 124 graphic_t *ascii, *gb2312; 125 } _HZEncodingInfo; 126 127 #define E0SET(ei) (&(ei)->e0) 128 #define E1SET(ei) (&(ei)->e1) 129 #define INIT0(ei) (TAILQ_FIRST(E0SET(ei))) 130 #define INIT1(ei) (TAILQ_FIRST(E1SET(ei))) 131 132 typedef struct { 133 int chlen; 134 char ch[ROWCOL_MAX]; 135 escape_t *inuse; 136 } _HZState; 137 138 typedef struct { 139 _HZEncodingInfo ei; 140 struct { 141 /* for future multi-locale facility */ 142 _HZState s_mblen; 143 _HZState s_mbrlen; 144 _HZState s_mbrtowc; 145 _HZState s_mbtowc; 146 _HZState s_mbsrtowcs; 147 _HZState s_wcrtomb; 148 _HZState s_wcsrtombs; 149 _HZState s_wctomb; 150 } states; 151 } _HZCTypeInfo; 152 153 #define _CEI_TO_EI(_cei_) (&(_cei_)->ei) 154 #define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_ 155 156 #define _FUNCNAME(m) _citrus_HZ_##m 157 #define _ENCODING_INFO _HZEncodingInfo 158 #define _CTYPE_INFO _HZCTypeInfo 159 #define _ENCODING_STATE _HZState 160 #define _ENCODING_MB_CUR_MAX(_ei_) MB_LEN_MAX 161 #define _ENCODING_IS_STATE_DEPENDENT 1 162 #define _STATE_NEEDS_EXPLICIT_INIT(_ps_) ((_ps_)->inuse == NULL) 163 164 static __inline void 165 _citrus_HZ_init_state(_HZEncodingInfo * __restrict ei, 166 _HZState * __restrict psenc) 167 { 168 _DIAGASSERT(ei != NULL); 169 _DIAGASSERT(psenc != NULL); 170 171 psenc->chlen = 0; 172 psenc->inuse = INIT0(ei); 173 } 174 175 static __inline void 176 /*ARGSUSED*/ 177 _citrus_HZ_pack_state(_HZEncodingInfo * __restrict ei, 178 void *__restrict pspriv, const _HZState * __restrict psenc) 179 { 180 /* ei may be unused */ 181 _DIAGASSERT(pspriv != NULL); 182 _DIAGASSERT(psenc != NULL); 183 184 memcpy(pspriv, (const void *)psenc, sizeof(*psenc)); 185 } 186 187 static __inline void 188 /*ARGSUSED*/ 189 _citrus_HZ_unpack_state(_HZEncodingInfo * __restrict ei, 190 _HZState * __restrict psenc, const void * __restrict pspriv) 191 { 192 /* ei may be unused */ 193 _DIAGASSERT(psenc != NULL); 194 _DIAGASSERT(pspriv != NULL); 195 196 memcpy((void *)psenc, pspriv, sizeof(*psenc)); 197 } 198 199 static int 200 _citrus_HZ_mbrtowc_priv(_HZEncodingInfo * __restrict ei, 201 wchar_t * __restrict pwc, const char ** __restrict s, size_t n, 202 _HZState * __restrict psenc, size_t * __restrict nresult) 203 { 204 const char *s0; 205 wchar_t wc; 206 int bit, head, tail, len, ch; 207 graphic_t *graphic; 208 escape_t *candidate, *init; 209 const range_t *range; 210 211 _DIAGASSERT(ei != NULL); 212 /* pwc may be null */ 213 _DIAGASSERT(s != NULL); 214 _DIAGASSERT(psenc != NULL); 215 _DIAGASSERT(nresult != NULL); 216 217 if (*s == NULL) { 218 _citrus_HZ_init_state(ei, psenc); 219 *nresult = 1; 220 return 0; 221 } 222 s0 = *s; 223 if (psenc->chlen < 0 || psenc->inuse == NULL) 224 return EINVAL; 225 226 wc = (wchar_t)0; 227 bit = head = tail = 0; 228 graphic = NULL; 229 for (len = 0; len <= MB_LEN_MAX; /**/) { 230 if (psenc->chlen == tail) { 231 if (n-- < 1) { 232 *s = s0; 233 *nresult = (size_t)-2; 234 return 0; 235 } 236 psenc->ch[psenc->chlen++] = *s0++; 237 ++len; 238 } 239 ch = (unsigned char)psenc->ch[tail++]; 240 if (tail == 1) { 241 if ((ch & ~0x80) <= 0x1F) { 242 if (psenc->inuse != INIT0(ei)) 243 break; 244 wc = (wchar_t)ch; 245 goto done; 246 } 247 if (ch & 0x80) { 248 graphic = GR(psenc->inuse); 249 bit = 0x80; 250 ch &= ~0x80; 251 } else { 252 graphic = GL(psenc->inuse); 253 if (ch == ESCAPE_CHAR) 254 continue; 255 bit = 0x0; 256 } 257 if (graphic == NULL) 258 break; 259 } else if (tail == 2 && psenc->ch[0] == ESCAPE_CHAR) { 260 if (tail < psenc->chlen) 261 return EINVAL; 262 if (ch == ESCAPE_CHAR) { 263 ++head; 264 } else if (ch == '\n') { 265 if (psenc->inuse != INIT0(ei)) 266 break; 267 tail = psenc->chlen = 0; 268 continue; 269 } else { 270 candidate = NULL; 271 init = INIT0(ei); 272 _DIAGASSERT(init != NULL); 273 if (psenc->inuse == init) { 274 init = INIT1(ei); 275 } else if (INIT(psenc->inuse) == init) { 276 if (ESC(init) != ch) 277 break; 278 candidate = init; 279 } 280 if (candidate == NULL) { 281 candidate = find_escape( 282 SET(psenc->inuse), ch); 283 if (candidate == NULL) { 284 if (init == NULL || 285 ESC(init) != ch) 286 break; 287 candidate = init; 288 } 289 } 290 psenc->inuse = candidate; 291 tail = psenc->chlen = 0; 292 continue; 293 } 294 } else if (ch & 0x80) { 295 if (graphic != GR(psenc->inuse)) 296 break; 297 ch &= ~0x80; 298 } else { 299 if (graphic != GL(psenc->inuse)) 300 break; 301 } 302 _DIAGASSERT(graphic != NULL); 303 range = &ranges[(size_t)graphic->charset]; 304 if (range->start > ch || range->end < ch) 305 break; 306 wc <<= 8; 307 wc |= ch; 308 if (graphic->length == (tail - head)) { 309 if (graphic->charset > GB2312) 310 bit |= ESC(psenc->inuse) << 24; 311 wc |= bit; 312 goto done; 313 } 314 } 315 *nresult = (size_t)-1; 316 return EILSEQ; 317 done: 318 if (tail < psenc->chlen) 319 return EINVAL; 320 *s = s0; 321 if (pwc != NULL) 322 *pwc = wc; 323 psenc->chlen = 0; 324 *nresult = (wc == 0) ? 0 : len; 325 326 return 0; 327 } 328 329 static int 330 _citrus_HZ_wcrtomb_priv(_HZEncodingInfo * __restrict ei, 331 char * __restrict s, size_t n, wchar_t wc, 332 _HZState * __restrict psenc, size_t * __restrict nresult) 333 { 334 int bit, ch; 335 escape_t *candidate, *init; 336 graphic_t *graphic; 337 size_t len; 338 const range_t *range; 339 340 _DIAGASSERT(ei != NULL); 341 _DIAGASSERT(s != NULL); 342 _DIAGASSERT(psenc != NULL); 343 _DIAGASSERT(nresult != NULL); 344 345 if (psenc->chlen != 0 || psenc->inuse == NULL) 346 return EINVAL; 347 if (wc & 0x80) { 348 bit = 0x80; 349 wc &= ~0x80; 350 } else { 351 bit = 0x0; 352 } 353 if ((uint32_t)wc <= 0x1F) { 354 candidate = INIT0(ei); 355 graphic = (bit == 0) 356 ? candidate->left : candidate->right; 357 if (graphic == NULL) 358 goto ilseq; 359 range = &ranges[(size_t)CTRL]; 360 len = 1; 361 } else if ((uint32_t)wc <= 0x7F) { 362 graphic = ei->ascii; 363 if (graphic == NULL) 364 goto ilseq; 365 candidate = graphic->escape; 366 range = &ranges[(size_t)graphic->charset]; 367 len = graphic->length; 368 } else if ((uint32_t)wc <= 0x7F7F) { 369 graphic = ei->gb2312; 370 if (graphic == NULL) 371 goto ilseq; 372 candidate = graphic->escape; 373 range = &ranges[(size_t)graphic->charset]; 374 len = graphic->length; 375 } else { 376 ch = (wc >> 24) & 0xFF; 377 candidate = find_escape(E0SET(ei), ch); 378 if (candidate == NULL) { 379 candidate = find_escape(E1SET(ei), ch); 380 if (candidate == NULL) 381 goto ilseq; 382 } 383 wc &= ~0xFF000000; 384 graphic = (bit == 0) 385 ? candidate->left : candidate->right; 386 if (graphic == NULL) 387 goto ilseq; 388 range = &ranges[(size_t)graphic->charset]; 389 len = graphic->length; 390 } 391 if (psenc->inuse != candidate) { 392 init = INIT0(ei); 393 if (SET(psenc->inuse) == SET(candidate)) { 394 if (INIT(psenc->inuse) != init || 395 psenc->inuse == init || candidate == init) 396 init = NULL; 397 } else if (candidate == (init = INIT(candidate))) { 398 init = NULL; 399 } 400 if (init != NULL) { 401 if (n < 2) 402 return E2BIG; 403 n -= 2; 404 psenc->ch[psenc->chlen++] = ESCAPE_CHAR; 405 psenc->ch[psenc->chlen++] = ESC(init); 406 } 407 if (n < 2) 408 return E2BIG; 409 n -= 2; 410 psenc->ch[psenc->chlen++] = ESCAPE_CHAR; 411 psenc->ch[psenc->chlen++] = ESC(candidate); 412 psenc->inuse = candidate; 413 } 414 if (n < len) 415 return E2BIG; 416 while (len-- > 0) { 417 ch = (wc >> (len * 8)) & 0xFF; 418 if (range->start > ch || range->end < ch) 419 goto ilseq; 420 psenc->ch[psenc->chlen++] = ch | bit; 421 } 422 memcpy(s, psenc->ch, psenc->chlen); 423 *nresult = psenc->chlen; 424 psenc->chlen = 0; 425 426 return 0; 427 428 ilseq: 429 *nresult = (size_t)-1; 430 return EILSEQ; 431 } 432 433 static __inline int 434 _citrus_HZ_put_state_reset(_HZEncodingInfo * __restrict ei, 435 char * __restrict s, size_t n, _HZState * __restrict psenc, 436 size_t * __restrict nresult) 437 { 438 escape_t *candidate; 439 440 _DIAGASSERT(ei != NULL); 441 _DIAGASSERT(s != NULL); 442 _DIAGASSERT(psenc != NULL); 443 _DIAGASSERT(nresult != NULL); 444 445 if (psenc->chlen != 0 || psenc->inuse == NULL) 446 return EINVAL; 447 candidate = INIT0(ei); 448 if (psenc->inuse != candidate) { 449 if (n < 2) 450 return E2BIG; 451 n -= 2; 452 psenc->ch[psenc->chlen++] = ESCAPE_CHAR; 453 psenc->ch[psenc->chlen++] = ESC(candidate); 454 } 455 if (n < 1) 456 return E2BIG; 457 if (psenc->chlen > 0) 458 memcpy(s, psenc->ch, psenc->chlen); 459 *nresult = psenc->chlen; 460 _citrus_HZ_init_state(ei, psenc); 461 462 return 0; 463 } 464 465 static __inline int 466 _citrus_HZ_stdenc_get_state_desc_generic(_HZEncodingInfo * __restrict ei, 467 _HZState * __restrict psenc, int * __restrict rstate) 468 { 469 _DIAGASSERT(ei != NULL); 470 _DIAGASSERT(psenc != NULL); 471 _DIAGASSERT(rstate != NULL); 472 473 if (psenc->chlen < 0 || psenc->inuse == NULL) 474 return EINVAL; 475 *rstate = (psenc->chlen == 0) 476 ? ((psenc->inuse == INIT0(ei)) 477 ? _STDENC_SDGEN_INITIAL 478 : _STDENC_SDGEN_STABLE) 479 : ((psenc->ch[0] == ESCAPE_CHAR) 480 ? _STDENC_SDGEN_INCOMPLETE_SHIFT 481 : _STDENC_SDGEN_INCOMPLETE_CHAR); 482 483 return 0; 484 } 485 486 static __inline int 487 /*ARGSUSED*/ 488 _citrus_HZ_stdenc_wctocs(_HZEncodingInfo * __restrict ei, 489 _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc) 490 { 491 int bit; 492 493 _DIAGASSERT(csid != NULL); 494 _DIAGASSERT(idx != NULL); 495 496 if (wc & 0x80) { 497 bit = 0x80; 498 wc &= ~0x80; 499 } else { 500 bit = 0x0; 501 } 502 if ((uint32_t)wc <= 0x7F) { 503 *csid = (_csid_t)bit; 504 *idx = (_index_t)wc; 505 } else if ((uint32_t)wc <= 0x7F7F) { 506 *csid = (_csid_t)(bit | 0x8000); 507 *idx = (_index_t)wc; 508 } else { 509 *csid = (_index_t)(wc & ~0x00FFFF7F); 510 *idx = (_csid_t)(wc & 0x00FFFF7F); 511 } 512 513 return 0; 514 } 515 516 static __inline int 517 /*ARGSUSED*/ 518 _citrus_HZ_stdenc_cstowc(_HZEncodingInfo * __restrict ei, 519 wchar_t * __restrict wc, _csid_t csid, _index_t idx) 520 { 521 _DIAGASSERT(ei != NULL); 522 _DIAGASSERT(wc != NULL); 523 524 *wc = (wchar_t)idx; 525 switch (csid) { 526 case 0x80: 527 case 0x8080: 528 *wc |= (wchar_t)0x80; 529 /*FALLTHROUGH*/ 530 case 0x0: 531 case 0x8000: 532 break; 533 default: 534 *wc |= (wchar_t)csid; 535 } 536 537 return 0; 538 } 539 540 static void 541 _citrus_HZ_encoding_module_uninit(_HZEncodingInfo *ei) 542 { 543 escape_t *escape; 544 545 _DIAGASSERT(ei != NULL); 546 while ((escape = TAILQ_FIRST(E0SET(ei))) != NULL) { 547 TAILQ_REMOVE(E0SET(ei), escape, entry); 548 free(GL(escape)); 549 free(GR(escape)); 550 free(escape); 551 } 552 while ((escape = TAILQ_FIRST(E1SET(ei))) != NULL) { 553 TAILQ_REMOVE(E1SET(ei), escape, entry); 554 free(GL(escape)); 555 free(GR(escape)); 556 free(escape); 557 } 558 } 559 560 static int 561 _citrus_HZ_parse_char(void **context, const char *name, const char *s) 562 { 563 void **p; 564 escape_t *escape; 565 566 _DIAGASSERT(context != NULL && *context != NULL); 567 _DIAGASSERT(name != NULL); 568 _DIAGASSERT(s != NULL); 569 570 p = (void **)*context; 571 escape = (escape_t *)p[0]; 572 if (escape->ch != '\0') 573 return EINVAL; 574 escape->ch = *s++; 575 if (escape->ch == ESCAPE_CHAR || *s != '\0') 576 return EINVAL; 577 578 return 0; 579 } 580 581 static int 582 _citrus_HZ_parse_graphic(void **context, const char *name, const char *s) 583 { 584 void **p; 585 _HZEncodingInfo *ei; 586 escape_t *escape; 587 graphic_t *graphic; 588 589 _DIAGASSERT(context != NULL && *context != NULL); 590 _DIAGASSERT(name != NULL); 591 _DIAGASSERT(s != NULL); 592 593 p = (void **)*context; 594 escape = (escape_t *)p[0]; 595 ei = (_HZEncodingInfo *)p[1]; 596 graphic = malloc(sizeof(*graphic)); 597 if (graphic == NULL) 598 return ENOMEM; 599 memset(graphic, 0, sizeof(*graphic)); 600 if (strcmp("GL", name) == 0) { 601 if (GL(escape) != NULL) 602 goto release; 603 GL(escape) = graphic; 604 } else if (strcmp("GR", name) == 0) { 605 if (GR(escape) != NULL) 606 goto release; 607 GR(escape) = graphic; 608 } else { 609 release: 610 free(graphic); 611 return EINVAL; 612 } 613 graphic->escape = escape; 614 if (_bcs_strncasecmp("ASCII", s, 5) == 0) { 615 if (s[5] != '\0') 616 return EINVAL; 617 graphic->charset = ASCII; 618 graphic->length = 1; 619 ei->ascii = graphic; 620 return 0; 621 } else if (_bcs_strncasecmp("GB2312", s, 6) == 0) { 622 if (s[6] != '\0') 623 return EINVAL; 624 graphic->charset = GB2312; 625 graphic->length = 2; 626 ei->gb2312 = graphic; 627 return 0; 628 } else if (strncmp("94*", s, 3) == 0) { 629 graphic->charset = CS94; 630 } else if (strncmp("96*", s, 3) == 0) { 631 graphic->charset = CS96; 632 } else { 633 return EINVAL; 634 } 635 s += 3; 636 switch(*s) { 637 case '1': case '2': case '3': 638 graphic->length = (size_t)(*s - '0'); 639 if (*++s == '\0') 640 break; 641 /*FALLTHROUGH*/ 642 default: 643 return EINVAL; 644 } 645 return 0; 646 } 647 648 static const _citrus_prop_hint_t escape_hints[] = { 649 _CITRUS_PROP_HINT_STR("CH", &_citrus_HZ_parse_char), 650 _CITRUS_PROP_HINT_STR("GL", &_citrus_HZ_parse_graphic), 651 _CITRUS_PROP_HINT_STR("GR", &_citrus_HZ_parse_graphic), 652 _CITRUS_PROP_HINT_END 653 }; 654 655 static int 656 _citrus_HZ_parse_escape(void **context, const char *name, const char *s) 657 { 658 _HZEncodingInfo *ei; 659 escape_t *escape; 660 void *p[2]; 661 662 _DIAGASSERT(context != NULL); 663 _DIAGASSERT(name != NULL); 664 _DIAGASSERT(s != NULL); 665 666 ei = (_HZEncodingInfo *)*context; 667 escape = malloc(sizeof(*escape)); 668 if (escape == NULL) 669 return EINVAL; 670 memset(escape, 0, sizeof(*escape)); 671 if (strcmp("0", name) == 0) { 672 escape->set = E0SET(ei); 673 TAILQ_INSERT_TAIL(E0SET(ei), escape, entry); 674 } else if (strcmp("1", name) == 0) { 675 escape->set = E1SET(ei); 676 TAILQ_INSERT_TAIL(E1SET(ei), escape, entry); 677 } else { 678 free(escape); 679 return EINVAL; 680 } 681 p[0] = (void *)escape; 682 p[1] = (void *)ei; 683 return _citrus_prop_parse_variable( 684 escape_hints, (void *)&p[0], s, strlen(s)); 685 } 686 687 static const _citrus_prop_hint_t root_hints[] = { 688 _CITRUS_PROP_HINT_STR("0", &_citrus_HZ_parse_escape), 689 _CITRUS_PROP_HINT_STR("1", &_citrus_HZ_parse_escape), 690 _CITRUS_PROP_HINT_END 691 }; 692 693 static int 694 _citrus_HZ_encoding_module_init(_HZEncodingInfo * __restrict ei, 695 const void * __restrict var, size_t lenvar) 696 { 697 int errnum; 698 699 _DIAGASSERT(ei != NULL); 700 701 memset(ei, 0, sizeof(*ei)); 702 TAILQ_INIT(E0SET(ei)); 703 TAILQ_INIT(E1SET(ei)); 704 errnum = _citrus_prop_parse_variable( 705 root_hints, (void *)ei, var, lenvar); 706 if (errnum != 0) 707 _citrus_HZ_encoding_module_uninit(ei); 708 return errnum; 709 } 710 711 /* ---------------------------------------------------------------------- 712 * public interface for ctype 713 */ 714 715 _CITRUS_CTYPE_DECLS(HZ); 716 _CITRUS_CTYPE_DEF_OPS(HZ); 717 718 #include "citrus_ctype_template.h" 719 720 /* ---------------------------------------------------------------------- 721 * public interface for stdenc 722 */ 723 724 _CITRUS_STDENC_DECLS(HZ); 725 _CITRUS_STDENC_DEF_OPS(HZ); 726 727 #include "citrus_stdenc_template.h" 728