Implement xlocale APIs from Darwin, mainly for use by libc++. This adds a

load of _l suffixed versions of various standard library functions that use
the global locale, making them take an explicit locale parameter.  Also
adds support for per-thread locales.  This work was funded by the FreeBSD
Foundation.

Please test any code you have that uses the C standard locale functions!

Reviewed by:    das (gdtoa changes)
Approved by:    dim (mentor)
This commit is contained in:
David Chisnall 2011-11-20 14:45:42 +00:00
parent 9e134d91bf
commit 3c87aa1d3d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=227753
154 changed files with 4595 additions and 843 deletions

View File

@ -201,6 +201,7 @@ THIS SOFTWARE.
#include "namespace.h"
#include <pthread.h>
#include "un-namespace.h"
#include "xlocale_private.h"
#ifdef KR_headers
#define Char char
@ -525,11 +526,11 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
#define strtoIQ __strtoIQ
#define strtoIx __strtoIx
#define strtoIxL __strtoIxL
#define strtord __strtord
#define strtord_l __strtord_l
#define strtordd __strtordd
#define strtorf __strtorf
#define strtorQ __strtorQ
#define strtorx __strtorx
#define strtorQ_l __strtorQ_l
#define strtorx_l __strtorx_l
#define strtorxL __strtorxL
#define strtodI __strtodI
#define strtopd __strtopd
@ -634,7 +635,7 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
extern Bigint *s2b ANSI((CONST char*, int, int, ULong, int));
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,17 +645,18 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
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 *));
extern int strtopdd ANSI((CONST char *, char **, double *));
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 strtorx ANSI((CONST char *, char **, int, void *));
extern int strtorQ_l ANSI((CONST char *, char **, int, void *, locale_t));
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*));

View File

@ -82,11 +82,11 @@ sulp
#endif /*}*/
double
strtod
strtod_l
#ifdef KR_headers
(s00, se) CONST char *s00; char **se;
(s00, se, loc) CONST char *s00; char **se; locale_t loc
#else
(CONST char *s00, char **se)
(CONST char *s00, char **se, locale_t loc)
#endif
{
#ifdef Avoid_Underflow
@ -108,14 +108,14 @@ strtod
#endif
#ifdef USE_LOCALE /*{{*/
#ifdef NO_LOCALE_CACHE
char *decimalpoint = localeconv()->decimal_point;
char *decimalpoint = localeconv_l(loc)->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(loc)->decimal_point;
if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
strcpy(decimalpoint_cache, s0);
s0 = decimalpoint_cache;
@ -1074,3 +1074,14 @@ strtod
return sign ? -dval(&rv) : dval(&rv);
}
double
strtod
#ifdef KR_headers
(s00, se, loc) CONST char *s00; char **se; locale_t
#else
(CONST char *s00, char **se)
#endif
{
return strtod_l(s00, se, __get_locale());
}

View File

@ -313,12 +313,12 @@ mantbits(U *d)
}
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, loc)
CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits; locale_t loc;
#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 loc)
#endif
{
int abe, abits, asub;
@ -334,14 +334,14 @@ strtodg
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(loc)->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(loc)->decimal_point;
if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
strcpy(decimalpoint_cache, s0);
s0 = decimalpoint_cache;

View File

@ -35,9 +35,9 @@ THIS SOFTWARE.
float
#ifdef KR_headers
strtof(s, sp) CONST char *s; char **sp;
strtof_l(s, sp, loc) CONST char *s; char **sp; locale_t loc;
#else
strtof(CONST char *s, char **sp)
strtof_l(CONST char *s, char **sp, locale_t loc)
#endif
{
static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI };
@ -51,7 +51,7 @@ strtof(CONST char *s, char **sp)
#define fpi &fpi0
#endif
k = strtodg(s, sp, fpi, &exp, bits);
k = strtodg_l(s, sp, fpi, &exp, bits, loc);
switch(k & STRTOG_Retmask) {
case STRTOG_NoNumber:
case STRTOG_Zero:
@ -82,3 +82,13 @@ strtof(CONST char *s, char **sp)
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());
}

View File

