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