Index: head/contrib/netbsd-tests/lib/libc/locale/t_mbrtowc.c =================================================================== --- head/contrib/netbsd-tests/lib/libc/locale/t_mbrtowc.c (revision 340275) +++ head/contrib/netbsd-tests/lib/libc/locale/t_mbrtowc.c (revision 340276) @@ -1,275 +1,272 @@ /* $NetBSD: t_mbrtowc.c,v 1.1 2011/07/15 07:35:21 jruoho Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by YAMAMOTO Takashi * * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. */ /*- * Copyright (c)2003 Citrus Project, * 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 __COPYRIGHT("@(#) Copyright (c) 2011\ The NetBSD Foundation, inc. All rights reserved."); __RCSID("$NetBSD: t_mbrtowc.c,v 1.1 2011/07/15 07:35:21 jruoho Exp $"); #include #include #include #include #include #include #include #include #define SIZE 256 static struct test { const char *locale; const char *data; const wchar_t wchars[64]; const wchar_t widths[64]; size_t length; } tests[] = { { "C", "ABCD01234_\\", { 0x41, 0x42, 0x43, 0x44, 0x30, 0x31, 0x32, 0x33, 0x34, 0x5F, 0x5C }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 11 }, { "en_US.UTF-8", "[\001\177][\302\200\337\277][\340\240\200\357\277\277][\360\220\200" "\200\364\217\277\277]", { 0x5b, 0x01, 0x7f, 0x5d, 0x5b, 0x80, 0x7ff, 0x5d, 0x5b, 0x800, 0xffff, 0x5d, 0x5b, 0x10000, 0x10ffff, 0x5d }, { 1, 1, 1, 1, 1, 2, 2, 1, 1, 3, 3, 1, 1, 4, 4, 1 }, 16 }, { "ja_JP.ISO2022-JP2", "\033$BF|K\1348l\033(BA\033$B$\"\033(BB\033$B$$\033(B", { 0x4200467c, 0x42004b5c, 0x4200386c, 0x41, 0x42002422, 0x42, 0x42002424 }, { 5, 2, 2, 4, 5, 4, 5 }, 7 }, { "ja_JP.SJIS", "\223\372\226{\214\352A\202\240B\202\242", { 0x93fa, 0x967b, 0x8cea, 0x41, 0x82a0, 0x42, 0x82a2 }, { 2, 2, 2, 1, 2, 1, 2 }, 7 }, { "ja_JP.eucJP", "\306\374\313\334\270\354A\244\242B\244\244", { 0xc6fc, 0xcbdc, 0xb8ec, 0x41, 0xa4a2, 0x42, 0xa4a4 }, { 2, 2, 2, 1, 2, 1, 2 }, 7 }, { NULL, NULL, { }, { }, 0 } }; static void h_ctype2(const struct test *t, bool use_mbstate) { mbstate_t *stp; mbstate_t st; char buf[SIZE]; char *str; size_t n; ATF_REQUIRE_STREQ(setlocale(LC_ALL, "C"), "C"); #ifdef __NetBSD__ ATF_REQUIRE(setlocale(LC_CTYPE, t->locale) != NULL); #else if (setlocale(LC_CTYPE, t->locale) == NULL) { fprintf(stderr, "Locale %s not found.\n", t->locale); return; } #endif (void)strvis(buf, t->data, VIS_WHITE | VIS_OCTAL); (void)printf("Checking string: \"%s\"\n", buf); ATF_REQUIRE((str = setlocale(LC_ALL, NULL)) != NULL); (void)printf("Using locale: %s\n", str); (void)printf("Using mbstate: %s\n", use_mbstate ? "yes" : "no"); (void)memset(&st, 0, sizeof(st)); // mbrtowc(0, 0, 0, &st); /* XXX for ISO2022-JP */ stp = use_mbstate ? &st : 0; for (n = 9; n > 0; n--) { const char *src = t->data; wchar_t dst; size_t nchar = 0; int width = 0; ATF_REQUIRE(mbsinit(stp) != 0); for (;;) { size_t rv = mbrtowc(&dst, src, n, stp); if (rv == 0) break; if (rv == (size_t)-2) { src += n; width += n; continue; } if (rv == (size_t)-1) { ATF_REQUIRE_EQ(errno, EILSEQ); atf_tc_fail("Invalid sequence"); /* NOTREACHED */ } width += rv; src += rv; if (dst != t->wchars[nchar] || width != t->widths[nchar]) { (void)printf("At position %zd:\n", nchar); (void)printf(" expected: 0x%04X (%u)\n", t->wchars[nchar], t->widths[nchar]); (void)printf(" got : 0x%04X (%u)\n", dst, width); atf_tc_fail("Test failed"); } nchar++; width = 0; } ATF_REQUIRE_EQ_MSG(dst, 0, "Incorrect terminating character: " "0x%04X (expected: 0x00)", dst); ATF_REQUIRE_EQ_MSG(nchar, t->length, "Incorrect length: " "%zd (expected: %zd)", nchar, t->length); } { wchar_t wbuf[SIZE]; size_t rv; char const *src = t->data; int i; (void)memset(wbuf, 0xFF, sizeof(wbuf)); rv = mbsrtowcs(wbuf, &src, SIZE, stp); ATF_REQUIRE_EQ_MSG(rv, t->length, "Incorrect length: %zd " "(expected: %zd)", rv, t->length); ATF_REQUIRE_EQ(src, NULL); for (i = 0; wbuf[i] != 0; ++i) { if (wbuf[i] == t->wchars[i]) continue; (void)printf("At position %d:\n", i); (void)printf(" expected: 0x%04X\n", t->wchars[i]); (void)printf(" got : 0x%04X\n", wbuf[i]); atf_tc_fail("Test failed"); } ATF_REQUIRE_EQ_MSG((size_t)i, t->length, "Incorrect length: " "%d (expected: %zd)", i, t->length); } (void)printf("Ok.\n"); } ATF_TC(mbrtowc_internal); ATF_TC_HEAD(mbrtowc_internal, tc) { atf_tc_set_md_var(tc, "descr", "Checks mbrtowc(3) and mbsrtowcs(3) (using internal " "state) with different locales"); } ATF_TC_BODY(mbrtowc_internal, tc) { struct test *t; -#ifdef __FreeBSD__ - atf_tc_expect_fail("ja_* locale fails"); -#endif for (t = &tests[0]; t->data != NULL; ++t) h_ctype2(t, false); } ATF_TC(mbrtowc_object); ATF_TC_HEAD(mbrtowc_object, tc) { atf_tc_set_md_var(tc, "descr", "Checks mbrtowc(3) and mbsrtowcs(3) (using state " "object) with different locales"); } ATF_TC_BODY(mbrtowc_object, tc) { struct test *t; for (t = &tests[0]; t->data != NULL; ++t) h_ctype2(t, true); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, mbrtowc_internal); ATF_TP_ADD_TC(tp, mbrtowc_object); return atf_no_error(); } Index: head/lib/libc/locale/cXXrtomb_iconv.h =================================================================== --- head/lib/libc/locale/cXXrtomb_iconv.h (revision 340275) +++ head/lib/libc/locale/cXXrtomb_iconv.h (revision 340276) @@ -1,117 +1,117 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2013 Ed Schouten * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include "../iconv/citrus_hash.h" #include "../iconv/citrus_module.h" #include "../iconv/citrus_iconv.h" -#include "xlocale_private.h" +#include "mblocal.h" typedef struct { bool initialized; struct _citrus_iconv iconv; union { charXX_t widechar[SRCBUF_LEN]; char bytes[sizeof(charXX_t) * SRCBUF_LEN]; } srcbuf; size_t srcbuf_len; } _ConversionState; _Static_assert(sizeof(_ConversionState) <= sizeof(mbstate_t), "Size of _ConversionState must not exceed mbstate_t's size."); size_t cXXrtomb_l(char * __restrict s, charXX_t c, mbstate_t * __restrict ps, locale_t locale) { _ConversionState *cs; struct _citrus_iconv *handle; char *src, *dst; size_t srcleft, dstleft, invlen; int err; FIX_LOCALE(locale); if (ps == NULL) - ps = &locale->cXXrtomb; + ps = &(XLOCALE_CTYPE(locale)->cXXrtomb); cs = (_ConversionState *)ps; handle = &cs->iconv; /* Reinitialize mbstate_t. */ if (s == NULL || !cs->initialized) { if (_citrus_iconv_open(&handle, UTF_XX_INTERNAL, nl_langinfo_l(CODESET, locale)) != 0) { cs->initialized = false; errno = EINVAL; return (-1); } handle->cv_shared->ci_discard_ilseq = true; handle->cv_shared->ci_hooks = NULL; cs->srcbuf_len = 0; cs->initialized = true; if (s == NULL) return (1); } assert(cs->srcbuf_len < sizeof(cs->srcbuf.widechar) / sizeof(charXX_t)); cs->srcbuf.widechar[cs->srcbuf_len++] = c; /* Perform conversion. */ src = cs->srcbuf.bytes; srcleft = cs->srcbuf_len * sizeof(charXX_t); dst = s; dstleft = MB_CUR_MAX_L(locale); err = _citrus_iconv_convert(handle, &src, &srcleft, &dst, &dstleft, 0, &invlen); /* Character is part of a surrogate pair. We need more input. */ if (err == EINVAL) return (0); cs->srcbuf_len = 0; /* Illegal sequence. */ if (dst == s) { errno = EILSEQ; return ((size_t)-1); } return (dst - s); } size_t cXXrtomb(char * __restrict s, charXX_t c, mbstate_t * __restrict ps) { return (cXXrtomb_l(s, c, ps, __get_locale())); } Index: head/lib/libc/locale/mblen.c =================================================================== --- head/lib/libc/locale/mblen.c (revision 340275) +++ head/lib/libc/locale/mblen.c (revision 340276) @@ -1,63 +1,64 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. * Portions of this software were developed by David Chisnall * under sponsorship from the FreeBSD Foundation. * * 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 __FBSDID("$FreeBSD$"); #include #include #include "mblocal.h" int mblen_l(const char *s, size_t n, locale_t locale) { static const mbstate_t initial; size_t rval; FIX_LOCALE(locale); if (s == NULL) { /* No support for state dependent encodings. */ - locale->mblen = initial; + XLOCALE_CTYPE(locale)->mblen = initial; return (0); } - rval = XLOCALE_CTYPE(locale)->__mbrtowc(NULL, s, n, &locale->mblen); + rval = XLOCALE_CTYPE(locale)->__mbrtowc(NULL, s, n, + &(XLOCALE_CTYPE(locale)->mblen)); if (rval == (size_t)-1 || rval == (size_t)-2) return (-1); return ((int)rval); } int mblen(const char *s, size_t n) { return mblen_l(s, n, __get_locale()); } Index: head/lib/libc/locale/mblocal.h =================================================================== --- head/lib/libc/locale/mblocal.h (revision 340275) +++ head/lib/libc/locale/mblocal.h (revision 340276) @@ -1,92 +1,120 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright 2013 Garrett D'Amore * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2004 Tim J. Robbins. * All rights reserved. * * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. * Portions of this software were developed by David Chisnall * under sponsorship from the FreeBSD Foundation. * * 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. * * $FreeBSD$ */ #ifndef _MBLOCAL_H_ #define _MBLOCAL_H_ #include #include "xlocale_private.h" #define SS2 0x008e #define SS3 0x008f /* * Conversion function pointers for current encoding. */ struct xlocale_ctype { struct xlocale_component header; _RuneLocale *runes; size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, size_t, mbstate_t * __restrict); int (*__mbsinit)(const mbstate_t *); size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict, size_t, size_t, mbstate_t * __restrict); size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict); size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict, size_t, size_t, mbstate_t * __restrict); int __mb_cur_max; int __mb_sb_limit; + /** Persistent state used by mblen() calls. */ + __mbstate_t mblen; + /** Persistent state used by mbrlen() calls. */ + __mbstate_t mbrlen; + /** Persistent state used by mbrtoc16() calls. */ + __mbstate_t mbrtoc16; + /** Persistent state used by mbrtoc32() calls. */ + __mbstate_t mbrtoc32; + /** Persistent state used by mbrtowc() calls. */ + __mbstate_t mbrtowc; + /** Persistent state used by mbsnrtowcs() calls. */ + __mbstate_t mbsnrtowcs; + /** Persistent state used by mbsrtowcs() calls. */ + __mbstate_t mbsrtowcs; + /** Persistent state used by mbtowc() calls. */ + __mbstate_t mbtowc; + /** Persistent state used by c16rtomb() calls. */ + __mbstate_t c16rtomb; + /** Persistent state used by c32rtomb() calls. */ + __mbstate_t c32rtomb; + /** Persistent state used by wcrtomb() calls. */ + __mbstate_t wcrtomb; + /** Persistent state used by wcsnrtombs() calls. */ + __mbstate_t wcsnrtombs; + /** Persistent state used by wcsrtombs() calls. */ + __mbstate_t wcsrtombs; + /** Persistent state used by wctomb() calls. */ + __mbstate_t wctomb; }; #define XLOCALE_CTYPE(x) ((struct xlocale_ctype*)(x)->components[XLC_CTYPE]) extern struct xlocale_ctype __xlocale_global_ctype; /* * Rune initialization function prototypes. */ int _none_init(struct xlocale_ctype *, _RuneLocale *) __hidden; int _UTF8_init(struct xlocale_ctype *, _RuneLocale *) __hidden; int _EUC_CN_init(struct xlocale_ctype *, _RuneLocale *) __hidden; int _EUC_JP_init(struct xlocale_ctype *, _RuneLocale *) __hidden; int _EUC_KR_init(struct xlocale_ctype *, _RuneLocale *) __hidden; int _EUC_TW_init(struct xlocale_ctype *, _RuneLocale *) __hidden; int _GB18030_init(struct xlocale_ctype *, _RuneLocale *) __hidden; int _GB2312_init(struct xlocale_ctype *, _RuneLocale *) __hidden; int _GBK_init(struct xlocale_ctype *, _RuneLocale *) __hidden; int _BIG5_init(struct xlocale_ctype *, _RuneLocale *) __hidden; int _MSKanji_init(struct xlocale_ctype *, _RuneLocale *) __hidden; int _ascii_init(struct xlocale_ctype *, _RuneLocale *) __hidden; typedef size_t (*mbrtowc_pfn_t)(wchar_t * __restrict, const char * __restrict, size_t, mbstate_t * __restrict); typedef size_t (*wcrtomb_pfn_t)(char * __restrict, wchar_t, mbstate_t * __restrict); size_t __mbsnrtowcs_std(wchar_t * __restrict, const char ** __restrict, size_t, size_t, mbstate_t * __restrict, mbrtowc_pfn_t); size_t __wcsnrtombs_std(char * __restrict, const wchar_t ** __restrict, size_t, size_t, mbstate_t * __restrict, wcrtomb_pfn_t); #endif /* _MBLOCAL_H_ */ Index: head/lib/libc/locale/mbrlen.c =================================================================== --- head/lib/libc/locale/mbrlen.c (revision 340275) +++ head/lib/libc/locale/mbrlen.c (revision 340276) @@ -1,53 +1,53 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. * Portions of this software were developed by David Chisnall * under sponsorship from the FreeBSD Foundation. * * 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 __FBSDID("$FreeBSD$"); #include #include "mblocal.h" size_t mbrlen_l(const char * __restrict s, size_t n, mbstate_t * __restrict ps, locale_t locale) { FIX_LOCALE(locale); if (ps == NULL) - ps = &locale->mbrlen; + ps = &(XLOCALE_CTYPE(locale)->mbrlen); return (XLOCALE_CTYPE(locale)->__mbrtowc(NULL, s, n, ps)); } size_t mbrlen(const char * __restrict s, size_t n, mbstate_t * __restrict ps) { return mbrlen_l(s, n, ps, __get_locale()); } Index: head/lib/libc/locale/mbrtocXX_iconv.h =================================================================== --- head/lib/libc/locale/mbrtocXX_iconv.h (revision 340275) +++ head/lib/libc/locale/mbrtocXX_iconv.h (revision 340276) @@ -1,160 +1,160 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2013 Ed Schouten * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include "../iconv/citrus_hash.h" #include "../iconv/citrus_module.h" #include "../iconv/citrus_iconv.h" -#include "xlocale_private.h" +#include "mblocal.h" typedef struct { bool initialized; struct _citrus_iconv iconv; char srcbuf[MB_LEN_MAX]; size_t srcbuf_len; union { charXX_t widechar[DSTBUF_LEN]; char bytes[sizeof(charXX_t) * DSTBUF_LEN]; } dstbuf; size_t dstbuf_len; } _ConversionState; _Static_assert(sizeof(_ConversionState) <= sizeof(mbstate_t), "Size of _ConversionState must not exceed mbstate_t's size."); size_t mbrtocXX_l(charXX_t * __restrict pc, const char * __restrict s, size_t n, mbstate_t * __restrict ps, locale_t locale) { _ConversionState *cs; struct _citrus_iconv *handle; size_t i, retval; charXX_t retchar; FIX_LOCALE(locale); if (ps == NULL) - ps = &locale->mbrtocXX; + ps = &(XLOCALE_CTYPE(locale)->mbrtocXX); cs = (_ConversionState *)ps; handle = &cs->iconv; /* Reinitialize mbstate_t. */ if (s == NULL || !cs->initialized) { if (_citrus_iconv_open(&handle, nl_langinfo_l(CODESET, locale), UTF_XX_INTERNAL) != 0) { cs->initialized = false; errno = EINVAL; return (-1); } handle->cv_shared->ci_discard_ilseq = true; handle->cv_shared->ci_hooks = NULL; cs->srcbuf_len = cs->dstbuf_len = 0; cs->initialized = true; if (s == NULL) return (0); } /* See if we still have characters left from the previous invocation. */ if (cs->dstbuf_len > 0) { retval = (size_t)-3; goto return_char; } /* Fill up the read buffer as far as possible. */ if (n > sizeof(cs->srcbuf) - cs->srcbuf_len) n = sizeof(cs->srcbuf) - cs->srcbuf_len; memcpy(cs->srcbuf + cs->srcbuf_len, s, n); /* Convert as few characters to the dst buffer as possible. */ for (i = 0; ; i++) { char *src, *dst; size_t srcleft, dstleft, invlen; int err; src = cs->srcbuf; srcleft = cs->srcbuf_len + n; dst = cs->dstbuf.bytes; dstleft = i * sizeof(charXX_t); assert(srcleft <= sizeof(cs->srcbuf) && dstleft <= sizeof(cs->dstbuf.bytes)); err = _citrus_iconv_convert(handle, &src, &srcleft, &dst, &dstleft, 0, &invlen); cs->dstbuf_len = (dst - cs->dstbuf.bytes) / sizeof(charXX_t); /* Got new character(s). Return the first. */ if (cs->dstbuf_len > 0) { assert(src - cs->srcbuf > cs->srcbuf_len); retval = src - cs->srcbuf - cs->srcbuf_len; cs->srcbuf_len = 0; goto return_char; } /* Increase dst buffer size, to obtain the surrogate pair. */ if (err == E2BIG) continue; /* Illegal sequence. */ if (invlen > 0) { cs->srcbuf_len = 0; errno = EILSEQ; return ((size_t)-1); } /* Save unprocessed remainder for the next invocation. */ memmove(cs->srcbuf, src, srcleft); cs->srcbuf_len = srcleft; return ((size_t)-2); } return_char: retchar = cs->dstbuf.widechar[0]; memmove(&cs->dstbuf.widechar[0], &cs->dstbuf.widechar[1], --cs->dstbuf_len * sizeof(charXX_t)); if (pc != NULL) *pc = retchar; if (retchar == 0) return (0); return (retval); } size_t mbrtocXX(charXX_t * __restrict pc, const char * __restrict s, size_t n, mbstate_t * __restrict ps) { return (mbrtocXX_l(pc, s, n, ps, __get_locale())); } Index: head/lib/libc/locale/mbrtowc.c =================================================================== --- head/lib/libc/locale/mbrtowc.c (revision 340275) +++ head/lib/libc/locale/mbrtowc.c (revision 340276) @@ -1,55 +1,55 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. * Portions of this software were developed by David Chisnall * under sponsorship from the FreeBSD Foundation. * * 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 __FBSDID("$FreeBSD$"); #include #include "mblocal.h" size_t mbrtowc_l(wchar_t * __restrict pwc, const char * __restrict s, size_t n, mbstate_t * __restrict ps, locale_t locale) { FIX_LOCALE(locale); if (ps == NULL) - ps = &locale->mbrtowc; + ps = &(XLOCALE_CTYPE(locale)->mbrtowc); return (XLOCALE_CTYPE(locale)->__mbrtowc(pwc, s, n, ps)); } size_t mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n, mbstate_t * __restrict ps) { return mbrtowc_l(pwc, s, n, ps, __get_locale()); } Index: head/lib/libc/locale/mbsnrtowcs.c =================================================================== --- head/lib/libc/locale/mbsnrtowcs.c (revision 340275) +++ head/lib/libc/locale/mbsnrtowcs.c (revision 340276) @@ -1,106 +1,106 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright 2013 Garrett D'Amore * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2002-2004 Tim J. Robbins. * * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. * Portions of this software were developed by David Chisnall * under sponsorship from the FreeBSD Foundation. * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include "mblocal.h" size_t mbsnrtowcs_l(wchar_t * __restrict dst, const char ** __restrict src, size_t nms, size_t len, mbstate_t * __restrict ps, locale_t locale) { FIX_LOCALE(locale); if (ps == NULL) - ps = &locale->mbsnrtowcs; + ps = &(XLOCALE_CTYPE(locale)->mbsnrtowcs); return (XLOCALE_CTYPE(locale)->__mbsnrtowcs(dst, src, nms, len, ps)); } size_t mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src, size_t nms, size_t len, mbstate_t * __restrict ps) { return mbsnrtowcs_l(dst, src, nms, len, ps, __get_locale()); } size_t __mbsnrtowcs_std(wchar_t * __restrict dst, const char ** __restrict src, size_t nms, size_t len, mbstate_t * __restrict ps, mbrtowc_pfn_t pmbrtowc) { const char *s; size_t nchr; wchar_t wc; size_t nb; s = *src; nchr = 0; if (dst == NULL) { for (;;) { if ((nb = pmbrtowc(&wc, s, nms, ps)) == (size_t)-1) /* Invalid sequence - mbrtowc() sets errno. */ return ((size_t)-1); else if (nb == 0 || nb == (size_t)-2) return (nchr); s += nb; nms -= nb; nchr++; } /*NOTREACHED*/ } while (len-- > 0) { if ((nb = pmbrtowc(dst, s, nms, ps)) == (size_t)-1) { *src = s; return ((size_t)-1); } else if (nb == (size_t)-2) { *src = s + nms; return (nchr); } else if (nb == 0) { *src = NULL; return (nchr); } s += nb; nms -= nb; nchr++; dst++; } *src = s; return (nchr); } Index: head/lib/libc/locale/mbsrtowcs.c =================================================================== --- head/lib/libc/locale/mbsrtowcs.c (revision 340275) +++ head/lib/libc/locale/mbsrtowcs.c (revision 340276) @@ -1,57 +1,57 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. * Portions of this software were developed by David Chisnall * under sponsorship from the FreeBSD Foundation. * * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include "mblocal.h" size_t mbsrtowcs_l(wchar_t * __restrict dst, const char ** __restrict src, size_t len, mbstate_t * __restrict ps, locale_t locale) { FIX_LOCALE(locale); if (ps == NULL) - ps = &locale->mbsrtowcs; + ps = &(XLOCALE_CTYPE(locale)->mbsrtowcs); return (XLOCALE_CTYPE(locale)->__mbsnrtowcs(dst, src, SIZE_T_MAX, len, ps)); } size_t mbsrtowcs(wchar_t * __restrict dst, const char ** __restrict src, size_t len, mbstate_t * __restrict ps) { return mbsrtowcs_l(dst, src, len, ps, __get_locale()); } Index: head/lib/libc/locale/mbtowc.c =================================================================== --- head/lib/libc/locale/mbtowc.c (revision 340275) +++ head/lib/libc/locale/mbtowc.c (revision 340276) @@ -1,69 +1,70 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. * Portions of this software were developed by David Chisnall * under sponsorship from the FreeBSD Foundation. * * 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 __FBSDID("$FreeBSD$"); #include #include #include #include "mblocal.h" int mbtowc_l(wchar_t * __restrict pwc, const char * __restrict s, size_t n, locale_t locale) { static const mbstate_t initial; size_t rval; FIX_LOCALE(locale); if (s == NULL) { /* No support for state dependent encodings. */ - locale->mbtowc = initial; + XLOCALE_CTYPE(locale)->mbtowc = initial; return (0); } - rval = XLOCALE_CTYPE(locale)->__mbrtowc(pwc, s, n, &locale->mbtowc); + rval = XLOCALE_CTYPE(locale)->__mbrtowc(pwc, s, n, + &(XLOCALE_CTYPE(locale)->mbtowc)); switch (rval) { case (size_t)-2: errno = EILSEQ; /* FALLTHROUGH */ case (size_t)-1: return (-1); default: return ((int)rval); } } int mbtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n) { return mbtowc_l(pwc, s, n, __get_locale()); } Index: head/lib/libc/locale/setrunelocale.c =================================================================== --- head/lib/libc/locale/setrunelocale.c (revision 340275) +++ head/lib/libc/locale/setrunelocale.c (revision 340276) @@ -1,213 +1,228 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Paul Borman at Krystal Technologies. * * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. * Portions of this software were developed by David Chisnall * under sponsorship from the FreeBSD Foundation. * * 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. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 __FBSDID("$FreeBSD$"); #define __RUNETYPE_INTERNAL 1 #include #include #include #include #include #include #include #include #include "ldpart.h" #include "mblocal.h" #include "setlocale.h" #undef _CurrentRuneLocale extern _RuneLocale const *_CurrentRuneLocale; #ifndef __NO_TLS /* * A cached version of the runes for this thread. Used by ctype.h */ _Thread_local const _RuneLocale *_ThreadRuneLocale; #endif extern int __mb_sb_limit; extern _RuneLocale *_Read_RuneMagi(const char *); static int __setrunelocale(struct xlocale_ctype *l, const char *); static void destruct_ctype(void *v) { struct xlocale_ctype *l = v; if (&_DefaultRuneLocale != l->runes) free(l->runes); free(l); } const _RuneLocale * __getCurrentRuneLocale(void) { return (XLOCALE_CTYPE(__get_locale())->runes); } static void free_runes(_RuneLocale *rl) { if ((rl != &_DefaultRuneLocale) && (rl)) { free(rl); } } static int __setrunelocale(struct xlocale_ctype *l, const char *encoding) { _RuneLocale *rl; int ret; char *path; struct xlocale_ctype saved = *l; /* * The "C" and "POSIX" locale are always here. */ if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) { free_runes(saved.runes); (void) _none_init(l, (_RuneLocale*)&_DefaultRuneLocale); return (0); } /* Range checking not needed, encoding length already checked before */ if (asprintf(&path, "%s/%s/LC_CTYPE", _PathLocale, encoding) == -1) return (errno); if ((rl = _Read_RuneMagi(path)) == NULL) { free(path); errno = EINVAL; return (errno); } free(path); l->__mbrtowc = NULL; l->__mbsinit = NULL; l->__mbsnrtowcs = NULL; l->__wcrtomb = NULL; l->__wcsnrtombs = NULL; rl->__sputrune = NULL; rl->__sgetrune = NULL; if (strcmp(rl->__encoding, "NONE:US-ASCII") == 0) ret = _ascii_init(l, rl); else if (strncmp(rl->__encoding, "NONE", 4) == 0) ret = _none_init(l, rl); else if (strcmp(rl->__encoding, "UTF-8") == 0) ret = _UTF8_init(l, rl); else if (strcmp(rl->__encoding, "EUC-CN") == 0) ret = _EUC_CN_init(l, rl); else if (strcmp(rl->__encoding, "EUC-JP") == 0) ret = _EUC_JP_init(l, rl); else if (strcmp(rl->__encoding, "EUC-KR") == 0) ret = _EUC_KR_init(l, rl); else if (strcmp(rl->__encoding, "EUC-TW") == 0) ret = _EUC_TW_init(l, rl); else if (strcmp(rl->__encoding, "GB18030") == 0) ret = _GB18030_init(l, rl); else if (strcmp(rl->__encoding, "GB2312") == 0) ret = _GB2312_init(l, rl); else if (strcmp(rl->__encoding, "GBK") == 0) ret = _GBK_init(l, rl); else if (strcmp(rl->__encoding, "BIG5") == 0) ret = _BIG5_init(l, rl); else if (strcmp(rl->__encoding, "MSKanji") == 0) ret = _MSKanji_init(l, rl); else ret = EFTYPE; if (ret == 0) { /* Free the old runes if it exists. */ free_runes(saved.runes); + /* Reset the mbstates */ + memset(&l->c16rtomb, 0, sizeof(l->c16rtomb)); + memset(&l->c32rtomb, 0, sizeof(l->c32rtomb)); + memset(&l->mblen, 0, sizeof(l->mblen)); + memset(&l->mbrlen, 0, sizeof(l->mbrlen)); + memset(&l->mbrtoc16, 0, sizeof(l->mbrtoc16)); + memset(&l->mbrtoc32, 0, sizeof(l->mbrtoc32)); + memset(&l->mbrtowc, 0, sizeof(l->mbrtowc)); + memset(&l->mbsnrtowcs, 0, sizeof(l->mbsnrtowcs)); + memset(&l->mbsrtowcs, 0, sizeof(l->mbsrtowcs)); + memset(&l->mbtowc, 0, sizeof(l->mbtowc)); + memset(&l->wcrtomb, 0, sizeof(l->wcrtomb)); + memset(&l->wcsnrtombs, 0, sizeof(l->wcsnrtombs)); + memset(&l->wcsrtombs, 0, sizeof(l->wcsrtombs)); + memset(&l->wctomb, 0, sizeof(l->wctomb)); } else { /* Restore the saved version if this failed. */ memcpy(l, &saved, sizeof(struct xlocale_ctype)); free(rl); } return (ret); } int __wrap_setrunelocale(const char *locale) { int ret = __setrunelocale(&__xlocale_global_ctype, locale); if (ret != 0) { errno = ret; return (_LDP_ERROR); } __mb_cur_max = __xlocale_global_ctype.__mb_cur_max; __mb_sb_limit = __xlocale_global_ctype.__mb_sb_limit; _CurrentRuneLocale = __xlocale_global_ctype.runes; return (_LDP_LOADED); } #ifndef __NO_TLS void __set_thread_rune_locale(locale_t loc) { if (loc == NULL) { _ThreadRuneLocale = &_DefaultRuneLocale; } else if (loc == LC_GLOBAL_LOCALE) { _ThreadRuneLocale = 0; } else { _ThreadRuneLocale = XLOCALE_CTYPE(loc)->runes; } } #endif void * __ctype_load(const char *locale, locale_t unused __unused) { struct xlocale_ctype *l = calloc(sizeof(struct xlocale_ctype), 1); l->header.header.destructor = destruct_ctype; if (__setrunelocale(l, locale)) { free(l); return (NULL); } return (l); } Index: head/lib/libc/locale/wcrtomb.c =================================================================== --- head/lib/libc/locale/wcrtomb.c (revision 340275) +++ head/lib/libc/locale/wcrtomb.c (revision 340276) @@ -1,54 +1,54 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. * Portions of this software were developed by David Chisnall * under sponsorship from the FreeBSD Foundation. * * 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 __FBSDID("$FreeBSD$"); #include #include "mblocal.h" size_t wcrtomb_l(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, locale_t locale) { FIX_LOCALE(locale); if (ps == NULL) - ps = &locale->wcrtomb; + ps = &(XLOCALE_CTYPE(locale)->wcrtomb); return (XLOCALE_CTYPE(locale)->__wcrtomb(s, wc, ps)); } size_t wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) { return wcrtomb_l(s, wc, ps, __get_locale()); } Index: head/lib/libc/locale/wcsnrtombs.c =================================================================== --- head/lib/libc/locale/wcsnrtombs.c (revision 340275) +++ head/lib/libc/locale/wcsnrtombs.c (revision 340276) @@ -1,127 +1,127 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright 2013 Garrett D'Amore * Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. * Portions of this software were developed by David Chisnall * under sponsorship from the FreeBSD Foundation. * * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include "mblocal.h" size_t wcsnrtombs_l(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc, size_t len, mbstate_t * __restrict ps, locale_t locale) { FIX_LOCALE(locale); if (ps == NULL) - ps = &locale->wcsnrtombs; + ps = &(XLOCALE_CTYPE(locale)->wcsnrtombs); return (XLOCALE_CTYPE(locale)->__wcsnrtombs(dst, src, nwc, len, ps)); } size_t wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc, size_t len, mbstate_t * __restrict ps) { return wcsnrtombs_l(dst, src, nwc, len, ps, __get_locale()); } size_t __wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc, size_t len, mbstate_t * __restrict ps, wcrtomb_pfn_t pwcrtomb) { mbstate_t mbsbak; char buf[MB_LEN_MAX]; const wchar_t *s; size_t nbytes; size_t nb; s = *src; nbytes = 0; if (dst == NULL) { while (nwc-- > 0) { if ((nb = pwcrtomb(buf, *s, ps)) == (size_t)-1) /* Invalid character - wcrtomb() sets errno. */ return ((size_t)-1); else if (*s == L'\0') return (nbytes + nb - 1); s++; nbytes += nb; } return (nbytes); } while (len > 0 && nwc-- > 0) { if (len > (size_t)MB_CUR_MAX) { /* Enough space to translate in-place. */ if ((nb = pwcrtomb(dst, *s, ps)) == (size_t)-1) { *src = s; return ((size_t)-1); } } else { /* * May not be enough space; use temp. buffer. * * We need to save a copy of the conversion state * here so we can restore it if the multibyte * character is too long for the buffer. */ mbsbak = *ps; if ((nb = pwcrtomb(buf, *s, ps)) == (size_t)-1) { *src = s; return ((size_t)-1); } if (nb > (int)len) { /* MB sequence for character won't fit. */ *ps = mbsbak; break; } memcpy(dst, buf, nb); } if (*s == L'\0') { *src = NULL; return (nbytes + nb - 1); } s++; dst += nb; len -= nb; nbytes += nb; } *src = s; return (nbytes); } Index: head/lib/libc/locale/wcsrtombs.c =================================================================== --- head/lib/libc/locale/wcsrtombs.c (revision 340275) +++ head/lib/libc/locale/wcsrtombs.c (revision 340276) @@ -1,58 +1,58 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. * Portions of this software were developed by David Chisnall * under sponsorship from the FreeBSD Foundation. * * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include "mblocal.h" size_t wcsrtombs_l(char * __restrict dst, const wchar_t ** __restrict src, size_t len, mbstate_t * __restrict ps, locale_t locale) { FIX_LOCALE(locale); if (ps == NULL) - ps = &locale->wcsrtombs; + ps = &(XLOCALE_CTYPE(locale)->wcsrtombs); return (XLOCALE_CTYPE(locale)->__wcsnrtombs(dst, src, SIZE_T_MAX, len, ps)); } size_t wcsrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t len, mbstate_t * __restrict ps) { return wcsrtombs_l(dst, src, len, ps, __get_locale()); } Index: head/lib/libc/locale/wctomb.c =================================================================== --- head/lib/libc/locale/wctomb.c (revision 340275) +++ head/lib/libc/locale/wctomb.c (revision 340276) @@ -1,61 +1,62 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. * Portions of this software were developed by David Chisnall * under sponsorship from the FreeBSD Foundation. * * 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 __FBSDID("$FreeBSD$"); #include #include #include "mblocal.h" int wctomb_l(char *s, wchar_t wchar, locale_t locale) { static const mbstate_t initial; size_t rval; FIX_LOCALE(locale); if (s == NULL) { /* No support for state dependent encodings. */ - locale->wctomb = initial; + XLOCALE_CTYPE(locale)->wctomb = initial; return (0); } - if ((rval = XLOCALE_CTYPE(locale)->__wcrtomb(s, wchar, &locale->wctomb)) == (size_t)-1) + if ((rval = XLOCALE_CTYPE(locale)->__wcrtomb(s, wchar, + &(XLOCALE_CTYPE(locale)->wctomb))) == (size_t)-1) return (-1); return ((int)rval); } int wctomb(char *s, wchar_t wchar) { return wctomb_l(s, wchar, __get_locale()); } Index: head/lib/libc/locale/xlocale_private.h =================================================================== --- head/lib/libc/locale/xlocale_private.h (revision 340275) +++ head/lib/libc/locale/xlocale_private.h (revision 340276) @@ -1,254 +1,226 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. * * This software was developed by David Chisnall under sponsorship from * the FreeBSD Foundation. * * 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. * * $FreeBSD$ */ #ifndef _XLOCALE_PRIVATE__H_ #define _XLOCALE_PRIVATE__H_ #include #include #include #include #include #include #include "setlocale.h" /** * The XLC_ values are indexes into the components array. They are defined in * the same order as the LC_ values in locale.h, but without the LC_ALL zero * value. Translating from LC_X to XLC_X is done by subtracting one. * * Any reordering of this enum should ensure that these invariants are not * violated. */ enum { XLC_COLLATE = 0, XLC_CTYPE, XLC_MONETARY, XLC_NUMERIC, XLC_TIME, XLC_MESSAGES, XLC_LAST }; _Static_assert(XLC_LAST - XLC_COLLATE == 6, "XLC values should be contiguous"); _Static_assert(XLC_COLLATE == LC_COLLATE - 1, "XLC_COLLATE doesn't match the LC_COLLATE value."); _Static_assert(XLC_CTYPE == LC_CTYPE - 1, "XLC_CTYPE doesn't match the LC_CTYPE value."); _Static_assert(XLC_MONETARY == LC_MONETARY - 1, "XLC_MONETARY doesn't match the LC_MONETARY value."); _Static_assert(XLC_NUMERIC == LC_NUMERIC - 1, "XLC_NUMERIC doesn't match the LC_NUMERIC value."); _Static_assert(XLC_TIME == LC_TIME - 1, "XLC_TIME doesn't match the LC_TIME value."); _Static_assert(XLC_MESSAGES == LC_MESSAGES - 1, "XLC_MESSAGES doesn't match the LC_MESSAGES value."); /** * Header used for objects that are reference counted. Objects may optionally * have a destructor associated, which is responsible for destroying the * structure. Global / static versions of the structure should have no * destructor set - they can then have their reference counts manipulated as * normal, but will not do anything with them. * * The header stores a retain count - objects are assumed to have a reference * count of 1 when they are created, but the retain count is 0. When the * retain count is less than 0, they are freed. */ struct xlocale_refcounted { /** Number of references to this component. */ long retain_count; /** Function used to destroy this component, if one is required*/ void(*destructor)(void*); }; /** * Header for a locale component. All locale components must begin with this * header. */ struct xlocale_component { struct xlocale_refcounted header; /** Name of the locale used for this component. */ char locale[ENCODING_LEN+1]; }; /** * xlocale structure, stores per-thread locale information. */ struct _xlocale { struct xlocale_refcounted header; /** Components for the locale. */ struct xlocale_component *components[XLC_LAST]; /** Flag indicating if components[XLC_MONETARY] has changed since the * last call to localeconv_l() with this locale. */ int monetary_locale_changed; /** Flag indicating whether this locale is actually using a locale for * LC_MONETARY (1), or if it should use the C default instead (0). */ int using_monetary_locale; /** Flag indicating if components[XLC_NUMERIC] has changed since the * last call to localeconv_l() with this locale. */ int numeric_locale_changed; /** Flag indicating whether this locale is actually using a locale for * LC_NUMERIC (1), or if it should use the C default instead (0). */ int using_numeric_locale; /** Flag indicating whether this locale is actually using a locale for * LC_TIME (1), or if it should use the C default instead (0). */ int using_time_locale; /** Flag indicating whether this locale is actually using a locale for * LC_MESSAGES (1), or if it should use the C default instead (0). */ int using_messages_locale; /** The structure to be returned from localeconv_l() for this locale. */ struct lconv lconv; - /** Persistent state used by mblen() calls. */ - __mbstate_t mblen; - /** Persistent state used by mbrlen() calls. */ - __mbstate_t mbrlen; - /** Persistent state used by mbrtoc16() calls. */ - __mbstate_t mbrtoc16; - /** Persistent state used by mbrtoc32() calls. */ - __mbstate_t mbrtoc32; - /** Persistent state used by mbrtowc() calls. */ - __mbstate_t mbrtowc; - /** Persistent state used by mbsnrtowcs() calls. */ - __mbstate_t mbsnrtowcs; - /** Persistent state used by mbsrtowcs() calls. */ - __mbstate_t mbsrtowcs; - /** Persistent state used by mbtowc() calls. */ - __mbstate_t mbtowc; - /** Persistent state used by c16rtomb() calls. */ - __mbstate_t c16rtomb; - /** Persistent state used by c32rtomb() calls. */ - __mbstate_t c32rtomb; - /** Persistent state used by wcrtomb() calls. */ - __mbstate_t wcrtomb; - /** Persistent state used by wcsnrtombs() calls. */ - __mbstate_t wcsnrtombs; - /** Persistent state used by wcsrtombs() calls. */ - __mbstate_t wcsrtombs; - /** Persistent state used by wctomb() calls. */ - __mbstate_t wctomb; /** Buffer used by nl_langinfo_l() */ char *csym; }; /** * Increments the reference count of a reference-counted structure. */ __attribute__((unused)) static void* xlocale_retain(void *val) { struct xlocale_refcounted *obj = val; atomic_add_long(&(obj->retain_count), 1); return (val); } /** * Decrements the reference count of a reference-counted structure, freeing it * if this is the last reference, calling its destructor if it has one. */ __attribute__((unused)) static void xlocale_release(void *val) { struct xlocale_refcounted *obj = val; long count; count = atomic_fetchadd_long(&(obj->retain_count), -1) - 1; if (count < 0 && obj->destructor != NULL) obj->destructor(obj); } /** * Load functions. Each takes the name of a locale and a pointer to the data * to be initialised as arguments. Two special values are allowed for the */ extern void* __collate_load(const char*, locale_t); extern void* __ctype_load(const char*, locale_t); extern void* __messages_load(const char*, locale_t); extern void* __monetary_load(const char*, locale_t); extern void* __numeric_load(const char*, locale_t); extern void* __time_load(const char*, locale_t); extern struct _xlocale __xlocale_global_locale; extern struct _xlocale __xlocale_C_locale; /** * Caches the rune table in TLS for fast access. */ void __set_thread_rune_locale(locale_t loc); /** * Flag indicating whether a per-thread locale has been set. If no per-thread * locale has ever been set, then we always use the global locale. */ extern int __has_thread_locale; #ifndef __NO_TLS /** * The per-thread locale. Avoids the need to use pthread lookup functions when * getting the per-thread locale. */ extern _Thread_local locale_t __thread_locale; /** * Returns the current locale for this thread, or the global locale if none is * set. The caller does not have to free the locale. The return value from * this call is not guaranteed to remain valid after the locale changes. As * such, this should only be called within libc functions. */ static inline locale_t __get_locale(void) { if (!__has_thread_locale) { return (&__xlocale_global_locale); } return (__thread_locale ? __thread_locale : &__xlocale_global_locale); } #else locale_t __get_locale(void); #endif /** * Two magic values are allowed for locale_t objects. NULL and -1. This * function maps those to the real locales that they represent. */ static inline locale_t get_real_locale(locale_t locale) { switch ((intptr_t)locale) { case 0: return (&__xlocale_C_locale); case -1: return (&__xlocale_global_locale); default: return (locale); } } /** * Replace a placeholder locale with the real global or thread-local locale_t. */ #define FIX_LOCALE(l) (l = get_real_locale(l)) #endif