15de42e6621b3d0131472c3f8838b7f0ccf3e8963Andrew Hsieh//===----------------------------------------------------------------------===//
25de42e6621b3d0131472c3f8838b7f0ccf3e8963Andrew Hsieh//
35de42e6621b3d0131472c3f8838b7f0ccf3e8963Andrew Hsieh//                     The LLVM Compiler Infrastructure
45de42e6621b3d0131472c3f8838b7f0ccf3e8963Andrew Hsieh//
55de42e6621b3d0131472c3f8838b7f0ccf3e8963Andrew Hsieh// This file is dual licensed under the MIT and the University of Illinois Open
65de42e6621b3d0131472c3f8838b7f0ccf3e8963Andrew Hsieh// Source Licenses. See LICENSE.TXT for details.
75de42e6621b3d0131472c3f8838b7f0ccf3e8963Andrew Hsieh//
85de42e6621b3d0131472c3f8838b7f0ccf3e8963Andrew Hsieh//===----------------------------------------------------------------------===//
9b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
10b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#ifdef __sun__
11b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
12b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#include <stdio.h>
13b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#include <stdlib.h>
14b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#include <string.h>
15b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#include <dlfcn.h>
16b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#include <locale.h>
17b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#include <limits.h>
18b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#include <assert.h>
19b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#include <sys/localedef.h>
20b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#include "xlocale.h"
21b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
22b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnerstatic _LC_locale_t *__C_locale;
23b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
24b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#define FIX_LOCALE(l) l = (l == 0) ? __C_locale : l
25b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
26b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#include "mbsnrtowcs.inc"
27b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#include "wcsnrtombs.inc"
28b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
29b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnersize_t __mb_cur_max(locale_t __l) {
30b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  FIX_LOCALE(__l);
31b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return (__l->lc_ctype->cmapp->cm_mb_cur_max);
32b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
33b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
34b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnerwint_t btowc_l(int __c, locale_t __l) {
35b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  FIX_LOCALE(__l);
36b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __l->lc_ctype->cmapp->core.user_api->btowc(__l->lc_ctype->cmapp, __c);
37b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
38b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
39b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnerint wctob_l(wint_t __c, locale_t __l) {
40b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  FIX_LOCALE(__l);
41b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __l->lc_ctype->cmapp->core.user_api->wctob(__l->lc_ctype->cmapp, __c);
42b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
43b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
44b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnersize_t wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l) {
45b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  FIX_LOCALE(__l);
46b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __l->lc_ctype->cmapp->core.user_api->wcrtomb(__l->lc_ctype->cmapp,
47b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner      __s, __wc, __ps);
48b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
49b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
50b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnersize_t mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n,
51b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner                 mbstate_t *__ps, locale_t __l) {
52b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  FIX_LOCALE(__l);
53b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __l->lc_ctype->cmapp->core.user_api->mbrtowc(__l->lc_ctype->cmapp,
54b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner      __pwc, __s, __n, __ps);
55b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
56b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
57b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnerint mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l) {
58b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  FIX_LOCALE(__l);
59b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __l->lc_ctype->cmapp->core.user_api->mbtowc(__l->lc_ctype->cmapp,
60b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner      __pwc, __pmb, __max);
61b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
62b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
63b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnersize_t mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l) {
64b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  FIX_LOCALE(__l);
65b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __l->lc_ctype->cmapp->core.user_api->mbrlen(__l->lc_ctype->cmapp, __s,
66b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner    __n, __ps);
67b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
68b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
69b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnerstruct lconv *localeconv_l(locale_t __l) {
70b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  FIX_LOCALE(__l);
71b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __l->core.user_api->localeconv(__l);
72b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
73b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
74b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnersize_t mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
75b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner                   mbstate_t *__ps, locale_t __l) {
76b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  FIX_LOCALE(__l);
77b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __l->lc_ctype->cmapp->core.user_api->mbsrtowcs(__l->lc_ctype->cmapp,
78b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner      __dest, __src, __len, __ps);
79b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
80b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
81b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnerint wcscoll_l(const wchar_t *__s1, const wchar_t *__s2, locale_t __l) {
82b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  FIX_LOCALE(__l);
83b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __l->lc_collate->core.user_api->wcscoll(__l->lc_collate,
84b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner      __s1, __s2);
85b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
86b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
87b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnerint strcoll_l(const char *__s1, const char *__s2, locale_t __l) {
88b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  FIX_LOCALE(__l);
89b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __l->lc_collate->core.user_api->strcoll(__l->lc_collate,
90b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner      __s1, __s2);
91b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
92b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
93b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnersize_t strxfrm_l(char *__s1, const char *__s2, size_t __n, locale_t __l) {
94b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  FIX_LOCALE(__l);
95b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __l->lc_collate->core.user_api->strxfrm(__l->lc_collate,
96b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner      __s1, __s2, __n);
97b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
98b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnersize_t strftime_l(char *__s, size_t __size, const char *__fmt, const struct tm
99b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner    *__tm, locale_t __l) {
100b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  FIX_LOCALE(__l);
101b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __l->lc_time->core.user_api->strftime(__l->lc_time,
102b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner      __s, __size, __fmt, __tm);
103b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
104b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
105b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnersize_t wcsxfrm_l(wchar_t *__ws1, const wchar_t *__ws2, size_t __n,
106b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner    locale_t __l) {
107b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  FIX_LOCALE(__l);
108b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __l->lc_collate->core.user_api->wcsxfrm(__l->lc_collate,
109b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner      __ws1, __ws2, __n);
110b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
111b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
112b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#define LOCALE_ISCTYPE(ctype, m) \
113b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  int is##ctype##_l(int __c, locale_t __l) { \
114b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner    if ((__c < 0) || (__c > 255)) return 0;\
115b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner    FIX_LOCALE(__l);\
116b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner    return __l->lc_ctype->mask[__c] & m;\
117b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  }\
118b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  int isw##ctype##_l(wchar_t __c, locale_t __l) { \
119b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner    FIX_LOCALE(__l);\
120b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner    return __l->lc_ctype->core.user_api->iswctype(__l->lc_ctype, __c, m);\
121b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  }
122b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
123b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' TurnerLOCALE_ISCTYPE(alnum, _ISALNUM)
124b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' TurnerLOCALE_ISCTYPE(alpha, _ISALPHA)
125b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' TurnerLOCALE_ISCTYPE(blank, _ISALPHA)
126b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' TurnerLOCALE_ISCTYPE(cntrl, _ISCNTRL)
127b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' TurnerLOCALE_ISCTYPE(digit, _ISDIGIT)
128b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' TurnerLOCALE_ISCTYPE(graph, _ISGRAPH)
129b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' TurnerLOCALE_ISCTYPE(lower, _ISLOWER)
130b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' TurnerLOCALE_ISCTYPE(print, _ISPRINT)
131b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' TurnerLOCALE_ISCTYPE(punct, _ISPUNCT)
132b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' TurnerLOCALE_ISCTYPE(space, _ISSPACE)
133b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' TurnerLOCALE_ISCTYPE(upper, _ISUPPER)
134b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' TurnerLOCALE_ISCTYPE(xdigit, _ISXDIGIT)
135b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
136b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnerint iswctype_l(wint_t __c, wctype_t __m, locale_t __l) {
137b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner    FIX_LOCALE(__l);\
138b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner    return __l->lc_ctype->core.user_api->iswctype(__l->lc_ctype, __c, __m);\
139b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
140b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
141b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnerint toupper_l(int __c, locale_t __l) {
142b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  FIX_LOCALE(__l);
143b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner    if ((__c < 0) || (__c > __l->lc_ctype->max_upper)) return __c;
144b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __l->lc_ctype->upper[__c];
145b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
146b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnerint tolower_l(int __c, locale_t __l) {
147b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  FIX_LOCALE(__l);
148b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  if ((__c < 0) || (__c > __l->lc_ctype->max_lower)) return __c;
149b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __l->lc_ctype->lower[__c];
150b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
151b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnerwint_t towupper_l(wint_t __c, locale_t __l) {
152b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  FIX_LOCALE(__l);
153b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __l->lc_ctype->core.user_api->towupper(__l->lc_ctype, __c);
154b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
155b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnerwint_t towlower_l(wint_t __c, locale_t __l) {
156b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  FIX_LOCALE(__l);
157b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __l->lc_ctype->core.user_api->towlower(__l->lc_ctype, __c);
158b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
159b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
160b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner// FIXME: This disregards the locale, which is Very Wrong
161b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#define vsnprintf_l(__s, __n, __l, __format, __va)  \
162b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner    vsnprintf(__s, __n, __format, __va)
163b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
164b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnerint sprintf_l(char *__s, locale_t __l, const char *__format, ...) {
165b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  va_list __va;
166b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  va_start(__va, __format);
167b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  int __res = vsnprintf_l(__s, SIZE_MAX, __l, __format, __va);
168b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  va_end(__va);
169b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __res;
170b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
171b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
172b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnerint snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...)
173b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner{
174b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  va_list __va;
175b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  va_start(__va, __format);
176b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  int __res = vsnprintf_l(__s, __n , __l, __format, __va);
177b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  va_end(__va);
178b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __res;
179b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
180b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
181b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnerint asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
182b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  va_list __va;
183b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  va_start(__va, __format);
184b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  // FIXME:
185b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  int __res = vasprintf(__s, __format, __va);
186b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  va_end(__va);
187b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __res;
188b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
189b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
190b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnerint sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
191b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  va_list __va;
192b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  va_start(__va, __format);
193b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  // FIXME:
194b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  int __res = vsscanf(__s, __format, __va);
195b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  va_end(__va);
196b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return __res;
197b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
198b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
199b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnerlocale_t newlocale(int mask, const char *locale, locale_t base) {
200b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
201b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  if ((locale == NULL) || (locale[0] == '\0') ||
202b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner      ((locale[0] == 'C') && (locale[1] == '\0')))
203b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  {
204b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner    return __C_locale;
205b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  }
206b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
207b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  // Solaris locales are shared libraries that contain
208b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  char *path;
209b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#ifdef __LP64
210b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  asprintf(&path, "/usr/lib/locale/%1$s/amd64/%1$s.so.3", locale);
211b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#else
212b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  asprintf(&path, "/usr/lib/locale/%1$s/%1$s.so.3", locale);
213b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#endif
214b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  void *handle = dlopen(path, RTLD_LOCAL | RTLD_NOW);
215b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  free(path);
216b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  if (!handle)
217b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner    return 0;
218b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  _LC_locale_t *(*init)() = dlsym(handle, "instantiate");
219b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  if (!init)
220b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner    return 0;
221b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  _LC_locale_t  *p = init();
222b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  if (!p)
223b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner    return 0;
224b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
225b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  if (!base)
226b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner    base = __C_locale;
227b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
228b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  locale_t ret = calloc(1, sizeof(struct _LC_locale_t));
229b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  memcpy(ret, p, sizeof (_LC_locale_t));
230b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  ret->lc_collate = (mask & LC_COLLATE_MASK) ? p->lc_collate : base->lc_collate;
231b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  ret->lc_ctype = (mask & LC_CTYPE_MASK) ? p->lc_ctype : base->lc_ctype;
232b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  ret->lc_messages = (mask & LC_MESSAGES_MASK) ? p->lc_messages : base->lc_messages;
233b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  ret->lc_monetary = (mask & LC_MONETARY_MASK) ? p->lc_monetary : base->lc_monetary;
234b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  ret->lc_time = (mask & LC_TIME_MASK) ? p->lc_time : base->lc_time;
235b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  return ret;
236b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
237b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
238b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnervoid freelocale(locale_t loc)
239b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner{
240b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  if (loc != __C_locale)
241b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner    free(loc);
242b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
243b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner
244b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner__attribute__((constructor))
245b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turnerstatic void setupCLocale(void) {
246b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  // The default initial locale is the C locale.  This is a statically
247b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  // allocated locale inside libc.  At program start, __lc_locale will point to
248b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  // this.  We need to grab a copy because it's not a public symbol.  If we had
249b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  // access to the source code for libc, then we'd just use it directly...
250b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  assert('C' == setlocale(LC_ALL, 0)[0]);
251b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner  __C_locale = __lc_locale;
252b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner}
253b9a36c36f4b257de79bd656aefa7bfde40cedb0fDavid 'Digit' Turner#endif
254