1 /* $NetBSD: citrus_ctype_template.h,v 1.36 2013/05/28 16:57:56 joerg 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 keeped 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 keeped 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
122 /* prototypes */
123
124 __BEGIN_DECLS
125 static void _FUNCNAME(init_state)(_ENCODING_INFO * __restrict,
126 _ENCODING_STATE * __restrict);
127 static void _FUNCNAME(pack_state)(_ENCODING_INFO * __restrict,
128 void * __restrict,
129 const _ENCODING_STATE * __restrict);
130 static void _FUNCNAME(unpack_state)(_ENCODING_INFO * __restrict,
131 _ENCODING_STATE * __restrict,
132 const void * __restrict);
133 #if _ENCODING_IS_STATE_DEPENDENT
134 static int _FUNCNAME(put_state_reset)(_ENCODING_INFO * __restrict,
135 char * __restrict, size_t,
136 _ENCODING_STATE * __restrict,
137 size_t * __restrict);
138 #endif
139
140 /*
141 * standard form of mbrtowc_priv.
142 *
143 * note (differences from real mbrtowc):
144 * - 3rd parameter is not "const char *s" but "const char **s".
145 * after the call of the function, *s will point the first byte of
146 * the next character.
147 * - additional 4th parameter is the size of src buffer.
148 * - 5th parameter is unpacked encoding-dependent state structure.
149 * - additional 6th parameter is the storage to be stored
150 * the return value in the real mbrtowc context.
151 * - return value means "errno" in the real mbrtowc context.
152 */
153
154 static int _FUNCNAME(mbrtowc_priv)(_ENCODING_INFO * __restrict,
155 wchar_t * __restrict,
156 const char ** __restrict,
157 size_t, _ENCODING_STATE * __restrict,
158 size_t * __restrict);
159
160 /*
161 * standard form of wcrtomb_priv.
162 *
163 * note (differences from real wcrtomb):
164 * - additional 3th parameter is the size of src buffer.
165 * - 5th parameter is unpacked encoding-dependent state structure.
166 * - additional 6th parameter is the storage to be stored
167 * the return value in the real mbrtowc context.
168 * - return value means "errno" in the real wcrtomb context.
169 * - caller should ensure that 2nd parameter isn't NULL.
170 * (XXX inconsist with mbrtowc_priv)
171 */
172
173 static int _FUNCNAME(wcrtomb_priv)(_ENCODING_INFO * __restrict,
174 char * __restrict, size_t, wchar_t,
175 _ENCODING_STATE * __restrict,
176 size_t * __restrict);
177 __END_DECLS
178
179
180 /*
181 * macros
182 */
183
184 #define _TO_CEI(_cl_) ((_CTYPE_INFO*)(_cl_))
185
186
187 /*
188 * templates
189 */
190
191 /* internal routines */
192
193 static __inline int
_FUNCNAME(mbtowc_priv)194 _FUNCNAME(mbtowc_priv)(_ENCODING_INFO * __restrict ei,
195 wchar_t * __restrict pwc, const char * __restrict s,
196 size_t n, _ENCODING_STATE * __restrict psenc,
197 int * __restrict nresult)
198 {
199 _ENCODING_STATE state;
200 size_t nr;
201 int err = 0;
202
203 _DIAGASSERT(ei != NULL);
204 _DIAGASSERT(psenc != NULL);
205
206 if (s == NULL) {
207 _FUNCNAME(init_state)(ei, psenc);
208 *nresult = _ENCODING_IS_STATE_DEPENDENT;
209 return (0);
210 }
211
212 state = *psenc;
213 err = _FUNCNAME(mbrtowc_priv)(ei, pwc, (const char **)&s, n, psenc, &nr);
214 if (nr == (size_t)-2)
215 err = EILSEQ;
216 if (err) {
217 /* In error case, we should restore the state. */
218 *psenc = state;
219 *nresult = -1;
220 return (err);
221 }
222
223 *nresult = (int)nr;
224
225 return (0);
226 }
227
228 static int
_FUNCNAME(mbsrtowcs_priv)229 _FUNCNAME(mbsrtowcs_priv)(_ENCODING_INFO * __restrict ei,
230 wchar_t * __restrict pwcs,
231 const char ** __restrict s,
232 size_t n, _ENCODING_STATE * __restrict psenc,
233 size_t * __restrict nresult)
234 {
235 int err, cnt;
236 size_t siz;
237 const char *s0;
238 size_t mbcurmax;
239
240 _DIAGASSERT(nresult != 0);
241 _DIAGASSERT(ei != NULL);
242 _DIAGASSERT(psenc != NULL);
243 _DIAGASSERT(s != NULL);
244 _DIAGASSERT(*s != NULL);
245
246 /* if pwcs is NULL, ignore n */
247 if (pwcs == NULL)
248 n = 1; /* arbitrary >0 value */
249
250 err = cnt = 0;
251 s0 = *s; /* to keep *s unchanged for now, use copy instead. */
252 mbcurmax = _ENCODING_MB_CUR_MAX(ei);
253 while (n > 0) {
254 err = _FUNCNAME(mbrtowc_priv)(ei, pwcs, &s0, mbcurmax,
255 psenc, &siz);
256 if (siz == (size_t)-2)
257 err = EILSEQ;
258 if (err) {
259 cnt = -1;
260 goto bye;
261 }
262 switch (siz) {
263 case 0:
264 if (pwcs) {
265 _FUNCNAME(init_state)(ei, psenc);
266 }
267 s0 = 0;
268 goto bye;
269 default:
270 if (pwcs) {
271 pwcs++;
272 n--;
273 }
274 cnt++;
275 break;
276 }
277 }
278 bye:
279 if (pwcs)
280 *s = s0;
281
282 *nresult = (size_t)cnt;
283
284 return err;
285 }
286
287 static int
_FUNCNAME(mbsnrtowcs_priv)288 _FUNCNAME(mbsnrtowcs_priv)(_ENCODING_INFO * __restrict ei,
289 wchar_t * __restrict pwcs,
290 const char ** __restrict s, size_t in,
291 size_t n, _ENCODING_STATE * __restrict psenc,
292 size_t * __restrict nresult)
293 {
294 int err;
295 size_t cnt, siz;
296 const char *s0, *se;
297
298 _DIAGASSERT(nresult != 0);
299 _DIAGASSERT(ei != NULL);
300 _DIAGASSERT(psenc != NULL);
301 _DIAGASSERT(s != NULL);
302 _DIAGASSERT(*s != NULL);
303
304 /* if pwcs is NULL, ignore n */
305 if (pwcs == NULL)
306 n = 1; /* arbitrary >0 value */
307
308 err = 0;
309 cnt = 0;
310 se = *s + in;
311 s0 = *s; /* to keep *s unchanged for now, use copy instead. */
312 while (s0 < se && n > 0) {
313 err = _FUNCNAME(mbrtowc_priv)(ei, pwcs, &s0, se - s0,
314 psenc, &siz);
315 if (err) {
316 cnt = (size_t)-1;
317 goto bye;
318 }
319 if (siz == (size_t)-2) {
320 s0 = se;
321 goto bye;
322 }
323 switch (siz) {
324 case 0:
325 if (pwcs) {
326 _FUNCNAME(init_state)(ei, psenc);
327 }
328 s0 = 0;
329 goto bye;
330 default:
331 if (pwcs) {
332 pwcs++;
333 n--;
334 }
335 cnt++;
336 break;
337 }
338 }
339 bye:
340 if (pwcs)
341 *s = s0;
342
343 *nresult = cnt;
344
345 return err;
346 }
347
348 static int
_FUNCNAME(wcsrtombs_priv)349 _FUNCNAME(wcsrtombs_priv)(_ENCODING_INFO * __restrict ei, char * __restrict s,
350 const wchar_t ** __restrict pwcs,
351 size_t n, _ENCODING_STATE * __restrict psenc,
352 size_t * __restrict nresult)
353 {
354 int err;
355 char buf[MB_LEN_MAX];
356 size_t cnt, siz;
357 const wchar_t* pwcs0;
358 #if _ENCODING_IS_STATE_DEPENDENT
359 _ENCODING_STATE state;
360 #endif
361
362 pwcs0 = *pwcs;
363
364 cnt = 0;
365 if (!s)
366 n = 1;
367
368 while (n > 0) {
369 #if _ENCODING_IS_STATE_DEPENDENT
370 state = *psenc;
371 #endif
372 err = _FUNCNAME(wcrtomb_priv)(ei, buf, sizeof(buf),
373 *pwcs0, psenc, &siz);
374 if (siz == (size_t)-1) {
375 *nresult = siz;
376 return (err);
377 }
378
379 if (s) {
380 if (n < siz) {
381 #if _ENCODING_IS_STATE_DEPENDENT
382 *psenc = state;
383 #endif
384 break;
385 }
386 memcpy(s, buf, siz);
387 s += siz;
388 n -= siz;
389 }
390 cnt += siz;
391 if (!*pwcs0) {
392 if (s) {
393 _FUNCNAME(init_state)(ei, psenc);
394 }
395 pwcs0 = 0;
396 cnt--; /* don't include terminating null */
397 break;
398 }
399 pwcs0++;
400 }
401 if (s)
402 *pwcs = pwcs0;
403
404 *nresult = cnt;
405 return (0);
406 }
407
408 static int
_FUNCNAME(wcsnrtombs_priv)409 _FUNCNAME(wcsnrtombs_priv)(_ENCODING_INFO * __restrict ei, char * __restrict s,
410 const wchar_t ** __restrict pwcs, size_t in,
411 size_t n, _ENCODING_STATE * __restrict psenc,
412 size_t * __restrict nresult)
413 {
414 int cnt = 0, err;
415 char buf[MB_LEN_MAX];
416 size_t siz;
417 const wchar_t* pwcs0;
418 #if _ENCODING_IS_STATE_DEPENDENT
419 _ENCODING_STATE state;
420 #endif
421
422 pwcs0 = *pwcs;
423
424 if (!s)
425 n = 1;
426
427 while (in > 0 && n > 0) {
428 #if _ENCODING_IS_STATE_DEPENDENT
429 state = *psenc;
430 #endif
431 err = _FUNCNAME(wcrtomb_priv)(ei, buf, sizeof(buf),
432 *pwcs0, psenc, &siz);
433 if (siz == (size_t)-1) {
434 *nresult = siz;
435 return (err);
436 }
437
438 if (s) {
439 if (n < siz) {
440 #if _ENCODING_IS_STATE_DEPENDENT
441 *psenc = state;
442 #endif
443 break;
444 }
445 memcpy(s, buf, siz);
446 s += siz;
447 n -= siz;
448 }
449 cnt += siz;
450 if (!*pwcs0) {
451 if (s) {
452 _FUNCNAME(init_state)(ei, psenc);
453 }
454 pwcs0 = 0;
455 cnt--; /* don't include terminating null */
456 break;
457 }
458 pwcs0++;
459 --in;
460 }
461 if (s)
462 *pwcs = pwcs0;
463
464 *nresult = (size_t)cnt;
465 return (0);
466 }
467
468
469 /* ----------------------------------------------------------------------
470 * templates for public functions
471 */
472
473 #define _RESTART_BEGIN(_func_, _cei_, _pspriv_, _pse_) \
474 do { \
475 _ENCODING_STATE _state; \
476 do { \
477 if (_pspriv_ == NULL) { \
478 _pse_ = &_CEI_TO_STATE(_cei_, _func_); \
479 if (_STATE_NEEDS_EXPLICIT_INIT(_pse_)) \
480 _FUNCNAME(init_state)(_CEI_TO_EI(_cei_), \
481 (_pse_)); \
482 } else { \
483 _pse_ = &_state; \
484 _FUNCNAME(unpack_state)(_CEI_TO_EI(_cei_), \
485 _pse_, _pspriv_); \
486 } \
487 } while (/*CONSTCOND*/0)
488
489 #define _RESTART_END(_func_, _cei_, _pspriv_, _pse_) \
490 if (_pspriv_ != NULL) { \
491 _FUNCNAME(pack_state)(_CEI_TO_EI(_cei_), _pspriv_, \
492 _pse_); \
493 } \
494 } while (/*CONSTCOND*/0)
495
496 int
_FUNCNAME(ctype_getops)497 _FUNCNAME(ctype_getops)(_citrus_ctype_ops_rec_t *ops, size_t lenops,
498 uint32_t expected_version)
499 {
500 if (expected_version<_CITRUS_CTYPE_ABI_VERSION || lenops<sizeof(*ops))
501 return (EINVAL);
502
503 memcpy(ops, &_FUNCNAME(ctype_ops), sizeof(_FUNCNAME(ctype_ops)));
504
505 return (0);
506 }
507
508 static int
_FUNCNAME(ctype_init)509 _FUNCNAME(ctype_init)(void ** __restrict cl,
510 void * __restrict var, size_t lenvar, size_t lenps)
511 {
512 _CTYPE_INFO *cei;
513
514 _DIAGASSERT(cl != NULL);
515
516 /* sanity check to avoid overruns */
517 if (sizeof(_ENCODING_STATE) > lenps)
518 return (EINVAL);
519
520 cei = calloc(1, sizeof(_CTYPE_INFO));
521 if (cei == NULL)
522 return (ENOMEM);
523
524 *cl = (void *)cei;
525
526 return _FUNCNAME(encoding_module_init)(_CEI_TO_EI(cei), var, lenvar);
527 }
528
529 static void
_FUNCNAME(ctype_uninit)530 _FUNCNAME(ctype_uninit)(void *cl)
531 {
532 if (cl) {
533 _FUNCNAME(encoding_module_uninit)(_CEI_TO_EI(_TO_CEI(cl)));
534 free(cl);
535 }
536 }
537
538 static unsigned
539 /*ARGSUSED*/
_FUNCNAME(ctype_get_mb_cur_max)540 _FUNCNAME(ctype_get_mb_cur_max)(void *cl)
541 {
542 return _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl)));
543 }
544
545 static int
_FUNCNAME(ctype_mblen)546 _FUNCNAME(ctype_mblen)(void * __restrict cl,
547 const char * __restrict s, size_t n,
548 int * __restrict nresult)
549 {
550 _ENCODING_STATE *psenc;
551 _ENCODING_INFO *ei;
552
553 _DIAGASSERT(cl != NULL);
554
555 psenc = &_CEI_TO_STATE(_TO_CEI(cl), mblen);
556 ei = _CEI_TO_EI(_TO_CEI(cl));
557 if (_STATE_NEEDS_EXPLICIT_INIT(psenc))
558 _FUNCNAME(init_state)(ei, psenc);
559 return _FUNCNAME(mbtowc_priv)(ei, NULL, s, n, psenc, nresult);
560 }
561
562 static int
_FUNCNAME(ctype_mbrlen)563 _FUNCNAME(ctype_mbrlen)(void * __restrict cl, const char * __restrict s,
564 size_t n, void * __restrict pspriv,
565 size_t * __restrict nresult)
566 {
567 _ENCODING_STATE *psenc;
568 _ENCODING_INFO *ei;
569 int err = 0;
570
571 _DIAGASSERT(cl != NULL);
572
573 ei = _CEI_TO_EI(_TO_CEI(cl));
574 _RESTART_BEGIN(mbrlen, _TO_CEI(cl), pspriv, psenc);
575 if (s == NULL) {
576 _FUNCNAME(init_state)(ei, psenc);
577 *nresult = 0;
578 } else {
579 err = _FUNCNAME(mbrtowc_priv)(ei, NULL, (const char **)&s, n,
580 (void *)psenc, nresult);
581 }
582 _RESTART_END(mbrlen, _TO_CEI(cl), pspriv, psenc);
583
584 return (err);
585 }
586
587 static int
_FUNCNAME(ctype_mbrtowc)588 _FUNCNAME(ctype_mbrtowc)(void * __restrict cl, wchar_t * __restrict pwc,
589 const char * __restrict s, size_t n,
590 void * __restrict pspriv, size_t * __restrict nresult)
591 {
592 _ENCODING_STATE *psenc;
593 _ENCODING_INFO *ei;
594 int err = 0;
595
596 _DIAGASSERT(cl != NULL);
597
598 ei = _CEI_TO_EI(_TO_CEI(cl));
599 _RESTART_BEGIN(mbrtowc, _TO_CEI(cl), pspriv, psenc);
600 if (s == NULL) {
601 _FUNCNAME(init_state)(ei, psenc);
602 *nresult = 0;
603 } else {
604 err = _FUNCNAME(mbrtowc_priv)(ei, pwc, (const char **)&s, n,
605 (void *)psenc, nresult);
606 }
607 _RESTART_END(mbrtowc, _TO_CEI(cl), pspriv, psenc);
608
609 return (err);
610 }
611
612 static int
613 /*ARGSUSED*/
_FUNCNAME(ctype_mbsinit)614 _FUNCNAME(ctype_mbsinit)(void * __restrict cl, const void * __restrict pspriv,
615 int * __restrict nresult)
616 {
617 _ENCODING_STATE state;
618
619 if (pspriv == NULL) {
620 *nresult = 1;
621 return (0);
622 }
623
624 _FUNCNAME(unpack_state)(_CEI_TO_EI(_TO_CEI(cl)), &state, pspriv);
625
626 *nresult = (state.chlen == 0); /* XXX: FIXME */
627
628 return (0);
629 }
630
631 static int
_FUNCNAME(ctype_mbsrtowcs)632 _FUNCNAME(ctype_mbsrtowcs)(void * __restrict cl, wchar_t * __restrict pwcs,
633 const char ** __restrict s, size_t n,
634 void * __restrict pspriv,
635 size_t * __restrict nresult)
636 {
637 _ENCODING_STATE *psenc;
638 _ENCODING_INFO *ei;
639 int err = 0;
640
641 _DIAGASSERT(cl != NULL);
642
643 ei = _CEI_TO_EI(_TO_CEI(cl));
644 _RESTART_BEGIN(mbsrtowcs, _TO_CEI(cl), pspriv, psenc);
645 err = _FUNCNAME(mbsrtowcs_priv)(ei, pwcs, s, n, psenc, nresult);
646 _RESTART_END(mbsrtowcs, _TO_CEI(cl), pspriv, psenc);
647
648 return (err);
649 }
650
651 static int __used
_FUNCNAME(ctype_mbsnrtowcs)652 _FUNCNAME(ctype_mbsnrtowcs)(_citrus_ctype_rec_t * __restrict cc, wchar_t * __restrict pwcs,
653 const char ** __restrict s, size_t in, size_t n,
654 void * __restrict pspriv,
655 size_t * __restrict nresult)
656 {
657 void *cl = cc->cc_closure;
658 _ENCODING_STATE *psenc;
659 _ENCODING_INFO *ei;
660 int err = 0;
661
662 _DIAGASSERT(cl != NULL);
663
664 ei = _CEI_TO_EI(_TO_CEI(cl));
665 _RESTART_BEGIN(mbsnrtowcs, _TO_CEI(cl), pspriv, psenc);
666 err = _FUNCNAME(mbsnrtowcs_priv)(ei, pwcs, s, in, n, psenc, nresult);
667 _RESTART_END(mbsnrtowcs, _TO_CEI(cl), pspriv, psenc);
668
669 return (err);
670 }
671
672 static int
_FUNCNAME(ctype_mbstowcs)673 _FUNCNAME(ctype_mbstowcs)(void * __restrict cl, wchar_t * __restrict pwcs,
674 const char * __restrict s, size_t n,
675 size_t * __restrict nresult)
676 {
677 int err;
678 _ENCODING_STATE state;
679 _ENCODING_INFO *ei;
680
681 _DIAGASSERT(cl != NULL);
682
683 ei = _CEI_TO_EI(_TO_CEI(cl));
684 _FUNCNAME(init_state)(ei, &state);
685 err = _FUNCNAME(mbsrtowcs_priv)(ei, pwcs, (const char **)&s, n,
686 &state, nresult);
687 if (*nresult == (size_t)-2) {
688 err = EILSEQ;
689 *nresult = (size_t)-1;
690 }
691
692 return (err);
693 }
694
695 static int
_FUNCNAME(ctype_mbtowc)696 _FUNCNAME(ctype_mbtowc)(void * __restrict cl, wchar_t * __restrict pwc,
697 const char * __restrict s, size_t n,
698 int * __restrict nresult)
699 {
700 _ENCODING_STATE *psenc;
701 _ENCODING_INFO *ei;
702
703 _DIAGASSERT(cl != NULL);
704
705 psenc = &_CEI_TO_STATE(_TO_CEI(cl), mbtowc);
706 ei = _CEI_TO_EI(_TO_CEI(cl));
707 if (_STATE_NEEDS_EXPLICIT_INIT(psenc))
708 _FUNCNAME(init_state)(ei, psenc);
709 return _FUNCNAME(mbtowc_priv)(ei, pwc, s, n, psenc, nresult);
710 }
711
712 static int
_FUNCNAME(ctype_wcrtomb)713 _FUNCNAME(ctype_wcrtomb)(void * __restrict cl, char * __restrict s, wchar_t wc,
714 void * __restrict pspriv, size_t * __restrict nresult)
715 {
716 _ENCODING_STATE *psenc;
717 char buf[MB_LEN_MAX];
718 int err = 0;
719 size_t sz;
720 #if _ENCODING_IS_STATE_DEPENDENT
721 size_t rsz = 0;
722 #endif
723
724 _DIAGASSERT(cl != NULL);
725
726 if (s == NULL) {
727 /*
728 * use internal buffer.
729 */
730 s = buf;
731 wc = L'\0'; /* SUSv3 */
732 }
733
734 _RESTART_BEGIN(wcrtomb, _TO_CEI(cl), pspriv, psenc);
735 sz = _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl)));
736 #if _ENCODING_IS_STATE_DEPENDENT
737 if (wc == L'\0') {
738 /* reset state */
739 err = _FUNCNAME(put_state_reset)(_CEI_TO_EI(_TO_CEI(cl)), s,
740 sz, psenc, &rsz);
741 if (err) {
742 *nresult = -1;
743 goto quit;
744 }
745 s += rsz;
746 sz -= rsz;
747 }
748 #endif
749 err = _FUNCNAME(wcrtomb_priv)(_CEI_TO_EI(_TO_CEI(cl)), s, sz,
750 wc, psenc, nresult);
751 #if _ENCODING_IS_STATE_DEPENDENT
752 if (err == 0)
753 *nresult += rsz;
754 quit:
755 #endif
756 if (err == E2BIG)
757 err = EINVAL;
758 _RESTART_END(wcrtomb, _TO_CEI(cl), pspriv, psenc);
759
760 return err;
761 }
762
763 static int
764 /*ARGSUSED*/
_FUNCNAME(ctype_wcsrtombs)765 _FUNCNAME(ctype_wcsrtombs)(void * __restrict cl, char * __restrict s,
766 const wchar_t ** __restrict pwcs, size_t n,
767 void * __restrict pspriv,
768 size_t * __restrict nresult)
769 {
770 _ENCODING_STATE *psenc;
771 _ENCODING_INFO *ei;
772 int err = 0;
773
774 _DIAGASSERT(cl != NULL);
775
776 ei = _CEI_TO_EI(_TO_CEI(cl));
777 _RESTART_BEGIN(wcsrtombs, _TO_CEI(cl), pspriv, psenc);
778 err = _FUNCNAME(wcsrtombs_priv)(ei, s, pwcs, n, psenc, nresult);
779 _RESTART_END(wcsrtombs, _TO_CEI(cl), pspriv, psenc);
780
781 return err;
782 }
783
784 static int __used
785 /*ARGSUSED*/
_FUNCNAME(ctype_wcsnrtombs)786 _FUNCNAME(ctype_wcsnrtombs)(_citrus_ctype_rec_t * __restrict cc,
787 char * __restrict s,
788 const wchar_t ** __restrict pwcs, size_t in,
789 size_t n, void * __restrict pspriv,
790 size_t * __restrict nresult)
791 {
792 void *cl = cc->cc_closure;
793 _ENCODING_STATE *psenc;
794 _ENCODING_INFO *ei;
795 int err = 0;
796
797 _DIAGASSERT(cl != NULL);
798
799 ei = _CEI_TO_EI(_TO_CEI(cl));
800 _RESTART_BEGIN(wcsnrtombs, _TO_CEI(cl), pspriv, psenc);
801 err = _FUNCNAME(wcsnrtombs_priv)(ei, s, pwcs, in, n, psenc, nresult);
802 _RESTART_END(wcsnrtombs, _TO_CEI(cl), pspriv, psenc);
803
804 return err;
805 }
806
807 static int
808 /*ARGSUSED*/
_FUNCNAME(ctype_wcstombs)809 _FUNCNAME(ctype_wcstombs)(void * __restrict cl, char * __restrict s,
810 const wchar_t * __restrict pwcs, size_t n,
811 size_t * __restrict nresult)
812 {
813 _ENCODING_STATE state;
814 _ENCODING_INFO *ei;
815 int err;
816
817 _DIAGASSERT(cl != NULL);
818
819 ei = _CEI_TO_EI(_TO_CEI(cl));
820 _FUNCNAME(init_state)(ei, &state);
821 err = _FUNCNAME(wcsrtombs_priv)(ei, s, (const wchar_t **)&pwcs, n,
822 &state, nresult);
823
824 return err;
825 }
826
827 static int
_FUNCNAME(ctype_wctomb)828 _FUNCNAME(ctype_wctomb)(void * __restrict cl, char * __restrict s, wchar_t wc,
829 int * __restrict nresult)
830 {
831 _ENCODING_STATE *psenc;
832 _ENCODING_INFO *ei;
833 size_t nr, sz;
834 #if _ENCODING_IS_STATE_DEPENDENT
835 size_t rsz = 0;
836 #endif
837 int err = 0;
838
839 _DIAGASSERT(cl != NULL);
840
841 ei = _CEI_TO_EI(_TO_CEI(cl));
842 psenc = &_CEI_TO_STATE(_TO_CEI(cl), wctomb);
843 if (_STATE_NEEDS_EXPLICIT_INIT(psenc))
844 _FUNCNAME(init_state)(ei, psenc);
845 if (s == NULL) {
846 _FUNCNAME(init_state)(ei, psenc);
847 *nresult = _ENCODING_IS_STATE_DEPENDENT;
848 return 0;
849 }
850 sz = _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl)));
851 #if _ENCODING_IS_STATE_DEPENDENT
852 if (wc == L'\0') {
853 /* reset state */
854 err = _FUNCNAME(put_state_reset)(_CEI_TO_EI(_TO_CEI(cl)), s,
855 sz, psenc, &rsz);
856 if (err) {
857 *nresult = -1; /* XXX */
858 return 0;
859 }
860 s += rsz;
861 sz -= rsz;
862 }
863 #endif
864 err = _FUNCNAME(wcrtomb_priv)(ei, s, sz, wc, psenc, &nr);
865 #if _ENCODING_IS_STATE_DEPENDENT
866 if (err == 0)
867 *nresult = (int)(nr + rsz);
868 else
869 #endif
870 *nresult = (int)nr;
871
872 return 0;
873 }
874
875 static int
876 /*ARGSUSED*/
_FUNCNAME(ctype_btowc)877 _FUNCNAME(ctype_btowc)(_citrus_ctype_rec_t * __restrict cc,
878 int c, wint_t * __restrict wcresult)
879 {
880 _ENCODING_STATE state;
881 _ENCODING_INFO *ei;
882 char mb;
883 char const *s;
884 wchar_t wc;
885 size_t nr;
886 int err;
887
888 _DIAGASSERT(cc != NULL && cc->cc_closure != NULL);
889
890 if (c == EOF) {
891 *wcresult = WEOF;
892 return 0;
893 }
894 ei = _CEI_TO_EI(_TO_CEI(cc->cc_closure));
895 _FUNCNAME(init_state)(ei, &state);
896 mb = (char)(unsigned)c;
897 s = &mb;
898 err = _FUNCNAME(mbrtowc_priv)(ei, &wc, &s, 1, &state, &nr);
899 if (!err && (nr == 0 || nr == 1))
900 *wcresult = (wint_t)wc;
901 else
902 *wcresult = WEOF;
903
904 return 0;
905 }
906
907 static int
908 /*ARGSUSED*/
_FUNCNAME(ctype_wctob)909 _FUNCNAME(ctype_wctob)(_citrus_ctype_rec_t * __restrict cc,
910 wint_t wc, int * __restrict cresult)
911 {
912 _ENCODING_STATE state;
913 _ENCODING_INFO *ei;
914 char buf[MB_LEN_MAX];
915 size_t nr;
916 int err;
917
918 _DIAGASSERT(cc != NULL && cc->cc_closure != NULL);
919
920 if (wc == WEOF) {
921 *cresult = EOF;
922 return 0;
923 }
924 ei = _CEI_TO_EI(_TO_CEI(cc->cc_closure));
925 _FUNCNAME(init_state)(ei, &state);
926 err = _FUNCNAME(wcrtomb_priv)(ei, buf, _ENCODING_MB_CUR_MAX(ei),
927 (wchar_t)wc, &state, &nr);
928 if (!err && nr == 1)
929 *cresult = buf[0];
930 else
931 *cresult = EOF;
932
933 return 0;
934 }
935