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