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:
parent
18b29f3fb8
commit
0f6ef690b3
@ -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*));
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
162
include/_xlocale_ctype.h
Normal 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
|
@ -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_ */
|
||||
|
@ -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_ */
|
||||
|
@ -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
258
include/xlocale.h
Normal 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
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
159
lib/libc/locale/DESIGN.xlocale
Normal file
159
lib/libc/locale/DESIGN.xlocale
Normal 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.
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
33
lib/libc/locale/ctype.c
Normal 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>
|
78
lib/libc/locale/duplocale.3
Normal file
78
lib/libc/locale/duplocale.3
Normal 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
|
@ -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);
|
||||
}
|
||||
|
||||
|
61
lib/libc/locale/freelocale.3
Normal file
61
lib/libc/locale/freelocale.3
Normal 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 .
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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
109
lib/libc/locale/newlocale.3
Normal 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
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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 */
|
||||
};
|
||||
|
57
lib/libc/locale/querylocale.3
Normal file
57
lib/libc/locale/querylocale.3
Normal 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
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
59
lib/libc/locale/uselocale.3
Normal file
59
lib/libc/locale/uselocale.3
Normal 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
|
@ -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);
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
270
lib/libc/locale/xlocale.3
Normal 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
334
lib/libc/locale/xlocale.c
Normal 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);
|
||||
}
|
||||
|
198
lib/libc/locale/xlocale_private.h
Normal file
198
lib/libc/locale/xlocale_private.h
Normal 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
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user