163d1a8abSmrg // Wrapper for underlying C-language localization -*- C++ -*-
263d1a8abSmrg 
3*ec02198aSmrg // Copyright (C) 2001-2020 Free Software Foundation, Inc.
463d1a8abSmrg //
563d1a8abSmrg // This file is part of the GNU ISO C++ Library.  This library is free
663d1a8abSmrg // software; you can redistribute it and/or modify it under the
763d1a8abSmrg // terms of the GNU General Public License as published by the
863d1a8abSmrg // Free Software Foundation; either version 3, or (at your option)
963d1a8abSmrg // any later version.
1063d1a8abSmrg 
1163d1a8abSmrg // This library is distributed in the hope that it will be useful,
1263d1a8abSmrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
1363d1a8abSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1463d1a8abSmrg // GNU General Public License for more details.
1563d1a8abSmrg 
1663d1a8abSmrg // Under Section 7 of GPL version 3, you are granted additional
1763d1a8abSmrg // permissions described in the GCC Runtime Library Exception, version
1863d1a8abSmrg // 3.1, as published by the Free Software Foundation.
1963d1a8abSmrg 
2063d1a8abSmrg // You should have received a copy of the GNU General Public License and
2163d1a8abSmrg // a copy of the GCC Runtime Library Exception along with this program;
2263d1a8abSmrg // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2363d1a8abSmrg // <http://www.gnu.org/licenses/>.
2463d1a8abSmrg 
2563d1a8abSmrg //
2663d1a8abSmrg // ISO C++ 14882: 22.8  Standard locale categories.
2763d1a8abSmrg //
2863d1a8abSmrg 
2963d1a8abSmrg // Written by Benjamin Kosnik <bkoz@redhat.com>
3063d1a8abSmrg 
3163d1a8abSmrg #include <cerrno>  // For errno
3263d1a8abSmrg #include <cmath>  // For isinf, finite, finitef, fabs
3363d1a8abSmrg #include <cstdlib>  // For strof, strtold
3463d1a8abSmrg #include <cstring>
3563d1a8abSmrg #include <cstdio>
3663d1a8abSmrg #include <locale>
3763d1a8abSmrg #include <limits>
3863d1a8abSmrg 
3963d1a8abSmrg #ifdef _GLIBCXX_HAVE_IEEEFP_H
4063d1a8abSmrg #include <ieeefp.h>
4163d1a8abSmrg #endif
4263d1a8abSmrg 
4363d1a8abSmrg namespace std _GLIBCXX_VISIBILITY(default)
4463d1a8abSmrg {
4563d1a8abSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
4663d1a8abSmrg 
4763d1a8abSmrg   namespace
4863d1a8abSmrg   {
4963d1a8abSmrg     struct _Save_errno
5063d1a8abSmrg     {
_Save_errnostd::__anonf18c3dc70111::_Save_errno5163d1a8abSmrg       _Save_errno() : _M_errno(errno) { errno = 0; }
~_Save_errnostd::__anonf18c3dc70111::_Save_errno5263d1a8abSmrg       ~_Save_errno() { if (errno == 0) errno = _M_errno; }
5363d1a8abSmrg       int _M_errno;
5463d1a8abSmrg     };
5563d1a8abSmrg   }
5663d1a8abSmrg 
5763d1a8abSmrg   template<>
5863d1a8abSmrg     void
__convert_to_v(const char * __s,float & __v,ios_base::iostate & __err,const __c_locale &)5963d1a8abSmrg     __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err,
6063d1a8abSmrg 		   const __c_locale&) throw()
6163d1a8abSmrg     {
6263d1a8abSmrg       // Assumes __s formatted for "C" locale.
6363d1a8abSmrg       char* __old = setlocale(LC_ALL, 0);
6463d1a8abSmrg       const size_t __len = strlen(__old) + 1;
6563d1a8abSmrg       char* __sav = new char[__len];
6663d1a8abSmrg       memcpy(__sav, __old, __len);
6763d1a8abSmrg       setlocale(LC_ALL, "C");
6863d1a8abSmrg       char* __sanity;
6963d1a8abSmrg       bool __overflow = false;
7063d1a8abSmrg 
7163d1a8abSmrg #if !__FLT_HAS_INFINITY__
7263d1a8abSmrg       const _Save_errno __save_errno;
7363d1a8abSmrg #endif
7463d1a8abSmrg 
7563d1a8abSmrg #ifdef _GLIBCXX_HAVE_STRTOF
7663d1a8abSmrg       __v = strtof(__s, &__sanity);
7763d1a8abSmrg #else
7863d1a8abSmrg       double __d = strtod(__s, &__sanity);
7963d1a8abSmrg       __v = static_cast<float>(__d);
8063d1a8abSmrg #ifdef _GLIBCXX_HAVE_FINITEF
8163d1a8abSmrg       if (!finitef (__v))
8263d1a8abSmrg 	__overflow = true;
8363d1a8abSmrg #elif defined (_GLIBCXX_HAVE_FINITE)
8463d1a8abSmrg       if (!finite (static_cast<double> (__v)))
8563d1a8abSmrg 	__overflow = true;
8663d1a8abSmrg #elif defined (_GLIBCXX_HAVE_ISINF)
8763d1a8abSmrg       if (isinf (static_cast<double> (__v)))
8863d1a8abSmrg 	__overflow = true;
8963d1a8abSmrg #else
9063d1a8abSmrg       if (fabs(__d) > numeric_limits<float>::max())
9163d1a8abSmrg 	__overflow = true;
9263d1a8abSmrg #endif
9363d1a8abSmrg #endif // _GLIBCXX_HAVE_STRTOF
9463d1a8abSmrg 
9563d1a8abSmrg       // _GLIBCXX_RESOLVE_LIB_DEFECTS
9663d1a8abSmrg       // 23. Num_get overflow result.
9763d1a8abSmrg       if (__sanity == __s || *__sanity != '\0')
9863d1a8abSmrg 	{
9963d1a8abSmrg 	  __v = 0.0f;
10063d1a8abSmrg 	  __err = ios_base::failbit;
10163d1a8abSmrg 	}
10263d1a8abSmrg       else if (__overflow
10363d1a8abSmrg #if __FLT_HAS_INFINITY__
10463d1a8abSmrg 	       || __v == numeric_limits<float>::infinity()
10563d1a8abSmrg 	       || __v == -numeric_limits<float>::infinity()
10663d1a8abSmrg #else
10763d1a8abSmrg 	       || ((__v > 1.0f || __v < -1.0f) && errno == ERANGE)
10863d1a8abSmrg #endif
10963d1a8abSmrg 	      )
11063d1a8abSmrg 	{
11163d1a8abSmrg 	  if (__v > 0.0f)
11263d1a8abSmrg 	    __v = numeric_limits<float>::max();
11363d1a8abSmrg 	  else
11463d1a8abSmrg 	    __v = -numeric_limits<float>::max();
11563d1a8abSmrg 	  __err = ios_base::failbit;
11663d1a8abSmrg 	}
11763d1a8abSmrg 
11863d1a8abSmrg       setlocale(LC_ALL, __sav);
11963d1a8abSmrg       delete [] __sav;
12063d1a8abSmrg     }
12163d1a8abSmrg 
12263d1a8abSmrg   template<>
12363d1a8abSmrg     void
__convert_to_v(const char * __s,double & __v,ios_base::iostate & __err,const __c_locale &)12463d1a8abSmrg     __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err,
12563d1a8abSmrg 		   const __c_locale&) throw()
12663d1a8abSmrg     {
12763d1a8abSmrg       // Assumes __s formatted for "C" locale.
12863d1a8abSmrg       char* __old = setlocale(LC_ALL, 0);
12963d1a8abSmrg       const size_t __len = strlen(__old) + 1;
13063d1a8abSmrg       char* __sav = new char[__len];
13163d1a8abSmrg       memcpy(__sav, __old, __len);
13263d1a8abSmrg       setlocale(LC_ALL, "C");
13363d1a8abSmrg       char* __sanity;
13463d1a8abSmrg 
13563d1a8abSmrg #if !__DBL_HAS_INFINITY__
13663d1a8abSmrg       const _Save_errno __save_errno;
13763d1a8abSmrg #endif
13863d1a8abSmrg 
13963d1a8abSmrg       __v = strtod(__s, &__sanity);
14063d1a8abSmrg 
14163d1a8abSmrg       // _GLIBCXX_RESOLVE_LIB_DEFECTS
14263d1a8abSmrg       // 23. Num_get overflow result.
14363d1a8abSmrg       if (__sanity == __s || *__sanity != '\0')
14463d1a8abSmrg 	{
14563d1a8abSmrg 	  __v = 0.0;
14663d1a8abSmrg 	  __err = ios_base::failbit;
14763d1a8abSmrg 	}
14863d1a8abSmrg       else if (
14963d1a8abSmrg #if __DBL_HAS_INFINITY__
15063d1a8abSmrg 	       __v == numeric_limits<double>::infinity()
15163d1a8abSmrg 	       || __v == -numeric_limits<double>::infinity())
15263d1a8abSmrg #else
15363d1a8abSmrg 	       (__v > 1.0 || __v < -1.0) && errno == ERANGE)
15463d1a8abSmrg #endif
15563d1a8abSmrg 	{
15663d1a8abSmrg 	  if (__v > 0.0)
15763d1a8abSmrg 	    __v = numeric_limits<double>::max();
15863d1a8abSmrg 	  else
15963d1a8abSmrg 	    __v = -numeric_limits<double>::max();
16063d1a8abSmrg 	  __err = ios_base::failbit;
16163d1a8abSmrg 	}
16263d1a8abSmrg 
16363d1a8abSmrg       setlocale(LC_ALL, __sav);
16463d1a8abSmrg       delete [] __sav;
16563d1a8abSmrg     }
16663d1a8abSmrg 
16763d1a8abSmrg   template<>
16863d1a8abSmrg     void
__convert_to_v(const char * __s,long double & __v,ios_base::iostate & __err,const __c_locale &)16963d1a8abSmrg     __convert_to_v(const char* __s, long double& __v,
17063d1a8abSmrg 		   ios_base::iostate& __err, const __c_locale&) throw()
17163d1a8abSmrg     {
17263d1a8abSmrg       // Assumes __s formatted for "C" locale.
17363d1a8abSmrg       char* __old = setlocale(LC_ALL, 0);
17463d1a8abSmrg       const size_t __len = strlen(__old) + 1;
17563d1a8abSmrg       char* __sav = new char[__len];
17663d1a8abSmrg       memcpy(__sav, __old, __len);
17763d1a8abSmrg       setlocale(LC_ALL, "C");
17863d1a8abSmrg 
17963d1a8abSmrg #if !__LDBL_HAS_INFINITY__
18063d1a8abSmrg       const _Save_errno __save_errno;
18163d1a8abSmrg #endif
18263d1a8abSmrg 
18363d1a8abSmrg #if defined(_GLIBCXX_HAVE_STRTOLD) && !defined(_GLIBCXX_HAVE_BROKEN_STRTOLD)
18463d1a8abSmrg       char* __sanity;
18563d1a8abSmrg       __v = strtold(__s, &__sanity);
18663d1a8abSmrg 
18763d1a8abSmrg       // _GLIBCXX_RESOLVE_LIB_DEFECTS
18863d1a8abSmrg       // 23. Num_get overflow result.
18963d1a8abSmrg       if (__sanity == __s || *__sanity != '\0')
19063d1a8abSmrg #else
19163d1a8abSmrg       typedef char_traits<char>::int_type int_type;
19263d1a8abSmrg       int __p = sscanf(__s, "%Lf", &__v);
19363d1a8abSmrg 
19463d1a8abSmrg       if (!__p || static_cast<int_type>(__p) == char_traits<char>::eof())
19563d1a8abSmrg #endif
19663d1a8abSmrg 	{
19763d1a8abSmrg 	  __v = 0.0l;
19863d1a8abSmrg 	  __err = ios_base::failbit;
19963d1a8abSmrg 	}
20063d1a8abSmrg        else if (
20163d1a8abSmrg #if __LDBL_HAS_INFINITY__
20263d1a8abSmrg 		__v == numeric_limits<long double>::infinity()
20363d1a8abSmrg 		|| __v == -numeric_limits<long double>::infinity())
20463d1a8abSmrg #else
20563d1a8abSmrg 		(__v > 1.0l || __v < -1.0l) && errno == ERANGE)
20663d1a8abSmrg #endif
20763d1a8abSmrg 	{
20863d1a8abSmrg 	  if (__v > 0.0l)
20963d1a8abSmrg 	    __v = numeric_limits<long double>::max();
21063d1a8abSmrg 	  else
21163d1a8abSmrg 	    __v = -numeric_limits<long double>::max();
21263d1a8abSmrg 	  __err = ios_base::failbit;
21363d1a8abSmrg 	}
21463d1a8abSmrg 
21563d1a8abSmrg       setlocale(LC_ALL, __sav);
21663d1a8abSmrg       delete [] __sav;
21763d1a8abSmrg     }
21863d1a8abSmrg 
21963d1a8abSmrg   void
_S_create_c_locale(__c_locale & __cloc,const char * __s,__c_locale)22063d1a8abSmrg   locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s,
22163d1a8abSmrg 				    __c_locale)
22263d1a8abSmrg   {
22363d1a8abSmrg     // Currently, the generic model only supports the "C" locale.
22463d1a8abSmrg     // See http://gcc.gnu.org/ml/libstdc++/2003-02/msg00345.html
22563d1a8abSmrg     __cloc = 0;
22663d1a8abSmrg     if (strcmp(__s, "C"))
22763d1a8abSmrg       __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
22863d1a8abSmrg 			    "name not valid"));
22963d1a8abSmrg   }
23063d1a8abSmrg 
23163d1a8abSmrg   void
_S_destroy_c_locale(__c_locale & __cloc)23263d1a8abSmrg   locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
23363d1a8abSmrg   { __cloc = 0; }
23463d1a8abSmrg 
23563d1a8abSmrg   __c_locale
_S_clone_c_locale(__c_locale &)23663d1a8abSmrg   locale::facet::_S_clone_c_locale(__c_locale&) throw()
23763d1a8abSmrg   { return __c_locale(); }
23863d1a8abSmrg 
23963d1a8abSmrg   __c_locale
_S_lc_ctype_c_locale(__c_locale,const char *)24063d1a8abSmrg   locale::facet::_S_lc_ctype_c_locale(__c_locale, const char*)
24163d1a8abSmrg   { return __c_locale(); }
24263d1a8abSmrg 
24363d1a8abSmrg _GLIBCXX_END_NAMESPACE_VERSION
24463d1a8abSmrg } // namespace
24563d1a8abSmrg 
24663d1a8abSmrg namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
24763d1a8abSmrg {
24863d1a8abSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
24963d1a8abSmrg 
25063d1a8abSmrg   const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
25163d1a8abSmrg     {
25263d1a8abSmrg       "LC_CTYPE",
25363d1a8abSmrg       "LC_NUMERIC",
25463d1a8abSmrg       "LC_TIME",
25563d1a8abSmrg       "LC_COLLATE",
25663d1a8abSmrg       "LC_MONETARY",
25763d1a8abSmrg       "LC_MESSAGES"
25863d1a8abSmrg     };
25963d1a8abSmrg 
26063d1a8abSmrg _GLIBCXX_END_NAMESPACE_VERSION
26163d1a8abSmrg } // namespace
26263d1a8abSmrg 
26363d1a8abSmrg namespace std _GLIBCXX_VISIBILITY(default)
26463d1a8abSmrg {
26563d1a8abSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
26663d1a8abSmrg 
26763d1a8abSmrg   const char* const* const locale::_S_categories = __gnu_cxx::category_names;
26863d1a8abSmrg 
26963d1a8abSmrg _GLIBCXX_END_NAMESPACE_VERSION
27063d1a8abSmrg } // namespace
27163d1a8abSmrg 
27263d1a8abSmrg // XXX GLIBCXX_ABI Deprecated
27363d1a8abSmrg #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT
27463d1a8abSmrg #define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \
27563d1a8abSmrg   extern "C" void ldbl (void) __attribute__ ((alias (#dbl)))
27663d1a8abSmrg _GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKPi, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKPi);
27763d1a8abSmrg #endif // _GLIBCXX_LONG_DOUBLE_COMPAT
278