@ -103,9 +103,10 @@ ULtoQ(ULong *L, ULong *bits, Long exp, int k)
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,7 @@ strtorQ(CONST char *s, char **sp, int rounding, void *L)
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;
}

View File

@ -70,9 +70,10 @@ ULtod(ULong *L, ULong *bits, Long exp, int k)
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,8 @@ strtord(CONST char *s, char **sp, int rounding, double *d)
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;
}

View File

@ -106,9 +106,10 @@ ULtox(UShort *L, ULong *bits, Long exp, int k)
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,7 @@ strtorx(CONST char *s, char **sp, int rounding, void *L)
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;
}

View File

@ -24,7 +24,7 @@ INCS= a.out.h ar.h assert.h bitstring.h complex.h cpio.h _ctype.h ctype.h \
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

162
include/_xlocale_ctype.h Normal file
View File

@ -0,0 +1,162 @@
/*-
* Copyright (c) 2011 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by David Chisnall under sponsorship from
* the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _XLOCALE_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->__mapupper[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->__mapupper[c];
}
#endif

View File

@ -79,4 +79,52 @@ struct lconv *localeconv(void);
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);
/**
* Returns an identical duplicate of the passed locale. The returned locale
* must be freed with freelocale(). The returned locale will share components
* with the original.
*/
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_ */

View File

@ -83,8 +83,14 @@ typedef struct {
} _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_ */

View File

