Sync psm/evdev/atkbd with FreeBSD
[dragonfly.git] / contrib / gcc-4.7 / libstdc++-v3 / config / locale / dragonfly / c_locale.cc
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