1 // Wrapper for underlying C-language localization -*- C++ -*-
2 
3 // Copyright (C) 2001-2019 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   namespace
48   {
49     struct _Save_errno
50     {
_Save_errnostd::__anona28cee670111::_Save_errno51       _Save_errno() : _M_errno(errno) { errno = 0; }
~_Save_errnostd::__anona28cee670111::_Save_errno52       ~_Save_errno() { if (errno == 0) errno = _M_errno; }
53       int _M_errno;
54     };
55   }
56 
57   template<>
58     void
__convert_to_v(const char * __s,float & __v,ios_base::iostate & __err,const __c_locale &)59     __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err,
60 		   const __c_locale&) throw()
61     {
62       // Assumes __s formatted for "C" locale.
63       char* __old = setlocale(LC_ALL, 0);
64       const size_t __len = strlen(__old) + 1;
65       char* __sav = new char[__len];
66       memcpy(__sav, __old, __len);
67       setlocale(LC_ALL, "C");
68       char* __sanity;
69       bool __overflow = false;
70 
71 #if !__FLT_HAS_INFINITY__
72       const _Save_errno __save_errno;
73 #endif
74 
75 #ifdef _GLIBCXX_HAVE_STRTOF
76       __v = strtof(__s, &__sanity);
77 #else
78       double __d = strtod(__s, &__sanity);
79       __v = static_cast<float>(__d);
80 #ifdef _GLIBCXX_HAVE_FINITEF
81       if (!finitef (__v))
82 	__overflow = true;
83 #elif defined (_GLIBCXX_HAVE_FINITE)
84       if (!finite (static_cast<double> (__v)))
85 	__overflow = true;
86 #elif defined (_GLIBCXX_HAVE_ISINF)
87       if (isinf (static_cast<double> (__v)))
88 	__overflow = true;
89 #else
90       if (fabs(__d) > numeric_limits<float>::max())
91 	__overflow = true;
92 #endif
93 #endif // _GLIBCXX_HAVE_STRTOF
94 
95       // _GLIBCXX_RESOLVE_LIB_DEFECTS
96       // 23. Num_get overflow result.
97       if (__sanity == __s || *__sanity != '\0')
98 	{
99 	  __v = 0.0f;
100 	  __err = ios_base::failbit;
101 	}
102       else if (__overflow
103 #if __FLT_HAS_INFINITY__
104 	       || __v == numeric_limits<float>::infinity()
105 	       || __v == -numeric_limits<float>::infinity()
106 #else
107 	       || ((__v > 1.0f || __v < -1.0f) && errno == ERANGE)
108 #endif
109 	      )
110 	{
111 	  if (__v > 0.0f)
112 	    __v = numeric_limits<float>::max();
113 	  else
114 	    __v = -numeric_limits<float>::max();
115 	  __err = ios_base::failbit;
116 	}
117 
118       setlocale(LC_ALL, __sav);
119       delete [] __sav;
120     }
121 
122   template<>
123     void
__convert_to_v(const char * __s,double & __v,ios_base::iostate & __err,const __c_locale &)124     __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err,
125 		   const __c_locale&) throw()
126     {
127       // Assumes __s formatted for "C" locale.
128       char* __old = setlocale(LC_ALL, 0);
129       const size_t __len = strlen(__old) + 1;
130       char* __sav = new char[__len];
131       memcpy(__sav, __old, __len);
132       setlocale(LC_ALL, "C");
133       char* __sanity;
134 
135 #if !__DBL_HAS_INFINITY__
136       const _Save_errno __save_errno;
137 #endif
138 
139       __v = strtod(__s, &__sanity);
140 
141       // _GLIBCXX_RESOLVE_LIB_DEFECTS
142       // 23. Num_get overflow result.
143       if (__sanity == __s || *__sanity != '\0')
144 	{
145 	  __v = 0.0;
146 	  __err = ios_base::failbit;
147 	}
148       else if (
149 #if __DBL_HAS_INFINITY__
150 	       __v == numeric_limits<double>::infinity()
151 	       || __v == -numeric_limits<double>::infinity())
152 #else
153 	       (__v > 1.0 || __v < -1.0) && errno == ERANGE)
154 #endif
155 	{
156 	  if (__v > 0.0)
157 	    __v = numeric_limits<double>::max();
158 	  else
159 	    __v = -numeric_limits<double>::max();
160 	  __err = ios_base::failbit;
161 	}
162 
163       setlocale(LC_ALL, __sav);
164       delete [] __sav;
165     }
166 
167   template<>
168     void
__convert_to_v(const char * __s,long double & __v,ios_base::iostate & __err,const __c_locale &)169     __convert_to_v(const char* __s, long double& __v,
170 		   ios_base::iostate& __err, const __c_locale&) throw()
171     {
172       // Assumes __s formatted for "C" locale.
173       char* __old = setlocale(LC_ALL, 0);
174       const size_t __len = strlen(__old) + 1;
175       char* __sav = new char[__len];
176       memcpy(__sav, __old, __len);
177       setlocale(LC_ALL, "C");
178 
179 #if !__LDBL_HAS_INFINITY__
180       const _Save_errno __save_errno;
181 #endif
182 
183 #if defined(_GLIBCXX_HAVE_STRTOLD) && !defined(_GLIBCXX_HAVE_BROKEN_STRTOLD)
184       char* __sanity;
185       __v = strtold(__s, &__sanity);
186 
187       // _GLIBCXX_RESOLVE_LIB_DEFECTS
188       // 23. Num_get overflow result.
189       if (__sanity == __s || *__sanity != '\0')
190 #else
191       typedef char_traits<char>::int_type int_type;
192       int __p = sscanf(__s, "%Lf", &__v);
193 
194       if (!__p || static_cast<int_type>(__p) == char_traits<char>::eof())
195 #endif
196 	{
197 	  __v = 0.0l;
198 	  __err = ios_base::failbit;
199 	}
200        else if (
201 #if __LDBL_HAS_INFINITY__
202 		__v == numeric_limits<long double>::infinity()
203 		|| __v == -numeric_limits<long double>::infinity())
204 #else
205 		(__v > 1.0l || __v < -1.0l) && errno == ERANGE)
206 #endif
207 	{
208 	  if (__v > 0.0l)
209 	    __v = numeric_limits<long double>::max();
210 	  else
211 	    __v = -numeric_limits<long double>::max();
212 	  __err = ios_base::failbit;
213 	}
214 
215       setlocale(LC_ALL, __sav);
216       delete [] __sav;
217     }
218 
219   void
_S_create_c_locale(__c_locale & __cloc,const char * __s,__c_locale)220   locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s,
221 				    __c_locale)
222   {
223     // Currently, the generic model only supports the "C" locale.
224     // See http://gcc.gnu.org/ml/libstdc++/2003-02/msg00345.html
225     __cloc = 0;
226     if (strcmp(__s, "C"))
227       __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
228 			    "name not valid"));
229   }
230 
231   void
_S_destroy_c_locale(__c_locale & __cloc)232   locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
233   { __cloc = 0; }
234 
235   __c_locale
_S_clone_c_locale(__c_locale &)236   locale::facet::_S_clone_c_locale(__c_locale&) throw()
237   { return __c_locale(); }
238 
239   __c_locale
_S_lc_ctype_c_locale(__c_locale,const char *)240   locale::facet::_S_lc_ctype_c_locale(__c_locale, const char*)
241   { return __c_locale(); }
242 
243 _GLIBCXX_END_NAMESPACE_VERSION
244 } // namespace
245 
246 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
247 {
248 _GLIBCXX_BEGIN_NAMESPACE_VERSION
249 
250   const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
251     {
252       "LC_CTYPE",
253       "LC_NUMERIC",
254       "LC_TIME",
255       "LC_COLLATE",
256       "LC_MONETARY",
257       "LC_MESSAGES"
258     };
259 
260 _GLIBCXX_END_NAMESPACE_VERSION
261 } // namespace
262 
263 namespace std _GLIBCXX_VISIBILITY(default)
264 {
265 _GLIBCXX_BEGIN_NAMESPACE_VERSION
266 
267   const char* const* const locale::_S_categories = __gnu_cxx::category_names;
268 
269 _GLIBCXX_END_NAMESPACE_VERSION
270 } // namespace
271 
272 // XXX GLIBCXX_ABI Deprecated
273 #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT
274 #define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \
275   extern "C" void ldbl (void) __attribute__ ((alias (#dbl)))
276 _GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKPi, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKPi);
277 #endif // _GLIBCXX_LONG_DOUBLE_COMPAT
278