@ -71,10 +71,11 @@ typedef struct {
#define RAND_MAX 0x7fffffff
extern int __mb_cur_max;
#define MB_CUR_MAX __mb_cur_max
__BEGIN_DECLS
extern int __mb_cur_max;
extern int ___mb_cur_max(void);
#define MB_CUR_MAX (___mb_cur_max())
void abort(void) __dead2;
int abs(int) __pure2;
int atexit(void (*)(void));

258
include/xlocale.h Normal file
View File

@ -0,0 +1,258 @@
/*-
* Copyright (c) 2011 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by David Chisnall under sponsorship from
* the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _XLOCALE_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(FILE *, locale_t);
wchar_t *
fgetws_l(wchar_t * __restrict, int, FILE * __restrict, locale_t);
wint_t fputwc_l(wchar_t, FILE *, locale_t);
int
fputws_l(const wchar_t * __restrict, FILE * __restrict, locale_t);
int
fwprintf_l(FILE * __restrict, locale_t, const wchar_t * __restrict,
...);
int
fwscanf_l(FILE * __restrict, locale_t, const wchar_t * __restrict, ...);
wint_t getwc_l(FILE *, 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, FILE *, 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, FILE *, locale_t);
int
vfwprintf_l(FILE * __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(FILE * __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, 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);
__END_DECLS
#endif

View File

@ -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:
@ -38,10 +43,10 @@ __FBSDID("$FreeBSD$");
#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;
}

View File

@ -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:
@ -34,10 +39,11 @@
__FBSDID("$FreeBSD$");
#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);
}

View File

@ -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:
@ -38,10 +43,11 @@ __FBSDID("$FreeBSD$");
#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;
}

View File

@ -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:
@ -222,6 +227,8 @@ rangematch(pattern, test, flags, newp, patmbs)
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 @@ rangematch(pattern, test, flags, newp, patmbs)
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)

View File

@ -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:
@ -751,6 +756,8 @@ match(Char *name, Char *pat, Char *patend)
{
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 @@ match(Char *name, Char *pat, Char *patend)
++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;

View File

@ -0,0 +1,159 @@
$FreeBSD$
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.

View File

@ -5,7 +5,7 @@
.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 @@ SRCS+= ascii.c big5.c btowc.c collate.c collcmp.c euc.c fix_grouping.c \
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
@ -37,7 +38,9 @@ MAN+= btowc.3 \
wcsftime.3 \
wcrtomb.3 \
wcsrtombs.3 wcstod.3 wcstol.3 wcstombs.3 wctomb.3 \
wctrans.3 wctype.3 wcwidth.3
wctrans.3 wctype.3 wcwidth.3 \
duplocale.3 freelocale.3 newlocale.3 querylocale.3 uselocale.3 xlocale.3
MAN+= big5.5 euc.5 gb18030.5 gb2312.5 gbk.5 mskanji.5 utf8.5
MLINKS+=btowc.3 wctob.3

View File

@ -101,6 +101,101 @@ FBSD_1.0 {
wcwidth;
};
FBSD_1.3 {
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;
___mb_cur_max_l;
towctrans_l;
wctrans_l;
wcsftime_l;
wcstod_l;
wcstof_l;
wcstoimax_l;
wcstol_l;
wcstold_l;
wcstoll_l;
wcstoul_l;
wcstoull_l;
wcstoumax_l;
__runes_for_locale;
};
FBSDprivate_1.0 {
_PathLocale;
__detect_path_locale;

View File

@ -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:
@ -56,17 +61,17 @@ static size_t _ascii_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
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);
}

View File

@ -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:
@ -62,15 +67,15 @@ typedef struct {
} _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);
}

View File

@ -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:
@ -32,12 +37,13 @@ __FBSDID("$FreeBSD$");
#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 @@ btowc(int c)
* 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());
}

View File

@ -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:
@ -44,24 +54,77 @@ __FBSDID("$FreeBSD$");
#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
};
struct xlocale_collate __xlocale_C_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)
{
if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) {
return &__xlocale_C_collate;
}
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 +132,6 @@ __collate_load_tables(const char *encoding)
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 +216,6 @@ __collate_load_tables(const char *encoding)
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 +251,7 @@ __collate_load_tables(const char *encoding)
}
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 +278,7 @@ __collate_substitute(const u_char *s)
}
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;

View File

@ -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:
@ -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 @@ struct __collate_st_chain_pri {
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

View File

@ -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:
@ -28,17 +33,20 @@
__FBSDID("$FreeBSD$");
#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));
}

33
lib/libc/locale/ctype.c Normal file
View File

@ -0,0 +1,33 @@
/*-
* Copyright (c) 2011 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by David Chisnall under sponsorship from
* the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#define _XLOCALE_INLINE
#include <ctype.h>
#include <wctype.h>
#include <xlocale.h>

View File

@ -0,0 +1,78 @@
.\" 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.
.\"
.\" $FreeBSD$
.\"
.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

View File

@ -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:
@ -70,7 +75,7 @@ typedef struct {
} _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 @@ _EUC_init(_RuneLocale *rl)
}
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);
}

View File

@ -0,0 +1,61 @@
.\" 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.
.\"
.\" $FreeBSD$
.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 .

View File

@ -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:
@ -39,8 +44,6 @@ __FBSDID("$FreeBSD$");
#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 @@ typedef struct {
} _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);
}

View File

@ -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:
@ -35,8 +40,6 @@ __FBSDID("$FreeBSD$");
#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 @@ typedef struct {
} _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);
}

View File

@ -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:
@ -55,15 +60,15 @@ typedef struct {
} _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);
}

View File

@ -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:
@ -36,6 +41,14 @@ __FBSDID("$FreeBSD$");
#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 @@ static const struct lc_messages_T _C_messages_locale = {
"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) == _LDP_ERROR) {
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);
}

View File

@ -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:
@ -29,6 +34,8 @@
#ifndef _LMESSAGES_H_
#define _LMESSAGES_H_
#include "xlocale_private.h"
struct lc_messages_T {
const char *yesexpr;
const char *noexpr;
@ -36,7 +43,7 @@ struct lc_messages_T {
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_ */

View File

@ -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:
@ -34,7 +39,6 @@ __FBSDID("$FreeBSD$");
#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 @@ static const struct lc_monetary_T _C_monetary_locale = {
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 @@ cnv(const char *str)
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 @@ __monetary_load_locale(const char *name)
*/
#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 @@ __monetary_load_locale(const char *name)
}
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_ERROR)
{
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);
}

View File

@ -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:
@ -28,6 +33,7 @@
#ifndef _LMONETARY_H_
#define _LMONETARY_H_
#include "xlocale_private.h"
struct lc_monetary_T {
const char *int_curr_symbol;
@ -52,8 +58,13 @@ struct lc_monetary_T {
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_ */

View File

@ -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:
@ -32,7 +37,6 @@ __FBSDID("$FreeBSD$");
#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 @@ static const struct lc_numeric_T _C_numeric_locale = {
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);
}
struct lc_numeric_T *
__get_current_numeric_locale(void)
int
__numeric_load_locale(const char *name)
{
return (_numeric_using_locale
? &_numeric_locale
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) == _LDP_ERROR)
{
xlocale_release(new);
return NULL;
}
return new;
}
struct lc_numeric_T *
__get_current_numeric_locale(locale_t loc)
{
return (loc->using_numeric_locale
? &((struct xlocale_numeric *)loc->components[XLC_NUMERIC])->locale
: (struct lc_numeric_T *)&_C_numeric_locale);
}

