1 // Wrapper for underlying C-language localization -*- C++ -*-
2 
3 // Copyright (C) 2001-2014 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 <locale>
32 #include <stdexcept>
33 #include <limits>
34 #include <langinfo.h>
35 #include <bits/c++locale_internal.h>
36 
37 namespace std _GLIBCXX_VISIBILITY(default)
38 {
39 _GLIBCXX_BEGIN_NAMESPACE_VERSION
40 
41   template<>
42     void
__convert_to_v(const char * __s,float & __v,ios_base::iostate & __err,const __c_locale & __cloc)43     __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err,
44 		   const __c_locale& __cloc) throw()
45     {
46       char* __sanity;
47       __v = __strtof_l(__s, &__sanity, __cloc);
48 
49       // _GLIBCXX_RESOLVE_LIB_DEFECTS
50       // 23. Num_get overflow result.
51       if (__sanity == __s || *__sanity != '\0')
52 	{
53 	  __v = 0.0f;
54 	  __err = ios_base::failbit;
55 	}
56       else if (__v == numeric_limits<float>::infinity())
57 	{
58 	  __v = numeric_limits<float>::max();
59 	  __err = ios_base::failbit;
60 	}
61       else if (__v == -numeric_limits<float>::infinity())
62 	{
63 	  __v = -numeric_limits<float>::max();
64 	  __err = ios_base::failbit;
65 	}
66     }
67 
68   template<>
69     void
__convert_to_v(const char * __s,double & __v,ios_base::iostate & __err,const __c_locale & __cloc)70     __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err,
71 		   const __c_locale& __cloc) throw()
72     {
73       char* __sanity;
74       __v = __strtod_l(__s, &__sanity, __cloc);
75 
76       // _GLIBCXX_RESOLVE_LIB_DEFECTS
77       // 23. Num_get overflow result.
78       if (__sanity == __s || *__sanity != '\0')
79 	{
80 	  __v = 0.0;
81 	  __err = ios_base::failbit;
82 	}
83       else if (__v == numeric_limits<double>::infinity())
84 	{
85 	  __v = numeric_limits<double>::max();
86 	  __err = ios_base::failbit;
87 	}
88       else if (__v == -numeric_limits<double>::infinity())
89 	{
90 	  __v = -numeric_limits<double>::max();
91 	  __err = ios_base::failbit;
92 	}
93     }
94 
95   template<>
96     void
__convert_to_v(const char * __s,long double & __v,ios_base::iostate & __err,const __c_locale & __cloc)97     __convert_to_v(const char* __s, long double& __v, ios_base::iostate& __err,
98 		   const __c_locale& __cloc) throw()
99     {
100       char* __sanity;
101 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
102       // Prefer strtold_l, as __strtold_l isn't prototyped in more recent
103       // glibc versions.
104       __v = strtold_l(__s, &__sanity, __cloc);
105 #else
106       __v = __strtold_l(__s, &__sanity, __cloc);
107 #endif
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 = __newlocale(1 << LC_ALL, __s, __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(__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 __duplocale(__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 = __duplocale(__cloc);
156     if (__dup == __c_locale(0))
157       __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale "
158 				"duplocale error"));
159 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
160     __c_locale __changed = __newlocale(LC_CTYPE_MASK, __s, __dup);
161 #else
162     __c_locale __changed = __newlocale(1 << LC_CTYPE, __s, __dup);
163 #endif
164     if (__changed == __c_locale(0))
165       {
166 	__freelocale(__dup);
167 	__throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale "
168 				  "newlocale error"));
169       }
170     return __changed;
171   }
172 
173 _GLIBCXX_END_NAMESPACE_VERSION
174 } // namespace
175 
176 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
177 {
178 _GLIBCXX_BEGIN_NAMESPACE_VERSION
179 
180   const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
181     {
182       "LC_CTYPE",
183       "LC_NUMERIC",
184       "LC_TIME",
185       "LC_COLLATE",
186       "LC_MONETARY",
187       "LC_MESSAGES",
188       "LC_PAPER",
189       "LC_NAME",
190       "LC_ADDRESS",
191       "LC_TELEPHONE",
192       "LC_MEASUREMENT",
193       "LC_IDENTIFICATION"
194     };
195 
196 _GLIBCXX_END_NAMESPACE_VERSION
197 } // namespace
198 
199 namespace std _GLIBCXX_VISIBILITY(default)
200 {
201 _GLIBCXX_BEGIN_NAMESPACE_VERSION
202 
203   const char* const* const locale::_S_categories = __gnu_cxx::category_names;
204 
205 _GLIBCXX_END_NAMESPACE_VERSION
206 } // namespace
207 
208 // XXX GLIBCXX_ABI Deprecated
209 #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT
210 #define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \
211   extern "C" void ldbl (void) __attribute__ ((alias (#dbl)))
212 _GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKP15__locale_struct, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKP15__locale_struct);
213 #endif // _GLIBCXX_LONG_DOUBLE_COMPAT
214