Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // Copyright (C) 1997-2015 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. #define _GLIBCXX_USE_CXX11_ABI 1
  24. #include <clocale>
  25. #include <cstring>
  26. #include <cstdlib>
  27. #include <locale>
  28.  
  29. namespace std _GLIBCXX_VISIBILITY(default)
  30. {
  31. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  32.  
  33.   using namespace __gnu_cxx;
  34.  
  35.   locale::locale(const char* __s) : _M_impl(0)
  36.   {
  37.     if (__s)
  38.       {
  39.         _S_initialize();
  40.         if (std::strcmp(__s, "C") == 0 || std::strcmp(__s, "POSIX") == 0)
  41.           (_M_impl = _S_classic)->_M_add_reference();
  42.         else if (std::strcmp(__s, "") != 0)
  43.           _M_impl = new _Impl(__s, 1);
  44.         else
  45.           {
  46.             // Get it from the environment.
  47.             char* __env = std::getenv("LC_ALL");
  48.             // If LC_ALL is set we are done.
  49.             if (__env && std::strcmp(__env, "") != 0)
  50.               {
  51.                 if (std::strcmp(__env, "C") == 0
  52.                     || std::strcmp(__env, "POSIX") == 0)
  53.                   (_M_impl = _S_classic)->_M_add_reference();
  54.                 else
  55.                   _M_impl = new _Impl(__env, 1);
  56.               }
  57.             else
  58.               {
  59.                 // LANG may set a default different from "C".
  60.                 string __lang;
  61.                 __env = std::getenv("LANG");
  62.                 if (!__env || std::strcmp(__env, "") == 0
  63.                     || std::strcmp(__env, "C") == 0
  64.                     || std::strcmp(__env, "POSIX") == 0)
  65.                   __lang = "C";
  66.                 else
  67.                   __lang = __env;
  68.                
  69.                 // Scan the categories looking for the first one
  70.                 // different from LANG.
  71.                 size_t __i = 0;
  72.                 if (__lang == "C")
  73.                   for (; __i < _S_categories_size; ++__i)
  74.                     {
  75.                       __env = std::getenv(_S_categories[__i]);
  76.                       if (__env && std::strcmp(__env, "") != 0
  77.                           && std::strcmp(__env, "C") != 0
  78.                           && std::strcmp(__env, "POSIX") != 0)
  79.                         break;
  80.                     }
  81.                 else
  82.                   for (; __i < _S_categories_size; ++__i)
  83.                     {
  84.                       __env = std::getenv(_S_categories[__i]);
  85.                       if (__env && std::strcmp(__env, "") != 0
  86.                           && __lang != __env)
  87.                         break;
  88.                     }
  89.        
  90.                 // If one is found, build the complete string of
  91.                 // the form LC_CTYPE=xxx;LC_NUMERIC=yyy; and so on...
  92.                 if (__i < _S_categories_size)
  93.                   {
  94.                     string __str;
  95.                     __str.reserve(128);
  96.                     for (size_t __j = 0; __j < __i; ++__j)
  97.                       {
  98.                         __str += _S_categories[__j];
  99.                         __str += '=';
  100.                         __str += __lang;
  101.                         __str += ';';
  102.                       }
  103.                     __str += _S_categories[__i];
  104.                     __str += '=';
  105.                     __str += __env;
  106.                     __str += ';';
  107.                     ++__i;
  108.                     for (; __i < _S_categories_size; ++__i)
  109.                       {
  110.                         __env = std::getenv(_S_categories[__i]);
  111.                         __str += _S_categories[__i];
  112.                         if (!__env || std::strcmp(__env, "") == 0)
  113.                           {
  114.                             __str += '=';
  115.                             __str += __lang;
  116.                             __str += ';';
  117.                           }
  118.                         else if (std::strcmp(__env, "C") == 0
  119.                                  || std::strcmp(__env, "POSIX") == 0)
  120.                           __str += "=C;";
  121.                         else
  122.                           {
  123.                             __str += '=';
  124.                             __str += __env;
  125.                             __str += ';';
  126.                           }
  127.                       }
  128.                     __str.erase(__str.end() - 1);
  129.                     _M_impl = new _Impl(__str.c_str(), 1);
  130.                   }
  131.                 // ... otherwise either an additional instance of
  132.                 // the "C" locale or LANG.
  133.                 else if (__lang == "C")
  134.                   (_M_impl = _S_classic)->_M_add_reference();
  135.                 else
  136.                   _M_impl = new _Impl(__lang.c_str(), 1);
  137.               }
  138.           }
  139.       }
  140.     else
  141.       __throw_runtime_error(__N("locale::locale null not valid"));
  142.   }
  143.  
  144.   locale::locale(const locale& __base, const char* __s, category __cat)
  145.   : _M_impl(0)
  146.   {
  147.     // NB: There are complicated, yet more efficient ways to do
  148.     // this. Building up locales on a per-category way is tedious, so
  149.     // let's do it this way until people complain.
  150.     locale __add(__s);
  151.     _M_coalesce(__base, __add, __cat);
  152.   }
  153.  
  154.   locale::locale(const locale& __base, const locale& __add, category __cat)
  155.   : _M_impl(0)
  156.   { _M_coalesce(__base, __add, __cat); }
  157.  
  158.   void
  159.   locale::_M_coalesce(const locale& __base, const locale& __add,
  160.                       category __cat)
  161.   {
  162.     __cat = _S_normalize_category(__cat);  
  163.     _M_impl = new _Impl(*__base._M_impl, 1);  
  164.  
  165.     __try
  166.       { _M_impl->_M_replace_categories(__add._M_impl, __cat); }
  167.     __catch(...)
  168.       {
  169.         _M_impl->_M_remove_reference();
  170.         __throw_exception_again;
  171.       }
  172.   }
  173.  
  174. const int num_facets = _GLIBCXX_NUM_FACETS + _GLIBCXX_NUM_UNICODE_FACETS
  175.   + (_GLIBCXX_USE_DUAL_ABI ? _GLIBCXX_NUM_CXX11_FACETS : 0);
  176.  
  177.   // Construct named _Impl.
  178.   locale::_Impl::
  179.   _Impl(const char* __s, size_t __refs)
  180.   : _M_refcount(__refs), _M_facets(0), _M_facets_size(num_facets),
  181.     _M_caches(0), _M_names(0)
  182.   {
  183.     // Initialize the underlying locale model, which also checks to
  184.     // see if the given name is valid.
  185.     __c_locale __cloc;
  186.     locale::facet::_S_create_c_locale(__cloc, __s);
  187.     __c_locale __clocm = __cloc;
  188.  
  189.     __try
  190.       {
  191.         _M_facets = new const facet*[_M_facets_size]();
  192.         _M_caches = new const facet*[_M_facets_size]();
  193.         _M_names = new char*[_S_categories_size]();
  194.  
  195.         // Name the categories.
  196.         const char* __smon = __s;
  197.         const size_t __len = std::strlen(__s);
  198.         if (!std::memchr(__s, ';', __len))
  199.           {
  200.             _M_names[0] = new char[__len + 1];
  201.             std::memcpy(_M_names[0], __s, __len + 1);
  202.           }
  203.         else
  204.           {
  205.             const char* __end = __s;
  206.             bool __found_ctype = false;
  207.             bool __found_monetary = false;
  208.             size_t __ci = 0, __mi = 0;
  209.             for (size_t __i = 0; __i < _S_categories_size; ++__i)
  210.               {
  211.                 const char* __beg = std::strchr(__end + 1, '=') + 1;
  212.                 __end = std::strchr(__beg, ';');
  213.                 if (!__end)
  214.                   __end = __s + __len;
  215.                 _M_names[__i] = new char[__end - __beg + 1];
  216.                 std::memcpy(_M_names[__i], __beg, __end - __beg);
  217.                 _M_names[__i][__end - __beg] = '\0';
  218.                 if (!__found_ctype
  219.                     && *(__beg - 2) == 'E' && *(__beg - 3) == 'P')
  220.                   {
  221.                     __found_ctype = true;
  222.                     __ci = __i;
  223.                   }
  224.                 else if (!__found_monetary && *(__beg - 2) == 'Y')
  225.                   {
  226.                     __found_monetary = true;
  227.                     __mi = __i;
  228.                   }
  229.               }
  230.  
  231.             if (std::strcmp(_M_names[__ci], _M_names[__mi]))
  232.               {
  233.                 __smon = _M_names[__mi];
  234.                 __clocm = locale::facet::_S_lc_ctype_c_locale(__cloc,
  235.                                                               __smon);
  236.               }
  237.           }
  238.  
  239.         // Construct all standard facets and add them to _M_facets.
  240.         _M_init_facet(new std::ctype<char>(__cloc, 0, false));
  241.         _M_init_facet(new codecvt<char, char, mbstate_t>(__cloc));
  242.         _M_init_facet(new numpunct<char>(__cloc));
  243.         _M_init_facet(new num_get<char>);
  244.         _M_init_facet(new num_put<char>);
  245.         _M_init_facet(new std::collate<char>(__cloc));
  246.         _M_init_facet(new moneypunct<char, false>(__cloc, 0));
  247.         _M_init_facet(new moneypunct<char, true>(__cloc, 0));
  248.         _M_init_facet(new money_get<char>);
  249.         _M_init_facet(new money_put<char>);
  250.         _M_init_facet(new __timepunct<char>(__cloc, __s));
  251.         _M_init_facet(new time_get<char>);
  252.         _M_init_facet(new time_put<char>);
  253.         _M_init_facet(new std::messages<char>(__cloc, __s));
  254.        
  255. #ifdef  _GLIBCXX_USE_WCHAR_T
  256.         _M_init_facet(new std::ctype<wchar_t>(__cloc));
  257.         _M_init_facet(new codecvt<wchar_t, char, mbstate_t>(__cloc));
  258.         _M_init_facet(new numpunct<wchar_t>(__cloc));
  259.         _M_init_facet(new num_get<wchar_t>);
  260.         _M_init_facet(new num_put<wchar_t>);
  261.         _M_init_facet(new std::collate<wchar_t>(__cloc));
  262.         _M_init_facet(new moneypunct<wchar_t, false>(__clocm, __smon));
  263.         _M_init_facet(new moneypunct<wchar_t, true>(__clocm, __smon));
  264.         _M_init_facet(new money_get<wchar_t>);
  265.         _M_init_facet(new money_put<wchar_t>);
  266.         _M_init_facet(new __timepunct<wchar_t>(__cloc, __s));
  267.         _M_init_facet(new time_get<wchar_t>);
  268.         _M_init_facet(new time_put<wchar_t>);
  269.         _M_init_facet(new std::messages<wchar_t>(__cloc, __s));
  270. #endif   
  271.  
  272. #ifdef _GLIBCXX_USE_C99_STDINT_TR1
  273.         _M_init_facet(new codecvt<char16_t, char, mbstate_t>);
  274.         _M_init_facet(new codecvt<char32_t, char, mbstate_t>);
  275. #endif
  276.  
  277. #if _GLIBCXX_USE_DUAL_ABI
  278.         _M_init_extra(&__cloc, &__clocm, __s, __smon);
  279. #endif
  280.  
  281.         locale::facet::_S_destroy_c_locale(__cloc);
  282.         if (__clocm != __cloc)
  283.           locale::facet::_S_destroy_c_locale(__clocm);
  284.       }
  285.     __catch(...)
  286.       {
  287.         locale::facet::_S_destroy_c_locale(__cloc);
  288.         if (__clocm != __cloc)
  289.           locale::facet::_S_destroy_c_locale(__clocm);
  290.         this->~_Impl();
  291.         __throw_exception_again;
  292.       }
  293.   }
  294.  
  295.   void
  296.   locale::_Impl::
  297.   _M_replace_categories(const _Impl* __imp, category __cat)
  298.   {
  299.     category __mask = 1;
  300.     if (!_M_names[0] || !__imp->_M_names[0])
  301.       {
  302.         if (_M_names[0])
  303.           {
  304.             delete [] _M_names[0];
  305.             _M_names[0] = 0;   // Unnamed.
  306.           }
  307.  
  308.         for (size_t __ix = 0; __ix < _S_categories_size; ++__ix, __mask <<= 1)
  309.           {
  310.             if (__mask & __cat)
  311.               // Need to replace entry in _M_facets with other locale's info.
  312.               _M_replace_category(__imp, _S_facet_categories[__ix]);
  313.           }
  314.       }
  315.     else
  316.       {
  317.         if (!_M_names[1])
  318.           {
  319.             // A full set of _M_names must be prepared, all identical
  320.             // to _M_names[0] to begin with. Then, below, a few will
  321.             // be replaced by the corresponding __imp->_M_names. I.e.,
  322.             // not a "simple" locale anymore (see locale::operator==).
  323.             const size_t __len = std::strlen(_M_names[0]) + 1;
  324.             for (size_t __i = 1; __i < _S_categories_size; ++__i)
  325.               {
  326.                 _M_names[__i] = new char[__len];
  327.                 std::memcpy(_M_names[__i], _M_names[0], __len);
  328.               }
  329.           }
  330.  
  331.         for (size_t __ix = 0; __ix < _S_categories_size; ++__ix, __mask <<= 1)
  332.           {
  333.             if (__mask & __cat)
  334.               {
  335.                 // Need to replace entry in _M_facets with other locale's info.
  336.                 _M_replace_category(__imp, _S_facet_categories[__ix]);
  337.  
  338.                 // FIXME: Hack for libstdc++/29217: the numerical encodings
  339.                 // of the time and collate categories are swapped vs the
  340.                 // order of the names in locale::_S_categories.  We'd like to
  341.                 // adjust the former (the latter is dictated by compatibility
  342.                 // with glibc) but we can't for binary compatibility.
  343.                 size_t __ix_name = __ix;
  344.                 if (__ix == 2 || __ix == 3)
  345.                   __ix_name = 5 - __ix;
  346.  
  347.                 char* __src = __imp->_M_names[__ix_name] ?
  348.                               __imp->_M_names[__ix_name] : __imp->_M_names[0];
  349.                 const size_t __len = std::strlen(__src) + 1;
  350.                 char* __new = new char[__len];
  351.                 std::memcpy(__new, __src, __len);
  352.                 delete [] _M_names[__ix_name];
  353.                 _M_names[__ix_name] = __new;
  354.               }
  355.           }
  356.       }
  357.   }
  358.  
  359. _GLIBCXX_END_NAMESPACE_VERSION
  360. } // namespace
  361.