View File

@ -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:
@ -28,14 +33,20 @@
#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_ */

View File

@ -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 value that is not in the current locale.
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 @@ which may be altered by later calls to
.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

View File

@ -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:
@ -48,25 +53,24 @@ __FBSDID("$FreeBSD$");
* 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 @@ localeconv()
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());
}

View File

@ -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:
@ -32,19 +37,25 @@ __FBSDID("$FreeBSD$");
#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());
}

View File

@ -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:
@ -30,35 +35,45 @@
#define _MBLOCAL_H_
#include <runetype.h>
#include "xlocale_private.h"
/*
* Rune initialization function prototypes.
*/
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 *);
/*
* Conversion function pointers for current encoding.
*/
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);
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;
/*
* Rune initialization function prototypes.
*/
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_ */

View File

@ -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,12 +35,17 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
#include "mblocal.h"
size_t
mbrlen_l(const char * __restrict s, size_t n, mbstate_t * __restrict ps, locale_t locale)
{
FIX_LOCALE(locale);
if (ps == NULL)
ps = &locale->mbrlen;
return (XLOCALE_CTYPE(locale)->__mbrtowc(NULL, s, n, ps));
}
size_t
mbrlen(const char * __restrict s, size_t n, mbstate_t * __restrict ps)
{
static mbstate_t mbs;
if (ps == NULL)
ps = &mbs;
return (__mbrtowc(NULL, s, n, ps));
return mbrlen_l(s, n, ps, __get_locale());
}

View File

@ -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,13 +35,19 @@ __FBSDID("$FreeBSD$");
#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());
}

View File

@ -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,9 +35,14 @@ __FBSDID("$FreeBSD$");
#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());
}

View File

@ -1,5 +1,10 @@
/*-
* 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
@ -33,15 +38,20 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
#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 @@ __mbsnrtowcs_std(wchar_t * __restrict dst, const char ** __restrict src,
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 @@ __mbsnrtowcs_std(wchar_t * __restrict dst, const char ** __restrict src,
}
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) {

View File

@ -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:
@ -33,13 +38,18 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
#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());
}

View File

@ -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:
@ -33,13 +38,19 @@ __FBSDID("$FreeBSD$");
#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());
}

View File

@ -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:
@ -32,19 +37,24 @@ __FBSDID("$FreeBSD$");
#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());
}

View File

@ -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:
@ -60,15 +65,15 @@ typedef struct {
} _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);
}

109
lib/libc/locale/newlocale.3 Normal file
View File

@ -0,0 +1,109 @@
.\" 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.
.\"
.\" $FreeBSD$
.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

View File

@ -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:
@ -30,12 +35,15 @@ __FBSDID("$FreeBSD$");
#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 @@ nextwctype(wint_t wc, wctype_t wct)
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 @@ nextwctype(wint_t wc, wctype_t wct)
}
return (-1);
}
wint_t
nextwctype(wint_t wc, wctype_t wct)
{
return nextwctype_l(wc, wct, __get_locale());
}

View File

@ -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:
@ -41,15 +46,16 @@ __FBSDID("$FreeBSD$");
#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 @@ nl_langinfo(nl_item item)
}
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 @@ nl_langinfo(nl_item item)
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 @@ nl_langinfo(nl_item item)
* 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());
}

View File

@ -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:
@ -64,17 +69,17 @@ int __mb_cur_max = 1;
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,26 @@ 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) = _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 */
};
const struct xlocale_ctype __xlocale_C_ctype = {
{{0}, "C"},
(_RuneLocale*)&_DefaultRuneLocale,
_none_mbrtowc,
_none_mbsinit,
_none_mbsnrtowcs,
_none_wcrtomb,
_none_wcsnrtombs,
1, /* __mb_cur_max, */
256 /* __mb_sb_limit */
};

