1 // Wrapper for underlying C-language localization -*- C++ -*- 2 3 // Copyright (C) 2001-2022 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 // 26 // ISO C++ 14882: 22.8 Standard locale categories. 27 // 28 29 // Written by Benjamin Kosnik <bkoz@redhat.com> 30 31 #include <cerrno> // For errno 32 #include <cmath> // For isinf, finite, finitef, fabs 33 #include <cstdlib> // For strof, strtold 34 #include <cstring> 35 #include <cstdio> 36 #include <locale> 37 #include <limits> 38 39 #ifdef _GLIBCXX_HAVE_IEEEFP_H 40 #include <ieeefp.h> 41 #endif 42 43 namespace std _GLIBCXX_VISIBILITY(default) 44 { 45 _GLIBCXX_BEGIN_NAMESPACE_VERSION 46 47 namespace 48 { 49 struct _Save_errno 50 { _Save_errnostd::__anon82839d040111::_Save_errno51 _Save_errno() : _M_errno(errno) { errno = 0; } ~_Save_errnostd::__anon82839d040111::_Save_errno52 ~_Save_errno() { if (errno == 0) errno = _M_errno; } 53 int _M_errno; 54 }; 55 56 // calls setlocale(LC_ALL, "C") and returns a string containing the old 57 // locale name. Caller must delete[] the string. Returns NULL on error. 58 const char* __set_C_locale()59 __set_C_locale() 60 { 61 char* __old = setlocale(LC_ALL, 0); 62 const size_t __len = strlen(__old) + 1; 63 char* __sav = new(nothrow) char[__len]; 64 if (__sav) 65 { 66 memcpy(__sav, __old, __len); 67 setlocale(LC_ALL, "C"); 68 } 69 return __sav; 70 } 71 } 72 73 template<> 74 void __convert_to_v(const char * __s,float & __v,ios_base::iostate & __err,const __c_locale &)75 __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err, 76 const __c_locale&) throw() 77 { 78 // Assumes __s formatted for "C" locale. 79 const char* __sav = __set_C_locale(); 80 if (!__sav) 81 { 82 __err = ios_base::failbit; 83 return; 84 } 85 char* __sanity; 86 bool __overflow = false; 87 88 #if !__FLT_HAS_INFINITY__ 89 const _Save_errno __save_errno; 90 #endif 91 92 #ifdef _GLIBCXX_HAVE_STRTOF 93 __v = strtof(__s, &__sanity); 94 #else 95 double __d = strtod(__s, &__sanity); 96 __v = static_cast<float>(__d); 97 #ifdef _GLIBCXX_HAVE_FINITEF 98 if (!finitef (__v)) 99 __overflow = true; 100 #elif defined (_GLIBCXX_HAVE_FINITE) 101 if (!finite (static_cast<double> (__v))) 102 __overflow = true; 103 #elif defined (_GLIBCXX_HAVE_ISINF) 104 if (isinf (static_cast<double> (__v))) 105 __overflow = true; 106 #else 107 if (fabs(__d) > numeric_limits<float>::max()) 108 __overflow = true; 109 #endif 110 #endif // _GLIBCXX_HAVE_STRTOF 111 112 // _GLIBCXX_RESOLVE_LIB_DEFECTS 113 // 23. Num_get overflow result. 114 if (__sanity == __s || *__sanity != '\0') 115 { 116 __v = 0.0f; 117 __err = ios_base::failbit; 118 } 119 else if (__overflow 120 #if __FLT_HAS_INFINITY__ 121 || __v == numeric_limits<float>::infinity() 122 || __v == -numeric_limits<float>::infinity() 123 #else 124 || ((__v > 1.0f || __v < -1.0f) && errno == ERANGE) 125 #endif 126 ) 127 { 128 if (__v > 0.0f) 129 __v = numeric_limits<float>::max(); 130 else 131 __v = -numeric_limits<float>::max(); 132 __err = ios_base::failbit; 133 } 134 135 setlocale(LC_ALL, __sav); 136 delete [] __sav; 137 } 138 139 template<> 140 void __convert_to_v(const char * __s,double & __v,ios_base::iostate & __err,const __c_locale &)141 __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err, 142 const __c_locale&) throw() 143 { 144 // Assumes __s formatted for "C" locale. 145 const char* __sav = __set_C_locale(); 146 if (!__sav) 147 { 148 __err = ios_base::failbit; 149 return; 150 } 151 char* __sanity; 152 153 #if !__DBL_HAS_INFINITY__ 154 const _Save_errno __save_errno; 155 #endif 156 157 __v = strtod(__s, &__sanity); 158 159 // _GLIBCXX_RESOLVE_LIB_DEFECTS 160 // 23. Num_get overflow result. 161 if (__sanity == __s || *__sanity != '\0') 162 { 163 __v = 0.0; 164 __err = ios_base::failbit; 165 } 166 else if ( 167 #if __DBL_HAS_INFINITY__ 168 __v == numeric_limits<double>::infinity() 169 || __v == -numeric_limits<double>::infinity()) 170 #else 171 (__v > 1.0 || __v < -1.0) && errno == ERANGE) 172 #endif 173 { 174 if (__v > 0.0) 175 __v = numeric_limits<double>::max(); 176 else 177 __v = -numeric_limits<double>::max(); 178 __err = ios_base::failbit; 179 } 180 181 setlocale(LC_ALL, __sav); 182 delete [] __sav; 183 } 184 185 template<> 186 void __convert_to_v(const char * __s,long double & __v,ios_base::iostate & __err,const __c_locale &)187 __convert_to_v(const char* __s, long double& __v, 188 ios_base::iostate& __err, const __c_locale&) throw() 189 { 190 // Assumes __s formatted for "C" locale. 191 const char* __sav = __set_C_locale(); 192 if (!__sav) 193 { 194 __err = ios_base::failbit; 195 return; 196 } 197 198 #if !__LDBL_HAS_INFINITY__ 199 const _Save_errno __save_errno; 200 #endif 201 202 #if defined(_GLIBCXX_HAVE_STRTOLD) && !defined(_GLIBCXX_HAVE_BROKEN_STRTOLD) 203 char* __sanity; 204 __v = strtold(__s, &__sanity); 205 206 // _GLIBCXX_RESOLVE_LIB_DEFECTS 207 // 23. Num_get overflow result. 208 if (__sanity == __s || *__sanity != '\0') 209 #else 210 typedef char_traits<char>::int_type int_type; 211 int __p = sscanf(__s, "%Lf", &__v); 212 213 if (!__p || static_cast<int_type>(__p) == char_traits<char>::eof()) 214 #endif 215 { 216 __v = 0.0l; 217 __err = ios_base::failbit; 218 } 219 else if ( 220 #if __LDBL_HAS_INFINITY__ 221 __v == numeric_limits<long double>::infinity() 222 || __v == -numeric_limits<long double>::infinity()) 223 #else 224 (__v > 1.0l || __v < -1.0l) && errno == ERANGE) 225 #endif 226 { 227 if (__v > 0.0l) 228 __v = numeric_limits<long double>::max(); 229 else 230 __v = -numeric_limits<long double>::max(); 231 __err = ios_base::failbit; 232 } 233 234 setlocale(LC_ALL, __sav); 235 delete [] __sav; 236 } 237 238 void _S_create_c_locale(__c_locale & __cloc,const char * __s,__c_locale)239 locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s, 240 __c_locale) 241 { 242 // Currently, the generic model only supports the "C" locale. 243 // See http://gcc.gnu.org/ml/libstdc++/2003-02/msg00345.html 244 __cloc = 0; 245 if (strcmp(__s, "C")) 246 __throw_runtime_error(__N("locale::facet::_S_create_c_locale " 247 "name not valid")); 248 } 249 250 void _S_destroy_c_locale(__c_locale & __cloc)251 locale::facet::_S_destroy_c_locale(__c_locale& __cloc) 252 { __cloc = 0; } 253 254 __c_locale _S_clone_c_locale(__c_locale &)255 locale::facet::_S_clone_c_locale(__c_locale&) throw() 256 { return __c_locale(); } 257 258 __c_locale _S_lc_ctype_c_locale(__c_locale,const char *)259 locale::facet::_S_lc_ctype_c_locale(__c_locale, const char*) 260 { return __c_locale(); } 261 262 _GLIBCXX_END_NAMESPACE_VERSION 263 } // namespace 264 265 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) 266 { 267 _GLIBCXX_BEGIN_NAMESPACE_VERSION 268 269 const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] = 270 { 271 "LC_CTYPE", 272 "LC_NUMERIC", 273 "LC_TIME", 274 "LC_COLLATE", 275 "LC_MONETARY", 276 "LC_MESSAGES" 277 }; 278 279 _GLIBCXX_END_NAMESPACE_VERSION 280 } // namespace 281 282 namespace std _GLIBCXX_VISIBILITY(default) 283 { 284 _GLIBCXX_BEGIN_NAMESPACE_VERSION 285 286 const char* const* const locale::_S_categories = __gnu_cxx::category_names; 287 288 _GLIBCXX_END_NAMESPACE_VERSION 289 } // namespace 290 291 // XXX GLIBCXX_ABI Deprecated 292 #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT 293 #define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \ 294 extern "C" void ldbl (void) __attribute__ ((alias (#dbl))) 295 _GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKPi, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKPi); 296 #endif // _GLIBCXX_LONG_DOUBLE_COMPAT 297