Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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