View File

@ -0,0 +1,57 @@
.\" 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.
.\"
.\" $FreeBSD$
.\"
.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

View File

@ -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:
@ -36,12 +41,15 @@ __FBSDID("$FreeBSD$");
#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 @@ ___runetype(__ct_rune_t c)
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;
}

View File

@ -95,7 +95,7 @@ static char current_locale_string[_LC_LAST * (ENCODING_LEN + 1/*"/"*/ + 1)];
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 @@ loadlocale(category)
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;
{

View File

@ -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:
@ -49,68 +54,46 @@ extern int __mb_sb_limit;
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 @@ __setrunelocale(const char *encoding)
}
(void)fclose(fp);
old__mbrtowc = __mbrtowc;
old__mbsinit = __mbsinit;
old__mbsnrtowcs = __mbsnrtowcs;
old__wcrtomb = __wcrtomb;
old__wcsnrtombs = __wcsnrtombs;
__mbrtowc = NULL;
__mbsinit = NULL;
__mbsnrtowcs = __mbsnrtowcs_std;
__wcrtomb = NULL;
__wcsnrtombs = __wcsnrtombs_std;
l->__mbrtowc = NULL;
l->__mbsinit = NULL;
l->__mbsnrtowcs = __mbsnrtowcs_std;
l->__wcrtomb = NULL;
l->__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 @@ __setrunelocale(const char *encoding)
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;
}

View File

@ -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:
@ -41,7 +46,7 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
#include "mblocal.h"
_RuneLocale _DefaultRuneLocale = {
const _RuneLocale _DefaultRuneLocale = {
_RUNE_MAGIC_1,
"NONE",
NULL,
@ -245,5 +250,14 @@ _RuneLocale _DefaultRuneLocale = {
},
};
_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;
}

View File

@ -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:
@ -36,13 +41,17 @@ __FBSDID("$FreeBSD$");
#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 @@ ___tolower(c)
return(c);
}
__ct_rune_t
___tolower(c)
__ct_rune_t c;
{
return ___tolower_l(c, __get_locale());
}

View File

@ -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:
@ -36,13 +41,17 @@ __FBSDID("$FreeBSD$");
#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)
@ -53,7 +62,9 @@ ___toupper(c)
for (lim = rr->__nranges; lim != 0; lim >>= 1) {
re = base + (lim >> 1);
if (re->__min <= c && c <= re->__max)
{
return (re->__map + c - re->__min);
}
else if (c > re->__max) {
base = re + 1;
lim--;
@ -62,3 +73,9 @@ ___toupper(c)
return(c);
}
__ct_rune_t
___toupper(c)
__ct_rune_t c;
{
return ___toupper_l(c, __get_locale());
}

View File

@ -0,0 +1,59 @@
.\" 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.
.\"
.\" $FreeBSD$
.\"
.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

View File

@ -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:
@ -55,22 +60,22 @@ typedef struct {
} _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);
}

View File

@ -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,12 +35,18 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
#include "mblocal.h"
size_t
wcrtomb_l(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps,
locale_t locale)
{
FIX_LOCALE(locale);
if (ps == NULL)
ps = &locale->wcrtomb;
return (XLOCALE_CTYPE(locale)->__wcrtomb(s, wc, ps));
}
size_t
wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
{
static mbstate_t mbs;
if (ps == NULL)
ps = &mbs;
return (__wcrtomb(s, wc, ps));
return wcrtomb_l(s, wc, ps, __get_locale());
}

View File

@ -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:
@ -32,6 +37,7 @@ __FBSDID("$FreeBSD$");
#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 @@ __FBSDID("$FreeBSD$");
* 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 @@ wcsftime(wchar_t * __restrict wcs, size_t maxsize,
const wchar_t *formatp;
size_t n, sflen;
int sverrno;
FIX_LOCALE(locale);
sformat = dst = NULL;
@ -66,13 +74,13 @@ wcsftime(wchar_t * __restrict wcs, size_t maxsize,
*/
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 @@ wcsftime(wchar_t * __restrict wcs, size_t maxsize,
}
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 @@ wcsftime(wchar_t * __restrict wcs, size_t maxsize,
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());
}

View File

@ -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:
@ -33,17 +38,23 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
#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 @@ __wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src,
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 @@ __wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src,
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 @@ __wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src,
* 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);
}

