summaryrefslogtreecommitdiff
path: root/libstdc++-v3/src/localename.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/src/localename.cc')
-rw-r--r--libstdc++-v3/src/localename.cc434
1 files changed, 132 insertions, 302 deletions
diff --git a/libstdc++-v3/src/localename.cc b/libstdc++-v3/src/localename.cc
index 56b2bdfe102..e14053c9580 100644
--- a/libstdc++-v3/src/localename.cc
+++ b/libstdc++-v3/src/localename.cc
@@ -30,123 +30,147 @@
#include <cstring>
#include <locale>
-namespace __gnu_cxx
-{
- using namespace std;
-
- // Defined in globals.cc.
- extern locale::facet* facet_vec[_GLIBCXX_NUM_FACETS];
- extern char* name_vec[6 + _GLIBCXX_NUM_CATEGORIES];
- extern char name_c[6 + _GLIBCXX_NUM_CATEGORIES][2];
-
- extern std::ctype<char> ctype_c;
- extern std::collate<char> collate_c;
- extern numpunct<char> numpunct_c;
- extern num_get<char> num_get_c;
- extern num_put<char> num_put_c;
- extern codecvt<char, char, mbstate_t> codecvt_c;
- extern moneypunct<char, false> moneypunct_cf;
- extern moneypunct<char, true> moneypunct_ct;
- extern money_get<char> money_get_c;
- extern money_put<char> money_put_c;
- extern __timepunct<char> timepunct_c;
- extern time_get<char> time_get_c;
- extern time_put<char> time_put_c;
- extern std::messages<char> messages_c;
-#ifdef _GLIBCXX_USE_WCHAR_T
- extern std::ctype<wchar_t> ctype_w;
- extern std::collate<wchar_t> collate_w;
- extern numpunct<wchar_t> numpunct_w;
- extern num_get<wchar_t> num_get_w;
- extern num_put<wchar_t> num_put_w;
- extern codecvt<wchar_t, char, mbstate_t> codecvt_w;
- extern moneypunct<wchar_t, false> moneypunct_wf;
- extern moneypunct<wchar_t, true> moneypunct_wt;
- extern money_get<wchar_t> money_get_w;
- extern money_put<wchar_t> money_put_w;
- extern __timepunct<wchar_t> timepunct_w;
- extern time_get<wchar_t> time_get_w;
- extern time_put<wchar_t> time_put_w;
- extern std::messages<wchar_t> messages_w;
-#endif
-
- // And the caches....
- extern locale::facet* cache_vec[_GLIBCXX_NUM_FACETS];
- extern __numpunct_cache<char> numpunct_cache_c;
- extern __moneypunct_cache<char> moneypunct_cache_cf;
- extern __moneypunct_cache<char> moneypunct_cache_ct;
- extern __timepunct_cache<char> timepunct_cache_c;
-#ifdef _GLIBCXX_USE_WCHAR_T
- extern __numpunct_cache<wchar_t> numpunct_cache_w;
- extern __moneypunct_cache<wchar_t> moneypunct_cache_wf;
- extern __moneypunct_cache<wchar_t> moneypunct_cache_wt;
- extern __timepunct_cache<wchar_t> timepunct_cache_w;
-#endif
-} // namespace __gnu_cxx
-
namespace std
{
using namespace __gnu_cxx;
- locale::_Impl::
- ~_Impl() throw()
- {
- if (_M_facets)
- for (size_t __i = 0; __i < _M_facets_size; ++__i)
- if (_M_facets[__i])
- _M_facets[__i]->_M_remove_reference();
- delete [] _M_facets;
-
- if (_M_caches)
- for (size_t __i = 0; __i < _M_facets_size; ++__i)
- if (_M_caches[__i])
- _M_caches[__i]->_M_remove_reference();
- delete [] _M_caches;
-
- if (_M_names)
- for (size_t __i = 0; __i < _S_categories_size; ++__i)
- delete [] _M_names[__i];
- delete [] _M_names;
- }
-
- // Clone existing _Impl object.
- locale::_Impl::
- _Impl(const _Impl& __imp, size_t __refs)
- : _M_references(__refs), _M_facets_size(__imp._M_facets_size)
+
+ locale::locale(const char* __s)
{
- _M_facets = _M_caches = 0;
- _M_names = 0;
- try
+ if (__s)
{
- _M_facets = new const facet*[_M_facets_size];
- for (size_t __i = 0; __i < _M_facets_size; ++__i)
- {
- _M_facets[__i] = __imp._M_facets[__i];
- if (_M_facets[__i])
- _M_facets[__i]->_M_add_reference();
- }
- _M_caches = new const facet*[_M_facets_size];
- for (size_t __i = 0; __i < _M_facets_size; ++__i)
- {
- _M_caches[__i] = __imp._M_caches[__i];
- if (_M_caches[__i])
- _M_caches[__i]->_M_add_reference();
- }
- _M_names = new char*[_S_categories_size];
- for (size_t __i = 0; __i < _S_categories_size; ++__i)
- _M_names[__i] = 0;
-
- // Name all the categories.
- for (size_t __i = 0; __i < _S_categories_size; ++__i)
+ _S_initialize();
+ if (std::strcmp(__s, "C") == 0 || std::strcmp(__s, "POSIX") == 0)
+ (_M_impl = _S_classic)->_M_add_reference();
+ else if (std::strcmp(__s, "") != 0)
+ _M_impl = new _Impl(__s, 1);
+ else
{
- char* __new = new char[std::strlen(__imp._M_names[__i]) + 1];
- std::strcpy(__new, __imp._M_names[__i]);
- _M_names[__i] = __new;
+ // Get it from the environment.
+ char* __env = std::getenv("LC_ALL");
+ // If LC_ALL is set we are done.
+ if (__env && std::strcmp(__env, "") != 0)
+ {
+ if (std::strcmp(__env, "C") == 0
+ || std::strcmp(__env, "POSIX") == 0)
+ (_M_impl = _S_classic)->_M_add_reference();
+ else
+ _M_impl = new _Impl(__env, 1);
+ }
+ else
+ {
+ string __res;
+ // LANG may set a default different from "C".
+ char* __env = std::getenv("LANG");
+ if (!__env || std::strcmp(__env, "") == 0
+ || std::strcmp(__env, "C") == 0
+ || std::strcmp(__env, "POSIX") == 0)
+ __res = "C";
+ else
+ __res = __env;
+
+ // Scan the categories looking for the first one
+ // different from LANG.
+ size_t __i = 0;
+ if (__res == "C")
+ for (; __i < _S_categories_size; ++__i)
+ {
+ __env = std::getenv(_S_categories[__i]);
+ if (__env && std::strcmp(__env, "") != 0
+ && std::strcmp(__env, "C") != 0
+ && std::strcmp(__env, "POSIX") != 0)
+ break;
+ }
+ else
+ for (; __i < _S_categories_size; ++__i)
+ {
+ __env = std::getenv(_S_categories[__i]);
+ if (__env && std::strcmp(__env, "") != 0
+ && __res != __env)
+ break;
+ }
+
+ // If one is found, build the complete string of
+ // the form LC_CTYPE=xxx;LC_NUMERIC=yyy; and so on...
+ if (__i < _S_categories_size)
+ {
+ string __str;
+ for (size_t __j = 0; __j < __i; ++__j)
+ {
+ __str += _S_categories[__j];
+ __str += '=';
+ __str += __res;
+ __str += ';';
+ }
+ __str += _S_categories[__i];
+ __str += '=';
+ __str += __env;
+ __str += ';';
+ __i++;
+ for (; __i < _S_categories_size; ++__i)
+ {
+ __env = std::getenv(_S_categories[__i]);
+ if (!__env || std::strcmp(__env, "") == 0)
+ {
+ __str += _S_categories[__i];
+ __str += '=';
+ __str += __res;
+ __str += ';';
+ }
+ else if (std::strcmp(__env, "C") == 0
+ || std::strcmp(__env, "POSIX") == 0)
+ {
+ __str += _S_categories[__i];
+ __str += "=C;";
+ }
+ else
+ {
+ __str += _S_categories[__i];
+ __str += '=';
+ __str += __env;
+ __str += ';';
+ }
+ }
+ __str.erase(__str.end() - 1);
+ _M_impl = new _Impl(__str.c_str(), 1);
+ }
+ // ... otherwise either an additional instance of
+ // the "C" locale or LANG.
+ else if (__res == "C")
+ (_M_impl = _S_classic)->_M_add_reference();
+ else
+ _M_impl = new _Impl(__res.c_str(), 1);
+ }
}
}
- catch(...)
- {
- this->~_Impl();
+ else
+ __throw_runtime_error("locale::locale NULL not valid");
+ }
+
+ locale::locale(const locale& __base, const char* __s, category __cat)
+ {
+ // NB: There are complicated, yet more efficient ways to do
+ // this. Building up locales on a per-category way is tedious, so
+ // let's do it this way until people complain.
+ locale __add(__s);
+ _M_coalesce(__base, __add, __cat);
+ }
+
+ locale::locale(const locale& __base, const locale& __add, category __cat)
+ { _M_coalesce(__base, __add, __cat); }
+
+ void
+ locale::_M_coalesce(const locale& __base, const locale& __add,
+ category __cat)
+ {
+ __cat = _S_normalize_category(__cat);
+ _M_impl = new _Impl(*__base._M_impl, 1);
+
+ try
+ { _M_impl->_M_replace_categories(__add._M_impl, __cat); }
+ catch (...)
+ {
+ _M_impl->_M_remove_reference();
__throw_exception_again;
}
}
@@ -243,103 +267,6 @@ namespace std
}
}
- // Construct "C" _Impl.
- locale::_Impl::
- _Impl(size_t __refs) throw()
- : _M_references(__refs), _M_facets_size(_GLIBCXX_NUM_FACETS)
- {
- _M_facets = new (&facet_vec) const facet*[_M_facets_size];
- _M_caches = new (&cache_vec) const facet*[_M_facets_size];
- for (size_t __i = 0; __i < _M_facets_size; ++__i)
- _M_facets[__i] = _M_caches[__i] = 0;
-
- // Name all the categories.
- _M_names = new (&name_vec) char*[_S_categories_size];
- for (size_t __i = 0; __i < _S_categories_size; ++__i)
- {
- _M_names[__i] = new (&name_c[__i]) char[2];
- std::strcpy(_M_names[__i], locale::facet::_S_get_c_name());
- }
-
- // This is needed as presently the C++ version of "C" locales
- // != data in the underlying locale model for __timepunct,
- // numpunct, and moneypunct. Also, the "C" locales must be
- // constructed in a way such that they are pre-allocated.
- // NB: Set locale::facets(ref) count to one so that each individual
- // facet is not destroyed when the locale (and thus locale::_Impl) is
- // destroyed.
- _M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1));
- _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1));
-
- typedef __numpunct_cache<char> num_cache_c;
- num_cache_c* __npc = new (&numpunct_cache_c) num_cache_c(2);
- _M_init_facet(new (&numpunct_c) numpunct<char>(__npc, 1));
-
- _M_init_facet(new (&num_get_c) num_get<char>(1));
- _M_init_facet(new (&num_put_c) num_put<char>(1));
- _M_init_facet(new (&collate_c) std::collate<char>(1));
-
- typedef __moneypunct_cache<char> money_cache_c;
- money_cache_c* __mpcf = new (&moneypunct_cache_cf) money_cache_c(2);
- _M_init_facet(new (&moneypunct_cf) moneypunct<char, false>(__mpcf, 1));
- money_cache_c* __mpct = new (&moneypunct_cache_ct) money_cache_c(2);
- _M_init_facet(new (&moneypunct_ct) moneypunct<char, true>(__mpct, 1));
-
- _M_init_facet(new (&money_get_c) money_get<char>(1));
- _M_init_facet(new (&money_put_c) money_put<char>(1));
-
- typedef __timepunct_cache<char> time_cache_c;
- time_cache_c* __tpc = new (&timepunct_cache_c) time_cache_c(2);
- _M_init_facet(new (&timepunct_c) __timepunct<char>(__tpc, 1));
-
- _M_init_facet(new (&time_get_c) time_get<char>(1));
- _M_init_facet(new (&time_put_c) time_put<char>(1));
- _M_init_facet(new (&messages_c) std::messages<char>(1));
-
-#ifdef _GLIBCXX_USE_WCHAR_T
- _M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1));
- _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1));
-
- typedef __numpunct_cache<wchar_t> num_cache_w;
- num_cache_w* __npw = new (&numpunct_cache_w) num_cache_w(2);
- _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(__npw, 1));
-
- _M_init_facet(new (&num_get_w) num_get<wchar_t>(1));
- _M_init_facet(new (&num_put_w) num_put<wchar_t>(1));
- _M_init_facet(new (&collate_w) std::collate<wchar_t>(1));
-
- typedef __moneypunct_cache<wchar_t> money_cache_w;
- money_cache_w* __mpwf = new (&moneypunct_cache_wf) money_cache_w(2);
- _M_init_facet(new (&moneypunct_wf) moneypunct<wchar_t, false>(__mpwf, 1));
- money_cache_w* __mpwt = new (&moneypunct_cache_wt) money_cache_w(2);
- _M_init_facet(new (&moneypunct_wt) moneypunct<wchar_t, true>(__mpwt, 1));
-
- _M_init_facet(new (&money_get_w) money_get<wchar_t>(1));
- _M_init_facet(new (&money_put_w) money_put<wchar_t>(1));
-
- typedef __timepunct_cache<wchar_t> time_cache_w;
- time_cache_w* __tpw = new (&timepunct_cache_w) time_cache_w(2);
- _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>(__tpw, 1));
-
- _M_init_facet(new (&time_get_w) time_get<wchar_t>(1));
- _M_init_facet(new (&time_put_w) time_put<wchar_t>(1));
- _M_init_facet(new (&messages_w) std::messages<wchar_t>(1));
-#endif
-
- // This locale is safe to pre-cache, after all the facets have
- // been created and installed.
- _M_caches[numpunct<char>::id._M_id()] = __npc;
- _M_caches[moneypunct<char, false>::id._M_id()] = __mpcf;
- _M_caches[moneypunct<char, true>::id._M_id()] = __mpct;
- _M_caches[__timepunct<char>::id._M_id()] = __tpc;
-#ifdef _GLIBCXX_USE_WCHAR_T
- _M_caches[numpunct<wchar_t>::id._M_id()] = __npw;
- _M_caches[moneypunct<wchar_t, false>::id._M_id()] = __mpwf;
- _M_caches[moneypunct<wchar_t, true>::id._M_id()] = __mpwt;
- _M_caches[__timepunct<wchar_t>::id._M_id()] = __tpw;
-#endif
- }
-
void
locale::_Impl::
_M_replace_categories(const _Impl* __imp, category __cat)
@@ -363,101 +290,4 @@ namespace std
}
}
}
-
- void
- locale::_Impl::
- _M_replace_category(const _Impl* __imp, const locale::id* const* __idpp)
- {
- for (; *__idpp; ++__idpp)
- _M_replace_facet(__imp, *__idpp);
- }
-
- void
- locale::_Impl::
- _M_replace_facet(const _Impl* __imp, const locale::id* __idp)
- {
- const size_t __index = __idp->_M_id();
- if ((__index > (__imp->_M_facets_size - 1)) || !__imp->_M_facets[__index])
- __throw_runtime_error("locale::_Impl::_M_replace_facet");
- _M_install_facet(__idp, __imp->_M_facets[__index]);
- }
-
- void
- locale::_Impl::
- _M_install_facet(const locale::id* __idp, const facet* __fp)
- {
- if (__fp)
- {
- size_t __index = __idp->_M_id();
-
- // Check size of facet vector to ensure adequate room.
- if (__index > _M_facets_size - 1)
- {
- const size_t __new_size = __index + 4;
-
- // New facet array.
- const facet** __oldf = _M_facets;
- const facet** __newf;
- __newf = new const facet*[__new_size];
- for (size_t __i = 0; __i < _M_facets_size; ++__i)
- __newf[__i] = _M_facets[__i];
- for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
- __newf[__i2] = 0;
-
- // New cache array.
- const facet** __oldc = _M_caches;
- const facet** __newc;
- try
- {
- __newc = new const facet*[__new_size];
- }
- catch(...)
- {
- delete [] __newf;
- __throw_exception_again;
- }
- for (size_t __i = 0; __i < _M_facets_size; ++__i)
- __newc[__i] = _M_caches[__i];
- for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
- __newc[__i2] = 0;
-
- _M_facets_size = __new_size;
- _M_facets = __newf;
- _M_caches = __newc;
- delete [] __oldf;
- delete [] __oldc;
- }
-
- __fp->_M_add_reference();
- const facet*& __fpr = _M_facets[__index];
- if (__fpr)
- {
- // Replacing an existing facet. Order matters.
- __fpr->_M_remove_reference();
- __fpr = __fp;
- }
- else
- {
- // Installing a newly created facet into an empty
- // _M_facets container, say a newly-constructed,
- // swanky-fresh _Impl.
- _M_facets[__index] = __fp;
- }
-
- // Ideally, it would be nice to only remove the caches that
- // are now incorrect. However, some of the caches depend on
- // multiple facets, and we only know about one facet
- // here. It's no great loss: the first use of the new facet
- // will create a new, correctly cached facet anyway.
- for (size_t __i = 0; __i < _M_facets_size; ++__i)
- {
- const facet* __cpr = _M_caches[__i];
- if (__cpr)
- {
- __cpr->_M_remove_reference();
- _M_caches[__i] = 0;
- }
- }
- }
- }
} // namespace std