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