View File

@ -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:
@ -33,13 +38,19 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
#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());
}

View File

@ -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:
@ -30,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include <wchar.h>
#include <wctype.h>
#include "xlocale_private.h"
/*
* Convert a string to a double-precision number.
@ -41,17 +47,22 @@ __FBSDID("$FreeBSD$");
* 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;
double val;
char *buf, *end;
const wchar_t *wcp;
const wchar_t *wcp = nptr;
size_t len;
size_t spaces = 0;
FIX_LOCALE(locale);
while (iswspace(*nptr))
nptr++;
while (iswspace_l(*wcp, locale)) {
wcp++;
spaces++;
}
/*
* Convert the supplied numeric wide char. string to multibyte.
@ -63,9 +74,8 @@ wcstod(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr)
* duplicates a lot of strtod()'s functionality and slows down the
* most common cases.
*/
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 +83,10 @@ wcstod(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr)
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_
@ -84,11 +94,20 @@ wcstod(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr)
* where it ended, count multibyte characters to find the
* corresponding position in the wide char string.
*/
if (endptr != NULL)
if (endptr != NULL) {
/* XXX Assume each wide char is one byte. */
*endptr = (wchar_t *)nptr + (end - buf);
if (buf != end)
*endptr += spaces;
}
free(buf);
return (val);
}
double
wcstod(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr)
{
return wcstod_l(nptr, endptr, __get_locale());
}

View File

@ -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:
@ -30,12 +35,14 @@ __FBSDID("$FreeBSD$");
#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 @@ wcstof(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr)
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 @@ wcstof(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr)
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 @@ wcstof(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr)
return (val);
}
float
wcstof(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr)
{
return wcstof_l(nptr, endptr, __get_locale());
}

View File

@ -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:
@ -41,19 +46,21 @@ __FBSDID("$FreeBSD$");
#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 @@ wcstoimax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
s = nptr;
do {
c = *s++;
} while (iswspace(c));
} while (iswspace_l(c, locale));
if (c == L'-') {
neg = 1;
c = *s++;
@ -88,8 +95,8 @@ wcstoimax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
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 @@ wcstoimax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
*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());
}

View File

@ -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:
@ -35,18 +40,21 @@ __FBSDID("$FreeBSD$");
#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 @@ wcstol(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base)
s = nptr;
do {
c = *s++;
} while (iswspace(c));
} while (iswspace_l(c, locale));
if (c == '-') {
neg = 1;
c = *s++;
@ -81,8 +89,8 @@ wcstol(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base)
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 @@ wcstol(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base)
*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());
}

View File

@ -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:
@ -30,26 +35,32 @@ __FBSDID("$FreeBSD$");
#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;
long double val;
char *buf, *end;
const wchar_t *wcp;
const wchar_t *wcp = nptr;
size_t len;
size_t spaces = 0;
FIX_LOCALE(locale);
while (iswspace(*nptr))
nptr++;
while (iswspace_l(*wcp, locale)) {
wcp++;
spaces++;
}
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,14 +68,23 @@ wcstold(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr)
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)
if (endptr != NULL) {
/* XXX Assume each wide char is one byte. */
*endptr = (wchar_t *)nptr + (end - buf);
if (buf != end)
*endptr += spaces;
}
free(buf);
return (val);
}
long double
wcstold(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr)
{
return wcstold_l(nptr, endptr, __get_locale());
}

View File

@ -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:
@ -41,18 +46,21 @@ __FBSDID("$FreeBSD$");
#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 @@ wcstoll(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base)
s = nptr;
do {
c = *s++;
} while (iswspace(c));
} while (iswspace_l(c, locale));
if (c == L'-') {
neg = 1;
c = *s++;
@ -87,8 +95,8 @@ wcstoll(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base)
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 @@ wcstoll(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base)
*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());
}

View File

@ -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:
@ -33,13 +38,21 @@ __FBSDID("$FreeBSD$");
#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());
}

View File

