Date: Mon, 19 Sep 2011 15:00:36 +0100 From: David Chisnall <theraven@theravensnest.org> To: Roman Divacky <rdivacky@freebsd.org>, hackers@freebsd.org Subject: xlocale patch Message-ID: <DCAF3E3D-B2E1-40EF-B654-23625A17C3F1@theravensnest.org>
next in thread | raw e-mail | index | archive | help
--Apple-Mail=_F55C7A91-4420-4E40-9517-BE01711EE0A4 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii Hello Roman et al., Here is a big patch that provides everything needed to get libc++ = building on FreeBSD (head), which I think means that the linker is now = the only bit of the C++ stack that is not permissively licensed. The = patch contains the following: - The POSIX2008 locale functions. The specifications of these are = evidence that the Austin Group has been indulging in the other product = that UCB is famous for. Where the specification is ambiguous (i.e. = everywhere), I have used the Darwin implementation as a guide. This was = done because libc++ is developed on Darwin, so will likely expect this = behaviour. - The xlocale (Darwin extension) APIs. These provide _l suffixed = versions of a load of libc functions, which take a locale_t as a special = argument. The standard libc functions are now modified to call the _l = version with the current locale. =20 - Some stub definitions in libm for the long double versions of the = functions (<cmath> needs them to be in <math.h>). These versions just = call the double versions, so they lose precision and are therefore = hidden if you define __NO_IMPRECISE_LIBM_FUNCTIONS. =20 I've also attached some tests. The check_functions tool can be used as = $(CC) when building libc. It scans each of the _l functions and ensures = that they don't refer to any global state or call any of the non-_l = versions. There are also tests for the new locale functions (these = expect a checkout of head in /root/head - modify the Makefile in the = tests if it is elsewhere). As well as running these tests, I've also = built world with this diff installed. This work was sponsored by The FreeBSD Foundation. Comments / bug = reports / test cases welcome! David --Apple-Mail=_F55C7A91-4420-4E40-9517-BE01711EE0A4 Content-Disposition: attachment; filename=xlocale.diff Content-Type: application/octet-stream; x-unix-mode=0644; name="xlocale.diff" Content-Transfer-Encoding: 7bit Index: include/wctype.h =================================================================== --- include/wctype.h (revision 225653) +++ include/wctype.h (working copy) @@ -25,7 +25,7 @@ * * citrus Id: wctype.h,v 1.4 2000/12/21 01:50:21 itojun Exp * $NetBSD: wctype.h,v 1.3 2000/12/22 14:16:16 itojun Exp $ - * $FreeBSD$ + * $FreeBSD: head/include/wctype.h 172630 2007-10-14 10:23:54Z ache $ */ #ifndef _WCTYPE_H_ Index: include/Makefile =================================================================== --- include/Makefile (revision 225653) +++ include/Makefile (working copy) @@ -1,5 +1,5 @@ # @(#)Makefile 8.2 (Berkeley) 1/4/94 -# $FreeBSD$ +# $FreeBSD: head/include/Makefile 220370 2011-04-05 18:41:01Z obrien $ # # Doing a "make install" builds /usr/include. @@ -24,7 +24,7 @@ strings.h sysexits.h tar.h termios.h tgmath.h \ time.h timeconv.h timers.h ttyent.h \ ulimit.h unistd.h utime.h utmpx.h uuid.h varargs.h vis.h \ - wchar.h wctype.h wordexp.h + wchar.h wctype.h wordexp.h xlocale.h _xlocale_ctype.h MHDRS= float.h floatingpoint.h stdarg.h Index: include/xlocale.h =================================================================== --- include/xlocale.h (revision 0) +++ include/xlocale.h (revision 0) @@ -0,0 +1,256 @@ +/*- + * 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. + */ + +#ifndef _XLOCALE_H_ +#define _XLOCALE_H_ + +#include <locale.h> + +__BEGIN_DECLS + +/* + * Extended locale versions of the locale-aware functions from string.h. + * + * Include <string.h> before <xlocale.h> to expose these. + */ +#ifdef _STRING_H_ +int strcoll_l(const char *, const char *, locale_t); +size_t strxfrm_l(char *, const char *, size_t, locale_t); +int strcasecmp_l(const char *, const char *, locale_t); +char *strcasestr_l(const char *, const char *, locale_t); +int strncasecmp_l(const char *, const char *, size_t, locale_t); +#endif +/* + * Extended locale versions of the locale-aware functions from inttypes.h. + * + * Include <inttypes.h> before <xlocale.h> to expose these. + */ +#ifdef _INTTYPES_H_ +intmax_t +strtoimax_l(const char * __restrict, char ** __restrict, int, locale_t); +uintmax_t +strtoumax_l(const char * __restrict, char ** __restrict, int, locale_t); +intmax_t +wcstoimax_l(const wchar_t * __restrict, wchar_t ** __restrict, int , locale_t); +uintmax_t +wcstoumax_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +#endif +/* + * Extended locale versions of the locale-aware functions from monetary.h. + * + * Include <monetary.h> before <xlocale.h> to expose these. + */ +#ifdef _MONETARY_H_ +ssize_t strfmon_l(char *, size_t, locale_t, const char *, ...) +# if __GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7 + __attribute__((__format__ (__strfmon__, 4, 5))) +# endif + ; +#endif + +/* + * Extended locale versions of the locale-aware functions from stdlib.h. + * + * Include <stdlib.h> before <xlocale.h> to expose these. + */ +#ifdef _STDLIB_H_ +double atof_l(const char *, locale_t); +int atoi_l(const char *, locale_t); +long atol_l(const char *, locale_t); +long long atoll_l(const char *, locale_t); +int mblen_l(const char *, size_t, locale_t); +size_t +mbstowcs_l(wchar_t * __restrict, const char * __restrict, size_t, locale_t); +int +mbtowc_l(wchar_t * __restrict, const char * __restrict, size_t, locale_t); +double strtod_l(const char *, char **, locale_t); +float strtof_l(const char *, char **, locale_t); +long strtol_l(const char *, char **, int, locale_t); +long double strtold_l(const char *, char **, locale_t); +long long strtoll_l(const char *, char **, int, locale_t); +unsigned long strtoul_l(const char *, char **, int, locale_t); +unsigned long long strtoull_l(const char *, char **, int, locale_t); +size_t +wcstombs_l(char * __restrict, const wchar_t * __restrict, size_t, locale_t); +int wctomb_l(char *, wchar_t, locale_t); + +int ___mb_cur_max_l(locale_t); +#define MB_CUR_MAX_L(x) (___mb_cur_max_l(x)) + +#endif +/* + * Extended locale versions of the locale-aware functions from time.h. + * + * Include <time.h> before <xlocale.h> to expose these. + */ +#ifdef _TIME_H_ +size_t +strftime_l(char * __restrict, size_t, const char * __restrict, const + struct tm * __restrict, locale_t) +# if __GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7 + __attribute__((__format__ (__strftime__, 3, 0))) +# endif + ; +char * +strptime_l(const char * __restrict, const char * __restrict, + struct tm * __restrict, locale_t); +#endif +#ifdef _LANGINFO_H_ +char *nl_langinfo_l(nl_item, locale_t); +#endif +#ifdef _CTYPE_H_ +#include <_xlocale_ctype.h> +#endif +#ifdef _WCTYPE_H_ +#define XLOCALE_WCTYPES 1 +#include <_xlocale_ctype.h> +#endif + +#ifdef _STDIO_H_ +int fprintf_l(FILE * __restrict, locale_t, const char * __restrict, ...) + __printflike(3, 4); +int fscanf_l(FILE * __restrict, locale_t, const char * __restrict, ...) + __scanflike(3, 4); +int printf_l(locale_t, const char * __restrict, ...) __printflike(2, 3); +int scanf_l(locale_t, const char * __restrict, ...) __scanflike(2, 3); +int sprintf_l(char * __restrict, locale_t, const char * __restrict, ...) + __printflike(3, 4); +int sscanf_l(const char * __restrict, locale_t, const char * __restrict, ...) + __scanflike(3, 4); +int vfprintf_l(FILE * __restrict, locale_t, const char * __restrict, __va_list) + __printflike(3, 0); +int vprintf_l(locale_t, const char * __restrict, __va_list) __printflike(2, 0); +int vsprintf_l(char * __restrict, locale_t, const char * __restrict, __va_list) + __printflike(3, 0); + +int snprintf_l(char * __restrict, size_t, locale_t, const char * __restrict, + ...) __printflike(4, 5); +int vfscanf_l(FILE * __restrict, locale_t, const char * __restrict, __va_list) + __scanflike(3, 0); +int vscanf_l(locale_t, const char * __restrict, __va_list) __scanflike(2, 0); +int vsnprintf_l(char * __restrict, size_t, locale_t, const char * __restrict, + va_list) __printflike(4, 0); +int vsscanf_l(const char * __restrict, locale_t, const char * __restrict, + va_list) __scanflike(3, 0); +int dprintf_l(int, locale_t, const char * __restrict, ...) __printflike(3, 4); +int vdprintf_l(int, locale_t, const char * __restrict, __va_list) + __printflike(3, 0); +int asprintf_l(char **, locale_t, const char *, ...) __printflike(3, 4); +int vasprintf_l(char **, locale_t, const char *, __va_list) __printflike(3, 0); +#endif +#ifdef _WCHAR_H_ +wint_t btowc_l(int, locale_t); +wint_t fgetwc_l(struct __sFILE *, locale_t); +wchar_t * +fgetws_l(wchar_t * __restrict, int, struct __sFILE * __restrict, locale_t); +wint_t fputwc_l(wchar_t, struct __sFILE *, locale_t); +int +fputws_l(const wchar_t * __restrict, struct __sFILE * __restrict, locale_t); +int +fwprintf_l(struct __sFILE * __restrict, locale_t, const wchar_t * __restrict, + ...); +int +fwscanf_l(struct __sFILE * __restrict, locale_t, const wchar_t * __restrict, ...); +wint_t getwc_l(struct __sFILE *, locale_t); +wint_t getwchar_l(locale_t); +size_t +mbrlen_l(const char * __restrict, size_t, mbstate_t * __restrict, locale_t); +size_t +mbrtowc_l(wchar_t * __restrict, const char * __restrict, size_t, + mbstate_t * __restrict, locale_t); +int mbsinit_l(const mbstate_t *, locale_t); +size_t +mbsrtowcs_l(wchar_t * __restrict, const char ** __restrict, size_t, + mbstate_t * __restrict, locale_t); +wint_t putwc_l(wchar_t, struct __sFILE *, locale_t); +wint_t putwchar_l(wchar_t, locale_t); +int +swprintf_l(wchar_t * __restrict, size_t n, locale_t, + const wchar_t * __restrict, ...); +int +swscanf_l(const wchar_t * __restrict, locale_t, const wchar_t * __restrict, + ...); +wint_t ungetwc_l(wint_t, struct __sFILE *, locale_t); +int +vfwprintf_l(struct __sFILE * __restrict, locale_t, const wchar_t * __restrict, + __va_list); +int +vswprintf_l(wchar_t * __restrict, size_t n, locale_t, + const wchar_t * __restrict, __va_list); +int vwprintf_l(locale_t, const wchar_t * __restrict, __va_list); +size_t +wcrtomb_l(char * __restrict, wchar_t, mbstate_t * __restrict, locale_t); +int wcscoll_l(const wchar_t *, const wchar_t *, locale_t); +size_t +wcsftime_l(wchar_t * __restrict, size_t, const wchar_t * __restrict, + const struct tm * __restrict, locale_t); +size_t +wcsrtombs_l(char * __restrict, const wchar_t ** __restrict, size_t, + mbstate_t * __restrict, locale_t); +double wcstod_l(const wchar_t * __restrict, wchar_t ** __restrict, locale_t); +long +wcstol_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +unsigned long +wcstoul_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +int wcswidth_l(const wchar_t *, size_t, locale_t); +size_t +wcsxfrm_l(wchar_t * __restrict, const wchar_t * __restrict, size_t, locale_t); +int wctob_l(wint_t, locale_t); +int wcwidth_l(wchar_t, locale_t); +int wprintf_l(locale_t, const wchar_t * __restrict, ...); +int wscanf_l(locale_t, const wchar_t * __restrict, ...); + +int +vfwscanf_l(struct __sFILE * __restrict, locale_t, const wchar_t * __restrict, + __va_list); +int vswscanf_l(const wchar_t * __restrict, locale_t, +const wchar_t * __restrict, __va_list); +int vwscanf_l(locale_t, const wchar_t * __restrict, __va_list); +float wcstof_l(const wchar_t * __restrict, wchar_t ** __restrict, locale_t); +long double +wcstold_l(const wchar_t * __restrict, wchar_t ** __restrict, locale_t); +long long +wcstoll_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +unsigned long long +wcstoull_l(const wchar_t * __restrict, wchar_t ** __restrict, int, locale_t); +size_t +mbsnrtowcs_l(wchar_t * __restrict, const char ** __restrict, size_t, size_t, + mbstate_t * __restrict, locale_t); +int wcscasecmp_l(const wchar_t *, const wchar_t *, locale_t); +int wcsncasecmp_l(const wchar_t *, const wchar_t *, size_t n, locale_t); +size_t +wcsnrtombs_l(char * __restrict, const wchar_t ** __restrict, size_t, size_t, + mbstate_t * __restrict, locale_t); + +#endif + +struct lconv * +localeconv_l(locale_t loc); +__END_DECLS + +#endif Index: include/locale.h =================================================================== --- include/locale.h (revision 225653) +++ include/locale.h (working copy) @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * @(#)locale.h 8.1 (Berkeley) 6/2/93 - * $FreeBSD$ + * $FreeBSD: head/include/locale.h 203964 2010-02-16 19:39:50Z imp $ */ #ifndef _LOCALE_H_ @@ -79,4 +79,48 @@ char *setlocale(int, const char *); __END_DECLS +#if __POSIX_VISIBLE >= 200809 + +#define LC_COLLATE_MASK (1<<0) +#define LC_CTYPE_MASK (1<<1) +#define LC_MESSAGES_MASK (1<<2) +#define LC_MONETARY_MASK (1<<3) +#define LC_NUMERIC_MASK (1<<4) +#define LC_TIME_MASK (1<<5) +#define LC_ALL_MASK (LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | \ + LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK) + +#define LC_GLOBAL_LOCALE ((locale_t)-1) + +__BEGIN_DECLS + +typedef struct _xlocale *locale_t; +/** + * Creates a new locale. + */ +locale_t newlocale(int mask, const char *locale, locale_t base); + +locale_t duplocale(locale_t base); +/* + * Free a locale_t. This is quite a poorly named function. It actually + * disclaims a reference to a locale_t, rather than freeing it. + */ +int +freelocale(locale_t loc); + +/* + * Returns the name of the locale for a particular component of a locale_t. + */ +const char *querylocale(int mask, locale_t loc); + +/* + * Installs the specified locale_t as this thread's locale. + */ +locale_t uselocale(locale_t loc); + +__END_DECLS + +#endif /* __POSIX_VISIBLE >= 200809 */ + + #endif /* _LOCALE_H_ */ Index: include/_xlocale_ctype.h =================================================================== --- include/_xlocale_ctype.h (revision 0) +++ include/_xlocale_ctype.h (revision 0) @@ -0,0 +1,160 @@ +/*- + * 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. + */ +#ifndef _XLOCALE_H_ +#error This header should only be included by <xlocale.h>, never directly. +#endif + +#ifndef _XLOCALE_CTYPE_H_ +__BEGIN_DECLS +unsigned long ___runetype_l(__ct_rune_t, locale_t) __pure; +__ct_rune_t ___tolower_l(__ct_rune_t, locale_t) __pure; +__ct_rune_t ___toupper_l(__ct_rune_t, locale_t) __pure; +_RuneLocale *__runes_for_locale(locale_t, int*); +__END_DECLS +#endif + +#ifndef _XLOCALE_INLINE +# if __GNUC__ && !__GNUC_STDC_INLINE__ +# define _XLOCALE_INLINE extern inline +# else +# define _XLOCALE_INLINE inline +# endif +#endif + +#ifdef XLOCALE_WCTYPES +static __inline int +__maskrune_l(__ct_rune_t _c, unsigned long _f, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (_c < 0 || _c >= _CACHED_RUNES) ? ___runetype_l(_c, locale) : + runes->__runetype[_c] & _f; +} + +static __inline int +__istype_l(__ct_rune_t _c, unsigned long _f, locale_t locale) +{ + return (!!__maskrune_l(_c, _f, locale)); +} + +# define XLOCALE_ISCTYPE(fname, cat) \ + _XLOCALE_INLINE int isw##fname##_l(int c, locale_t l)\ + { return __istype_l(c, cat, l); } +#else +static __inline int +__sbmaskrune_l(__ct_rune_t _c, unsigned long _f, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (_c < 0 || _c >= mb_sb_limit) ? 0 : + runes->__runetype[_c] & _f; +} + +static __inline int +__sbistype_l(__ct_rune_t _c, unsigned long _f, locale_t locale) +{ + return (!!__sbmaskrune_l(_c, _f, locale)); +} + +# define XLOCALE_ISCTYPE(fname, cat) \ + _XLOCALE_INLINE int is##fname##_l(int c, locale_t l)\ + { return __sbistype_l(c, cat, l); } +#endif + +XLOCALE_ISCTYPE(alnum, _CTYPE_A|_CTYPE_D) +XLOCALE_ISCTYPE(alpha, _CTYPE_A) +XLOCALE_ISCTYPE(blank, _CTYPE_B) +XLOCALE_ISCTYPE(cntrl, _CTYPE_C) +XLOCALE_ISCTYPE(digit, _CTYPE_D) +XLOCALE_ISCTYPE(graph, _CTYPE_G) +XLOCALE_ISCTYPE(hexnumber, _CTYPE_X) +XLOCALE_ISCTYPE(ideogram, _CTYPE_I) +XLOCALE_ISCTYPE(lower, _CTYPE_L) +XLOCALE_ISCTYPE(number, _CTYPE_D) +XLOCALE_ISCTYPE(phonogram, _CTYPE_Q) +XLOCALE_ISCTYPE(print, _CTYPE_R) +XLOCALE_ISCTYPE(punct, _CTYPE_P) +XLOCALE_ISCTYPE(rune, 0xFFFFFF00L) +XLOCALE_ISCTYPE(space, _CTYPE_S) +XLOCALE_ISCTYPE(special, _CTYPE_T) +XLOCALE_ISCTYPE(upper, _CTYPE_U) +XLOCALE_ISCTYPE(xdigit, _CTYPE_X) +#undef XLOCALE_ISCTYPE + +#ifdef XLOCALE_WCTYPES +_XLOCALE_INLINE int towlower_l(int c, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (c < 0 || c >= _CACHED_RUNES) ? ___tolower_l(c, locale) : + runes->__maplower[c]; +} +_XLOCALE_INLINE int towupper_l(int c, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (c < 0 || c >= _CACHED_RUNES) ? ___toupper_l(c, locale) : + runes->__maplower[c]; +} +_XLOCALE_INLINE int +__wcwidth_l(__ct_rune_t _c, locale_t locale) +{ + unsigned int _x; + + if (_c == 0) + return (0); + _x = (unsigned int)__maskrune_l(_c, _CTYPE_SWM|_CTYPE_R, locale); + if ((_x & _CTYPE_SWM) != 0) + return ((_x & _CTYPE_SWM) >> _CTYPE_SWS); + return ((_x & _CTYPE_R) != 0 ? 1 : -1); +} +int iswctype_l(wint_t wc, wctype_t charclass, locale_t locale); +wctype_t wctype_l(const char *property, locale_t locale); +wint_t towctrans_l(wint_t wc, wctrans_t desc, locale_t locale); +wint_t nextwctype_l(wint_t wc, wctype_t wct, locale_t locale); +wctrans_t wctrans_l(const char *charclass, locale_t locale); +#undef XLOCALE_WCTYPES +#else +_XLOCALE_INLINE int digittoint_l(int c, locale_t locale) +{ return __sbmaskrune_l((c), 0xFF, locale); } + +_XLOCALE_INLINE int tolower_l(int c, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (c < 0 || c >= mb_sb_limit) ? c : + runes->__maplower[c]; +} +_XLOCALE_INLINE int toupper_l(int c, locale_t locale) +{ + int mb_sb_limit; + _RuneLocale *runes = __runes_for_locale(locale, &mb_sb_limit); + return (c < 0 || c >= mb_sb_limit) ? c : + runes->__maplower[c]; +} +#endif Index: include/string.h =================================================================== --- include/string.h (revision 225653) +++ include/string.h (working copy) @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * @(#)string.h 8.1 (Berkeley) 6/2/93 - * $FreeBSD$ + * $FreeBSD: head/include/string.h 203964 2010-02-16 19:39:50Z imp $ */ #ifndef _STRING_H_ Index: include/runetype.h =================================================================== --- include/runetype.h (revision 225653) +++ include/runetype.h (working copy) @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * @(#)runetype.h 8.1 (Berkeley) 6/2/93 - * $FreeBSD$ + * $FreeBSD: head/include/runetype.h 203964 2010-02-16 19:39:50Z imp $ */ #ifndef _RUNETYPE_H_ @@ -83,8 +83,14 @@ } _RuneLocale; #define _RUNE_MAGIC_1 "RuneMagi" /* Indicates version 0 of RuneLocale */ - -extern _RuneLocale _DefaultRuneLocale; +__BEGIN_DECLS +extern const _RuneLocale _DefaultRuneLocale; +__attribute__((deprecated)) extern _RuneLocale *_CurrentRuneLocale; +/* TODO: This is called quite a lot, so we should use a __thread variable when + * it's available. */ +extern _RuneLocale *__getCurrentRuneLocale(void); +#define _CurrentRuneLocale (__getCurrentRuneLocale()) +__END_DECLS #endif /* !_RUNETYPE_H_ */ Index: include/stdlib.h =================================================================== --- include/stdlib.h (revision 225653) +++ include/stdlib.h (working copy) @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * @(#)stdlib.h 8.5 (Berkeley) 5/19/95 - * $FreeBSD$ + * $FreeBSD: head/include/stdlib.h 206997 2010-04-21 16:38:37Z kib $ */ #ifndef _STDLIB_H_ @@ -71,10 +71,11 @@ #define RAND_MAX 0x7fffffff +__BEGIN_DECLS extern int __mb_cur_max; -#define MB_CUR_MAX __mb_cur_max +extern int ___mb_cur_max(void); +#define MB_CUR_MAX (___mb_cur_max()) -__BEGIN_DECLS void abort(void) __dead2; int abs(int) __pure2; int atexit(void (*)(void)); Index: include/_ctype.h =================================================================== --- include/_ctype.h (revision 225653) +++ include/_ctype.h (working copy) @@ -36,7 +36,7 @@ * * From @(#)ctype.h 8.4 (Berkeley) 1/21/94 * From FreeBSD: src/include/ctype.h,v 1.27 2004/06/23 07:11:39 tjr Exp - * $FreeBSD$ + * $FreeBSD: head/include/_ctype.h 203964 2010-02-16 19:39:50Z imp $ */ #ifndef __CTYPE_H_ Index: contrib/gdtoa/gdtoaimp.h =================================================================== --- contrib/gdtoa/gdtoaimp.h (revision 225653) +++ contrib/gdtoa/gdtoaimp.h (working copy) @@ -26,7 +26,7 @@ ****************************************************************/ -/* $FreeBSD$ */ +/* $FreeBSD: head/contrib/gdtoa/gdtoaimp.h 219557 2011-03-12 07:03:06Z das $ */ /* This is a variation on dtoa.c that converts arbitary binary floating-point formats to and from decimal notation. It uses @@ -201,6 +201,7 @@ #include "namespace.h" #include <pthread.h> #include "un-namespace.h" +#include "xlocale_private.h" #ifdef KR_headers #define Char char @@ -526,10 +527,13 @@ #define strtoIx __strtoIx #define strtoIxL __strtoIxL #define strtord __strtord +#define strtord_l __strtord_l #define strtordd __strtordd #define strtorf __strtorf #define strtorQ __strtorQ +#define strtorQ_l __strtorQ_l #define strtorx __strtorx +#define strtorx_l __strtorx_l #define strtorxL __strtorxL #define strtodI __strtodI #define strtopd __strtopd @@ -635,6 +639,7 @@ extern Bigint *set_ones ANSI((Bigint*, int)); extern char *strcp ANSI((char*, const char*)); extern int strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*)); + extern int strtodg_l ANSI((CONST char*, char**, FPI*, Long*, ULong*, locale_t)); extern int strtoId ANSI((CONST char *, char **, double *, double *)); extern int strtoIdd ANSI((CONST char *, char **, double *, double *)); @@ -644,6 +649,7 @@ extern int strtoIx ANSI((CONST char *, char **, void *, void *)); extern int strtoIxL ANSI((CONST char *, char **, void *, void *)); extern double strtod ANSI((const char *s00, char **se)); + extern double strtod_l ANSI((const char *s00, char **se, locale_t)); extern int strtopQ ANSI((CONST char *, char **, Void *)); extern int strtopf ANSI((CONST char *, char **, float *)); extern int strtopd ANSI((CONST char *, char **, double *)); @@ -651,10 +657,13 @@ extern int strtopx ANSI((CONST char *, char **, Void *)); extern int strtopxL ANSI((CONST char *, char **, Void *)); extern int strtord ANSI((CONST char *, char **, int, double *)); + extern int strtord_l ANSI((CONST char *, char **, int, double *, locale_t)); extern int strtordd ANSI((CONST char *, char **, int, double *)); extern int strtorf ANSI((CONST char *, char **, int, float *)); extern int strtorQ ANSI((CONST char *, char **, int, void *)); + extern int strtorQ_l ANSI((CONST char *, char **, int, void *, locale_t)); extern int strtorx ANSI((CONST char *, char **, int, void *)); + extern int strtorx_l ANSI((CONST char *, char **, int, void *, locale_t)); extern int strtorxL ANSI((CONST char *, char **, int, void *)); extern Bigint *sum ANSI((Bigint*, Bigint*)); extern int trailz ANSI((Bigint*)); Index: contrib/gdtoa/strtopQ.c =================================================================== --- contrib/gdtoa/strtopQ.c (revision 225653) +++ contrib/gdtoa/strtopQ.c (working copy) @@ -56,7 +56,7 @@ strtopQ(CONST char *s, char **sp, void *V) #endif { - static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, SI }; + static const FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, SI }; ULong bits[4]; Long exp; int k; Index: contrib/gdtoa/strtorQ.c =================================================================== --- contrib/gdtoa/strtorQ.c (revision 225653) +++ contrib/gdtoa/strtorQ.c (working copy) @@ -29,7 +29,7 @@ /* Please send bug reports to David M. Gay (dmg at acm dot org, * with " at " changed at "@" and " dot " changed to "."). */ -/* $FreeBSD$ */ +/* $FreeBSD: head/contrib/gdtoa/strtorQ.c 174690 2007-12-16 23:31:55Z das $ */ #include "gdtoaimp.h" @@ -103,9 +103,10 @@ int #ifdef KR_headers -strtorQ(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; +strtorQ_l(s, sp, rounding, L, locale) CONST char *s; char **sp; int rounding; +void *L; locale_t locale; #else -strtorQ(CONST char *s, char **sp, int rounding, void *L) +strtorQ_l(CONST char *s, char **sp, int rounding, void *L, locale_t locale) #endif { static FPI fpi0 = { 113, 1-16383-113+1, 32766-16383-113+1, 1, SI }; @@ -120,7 +121,17 @@ fpi1.rounding = rounding; fpi = &fpi1; } - k = strtodg(s, sp, fpi, &exp, bits); + k = strtodg_l(s, sp, fpi, &exp, bits, locale); ULtoQ((ULong*)L, bits, exp, k); return k; } + + int +#ifdef KR_headers +strtorQ(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; +#else +strtorQ(CONST char *s, char **sp, int rounding, void *L) +#endif +{ + return strtorQ_l(s, sp, rounding, L, __get_locale()); +} Index: contrib/gdtoa/strtodg.c =================================================================== --- contrib/gdtoa/strtodg.c (revision 225653) +++ contrib/gdtoa/strtodg.c (working copy) @@ -34,6 +34,7 @@ #ifdef USE_LOCALE #include "locale.h" #endif +#include "xlocale_private.h" static CONST int fivesbits[] = { 0, 3, 5, 7, 10, 12, 14, 17, 19, 21, @@ -313,12 +314,12 @@ } int -strtodg +strtodg_l #ifdef KR_headers - (s00, se, fpi, exp, bits) - CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; + (s00, se, fpi, exp, bits, l) + CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; locale_t l; #else - (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits) + (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits, locale_t l) #endif { int abe, abits, asub; @@ -334,14 +335,14 @@ Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0; #ifdef USE_LOCALE /*{{*/ #ifdef NO_LOCALE_CACHE - char *decimalpoint = localeconv()->decimal_point; + char *decimalpoint = localeconv_l(l)->decimal_point; int dplen = strlen(decimalpoint); #else char *decimalpoint; static char *decimalpoint_cache; static int dplen; if (!(s0 = decimalpoint_cache)) { - s0 = localeconv()->decimal_point; + s0 = localeconv_l(l)->decimal_point; if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { strcpy(decimalpoint_cache, s0); s0 = decimalpoint_cache; @@ -1063,3 +1064,15 @@ } return irv; } + + int +strtodg +#ifdef KR_headers + (s00, se, fpi, exp, bits) + CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; +#else + (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits) +#endif +{ + return strtodg_l(s00, se, fpi, exp, bits, __get_locale()); +} Index: contrib/gdtoa/strtord.c =================================================================== --- contrib/gdtoa/strtord.c (revision 225653) +++ contrib/gdtoa/strtord.c (working copy) @@ -70,9 +70,10 @@ int #ifdef KR_headers -strtord(s, sp, rounding, d) CONST char *s; char **sp; int rounding; double *d; +strtord_l(s, sp, rounding, d, locale) CONST char *s; char **sp; int rounding; +double *d; locale_t locale; #else -strtord(CONST char *s, char **sp, int rounding, double *d) +strtord_l(CONST char *s, char **sp, int rounding, double *d, locale_t locale) #endif { static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; @@ -87,7 +88,17 @@ fpi1.rounding = rounding; fpi = &fpi1; } - k = strtodg(s, sp, fpi, &exp, bits); + k = strtodg_l(s, sp, fpi, &exp, bits, locale); ULtod((ULong*)d, bits, exp, k); return k; } + int +#ifdef KR_headers +strtord(s, sp, rounding, L, locale) CONST char *s; char **sp; int rounding; +void *L; +#else +strtord(CONST char *s, char **sp, int rounding, double *d) +#endif +{ + return strtord_l(s, sp, rounding, d, __get_locale()); +} Index: contrib/gdtoa/strtod.c =================================================================== --- contrib/gdtoa/strtod.c (revision 225653) +++ contrib/gdtoa/strtod.c (working copy) @@ -29,7 +29,7 @@ /* Please send bug reports to David M. Gay (dmg at acm dot org, * with " at " changed at "@" and " dot " changed to "."). */ -/* $FreeBSD$ */ +/* $FreeBSD: head/contrib/gdtoa/strtod.c 219557 2011-03-12 07:03:06Z das $ */ #include "gdtoaimp.h" #ifndef NO_FENV_H @@ -39,6 +39,7 @@ #ifdef USE_LOCALE #include "locale.h" #endif +#include "xlocale_private.h" #ifdef IEEE_Arith #ifndef NO_IEEE_Scale @@ -82,11 +83,11 @@ #endif /*}*/ double -strtod +strtod_l #ifdef KR_headers - (s00, se) CONST char *s00; char **se; + (s00, se, l) CONST char *s00; char **se; locale_t l #else - (CONST char *s00, char **se) + (CONST char *s00, char **se, locale_t l) #endif { #ifdef Avoid_Underflow @@ -108,14 +109,14 @@ #endif #ifdef USE_LOCALE /*{{*/ #ifdef NO_LOCALE_CACHE - char *decimalpoint = localeconv()->decimal_point; + char *decimalpoint = localeconv_l(l)->decimal_point; int dplen = strlen(decimalpoint); #else char *decimalpoint; static char *decimalpoint_cache; static int dplen; if (!(s0 = decimalpoint_cache)) { - s0 = localeconv()->decimal_point; + s0 = localeconv_l(l)->decimal_point; if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { strcpy(decimalpoint_cache, s0); s0 = decimalpoint_cache; @@ -168,7 +169,7 @@ if (*s == '0') { #ifndef NO_HEX_FP /*{*/ { - static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; + static const FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI }; Long exp; ULong bits[2]; switch(s[1]) { @@ -295,7 +296,7 @@ #ifdef INFNAN_CHECK /* Check for Nan and Infinity */ ULong bits[2]; - static FPI fpinan = /* only 52 explicit bits */ + static const FPI fpinan = /* only 52 explicit bits */ { 52, 1-1023-53+1, 2046-1023-53+1, 1, SI }; if (!decpt) switch(c) { @@ -1074,3 +1075,13 @@ return sign ? -dval(&rv) : dval(&rv); } + double +strtod +#ifdef KR_headers + (s00, se, l) CONST char *s00; char **se; locale_t +#else + (CONST char *s00, char **se) +#endif +{ + return strtod_l(s00, se, __get_locale()); +} Index: contrib/gdtoa/strtof.c =================================================================== --- contrib/gdtoa/strtof.c (revision 225653) +++ contrib/gdtoa/strtof.c (working copy) @@ -29,18 +29,19 @@ /* Please send bug reports to David M. Gay (dmg at acm dot org, * with " at " changed at "@" and " dot " changed to "."). */ -/* $FreeBSD$ */ +/* $FreeBSD: head/contrib/gdtoa/strtof.c 219557 2011-03-12 07:03:06Z das $ */ #include "gdtoaimp.h" +#include "xlocale_private.h" float #ifdef KR_headers -strtof(s, sp) CONST char *s; char **sp; +strtof_l(s, sp, l) CONST char *s; char **sp; locale_t l; #else -strtof(CONST char *s, char **sp) +strtof_l(CONST char *s, char **sp, locale_t l) #endif { - static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; + static const FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI }; ULong bits[1]; Long exp; int k; @@ -51,7 +52,7 @@ #define fpi &fpi0 #endif - k = strtodg(s, sp, fpi, &exp, bits); + k = strtodg_l(s, sp, fpi, &exp, bits, l); switch(k & STRTOG_Retmask) { case STRTOG_NoNumber: case STRTOG_Zero: @@ -82,3 +83,13 @@ u.L[0] |= 0x80000000L; return u.f; } + + float +#ifdef KR_headers +strtof(s, sp) CONST char *s; char **sp; +#else +strtof(CONST char *s, char **sp) +#endif +{ + return strtof_l(s, sp, __get_locale()); +} Index: contrib/gdtoa/strtorx.c =================================================================== --- contrib/gdtoa/strtorx.c (revision 225653) +++ contrib/gdtoa/strtorx.c (working copy) @@ -29,7 +29,7 @@ /* Please send bug reports to David M. Gay (dmg at acm dot org, * with " at " changed at "@" and " dot " changed to "."). */ -/* $FreeBSD$ */ +/* $FreeBSD: head/contrib/gdtoa/strtorx.c 219557 2011-03-12 07:03:06Z das $ */ #include "gdtoaimp.h" @@ -106,9 +106,10 @@ int #ifdef KR_headers -strtorx(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; +strtorx_l(s, sp, rounding, L, locale) CONST char *s; char **sp; int rounding; +void *L; locale_t locale; #else -strtorx(CONST char *s, char **sp, int rounding, void *L) +strtorx_l(CONST char *s, char **sp, int rounding, void *L, locale_t locale) #endif { static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; @@ -123,7 +124,16 @@ fpi1.rounding = rounding; fpi = &fpi1; } - k = strtodg(s, sp, fpi, &exp, bits); + k = strtodg_l(s, sp, fpi, &exp, bits, locale); ULtox((UShort*)L, bits, exp, k); return k; } + int +#ifdef KR_headers +strtorx(s, sp, rounding, L) CONST char *s; char **sp; int rounding; void *L; +#else +strtorx(CONST char *s, char **sp, int rounding, void *L) +#endif +{ + return strtorx_l(s, sp, rounding, L, __get_locale()); +} Index: lib/msun/src/math.h =================================================================== --- lib/msun/src/math.h (revision 225653) +++ lib/msun/src/math.h (working copy) @@ -398,32 +398,32 @@ * long double versions of ISO/POSIX math functions */ #if __ISO_C_VISIBLE >= 1999 -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double acoshl(long double); #endif long double acosl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double asinhl(long double); #endif long double asinl(long double); long double atan2l(long double, long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double atanhl(long double); #endif long double atanl(long double); long double cbrtl(long double); long double ceill(long double); long double copysignl(long double, long double) __pure2; -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double coshl(long double); #endif long double cosl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double erfcl(long double); long double erfl(long double); #endif long double exp2l(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double expl(long double); long double expm1l(long double); #endif @@ -438,18 +438,18 @@ long double hypotl(long double, long double); int ilogbl(long double) __pure2; long double ldexpl(long double, int); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double lgammal(long double); #endif long long llrintl(long double); long long llroundl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double log10l(long double); long double log1pl(long double); long double log2l(long double); #endif long double logbl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double logl(long double); #endif long lrintl(long double); @@ -461,7 +461,7 @@ double nexttoward(double, long double); float nexttowardf(float, long double); long double nexttowardl(long double, long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double powl(long double, long double); #endif long double remainderl(long double, long double); @@ -470,16 +470,16 @@ long double roundl(long double); long double scalblnl(long double, long); long double scalbnl(long double, int); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double sinhl(long double); #endif long double sinl(long double); long double sqrtl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double tanhl(long double); #endif long double tanl(long double); -#if 0 +#if !__NO_IMPRECISE_LIBM_FUNCTIONS long double tgammal(long double); #endif long double truncl(long double); Index: lib/msun/src/stubs.c =================================================================== --- lib/msun/src/stubs.c (revision 0) +++ lib/msun/src/stubs.c (revision 0) @@ -0,0 +1,22 @@ +#include <math.h> + +#define LIBCXX_LONG_DOUBLE_STUB(fn) __attribute__((weak)) long double fn ## l(long double x) { return fn(x); } +#define LIBCXX_LONG_DOUBLE_STUB2(fn) __attribute__((weak)) long double fn ## l(long double x, long double y) { return fn(x, y); } + +LIBCXX_LONG_DOUBLE_STUB(cosh) +LIBCXX_LONG_DOUBLE_STUB(asinh) +LIBCXX_LONG_DOUBLE_STUB(atanh) +LIBCXX_LONG_DOUBLE_STUB(acosh) +LIBCXX_LONG_DOUBLE_STUB(erfc) +LIBCXX_LONG_DOUBLE_STUB(erf) +LIBCXX_LONG_DOUBLE_STUB(exp) +LIBCXX_LONG_DOUBLE_STUB(expm1) +LIBCXX_LONG_DOUBLE_STUB(lgamma) +LIBCXX_LONG_DOUBLE_STUB(log10) +LIBCXX_LONG_DOUBLE_STUB(log1p) +LIBCXX_LONG_DOUBLE_STUB(log2) +LIBCXX_LONG_DOUBLE_STUB(log) +LIBCXX_LONG_DOUBLE_STUB(tanh) +LIBCXX_LONG_DOUBLE_STUB(sinh) +LIBCXX_LONG_DOUBLE_STUB(tgamma) +LIBCXX_LONG_DOUBLE_STUB2(pow) Index: lib/msun/Makefile =================================================================== --- lib/msun/Makefile (revision 225653) +++ lib/msun/Makefile (working copy) @@ -1,5 +1,5 @@ # @(#)Makefile 5.1beta 93/09/24 -# $FreeBSD$ +# $FreeBSD: head/lib/msun/Makefile 219576 2011-03-12 19:37:35Z kargl $ # # ==================================================== # Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. @@ -70,7 +70,7 @@ s_scalbln.c s_scalbn.c s_scalbnf.c s_signbit.c \ s_signgam.c s_significand.c s_significandf.c s_sin.c s_sinf.c \ s_tan.c s_tanf.c s_tanh.c s_tanhf.c s_tgammaf.c s_trunc.c s_truncf.c \ - w_cabs.c w_cabsf.c w_drem.c w_dremf.c + w_cabs.c w_cabsf.c w_drem.c w_dremf.c stubs.c # Location of fpmath.h and _fpmath.h LIBCDIR= ${.CURDIR}/../libc Index: lib/libc/stdlib/Symbol.map =================================================================== --- lib/libc/stdlib/Symbol.map (revision 225653) +++ lib/libc/stdlib/Symbol.map (working copy) @@ -1,5 +1,5 @@ /* - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdlib/Symbol.map 182225 2008-08-27 02:00:53Z jasone $ */ FBSD_1.0 { @@ -90,6 +90,21 @@ tfind; tsearch; twalk; + atof_l; + atoi_l; + atol_l; + atoll_l; + strtod_l; + strtol_l; + strtoll_l; + strtof_l; + strtoimax_l; + strtold_l; + strtoq_l; + strtoul_l; + strtoull_l; + strtoumax_l; + strtouq_l; }; FBSDprivate_1.0 { Index: lib/libc/stdlib/atoll.c =================================================================== --- lib/libc/stdlib/atoll.c (revision 225653) +++ lib/libc/stdlib/atoll.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1988, 1993 * The Regents of the University of California. 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: @@ -28,9 +33,10 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/atoll.c 165903 2007-01-09 00:28:16Z imp $"); #include <stdlib.h> +#include <xlocale.h> long long atoll(str) @@ -38,3 +44,11 @@ { return strtoll(str, (char **)NULL, 10); } + +long long +atoll_l(str, locale) + const char *str; + locale_t locale; +{ + return strtoll_l(str, (char **)NULL, 10, locale); +} Index: lib/libc/stdlib/strfmon.c =================================================================== --- lib/libc/stdlib/strfmon.c (revision 225653) +++ lib/libc/stdlib/strfmon.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org> * 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: @@ -26,7 +31,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/strfmon.c 203734 2010-02-10 00:02:09Z cracauer $"); #include <sys/types.h> #include <ctype.h> @@ -38,6 +43,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include "xlocale_private.h" /* internal flags */ #define NEED_GROUPING 0x01 /* print digits grouped (default) */ @@ -92,11 +98,10 @@ static int __calc_left_pad(int, char *); static char *__format_grouped_double(double, int *, int, int, int); -ssize_t -strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, - ...) +static ssize_t +vstrfmon_l(char * __restrict s, size_t maxsize, locale_t loc, + const char * __restrict format, va_list ap) { - va_list ap; char *dst; /* output destination pointer */ const char *fmt; /* current format poistion pointer */ struct lconv *lc; /* pointer to lconv structure */ @@ -119,10 +124,10 @@ char *tmpptr; /* temporary vars */ int sverrno; + FIX_LOCALE(loc); - va_start(ap, format); - lc = localeconv(); + lc = localeconv_l(loc); dst = s; fmt = format; asciivalue = NULL; @@ -380,7 +385,6 @@ } PRINT('\0'); - va_end(ap); free(asciivalue); free(currency_symbol); return (dst - s - 1); /* return size of put data except trailing '\0' */ @@ -399,10 +403,34 @@ if (currency_symbol != NULL) free(currency_symbol); errno = sverrno; - va_end(ap); return (-1); } +ssize_t +strfmon_l(char * __restrict s, size_t maxsize, locale_t loc, const char * __restrict format, + ...) +{ + size_t ret; + va_list ap; + FIX_LOCALE(loc); + va_start(ap, format); + ret = vstrfmon_l(s, maxsize, loc, format, ap); + va_end(ap); + return ret; +} +ssize_t +strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, + ...) +{ + size_t ret; + va_list ap; + va_start(ap, format); + ret = vstrfmon_l(s, maxsize, __get_locale(), format, ap); + va_end(ap); + return ret; +} + + static void __setup_vars(int flags, char *cs_precedes, char *sep_by_space, char *sign_posn, char **signstr) { Index: lib/libc/stdlib/atof.c =================================================================== --- lib/libc/stdlib/atof.c (revision 225653) +++ lib/libc/stdlib/atof.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1988, 1993 * The Regents of the University of California. 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: @@ -31,9 +36,10 @@ static char sccsid[] = "@(#)atof.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/atof.c 165903 2007-01-09 00:28:16Z imp $"); #include <stdlib.h> +#include <xlocale.h> double atof(ascii) @@ -41,3 +47,11 @@ { return strtod(ascii, (char **)NULL); } + +double +atof_l(ascii, locale) + const char *ascii; + locale_t locale; +{ + return strtod_l(ascii, (char **)NULL, locale); +} Index: lib/libc/stdlib/strtoimax.c =================================================================== --- lib/libc/stdlib/strtoimax.c (revision 225653) +++ lib/libc/stdlib/strtoimax.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. 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: @@ -31,12 +36,13 @@ static char sccsid[] = "from @(#)strtol.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/strtoimax.c 165903 2007-01-09 00:28:16Z imp $"); #include <ctype.h> #include <errno.h> #include <stdlib.h> #include <inttypes.h> +#include "xlocale_private.h" /* * Convert a string to an intmax_t integer. @@ -45,13 +51,15 @@ * alphabets and digits are each contiguous. */ intmax_t -strtoimax(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoimax_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; uintmax_t acc; char c; uintmax_t cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * Skip white space and pick up leading +/- sign if any. @@ -61,7 +69,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -138,3 +146,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +intmax_t +strtoimax(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoimax_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/atol.c =================================================================== --- lib/libc/stdlib/atol.c (revision 225653) +++ lib/libc/stdlib/atol.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1988, 1993 * The Regents of the University of California. 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: @@ -31,9 +36,10 @@ static char sccsid[] = "@(#)atol.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/atol.c 165903 2007-01-09 00:28:16Z imp $"); #include <stdlib.h> +#include <xlocale.h> long atol(str) @@ -41,3 +47,11 @@ { return strtol(str, (char **)NULL, 10); } + +long +atol_l(str, locale) + const char *str; + locale_t locale; +{ + return strtol_l(str, (char **)NULL, 10, locale); +} Index: lib/libc/stdlib/strtoumax.c =================================================================== --- lib/libc/stdlib/strtoumax.c (revision 225653) +++ lib/libc/stdlib/strtoumax.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. 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: @@ -31,12 +36,13 @@ static char sccsid[] = "from @(#)strtoul.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/strtoumax.c 165903 2007-01-09 00:28:16Z imp $"); #include <ctype.h> #include <errno.h> #include <stdlib.h> #include <inttypes.h> +#include "xlocale_private.h" /* * Convert a string to a uintmax_t integer. @@ -45,13 +51,15 @@ * alphabets and digits are each contiguous. */ uintmax_t -strtoumax(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoumax_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; uintmax_t acc; char c; uintmax_t cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoimax for comments as to the logic used. @@ -59,7 +67,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -116,3 +124,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +uintmax_t +strtoumax(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoumax_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/strtoul.c =================================================================== --- lib/libc/stdlib/strtoul.c (revision 225653) +++ lib/libc/stdlib/strtoul.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. 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: @@ -31,12 +36,13 @@ static char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/strtoul.c 165903 2007-01-09 00:28:16Z imp $"); #include <limits.h> #include <ctype.h> #include <errno.h> #include <stdlib.h> +#include "xlocale_private.h" /* * Convert a string to an unsigned long integer. @@ -45,13 +51,14 @@ * alphabets and digits are each contiguous. */ unsigned long -strtoul(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoul_l(const char * __restrict nptr, char ** __restrict endptr, int base, locale_t locale) { const char *s; unsigned long acc; char c; unsigned long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtol for comments as to the logic used. @@ -59,7 +66,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -116,3 +123,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +unsigned long +strtoul(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoul_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/strtoull.c =================================================================== --- lib/libc/stdlib/strtoull.c (revision 225653) +++ lib/libc/stdlib/strtoull.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. 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: @@ -31,12 +36,13 @@ static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/strtoull.c 165903 2007-01-09 00:28:16Z imp $"); #include <limits.h> #include <errno.h> #include <ctype.h> #include <stdlib.h> +#include "xlocale_private.h" /* * Convert a string to an unsigned long long integer. @@ -45,13 +51,15 @@ * alphabets and digits are each contiguous. */ unsigned long long -strtoull(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoull_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; unsigned long long acc; char c; unsigned long long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoq for comments as to the logic used. @@ -59,7 +67,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -116,3 +124,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +unsigned long long +strtoull(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoull_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/strtoll.c =================================================================== --- lib/libc/stdlib/strtoll.c (revision 225653) +++ lib/libc/stdlib/strtoll.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. 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: @@ -31,12 +36,13 @@ static char sccsid[] = "@(#)strtoq.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/strtoll.c 165903 2007-01-09 00:28:16Z imp $"); #include <limits.h> #include <errno.h> #include <ctype.h> #include <stdlib.h> +#include <xlocale_private.h> /* * Convert a string to a long long integer. @@ -45,13 +51,15 @@ * alphabets and digits are each contiguous. */ long long -strtoll(const char * __restrict nptr, char ** __restrict endptr, int base) +strtoll_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; unsigned long long acc; char c; unsigned long long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * Skip white space and pick up leading +/- sign if any. @@ -61,7 +69,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -138,3 +146,8 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +long long +strtoll(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtoll_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/stdlib/strtol.c =================================================================== --- lib/libc/stdlib/strtol.c (revision 225653) +++ lib/libc/stdlib/strtol.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. 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: @@ -31,12 +36,13 @@ static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/strtol.c 165903 2007-01-09 00:28:16Z imp $"); #include <limits.h> #include <ctype.h> #include <errno.h> #include <stdlib.h> +#include "xlocale_private.h" /* @@ -46,13 +52,15 @@ * alphabets and digits are each contiguous. */ long -strtol(const char * __restrict nptr, char ** __restrict endptr, int base) +strtol_l(const char * __restrict nptr, char ** __restrict endptr, int base, + locale_t locale) { const char *s; unsigned long acc; char c; unsigned long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * Skip white space and pick up leading +/- sign if any. @@ -62,7 +70,7 @@ s = nptr; do { c = *s++; - } while (isspace((unsigned char)c)); + } while (isspace_l((unsigned char)c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -138,3 +146,13 @@ *endptr = (char *)(any ? s - 1 : nptr); return (acc); } +long +strtol(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + return strtol_l(nptr, endptr, base, __get_locale()); +} +long double +strtold(const char * __restrict nptr, char ** __restrict endptr) +{ + return strtold_l(nptr, endptr, __get_locale()); +} Index: lib/libc/stdlib/atoi.c =================================================================== --- lib/libc/stdlib/atoi.c (revision 225653) +++ lib/libc/stdlib/atoi.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1988, 1993 * The Regents of the University of California. 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: @@ -31,9 +36,10 @@ static char sccsid[] = "@(#)atoi.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/atoi.c 165903 2007-01-09 00:28:16Z imp $"); #include <stdlib.h> +#include <xlocale.h> int atoi(str) @@ -41,3 +47,11 @@ { return (int)strtol(str, (char **)NULL, 10); } + +int +atoi_l(str, locale) + const char *str; + locale_t locale; +{ + return (int)strtol_l(str, (char **)NULL, 10, locale); +} Index: lib/libc/stdio/tempnam.c =================================================================== --- lib/libc/stdio/tempnam.c (revision 225653) +++ lib/libc/stdio/tempnam.c (working copy) @@ -31,7 +31,7 @@ static char sccsid[] = "@(#)tempnam.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/tempnam.c 165903 2007-01-09 00:28:16Z imp $"); #include <sys/param.h> #include <errno.h> Index: lib/libc/stdio/putwc.c =================================================================== --- lib/libc/stdio/putwc.c (revision 225653) +++ lib/libc/stdio/putwc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/putwc.c 129705 2004-05-25 10:42:52Z tjr $"); #include "namespace.h" #include <stdio.h> @@ -33,6 +38,7 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" #undef putwc @@ -41,8 +47,13 @@ * macro, may evaluate `fp' more than once. */ wint_t +putwc_l(wchar_t wc, FILE *fp, locale_t locale) +{ + FIX_LOCALE(locale); + return (fputwc_l(wc, fp, locale)); +} +wint_t putwc(wchar_t wc, FILE *fp) { - - return (fputwc(wc, fp)); + return putwc_l(wc, fp, __get_locale()); } Index: lib/libc/stdio/printf.c =================================================================== --- lib/libc/stdio/printf.c (revision 225653) +++ lib/libc/stdio/printf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * 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: @@ -34,10 +39,11 @@ static char sccsid[] = "@(#)printf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/printf.c 165903 2007-01-09 00:28:16Z imp $"); #include <stdio.h> #include <stdarg.h> +#include <xlocale.h> int printf(char const * __restrict fmt, ...) @@ -50,3 +56,14 @@ va_end(ap); return (ret); } +int +printf_l(locale_t locale, char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfprintf_l(stdout, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/getwchar.c =================================================================== --- lib/libc/stdio/getwchar.c (revision 225653) +++ lib/libc/stdio/getwchar.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 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: @@ -25,11 +30,12 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/getwchar.c 129705 2004-05-25 10:42:52Z tjr $"); #include "namespace.h" #include <stdio.h> #include <wchar.h> +#include <xlocale.h> #include "un-namespace.h" #include "libc_private.h" #include "local.h" @@ -42,6 +48,10 @@ wint_t getwchar(void) { - return (fgetwc(stdin)); } +wint_t +getwchar_l(locale_t locale) +{ + return (fgetwc_l(stdin, locale)); +} Index: lib/libc/stdio/fwalk.c =================================================================== --- lib/libc/stdio/fwalk.c (revision 225653) +++ lib/libc/stdio/fwalk.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fwalk.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fwalk.c 165903 2007-01-09 00:28:16Z imp $"); #include <sys/types.h> #include <machine/atomic.h> Index: lib/libc/stdio/fgetpos.c =================================================================== --- lib/libc/stdio/fgetpos.c (revision 225653) +++ lib/libc/stdio/fgetpos.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fgetpos.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fgetpos.c 165903 2007-01-09 00:28:16Z imp $"); #include <stdio.h> Index: lib/libc/stdio/fgets.c =================================================================== --- lib/libc/stdio/fgets.c (revision 225653) +++ lib/libc/stdio/fgets.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fgets.c 8.2 (Berkeley) 12/22/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fgets.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <stdio.h> Index: lib/libc/stdio/perror.c =================================================================== --- lib/libc/stdio/perror.c (revision 225653) +++ lib/libc/stdio/perror.c (working copy) @@ -31,7 +31,7 @@ static char sccsid[] = "@(#)perror.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/perror.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <sys/types.h> Index: lib/libc/stdio/refill.c =================================================================== --- lib/libc/stdio/refill.c (revision 225653) +++ lib/libc/stdio/refill.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)refill.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/refill.c 178287 2008-04-17 22:17:54Z jhb $"); #include "namespace.h" #include <errno.h> Index: lib/libc/stdio/getc.c =================================================================== --- lib/libc/stdio/getc.c (revision 225653) +++ lib/libc/stdio/getc.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)getc.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/getc.c 178778 2008-05-05 16:03:52Z jhb $"); #include "namespace.h" #include <stdio.h> Index: lib/libc/stdio/setbuffer.c =================================================================== --- lib/libc/stdio/setbuffer.c (revision 225653) +++ lib/libc/stdio/setbuffer.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)setbuffer.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/setbuffer.c 165903 2007-01-09 00:28:16Z imp $"); #include <stdio.h> Index: lib/libc/stdio/getline.c =================================================================== --- lib/libc/stdio/getline.c (revision 225653) +++ lib/libc/stdio/getline.c (working copy) @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/getline.c 189136 2009-02-28 06:00:58Z das $"); #define _WITH_GETLINE #include <stdio.h> Index: lib/libc/stdio/setbuf.c =================================================================== --- lib/libc/stdio/setbuf.c (revision 225653) +++ lib/libc/stdio/setbuf.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)setbuf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/setbuf.c 165903 2007-01-09 00:28:16Z imp $"); #include <stdio.h> #include "local.h" Index: lib/libc/stdio/fpurge.c =================================================================== --- lib/libc/stdio/fpurge.c (revision 225653) +++ lib/libc/stdio/fpurge.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fpurge.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fpurge.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <errno.h> Index: lib/libc/stdio/Symbol.map =================================================================== --- lib/libc/stdio/Symbol.map (revision 225653) +++ lib/libc/stdio/Symbol.map (working copy) @@ -1,5 +1,5 @@ /* - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/Symbol.map 189356 2009-03-04 03:38:51Z das $ */ FBSD_1.0 { @@ -108,6 +108,43 @@ __swbuf; wprintf; wscanf; + asprintf_l; + fprintf_l; + fwprintf_l; + printf_l; + snprintf_l; + sprintf_l; + swprintf_l; + vasprintf_l; + vfprintf_l; + vfwprintf_l; + vprintf_l; + vsnprintf_l; + vsprintf_l; + vswprintf_l; + vwprintf_l; + wprintf_l; + fgetwc_l; + fputwc_l; + ungetwc_l; + vfwscanf_l; + vswscanf_l; + fscanf_l; + fwscanf_l; + scanf_l; + sscanf_l; + swscanf_l; + vfscanf_l; + vscanf_l; + vsscanf_l; + vwscanf_l; + wscanf_l; + fgetws_l; + fputws_l; + getwc_l; + getwchar_l; + putwc_l; + putwchar_l; }; FBSD_1.1 { Index: lib/libc/stdio/gets.c =================================================================== --- lib/libc/stdio/gets.c (revision 225653) +++ lib/libc/stdio/gets.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)gets.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/gets.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <unistd.h> Index: lib/libc/stdio/getw.c =================================================================== --- lib/libc/stdio/getw.c (revision 225653) +++ lib/libc/stdio/getw.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)getw.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/getw.c 165903 2007-01-09 00:28:16Z imp $"); #include <stdio.h> Index: lib/libc/stdio/fgetwln.c =================================================================== --- lib/libc/stdio/fgetwln.c (revision 225653) +++ lib/libc/stdio/fgetwln.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fgetwln.c 133223 2004-08-06 17:00:09Z tjr $"); #include "namespace.h" #include <stdio.h> @@ -33,18 +38,20 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" wchar_t * -fgetwln(FILE * __restrict fp, size_t *lenp) +fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t locale) { wint_t wc; size_t len; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); len = 0; - while ((wc = __fgetwc(fp)) != WEOF) { + while ((wc = __fgetwc(fp, locale)) != WEOF) { #define GROW 512 if (len * sizeof(wchar_t) >= fp->_lb._size && __slbexpand(fp, (len + GROW) * sizeof(wchar_t))) @@ -65,3 +72,8 @@ *lenp = 0; return (NULL); } +wchar_t * +fgetwln(FILE * __restrict fp, size_t *lenp) +{ + return fgetwln_l(fp, lenp, __get_locale()); +} Index: lib/libc/stdio/getwc.c =================================================================== --- lib/libc/stdio/getwc.c (revision 225653) +++ lib/libc/stdio/getwc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 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: @@ -25,11 +30,12 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/getwc.c 129705 2004-05-25 10:42:52Z tjr $"); #include "namespace.h" #include <stdio.h> #include <wchar.h> +#include <xlocale.h> #include "un-namespace.h" #include "libc_private.h" #include "local.h" @@ -43,6 +49,10 @@ wint_t getwc(FILE *fp) { - return (fgetwc(fp)); } +wint_t +getwc_l(FILE *fp, locale_t locale) +{ + return (fgetwc_l(fp, locale)); +} Index: lib/libc/stdio/xprintf_vis.c =================================================================== --- lib/libc/stdio/xprintf_vis.c (revision 225653) +++ lib/libc/stdio/xprintf_vis.c (working copy) @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/xprintf_vis.c 154815 2006-01-25 12:45:24Z phk $ */ #include <namespace.h> Index: lib/libc/stdio/xprintf_float.c =================================================================== --- lib/libc/stdio/xprintf_float.c (revision 225653) +++ lib/libc/stdio/xprintf_float.c (working copy) @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/xprintf_float.c 153486 2005-12-16 18:56:39Z phk $ */ #include <namespace.h> Index: lib/libc/stdio/vsnprintf.c =================================================================== --- lib/libc/stdio/vsnprintf.c (revision 225653) +++ lib/libc/stdio/vsnprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * 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: @@ -34,20 +39,22 @@ static char sccsid[] = "@(#)vsnprintf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vsnprintf.c 205021 2010-03-11 17:03:32Z jhb $"); #include <limits.h> #include <stdio.h> #include "local.h" +#include "xlocale_private.h" int -vsnprintf(char * __restrict str, size_t n, const char * __restrict fmt, - __va_list ap) +vsnprintf_l(char * __restrict str, size_t n, locale_t locale, + const char * __restrict fmt, __va_list ap) { size_t on; int ret; char dummy[2]; FILE f = FAKE_FILE; + FIX_LOCALE(locale); on = n; if (n != 0) @@ -64,8 +71,14 @@ f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = n; - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, locale, fmt, ap); if (on > 0) *f._p = '\0'; return (ret); } +int +vsnprintf(char * __restrict str, size_t n, const char * __restrict fmt, + __va_list ap) +{ + return vsnprintf_l(str, n, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/flags.c =================================================================== --- lib/libc/stdio/flags.c (revision 225653) +++ lib/libc/stdio/flags.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)flags.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/flags.c 165903 2007-01-09 00:28:16Z imp $"); #include <sys/types.h> #include <sys/file.h> Index: lib/libc/stdio/putwchar.c =================================================================== --- lib/libc/stdio/putwchar.c (revision 225653) +++ lib/libc/stdio/putwchar.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/putwchar.c 129705 2004-05-25 10:42:52Z tjr $"); #include "namespace.h" #include <stdio.h> @@ -33,6 +38,7 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" #undef putwchar @@ -40,8 +46,13 @@ * Synonym for fputwc(wc, stdout). */ wint_t +putwchar_l(wchar_t wc, locale_t locale) +{ + FIX_LOCALE(locale); + return (fputwc_l(wc, stdout, locale)); +} +wint_t putwchar(wchar_t wc) { - - return (fputwc(wc, stdout)); + return putwchar_l(wc, __get_locale()); } Index: lib/libc/stdio/ferror.c =================================================================== --- lib/libc/stdio/ferror.c (revision 225653) +++ lib/libc/stdio/ferror.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)ferror.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/ferror.c 178778 2008-05-05 16:03:52Z jhb $"); #include "namespace.h" #include <stdio.h> Index: lib/libc/stdio/vswprintf.c =================================================================== --- lib/libc/stdio/vswprintf.c (revision 225653) +++ lib/libc/stdio/vswprintf.c (working copy) @@ -4,6 +4,11 @@ * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> * 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: @@ -31,17 +36,18 @@ #if 0 __FBSDID("FreeBSD: src/lib/libc/stdio/vasprintf.c,v 1.16 2002/08/21 16:19:57 mike Exp "); #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vswprintf.c 205021 2010-03-11 17:03:32Z jhb $"); #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <wchar.h> #include "local.h" +#include "xlocale_private.h" int -vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, - __va_list ap) +vswprintf_l(wchar_t * __restrict s, size_t n, locale_t locale, + const wchar_t * __restrict fmt, __va_list ap) { static const mbstate_t initial; mbstate_t mbs; @@ -49,6 +55,7 @@ char *mbp; int ret, sverrno; size_t nwc; + FIX_LOCALE(locale); if (n == 0) { errno = EINVAL; @@ -62,7 +69,7 @@ return (-1); } f._bf._size = f._w = 127; /* Leave room for the NUL */ - ret = __vfwprintf(&f, fmt, ap); + ret = __vfwprintf(&f, locale, fmt, ap); if (ret < 0) { sverrno = errno; free(f._bf._base); @@ -76,7 +83,7 @@ * fputwc() did in __vfwprintf(). */ mbs = initial; - nwc = mbsrtowcs(s, (const char **)&mbp, n, &mbs); + nwc = mbsrtowcs_l(s, (const char **)&mbp, n, &mbs, locale); free(f._bf._base); if (nwc == (size_t)-1) { errno = EILSEQ; @@ -90,3 +97,9 @@ return (ret); } +int +vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, + __va_list ap) +{ + return vswprintf_l(s, n, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/vsscanf.c =================================================================== --- lib/libc/stdio/vsscanf.c (revision 225653) +++ lib/libc/stdio/vsscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. 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. + * * This code is derived from software contributed to Berkeley by * Donn Seeley at UUNET Technologies, Inc. * @@ -34,11 +39,12 @@ static char sccsid[] = "@(#)vsscanf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vsscanf.c 205021 2010-03-11 17:03:32Z jhb $"); #include <stdio.h> #include <string.h> #include "local.h" +#include "xlocale_private.h" static int eofread(void *, char *, int); @@ -52,14 +58,21 @@ } int -vsscanf(const char * __restrict str, const char * __restrict fmt, - __va_list ap) +vsscanf_l(const char * __restrict str, locale_t locale, + const char * __restrict fmt, __va_list ap) { FILE f = FAKE_FILE; + FIX_LOCALE(locale); f._flags = __SRD; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._r = strlen(str); f._read = eofread; - return (__svfscanf(&f, fmt, ap)); + return (__svfscanf(&f, locale, fmt, ap)); } +int +vsscanf(const char * __restrict str, const char * __restrict fmt, + __va_list ap) +{ + return vsscanf_l(str, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/snprintf.c =================================================================== --- lib/libc/stdio/snprintf.c (revision 225653) +++ lib/libc/stdio/snprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. 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. + * * This code is derived from software contributed to Berkeley by * Chris Torek. * @@ -34,11 +39,12 @@ static char sccsid[] = "@(#)snprintf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/snprintf.c 205021 2010-03-11 17:03:32Z jhb $"); #include <limits.h> #include <stdio.h> #include <stdarg.h> +#include "xlocale_private.h" #include "local.h" @@ -59,9 +65,34 @@ f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = n; - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, __get_locale(), fmt, ap); if (on > 0) *f._p = '\0'; va_end(ap); return (ret); } +int +snprintf_l(char * __restrict str, size_t n, locale_t locale, + char const * __restrict fmt, ...) +{ + size_t on; + int ret; + va_list ap; + FILE f = FAKE_FILE; + FIX_LOCALE(locale); + + on = n; + if (n != 0) + n--; + if (n > INT_MAX) + n = INT_MAX; + va_start(ap, fmt); + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *)str; + f._bf._size = f._w = n; + ret = __vfprintf(&f, locale, fmt, ap); + if (on > 0) + *f._p = '\0'; + va_end(ap); + return (ret); +} Index: lib/libc/stdio/ungetwc.c =================================================================== --- lib/libc/stdio/ungetwc.c (revision 225653) +++ lib/libc/stdio/ungetwc.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/ungetwc.c 178287 2008-04-17 22:17:54Z jhb $"); #include "namespace.h" #include <errno.h> @@ -37,19 +42,21 @@ #include "libc_private.h" #include "local.h" #include "mblocal.h" +#include "xlocale_private.h" /* * Non-MT-safe version. */ wint_t -__ungetwc(wint_t wc, FILE *fp) +__ungetwc(wint_t wc, FILE *fp, locale_t locale) { char buf[MB_LEN_MAX]; size_t len; + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); if (wc == WEOF) return (WEOF); - if ((len = __wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { + if ((len = l->__wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { fp->_flags |= __SERR; return (WEOF); } @@ -64,14 +71,20 @@ * MT-safe version. */ wint_t -ungetwc(wint_t wc, FILE *fp) +ungetwc_l(wint_t wc, FILE *fp, locale_t locale) { wint_t r; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - r = __ungetwc(wc, fp); + r = __ungetwc(wc, fp, locale); FUNLOCKFILE(fp); return (r); } +wint_t +ungetwc(wint_t wc, FILE *fp) +{ + return ungetwc_l(wc, fp, __get_locale()); +} Index: lib/libc/stdio/swprintf.c =================================================================== --- lib/libc/stdio/swprintf.c (revision 225653) +++ lib/libc/stdio/swprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 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: @@ -25,11 +30,12 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/swprintf.c 103739 2002-09-21 13:00:30Z tjr $"); #include <stdarg.h> #include <stdio.h> #include <wchar.h> +#include <xlocale.h> int swprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,16 @@ return (ret); } +int +swprintf_l(wchar_t * __restrict s, size_t n, locale_t locale, + const wchar_t * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vswprintf_l(s, n, locale, fmt, ap); + va_end(ap); + + return (ret); +} Index: lib/libc/stdio/getchar.c =================================================================== --- lib/libc/stdio/getchar.c (revision 225653) +++ lib/libc/stdio/getchar.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)getchar.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/getchar.c 178778 2008-05-05 16:03:52Z jhb $"); /* * A subroutine version of the macro getchar. Index: lib/libc/stdio/feof.c =================================================================== --- lib/libc/stdio/feof.c (revision 225653) +++ lib/libc/stdio/feof.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)feof.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/feof.c 178778 2008-05-05 16:03:52Z jhb $"); #include "namespace.h" #include <stdio.h> Index: lib/libc/stdio/wscanf.c =================================================================== --- lib/libc/stdio/wscanf.c (revision 225653) +++ lib/libc/stdio/wscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 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: @@ -25,11 +30,12 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/wscanf.c 103856 2002-09-23 12:40:06Z tjr $"); #include <stdarg.h> #include <stdio.h> #include <wchar.h> +#include <xlocale.h> int wscanf(const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ return (r); } +int +wscanf_l(locale_t locale, const wchar_t * __restrict fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = vfwscanf_l(stdin, locale, fmt, ap); + va_end(ap); + + return (r); +} Index: lib/libc/stdio/stdio.c =================================================================== --- lib/libc/stdio/stdio.c (revision 225653) +++ lib/libc/stdio/stdio.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)stdio.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/stdio.c 178782 2008-05-05 16:14:02Z jhb $"); #include "namespace.h" #include <errno.h> Index: lib/libc/stdio/fvwrite.c =================================================================== --- lib/libc/stdio/fvwrite.c (revision 225653) +++ lib/libc/stdio/fvwrite.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fvwrite.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fvwrite.c 199781 2009-11-25 04:21:42Z wollman $"); #include <stdio.h> #include <stdlib.h> Index: lib/libc/stdio/wsetup.c =================================================================== --- lib/libc/stdio/wsetup.c (revision 225653) +++ lib/libc/stdio/wsetup.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)wsetup.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/wsetup.c 186887 2009-01-08 06:38:06Z das $"); #include <errno.h> #include <stdio.h> Index: lib/libc/stdio/mktemp.c =================================================================== --- lib/libc/stdio/mktemp.c (revision 225653) +++ lib/libc/stdio/mktemp.c (working copy) @@ -31,7 +31,7 @@ static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/mktemp.c 204447 2010-02-28 13:31:29Z jh $"); #include "namespace.h" #include <sys/param.h> Index: lib/libc/stdio/xprintf_errno.c =================================================================== --- lib/libc/stdio/xprintf_errno.c (revision 225653) +++ lib/libc/stdio/xprintf_errno.c (working copy) @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/xprintf_errno.c 154815 2006-01-25 12:45:24Z phk $ */ #include <namespace.h> Index: lib/libc/stdio/fscanf.c =================================================================== --- lib/libc/stdio/fscanf.c (revision 225653) +++ lib/libc/stdio/fscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * 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: @@ -34,7 +39,7 @@ static char sccsid[] = "@(#)fscanf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fscanf.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <stdio.h> @@ -42,6 +47,7 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" int fscanf(FILE * __restrict fp, char const * __restrict fmt, ...) @@ -51,8 +57,22 @@ va_start(ap, fmt); FLOCKFILE(fp); - ret = __svfscanf(fp, fmt, ap); + ret = __svfscanf(fp, __get_locale(), fmt, ap); va_end(ap); FUNLOCKFILE(fp); return (ret); } +int +fscanf_l(FILE * __restrict fp, locale_t locale, char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + FLOCKFILE(fp); + ret = __svfscanf(fp, locale, fmt, ap); + va_end(ap); + FUNLOCKFILE(fp); + return (ret); +} Index: lib/libc/stdio/fcloseall.c =================================================================== --- lib/libc/stdio/fcloseall.c (revision 225653) +++ lib/libc/stdio/fcloseall.c (working copy) @@ -24,7 +24,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fcloseall.c 157963 2006-04-22 16:47:59Z deischen $"); #include <stdio.h> #include "local.h" Index: lib/libc/stdio/putchar.c =================================================================== --- lib/libc/stdio/putchar.c (revision 225653) +++ lib/libc/stdio/putchar.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)putchar.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/putchar.c 178778 2008-05-05 16:03:52Z jhb $"); #include "namespace.h" #include <stdio.h> Index: lib/libc/stdio/dprintf.c =================================================================== --- lib/libc/stdio/dprintf.c (revision 225653) +++ lib/libc/stdio/dprintf.c (working copy) @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/dprintf.c 189356 2009-03-04 03:38:51Z das $"); #define _WITH_DPRINTF #include "namespace.h" Index: lib/libc/stdio/ftell.c =================================================================== --- lib/libc/stdio/ftell.c (revision 225653) +++ lib/libc/stdio/ftell.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)ftell.c 8.2 (Berkeley) 5/4/95"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/ftell.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <sys/types.h> Index: lib/libc/stdio/fprintf.c =================================================================== --- lib/libc/stdio/fprintf.c (revision 225653) +++ lib/libc/stdio/fprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * 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: @@ -34,10 +39,11 @@ static char sccsid[] = "@(#)fprintf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fprintf.c 165903 2007-01-09 00:28:16Z imp $"); #include <stdio.h> #include <stdarg.h> +#include "xlocale_private.h" int fprintf(FILE * __restrict fp, const char * __restrict fmt, ...) @@ -46,7 +52,19 @@ va_list ap; va_start(ap, fmt); - ret = vfprintf(fp, fmt, ap); + ret = vfprintf_l(fp, __get_locale(), fmt, ap); va_end(ap); return (ret); } +int +fprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt, ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + ret = vfprintf_l(fp, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/fgetln.c =================================================================== --- lib/libc/stdio/fgetln.c (revision 225653) +++ lib/libc/stdio/fgetln.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fgetln.c 8.2 (Berkeley) 1/2/94"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fgetln.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <stdio.h> Index: lib/libc/stdio/vscanf.c =================================================================== --- lib/libc/stdio/vscanf.c (revision 225653) +++ lib/libc/stdio/vscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Donn Seeley at UUNET Technologies, Inc. * + * 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: @@ -34,23 +39,33 @@ static char sccsid[] = "@(#)vscanf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vscanf.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <stdio.h> #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" int -vscanf(fmt, ap) +vscanf_l(locale, fmt, ap) + locale_t locale; const char * __restrict fmt; __va_list ap; { int retval; + FIX_LOCALE(locale); FLOCKFILE(stdin); - retval = __svfscanf(stdin, fmt, ap); + retval = __svfscanf(stdin, locale, fmt, ap); FUNLOCKFILE(stdin); return (retval); } +int +vscanf(fmt, ap) + const char * __restrict fmt; + __va_list ap; +{ + return vscanf_l(__get_locale(), fmt, ap); +} Index: lib/libc/stdio/printfcommon.h =================================================================== --- lib/libc/stdio/printfcommon.h (revision 225653) +++ lib/libc/stdio/printfcommon.h (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * 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: @@ -29,7 +34,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/printfcommon.h 187582 2009-01-22 08:14:28Z das $ */ /* @@ -79,14 +84,14 @@ * remain valid until io_flush() is called. */ static inline int -io_print(struct io_state *iop, const CHAR * __restrict ptr, int len) +io_print(struct io_state *iop, const CHAR * __restrict ptr, int len, locale_t locale) { iop->iov[iop->uio.uio_iovcnt].iov_base = (char *)ptr; iop->iov[iop->uio.uio_iovcnt].iov_len = len; iop->uio.uio_resid += len; if (++iop->uio.uio_iovcnt >= NIOV) - return (__sprint(iop->fp, &iop->uio)); + return (__sprint(iop->fp, &iop->uio, locale)); else return (0); } @@ -107,13 +112,14 @@ * or the zeroes array. */ static inline int -io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with) +io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with, + locale_t locale) { int n; while (howmany > 0) { n = (howmany >= PADSIZE) ? PADSIZE : howmany; - if (io_print(iop, with, n)) + if (io_print(iop, with, n, locale)) return (-1); howmany -= n; } @@ -126,7 +132,7 @@ */ static inline int io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep, - int len, const CHAR * __restrict with) + int len, const CHAR * __restrict with, locale_t locale) { int p_len; @@ -134,19 +140,19 @@ if (p_len > len) p_len = len; if (p_len > 0) { - if (io_print(iop, p, p_len)) + if (io_print(iop, p, p_len, locale)) return (-1); } else { p_len = 0; } - return (io_pad(iop, len - p_len, with)); + return (io_pad(iop, len - p_len, with, locale)); } static inline int -io_flush(struct io_state *iop) +io_flush(struct io_state *iop, locale_t locale) { - return (__sprint(iop->fp, &iop->uio)); + return (__sprint(iop->fp, &iop->uio, locale)); } /* Index: lib/libc/stdio/sprintf.c =================================================================== --- lib/libc/stdio/sprintf.c (revision 225653) +++ lib/libc/stdio/sprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * 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: @@ -34,12 +39,13 @@ static char sccsid[] = "@(#)sprintf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/sprintf.c 200802 2009-12-21 19:59:38Z delphij $"); #include <stdio.h> #include <stdarg.h> #include <limits.h> #include "local.h" +#include "xlocale_private.h" int sprintf(char * __restrict str, char const * __restrict fmt, ...) @@ -52,3 +58,16 @@ va_end(ap); return (ret); } +int +sprintf_l(char * __restrict str, locale_t locale, char const * __restrict fmt, + ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + ret = vsprintf_l(str, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/vprintf.c =================================================================== --- lib/libc/stdio/vprintf.c (revision 225653) +++ lib/libc/stdio/vprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * 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: @@ -34,13 +39,18 @@ static char sccsid[] = "@(#)vprintf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vprintf.c 165903 2007-01-09 00:28:16Z imp $"); #include <stdio.h> +#include <xlocale.h> int vprintf(const char * __restrict fmt, __va_list ap) { - return (vfprintf(stdout, fmt, ap)); } +int +vprintf_l(locale_t locale, const char * __restrict fmt, __va_list ap) +{ + return (vfprintf_l(stdout, locale, fmt, ap)); +} Index: lib/libc/stdio/rewind.c =================================================================== --- lib/libc/stdio/rewind.c (revision 225653) +++ lib/libc/stdio/rewind.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)rewind.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/rewind.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <errno.h> Index: lib/libc/stdio/clrerr.c =================================================================== --- lib/libc/stdio/clrerr.c (revision 225653) +++ lib/libc/stdio/clrerr.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)clrerr.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/clrerr.c 178778 2008-05-05 16:03:52Z jhb $"); #include "namespace.h" #include <stdio.h> Index: lib/libc/stdio/wprintf.c =================================================================== --- lib/libc/stdio/wprintf.c (revision 225653) +++ lib/libc/stdio/wprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 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: @@ -25,11 +30,12 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/wprintf.c 103739 2002-09-21 13:00:30Z tjr $"); #include <stdarg.h> #include <stdio.h> #include <wchar.h> +#include <xlocale.h> int wprintf(const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ return (ret); } +int +wprintf_l(locale_t locale, const wchar_t * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfwprintf_l(stdout, locale, fmt, ap); + va_end(ap); + + return (ret); +} Index: lib/libc/stdio/xprintf.c =================================================================== --- lib/libc/stdio/xprintf.c (revision 225653) +++ lib/libc/stdio/xprintf.c (working copy) @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/xprintf.c 205021 2010-03-11 17:03:32Z jhb $ */ #include "namespace.h" Index: lib/libc/stdio/remove.c =================================================================== --- lib/libc/stdio/remove.c (revision 225653) +++ lib/libc/stdio/remove.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)remove.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/remove.c 165903 2007-01-09 00:28:16Z imp $"); #include <sys/types.h> #include <sys/stat.h> Index: lib/libc/stdio/freopen.c =================================================================== --- lib/libc/stdio/freopen.c (revision 225653) +++ lib/libc/stdio/freopen.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)freopen.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/freopen.c 216334 2010-12-09 20:28:30Z jhb $"); #include "namespace.h" #include <sys/types.h> Index: lib/libc/stdio/fwide.c =================================================================== --- lib/libc/stdio/fwide.c (revision 225653) +++ lib/libc/stdio/fwide.c (working copy) @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fwide.c 178287 2008-04-17 22:17:54Z jhb $"); #include "namespace.h" #include <errno.h> Index: lib/libc/stdio/printf-pos.c =================================================================== --- lib/libc/stdio/printf-pos.c (revision 225653) +++ lib/libc/stdio/printf-pos.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/printf-pos.c 216121 2010-12-02 13:40:21Z gavin $"); /* * This is the code responsible for handling positional arguments Index: lib/libc/stdio/xprintf_quote.c =================================================================== --- lib/libc/stdio/xprintf_quote.c (revision 225653) +++ lib/libc/stdio/xprintf_quote.c (working copy) @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/xprintf_quote.c 156207 2006-03-02 08:53:45Z phk $ */ #include <namespace.h> Index: lib/libc/stdio/xprintf_str.c =================================================================== --- lib/libc/stdio/xprintf_str.c (revision 225653) +++ lib/libc/stdio/xprintf_str.c (working copy) @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/xprintf_str.c 153486 2005-12-16 18:56:39Z phk $ */ #include <namespace.h> Index: lib/libc/stdio/fsetpos.c =================================================================== --- lib/libc/stdio/fsetpos.c (revision 225653) +++ lib/libc/stdio/fsetpos.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fsetpos.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fsetpos.c 165903 2007-01-09 00:28:16Z imp $"); #include <sys/types.h> #include <stdio.h> Index: lib/libc/stdio/vfwprintf.c =================================================================== --- lib/libc/stdio/vfwprintf.c (revision 225653) +++ lib/libc/stdio/vfwprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * 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: @@ -36,7 +41,7 @@ #endif /* LIBC_SCCS and not lint */ #endif #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vfwprintf.c 199782 2009-11-25 04:27:55Z wollman $"); /* * Actual wprintf innards. @@ -65,10 +70,11 @@ #include "local.h" #include "fvwrite.h" #include "printflocal.h" +#include "xlocale_private.h" -static int __sprint(FILE *, struct __suio *); -static int __sbprintf(FILE *, const wchar_t *, va_list) __noinline; -static wint_t __xfputwc(wchar_t, FILE *); +static int __sprint(FILE *, struct __suio *, locale_t); +static int __sbprintf(FILE *, locale_t, const wchar_t *, va_list) __noinline; +static wint_t __xfputwc(wchar_t, FILE *, locale_t); static wchar_t *__mbsconv(char *, int); #define CHAR wchar_t @@ -85,28 +91,28 @@ static const mbstate_t initial_mbs; static inline wchar_t -get_decpt(void) +get_decpt(locale_t locale) { mbstate_t mbs; wchar_t decpt; int nconv; mbs = initial_mbs; - nconv = mbrtowc(&decpt, localeconv()->decimal_point, MB_CUR_MAX, &mbs); + nconv = mbrtowc(&decpt, localeconv_l(locale)->decimal_point, MB_CUR_MAX, &mbs); if (nconv == (size_t)-1 || nconv == (size_t)-2) decpt = '.'; /* failsafe */ return (decpt); } static inline wchar_t -get_thousep(void) +get_thousep(locale_t locale) { mbstate_t mbs; wchar_t thousep; int nconv; mbs = initial_mbs; - nconv = mbrtowc(&thousep, localeconv()->thousands_sep, + nconv = mbrtowc(&thousep, localeconv_l(locale)->thousands_sep, MB_CUR_MAX, &mbs); if (nconv == (size_t)-1 || nconv == (size_t)-2) thousep = '\0'; /* failsafe */ @@ -119,11 +125,11 @@ * of wide characters that will be printed. */ static int -grouping_init(struct grouping_state *gs, int ndigits) +grouping_init(struct grouping_state *gs, int ndigits, locale_t locale) { - gs->grouping = localeconv()->grouping; - gs->thousands_sep = get_thousep(); + gs->grouping = localeconv_l(locale)->grouping; + gs->thousands_sep = get_thousep(locale); gs->nseps = gs->nrepeats = 0; gs->lead = ndigits; @@ -145,11 +151,11 @@ */ static int grouping_print(struct grouping_state *gs, struct io_state *iop, - const CHAR *cp, const CHAR *ep) + const CHAR *cp, const CHAR *ep, locale_t locale) { const CHAR *cp0 = cp; - if (io_printandpad(iop, cp, ep, gs->lead, zeroes)) + if (io_printandpad(iop, cp, ep, gs->lead, zeroes, locale)) return (-1); cp += gs->lead; while (gs->nseps > 0 || gs->nrepeats > 0) { @@ -159,9 +165,9 @@ gs->grouping--; gs->nseps--; } - if (io_print(iop, &gs->thousands_sep, 1)) + if (io_print(iop, &gs->thousands_sep, 1, locale)) return (-1); - if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes)) + if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, locale)) return (-1); cp += *gs->grouping; } @@ -180,7 +186,7 @@ * string eclipses the benefits of buffering. */ static int -__sprint(FILE *fp, struct __suio *uio) +__sprint(FILE *fp, struct __suio *uio, locale_t locale) { struct __siov *iov; wchar_t *p; @@ -191,7 +197,7 @@ p = (wchar_t *)iov->iov_base; len = iov->iov_len; for (i = 0; i < len; i++) { - if (__xfputwc(p[i], fp) == WEOF) + if (__xfputwc(p[i], fp, locale) == WEOF) return (-1); } } @@ -205,7 +211,7 @@ * worries about ungetc buffers and so forth. */ static int -__sbprintf(FILE *fp, const wchar_t *fmt, va_list ap) +__sbprintf(FILE *fp, locale_t locale, const wchar_t *fmt, va_list ap) { int ret; FILE fake; @@ -229,7 +235,7 @@ fake._lbfsize = 0; /* not actually used, but Just In Case */ /* do the work, then copy any error status */ - ret = __vfwprintf(&fake, fmt, ap); + ret = __vfwprintf(&fake, locale, fmt, ap); if (ret >= 0 && __fflush(&fake)) ret = WEOF; if (fake._flags & __SERR) @@ -242,7 +248,7 @@ * File must already be locked. */ static wint_t -__xfputwc(wchar_t wc, FILE *fp) +__xfputwc(wchar_t wc, FILE *fp, locale_t locale) { mbstate_t mbs; char buf[MB_LEN_MAX]; @@ -251,7 +257,7 @@ size_t len; if ((fp->_flags & __SSTR) == 0) - return (__fputwc(wc, fp)); + return (__fputwc(wc, fp, locale)); mbs = initial_mbs; if ((len = wcrtomb(buf, wc, &mbs)) == (size_t)-1) { @@ -343,21 +349,27 @@ * MT-safe version */ int -vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap) +vfwprintf_l(FILE * __restrict fp, locale_t locale, + const wchar_t * __restrict fmt0, va_list ap) { int ret; - + FIX_LOCALE(locale); FLOCKFILE(fp); /* optimise fprintf(stderr) (and other unbuffered Unix files) */ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && fp->_file >= 0) - ret = __sbprintf(fp, fmt0, ap); + ret = __sbprintf(fp, locale, fmt0, ap); else - ret = __vfwprintf(fp, fmt0, ap); + ret = __vfwprintf(fp, locale, fmt0, ap); FUNLOCKFILE(fp); return (ret); } +int +vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap) +{ + return vfwprintf_l(fp, __get_locale(), fmt0, ap); +} /* * The size of the buffer we use as scratch space for integer @@ -374,7 +386,7 @@ * Non-MT-safe version */ int -__vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap) +__vfwprintf(FILE *fp, locale_t locale, const wchar_t *fmt0, va_list ap) { wchar_t *fmt; /* format string */ wchar_t ch; /* character from fmt */ @@ -437,19 +449,19 @@ /* BEWARE, these `goto error' on error. */ #define PRINT(ptr, len) do { \ - if (io_print(&io, (ptr), (len))) \ + if (io_print(&io, (ptr), (len), locale)) \ goto error; \ } while (0) #define PAD(howmany, with) { \ - if (io_pad(&io, (howmany), (with))) \ + if (io_pad(&io, (howmany), (with), locale)) \ goto error; \ } #define PRINTANDPAD(p, ep, len, with) { \ - if (io_printandpad(&io, (p), (ep), (len), (with))) \ + if (io_printandpad(&io, (p), (ep), (len), (with), locale)) \ goto error; \ } #define FLUSH() { \ - if (io_flush(&io)) \ + if (io_flush(&io, locale)) \ goto error; \ } @@ -529,7 +541,7 @@ io_init(&io, fp); ret = 0; #ifndef NO_FLOATING_POINT - decimal_point = get_decpt(); + decimal_point = get_decpt(locale); #endif /* @@ -816,7 +828,7 @@ if (prec || flags & ALT) size += prec + 1; if ((flags & GROUPING) && expt > 0) - size += grouping_init(&gs, expt); + size += grouping_init(&gs, expt, locale); } break; #endif /* !NO_FLOATING_POINT */ @@ -955,7 +967,7 @@ if (size > BUF) /* should never happen */ abort(); if ((flags & GROUPING) && size != 0) - size += grouping_init(&gs, size); + size += grouping_init(&gs, size, locale); break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') @@ -1018,7 +1030,7 @@ /* leading zeroes from decimal precision */ PAD(dprec - size, zeroes); if (gs.grouping) { - if (grouping_print(&gs, &io, cp, buf+BUF) < 0) + if (grouping_print(&gs, &io, cp, buf+BUF, locale) < 0) goto error; } else { PRINT(cp, size); @@ -1036,7 +1048,7 @@ } else { if (gs.grouping) { n = grouping_print(&gs, &io, - cp, convbuf + ndig); + cp, convbuf + ndig, locale); if (n < 0) goto error; cp += n; Index: lib/libc/stdio/_flock_stub.c =================================================================== --- lib/libc/stdio/_flock_stub.c (revision 225653) +++ lib/libc/stdio/_flock_stub.c (working copy) @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/_flock_stub.c 178287 2008-04-17 22:17:54Z jhb $"); #include "namespace.h" #include <stdio.h> Index: lib/libc/stdio/vdprintf.c =================================================================== --- lib/libc/stdio/vdprintf.c (revision 225653) +++ lib/libc/stdio/vdprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2009 David Schultz <das@FreeBSD.org> * 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vdprintf.c 205021 2010-03-11 17:03:32Z jhb $"); #include "namespace.h" #include <errno.h> @@ -35,6 +40,7 @@ #include "un-namespace.h" #include "local.h" +#include "xlocale_private.h" int vdprintf(int fd, const char * __restrict fmt, va_list ap) @@ -57,7 +63,7 @@ f._bf._base = buf; f._bf._size = sizeof(buf); - if ((ret = __vfprintf(&f, fmt, ap)) < 0) + if ((ret = __vfprintf(&f, __get_locale(), fmt, ap)) < 0) return (ret); return (__fflush(&f) ? EOF : ret); Index: lib/libc/stdio/vfprintf.c =================================================================== --- lib/libc/stdio/vfprintf.c (revision 225653) +++ lib/libc/stdio/vfprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * 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: @@ -34,7 +39,7 @@ static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vfprintf.c 205021 2010-03-11 17:03:32Z jhb $"); /* * Actual printf innards. @@ -57,6 +62,7 @@ #include <printf.h> #include <stdarg.h> +#include "xlocale_private.h" #include "un-namespace.h" #include "libc_private.h" @@ -64,8 +70,8 @@ #include "fvwrite.h" #include "printflocal.h" -static int __sprint(FILE *, struct __suio *); -static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0) +static int __sprint(FILE *, struct __suio *, locale_t); +static int __sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0) __noinline; static char *__wcsconv(wchar_t *, int); @@ -87,11 +93,11 @@ * of bytes that will be needed. */ static int -grouping_init(struct grouping_state *gs, int ndigits) +grouping_init(struct grouping_state *gs, int ndigits, locale_t loc) { struct lconv *locale; - locale = localeconv(); + locale = localeconv_l(loc); gs->grouping = locale->grouping; gs->thousands_sep = locale->thousands_sep; gs->thousep_len = strlen(gs->thousands_sep); @@ -116,11 +122,11 @@ */ static int grouping_print(struct grouping_state *gs, struct io_state *iop, - const CHAR *cp, const CHAR *ep) + const CHAR *cp, const CHAR *ep, locale_t locale) { const CHAR *cp0 = cp; - if (io_printandpad(iop, cp, ep, gs->lead, zeroes)) + if (io_printandpad(iop, cp, ep, gs->lead, zeroes, locale)) return (-1); cp += gs->lead; while (gs->nseps > 0 || gs->nrepeats > 0) { @@ -130,9 +136,9 @@ gs->grouping--; gs->nseps--; } - if (io_print(iop, gs->thousands_sep, gs->thousep_len)) + if (io_print(iop, gs->thousands_sep, gs->thousep_len, locale)) return (-1); - if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes)) + if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, locale)) return (-1); cp += *gs->grouping; } @@ -146,7 +152,7 @@ * then reset it so that it can be reused. */ static int -__sprint(FILE *fp, struct __suio *uio) +__sprint(FILE *fp, struct __suio *uio, locale_t locale) { int err; @@ -166,7 +172,7 @@ * worries about ungetc buffers and so forth. */ static int -__sbprintf(FILE *fp, const char *fmt, va_list ap) +__sbprintf(FILE *fp, locale_t locale, const char *fmt, va_list ap) { int ret; FILE fake = FAKE_FILE; @@ -190,7 +196,7 @@ fake._lbfsize = 0; /* not actually used, but Just In Case */ /* do the work, then copy any error status */ - ret = __vfprintf(&fake, fmt, ap); + ret = __vfprintf(&fake, locale, fmt, ap); if (ret >= 0 && __fflush(&fake)) ret = EOF; if (fake._flags & __SERR) @@ -261,21 +267,27 @@ * MT-safe version */ int -vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap) - +vfprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt0, + va_list ap) { int ret; + FIX_LOCALE(locale); FLOCKFILE(fp); /* optimise fprintf(stderr) (and other unbuffered Unix files) */ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && fp->_file >= 0) - ret = __sbprintf(fp, fmt0, ap); + ret = __sbprintf(fp, locale, fmt0, ap); else - ret = __vfprintf(fp, fmt0, ap); + ret = __vfprintf(fp, locale, fmt0, ap); FUNLOCKFILE(fp); return (ret); } +int +vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap) +{ + return vfprintf_l(fp, __get_locale(), fmt0, ap); +} /* * The size of the buffer we use as scratch space for integer @@ -292,7 +304,7 @@ * Non-MT-safe version */ int -__vfprintf(FILE *fp, const char *fmt0, va_list ap) +__vfprintf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) { char *fmt; /* format string */ int ch; /* character from fmt */ @@ -357,19 +369,19 @@ /* BEWARE, these `goto error' on error. */ #define PRINT(ptr, len) { \ - if (io_print(&io, (ptr), (len))) \ + if (io_print(&io, (ptr), (len), locale)) \ goto error; \ } #define PAD(howmany, with) { \ - if (io_pad(&io, (howmany), (with))) \ + if (io_pad(&io, (howmany), (with), locale)) \ goto error; \ } #define PRINTANDPAD(p, ep, len, with) { \ - if (io_printandpad(&io, (p), (ep), (len), (with))) \ + if (io_printandpad(&io, (p), (ep), (len), (with), locale)) \ goto error; \ } #define FLUSH() { \ - if (io_flush(&io)) \ + if (io_flush(&io, locale)) \ goto error; \ } @@ -454,7 +466,7 @@ ret = 0; #ifndef NO_FLOATING_POINT dtoaresult = NULL; - decimal_point = localeconv()->decimal_point; + decimal_point = localeconv_l(locale)->decimal_point; /* The overwhelmingly common case is decpt_len == 1. */ decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point)); #endif @@ -750,7 +762,7 @@ if (prec || flags & ALT) size += prec + decpt_len; if ((flags & GROUPING) && expt > 0) - size += grouping_init(&gs, expt); + size += grouping_init(&gs, expt, locale); } break; #endif /* !NO_FLOATING_POINT */ @@ -887,7 +899,7 @@ if (size > BUF) /* should never happen */ abort(); if ((flags & GROUPING) && size != 0) - size += grouping_init(&gs, size); + size += grouping_init(&gs, size, locale); break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') @@ -950,7 +962,7 @@ /* leading zeroes from decimal precision */ PAD(dprec - size, zeroes); if (gs.grouping) { - if (grouping_print(&gs, &io, cp, buf+BUF) < 0) + if (grouping_print(&gs, &io, cp, buf+BUF, locale) < 0) goto error; } else { PRINT(cp, size); @@ -968,7 +980,7 @@ } else { if (gs.grouping) { n = grouping_print(&gs, &io, - cp, dtoaend); + cp, dtoaend, locale); if (n < 0) goto error; cp += n; Index: lib/libc/stdio/local.h =================================================================== --- lib/libc/stdio/local.h (revision 225653) +++ lib/libc/stdio/local.h (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * 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: @@ -30,13 +35,14 @@ * SUCH DAMAGE. * * @(#)local.h 8.3 (Berkeley) 7/3/94 - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/local.h 205021 2010-03-11 17:03:32Z jhb $ */ #include <sys/types.h> /* for off_t */ #include <pthread.h> #include <string.h> #include <wchar.h> +#include <locale.h> /* * Information local to this implementation of stdio, @@ -50,8 +56,8 @@ extern int _fseeko(FILE *, off_t, int, int); extern int __fflush(FILE *fp); extern void __fcloseall(void); -extern wint_t __fgetwc(FILE *); -extern wint_t __fputwc(wchar_t, FILE *); +extern wint_t __fgetwc(FILE *, locale_t); +extern wint_t __fputwc(wchar_t, FILE *, locale_t); extern int __sflush(FILE *); extern FILE *__sfp(void); extern int __slbexpand(FILE *, size_t); @@ -65,15 +71,15 @@ extern void __smakebuf(FILE *); extern int __swhatbuf(FILE *, size_t *, int *); extern int _fwalk(int (*)(FILE *)); -extern int __svfscanf(FILE *, const char *, __va_list); +extern int __svfscanf(FILE *, locale_t, const char *, __va_list); extern int __swsetup(FILE *); extern int __sflags(const char *, int *); extern int __ungetc(int, FILE *); -extern wint_t __ungetwc(wint_t, FILE *); -extern int __vfprintf(FILE *, const char *, __va_list); +extern wint_t __ungetwc(wint_t, FILE *, locale_t); +extern int __vfprintf(FILE *, locale_t, const char *, __va_list); extern int __vfscanf(FILE *, const char *, __va_list); -extern int __vfwprintf(FILE *, const wchar_t *, __va_list); -extern int __vfwscanf(FILE * __restrict, const wchar_t * __restrict, +extern int __vfwprintf(FILE *, locale_t, const wchar_t *, __va_list); +extern int __vfwscanf(FILE * __restrict, locale_t, const wchar_t * __restrict, __va_list); extern size_t __fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp); Index: lib/libc/stdio/fwprintf.c =================================================================== --- lib/libc/stdio/fwprintf.c (revision 225653) +++ lib/libc/stdio/fwprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 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: @@ -25,11 +30,12 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fwprintf.c 103739 2002-09-21 13:00:30Z tjr $"); #include <stdarg.h> #include <stdio.h> #include <wchar.h> +#include <xlocale.h> int fwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ return (ret); } +int +fwprintf_l(FILE * __restrict fp, locale_t locale, const wchar_t * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfwprintf_l(fp, locale, fmt, ap); + va_end(ap); + + return (ret); +} Index: lib/libc/stdio/tmpfile.c =================================================================== --- lib/libc/stdio/tmpfile.c (revision 225653) +++ lib/libc/stdio/tmpfile.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)tmpfile.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/tmpfile.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <sys/types.h> Index: lib/libc/stdio/rget.c =================================================================== --- lib/libc/stdio/rget.c (revision 225653) +++ lib/libc/stdio/rget.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)rget.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/rget.c 165903 2007-01-09 00:28:16Z imp $"); #include <stdio.h> #include "local.h" Index: lib/libc/stdio/fopen.c =================================================================== --- lib/libc/stdio/fopen.c (revision 225653) +++ lib/libc/stdio/fopen.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fopen.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fopen.c 178427 2008-04-22 17:03:32Z jhb $"); #include "namespace.h" #include <sys/types.h> Index: lib/libc/stdio/fputwc.c =================================================================== --- lib/libc/stdio/fputwc.c (revision 225653) +++ lib/libc/stdio/fputwc.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fputwc.c 178287 2008-04-17 22:17:54Z jhb $"); #include "namespace.h" #include <errno.h> @@ -42,10 +47,11 @@ * Non-MT-safe version. */ wint_t -__fputwc(wchar_t wc, FILE *fp) +__fputwc(wchar_t wc, FILE *fp, locale_t locale) { char buf[MB_LEN_MAX]; size_t i, len; + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); if (MB_CUR_MAX == 1 && wc > 0 && wc <= UCHAR_MAX) { /* @@ -56,7 +62,7 @@ *buf = (unsigned char)wc; len = 1; } else { - if ((len = __wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { + if ((len = l->__wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { fp->_flags |= __SERR; return (WEOF); } @@ -73,14 +79,20 @@ * MT-safe version. */ wint_t -fputwc(wchar_t wc, FILE *fp) +fputwc_l(wchar_t wc, FILE *fp, locale_t locale) { wint_t r; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - r = __fputwc(wc, fp); + r = __fputwc(wc, fp, locale); FUNLOCKFILE(fp); return (r); } +wint_t +fputwc(wchar_t wc, FILE *fp) +{ + return fputwc_l(wc, fp, __get_locale()); +} Index: lib/libc/stdio/vsprintf.c =================================================================== --- lib/libc/stdio/vsprintf.c (revision 225653) +++ lib/libc/stdio/vsprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * 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: @@ -34,22 +39,30 @@ static char sccsid[] = "@(#)vsprintf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vsprintf.c 205021 2010-03-11 17:03:32Z jhb $"); #include <stdio.h> #include <limits.h> #include "local.h" +#include "xlocale_private.h" int -vsprintf(char * __restrict str, const char * __restrict fmt, __va_list ap) +vsprintf_l(char * __restrict str, locale_t locale, + const char * __restrict fmt, __va_list ap) { int ret; FILE f = FAKE_FILE; + FIX_LOCALE(locale); f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = INT_MAX; - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, locale, fmt, ap); *f._p = 0; return (ret); } +int +vsprintf(char * __restrict str, const char * __restrict fmt, __va_list ap) +{ + return vsprintf_l(str, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/fclose.c =================================================================== --- lib/libc/stdio/fclose.c (revision 225653) +++ lib/libc/stdio/fclose.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fclose.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fclose.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <errno.h> Index: lib/libc/stdio/vwprintf.c =================================================================== --- lib/libc/stdio/vwprintf.c (revision 225653) +++ lib/libc/stdio/vwprintf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 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: @@ -25,15 +30,20 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vwprintf.c 103739 2002-09-21 13:00:30Z tjr $"); #include <stdarg.h> #include <stdio.h> #include <wchar.h> +#include <xlocale.h> int vwprintf(const wchar_t * __restrict fmt, va_list ap) { - return (vfwprintf(stdout, fmt, ap)); } +int +vwprintf_l(locale_t locale, const wchar_t * __restrict fmt, va_list ap) +{ + return (vfwprintf_l(stdout, locale, fmt, ap)); +} Index: lib/libc/stdio/fputc.c =================================================================== --- lib/libc/stdio/fputc.c (revision 225653) +++ lib/libc/stdio/fputc.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fputc.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fputc.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <stdio.h> Index: lib/libc/stdio/fflush.c =================================================================== --- lib/libc/stdio/fflush.c (revision 225653) +++ lib/libc/stdio/fflush.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fflush.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fflush.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <errno.h> Index: lib/libc/stdio/fwscanf.c =================================================================== --- lib/libc/stdio/fwscanf.c (revision 225653) +++ lib/libc/stdio/fwscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 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: @@ -25,11 +30,12 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fwscanf.c 103856 2002-09-23 12:40:06Z tjr $"); #include <stdarg.h> #include <stdio.h> #include <wchar.h> +#include <xlocale.h> int fwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ return (r); } +int +fwscanf_l(FILE * __restrict fp, locale_t locale, const wchar_t * __restrict fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = vfwscanf_l(fp, locale, fmt, ap); + va_end(ap); + + return (r); +} Index: lib/libc/stdio/fputws.c =================================================================== --- lib/libc/stdio/fputws.c (revision 225653) +++ lib/libc/stdio/fputws.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fputws.c 187302 2009-01-15 18:53:52Z rdivacky $"); #include "namespace.h" #include <errno.h> @@ -39,13 +44,15 @@ #include "mblocal.h" int -fputws(const wchar_t * __restrict ws, FILE * __restrict fp) +fputws_l(const wchar_t * __restrict ws, FILE * __restrict fp, locale_t locale) { size_t nbytes; char buf[BUFSIZ]; struct __suio uio; struct __siov iov; const wchar_t *wsp; + FIX_LOCALE(locale); + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); FLOCKFILE(fp); ORIENT(fp, 1); @@ -56,7 +63,7 @@ iov.iov_base = buf; do { wsp = ws; - nbytes = __wcsnrtombs(buf, &wsp, SIZE_T_MAX, sizeof(buf), + nbytes = l->__wcsnrtombs(buf, &wsp, SIZE_T_MAX, sizeof(buf), &fp->_mbstate); if (nbytes == (size_t)-1) goto error; @@ -71,3 +78,9 @@ FUNLOCKFILE(fp); return (-1); } + +int +fputws(const wchar_t * __restrict ws, FILE * __restrict fp) +{ + return fputws_l(ws, fp, __get_locale()); +} Index: lib/libc/stdio/scanf.c =================================================================== --- lib/libc/stdio/scanf.c (revision 225653) +++ lib/libc/stdio/scanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * 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: @@ -34,7 +39,7 @@ static char sccsid[] = "@(#)scanf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/scanf.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <stdio.h> @@ -42,6 +47,7 @@ #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" int scanf(char const * __restrict fmt, ...) @@ -51,8 +57,22 @@ va_start(ap, fmt); FLOCKFILE(stdin); - ret = __svfscanf(stdin, fmt, ap); + ret = __svfscanf(stdin, __get_locale(), fmt, ap); FUNLOCKFILE(stdin); va_end(ap); return (ret); } +int +scanf_l(locale_t locale, char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + FLOCKFILE(stdin); + ret = __svfscanf(stdin, locale, fmt, ap); + FUNLOCKFILE(stdin); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/getdelim.c =================================================================== --- lib/libc/stdio/getdelim.c (revision 225653) +++ lib/libc/stdio/getdelim.c (working copy) @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/getdelim.c 197752 2009-10-04 19:43:36Z das $"); #include "namespace.h" #include <sys/param.h> Index: lib/libc/stdio/tmpnam.c =================================================================== --- lib/libc/stdio/tmpnam.c (revision 225653) +++ lib/libc/stdio/tmpnam.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)tmpnam.c 8.3 (Berkeley) 3/28/94"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/tmpnam.c 165903 2007-01-09 00:28:16Z imp $"); #include <sys/types.h> Index: lib/libc/stdio/fputs.c =================================================================== --- lib/libc/stdio/fputs.c (revision 225653) +++ lib/libc/stdio/fputs.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fputs.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fputs.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <stdio.h> Index: lib/libc/stdio/wbuf.c =================================================================== --- lib/libc/stdio/wbuf.c (revision 225653) +++ lib/libc/stdio/wbuf.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)wbuf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/wbuf.c 165903 2007-01-09 00:28:16Z imp $"); #include <stdio.h> #include "local.h" Index: lib/libc/stdio/swscanf.c =================================================================== --- lib/libc/stdio/swscanf.c (revision 225653) +++ lib/libc/stdio/swscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 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: @@ -25,11 +30,12 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/swscanf.c 103856 2002-09-23 12:40:06Z tjr $"); #include <stdarg.h> #include <stdio.h> #include <wchar.h> +#include <xlocale.h> int swscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,16 @@ return (r); } +int +swscanf_l(const wchar_t * __restrict str, locale_t locale, + const wchar_t * __restrict fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = vswscanf_l(str, locale, fmt, ap); + va_end(ap); + + return (r); +} Index: lib/libc/stdio/xprintf_int.c =================================================================== --- lib/libc/stdio/xprintf_int.c (revision 225653) +++ lib/libc/stdio/xprintf_int.c (working copy) @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/xprintf_int.c 153641 2005-12-22 14:23:54Z cognet $ */ #include <namespace.h> Index: lib/libc/stdio/findfp.c =================================================================== --- lib/libc/stdio/findfp.c (revision 225653) +++ lib/libc/stdio/findfp.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)findfp.c 8.2 (Berkeley) 1/4/94"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/findfp.c 205021 2010-03-11 17:03:32Z jhb $"); #include <sys/param.h> #include <machine/atomic.h> Index: lib/libc/stdio/vwscanf.c =================================================================== --- lib/libc/stdio/vwscanf.c (revision 225653) +++ lib/libc/stdio/vwscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 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: @@ -25,15 +30,20 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vwscanf.c 103856 2002-09-23 12:40:06Z tjr $"); #include <stdarg.h> #include <stdio.h> #include <wchar.h> +#include <xlocale.h> int vwscanf(const wchar_t * __restrict fmt, va_list ap) { - return (vfwscanf(stdin, fmt, ap)); } +int +vwscanf_l(locale_t locale, const wchar_t * __restrict fmt, va_list ap) +{ + return (vfwscanf_l(stdin, locale, fmt, ap)); +} Index: lib/libc/stdio/xprintf_time.c =================================================================== --- lib/libc/stdio/xprintf_time.c (revision 225653) +++ lib/libc/stdio/xprintf_time.c (working copy) @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/xprintf_time.c 219346 2011-03-06 19:47:46Z pjd $ */ #include <namespace.h> #include <stdio.h> Index: lib/libc/stdio/makebuf.c =================================================================== --- lib/libc/stdio/makebuf.c (revision 225653) +++ lib/libc/stdio/makebuf.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)makebuf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/makebuf.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <sys/types.h> Index: lib/libc/stdio/putc.c =================================================================== --- lib/libc/stdio/putc.c (revision 225653) +++ lib/libc/stdio/putc.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)putc.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/putc.c 178778 2008-05-05 16:03:52Z jhb $"); #include "namespace.h" #include <stdio.h> Index: lib/libc/stdio/fdopen.c =================================================================== --- lib/libc/stdio/fdopen.c (revision 225653) +++ lib/libc/stdio/fdopen.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fdopen.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fdopen.c 178921 2008-05-10 18:39:20Z antoine $"); #include "namespace.h" #include <sys/types.h> Index: lib/libc/stdio/fileno.c =================================================================== --- lib/libc/stdio/fileno.c (revision 225653) +++ lib/libc/stdio/fileno.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fileno.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fileno.c 178778 2008-05-05 16:03:52Z jhb $"); #include "namespace.h" #include <stdio.h> Index: lib/libc/stdio/sscanf.c =================================================================== --- lib/libc/stdio/sscanf.c (revision 225653) +++ lib/libc/stdio/sscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * 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: @@ -34,11 +39,12 @@ static char sccsid[] = "@(#)sscanf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/sscanf.c 200800 2009-12-21 19:56:03Z delphij $"); #include <stdio.h> #include <string.h> #include <stdarg.h> +#include <xlocale.h> #include "local.h" int @@ -52,3 +58,15 @@ va_end(ap); return (ret); } +int +sscanf_l(const char * __restrict str, locale_t locale, + char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vsscanf_l(str, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/setvbuf.c =================================================================== --- lib/libc/stdio/setvbuf.c (revision 225653) +++ lib/libc/stdio/setvbuf.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)setvbuf.c 8.2 (Berkeley) 11/16/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/setvbuf.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <stdio.h> Index: lib/libc/stdio/fgetwc.c =================================================================== --- lib/libc/stdio/fgetwc.c (revision 225653) +++ lib/libc/stdio/fgetwc.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fgetwc.c 178287 2008-04-17 22:17:54Z jhb $"); #include "namespace.h" #include <errno.h> @@ -36,31 +41,39 @@ #include "libc_private.h" #include "local.h" #include "mblocal.h" +#include "xlocale_private.h" /* * MT-safe version. */ wint_t -fgetwc(FILE *fp) +fgetwc_l(FILE *fp, locale_t locale) { wint_t r; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - r = __fgetwc(fp); + r = __fgetwc(fp, locale); FUNLOCKFILE(fp); return (r); } +wint_t +fgetwc(FILE *fp) +{ + return fgetwc_l(fp, __get_locale()); +} /* * Non-MT-safe version. */ wint_t -__fgetwc(FILE *fp) +__fgetwc(FILE *fp, locale_t locale) { wchar_t wc; size_t nconv; + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); if (fp->_r <= 0 && __srefill(fp)) return (WEOF); @@ -71,7 +84,7 @@ return (wc); } do { - nconv = __mbrtowc(&wc, fp->_p, fp->_r, &fp->_mbstate); + nconv = l->__mbrtowc(&wc, fp->_p, fp->_r, &fp->_mbstate); if (nconv == (size_t)-1) break; else if (nconv == (size_t)-2) Index: lib/libc/stdio/ungetc.c =================================================================== --- lib/libc/stdio/ungetc.c (revision 225653) +++ lib/libc/stdio/ungetc.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)ungetc.c 8.2 (Berkeley) 11/3/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/ungetc.c 178287 2008-04-17 22:17:54Z jhb $"); #include "namespace.h" #include <stdio.h> Index: lib/libc/stdio/vfscanf.c =================================================================== --- lib/libc/stdio/vfscanf.c (revision 225653) +++ lib/libc/stdio/vfscanf.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. 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. + * * This code is derived from software contributed to Berkeley by * Chris Torek. * @@ -34,7 +39,7 @@ static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vfscanf.c 187422 2009-01-19 06:19:51Z das $"); #include "namespace.h" #include <ctype.h> @@ -51,6 +56,7 @@ #include "collate.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" #ifndef NO_FLOATING_POINT #include <locale.h> @@ -95,11 +101,12 @@ static const u_char *__sccl(char *, const u_char *); #ifndef NO_FLOATING_POINT -static int parsefloat(FILE *, char *, char *); +static int parsefloat(FILE *, char *, char *, locale_t); #endif __weak_reference(__vfscanf, vfscanf); + /* * __vfscanf - MT-safe version */ @@ -109,16 +116,27 @@ int ret; FLOCKFILE(fp); - ret = __svfscanf(fp, fmt0, ap); + ret = __svfscanf(fp, __get_locale(), fmt0, ap); FUNLOCKFILE(fp); return (ret); } +int +vfscanf_l(FILE *fp, locale_t locale, char const *fmt0, va_list ap) +{ + int ret; + FIX_LOCALE(locale); + FLOCKFILE(fp); + ret = __svfscanf(fp, locale, fmt0, ap); + FUNLOCKFILE(fp); + return (ret); +} + /* * __svfscanf - non-MT-safe version of __vfscanf */ int -__svfscanf(FILE *fp, const char *fmt0, va_list ap) +__svfscanf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) { const u_char *fmt = (const u_char *)fmt0; int c; /* character from format, or conversion */ @@ -455,8 +473,7 @@ !ccltab[wctob(*wcp)]) { while (n != 0) { n--; - __ungetc(buf[n], - fp); + __ungetc(buf[n], fp); } break; } @@ -555,8 +572,7 @@ if (iswspace(*wcp)) { while (n != 0) { n--; - __ungetc(buf[n], - fp); + __ungetc(buf[n], fp); } break; } @@ -733,9 +749,9 @@ *p = 0; if ((flags & UNSIGNED) == 0) - res = strtoimax(buf, (char **)NULL, base); + res = strtoimax_l(buf, (char **)NULL, base, locale); else - res = strtoumax(buf, (char **)NULL, base); + res = strtoumax_l(buf, (char **)NULL, base, locale); if (flags & POINTER) *va_arg(ap, void **) = (void *)(uintptr_t)res; @@ -766,17 +782,17 @@ /* scan a floating point number as if by strtod */ if (width == 0 || width > sizeof(buf) - 1) width = sizeof(buf) - 1; - if ((width = parsefloat(fp, buf, buf + width)) == 0) + if ((width = parsefloat(fp, buf, buf + width, locale)) == 0) goto match_failure; if ((flags & SUPPRESS) == 0) { if (flags & LONGDBL) { - long double res = strtold(buf, &p); + long double res = strtold_l(buf, &p, locale); *va_arg(ap, long double *) = res; } else if (flags & LONG) { - double res = strtod(buf, &p); + double res = strtod_l(buf, &p, locale); *va_arg(ap, double *) = res; } else { - float res = strtof(buf, &p); + float res = strtof_l(buf, &p, locale); *va_arg(ap, float *) = res; } nassigned++; @@ -805,6 +821,8 @@ const u_char *fmt; { int c, n, v, i; + struct xlocale_collate *table = + (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; /* first `clear' the whole table */ c = *fmt++; /* first char hat => negated scanset */ @@ -858,8 +876,8 @@ */ n = *fmt; if (n == ']' - || (__collate_load_error ? n < c : - __collate_range_cmp (n, c) < 0 + || (table->__collate_load_error ? n < c : + __collate_range_cmp (table, n, c) < 0 ) ) { c = '-'; @@ -867,14 +885,14 @@ } fmt++; /* fill in the range */ - if (__collate_load_error) { + if (table->__collate_load_error) { do { tab[++c] = v; } while (c < n); } else { for (i = 0; i < 256; i ++) - if ( __collate_range_cmp (c, i) < 0 - && __collate_range_cmp (i, n) <= 0 + if ( __collate_range_cmp (table, c, i) < 0 + && __collate_range_cmp (table, i, n) <= 0 ) tab[i] = v; } @@ -908,7 +926,7 @@ #ifndef NO_FLOATING_POINT static int -parsefloat(FILE *fp, char *buf, char *end) +parsefloat(FILE *fp, char *buf, char *end, locale_t locale) { char *commit, *p; int infnanpos = 0, decptpos = 0; @@ -917,7 +935,7 @@ S_DIGITS, S_DECPT, S_FRAC, S_EXP, S_EXPDIGITS } state = S_START; unsigned char c; - const char *decpt = localeconv()->decimal_point; + const char *decpt = localeconv_l(locale)->decimal_point; _Bool gotmantdig = 0, ishex = 0; /* Index: lib/libc/stdio/puts.c =================================================================== --- lib/libc/stdio/puts.c (revision 225653) +++ lib/libc/stdio/puts.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)puts.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/puts.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <stdio.h> Index: lib/libc/stdio/fseek.c =================================================================== --- lib/libc/stdio/fseek.c (revision 225653) +++ lib/libc/stdio/fseek.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fseek.c 8.3 (Berkeley) 1/2/94"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fseek.c 178287 2008-04-17 22:17:54Z jhb $"); #include "namespace.h" #include <sys/types.h> Index: lib/libc/stdio/putw.c =================================================================== --- lib/libc/stdio/putw.c (revision 225653) +++ lib/libc/stdio/putw.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)putw.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/putw.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <stdio.h> Index: lib/libc/stdio/fgetws.c =================================================================== --- lib/libc/stdio/fgetws.c (revision 225653) +++ lib/libc/stdio/fgetws.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fgetws.c 199784 2009-11-25 04:45:45Z wollman $"); #include "namespace.h" #include <errno.h> @@ -38,12 +43,14 @@ #include "mblocal.h" wchar_t * -fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp) +fgetws_l(wchar_t * __restrict ws, int n, FILE * __restrict fp, locale_t locale) { wchar_t *wsp; size_t nconv; const char *src; unsigned char *nl; + FIX_LOCALE(locale); + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); FLOCKFILE(fp); ORIENT(fp, 1); @@ -60,7 +67,7 @@ do { src = fp->_p; nl = memchr(fp->_p, '\n', fp->_r); - nconv = __mbsnrtowcs(wsp, &src, + nconv = l->__mbsnrtowcs(wsp, &src, nl != NULL ? (nl - fp->_p + 1) : fp->_r, n - 1, &fp->_mbstate); if (nconv == (size_t)-1) @@ -86,7 +93,7 @@ if (wsp == ws) /* EOF */ goto error; - if (!__mbsinit(&fp->_mbstate)) + if (!l->__mbsinit(&fp->_mbstate)) /* Incomplete character */ goto error; *wsp = L'\0'; @@ -98,3 +105,8 @@ FUNLOCKFILE(fp); return (NULL); } +wchar_t * +fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp) +{ + return fgetws_l(ws, n, fp, __get_locale()); +} Index: lib/libc/stdio/fwrite.c =================================================================== --- lib/libc/stdio/fwrite.c (revision 225653) +++ lib/libc/stdio/fwrite.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fwrite.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fwrite.c 201999 2010-01-10 14:30:30Z cperciva $"); #include "namespace.h" #include <errno.h> Index: lib/libc/stdio/funopen.c =================================================================== --- lib/libc/stdio/funopen.c (revision 225653) +++ lib/libc/stdio/funopen.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)funopen.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/funopen.c 200150 2009-12-05 19:31:38Z ed $"); #include <stdio.h> #include <errno.h> Index: lib/libc/stdio/vasprintf.c =================================================================== --- lib/libc/stdio/vasprintf.c (revision 225653) +++ lib/libc/stdio/vasprintf.c (working copy) @@ -4,6 +4,11 @@ * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> * 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: @@ -28,18 +33,20 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vasprintf.c 206217 2010-04-05 22:09:29Z obrien $"); #include <stdio.h> #include <stdlib.h> #include <errno.h> +#include "xlocale_private.h" #include "local.h" int -vasprintf(char **str, const char *fmt, __va_list ap) +vasprintf_l(char **str, locale_t locale, const char *fmt, __va_list ap) { FILE f = FAKE_FILE; int ret; + FIX_LOCALE(locale); f._flags = __SWR | __SSTR | __SALC; f._bf._base = f._p = malloc(128); @@ -49,7 +56,7 @@ return (-1); } f._bf._size = f._w = 127; /* Leave room for the NUL */ - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, locale, fmt, ap); if (ret < 0) { free(f._bf._base); *str = NULL; @@ -60,3 +67,8 @@ *str = (char *)f._bf._base; return (ret); } +int +vasprintf(char **str, const char *fmt, __va_list ap) +{ + return vasprintf_l(str, __get_locale(), fmt, ap); +} Index: lib/libc/stdio/vfwscanf.c =================================================================== --- lib/libc/stdio/vfwscanf.c (revision 225653) +++ lib/libc/stdio/vfwscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * 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: @@ -36,7 +41,7 @@ #endif /* LIBC_SCCS and not lint */ #endif #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vfwscanf.c 187422 2009-01-19 06:19:51Z das $"); #include "namespace.h" #include <ctype.h> @@ -53,11 +58,8 @@ #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" -#ifndef NO_FLOATING_POINT -#include <locale.h> -#endif - #define BUF 513 /* Maximum length of numeric string. */ /* @@ -96,7 +98,7 @@ #define CT_FLOAT 4 /* %[efgEFG] conversion */ #ifndef NO_FLOATING_POINT -static int parsefloat(FILE *, wchar_t *, wchar_t *); +static int parsefloat(FILE *, wchar_t *, wchar_t *, locale_t); #endif #define INCCL(_c) \ @@ -109,22 +111,30 @@ * MT-safe version. */ int -vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap) +vfwscanf_l(FILE * __restrict fp, locale_t locale, + const wchar_t * __restrict fmt, va_list ap) { int ret; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - ret = __vfwscanf(fp, fmt, ap); + ret = __vfwscanf(fp, locale, fmt, ap); FUNLOCKFILE(fp); return (ret); } +int +vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap) +{ + return vfwscanf_l(fp, __get_locale(), fmt, ap); +} /* * Non-MT-safe version. */ int -__vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap) +__vfwscanf(FILE * __restrict fp, locale_t locale, + const wchar_t * __restrict fmt, va_list ap) { wint_t c; /* character from format, or conversion */ size_t width; /* field width, or 0 */ @@ -159,11 +169,11 @@ if (c == 0) return (nassigned); if (iswspace(c)) { - while ((c = __fgetwc(fp)) != WEOF && - iswspace(c)) + while ((c = __fgetwc(fp, locale)) != WEOF && + iswspace_l(c, locale)) ; if (c != WEOF) - __ungetwc(c, fp); + __ungetwc(c, fp, locale); continue; } if (c != '%') @@ -178,10 +188,10 @@ switch (c) { case '%': literal: - if ((wi = __fgetwc(fp)) == WEOF) + if ((wi = __fgetwc(fp, locale)) == WEOF) goto input_failure; if (wi != c) { - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); goto input_failure; } nread++; @@ -341,11 +351,11 @@ * that suppress this. */ if ((flags & NOSKIP) == 0) { - while ((wi = __fgetwc(fp)) != WEOF && iswspace(wi)) + while ((wi = __fgetwc(fp, locale)) != WEOF && iswspace(wi)) nread++; if (wi == WEOF) goto input_failure; - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); } /* @@ -362,7 +372,7 @@ p = va_arg(ap, wchar_t *); n = 0; while (width-- != 0 && - (wi = __fgetwc(fp)) != WEOF) { + (wi = __fgetwc(fp, locale)) != WEOF) { if (!(flags & SUPPRESS)) *p++ = (wchar_t)wi; n++; @@ -378,7 +388,7 @@ n = 0; mbs = initial_mbs; while (width != 0 && - (wi = __fgetwc(fp)) != WEOF) { + (wi = __fgetwc(fp, locale)) != WEOF) { if (width >= MB_CUR_MAX && !(flags & SUPPRESS)) { nconv = wcrtomb(mbp, wi, &mbs); @@ -390,7 +400,7 @@ if (nconv == (size_t)-1) goto input_failure; if (nconv > width) { - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); break; } if (!(flags & SUPPRESS)) @@ -418,20 +428,20 @@ /* take only those things in the class */ if ((flags & SUPPRESS) && (flags & LONG)) { n = 0; - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && INCCL(wi)) n++; if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); if (n == 0) goto match_failure; } else if (flags & LONG) { p0 = p = va_arg(ap, wchar_t *); - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && INCCL(wi)) *p++ = (wchar_t)wi; if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); n = p - p0; if (n == 0) goto match_failure; @@ -442,7 +452,7 @@ mbp = va_arg(ap, char *); n = 0; mbs = initial_mbs; - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width != 0 && INCCL(wi)) { if (width >= MB_CUR_MAX && !(flags & SUPPRESS)) { @@ -466,7 +476,7 @@ n++; } if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); if (!(flags & SUPPRESS)) { *mbp = 0; nassigned++; @@ -481,29 +491,29 @@ if (width == 0) width = (size_t)~0; if ((flags & SUPPRESS) && (flags & LONG)) { - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && !iswspace(wi)) nread++; if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); } else if (flags & LONG) { p0 = p = va_arg(ap, wchar_t *); - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && !iswspace(wi)) { *p++ = (wchar_t)wi; nread++; } if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); *p = '\0'; nassigned++; } else { if (!(flags & SUPPRESS)) mbp = va_arg(ap, char *); mbs = initial_mbs; - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width != 0 && !iswspace(wi)) { if (width >= MB_CUR_MAX && @@ -528,7 +538,7 @@ nread++; } if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); if (!(flags & SUPPRESS)) { *mbp = 0; nassigned++; @@ -544,7 +554,7 @@ width = sizeof(buf) / sizeof(*buf) - 1; flags |= SIGNOK | NDIGITS | NZDIGITS; for (p = buf; width; width--) { - c = __fgetwc(fp); + c = __fgetwc(fp, locale); /* * Switch on the character; `goto ok' * if we accept it as a part of number. @@ -628,7 +638,7 @@ * for a number. Stop accumulating digits. */ if (c != WEOF) - __ungetwc(c, fp); + __ungetwc(c, fp, locale); break; ok: /* @@ -644,13 +654,13 @@ */ if (flags & NDIGITS) { if (p > buf) - __ungetwc(*--p, fp); + __ungetwc(*--p, fp, locale); goto match_failure; } c = p[-1]; if (c == 'x' || c == 'X') { --p; - __ungetwc(c, fp); + __ungetwc(c, fp, locale); } if ((flags & SUPPRESS) == 0) { uintmax_t res; @@ -691,7 +701,7 @@ if (width == 0 || width > sizeof(buf) / sizeof(*buf) - 1) width = sizeof(buf) / sizeof(*buf) - 1; - if ((width = parsefloat(fp, buf, buf + width)) == 0) + if ((width = parsefloat(fp, buf, buf + width, locale)) == 0) goto match_failure; if ((flags & SUPPRESS) == 0) { if (flags & LONGDBL) { @@ -720,7 +730,7 @@ #ifndef NO_FLOATING_POINT static int -parsefloat(FILE *fp, wchar_t *buf, wchar_t *end) +parsefloat(FILE *fp, wchar_t *buf, wchar_t *end, locale_t locale) { mbstate_t mbs; size_t nconv; @@ -751,7 +761,7 @@ commit = buf - 1; c = WEOF; for (p = buf; p < end; ) { - if ((c = __fgetwc(fp)) == WEOF) + if ((c = __fgetwc(fp, locale)) == WEOF) break; reswitch: switch (state) { @@ -871,9 +881,9 @@ parsedone: if (c != WEOF) - __ungetwc(c, fp); + __ungetwc(c, fp, locale); while (commit < --p) - __ungetwc(*p, fp); + __ungetwc(*p, fp, locale); *++commit = '\0'; return (commit - buf); } Index: lib/libc/stdio/fread.c =================================================================== --- lib/libc/stdio/fread.c (revision 225653) +++ lib/libc/stdio/fread.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fread.c 8.2 (Berkeley) 12/11/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fread.c 201999 2010-01-10 14:30:30Z cperciva $"); #include "namespace.h" #include <errno.h> Index: lib/libc/stdio/xprintf_hexdump.c =================================================================== --- lib/libc/stdio/xprintf_hexdump.c (revision 225653) +++ lib/libc/stdio/xprintf_hexdump.c (working copy) @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdio/xprintf_hexdump.c 153486 2005-12-16 18:56:39Z phk $ */ #include <namespace.h> Index: lib/libc/stdio/asprintf.c =================================================================== --- lib/libc/stdio/asprintf.c (revision 225653) +++ lib/libc/stdio/asprintf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * 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: @@ -31,10 +36,11 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/asprintf.c 199096 2009-11-09 18:50:34Z jhb $"); #include <stdio.h> #include <stdarg.h> +#include <xlocale.h> int asprintf(char ** __restrict s, char const * __restrict fmt, ...) @@ -47,3 +53,15 @@ va_end(ap); return (ret); } +int +asprintf_l(char ** __restrict s, locale_t locale, char const * __restrict fmt, + ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vasprintf_l(s, locale, fmt, ap); + va_end(ap); + return (ret); +} Index: lib/libc/stdio/fgetc.c =================================================================== --- lib/libc/stdio/fgetc.c (revision 225653) +++ lib/libc/stdio/fgetc.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)fgetc.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/fgetc.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <stdio.h> Index: lib/libc/stdio/vswscanf.c =================================================================== --- lib/libc/stdio/vswscanf.c (revision 225653) +++ lib/libc/stdio/vswscanf.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Donn Seeley at UUNET Technologies, Inc. * + * 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: @@ -37,7 +42,7 @@ #endif /* LIBC_SCCS and not lint */ __FBSDID("FreeBSD: src/lib/libc/stdio/vsscanf.c,v 1.11 2002/08/21 16:19:57 mike Exp "); #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdio/vswscanf.c 205021 2010-03-11 17:03:32Z jhb $"); #include <limits.h> #include <stdarg.h> @@ -46,6 +51,7 @@ #include <string.h> #include <wchar.h> #include "local.h" +#include "xlocale_private.h" static int eofread(void *, char *, int); @@ -57,8 +63,8 @@ } int -vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, - va_list ap) +vswscanf_l(const wchar_t * __restrict str, locale_t locale, + const wchar_t * __restrict fmt, va_list ap) { static const mbstate_t initial; mbstate_t mbs; @@ -67,6 +73,7 @@ size_t mlen; int r; const wchar_t *strp; + FIX_LOCALE(locale); /* * XXX Convert the wide character string to multibyte, which @@ -76,7 +83,7 @@ return (EOF); mbs = initial; strp = str; - if ((mlen = wcsrtombs(mbstr, &strp, SIZE_T_MAX, &mbs)) == (size_t)-1) { + if ((mlen = wcsrtombs_l(mbstr, &strp, SIZE_T_MAX, &mbs, locale)) == (size_t)-1) { free(mbstr); return (EOF); } @@ -84,8 +91,14 @@ f._bf._base = f._p = (unsigned char *)mbstr; f._bf._size = f._r = mlen; f._read = eofread; - r = __vfwscanf(&f, fmt, ap); + r = __vfwscanf(&f, locale, fmt, ap); free(mbstr); return (r); } +int +vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, + va_list ap) +{ + return vswscanf_l(str, __get_locale(), fmt, ap); +} Index: lib/libc/locale/collate.c =================================================================== --- lib/libc/locale/collate.c (revision 225653) +++ lib/libc/locale/collate.c (working copy) @@ -3,6 +3,16 @@ * at Electronni Visti IA, Kiev, Ukraine. * 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. + * + * 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: @@ -26,7 +36,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/collate.c 142686 2005-02-27 20:31:13Z ru $"); #include "namespace.h" #include <arpa/inet.h> @@ -44,24 +54,70 @@ #include "libc_private.h" -int __collate_load_error = 1; -int __collate_substitute_nontrivial; +/* + * To avoid modifying the original (single-threaded) code too much, we'll just + * define the old globals as fields inside the table. + * + * We also modify the collation table test functions to search the thread-local + * table first and the global table second. + */ +#define __collate_load_error (table->__collate_load_error) +#define __collate_substitute_nontrivial (table->__collate_substitute_nontrivial) +#define __collate_substitute_table_ptr (table->__collate_substitute_table_ptr) +#define __collate_char_pri_table_ptr (table->__collate_char_pri_table_ptr) +#define __collate_chain_pri_table (table->__collate_chain_pri_table) -u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; -struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; -struct __collate_st_chain_pri *__collate_chain_pri_table; +struct xlocale_collate __xlocale_global_collate = { + {{0}, "C"}, 1, 0 +}; + void __collate_err(int ex, const char *f) __dead2; int +__collate_load_tables_l(const char *encoding, struct xlocale_collate *table); + +static void +destruct_collate(void *t) +{ + struct xlocale_collate *table = t; + if (__collate_chain_pri_table) { + free(__collate_chain_pri_table); + } + free(t); +} + +void * +__collate_load(const char *encoding, locale_t unused) +{ + struct xlocale_collate *table = calloc(sizeof(struct xlocale_collate), 1); + table->header.header.destructor = destruct_collate; + // FIXME: Make sure that _LDP_CACHE is never returned. We should be doing + // the caching outside of this section + if (__collate_load_tables_l(encoding, table) != _LDP_LOADED) { + xlocale_release(table); + return NULL; + } + return table; +} + +/** + * Load the collation tables for the specified encoding into the global table. + */ +int __collate_load_tables(const char *encoding) { + return __collate_load_tables_l(encoding, &__xlocale_global_collate); +} + +int +__collate_load_tables_l(const char *encoding, struct xlocale_collate *table) +{ FILE *fp; int i, saverr, chains; uint32_t u32; char strbuf[STR_LEN], buf[PATH_MAX]; void *TMP_substitute_table, *TMP_char_pri_table, *TMP_chain_pri_table; - static char collate_encoding[ENCODING_LEN + 1]; /* 'encoding' must be already checked. */ if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) { @@ -69,18 +125,6 @@ return (_LDP_CACHE); } - /* - * If the locale name is the same as our cache, use the cache. - */ - if (strcmp(encoding, collate_encoding) == 0) { - __collate_load_error = 0; - return (_LDP_CACHE); - } - - /* - * Slurp the locale file into the cache. - */ - /* 'PathLocale' must be already set & checked. */ /* Range checking not needed, encoding has fixed size */ (void)strcpy(buf, _PathLocale); @@ -165,7 +209,6 @@ sizeof(*__collate_chain_pri_table), chains, fp); (void)fclose(fp); - (void)strcpy(collate_encoding, encoding); if (__collate_substitute_table_ptr != NULL) free(__collate_substitute_table_ptr); __collate_substitute_table_ptr = TMP_substitute_table; @@ -201,7 +244,7 @@ } u_char * -__collate_substitute(const u_char *s) +__collate_substitute(struct xlocale_collate *table, const u_char *s) { int dest_len, len, nlen; int delta = strlen(s); @@ -228,7 +271,7 @@ } void -__collate_lookup(const u_char *t, int *len, int *prim, int *sec) +__collate_lookup(struct xlocale_collate *table, const u_char *t, int *len, int *prim, int *sec) { struct __collate_st_chain_pri *p2; Index: lib/libc/locale/xlocale.c =================================================================== --- lib/libc/locale/xlocale.c (revision 0) +++ lib/libc/locale/xlocale.c (revision 0) @@ -0,0 +1,312 @@ +/*- + * 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. + */ + +#include <pthread.h> +#include <stdio.h> +#include <string.h> +#include "libc_private.h" +#include "xlocale_private.h" + +/** + * Each locale loader declares a global component. This is used by setlocale() + * and also by xlocale with LC_GLOBAL_LOCALE.. + */ +extern struct xlocale_component __xlocale_global_collate; +extern struct xlocale_component __xlocale_global_ctype; +extern struct xlocale_component __xlocale_global_monetary; +extern struct xlocale_component __xlocale_global_numeric; +extern struct xlocale_component __xlocale_global_time; +extern struct xlocale_component __xlocale_global_messages; +/* + * Private functions in setlocale.c. + */ +const char * +__get_locale_env(int category); +int +__detect_path_locale(void); + +struct _xlocale __xlocale_global_locale = { + {0}, + { + &__xlocale_global_collate, + &__xlocale_global_ctype, + &__xlocale_global_monetary, + &__xlocale_global_numeric, + &__xlocale_global_time, + &__xlocale_global_messages + }, + 1, + 0, + 1, + 0 +}; + +static void*(*constructors[])(const char*, locale_t) = +{ + __collate_load, + __ctype_load, + __monetary_load, + __numeric_load, + __time_load, + __messages_load +}; + +static pthread_key_t locale_info_key; +static int fake_tls; +static locale_t thread_local_locale; + +static void init_key(void) +{ + pthread_key_create(&locale_info_key, xlocale_release); + pthread_setspecific(locale_info_key, (void*)42); + if (pthread_getspecific(locale_info_key) == (void*)42) { + pthread_setspecific(locale_info_key, 0); + } else { + fake_tls = 1; + } + __detect_path_locale(); +} + +static pthread_once_t once_control = PTHREAD_ONCE_INIT; + +static locale_t +get_thread_locale(void) +{ + _once(&once_control, init_key); + + return fake_tls ? thread_local_locale : + pthread_getspecific(locale_info_key); +} + +locale_t +__get_locale(void) +{ + locale_t l = get_thread_locale(); + return l ? l : &__xlocale_global_locale; + +} + +static void +set_thread_locale(locale_t loc) +{ + pthread_once(&once_control, init_key); + + if (NULL != loc) { + xlocale_retain((struct xlocale_refcounted*)loc); + } + locale_t old = pthread_getspecific(locale_info_key); + if ((NULL != old) && (loc != old)) { + xlocale_release((struct xlocale_refcounted*)old); + } + if (fake_tls) { + thread_local_locale = loc; + } else { + pthread_setspecific(locale_info_key, loc); + } +} + +/** + * Clean up a locale, once its reference count reaches zero. This function is + * called by xlocale_release(), it should not be called directly. + */ +static void +destruct_locale(void *l) +{ + locale_t loc = l; + for (int type=0 ; type<XLC_LAST ; type++) { + if (loc->components[type]) { + xlocale_release(loc->components[type]); + } + } + if (loc->csym) { + free(loc->csym); + } + free(l); +} + +/** + * Allocates a new, uninitialised, locale. + */ +static locale_t +alloc_locale(void) +{ + locale_t new = calloc(sizeof(struct _xlocale), 1); + new->header.destructor = destruct_locale; + new->monetary_locale_changed = 1; + new->numeric_locale_changed = 1; + return new; +} +static void +copyflags(locale_t new, locale_t old) +{ + new->using_monetary_locale = old->using_monetary_locale; + new->using_numeric_locale = old->using_numeric_locale; + new->using_time_locale = old->using_time_locale; + new->using_messages_locale = old->using_messages_locale; +} + +static int dupcomponent(int type, locale_t base, locale_t new) +{ + /* Always copy from the global locale, since it has mutable components. */ + struct xlocale_component *src = base->components[type]; + if (&__xlocale_global_locale == base) { + new->components[type] = constructors[type](src->locale, new); + if (new->components[type]) { + strncpy(new->components[type]->locale, src->locale, ENCODING_LEN); + } + } else { + new->components[type] = xlocale_retain(base->components[type]); + } + return 0 != new->components[type]; +} + +/* + * Public interfaces. These are the five public functions described by the + * xlocale interface. + */ + +locale_t newlocale(int mask, const char *locale, locale_t base) +{ + int type; + const char *realLocale = locale; + int useenv = 0; + int success = 1; + + _once(&once_control, init_key); + + locale_t new = alloc_locale(); + if (NULL == new) { + return NULL; + } + + FIX_LOCALE(base); + copyflags(new, base); + + if (NULL == locale) { + realLocale = "C"; + } else if ('\0' == locale[0]) { + useenv = 1; + } + + for (type=0 ; type<XLC_LAST ; type++) { + if (mask & 1) { + if (useenv) { + realLocale = __get_locale_env(type); + } + new->components[type] = constructors[type](realLocale, new); + if (new->components[type]) { + strncpy(new->components[type]->locale, realLocale, ENCODING_LEN); + } else { + success = 0; + } + } else { + if (!dupcomponent(type, base, new)) { + success = 0; + } + } + mask >>= 1; + } + if (0 == success) { + xlocale_release(new); + new = NULL; + } + + return new; +} + +locale_t duplocale(locale_t base) +{ + locale_t new = alloc_locale(); + int type; + + _once(&once_control, init_key); + + if (NULL == new) { + return NULL; + } + + FIX_LOCALE(base); + copyflags(new, base); + + for (type=0 ; type<XLC_LAST ; type++) { + dupcomponent(type, base, new); + } + + return new; +} + +/* + * Free a locale_t. This is quite a poorly named function. It actually + * disclaims a reference to a locale_t, rather than freeing it. + */ +int +freelocale(locale_t loc) +{ + /* Fail if we're passed something that isn't a locale. */ + if ((NULL == loc) || (LC_GLOBAL_LOCALE == loc)) { + return -1; + } + /* If we're passed the global locale, pretend that we freed it but don't + * actually do anything. */ + if (&__xlocale_global_locale == loc) { + return 0; + } + xlocale_release(loc); + return 0; +} + +/* + * Returns the name of the locale for a particular component of a locale_t. + */ +const char *querylocale(int mask, locale_t loc) +{ + FIX_LOCALE(loc); + for (int type=0 ; type<XLC_LAST ; type++) { + if (mask & 1) { + return loc->components[type]->locale; + } + mask >>= 1; + } + return NULL; +} + +/* + * Installs the specified locale_t as this thread's locale. + */ +locale_t uselocale(locale_t loc) +{ + locale_t old = get_thread_locale(); + if (NULL != loc) { + if (LC_GLOBAL_LOCALE == loc) { + loc = NULL; + } + set_thread_locale(loc); + } + return old ? old : LC_GLOBAL_LOCALE; +} + Index: lib/libc/locale/ascii.c =================================================================== --- lib/libc/locale/ascii.c (revision 225653) +++ lib/libc/locale/ascii.c (working copy) @@ -6,6 +6,11 @@ * 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: @@ -32,7 +37,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/ascii.c 175553 2008-01-21 23:48:12Z ache $"); #include <errno.h> #include <limits.h> @@ -56,17 +61,17 @@ size_t, size_t, mbstate_t * __restrict); int -_ascii_init(_RuneLocale *rl) +_ascii_init(struct xlocale_ctype *l,_RuneLocale *rl) { - __mbrtowc = _ascii_mbrtowc; - __mbsinit = _ascii_mbsinit; - __mbsnrtowcs = _ascii_mbsnrtowcs; - __wcrtomb = _ascii_wcrtomb; - __wcsnrtombs = _ascii_wcsnrtombs; - _CurrentRuneLocale = rl; - __mb_cur_max = 1; - __mb_sb_limit = 128; + l->__mbrtowc = _ascii_mbrtowc; + l->__mbsinit = _ascii_mbsinit; + l->__mbsnrtowcs = _ascii_mbsnrtowcs; + l->__wcrtomb = _ascii_wcrtomb; + l->__wcsnrtombs = _ascii_wcsnrtombs; + l->runes = rl; + l->__mb_cur_max = 1; + l->__mb_sb_limit = 128; return(0); } Index: lib/libc/locale/collate.h =================================================================== --- lib/libc/locale/collate.h (revision 225653) +++ lib/libc/locale/collate.h (working copy) @@ -3,6 +3,11 @@ * at Electronni Visti IA, Kiev, Ukraine. * 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: @@ -24,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/locale/collate.h 142686 2005-02-27 20:31:13Z ru $ */ #ifndef _COLLATE_H_ @@ -33,6 +38,7 @@ #include <sys/cdefs.h> #include <sys/types.h> #include <limits.h> +#include "xlocale_private.h" #define STR_LEN 10 #define TABLE_SIZE 100 @@ -47,20 +53,26 @@ int prim, sec; }; -extern int __collate_load_error; -extern int __collate_substitute_nontrivial; #define __collate_substitute_table (*__collate_substitute_table_ptr) -extern u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; #define __collate_char_pri_table (*__collate_char_pri_table_ptr) -extern struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; -extern struct __collate_st_chain_pri *__collate_chain_pri_table; +struct xlocale_collate { + struct xlocale_component header; + int __collate_load_error; + int __collate_substitute_nontrivial; + + u_char (*__collate_substitute_table_ptr)[UCHAR_MAX + 1][STR_LEN]; + struct __collate_st_char_pri (*__collate_char_pri_table_ptr)[UCHAR_MAX + 1]; + struct __collate_st_chain_pri *__collate_chain_pri_table; +}; + + __BEGIN_DECLS u_char *__collate_strdup(u_char *); -u_char *__collate_substitute(const u_char *); +u_char *__collate_substitute(struct xlocale_collate *, const u_char *); int __collate_load_tables(const char *); -void __collate_lookup(const u_char *, int *, int *, int *); -int __collate_range_cmp(int, int); +void __collate_lookup(struct xlocale_collate *, const u_char *, int *, int *, int *); +int __collate_range_cmp(struct xlocale_collate *, int, int); #ifdef COLLATE_DEBUG void __collate_print_tables(void); #endif Index: lib/libc/locale/wcstoumax.c =================================================================== --- lib/libc/locale/wcstoumax.c (revision 225653) +++ lib/libc/locale/wcstoumax.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. 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: @@ -34,26 +39,28 @@ #endif /* LIBC_SCCS and not lint */ __FBSDID("FreeBSD: src/lib/libc/stdlib/strtoumax.c,v 1.8 2002/09/06 11:23:59 tjr Exp "); #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstoumax.c 165903 2007-01-09 00:28:16Z imp $"); #include <errno.h> #include <inttypes.h> #include <stdlib.h> #include <wchar.h> #include <wctype.h> +#include "xlocale_private.h" /* * Convert a wide character string to a uintmax_t integer. */ uintmax_t -wcstoumax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, - int base) +wcstoumax_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; uintmax_t acc; wchar_t c; uintmax_t cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoimax for comments as to the logic used. @@ -61,7 +68,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -86,8 +93,8 @@ cutlim = UINTMAX_MAX % base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -120,3 +127,9 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +uintmax_t +wcstoumax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base) +{ + return wcstoumax_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/mbtowc.c =================================================================== --- lib/libc/locale/mbtowc.c (revision 225653) +++ lib/libc/locale/mbtowc.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,26 +30,31 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/mbtowc.c 132821 2004-07-29 06:18:40Z tjr $"); #include <stdlib.h> #include <wchar.h> #include "mblocal.h" int -mbtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n) +mbtowc_l(wchar_t * __restrict pwc, const char * __restrict s, size_t n, locale_t locale) { static const mbstate_t initial; - static mbstate_t mbs; size_t rval; + FIX_LOCALE(locale); if (s == NULL) { /* No support for state dependent encodings. */ - mbs = initial; + locale->mbtowc = initial; return (0); } - rval = __mbrtowc(pwc, s, n, &mbs); + rval = XLOCALE_CTYPE(locale)->__mbrtowc(pwc, s, n, &locale->mbtowc); if (rval == (size_t)-1 || rval == (size_t)-2) return (-1); 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: lib/libc/locale/wcstoul.c =================================================================== --- lib/libc/locale/wcstoul.c (revision 225653) +++ lib/libc/locale/wcstoul.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. 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: @@ -28,25 +33,28 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstoul.c 165903 2007-01-09 00:28:16Z imp $"); #include <ctype.h> #include <errno.h> #include <limits.h> #include <wchar.h> #include <wctype.h> +#include "xlocale_private.h" /* * Convert a wide character string to an unsigned long integer. */ unsigned long -wcstoul(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +wcstoul_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; unsigned long acc; wchar_t c; unsigned long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtol for comments as to the logic used. @@ -54,7 +62,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -79,8 +87,8 @@ cutlim = ULONG_MAX % base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -113,3 +121,8 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +unsigned long +wcstoul(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +{ + return wcstoul_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/gb2312.c =================================================================== --- lib/libc/locale/gb2312.c (revision 225653) +++ lib/libc/locale/gb2312.c (working copy) @@ -3,6 +3,11 @@ * Copyright (c) 2003 David Xu <davidxu@freebsd.org> * 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: @@ -26,7 +31,7 @@ */ #include <sys/param.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/gb2312.c 172619 2007-10-13 16:28:22Z ache $"); #include <errno.h> #include <runetype.h> @@ -35,8 +40,6 @@ #include <wchar.h> #include "mblocal.h" -extern int __mb_sb_limit; - static size_t _GB2312_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t, mbstate_t * __restrict); static int _GB2312_mbsinit(const mbstate_t *); @@ -49,15 +52,15 @@ } _GB2312State; int -_GB2312_init(_RuneLocale *rl) +_GB2312_init(struct xlocale_ctype *l, _RuneLocale *rl) { - _CurrentRuneLocale = rl; - __mbrtowc = _GB2312_mbrtowc; - __wcrtomb = _GB2312_wcrtomb; - __mbsinit = _GB2312_mbsinit; - __mb_cur_max = 2; - __mb_sb_limit = 128; + l->runes = rl; + l->__mbrtowc = _GB2312_mbrtowc; + l->__wcrtomb = _GB2312_wcrtomb; + l->__mbsinit = _GB2312_mbsinit; + l->__mb_cur_max = 2; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/Symbol.map =================================================================== --- lib/libc/locale/Symbol.map (revision 225653) +++ lib/libc/locale/Symbol.map (working copy) @@ -1,5 +1,5 @@ /* - * $FreeBSD$ + * $FreeBSD: head/lib/libc/locale/Symbol.map 172619 2007-10-13 16:28:22Z ache $ */ FBSD_1.0 { @@ -99,6 +99,96 @@ iswctype; wctype; wcwidth; + newlocale; + duplocale; + freelocale; + querylocale; + uselocale; + __getCurrentRuneLocale; + btowc_l; + localeconv_l; + mblen_l; + mbrlen_l; + mbrtowc_l; + mbsinit_l; + mbsnrtowcs_l; + mbsrtowcs_l; + mbstowcs_l; + mbtowc_l; + nl_langinfo_l; + strcoll_l; + strfmon_l; + strftime_l; + strptime_l; + strxfrm_l; + wcrtomb_l; + wcscoll_l; + wcsnrtombs_l; + wcsrtombs_l; + wcstombs_l; + wcsxfrm_l; + wctob_l; + wctomb_l; + ___tolower_l; + ___toupper_l; + ___runetype_l; + digittoint_l; + isalnum_l; + isalpha_l; + isblank_l; + iscntrl_l; + isdigit_l; + isgraph_l; + ishexnumber_l; + isideogram_l; + islower_l; + isnumber_l; + isphonogram_l; + isprint_l; + ispunct_l; + isrune_l; + isspace_l; + isspecial_l; + isupper_l; + isxdigit_l; + tolower_l; + toupper_l; + iswalnum_l; + iswalpha_l; + iswblank_l; + iswcntrl_l; + iswdigit_l; + iswgraph_l; + iswhexnumber_l; + iswideogram_l; + iswlower_l; + iswnumber_l; + iswphonogram_l; + iswprint_l; + iswpunct_l; + iswrune_l; + iswspace_l; + iswspecial_l; + iswupper_l; + iswxdigit_l; + towlower_l; + towupper_l; + iswctype_l; + wctype_l; + nextwctype_l; + ___mb_cur_max; + towctrans_l; + wctrans_l; + wcsftime_l; + wcstod_l; + wcstof_l; + wcstoimax_l; + wcstol_l; + wcstold_l; + wcstoll_l; + wcstoul_l; + wcstoull_l; + wcstoumax_l; }; FBSDprivate_1.0 { Index: lib/libc/locale/mblocal.h =================================================================== --- lib/libc/locale/mblocal.h (revision 225653) +++ lib/libc/locale/mblocal.h (working copy) @@ -2,6 +2,11 @@ * 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: @@ -23,42 +28,52 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/locale/mblocal.h 175553 2008-01-21 23:48:12Z ache $ */ #ifndef _MBLOCAL_H_ #define _MBLOCAL_H_ #include <runetype.h> +#include "xlocale_private.h" + /* - * Rune initialization function prototypes. + * Conversion function pointers for current encoding. */ -int _none_init(_RuneLocale *); -int _ascii_init(_RuneLocale *); -int _UTF8_init(_RuneLocale *); -int _EUC_init(_RuneLocale *); -int _GB18030_init(_RuneLocale *); -int _GB2312_init(_RuneLocale *); -int _GBK_init(_RuneLocale *); -int _BIG5_init(_RuneLocale *); -int _MSKanji_init(_RuneLocale *); +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; +}; +#define XLOCALE_CTYPE(x) ((struct xlocale_ctype*)(x)->components[XLC_CTYPE]) +extern struct xlocale_ctype __xlocale_global_ctype; /* - * Conversion function pointers for current encoding. + * Rune initialization function prototypes. */ -extern size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, - size_t, mbstate_t * __restrict); -extern int (*__mbsinit)(const mbstate_t *); -extern size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict, - size_t, size_t, mbstate_t * __restrict); -extern size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict); -extern size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict, - size_t, size_t, mbstate_t * __restrict); +int _none_init(struct xlocale_ctype *, _RuneLocale *); +int _ascii_init(struct xlocale_ctype *, _RuneLocale *); +int _UTF8_init(struct xlocale_ctype *, _RuneLocale *); +int _EUC_init(struct xlocale_ctype *, _RuneLocale *); +int _GB18030_init(struct xlocale_ctype *, _RuneLocale *); +int _GB2312_init(struct xlocale_ctype *, _RuneLocale *); +int _GBK_init(struct xlocale_ctype *, _RuneLocale *); +int _BIG5_init(struct xlocale_ctype *, _RuneLocale *); +int _MSKanji_init(struct xlocale_ctype *, _RuneLocale *); extern size_t __mbsnrtowcs_std(wchar_t * __restrict, const char ** __restrict, - size_t, size_t, mbstate_t * __restrict); + size_t, size_t, mbstate_t * __restrict); extern size_t __wcsnrtombs_std(char * __restrict, const wchar_t ** __restrict, - size_t, size_t, mbstate_t * __restrict); + size_t, size_t, mbstate_t * __restrict); #endif /* _MBLOCAL_H_ */ Index: lib/libc/locale/DESIGN.xlocale =================================================================== --- lib/libc/locale/DESIGN.xlocale (revision 0) +++ lib/libc/locale/DESIGN.xlocale (revision 0) @@ -0,0 +1,157 @@ +Design of xlocale +================= + +The xlocale APIs come from Darwin, although a subset is now part of POSIX 2008. +They fall into two broad categories: + +- Manipulation of per-thread locales (POSIX) +- Locale-aware functions taking an explicit locale argument (Darwin) + +This document describes the implementation of these APIs for FreeBSD. + +Goals +----- + +The overall goal of this implementation is to be compatible with the Darwin +version. Additionally, it should include minimal changes to the existing +locale code. A lot of the existing locale code originates with 4BSD or earlier +and has had over a decade of testing. Replacing this code, unless absolutely +necessary, gives us the potential for more bugs without much benefit. + +With this in mind, various libc-private functions have been modified to take a +locale_t parameter. This causes a compiler error if they are accidentally +called without a locale. This approach was taken, rather than adding _l +variants of these functions, to make it harder for accidental uses of the +global-locale versions to slip in. + +Locale Objects +-------------- + +A locale is encapsulated in a `locale_t`, which is an opaque type: a pointer to +a `struct _xlocale`. The name `_xlocale` is unfortunate, as it does not fit +well with existing conventions, but is used because this is the name the Darwin +implementation gives to this structure and so may be used by existing (bad) code. + +This structure should include all of the information corresponding to a locale. +A locale_t is almost immutable after creation. There are no functions that modify it, +and it can therefore be used without locking. It is the responsibility of the +caller to ensure that a locale is not deallocated during a call that uses it. + +Each locale contains a number of components, one for each of the categories +supported by `setlocale()`. These are likewise immutable after creation. This +differs from the Darwin implementation, which includes a deprecated +`setinvalidrune()` function that can modify the rune locale. + +The exception to these mutability rules is a set of `mbstate_t` flags stored +with each locale. These are used by various functions that previously had a +static local `mbstate_t` variable. + +The components are reference counted, and so can be aliased between locale +objects. This makes copying locales very cheap. + +The Global Locale +----------------- + +All locales and locale components are reference counted. The global locale, +however, is special. It, and all of its components, are static and so no +malloc() memory is required when using a single locale. + +This means that threads using the global locale are subject to the same +constraints as with the pre-xlocale libc. Calls to any locale-aware functions +in threads using the global locale, while modifying the global locale, have +undefined behaviour. + +Because of this, we have to ensure that we always copy the components of the +global locale, rather than alias them. + +It would be cleaner to simply remove the special treatment of the global locale +and have a locale_t lazily allocated for the global context. This would cost a +little more `malloc()` memory, so is not done in the initial version. + +Caching +------- + +The existing locale implementation included several ad-hoc caching layers. +None of these were thread safe. Caching is only really of use for supporting +the pattern where the locale is briefly changed to something and then changed +back. + +The current xlocale implementation removes the caching entirely. This pattern +is not one that should be encouraged. If you need to make some calls with a +modified locale, then you should use the _l suffix versions of the calls, +rather than switch the global locale. If you do need to temporarily switch the +locale and then switch it back, `uselocale()` provides a way of doing this very +easily: It returns the old locale, which can then be passed to a subsequent +call to `uselocale()` to restore it, without the need to load any locale data +from the disk. + +If, in the future, it is determined that caching is beneficial, it can be added +quite easily in xlocale.c. Given, however, that any locale-aware call is going +to be a preparation for presenting data to the user, and so is invariably going +to be part of an I/O operation, this seems like a case of premature +optimisation. + +localeconv +---------- + +The `localeconv()` function is an exception to the immutable-after-creation +rule. In the classic implementation, this function returns a pointer to some +global storage, which is initialised with the data from the current locale. +This is not possible in a multithreaded environment, with multiple locales. + +Instead, each locale contains a `struct lconv` that is lazily initialised on +calls to `localeconv()`. This is not protected by any locking, however this is +still safe on any machine where word-sized stores are atomic: two concurrent +calls will write the same data into the structure. + +Explicit Locale Calls +--------------------- + +A large number of functions have been modified to take an explicit `locale_t` +parameter. The old APIs are then reimplemented with a call to `__get_locale()` +to supply the `locale_t` parameter. This is in line with the Darwin public +APIs, but also simplifies the modifications to these functions. The +`__get_locale()` function is now the only way to access the current locale +within libc. All of the old globals have gone, so there is now a linker error +if any functions attempt to use them. + +The ctype.h functions are a little different. These are not implemented in +terms of their locale-aware versions, for performance reasons. Each of these +is implemented as a short inline function. + +Differences to Darwin APIs +-------------------------- + +`strtoq_l()` and `strtouq_l() `are not provided. These are extensions to +deprecated functions - we should not be encouraging people to use deprecated +interfaces. + +Locale Placeholders +------------------- + +The pointer values 0 and -1 have special meanings as `locale_t` values. Any +public function that accepts a `locale_t` parameter must use the `FIX_LOCALE()` +macro on it before using it. For efficiency, this can be emitted in functions +which *only* use their locale parameter as an argument to another public +function, as the callee will do the `FIX_LOCALE()` itself. + +Potential Improvements +---------------------- + +Currently, the current rune set is accessed via a function call. This makes it +fairly expensive to use any of the ctype.h functions. We could improve this +quite a lot by storing the rune locale data in a __thread-qualified variable. + +Several of the existing FreeBSD locale-aware functions appear to be wrong. For +example, most of the `strto*()` family should probably use `digittoint_l()`, +but instead they assume ASCII. These will break if using a character encoding +that does not put numbers and the letters A-F in the same location as ASCII. +Some functions, like `strcoll()` only work on single-byte encodings. No +attempt has been made to fix existing limitations in the libc functions other +than to add support for xlocale. + +Intuitively, setting a thread-local locale should ensure that all locale-aware +functions can be used safely from that thread. In fact, this is not the case +in either this implementation or the Darwin one. You must call `duplocale()` +or `newlocale()` before calling `uselocale()`. This is a bit ugly, and it +would be better if libc ensure that every thread had its own locale object. Index: lib/libc/locale/mbsrtowcs.c =================================================================== --- lib/libc/locale/mbsrtowcs.c (revision 225653) +++ lib/libc/locale/mbsrtowcs.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/mbsrtowcs.c 132497 2004-07-21 10:54:57Z tjr $"); #include <errno.h> #include <limits.h> @@ -34,12 +39,17 @@ #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; + 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) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__mbsnrtowcs(dst, src, SIZE_T_MAX, len, ps)); + return mbsrtowcs_l(dst, src, len, ps, __get_locale()); } Index: lib/libc/locale/utf8.c =================================================================== --- lib/libc/locale/utf8.c (revision 225653) +++ lib/libc/locale/utf8.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,7 +30,7 @@ */ #include <sys/param.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/utf8.c 172661 2007-10-15 09:51:30Z ache $"); #include <errno.h> #include <limits.h> @@ -55,22 +60,22 @@ } _UTF8State; int -_UTF8_init(_RuneLocale *rl) +_UTF8_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _UTF8_mbrtowc; - __wcrtomb = _UTF8_wcrtomb; - __mbsinit = _UTF8_mbsinit; - __mbsnrtowcs = _UTF8_mbsnrtowcs; - __wcsnrtombs = _UTF8_wcsnrtombs; - _CurrentRuneLocale = rl; - __mb_cur_max = 6; + l->__mbrtowc = _UTF8_mbrtowc; + l->__wcrtomb = _UTF8_wcrtomb; + l->__mbsinit = _UTF8_mbsinit; + l->__mbsnrtowcs = _UTF8_mbsnrtowcs; + l->__wcsnrtombs = _UTF8_wcsnrtombs; + l->runes = rl; + l->__mb_cur_max = 6; /* * UCS-4 encoding used as the internal representation, so * slots 0x0080-0x00FF are occuped and must be excluded * from the single byte ctype by setting the limit. */ - __mb_sb_limit = 128; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/collcmp.c =================================================================== --- lib/libc/locale/collcmp.c (revision 225653) +++ lib/libc/locale/collcmp.c (working copy) @@ -2,6 +2,11 @@ * Copyright (C) 1996 by Andrey A. Chernov, Moscow, Russia. * 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: @@ -25,20 +30,23 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/collcmp.c 142653 2005-02-27 14:54:23Z phantom $"); #include <string.h> +#include <xlocale.h> #include "collate.h" /* * Compare two characters using collate */ -int __collate_range_cmp(int c1, int c2) +int __collate_range_cmp(struct xlocale_collate *table, int c1, int c2) { static char s1[2], s2[2]; s1[0] = c1; s2[0] = c2; - return (strcoll(s1, s2)); + struct _xlocale l = {{0}}; + l.components[XLC_COLLATE] = (struct xlocale_component *)table; + return (strcoll_l(s1, s2, &l)); } Index: lib/libc/locale/Makefile.inc =================================================================== --- lib/libc/locale/Makefile.inc (revision 225653) +++ lib/libc/locale/Makefile.inc (working copy) @@ -1,11 +1,11 @@ # from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93 -# $FreeBSD$ +# $FreeBSD: head/lib/libc/locale/Makefile.inc 211774 2010-08-24 20:54:43Z imp $ # locale sources .PATH: ${.CURDIR}/${LIBC_ARCH}/locale ${.CURDIR}/locale SRCS+= ascii.c big5.c btowc.c collate.c collcmp.c euc.c fix_grouping.c \ - gb18030.c gb2312.c gbk.c isctype.c iswctype.c \ + gb18030.c gb2312.c gbk.c ctype.c isctype.c iswctype.c \ ldpart.c lmessages.c lmonetary.c lnumeric.c localeconv.c mblen.c \ mbrlen.c \ mbrtowc.c mbsinit.c mbsnrtowcs.c \ @@ -20,7 +20,8 @@ wcstoimax.c wcstol.c wcstold.c wcstoll.c \ wcstombs.c \ wcstoul.c wcstoull.c wcstoumax.c wctob.c wctomb.c wctrans.c wctype.c \ - wcwidth.c + wcwidth.c\ + xlocale.c SYM_MAPS+=${.CURDIR}/locale/Symbol.map Index: lib/libc/locale/wcstof.c =================================================================== --- lib/libc/locale/wcstof.c (revision 225653) +++ lib/libc/locale/wcstof.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002, 2003 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: @@ -25,17 +30,19 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstof.c 127998 2004-04-07 09:47:56Z tjr $"); #include <stdlib.h> #include <wchar.h> #include <wctype.h> +#include "xlocale_private.h" /* * See wcstod() for comments as to the logic used. */ float -wcstof(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +wcstof_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; @@ -43,13 +50,14 @@ char *buf, *end; const wchar_t *wcp; size_t len; + FIX_LOCALE(locale); - while (iswspace(*nptr)) + while (iswspace_l(*nptr, locale)) nptr++; wcp = nptr; mbs = initial; - if ((len = wcsrtombs(NULL, &wcp, 0, &mbs)) == (size_t)-1) { + if ((len = wcsrtombs_l(NULL, &wcp, 0, &mbs, locale)) == (size_t)-1) { if (endptr != NULL) *endptr = (wchar_t *)nptr; return (0.0); @@ -57,9 +65,9 @@ if ((buf = malloc(len + 1)) == NULL) return (0.0); mbs = initial; - wcsrtombs(buf, &wcp, len + 1, &mbs); + wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale); - val = strtof(buf, &end); + val = strtof_l(buf, &end, locale); if (endptr != NULL) *endptr = (wchar_t *)nptr + (end - buf); @@ -68,3 +76,8 @@ return (val); } +float +wcstof(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +{ + return wcstof_l(nptr, endptr, __get_locale()); +} Index: lib/libc/locale/localeconv.3 =================================================================== --- lib/libc/locale/localeconv.3 (revision 225653) +++ lib/libc/locale/localeconv.3 (working copy) @@ -30,7 +30,7 @@ .\" .\" From @(#)setlocale.3 8.1 (Berkeley) 6/9/93 .\" From FreeBSD: src/lib/libc/locale/setlocale.3,v 1.28 2003/11/15 02:26:04 tjr Exp -.\" $FreeBSD$ +.\" $FreeBSD: head/lib/libc/locale/localeconv.3 213573 2010-10-08 12:40:16Z uqs $ .\" .Dd November 21, 2003 .Dt LOCALECONV 3 @@ -44,6 +44,9 @@ .In locale.h .Ft struct lconv * .Fn localeconv "void" +.In xlocale.h +.Ft struct lconv * +.Fn localeconv_l "locale_t locale" .Sh DESCRIPTION The .Fn localeconv @@ -196,6 +199,11 @@ A .Dv CHAR_MAX result similarly denotes an unavailable value. +.Pp +The +.Fn localeconv_l +function takes an explicit locale parameter. For more information, see +.Xr xlocale 3 . .Sh RETURN VALUES The .Fn localeconv @@ -204,6 +212,13 @@ .Xr setlocale 3 or .Fn localeconv . +The return value for +.Fn localeconv_l +is stored with the locale. It will remain valid until a subsequent call to +.Xr freelocale 3 . +If a thread-local locale is in effect then the return value from +.Fn localeconv +will remain valid until the locale is destroyed. .Sh ERRORS No errors are defined. .Sh SEE ALSO Index: lib/libc/locale/mbsinit.c =================================================================== --- lib/libc/locale/mbsinit.c (revision 225653) +++ lib/libc/locale/mbsinit.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,14 +30,19 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/mbsinit.c 129153 2004-05-12 14:09:04Z tjr $"); #include <wchar.h> #include "mblocal.h" int +mbsinit_l(const mbstate_t *ps, locale_t locale) +{ + FIX_LOCALE(locale); + return (XLOCALE_CTYPE(locale)->__mbsinit(ps)); +} +int mbsinit(const mbstate_t *ps) { - - return (__mbsinit(ps)); + return mbsinit_l(ps, __get_locale()); } Index: lib/libc/locale/wcwidth.c =================================================================== --- lib/libc/locale/wcwidth.c (revision 225653) +++ lib/libc/locale/wcwidth.c (working copy) @@ -10,6 +10,11 @@ * 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: @@ -36,15 +41,21 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcwidth.c 165903 2007-01-09 00:28:16Z imp $"); #include <wchar.h> +#include <wctype.h> +#include <xlocale.h> #undef wcwidth int wcwidth(wchar_t wc) { - return (__wcwidth(wc)); } +int +wcwidth_l(wchar_t wc, locale_t locale) +{ + return (__wcwidth_l(wc, locale)); +} Index: lib/libc/locale/rune.c =================================================================== --- lib/libc/locale/rune.c (revision 225653) +++ lib/libc/locale/rune.c (working copy) @@ -34,7 +34,7 @@ static char sccsid[] = "@(#)rune.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/rune.c 165903 2007-01-09 00:28:16Z imp $"); #include "namespace.h" #include <arpa/inet.h> Index: lib/libc/locale/setlocale.c =================================================================== --- lib/libc/locale/setlocale.c (revision 225653) +++ lib/libc/locale/setlocale.c (working copy) @@ -35,7 +35,7 @@ static char sccsid[] = "@(#)setlocale.c 8.1 (Berkeley) 7/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/setlocale.c 165903 2007-01-09 00:28:16Z imp $"); #include <sys/types.h> #include <sys/stat.h> @@ -95,7 +95,7 @@ static char *currentlocale(void); static char *loadlocale(int); -static const char *__get_locale_env(int); +const char *__get_locale_env(int); char * setlocale(category, locale) @@ -278,13 +278,14 @@ if (func(new) != _LDP_ERROR) { (void)strcpy(old, new); + (void)strcpy(__xlocale_global_locale.components[category-1]->locale, new); return (old); } return (NULL); } -static const char * +const char * __get_locale_env(category) int category; { Index: lib/libc/locale/runetype.c =================================================================== --- lib/libc/locale/runetype.c (revision 225653) +++ lib/libc/locale/runetype.c (working copy) @@ -5,6 +5,11 @@ * 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: @@ -31,17 +36,20 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/runetype.c 165903 2007-01-09 00:28:16Z imp $"); #include <ctype.h> #include <stdio.h> #include <runetype.h> +#include <wchar.h> +#include "mblocal.h" unsigned long -___runetype(__ct_rune_t c) +___runetype_l(__ct_rune_t c, locale_t locale) { size_t lim; - _RuneRange *rr = &_CurrentRuneLocale->__runetype_ext; + FIX_LOCALE(locale); + _RuneRange *rr = &(XLOCALE_CTYPE(locale)->runes->__runetype_ext); _RuneEntry *base, *re; if (c < 0 || c == EOF) @@ -64,3 +72,18 @@ return(0L); } +unsigned long +___runetype(__ct_rune_t c) +{ + return ___runetype_l(c, __get_locale()); +} + +int ___mb_cur_max(void) +{ + return XLOCALE_CTYPE(__get_locale())->__mb_cur_max; +} +int ___mb_cur_max_l(locale_t locale) +{ + FIX_LOCALE(locale); + return XLOCALE_CTYPE(locale)->__mb_cur_max; +} Index: lib/libc/locale/btowc.c =================================================================== --- lib/libc/locale/btowc.c (revision 225653) +++ lib/libc/locale/btowc.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002, 2003 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: @@ -25,19 +30,20 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/btowc.c 129154 2004-05-12 14:26:54Z tjr $"); #include <stdio.h> #include <wchar.h> #include "mblocal.h" wint_t -btowc(int c) +btowc_l(int c, locale_t l) { static const mbstate_t initial; mbstate_t mbs = initial; char cc; wchar_t wc; + FIX_LOCALE(l); if (c == EOF) return (WEOF); @@ -47,7 +53,12 @@ * counts. */ cc = (char)c; - if (__mbrtowc(&wc, &cc, 1, &mbs) > 1) + if (XLOCALE_CTYPE(l)->__mbrtowc(&wc, &cc, 1, &mbs) > 1) return (WEOF); return (wc); } +wint_t +btowc(int c) +{ + return btowc_l(c, __get_locale()); +} Index: lib/libc/locale/mbrlen.c =================================================================== --- lib/libc/locale/mbrlen.c (revision 225653) +++ lib/libc/locale/mbrlen.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,17 +30,22 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/mbrlen.c 129154 2004-05-12 14:26:54Z tjr $"); #include <wchar.h> #include "mblocal.h" size_t -mbrlen(const char * __restrict s, size_t n, mbstate_t * __restrict ps) +mbrlen_l(const char * __restrict s, size_t n, mbstate_t * __restrict ps, locale_t locale) { - static mbstate_t mbs; - + FIX_LOCALE(locale); if (ps == NULL) - ps = &mbs; - return (__mbrtowc(NULL, s, n, ps)); + ps = &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: lib/libc/locale/setlocale.h =================================================================== --- lib/libc/locale/setlocale.h (revision 225653) +++ lib/libc/locale/setlocale.h (working copy) @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/locale/setlocale.h 117270 2003-07-06 02:03:37Z ache $ */ #ifndef _SETLOCALE_H_ Index: lib/libc/locale/lmessages.c =================================================================== --- lib/libc/locale/lmessages.c (revision 225653) +++ lib/libc/locale/lmessages.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org> * 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/lmessages.c 116875 2003-06-26 10:46:16Z phantom $"); #include <stddef.h> @@ -36,6 +41,14 @@ #define LCMESSAGES_SIZE_MIN \ (offsetof(struct lc_messages_T, yesstr) / sizeof(char *)) +struct xlocale_messages { + struct xlocale_component header; + char *buffer; + struct lc_messages_T locale; +}; + +struct xlocale_messages __xlocale_global_messages; + static char empty[] = ""; static const struct lc_messages_T _C_messages_locale = { @@ -45,33 +58,55 @@ "no" /* nostr */ }; -static struct lc_messages_T _messages_locale; -static int _messages_using_locale; -static char *_messages_locale_buf; +static void destruct_messages(void *v) +{ + struct xlocale_messages *l = v; + if (l->buffer) + free(l->buffer); + free(l); +} -int -__messages_load_locale(const char *name) +static int +messages_load_locale(struct xlocale_messages *loc, int *using_locale, const char *name) { int ret; + struct lc_messages_T *l = &loc->locale; - ret = __part_load_locale(name, &_messages_using_locale, - &_messages_locale_buf, "LC_MESSAGES", + ret = __part_load_locale(name, using_locale, + &loc->buffer, "LC_MESSAGES", LCMESSAGES_SIZE_FULL, LCMESSAGES_SIZE_MIN, - (const char **)&_messages_locale); + (const char **)l); if (ret == _LDP_LOADED) { - if (_messages_locale.yesstr == NULL) - _messages_locale.yesstr = empty; - if (_messages_locale.nostr == NULL) - _messages_locale.nostr = empty; + if (l->yesstr == NULL) + l->yesstr = empty; + if (l->nostr == NULL) + l->nostr = empty; } return (ret); } +int +__messages_load_locale(const char *name) +{ + return messages_load_locale(&__xlocale_global_messages, + &__xlocale_global_locale.using_messages_locale, name); +} +void * +__messages_load(const char *name, locale_t l) +{ + struct xlocale_messages *new = calloc(sizeof(struct xlocale_messages), 1); + new->header.header.destructor = destruct_messages; + if (messages_load_locale(new, &l->using_messages_locale, name)) { + xlocale_release(new); + return NULL; + } + return new; +} struct lc_messages_T * -__get_current_messages_locale(void) +__get_current_messages_locale(locale_t loc) { - return (_messages_using_locale - ? &_messages_locale + return (loc->using_messages_locale + ? &((struct xlocale_messages *)loc->components[XLC_MESSAGES])->locale : (struct lc_messages_T *)&_C_messages_locale); } Index: lib/libc/locale/big5.c =================================================================== --- lib/libc/locale/big5.c (revision 225653) +++ lib/libc/locale/big5.c (working copy) @@ -6,6 +6,11 @@ * 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: @@ -39,7 +44,7 @@ static char sccsid[] = "@(#)big5.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/big5.c 172619 2007-10-13 16:28:22Z ache $"); #include <sys/types.h> #include <errno.h> @@ -62,15 +67,15 @@ } _BIG5State; int -_BIG5_init(_RuneLocale *rl) +_BIG5_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _BIG5_mbrtowc; - __wcrtomb = _BIG5_wcrtomb; - __mbsinit = _BIG5_mbsinit; - _CurrentRuneLocale = rl; - __mb_cur_max = 2; - __mb_sb_limit = 128; + l->__mbrtowc = _BIG5_mbrtowc; + l->__wcrtomb = _BIG5_wcrtomb; + l->__mbsinit = _BIG5_mbsinit; + l->runes = rl; + l->__mb_cur_max = 2; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/lmessages.h =================================================================== --- lib/libc/locale/lmessages.h (revision 225653) +++ lib/libc/locale/lmessages.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org> * 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: @@ -23,12 +28,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/locale/lmessages.h 88309 2001-12-20 18:28:52Z phantom $ */ #ifndef _LMESSAGES_H_ #define _LMESSAGES_H_ +#include "xlocale_private.h" + struct lc_messages_T { const char *yesexpr; const char *noexpr; @@ -36,7 +43,7 @@ const char *nostr; }; -struct lc_messages_T *__get_current_messages_locale(void); +struct lc_messages_T *__get_current_messages_locale(locale_t); int __messages_load_locale(const char *); #endif /* !_LMESSAGES_H_ */ Index: lib/libc/locale/duplocale.3 =================================================================== --- lib/libc/locale/duplocale.3 (revision 0) +++ lib/libc/locale/duplocale.3 (revision 0) @@ -0,0 +1,79 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written 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 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. +.\" +.\" @(#)ctype.3 8.1 (Berkeley) 6/4/93 +.\" $FreeBSD: head/lib/libc/locale/ctype.3 196820 2009-09-04 07:44:58Z des $ +.\" +.Dd September 17 2011 +.Dt DUPLOCALE 3 +.Os +.Sh NAME +.Nm duplocale +.Nd duplicate an locale +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Ft locale_t +.Fn duplocale "locale_t locale" +.Sh DESCRIPTION +Duplicates an existing +.Fa locale_t +returning a new +.Fa locale_t +that refers to the same locale values but has independent internal state. +Various functions, such as +.Xr mblen 3 +require presistent state. These functions formerly used static variables and +calls to them from multiple threads had undefined behavior. They now use +fields in the +.Fa locale_t +associated with the current thread by +.Xr uselocale 3 . +These calls are therefore only thread safe on threads with a unique per-thread +locale. +.Pt +The locale returned by this call must be freed with +.Xr freelocale 3 . +.Sh BUGS +Ideally, +.Xr uselocale 3 +should make a copy of the +.Fa locale_t +implicitly to ensure thread safety, and a copy of the global locale should be +installed lazily on each thread. The FreeBSD implementation does not do this, +for compatibility with Darwin. +.Sh SEE ALSO +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr querylocale 3 , +.Xr uselocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 Index: lib/libc/locale/uselocale.3 =================================================================== --- lib/libc/locale/uselocale.3 (revision 0) +++ lib/libc/locale/uselocale.3 (revision 0) @@ -0,0 +1,60 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written 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 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. +.\" +.\" @(#)ctype.3 8.1 (Berkeley) 6/4/93 +.\" $FreeBSD: head/lib/libc/locale/ctype.3 196820 2009-09-04 07:44:58Z des $ +.\" +.Dd September 17 2011 +.Dt USELOCALE 3 +.Os +.Sh NAME +.Nm uselocale +.Nd Sets a thread-local locale. +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Ft locale_t +.Fn uselocale "locale_t locale" +.Sh DESCRIPTION +Specifies the locale for this thread to use. Specifying +.Fa LC_GLOBAL_LOCALE +disables the per-thread locale, while NULL returns the current locale without +setting a new one. +.Sh RETURN VALUES +Returns the previous locale, or LC_GLOBAL_LOCALE if this thread has no locale +associated with it. +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr querylocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 Index: lib/libc/locale/isctype.c =================================================================== --- lib/libc/locale/isctype.c (revision 225653) +++ lib/libc/locale/isctype.c (working copy) @@ -39,7 +39,7 @@ static char sccsid[] = "@(#)isctype.c 8.3 (Berkeley) 2/24/94"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/isctype.c 172619 2007-10-13 16:28:22Z ache $"); #include <ctype.h> Index: lib/libc/locale/freelocale.3 =================================================================== --- lib/libc/locale/freelocale.3 (revision 0) +++ lib/libc/locale/freelocale.3 (revision 0) @@ -0,0 +1,63 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written 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 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. +.\" +.\" @(#)ctype.3 8.1 (Berkeley) 6/4/93 +.\" $FreeBSD: head/lib/libc/locale/ctype.3 196820 2009-09-04 07:44:58Z des $ +.\" +.Dd September 17 2011 +.Dt FREELOCALE 3 +.Os +.Sh NAME +.Nm freelocale +.Nd Frees a locale created with +.Xr duplocale 3 +or +.Xr newlocale 3 . +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Ft int +.Fn freelocale "locale_t locale" +.Sh DESCRIPTION +Frees a +.Fa locale_t . +This relinquishes any resources held exclusively by this locale. Note that +locales share reference-counted components, so a call to this function is not +guaranteed to free all of the components. +.Sh RETURN VALUES +Returns 0 on success or -1 on error. +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr querylocale 3 , +.Xr uselocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 . Index: lib/libc/locale/wcsrtombs.c =================================================================== --- lib/libc/locale/wcsrtombs.c (revision 225653) +++ lib/libc/locale/wcsrtombs.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcsrtombs.c 132497 2004-07-21 10:54:57Z tjr $"); #include <limits.h> #include <stdlib.h> @@ -34,12 +39,18 @@ #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; + 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) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__wcsnrtombs(dst, src, SIZE_T_MAX, len, ps)); + return wcsrtombs_l(dst, src, len, ps, __get_locale()); } Index: lib/libc/locale/localeconv.c =================================================================== --- lib/libc/locale/localeconv.c (revision 225653) +++ lib/libc/locale/localeconv.c (working copy) @@ -3,6 +3,11 @@ * Copyright (c) 1991, 1993 * The Regents of the University of California. 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: @@ -32,7 +37,7 @@ static char sccsid[] = "@(#)localeconv.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/localeconv.c 174546 2007-12-12 07:43:23Z phantom $"); #include <locale.h> @@ -48,25 +53,24 @@ * lconv structure are computed only when the monetary or numeric * locale has been changed. */ -int __mlocale_changed = 1; -int __nlocale_changed = 1; /* * Return the current locale conversion. */ struct lconv * -localeconv() +localeconv_l(locale_t loc) { - static struct lconv ret; + FIX_LOCALE(loc); + struct lconv *ret = &loc->lconv; - if (__mlocale_changed) { + if (loc->monetary_locale_changed) { /* LC_MONETARY part */ struct lc_monetary_T * mptr; -#define M_ASSIGN_STR(NAME) (ret.NAME = (char*)mptr->NAME) -#define M_ASSIGN_CHAR(NAME) (ret.NAME = mptr->NAME[0]) +#define M_ASSIGN_STR(NAME) (ret->NAME = (char*)mptr->NAME) +#define M_ASSIGN_CHAR(NAME) (ret->NAME = mptr->NAME[0]) - mptr = __get_current_monetary_locale(); + mptr = __get_current_monetary_locale(loc); M_ASSIGN_STR(int_curr_symbol); M_ASSIGN_STR(currency_symbol); M_ASSIGN_STR(mon_decimal_point); @@ -88,21 +92,26 @@ M_ASSIGN_CHAR(int_n_sep_by_space); M_ASSIGN_CHAR(int_p_sign_posn); M_ASSIGN_CHAR(int_n_sign_posn); - __mlocale_changed = 0; + loc->monetary_locale_changed = 0; } - if (__nlocale_changed) { + if (loc->numeric_locale_changed) { /* LC_NUMERIC part */ struct lc_numeric_T * nptr; -#define N_ASSIGN_STR(NAME) (ret.NAME = (char*)nptr->NAME) +#define N_ASSIGN_STR(NAME) (ret->NAME = (char*)nptr->NAME) - nptr = __get_current_numeric_locale(); + nptr = __get_current_numeric_locale(loc); N_ASSIGN_STR(decimal_point); N_ASSIGN_STR(thousands_sep); N_ASSIGN_STR(grouping); - __nlocale_changed = 0; + loc->numeric_locale_changed = 0; } - return (&ret); + return ret; } +struct lconv * +localeconv(void) +{ + return localeconv_l(__get_locale()); +} Index: lib/libc/locale/wcsnrtombs.c =================================================================== --- lib/libc/locale/wcsnrtombs.c (revision 225653) +++ lib/libc/locale/wcsnrtombs.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcsnrtombs.c 141716 2005-02-12 08:45:12Z stefanf $"); #include <limits.h> #include <stdlib.h> @@ -34,16 +39,22 @@ #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; + 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) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__wcsnrtombs(dst, src, nwc, len, 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) @@ -53,13 +64,14 @@ const wchar_t *s; size_t nbytes; size_t nb; + struct xlocale_ctype *l = XLOCALE_CTYPE(__get_locale()); s = *src; nbytes = 0; if (dst == NULL) { while (nwc-- > 0) { - if ((nb = __wcrtomb(buf, *s, ps)) == (size_t)-1) + if ((nb = l->__wcrtomb(buf, *s, ps)) == (size_t)-1) /* Invalid character - wcrtomb() sets errno. */ return ((size_t)-1); else if (*s == L'\0') @@ -73,7 +85,7 @@ while (len > 0 && nwc-- > 0) { if (len > (size_t)MB_CUR_MAX) { /* Enough space to translate in-place. */ - if ((nb = __wcrtomb(dst, *s, ps)) == (size_t)-1) { + if ((nb = l->__wcrtomb(dst, *s, ps)) == (size_t)-1) { *src = s; return ((size_t)-1); } @@ -86,7 +98,7 @@ * character is too long for the buffer. */ mbsbak = *ps; - if ((nb = __wcrtomb(buf, *s, ps)) == (size_t)-1) { + if ((nb = l->__wcrtomb(buf, *s, ps)) == (size_t)-1) { *src = s; return ((size_t)-1); } Index: lib/libc/locale/gbk.c =================================================================== --- lib/libc/locale/gbk.c (revision 225653) +++ lib/libc/locale/gbk.c (working copy) @@ -6,6 +6,11 @@ * 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: @@ -32,7 +37,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/gbk.c 172619 2007-10-13 16:28:22Z ache $"); #include <sys/types.h> #include <errno.h> @@ -55,15 +60,15 @@ } _GBKState; int -_GBK_init(_RuneLocale *rl) +_GBK_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _GBK_mbrtowc; - __wcrtomb = _GBK_wcrtomb; - __mbsinit = _GBK_mbsinit; - _CurrentRuneLocale = rl; - __mb_cur_max = 2; - __mb_sb_limit = 128; + l->__mbrtowc = _GBK_mbrtowc; + l->__wcrtomb = _GBK_wcrtomb; + l->__mbsinit = _GBK_mbsinit; + l->runes = rl; + l->__mb_cur_max = 2; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/querylocale.3 =================================================================== --- lib/libc/locale/querylocale.3 (revision 0) +++ lib/libc/locale/querylocale.3 (revision 0) @@ -0,0 +1,58 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written 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 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. +.\" +.\" @(#)ctype.3 8.1 (Berkeley) 6/4/93 +.\" $FreeBSD: head/lib/libc/locale/ctype.3 196820 2009-09-04 07:44:58Z des $ +.\" +.Dd September 17 2011 +.Dt QUERYLOCALE 3 +.Os +.Sh NAME +.Nm querylocale +.Nd Look up the locale name for a specified category. +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Ft const char * +.Fn querylocale "int mask" "locale_t locale" +.Sh DESCRIPTION +Returns the name of the locale for the category specified by +.Fa mask. +This possible values for the mask are the same as those in +.Xr newlocale 3 . If more than one bit in the mask is set, the returned value +is undefined. +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr uselocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 Index: lib/libc/locale/iswctype.c =================================================================== --- lib/libc/locale/iswctype.c (revision 225653) +++ lib/libc/locale/iswctype.c (working copy) @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/iswctype.c 172909 2007-10-23 17:39:28Z ache $"); #include <wctype.h> Index: lib/libc/locale/wctype.c =================================================================== --- lib/libc/locale/wctype.c (revision 225653) +++ lib/libc/locale/wctype.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 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: @@ -25,22 +30,32 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wctype.c 177311 2008-03-17 18:22:23Z antoine $"); #include <ctype.h> #include <string.h> #include <wctype.h> +#include <xlocale.h> #undef iswctype int iswctype(wint_t wc, wctype_t charclass) { - return (__istype(wc, charclass)); } +int +iswctype_l(wint_t wc, wctype_t charclass, locale_t locale) +{ + return __istype_l(wc, charclass, locale); +} +/* + * IMPORTANT: The 0 in the call to this function in wctype() must be changed to + * __get_locale() if wctype_l() ie ever modified to actually use the locale + * parameter. + */ wctype_t -wctype(const char *property) +wctype_l(const char *property, locale_t locale) { static const struct { const char *name; @@ -72,3 +87,8 @@ return (props[i].mask); } + +wctype_t wctype(const char *property) +{ + return wctype_l(property, 0); +} Index: lib/libc/locale/lnumeric.c =================================================================== --- lib/libc/locale/lnumeric.c (revision 225653) +++ lib/libc/locale/lnumeric.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org> * 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: @@ -25,14 +30,13 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/lnumeric.c 116875 2003-06-26 10:46:16Z phantom $"); #include <limits.h> #include "ldpart.h" #include "lnumeric.h" -extern int __nlocale_changed; extern const char *__fix_locale_grouping_str(const char *); #define LCNUMERIC_SIZE (sizeof(struct lc_numeric_T) / sizeof(char *)) @@ -45,37 +49,67 @@ numempty /* grouping */ }; -static struct lc_numeric_T _numeric_locale; -static int _numeric_using_locale; -static char *_numeric_locale_buf; +static void +destruct_numeric(void *v) +{ + struct xlocale_numeric *l = v; + if (l->buffer) + free(l->buffer); + free(l); +} -int -__numeric_load_locale(const char *name) +struct xlocale_numeric __xlocale_global_numeric; + +static int +numeric_load_locale(struct xlocale_numeric *loc, int *using_locale, int *changed, + const char *name) { int ret; + struct lc_numeric_T *l = &loc->locale; - ret = __part_load_locale(name, &_numeric_using_locale, - &_numeric_locale_buf, "LC_NUMERIC", + ret = __part_load_locale(name, using_locale, + &loc->buffer, "LC_NUMERIC", LCNUMERIC_SIZE, LCNUMERIC_SIZE, - (const char **)&_numeric_locale); + (const char**)l); if (ret != _LDP_ERROR) - __nlocale_changed = 1; + *changed= 1; if (ret == _LDP_LOADED) { /* Can't be empty according to C99 */ - if (*_numeric_locale.decimal_point == '\0') - _numeric_locale.decimal_point = + if (*l->decimal_point == '\0') + l->decimal_point = _C_numeric_locale.decimal_point; - _numeric_locale.grouping = - __fix_locale_grouping_str(_numeric_locale.grouping); + l->grouping = + __fix_locale_grouping_str(l->grouping); } return (ret); } +int +__numeric_load_locale(const char *name) +{ + return numeric_load_locale(&__xlocale_global_numeric, + &__xlocale_global_locale.using_numeric_locale, + &__xlocale_global_locale.numeric_locale_changed, name); +} +void * +__numeric_load(const char *name, locale_t l) +{ + struct xlocale_numeric *new = calloc(sizeof(struct xlocale_numeric), 1); + new->header.header.destructor = destruct_numeric; + if (numeric_load_locale(new, &l->using_numeric_locale, + &l->numeric_locale_changed, name)) + { + xlocale_release(new); + return NULL; + } + return new; +} + struct lc_numeric_T * -__get_current_numeric_locale(void) +__get_current_numeric_locale(locale_t loc) { - return (_numeric_using_locale - ? &_numeric_locale + return (loc->using_numeric_locale + ? &((struct xlocale_numeric *)loc->components[XLC_NUMERIC])->locale : (struct lc_numeric_T *)&_C_numeric_locale); } Index: lib/libc/locale/wcstoimax.c =================================================================== --- lib/libc/locale/wcstoimax.c (revision 225653) +++ lib/libc/locale/wcstoimax.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. 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: @@ -34,26 +39,28 @@ #endif /* LIBC_SCCS and not lint */ __FBSDID("FreeBSD: src/lib/libc/stdlib/strtoimax.c,v 1.8 2002/09/06 11:23:59 tjr Exp "); #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstoimax.c 165903 2007-01-09 00:28:16Z imp $"); #include <errno.h> #include <inttypes.h> #include <stdlib.h> #include <wchar.h> #include <wctype.h> +#include "xlocale_private.h" /* * Convert a wide character string to an intmax_t integer. */ intmax_t -wcstoimax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, - int base) +wcstoimax_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; uintmax_t acc; wchar_t c; uintmax_t cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoimax for comments as to the logic used. @@ -61,7 +68,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -88,8 +95,8 @@ cutoff /= base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -122,3 +129,9 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +intmax_t +wcstoimax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base) +{ + return wcstoimax_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/lnumeric.h =================================================================== --- lib/libc/locale/lnumeric.h (revision 225653) +++ lib/libc/locale/lnumeric.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org> * 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: @@ -23,19 +28,25 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/locale/lnumeric.h 88309 2001-12-20 18:28:52Z phantom $ */ #ifndef _LNUMERIC_H_ #define _LNUMERIC_H_ +#include "xlocale_private.h" struct lc_numeric_T { const char *decimal_point; const char *thousands_sep; const char *grouping; }; +struct xlocale_numeric { + struct xlocale_component header; + char *buffer; + struct lc_numeric_T locale; +}; -struct lc_numeric_T *__get_current_numeric_locale(void); +struct lc_numeric_T *__get_current_numeric_locale(locale_t loc); int __numeric_load_locale(const char *); #endif /* !_LNUMERIC_H_ */ Index: lib/libc/locale/ldpart.c =================================================================== --- lib/libc/locale/ldpart.c (revision 225653) +++ lib/libc/locale/ldpart.c (working copy) @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/ldpart.c 128650 2004-04-25 19:56:50Z ache $"); #include "namespace.h" #include <sys/types.h> Index: lib/libc/locale/wctomb.c =================================================================== --- lib/libc/locale/wctomb.c (revision 225653) +++ lib/libc/locale/wctomb.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,25 +30,30 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wctomb.c 132821 2004-07-29 06:18:40Z tjr $"); #include <stdlib.h> #include <wchar.h> #include "mblocal.h" int -wctomb(char *s, wchar_t wchar) +wctomb_l(char *s, wchar_t wchar, locale_t locale) { static const mbstate_t initial; - static mbstate_t mbs; size_t rval; + FIX_LOCALE(locale); if (s == NULL) { /* No support for state dependent encodings. */ - mbs = initial; + locale->wctomb = initial; return (0); } - if ((rval = __wcrtomb(s, wchar, &mbs)) == (size_t)-1) + if ((rval = XLOCALE_CTYPE(locale)->__wcrtomb(s, wchar, &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: lib/libc/locale/toupper.c =================================================================== --- lib/libc/locale/toupper.c (revision 225653) +++ lib/libc/locale/toupper.c (working copy) @@ -5,6 +5,11 @@ * 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: @@ -31,18 +36,22 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/toupper.c 165903 2007-01-09 00:28:16Z imp $"); #include <ctype.h> #include <stdio.h> #include <runetype.h> +#include <wchar.h> +#include "mblocal.h" __ct_rune_t -___toupper(c) +___toupper_l(c, l) __ct_rune_t c; + locale_t l; { size_t lim; - _RuneRange *rr = &_CurrentRuneLocale->__mapupper_ext; + FIX_LOCALE(l); + _RuneRange *rr = &XLOCALE_CTYPE(l)->runes->__maplower_ext; _RuneEntry *base, *re; if (c < 0 || c == EOF) @@ -62,3 +71,9 @@ return(c); } +__ct_rune_t +___toupper(c) + __ct_rune_t c; +{ + return ___toupper_l(c, __get_locale()); +} Index: lib/libc/locale/fix_grouping.c =================================================================== --- lib/libc/locale/fix_grouping.c (revision 225653) +++ lib/libc/locale/fix_grouping.c (working copy) @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/fix_grouping.c 116875 2003-06-26 10:46:16Z phantom $"); #include <ctype.h> #include <limits.h> Index: lib/libc/locale/wcstombs.c =================================================================== --- lib/libc/locale/wcstombs.c (revision 225653) +++ lib/libc/locale/wcstombs.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstombs.c 187302 2009-01-15 18:53:52Z rdivacky $"); #include <limits.h> #include <stdlib.h> @@ -33,13 +38,21 @@ #include "mblocal.h" size_t -wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n) +wcstombs_l(char * __restrict s, const wchar_t * __restrict pwcs, size_t n, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; const wchar_t *pwcsp; + FIX_LOCALE(locale); mbs = initial; pwcsp = pwcs; - return (__wcsnrtombs(s, &pwcsp, SIZE_T_MAX, n, &mbs)); + return (XLOCALE_CTYPE(locale)->__wcsnrtombs(s, &pwcsp, SIZE_T_MAX, n, &mbs)); } +size_t +wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n) +{ + return wcstombs_l(s, pwcs, n, __get_locale()); +} + Index: lib/libc/locale/wcstoull.c =================================================================== --- lib/libc/locale/wcstoull.c (revision 225653) +++ lib/libc/locale/wcstoull.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. 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: @@ -34,26 +39,28 @@ #endif /* LIBC_SCCS and not lint */ __FBSDID("FreeBSD: src/lib/libc/stdlib/strtoull.c,v 1.18 2002/09/06 11:23:59 tjr Exp "); #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstoull.c 165903 2007-01-09 00:28:16Z imp $"); #include <errno.h> #include <limits.h> #include <stdlib.h> #include <wchar.h> #include <wctype.h> +#include "xlocale_private.h" /* * Convert a wide character string to an unsigned long long integer. */ unsigned long long -wcstoull(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, - int base) +wcstoull_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; unsigned long long acc; wchar_t c; unsigned long long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoull for comments as to the logic used. @@ -61,7 +68,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -86,8 +93,8 @@ cutlim = ULLONG_MAX % base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -120,3 +127,9 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +unsigned long long +wcstoull(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base) +{ + return wcstoull_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/euc.c =================================================================== --- lib/libc/locale/euc.c (revision 225653) +++ lib/libc/locale/euc.c (working copy) @@ -6,6 +6,11 @@ * 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: @@ -39,7 +44,7 @@ static char sccsid[] = "@(#)euc.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/param.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/euc.c 172619 2007-10-13 16:28:22Z ache $"); #include <errno.h> #include <limits.h> @@ -70,7 +75,7 @@ } _EucState; int -_EUC_init(_RuneLocale *rl) +_EUC_init(struct xlocale_ctype *l, _RuneLocale *rl) { _EucInfo *ei; int x, new__mb_cur_max; @@ -113,12 +118,12 @@ } rl->__variable = ei; rl->__variable_len = sizeof(_EucInfo); - _CurrentRuneLocale = rl; - __mb_cur_max = new__mb_cur_max; - __mbrtowc = _EUC_mbrtowc; - __wcrtomb = _EUC_wcrtomb; - __mbsinit = _EUC_mbsinit; - __mb_sb_limit = 256; + l->runes = rl; + l->__mb_cur_max = new__mb_cur_max; + l->__mbrtowc = _EUC_mbrtowc; + l->__wcrtomb = _EUC_wcrtomb; + l->__mbsinit = _EUC_mbsinit; + l->__mb_sb_limit = 256; return (0); } Index: lib/libc/locale/wctob.c =================================================================== --- lib/libc/locale/wctob.c (revision 225653) +++ lib/libc/locale/wctob.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wctob.c 129154 2004-05-12 14:26:54Z tjr $"); #include <limits.h> #include <stdio.h> @@ -33,13 +38,19 @@ #include "mblocal.h" int -wctob(wint_t c) +wctob_l(wint_t c, locale_t locale) { static const mbstate_t initial; mbstate_t mbs = initial; char buf[MB_LEN_MAX]; + FIX_LOCALE(locale); - if (c == WEOF || __wcrtomb(buf, c, &mbs) != 1) + if (c == WEOF || XLOCALE_CTYPE(locale)->__wcrtomb(buf, c, &mbs) != 1) return (EOF); return ((unsigned char)*buf); } +int +wctob(wint_t c) +{ + return wctob_l(c, __get_locale()); +} Index: lib/libc/locale/wcstold.c =================================================================== --- lib/libc/locale/wcstold.c (revision 225653) +++ lib/libc/locale/wcstold.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002, 2003 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: @@ -25,17 +30,19 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstold.c 127998 2004-04-07 09:47:56Z tjr $"); #include <stdlib.h> #include <wchar.h> #include <wctype.h> +#include "xlocale_private.h" /* * See wcstod() for comments as to the logic used. */ long double -wcstold(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +wcstold_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; @@ -43,13 +50,14 @@ char *buf, *end; const wchar_t *wcp; size_t len; + FIX_LOCALE(locale); - while (iswspace(*nptr)) + while (iswspace_l(*nptr, locale)) nptr++; wcp = nptr; mbs = initial; - if ((len = wcsrtombs(NULL, &wcp, 0, &mbs)) == (size_t)-1) { + if ((len = wcsrtombs_l(NULL, &wcp, 0, &mbs, locale)) == (size_t)-1) { if (endptr != NULL) *endptr = (wchar_t *)nptr; return (0.0); @@ -57,9 +65,9 @@ if ((buf = malloc(len + 1)) == NULL) return (0.0); mbs = initial; - wcsrtombs(buf, &wcp, len + 1, &mbs); + wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale); - val = strtold(buf, &end); + val = strtold_l(buf, &end, locale); if (endptr != NULL) *endptr = (wchar_t *)nptr + (end - buf); @@ -68,3 +76,8 @@ return (val); } +long double +wcstold(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +{ + return wcstold_l(nptr, endptr, __get_locale()); +} Index: lib/libc/locale/wctrans.c =================================================================== --- lib/libc/locale/wctrans.c (revision 225653) +++ lib/libc/locale/wctrans.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 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: @@ -25,11 +30,12 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wctrans.c 121852 2003-11-01 08:20:58Z tjr $"); #include <errno.h> #include <string.h> #include <wctype.h> +#include "xlocale_private.h" enum { _WCT_ERROR = 0, @@ -38,15 +44,14 @@ }; wint_t -towctrans(wint_t wc, wctrans_t desc) +towctrans_l(wint_t wc, wctrans_t desc, locale_t locale) { - switch (desc) { case _WCT_TOLOWER: - wc = towlower(wc); + wc = towlower_l(wc, locale); break; case _WCT_TOUPPER: - wc = towupper(wc); + wc = towupper_l(wc, locale); break; case _WCT_ERROR: default: @@ -56,9 +61,18 @@ return (wc); } +wint_t +towctrans(wint_t wc, wctrans_t desc) +{ + return towctrans_l(wc, desc, __get_locale()); +} +/* + * wctrans() calls this will a 0 locale. If this is ever modified to actually + * use the locale, wctrans() must be modified to call __get_locale(). + */ wctrans_t -wctrans(const char *charclass) +wctrans_l(const char *charclass, locale_t locale) { struct { const char *name; @@ -78,3 +92,10 @@ errno = EINVAL; return (ccls[i].trans); } + +wctrans_t +wctrans(const char *charclass) +{ + return wctrans_l(charclass, 0); +} + Index: lib/libc/locale/gb18030.c =================================================================== --- lib/libc/locale/gb18030.c (revision 225653) +++ lib/libc/locale/gb18030.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -30,7 +35,7 @@ */ #include <sys/param.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/gb18030.c 172619 2007-10-13 16:28:22Z ache $"); #include <errno.h> #include <runetype.h> @@ -39,8 +44,6 @@ #include <wchar.h> #include "mblocal.h" -extern int __mb_sb_limit; - static size_t _GB18030_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t, mbstate_t * __restrict); static int _GB18030_mbsinit(const mbstate_t *); @@ -53,15 +56,15 @@ } _GB18030State; int -_GB18030_init(_RuneLocale *rl) +_GB18030_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _GB18030_mbrtowc; - __wcrtomb = _GB18030_wcrtomb; - __mbsinit = _GB18030_mbsinit; - _CurrentRuneLocale = rl; - __mb_cur_max = 4; - __mb_sb_limit = 128; + l->__mbrtowc = _GB18030_mbrtowc; + l->__wcrtomb = _GB18030_wcrtomb; + l->__mbsinit = _GB18030_mbsinit; + l->runes = rl; + l->__mb_cur_max = 4; + l->__mb_sb_limit = 128; return (0); } Index: lib/libc/locale/nl_langinfo.c =================================================================== --- lib/libc/locale/nl_langinfo.c (revision 225653) +++ lib/libc/locale/nl_langinfo.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2001, 2003 Alexey Zelkin <phantom@FreeBSD.org> * 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/nl_langinfo.c 197765 2009-10-05 07:13:15Z edwin $"); #include <langinfo.h> #include <limits.h> @@ -41,15 +46,16 @@ #define _REL(BASE) ((int)item-BASE) char * -nl_langinfo(nl_item item) +nl_langinfo_l(nl_item item, locale_t loc) { - char *ret, *s, *cs; - static char *csym = NULL; + char *ret, *cs; + const char *s; + FIX_LOCALE(loc); switch (item) { case CODESET: ret = ""; - if ((s = setlocale(LC_CTYPE, NULL)) != NULL) { + if ((s = querylocale(LC_CTYPE_MASK, loc)) != NULL) { if ((cs = strchr(s, '.')) != NULL) ret = cs + 1; else if (strcmp(s, "C") == 0 || @@ -58,46 +64,46 @@ } break; case D_T_FMT: - ret = (char *) __get_current_time_locale()->c_fmt; + ret = (char *) __get_current_time_locale(loc)->c_fmt; break; case D_FMT: - ret = (char *) __get_current_time_locale()->x_fmt; + ret = (char *) __get_current_time_locale(loc)->x_fmt; break; case T_FMT: - ret = (char *) __get_current_time_locale()->X_fmt; + ret = (char *) __get_current_time_locale(loc)->X_fmt; break; case T_FMT_AMPM: - ret = (char *) __get_current_time_locale()->ampm_fmt; + ret = (char *) __get_current_time_locale(loc)->ampm_fmt; break; case AM_STR: - ret = (char *) __get_current_time_locale()->am; + ret = (char *) __get_current_time_locale(loc)->am; break; case PM_STR: - ret = (char *) __get_current_time_locale()->pm; + ret = (char *) __get_current_time_locale(loc)->pm; break; case DAY_1: case DAY_2: case DAY_3: case DAY_4: case DAY_5: case DAY_6: case DAY_7: - ret = (char*) __get_current_time_locale()->weekday[_REL(DAY_1)]; + ret = (char*) __get_current_time_locale(loc)->weekday[_REL(DAY_1)]; break; case ABDAY_1: case ABDAY_2: case ABDAY_3: case ABDAY_4: case ABDAY_5: case ABDAY_6: case ABDAY_7: - ret = (char*) __get_current_time_locale()->wday[_REL(ABDAY_1)]; + ret = (char*) __get_current_time_locale(loc)->wday[_REL(ABDAY_1)]; break; case MON_1: case MON_2: case MON_3: case MON_4: case MON_5: case MON_6: case MON_7: case MON_8: case MON_9: case MON_10: case MON_11: case MON_12: - ret = (char*) __get_current_time_locale()->month[_REL(MON_1)]; + ret = (char*) __get_current_time_locale(loc)->month[_REL(MON_1)]; break; case ABMON_1: case ABMON_2: case ABMON_3: case ABMON_4: case ABMON_5: case ABMON_6: case ABMON_7: case ABMON_8: case ABMON_9: case ABMON_10: case ABMON_11: case ABMON_12: - ret = (char*) __get_current_time_locale()->mon[_REL(ABMON_1)]; + ret = (char*) __get_current_time_locale(loc)->mon[_REL(ABMON_1)]; break; case ALTMON_1: case ALTMON_2: case ALTMON_3: case ALTMON_4: case ALTMON_5: case ALTMON_6: case ALTMON_7: case ALTMON_8: case ALTMON_9: case ALTMON_10: case ALTMON_11: case ALTMON_12: ret = (char*) - __get_current_time_locale()->alt_month[_REL(ALTMON_1)]; + __get_current_time_locale(loc)->alt_month[_REL(ALTMON_1)]; break; case ERA: /* XXX: need to be implemented */ @@ -120,16 +126,16 @@ ret = ""; break; case RADIXCHAR: - ret = (char*) __get_current_numeric_locale()->decimal_point; + ret = (char*) __get_current_numeric_locale(loc)->decimal_point; break; case THOUSEP: - ret = (char*) __get_current_numeric_locale()->thousands_sep; + ret = (char*) __get_current_numeric_locale(loc)->thousands_sep; break; case YESEXPR: - ret = (char*) __get_current_messages_locale()->yesexpr; + ret = (char*) __get_current_messages_locale(loc)->yesexpr; break; case NOEXPR: - ret = (char*) __get_current_messages_locale()->noexpr; + ret = (char*) __get_current_messages_locale(loc)->noexpr; break; /* * YESSTR and NOSTR items marked with LEGACY are available, but not @@ -137,45 +143,51 @@ * they're subject to remove in future specification editions. */ case YESSTR: /* LEGACY */ - ret = (char*) __get_current_messages_locale()->yesstr; + ret = (char*) __get_current_messages_locale(loc)->yesstr; break; case NOSTR: /* LEGACY */ - ret = (char*) __get_current_messages_locale()->nostr; + ret = (char*) __get_current_messages_locale(loc)->nostr; break; /* * SUSv2 special formatted currency string */ case CRNCYSTR: ret = ""; - cs = (char*) __get_current_monetary_locale()->currency_symbol; + cs = (char*) __get_current_monetary_locale(loc)->currency_symbol; if (*cs != '\0') { - char pos = localeconv()->p_cs_precedes; + char pos = localeconv_l(loc)->p_cs_precedes; - if (pos == localeconv()->n_cs_precedes) { + if (pos == localeconv_l(loc)->n_cs_precedes) { char psn = '\0'; if (pos == CHAR_MAX) { - if (strcmp(cs, __get_current_monetary_locale()->mon_decimal_point) == 0) + if (strcmp(cs, __get_current_monetary_locale(loc)->mon_decimal_point) == 0) psn = '.'; } else psn = pos ? '-' : '+'; if (psn != '\0') { int clen = strlen(cs); - if ((csym = reallocf(csym, clen + 2)) != NULL) { - *csym = psn; - strcpy(csym + 1, cs); - ret = csym; + if ((loc->csym = reallocf(loc->csym, clen + 2)) != NULL) { + *loc->csym = psn; + strcpy(loc->csym + 1, cs); + ret = loc->csym; } } } } break; case D_MD_ORDER: /* FreeBSD local extension */ - ret = (char *) __get_current_time_locale()->md_order; + ret = (char *) __get_current_time_locale(loc)->md_order; break; default: ret = ""; } return (ret); } + +char * +nl_langinfo(nl_item item) +{ + return nl_langinfo_l(item, __get_locale()); +} Index: lib/libc/locale/table.c =================================================================== --- lib/libc/locale/table.c (revision 225653) +++ lib/libc/locale/table.c (working copy) @@ -5,6 +5,11 @@ * 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: @@ -34,14 +39,14 @@ static char sccsid[] = "@(#)table.c 8.1 (Berkeley) 6/27/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/table.c 165903 2007-01-09 00:28:16Z imp $"); #include <ctype.h> #include <runetype.h> #include <wchar.h> #include "mblocal.h" -_RuneLocale _DefaultRuneLocale = { +const _RuneLocale _DefaultRuneLocale = { _RUNE_MAGIC_1, "NONE", NULL, @@ -245,5 +250,14 @@ }, }; -_RuneLocale *_CurrentRuneLocale = &_DefaultRuneLocale; +#undef _CurrentRuneLocale +_RuneLocale *_CurrentRuneLocale = (_RuneLocale*)&_DefaultRuneLocale; +_RuneLocale * +__runes_for_locale(locale_t locale, int *mb_sb_limit) +{ + FIX_LOCALE(locale); + struct xlocale_ctype *c = XLOCALE_CTYPE(locale); + *mb_sb_limit = c->__mb_sb_limit; + return c->runes; +} Index: lib/libc/locale/wcstoll.c =================================================================== --- lib/libc/locale/wcstoll.c (revision 225653) +++ lib/libc/locale/wcstoll.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1992, 1993 * The Regents of the University of California. 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: @@ -34,25 +39,28 @@ #endif /* LIBC_SCCS and not lint */ __FBSDID("FreeBSD: src/lib/libc/stdlib/strtoll.c,v 1.19 2002/09/06 11:23:59 tjr Exp "); #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstoll.c 165903 2007-01-09 00:28:16Z imp $"); #include <errno.h> #include <limits.h> #include <stdlib.h> #include <wchar.h> #include <wctype.h> +#include "xlocale_private.h" /* * Convert a wide character string to a long long integer. */ long long -wcstoll(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +wcstoll_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + int base, locale_t locale) { const wchar_t *s; unsigned long long acc; wchar_t c; unsigned long long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtoll for comments as to the logic used. @@ -60,7 +68,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == L'-') { neg = 1; c = *s++; @@ -87,8 +95,8 @@ cutoff /= base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -121,3 +129,8 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +long long +wcstoll(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +{ + return wcstoll_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/tolower.c =================================================================== --- lib/libc/locale/tolower.c (revision 225653) +++ lib/libc/locale/tolower.c (working copy) @@ -5,6 +5,11 @@ * 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: @@ -31,18 +36,22 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/tolower.c 165903 2007-01-09 00:28:16Z imp $"); #include <ctype.h> #include <stdio.h> #include <runetype.h> +#include <wchar.h> +#include "mblocal.h" __ct_rune_t -___tolower(c) +___tolower_l(c, l) __ct_rune_t c; + locale_t l; { size_t lim; - _RuneRange *rr = &_CurrentRuneLocale->__maplower_ext; + FIX_LOCALE(l); + _RuneRange *rr = &XLOCALE_CTYPE(l)->runes->__maplower_ext; _RuneEntry *base, *re; if (c < 0 || c == EOF) @@ -62,3 +71,9 @@ return(c); } +__ct_rune_t +___tolower(c) + __ct_rune_t c; +{ + return ___tolower_l(c, __get_locale()); +} Index: lib/libc/locale/mskanji.c =================================================================== --- lib/libc/locale/mskanji.c (revision 225653) +++ lib/libc/locale/mskanji.c (working copy) @@ -6,6 +6,11 @@ * (C) Sin'ichiro MIYATANI / Phase One, Inc * May 12, 1995 * + * 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: @@ -37,7 +42,7 @@ static char sccsid[] = "@(#)mskanji.c 1.0 (Phase One) 5/5/95"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/mskanji.c 172619 2007-10-13 16:28:22Z ache $"); #include <sys/types.h> #include <errno.h> @@ -60,15 +65,15 @@ } _MSKanjiState; int -_MSKanji_init(_RuneLocale *rl) +_MSKanji_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _MSKanji_mbrtowc; - __wcrtomb = _MSKanji_wcrtomb; - __mbsinit = _MSKanji_mbsinit; - _CurrentRuneLocale = rl; - __mb_cur_max = 2; - __mb_sb_limit = 256; + l->__mbrtowc = _MSKanji_mbrtowc; + l->__wcrtomb = _MSKanji_wcrtomb; + l->__mbsinit = _MSKanji_mbsinit; + l->runes = rl; + l->__mb_cur_max = 2; + l->__mb_sb_limit = 256; return (0); } Index: lib/libc/locale/mblen.c =================================================================== --- lib/libc/locale/mblen.c (revision 225653) +++ lib/libc/locale/mblen.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,26 +30,32 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/mblen.c 132821 2004-07-29 06:18:40Z tjr $"); #include <stdlib.h> #include <wchar.h> #include "mblocal.h" int -mblen(const char *s, size_t n) +mblen_l(const char *s, size_t n, locale_t locale) { static const mbstate_t initial; - static mbstate_t mbs; size_t rval; + FIX_LOCALE(locale); if (s == NULL) { /* No support for state dependent encodings. */ - mbs = initial; + locale->mblen = initial; return (0); } - rval = __mbrtowc(NULL, s, n, &mbs); + rval = XLOCALE_CTYPE(locale)->__mbrtowc(NULL, s, n, &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: lib/libc/locale/rpmatch.c =================================================================== --- lib/libc/locale/rpmatch.c (revision 225653) +++ lib/libc/locale/rpmatch.c (working copy) @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/rpmatch.c 139922 2005-01-09 03:55:13Z tjr $"); #include <langinfo.h> #include <regex.h> Index: lib/libc/locale/none.c =================================================================== --- lib/libc/locale/none.c (revision 225653) +++ lib/libc/locale/none.c (working copy) @@ -6,6 +6,11 @@ * 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: @@ -35,7 +40,7 @@ static char sccsid[] = "@(#)none.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/none.c 172619 2007-10-13 16:28:22Z ache $"); #include <errno.h> #include <limits.h> @@ -64,17 +69,17 @@ int __mb_sb_limit = 256; /* Expected to be <= _CACHED_RUNES */ int -_none_init(_RuneLocale *rl) +_none_init(struct xlocale_ctype *l, _RuneLocale *rl) { - __mbrtowc = _none_mbrtowc; - __mbsinit = _none_mbsinit; - __mbsnrtowcs = _none_mbsnrtowcs; - __wcrtomb = _none_wcrtomb; - __wcsnrtombs = _none_wcsnrtombs; - _CurrentRuneLocale = rl; - __mb_cur_max = 1; - __mb_sb_limit = 256; + l->__mbrtowc = _none_mbrtowc; + l->__mbsinit = _none_mbsinit; + l->__mbsnrtowcs = _none_mbsnrtowcs; + l->__wcrtomb = _none_wcrtomb; + l->__wcsnrtombs = _none_wcsnrtombs; + l->runes = rl; + l->__mb_cur_max = 1; + l->__mb_sb_limit = 256; return(0); } @@ -192,3 +197,15 @@ size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict, size_t, size_t, mbstate_t * __restrict) = _none_wcsnrtombs; +struct xlocale_ctype __xlocale_global_ctype = { + {{0}, "C"}, + (_RuneLocale*)&_DefaultRuneLocale, + _none_mbrtowc, + _none_mbsinit, + _none_mbsnrtowcs, + _none_wcrtomb, + _none_wcsnrtombs, + 1, /* __mb_cur_max, */ + 256 /* __mb_sb_limit */ +}; + Index: lib/libc/locale/mbstowcs.c =================================================================== --- lib/libc/locale/mbstowcs.c (revision 225653) +++ lib/libc/locale/mbstowcs.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/mbstowcs.c 187302 2009-01-15 18:53:52Z rdivacky $"); #include <limits.h> #include <stdlib.h> @@ -33,13 +38,19 @@ #include "mblocal.h" size_t -mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n) +mbstowcs_l(wchar_t * __restrict pwcs, const char * __restrict s, size_t n, locale_t locale) { static const mbstate_t initial; mbstate_t mbs; const char *sp; + FIX_LOCALE(locale); mbs = initial; sp = s; - return (__mbsnrtowcs(pwcs, &sp, SIZE_T_MAX, n, &mbs)); + return (XLOCALE_CTYPE(locale)->__mbsnrtowcs(pwcs, &sp, SIZE_T_MAX, n, &mbs)); } +size_t +mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n) +{ + return mbstowcs_l(pwcs, s, n, __get_locale()); +} Index: lib/libc/locale/wcstod.c =================================================================== --- lib/libc/locale/wcstod.c (revision 225653) +++ lib/libc/locale/wcstod.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 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: @@ -25,11 +30,12 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstod.c 127998 2004-04-07 09:47:56Z tjr $"); #include <stdlib.h> #include <wchar.h> #include <wctype.h> +#include "xlocale_private.h" /* * Convert a string to a double-precision number. @@ -41,7 +47,8 @@ * for at least the digits, radix character and letters. */ double -wcstod(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +wcstod_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; @@ -49,8 +56,9 @@ char *buf, *end; const wchar_t *wcp; size_t len; + FIX_LOCALE(locale); - while (iswspace(*nptr)) + while (iswspace_l(*nptr, locale)) nptr++; /* @@ -65,7 +73,7 @@ */ wcp = nptr; mbs = initial; - if ((len = wcsrtombs(NULL, &wcp, 0, &mbs)) == (size_t)-1) { + if ((len = wcsrtombs_l(NULL, &wcp, 0, &mbs, locale)) == (size_t)-1) { if (endptr != NULL) *endptr = (wchar_t *)nptr; return (0.0); @@ -73,10 +81,10 @@ if ((buf = malloc(len + 1)) == NULL) return (0.0); mbs = initial; - wcsrtombs(buf, &wcp, len + 1, &mbs); + wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale); /* Let strtod() do most of the work for us. */ - val = strtod(buf, &end); + val = strtod_l(buf, &end, locale); /* * We only know where the number ended in the _multibyte_ @@ -92,3 +100,8 @@ return (val); } +double +wcstod(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr) +{ + return wcstod_l(nptr, endptr, __get_locale()); +} Index: lib/libc/locale/setrunelocale.c =================================================================== --- lib/libc/locale/setrunelocale.c (revision 225653) +++ lib/libc/locale/setrunelocale.c (working copy) @@ -5,6 +5,11 @@ * 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: @@ -31,7 +36,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/setrunelocale.c 175586 2008-01-23 03:05:35Z ache $"); #include <runetype.h> #include <errno.h> @@ -49,68 +54,46 @@ extern _RuneLocale *_Read_RuneMagi(FILE *); -static int __setrunelocale(const char *); +static int __setrunelocale(struct xlocale_ctype *l, const char *); +#define __collate_load_error (table->__collate_load_error) +#define __collate_substitute_nontrivial (table->__collate_substitute_nontrivial) +#define __collate_substitute_table_ptr (table->__collate_substitute_table_ptr) +#define __collate_char_pri_table_ptr (table->__collate_char_pri_table_ptr) +#define __collate_chain_pri_table (table->__collate_chain_pri_table) + + +static void destruct_ctype(void *v) +{ + struct xlocale_ctype *l = v; + if (strcmp(l->runes->__encoding, "EUC") == 0) + free(l->runes->__variable); + if (&_DefaultRuneLocale != l->runes) + free(l->runes); + free(l); +} +_RuneLocale *__getCurrentRuneLocale(void) +{ + return XLOCALE_CTYPE(__get_locale())->runes; +} + static int -__setrunelocale(const char *encoding) +__setrunelocale(struct xlocale_ctype *l, const char *encoding) { FILE *fp; char name[PATH_MAX]; _RuneLocale *rl; int saverr, ret; - size_t (*old__mbrtowc)(wchar_t * __restrict, - const char * __restrict, size_t, mbstate_t * __restrict); - size_t (*old__wcrtomb)(char * __restrict, wchar_t, - mbstate_t * __restrict); - int (*old__mbsinit)(const mbstate_t *); - size_t (*old__mbsnrtowcs)(wchar_t * __restrict, - const char ** __restrict, size_t, size_t, mbstate_t * __restrict); - size_t (*old__wcsnrtombs)(char * __restrict, - const wchar_t ** __restrict, size_t, size_t, - mbstate_t * __restrict); - static char ctype_encoding[ENCODING_LEN + 1]; - static _RuneLocale *CachedRuneLocale; - static int Cached__mb_cur_max; - static int Cached__mb_sb_limit; - static size_t (*Cached__mbrtowc)(wchar_t * __restrict, - const char * __restrict, size_t, mbstate_t * __restrict); - static size_t (*Cached__wcrtomb)(char * __restrict, wchar_t, - mbstate_t * __restrict); - static int (*Cached__mbsinit)(const mbstate_t *); - static size_t (*Cached__mbsnrtowcs)(wchar_t * __restrict, - const char ** __restrict, size_t, size_t, mbstate_t * __restrict); - static size_t (*Cached__wcsnrtombs)(char * __restrict, - const wchar_t ** __restrict, size_t, size_t, - mbstate_t * __restrict); + struct xlocale_ctype saved = *l; /* * The "C" and "POSIX" locale are always here. */ if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) { - (void) _none_init(&_DefaultRuneLocale); + (void) _none_init(l, (_RuneLocale*)&_DefaultRuneLocale); return (0); } - /* - * If the locale name is the same as our cache, use the cache. - */ - if (CachedRuneLocale != NULL && - strcmp(encoding, ctype_encoding) == 0) { - _CurrentRuneLocale = CachedRuneLocale; - __mb_cur_max = Cached__mb_cur_max; - __mb_sb_limit = Cached__mb_sb_limit; - __mbrtowc = Cached__mbrtowc; - __mbsinit = Cached__mbsinit; - __mbsnrtowcs = Cached__mbsnrtowcs; - __wcrtomb = Cached__wcrtomb; - __wcsnrtombs = Cached__wcsnrtombs; - return (0); - } - - /* - * Slurp the locale file into the cache. - */ - /* Range checking not needed, encoding length already checked before */ (void) strcpy(name, _PathLocale); (void) strcat(name, "/"); @@ -127,63 +110,47 @@ } (void)fclose(fp); - old__mbrtowc = __mbrtowc; - old__mbsinit = __mbsinit; - old__mbsnrtowcs = __mbsnrtowcs; - old__wcrtomb = __wcrtomb; - old__wcsnrtombs = __wcsnrtombs; + l->__mbrtowc = NULL; + l->__mbsinit = NULL; + l->__mbsnrtowcs = __mbsnrtowcs_std; + l->__wcrtomb = NULL; + l->__wcsnrtombs = __wcsnrtombs_std; - __mbrtowc = NULL; - __mbsinit = NULL; - __mbsnrtowcs = __mbsnrtowcs_std; - __wcrtomb = NULL; - __wcsnrtombs = __wcsnrtombs_std; - rl->__sputrune = NULL; rl->__sgetrune = NULL; if (strcmp(rl->__encoding, "NONE") == 0) - ret = _none_init(rl); + ret = _none_init(l, rl); else if (strcmp(rl->__encoding, "ASCII") == 0) - ret = _ascii_init(rl); + ret = _ascii_init(l, rl); else if (strcmp(rl->__encoding, "UTF-8") == 0) - ret = _UTF8_init(rl); + ret = _UTF8_init(l, rl); else if (strcmp(rl->__encoding, "EUC") == 0) - ret = _EUC_init(rl); + ret = _EUC_init(l, rl); else if (strcmp(rl->__encoding, "GB18030") == 0) - ret = _GB18030_init(rl); + ret = _GB18030_init(l, rl); else if (strcmp(rl->__encoding, "GB2312") == 0) - ret = _GB2312_init(rl); + ret = _GB2312_init(l, rl); else if (strcmp(rl->__encoding, "GBK") == 0) - ret = _GBK_init(rl); + ret = _GBK_init(l, rl); else if (strcmp(rl->__encoding, "BIG5") == 0) - ret = _BIG5_init(rl); + ret = _BIG5_init(l, rl); else if (strcmp(rl->__encoding, "MSKanji") == 0) - ret = _MSKanji_init(rl); + ret = _MSKanji_init(l, rl); else ret = EFTYPE; if (ret == 0) { - if (CachedRuneLocale != NULL) { - /* See euc.c */ - if (strcmp(CachedRuneLocale->__encoding, "EUC") == 0) - free(CachedRuneLocale->__variable); - free(CachedRuneLocale); + /* Free the old runes if it exists. */ + /* FIXME: The "EUC" check here is a hideous abstraction violation. */ + if ((saved.runes != &_DefaultRuneLocale) && (saved.runes)) { + if (strcmp(saved.runes->__encoding, "EUC") == 0) { + free(saved.runes->__variable); + } + free(saved.runes); } - CachedRuneLocale = _CurrentRuneLocale; - Cached__mb_cur_max = __mb_cur_max; - Cached__mb_sb_limit = __mb_sb_limit; - Cached__mbrtowc = __mbrtowc; - Cached__mbsinit = __mbsinit; - Cached__mbsnrtowcs = __mbsnrtowcs; - Cached__wcrtomb = __wcrtomb; - Cached__wcsnrtombs = __wcsnrtombs; - (void)strcpy(ctype_encoding, encoding); } else { - __mbrtowc = old__mbrtowc; - __mbsinit = old__mbsinit; - __mbsnrtowcs = old__mbsnrtowcs; - __wcrtomb = old__wcrtomb; - __wcsnrtombs = old__wcsnrtombs; + /* Restore the saved version if this failed. */ + memcpy(l, &saved, sizeof(struct xlocale_ctype)); free(rl); } @@ -193,12 +160,24 @@ int __wrap_setrunelocale(const char *locale) { - int ret = __setrunelocale(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; return (_LDP_LOADED); } - +void *__ctype_load(const char *locale, locale_t 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: lib/libc/locale/lmonetary.c =================================================================== --- lib/libc/locale/lmonetary.c (revision 225653) +++ lib/libc/locale/lmonetary.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org> * 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/lmonetary.c 116875 2003-06-26 10:46:16Z phantom $"); #include <limits.h> #include <stddef.h> @@ -34,7 +39,6 @@ #include "ldpart.h" #include "lmonetary.h" -extern int __mlocale_changed; extern const char * __fix_locale_grouping_str(const char *); #define LCMONETARY_SIZE_FULL (sizeof(struct lc_monetary_T) / sizeof(char *)) @@ -69,9 +73,7 @@ numempty /* int_n_sign_posn */ }; -static struct lc_monetary_T _monetary_locale; -static int _monetary_using_locale; -static char *_monetary_locale_buf; +struct xlocale_monetary __xlocale_global_monetary; static char cnv(const char *str) @@ -83,23 +85,34 @@ return ((char)i); } -int -__monetary_load_locale(const char *name) +static void +destruct_monetary(void *v) { + struct xlocale_monetary *l = v; + if (l->buffer) + free(l->buffer); + free(l); +} + +static int +monetary_load_locale_l(struct xlocale_monetary *loc, int *using_locale, + int *changed, const char *name) +{ int ret; + struct lc_monetary_T *l = &loc->locale; - ret = __part_load_locale(name, &_monetary_using_locale, - &_monetary_locale_buf, "LC_MONETARY", + ret = __part_load_locale(name, using_locale, + &loc->buffer, "LC_MONETARY", LCMONETARY_SIZE_FULL, LCMONETARY_SIZE_MIN, - (const char **)&_monetary_locale); + (const char **)l); if (ret != _LDP_ERROR) - __mlocale_changed = 1; + *changed = 1; if (ret == _LDP_LOADED) { - _monetary_locale.mon_grouping = - __fix_locale_grouping_str(_monetary_locale.mon_grouping); + l->mon_grouping = + __fix_locale_grouping_str(l->mon_grouping); -#define M_ASSIGN_CHAR(NAME) (((char *)_monetary_locale.NAME)[0] = \ - cnv(_monetary_locale.NAME)) +#define M_ASSIGN_CHAR(NAME) (((char *)l->NAME)[0] = \ + cnv(l->NAME)) M_ASSIGN_CHAR(int_frac_digits); M_ASSIGN_CHAR(frac_digits); @@ -117,9 +130,9 @@ */ #define M_ASSIGN_ICHAR(NAME) \ do { \ - if (_monetary_locale.int_##NAME == NULL) \ - _monetary_locale.int_##NAME = \ - _monetary_locale.NAME; \ + if (l->int_##NAME == NULL) \ + l->int_##NAME = \ + l->NAME; \ else \ M_ASSIGN_CHAR(int_##NAME); \ } while (0) @@ -133,12 +146,32 @@ } return (ret); } +int +__monetary_load_locale(const char *name) +{ + return monetary_load_locale_l(&__xlocale_global_monetary, + &__xlocale_global_locale.using_monetary_locale, + &__xlocale_global_locale.monetary_locale_changed, name); +} +void* __monetary_load(const char *name, locale_t l) +{ + struct xlocale_monetary *new = calloc(sizeof(struct xlocale_monetary), 1); + new->header.header.destructor = destruct_monetary; + if (monetary_load_locale_l(new, &l->using_monetary_locale, + &l->monetary_locale_changed, name) != _LDP_LOADED) + { + xlocale_release(new); + return NULL; + } + return new; +} + struct lc_monetary_T * -__get_current_monetary_locale(void) +__get_current_monetary_locale(locale_t loc) { - return (_monetary_using_locale - ? &_monetary_locale + return (loc->using_monetary_locale + ? &((struct xlocale_monetary*)loc->components[XLC_MONETARY])->locale : (struct lc_monetary_T *)&_C_monetary_locale); } Index: lib/libc/locale/nextwctype.c =================================================================== --- lib/libc/locale/nextwctype.c (revision 225653) +++ lib/libc/locale/nextwctype.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,17 +30,20 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/nextwctype.c 131787 2004-07-08 06:43:37Z tjr $"); #include <runetype.h> #include <wchar.h> #include <wctype.h> +#include "mblocal.h" wint_t -nextwctype(wint_t wc, wctype_t wct) +nextwctype_l(wint_t wc, wctype_t wct, locale_t locale) { size_t lim; - _RuneRange *rr = &_CurrentRuneLocale->__runetype_ext; + FIX_LOCALE(locale); + _RuneLocale *runes = XLOCALE_CTYPE(locale)->runes; + _RuneRange *rr = &runes->__runetype_ext; _RuneEntry *base, *re; int noinc; @@ -43,7 +51,7 @@ if (wc < _CACHED_RUNES) { wc++; while (wc < _CACHED_RUNES) { - if (_CurrentRuneLocale->__runetype[wc] & wct) + if (runes->__runetype[wc] & wct) return (wc); wc++; } @@ -88,3 +96,8 @@ } return (-1); } +wint_t +nextwctype(wint_t wc, wctype_t wct) +{ + return nextwctype_l(wc, wct, __get_locale()); +} Index: lib/libc/locale/wcstol.c =================================================================== --- lib/libc/locale/wcstol.c (revision 225653) +++ lib/libc/locale/wcstol.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. 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: @@ -28,25 +33,28 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcstol.c 165903 2007-01-09 00:28:16Z imp $"); #include <ctype.h> #include <errno.h> #include <limits.h> #include <wchar.h> #include <wctype.h> +#include "xlocale_private.h" /* * Convert a string to a long integer. */ long -wcstol(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +wcstol_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int + base, locale_t locale) { const wchar_t *s; unsigned long acc; wchar_t c; unsigned long cutoff; int neg, any, cutlim; + FIX_LOCALE(locale); /* * See strtol for comments as to the logic used. @@ -54,7 +62,7 @@ s = nptr; do { c = *s++; - } while (iswspace(c)); + } while (iswspace_l(c, locale)); if (c == '-') { neg = 1; c = *s++; @@ -81,8 +89,8 @@ cutoff /= base; for ( ; ; c = *s++) { #ifdef notyet - if (iswdigit(c)) - c = digittoint(c); + if (iswdigit_l(c, locale)) + c = digittoint_l(c, locale); else #endif if (c >= L'0' && c <= L'9') @@ -115,3 +123,8 @@ *endptr = (wchar_t *)(any ? s - 1 : nptr); return (acc); } +long +wcstol(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base) +{ + return wcstol_l(nptr, endptr, base, __get_locale()); +} Index: lib/libc/locale/wcrtomb.c =================================================================== --- lib/libc/locale/wcrtomb.c (revision 225653) +++ lib/libc/locale/wcrtomb.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,17 +30,23 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcrtomb.c 129153 2004-05-12 14:09:04Z tjr $"); #include <wchar.h> #include "mblocal.h" size_t -wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) +wcrtomb_l(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps, + locale_t locale) { - static mbstate_t mbs; - + FIX_LOCALE(locale); if (ps == NULL) - ps = &mbs; - return (__wcrtomb(s, wc, ps)); + ps = &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: lib/libc/locale/lmonetary.h =================================================================== --- lib/libc/locale/lmonetary.h (revision 225653) +++ lib/libc/locale/lmonetary.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org> * 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: @@ -23,11 +28,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/locale/lmonetary.h 104711 2002-10-09 09:19:28Z tjr $ */ #ifndef _LMONETARY_H_ #define _LMONETARY_H_ +#include "xlocale_private.h" struct lc_monetary_T { const char *int_curr_symbol; @@ -52,8 +58,13 @@ const char *int_p_sign_posn; const char *int_n_sign_posn; }; +struct xlocale_monetary { + struct xlocale_component header; + char *buffer; + struct lc_monetary_T locale; +}; -struct lc_monetary_T *__get_current_monetary_locale(void); +struct lc_monetary_T *__get_current_monetary_locale(locale_t loc); int __monetary_load_locale(const char *); #endif /* !_LMONETARY_H_ */ Index: lib/libc/locale/nomacros.c =================================================================== --- lib/libc/locale/nomacros.c (revision 225653) +++ lib/libc/locale/nomacros.c (working copy) @@ -1,5 +1,5 @@ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/nomacros.c 92986 2002-03-22 21:53:29Z obrien $"); /* * Tell <ctype.h> to generate extern versions of all its inline Index: lib/libc/locale/wcsftime.c =================================================================== --- lib/libc/locale/wcsftime.c (revision 225653) +++ lib/libc/locale/wcsftime.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 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: @@ -25,13 +30,14 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/wcsftime.c 187312 2009-01-15 20:45:59Z rdivacky $"); #include <errno.h> #include <limits.h> #include <stdlib.h> #include <time.h> #include <wchar.h> +#include "xlocale_private.h" /* * Convert date and time to a wide-character string. @@ -47,8 +53,9 @@ * format specifications in the format string. */ size_t -wcsftime(wchar_t * __restrict wcs, size_t maxsize, - const wchar_t * __restrict format, const struct tm * __restrict timeptr) +wcsftime_l(wchar_t * __restrict wcs, size_t maxsize, + const wchar_t * __restrict format, const struct tm * __restrict timeptr, + locale_t locale) { static const mbstate_t initial; mbstate_t mbs; @@ -57,6 +64,7 @@ const wchar_t *formatp; size_t n, sflen; int sverrno; + FIX_LOCALE(locale); sformat = dst = NULL; @@ -66,13 +74,13 @@ */ mbs = initial; formatp = format; - sflen = wcsrtombs(NULL, &formatp, 0, &mbs); + sflen = wcsrtombs_l(NULL, &formatp, 0, &mbs, locale); if (sflen == (size_t)-1) goto error; if ((sformat = malloc(sflen + 1)) == NULL) goto error; mbs = initial; - wcsrtombs(sformat, &formatp, sflen + 1, &mbs); + wcsrtombs_l(sformat, &formatp, sflen + 1, &mbs, locale); /* * Allocate memory for longest multibyte sequence that will fit @@ -87,11 +95,11 @@ } if ((dst = malloc(maxsize * MB_CUR_MAX)) == NULL) goto error; - if (strftime(dst, maxsize, sformat, timeptr) == 0) + if (strftime_l(dst, maxsize, sformat, timeptr, locale) == 0) goto error; dstp = dst; mbs = initial; - n = mbsrtowcs(wcs, &dstp, maxsize, &mbs); + n = mbsrtowcs_l(wcs, &dstp, maxsize, &mbs, locale); if (n == (size_t)-2 || n == (size_t)-1 || dstp != NULL) goto error; @@ -106,3 +114,9 @@ errno = sverrno; return (0); } +size_t +wcsftime(wchar_t * __restrict wcs, size_t maxsize, + const wchar_t * __restrict format, const struct tm * __restrict timeptr) +{ + return wcsftime_l(wcs, maxsize, format, timeptr, __get_locale()); +} Index: lib/libc/locale/xlocale_private.h =================================================================== --- lib/libc/locale/xlocale_private.h (revision 0) +++ lib/libc/locale/xlocale_private.h (revision 0) @@ -0,0 +1,199 @@ +/*- + * 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. + */ + +#ifndef _XLOCALE_PRIVATE__H_ +#define _XLOCALE_PRIVATE__H_ + +#include <xlocale.h> +#include <locale.h> +#include <stdlib.h> +#include <stdint.h> +#include "setlocale.h" + +enum { + XLC_COLLATE = 0, + XLC_CTYPE, + XLC_MONETARY, + XLC_NUMERIC, + XLC_TIME, + XLC_MESSAGES, + XLC_LAST +}; + + +/** + * 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. + * + * Note: We could save a few bytes by using a bitfield for the flags at the end + * of this structure. I imagine that most programs will not have more than + * half a dozen locales though, so this doesn't seem worthwhile. + */ +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 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 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; + __sync_fetch_and_add(&(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 = __sync_sub_and_fetch(&(obj->retain_count), 1); + if (count < 0) + { + if (0 != obj->destructor) + { + 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; + +/** + * 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. + */ +locale_t __get_locale(void); + +/** + * 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_global_locale; + case -1: return __get_locale(); + default: return locale; + } +} + +/** + * Replace a plaecholder locale with the real global or thread-local locale_t. + */ +#define FIX_LOCALE(l) (l = get_real_locale(l)) + +#endif Index: lib/libc/locale/newlocale.3 =================================================================== --- lib/libc/locale/newlocale.3 (revision 0) +++ lib/libc/locale/newlocale.3 (revision 0) @@ -0,0 +1,111 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written 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 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. +.\" +.\" @(#)ctype.3 8.1 (Berkeley) 6/4/93 +.\" $FreeBSD: head/lib/libc/locale/ctype.3 196820 2009-09-04 07:44:58Z des $ +.\" +.Dd September 17 2011 +.Dt newlocale 3 +.Os +.Sh NAME +.Nm newlocale +.Nd Creates a new locale +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale +.Ft +.Fn newlocale "int mask" "const char * locale" "locale_t base" +.Sh DESCRIPTION +Creates a new locale, inheriting some properties from an existing locale. The +.Fa mask +defines the components that the new locale will have set to the locale with the +name specified in the +.Fa locale +parameter. Any other components will be inherited from +.Fa base . +.Pt +The +.Fa mask +is either +.Fa LC_ALL_MASK, +indicating all possible locale components, or the logical OR of some +combination of the following: +.Bl -tag -width "LC_MESSAGES_MASK" -offset indent +.It LC_COLLATE_MASK +The locale for string collation routines. This controls alphabetic ordering in +.Xr strcoll 3 + and +.Xr strxfrm 3 . +.It LC_CTYPE_MASK +The locale for the +.Xr ctype 3 +and +.Xr multibyte 3 +functions. This controls recognition of upper and lower case, alpha- betic or +non-alphabetic characters, and so on. +.It LC_MESSAGES_MASK +Set a locale for message catalogs, see +.Xr catopen 3 +function. +.It LC_MONETARY_MASK +Set a locale for formatting monetary values; this affects +the +.Xr localeconv 3 +function. +.It LC_NUMERIC_MASK +Set a locale for formatting numbers. This controls the for- +matting of decimal points in input and output of floating +point numbers in functions such as +.Xr printf 3 +and +.Xr scanf 3 , +as well as values returned by +.Xr localeconv 3 . +.It LC_TIME_MASK +Set a locale for formatting dates and times using the +.Xr strftime 3 +function. +.El + +This function uses the same rules for loading locale components as +.Xr setlocale 3 . +.Sh RETURN VALUES +Returns a new, valid, +.Fa locale_t +or NULL if an error occurs. You must free the returned locale with +.Xr freelocale 3 . +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr querylocale 3 , +.Xr uselocale 3 , +.Xr xlocale 3 +.Sh STANDARDS +This function, conforms to +.St -p1003.1-2008 Index: lib/libc/locale/mbsnrtowcs.c =================================================================== --- lib/libc/locale/mbsnrtowcs.c (revision 225653) +++ lib/libc/locale/mbsnrtowcs.c (working copy) @@ -1,6 +1,11 @@ /*- * 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 @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/mbsnrtowcs.c 132497 2004-07-21 10:54:57Z tjr $"); #include <errno.h> #include <limits.h> @@ -34,14 +39,19 @@ #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; + 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) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__mbsnrtowcs(dst, src, nms, len, ps)); + return mbsnrtowcs_l(dst, src, nms, len, ps, __get_locale()); } size_t @@ -52,13 +62,14 @@ size_t nchr; wchar_t wc; size_t nb; + struct xlocale_ctype *ct = XLOCALE_CTYPE(__get_locale()); s = *src; nchr = 0; if (dst == NULL) { for (;;) { - if ((nb = __mbrtowc(&wc, s, nms, ps)) == (size_t)-1) + if ((nb = ct->__mbrtowc(&wc, s, nms, ps)) == (size_t)-1) /* Invalid sequence - mbrtowc() sets errno. */ return ((size_t)-1); else if (nb == 0 || nb == (size_t)-2) @@ -71,7 +82,7 @@ } while (len-- > 0) { - if ((nb = __mbrtowc(dst, s, nms, ps)) == (size_t)-1) { + if ((nb = ct->__mbrtowc(dst, s, nms, ps)) == (size_t)-1) { *src = s; return ((size_t)-1); } else if (nb == (size_t)-2) { Index: lib/libc/locale/xlocale.3 =================================================================== --- lib/libc/locale/xlocale.3 (revision 0) +++ lib/libc/locale/xlocale.3 (revision 0) @@ -0,0 +1,268 @@ +.\" Copyright (c) 2011 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written 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 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. +.\" +.\" @(#)ctype.3 8.1 (Berkeley) 6/4/93 +.\" $FreeBSD: head/lib/libc/locale/ctype.3 196820 2009-09-04 07:44:58Z des $ +.\" +.Dd September 17 2011 +.Dt XLOCALE 3 +.Os +.Sh NAME +.Nm xlocale +.Nd Thread-safe extended locale support. +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In xlocale.h +.Sh DESCRIPTION +The extended locale support includes a set of functions for setting +thread-local locales, as well convenience functions for performing locale-aware +calls with a specified locale. +.Pp +The core of the xlocale API is the +.Fa locale_t +type. This is an opqaue type encapsulating a locale. Instances of this can be +either set as the locale for a specific thread or passed directly to the +.Fa _l +suffixed variants of various standard C functions. Two special +.Fa locale_t +values are available: +.Bl -bullet -offset indent +.It +NULL refers to the current locale for the thread, or to the global locale if no +locale has been set for this thread. +.It +LC_GLOBAL_LOCALE refers to the global locale. +.El +.Pp +The global locale is the locale set with the +.Xr setlocale 3 +function. +.Sh CAVEATS +The +.Xr setlocale 3 +function, and others in the family, refer to the global locale. Other +functions that depend on the locale, however, will take the thread-local locale +if one has been set. This means that the idiom of setting the locale using +.Xr setlocale 3 , +calling a locale-dependent function, and then restoring the locale will not +have the expected behavior if the current thread has had a locale set using +.Xr uselocale 3 . +You should avoid this idiom and prefer to use the +.Fa _l +suffixed versions instead. +.Sh SEE ALSO +.Xr duplocale 3 , +.Xr freelocale 3 , +.Xr localeconv 3 , +.Xr newlocale 3 , +.Xr querylocale 3 , +.Xr uselocale 3 , +.Sh CONVENIENCE FUNCTIONS +The xlocale API includes a number of +.Fa _l +suffixed convenience functions. These are variants of standard C functions +that have been modified to take an explicit +.Fa locale_t +parameter as the final argument or, in the case of variadic functions, as an +additional argument directly before the format string. +.Pp +These functions are exposed by including +.In xlocale.h +.Em after +including the relevant headers for the standard variant. For example, the +.Xr strtol_l 3 +function is exposed by including +.In xlocale.h +after +.In stdlib.h , +which defines +.Xr strtol 3 . +.Pp +For reference, a complete list of the locale-aware functions that are available +in this form, along with the headers that expose them, is provided here: +.Pp +.Bl -tag -width "<monetary.h> " +.It In wctype.h +.Xr iswalnum_l 3 , +.Xr iswalpha_l 3 , +.Xr iswcntrl_l 3 , +.Xr iswctype_l 3 , +.Xr iswdigit_l 3 , +.Xr iswgraph_l 3 , +.Xr iswlower_l 3 , +.Xr iswprint_l 3 , +.Xr iswpunct_l 3 , +.Xr iswspace_l 3 , +.Xr iswupper_l 3 , +.Xr iswxdigit_l 3 , +.Xr towlower_l 3 , +.Xr towupper_l 3 , +.Xr wctype_l 3 , +.It In ctype.h +.Xr digittoint_l 3 , +.Xr isalnum_l 3 , +.Xr isalpha_l 3 , +.Xr isblank_l 3 , +.Xr iscntrl_l 3 , +.Xr isdigit_l 3 , +.Xr isgraph_l 3 , +.Xr ishexnumber_l 3 , +.Xr isideogram_l 3 , +.Xr islower_l 3 , +.Xr isnumber_l 3 , +.Xr isphonogram_l 3 , +.Xr isprint_l 3 , +.Xr ispunct_l 3 , +.Xr isrune_l 3 , +.Xr isspace_l 3 , +.Xr isspecial_l 3 , +.Xr isupper_l 3 , +.Xr isxdigit_l 3 , +.Xr tolower_l 3 , +.Xr toupper_l 3 +.It In inttypes.h +.Xr strtoimax_l 3 , +.Xr strtoumax_l 3 , +.Xr wcstoimax_l 3 , +.Xr wcstoumax_l 3 +.It In langinfo.h +.Xr nl_langinfo_l 3 +.It In monetary.h +.Xr strfmon_l 3 +.It In stdio.h +.Xr asprintf_l 3 , +.Xr fprintf_l 3 , +.Xr fscanf_l 3 , +.Xr printf_l 3 , +.Xr scanf_l 3 , +.Xr snprintf_l 3 , +.Xr sprintf_l 3 , +.Xr sscanf_l 3 , +.Xr vasprintf_l 3 , +.Xr vfprintf_l 3 , +.Xr vfscanf_l 3 , +.Xr vprintf_l 3 , +.Xr vscanf_l 3 , +.Xr vsnprintf_l 3 , +.Xr vsprintf_l 3 , +.Xr vsscanf_l 3 +.It In stdlib.h +.Xr atof_l 3 , +.Xr atoi_l 3 , +.Xr atol_l 3 , +.Xr atoll_l 3 , +.Xr mblen_l 3 , +.Xr mbstowcs_l 3 , +.Xr mbtowc_l 3 , +.Xr strtod_l 3 , +.Xr strtof_l 3 , +.Xr strtol_l 3 , +.Xr strtold_l 3 , +.Xr strtoll_l 3 , +.Xr strtoq_l 3 , +.Xr strtoul_l 3 , +.Xr strtoull_l 3 , +.Xr strtouq_l 3 , +.Xr wcstombs_l 3 , +.Xr wctomb_l 3 +.It In string.h +.Xr strcoll_l 3 , +.Xr strxfrm_l 3 , +.Xr strcasecmp_l 3 , +.Xr strcasestr_l 3 , +.Xr strncasecmp_l 3 +.It In time.h +.Xr strftime_l 3 +.Xr strptime_l 3 +.It In wchar.h +.Xr btowc_l 3 , +.Xr fgetwc_l 3 , +.Xr fgetws_l 3 , +.Xr fputwc_l 3 , +.Xr fputws_l 3 , +.Xr fwprintf_l 3 , +.Xr fwscanf_l 3 , +.Xr getwc_l 3 , +.Xr getwchar_l 3 , +.Xr mbrlen_l 3 , +.Xr mbrtowc_l 3 , +.Xr mbsinit_l 3 , +.Xr mbsnrtowcs_l 3 , +.Xr mbsrtowcs_l 3 , +.Xr putwc_l 3 , +.Xr putwchar_l 3 , +.Xr swprintf_l 3 , +.Xr swscanf_l 3 , +.Xr ungetwc_l 3 , +.Xr vfwprintf_l 3 , +.Xr vfwscanf_l 3 , +.Xr vswprintf_l 3 , +.Xr vswscanf_l 3 , +.Xr vwprintf_l 3 , +.Xr vwscanf_l 3 , +.Xr wcrtomb_l 3 , +.Xr wcscoll_l 3 , +.Xr wcsftime_l 3 , +.Xr wcsnrtombs_l 3 , +.Xr wcsrtombs_l 3 , +.Xr wcstod_l 3 , +.Xr wcstof_l 3 , +.Xr wcstol_l 3 , +.Xr wcstold_l 3 , +.Xr wcstoll_l 3 , +.Xr wcstoul_l 3 , +.Xr wcstoull_l 3 , +.Xr wcswidth_l 3 , +.Xr wcsxfrm_l 3 , +.Xr wctob_l 3 , +.Xr wcwidth_l 3 , +.Xr wprintf_l 3 , +.Xr wscanf_l 3 +.It In wctype.h +.Xr iswblank_l 3 , +.Xr iswhexnumber_l 3 , +.Xr iswideogram_l 3 , +.Xr iswnumber_l 3 , +.Xr iswphonogram_l 3 , +.Xr iswrune_l 3 , +.Xr iswspecial_l 3 , +.Xr nextwctype_l 3 , +.Xr towctrans_l 3 , +.Xr wctrans_l 3 +.It In xlocale.h +.Xr localeconv_l 3 +.El +.Sh STANDARDS +The functions +conform to +.St -p1003.1-2008 . +.Sh HISTORY +The xlocale APIs first appeared in Darwin 8.0. This implementation was +written by David Chisnall, under sponsorship from the FreeBSD Foundation and +first appeared in +.Fx 9.1 . Index: lib/libc/locale/mbrtowc.c =================================================================== --- lib/libc/locale/mbrtowc.c (revision 225653) +++ lib/libc/locale/mbrtowc.c (working copy) @@ -2,6 +2,11 @@ * 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: @@ -25,18 +30,24 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/locale/mbrtowc.c 129153 2004-05-12 14:09:04Z tjr $"); #include <wchar.h> #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; + 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) { - static mbstate_t mbs; - - if (ps == NULL) - ps = &mbs; - return (__mbrtowc(pwc, s, n, ps)); + return mbrtowc_l(pwc, s, n, ps, __get_locale()); } Index: lib/libc/locale/ctype.c =================================================================== --- lib/libc/locale/ctype.c (revision 0) +++ lib/libc/locale/ctype.c (revision 0) @@ -0,0 +1,31 @@ +/*- + * 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. + */ +#define _XLOCALE_INLINE +#include <ctype.h> +#include <wctype.h> +#include <xlocale.h> Index: lib/libc/stdtime/timelocal.h =================================================================== --- lib/libc/stdtime/timelocal.h (revision 225653) +++ lib/libc/stdtime/timelocal.h (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1997-2002 FreeBSD Project. * 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: @@ -23,11 +28,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdtime/timelocal.h 89736 2002-01-24 15:07:44Z phantom $ */ #ifndef _TIMELOCAL_H_ #define _TIMELOCAL_H_ +#include "xlocale_private.h" /* * Private header file for the strftime and strptime localization @@ -49,7 +55,7 @@ const char *ampm_fmt; }; -struct lc_time_T *__get_current_time_locale(void); +struct lc_time_T *__get_current_time_locale(locale_t); int __time_load_locale(const char *); #endif /* !_TIMELOCAL_H_ */ Index: lib/libc/stdtime/strptime.c =================================================================== --- lib/libc/stdtime/strptime.c (revision 225653) +++ lib/libc/stdtime/strptime.c (working copy) @@ -22,6 +22,11 @@ /* * Copyright (c) 1994 Powerdog Industries. 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: @@ -59,7 +64,7 @@ static char sccsid[] __unused = "@(#)strptime.c 0.1 (Powerdog) 94/03/27"; #endif /* !defined NOID */ #endif /* not lint */ -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdtime/strptime.c 207830 2010-05-09 22:01:35Z edwin $"); #include "namespace.h" #include <time.h> @@ -72,19 +77,20 @@ #include "libc_private.h" #include "timelocal.h" -static char * _strptime(const char *, const char *, struct tm *, int *); +static char * _strptime(const char *, const char *, struct tm *, int *, locale_t); #define asizeof(a) (sizeof (a) / sizeof ((a)[0])) static char * -_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp) +_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp, + locale_t locale) { char c; const char *ptr; int i, len; int Ealternative, Oalternative; - struct lc_time_T *tptr = __get_current_time_locale(); + struct lc_time_T *tptr = __get_current_time_locale(locale); ptr = fmt; while (*ptr != 0) { @@ -94,8 +100,8 @@ c = *ptr++; if (c != '%') { - if (isspace((unsigned char)c)) - while (*buf != 0 && isspace((unsigned char)*buf)) + if (isspace_l((unsigned char)c, locale)) + while (*buf != 0 && isspace_l((unsigned char)*buf, locale)) buf++; else if (c != *buf++) return 0; @@ -114,18 +120,18 @@ break; case '+': - buf = _strptime(buf, tptr->date_fmt, tm, GMTp); + buf = _strptime(buf, tptr->date_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'C': - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; /* XXX This will break for 3-digit centuries. */ len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -137,13 +143,13 @@ break; case 'c': - buf = _strptime(buf, tptr->c_fmt, tm, GMTp); + buf = _strptime(buf, tptr->c_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'D': - buf = _strptime(buf, "%m/%d/%y", tm, GMTp); + buf = _strptime(buf, "%m/%d/%y", tm, GMTp, locale); if (buf == 0) return 0; break; @@ -161,47 +167,47 @@ goto label; case 'F': - buf = _strptime(buf, "%Y-%m-%d", tm, GMTp); + buf = _strptime(buf, "%Y-%m-%d", tm, GMTp, locale); if (buf == 0) return 0; break; case 'R': - buf = _strptime(buf, "%H:%M", tm, GMTp); + buf = _strptime(buf, "%H:%M", tm, GMTp, locale); if (buf == 0) return 0; break; case 'r': - buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp); + buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'T': - buf = _strptime(buf, "%H:%M:%S", tm, GMTp); + buf = _strptime(buf, "%H:%M:%S", tm, GMTp, locale); if (buf == 0) return 0; break; case 'X': - buf = _strptime(buf, tptr->X_fmt, tm, GMTp); + buf = _strptime(buf, tptr->X_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'x': - buf = _strptime(buf, tptr->x_fmt, tm, GMTp); + buf = _strptime(buf, tptr->x_fmt, tm, GMTp, locale); if (buf == 0) return 0; break; case 'j': - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 3; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -214,14 +220,14 @@ case 'M': case 'S': - if (*buf == 0 || isspace((unsigned char)*buf)) + if (*buf == 0 || isspace_l((unsigned char)*buf, locale)) break; - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -237,8 +243,8 @@ tm->tm_sec = i; } - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -254,11 +260,11 @@ * XXX The %l specifier may gobble one too many * digits if used incorrectly. */ - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -271,8 +277,8 @@ tm->tm_hour = i; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -282,7 +288,7 @@ * specifiers. */ len = strlen(tptr->am); - if (strncasecmp(buf, tptr->am, len) == 0) { + if (strncasecmp_l(buf, tptr->am, len, locale) == 0) { if (tm->tm_hour > 12) return 0; if (tm->tm_hour == 12) @@ -292,7 +298,7 @@ } len = strlen(tptr->pm); - if (strncasecmp(buf, tptr->pm, len) == 0) { + if (strncasecmp_l(buf, tptr->pm, len, locale) == 0) { if (tm->tm_hour > 12) return 0; if (tm->tm_hour != 12) @@ -307,12 +313,12 @@ case 'a': for (i = 0; i < asizeof(tptr->weekday); i++) { len = strlen(tptr->weekday[i]); - if (strncasecmp(buf, tptr->weekday[i], - len) == 0) + if (strncasecmp_l(buf, tptr->weekday[i], + len, locale) == 0) break; len = strlen(tptr->wday[i]); - if (strncasecmp(buf, tptr->wday[i], - len) == 0) + if (strncasecmp_l(buf, tptr->wday[i], + len, locale) == 0) break; } if (i == asizeof(tptr->weekday)) @@ -330,11 +336,11 @@ * point to calculate a real value, so just check the * range for now. */ - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -342,13 +348,13 @@ if (i > 53) return 0; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; case 'w': - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; i = *buf - '0'; @@ -357,8 +363,8 @@ tm->tm_wday = i; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -372,11 +378,11 @@ * XXX The %e specifier may gobble one too many * digits if used incorrectly. */ - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -386,8 +392,8 @@ tm->tm_mday = i; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -398,15 +404,15 @@ if (Oalternative) { if (c == 'B') { len = strlen(tptr->alt_month[i]); - if (strncasecmp(buf, + if (strncasecmp_l(buf, tptr->alt_month[i], - len) == 0) + len, locale) == 0) break; } } else { len = strlen(tptr->month[i]); - if (strncasecmp(buf, tptr->month[i], - len) == 0) + if (strncasecmp_l(buf, tptr->month[i], + len, locale) == 0) break; } } @@ -417,8 +423,8 @@ if (i == asizeof(tptr->month) && !Oalternative) { for (i = 0; i < asizeof(tptr->month); i++) { len = strlen(tptr->mon[i]); - if (strncasecmp(buf, tptr->mon[i], - len) == 0) + if (strncasecmp_l(buf, tptr->mon[i], + len, locale) == 0) break; } } @@ -430,11 +436,11 @@ break; case 'm': - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -444,8 +450,8 @@ tm->tm_mon = i - 1; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -458,7 +464,7 @@ sverrno = errno; errno = 0; - n = strtol(buf, &cp, 10); + n = strtol_l(buf, &cp, 10, locale); if (errno == ERANGE || (long)(t = n) != n) { errno = sverrno; return 0; @@ -472,14 +478,14 @@ case 'Y': case 'y': - if (*buf == 0 || isspace((unsigned char)*buf)) + if (*buf == 0 || isspace_l((unsigned char)*buf, locale)) break; - if (!isdigit((unsigned char)*buf)) + if (!isdigit_l((unsigned char)*buf, locale)) return 0; len = (c == 'Y') ? 4 : 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + for (i = 0; len && *buf != 0 && isdigit_l((unsigned char)*buf, locale); buf++) { i *= 10; i += *buf - '0'; len--; @@ -493,8 +499,8 @@ tm->tm_year = i; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) + if (*buf != 0 && isspace_l((unsigned char)*buf, locale)) + while (*ptr != 0 && !isspace_l((unsigned char)*ptr, locale)) ptr++; break; @@ -503,7 +509,7 @@ const char *cp; char *zonestr; - for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) {/*empty*/} + for (cp = buf; *cp && isupper_l((unsigned char)*cp, locale); ++cp) {/*empty*/} if (cp - buf) { zonestr = alloca(cp - buf + 1); strncpy(zonestr, buf, cp - buf); @@ -537,7 +543,7 @@ buf++; i = 0; for (len = 4; len > 0; len--) { - if (isdigit((unsigned char)*buf)) { + if (isdigit_l((unsigned char)*buf, locale)) { i *= 10; i += *buf - '0'; buf++; @@ -557,14 +563,15 @@ char * -strptime(const char * __restrict buf, const char * __restrict fmt, - struct tm * __restrict tm) +strptime_l(const char * __restrict buf, const char * __restrict fmt, + struct tm * __restrict tm, locale_t loc) { char *ret; int gmt; + FIX_LOCALE(loc); gmt = 0; - ret = _strptime(buf, fmt, tm, &gmt); + ret = _strptime(buf, fmt, tm, &gmt, loc); if (ret && gmt) { time_t t = timegm(tm); localtime_r(&t, tm); @@ -572,3 +579,9 @@ return (ret); } +char * +strptime(const char * __restrict buf, const char * __restrict fmt, + struct tm * __restrict tm) +{ + return strptime_l(buf, fmt, tm, __get_locale()); +} Index: lib/libc/stdtime/timelocal.c =================================================================== --- lib/libc/stdtime/timelocal.c (revision 225653) +++ lib/libc/stdtime/timelocal.c (working copy) @@ -3,6 +3,11 @@ * Copyright (c) 1997 FreeBSD Inc. * 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: @@ -26,17 +31,21 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdtime/timelocal.c 116274 2003-06-13 00:14:07Z jkh $"); #include <stddef.h> #include "ldpart.h" #include "timelocal.h" -static struct lc_time_T _time_locale; -static int _time_using_locale; -static char *time_locale_buf; +struct xlocale_time { + struct xlocale_component header; + char *buffer; + struct lc_time_T locale; +}; +struct xlocale_time __xlocale_global_time; + #define LCTIME_SIZE (sizeof(struct lc_time_T) / sizeof(char *)) static const struct lc_time_T _C_time_locale = { @@ -99,19 +108,47 @@ "%I:%M:%S %p" }; +static void destruct_time(void *v) +{ + struct xlocale_time *l = v; + if (l->buffer) + free(l->buffer); + free(l); +} + +#include <stdio.h> struct lc_time_T * -__get_current_time_locale(void) +__get_current_time_locale(locale_t loc) { - return (_time_using_locale - ? &_time_locale + return (loc->using_time_locale + ? &((struct xlocale_time *)loc->components[XLC_TIME])->locale : (struct lc_time_T *)&_C_time_locale); } +static int +time_load_locale(struct xlocale_time *l, int *using_locale, const char *name) +{ + struct lc_time_T *time_locale = &l->locale; + return (__part_load_locale(name, using_locale, + &l->buffer, "LC_TIME", + LCTIME_SIZE, LCTIME_SIZE, + (const char **)time_locale)); +} int __time_load_locale(const char *name) { - return (__part_load_locale(name, &_time_using_locale, - &time_locale_buf, "LC_TIME", - LCTIME_SIZE, LCTIME_SIZE, - (const char **)&_time_locale)); + return time_load_locale(&__xlocale_global_time, + &__xlocale_global_locale.using_time_locale, name); } +extern void* __time_load(const char* name, locale_t loc) +{ + struct xlocale_time *new = calloc(sizeof(struct xlocale_time), 1); + new->header.header.destructor = destruct_time; + if (time_load_locale(new, &loc->using_time_locale, name) != _LDP_LOADED) + { + xlocale_release(new); + return NULL; + } + return new; +} + Index: lib/libc/stdtime/strftime.c =================================================================== --- lib/libc/stdtime/strftime.c (revision 225653) +++ lib/libc/stdtime/strftime.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1989 The Regents of the University of California. * 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 are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, @@ -32,7 +37,7 @@ static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdtime/strftime.c 193817 2009-06-09 09:02:58Z delphij $"); #include "tzfile.h" #include <fcntl.h> @@ -43,7 +48,7 @@ static char * _add(const char *, char *, const char *); static char * _conv(int, const char *, char *, const char *); static char * _fmt(const char *, const struct tm *, char *, const char *, - int *); + int *, locale_t); static char * _yconv(int, int, int, int, char *, const char *); extern char * tzname[]; @@ -82,29 +87,30 @@ }; size_t -strftime(char * __restrict s, size_t maxsize, const char * __restrict format, - const struct tm * __restrict t) +strftime_l(char * __restrict s, size_t maxsize, const char * __restrict format, + const struct tm * __restrict t, locale_t loc) { char * p; int warn; + FIX_LOCALE(loc); tzset(); warn = IN_NONE; - p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn); + p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn, loc); #ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) { - (void) fprintf(stderr, "\n"); + (void) fprintf_l(stderr, loc, "\n"); if (format == NULL) - (void) fprintf(stderr, "NULL strftime format "); - else (void) fprintf(stderr, "strftime format \"%s\" ", + (void) fprintf_l(stderr, loc, "NULL strftime format "); + else (void) fprintf_l(stderr, loc, "strftime format \"%s\" ", format); - (void) fprintf(stderr, "yields only two digits of years in "); + (void) fprintf_l(stderr, loc, "yields only two digits of years in "); if (warn == IN_SOME) - (void) fprintf(stderr, "some locales"); + (void) fprintf_l(stderr, loc, "some locales"); else if (warn == IN_THIS) - (void) fprintf(stderr, "the current locale"); - else (void) fprintf(stderr, "all locales"); - (void) fprintf(stderr, "\n"); + (void) fprintf_l(stderr, loc, "the current locale"); + else (void) fprintf_l(stderr, loc, "all locales"); + (void) fprintf_l(stderr, loc, "\n"); } #endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */ if (p == s + maxsize) @@ -113,16 +119,24 @@ return p - s; } +size_t +strftime(char * __restrict s, size_t maxsize, const char * __restrict format, + const struct tm * __restrict t) +{ + return strftime_l(s, maxsize, format, t, __get_locale()); +} + static char * -_fmt(format, t, pt, ptlim, warnp) +_fmt(format, t, pt, ptlim, warnp, loc) const char * format; const struct tm * const t; char * pt; const char * const ptlim; int * warnp; +locale_t loc; { int Ealternative, Oalternative, PadIndex; - struct lc_time_T *tptr = __get_current_time_locale(); + struct lc_time_T *tptr = __get_current_time_locale(loc); for ( ; *format; ++format) { if (*format == '%') { @@ -175,7 +189,7 @@ { int warn2 = IN_SOME; - pt = _fmt(tptr->c_fmt, t, pt, ptlim, &warn2); + pt = _fmt(tptr->c_fmt, t, pt, ptlim, &warn2, loc); if (warn2 == IN_ALL) warn2 = IN_THIS; if (warn2 > *warnp) @@ -183,7 +197,7 @@ } continue; case 'D': - pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp); + pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp, loc); continue; case 'd': pt = _conv(t->tm_mday, fmt_padding[PAD_FMT_DAYOFMONTH][PadIndex], @@ -216,7 +230,7 @@ fmt_padding[PAD_FMT_SDAYOFMONTH][PadIndex], pt, ptlim); continue; case 'F': - pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp); + pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp, loc); continue; case 'H': pt = _conv(t->tm_hour, fmt_padding[PAD_FMT_HMS][PadIndex], @@ -285,11 +299,11 @@ pt, ptlim); continue; case 'R': - pt = _fmt("%H:%M", t, pt, ptlim, warnp); + pt = _fmt("%H:%M", t, pt, ptlim, warnp, loc); continue; case 'r': pt = _fmt(tptr->ampm_fmt, t, pt, ptlim, - warnp); + warnp, loc); continue; case 'S': pt = _conv(t->tm_sec, fmt_padding[PAD_FMT_HMS][PadIndex], @@ -313,7 +327,7 @@ } continue; case 'T': - pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp); + pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp, loc); continue; case 't': pt = _add("\t", pt, ptlim); @@ -428,7 +442,7 @@ ** "date as dd-bbb-YYYY" ** (ado, 1993-05-24) */ - pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp); + pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp, loc); continue; case 'W': pt = _conv((t->tm_yday + DAYSPERWEEK - @@ -441,13 +455,13 @@ pt = _conv(t->tm_wday, "%d", pt, ptlim); continue; case 'X': - pt = _fmt(tptr->X_fmt, t, pt, ptlim, warnp); + pt = _fmt(tptr->X_fmt, t, pt, ptlim, warnp, loc); continue; case 'x': { int warn2 = IN_SOME; - pt = _fmt(tptr->x_fmt, t, pt, ptlim, &warn2); + pt = _fmt(tptr->x_fmt, t, pt, ptlim, &warn2, loc); if (warn2 == IN_ALL) warn2 = IN_THIS; if (warn2 > *warnp) @@ -534,7 +548,7 @@ continue; case '+': pt = _fmt(tptr->date_fmt, t, pt, ptlim, - warnp); + warnp, loc); continue; case '-': if (PadIndex != PAD_DEFAULT) Index: lib/libc/gen/glob.c =================================================================== --- lib/libc/gen/glob.c (revision 225653) +++ lib/libc/gen/glob.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Guido van Rossum. * + * 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: @@ -34,7 +39,7 @@ static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/gen/glob.c 207981 2010-05-12 17:44:00Z gordon $"); /* * glob(3) -- a superset of the one defined in POSIX 1003.2. @@ -751,6 +756,8 @@ { int ok, negate_range; Char c, k; + struct xlocale_collate *table = + (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; while (pat < patend) { c = *pat++; @@ -775,10 +782,10 @@ ++pat; while (((c = *pat++) & M_MASK) != M_END) if ((*pat & M_MASK) == M_RNG) { - if (__collate_load_error ? + if (table->__collate_load_error ? CHAR(c) <= CHAR(k) && CHAR(k) <= CHAR(pat[1]) : - __collate_range_cmp(CHAR(c), CHAR(k)) <= 0 - && __collate_range_cmp(CHAR(k), CHAR(pat[1])) <= 0 + __collate_range_cmp(table, CHAR(c), CHAR(k)) <= 0 + && __collate_range_cmp(table, CHAR(k), CHAR(pat[1])) <= 0 ) ok = 1; pat += 2; Index: lib/libc/gen/fnmatch.c =================================================================== --- lib/libc/gen/fnmatch.c (revision 225653) +++ lib/libc/gen/fnmatch.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Guido van Rossum. * + * 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: @@ -34,7 +39,7 @@ static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/gen/fnmatch.c 206711 2010-04-16 22:29:24Z jilles $"); /* * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. @@ -222,6 +227,8 @@ wchar_t c, c2; size_t pclen; const char *origpat; + struct xlocale_collate *table = + (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; /* * A bracket expression starting with an unquoted circumflex @@ -276,10 +283,10 @@ if (flags & FNM_CASEFOLD) c2 = towlower(c2); - if (__collate_load_error ? + if (table->__collate_load_error ? c <= test && test <= c2 : - __collate_range_cmp(c, test) <= 0 - && __collate_range_cmp(test, c2) <= 0 + __collate_range_cmp(table, c, test) <= 0 + && __collate_range_cmp(table, test, c2) <= 0 ) ok = 1; } else if (c == test) Index: lib/libc/regex/regcomp.c =================================================================== --- lib/libc/regex/regcomp.c (revision 225653) +++ lib/libc/regex/regcomp.c (working copy) @@ -3,9 +3,19 @@ * Copyright (c) 1992, 1993, 1994 * The Regents of the University of California. 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. + * * This code is derived from software contributed to Berkeley by * Henry Spencer. * + * 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: @@ -37,7 +47,7 @@ static char sccsid[] = "@(#)regcomp.c 8.5 (Berkeley) 3/20/94"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/regex/regcomp.c 170528 2007-06-11 03:05:54Z delphij $"); #include <sys/types.h> #include <stdio.h> @@ -730,6 +740,8 @@ char c; wint_t start, finish; wint_t i; + struct xlocale_collate *table = + (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; /* classify what we've got */ switch ((MORE()) ? PEEK() : '\0') { @@ -778,14 +790,14 @@ if (start == finish) CHadd(p, cs, start); else { - if (__collate_load_error) { + if (table->__collate_load_error) { (void)REQUIRE((uch)start <= (uch)finish, REG_ERANGE); CHaddrange(p, cs, start, finish); } else { - (void)REQUIRE(__collate_range_cmp(start, finish) <= 0, REG_ERANGE); + (void)REQUIRE(__collate_range_cmp(table, start, finish) <= 0, REG_ERANGE); for (i = 0; i <= UCHAR_MAX; i++) { - if ( __collate_range_cmp(start, i) <= 0 - && __collate_range_cmp(i, finish) <= 0 + if ( __collate_range_cmp(table, start, i) <= 0 + && __collate_range_cmp(table, i, finish) <= 0 ) CHadd(p, cs, i); } Index: lib/libc/Makefile =================================================================== --- lib/libc/Makefile (revision 225653) +++ lib/libc/Makefile (working copy) @@ -1,8 +1,11 @@ # @(#)Makefile 8.2 (Berkeley) 2/3/94 -# $FreeBSD$ +# $FreeBSD: head/lib/libc/Makefile 219019 2011-02-25 00:04:39Z gabor $ SHLIBDIR?= /lib +DEBUG_CFLAGS+=-g +CFLAGS+=-g + .include <bsd.own.mk> # Pick the current architecture directory for libc. In general, this is @@ -36,6 +39,7 @@ CFLAGS+=${CANCELPOINTS_CFLAGS} .endif + # # Only link with static libgcc.a (no libgcc_eh.a). # Index: lib/libc/gdtoa/machdep_ldisd.c =================================================================== --- lib/libc/gdtoa/machdep_ldisd.c (revision 225653) +++ lib/libc/gdtoa/machdep_ldisd.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG> * 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: @@ -31,13 +36,13 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/gdtoa/machdep_ldisd.c 112163 2003-03-12 20:30:00Z das $"); #include "gdtoaimp.h" +#undef strtold_l long double -strtold(const char * __restrict s, char ** __restrict sp) +strtold_l(const char * __restrict s, char ** __restrict sp, locale_t locale) { - - return strtod(s, sp); + return __strtod_l(s, sp, locale); } Index: lib/libc/gdtoa/machdep_ldisx.c =================================================================== --- lib/libc/gdtoa/machdep_ldisx.c (revision 225653) +++ lib/libc/gdtoa/machdep_ldisx.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG> * 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: @@ -31,17 +36,18 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/gdtoa/machdep_ldisx.c 174204 2007-12-03 07:17:33Z das $"); #include <float.h> #include "gdtoaimp.h" long double -strtold(const char * __restrict s, char ** __restrict sp) +strtold_l(const char * __restrict s, char ** __restrict sp, locale_t locale) { long double result; + FIX_LOCALE(locale); - strtorx(s, sp, FLT_ROUNDS, &result); + strtorx_l(s, sp, FLT_ROUNDS, &result, locale); return result; } Index: lib/libc/gdtoa/machdep_ldisQ.c =================================================================== --- lib/libc/gdtoa/machdep_ldisQ.c (revision 225653) +++ lib/libc/gdtoa/machdep_ldisQ.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG> * 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: @@ -31,17 +36,17 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/gdtoa/machdep_ldisQ.c 174204 2007-12-03 07:17:33Z das $"); #include <float.h> #include "gdtoaimp.h" long double -strtold(const char * __restrict s, char ** __restrict sp) +strtold_l(const char * __restrict s, char ** __restrict sp, locale_t locale) { long double result; - strtorQ(s, sp, FLT_ROUNDS, &result); + strtorQ_l(s, sp, FLT_ROUNDS, &result, locale); return result; } Index: lib/libc/string/strcasecmp.c =================================================================== --- lib/libc/string/strcasecmp.c (revision 225653) +++ lib/libc/string/strcasecmp.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 1987, 1993 * The Regents of the University of California. 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: @@ -31,40 +36,54 @@ static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/strcasecmp.c 188080 2009-02-03 17:58:20Z danger $"); #include <strings.h> #include <ctype.h> +#include "xlocale_private.h" typedef unsigned char u_char; int -strcasecmp(const char *s1, const char *s2) +strcasecmp_l(const char *s1, const char *s2, locale_t locale) { const u_char *us1 = (const u_char *)s1, *us2 = (const u_char *)s2; + FIX_LOCALE(locale); - while (tolower(*us1) == tolower(*us2++)) + while (tolower_l(*us1, locale) == tolower_l(*us2++, locale)) if (*us1++ == '\0') return (0); - return (tolower(*us1) - tolower(*--us2)); + return (tolower_l(*us1, locale) - tolower_l(*--us2, locale)); } +int +strcasecmp(const char *s1, const char *s2) +{ + return strcasecmp_l(s1, s2, __get_locale()); +} int -strncasecmp(const char *s1, const char *s2, size_t n) +strncasecmp_l(const char *s1, const char *s2, size_t n, locale_t locale) { + FIX_LOCALE(locale); if (n != 0) { const u_char *us1 = (const u_char *)s1, *us2 = (const u_char *)s2; do { - if (tolower(*us1) != tolower(*us2++)) - return (tolower(*us1) - tolower(*--us2)); + if (tolower_l(*us1, locale) != tolower_l(*us2++, locale)) + return (tolower_l(*us1, locale) - tolower_l(*--us2, locale)); if (*us1++ == '\0') break; } while (--n != 0); } return (0); } + +int +strncasecmp(const char *s1, const char *s2, size_t n) +{ + return strncasecmp_l(s1, s2, n, __get_locale()); +} Index: lib/libc/string/wcscoll.c =================================================================== --- lib/libc/string/wcscoll.c (revision 225653) +++ lib/libc/string/wcscoll.c (working copy) @@ -2,6 +2,11 @@ * Copyright (c) 2002 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: @@ -25,7 +30,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcscoll.c 127998 2004-04-07 09:47:56Z tjr $"); #include <errno.h> #include <stdlib.h> @@ -41,12 +46,15 @@ * with extended character sets. */ int -wcscoll(const wchar_t *ws1, const wchar_t *ws2) +wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t locale) { char *mbs1, *mbs2; int diff, sverrno; + FIX_LOCALE(locale); + struct xlocale_collate *table = + (struct xlocale_collate*)locale->components[XLC_COLLATE]; - if (__collate_load_error || MB_CUR_MAX > 1) + if (table->__collate_load_error || MB_CUR_MAX > 1) /* * Locale has no special collating order, could not be * loaded, or has an extended character set; do a fast binary @@ -67,7 +75,7 @@ return (wcscmp(ws1, ws2)); } - diff = strcoll(mbs1, mbs2); + diff = strcoll_l(mbs1, mbs2, locale); sverrno = errno; free(mbs1); free(mbs2); @@ -76,6 +84,12 @@ return (diff); } +int +wcscoll(const wchar_t *ws1, const wchar_t *ws2) +{ + return wcscoll_l(ws1, ws2, __get_locale()); +} + static char * __mbsdup(const wchar_t *ws) { Index: lib/libc/string/wcswidth.c =================================================================== --- lib/libc/string/wcswidth.c (revision 225653) +++ lib/libc/string/wcswidth.c (working copy) @@ -10,6 +10,11 @@ * 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: @@ -36,22 +41,29 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcswidth.c 165903 2007-01-09 00:28:16Z imp $"); #include <wchar.h> +#include "xlocale_private.h" int -wcswidth(const wchar_t *pwcs, size_t n) +wcswidth_l(const wchar_t *pwcs, size_t n, locale_t locale) { wchar_t wc; int len, l; + FIX_LOCALE(locale); len = 0; while (n-- > 0 && (wc = *pwcs++) != L'\0') { - if ((l = wcwidth(wc)) < 0) + if ((l = wcwidth_l(wc, locale)) < 0) return (-1); len += l; } return (len); } +int +wcswidth(const wchar_t *pwcs, size_t n) +{ + return wcswidth_l(pwcs, n, __get_locale()); +} Index: lib/libc/string/Symbol.map =================================================================== --- lib/libc/string/Symbol.map (revision 225653) +++ lib/libc/string/Symbol.map (working copy) @@ -1,5 +1,5 @@ /* - * $FreeBSD$ + * $FreeBSD: head/lib/libc/string/Symbol.map 189361 2009-03-04 06:01:27Z das $ */ FBSD_1.0 { @@ -75,6 +75,11 @@ wmemcpy; wmemmove; wmemset; + strcasecmp_l; + strcasestr_l; + strncasecmp_l; + wcswidth_l; + wcwidth_l; }; FBSD_1.1 { Index: lib/libc/string/strcoll.c =================================================================== --- lib/libc/string/strcoll.c (revision 225653) +++ lib/libc/string/strcoll.c (working copy) @@ -3,6 +3,11 @@ * at Electronni Visti IA, Kiev, Ukraine. * 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: @@ -26,27 +31,32 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/strcoll.c 188080 2009-02-03 17:58:20Z danger $"); #include <stdlib.h> #include <string.h> #include "collate.h" +#include <stdio.h> + int -strcoll(const char *s, const char *s2) +strcoll_l(const char *s, const char *s2, locale_t locale) { int len, len2, prim, prim2, sec, sec2, ret, ret2; const char *t, *t2; char *tt, *tt2; + FIX_LOCALE(locale); + struct xlocale_collate *table = + (struct xlocale_collate*)locale->components[XLC_COLLATE]; - if (__collate_load_error) + if (table->__collate_load_error) return strcmp(s, s2); len = len2 = 1; ret = ret2 = 0; - if (__collate_substitute_nontrivial) { - t = tt = __collate_substitute(s); - t2 = tt2 = __collate_substitute(s2); + if (table->__collate_substitute_nontrivial) { + t = tt = __collate_substitute(table, s); + t2 = tt2 = __collate_substitute(table, s2); } else { tt = tt2 = NULL; t = s; @@ -55,11 +65,11 @@ while(*t && *t2) { prim = prim2 = 0; while(*t && !prim) { - __collate_lookup(t, &len, &prim, &sec); + __collate_lookup(table, t, &len, &prim, &sec); t += len; } while(*t2 && !prim2) { - __collate_lookup(t2, &len2, &prim2, &sec2); + __collate_lookup(table, t2, &len2, &prim2, &sec2); t2 += len2; } if(!prim || !prim2) @@ -83,3 +93,10 @@ return ret; } + +int +strcoll(const char *s, const char *s2) +{ + return strcoll_l(s, s2, __get_locale()); +} + Index: lib/libc/string/wcsxfrm.c =================================================================== --- lib/libc/string/wcsxfrm.c (revision 225653) +++ lib/libc/string/wcsxfrm.c (working copy) @@ -3,6 +3,11 @@ * at Electronni Visti IA, Kiev, Ukraine. * 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: @@ -29,7 +34,7 @@ #if 0 __FBSDID("FreeBSD: src/lib/libc/string/strxfrm.c,v 1.15 2002/09/06 11:24:06 tjr Exp "); #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcsxfrm.c 127998 2004-04-07 09:47:56Z tjr $"); #include <stdlib.h> #include <string.h> @@ -43,11 +48,14 @@ * the logic used. */ size_t -wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len) +wcsxfrm_l(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len, locale_t locale) { int prim, sec, l; size_t slen; char *mbsrc, *s, *ss; + FIX_LOCALE(locale); + struct xlocale_collate *table = + (struct xlocale_collate*)locale->components[XLC_COLLATE]; if (*src == L'\0') { if (len != 0) @@ -55,7 +63,7 @@ return (0); } - if (__collate_load_error || MB_CUR_MAX > 1) { + if (table->__collate_load_error || MB_CUR_MAX > 1) { slen = wcslen(src); if (len > 0) { if (slen < len) @@ -71,10 +79,10 @@ mbsrc = __mbsdup(src); slen = 0; prim = sec = 0; - ss = s = __collate_substitute(mbsrc); + ss = s = __collate_substitute(table, mbsrc); while (*s != '\0') { while (*s != '\0' && prim == 0) { - __collate_lookup(s, &l, &prim, &sec); + __collate_lookup(table, s, &l, &prim, &sec); s += l; } if (prim != 0) { @@ -93,6 +101,11 @@ return (slen); } +size_t +wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len) +{ + return wcsxfrm_l(dest, src, len, __get_locale()); +} static char * __mbsdup(const wchar_t *ws) Index: lib/libc/string/strcasestr.c =================================================================== --- lib/libc/string/strcasestr.c (revision 225653) +++ lib/libc/string/strcasestr.c (working copy) @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * 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: @@ -31,30 +36,37 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/strcasestr.c 188080 2009-02-03 17:58:20Z danger $"); #include <ctype.h> #include <string.h> +#include "xlocale_private.h" /* * Find the first occurrence of find in s, ignore case. */ char * -strcasestr(const char *s, const char *find) +strcasestr_l(const char *s, const char *find, locale_t locale) { char c, sc; size_t len; + FIX_LOCALE(locale); if ((c = *find++) != 0) { - c = tolower((unsigned char)c); + c = tolower_l((unsigned char)c, locale); len = strlen(find); do { do { if ((sc = *s++) == 0) return (NULL); - } while ((char)tolower((unsigned char)sc) != c); - } while (strncasecmp(s, find, len) != 0); + } while ((char)tolower_l((unsigned char)sc, locale) != c); + } while (strncasecmp_l(s, find, len, locale) != 0); s--; } return ((char *)s); } +char * +strcasestr(const char *s, const char *find) +{ + return strcasestr_l(s, find, __get_locale()); +} Index: lib/libc/string/strxfrm.c =================================================================== --- lib/libc/string/strxfrm.c (revision 225653) +++ lib/libc/string/strxfrm.c (working copy) @@ -3,6 +3,11 @@ * at Electronni Visti IA, Kiev, Ukraine. * 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: @@ -26,18 +31,29 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/strxfrm.c 184055 2008-10-19 09:10:44Z delphij $"); #include <stdlib.h> #include <string.h> #include "collate.h" size_t +strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len, locale_t loc); +size_t strxfrm(char * __restrict dest, const char * __restrict src, size_t len) { + return strxfrm_l(dest, src, len, __get_locale()); +} + +size_t +strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len, locale_t locale) +{ int prim, sec, l; size_t slen; char *s, *ss; + FIX_LOCALE(locale); + struct xlocale_collate *table = + (struct xlocale_collate*)locale->components[XLC_COLLATE]; if (!*src) { if (len > 0) @@ -45,15 +61,15 @@ return 0; } - if (__collate_load_error) + if (table->__collate_load_error) return strlcpy(dest, src, len); slen = 0; prim = sec = 0; - ss = s = __collate_substitute(src); + ss = s = __collate_substitute(table, src); while (*s) { while (*s && !prim) { - __collate_lookup(s, &l, &prim, &sec); + __collate_lookup(table, s, &l, &prim, &sec); s += l; } if (prim) { Index: sys/sys/cdefs.h =================================================================== --- sys/sys/cdefs.h (revision 225653) +++ sys/sys/cdefs.h (working copy) @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * @(#)cdefs.h 8.8 (Berkeley) 1/9/95 - * $FreeBSD$ + * $FreeBSD: head/sys/sys/cdefs.h 218824 2011-02-18 21:44:53Z nwhitehorn $ */ #ifndef _SYS_CDEFS_H_ @@ -249,7 +249,7 @@ #define __func__ NULL #endif -#if (defined(__INTEL_COMPILER) || (defined(__GNUC__) && __GNUC__ >= 2)) && !defined(__STRICT_ANSI__) || __STDC_VERSION__ >= 199901 +#if (defined(__INTEL_COMPILER) || (defined(__GNUC__) && __GNUC__ >= 2)) && !defined(__STRICT_ANSI__) || __STDC_VERSION__ >= 199901 || __cplusplus >= 201103L #define __LONG_LONG_SUPPORTED #endif @@ -407,7 +407,7 @@ * Embed the rcs id of a source file in the resulting library. Note that in * more recent ELF binutils, we use .ident allowing the ID to be stripped. * Usage: - * __FBSDID("$FreeBSD$"); + * __FBSDID("$FreeBSD: head/sys/sys/cdefs.h 218824 2011-02-18 21:44:53Z nwhitehorn $"); */ #ifndef __FBSDID #if !defined(lint) && !defined(STRIP_FBSDID) --Apple-Mail=_F55C7A91-4420-4E40-9517-BE01711EE0A4 Content-Disposition: attachment; filename=test.tbz Content-Type: application/octet-stream; x-unix-mode=0644; name="test.tbz" Content-Transfer-Encoding: base64 QlpoOTFBWSZTWReH/4cBZJ1/////////////////////////////////////////////4GuZfYOi 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 222222222222221SyQlKU76nWtcEta1rWta1rWta1rWta1rWta1rWta1rWta1rWta5hha1rWta3i 1rWta1KUpSlKUpSlKU/fv379KUpSlKUpSlKXyU5xSlKUpSlKUpSlKUpSlKUpSlKUpSlKfv379+/f v379+/fv379+/f9yzJSlKUtvnz58+fPptuIbbbbbbbbbbbbbm0pSlb9+/fv379+/fv0pSlLbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbc2lKUpSlKUpSlKUpSmZVF2Z+/fv3T+aVNLUpSn79KYpKUpSlK UpSlKUpSlKUpSlKUpS23YZJpppppppppppqEaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabfPnz6Kl WmmmmmnLTTS30ytppb58+fPnz58+fPnz58+sam2222222222222221pTJtttttttttttttwrbbbb ba0pSlKUpSlKUpSlKUpSlKUpSlKUpSlKUpSlKUrWpSlKUpSlKUpSlKUpSlKUpSlKUpSlKUpSlKVZ 4ha1rWta1rWta1xC1rWtSlKUpSlKUpSlKUqUUpSlKUpSlKUpU5MRy1rWta1vFrWta1rWta1rWta1 rWuxLWta1rWta1rWta1rWta3tlaWta1rcrWta1rWta1qi5pa1rWta1rWta5Fa1rWta1rWta1rWtc 01NTU1NTU1NOppa1rWta1rUpSlKUpSlKUpT9+/SlKUpSlKUpSlMAvJ9mP0Z+Qfs5/2noFJSUlJSU kNSUlJQKtMhSUkZTY26x4ypcmIG17ms3aGGGGD5Pz6E7hIuIIwZH5wWu/XJwgOg4pEg8AHDw4cOH Dhcw4cGDBgwYIo8RIBfH8rL8Dk/haRFo51zjNreRYpSlKUpSthZZZZZZJ02ZOXA4Pl9UuJjMwMKk rpSlKUpSlKUpTTFHDWgeiYHlVfHnannnnnnnnnnnnnn/PqlooQMoZ9/+NH1fKMfSa7EwB+LHqZ5W 222222222222220ZxW6NtHVGPFlw+p6ku6Z0GGW9H7LHHsfLX+5yIvZLpFd3+8W8E8cePHjlx48e PHjkpKSkoiMsoQQkqK0e+PUABjkgCj/xAbOP3QrUMmGTxEPB/ty+bBOPm/9Bb5XgWo8fzgh8B/+7 2N74q7n7AweB6PQw9f9OvkVXqpLzpIhQOwcF39t7Xdv3Ww+AfUhtZnexpo9AFNFTe60qUB4iKC94 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 --Apple-Mail=_F55C7A91-4420-4E40-9517-BE01711EE0A4--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?DCAF3E3D-B2E1-40EF-B654-23625A17C3F1>