xref: /freebsd/lib/libc/locale/euc.c (revision e58504783b6e3b95606489435fd65ebbccb92586)
158f0484fSRodney W. Grimes /*-
27b247341SBaptiste Daroussin  * Copyright 2013 Garrett D'Amore <garrett@damore.org>
37b247341SBaptiste Daroussin  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
4ca2dae42STim J. Robbins  * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
558f0484fSRodney W. Grimes  * Copyright (c) 1993
658f0484fSRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
758f0484fSRodney W. Grimes  *
858f0484fSRodney W. Grimes  * This code is derived from software contributed to Berkeley by
958f0484fSRodney W. Grimes  * Paul Borman at Krystal Technologies.
1058f0484fSRodney W. Grimes  *
113c87aa1dSDavid Chisnall  * Copyright (c) 2011 The FreeBSD Foundation
123c87aa1dSDavid Chisnall  * All rights reserved.
133c87aa1dSDavid Chisnall  * Portions of this software were developed by David Chisnall
143c87aa1dSDavid Chisnall  * under sponsorship from the FreeBSD Foundation.
153c87aa1dSDavid Chisnall  *
1658f0484fSRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
1758f0484fSRodney W. Grimes  * modification, are permitted provided that the following conditions
1858f0484fSRodney W. Grimes  * are met:
1958f0484fSRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
2058f0484fSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
2158f0484fSRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
2258f0484fSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
2358f0484fSRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
247b247341SBaptiste Daroussin  * 3. Neither the name of the University nor the names of its contributors
2558f0484fSRodney W. Grimes  *    may be used to endorse or promote products derived from this software
2658f0484fSRodney W. Grimes  *    without specific prior written permission.
2758f0484fSRodney W. Grimes  *
2858f0484fSRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2958f0484fSRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3058f0484fSRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3158f0484fSRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3258f0484fSRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3358f0484fSRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3458f0484fSRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3558f0484fSRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3658f0484fSRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3758f0484fSRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3858f0484fSRodney W. Grimes  * SUCH DAMAGE.
3958f0484fSRodney W. Grimes  */
4058f0484fSRodney W. Grimes 
4158f0484fSRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint)
4258f0484fSRodney W. Grimes static char sccsid[] = "@(#)euc.c	8.1 (Berkeley) 6/4/93";
4358f0484fSRodney W. Grimes #endif /* LIBC_SCCS and not lint */
44ca2dae42STim J. Robbins #include <sys/param.h>
45333fc21eSDavid E. O'Brien __FBSDID("$FreeBSD$");
4658f0484fSRodney W. Grimes 
4758f0484fSRodney W. Grimes #include <errno.h>
48ca2dae42STim J. Robbins #include <limits.h>
4902f4f60aSTim J. Robbins #include <runetype.h>
5058f0484fSRodney W. Grimes #include <stdlib.h>
51ca2dae42STim J. Robbins #include <string.h>
5202f4f60aSTim J. Robbins #include <wchar.h>
532051a8f2STim J. Robbins #include "mblocal.h"
5402f4f60aSTim J. Robbins 
55367ed4e1SAndrey A. Chernov extern int __mb_sb_limit;
56367ed4e1SAndrey A. Chernov 
577b247341SBaptiste Daroussin static size_t	_EUC_mbrtowc_impl(wchar_t * __restrict, const char * __restrict,
587b247341SBaptiste Daroussin     size_t, mbstate_t * __restrict, uint8_t, uint8_t, uint8_t, uint8_t);
597b247341SBaptiste Daroussin static size_t	_EUC_wcrtomb_impl(char * __restrict, wchar_t,
607b247341SBaptiste Daroussin     mbstate_t * __restrict, uint8_t, uint8_t, uint8_t, uint8_t);
617b247341SBaptiste Daroussin 
627b247341SBaptiste Daroussin static size_t	_EUC_CN_mbrtowc(wchar_t * __restrict, const char * __restrict,
63e94c6cb4SAlexey Zelkin 		    size_t, mbstate_t * __restrict);
647b247341SBaptiste Daroussin static size_t	_EUC_JP_mbrtowc(wchar_t * __restrict, const char * __restrict,
657b247341SBaptiste Daroussin 		    size_t, mbstate_t * __restrict);
667b247341SBaptiste Daroussin static size_t	_EUC_KR_mbrtowc(wchar_t * __restrict, const char * __restrict,
677b247341SBaptiste Daroussin 		    size_t, mbstate_t * __restrict);
687b247341SBaptiste Daroussin static size_t	_EUC_TW_mbrtowc(wchar_t * __restrict, const char * __restrict,
697b247341SBaptiste Daroussin 		    size_t, mbstate_t * __restrict);
707b247341SBaptiste Daroussin 
717b247341SBaptiste Daroussin static size_t	_EUC_CN_wcrtomb(char * __restrict, wchar_t,
727b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
737b247341SBaptiste Daroussin static size_t	_EUC_JP_wcrtomb(char * __restrict, wchar_t,
747b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
757b247341SBaptiste Daroussin static size_t	_EUC_KR_wcrtomb(char * __restrict, wchar_t,
767b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
777b247341SBaptiste Daroussin static size_t	_EUC_TW_wcrtomb(char * __restrict, wchar_t,
7802f4f60aSTim J. Robbins 		    mbstate_t * __restrict);
7958f0484fSRodney W. Grimes 
807b247341SBaptiste Daroussin static size_t	_EUC_CN_mbsnrtowcs(wchar_t * __restrict,
817b247341SBaptiste Daroussin 		    const char ** __restrict, size_t, size_t,
827b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
837b247341SBaptiste Daroussin static size_t	_EUC_JP_mbsnrtowcs(wchar_t * __restrict,
847b247341SBaptiste Daroussin 		    const char ** __restrict, size_t, size_t,
857b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
867b247341SBaptiste Daroussin static size_t	_EUC_KR_mbsnrtowcs(wchar_t * __restrict,
877b247341SBaptiste Daroussin 		    const char ** __restrict, size_t, size_t,
887b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
897b247341SBaptiste Daroussin static size_t	_EUC_TW_mbsnrtowcs(wchar_t * __restrict,
907b247341SBaptiste Daroussin 		    const char ** __restrict, size_t, size_t,
917b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
927b247341SBaptiste Daroussin 
937b247341SBaptiste Daroussin static size_t	_EUC_CN_wcsnrtombs(char * __restrict,
947b247341SBaptiste Daroussin 		    const wchar_t ** __restrict, size_t, size_t,
957b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
967b247341SBaptiste Daroussin static size_t	_EUC_JP_wcsnrtombs(char * __restrict,
977b247341SBaptiste Daroussin 		    const wchar_t ** __restrict, size_t, size_t,
987b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
997b247341SBaptiste Daroussin static size_t	_EUC_KR_wcsnrtombs(char * __restrict,
1007b247341SBaptiste Daroussin 		    const wchar_t ** __restrict, size_t, size_t,
1017b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
1027b247341SBaptiste Daroussin static size_t	_EUC_TW_wcsnrtombs(char * __restrict,
1037b247341SBaptiste Daroussin 		    const wchar_t ** __restrict, size_t, size_t,
1047b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
1057b247341SBaptiste Daroussin 
1067b247341SBaptiste Daroussin static int	_EUC_mbsinit(const mbstate_t *);
10758f0484fSRodney W. Grimes 
108ca2dae42STim J. Robbins typedef struct {
109c05bd9aeSTim J. Robbins 	wchar_t	ch;
110c05bd9aeSTim J. Robbins 	int	set;
111c05bd9aeSTim J. Robbins 	int	want;
112ca2dae42STim J. Robbins } _EucState;
113ca2dae42STim J. Robbins 
114e94c6cb4SAlexey Zelkin static int
115ca2dae42STim J. Robbins _EUC_mbsinit(const mbstate_t *ps)
116ca2dae42STim J. Robbins {
117ca2dae42STim J. Robbins 
118c05bd9aeSTim J. Robbins 	return (ps == NULL || ((const _EucState *)ps)->want == 0);
119ca2dae42STim J. Robbins }
120ca2dae42STim J. Robbins 
1217b247341SBaptiste Daroussin /*
1227b247341SBaptiste Daroussin  * EUC-CN uses CS0, CS1 and CS2 (4 bytes).
1237b247341SBaptiste Daroussin  */
1247b247341SBaptiste Daroussin int
1257b247341SBaptiste Daroussin _EUC_CN_init(struct xlocale_ctype *l, _RuneLocale *rl)
12658f0484fSRodney W. Grimes {
1277b247341SBaptiste Daroussin 	l->__mbrtowc = _EUC_CN_mbrtowc;
1287b247341SBaptiste Daroussin 	l->__wcrtomb = _EUC_CN_wcrtomb;
1297b247341SBaptiste Daroussin 	l->__mbsnrtowcs = _EUC_CN_mbsnrtowcs;
1307b247341SBaptiste Daroussin 	l->__wcsnrtombs = _EUC_CN_wcsnrtombs;
1317b247341SBaptiste Daroussin 	l->__mbsinit = _EUC_mbsinit;
132e94c6cb4SAlexey Zelkin 
1337b247341SBaptiste Daroussin 	l->runes = rl;
1347b247341SBaptiste Daroussin 	l->__mb_cur_max = 4;
1357b247341SBaptiste Daroussin 	l->__mb_sb_limit = 256;
1367b247341SBaptiste Daroussin 	return (0);
13758f0484fSRodney W. Grimes }
13858f0484fSRodney W. Grimes 
139e94c6cb4SAlexey Zelkin static size_t
1407b247341SBaptiste Daroussin _EUC_CN_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
1417b247341SBaptiste Daroussin     size_t n, mbstate_t * __restrict ps)
1427b247341SBaptiste Daroussin {
1437b247341SBaptiste Daroussin 	return (_EUC_mbrtowc_impl(pwc, s, n, ps, SS2, 4, 0, 0));
1447b247341SBaptiste Daroussin }
1457b247341SBaptiste Daroussin 
1467b247341SBaptiste Daroussin static size_t
1477b247341SBaptiste Daroussin _EUC_CN_mbsnrtowcs(wchar_t * __restrict dst,
1487b247341SBaptiste Daroussin     const char ** __restrict src,
1497b247341SBaptiste Daroussin     size_t nms, size_t len, mbstate_t * __restrict ps)
1507b247341SBaptiste Daroussin {
1517b247341SBaptiste Daroussin 	return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_CN_mbrtowc));
1527b247341SBaptiste Daroussin }
1537b247341SBaptiste Daroussin 
1547b247341SBaptiste Daroussin static size_t
1557b247341SBaptiste Daroussin _EUC_CN_wcrtomb(char * __restrict s, wchar_t wc,
156ca2dae42STim J. Robbins     mbstate_t * __restrict ps)
15702f4f60aSTim J. Robbins {
1587b247341SBaptiste Daroussin 	return (_EUC_wcrtomb_impl(s, wc, ps, SS2, 4, 0, 0));
1597b247341SBaptiste Daroussin }
1607b247341SBaptiste Daroussin 
1617b247341SBaptiste Daroussin static size_t
1627b247341SBaptiste Daroussin _EUC_CN_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
1637b247341SBaptiste Daroussin 	size_t nwc, size_t len, mbstate_t * __restrict ps)
1647b247341SBaptiste Daroussin {
1657b247341SBaptiste Daroussin 	return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_CN_wcrtomb));
1667b247341SBaptiste Daroussin }
1677b247341SBaptiste Daroussin 
1687b247341SBaptiste Daroussin /*
1697b247341SBaptiste Daroussin  * EUC-KR uses only CS0 and CS1.
1707b247341SBaptiste Daroussin  */
1717b247341SBaptiste Daroussin int
1727b247341SBaptiste Daroussin _EUC_KR_init(struct xlocale_ctype *l, _RuneLocale *rl)
1737b247341SBaptiste Daroussin {
1747b247341SBaptiste Daroussin 	l->__mbrtowc = _EUC_KR_mbrtowc;
1757b247341SBaptiste Daroussin 	l->__wcrtomb = _EUC_KR_wcrtomb;
1767b247341SBaptiste Daroussin 	l->__mbsnrtowcs = _EUC_KR_mbsnrtowcs;
1777b247341SBaptiste Daroussin 	l->__wcsnrtombs = _EUC_KR_wcsnrtombs;
1787b247341SBaptiste Daroussin 	l->__mbsinit = _EUC_mbsinit;
1797b247341SBaptiste Daroussin 
1807b247341SBaptiste Daroussin 	l->runes = rl;
1817b247341SBaptiste Daroussin 	l->__mb_cur_max = 2;
1827b247341SBaptiste Daroussin 	l->__mb_sb_limit = 128;
1837b247341SBaptiste Daroussin 	return (0);
1847b247341SBaptiste Daroussin }
1857b247341SBaptiste Daroussin 
1867b247341SBaptiste Daroussin static size_t
1877b247341SBaptiste Daroussin _EUC_KR_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
1887b247341SBaptiste Daroussin     size_t n, mbstate_t * __restrict ps)
1897b247341SBaptiste Daroussin {
1907b247341SBaptiste Daroussin 	return (_EUC_mbrtowc_impl(pwc, s, n, ps, 0, 0, 0, 0));
1917b247341SBaptiste Daroussin }
1927b247341SBaptiste Daroussin 
1937b247341SBaptiste Daroussin static size_t
1947b247341SBaptiste Daroussin _EUC_KR_mbsnrtowcs(wchar_t * __restrict dst,
1957b247341SBaptiste Daroussin     const char ** __restrict src,
1967b247341SBaptiste Daroussin     size_t nms, size_t len, mbstate_t * __restrict ps)
1977b247341SBaptiste Daroussin {
1987b247341SBaptiste Daroussin 	return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_KR_mbrtowc));
1997b247341SBaptiste Daroussin }
2007b247341SBaptiste Daroussin 
2017b247341SBaptiste Daroussin static size_t
2027b247341SBaptiste Daroussin _EUC_KR_wcrtomb(char * __restrict s, wchar_t wc,
2037b247341SBaptiste Daroussin 	mbstate_t * __restrict ps)
2047b247341SBaptiste Daroussin {
2057b247341SBaptiste Daroussin 	return (_EUC_wcrtomb_impl(s, wc, ps, 0, 0, 0, 0));
2067b247341SBaptiste Daroussin }
2077b247341SBaptiste Daroussin 
2087b247341SBaptiste Daroussin static size_t
2097b247341SBaptiste Daroussin _EUC_KR_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
2107b247341SBaptiste Daroussin 	size_t nwc, size_t len, mbstate_t * __restrict ps)
2117b247341SBaptiste Daroussin {
2127b247341SBaptiste Daroussin 	return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_KR_wcrtomb));
2137b247341SBaptiste Daroussin }
2147b247341SBaptiste Daroussin 
2157b247341SBaptiste Daroussin /*
2167b247341SBaptiste Daroussin  * EUC-JP uses CS0, CS1, CS2, and CS3.
2177b247341SBaptiste Daroussin  */
2187b247341SBaptiste Daroussin int
2197b247341SBaptiste Daroussin _EUC_JP_init(struct xlocale_ctype *l, _RuneLocale *rl)
2207b247341SBaptiste Daroussin {
2217b247341SBaptiste Daroussin 	l->__mbrtowc = _EUC_JP_mbrtowc;
2227b247341SBaptiste Daroussin 	l->__wcrtomb = _EUC_JP_wcrtomb;
2237b247341SBaptiste Daroussin 	l->__mbsnrtowcs = _EUC_JP_mbsnrtowcs;
2247b247341SBaptiste Daroussin 	l->__wcsnrtombs = _EUC_JP_wcsnrtombs;
2257b247341SBaptiste Daroussin 	l->__mbsinit = _EUC_mbsinit;
2267b247341SBaptiste Daroussin 
2277b247341SBaptiste Daroussin 	l->runes = rl;
2287b247341SBaptiste Daroussin 	l->__mb_cur_max = 3;
2297b247341SBaptiste Daroussin 	l->__mb_sb_limit = 196;
2307b247341SBaptiste Daroussin 	return (0);
2317b247341SBaptiste Daroussin }
2327b247341SBaptiste Daroussin 
2337b247341SBaptiste Daroussin static size_t
2347b247341SBaptiste Daroussin _EUC_JP_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
2357b247341SBaptiste Daroussin     size_t n, mbstate_t * __restrict ps)
2367b247341SBaptiste Daroussin {
2377b247341SBaptiste Daroussin 	return (_EUC_mbrtowc_impl(pwc, s, n, ps, SS2, 2, SS3, 3));
2387b247341SBaptiste Daroussin }
2397b247341SBaptiste Daroussin 
2407b247341SBaptiste Daroussin static size_t
2417b247341SBaptiste Daroussin _EUC_JP_mbsnrtowcs(wchar_t * __restrict dst,
2427b247341SBaptiste Daroussin     const char ** __restrict src,
2437b247341SBaptiste Daroussin     size_t nms, size_t len, mbstate_t * __restrict ps)
2447b247341SBaptiste Daroussin {
2457b247341SBaptiste Daroussin 	return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_JP_mbrtowc));
2467b247341SBaptiste Daroussin }
2477b247341SBaptiste Daroussin 
2487b247341SBaptiste Daroussin static size_t
2497b247341SBaptiste Daroussin _EUC_JP_wcrtomb(char * __restrict s, wchar_t wc,
2507b247341SBaptiste Daroussin     mbstate_t * __restrict ps)
2517b247341SBaptiste Daroussin {
2527b247341SBaptiste Daroussin 	return (_EUC_wcrtomb_impl(s, wc, ps, SS2, 2, SS3, 3));
2537b247341SBaptiste Daroussin }
2547b247341SBaptiste Daroussin 
2557b247341SBaptiste Daroussin static size_t
2567b247341SBaptiste Daroussin _EUC_JP_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
2577b247341SBaptiste Daroussin 	size_t nwc, size_t len, mbstate_t * __restrict ps)
2587b247341SBaptiste Daroussin {
2597b247341SBaptiste Daroussin 	return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_JP_wcrtomb));
2607b247341SBaptiste Daroussin }
2617b247341SBaptiste Daroussin 
2627b247341SBaptiste Daroussin /*
2637b247341SBaptiste Daroussin  * EUC-TW uses CS0, CS1, and CS2.
2647b247341SBaptiste Daroussin  */
2657b247341SBaptiste Daroussin int
2667b247341SBaptiste Daroussin _EUC_TW_init(struct xlocale_ctype *l, _RuneLocale *rl)
2677b247341SBaptiste Daroussin {
2687b247341SBaptiste Daroussin 	l->__mbrtowc = _EUC_TW_mbrtowc;
2697b247341SBaptiste Daroussin 	l->__wcrtomb = _EUC_TW_wcrtomb;
2707b247341SBaptiste Daroussin 	l->__mbsnrtowcs = _EUC_TW_mbsnrtowcs;
2717b247341SBaptiste Daroussin 	l->__wcsnrtombs = _EUC_TW_wcsnrtombs;
2727b247341SBaptiste Daroussin 	l->__mbsinit = _EUC_mbsinit;
2737b247341SBaptiste Daroussin 
2747b247341SBaptiste Daroussin 	l->runes = rl;
2757b247341SBaptiste Daroussin 	l->__mb_cur_max = 4;
2767b247341SBaptiste Daroussin 	l->__mb_sb_limit = 256;
2777b247341SBaptiste Daroussin 	return (0);
2787b247341SBaptiste Daroussin }
2797b247341SBaptiste Daroussin 
2807b247341SBaptiste Daroussin static size_t
2817b247341SBaptiste Daroussin _EUC_TW_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
2827b247341SBaptiste Daroussin 	size_t n, mbstate_t * __restrict ps)
2837b247341SBaptiste Daroussin {
2847b247341SBaptiste Daroussin 	return (_EUC_mbrtowc_impl(pwc, s, n, ps, SS2, 4, 0, 0));
2857b247341SBaptiste Daroussin }
2867b247341SBaptiste Daroussin 
2877b247341SBaptiste Daroussin static size_t
2887b247341SBaptiste Daroussin _EUC_TW_mbsnrtowcs(wchar_t * __restrict dst,
2897b247341SBaptiste Daroussin 	const char ** __restrict src,
2907b247341SBaptiste Daroussin 	size_t nms, size_t len, mbstate_t * __restrict ps)
2917b247341SBaptiste Daroussin {
2927b247341SBaptiste Daroussin 	return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_TW_mbrtowc));
2937b247341SBaptiste Daroussin }
2947b247341SBaptiste Daroussin 
2957b247341SBaptiste Daroussin static size_t
2967b247341SBaptiste Daroussin _EUC_TW_wcrtomb(char * __restrict s, wchar_t wc,
2977b247341SBaptiste Daroussin 	mbstate_t * __restrict ps)
2987b247341SBaptiste Daroussin {
2997b247341SBaptiste Daroussin 	return (_EUC_wcrtomb_impl(s, wc, ps, SS2, 4, 0, 0));
3007b247341SBaptiste Daroussin }
3017b247341SBaptiste Daroussin 
3027b247341SBaptiste Daroussin static size_t
3037b247341SBaptiste Daroussin _EUC_TW_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
3047b247341SBaptiste Daroussin 	size_t nwc, size_t len, mbstate_t * __restrict ps)
3057b247341SBaptiste Daroussin {
3067b247341SBaptiste Daroussin 	return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_TW_wcrtomb));
3077b247341SBaptiste Daroussin }
3087b247341SBaptiste Daroussin 
3097b247341SBaptiste Daroussin /*
3107b247341SBaptiste Daroussin  * Common EUC code.
3117b247341SBaptiste Daroussin  */
3127b247341SBaptiste Daroussin 
3137b247341SBaptiste Daroussin static size_t
3147b247341SBaptiste Daroussin _EUC_mbrtowc_impl(wchar_t * __restrict pwc, const char * __restrict s,
3157b247341SBaptiste Daroussin 	size_t n, mbstate_t * __restrict ps,
3167b247341SBaptiste Daroussin 	uint8_t cs2, uint8_t cs2width, uint8_t cs3, uint8_t cs3width)
3177b247341SBaptiste Daroussin {
318ca2dae42STim J. Robbins 	_EucState *es;
3197b247341SBaptiste Daroussin 	int i, want;
320d8ed03efSBaptiste Daroussin 	wchar_t wc = 0;
321d8ed03efSBaptiste Daroussin 	unsigned char ch, chs;
32202f4f60aSTim J. Robbins 
323ca2dae42STim J. Robbins 	es = (_EucState *)ps;
324ca2dae42STim J. Robbins 
3257b247341SBaptiste Daroussin 	if (es->want < 0 || es->want > MB_CUR_MAX) {
326fc813796STim J. Robbins 		errno = EINVAL;
327fc813796STim J. Robbins 		return ((size_t)-1);
328fc813796STim J. Robbins 	}
329fc813796STim J. Robbins 
330ca2dae42STim J. Robbins 	if (s == NULL) {
331ca2dae42STim J. Robbins 		s = "";
332ca2dae42STim J. Robbins 		n = 1;
333ca2dae42STim J. Robbins 		pwc = NULL;
334ca2dae42STim J. Robbins 	}
335ca2dae42STim J. Robbins 
336c05bd9aeSTim J. Robbins 	if (n == 0)
33702f4f60aSTim J. Robbins 		/* Incomplete multibyte sequence */
33802f4f60aSTim J. Robbins 		return ((size_t)-2);
339c05bd9aeSTim J. Robbins 
340c05bd9aeSTim J. Robbins 	if (es->want == 0) {
3417b247341SBaptiste Daroussin 		/* Fast path for plain ASCII (CS0) */
3427b247341SBaptiste Daroussin 		if (((ch = (unsigned char)*s) & 0x80) == 0) {
3437b247341SBaptiste Daroussin 			if (pwc != NULL)
3447b247341SBaptiste Daroussin 				*pwc = ch;
3457b247341SBaptiste Daroussin 			return (ch != '\0' ? 1 : 0);
346c05bd9aeSTim J. Robbins 		}
3477b247341SBaptiste Daroussin 
3487b247341SBaptiste Daroussin 		if (ch >= 0xa1) {
3497b247341SBaptiste Daroussin 			/* CS1 */
3507b247341SBaptiste Daroussin 			want = 2;
3517b247341SBaptiste Daroussin 		} else if (ch == cs2) {
3527b247341SBaptiste Daroussin 			want = cs2width;
3537b247341SBaptiste Daroussin 		} else if (ch == cs3) {
3547b247341SBaptiste Daroussin 			want = cs3width;
3557b247341SBaptiste Daroussin 		} else {
356c05bd9aeSTim J. Robbins 			errno = EILSEQ;
357c05bd9aeSTim J. Robbins 			return ((size_t)-1);
358c05bd9aeSTim J. Robbins 		}
3597b247341SBaptiste Daroussin 
3607b247341SBaptiste Daroussin 
3617b247341SBaptiste Daroussin 		es->want = want;
3627b247341SBaptiste Daroussin 		es->ch = 0;
363c05bd9aeSTim J. Robbins 	} else {
364c05bd9aeSTim J. Robbins 		want = es->want;
365c05bd9aeSTim J. Robbins 		wc = es->ch;
366c05bd9aeSTim J. Robbins 	}
3677b247341SBaptiste Daroussin 
3687b247341SBaptiste Daroussin 	for (i = 0; i < MIN(want, n); i++) {
3697b247341SBaptiste Daroussin 		wc <<= 8;
370d8ed03efSBaptiste Daroussin 		chs = *s;
371d8ed03efSBaptiste Daroussin 		wc |= chs;
3727b247341SBaptiste Daroussin 		s++;
37388af941aSTim J. Robbins 	}
374c05bd9aeSTim J. Robbins 	if (i < want) {
375c05bd9aeSTim J. Robbins 		/* Incomplete multibyte sequence */
376c05bd9aeSTim J. Robbins 		es->want = want - i;
377c05bd9aeSTim J. Robbins 		es->ch = wc;
378*e5850478SBaptiste Daroussin 		errno = EILSEQ;
379c05bd9aeSTim J. Robbins 		return ((size_t)-2);
38058f0484fSRodney W. Grimes 	}
38102f4f60aSTim J. Robbins 	if (pwc != NULL)
38202f4f60aSTim J. Robbins 		*pwc = wc;
383c05bd9aeSTim J. Robbins 	es->want = 0;
3847b247341SBaptiste Daroussin 	return (wc == L'\0' ? 0 : want);
38558f0484fSRodney W. Grimes }
38658f0484fSRodney W. Grimes 
387e94c6cb4SAlexey Zelkin static size_t
3887b247341SBaptiste Daroussin _EUC_wcrtomb_impl(char * __restrict s, wchar_t wc,
3897b247341SBaptiste Daroussin     mbstate_t * __restrict ps,
3907b247341SBaptiste Daroussin     uint8_t cs2, uint8_t cs2width, uint8_t cs3, uint8_t cs3width)
39158f0484fSRodney W. Grimes {
392fc813796STim J. Robbins 	_EucState *es;
39358f0484fSRodney W. Grimes 	int i, len;
3947b247341SBaptiste Daroussin 	wchar_t nm;
39558f0484fSRodney W. Grimes 
396fc813796STim J. Robbins 	es = (_EucState *)ps;
397fc813796STim J. Robbins 
398c05bd9aeSTim J. Robbins 	if (es->want != 0) {
399fc813796STim J. Robbins 		errno = EINVAL;
400fc813796STim J. Robbins 		return ((size_t)-1);
401fc813796STim J. Robbins 	}
402fc813796STim J. Robbins 
40302f4f60aSTim J. Robbins 	if (s == NULL)
40402f4f60aSTim J. Robbins 		/* Reset to initial shift state (no-op) */
40502f4f60aSTim J. Robbins 		return (1);
40602f4f60aSTim J. Robbins 
4077b247341SBaptiste Daroussin 	if ((wc & ~0x7f) == 0) {
4087b247341SBaptiste Daroussin 		/* Fast path for plain ASCII (CS0) */
4097b247341SBaptiste Daroussin 		*s = (char)wc;
4107b247341SBaptiste Daroussin 		return (1);
4117b247341SBaptiste Daroussin 	}
41202f4f60aSTim J. Robbins 
4137b247341SBaptiste Daroussin 	/* Determine the "length" */
4147b247341SBaptiste Daroussin 	if ((unsigned)wc > 0xffffff) {
4157b247341SBaptiste Daroussin 		len = 4;
4167b247341SBaptiste Daroussin 	} else if ((unsigned)wc > 0xffff) {
4177b247341SBaptiste Daroussin 		len = 3;
4187b247341SBaptiste Daroussin 	} else if ((unsigned)wc > 0xff) {
4197b247341SBaptiste Daroussin 		len = 2;
42058f0484fSRodney W. Grimes 	} else {
4217b247341SBaptiste Daroussin 		len = 1;
4227b247341SBaptiste Daroussin 	}
4237b247341SBaptiste Daroussin 
4247b247341SBaptiste Daroussin 	if (len > MB_CUR_MAX) {
4257b247341SBaptiste Daroussin 		errno = EILSEQ;
4267b247341SBaptiste Daroussin 		return ((size_t)-1);
4277b247341SBaptiste Daroussin 	}
4287b247341SBaptiste Daroussin 
4297b247341SBaptiste Daroussin 	/* This first check excludes CS1, which is implicitly valid. */
4307b247341SBaptiste Daroussin 	if ((wc < 0xa100) || (wc > 0xffff)) {
4317b247341SBaptiste Daroussin 		/* Check for valid CS2 or CS3 */
4327b247341SBaptiste Daroussin 		nm = (wc >> ((len - 1) * 8));
4337b247341SBaptiste Daroussin 		if (nm == cs2) {
4347b247341SBaptiste Daroussin 			if (len != cs2width) {
4357b247341SBaptiste Daroussin 				errno = EILSEQ;
4367b247341SBaptiste Daroussin 				return ((size_t)-1);
4377b247341SBaptiste Daroussin 			}
4387b247341SBaptiste Daroussin 		} else if (nm == cs3) {
4397b247341SBaptiste Daroussin 			if (len != cs3width) {
4407b247341SBaptiste Daroussin 				errno = EILSEQ;
4417b247341SBaptiste Daroussin 				return ((size_t)-1);
4427b247341SBaptiste Daroussin 			}
4437b247341SBaptiste Daroussin 		} else {
4447b247341SBaptiste Daroussin 			errno = EILSEQ;
4457b247341SBaptiste Daroussin 			return ((size_t)-1);
4467b247341SBaptiste Daroussin 		}
4477b247341SBaptiste Daroussin 	}
4487b247341SBaptiste Daroussin 
4497b247341SBaptiste Daroussin 	/* Stash the bytes, least significant last */
4507b247341SBaptiste Daroussin 	for (i = len - 1; i >= 0; i--) {
4517b247341SBaptiste Daroussin 		s[i] = (wc & 0xff);
4527b247341SBaptiste Daroussin 		wc >>= 8;
45358f0484fSRodney W. Grimes 	}
45458f0484fSRodney W. Grimes 	return (len);
45558f0484fSRodney W. Grimes }
456