14297a3b0SGarrett D'Amore /*
2*2d08521bSGarrett D'Amore * Copyright 2013 Garrett D'Amore <garrett@damore.org>
39d04e500SGarrett D'Amore * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
44297a3b0SGarrett D'Amore * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
54297a3b0SGarrett D'Amore * Copyright (c) 1993
64297a3b0SGarrett D'Amore * The Regents of the University of California. All rights reserved.
74297a3b0SGarrett D'Amore *
84297a3b0SGarrett D'Amore * This code is derived from software contributed to Berkeley by
94297a3b0SGarrett D'Amore * Paul Borman at Krystal Technologies.
104297a3b0SGarrett D'Amore *
114297a3b0SGarrett D'Amore * Redistribution and use in source and binary forms, with or without
124297a3b0SGarrett D'Amore * modification, are permitted provided that the following conditions
134297a3b0SGarrett D'Amore * are met:
144297a3b0SGarrett D'Amore * 1. Redistributions of source code must retain the above copyright
154297a3b0SGarrett D'Amore * notice, this list of conditions and the following disclaimer.
164297a3b0SGarrett D'Amore * 2. Redistributions in binary form must reproduce the above copyright
174297a3b0SGarrett D'Amore * notice, this list of conditions and the following disclaimer in the
184297a3b0SGarrett D'Amore * documentation and/or other materials provided with the distribution.
194297a3b0SGarrett D'Amore * 4. Neither the name of the University nor the names of its contributors
204297a3b0SGarrett D'Amore * may be used to endorse or promote products derived from this software
214297a3b0SGarrett D'Amore * without specific prior written permission.
224297a3b0SGarrett D'Amore *
234297a3b0SGarrett D'Amore * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
244297a3b0SGarrett D'Amore * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
254297a3b0SGarrett D'Amore * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
264297a3b0SGarrett D'Amore * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
274297a3b0SGarrett D'Amore * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
284297a3b0SGarrett D'Amore * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
294297a3b0SGarrett D'Amore * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
304297a3b0SGarrett D'Amore * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
314297a3b0SGarrett D'Amore * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
324297a3b0SGarrett D'Amore * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
334297a3b0SGarrett D'Amore * SUCH DAMAGE.
344297a3b0SGarrett D'Amore */
354297a3b0SGarrett D'Amore
364297a3b0SGarrett D'Amore #include "lint.h"
374297a3b0SGarrett D'Amore #include <errno.h>
384297a3b0SGarrett D'Amore #include <limits.h>
394297a3b0SGarrett D'Amore #include <stdlib.h>
404297a3b0SGarrett D'Amore #include <string.h>
414297a3b0SGarrett D'Amore #include <wchar.h>
424297a3b0SGarrett D'Amore #include <sys/types.h>
439d04e500SGarrett D'Amore #include <sys/euc.h>
444297a3b0SGarrett D'Amore #include "mblocal.h"
45*2d08521bSGarrett D'Amore #include "lctype.h"
464297a3b0SGarrett D'Amore
479d04e500SGarrett D'Amore static size_t _EUC_mbrtowc_impl(wchar_t *_RESTRICT_KYWD,
489d04e500SGarrett D'Amore const char *_RESTRICT_KYWD,
499d04e500SGarrett D'Amore size_t, mbstate_t *_RESTRICT_KYWD, uint8_t, uint8_t, uint8_t, uint8_t);
509d04e500SGarrett D'Amore static size_t _EUC_wcrtomb_impl(char *_RESTRICT_KYWD, wchar_t,
519d04e500SGarrett D'Amore mbstate_t *_RESTRICT_KYWD, uint8_t, uint8_t, uint8_t, uint8_t);
524297a3b0SGarrett D'Amore
539d04e500SGarrett D'Amore static size_t _EUC_CN_mbrtowc(wchar_t *_RESTRICT_KYWD,
544297a3b0SGarrett D'Amore const char *_RESTRICT_KYWD,
554297a3b0SGarrett D'Amore size_t, mbstate_t *_RESTRICT_KYWD);
569d04e500SGarrett D'Amore static size_t _EUC_JP_mbrtowc(wchar_t *_RESTRICT_KYWD,
579d04e500SGarrett D'Amore const char *_RESTRICT_KYWD,
589d04e500SGarrett D'Amore size_t, mbstate_t *_RESTRICT_KYWD);
599d04e500SGarrett D'Amore static size_t _EUC_KR_mbrtowc(wchar_t *_RESTRICT_KYWD,
609d04e500SGarrett D'Amore const char *_RESTRICT_KYWD,
619d04e500SGarrett D'Amore size_t, mbstate_t *_RESTRICT_KYWD);
629d04e500SGarrett D'Amore static size_t _EUC_TW_mbrtowc(wchar_t *_RESTRICT_KYWD,
639d04e500SGarrett D'Amore const char *_RESTRICT_KYWD,
649d04e500SGarrett D'Amore size_t, mbstate_t *_RESTRICT_KYWD);
65*2d08521bSGarrett D'Amore
669d04e500SGarrett D'Amore static size_t _EUC_CN_wcrtomb(char *_RESTRICT_KYWD, wchar_t,
674297a3b0SGarrett D'Amore mbstate_t *_RESTRICT_KYWD);
689d04e500SGarrett D'Amore static size_t _EUC_JP_wcrtomb(char *_RESTRICT_KYWD, wchar_t,
699d04e500SGarrett D'Amore mbstate_t *_RESTRICT_KYWD);
709d04e500SGarrett D'Amore static size_t _EUC_KR_wcrtomb(char *_RESTRICT_KYWD, wchar_t,
719d04e500SGarrett D'Amore mbstate_t *_RESTRICT_KYWD);
729d04e500SGarrett D'Amore static size_t _EUC_TW_wcrtomb(char *_RESTRICT_KYWD, wchar_t,
739d04e500SGarrett D'Amore mbstate_t *_RESTRICT_KYWD);
74*2d08521bSGarrett D'Amore
75*2d08521bSGarrett D'Amore static size_t _EUC_CN_mbsnrtowcs(wchar_t *_RESTRICT_KYWD,
76*2d08521bSGarrett D'Amore const char **_RESTRICT_KYWD, size_t, size_t,
77*2d08521bSGarrett D'Amore mbstate_t *_RESTRICT_KYWD);
78*2d08521bSGarrett D'Amore static size_t _EUC_JP_mbsnrtowcs(wchar_t *_RESTRICT_KYWD,
79*2d08521bSGarrett D'Amore const char **_RESTRICT_KYWD, size_t, size_t,
80*2d08521bSGarrett D'Amore mbstate_t *_RESTRICT_KYWD);
81*2d08521bSGarrett D'Amore static size_t _EUC_KR_mbsnrtowcs(wchar_t *_RESTRICT_KYWD,
82*2d08521bSGarrett D'Amore const char **_RESTRICT_KYWD, size_t, size_t,
83*2d08521bSGarrett D'Amore mbstate_t *_RESTRICT_KYWD);
84*2d08521bSGarrett D'Amore static size_t _EUC_TW_mbsnrtowcs(wchar_t *_RESTRICT_KYWD,
85*2d08521bSGarrett D'Amore const char **_RESTRICT_KYWD, size_t, size_t,
86*2d08521bSGarrett D'Amore mbstate_t *_RESTRICT_KYWD);
87*2d08521bSGarrett D'Amore
88*2d08521bSGarrett D'Amore static size_t _EUC_CN_wcsnrtombs(char *_RESTRICT_KYWD,
89*2d08521bSGarrett D'Amore const wchar_t **_RESTRICT_KYWD, size_t, size_t,
90*2d08521bSGarrett D'Amore mbstate_t *_RESTRICT_KYWD);
91*2d08521bSGarrett D'Amore static size_t _EUC_JP_wcsnrtombs(char *_RESTRICT_KYWD,
92*2d08521bSGarrett D'Amore const wchar_t **_RESTRICT_KYWD, size_t, size_t,
93*2d08521bSGarrett D'Amore mbstate_t *_RESTRICT_KYWD);
94*2d08521bSGarrett D'Amore static size_t _EUC_KR_wcsnrtombs(char *_RESTRICT_KYWD,
95*2d08521bSGarrett D'Amore const wchar_t **_RESTRICT_KYWD, size_t, size_t,
96*2d08521bSGarrett D'Amore mbstate_t *_RESTRICT_KYWD);
97*2d08521bSGarrett D'Amore static size_t _EUC_TW_wcsnrtombs(char *_RESTRICT_KYWD,
98*2d08521bSGarrett D'Amore const wchar_t **_RESTRICT_KYWD, size_t, size_t,
99*2d08521bSGarrett D'Amore mbstate_t *_RESTRICT_KYWD);
100*2d08521bSGarrett D'Amore
1019d04e500SGarrett D'Amore static int _EUC_mbsinit(const mbstate_t *);
1024297a3b0SGarrett D'Amore
1034297a3b0SGarrett D'Amore typedef struct {
1044297a3b0SGarrett D'Amore wchar_t ch;
1054297a3b0SGarrett D'Amore int set;
1064297a3b0SGarrett D'Amore int want;
1074297a3b0SGarrett D'Amore } _EucState;
1084297a3b0SGarrett D'Amore
109*2d08521bSGarrett D'Amore int
_EUC_mbsinit(const mbstate_t * ps)1104297a3b0SGarrett D'Amore _EUC_mbsinit(const mbstate_t *ps)
1114297a3b0SGarrett D'Amore {
1124297a3b0SGarrett D'Amore
1134297a3b0SGarrett D'Amore return (ps == NULL || ((const _EucState *)ps)->want == 0);
1144297a3b0SGarrett D'Amore }
1154297a3b0SGarrett D'Amore
1169d04e500SGarrett D'Amore /*
1179d04e500SGarrett D'Amore * EUC-CN uses CS0, CS1 and CS2 (4 bytes).
1189d04e500SGarrett D'Amore */
119*2d08521bSGarrett D'Amore void
_EUC_CN_init(struct lc_ctype * lct)120*2d08521bSGarrett D'Amore _EUC_CN_init(struct lc_ctype *lct)
1214297a3b0SGarrett D'Amore {
122*2d08521bSGarrett D'Amore lct->lc_mbrtowc = _EUC_CN_mbrtowc;
123*2d08521bSGarrett D'Amore lct->lc_wcrtomb = _EUC_CN_wcrtomb;
124*2d08521bSGarrett D'Amore lct->lc_mbsnrtowcs = _EUC_CN_mbsnrtowcs;
125*2d08521bSGarrett D'Amore lct->lc_wcsnrtombs = _EUC_CN_wcsnrtombs;
126*2d08521bSGarrett D'Amore lct->lc_mbsinit = _EUC_mbsinit;
1274297a3b0SGarrett D'Amore
128*2d08521bSGarrett D'Amore lct->lc_max_mblen = 4;
129*2d08521bSGarrett D'Amore lct->lc_is_ascii = 0;
1304297a3b0SGarrett D'Amore }
1314297a3b0SGarrett D'Amore
1324297a3b0SGarrett D'Amore static size_t
_EUC_CN_mbrtowc(wchar_t * _RESTRICT_KYWD pwc,const char * _RESTRICT_KYWD s,size_t n,mbstate_t * _RESTRICT_KYWD ps)1339d04e500SGarrett D'Amore _EUC_CN_mbrtowc(wchar_t *_RESTRICT_KYWD pwc, const char *_RESTRICT_KYWD s,
1344297a3b0SGarrett D'Amore size_t n, mbstate_t *_RESTRICT_KYWD ps)
1354297a3b0SGarrett D'Amore {
1369d04e500SGarrett D'Amore return (_EUC_mbrtowc_impl(pwc, s, n, ps, SS2, 4, 0, 0));
1379d04e500SGarrett D'Amore }
1389d04e500SGarrett D'Amore
1399d04e500SGarrett D'Amore static size_t
_EUC_CN_mbsnrtowcs(wchar_t * _RESTRICT_KYWD dst,const char ** _RESTRICT_KYWD src,size_t nms,size_t len,mbstate_t * _RESTRICT_KYWD ps)140*2d08521bSGarrett D'Amore _EUC_CN_mbsnrtowcs(wchar_t *_RESTRICT_KYWD dst,
141*2d08521bSGarrett D'Amore const char **_RESTRICT_KYWD src,
142*2d08521bSGarrett D'Amore size_t nms, size_t len, mbstate_t *_RESTRICT_KYWD ps)
143*2d08521bSGarrett D'Amore {
144*2d08521bSGarrett D'Amore return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_CN_mbrtowc));
145*2d08521bSGarrett D'Amore }
146*2d08521bSGarrett D'Amore
147*2d08521bSGarrett D'Amore static size_t
_EUC_CN_wcrtomb(char * _RESTRICT_KYWD s,wchar_t wc,mbstate_t * _RESTRICT_KYWD ps)1489d04e500SGarrett D'Amore _EUC_CN_wcrtomb(char *_RESTRICT_KYWD s, wchar_t wc,
1499d04e500SGarrett D'Amore mbstate_t *_RESTRICT_KYWD ps)
1509d04e500SGarrett D'Amore {
1519d04e500SGarrett D'Amore return (_EUC_wcrtomb_impl(s, wc, ps, SS2, 4, 0, 0));
1529d04e500SGarrett D'Amore }
1539d04e500SGarrett D'Amore
154*2d08521bSGarrett D'Amore static size_t
_EUC_CN_wcsnrtombs(char * _RESTRICT_KYWD dst,const wchar_t ** _RESTRICT_KYWD src,size_t nwc,size_t len,mbstate_t * _RESTRICT_KYWD ps)155*2d08521bSGarrett D'Amore _EUC_CN_wcsnrtombs(char *_RESTRICT_KYWD dst, const wchar_t **_RESTRICT_KYWD src,
156*2d08521bSGarrett D'Amore size_t nwc, size_t len, mbstate_t *_RESTRICT_KYWD ps)
157*2d08521bSGarrett D'Amore {
158*2d08521bSGarrett D'Amore return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_CN_wcrtomb));
159*2d08521bSGarrett D'Amore }
160*2d08521bSGarrett D'Amore
1619d04e500SGarrett D'Amore /*
1629d04e500SGarrett D'Amore * EUC-KR uses only CS0 and CS1.
1639d04e500SGarrett D'Amore */
164*2d08521bSGarrett D'Amore void
_EUC_KR_init(struct lc_ctype * lct)165*2d08521bSGarrett D'Amore _EUC_KR_init(struct lc_ctype *lct)
1669d04e500SGarrett D'Amore {
167*2d08521bSGarrett D'Amore lct->lc_mbrtowc = _EUC_KR_mbrtowc;
168*2d08521bSGarrett D'Amore lct->lc_wcrtomb = _EUC_KR_wcrtomb;
169*2d08521bSGarrett D'Amore lct->lc_mbsnrtowcs = _EUC_KR_mbsnrtowcs;
170*2d08521bSGarrett D'Amore lct->lc_wcsnrtombs = _EUC_KR_wcsnrtombs;
171*2d08521bSGarrett D'Amore lct->lc_mbsinit = _EUC_mbsinit;
1729d04e500SGarrett D'Amore
173*2d08521bSGarrett D'Amore lct->lc_max_mblen = 2;
174*2d08521bSGarrett D'Amore lct->lc_is_ascii = 0;
1759d04e500SGarrett D'Amore }
1769d04e500SGarrett D'Amore
1779d04e500SGarrett D'Amore static size_t
_EUC_KR_mbrtowc(wchar_t * _RESTRICT_KYWD pwc,const char * _RESTRICT_KYWD s,size_t n,mbstate_t * _RESTRICT_KYWD ps)1789d04e500SGarrett D'Amore _EUC_KR_mbrtowc(wchar_t *_RESTRICT_KYWD pwc, const char *_RESTRICT_KYWD s,
1799d04e500SGarrett D'Amore size_t n, mbstate_t *_RESTRICT_KYWD ps)
1809d04e500SGarrett D'Amore {
1819d04e500SGarrett D'Amore return (_EUC_mbrtowc_impl(pwc, s, n, ps, 0, 0, 0, 0));
1829d04e500SGarrett D'Amore }
1839d04e500SGarrett D'Amore
1849d04e500SGarrett D'Amore static size_t
_EUC_KR_mbsnrtowcs(wchar_t * _RESTRICT_KYWD dst,const char ** _RESTRICT_KYWD src,size_t nms,size_t len,mbstate_t * _RESTRICT_KYWD ps)185*2d08521bSGarrett D'Amore _EUC_KR_mbsnrtowcs(wchar_t *_RESTRICT_KYWD dst,
186*2d08521bSGarrett D'Amore const char **_RESTRICT_KYWD src,
187*2d08521bSGarrett D'Amore size_t nms, size_t len, mbstate_t *_RESTRICT_KYWD ps)
188*2d08521bSGarrett D'Amore {
189*2d08521bSGarrett D'Amore return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_KR_mbrtowc));
190*2d08521bSGarrett D'Amore }
191*2d08521bSGarrett D'Amore
192*2d08521bSGarrett D'Amore static size_t
_EUC_KR_wcrtomb(char * _RESTRICT_KYWD s,wchar_t wc,mbstate_t * _RESTRICT_KYWD ps)1939d04e500SGarrett D'Amore _EUC_KR_wcrtomb(char *_RESTRICT_KYWD s, wchar_t wc,
1949d04e500SGarrett D'Amore mbstate_t *_RESTRICT_KYWD ps)
1959d04e500SGarrett D'Amore {
1969d04e500SGarrett D'Amore return (_EUC_wcrtomb_impl(s, wc, ps, 0, 0, 0, 0));
1979d04e500SGarrett D'Amore }
1989d04e500SGarrett D'Amore
199*2d08521bSGarrett D'Amore static size_t
_EUC_KR_wcsnrtombs(char * _RESTRICT_KYWD dst,const wchar_t ** _RESTRICT_KYWD src,size_t nwc,size_t len,mbstate_t * _RESTRICT_KYWD ps)200*2d08521bSGarrett D'Amore _EUC_KR_wcsnrtombs(char *_RESTRICT_KYWD dst, const wchar_t **_RESTRICT_KYWD src,
201*2d08521bSGarrett D'Amore size_t nwc, size_t len, mbstate_t *_RESTRICT_KYWD ps)
202*2d08521bSGarrett D'Amore {
203*2d08521bSGarrett D'Amore return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_KR_wcrtomb));
204*2d08521bSGarrett D'Amore }
205*2d08521bSGarrett D'Amore
2069d04e500SGarrett D'Amore /*
2079d04e500SGarrett D'Amore * EUC-JP uses CS0, CS1, CS2, and CS3.
2089d04e500SGarrett D'Amore */
209*2d08521bSGarrett D'Amore void
_EUC_JP_init(struct lc_ctype * lct)210*2d08521bSGarrett D'Amore _EUC_JP_init(struct lc_ctype *lct)
2119d04e500SGarrett D'Amore {
212*2d08521bSGarrett D'Amore lct->lc_mbrtowc = _EUC_JP_mbrtowc;
213*2d08521bSGarrett D'Amore lct->lc_wcrtomb = _EUC_JP_wcrtomb;
214*2d08521bSGarrett D'Amore lct->lc_mbsnrtowcs = _EUC_JP_mbsnrtowcs;
215*2d08521bSGarrett D'Amore lct->lc_wcsnrtombs = _EUC_JP_wcsnrtombs;
216*2d08521bSGarrett D'Amore lct->lc_mbsinit = _EUC_mbsinit;
2179d04e500SGarrett D'Amore
218*2d08521bSGarrett D'Amore lct->lc_max_mblen = 3;
219*2d08521bSGarrett D'Amore lct->lc_is_ascii = 0;
2209d04e500SGarrett D'Amore }
2219d04e500SGarrett D'Amore
2229d04e500SGarrett D'Amore static size_t
_EUC_JP_mbrtowc(wchar_t * _RESTRICT_KYWD pwc,const char * _RESTRICT_KYWD s,size_t n,mbstate_t * _RESTRICT_KYWD ps)2239d04e500SGarrett D'Amore _EUC_JP_mbrtowc(wchar_t *_RESTRICT_KYWD pwc, const char *_RESTRICT_KYWD s,
2249d04e500SGarrett D'Amore size_t n, mbstate_t *_RESTRICT_KYWD ps)
2259d04e500SGarrett D'Amore {
2269d04e500SGarrett D'Amore return (_EUC_mbrtowc_impl(pwc, s, n, ps, SS2, 2, SS3, 3));
2279d04e500SGarrett D'Amore }
2289d04e500SGarrett D'Amore
2299d04e500SGarrett D'Amore static size_t
_EUC_JP_mbsnrtowcs(wchar_t * _RESTRICT_KYWD dst,const char ** _RESTRICT_KYWD src,size_t nms,size_t len,mbstate_t * _RESTRICT_KYWD ps)230*2d08521bSGarrett D'Amore _EUC_JP_mbsnrtowcs(wchar_t *_RESTRICT_KYWD dst,
231*2d08521bSGarrett D'Amore const char **_RESTRICT_KYWD src,
232*2d08521bSGarrett D'Amore size_t nms, size_t len, mbstate_t *_RESTRICT_KYWD ps)
233*2d08521bSGarrett D'Amore {
234*2d08521bSGarrett D'Amore return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_JP_mbrtowc));
235*2d08521bSGarrett D'Amore }
236*2d08521bSGarrett D'Amore
237*2d08521bSGarrett D'Amore static size_t
_EUC_JP_wcrtomb(char * _RESTRICT_KYWD s,wchar_t wc,mbstate_t * _RESTRICT_KYWD ps)2389d04e500SGarrett D'Amore _EUC_JP_wcrtomb(char *_RESTRICT_KYWD s, wchar_t wc,
2399d04e500SGarrett D'Amore mbstate_t *_RESTRICT_KYWD ps)
2409d04e500SGarrett D'Amore {
2419d04e500SGarrett D'Amore return (_EUC_wcrtomb_impl(s, wc, ps, SS2, 2, SS3, 3));
2429d04e500SGarrett D'Amore }
2439d04e500SGarrett D'Amore
244*2d08521bSGarrett D'Amore static size_t
_EUC_JP_wcsnrtombs(char * _RESTRICT_KYWD dst,const wchar_t ** _RESTRICT_KYWD src,size_t nwc,size_t len,mbstate_t * _RESTRICT_KYWD ps)245*2d08521bSGarrett D'Amore _EUC_JP_wcsnrtombs(char *_RESTRICT_KYWD dst, const wchar_t **_RESTRICT_KYWD src,
246*2d08521bSGarrett D'Amore size_t nwc, size_t len, mbstate_t *_RESTRICT_KYWD ps)
247*2d08521bSGarrett D'Amore {
248*2d08521bSGarrett D'Amore return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_JP_wcrtomb));
249*2d08521bSGarrett D'Amore }
250*2d08521bSGarrett D'Amore
2519d04e500SGarrett D'Amore /*
2529d04e500SGarrett D'Amore * EUC-TW uses CS0, CS1, and CS2.
2539d04e500SGarrett D'Amore */
254*2d08521bSGarrett D'Amore void
_EUC_TW_init(struct lc_ctype * lct)255*2d08521bSGarrett D'Amore _EUC_TW_init(struct lc_ctype *lct)
2569d04e500SGarrett D'Amore {
257*2d08521bSGarrett D'Amore lct->lc_mbrtowc = _EUC_TW_mbrtowc;
258*2d08521bSGarrett D'Amore lct->lc_wcrtomb = _EUC_TW_wcrtomb;
259*2d08521bSGarrett D'Amore lct->lc_mbsnrtowcs = _EUC_TW_mbsnrtowcs;
260*2d08521bSGarrett D'Amore lct->lc_wcsnrtombs = _EUC_TW_wcsnrtombs;
261*2d08521bSGarrett D'Amore lct->lc_mbsinit = _EUC_mbsinit;
2629d04e500SGarrett D'Amore
263*2d08521bSGarrett D'Amore lct->lc_max_mblen = 4;
264*2d08521bSGarrett D'Amore lct->lc_is_ascii = 0;
2659d04e500SGarrett D'Amore }
2669d04e500SGarrett D'Amore
2679d04e500SGarrett D'Amore static size_t
_EUC_TW_mbrtowc(wchar_t * _RESTRICT_KYWD pwc,const char * _RESTRICT_KYWD s,size_t n,mbstate_t * _RESTRICT_KYWD ps)2689d04e500SGarrett D'Amore _EUC_TW_mbrtowc(wchar_t *_RESTRICT_KYWD pwc, const char *_RESTRICT_KYWD s,
2699d04e500SGarrett D'Amore size_t n, mbstate_t *_RESTRICT_KYWD ps)
2709d04e500SGarrett D'Amore {
2719d04e500SGarrett D'Amore return (_EUC_mbrtowc_impl(pwc, s, n, ps, SS2, 4, 0, 0));
2729d04e500SGarrett D'Amore }
2739d04e500SGarrett D'Amore
2749d04e500SGarrett D'Amore static size_t
_EUC_TW_mbsnrtowcs(wchar_t * _RESTRICT_KYWD dst,const char ** _RESTRICT_KYWD src,size_t nms,size_t len,mbstate_t * _RESTRICT_KYWD ps)275*2d08521bSGarrett D'Amore _EUC_TW_mbsnrtowcs(wchar_t *_RESTRICT_KYWD dst,
276*2d08521bSGarrett D'Amore const char **_RESTRICT_KYWD src,
277*2d08521bSGarrett D'Amore size_t nms, size_t len, mbstate_t *_RESTRICT_KYWD ps)
278*2d08521bSGarrett D'Amore {
279*2d08521bSGarrett D'Amore return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_TW_mbrtowc));
280*2d08521bSGarrett D'Amore }
281*2d08521bSGarrett D'Amore
282*2d08521bSGarrett D'Amore static size_t
_EUC_TW_wcrtomb(char * _RESTRICT_KYWD s,wchar_t wc,mbstate_t * _RESTRICT_KYWD ps)2839d04e500SGarrett D'Amore _EUC_TW_wcrtomb(char *_RESTRICT_KYWD s, wchar_t wc,
2849d04e500SGarrett D'Amore mbstate_t *_RESTRICT_KYWD ps)
2859d04e500SGarrett D'Amore {
2869d04e500SGarrett D'Amore return (_EUC_wcrtomb_impl(s, wc, ps, SS2, 4, 0, 0));
2879d04e500SGarrett D'Amore }
2889d04e500SGarrett D'Amore
289*2d08521bSGarrett D'Amore static size_t
_EUC_TW_wcsnrtombs(char * _RESTRICT_KYWD dst,const wchar_t ** _RESTRICT_KYWD src,size_t nwc,size_t len,mbstate_t * _RESTRICT_KYWD ps)290*2d08521bSGarrett D'Amore _EUC_TW_wcsnrtombs(char *_RESTRICT_KYWD dst, const wchar_t **_RESTRICT_KYWD src,
291*2d08521bSGarrett D'Amore size_t nwc, size_t len, mbstate_t *_RESTRICT_KYWD ps)
292*2d08521bSGarrett D'Amore {
293*2d08521bSGarrett D'Amore return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_TW_wcrtomb));
294*2d08521bSGarrett D'Amore }
295*2d08521bSGarrett D'Amore
2969d04e500SGarrett D'Amore /*
2979d04e500SGarrett D'Amore * Common EUC code.
2989d04e500SGarrett D'Amore */
2999d04e500SGarrett D'Amore
3009d04e500SGarrett D'Amore static size_t
_EUC_mbrtowc_impl(wchar_t * _RESTRICT_KYWD pwc,const char * _RESTRICT_KYWD s,size_t n,mbstate_t * _RESTRICT_KYWD ps,uint8_t cs2,uint8_t cs2width,uint8_t cs3,uint8_t cs3width)3019d04e500SGarrett D'Amore _EUC_mbrtowc_impl(wchar_t *_RESTRICT_KYWD pwc, const char *_RESTRICT_KYWD s,
3029d04e500SGarrett D'Amore size_t n, mbstate_t *_RESTRICT_KYWD ps,
3039d04e500SGarrett D'Amore uint8_t cs2, uint8_t cs2width, uint8_t cs3, uint8_t cs3width)
3049d04e500SGarrett D'Amore {
3054297a3b0SGarrett D'Amore _EucState *es;
3069d04e500SGarrett D'Amore int i, want;
3074297a3b0SGarrett D'Amore wchar_t wc;
3089d04e500SGarrett D'Amore unsigned char ch;
3094297a3b0SGarrett D'Amore
3104297a3b0SGarrett D'Amore es = (_EucState *)ps;
3114297a3b0SGarrett D'Amore
3129d04e500SGarrett D'Amore if (es->want < 0 || es->want > MB_CUR_MAX) {
3134297a3b0SGarrett D'Amore errno = EINVAL;
3144297a3b0SGarrett D'Amore return ((size_t)-1);
3154297a3b0SGarrett D'Amore }
3164297a3b0SGarrett D'Amore
3174297a3b0SGarrett D'Amore if (s == NULL) {
3184297a3b0SGarrett D'Amore s = "";
3194297a3b0SGarrett D'Amore n = 1;
3204297a3b0SGarrett D'Amore pwc = NULL;
3214297a3b0SGarrett D'Amore }
3224297a3b0SGarrett D'Amore
3234297a3b0SGarrett D'Amore if (n == 0)
3244297a3b0SGarrett D'Amore /* Incomplete multibyte sequence */
3254297a3b0SGarrett D'Amore return ((size_t)-2);
3264297a3b0SGarrett D'Amore
3274297a3b0SGarrett D'Amore if (es->want == 0) {
3289d04e500SGarrett D'Amore /* Fast path for plain ASCII (CS0) */
3299d04e500SGarrett D'Amore if (((ch = (unsigned char)*s) & 0x80) == 0) {
3309d04e500SGarrett D'Amore if (pwc != NULL)
3319d04e500SGarrett D'Amore *pwc = ch;
3329d04e500SGarrett D'Amore return (ch != '\0' ? 1 : 0);
3334297a3b0SGarrett D'Amore }
3349d04e500SGarrett D'Amore
3359d04e500SGarrett D'Amore if (ch >= 0xa1) {
3369d04e500SGarrett D'Amore /* CS1 */
3379d04e500SGarrett D'Amore want = 2;
3389d04e500SGarrett D'Amore } else if (ch == cs2) {
3399d04e500SGarrett D'Amore want = cs2width;
3409d04e500SGarrett D'Amore } else if (ch == cs3) {
3419d04e500SGarrett D'Amore want = cs3width;
3429d04e500SGarrett D'Amore } else {
3434297a3b0SGarrett D'Amore errno = EILSEQ;
3444297a3b0SGarrett D'Amore return ((size_t)-1);
3454297a3b0SGarrett D'Amore }
3469d04e500SGarrett D'Amore
3479d04e500SGarrett D'Amore
3489d04e500SGarrett D'Amore es->want = want;
3499d04e500SGarrett D'Amore es->ch = 0;
3504297a3b0SGarrett D'Amore } else {
3514297a3b0SGarrett D'Amore want = es->want;
3524297a3b0SGarrett D'Amore wc = es->ch;
3534297a3b0SGarrett D'Amore }
3549d04e500SGarrett D'Amore
3559d04e500SGarrett D'Amore for (i = 0; i < MIN(want, n); i++) {
3569d04e500SGarrett D'Amore wc <<= 8;
3579d04e500SGarrett D'Amore wc |= *s;
3589d04e500SGarrett D'Amore s++;
3594297a3b0SGarrett D'Amore }
3604297a3b0SGarrett D'Amore if (i < want) {
3614297a3b0SGarrett D'Amore /* Incomplete multibyte sequence */
3624297a3b0SGarrett D'Amore es->want = want - i;
3634297a3b0SGarrett D'Amore es->ch = wc;
3644297a3b0SGarrett D'Amore return ((size_t)-2);
3654297a3b0SGarrett D'Amore }
3664297a3b0SGarrett D'Amore if (pwc != NULL)
3674297a3b0SGarrett D'Amore *pwc = wc;
3684297a3b0SGarrett D'Amore es->want = 0;
3699d04e500SGarrett D'Amore return (wc == L'\0' ? 0 : want);
3704297a3b0SGarrett D'Amore }
3714297a3b0SGarrett D'Amore
3724297a3b0SGarrett D'Amore static size_t
_EUC_wcrtomb_impl(char * _RESTRICT_KYWD s,wchar_t wc,mbstate_t * _RESTRICT_KYWD ps,uint8_t cs2,uint8_t cs2width,uint8_t cs3,uint8_t cs3width)3739d04e500SGarrett D'Amore _EUC_wcrtomb_impl(char *_RESTRICT_KYWD s, wchar_t wc,
3749d04e500SGarrett D'Amore mbstate_t *_RESTRICT_KYWD ps,
3759d04e500SGarrett D'Amore uint8_t cs2, uint8_t cs2width, uint8_t cs3, uint8_t cs3width)
3764297a3b0SGarrett D'Amore {
3774297a3b0SGarrett D'Amore _EucState *es;
3784297a3b0SGarrett D'Amore int i, len;
3799d04e500SGarrett D'Amore wchar_t nm;
3804297a3b0SGarrett D'Amore
3814297a3b0SGarrett D'Amore es = (_EucState *)ps;
3824297a3b0SGarrett D'Amore
3834297a3b0SGarrett D'Amore if (es->want != 0) {
3844297a3b0SGarrett D'Amore errno = EINVAL;
3854297a3b0SGarrett D'Amore return ((size_t)-1);
3864297a3b0SGarrett D'Amore }
3874297a3b0SGarrett D'Amore
3884297a3b0SGarrett D'Amore if (s == NULL)
3894297a3b0SGarrett D'Amore /* Reset to initial shift state (no-op) */
3904297a3b0SGarrett D'Amore return (1);
3914297a3b0SGarrett D'Amore
3929d04e500SGarrett D'Amore if ((wc & ~0x7f) == 0) {
3939d04e500SGarrett D'Amore /* Fast path for plain ASCII (CS0) */
3949d04e500SGarrett D'Amore *s = (char)wc;
3959d04e500SGarrett D'Amore return (1);
3969d04e500SGarrett D'Amore }
3974297a3b0SGarrett D'Amore
3989d04e500SGarrett D'Amore /* Determine the "length" */
3999d04e500SGarrett D'Amore if ((unsigned)wc > 0xffffff) {
4009d04e500SGarrett D'Amore len = 4;
4019d04e500SGarrett D'Amore } else if ((unsigned)wc > 0xffff) {
4029d04e500SGarrett D'Amore len = 3;
4039d04e500SGarrett D'Amore } else if ((unsigned)wc > 0xff) {
4049d04e500SGarrett D'Amore len = 2;
4059d04e500SGarrett D'Amore } else {
4069d04e500SGarrett D'Amore len = 1;
4079d04e500SGarrett D'Amore }
4089d04e500SGarrett D'Amore
4099d04e500SGarrett D'Amore if (len > MB_CUR_MAX) {
4109d04e500SGarrett D'Amore errno = EILSEQ;
4119d04e500SGarrett D'Amore return ((size_t)-1);
4129d04e500SGarrett D'Amore }
4139d04e500SGarrett D'Amore
4149d04e500SGarrett D'Amore /* This first check excludes CS1, which is implicitly valid. */
4159d04e500SGarrett D'Amore if ((wc < 0xa100) || (wc > 0xffff)) {
4169d04e500SGarrett D'Amore /* Check for valid CS2 or CS3 */
4179d04e500SGarrett D'Amore nm = (wc >> ((len - 1) * 8));
4189d04e500SGarrett D'Amore if (nm == cs2) {
4199d04e500SGarrett D'Amore if (len != cs2width) {
4209d04e500SGarrett D'Amore errno = EILSEQ;
4219d04e500SGarrett D'Amore return ((size_t)-1);
4229d04e500SGarrett D'Amore }
4239d04e500SGarrett D'Amore } else if (nm == cs3) {
4249d04e500SGarrett D'Amore if (len != cs3width) {
4259d04e500SGarrett D'Amore errno = EILSEQ;
4269d04e500SGarrett D'Amore return ((size_t)-1);
4274297a3b0SGarrett D'Amore }
4284297a3b0SGarrett D'Amore } else {
4299d04e500SGarrett D'Amore errno = EILSEQ;
4309d04e500SGarrett D'Amore return ((size_t)-1);
4319d04e500SGarrett D'Amore }
4329d04e500SGarrett D'Amore }
4339d04e500SGarrett D'Amore
4349d04e500SGarrett D'Amore /* Stash the bytes, least significant last */
4359d04e500SGarrett D'Amore for (i = len - 1; i >= 0; i--) {
4369d04e500SGarrett D'Amore s[i] = (wc & 0xff);
4379d04e500SGarrett D'Amore wc >>= 8;
4384297a3b0SGarrett D'Amore }
4394297a3b0SGarrett D'Amore return (len);
4404297a3b0SGarrett D'Amore }
441