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 objects for locale initialization. 00093 __glibcxx_mutex_define_initialized(locale_cons_mutex); 00094 __glibcxx_mutex_define_initialized(locale_global_mutex); 00095 } // namespace __gnu_internal 00096 00097 namespace std 00098 { 00099 using namespace __gnu_internal; 00100 00101 locale::locale() throw() : _M_impl(0) 00102 { 00103 _S_initialize(); 00104 __glibcxx_mutex_lock(__gnu_internal::locale_cons_mutex); 00105 _S_global->_M_add_reference(); 00106 _M_impl = _S_global; 00107 __glibcxx_mutex_unlock(__gnu_internal::locale_cons_mutex); 00108 } 00109 00110 locale 00111 locale::global(const locale& __other) 00112 { 00113 _S_initialize(); 00114 __glibcxx_mutex_lock(__gnu_internal::locale_global_mutex); 00115 _Impl* __old = _S_global; 00116 __other._M_impl->_M_add_reference(); 00117 _S_global = __other._M_impl; 00118 const string __other_name = __other.name(); 00119 if (__other_name != "*") 00120 setlocale(LC_ALL, __other_name.c_str()); 00121 __glibcxx_mutex_unlock(__gnu_internal::locale_global_mutex); 00122 00123 // Reference count sanity check: one reference removed for the 00124 // subsition of __other locale, one added by return-by-value. Net 00125 // difference: zero. When the returned locale object's destrutor 00126 // is called, then the reference count is decremented and possibly 00127 // destroyed. 00128 return locale(__old); 00129 } 00130 00131 const locale& 00132 locale::classic() 00133 { 00134 _S_initialize(); 00135 return c_locale; 00136 } 00137 00138 void 00139 locale::_S_initialize_once() 00140 { 00141 // 2 references. 00142 // One reference for _S_classic, one for _S_global 00143 _S_classic = new (&c_locale_impl) _Impl(2); 00144 _S_global = _S_classic; 00145 new (&c_locale) locale(_S_classic); 00146 } 00147 00148 void 00149 locale::_S_initialize() 00150 { 00151 #ifdef __GTHREADS 00152 if (__gthread_active_p()) 00153 __gthread_once(&_S_once, _S_initialize_once); 00154 #endif 00155 if (!_S_classic) 00156 _S_initialize_once(); 00157 } 00158 00159 // Definitions for static const data members of locale::_Impl 00160 const locale::id* const 00161 locale::_Impl::_S_id_ctype[] = 00162 { 00163 &std::ctype<char>::id, 00164 &codecvt<char, char, mbstate_t>::id, 00165 #ifdef _GLIBCXX_USE_WCHAR_T 00166 &std::ctype<wchar_t>::id, 00167 &codecvt<wchar_t, char, mbstate_t>::id, 00168 #endif 00169 0 00170 }; 00171 00172 const locale::id* const 00173 locale::_Impl::_S_id_numeric[] = 00174 { 00175 &num_get<char>::id, 00176 &num_put<char>::id, 00177 &numpunct<char>::id, 00178 #ifdef _GLIBCXX_USE_WCHAR_T 00179 &num_get<wchar_t>::id, 00180 &num_put<wchar_t>::id, 00181 &numpunct<wchar_t>::id, 00182 #endif 00183 0 00184 }; 00185 00186 const locale::id* const 00187 locale::_Impl::_S_id_collate[] = 00188 { 00189 &std::collate<char>::id, 00190 #ifdef _GLIBCXX_USE_WCHAR_T 00191 &std::collate<wchar_t>::id, 00192 #endif 00193 0 00194 }; 00195 00196 const locale::id* const 00197 locale::_Impl::_S_id_time[] = 00198 { 00199 &__timepunct<char>::id, 00200 &time_get<char>::id, 00201 &time_put<char>::id, 00202 #ifdef _GLIBCXX_USE_WCHAR_T 00203 &__timepunct<wchar_t>::id, 00204 &time_get<wchar_t>::id, 00205 &time_put<wchar_t>::id, 00206 #endif 00207 0 00208 }; 00209 00210 const locale::id* const 00211 locale::_Impl::_S_id_monetary[] = 00212 { 00213 &money_get<char>::id, 00214 &money_put<char>::id, 00215 &moneypunct<char, false>::id, 00216 &moneypunct<char, true >::id, 00217 #ifdef _GLIBCXX_USE_WCHAR_T 00218 &money_get<wchar_t>::id, 00219 &money_put<wchar_t>::id, 00220 &moneypunct<wchar_t, false>::id, 00221 &moneypunct<wchar_t, true >::id, 00222 #endif 00223 0 00224 }; 00225 00226 const locale::id* const 00227 locale::_Impl::_S_id_messages[] = 00228 { 00229 &std::messages<char>::id, 00230 #ifdef _GLIBCXX_USE_WCHAR_T 00231 &std::messages<wchar_t>::id, 00232 #endif 00233 0 00234 }; 00235 00236 const locale::id* const* const 00237 locale::_Impl::_S_facet_categories[] = 00238 { 00239 // Order must match the decl order in class locale. 00240 locale::_Impl::_S_id_ctype, 00241 locale::_Impl::_S_id_numeric, 00242 locale::_Impl::_S_id_collate, 00243 locale::_Impl::_S_id_time, 00244 locale::_Impl::_S_id_monetary, 00245 locale::_Impl::_S_id_messages, 00246 0 00247 }; 00248 00249 // Construct "C" _Impl. 00250 locale::_Impl:: 00251 _Impl(size_t __refs) throw() 00252 : _M_refcount(__refs), _M_facets(0), _M_facets_size(_GLIBCXX_NUM_FACETS), 00253 _M_caches(0), _M_names(0) 00254 { 00255 _M_facets = new (&facet_vec) const facet*[_M_facets_size]; 00256 _M_caches = new (&cache_vec) const facet*[_M_facets_size]; 00257 for (size_t __i = 0; __i < _M_facets_size; ++__i) 00258 _M_facets[__i] = _M_caches[__i] = 0; 00259 00260 // Name the categories. 00261 _M_names = new (&name_vec) char*[_S_categories_size]; 00262 _M_names[0] = new (&name_c[0]) char[2]; 00263 std::memcpy(_M_names[0], locale::facet::_S_get_c_name(), 2); 00264 for (size_t __j = 1; __j < _S_categories_size; ++__j) 00265 _M_names[__j] = 0; 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 Jun 9 11:18:40 2004 for libstdc++-v3 Source by doxygen 1.3.7