@ -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:
@ -35,18 +40,21 @@ __FBSDID("$FreeBSD$");
#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 @@ wcstoul(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base)
s = nptr;
do {
c = *s++;
} while (iswspace(c));
} while (iswspace_l(c, locale));
if (c == L'-') {
neg = 1;
c = *s++;
@ -79,8 +87,8 @@ wcstoul(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base)
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 @@ wcstoul(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base)
*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());
}

View File

@ -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:
@ -41,19 +46,21 @@ __FBSDID("$FreeBSD$");
#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 @@ wcstoull(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
s = nptr;
do {
c = *s++;
} while (iswspace(c));
} while (iswspace_l(c, locale));
if (c == L'-') {
neg = 1;
c = *s++;
@ -86,8 +93,8 @@ wcstoull(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
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 @@ wcstoull(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
*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());
}

View File

@ -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:
@ -41,19 +46,21 @@ __FBSDID("$FreeBSD$");
#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 @@ wcstoumax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
s = nptr;
do {
c = *s++;
} while (iswspace(c));
} while (iswspace_l(c, locale));
if (c == L'-') {
neg = 1;
c = *s++;
@ -86,8 +93,8 @@ wcstoumax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
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 @@ wcstoumax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
*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());
}

View File

@ -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:
@ -33,13 +38,19 @@ __FBSDID("$FreeBSD$");
#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());
}

View File

@ -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:
@ -32,18 +37,23 @@ __FBSDID("$FreeBSD$");
#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());
}

View File

@ -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:
@ -30,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <string.h>
#include <wctype.h>
#include "xlocale_private.h"
enum {
_WCT_ERROR = 0,
@ -38,15 +44,14 @@ enum {
};
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 @@ towctrans(wint_t wc, wctrans_t desc)
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 @@ wctrans(const char *charclass)
errno = EINVAL;
return (ccls[i].trans);
}
wctrans_t
wctrans(const char *charclass)
{
return wctrans_l(charclass, 0);
}

View File

@ -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:
@ -30,17 +35,27 @@ __FBSDID("$FreeBSD$");
#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() is 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 @@ wctype(const char *property)
return (props[i].mask);
}
wctype_t wctype(const char *property)
{
return wctype_l(property, 0);
}

View File

@ -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:
@ -39,12 +44,18 @@
__FBSDID("$FreeBSD$");
#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));
}

270
lib/libc/locale/xlocale.3 Normal file
View File

@ -0,0 +1,270 @@
.\" 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.
.\"
.\" $FreeBSD$
.\"
.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 opaque 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. Each of these functions
accepts either NULL or LC_GLOBAL_LOCALE. In these functions, NULL refers to
the C locale, rather than the thread's current locale. If you wish to use the
thread's current locale, then use the unsuffixed version of the function.
.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 .

334
lib/libc/locale/xlocale.c Normal file
View File

@ -0,0 +1,334 @@
/*-
* Copyright (c) 2011 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by David Chisnall under sponsorship from
* the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#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;
/*
* And another version for the statically-allocated C locale. We only have
* components for the parts that are expected to be sensible.
*/
extern struct xlocale_component __xlocale_C_collate;
extern struct xlocale_component __xlocale_C_ctype;
/*
* 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
};
struct _xlocale __xlocale_C_locale = {
{0},
{
&__xlocale_C_collate,
&__xlocale_C_ctype,
0, 0, 0, 0
},
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;
break;
}
} else {
if (!dupcomponent(type, base, new)) {
success = 0;
break;
}
}
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)
{
int type = ffs(mask) - 1;
FIX_LOCALE(loc);
if (type >= XLC_LAST)
return (NULL);
if (loc->components[type])
return (loc->components[type]->locale);
return "C";
}
/*
* 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);
}

View File

@ -0,0 +1,198 @@
/*-
* Copyright (c) 2011 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by David Chisnall under sponsorship from
* the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _XLOCALE_PRIVATE__H_
#define _XLOCALE_PRIVATE__H_
#include <xlocale.h>
#include <locale.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <machine/atomic.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.
*/
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;
atomic_add_long(&(obj->retain_count), 1);
return (val);
}
/**
* Decrements the reference count of a reference-counted structure, freeing it
* if this is the last reference, calling its destructor if it has one.
*/
__attribute__((unused)) static void
xlocale_release(void *val)
{
struct xlocale_refcounted *obj = val;
long count = atomic_fetchadd_long(&(obj->retain_count), -1) - 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;
extern struct _xlocale __xlocale_C_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_C_locale);
case -1: return (&__xlocale_global_locale);
default: return (locale);
}
}
/**
* Replace a placeholder locale with the real global or thread-local locale_t.
*/
#define FIX_LOCALE(l) (l = get_real_locale(l))
#endif

