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