xref: /freebsd/lib/libc/locale/euc.c (revision dc36d6f9bb1753f3808552f3afd30eda9a7b206a)
158f0484fSRodney W. Grimes /*-
291fb056eSPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
3df57947fSPedro F. Giffuni  *
47b247341SBaptiste Daroussin  * Copyright 2013 Garrett D'Amore <garrett@damore.org>
57b247341SBaptiste Daroussin  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
6ca2dae42STim J. Robbins  * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
758f0484fSRodney W. Grimes  * Copyright (c) 1993
858f0484fSRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
958f0484fSRodney W. Grimes  *
1058f0484fSRodney W. Grimes  * This code is derived from software contributed to Berkeley by
1158f0484fSRodney W. Grimes  * Paul Borman at Krystal Technologies.
1258f0484fSRodney W. Grimes  *
133c87aa1dSDavid Chisnall  * Copyright (c) 2011 The FreeBSD Foundation
14*5b5fa75aSEd Maste  *
153c87aa1dSDavid Chisnall  * Portions of this software were developed by David Chisnall
163c87aa1dSDavid Chisnall  * under sponsorship from the FreeBSD Foundation.
173c87aa1dSDavid Chisnall  *
1858f0484fSRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
1958f0484fSRodney W. Grimes  * modification, are permitted provided that the following conditions
2058f0484fSRodney W. Grimes  * are met:
2158f0484fSRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
2258f0484fSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
2358f0484fSRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
2458f0484fSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
2558f0484fSRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
267b247341SBaptiste Daroussin  * 3. Neither the name of the University nor the names of its contributors
2758f0484fSRodney W. Grimes  *    may be used to endorse or promote products derived from this software
2858f0484fSRodney W. Grimes  *    without specific prior written permission.
2958f0484fSRodney W. Grimes  *
3058f0484fSRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
3158f0484fSRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3258f0484fSRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3358f0484fSRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3458f0484fSRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3558f0484fSRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3658f0484fSRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3758f0484fSRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3858f0484fSRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3958f0484fSRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4058f0484fSRodney W. Grimes  * SUCH DAMAGE.
4158f0484fSRodney W. Grimes  */
4258f0484fSRodney W. Grimes 
43ca2dae42STim J. Robbins #include <sys/param.h>
4458f0484fSRodney W. Grimes #include <errno.h>
45ca2dae42STim J. Robbins #include <limits.h>
4602f4f60aSTim J. Robbins #include <runetype.h>
4758f0484fSRodney W. Grimes #include <stdlib.h>
48ca2dae42STim J. Robbins #include <string.h>
4902f4f60aSTim J. Robbins #include <wchar.h>
502051a8f2STim J. Robbins #include "mblocal.h"
5102f4f60aSTim J. Robbins 
52367ed4e1SAndrey A. Chernov extern int __mb_sb_limit;
53367ed4e1SAndrey A. Chernov 
547b247341SBaptiste Daroussin static size_t	_EUC_mbrtowc_impl(wchar_t * __restrict, const char * __restrict,
557b247341SBaptiste Daroussin     size_t, mbstate_t * __restrict, uint8_t, uint8_t, uint8_t, uint8_t);
567b247341SBaptiste Daroussin static size_t	_EUC_wcrtomb_impl(char * __restrict, wchar_t,
577b247341SBaptiste Daroussin     mbstate_t * __restrict, uint8_t, uint8_t, uint8_t, uint8_t);
587b247341SBaptiste Daroussin 
597b247341SBaptiste Daroussin static size_t	_EUC_CN_mbrtowc(wchar_t * __restrict, const char * __restrict,
60e94c6cb4SAlexey Zelkin 		    size_t, mbstate_t * __restrict);
617b247341SBaptiste Daroussin static size_t	_EUC_JP_mbrtowc(wchar_t * __restrict, const char * __restrict,
627b247341SBaptiste Daroussin 		    size_t, mbstate_t * __restrict);
637b247341SBaptiste Daroussin static size_t	_EUC_KR_mbrtowc(wchar_t * __restrict, const char * __restrict,
647b247341SBaptiste Daroussin 		    size_t, mbstate_t * __restrict);
657b247341SBaptiste Daroussin static size_t	_EUC_TW_mbrtowc(wchar_t * __restrict, const char * __restrict,
667b247341SBaptiste Daroussin 		    size_t, mbstate_t * __restrict);
677b247341SBaptiste Daroussin 
687b247341SBaptiste Daroussin static size_t	_EUC_CN_wcrtomb(char * __restrict, wchar_t,
697b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
707b247341SBaptiste Daroussin static size_t	_EUC_JP_wcrtomb(char * __restrict, wchar_t,
717b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
727b247341SBaptiste Daroussin static size_t	_EUC_KR_wcrtomb(char * __restrict, wchar_t,
737b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
747b247341SBaptiste Daroussin static size_t	_EUC_TW_wcrtomb(char * __restrict, wchar_t,
7502f4f60aSTim J. Robbins 		    mbstate_t * __restrict);
7658f0484fSRodney W. Grimes 
777b247341SBaptiste Daroussin static size_t	_EUC_CN_mbsnrtowcs(wchar_t * __restrict,
787b247341SBaptiste Daroussin 		    const char ** __restrict, size_t, size_t,
797b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
807b247341SBaptiste Daroussin static size_t	_EUC_JP_mbsnrtowcs(wchar_t * __restrict,
817b247341SBaptiste Daroussin 		    const char ** __restrict, size_t, size_t,
827b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
837b247341SBaptiste Daroussin static size_t	_EUC_KR_mbsnrtowcs(wchar_t * __restrict,
847b247341SBaptiste Daroussin 		    const char ** __restrict, size_t, size_t,
857b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
867b247341SBaptiste Daroussin static size_t	_EUC_TW_mbsnrtowcs(wchar_t * __restrict,
877b247341SBaptiste Daroussin 		    const char ** __restrict, size_t, size_t,
887b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
897b247341SBaptiste Daroussin 
907b247341SBaptiste Daroussin static size_t	_EUC_CN_wcsnrtombs(char * __restrict,
917b247341SBaptiste Daroussin 		    const wchar_t ** __restrict, size_t, size_t,
927b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
937b247341SBaptiste Daroussin static size_t	_EUC_JP_wcsnrtombs(char * __restrict,
947b247341SBaptiste Daroussin 		    const wchar_t ** __restrict, size_t, size_t,
957b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
967b247341SBaptiste Daroussin static size_t	_EUC_KR_wcsnrtombs(char * __restrict,
977b247341SBaptiste Daroussin 		    const wchar_t ** __restrict, size_t, size_t,
987b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
997b247341SBaptiste Daroussin static size_t	_EUC_TW_wcsnrtombs(char * __restrict,
1007b247341SBaptiste Daroussin 		    const wchar_t ** __restrict, size_t, size_t,
1017b247341SBaptiste Daroussin 		    mbstate_t * __restrict);
1027b247341SBaptiste Daroussin 
1037b247341SBaptiste Daroussin static int	_EUC_mbsinit(const mbstate_t *);
10458f0484fSRodney W. Grimes 
105ca2dae42STim J. Robbins typedef struct {
106c05bd9aeSTim J. Robbins 	wchar_t	ch;
107c05bd9aeSTim J. Robbins 	int	set;
108c05bd9aeSTim J. Robbins 	int	want;
109ca2dae42STim J. Robbins } _EucState;
110ca2dae42STim J. Robbins 
111e94c6cb4SAlexey Zelkin static int
_EUC_mbsinit(const mbstate_t * ps)112ca2dae42STim J. Robbins _EUC_mbsinit(const mbstate_t *ps)
113ca2dae42STim J. Robbins {
114ca2dae42STim J. Robbins 
115c05bd9aeSTim J. Robbins 	return (ps == NULL || ((const _EucState *)ps)->want == 0);
116ca2dae42STim J. Robbins }
117ca2dae42STim J. Robbins 
1187b247341SBaptiste Daroussin /*
1197b247341SBaptiste Daroussin  * EUC-CN uses CS0, CS1 and CS2 (4 bytes).
1207b247341SBaptiste Daroussin  */
1217b247341SBaptiste Daroussin int
_EUC_CN_init(struct xlocale_ctype * l,_RuneLocale * rl)1227b247341SBaptiste Daroussin _EUC_CN_init(struct xlocale_ctype *l, _RuneLocale *rl)
12358f0484fSRodney W. Grimes {
1247b247341SBaptiste Daroussin 	l->__mbrtowc = _EUC_CN_mbrtowc;
1257b247341SBaptiste Daroussin 	l->__wcrtomb = _EUC_CN_wcrtomb;
1267b247341SBaptiste Daroussin 	l->__mbsnrtowcs = _EUC_CN_mbsnrtowcs;
1277b247341SBaptiste Daroussin 	l->__wcsnrtombs = _EUC_CN_wcsnrtombs;
1287b247341SBaptiste Daroussin 	l->__mbsinit = _EUC_mbsinit;
129e94c6cb4SAlexey Zelkin 
1307b247341SBaptiste Daroussin 	l->runes = rl;
1317b247341SBaptiste Daroussin 	l->__mb_cur_max = 4;
132e08c3b7cSAndrey A. Chernov 	l->__mb_sb_limit = 128;
1337b247341SBaptiste Daroussin 	return (0);
13458f0484fSRodney W. Grimes }
13558f0484fSRodney W. Grimes 
136e94c6cb4SAlexey Zelkin static size_t
_EUC_CN_mbrtowc(wchar_t * __restrict pwc,const char * __restrict s,size_t n,mbstate_t * __restrict ps)1377b247341SBaptiste Daroussin _EUC_CN_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
1387b247341SBaptiste Daroussin     size_t n, mbstate_t * __restrict ps)
1397b247341SBaptiste Daroussin {
1407b247341SBaptiste Daroussin 	return (_EUC_mbrtowc_impl(pwc, s, n, ps, SS2, 4, 0, 0));
1417b247341SBaptiste Daroussin }
1427b247341SBaptiste Daroussin 
1437b247341SBaptiste Daroussin static size_t
_EUC_CN_mbsnrtowcs(wchar_t * __restrict dst,const char ** __restrict src,size_t nms,size_t len,mbstate_t * __restrict ps)1447b247341SBaptiste Daroussin _EUC_CN_mbsnrtowcs(wchar_t * __restrict dst,
1457b247341SBaptiste Daroussin     const char ** __restrict src,
1467b247341SBaptiste Daroussin     size_t nms, size_t len, mbstate_t * __restrict ps)
1477b247341SBaptiste Daroussin {
1487b247341SBaptiste Daroussin 	return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_CN_mbrtowc));
1497b247341SBaptiste Daroussin }
1507b247341SBaptiste Daroussin 
1517b247341SBaptiste Daroussin static size_t
_EUC_CN_wcrtomb(char * __restrict s,wchar_t wc,mbstate_t * __restrict ps)1527b247341SBaptiste Daroussin _EUC_CN_wcrtomb(char * __restrict s, wchar_t wc,
153ca2dae42STim J. Robbins     mbstate_t * __restrict ps)
15402f4f60aSTim J. Robbins {
1557b247341SBaptiste Daroussin 	return (_EUC_wcrtomb_impl(s, wc, ps, SS2, 4, 0, 0));
1567b247341SBaptiste Daroussin }
1577b247341SBaptiste Daroussin 
1587b247341SBaptiste Daroussin static size_t
_EUC_CN_wcsnrtombs(char * __restrict dst,const wchar_t ** __restrict src,size_t nwc,size_t len,mbstate_t * __restrict ps)1597b247341SBaptiste Daroussin _EUC_CN_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
1607b247341SBaptiste Daroussin 	size_t nwc, size_t len, mbstate_t * __restrict ps)
1617b247341SBaptiste Daroussin {
1627b247341SBaptiste Daroussin 	return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_CN_wcrtomb));
1637b247341SBaptiste Daroussin }
1647b247341SBaptiste Daroussin 
1657b247341SBaptiste Daroussin /*
1667b247341SBaptiste Daroussin  * EUC-KR uses only CS0 and CS1.
1677b247341SBaptiste Daroussin  */
1687b247341SBaptiste Daroussin int
_EUC_KR_init(struct xlocale_ctype * l,_RuneLocale * rl)1697b247341SBaptiste Daroussin _EUC_KR_init(struct xlocale_ctype *l, _RuneLocale *rl)
1707b247341SBaptiste Daroussin {
1717b247341SBaptiste Daroussin 	l->__mbrtowc = _EUC_KR_mbrtowc;
1727b247341SBaptiste Daroussin 	l->__wcrtomb = _EUC_KR_wcrtomb;
1737b247341SBaptiste Daroussin 	l->__mbsnrtowcs = _EUC_KR_mbsnrtowcs;
1747b247341SBaptiste Daroussin 	l->__wcsnrtombs = _EUC_KR_wcsnrtombs;
1757b247341SBaptiste Daroussin 	l->__mbsinit = _EUC_mbsinit;
1767b247341SBaptiste Daroussin 
1777b247341SBaptiste Daroussin 	l->runes = rl;
1787b247341SBaptiste Daroussin 	l->__mb_cur_max = 2;
1797b247341SBaptiste Daroussin 	l->__mb_sb_limit = 128;
1807b247341SBaptiste Daroussin 	return (0);
1817b247341SBaptiste Daroussin }
1827b247341SBaptiste Daroussin 
1837b247341SBaptiste Daroussin static size_t
_EUC_KR_mbrtowc(wchar_t * __restrict pwc,const char * __restrict s,size_t n,mbstate_t * __restrict ps)1847b247341SBaptiste Daroussin _EUC_KR_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
1857b247341SBaptiste Daroussin     size_t n, mbstate_t * __restrict ps)
1867b247341SBaptiste Daroussin {
1877b247341SBaptiste Daroussin 	return (_EUC_mbrtowc_impl(pwc, s, n, ps, 0, 0, 0, 0));
1887b247341SBaptiste Daroussin }
1897b247341SBaptiste Daroussin 
1907b247341SBaptiste Daroussin static size_t
_EUC_KR_mbsnrtowcs(wchar_t * __restrict dst,const char ** __restrict src,size_t nms,size_t len,mbstate_t * __restrict ps)1917b247341SBaptiste Daroussin _EUC_KR_mbsnrtowcs(wchar_t * __restrict dst,
1927b247341SBaptiste Daroussin     const char ** __restrict src,
1937b247341SBaptiste Daroussin     size_t nms, size_t len, mbstate_t * __restrict ps)
1947b247341SBaptiste Daroussin {
1957b247341SBaptiste Daroussin 	return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_KR_mbrtowc));
1967b247341SBaptiste Daroussin }
1977b247341SBaptiste Daroussin 
1987b247341SBaptiste Daroussin static size_t
_EUC_KR_wcrtomb(char * __restrict s,wchar_t wc,mbstate_t * __restrict ps)1997b247341SBaptiste Daroussin _EUC_KR_wcrtomb(char * __restrict s, wchar_t wc,
2007b247341SBaptiste Daroussin 	mbstate_t * __restrict ps)
2017b247341SBaptiste Daroussin {
2027b247341SBaptiste Daroussin 	return (_EUC_wcrtomb_impl(s, wc, ps, 0, 0, 0, 0));
2037b247341SBaptiste Daroussin }
2047b247341SBaptiste Daroussin 
2057b247341SBaptiste Daroussin static size_t
_EUC_KR_wcsnrtombs(char * __restrict dst,const wchar_t ** __restrict src,size_t nwc,size_t len,mbstate_t * __restrict ps)2067b247341SBaptiste Daroussin _EUC_KR_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
2077b247341SBaptiste Daroussin 	size_t nwc, size_t len, mbstate_t * __restrict ps)
2087b247341SBaptiste Daroussin {
2097b247341SBaptiste Daroussin 	return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_KR_wcrtomb));
2107b247341SBaptiste Daroussin }
2117b247341SBaptiste Daroussin 
2127b247341SBaptiste Daroussin /*
2137b247341SBaptiste Daroussin  * EUC-JP uses CS0, CS1, CS2, and CS3.
2147b247341SBaptiste Daroussin  */
2157b247341SBaptiste Daroussin int
_EUC_JP_init(struct xlocale_ctype * l,_RuneLocale * rl)2167b247341SBaptiste Daroussin _EUC_JP_init(struct xlocale_ctype *l, _RuneLocale *rl)
2177b247341SBaptiste Daroussin {
2187b247341SBaptiste Daroussin 	l->__mbrtowc = _EUC_JP_mbrtowc;
2197b247341SBaptiste Daroussin 	l->__wcrtomb = _EUC_JP_wcrtomb;
2207b247341SBaptiste Daroussin 	l->__mbsnrtowcs = _EUC_JP_mbsnrtowcs;
2217b247341SBaptiste Daroussin 	l->__wcsnrtombs = _EUC_JP_wcsnrtombs;
2227b247341SBaptiste Daroussin 	l->__mbsinit = _EUC_mbsinit;
2237b247341SBaptiste Daroussin 
2247b247341SBaptiste Daroussin 	l->runes = rl;
2257b247341SBaptiste Daroussin 	l->__mb_cur_max = 3;
226e08c3b7cSAndrey A. Chernov 	l->__mb_sb_limit = 128;
2277b247341SBaptiste Daroussin 	return (0);
2287b247341SBaptiste Daroussin }
2297b247341SBaptiste Daroussin 
2307b247341SBaptiste Daroussin static size_t
_EUC_JP_mbrtowc(wchar_t * __restrict pwc,const char * __restrict s,size_t n,mbstate_t * __restrict ps)2317b247341SBaptiste Daroussin _EUC_JP_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
2327b247341SBaptiste Daroussin     size_t n, mbstate_t * __restrict ps)
2337b247341SBaptiste Daroussin {
2347b247341SBaptiste Daroussin 	return (_EUC_mbrtowc_impl(pwc, s, n, ps, SS2, 2, SS3, 3));
2357b247341SBaptiste Daroussin }
2367b247341SBaptiste Daroussin 
2377b247341SBaptiste Daroussin static size_t
_EUC_JP_mbsnrtowcs(wchar_t * __restrict dst,const char ** __restrict src,size_t nms,size_t len,mbstate_t * __restrict ps)2387b247341SBaptiste Daroussin _EUC_JP_mbsnrtowcs(wchar_t * __restrict dst,
2397b247341SBaptiste Daroussin     const char ** __restrict src,
2407b247341SBaptiste Daroussin     size_t nms, size_t len, mbstate_t * __restrict ps)
2417b247341SBaptiste Daroussin {
2427b247341SBaptiste Daroussin 	return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_JP_mbrtowc));
2437b247341SBaptiste Daroussin }
2447b247341SBaptiste Daroussin 
2457b247341SBaptiste Daroussin static size_t
_EUC_JP_wcrtomb(char * __restrict s,wchar_t wc,mbstate_t * __restrict ps)2467b247341SBaptiste Daroussin _EUC_JP_wcrtomb(char * __restrict s, wchar_t wc,
2477b247341SBaptiste Daroussin     mbstate_t * __restrict ps)
2487b247341SBaptiste Daroussin {
2497b247341SBaptiste Daroussin 	return (_EUC_wcrtomb_impl(s, wc, ps, SS2, 2, SS3, 3));
2507b247341SBaptiste Daroussin }
2517b247341SBaptiste Daroussin 
2527b247341SBaptiste Daroussin static size_t
_EUC_JP_wcsnrtombs(char * __restrict dst,const wchar_t ** __restrict src,size_t nwc,size_t len,mbstate_t * __restrict ps)2537b247341SBaptiste Daroussin _EUC_JP_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
2547b247341SBaptiste Daroussin 	size_t nwc, size_t len, mbstate_t * __restrict ps)
2557b247341SBaptiste Daroussin {
2567b247341SBaptiste Daroussin 	return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_JP_wcrtomb));
2577b247341SBaptiste Daroussin }
2587b247341SBaptiste Daroussin 
2597b247341SBaptiste Daroussin /*
2607b247341SBaptiste Daroussin  * EUC-TW uses CS0, CS1, and CS2.
2617b247341SBaptiste Daroussin  */
2627b247341SBaptiste Daroussin int
_EUC_TW_init(struct xlocale_ctype * l,_RuneLocale * rl)2637b247341SBaptiste Daroussin _EUC_TW_init(struct xlocale_ctype *l, _RuneLocale *rl)
2647b247341SBaptiste Daroussin {
2657b247341SBaptiste Daroussin 	l->__mbrtowc = _EUC_TW_mbrtowc;
2667b247341SBaptiste Daroussin 	l->__wcrtomb = _EUC_TW_wcrtomb;
2677b247341SBaptiste Daroussin 	l->__mbsnrtowcs = _EUC_TW_mbsnrtowcs;
2687b247341SBaptiste Daroussin 	l->__wcsnrtombs = _EUC_TW_wcsnrtombs;
2697b247341SBaptiste Daroussin 	l->__mbsinit = _EUC_mbsinit;
2707b247341SBaptiste Daroussin 
2717b247341SBaptiste Daroussin 	l->runes = rl;
2727b247341SBaptiste Daroussin 	l->__mb_cur_max = 4;
273e08c3b7cSAndrey A. Chernov 	l->__mb_sb_limit = 128;
2747b247341SBaptiste Daroussin 	return (0);
2757b247341SBaptiste Daroussin }
2767b247341SBaptiste Daroussin 
2777b247341SBaptiste Daroussin static size_t
_EUC_TW_mbrtowc(wchar_t * __restrict pwc,const char * __restrict s,size_t n,mbstate_t * __restrict ps)2787b247341SBaptiste Daroussin _EUC_TW_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
2797b247341SBaptiste Daroussin 	size_t n, mbstate_t * __restrict ps)
2807b247341SBaptiste Daroussin {
2817b247341SBaptiste Daroussin 	return (_EUC_mbrtowc_impl(pwc, s, n, ps, SS2, 4, 0, 0));
2827b247341SBaptiste Daroussin }
2837b247341SBaptiste Daroussin 
2847b247341SBaptiste Daroussin static size_t
_EUC_TW_mbsnrtowcs(wchar_t * __restrict dst,const char ** __restrict src,size_t nms,size_t len,mbstate_t * __restrict ps)2857b247341SBaptiste Daroussin _EUC_TW_mbsnrtowcs(wchar_t * __restrict dst,
2867b247341SBaptiste Daroussin 	const char ** __restrict src,
2877b247341SBaptiste Daroussin 	size_t nms, size_t len, mbstate_t * __restrict ps)
2887b247341SBaptiste Daroussin {
2897b247341SBaptiste Daroussin 	return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_TW_mbrtowc));
2907b247341SBaptiste Daroussin }
2917b247341SBaptiste Daroussin 
2927b247341SBaptiste Daroussin static size_t
_EUC_TW_wcrtomb(char * __restrict s,wchar_t wc,mbstate_t * __restrict ps)2937b247341SBaptiste Daroussin _EUC_TW_wcrtomb(char * __restrict s, wchar_t wc,
2947b247341SBaptiste Daroussin 	mbstate_t * __restrict ps)
2957b247341SBaptiste Daroussin {
2967b247341SBaptiste Daroussin 	return (_EUC_wcrtomb_impl(s, wc, ps, SS2, 4, 0, 0));
2977b247341SBaptiste Daroussin }
2987b247341SBaptiste Daroussin 
2997b247341SBaptiste Daroussin static size_t
_EUC_TW_wcsnrtombs(char * __restrict dst,const wchar_t ** __restrict src,size_t nwc,size_t len,mbstate_t * __restrict ps)3007b247341SBaptiste Daroussin _EUC_TW_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
3017b247341SBaptiste Daroussin 	size_t nwc, size_t len, mbstate_t * __restrict ps)
3027b247341SBaptiste Daroussin {
3037b247341SBaptiste Daroussin 	return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_TW_wcrtomb));
3047b247341SBaptiste Daroussin }
3057b247341SBaptiste Daroussin 
3067b247341SBaptiste Daroussin /*
3077b247341SBaptiste Daroussin  * Common EUC code.
3087b247341SBaptiste Daroussin  */
3097b247341SBaptiste Daroussin 
3107b247341SBaptiste Daroussin static size_t
_EUC_mbrtowc_impl(wchar_t * __restrict pwc,const char * __restrict s,size_t n,mbstate_t * __restrict ps,uint8_t cs2,uint8_t cs2width,uint8_t cs3,uint8_t cs3width)3117b247341SBaptiste Daroussin _EUC_mbrtowc_impl(wchar_t * __restrict pwc, const char * __restrict s,
3127b247341SBaptiste Daroussin 	size_t n, mbstate_t * __restrict ps,
3137b247341SBaptiste Daroussin 	uint8_t cs2, uint8_t cs2width, uint8_t cs3, uint8_t cs3width)
3147b247341SBaptiste Daroussin {
315ca2dae42STim J. Robbins 	_EucState *es;
3167b247341SBaptiste Daroussin 	int i, want;
317d8ed03efSBaptiste Daroussin 	wchar_t wc = 0;
318d8ed03efSBaptiste Daroussin 	unsigned char ch, chs;
31902f4f60aSTim J. Robbins 
320ca2dae42STim J. Robbins 	es = (_EucState *)ps;
321ca2dae42STim J. Robbins 
3227b247341SBaptiste Daroussin 	if (es->want < 0 || es->want > MB_CUR_MAX) {
323fc813796STim J. Robbins 		errno = EINVAL;
324fc813796STim J. Robbins 		return ((size_t)-1);
325fc813796STim J. Robbins 	}
326fc813796STim J. Robbins 
327ca2dae42STim J. Robbins 	if (s == NULL) {
328ca2dae42STim J. Robbins 		s = "";
329ca2dae42STim J. Robbins 		n = 1;
330ca2dae42STim J. Robbins 		pwc = NULL;
331ca2dae42STim J. Robbins 	}
332ca2dae42STim J. Robbins 
333c05bd9aeSTim J. Robbins 	if (n == 0)
33402f4f60aSTim J. Robbins 		/* Incomplete multibyte sequence */
33502f4f60aSTim J. Robbins 		return ((size_t)-2);
336c05bd9aeSTim J. Robbins 
337c05bd9aeSTim J. Robbins 	if (es->want == 0) {
3387b247341SBaptiste Daroussin 		/* Fast path for plain ASCII (CS0) */
3397b247341SBaptiste Daroussin 		if (((ch = (unsigned char)*s) & 0x80) == 0) {
3407b247341SBaptiste Daroussin 			if (pwc != NULL)
3417b247341SBaptiste Daroussin 				*pwc = ch;
3427b247341SBaptiste Daroussin 			return (ch != '\0' ? 1 : 0);
343c05bd9aeSTim J. Robbins 		}
3447b247341SBaptiste Daroussin 
3457b247341SBaptiste Daroussin 		if (ch >= 0xa1) {
3467b247341SBaptiste Daroussin 			/* CS1 */
3477b247341SBaptiste Daroussin 			want = 2;
3487b247341SBaptiste Daroussin 		} else if (ch == cs2) {
3497b247341SBaptiste Daroussin 			want = cs2width;
3507b247341SBaptiste Daroussin 		} else if (ch == cs3) {
3517b247341SBaptiste Daroussin 			want = cs3width;
3527b247341SBaptiste Daroussin 		} else {
353c05bd9aeSTim J. Robbins 			errno = EILSEQ;
354c05bd9aeSTim J. Robbins 			return ((size_t)-1);
355c05bd9aeSTim J. Robbins 		}
3567b247341SBaptiste Daroussin 
3577b247341SBaptiste Daroussin 
3587b247341SBaptiste Daroussin 		es->want = want;
3597b247341SBaptiste Daroussin 		es->ch = 0;
360c05bd9aeSTim J. Robbins 	} else {
361c05bd9aeSTim J. Robbins 		want = es->want;
362c05bd9aeSTim J. Robbins 		wc = es->ch;
363c05bd9aeSTim J. Robbins 	}
3647b247341SBaptiste Daroussin 
3657b247341SBaptiste Daroussin 	for (i = 0; i < MIN(want, n); i++) {
3667b247341SBaptiste Daroussin 		wc <<= 8;
367d8ed03efSBaptiste Daroussin 		chs = *s;
368d8ed03efSBaptiste Daroussin 		wc |= chs;
3697b247341SBaptiste Daroussin 		s++;
37088af941aSTim J. Robbins 	}
371c05bd9aeSTim J. Robbins 	if (i < want) {
372c05bd9aeSTim J. Robbins 		/* Incomplete multibyte sequence */
373c05bd9aeSTim J. Robbins 		es->want = want - i;
374c05bd9aeSTim J. Robbins 		es->ch = wc;
375e5850478SBaptiste Daroussin 		errno = EILSEQ;
376c05bd9aeSTim J. Robbins 		return ((size_t)-2);
37758f0484fSRodney W. Grimes 	}
37802f4f60aSTim J. Robbins 	if (pwc != NULL)
37902f4f60aSTim J. Robbins 		*pwc = wc;
380c05bd9aeSTim J. Robbins 	es->want = 0;
3817b247341SBaptiste Daroussin 	return (wc == L'\0' ? 0 : want);
38258f0484fSRodney W. Grimes }
38358f0484fSRodney W. Grimes 
384e94c6cb4SAlexey Zelkin static size_t
_EUC_wcrtomb_impl(char * __restrict s,wchar_t wc,mbstate_t * __restrict ps,uint8_t cs2,uint8_t cs2width,uint8_t cs3,uint8_t cs3width)3857b247341SBaptiste Daroussin _EUC_wcrtomb_impl(char * __restrict s, wchar_t wc,
3867b247341SBaptiste Daroussin     mbstate_t * __restrict ps,
3877b247341SBaptiste Daroussin     uint8_t cs2, uint8_t cs2width, uint8_t cs3, uint8_t cs3width)
38858f0484fSRodney W. Grimes {
389fc813796STim J. Robbins 	_EucState *es;
39058f0484fSRodney W. Grimes 	int i, len;
3917b247341SBaptiste Daroussin 	wchar_t nm;
39258f0484fSRodney W. Grimes 
393fc813796STim J. Robbins 	es = (_EucState *)ps;
394fc813796STim J. Robbins 
395c05bd9aeSTim J. Robbins 	if (es->want != 0) {
396fc813796STim J. Robbins 		errno = EINVAL;
397fc813796STim J. Robbins 		return ((size_t)-1);
398fc813796STim J. Robbins 	}
399fc813796STim J. Robbins 
40002f4f60aSTim J. Robbins 	if (s == NULL)
40102f4f60aSTim J. Robbins 		/* Reset to initial shift state (no-op) */
40202f4f60aSTim J. Robbins 		return (1);
40302f4f60aSTim J. Robbins 
4047b247341SBaptiste Daroussin 	if ((wc & ~0x7f) == 0) {
4057b247341SBaptiste Daroussin 		/* Fast path for plain ASCII (CS0) */
4067b247341SBaptiste Daroussin 		*s = (char)wc;
4077b247341SBaptiste Daroussin 		return (1);
4087b247341SBaptiste Daroussin 	}
40902f4f60aSTim J. Robbins 
4107b247341SBaptiste Daroussin 	/* Determine the "length" */
4117b247341SBaptiste Daroussin 	if ((unsigned)wc > 0xffffff) {
4127b247341SBaptiste Daroussin 		len = 4;
4137b247341SBaptiste Daroussin 	} else if ((unsigned)wc > 0xffff) {
4147b247341SBaptiste Daroussin 		len = 3;
4157b247341SBaptiste Daroussin 	} else if ((unsigned)wc > 0xff) {
4167b247341SBaptiste Daroussin 		len = 2;
41758f0484fSRodney W. Grimes 	} else {
4187b247341SBaptiste Daroussin 		len = 1;
4197b247341SBaptiste Daroussin 	}
4207b247341SBaptiste Daroussin 
4217b247341SBaptiste Daroussin 	if (len > MB_CUR_MAX) {
4227b247341SBaptiste Daroussin 		errno = EILSEQ;
4237b247341SBaptiste Daroussin 		return ((size_t)-1);
4247b247341SBaptiste Daroussin 	}
4257b247341SBaptiste Daroussin 
4267b247341SBaptiste Daroussin 	/* This first check excludes CS1, which is implicitly valid. */
4277b247341SBaptiste Daroussin 	if ((wc < 0xa100) || (wc > 0xffff)) {
4287b247341SBaptiste Daroussin 		/* Check for valid CS2 or CS3 */
4297b247341SBaptiste Daroussin 		nm = (wc >> ((len - 1) * 8));
4307b247341SBaptiste Daroussin 		if (nm == cs2) {
4317b247341SBaptiste Daroussin 			if (len != cs2width) {
4327b247341SBaptiste Daroussin 				errno = EILSEQ;
4337b247341SBaptiste Daroussin 				return ((size_t)-1);
4347b247341SBaptiste Daroussin 			}
4357b247341SBaptiste Daroussin 		} else if (nm == cs3) {
4367b247341SBaptiste Daroussin 			if (len != cs3width) {
4377b247341SBaptiste Daroussin 				errno = EILSEQ;
4387b247341SBaptiste Daroussin 				return ((size_t)-1);
4397b247341SBaptiste Daroussin 			}
4407b247341SBaptiste Daroussin 		} else {
4417b247341SBaptiste Daroussin 			errno = EILSEQ;
4427b247341SBaptiste Daroussin 			return ((size_t)-1);
4437b247341SBaptiste Daroussin 		}
4447b247341SBaptiste Daroussin 	}
4457b247341SBaptiste Daroussin 
4467b247341SBaptiste Daroussin 	/* Stash the bytes, least significant last */
4477b247341SBaptiste Daroussin 	for (i = len - 1; i >= 0; i--) {
4487b247341SBaptiste Daroussin 		s[i] = (wc & 0xff);
4497b247341SBaptiste Daroussin 		wc >>= 8;
45058f0484fSRodney W. Grimes 	}
45158f0484fSRodney W. Grimes 	return (len);
45258f0484fSRodney W. Grimes }
453