Import pre-release gcc-5.0 to new vendor branch
[dragonfly.git] / contrib / gcc-5.0 / libstdc++-v3 / config / locale / dragonfly / c_locale.cc
1 // Wrapper for underlying C-language localization -*- C++ -*-
2
3 // Copyright (C) 2014-2015 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   template<>
48     void
49     __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err,
50                    const __c_locale&) throw()
51     {
52       // Assumes __s formatted for "C" locale.
53       char* __old = setlocale(LC_ALL, 0);
54       const size_t __len = strlen(__old) + 1;
55       char* __sav = new char[__len];
56       memcpy(__sav, __old, __len);
57       setlocale(LC_ALL, "C");
58       char* __sanity;
59       bool __overflow = false;
60
61 #if !__FLT_HAS_INFINITY__
62       errno = 0;
63 #endif
64
65 #ifdef _GLIBCXX_HAVE_STRTOF
66       __v = strtof(__s, &__sanity);
67 #else
68       double __d = strtod(__s, &__sanity);
69       __v = static_cast<float>(__d);
70 #ifdef _GLIBCXX_HAVE_FINITEF
71       if (!finitef (__v))
72         __overflow = true;
73 #elif defined (_GLIBCXX_HAVE_FINITE)
74       if (!finite (static_cast<double> (__v)))
75         __overflow = true;
76 #elif defined (_GLIBCXX_HAVE_ISINF)
77       if (isinf (static_cast<double> (__v)))
78         __overflow = true;
79 #else
80       if (fabs(__d) > numeric_limits<float>::max())
81         __overflow = true;
82 #endif
83 #endif // _GLIBCXX_HAVE_STRTOF
84
85       // _GLIBCXX_RESOLVE_LIB_DEFECTS
86       // 23. Num_get overflow result.
87       if (__sanity == __s || *__sanity != '\0')
88         {
89           __v = 0.0f;
90           __err = ios_base::failbit;
91         }
92       else if (__overflow
93 #if __FLT_HAS_INFINITY__
94                || __v == numeric_limits<float>::infinity()
95                || __v == -numeric_limits<float>::infinity()
96 #else
97                || ((__v > 1.0f || __v < -1.0f) && errno == ERANGE)
98 #endif
99               )
100         {
101           if (__v > 0.0f)
102             __v = numeric_limits<float>::max();
103           else
104             __v = -numeric_limits<float>::max();
105           __err = ios_base::failbit;
106         }
107
108       setlocale(LC_ALL, __sav);
109       delete [] __sav;
110     }
111
112   template<>
113     void
114     __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err,
115                    const __c_locale&) throw()
116     {
117       // Assumes __s formatted for "C" locale.
118       char* __old = setlocale(LC_ALL, 0);
119       const size_t __len = strlen(__old) + 1;
120       char* __sav = new char[__len];
121       memcpy(__sav, __old, __len);
122       setlocale(LC_ALL, "C");
123       char* __sanity;
124
125 #if !__DBL_HAS_INFINITY__
126       errno = 0;
127 #endif
128
129       __v = strtod(__s, &__sanity);
130
131       // _GLIBCXX_RESOLVE_LIB_DEFECTS
132       // 23. Num_get overflow result.
133       if (__sanity == __s || *__sanity != '\0')
134         {
135           __v = 0.0;
136           __err = ios_base::failbit;
137         }
138       else if (
139 #if __DBL_HAS_INFINITY__
140                __v == numeric_limits<double>::infinity()
141                || __v == -numeric_limits<double>::infinity())
142 #else
143                (__v > 1.0 || __v < -1.0) && errno == ERANGE)
144 #endif
145         {
146           if (__v > 0.0)
147             __v = numeric_limits<double>::max();
148           else
149             __v = -numeric_limits<double>::max();
150           __err = ios_base::failbit;
151         }
152
153       setlocale(LC_ALL, __sav);
154       delete [] __sav;
155     }
156
157   template<>
158     void
159     __convert_to_v(const char* __s, long double& __v,
160                    ios_base::iostate& __err, const __c_locale&) throw()
161     {
162       // Assumes __s formatted for "C" locale.
163       char* __old = setlocale(LC_ALL, 0);
164       const size_t __len = strlen(__old) + 1;
165       char* __sav = new char[__len];
166       memcpy(__sav, __old, __len);
167       setlocale(LC_ALL, "C");
168
169 #if !__LDBL_HAS_INFINITY__
170       errno = 0;
171 #endif
172
173 #if defined(_GLIBCXX_HAVE_STRTOLD) && !defined(_GLIBCXX_HAVE_BROKEN_STRTOLD)
174       char* __sanity;
175       __v = strtold(__s, &__sanity);
176
177       // _GLIBCXX_RESOLVE_LIB_DEFECTS
178       // 23. Num_get overflow result.
179       if (__sanity == __s || *__sanity != '\0')
180 #else
181       typedef char_traits<char>::int_type int_type;
182       int __p = sscanf(__s, "%Lf", &__v);
183
184       if (!__p || static_cast<int_type>(__p) == char_traits<char>::eof())
185 #endif
186         {
187           __v = 0.0l;
188           __err = ios_base::failbit;
189         }
190        else if (
191 #if __LDBL_HAS_INFINITY__
192                 __v == numeric_limits<long double>::infinity()
193                 || __v == -numeric_limits<long double>::infinity())
194 #else
195                 (__v > 1.0l || __v < -1.0l) && errno == ERANGE)
196 #endif
197         {
198           if (__v > 0.0l)
199             __v = numeric_limits<long double>::max();
200           else
201             __v = -numeric_limits<long double>::max();
202           __err = ios_base::failbit;
203         }
204
205       setlocale(LC_ALL, __sav);
206       delete [] __sav;
207     }
208
209
210   /*  DragonFly's implementation of setlocale won't accept something like
211       "de_DE".  According to nls manpage, the expected format is:
212       language[_territory][.codeset][@modifier], but it seems that both
213       the _territory and .codeset components are required.
214       
215       As an attempt to correct for this, we'll tack on ".UTF-8" if 
216       a period is not detected in the locale string.  
217
218       There are no locales with modifiers on DragonFly so if found, they
219       will just be stripped off silently.  e.g "de_DE@euro" will be reduced
220       to "de_DE".  The UTF-8 default would be added after that.
221   */
222
223   void
224   locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s,
225                                     __c_locale)
226   {
227     const size_t size__s = (__s == NULL) ? 1 : strlen (__s);
228     const char UTF8[] = ".UTF-8";
229     char localspec[size__s + 6 + 1];
230     
231     if (__s == NULL) {
232        localspec[0] = '\0';
233     } else {
234        strcpy (localspec, __s);
235        char * pch = strchr (localspec, '@');
236        if (pch != NULL)
237           *pch = 0;
238
239        if (  (strchr (__s, '.') == NULL)
240           && (strcmp (__s, "C") != 0)
241           && (strcmp (__s, "POSIX") != 0))
242           strncat (localspec, UTF8, 6);
243     }
244
245     const char * result = std::setlocale(LC_ALL, localspec);
246     
247     if ((strcmp(result, "C") != 0) && (strcmp (result, localspec) != 0))
248       __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
249                             "name not valid"));
250     __cloc = 0;
251   }
252
253   void
254   locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
255   { __cloc = 0; }
256
257   __c_locale
258   locale::facet::_S_clone_c_locale(__c_locale&) throw()
259   { return __c_locale(); }
260
261   __c_locale
262   locale::facet::_S_lc_ctype_c_locale(__c_locale, const char*)
263   { return __c_locale(); }
264
265 _GLIBCXX_END_NAMESPACE_VERSION
266 } // namespace
267
268 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
269 {
270 _GLIBCXX_BEGIN_NAMESPACE_VERSION
271
272   const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
273     {
274       "LC_CTYPE",
275       "LC_NUMERIC",
276       "LC_TIME",
277       "LC_COLLATE",
278       "LC_MONETARY",
279       "LC_MESSAGES"
280     };
281
282 _GLIBCXX_END_NAMESPACE_VERSION
283 } // namespace
284
285 namespace std _GLIBCXX_VISIBILITY(default)
286 {
287 _GLIBCXX_BEGIN_NAMESPACE_VERSION
288
289   const char* const* const locale::_S_categories = __gnu_cxx::category_names;
290
291 _GLIBCXX_END_NAMESPACE_VERSION
292 } // namespace
293
294 // XXX GLIBCXX_ABI Deprecated
295 #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT
296 #define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \
297   extern "C" void ldbl (void) __attribute__ ((alias (#dbl)))
298 _GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKPi, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKPi);
299 #endif // _GLIBCXX_LONG_DOUBLE_COMPAT