1/* $NetBSD: citrus_ctype_template.h,v 1.40 2022/05/28 22:16:43 andvar Exp $ */ 2 3/*- 4 * Copyright (c)2002 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 * Copyright (c) 1993 31 * The Regents of the University of California. All rights reserved. 32 * 33 * This code is derived from software contributed to Berkeley by 34 * Paul Borman at Krystal Technologies. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. Neither the name of the University nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 */ 60 61 62/* 63 * CAUTION: THIS IS NOT STANDALONE FILE 64 * 65 * function templates of ctype encoding handler for each encodings. 66 * 67 * you need to define the macros below: 68 * 69 * _FUNCNAME(method) : 70 * It should convine the real function name for the method. 71 * e.g. _FUNCNAME(mbrtowc) should be expanded to 72 * _EUC_ctype_mbrtowc 73 * for EUC locale. 74 * 75 * _CEI_TO_STATE(cei, method) : 76 * It should be expanded to the pointer of the method-internal state 77 * structures. 78 * e.g. _CEI_TO_STATE(cei, mbrtowc) might be expanded to 79 * (cei)->states.s_mbrtowc 80 * This structure may use if the function is called as 81 * mbrtowc(&wc, s, n, NULL); 82 * Such individual structures are needed by: 83 * mblen 84 * mbrlen 85 * mbrtowc 86 * mbtowc 87 * mbsrtowcs 88 * mbsnrtowcs 89 * wcrtomb 90 * wcsrtombs 91 * wcsnrtombs 92 * wctomb 93 * These need to be kept in the ctype encoding information structure, 94 * pointed by "cei". 95 * 96 * _ENCODING_INFO : 97 * It should be expanded to the name of the encoding information structure. 98 * e.g. For EUC encoding, this macro is expanded to _EUCInfo. 99 * Encoding information structure need to contain the common informations 100 * for the codeset. 101 * 102 * _ENCODING_STATE : 103 * It should be expanded to the name of the encoding state structure. 104 * e.g. For EUC encoding, this macro is expanded to _EUCState. 105 * Encoding state structure need to contain the context-dependent states, 106 * which are "unpacked-form" of mbstate_t type and kept during sequent 107 * calls of mb/wc functions, 108 * 109 * _ENCODING_IS_STATE_DEPENDENT : 110 * If the encoding is state dependent, this should be expanded to 111 * non-zero integral value. Otherwise, 0. 112 * 113 * _STATE_NEEDS_EXPLICIT_INIT(ps) : 114 * some encodings, states needs some explicit initialization. 115 * (ie. initialization with memset isn't enough.) 116 * If the encoding state pointed by "ps" needs to be initialized 117 * explicitly, return non-zero. Otherwize, 0. 118 * 119 */ 120 121#include <stdalign.h> 122 123/* prototypes */ 124 125__BEGIN_DECLS 126static void _FUNCNAME(init_state)(_ENCODING_INFO * __restrict, 127 _ENCODING_STATE * __restrict); 128static void _FUNCNAME(pack_state)(_ENCODING_INFO * __restrict, 129 void * __restrict, 130 const _ENCODING_STATE * __restrict); 131static void _FUNCNAME(unpack_state)(_ENCODING_INFO * __restrict, 132 _ENCODING_STATE * __restrict, 133 const void * __restrict); 134#if _ENCODING_IS_STATE_DEPENDENT 135static int _FUNCNAME(put_state_reset)(_ENCODING_INFO * __restrict, 136 char * __restrict, size_t, 137 _ENCODING_STATE * __restrict, 138 size_t * __restrict); 139#endif 140 141/* 142 * standard form of mbrtowc_priv. 143 * 144 * note (differences from real mbrtowc): 145 * - 3rd parameter is not "const char *s" but "const char **s". 146 * after the call of the function, *s will point the first byte of 147 * the next character. 148 * - additional 4th parameter is the size of src buffer. 149 * - 5th parameter is unpacked encoding-dependent state structure. 150 * - additional 6th parameter is the storage to be stored 151 * the return value in the real mbrtowc context. 152 * - return value means "errno" in the real mbrtowc context. 153 */ 154 155static int _FUNCNAME(mbrtowc_priv)(_ENCODING_INFO * __restrict, 156 wchar_t * __restrict, 157 const char ** __restrict, 158 size_t, _ENCODING_STATE * __restrict, 159 size_t * __restrict); 160 161/* 162 * standard form of wcrtomb_priv. 163 * 164 * note (differences from real wcrtomb): 165 * - additional 3th parameter is the size of src buffer. 166 * - 5th parameter is unpacked encoding-dependent state structure. 167 * - additional 6th parameter is the storage to be stored 168 * the return value in the real mbrtowc context. 169 * - return value means "errno" in the real wcrtomb context. 170 * - caller should ensure that 2nd parameter isn't NULL. 171 * (XXX inconsist with mbrtowc_priv) 172 */ 173 174static int _FUNCNAME(wcrtomb_priv)(_ENCODING_INFO * __restrict, 175 char * __restrict, size_t, wchar_t, 176 _ENCODING_STATE * __restrict, 177 size_t * __restrict); 178__END_DECLS 179 180 181/* 182 * macros 183 */ 184 185#define _TO_CEI(_cl_) ((_CTYPE_INFO*)(_cl_)) 186 187 188/* 189 * templates 190 */ 191 192/* internal routines */ 193 194static __inline int 195_FUNCNAME(mbtowc_priv)(_ENCODING_INFO * __restrict ei, 196 wchar_t * __restrict pwc, const char * __restrict s, 197 size_t n, _ENCODING_STATE * __restrict psenc, 198 int * __restrict nresult) 199{ 200 _ENCODING_STATE state; 201 size_t nr; 202 int err = 0; 203 204 _DIAGASSERT(ei != NULL); 205 _DIAGASSERT(psenc != NULL); 206 207 if (s == NULL) { 208 _FUNCNAME(init_state)(ei, psenc); 209 *nresult = _ENCODING_IS_STATE_DEPENDENT; 210 return (0); 211 } 212 213 state = *psenc; 214 err = _FUNCNAME(mbrtowc_priv)(ei, pwc, (const char **)&s, n, psenc, &nr); 215 if (nr == (size_t)-2) 216 err = EILSEQ; 217 if (err) { 218 /* In error case, we should restore the state. */ 219 *psenc = state; 220 *nresult = -1; 221 return (err); 222 } 223 224 *nresult = (int)nr; 225 226 return (0); 227} 228 229static int 230_FUNCNAME(mbsrtowcs_priv)(_ENCODING_INFO * __restrict ei, 231 wchar_t * __restrict pwcs, 232 const char ** __restrict s, 233 size_t n, _ENCODING_STATE * __restrict psenc, 234 size_t * __restrict nresult) 235{ 236 int err, cnt; 237 size_t siz; 238 const char *s0; 239 size_t mbcurmax; 240 241 _DIAGASSERT(nresult != 0); 242 _DIAGASSERT(ei != NULL); 243 _DIAGASSERT(psenc != NULL); 244 _DIAGASSERT(s != NULL); 245 _DIAGASSERT(*s != NULL); 246 247 /* if pwcs is NULL, ignore n */ 248 if (pwcs == NULL) 249 n = 1; /* arbitrary >0 value */ 250 251 err = cnt = 0; 252 s0 = *s; /* to keep *s unchanged for now, use copy instead. */ 253 mbcurmax = _ENCODING_MB_CUR_MAX(ei); 254 while (n > 0) { 255 err = _FUNCNAME(mbrtowc_priv)(ei, pwcs, &s0, mbcurmax, 256 psenc, &siz); 257 if (siz == (size_t)-2) 258 err = EILSEQ; 259 if (err) { 260 cnt = -1; 261 goto bye; 262 } 263 switch (siz) { 264 case 0: 265 if (pwcs) { 266 _FUNCNAME(init_state)(ei, psenc); 267 } 268 s0 = 0; 269 goto bye; 270 default: 271 if (pwcs) { 272 pwcs++; 273 n--; 274 } 275 cnt++; 276 break; 277 } 278 } 279bye: 280 if (pwcs) 281 *s = s0; 282 283 *nresult = (size_t)cnt; 284 285 return err; 286} 287 288static int 289_FUNCNAME(mbsnrtowcs_priv)(_ENCODING_INFO * __restrict ei, 290 wchar_t * __restrict pwcs, 291 const char ** __restrict s, size_t in, 292 size_t n, _ENCODING_STATE * __restrict psenc, 293 size_t * __restrict nresult) 294{ 295 int err; 296 size_t cnt, siz; 297 const char *s0, *se; 298 299 _DIAGASSERT(nresult != 0); 300 _DIAGASSERT(ei != NULL); 301 _DIAGASSERT(psenc != NULL); 302 _DIAGASSERT(s != NULL); 303 _DIAGASSERT(*s != NULL); 304 305 /* if pwcs is NULL, ignore n */ 306 if (pwcs == NULL) 307 n = 1; /* arbitrary >0 value */ 308 309 err = 0; 310 cnt = 0; 311 se = *s + in; 312 s0 = *s; /* to keep *s unchanged for now, use copy instead. */ 313 while (s0 < se && n > 0) { 314 err = _FUNCNAME(mbrtowc_priv)(ei, pwcs, &s0, se - s0, 315 psenc, &siz); 316 if (err) { 317 cnt = (size_t)-1; 318 goto bye; 319 } 320 if (siz == (size_t)-2) { 321 s0 = se; 322 goto bye; 323 } 324 switch (siz) { 325 case 0: 326 if (pwcs) { 327 _FUNCNAME(init_state)(ei, psenc); 328 } 329 s0 = 0; 330 goto bye; 331 default: 332 if (pwcs) { 333 pwcs++; 334 n--; 335 } 336 cnt++; 337 break; 338 } 339 } 340bye: 341 if (pwcs) 342 *s = s0; 343 344 *nresult = cnt; 345 346 return err; 347} 348 349static int 350_FUNCNAME(wcsrtombs_priv)(_ENCODING_INFO * __restrict ei, char * __restrict s, 351 const wchar_t ** __restrict pwcs, 352 size_t n, _ENCODING_STATE * __restrict psenc, 353 size_t * __restrict nresult) 354{ 355 int err; 356 char buf[MB_LEN_MAX]; 357 size_t cnt, siz; 358 const wchar_t* pwcs0; 359#if _ENCODING_IS_STATE_DEPENDENT 360 _ENCODING_STATE state; 361#endif 362 363 pwcs0 = *pwcs; 364 365 cnt = 0; 366 if (!s) 367 n = 1; 368 369 while (n > 0) { 370#if _ENCODING_IS_STATE_DEPENDENT 371 state = *psenc; 372#endif 373 err = _FUNCNAME(wcrtomb_priv)(ei, buf, sizeof(buf), 374 *pwcs0, psenc, &siz); 375 if (siz == (size_t)-1) { 376 *pwcs = pwcs0; 377 *nresult = siz; 378 return (err); 379 } 380 381 if (s) { 382 if (n < siz) { 383#if _ENCODING_IS_STATE_DEPENDENT 384 *psenc = state; 385#endif 386 break; 387 } 388 memcpy(s, buf, siz); 389 s += siz; 390 n -= siz; 391 } 392 cnt += siz; 393 if (!*pwcs0) { 394 if (s) { 395 _FUNCNAME(init_state)(ei, psenc); 396 } 397 pwcs0 = 0; 398 cnt--; /* don't include terminating null */ 399 break; 400 } 401 pwcs0++; 402 } 403 if (s) 404 *pwcs = pwcs0; 405 406 *nresult = cnt; 407 return (0); 408} 409 410static int 411_FUNCNAME(wcsnrtombs_priv)(_ENCODING_INFO * __restrict ei, char * __restrict s, 412 const wchar_t ** __restrict pwcs, size_t in, 413 size_t n, _ENCODING_STATE * __restrict psenc, 414 size_t * __restrict nresult) 415{ 416 int cnt = 0, err; 417 char buf[MB_LEN_MAX]; 418 size_t siz; 419 const wchar_t* pwcs0; 420#if _ENCODING_IS_STATE_DEPENDENT 421 _ENCODING_STATE state; 422#endif 423 424 pwcs0 = *pwcs; 425 426 if (!s) 427 n = 1; 428 429 while (in > 0 && n > 0) { 430#if _ENCODING_IS_STATE_DEPENDENT 431 state = *psenc; 432#endif 433 err = _FUNCNAME(wcrtomb_priv)(ei, buf, sizeof(buf), 434 *pwcs0, psenc, &siz); 435 if (siz == (size_t)-1) { 436 *nresult = siz; 437 return (err); 438 } 439 440 if (s) { 441 if (n < siz) { 442#if _ENCODING_IS_STATE_DEPENDENT 443 *psenc = state; 444#endif 445 break; 446 } 447 memcpy(s, buf, siz); 448 s += siz; 449 n -= siz; 450 } 451 cnt += siz; 452 if (!*pwcs0) { 453 if (s) { 454 _FUNCNAME(init_state)(ei, psenc); 455 } 456 pwcs0 = 0; 457 cnt--; /* don't include terminating null */ 458 break; 459 } 460 pwcs0++; 461 --in; 462 } 463 if (s) 464 *pwcs = pwcs0; 465 466 *nresult = (size_t)cnt; 467 return (0); 468} 469 470 471/* ---------------------------------------------------------------------- 472 * templates for public functions 473 */ 474 475#define _RESTART_BEGIN(_func_, _cei_, _pspriv_, _pse_) \ 476do { \ 477 _ENCODING_STATE _state; \ 478 do { \ 479 if (_pspriv_ == NULL) { \ 480 _pse_ = &_CEI_TO_STATE(_cei_, _func_); \ 481 if (_STATE_NEEDS_EXPLICIT_INIT(_pse_)) \ 482 _FUNCNAME(init_state)(_CEI_TO_EI(_cei_), \ 483 (_pse_)); \ 484 } else { \ 485 _pse_ = &_state; \ 486 _FUNCNAME(unpack_state)(_CEI_TO_EI(_cei_), \ 487 _pse_, _pspriv_); \ 488 } \ 489 } while (0) 490 491#define _RESTART_END(_func_, _cei_, _pspriv_, _pse_) \ 492 if (_pspriv_ != NULL) { \ 493 _FUNCNAME(pack_state)(_CEI_TO_EI(_cei_), _pspriv_, \ 494 _pse_); \ 495 } \ 496} while (0) 497 498int 499_FUNCNAME(ctype_getops)(_citrus_ctype_ops_rec_t *ops, size_t lenops, 500 uint32_t expected_version) 501{ 502 if (expected_version<_CITRUS_CTYPE_ABI_VERSION || lenops<sizeof(*ops)) 503 return (EINVAL); 504 505 memcpy(ops, &_FUNCNAME(ctype_ops), sizeof(_FUNCNAME(ctype_ops))); 506 507 return (0); 508} 509 510/* Ensure alignment matches guarantees from locale/multibyte.h */ 511__CTASSERT(alignof(_ENCODING_STATE) <= alignof(int) || 512 alignof(_ENCODING_STATE) <= alignof(void *)); 513 514static int 515_FUNCNAME(ctype_init)(void ** __restrict cl, 516 void * __restrict var, size_t lenvar, size_t lenps) 517{ 518 _CTYPE_INFO *cei; 519 520 _DIAGASSERT(cl != NULL); 521 522 /* sanity check to avoid overruns */ 523 if (sizeof(_ENCODING_STATE) > lenps) 524 return (EINVAL); 525 526 cei = calloc(1, sizeof(_CTYPE_INFO)); 527 if (cei == NULL) 528 return (ENOMEM); 529 530 *cl = (void *)cei; 531 532 return _FUNCNAME(encoding_module_init)(_CEI_TO_EI(cei), var, lenvar); 533} 534 535static void 536_FUNCNAME(ctype_uninit)(void *cl) 537{ 538 if (cl) { 539 _FUNCNAME(encoding_module_uninit)(_CEI_TO_EI(_TO_CEI(cl))); 540 free(cl); 541 } 542} 543 544static unsigned 545/*ARGSUSED*/ 546_FUNCNAME(ctype_get_mb_cur_max)(void *cl) 547{ 548 return _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl))); 549} 550 551static int 552_FUNCNAME(ctype_mblen)(void * __restrict cl, 553 const char * __restrict s, size_t n, 554 int * __restrict nresult) 555{ 556 _ENCODING_STATE *psenc; 557 _ENCODING_INFO *ei; 558 559 _DIAGASSERT(cl != NULL); 560 561 psenc = &_CEI_TO_STATE(_TO_CEI(cl), mblen); 562 ei = _CEI_TO_EI(_TO_CEI(cl)); 563 if (_STATE_NEEDS_EXPLICIT_INIT(psenc)) 564 _FUNCNAME(init_state)(ei, psenc); 565 return _FUNCNAME(mbtowc_priv)(ei, NULL, s, n, psenc, nresult); 566} 567 568static int 569_FUNCNAME(ctype_mbrlen)(void * __restrict cl, const char * __restrict s, 570 size_t n, void * __restrict pspriv, 571 size_t * __restrict nresult) 572{ 573 _ENCODING_STATE *psenc; 574 _ENCODING_INFO *ei; 575 int err = 0; 576 577 _DIAGASSERT(cl != NULL); 578 579 ei = _CEI_TO_EI(_TO_CEI(cl)); 580 _RESTART_BEGIN(mbrlen, _TO_CEI(cl), pspriv, psenc); 581 if (s == NULL) { 582 _FUNCNAME(init_state)(ei, psenc); 583 *nresult = 0; 584 } else { 585 err = _FUNCNAME(mbrtowc_priv)(ei, NULL, (const char **)&s, n, 586 (void *)psenc, nresult); 587 } 588 _RESTART_END(mbrlen, _TO_CEI(cl), pspriv, psenc); 589 590 return (err); 591} 592 593static int 594_FUNCNAME(ctype_mbrtowc)(void * __restrict cl, wchar_t * __restrict pwc, 595 const char * __restrict s, size_t n, 596 void * __restrict pspriv, size_t * __restrict nresult) 597{ 598 _ENCODING_STATE *psenc; 599 _ENCODING_INFO *ei; 600 int err = 0; 601 602 _DIAGASSERT(cl != NULL); 603 604 ei = _CEI_TO_EI(_TO_CEI(cl)); 605 _RESTART_BEGIN(mbrtowc, _TO_CEI(cl), pspriv, psenc); 606 if (s == NULL) { 607 _FUNCNAME(init_state)(ei, psenc); 608 *nresult = 0; 609 } else { 610 err = _FUNCNAME(mbrtowc_priv)(ei, pwc, (const char **)&s, n, 611 (void *)psenc, nresult); 612 } 613 _RESTART_END(mbrtowc, _TO_CEI(cl), pspriv, psenc); 614 615 return (err); 616} 617 618static int 619/*ARGSUSED*/ 620_FUNCNAME(ctype_mbsinit)(void * __restrict cl, const void * __restrict pspriv, 621 int * __restrict nresult) 622{ 623 _ENCODING_STATE state; 624 625 if (pspriv == NULL) { 626 *nresult = 1; 627 return (0); 628 } 629 630 _FUNCNAME(unpack_state)(_CEI_TO_EI(_TO_CEI(cl)), &state, pspriv); 631 632 *nresult = (state.chlen == 0); /* XXX: FIXME */ 633 634 return (0); 635} 636 637static int 638_FUNCNAME(ctype_mbsrtowcs)(void * __restrict cl, wchar_t * __restrict pwcs, 639 const char ** __restrict s, size_t n, 640 void * __restrict pspriv, 641 size_t * __restrict nresult) 642{ 643 _ENCODING_STATE *psenc; 644 _ENCODING_INFO *ei; 645 int err = 0; 646 647 _DIAGASSERT(cl != NULL); 648 649 ei = _CEI_TO_EI(_TO_CEI(cl)); 650 _RESTART_BEGIN(mbsrtowcs, _TO_CEI(cl), pspriv, psenc); 651 err = _FUNCNAME(mbsrtowcs_priv)(ei, pwcs, s, n, psenc, nresult); 652 _RESTART_END(mbsrtowcs, _TO_CEI(cl), pspriv, psenc); 653 654 return (err); 655} 656 657static int __used 658_FUNCNAME(ctype_mbsnrtowcs)(_citrus_ctype_rec_t * __restrict cc, wchar_t * __restrict pwcs, 659 const char ** __restrict s, size_t in, size_t n, 660 void * __restrict pspriv, 661 size_t * __restrict nresult) 662{ 663 void *cl = cc->cc_closure; 664 _ENCODING_STATE *psenc; 665 _ENCODING_INFO *ei; 666 int err = 0; 667 668 _DIAGASSERT(cl != NULL); 669 670 ei = _CEI_TO_EI(_TO_CEI(cl)); 671 _RESTART_BEGIN(mbsnrtowcs, _TO_CEI(cl), pspriv, psenc); 672 err = _FUNCNAME(mbsnrtowcs_priv)(ei, pwcs, s, in, n, psenc, nresult); 673 _RESTART_END(mbsnrtowcs, _TO_CEI(cl), pspriv, psenc); 674 675 return (err); 676} 677 678static int 679_FUNCNAME(ctype_mbstowcs)(void * __restrict cl, wchar_t * __restrict pwcs, 680 const char * __restrict s, size_t n, 681 size_t * __restrict nresult) 682{ 683 int err; 684 _ENCODING_STATE state; 685 _ENCODING_INFO *ei; 686 687 _DIAGASSERT(cl != NULL); 688 689 ei = _CEI_TO_EI(_TO_CEI(cl)); 690 _FUNCNAME(init_state)(ei, &state); 691 err = _FUNCNAME(mbsrtowcs_priv)(ei, pwcs, (const char **)&s, n, 692 &state, nresult); 693 if (*nresult == (size_t)-2) { 694 err = EILSEQ; 695 *nresult = (size_t)-1; 696 } 697 698 return (err); 699} 700 701static int 702_FUNCNAME(ctype_mbtowc)(void * __restrict cl, wchar_t * __restrict pwc, 703 const char * __restrict s, size_t n, 704 int * __restrict nresult) 705{ 706 _ENCODING_STATE *psenc; 707 _ENCODING_INFO *ei; 708 709 _DIAGASSERT(cl != NULL); 710 711 psenc = &_CEI_TO_STATE(_TO_CEI(cl), mbtowc); 712 ei = _CEI_TO_EI(_TO_CEI(cl)); 713 if (_STATE_NEEDS_EXPLICIT_INIT(psenc)) 714 _FUNCNAME(init_state)(ei, psenc); 715 return _FUNCNAME(mbtowc_priv)(ei, pwc, s, n, psenc, nresult); 716} 717 718static int 719_FUNCNAME(ctype_wcrtomb)(void * __restrict cl, char * __restrict s, wchar_t wc, 720 void * __restrict pspriv, size_t * __restrict nresult) 721{ 722 _ENCODING_STATE *psenc; 723 char buf[MB_LEN_MAX]; 724 int err = 0; 725 size_t sz; 726#if _ENCODING_IS_STATE_DEPENDENT 727 size_t rsz = 0; 728#endif 729 730 _DIAGASSERT(cl != NULL); 731 732 if (s == NULL) { 733 /* 734 * use internal buffer. 735 */ 736 s = buf; 737 wc = L'\0'; /* SUSv3 */ 738 } 739 740 _RESTART_BEGIN(wcrtomb, _TO_CEI(cl), pspriv, psenc); 741 sz = _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl))); 742#if _ENCODING_IS_STATE_DEPENDENT 743 if (wc == L'\0') { 744 /* reset state */ 745 err = _FUNCNAME(put_state_reset)(_CEI_TO_EI(_TO_CEI(cl)), s, 746 sz, psenc, &rsz); 747 if (err) { 748 *nresult = -1; 749 goto quit; 750 } 751 s += rsz; 752 sz -= rsz; 753 } 754#endif 755 err = _FUNCNAME(wcrtomb_priv)(_CEI_TO_EI(_TO_CEI(cl)), s, sz, 756 wc, psenc, nresult); 757#if _ENCODING_IS_STATE_DEPENDENT 758 if (err == 0) 759 *nresult += rsz; 760quit: 761#endif 762 if (err == E2BIG) 763 err = EINVAL; 764 _RESTART_END(wcrtomb, _TO_CEI(cl), pspriv, psenc); 765 766 return err; 767} 768 769static int 770/*ARGSUSED*/ 771_FUNCNAME(ctype_wcsrtombs)(void * __restrict cl, char * __restrict s, 772 const wchar_t ** __restrict pwcs, size_t n, 773 void * __restrict pspriv, 774 size_t * __restrict nresult) 775{ 776 _ENCODING_STATE *psenc; 777 _ENCODING_INFO *ei; 778 int err = 0; 779 780 _DIAGASSERT(cl != NULL); 781 782 ei = _CEI_TO_EI(_TO_CEI(cl)); 783 _RESTART_BEGIN(wcsrtombs, _TO_CEI(cl), pspriv, psenc); 784 err = _FUNCNAME(wcsrtombs_priv)(ei, s, pwcs, n, psenc, nresult); 785 _RESTART_END(wcsrtombs, _TO_CEI(cl), pspriv, psenc); 786 787 return err; 788} 789 790static int __used 791/*ARGSUSED*/ 792_FUNCNAME(ctype_wcsnrtombs)(_citrus_ctype_rec_t * __restrict cc, 793 char * __restrict s, 794 const wchar_t ** __restrict pwcs, size_t in, 795 size_t n, void * __restrict pspriv, 796 size_t * __restrict nresult) 797{ 798 void *cl = cc->cc_closure; 799 _ENCODING_STATE *psenc; 800 _ENCODING_INFO *ei; 801 int err = 0; 802 803 _DIAGASSERT(cl != NULL); 804 805 ei = _CEI_TO_EI(_TO_CEI(cl)); 806 _RESTART_BEGIN(wcsnrtombs, _TO_CEI(cl), pspriv, psenc); 807 err = _FUNCNAME(wcsnrtombs_priv)(ei, s, pwcs, in, n, psenc, nresult); 808 _RESTART_END(wcsnrtombs, _TO_CEI(cl), pspriv, psenc); 809 810 return err; 811} 812 813static int 814/*ARGSUSED*/ 815_FUNCNAME(ctype_wcstombs)(void * __restrict cl, char * __restrict s, 816 const wchar_t * __restrict pwcs, size_t n, 817 size_t * __restrict nresult) 818{ 819 _ENCODING_STATE state; 820 _ENCODING_INFO *ei; 821 int err; 822 823 _DIAGASSERT(cl != NULL); 824 825 ei = _CEI_TO_EI(_TO_CEI(cl)); 826 _FUNCNAME(init_state)(ei, &state); 827 err = _FUNCNAME(wcsrtombs_priv)(ei, s, (const wchar_t **)&pwcs, n, 828 &state, nresult); 829 830 return err; 831} 832 833static int 834_FUNCNAME(ctype_wctomb)(void * __restrict cl, char * __restrict s, wchar_t wc, 835 int * __restrict nresult) 836{ 837 _ENCODING_STATE *psenc; 838 _ENCODING_INFO *ei; 839 size_t nr, sz; 840#if _ENCODING_IS_STATE_DEPENDENT 841 size_t rsz = 0; 842#endif 843 int err = 0; 844 845 _DIAGASSERT(cl != NULL); 846 847 ei = _CEI_TO_EI(_TO_CEI(cl)); 848 psenc = &_CEI_TO_STATE(_TO_CEI(cl), wctomb); 849 if (_STATE_NEEDS_EXPLICIT_INIT(psenc)) 850 _FUNCNAME(init_state)(ei, psenc); 851 if (s == NULL) { 852 _FUNCNAME(init_state)(ei, psenc); 853 *nresult = _ENCODING_IS_STATE_DEPENDENT; 854 return 0; 855 } 856 sz = _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl))); 857#if _ENCODING_IS_STATE_DEPENDENT 858 if (wc == L'\0') { 859 /* reset state */ 860 err = _FUNCNAME(put_state_reset)(_CEI_TO_EI(_TO_CEI(cl)), s, 861 sz, psenc, &rsz); 862 if (err) { 863 *nresult = -1; /* XXX */ 864 return 0; 865 } 866 s += rsz; 867 sz -= rsz; 868 } 869#endif 870 err = _FUNCNAME(wcrtomb_priv)(ei, s, sz, wc, psenc, &nr); 871#if _ENCODING_IS_STATE_DEPENDENT 872 if (err == 0) 873 *nresult = (int)(nr + rsz); 874 else 875#endif 876 *nresult = (int)nr; 877 878 return 0; 879} 880 881static int 882/*ARGSUSED*/ 883_FUNCNAME(ctype_btowc)(_citrus_ctype_rec_t * __restrict cc, 884 int c, wint_t * __restrict wcresult) 885{ 886 _ENCODING_STATE state; 887 _ENCODING_INFO *ei; 888 char mb; 889 char const *s; 890 wchar_t wc; 891 size_t nr; 892 int err; 893 894 _DIAGASSERT(cc != NULL && cc->cc_closure != NULL); 895 896 if (c == EOF) { 897 *wcresult = WEOF; 898 return 0; 899 } 900 ei = _CEI_TO_EI(_TO_CEI(cc->cc_closure)); 901 _FUNCNAME(init_state)(ei, &state); 902 mb = (char)(unsigned)c; 903 s = &mb; 904 err = _FUNCNAME(mbrtowc_priv)(ei, &wc, &s, 1, &state, &nr); 905 if (!err && (nr == 0 || nr == 1)) 906 *wcresult = (wint_t)wc; 907 else 908 *wcresult = WEOF; 909 910 return 0; 911} 912 913static int 914/*ARGSUSED*/ 915_FUNCNAME(ctype_wctob)(_citrus_ctype_rec_t * __restrict cc, 916 wint_t wc, int * __restrict cresult) 917{ 918 _ENCODING_STATE state; 919 _ENCODING_INFO *ei; 920 char buf[MB_LEN_MAX]; 921 size_t nr; 922 int err; 923 924 _DIAGASSERT(cc != NULL && cc->cc_closure != NULL); 925 926 if (wc == WEOF) { 927 *cresult = EOF; 928 return 0; 929 } 930 ei = _CEI_TO_EI(_TO_CEI(cc->cc_closure)); 931 _FUNCNAME(init_state)(ei, &state); 932 err = _FUNCNAME(wcrtomb_priv)(ei, buf, _ENCODING_MB_CUR_MAX(ei), 933 (wchar_t)wc, &state, &nr); 934 if (!err && nr == 1) 935 *cresult = buf[0]; 936 else 937 *cresult = EOF; 938 939 return 0; 940} 941