X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/9385eb3d10ebe5eb398c52040ec3dbfba9b0cdcf..974e388456677d82eb6d10d4fd72390641a5bdfe:/locale/FreeBSD/euc.c diff --git a/locale/FreeBSD/euc.c b/locale/FreeBSD/euc.c index 02c46ba..5504b7b 100644 --- a/locale/FreeBSD/euc.c +++ b/locale/FreeBSD/euc.c @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved. * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * @@ -37,42 +38,56 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)euc.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ -#include -__FBSDID("$FreeBSD: src/lib/libc/locale/euc.c,v 1.11 2002/08/09 08:22:29 ache Exp $"); +#include +__FBSDID("$FreeBSD: src/lib/libc/locale/euc.c,v 1.22 2007/10/13 16:28:21 ache Exp $"); -#include +#include "xlocale_private.h" #include -#include -#include -#include +#include +#include #include #include +#include +#include "mblocal.h" -rune_t _EUC_sgetrune(const char *, size_t, char const **); -int _EUC_sputrune(rune_t, char *, size_t, char **); +static size_t _EUC_mbrtowc(wchar_t * __restrict, const char * __restrict, + size_t, mbstate_t * __restrict, locale_t); +static int _EUC_mbsinit(const mbstate_t *, locale_t); +static size_t _EUC_wcrtomb(char * __restrict, wchar_t, + mbstate_t * __restrict, locale_t); typedef struct { int count[4]; - rune_t bits[4]; - rune_t mask; + wchar_t bits[4]; + wchar_t mask; } _EucInfo; +typedef struct { + wchar_t ch; + int set; + int want; +} _EucState; + +/* This will be called by the XL_RELEASE() macro to free the extra storage */ +static void +_EUC_free_extra(struct __xlocale_st_runelocale *xrl) +{ + free(xrl->_CurrentRuneLocale.__variable); +} + int -_EUC_init(rl) - _RuneLocale *rl; +_EUC_init(struct __xlocale_st_runelocale *xrl) { _EucInfo *ei; int x, new__mb_cur_max; char *v, *e; + _RuneLocale *rl = &xrl->_CurrentRuneLocale; - rl->sgetrune = _EUC_sgetrune; - rl->sputrune = _EUC_sputrune; - - if (rl->variable == NULL) + if (rl->__variable == NULL) return (EFTYPE); - v = (char *)rl->variable; + v = (char *)rl->__variable; while (*v == ' ' || *v == '\t') ++v; @@ -104,119 +119,159 @@ _EUC_init(rl) free(ei); return (EFTYPE); } - rl->variable = ei; - rl->variable_len = sizeof(_EucInfo); - _CurrentRuneLocale = rl; - __mb_cur_max = new__mb_cur_max; + rl->__variable = ei; + rl->__variable_len = sizeof(_EucInfo); + xrl->__mb_cur_max = new__mb_cur_max; + xrl->__mbrtowc = _EUC_mbrtowc; + xrl->__wcrtomb = _EUC_wcrtomb; + xrl->__mbsinit = _EUC_mbsinit; + xrl->__mb_sb_limit = 256; + xrl->__free_extra = (__free_extra_t)_EUC_free_extra; return (0); } -#define CEI ((_EucInfo *)(_CurrentRuneLocale->variable)) +static int +_EUC_mbsinit(const mbstate_t *ps, locale_t loc __unused) +{ + + return (ps == NULL || ((const _EucState *)ps)->want == 0); +} #define _SS2 0x008e #define _SS3 0x008f #define GR_BITS 0x80808080 /* XXX: to be fixed */ -static inline int -_euc_set(c) - u_int c; +static __inline int +_euc_set(u_int c) { - c &= 0xff; + c &= 0xff; return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0); } -rune_t -_EUC_sgetrune(string, n, result) - const char *string; - size_t n; - char const **result; + +static size_t +_EUC_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n, + mbstate_t * __restrict ps, locale_t loc) { - rune_t rune = 0; - int len, set; + _EucState *es; + int i, set, want; + wchar_t wc; + const char *os; + struct __xlocale_st_runelocale *rl = loc->__lc_ctype; + _EucInfo *CEI = (_EucInfo *)rl->_CurrentRuneLocale.__variable; + + es = (_EucState *)ps; + + if (es->want < 0 || es->want > rl->__mb_cur_max || es->set < 0 || + es->set > 3) { + errno = EINVAL; + return ((size_t)-1); + } + + if (s == NULL) { + s = ""; + n = 1; + pwc = NULL; + } - if (n < 1 || (len = CEI->count[set = _euc_set(*string)]) > n) { - if (result) - *result = string; - return (_INVALID_RUNE); + if (n == 0) + /* Incomplete multibyte sequence */ + return ((size_t)-2); + + os = s; + + if (es->want == 0) { + want = CEI->count[set = _euc_set(*s)]; + if (set == 2 || set == 3) { + --want; + if (--n == 0) { + /* Incomplete multibyte sequence */ + es->set = set; + es->want = want; + es->ch = 0; + return ((size_t)-2); + } + ++s; + if (*s == '\0') { + errno = EILSEQ; + return ((size_t)-1); + } + } + wc = (unsigned char)*s++; + } else { + set = es->set; + want = es->want; + wc = es->ch; + } + for (i = (es->want == 0) ? 1 : 0; i < MIN(want, n); i++) { + if (*s == '\0') { + errno = EILSEQ; + return ((size_t)-1); + } + wc = (wc << 8) | (unsigned char)*s++; } - switch (set) { - case 3: - case 2: - --len; - ++string; - /* FALLTHROUGH */ - case 1: - case 0: - while (len-- > 0) - rune = (rune << 8) | ((u_int)(*string++) & 0xff); - break; + if (i < want) { + /* Incomplete multibyte sequence */ + es->set = set; + es->want = want - i; + es->ch = wc; + return ((size_t)-2); } - if (result) - *result = string; - return ((rune & ~CEI->mask) | CEI->bits[set]); + wc = (wc & ~CEI->mask) | CEI->bits[set]; + if (pwc != NULL) + *pwc = wc; + es->want = 0; + return (wc == L'\0' ? 0 : s - os); } -int -_EUC_sputrune(c, string, n, result) - rune_t c; - char *string, **result; - size_t n; +static size_t +_EUC_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t loc) { - rune_t m = c & CEI->mask; - rune_t nm = c & ~m; + _EucState *es; + wchar_t m, nm; int i, len; + _EucInfo *CEI = (_EucInfo *)loc->__lc_ctype->_CurrentRuneLocale.__variable; + + es = (_EucState *)ps; + + if (es->want != 0) { + errno = EINVAL; + return ((size_t)-1); + } + + if (s == NULL) + /* Reset to initial shift state (no-op) */ + return (1); + + m = wc & CEI->mask; + nm = wc & ~m; if (m == CEI->bits[1]) { CodeSet1: /* Codeset 1: The first byte must have 0x80 in it. */ i = len = CEI->count[1]; - if (n >= len) { - if (result) - *result = string + len; - while (i-- > 0) - *string++ = (nm >> (i << 3)) | 0x80; - } else - if (result) - *result = (char *) 0; + while (i-- > 0) + *s++ = (nm >> (i << 3)) | 0x80; } else { - if (m == CEI->bits[0]) { + if (m == CEI->bits[0]) i = len = CEI->count[0]; - if (n < len) { - if (result) - *result = NULL; - return (len); - } + else if (m == CEI->bits[2]) { + i = len = CEI->count[2]; + *s++ = _SS2; + --i; + /* SS2 designates G2 into GR */ + nm |= GR_BITS; + } else if (m == CEI->bits[3]) { + i = len = CEI->count[3]; + *s++ = _SS3; + --i; + /* SS3 designates G3 into GR */ + nm |= GR_BITS; } else - if (m == CEI->bits[2]) { - i = len = CEI->count[2]; - if (n < len) { - if (result) - *result = NULL; - return (len); - } - *string++ = _SS2; - --i; - /* SS2 designates G2 into GR */ - nm |= GR_BITS; - } else - if (m == CEI->bits[3]) { - i = len = CEI->count[3]; - if (n < len) { - if (result) - *result = NULL; - return (len); - } - *string++ = _SS3; - --i; - /* SS3 designates G3 into GR */ - nm |= GR_BITS; - } else - goto CodeSet1; /* Bletch */ + goto CodeSet1; /* Bletch */ while (i-- > 0) - *string++ = (nm >> (i << 3)) & 0xff; - if (result) - *result = string; + *s++ = (nm >> (i << 3)) & 0xff; } return (len); }