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