locale_init.cc

00001 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 00002 // Free Software Foundation, Inc. 00003 // 00004 // This file is part of the GNU ISO C++ Library. This library is free 00005 // software; you can redistribute it and/or modify it under the 00006 // terms of the GNU General Public License as published by the 00007 // Free Software Foundation; either version 2, or (at your option) 00008 // any later version. 00009 00010 // This library is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 00015 // You should have received a copy of the GNU General Public License along 00016 // with this library; see the file COPYING. If not, write to the Free 00017 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 00018 // USA. 00019 00020 // As a special exception, you may use this file as part of a free software 00021 // library without restriction. Specifically, if other files instantiate 00022 // templates or use macros or inline functions from this file, or you compile 00023 // this file and link it with other files to produce an executable, this 00024 // file does not by itself cause the resulting executable to be covered by 00025 // the GNU General Public License. This exception does not however 00026 // invalidate any other reasons why the executable file might be covered by 00027 // the GNU General Public License. 00028 00029 #include <clocale> 00030 #include <cstring> 00031 #include <cstdlib> // For getenv, free. 00032 #include <cctype> 00033 #include <cwctype> // For towupper, etc. 00034 #include <locale> 00035 #include <bits/atomicity.h> 00036 #include <bits/concurrence.h> 00037 00038 namespace __gnu_internal 00039 { 00040 // Defined in globals.cc. 00041 extern std::locale c_locale; 00042 extern std::locale::_Impl c_locale_impl; 00043 00044 extern std::locale::facet* facet_vec[_GLIBCXX_NUM_FACETS]; 00045 extern char* name_vec[6 + _GLIBCXX_NUM_CATEGORIES]; 00046 extern char name_c[6 + _GLIBCXX_NUM_CATEGORIES][2]; 00047 00048 extern std::ctype<char> ctype_c; 00049 extern std::collate<char> collate_c; 00050 extern std::numpunct<char> numpunct_c; 00051 extern std::num_get<char> num_get_c; 00052 extern std::num_put<char> num_put_c; 00053 extern std::codecvt<char, char, mbstate_t> codecvt_c; 00054 extern std::moneypunct<char, false> moneypunct_cf; 00055 extern std::moneypunct<char, true> moneypunct_ct; 00056 extern std::money_get<char> money_get_c; 00057 extern std::money_put<char> money_put_c; 00058 extern std::__timepunct<char> timepunct_c; 00059 extern std::time_get<char> time_get_c; 00060 extern std::time_put<char> time_put_c; 00061 extern std::messages<char> messages_c; 00062 #ifdef _GLIBCXX_USE_WCHAR_T 00063 extern std::ctype<wchar_t> ctype_w; 00064 extern std::collate<wchar_t> collate_w; 00065 extern std::numpunct<wchar_t> numpunct_w; 00066 extern std::num_get<wchar_t> num_get_w; 00067 extern std::num_put<wchar_t> num_put_w; 00068 extern std::codecvt<wchar_t, char, mbstate_t> codecvt_w; 00069 extern std::moneypunct<wchar_t, false> moneypunct_wf; 00070 extern std::moneypunct<wchar_t, true> moneypunct_wt; 00071 extern std::money_get<wchar_t> money_get_w; 00072 extern std::money_put<wchar_t> money_put_w; 00073 extern std::__timepunct<wchar_t> timepunct_w; 00074 extern std::time_get<wchar_t> time_get_w; 00075 extern std::time_put<wchar_t> time_put_w; 00076 extern std::messages<wchar_t> messages_w; 00077 #endif 00078 00079 // And the caches.... 00080 extern std::locale::facet* cache_vec[_GLIBCXX_NUM_FACETS]; 00081 extern std::__numpunct_cache<char> numpunct_cache_c; 00082 extern std::__moneypunct_cache<char, false> moneypunct_cache_cf; 00083 extern std::__moneypunct_cache<char, true> moneypunct_cache_ct; 00084 extern std::__timepunct_cache<char> timepunct_cache_c; 00085 #ifdef _GLIBCXX_USE_WCHAR_T 00086 extern std::__numpunct_cache<wchar_t> numpunct_cache_w; 00087 extern std::__moneypunct_cache<wchar_t, false> moneypunct_cache_wf; 00088 extern std::__moneypunct_cache<wchar_t, true> moneypunct_cache_wt; 00089 extern std::__timepunct_cache<wchar_t> timepunct_cache_w; 00090 #endif 00091 00092 // Mutex object for locale initialization. 00093 __glibcxx_mutex_define_initialized(locale_mutex); 00094 } // namespace __gnu_internal 00095 00096 namespace std 00097 { 00098 using namespace __gnu_internal; 00099 00100 locale::locale() throw() : _M_impl(0) 00101 { 00102 _S_initialize(); 00103 __gnu_cxx::lock sentry(__gnu_internal::locale_mutex); 00104 _S_global->_M_add_reference(); 00105 _M_impl = _S_global; 00106 } 00107 00108 locale 00109 locale::global(const locale& __other) 00110 { 00111 _S_initialize(); 00112 _Impl* __old; 00113 { 00114 __gnu_cxx::lock sentry(__gnu_internal::locale_mutex); 00115 __old = _S_global; 00116 __other._M_impl->_M_add_reference(); 00117 _S_global = __other._M_impl; 00118 if (__other.name() != "*") 00119 setlocale(LC_ALL, __other.name().c_str()); 00120 } 00121 00122 // Reference count sanity check: one reference removed for the 00123 // subsition of __other locale, one added by return-by-value. Net 00124 // difference: zero. When the returned locale object's destrutor 00125 // is called, then the reference count is decremented and possibly 00126 // destroyed. 00127 return locale(__old); 00128 } 00129 00130 const locale& 00131 locale::classic() 00132 { 00133 _S_initialize(); 00134 return c_locale; 00135 } 00136 00137 void 00138 locale::_S_initialize_once() 00139 { 00140 // 2 references. 00141 // One reference for _S_classic, one for _S_global 00142 _S_classic = new (&c_locale_impl) _Impl(2); 00143 _S_global = _S_classic; 00144 new (&c_locale) locale(_S_classic); 00145 } 00146 00147 void 00148 locale::_S_initialize() 00149 { 00150 #ifdef __GTHREADS 00151 if (__gthread_active_p()) 00152 __gthread_once(&_S_once, _S_initialize_once); 00153 #endif 00154 if (!_S_classic) 00155 _S_initialize_once(); 00156 } 00157 00158 // Definitions for static const data members of locale::_Impl 00159 const locale::id* const 00160 locale::_Impl::_S_id_ctype[] = 00161 { 00162 &std::ctype<char>::id, 00163 &codecvt<char, char, mbstate_t>::id, 00164 #ifdef _GLIBCXX_USE_WCHAR_T 00165 &std::ctype<wchar_t>::id, 00166 &codecvt<wchar_t, char, mbstate_t>::id, 00167 #endif 00168 0 00169 }; 00170 00171 const locale::id* const 00172 locale::_Impl::_S_id_numeric[] = 00173 { 00174 &num_get<char>::id, 00175 &num_put<char>::id, 00176 &numpunct<char>::id, 00177 #ifdef _GLIBCXX_USE_WCHAR_T 00178 &num_get<wchar_t>::id, 00179 &num_put<wchar_t>::id, 00180 &numpunct<wchar_t>::id, 00181 #endif 00182 0 00183 }; 00184 00185 const locale::id* const 00186 locale::_Impl::_S_id_collate[] = 00187 { 00188 &std::collate<char>::id, 00189 #ifdef _GLIBCXX_USE_WCHAR_T 00190 &std::collate<wchar_t>::id, 00191 #endif 00192 0 00193 }; 00194 00195 const locale::id* const 00196 locale::_Impl::_S_id_time[] = 00197 { 00198 &__timepunct<char>::id, 00199 &time_get<char>::id, 00200 &time_put<char>::id, 00201 #ifdef _GLIBCXX_USE_WCHAR_T 00202 &__timepunct<wchar_t>::id, 00203 &time_get<wchar_t>::id, 00204 &time_put<wchar_t>::id, 00205 #endif 00206 0 00207 }; 00208 00209 const locale::id* const 00210 locale::_Impl::_S_id_monetary[] = 00211 { 00212 &money_get<char>::id, 00213 &money_put<char>::id, 00214 &moneypunct<char, false>::id, 00215 &moneypunct<char, true >::id, 00216 #ifdef _GLIBCXX_USE_WCHAR_T 00217 &money_get<wchar_t>::id, 00218 &money_put<wchar_t>::id, 00219 &moneypunct<wchar_t, false>::id, 00220 &moneypunct<wchar_t, true >::id, 00221 #endif 00222 0 00223 }; 00224 00225 const locale::id* const 00226 locale::_Impl::_S_id_messages[] = 00227 { 00228 &std::messages<char>::id, 00229 #ifdef _GLIBCXX_USE_WCHAR_T 00230 &std::messages<wchar_t>::id, 00231 #endif 00232 0 00233 }; 00234 00235 const locale::id* const* const 00236 locale::_Impl::_S_facet_categories[] = 00237 { 00238 // Order must match the decl order in class locale. 00239 locale::_Impl::_S_id_ctype, 00240 locale::_Impl::_S_id_numeric, 00241 locale::_Impl::_S_id_collate, 00242 locale::_Impl::_S_id_time, 00243 locale::_Impl::_S_id_monetary, 00244 locale::_Impl::_S_id_messages, 00245 0 00246 }; 00247 00248 // Construct "C" _Impl. 00249 locale::_Impl:: 00250 _Impl(size_t __refs) throw() 00251 : _M_refcount(__refs), _M_facets(0), _M_facets_size(_GLIBCXX_NUM_FACETS), 00252 _M_caches(0), _M_names(0) 00253 { 00254 _M_facets = new (&facet_vec) const facet*[_M_facets_size]; 00255 _M_caches = new (&cache_vec) const facet*[_M_facets_size]; 00256 for (size_t __i = 0; __i < _M_facets_size; ++__i) 00257 _M_facets[__i] = _M_caches[__i] = 0; 00258 00259 // Name all the categories. 00260 _M_names = new (&name_vec) char*[_S_categories_size]; 00261 for (size_t __j = 0; __j < _S_categories_size; ++__j) 00262 { 00263 _M_names[__j] = new (&name_c[__j]) char[2]; 00264 std::strcpy(_M_names[__j], locale::facet::_S_get_c_name()); 00265 } 00266 00267 // This is needed as presently the C++ version of "C" locales 00268 // != data in the underlying locale model for __timepunct, 00269 // numpunct, and moneypunct. Also, the "C" locales must be 00270 // constructed in a way such that they are pre-allocated. 00271 // NB: Set locale::facets(ref) count to one so that each individual 00272 // facet is not destroyed when the locale (and thus locale::_Impl) is 00273 // destroyed. 00274 _M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1)); 00275 _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1)); 00276 00277 typedef __numpunct_cache<char> num_cache_c; 00278 num_cache_c* __npc = new (&numpunct_cache_c) num_cache_c(2); 00279 _M_init_facet(new (&numpunct_c) numpunct<char>(__npc, 1)); 00280 00281 _M_init_facet(new (&num_get_c) num_get<char>(1)); 00282 _M_init_facet(new (&num_put_c) num_put<char>(1)); 00283 _M_init_facet(new (&collate_c) std::collate<char>(1)); 00284 00285 typedef __moneypunct_cache<char, false> money_cache_cf; 00286 typedef __moneypunct_cache<char, true> money_cache_ct; 00287 money_cache_cf* __mpcf = new (&moneypunct_cache_cf) money_cache_cf(2); 00288 _M_init_facet(new (&moneypunct_cf) moneypunct<char, false>(__mpcf, 1)); 00289 money_cache_ct* __mpct = new (&moneypunct_cache_ct) money_cache_ct(2); 00290 _M_init_facet(new (&moneypunct_ct) moneypunct<char, true>(__mpct, 1)); 00291 00292 _M_init_facet(new (&money_get_c) money_get<char>(1)); 00293 _M_init_facet(new (&money_put_c) money_put<char>(1)); 00294 00295 typedef __timepunct_cache<char> time_cache_c; 00296 time_cache_c* __tpc = new (&timepunct_cache_c) time_cache_c(2); 00297 _M_init_facet(new (&timepunct_c) __timepunct<char>(__tpc, 1)); 00298 00299 _M_init_facet(new (&time_get_c) time_get<char>(1)); 00300 _M_init_facet(new (&time_put_c) time_put<char>(1)); 00301 _M_init_facet(new (&messages_c) std::messages<char>(1)); 00302 00303 #ifdef _GLIBCXX_USE_WCHAR_T 00304 _M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1)); 00305 _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1)); 00306 00307 typedef __numpunct_cache<wchar_t> num_cache_w; 00308 num_cache_w* __npw = new (&numpunct_cache_w) num_cache_w(2); 00309 _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(__npw, 1)); 00310 00311 _M_init_facet(new (&num_get_w) num_get<wchar_t>(1)); 00312 _M_init_facet(new (&num_put_w) num_put<wchar_t>(1)); 00313 _M_init_facet(new (&collate_w) std::collate<wchar_t>(1)); 00314 00315 typedef __moneypunct_cache<wchar_t, false> money_cache_wf; 00316 typedef __moneypunct_cache<wchar_t, true> money_cache_wt; 00317 money_cache_wf* __mpwf = new (&moneypunct_cache_wf) money_cache_wf(2); 00318 _M_init_facet(new (&moneypunct_wf) moneypunct<wchar_t, false>(__mpwf, 1)); 00319 money_cache_wt* __mpwt = new (&moneypunct_cache_wt) money_cache_wt(2); 00320 _M_init_facet(new (&moneypunct_wt) moneypunct<wchar_t, true>(__mpwt, 1)); 00321 00322 _M_init_facet(new (&money_get_w) money_get<wchar_t>(1)); 00323 _M_init_facet(new (&money_put_w) money_put<wchar_t>(1)); 00324 00325 typedef __timepunct_cache<wchar_t> time_cache_w; 00326 time_cache_w* __tpw = new (&timepunct_cache_w) time_cache_w(2); 00327 _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>(__tpw, 1)); 00328 00329 _M_init_facet(new (&time_get_w) time_get<wchar_t>(1)); 00330 _M_init_facet(new (&time_put_w) time_put<wchar_t>(1)); 00331 _M_init_facet(new (&messages_w) std::messages<wchar_t>(1)); 00332 #endif 00333 00334 // This locale is safe to pre-cache, after all the facets have 00335 // been created and installed. 00336 _M_caches[numpunct<char>::id._M_id()] = __npc; 00337 _M_caches[moneypunct<char, false>::id._M_id()] = __mpcf; 00338 _M_caches[moneypunct<char, true>::id._M_id()] = __mpct; 00339 _M_caches[__timepunct<char>::id._M_id()] = __tpc; 00340 #ifdef _GLIBCXX_USE_WCHAR_T 00341 _M_caches[numpunct<wchar_t>::id._M_id()] = __npw; 00342 _M_caches[moneypunct<wchar_t, false>::id._M_id()] = __mpwf; 00343 _M_caches[moneypunct<wchar_t, true>::id._M_id()] = __mpwt; 00344 _M_caches[__timepunct<wchar_t>::id._M_id()] = __tpw; 00345 #endif 00346 } 00347 } // namespace std

Generated on Wed Sep 8 10:19:35 2004 for libstdc++-v3 Source by doxygen 1.3.8