9231958113ab56c3dbe00305a94f99f6a48cd7a6
[dragonfly.git] / lib / libc / citrus / citrus_ctype_template.h
1 /* $NetBSD: citrus_ctype_template.h,v 1.35 2008/02/09 14:56:20 junyoung Exp $ */
2 /* $DragonFly: src/lib/libc/citrus/citrus_ctype_template.h,v 1.2 2008/04/10 10:21:01 hasso Exp $ */
3
4
5 /*-
6  * Copyright (c)2002 Citrus Project,
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30
31 /*-
32  * Copyright (c) 1993
33  *      The Regents of the University of California.  All rights reserved.
34  *
35  * This code is derived from software contributed to Berkeley by
36  * Paul Borman at Krystal Technologies.
37  *
38  * Redistribution and use in source and binary forms, with or without
39  * modification, are permitted provided that the following conditions
40  * are met:
41  * 1. Redistributions of source code must retain the above copyright
42  *    notice, this list of conditions and the following disclaimer.
43  * 2. Redistributions in binary form must reproduce the above copyright
44  *    notice, this list of conditions and the following disclaimer in the
45  *    documentation and/or other materials provided with the distribution.
46  * 3. Neither the name of the University nor the names of its contributors
47  *    may be used to endorse or promote products derived from this software
48  *    without specific prior written permission.
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60  * SUCH DAMAGE.
61  */
62
63
64 /*
65  * CAUTION: THIS IS NOT STANDALONE FILE
66  *
67  * function templates of ctype encoding handler for each encodings.
68  *
69  * you need to define the macros below:
70  *
71  *   _FUNCNAME(method) :
72  *     It should convine the real function name for the method.
73  *      e.g. _FUNCNAME(mbrtowc) should be expanded to
74  *             _EUC_ctype_mbrtowc
75  *           for EUC locale.
76  *
77  *   _CEI_TO_STATE(cei, method) :
78  *     It should be expanded to the pointer of the method-internal state
79  *     structures.
80  *     e.g. _CEI_TO_STATE(cei, mbrtowc) might be expanded to
81  *             (cei)->states.s_mbrtowc
82  *     This structure may use if the function is called as
83  *           mbrtowc(&wc, s, n, NULL);
84  *     Such individual structures are needed by:
85  *           mblen
86  *           mbrlen
87  *           mbrtowc
88  *           mbtowc
89  *           mbsrtowcs
90  *           wcrtomb
91  *           wcsrtombs
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
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
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
288 static int
289 _FUNCNAME(wcsrtombs_priv)(_ENCODING_INFO * __restrict ei, char * __restrict s,
290                           const wchar_t ** __restrict pwcs,
291                           size_t n, _ENCODING_STATE * __restrict psenc,
292                           size_t * __restrict nresult)
293 {
294         int cnt = 0, err;
295         char buf[MB_LEN_MAX];
296         size_t siz;
297         const wchar_t* pwcs0;
298 #if _ENCODING_IS_STATE_DEPENDENT
299         _ENCODING_STATE state;
300 #endif
301
302         pwcs0 = *pwcs;
303
304         if (!s)
305                 n = 1;
306
307         while (n > 0) {
308 #if _ENCODING_IS_STATE_DEPENDENT
309                 state = *psenc;
310 #endif
311                 err = _FUNCNAME(wcrtomb_priv)(ei, buf, sizeof(buf),
312                                               *pwcs0, psenc, &siz);
313                 if (siz == (size_t)-1) {
314                         *nresult = siz;
315                         return (err);
316                 }
317
318                 if (s) {
319                         if (n < siz) {
320 #if _ENCODING_IS_STATE_DEPENDENT
321                                 *psenc = state;
322 #endif
323                                 break;
324                         }
325                         memcpy(s, buf, siz);
326                         s += siz;
327                         n -= siz;
328                 }
329                 cnt += siz;
330                 if (!*pwcs0) {
331                         if (s) {
332                                 _FUNCNAME(init_state)(ei, psenc);
333                         }
334                         pwcs0 = 0;
335                         cnt--; /* don't include terminating null */
336                         break;
337                 }
338                 pwcs0++;
339         }
340         if (s)
341                 *pwcs = pwcs0;
342
343         *nresult = (size_t)cnt;
344         return (0);
345 }
346
347
348 /* ----------------------------------------------------------------------
349  * templates for public functions
350  */
351
352 #define _RESTART_BEGIN(_func_, _cei_, _pspriv_, _pse_)                  \
353 do {                                                                    \
354         _ENCODING_STATE _state;                                         \
355         do {                                                            \
356                 if (_pspriv_ == NULL) {                                 \
357                         _pse_ = &_CEI_TO_STATE(_cei_, _func_);          \
358                         if (_STATE_NEEDS_EXPLICIT_INIT(_pse_))          \
359                             _FUNCNAME(init_state)(_CEI_TO_EI(_cei_),    \
360                                                         (_pse_));       \
361                 } else {                                                \
362                         _pse_ = &_state;                                \
363                         _FUNCNAME(unpack_state)(_CEI_TO_EI(_cei_),      \
364                                                 _pse_, _pspriv_);       \
365                 }                                                       \
366         } while (/*CONSTCOND*/0)
367
368 #define _RESTART_END(_func_, _cei_, _pspriv_, _pse_)                    \
369         if (_pspriv_ != NULL) {                                         \
370                 _FUNCNAME(pack_state)(_CEI_TO_EI(_cei_), _pspriv_,      \
371                                       _pse_);                           \
372         }                                                               \
373 } while (/*CONSTCOND*/0)
374
375 int
376 _FUNCNAME(ctype_getops)(_citrus_ctype_ops_rec_t *ops, size_t lenops,
377                         uint32_t expected_version)
378 {
379         if (expected_version<_CITRUS_CTYPE_ABI_VERSION || lenops<sizeof(*ops))
380                 return (EINVAL);
381
382         memcpy(ops, &_FUNCNAME(ctype_ops), sizeof(_FUNCNAME(ctype_ops)));
383
384         return (0);
385 }
386
387 static int
388 _FUNCNAME(ctype_init)(void ** __restrict cl,
389                       void * __restrict var, size_t lenvar, size_t lenps)
390 {
391         _CTYPE_INFO *cei;
392
393         _DIAGASSERT(cl != NULL);
394
395         /* sanity check to avoid overruns */
396         if (sizeof(_ENCODING_STATE) > lenps)
397                 return (EINVAL);
398
399         cei = calloc(1, sizeof(_CTYPE_INFO));
400         if (cei == NULL)
401                 return (ENOMEM);
402
403         *cl = (void *)cei;
404
405         return _FUNCNAME(encoding_module_init)(_CEI_TO_EI(cei), var, lenvar);
406 }
407
408 static void
409 _FUNCNAME(ctype_uninit)(void *cl)
410 {
411         if (cl) {
412                 _FUNCNAME(encoding_module_uninit)(_CEI_TO_EI(_TO_CEI(cl)));
413                 free(cl);
414         }
415 }
416
417 static unsigned
418 /*ARGSUSED*/
419 _FUNCNAME(ctype_get_mb_cur_max)(void *cl)
420 {
421         return _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl)));
422 }
423
424 static int
425 _FUNCNAME(ctype_mblen)(void * __restrict cl,
426                        const char * __restrict s, size_t n,
427                        int * __restrict nresult)
428 {
429         _ENCODING_STATE *psenc;
430         _ENCODING_INFO *ei;
431
432         _DIAGASSERT(cl != NULL);
433
434         psenc = &_CEI_TO_STATE(_TO_CEI(cl), mblen);
435         ei = _CEI_TO_EI(_TO_CEI(cl));
436         if (_STATE_NEEDS_EXPLICIT_INIT(psenc))
437                 _FUNCNAME(init_state)(ei, psenc);
438         return _FUNCNAME(mbtowc_priv)(ei, NULL, s, n, psenc, nresult);
439 }
440
441 static int
442 _FUNCNAME(ctype_mbrlen)(void * __restrict cl, const char * __restrict s,
443                         size_t n, void * __restrict pspriv,
444                         size_t * __restrict nresult)
445 {
446         _ENCODING_STATE *psenc;
447         _ENCODING_INFO *ei;
448         int err = 0;
449
450         _DIAGASSERT(cl != NULL);
451
452         ei = _CEI_TO_EI(_TO_CEI(cl));
453         _RESTART_BEGIN(mbrlen, _TO_CEI(cl), pspriv, psenc);
454         if (s == NULL) {
455                 _FUNCNAME(init_state)(ei, psenc);
456                 *nresult = 0;
457         } else {
458                 err = _FUNCNAME(mbrtowc_priv)(ei, NULL, (const char **)&s, n,
459                     (void *)psenc, nresult);
460         }
461         _RESTART_END(mbrlen, _TO_CEI(cl), pspriv, psenc);
462
463         return (err);
464 }
465
466 static int
467 _FUNCNAME(ctype_mbrtowc)(void * __restrict cl, wchar_t * __restrict pwc,
468                          const char * __restrict s, size_t n,
469                          void * __restrict pspriv, size_t * __restrict nresult)
470 {
471         _ENCODING_STATE *psenc;
472         _ENCODING_INFO *ei;
473         int err = 0;
474
475         _DIAGASSERT(cl != NULL);
476
477         ei = _CEI_TO_EI(_TO_CEI(cl));
478         _RESTART_BEGIN(mbrtowc, _TO_CEI(cl), pspriv, psenc);
479         if (s == NULL) {
480                 _FUNCNAME(init_state)(ei, psenc);
481                 *nresult = 0;
482         } else {
483                 err = _FUNCNAME(mbrtowc_priv)(ei, pwc, (const char **)&s, n,
484                     (void *)psenc, nresult);
485         }
486         _RESTART_END(mbrtowc, _TO_CEI(cl), pspriv, psenc);
487
488         return (err);
489 }
490
491 static int
492 /*ARGSUSED*/
493 _FUNCNAME(ctype_mbsinit)(void * __restrict cl, const void * __restrict pspriv,
494                          int * __restrict nresult)
495 {
496         _ENCODING_STATE state;
497
498         if (pspriv == NULL) {
499                 *nresult = 1;
500                 return (0);
501         }
502
503         _FUNCNAME(unpack_state)(_CEI_TO_EI(_TO_CEI(cl)), &state, pspriv);
504
505         *nresult = (state.chlen == 0); /* XXX: FIXME */
506
507         return (0);
508 }
509
510 static int
511 _FUNCNAME(ctype_mbsrtowcs)(void * __restrict cl, wchar_t * __restrict pwcs,
512                            const char ** __restrict s, size_t n,
513                            void * __restrict pspriv,
514                            size_t * __restrict nresult)
515 {
516         _ENCODING_STATE *psenc;
517         _ENCODING_INFO *ei;
518         int err = 0;
519
520         _DIAGASSERT(cl != NULL);
521
522         ei = _CEI_TO_EI(_TO_CEI(cl));
523         _RESTART_BEGIN(mbsrtowcs, _TO_CEI(cl), pspriv, psenc);
524         err = _FUNCNAME(mbsrtowcs_priv)(ei, pwcs, s, n, psenc, nresult);
525         _RESTART_END(mbsrtowcs, _TO_CEI(cl), pspriv, psenc);
526
527         return (err);
528 }
529
530 static int
531 _FUNCNAME(ctype_mbstowcs)(void * __restrict cl, wchar_t * __restrict pwcs,
532                           const char * __restrict s, size_t n,
533                           size_t * __restrict nresult)
534 {
535         int err;
536         _ENCODING_STATE state;
537         _ENCODING_INFO *ei;
538
539         _DIAGASSERT(cl != NULL);
540
541         ei = _CEI_TO_EI(_TO_CEI(cl));
542         _FUNCNAME(init_state)(ei, &state);
543         err = _FUNCNAME(mbsrtowcs_priv)(ei, pwcs, (const char **)&s, n,
544                                         &state, nresult);
545         if (*nresult == (size_t)-2) {
546                 err = EILSEQ;
547                 *nresult = (size_t)-1;
548         }
549
550         return (err);
551 }
552
553 static int
554 _FUNCNAME(ctype_mbtowc)(void * __restrict cl, wchar_t * __restrict pwc,
555                         const char * __restrict s, size_t n,
556                         int * __restrict nresult)
557 {
558         _ENCODING_STATE *psenc;
559         _ENCODING_INFO *ei;
560
561         _DIAGASSERT(cl != NULL);
562
563         psenc = &_CEI_TO_STATE(_TO_CEI(cl), mbtowc);
564         ei = _CEI_TO_EI(_TO_CEI(cl));
565         if (_STATE_NEEDS_EXPLICIT_INIT(psenc))
566                 _FUNCNAME(init_state)(ei, psenc);
567         return _FUNCNAME(mbtowc_priv)(ei, pwc, s, n, psenc, nresult);
568 }
569
570 static int
571 _FUNCNAME(ctype_wcrtomb)(void * __restrict cl, char * __restrict s, wchar_t wc,
572                          void * __restrict pspriv, size_t * __restrict nresult)
573 {
574         _ENCODING_STATE *psenc;
575         char buf[MB_LEN_MAX];
576         int err = 0;
577         size_t sz;
578 #if _ENCODING_IS_STATE_DEPENDENT
579         size_t rsz = 0;
580 #endif
581
582         _DIAGASSERT(cl != NULL);
583
584         if (s == NULL) {
585                 /*
586                  * use internal buffer.
587                  */
588                 s = buf;
589                 wc = L'\0'; /* SUSv3 */
590         }
591
592         _RESTART_BEGIN(wcrtomb, _TO_CEI(cl), pspriv, psenc);
593         sz = _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl)));
594 #if _ENCODING_IS_STATE_DEPENDENT
595         if (wc == L'\0') {
596                 /* reset state */
597                 err = _FUNCNAME(put_state_reset)(_CEI_TO_EI(_TO_CEI(cl)), s,
598                                                  sz, psenc, &rsz);
599                 if (err) {
600                         *nresult = -1;
601                         goto quit;
602                 }
603                 s += rsz;
604                 sz -= rsz;
605         }
606 #endif
607         err = _FUNCNAME(wcrtomb_priv)(_CEI_TO_EI(_TO_CEI(cl)), s, sz,
608                                       wc, psenc, nresult);
609 #if _ENCODING_IS_STATE_DEPENDENT
610         if (err == 0)
611                 *nresult += rsz;
612 quit:
613 #endif
614         if (err == E2BIG)
615                 err = EINVAL;
616         _RESTART_END(wcrtomb, _TO_CEI(cl), pspriv, psenc);
617
618         return err;
619 }
620
621 static int
622 /*ARGSUSED*/
623 _FUNCNAME(ctype_wcsrtombs)(void * __restrict cl, char * __restrict s,
624                            const wchar_t ** __restrict pwcs, size_t n,
625                            void * __restrict pspriv,
626                            size_t * __restrict nresult)
627 {
628         _ENCODING_STATE *psenc;
629         _ENCODING_INFO *ei;
630         int err = 0;
631
632         _DIAGASSERT(cl != NULL);
633
634         ei = _CEI_TO_EI(_TO_CEI(cl));
635         _RESTART_BEGIN(wcsrtombs, _TO_CEI(cl), pspriv, psenc);
636         err = _FUNCNAME(wcsrtombs_priv)(ei, s, pwcs, n, psenc, nresult);
637         _RESTART_END(wcsrtombs, _TO_CEI(cl), pspriv, psenc);
638
639         return err;
640 }
641
642 static int
643 /*ARGSUSED*/
644 _FUNCNAME(ctype_wcstombs)(void * __restrict cl, char * __restrict s,
645                           const wchar_t * __restrict pwcs, size_t n,
646                           size_t * __restrict nresult)
647 {
648         _ENCODING_STATE state;
649         _ENCODING_INFO *ei;
650         int err;
651
652         _DIAGASSERT(cl != NULL);
653
654         ei = _CEI_TO_EI(_TO_CEI(cl));
655         _FUNCNAME(init_state)(ei, &state);
656         err = _FUNCNAME(wcsrtombs_priv)(ei, s, (const wchar_t **)&pwcs, n,
657                                         &state, nresult);
658
659         return err;
660 }
661
662 static int
663 _FUNCNAME(ctype_wctomb)(void * __restrict cl, char * __restrict s, wchar_t wc,
664                         int * __restrict nresult)
665 {
666         _ENCODING_STATE *psenc;
667         _ENCODING_INFO *ei;
668         size_t nr, sz;
669 #if _ENCODING_IS_STATE_DEPENDENT
670         size_t rsz = 0;
671 #endif
672         int err = 0;
673
674         _DIAGASSERT(cl != NULL);
675
676         ei = _CEI_TO_EI(_TO_CEI(cl));
677         psenc = &_CEI_TO_STATE(_TO_CEI(cl), wctomb);
678         if (_STATE_NEEDS_EXPLICIT_INIT(psenc))
679                 _FUNCNAME(init_state)(ei, psenc);
680         if (s == NULL) {
681                 _FUNCNAME(init_state)(ei, psenc);
682                 *nresult = _ENCODING_IS_STATE_DEPENDENT;
683                 return 0;
684         }
685         sz = _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl)));
686 #if _ENCODING_IS_STATE_DEPENDENT
687         if (wc == L'\0') {
688                 /* reset state */
689                 err = _FUNCNAME(put_state_reset)(_CEI_TO_EI(_TO_CEI(cl)), s,
690                                                  sz, psenc, &rsz);
691                 if (err) {
692                         *nresult = -1; /* XXX */
693                         return 0;
694                 }
695                 s += rsz;
696                 sz -= rsz;
697         }
698 #endif
699         err = _FUNCNAME(wcrtomb_priv)(ei, s, sz, wc, psenc, &nr);
700 #if _ENCODING_IS_STATE_DEPENDENT
701         if (err == 0)
702                 *nresult = (int)(nr + rsz);
703         else
704 #endif
705         *nresult = (int)nr;
706
707         return 0;
708 }
709
710 static int
711 /*ARGSUSED*/
712 _FUNCNAME(ctype_btowc)(_citrus_ctype_rec_t * __restrict cc,
713                        int c, wint_t * __restrict wcresult)
714 {
715         _ENCODING_STATE state;
716         _ENCODING_INFO *ei;
717         char mb;
718         char const *s;
719         wchar_t wc;
720         size_t nr;
721         int err;
722
723         _DIAGASSERT(cc != NULL && cc->cc_closure != NULL);
724
725         if (c == EOF) {
726                 *wcresult = WEOF;
727                 return 0;
728         }
729         ei = _CEI_TO_EI(_TO_CEI(cc->cc_closure));
730         _FUNCNAME(init_state)(ei, &state);
731         mb = (char)(unsigned)c;
732         s = &mb;
733         err = _FUNCNAME(mbrtowc_priv)(ei, &wc, &s, 1, &state, &nr);
734         if (!err && (nr == 0 || nr == 1))
735                 *wcresult = (wint_t)wc;
736         else
737                 *wcresult = WEOF;
738
739         return 0;
740 }
741
742 static int
743 /*ARGSUSED*/
744 _FUNCNAME(ctype_wctob)(_citrus_ctype_rec_t * __restrict cc,
745                        wint_t wc, int * __restrict cresult)
746 {
747         _ENCODING_STATE state;
748         _ENCODING_INFO *ei;
749         char buf[MB_LEN_MAX];
750         size_t nr;
751         int err;
752
753         _DIAGASSERT(cc != NULL && cc->cc_closure != NULL);
754
755         if (wc == WEOF) {
756                 *cresult = EOF;
757                 return 0;
758         }
759         ei = _CEI_TO_EI(_TO_CEI(cc->cc_closure));
760         _FUNCNAME(init_state)(ei, &state);
761         err = _FUNCNAME(wcrtomb_priv)(ei, buf, _ENCODING_MB_CUR_MAX(ei),
762                                       (wchar_t)wc, &state, &nr);
763         if (!err && nr == 1)
764                 *cresult = buf[0];
765         else
766                 *cresult = EOF;
767
768         return 0;
769 }