aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Chisnall <theraven@FreeBSD.org>2012-03-04 15:31:13 +0000
committerDavid Chisnall <theraven@FreeBSD.org>2012-03-04 15:31:13 +0000
commita8ed63bb3d75a8057a0ed2e758964b7785106f33 (patch)
treeefbc43bd49ea1f884ea3864a768f788cee4827e7
parent2dee0268431dbcfe88ece41d5e3748e001bcb920 (diff)
downloadsrc-a8ed63bb3d75a8057a0ed2e758964b7785106f33.tar.gz
src-a8ed63bb3d75a8057a0ed2e758964b7785106f33.zip
Reapply 227753 (xlocale cleanup), plus some fixes so that it passes build
universe with gcc. Approved by: dim (mentor)
Notes
Notes: svn path=/head/; revision=232498
-rw-r--r--etc/mtree/BSD.include.dist2
-rw-r--r--include/Makefile4
-rw-r--r--include/_xlocale_ctype.h162
-rw-r--r--include/ctype.h4
-rw-r--r--include/langinfo.h4
-rw-r--r--include/locale.h47
-rw-r--r--include/runetype.h20
-rw-r--r--include/string.h4
-rw-r--r--include/time.h4
-rw-r--r--include/wchar.h4
-rw-r--r--include/wctype.h5
-rw-r--r--include/xlocale.h227
-rw-r--r--include/xlocale/Makefile8
-rw-r--r--include/xlocale/_ctype.h193
-rw-r--r--include/xlocale/_inttypes.h44
-rw-r--r--include/xlocale/_langinfo.h42
-rw-r--r--include/xlocale/_locale.h56
-rw-r--r--include/xlocale/_monetary.h45
-rw-r--r--include/xlocale/_stdio.h64
-rw-r--r--include/xlocale/_stdlib.h59
-rw-r--r--include/xlocale/_string.h61
-rw-r--r--include/xlocale/_time.h58
-rw-r--r--include/xlocale/_wchar.h133
-rw-r--r--lib/libc/locale/Symbol.map1
-rw-r--r--lib/libc/locale/setrunelocale.c31
-rw-r--r--lib/libc/locale/table.c2
-rw-r--r--lib/libc/locale/xlocale.c64
-rw-r--r--lib/libc/locale/xlocale_private.h46
-rw-r--r--sys/sys/cdefs.h13
29 files changed, 963 insertions, 444 deletions
diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist
index c841ca8fef20..788d3ae8c8b6 100644
--- a/etc/mtree/BSD.include.dist
+++ b/etc/mtree/BSD.include.dist
@@ -329,4 +329,6 @@
..
vm
..
+ xlocale
+ ..
..
diff --git a/include/Makefile b/include/Makefile
index 5fc39230bde5..e54f9cd84c4b 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -6,7 +6,7 @@
.include <bsd.own.mk>
CLEANFILES= osreldate.h version vers.c
-SUBDIR= arpa gssapi protocols rpcsvc rpc
+SUBDIR= arpa gssapi protocols rpcsvc rpc xlocale
INCS= a.out.h ar.h assert.h bitstring.h complex.h cpio.h _ctype.h ctype.h \
db.h \
dirent.h dlfcn.h elf.h elf-hints.h err.h fmtmsg.h fnmatch.h fstab.h \
@@ -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 xlocale.h _xlocale_ctype.h
+ wchar.h wctype.h wordexp.h xlocale.h
MHDRS= float.h floatingpoint.h stdarg.h
diff --git a/include/_xlocale_ctype.h b/include/_xlocale_ctype.h
deleted file mode 100644
index 1b2e21b0f1fe..000000000000
--- a/include/_xlocale_ctype.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*-
- * 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
diff --git a/include/ctype.h b/include/ctype.h
index c3f80f3b5f35..f0ca79798b79 100644
--- a/include/ctype.h
+++ b/include/ctype.h
@@ -78,6 +78,10 @@ int isphonogram(int);
int isrune(int);
int isspecial(int);
#endif
+
+#if __POSIX_VISIBLE >= 200809
+#include <xlocale/_ctype.h>
+#endif
__END_DECLS
#ifndef __cplusplus
diff --git a/include/langinfo.h b/include/langinfo.h
index 6d6b95f2cc4e..42ad832bb486 100644
--- a/include/langinfo.h
+++ b/include/langinfo.h
@@ -130,6 +130,10 @@ typedef __nl_item nl_item;
__BEGIN_DECLS
char *nl_langinfo(nl_item);
+
+#if __POSIX_VISIBLE >= 200809
+#include <xlocale/_langinfo.h>
+#endif
__END_DECLS
#endif /* !_LANGINFO_H_ */
diff --git a/include/locale.h b/include/locale.h
index 8df0a6a8882b..0edc3eab716d 100644
--- a/include/locale.h
+++ b/include/locale.h
@@ -77,54 +77,11 @@ struct lconv {
__BEGIN_DECLS
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);
-
+#include <xlocale/_locale.h>
+#endif
__END_DECLS
-#endif /* __POSIX_VISIBLE >= 200809 */
-
#endif /* _LOCALE_H_ */
diff --git a/include/runetype.h b/include/runetype.h
index c33ea2b6904f..972242a6016f 100644
--- a/include/runetype.h
+++ b/include/runetype.h
@@ -85,11 +85,21 @@ typedef struct {
#define _RUNE_MAGIC_1 "RuneMagi" /* Indicates version 0 of RuneLocale */
__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);
+extern const _RuneLocale *_CurrentRuneLocale;
+#if defined(__NO_TLS) || defined(__RUNETYPE_INTERNAL)
+extern const _RuneLocale *__getCurrentRuneLocale(void);
+#else
+extern _Thread_local const _RuneLocale *_ThreadRuneLocale;
+static inline const _RuneLocale *__getCurrentRuneLocale(void)
+{
+
+ if (_ThreadRuneLocale)
+ return _ThreadRuneLocale;
+ if (_CurrentRuneLocale)
+ return _CurrentRuneLocale;
+ return &_DefaultRuneLocale;
+}
+#endif /* __NO_TLS || __RUNETYPE_INTERNAL */
#define _CurrentRuneLocale (__getCurrentRuneLocale())
__END_DECLS
diff --git a/include/string.h b/include/string.h
index 239a76f5ec1a..074c20471910 100644
--- a/include/string.h
+++ b/include/string.h
@@ -132,6 +132,10 @@ void swab(const void * __restrict, void * __restrict, ssize_t);
#endif /* _SWAB_DECLARED */
#endif /* __BSD_VISIBLE */
+
+#if __POSIX_VISIBLE >= 200809
+#include <xlocale/_string.h>
+#endif
__END_DECLS
#endif /* _STRING_H_ */
diff --git a/include/time.h b/include/time.h
index add970e5df74..812575a86e71 100644
--- a/include/time.h
+++ b/include/time.h
@@ -183,6 +183,10 @@ void tzsetwall(void);
time_t timelocal(struct tm * const);
time_t timegm(struct tm * const);
#endif /* __BSD_VISIBLE */
+
+#if __POSIX_VISIBLE >= 200809
+#include <xlocale/_time.h>
+#endif
__END_DECLS
#endif /* !_TIME_H_ */
diff --git a/include/wchar.h b/include/wchar.h
index c641165baf9b..4e44b53633a1 100644
--- a/include/wchar.h
+++ b/include/wchar.h
@@ -224,6 +224,10 @@ wchar_t *fgetwln(FILE * __restrict, size_t * __restrict);
size_t wcslcat(wchar_t *, const wchar_t *, size_t);
size_t wcslcpy(wchar_t *, const wchar_t *, size_t);
#endif
+
+#if __POSIX_VISIBLE >= 200809
+#include <xlocale/_wchar.h>
+#endif
__END_DECLS
#endif /* !_WCHAR_H_ */
diff --git a/include/wctype.h b/include/wctype.h
index 183a2cd76534..2a2abd9c460d 100644
--- a/include/wctype.h
+++ b/include/wctype.h
@@ -87,6 +87,11 @@ wint_t iswrune(wint_t);
wint_t iswspecial(wint_t);
wint_t nextwctype(wint_t, wctype_t);
#endif
+
+#if __POSIX_VISIBLE >= 200809
+#define _XLOCALE_WCTYPES 1
+#include <xlocale/_ctype.h>
+#endif /* __POSIX_VISIBLE >= 200809 */
__END_DECLS
#ifndef __cplusplus
diff --git a/include/xlocale.h b/include/xlocale.h
index 1f27894f9c97..cdeff3edddf8 100644
--- a/include/xlocale.h
+++ b/include/xlocale.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 The FreeBSD Foundation
+ * Copyright (c) 2011, 2012 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by David Chisnall under sponsorship from
@@ -8,16 +8,16 @@
* 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.
+ * 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
+ * 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)
@@ -33,224 +33,51 @@
#define _XLOCALE_H_
#include <locale.h>
-
__BEGIN_DECLS
+#include <xlocale/_locale.h>
-/*
- * 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);
+#include <xlocale/_string.h>
#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);
+#include <xlocale/_inttypes.h>
#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
- ;
+#include <xlocale/_monetary.h>
#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))
-
+#include <xlocale/_stdlib.h>
#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);
+#include <xlocale/_time.h>
#endif
+
#ifdef _LANGINFO_H_
-char *nl_langinfo_l(nl_item, locale_t);
+#include <xlocale/_langinfo.h>
#endif
+
#ifdef _CTYPE_H_
-#include <_xlocale_ctype.h>
+#include <xlocale/_ctype.h>
#endif
+
#ifdef _WCTYPE_H_
-#define XLOCALE_WCTYPES 1
-#include <_xlocale_ctype.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);
+#include <xlocale/_stdio.h>
#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, ...);
+#include <xlocale/_wchar.h>
+#endif
-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
diff --git a/include/xlocale/Makefile b/include/xlocale/Makefile
new file mode 100644
index 000000000000..e45ddca8e84d
--- /dev/null
+++ b/include/xlocale/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+NO_OBJ=
+INCS= _ctype.h _inttypes.h _langinfo.h _locale.h _monetary.h _stdio.h\
+ _stdlib.h _string.h _time.h _wchar.h
+INCSDIR=${INCLUDEDIR}/xlocale
+
+.include <bsd.prog.mk>
diff --git a/include/xlocale/_ctype.h b/include/xlocale/_ctype.h
new file mode 100644
index 000000000000..d0e5a473d40b
--- /dev/null
+++ b/include/xlocale/_ctype.h
@@ -0,0 +1,193 @@
+/*-
+ * 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$
+ */
+
+
+#if (defined(_XLOCALE_WCTYPES) && !defined(_XLOCALE_WCTYPE_H)) || \
+ (!defined(_XLOCALE_WCTYPES) && !defined(_XLOCALE_CTYPE_H))
+
+#ifdef _XLOCALE_WCTYPES
+#define _XLOCALE_WCTYPE_H
+#else
+#define _XLOCALE_CTYPE_H
+#endif
+
+#ifndef _LOCALE_T_DEFINED
+#define _LOCALE_T_DEFINED
+typedef struct _xlocale *locale_t;
+#endif
+
+#ifndef _XLOCALE_RUN_FUNCTIONS_DEFINED
+#define _XLOCALE_RUN_FUNCTIONS_DEFINED 1
+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*);
+#endif
+
+#ifndef _XLOCALE_INLINE
+#if __GNUC__ && !__GNUC_STDC_INLINE__
+/* GNU89 inline has nonstandard semantics. */
+#define _XLOCALE_INLINE extern inline
+#else
+/* Hack to work around people who define inline away */
+#ifdef inline
+#define _XLOCALE_INLINE __inline static
+#else
+/* Define with C++ / C99 compatible semantics */
+#define _XLOCALE_INLINE inline
+#endif
+#endif
+#endif /* _XLOCALE_INLINE */
+
+#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, locale_t);\
+ _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); \
+ _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, locale_t);
+_XLOCALE_INLINE int __wcwidth_l(__ct_rune_t, locale_t);
+_XLOCALE_INLINE int towupper_l(int, locale_t);
+
+_XLOCALE_INLINE int towlower_l(int __c, locale_t __l)
+{
+ int mb_sb_limit;
+ _RuneLocale *__runes = __runes_for_locale(__l, &mb_sb_limit);
+ return (__c < 0 || __c >= _CACHED_RUNES) ? ___tolower_l(__c, __l) :
+ __runes->__maplower[__c];
+}
+_XLOCALE_INLINE int towupper_l(int __c, locale_t __l)
+{
+ int mb_sb_limit;
+ _RuneLocale *__runes = __runes_for_locale(__l, &mb_sb_limit);
+ return (__c < 0 || __c >= _CACHED_RUNES) ? ___toupper_l(__c, __l) :
+ __runes->__mapupper[__c];
+}
+_XLOCALE_INLINE int
+__wcwidth_l(__ct_rune_t _c, locale_t __l)
+{
+ unsigned int _x;
+
+ if (_c == 0)
+ return (0);
+ _x = (unsigned int)__maskrune_l(_c, _CTYPE_SWM|_CTYPE_R, __l);
+ 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 __l);
+wctype_t wctype_l(const char *property, locale_t __l);
+wint_t towctrans_l(wint_t __wc, wctrans_t desc, locale_t __l);
+wint_t nextwctype_l(wint_t __wc, wctype_t wct, locale_t __l);
+wctrans_t wctrans_l(const char *__charclass, locale_t __l);
+#undef _XLOCALE_WCTYPES
+#else
+_XLOCALE_INLINE int digittoint_l(int, locale_t);
+_XLOCALE_INLINE int tolower_l(int, locale_t);
+_XLOCALE_INLINE int toupper_l(int, locale_t);
+
+_XLOCALE_INLINE int digittoint_l(int __c, locale_t __l)
+{ return __sbmaskrune_l((__c), 0xFF, __l); }
+
+_XLOCALE_INLINE int tolower_l(int __c, locale_t __l)
+{
+ int __limit;
+ _RuneLocale *__runes = __runes_for_locale(__l, &__limit);
+ return (__c < 0 || __c >= __limit) ? __c :
+ __runes->__maplower[__c];
+}
+_XLOCALE_INLINE int toupper_l(int __c, locale_t __l)
+{
+ int __limit;
+ _RuneLocale *__runes = __runes_for_locale(__l, &__limit);
+ return (__c < 0 || __c >= __limit) ? __c :
+ __runes->__mapupper[__c];
+}
+#endif
+#endif /* (defined(_XLOCALE_WCTYPES) && !defined(_XLOCALE_WCTYPE_H)) || \
+ (!defined(_XLOCALE_WCTYPES) && !defined(_XLOCALE_CTYPE_H)) */
diff --git a/include/xlocale/_inttypes.h b/include/xlocale/_inttypes.h
new file mode 100644
index 000000000000..58e434ecf3d5
--- /dev/null
+++ b/include/xlocale/_inttypes.h
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 2011, 2012 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$
+ */
+
+
+/*
+ * Extended locale versions of the locale-aware functions from inttypes.h.
+ * Include <inttypes.h> before <xlocale.h> to expose these.
+ */
+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);
diff --git a/include/xlocale/_langinfo.h b/include/xlocale/_langinfo.h
new file mode 100644
index 000000000000..e4f8c50a27a3
--- /dev/null
+++ b/include/xlocale/_langinfo.h
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2011, 2012 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_LANGINFO_H
+#define _XLOCALE_LANGINFO_H
+
+#ifndef _LOCALE_T_DEFINED
+#define _LOCALE_T_DEFINED
+typedef struct _xlocale *locale_t;
+#endif
+
+char *nl_langinfo_l(nl_item, locale_t);
+
+#endif /* _XLOCALE_LANGINFO_H */
diff --git a/include/xlocale/_locale.h b/include/xlocale/_locale.h
new file mode 100644
index 000000000000..f8aafb8a1ba9
--- /dev/null
+++ b/include/xlocale/_locale.h
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2011, 2012 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_LOCALE_H
+#define _XLOCALE_LOCALE_H
+
+#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)
+
+#ifndef _LOCALE_T_DEFINED
+#define _LOCALE_T_DEFINED
+typedef struct _xlocale *locale_t;
+#endif
+
+locale_t duplocale(locale_t base);
+int freelocale(locale_t loc);
+locale_t newlocale(int mask, const char *locale, locale_t base);
+const char *querylocale(int mask, locale_t loc);
+locale_t uselocale(locale_t loc);
+
+#endif /* _XLOCALE_LOCALE_H */
diff --git a/include/xlocale/_monetary.h b/include/xlocale/_monetary.h
new file mode 100644
index 000000000000..3481278acf01
--- /dev/null
+++ b/include/xlocale/_monetary.h
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2011, 2012 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 _LOCALE_T_DEFINED
+#define _LOCALE_T_DEFINED
+typedef struct _xlocale *locale_t;
+#endif
+
+#if __POSIX_VISIBLE >= 200809 || defined(_XLOCALE_H_)
+#ifndef _XLOCALE_MONETARY_H
+#define _XLOCALE_MONETARY_H
+
+ssize_t strfmon_l(char *, size_t, locale_t, const char *, ...)
+ __strfmonlike(4, 5);
+
+#endif /* _XLOCALE_MONETARY_H */
+#endif /* __POSIX_VISIBLE >= 200809 || defined(_XLOCALE_H_) */
diff --git a/include/xlocale/_stdio.h b/include/xlocale/_stdio.h
new file mode 100644
index 000000000000..0aebdcf97bf8
--- /dev/null
+++ b/include/xlocale/_stdio.h
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 2011, 2012 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$
+ */
+
+int asprintf_l(char **, locale_t, const char *, ...) __printflike(3, 4);
+int dprintf_l(int, locale_t, const char * __restrict, ...)
+ __printflike(3, 4);
+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 snprintf_l(char * __restrict, size_t, locale_t,
+ const char * __restrict, ...) __printflike(4, 5);
+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 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 vdprintf_l(int, locale_t, const char * __restrict, __va_list)
+ __printflike(3, 0);
+int vasprintf_l(char **, locale_t, const char *, __va_list)
+ __printflike(3, 0);
diff --git a/include/xlocale/_stdlib.h b/include/xlocale/_stdlib.h
new file mode 100644
index 000000000000..35a2580d4157
--- /dev/null
+++ b/include/xlocale/_stdlib.h
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2011, 2012 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$
+ */
+
+/*
+ * Extended locale versions of the locale-aware functions from stdlib.h.
+ *
+ * Include <stdlib.h> before <xlocale.h> to expose these.
+ */
+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))
+
diff --git a/include/xlocale/_string.h b/include/xlocale/_string.h
new file mode 100644
index 000000000000..262728066c27
--- /dev/null
+++ b/include/xlocale/_string.h
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2011, 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LOCALE_T_DEFINED
+#define _LOCALE_T_DEFINED
+typedef struct _xlocale *locale_t;
+#endif
+
+/*
+ * This file is included from both string.h and xlocale.h. We need to expose
+ * the declarations unconditionally if we are included from xlocale.h, but only
+ * if we are in POSIX2008 mode if included from string.h.
+ */
+
+#ifndef _XLOCALE_STRING1_H
+#define _XLOCALE_STRING1_H
+
+/*
+ * POSIX2008 functions
+ */
+int strcoll_l(const char *, const char *, locale_t);
+size_t strxfrm_l(char *, const char *, size_t, locale_t);
+#endif /* _XLOCALE_STRING1_H */
+
+/*
+ * xlocale extensions
+ */
+#ifdef _XLOCALE_H_
+#ifndef _XLOCALE_STRING2_H
+#define _XLOCALE_STRING2_H
+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 /* _XLOCALE_STRING2_H */
+#endif /* _XLOCALE_H_ */
diff --git a/include/xlocale/_time.h b/include/xlocale/_time.h
new file mode 100644
index 000000000000..4493fdd449b5
--- /dev/null
+++ b/include/xlocale/_time.h
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 2011, 2012 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 _LOCALE_T_DEFINED
+#define _LOCALE_T_DEFINED
+typedef struct _xlocale *locale_t;
+#endif
+
+/*
+ * This file is included from both locale.h and xlocale.h. We need to expose
+ * the declarations unconditionally if we are included from xlocale.h, but only
+ * if we are in POSIX2008 mode if included from locale.h.
+ */
+#ifndef _XLOCALE_LOCALE1_H
+#define _XLOCALE_LOCALE1_H
+
+size_t strftime_l(char * __restrict, size_t, const char * __restrict,
+ const struct tm * __restrict, locale_t) __strftimelike(3, 0);
+
+#endif /* _XLOCALE_LOCALE1_H */
+
+#ifdef _XLOCALE_H_
+#ifndef _XLOCALE_LOCALE2_H
+#define _XLOCALE_LOCALE2_H
+
+char *strptime_l(const char * __restrict, const char * __restrict,
+ struct tm * __restrict, locale_t);
+
+#endif /* _XLOCALE_LOCALE2_H */
+#endif /* _XLOCALE_H_ */
diff --git a/include/xlocale/_wchar.h b/include/xlocale/_wchar.h
new file mode 100644
index 000000000000..6b02d05c96d2
--- /dev/null
+++ b/include/xlocale/_wchar.h
@@ -0,0 +1,133 @@
+/*-
+ * Copyright (c) 2011, 2012 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 _LOCALE_T_DEFINED
+#define _LOCALE_T_DEFINED
+typedef struct _xlocale *locale_t;
+#endif
+
+#ifndef _XLOCALE_WCHAR1_H
+#define _XLOCALE_WCHAR1_H
+int wcscasecmp_l(const wchar_t *, const wchar_t *,
+ locale_t);
+int wcsncasecmp_l(const wchar_t *, const wchar_t *, size_t,
+ locale_t);
+int wcscoll_l(const wchar_t *, const wchar_t *, locale_t);
+size_t wcsxfrm_l(wchar_t * __restrict,
+ const wchar_t * __restrict, size_t, locale_t);
+
+#endif /* _XLOCALE_WCHAR1_H */
+
+/*
+ * Only declare the non-POSIX functions if we're included from xlocale.h.
+ */
+
+#ifdef _XLOCALE_H_
+#ifndef _XLOCALE_WCHAR2_H
+#define _XLOCALE_WCHAR2_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);
+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);
+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);
+size_t wcsnrtombs_l(char * __restrict,
+ const wchar_t ** __restrict, size_t, size_t,
+ mbstate_t * __restrict, locale_t);
+
+#endif /* _XLOCALE_WCHAR_H */
+#endif /* _XLOCALE_H_ */
diff --git a/lib/libc/locale/Symbol.map b/lib/libc/locale/Symbol.map
index 01242b694f7a..a65acc24d656 100644
--- a/lib/libc/locale/Symbol.map
+++ b/lib/libc/locale/Symbol.map
@@ -194,6 +194,7 @@ FBSD_1.3 {
wcstoull_l;
wcstoumax_l;
__runes_for_locale;
+ _ThreadRuneLocale;
};
FBSDprivate_1.0 {
diff --git a/lib/libc/locale/setrunelocale.c b/lib/libc/locale/setrunelocale.c
index 61ce5d9f925c..bc04e9e4798b 100644
--- a/lib/libc/locale/setrunelocale.c
+++ b/lib/libc/locale/setrunelocale.c
@@ -38,6 +38,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#define __RUNETYPE_INTERNAL 1
+
#include <runetype.h>
#include <errno.h>
#include <limits.h>
@@ -50,6 +52,15 @@ __FBSDID("$FreeBSD$");
#include "mblocal.h"
#include "setlocale.h"
+#undef _CurrentRuneLocale
+extern _RuneLocale const *_CurrentRuneLocale;
+#ifndef __NO_TLS
+/*
+ * A cached version of the runes for this thread. Used by ctype.h
+ */
+_Thread_local const _RuneLocale *_ThreadRuneLocale;
+#endif
+
extern int __mb_sb_limit;
extern _RuneLocale *_Read_RuneMagi(FILE *);
@@ -72,7 +83,8 @@ static void destruct_ctype(void *v)
free(l->runes);
free(l);
}
-_RuneLocale *__getCurrentRuneLocale(void)
+
+const _RuneLocale *__getCurrentRuneLocale(void)
{
return XLOCALE_CTYPE(__get_locale())->runes;
}
@@ -168,9 +180,24 @@ __wrap_setrunelocale(const char *locale)
}
__mb_cur_max = __xlocale_global_ctype.__mb_cur_max;
__mb_sb_limit = __xlocale_global_ctype.__mb_sb_limit;
+ _CurrentRuneLocale = __xlocale_global_ctype.runes;
return (_LDP_LOADED);
}
-void *__ctype_load(const char *locale, locale_t unused)
+
+#ifndef __NO_TLS
+void
+__set_thread_rune_locale(locale_t loc) {
+
+ if (loc == NULL) {
+ _ThreadRuneLocale = &_DefaultRuneLocale;
+ } else {
+ _ThreadRuneLocale = XLOCALE_CTYPE(loc)->runes;
+ }
+}
+#endif
+
+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;
diff --git a/lib/libc/locale/table.c b/lib/libc/locale/table.c
index 8c876e95a124..e89d4799b394 100644
--- a/lib/libc/locale/table.c
+++ b/lib/libc/locale/table.c
@@ -251,7 +251,7 @@ const _RuneLocale _DefaultRuneLocale = {
};
#undef _CurrentRuneLocale
-_RuneLocale *_CurrentRuneLocale = (_RuneLocale*)&_DefaultRuneLocale;
+const _RuneLocale *_CurrentRuneLocale = &_DefaultRuneLocale;
_RuneLocale *
__runes_for_locale(locale_t locale, int *mb_sb_limit)
diff --git a/lib/libc/locale/xlocale.c b/lib/libc/locale/xlocale.c
index ece00766d386..e114bac74f2c 100644
--- a/lib/libc/locale/xlocale.c
+++ b/lib/libc/locale/xlocale.c
@@ -6,17 +6,18 @@
* 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.
+ * 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
+ * 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)
@@ -31,6 +32,7 @@
#include <pthread.h>
#include <stdio.h>
#include <string.h>
+#include <runetype.h>
#include "libc_private.h"
#include "xlocale_private.h"
@@ -50,6 +52,17 @@ extern struct xlocale_component __xlocale_global_messages;
*/
extern struct xlocale_component __xlocale_C_collate;
extern struct xlocale_component __xlocale_C_ctype;
+
+#ifndef __NO_TLS
+/*
+ * The locale for this thread.
+ */
+_Thread_local locale_t __thread_locale;
+#endif
+/*
+ * Flag indicating that one or more per-thread locales exist.
+ */
+int __has_thread_locale;
/*
* Private functions in setlocale.c.
*/
@@ -103,6 +116,7 @@ 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) {
@@ -110,6 +124,8 @@ static void init_key(void)
} else {
fake_tls = 1;
}
+ /* At least one per-thread locale has now been set. */
+ __has_thread_locale = 1;
__detect_path_locale();
}
@@ -118,12 +134,14 @@ 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));
}
+#ifdef __NO_TLS
locale_t
__get_locale(void)
{
@@ -131,11 +149,13 @@ __get_locale(void)
return (l ? l : &__xlocale_global_locale);
}
+#endif
static void
set_thread_locale(locale_t loc)
{
- pthread_once(&once_control, init_key);
+
+ _once(&once_control, init_key);
if (NULL != loc) {
xlocale_retain((struct xlocale_refcounted*)loc);
@@ -149,6 +169,10 @@ set_thread_locale(locale_t loc)
} else {
pthread_setspecific(locale_info_key, loc);
}
+#ifndef __NO_TLS
+ __thread_locale = loc;
+ __set_thread_rune_locale(loc);
+#endif
}
/**
@@ -159,6 +183,7 @@ 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]);
@@ -177,6 +202,7 @@ 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;
@@ -193,19 +219,23 @@ copyflags(locale_t new, locale_t old)
static int dupcomponent(int type, locale_t base, locale_t new)
{
- /* Always copy from the global locale, since it has mutable components. */
+ /* 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);
+ strncpy(new->components[type]->locale, src->locale,
+ ENCODING_LEN);
}
} else if (base->components[type]) {
new->components[type] = xlocale_retain(base->components[type]);
} else {
- /* If the component was NULL, return success - if base is a valid
- * locale then the flag indicating that this isn't present should be
- * set. If it isn't a valid locale, then we're stuck anyway. */
+ /* If the component was NULL, return success - if base is a
+ * valid locale then the flag indicating that this isn't
+ * present should be set. If it isn't a valid locale, then
+ * we're stuck anyway. */
return 1;
}
return (0 != new->components[type]);
@@ -244,9 +274,11 @@ locale_t newlocale(int mask, const char *locale, locale_t base)
if (useenv) {
realLocale = __get_locale_env(type);
}
- new->components[type] = constructors[type](realLocale, new);
+ new->components[type] =
+ constructors[type](realLocale, new);
if (new->components[type]) {
- strncpy(new->components[type]->locale, realLocale, ENCODING_LEN);
+ strncpy(new->components[type]->locale,
+ realLocale, ENCODING_LEN);
} else {
success = 0;
break;
@@ -319,7 +351,7 @@ const char *querylocale(int mask, locale_t loc)
return (NULL);
if (loc->components[type])
return (loc->components[type]->locale);
- return "C";
+ return ("C");
}
/*
diff --git a/lib/libc/locale/xlocale_private.h b/lib/libc/locale/xlocale_private.h
index 272d15ec8c83..8b4a26d4263d 100644
--- a/lib/libc/locale/xlocale_private.h
+++ b/lib/libc/locale/xlocale_private.h
@@ -8,16 +8,16 @@
* 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.
+ * 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
+ * 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)
@@ -85,14 +85,14 @@ 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. */
+ /** 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. */
+ /** 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). */
@@ -170,12 +170,38 @@ extern struct _xlocale __xlocale_global_locale;
extern struct _xlocale __xlocale_C_locale;
/**
+ * Caches the rune table in TLS for fast access.
+ */
+void __set_thread_rune_locale(locale_t loc);
+/**
+ * Flag indicating whether a per-thread locale has been set. If no per-thread
+ * locale has ever been set, then we always use the global locale.
+ */
+extern int __has_thread_locale;
+#ifndef __NO_TLS
+/**
+ * The per-thread locale. Avoids the need to use pthread lookup functions when
+ * getting the per-thread locale.
+ */
+extern _Thread_local locale_t __thread_locale;
+
+/**
* Returns the current locale for this thread, or the global locale if none is
* set. The caller does not have to free the locale. The return value from
* this call is not guaranteed to remain valid after the locale changes. As
* such, this should only be called within libc functions.
*/
+inline locale_t __get_locale(void)
+{
+
+ if (!__has_thread_locale) {
+ return (&__xlocale_global_locale);
+ }
+ return (__thread_locale ? __thread_locale : &__xlocale_global_locale);
+}
+#else
locale_t __get_locale(void);
+#endif
/**
* Two magic values are allowed for locale_t objects. NULL and -1. This
diff --git a/sys/sys/cdefs.h b/sys/sys/cdefs.h
index b80a09012bd7..076842d8ebe2 100644
--- a/sys/sys/cdefs.h
+++ b/sys/sys/cdefs.h
@@ -230,7 +230,8 @@
#define _Alignof(e) alignof(e)
#define _Noreturn [[noreturn]]
#define _Static_assert(e, s) static_assert(e, s)
-#define _Thread_local thread_local
+/* FIXME: change this to thread_local when clang in base supports it */
+#define _Thread_local __thread
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
/* Do nothing. They are language keywords. */
#else
@@ -400,12 +401,18 @@
#define __printflike(fmtarg, firstvararg)
#define __scanflike(fmtarg, firstvararg)
#define __format_arg(fmtarg)
+#define __strfmonlike(fmtarg, firstvararg)
+#define __strftimelike(fmtarg, firstvararg)
#else
#define __printflike(fmtarg, firstvararg) \
__attribute__((__format__ (__printf__, fmtarg, firstvararg)))
#define __scanflike(fmtarg, firstvararg) \
__attribute__((__format__ (__scanf__, fmtarg, firstvararg)))
#define __format_arg(fmtarg) __attribute__((__format_arg__ (fmtarg)))
+#define __strfmonlike(fmtarg, firstvararg) \
+ __attribute__((__format__ (__strfmon__, fmtarg, firstvararg)))
+#define __strftimelike(fmtarg, firstvararg) \
+ __attribute__((__format__ (__strftime__, fmtarg, firstvararg)))
#endif
/* Compiler-dependent macros that rely on FreeBSD-specific extensions. */
@@ -650,4 +657,8 @@
#define __has_builtin(x) 0
#endif
+#if defined(__mips) || defined(__powerpc64__)
+#define __NO_TLS 1
+#endif
+
#endif /* !_SYS_CDEFS_H_ */