]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/config/locale/generic/c_locale.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / config / locale / generic / c_locale.cc
CommitLineData
0214010c
BK
1// Wrapper for underlying C-language localization -*- C++ -*-
2
83ffe9cd 3// Copyright (C) 2001-2023 Free Software Foundation, Inc.
0214010c
BK
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
748086b7 8// Free Software Foundation; either version 3, or (at your option)
0214010c
BK
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
748086b7
JJ
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/>.
0214010c
BK
24
25//
26// ISO C++ 14882: 22.8 Standard locale categories.
27//
28
29// Written by Benjamin Kosnik <bkoz@redhat.com>
30
19df3b83 31#include <cerrno> // For errno
4f363232
PC
32#include <cmath> // For isinf, finite, finitef, fabs
33#include <cstdlib> // For strof, strtold
538075fe 34#include <cstring>
4d5670aa 35#include <cstdio>
0214010c 36#include <locale>
587024cf 37#include <limits>
0214010c 38
3d7c150e 39#ifdef _GLIBCXX_HAVE_IEEEFP_H
99a4deb8
LR
40#include <ieeefp.h>
41#endif
42
12ffa228
BK
43namespace std _GLIBCXX_VISIBILITY(default)
44{
45_GLIBCXX_BEGIN_NAMESPACE_VERSION
3cbc7af0 46
f14decaf
JW
47 namespace
48 {
49 struct _Save_errno
50 {
51 _Save_errno() : _M_errno(errno) { errno = 0; }
52 ~_Save_errno() { if (errno == 0) errno = _M_errno; }
53 int _M_errno;
54 };
5dfbc522
JW
55
56 // calls setlocale(LC_ALL, "C") and returns a string containing the old
57 // locale name. Caller must delete[] the string. Returns NULL on error.
58 const char*
59 __set_C_locale()
60 {
61 char* __old = setlocale(LC_ALL, 0);
62 const size_t __len = strlen(__old) + 1;
63 char* __sav = new(nothrow) char[__len];
64 if (__sav)
65 {
66 memcpy(__sav, __old, __len);
67 setlocale(LC_ALL, "C");
68 }
69 return __sav;
70 }
f14decaf
JW
71 }
72
4b9aaf63
BK
73 template<>
74 void
32ade559
BK
75 __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err,
76 const __c_locale&) throw()
4b9aaf63 77 {
d04e9b7f 78 // Assumes __s formatted for "C" locale.
5dfbc522
JW
79 const char* __sav = __set_C_locale();
80 if (!__sav)
81 {
82 __err = ios_base::failbit;
83 return;
84 }
d04e9b7f 85 char* __sanity;
5ef46f95 86 bool __overflow = false;
19df3b83
PC
87
88#if !__FLT_HAS_INFINITY__
f14decaf 89 const _Save_errno __save_errno;
19df3b83
PC
90#endif
91
5ef46f95
PC
92#ifdef _GLIBCXX_HAVE_STRTOF
93 __v = strtof(__s, &__sanity);
4b9aaf63 94#else
d04e9b7f 95 double __d = strtod(__s, &__sanity);
5ef46f95 96 __v = static_cast<float>(__d);
3d7c150e 97#ifdef _GLIBCXX_HAVE_FINITEF
5ef46f95
PC
98 if (!finitef (__v))
99 __overflow = true;
3d7c150e 100#elif defined (_GLIBCXX_HAVE_FINITE)
5ef46f95
PC
101 if (!finite (static_cast<double> (__v)))
102 __overflow = true;
3d7c150e 103#elif defined (_GLIBCXX_HAVE_ISINF)
5ef46f95
PC
104 if (isinf (static_cast<double> (__v)))
105 __overflow = true;
99a4deb8 106#else
d04e9b7f 107 if (fabs(__d) > numeric_limits<float>::max())
5ef46f95 108 __overflow = true;
99a4deb8 109#endif
5ef46f95
PC
110#endif // _GLIBCXX_HAVE_STRTOF
111
112 // _GLIBCXX_RESOLVE_LIB_DEFECTS
113 // 23. Num_get overflow result.
114 if (__sanity == __s || *__sanity != '\0')
115 {
116 __v = 0.0f;
117 __err = ios_base::failbit;
118 }
119 else if (__overflow
120#if __FLT_HAS_INFINITY__
121 || __v == numeric_limits<float>::infinity()
ffecec4d 122 || __v == -numeric_limits<float>::infinity()
19df3b83 123#else
5ef46f95 124 || ((__v > 1.0f || __v < -1.0f) && errno == ERANGE)
19df3b83 125#endif
ffecec4d 126 )
5ef46f95
PC
127 {
128 if (__v > 0.0f)
129 __v = numeric_limits<float>::max();
130 else
131 __v = -numeric_limits<float>::max();
132 __err = ios_base::failbit;
133 }
19df3b83 134
538075fe
PC
135 setlocale(LC_ALL, __sav);
136 delete [] __sav;
4b9aaf63
BK
137 }
138
139 template<>
140 void
32ade559
BK
141 __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err,
142 const __c_locale&) throw()
4b9aaf63 143 {
d04e9b7f 144 // Assumes __s formatted for "C" locale.
5dfbc522
JW
145 const char* __sav = __set_C_locale();
146 if (!__sav)
147 {
148 __err = ios_base::failbit;
149 return;
150 }
d04e9b7f 151 char* __sanity;
19df3b83
PC
152
153#if !__DBL_HAS_INFINITY__
f14decaf 154 const _Save_errno __save_errno;
19df3b83
PC
155#endif
156
5ef46f95
PC
157 __v = strtod(__s, &__sanity);
158
159 // _GLIBCXX_RESOLVE_LIB_DEFECTS
160 // 23. Num_get overflow result.
161 if (__sanity == __s || *__sanity != '\0')
162 {
163 __v = 0.0;
164 __err = ios_base::failbit;
165 }
166 else if (
167#if __DBL_HAS_INFINITY__
168 __v == numeric_limits<double>::infinity()
169 || __v == -numeric_limits<double>::infinity())
32ade559 170#else
5ef46f95 171 (__v > 1.0 || __v < -1.0) && errno == ERANGE)
19df3b83 172#endif
5ef46f95
PC
173 {
174 if (__v > 0.0)
175 __v = numeric_limits<double>::max();
176 else
177 __v = -numeric_limits<double>::max();
178 __err = ios_base::failbit;
179 }
19df3b83 180
538075fe
PC
181 setlocale(LC_ALL, __sav);
182 delete [] __sav;
4b9aaf63
BK
183 }
184
185 template<>
186 void
32ade559
BK
187 __convert_to_v(const char* __s, long double& __v,
188 ios_base::iostate& __err, const __c_locale&) throw()
4b9aaf63 189 {
d04e9b7f 190 // Assumes __s formatted for "C" locale.
5dfbc522
JW
191 const char* __sav = __set_C_locale();
192 if (!__sav)
193 {
194 __err = ios_base::failbit;
195 return;
196 }
19df3b83
PC
197
198#if !__LDBL_HAS_INFINITY__
f14decaf 199 const _Save_errno __save_errno;
19df3b83
PC
200#endif
201
18efbe51 202#if defined(_GLIBCXX_HAVE_STRTOLD) && !defined(_GLIBCXX_HAVE_BROKEN_STRTOLD)
d04e9b7f 203 char* __sanity;
5ef46f95 204 __v = strtold(__s, &__sanity);
19df3b83 205
5ef46f95
PC
206 // _GLIBCXX_RESOLVE_LIB_DEFECTS
207 // 23. Num_get overflow result.
208 if (__sanity == __s || *__sanity != '\0')
4b9aaf63 209#else
d04e9b7f 210 typedef char_traits<char>::int_type int_type;
5ef46f95 211 int __p = sscanf(__s, "%Lf", &__v);
19df3b83 212
5ef46f95 213 if (!__p || static_cast<int_type>(__p) == char_traits<char>::eof())
19df3b83 214#endif
5ef46f95
PC
215 {
216 __v = 0.0l;
217 __err = ios_base::failbit;
218 }
219 else if (
220#if __LDBL_HAS_INFINITY__
32ade559
BK
221 __v == numeric_limits<long double>::infinity()
222 || __v == -numeric_limits<long double>::infinity())
5ef46f95 223#else
32ade559 224 (__v > 1.0l || __v < -1.0l) && errno == ERANGE)
4b9aaf63 225#endif
5ef46f95
PC
226 {
227 if (__v > 0.0l)
228 __v = numeric_limits<long double>::max();
229 else
230 __v = -numeric_limits<long double>::max();
231 __err = ios_base::failbit;
232 }
19df3b83 233
538075fe
PC
234 setlocale(LC_ALL, __sav);
235 delete [] __sav;
4b9aaf63
BK
236 }
237
0214010c 238 void
32ade559 239 locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s,
d3a193e3 240 __c_locale)
85c39c6d 241 {
988ad90d
BK
242 // Currently, the generic model only supports the "C" locale.
243 // See http://gcc.gnu.org/ml/libstdc++/2003-02/msg00345.html
445877a9 244 __cloc = 0;
3d838e28 245 if (strcmp(__s, "C"))
ba9119ec
PC
246 __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
247 "name not valid"));
85c39c6d 248 }
0214010c
BK
249
250 void
d3a193e3 251 locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
445877a9 252 { __cloc = 0; }
0214010c 253
33590f13 254 __c_locale
32ade559 255 locale::facet::_S_clone_c_locale(__c_locale&) throw()
33590f13 256 { return __c_locale(); }
aa53f832 257
c8036448
PC
258 __c_locale
259 locale::facet::_S_lc_ctype_c_locale(__c_locale, const char*)
260 { return __c_locale(); }
261
12ffa228
BK
262_GLIBCXX_END_NAMESPACE_VERSION
263} // namespace
3cbc7af0 264
12ffa228
BK
265namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
266{
267_GLIBCXX_BEGIN_NAMESPACE_VERSION
3cbc7af0 268
8ae81136 269 const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
aa53f832 270 {
32ade559 271 "LC_CTYPE",
0e9501e6 272 "LC_NUMERIC",
32ade559
BK
273 "LC_TIME",
274 "LC_COLLATE",
aa53f832
PC
275 "LC_MONETARY",
276 "LC_MESSAGES"
277 };
73c4dcc6 278
12ffa228
BK
279_GLIBCXX_END_NAMESPACE_VERSION
280} // namespace
3cbc7af0 281
12ffa228
BK
282namespace std _GLIBCXX_VISIBILITY(default)
283{
284_GLIBCXX_BEGIN_NAMESPACE_VERSION
3cbc7af0 285
8ae81136 286 const char* const* const locale::_S_categories = __gnu_cxx::category_names;
3cbc7af0 287
12ffa228
BK
288_GLIBCXX_END_NAMESPACE_VERSION
289} // namespace
6defecc2
JJ
290
291// XXX GLIBCXX_ABI Deprecated
292#ifdef _GLIBCXX_LONG_DOUBLE_COMPAT
293#define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \
294 extern "C" void ldbl (void) __attribute__ ((alias (#dbl)))
295_GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKPi, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKPi);
296#endif // _GLIBCXX_LONG_DOUBLE_COMPAT