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