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