14297a3b0SGarrett D'Amore /* 22d08521bSGarrett D'Amore * Copyright 2013 Garrett D'Amore <garrett@damore.org> 36b5e5868SGarrett D'Amore * Copyright 2010 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 <sys/types.h> 384297a3b0SGarrett D'Amore #include <errno.h> 394297a3b0SGarrett D'Amore #include <stdlib.h> 404297a3b0SGarrett D'Amore #include <string.h> 414297a3b0SGarrett D'Amore #include <wchar.h> 424297a3b0SGarrett D'Amore #include "mblocal.h" 432d08521bSGarrett D'Amore #include "lctype.h" 444297a3b0SGarrett D'Amore 454297a3b0SGarrett D'Amore static size_t _GBK_mbrtowc(wchar_t *_RESTRICT_KYWD, 464297a3b0SGarrett D'Amore const char *_RESTRICT_KYWD, 47*d8e0a9a1SRobert Mustacchi size_t, mbstate_t *_RESTRICT_KYWD, boolean_t); 484297a3b0SGarrett D'Amore static int _GBK_mbsinit(const mbstate_t *); 494297a3b0SGarrett D'Amore static size_t _GBK_wcrtomb(char *_RESTRICT_KYWD, wchar_t, 504297a3b0SGarrett D'Amore mbstate_t *_RESTRICT_KYWD); 512d08521bSGarrett D'Amore static size_t _GBK_mbsnrtowcs(wchar_t *_RESTRICT_KYWD, 522d08521bSGarrett D'Amore const char **_RESTRICT_KYWD, size_t, size_t, 532d08521bSGarrett D'Amore mbstate_t *_RESTRICT_KYWD); 542d08521bSGarrett D'Amore static size_t _GBK_wcsnrtombs(char *_RESTRICT_KYWD, 552d08521bSGarrett D'Amore const wchar_t **_RESTRICT_KYWD, size_t, size_t, 562d08521bSGarrett D'Amore mbstate_t *_RESTRICT_KYWD); 574297a3b0SGarrett D'Amore 582d08521bSGarrett D'Amore void 592d08521bSGarrett D'Amore _GBK_init(struct lc_ctype *lct) 604297a3b0SGarrett D'Amore { 612d08521bSGarrett D'Amore lct->lc_mbrtowc = _GBK_mbrtowc; 622d08521bSGarrett D'Amore lct->lc_wcrtomb = _GBK_wcrtomb; 632d08521bSGarrett D'Amore lct->lc_mbsinit = _GBK_mbsinit; 642d08521bSGarrett D'Amore lct->lc_mbsnrtowcs = _GBK_mbsnrtowcs; 652d08521bSGarrett D'Amore lct->lc_wcsnrtombs = _GBK_wcsnrtombs; 662d08521bSGarrett D'Amore lct->lc_max_mblen = 2; 672d08521bSGarrett D'Amore lct->lc_is_ascii = 0; 684297a3b0SGarrett D'Amore } 694297a3b0SGarrett D'Amore 704297a3b0SGarrett D'Amore static int 714297a3b0SGarrett D'Amore _GBK_mbsinit(const mbstate_t *ps) 724297a3b0SGarrett D'Amore { 734297a3b0SGarrett D'Amore 744297a3b0SGarrett D'Amore return (ps == NULL || ((const _GBKState *)ps)->ch == 0); 754297a3b0SGarrett D'Amore } 764297a3b0SGarrett D'Amore 774297a3b0SGarrett D'Amore static int 784297a3b0SGarrett D'Amore _gbk_check(uint_t c) 794297a3b0SGarrett D'Amore { 804297a3b0SGarrett D'Amore 814297a3b0SGarrett D'Amore c &= 0xff; 824297a3b0SGarrett D'Amore return ((c >= 0x81 && c <= 0xfe) ? 2 : 1); 834297a3b0SGarrett D'Amore } 844297a3b0SGarrett D'Amore 854297a3b0SGarrett D'Amore static size_t 864297a3b0SGarrett D'Amore _GBK_mbrtowc(wchar_t *_RESTRICT_KYWD pwc, const char *_RESTRICT_KYWD s, 87*d8e0a9a1SRobert Mustacchi size_t n, mbstate_t *_RESTRICT_KYWD ps, boolean_t zero) 884297a3b0SGarrett D'Amore { 894297a3b0SGarrett D'Amore _GBKState *gs; 904297a3b0SGarrett D'Amore wchar_t wc; 914297a3b0SGarrett D'Amore size_t len; 924297a3b0SGarrett D'Amore 934297a3b0SGarrett D'Amore gs = (_GBKState *)ps; 944297a3b0SGarrett D'Amore 954297a3b0SGarrett D'Amore if ((gs->ch & ~0xFF) != 0) { 964297a3b0SGarrett D'Amore /* Bad conversion state. */ 974297a3b0SGarrett D'Amore errno = EINVAL; 984297a3b0SGarrett D'Amore return ((size_t)-1); 994297a3b0SGarrett D'Amore } 1004297a3b0SGarrett D'Amore 1014297a3b0SGarrett D'Amore if (s == NULL) { 1024297a3b0SGarrett D'Amore s = ""; 1034297a3b0SGarrett D'Amore n = 1; 1044297a3b0SGarrett D'Amore pwc = NULL; 1054297a3b0SGarrett D'Amore } 1064297a3b0SGarrett D'Amore 1074297a3b0SGarrett D'Amore if (n == 0) 1084297a3b0SGarrett D'Amore /* Incomplete multibyte sequence */ 1094297a3b0SGarrett D'Amore return ((size_t)-2); 1104297a3b0SGarrett D'Amore 1114297a3b0SGarrett D'Amore if (gs->ch != 0) { 1124297a3b0SGarrett D'Amore if (*s == '\0') { 1134297a3b0SGarrett D'Amore errno = EILSEQ; 1144297a3b0SGarrett D'Amore return ((size_t)-1); 1154297a3b0SGarrett D'Amore } 1164297a3b0SGarrett D'Amore wc = (gs->ch << 8) | (*s & 0xFF); 1174297a3b0SGarrett D'Amore if (pwc != NULL) 1184297a3b0SGarrett D'Amore *pwc = wc; 1194297a3b0SGarrett D'Amore gs->ch = 0; 1204297a3b0SGarrett D'Amore return (1); 1214297a3b0SGarrett D'Amore } 1224297a3b0SGarrett D'Amore 1234297a3b0SGarrett D'Amore len = (size_t)_gbk_check(*s); 1244297a3b0SGarrett D'Amore wc = *s++ & 0xff; 1254297a3b0SGarrett D'Amore if (len == 2) { 1264297a3b0SGarrett D'Amore if (n < 2) { 1274297a3b0SGarrett D'Amore /* Incomplete multibyte sequence */ 1284297a3b0SGarrett D'Amore gs->ch = wc; 1294297a3b0SGarrett D'Amore return ((size_t)-2); 1304297a3b0SGarrett D'Amore } 1314297a3b0SGarrett D'Amore if (*s == '\0') { 1324297a3b0SGarrett D'Amore errno = EILSEQ; 1334297a3b0SGarrett D'Amore return ((size_t)-1); 1344297a3b0SGarrett D'Amore } 1354297a3b0SGarrett D'Amore wc = (wc << 8) | (*s++ & 0xff); 1364297a3b0SGarrett D'Amore if (pwc != NULL) 1374297a3b0SGarrett D'Amore *pwc = wc; 1384297a3b0SGarrett D'Amore return (2); 1394297a3b0SGarrett D'Amore } else { 1404297a3b0SGarrett D'Amore if (pwc != NULL) 1414297a3b0SGarrett D'Amore *pwc = wc; 142*d8e0a9a1SRobert Mustacchi if (zero || wc != L'\0') { 143*d8e0a9a1SRobert Mustacchi return (1); 144*d8e0a9a1SRobert Mustacchi } else { 145*d8e0a9a1SRobert Mustacchi return (0); 146*d8e0a9a1SRobert Mustacchi } 1474297a3b0SGarrett D'Amore } 1484297a3b0SGarrett D'Amore } 1494297a3b0SGarrett D'Amore 1504297a3b0SGarrett D'Amore static size_t 1514297a3b0SGarrett D'Amore _GBK_wcrtomb(char *_RESTRICT_KYWD s, wchar_t wc, mbstate_t *_RESTRICT_KYWD ps) 1524297a3b0SGarrett D'Amore { 1534297a3b0SGarrett D'Amore _GBKState *gs; 1544297a3b0SGarrett D'Amore 1554297a3b0SGarrett D'Amore gs = (_GBKState *)ps; 1564297a3b0SGarrett D'Amore 1574297a3b0SGarrett D'Amore if (gs->ch != 0) { 1584297a3b0SGarrett D'Amore errno = EINVAL; 1594297a3b0SGarrett D'Amore return ((size_t)-1); 1604297a3b0SGarrett D'Amore } 1614297a3b0SGarrett D'Amore 1624297a3b0SGarrett D'Amore if (s == NULL) 1634297a3b0SGarrett D'Amore /* Reset to initial shift state (no-op) */ 1644297a3b0SGarrett D'Amore return (1); 1654297a3b0SGarrett D'Amore if (wc & 0x8000) { 1664297a3b0SGarrett D'Amore *s++ = (wc >> 8) & 0xff; 1674297a3b0SGarrett D'Amore *s = wc & 0xff; 1684297a3b0SGarrett D'Amore return (2); 1694297a3b0SGarrett D'Amore } 1704297a3b0SGarrett D'Amore *s = wc & 0xff; 1714297a3b0SGarrett D'Amore return (1); 1724297a3b0SGarrett D'Amore } 1732d08521bSGarrett D'Amore 1742d08521bSGarrett D'Amore static size_t 1752d08521bSGarrett D'Amore _GBK_mbsnrtowcs(wchar_t *_RESTRICT_KYWD dst, const char **_RESTRICT_KYWD src, 1762d08521bSGarrett D'Amore size_t nms, size_t len, mbstate_t *_RESTRICT_KYWD ps) 1772d08521bSGarrett D'Amore { 1782d08521bSGarrett D'Amore return (__mbsnrtowcs_std(dst, src, nms, len, ps, _GBK_mbrtowc)); 1792d08521bSGarrett D'Amore } 1802d08521bSGarrett D'Amore 1812d08521bSGarrett D'Amore static size_t 1822d08521bSGarrett D'Amore _GBK_wcsnrtombs(char *_RESTRICT_KYWD dst, const wchar_t **_RESTRICT_KYWD src, 1832d08521bSGarrett D'Amore size_t nwc, size_t len, mbstate_t *_RESTRICT_KYWD ps) 1842d08521bSGarrett D'Amore { 1852d08521bSGarrett D'Amore return (__wcsnrtombs_std(dst, src, nwc, len, ps, _GBK_wcrtomb)); 1862d08521bSGarrett D'Amore } 187