xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/config/locale/dragonfly/c_locale.cc (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1 // localization implementation details, DragonFly version -*- C++ -*-
2 
3 // Copyright (C) 2014-2020 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 // Modified for DragonFly by John Marino <gnugcc@marino.st>
31 // Modified for NetBSD by Christos Zoulas <christos@zoulas.com> and
32 // matthew green <mrg@eterna.com.au>
33 
34 #include <cstdlib>
35 #include <locale>
36 #include <stdexcept>
37 #include <limits>
38 #include <langinfo.h>
39 #ifndef __NetBSD__
40 #include <xlocale.h>
41 #endif
42 
43 namespace std _GLIBCXX_VISIBILITY(default)
44 {
45 _GLIBCXX_BEGIN_NAMESPACE_VERSION
46 
47   template<>
48     void
__convert_to_v(const char * __s,float & __v,ios_base::iostate & __err,const __c_locale & __cloc)49     __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err,
50 		   const __c_locale& __cloc) throw()
51     {
52       char* __sanity;
53       __v = strtof_l(__s, &__sanity, (locale_t)__cloc);
54 
55       // _GLIBCXX_RESOLVE_LIB_DEFECTS
56       // 23. Num_get overflow result.
57       if (__sanity == __s || *__sanity != '\0')
58 	{
59 	  __v = 0.0f;
60 	  __err = ios_base::failbit;
61 	}
62       else if (__v == numeric_limits<float>::infinity())
63 	{
64 	  __v = numeric_limits<float>::max();
65 	  __err = ios_base::failbit;
66 	}
67       else if (__v == -numeric_limits<float>::infinity())
68 	{
69 	  __v = -numeric_limits<float>::max();
70 	  __err = ios_base::failbit;
71 	}
72     }
73 
74   template<>
75     void
__convert_to_v(const char * __s,double & __v,ios_base::iostate & __err,const __c_locale & __cloc)76     __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err,
77 		   const __c_locale& __cloc) throw()
78     {
79       char* __sanity;
80       __v = strtod_l(__s, &__sanity, (locale_t)__cloc);
81 
82       // _GLIBCXX_RESOLVE_LIB_DEFECTS
83       // 23. Num_get overflow result.
84       if (__sanity == __s || *__sanity != '\0')
85 	{
86 	  __v = 0.0;
87 	  __err = ios_base::failbit;
88 	}
89       else if (__v == numeric_limits<double>::infinity())
90 	{
91 	  __v = numeric_limits<double>::max();
92 	  __err = ios_base::failbit;
93 	}
94       else if (__v == -numeric_limits<double>::infinity())
95 	{
96 	  __v = -numeric_limits<double>::max();
97 	  __err = ios_base::failbit;
98 	}
99     }
100 
101   template<>
102     void
__convert_to_v(const char * __s,long double & __v,ios_base::iostate & __err,const __c_locale & __cloc)103     __convert_to_v(const char* __s, long double& __v, ios_base::iostate& __err,
104 		   const __c_locale& __cloc) throw()
105     {
106       char* __sanity;
107       __v = strtold_l(__s, &__sanity, (locale_t)__cloc);
108 
109       // _GLIBCXX_RESOLVE_LIB_DEFECTS
110       // 23. Num_get overflow result.
111       if (__sanity == __s || *__sanity != '\0')
112 	{
113 	  __v = 0.0l;
114 	  __err = ios_base::failbit;
115 	}
116       else if (__v == numeric_limits<long double>::infinity())
117 	{
118 	  __v = numeric_limits<long double>::max();
119 	  __err = ios_base::failbit;
120 	}
121       else if (__v == -numeric_limits<long double>::infinity())
122 	{
123 	  __v = -numeric_limits<long double>::max();
124 	  __err = ios_base::failbit;
125 	}
126     }
127 
128   void
_S_create_c_locale(__c_locale & __cloc,const char * __s,__c_locale __old)129   locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s,
130 				    __c_locale __old)
131   {
132     __cloc = (__c_locale)newlocale(LC_ALL_MASK, __s, (locale_t)__old);
133     if (!__cloc)
134       {
135 	// This named locale is not supported by the underlying OS.
136 	__throw_runtime_error(__N("locale::facet::_S_create_c_locale "
137 				  "name not valid"));
138       }
139   }
140 
141   void
_S_destroy_c_locale(__c_locale & __cloc)142   locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
143   {
144     if (__cloc && _S_get_c_locale() != __cloc)
145       freelocale((locale_t)__cloc);
146   }
147 
148   __c_locale
_S_clone_c_locale(__c_locale & __cloc)149   locale::facet::_S_clone_c_locale(__c_locale& __cloc) throw()
150   { return (__c_locale)duplocale((locale_t)__cloc); }
151 
152   __c_locale
_S_lc_ctype_c_locale(__c_locale __cloc,const char * __s)153   locale::facet::_S_lc_ctype_c_locale(__c_locale __cloc, const char* __s)
154   {
155     __c_locale __dup = (__c_locale)duplocale((locale_t)__cloc);
156     if (__dup == __c_locale(0))
157       __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale "
158 				"duplocale error"));
159     __c_locale __changed = (__c_locale)newlocale(LC_CTYPE_MASK, __s,
160 						 (locale_t)__dup);
161     if (__changed == __c_locale(0))
162       {
163 	freelocale((locale_t)__dup);
164 	__throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale "
165 				  "newlocale error"));
166       }
167     return __changed;
168   }
169 
170 _GLIBCXX_END_NAMESPACE_VERSION
171 } // namespace
172 
173 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
174 {
175 _GLIBCXX_BEGIN_NAMESPACE_VERSION
176 
177   const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
178     {
179       "LC_CTYPE",
180       "LC_NUMERIC",
181       "LC_TIME",
182       "LC_COLLATE",
183       "LC_MONETARY",
184       "LC_MESSAGES"
185     };
186 
187 _GLIBCXX_END_NAMESPACE_VERSION
188 } // namespace
189 
190 namespace std _GLIBCXX_VISIBILITY(default)
191 {
192 _GLIBCXX_BEGIN_NAMESPACE_VERSION
193 
194   const char* const* const locale::_S_categories = __gnu_cxx::category_names;
195 
196 #ifdef __NetBSD__
197   int
__convert_from_v(const __c_locale & __cloc,char * __out,const int __size,const char * __fmt,...)198   __convert_from_v(const __c_locale& __cloc, char* __out,
199 		   const int __size __attribute__ ((__unused__)),
200 		   const char* __fmt, ...)
201   {
202     __builtin_va_list __args;
203     __builtin_va_start(__args, __fmt);
204 
205     const int __ret = vsnprintf_l(__out, __size, (struct _locale *)__cloc,
206       __fmt, __args);
207 
208     __builtin_va_end(__args);
209 
210     return __ret;
211   }
212 #endif
213 
214 _GLIBCXX_END_NAMESPACE_VERSION
215 } // namespace
216 
217 // XXX GLIBCXX_ABI Deprecated
218 #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT
219 #define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \
220   extern "C" void ldbl (void) __attribute__ ((alias (#dbl)))
221 _GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKP15__locale_struct, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKP15__locale_struct);
222 #endif // _GLIBCXX_LONG_DOUBLE_COMPAT
223