xref: /dflybsd-src/contrib/gcc-4.7/libstdc++-v3/config/locale/dragonfly/c_locale.cc (revision 0c8a28221521252cd35eb2174b0d147c136bb2db)
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