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