diff options
-rw-r--r-- | lib/libc/locale/Makefile.inc | 2 | ||||
-rw-r--r-- | lib/libc/locale/gb2312.c | 116 | ||||
-rw-r--r-- | lib/libc/locale/setrunelocale.c | 3 | ||||
-rw-r--r-- | usr.bin/mklocale/yacc.y | 1 |
4 files changed, 121 insertions, 1 deletions
diff --git a/lib/libc/locale/Makefile.inc b/lib/libc/locale/Makefile.inc index 9003321..54e9e23 100644 --- a/lib/libc/locale/Makefile.inc +++ b/lib/libc/locale/Makefile.inc @@ -5,7 +5,7 @@ .PATH: ${.CURDIR}/${MACHINE_ARCH}/locale ${.CURDIR}/locale SRCS+= big5.c btowc.c collate.c collcmp.c euc.c fix_grouping.c frune.c \ - gb18030.c gbk.c isctype.c iswctype.c \ + gb18030.c gb2312.c gbk.c isctype.c iswctype.c \ ldpart.c lmessages.c lmonetary.c lnumeric.c localeconv.c mblen.c \ mbrlen.c \ mbrtowc.c mbrune.c mbsinit.c mbsrtowcs.c mbtowc.c mbstowcs.c \ diff --git a/lib/libc/locale/gb2312.c b/lib/libc/locale/gb2312.c new file mode 100644 index 0000000..0b82eca --- /dev/null +++ b/lib/libc/locale/gb2312.c @@ -0,0 +1,116 @@ +/*- + * Copyright (c) 2003 David Xu <davidxu@freebsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <runetype.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <wchar.h> + +extern size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, + size_t, mbstate_t * __restrict); +extern size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict); + +int _GB2312_init(_RuneLocale *); +size_t _GB2312_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t, + mbstate_t * __restrict); +size_t _GB2312_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict); + +int +_GB2312_init(_RuneLocale *rl) +{ + + _CurrentRuneLocale = rl; + __mbrtowc = _GB2312_mbrtowc; + __wcrtomb = _GB2312_wcrtomb; + __mb_cur_max = 2; + return (0); +} + +static inline int +_GB2312_check(const char *str, size_t n) +{ + const u_char *s = (const u_char *)str; + + if (n == 0) + /* Incomplete multibyte sequence */ + return (-2); + if (s[0] >= 0xa1 && s[0] <= 0xfe) { + if (n < 2) + /* Incomplete multibyte sequence */ + return (-2); + if (s[1] < 0xa1 || s[1] > 0xfe) + /* Invalid multibyte sequence */ + return (-1); + return (2); + } else if (s[0] & 0x80) { + /* Invalid multibyte sequence */ + return (-1); + } + return (1); +} + +size_t +_GB2312_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n, + mbstate_t * __restrict ps __unused) +{ + wchar_t wc; + int i, len; + + if (s == NULL) + /* Reset to initial shift state (no-op) */ + return (0); + if ((len = _GB2312_check(s, n)) < 0) + return ((size_t)len); + wc = 0; + i = len; + while (i-- > 0) + wc = (wc << 8) | (unsigned char)*s++; + if (pwc != NULL) + *pwc = wc; + return (wc == L'\0' ? 0 : len); +} + +size_t +_GB2312_wcrtomb(char * __restrict s, wchar_t wc, + mbstate_t * __restrict ps __unused) +{ + + if (s == NULL) + /* Reset to initial shift state (no-op) */ + return (1); + if (wc & 0x8000) { + *s++ = (wc >> 8) & 0xff; + *s = wc & 0xff; + return (2); + } + *s = wc & 0xff; + return (1); +} diff --git a/lib/libc/locale/setrunelocale.c b/lib/libc/locale/setrunelocale.c index 0037f9c..43b759a 100644 --- a/lib/libc/locale/setrunelocale.c +++ b/lib/libc/locale/setrunelocale.c @@ -56,6 +56,7 @@ extern int _UTF2_init(_RuneLocale *); extern int _UTF8_init(_RuneLocale *); extern int _EUC_init(_RuneLocale *); extern int _GB18030_init(_RuneLocale *); +extern int _GB2312_init(_RuneLocale *); extern int _GBK_init(_RuneLocale *); extern int _BIG5_init(_RuneLocale *); extern int _MSKanji_init(_RuneLocale *); @@ -157,6 +158,8 @@ __setrunelocale(const char *encoding) ret = _EUC_init(rl); else if (strcmp(rl->encoding, "GB18030") == 0) ret = _GB18030_init(rl); + else if (strcmp(rl->encoding, "GB2312") == 0) + ret = _GB2312_init(rl); else if (strcmp(rl->encoding, "GBK") == 0) ret = _GBK_init(rl); else if (strcmp(rl->encoding, "BIG5") == 0) diff --git a/usr.bin/mklocale/yacc.y b/usr.bin/mklocale/yacc.y index 8362517..92b4743 100644 --- a/usr.bin/mklocale/yacc.y +++ b/usr.bin/mklocale/yacc.y @@ -123,6 +123,7 @@ entry : ENCODING STRING strcmp($2, "EUC") && strcmp($2, "GBK") && strcmp($2, "GB18030") && + strcmp($2, "GB2312") && strcmp($2, "BIG5") && strcmp($2, "MSKanji")) warnx("ENCODING %s is not supported by libc", $2); |