1 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2 // 2009, 2010 3 // Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 #include <clocale> 26 #include <cstring> 27 #include <cstdlib> // For getenv, free. 28 #include <cctype> 29 #include <cwctype> // For towupper, etc. 30 #include <locale> 31 #include <ext/concurrence.h> 32 33 namespace 34 { 35 __gnu_cxx::__mutex& 36 get_locale_mutex() 37 { 38 static __gnu_cxx::__mutex locale_mutex; 39 return locale_mutex; 40 } 41 42 using namespace std; 43 44 typedef char fake_locale_Impl[sizeof(locale::_Impl)] 45 __attribute__ ((aligned(__alignof__(locale::_Impl)))); 46 fake_locale_Impl c_locale_impl; 47 48 typedef char fake_locale[sizeof(locale)] 49 __attribute__ ((aligned(__alignof__(locale)))); 50 fake_locale c_locale; 51 52 typedef char fake_name_vec[sizeof(char*)] 53 __attribute__ ((aligned(__alignof__(char*)))); 54 fake_name_vec name_vec[6 + _GLIBCXX_NUM_CATEGORIES]; 55 56 typedef char fake_names[sizeof(char[2])] 57 __attribute__ ((aligned(__alignof__(char[2])))); 58 fake_names name_c[6 + _GLIBCXX_NUM_CATEGORIES]; 59 60 typedef char fake_facet_vec[sizeof(locale::facet*)] 61 __attribute__ ((aligned(__alignof__(locale::facet*)))); 62 fake_facet_vec facet_vec[_GLIBCXX_NUM_FACETS]; 63 64 typedef char fake_cache_vec[sizeof(locale::facet*)] 65 __attribute__ ((aligned(__alignof__(locale::facet*)))); 66 fake_cache_vec cache_vec[_GLIBCXX_NUM_FACETS]; 67 68 typedef char fake_ctype_c[sizeof(std::ctype<char>)] 69 __attribute__ ((aligned(__alignof__(std::ctype<char>)))); 70 fake_ctype_c ctype_c; 71 72 typedef char fake_collate_c[sizeof(std::collate<char>)] 73 __attribute__ ((aligned(__alignof__(std::collate<char>)))); 74 fake_collate_c collate_c; 75 76 typedef char fake_numpunct_c[sizeof(numpunct<char>)] 77 __attribute__ ((aligned(__alignof__(numpunct<char>)))); 78 fake_numpunct_c numpunct_c; 79 80 typedef char fake_num_get_c[sizeof(num_get<char>)] 81 __attribute__ ((aligned(__alignof__(num_get<char>)))); 82 fake_num_get_c num_get_c; 83 84 typedef char fake_num_put_c[sizeof(num_put<char>)] 85 __attribute__ ((aligned(__alignof__(num_put<char>)))); 86 fake_num_put_c num_put_c; 87 88 typedef char fake_codecvt_c[sizeof(codecvt<char, char, mbstate_t>)] 89 __attribute__ ((aligned(__alignof__(codecvt<char, char, mbstate_t>)))); 90 fake_codecvt_c codecvt_c; 91 92 typedef char fake_moneypunct_c[sizeof(moneypunct<char, true>)] 93 __attribute__ ((aligned(__alignof__(moneypunct<char, true>)))); 94 fake_moneypunct_c moneypunct_ct; 95 fake_moneypunct_c moneypunct_cf; 96 97 typedef char fake_money_get_c[sizeof(money_get<char>)] 98 __attribute__ ((aligned(__alignof__(money_get<char>)))); 99 fake_money_get_c money_get_c; 100 101 typedef char fake_money_put_c[sizeof(money_put<char>)] 102 __attribute__ ((aligned(__alignof__(money_put<char>)))); 103 fake_money_put_c money_put_c; 104 105 typedef char fake_timepunct_c[sizeof(__timepunct<char>)] 106 __attribute__ ((aligned(__alignof__(__timepunct<char>)))); 107 fake_timepunct_c timepunct_c; 108 109 typedef char fake_time_get_c[sizeof(time_get<char>)] 110 __attribute__ ((aligned(__alignof__(time_get<char>)))); 111 fake_time_get_c time_get_c; 112 113 typedef char fake_time_put_c[sizeof(time_put<char>)] 114 __attribute__ ((aligned(__alignof__(time_put<char>)))); 115 fake_time_put_c time_put_c; 116 117 typedef char fake_messages_c[sizeof(messages<char>)] 118 __attribute__ ((aligned(__alignof__(messages<char>)))); 119 fake_messages_c messages_c; 120 121 #ifdef _GLIBCXX_USE_WCHAR_T 122 typedef char fake_wtype_w[sizeof(std::ctype<wchar_t>)] 123 __attribute__ ((aligned(__alignof__(std::ctype<wchar_t>)))); 124 fake_wtype_w ctype_w; 125 126 typedef char fake_wollate_w[sizeof(std::collate<wchar_t>)] 127 __attribute__ ((aligned(__alignof__(std::collate<wchar_t>)))); 128 fake_wollate_w collate_w; 129 130 typedef char fake_numpunct_w[sizeof(numpunct<wchar_t>)] 131 __attribute__ ((aligned(__alignof__(numpunct<wchar_t>)))); 132 fake_numpunct_w numpunct_w; 133 134 typedef char fake_num_get_w[sizeof(num_get<wchar_t>)] 135 __attribute__ ((aligned(__alignof__(num_get<wchar_t>)))); 136 fake_num_get_w num_get_w; 137 138 typedef char fake_num_put_w[sizeof(num_put<wchar_t>)] 139 __attribute__ ((aligned(__alignof__(num_put<wchar_t>)))); 140 fake_num_put_w num_put_w; 141 142 typedef char fake_wodecvt_w[sizeof(codecvt<wchar_t, char, mbstate_t>)] 143 __attribute__ ((aligned(__alignof__(codecvt<wchar_t, char, mbstate_t>)))); 144 fake_wodecvt_w codecvt_w; 145 146 typedef char fake_moneypunct_w[sizeof(moneypunct<wchar_t, true>)] 147 __attribute__ ((aligned(__alignof__(moneypunct<wchar_t, true>)))); 148 fake_moneypunct_w moneypunct_wt; 149 fake_moneypunct_w moneypunct_wf; 150 151 typedef char fake_money_get_w[sizeof(money_get<wchar_t>)] 152 __attribute__ ((aligned(__alignof__(money_get<wchar_t>)))); 153 fake_money_get_w money_get_w; 154 155 typedef char fake_money_put_w[sizeof(money_put<wchar_t>)] 156 __attribute__ ((aligned(__alignof__(money_put<wchar_t>)))); 157 fake_money_put_w money_put_w; 158 159 typedef char fake_timepunct_w[sizeof(__timepunct<wchar_t>)] 160 __attribute__ ((aligned(__alignof__(__timepunct<wchar_t>)))); 161 fake_timepunct_w timepunct_w; 162 163 typedef char fake_time_get_w[sizeof(time_get<wchar_t>)] 164 __attribute__ ((aligned(__alignof__(time_get<wchar_t>)))); 165 fake_time_get_w time_get_w; 166 167 typedef char fake_time_put_w[sizeof(time_put<wchar_t>)] 168 __attribute__ ((aligned(__alignof__(time_put<wchar_t>)))); 169 fake_time_put_w time_put_w; 170 171 typedef char fake_messages_w[sizeof(messages<wchar_t>)] 172 __attribute__ ((aligned(__alignof__(messages<wchar_t>)))); 173 fake_messages_w messages_w; 174 #endif 175 176 // Storage for "C" locale caches. 177 typedef char fake_num_cache_c[sizeof(std::__numpunct_cache<char>)] 178 __attribute__ ((aligned(__alignof__(std::__numpunct_cache<char>)))); 179 fake_num_cache_c numpunct_cache_c; 180 181 typedef char fake_money_cache_c[sizeof(std::__moneypunct_cache<char, true>)] 182 __attribute__ ((aligned(__alignof__(std::__moneypunct_cache<char, true>)))); 183 fake_money_cache_c moneypunct_cache_ct; 184 fake_money_cache_c moneypunct_cache_cf; 185 186 typedef char fake_time_cache_c[sizeof(std::__timepunct_cache<char>)] 187 __attribute__ ((aligned(__alignof__(std::__timepunct_cache<char>)))); 188 fake_time_cache_c timepunct_cache_c; 189 190 #ifdef _GLIBCXX_USE_WCHAR_T 191 typedef char fake_num_cache_w[sizeof(std::__numpunct_cache<wchar_t>)] 192 __attribute__ ((aligned(__alignof__(std::__numpunct_cache<wchar_t>)))); 193 fake_num_cache_w numpunct_cache_w; 194 195 typedef char fake_money_cache_w[sizeof(std::__moneypunct_cache<wchar_t,true>)] 196 __attribute__ ((aligned(__alignof__(std::__moneypunct_cache<wchar_t,true>)))); 197 fake_money_cache_w moneypunct_cache_wt; 198 fake_money_cache_w moneypunct_cache_wf; 199 200 typedef char fake_time_cache_w[sizeof(std::__timepunct_cache<wchar_t>)] 201 __attribute__ ((aligned(__alignof__(std::__timepunct_cache<wchar_t>)))); 202 fake_time_cache_w timepunct_cache_w; 203 #endif 204 } // anonymous namespace 205 206 namespace std _GLIBCXX_VISIBILITY(default) 207 { 208 _GLIBCXX_BEGIN_NAMESPACE_VERSION 209 210 locale::locale() throw() : _M_impl(0) 211 { 212 _S_initialize(); 213 214 // Checked locking to optimize the common case where _S_global 215 // still points to _S_classic (locale::_S_initialize_once()): 216 // - If they are the same, just increment the reference count and 217 // we are done. This effectively constructs a C locale object 218 // identical to the static c_locale. 219 // - Otherwise, _S_global can and may be destroyed due to 220 // locale::global() call on another thread, in which case we 221 // fall back to lock protected access to both _S_global and 222 // its reference count. 223 _M_impl = _S_global; 224 if (_M_impl == _S_classic) 225 _M_impl->_M_add_reference(); 226 else 227 { 228 __gnu_cxx::__scoped_lock sentry(get_locale_mutex()); 229 _S_global->_M_add_reference(); 230 _M_impl = _S_global; 231 } 232 } 233 234 locale 235 locale::global(const locale& __other) 236 { 237 _S_initialize(); 238 _Impl* __old; 239 { 240 __gnu_cxx::__scoped_lock sentry(get_locale_mutex()); 241 __old = _S_global; 242 __other._M_impl->_M_add_reference(); 243 _S_global = __other._M_impl; 244 const string __other_name = __other.name(); 245 if (__other_name != "*") 246 setlocale(LC_ALL, __other_name.c_str()); 247 } 248 249 // Reference count sanity check: one reference removed for the 250 // subsition of __other locale, one added by return-by-value. Net 251 // difference: zero. When the returned locale object's destrutor 252 // is called, then the reference count is decremented and possibly 253 // destroyed. 254 return locale(__old); 255 } 256 257 const locale& 258 locale::classic() 259 { 260 _S_initialize(); 261 return *(new (&c_locale) locale(_S_classic)); 262 } 263 264 void 265 locale::_S_initialize_once() throw() 266 { 267 // 2 references. 268 // One reference for _S_classic, one for _S_global 269 _S_classic = new (&c_locale_impl) _Impl(2); 270 _S_global = _S_classic; 271 } 272 273 void 274 locale::_S_initialize() 275 { 276 #ifdef __GTHREADS 277 if (__gthread_active_p()) 278 __gthread_once(&_S_once, _S_initialize_once); 279 #endif 280 if (!_S_classic) 281 _S_initialize_once(); 282 } 283 284 // Definitions for static const data members of locale::_Impl 285 const locale::id* const 286 locale::_Impl::_S_id_ctype[] = 287 { 288 &std::ctype<char>::id, 289 &codecvt<char, char, mbstate_t>::id, 290 #ifdef _GLIBCXX_USE_WCHAR_T 291 &std::ctype<wchar_t>::id, 292 &codecvt<wchar_t, char, mbstate_t>::id, 293 #endif 294 0 295 }; 296 297 const locale::id* const 298 locale::_Impl::_S_id_numeric[] = 299 { 300 &num_get<char>::id, 301 &num_put<char>::id, 302 &numpunct<char>::id, 303 #ifdef _GLIBCXX_USE_WCHAR_T 304 &num_get<wchar_t>::id, 305 &num_put<wchar_t>::id, 306 &numpunct<wchar_t>::id, 307 #endif 308 0 309 }; 310 311 const locale::id* const 312 locale::_Impl::_S_id_collate[] = 313 { 314 &std::collate<char>::id, 315 #ifdef _GLIBCXX_USE_WCHAR_T 316 &std::collate<wchar_t>::id, 317 #endif 318 0 319 }; 320 321 const locale::id* const 322 locale::_Impl::_S_id_time[] = 323 { 324 &__timepunct<char>::id, 325 &time_get<char>::id, 326 &time_put<char>::id, 327 #ifdef _GLIBCXX_USE_WCHAR_T 328 &__timepunct<wchar_t>::id, 329 &time_get<wchar_t>::id, 330 &time_put<wchar_t>::id, 331 #endif 332 0 333 }; 334 335 const locale::id* const 336 locale::_Impl::_S_id_monetary[] = 337 { 338 &money_get<char>::id, 339 &money_put<char>::id, 340 &moneypunct<char, false>::id, 341 &moneypunct<char, true >::id, 342 #ifdef _GLIBCXX_USE_WCHAR_T 343 &money_get<wchar_t>::id, 344 &money_put<wchar_t>::id, 345 &moneypunct<wchar_t, false>::id, 346 &moneypunct<wchar_t, true >::id, 347 #endif 348 0 349 }; 350 351 const locale::id* const 352 locale::_Impl::_S_id_messages[] = 353 { 354 &std::messages<char>::id, 355 #ifdef _GLIBCXX_USE_WCHAR_T 356 &std::messages<wchar_t>::id, 357 #endif 358 0 359 }; 360 361 const locale::id* const* const 362 locale::_Impl::_S_facet_categories[] = 363 { 364 // Order must match the decl order in class locale. 365 locale::_Impl::_S_id_ctype, 366 locale::_Impl::_S_id_numeric, 367 locale::_Impl::_S_id_collate, 368 locale::_Impl::_S_id_time, 369 locale::_Impl::_S_id_monetary, 370 locale::_Impl::_S_id_messages, 371 0 372 }; 373 374 // Construct "C" _Impl. 375 locale::_Impl:: 376 _Impl(size_t __refs) throw() 377 : _M_refcount(__refs), _M_facets(0), _M_facets_size(_GLIBCXX_NUM_FACETS), 378 _M_caches(0), _M_names(0) 379 { 380 _M_facets = new (&facet_vec) const facet*[_M_facets_size]; 381 _M_caches = new (&cache_vec) const facet*[_M_facets_size]; 382 for (size_t __i = 0; __i < _M_facets_size; ++__i) 383 _M_facets[__i] = _M_caches[__i] = 0; 384 385 // Name the categories. 386 _M_names = new (&name_vec) char*[_S_categories_size]; 387 _M_names[0] = new (&name_c[0]) char[2]; 388 std::memcpy(_M_names[0], locale::facet::_S_get_c_name(), 2); 389 for (size_t __j = 1; __j < _S_categories_size; ++__j) 390 _M_names[__j] = 0; 391 392 // This is needed as presently the C++ version of "C" locales 393 // != data in the underlying locale model for __timepunct, 394 // numpunct, and moneypunct. Also, the "C" locales must be 395 // constructed in a way such that they are pre-allocated. 396 // NB: Set locale::facets(ref) count to one so that each individual 397 // facet is not destroyed when the locale (and thus locale::_Impl) is 398 // destroyed. 399 _M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1)); 400 _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1)); 401 402 typedef __numpunct_cache<char> num_cache_c; 403 num_cache_c* __npc = new (&numpunct_cache_c) num_cache_c(2); 404 _M_init_facet(new (&numpunct_c) numpunct<char>(__npc, 1)); 405 406 _M_init_facet(new (&num_get_c) num_get<char>(1)); 407 _M_init_facet(new (&num_put_c) num_put<char>(1)); 408 _M_init_facet(new (&collate_c) std::collate<char>(1)); 409 410 typedef __moneypunct_cache<char, false> money_cache_cf; 411 typedef __moneypunct_cache<char, true> money_cache_ct; 412 money_cache_cf* __mpcf = new (&moneypunct_cache_cf) money_cache_cf(2); 413 _M_init_facet(new (&moneypunct_cf) moneypunct<char, false>(__mpcf, 1)); 414 money_cache_ct* __mpct = new (&moneypunct_cache_ct) money_cache_ct(2); 415 _M_init_facet(new (&moneypunct_ct) moneypunct<char, true>(__mpct, 1)); 416 417 _M_init_facet(new (&money_get_c) money_get<char>(1)); 418 _M_init_facet(new (&money_put_c) money_put<char>(1)); 419 420 typedef __timepunct_cache<char> time_cache_c; 421 time_cache_c* __tpc = new (&timepunct_cache_c) time_cache_c(2); 422 _M_init_facet(new (&timepunct_c) __timepunct<char>(__tpc, 1)); 423 424 _M_init_facet(new (&time_get_c) time_get<char>(1)); 425 _M_init_facet(new (&time_put_c) time_put<char>(1)); 426 _M_init_facet(new (&messages_c) std::messages<char>(1)); 427 428 #ifdef _GLIBCXX_USE_WCHAR_T 429 _M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1)); 430 _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1)); 431 432 typedef __numpunct_cache<wchar_t> num_cache_w; 433 num_cache_w* __npw = new (&numpunct_cache_w) num_cache_w(2); 434 _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(__npw, 1)); 435 436 _M_init_facet(new (&num_get_w) num_get<wchar_t>(1)); 437 _M_init_facet(new (&num_put_w) num_put<wchar_t>(1)); 438 _M_init_facet(new (&collate_w) std::collate<wchar_t>(1)); 439 440 typedef __moneypunct_cache<wchar_t, false> money_cache_wf; 441 typedef __moneypunct_cache<wchar_t, true> money_cache_wt; 442 money_cache_wf* __mpwf = new (&moneypunct_cache_wf) money_cache_wf(2); 443 _M_init_facet(new (&moneypunct_wf) moneypunct<wchar_t, false>(__mpwf, 1)); 444 money_cache_wt* __mpwt = new (&moneypunct_cache_wt) money_cache_wt(2); 445 _M_init_facet(new (&moneypunct_wt) moneypunct<wchar_t, true>(__mpwt, 1)); 446 447 _M_init_facet(new (&money_get_w) money_get<wchar_t>(1)); 448 _M_init_facet(new (&money_put_w) money_put<wchar_t>(1)); 449 450 typedef __timepunct_cache<wchar_t> time_cache_w; 451 time_cache_w* __tpw = new (&timepunct_cache_w) time_cache_w(2); 452 _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>(__tpw, 1)); 453 454 _M_init_facet(new (&time_get_w) time_get<wchar_t>(1)); 455 _M_init_facet(new (&time_put_w) time_put<wchar_t>(1)); 456 _M_init_facet(new (&messages_w) std::messages<wchar_t>(1)); 457 #endif 458 459 // This locale is safe to pre-cache, after all the facets have 460 // been created and installed. 461 _M_caches[numpunct<char>::id._M_id()] = __npc; 462 _M_caches[moneypunct<char, false>::id._M_id()] = __mpcf; 463 _M_caches[moneypunct<char, true>::id._M_id()] = __mpct; 464 _M_caches[__timepunct<char>::id._M_id()] = __tpc; 465 #ifdef _GLIBCXX_USE_WCHAR_T 466 _M_caches[numpunct<wchar_t>::id._M_id()] = __npw; 467 _M_caches[moneypunct<wchar_t, false>::id._M_id()] = __mpwf; 468 _M_caches[moneypunct<wchar_t, true>::id._M_id()] = __mpwt; 469 _M_caches[__timepunct<wchar_t>::id._M_id()] = __tpw; 470 #endif 471 } 472 473 _GLIBCXX_END_NAMESPACE_VERSION 474 } // namespace 475