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
126 static void _FUNCNAME(init_state)(_ENCODING_INFO * __restrict,
127 _ENCODING_STATE * __restrict);
128 static void _FUNCNAME(pack_state)(_ENCODING_INFO * __restrict,
129 void * __restrict,
130 const _ENCODING_STATE * __restrict);
131 static void _FUNCNAME(unpack_state)(_ENCODING_INFO * __restrict,
132 _ENCODING_STATE * __restrict,
133 const void * __restrict);
134 #if _ENCODING_IS_STATE_DEPENDENT
135 static 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
155 static 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
174 static 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
194 static __inline int
_FUNCNAME(mbtowc_priv)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
229 static int
_FUNCNAME(mbsrtowcs_priv)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 }
279 bye:
280 if (pwcs)
281 *s = s0;
282
283 *nresult = (size_t)cnt;
284
285 return err;
286 }
287
288 static int
_FUNCNAME(mbsnrtowcs_priv)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 }
340 bye:
341 if (pwcs)
342 *s = s0;
343
344 *nresult = cnt;
345
346 return err;
347 }
348
349 static int
_FUNCNAME(wcsrtombs_priv)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
410 static int
_FUNCNAME(wcsnrtombs_priv)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_) \
476 do { \
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
498 int
_FUNCNAME(ctype_getops)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
514 static int
_FUNCNAME(ctype_init)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
535 static void
_FUNCNAME(ctype_uninit)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
544 static unsigned
545 /*ARGSUSED*/
_FUNCNAME(ctype_get_mb_cur_max)546 _FUNCNAME(ctype_get_mb_cur_max)(void *cl)
547 {
548 return _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl)));
549 }
550
551 static int
_FUNCNAME(ctype_mblen)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
568 static int
_FUNCNAME(ctype_mbrlen)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
593 static int
_FUNCNAME(ctype_mbrtowc)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
618 static int
619 /*ARGSUSED*/
_FUNCNAME(ctype_mbsinit)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
637 static int
_FUNCNAME(ctype_mbsrtowcs)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
657 static int __used
_FUNCNAME(ctype_mbsnrtowcs)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
678 static int
_FUNCNAME(ctype_mbstowcs)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
701 static int
_FUNCNAME(ctype_mbtowc)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
718 static int
_FUNCNAME(ctype_wcrtomb)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;
760 quit:
761 #endif
762 if (err == E2BIG)
763 err = EINVAL;
764 _RESTART_END(wcrtomb, _TO_CEI(cl), pspriv, psenc);
765
766 return err;
767 }
768
769 static int
770 /*ARGSUSED*/
_FUNCNAME(ctype_wcsrtombs)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
790 static int __used
791 /*ARGSUSED*/
_FUNCNAME(ctype_wcsnrtombs)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
813 static int
814 /*ARGSUSED*/
_FUNCNAME(ctype_wcstombs)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
833 static int
_FUNCNAME(ctype_wctomb)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
881 static int
882 /*ARGSUSED*/
_FUNCNAME(ctype_btowc)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
913 static int
914 /*ARGSUSED*/
_FUNCNAME(ctype_wctob)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