View File

@ -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:
@ -730,6 +740,8 @@ p_b_term(struct parse *p, cset *cs)
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 @@ p_b_term(struct parse *p, cset *cs)
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);
}

View File

@ -117,6 +117,46 @@ FBSD_1.1 {
vdprintf;
};
FBSD_1.3 {
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;
};
FBSDprivate_1.0 {
_flockfile;
_flockfile_debug_stub;

View File

@ -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:
@ -35,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <stdarg.h>
#include <xlocale.h>
int
asprintf(char ** __restrict s, char const * __restrict fmt, ...)
@ -47,3 +53,15 @@ asprintf(char ** __restrict s, char const * __restrict fmt, ...)
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);
}

View File

@ -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:
@ -36,31 +41,39 @@ __FBSDID("$FreeBSD$");
#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 @@ __fgetwc(FILE *fp)
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)

View File

@ -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:
@ -33,18 +38,20 @@ __FBSDID("$FreeBSD$");
#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 @@ fgetwln(FILE * __restrict fp, size_t *lenp)
*lenp = 0;
return (NULL);
}
wchar_t *
fgetwln(FILE * __restrict fp, size_t *lenp)
{
return fgetwln_l(fp, lenp, __get_locale());
}

View File

@ -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:
@ -38,12 +43,14 @@ __FBSDID("$FreeBSD$");
#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 @@ fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp)
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 @@ fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp)
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 @@ fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp)
FUNLOCKFILE(fp);
return (NULL);
}
wchar_t *
fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp)
{
return fgetws_l(ws, n, fp, __get_locale());
}

View File

@ -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:
@ -38,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <stdarg.h>
#include "xlocale_private.h"
int
fprintf(FILE * __restrict fp, const char * __restrict fmt, ...)
@ -46,7 +52,19 @@ fprintf(FILE * __restrict fp, const char * __restrict fmt, ...)
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);
}

View File

@ -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:
@ -42,10 +47,11 @@ __FBSDID("$FreeBSD$");
* 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 @@ __fputwc(wchar_t wc, FILE *fp)
*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 @@ __fputwc(wchar_t wc, FILE *fp)
* 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());
}

View File

@ -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:
@ -39,13 +44,15 @@ __FBSDID("$FreeBSD$");
#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 @@ fputws(const wchar_t * __restrict ws, FILE * __restrict fp)
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 @@ fputws(const wchar_t * __restrict ws, FILE * __restrict fp)
FUNLOCKFILE(fp);
return (-1);
}
int
fputws(const wchar_t * __restrict ws, FILE * __restrict fp)
{
return fputws_l(ws, fp, __get_locale());
}

View File

@ -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:
@ -42,6 +47,7 @@ __FBSDID("$FreeBSD$");
#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,7 +57,21 @@ fscanf(FILE * __restrict fp, char const * __restrict fmt, ...)
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);

View File

@ -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:
@ -30,6 +35,7 @@ __FBSDID("$FreeBSD$");
#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 @@ fwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...)
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);
}

View File

@ -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:
@ -30,6 +35,7 @@ __FBSDID("$FreeBSD$");
#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 @@ fwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...)
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);
}

View File

@ -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:
@ -30,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include "namespace.h"
#include <stdio.h>
#include <wchar.h>
#include <xlocale.h>
#include "un-namespace.h"
#include "libc_private.h"
#include "local.h"
@ -46,3 +52,9 @@ getwc(FILE *fp)
return (fgetwc(fp));
}
wint_t
getwc_l(FILE *fp, locale_t locale)
{
return (fgetwc_l(fp, locale));
}

Some files were not shown because too many files have changed in this diff Show More