1*38fd1498Szrj // Locale support -*- C++ -*-
2*38fd1498Szrj 
3*38fd1498Szrj // Copyright (C) 2014-2018 Free Software Foundation, Inc.
4*38fd1498Szrj //
5*38fd1498Szrj // This file is part of the GNU ISO C++ Library.  This library is free
6*38fd1498Szrj // software; you can redistribute it and/or modify it under the
7*38fd1498Szrj // terms of the GNU General Public License as published by the
8*38fd1498Szrj // Free Software Foundation; either version 3, or (at your option)
9*38fd1498Szrj // any later version.
10*38fd1498Szrj 
11*38fd1498Szrj // This library is distributed in the hope that it will be useful,
12*38fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*38fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*38fd1498Szrj // GNU General Public License for more details.
15*38fd1498Szrj 
16*38fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional
17*38fd1498Szrj // permissions described in the GCC Runtime Library Exception, version
18*38fd1498Szrj // 3.1, as published by the Free Software Foundation.
19*38fd1498Szrj 
20*38fd1498Szrj // You should have received a copy of the GNU General Public License and
21*38fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program;
22*38fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23*38fd1498Szrj // <http://www.gnu.org/licenses/>.
24*38fd1498Szrj 
25*38fd1498Szrj //
26*38fd1498Szrj // ISO C++ 14882: 22.1  Locales
27*38fd1498Szrj //
28*38fd1498Szrj 
29*38fd1498Szrj // This file defines classes that behave like the standard predefined locale
30*38fd1498Szrj // facets (collate, money_get etc.) except that they forward all virtual
31*38fd1498Szrj // functions to another facet which uses a different std::string ABI,
32*38fd1498Szrj // converting between string types as needed.
33*38fd1498Szrj // When a user replaces one of the relevant facets the corresponding shim in
34*38fd1498Szrj // this file is used so that the replacement facet can be used (via the shim)
35*38fd1498Szrj // in code that uses the other std::string ABI from the replacing code.
36*38fd1498Szrj 
37*38fd1498Szrj #ifndef _GLIBCXX_USE_CXX11_ABI
38*38fd1498Szrj # define _GLIBCXX_USE_CXX11_ABI 1
39*38fd1498Szrj #endif
40*38fd1498Szrj #include <locale>
41*38fd1498Szrj 
42*38fd1498Szrj #if ! _GLIBCXX_USE_DUAL_ABI
43*38fd1498Szrj # error This file should not be compiled for this configuration.
44*38fd1498Szrj #endif
45*38fd1498Szrj 
46*38fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default)
47*38fd1498Szrj {
48*38fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
49*38fd1498Szrj 
50*38fd1498Szrj   // Base class of facet shims, holds a reference to the underlying facet
51*38fd1498Szrj   // that the shim forwards to.
52*38fd1498Szrj   class locale::facet::__shim
53*38fd1498Szrj   {
54*38fd1498Szrj   public:
_M_get() const55*38fd1498Szrj     const facet* _M_get() const { return _M_facet; }
56*38fd1498Szrj 
57*38fd1498Szrj     __shim(const __shim&) = delete;
58*38fd1498Szrj     __shim& operator=(const __shim&) = delete;
59*38fd1498Szrj 
60*38fd1498Szrj   protected:
61*38fd1498Szrj     explicit
__shim(const facet * __f)62*38fd1498Szrj     __shim(const facet* __f) : _M_facet(__f) { __f->_M_add_reference(); }
63*38fd1498Szrj 
~__shim()64*38fd1498Szrj     ~__shim() { _M_facet->_M_remove_reference(); }
65*38fd1498Szrj 
66*38fd1498Szrj   private:
67*38fd1498Szrj     const facet* _M_facet;
68*38fd1498Szrj   };
69*38fd1498Szrj 
70*38fd1498Szrj namespace __facet_shims
71*38fd1498Szrj {
72*38fd1498Szrj   namespace // unnamed
73*38fd1498Szrj   {
74*38fd1498Szrj     template<typename C>
__destroy_string(void * p)75*38fd1498Szrj       void __destroy_string(void* p)
76*38fd1498Szrj       {
77*38fd1498Szrj 	static_cast<std::basic_string<C>*>(p)->~basic_string();
78*38fd1498Szrj       }
79*38fd1498Szrj   } // namespace
80*38fd1498Szrj 
81*38fd1498Szrj   // Manages a buffer of uninitialized memory that can store a std::string
82*38fd1498Szrj   // or std::wstring, using either ABI, and convert to the other ABI.
83*38fd1498Szrj   class __any_string
84*38fd1498Szrj   {
85*38fd1498Szrj     struct __attribute__((may_alias)) __str_rep
86*38fd1498Szrj     {
87*38fd1498Szrj       union {
88*38fd1498Szrj 	const void* _M_p;
89*38fd1498Szrj 	char* _M_pc;
90*38fd1498Szrj #ifdef _GLIBCXX_USE_WCHAR_T
91*38fd1498Szrj 	wchar_t* _M_pwc;
92*38fd1498Szrj #endif
93*38fd1498Szrj       };
94*38fd1498Szrj       size_t _M_len;
95*38fd1498Szrj       char _M_unused[16];
96*38fd1498Szrj 
operator const char*std::__facet_shims::__any_string::__str_rep97*38fd1498Szrj       operator const char*() const { return _M_pc; }
98*38fd1498Szrj #ifdef _GLIBCXX_USE_WCHAR_T
operator const wchar_t*std::__facet_shims::__any_string::__str_rep99*38fd1498Szrj       operator const wchar_t*() const { return _M_pwc; }
100*38fd1498Szrj #endif
101*38fd1498Szrj     };
102*38fd1498Szrj     union {
103*38fd1498Szrj       __str_rep _M_str;
104*38fd1498Szrj       char _M_bytes[sizeof(__str_rep)];
105*38fd1498Szrj     };
106*38fd1498Szrj     using __dtor_func = void(*)(void*);
107*38fd1498Szrj     __dtor_func _M_dtor = nullptr;
108*38fd1498Szrj 
109*38fd1498Szrj #if _GLIBCXX_USE_CXX11_ABI
110*38fd1498Szrj     // SSO strings overlay the entire __str_rep structure.
111*38fd1498Szrj     static_assert(sizeof(std::string) == sizeof(__str_rep),
112*38fd1498Szrj 		  "std::string changed size!");
113*38fd1498Szrj #else
114*38fd1498Szrj     // COW strings overlay just the pointer, the length is stored manually.
115*38fd1498Szrj     static_assert(sizeof(std::string) == sizeof(__str_rep::_M_p),
116*38fd1498Szrj 		  "std::string changed size!");
117*38fd1498Szrj #endif
118*38fd1498Szrj # ifdef _GLIBCXX_USE_WCHAR_T
119*38fd1498Szrj     static_assert(sizeof(std::wstring) == sizeof(std::string),
120*38fd1498Szrj 		  "std::wstring and std::string are different sizes!");
121*38fd1498Szrj # endif
122*38fd1498Szrj 
123*38fd1498Szrj   public:
124*38fd1498Szrj     __any_string() = default;
~__any_string()125*38fd1498Szrj     ~__any_string() { if (_M_dtor) _M_dtor(_M_bytes); }
126*38fd1498Szrj 
127*38fd1498Szrj     __any_string(const __any_string&) = delete;
128*38fd1498Szrj     __any_string& operator=(const __any_string&) = delete;
129*38fd1498Szrj 
130*38fd1498Szrj     // Store a string (and its length if needed) in the buffer and
131*38fd1498Szrj     // set _M_dtor to the function that runs the right destructor.
132*38fd1498Szrj     template<typename C>
133*38fd1498Szrj       __any_string&
operator =(const basic_string<C> & s)134*38fd1498Szrj       operator=(const basic_string<C>& s)
135*38fd1498Szrj       {
136*38fd1498Szrj 	if (_M_dtor)
137*38fd1498Szrj 	  _M_dtor(_M_bytes);
138*38fd1498Szrj 	::new(_M_bytes) basic_string<C>(s);
139*38fd1498Szrj #if ! _GLIBCXX_USE_CXX11_ABI
140*38fd1498Szrj 	_M_str._M_len = s.length();
141*38fd1498Szrj #endif
142*38fd1498Szrj 	_M_dtor = __destroy_string<C>;
143*38fd1498Szrj 	return *this;
144*38fd1498Szrj       }
145*38fd1498Szrj 
146*38fd1498Szrj     // Create a new string with a copy of the characters in the stored string.
147*38fd1498Szrj     // The returned object will match the caller's string ABI, even when the
148*38fd1498Szrj     // stored string doesn't.
149*38fd1498Szrj     template<typename C>
150*38fd1498Szrj       _GLIBCXX_DEFAULT_ABI_TAG
operator basic_string<C>() const151*38fd1498Szrj       operator basic_string<C>() const
152*38fd1498Szrj       {
153*38fd1498Szrj 	if (!_M_dtor)
154*38fd1498Szrj 	  __throw_logic_error("uninitialized __any_string");
155*38fd1498Szrj 	return basic_string<C>(static_cast<const C*>(_M_str), _M_str._M_len);
156*38fd1498Szrj       }
157*38fd1498Szrj   };
158*38fd1498Szrj 
159*38fd1498Szrj   // This file is compiled twice, with and without this macro defined.
160*38fd1498Szrj   // Define tag types to distinguish between the two cases and to allow
161*38fd1498Szrj   // overloading on the tag.
162*38fd1498Szrj   using current_abi = __bool_constant<_GLIBCXX_USE_CXX11_ABI>;
163*38fd1498Szrj   using other_abi = __bool_constant<!_GLIBCXX_USE_CXX11_ABI>;
164*38fd1498Szrj 
165*38fd1498Szrj   using facet = locale::facet;
166*38fd1498Szrj 
167*38fd1498Szrj   // Declare the functions that shims defined in this file will call to
168*38fd1498Szrj   // perform work in the context of the other ABI.
169*38fd1498Szrj   // These will be defined when this file is recompiled for the other ABI
170*38fd1498Szrj   // (at which point what is now "current_abi" will become "other_abi").
171*38fd1498Szrj 
172*38fd1498Szrj   template<typename C>
173*38fd1498Szrj     void
174*38fd1498Szrj     __numpunct_fill_cache(other_abi, const facet*, __numpunct_cache<C>*);
175*38fd1498Szrj 
176*38fd1498Szrj   template<typename C>
177*38fd1498Szrj     int
178*38fd1498Szrj     __collate_compare(other_abi, const facet*, const C*, const C*,
179*38fd1498Szrj 		      const C*, const C*);
180*38fd1498Szrj 
181*38fd1498Szrj   template<typename C>
182*38fd1498Szrj     void
183*38fd1498Szrj     __collate_transform(other_abi, const facet*, __any_string&,
184*38fd1498Szrj 			const C*, const C*);
185*38fd1498Szrj 
186*38fd1498Szrj   template<typename C>
187*38fd1498Szrj     time_base::dateorder
188*38fd1498Szrj     __time_get_dateorder(other_abi, const facet* f);
189*38fd1498Szrj 
190*38fd1498Szrj   template<typename C>
191*38fd1498Szrj     istreambuf_iterator<C>
192*38fd1498Szrj     __time_get(other_abi, const facet* f,
193*38fd1498Szrj 	       istreambuf_iterator<C> beg, istreambuf_iterator<C> end,
194*38fd1498Szrj 	       ios_base& io, ios_base::iostate& err, tm* t, char which);
195*38fd1498Szrj 
196*38fd1498Szrj   template<typename C, bool Intl>
197*38fd1498Szrj     void
198*38fd1498Szrj     __moneypunct_fill_cache(other_abi, const facet*,
199*38fd1498Szrj 			    __moneypunct_cache<C, Intl>*);
200*38fd1498Szrj 
201*38fd1498Szrj   template<typename C>
202*38fd1498Szrj     istreambuf_iterator<C>
203*38fd1498Szrj     __money_get(other_abi, const facet*,
204*38fd1498Szrj 		istreambuf_iterator<C>, istreambuf_iterator<C>,
205*38fd1498Szrj 		bool, ios_base&, ios_base::iostate&,
206*38fd1498Szrj 		long double*, __any_string*);
207*38fd1498Szrj 
208*38fd1498Szrj   template<typename C>
209*38fd1498Szrj     ostreambuf_iterator<C>
210*38fd1498Szrj     __money_put(other_abi, const facet*, ostreambuf_iterator<C>, bool,
211*38fd1498Szrj 		ios_base&, C, long double, const __any_string*);
212*38fd1498Szrj 
213*38fd1498Szrj   template<typename C>
214*38fd1498Szrj     messages_base::catalog
215*38fd1498Szrj     __messages_open(other_abi, const facet*, const char*, size_t,
216*38fd1498Szrj 		    const locale&);
217*38fd1498Szrj 
218*38fd1498Szrj   template<typename C>
219*38fd1498Szrj     void
220*38fd1498Szrj     __messages_get(other_abi, const facet*, __any_string&,
221*38fd1498Szrj 		   messages_base::catalog, int, int, const C*, size_t);
222*38fd1498Szrj 
223*38fd1498Szrj   template<typename C>
224*38fd1498Szrj     void
225*38fd1498Szrj     __messages_close(other_abi, const facet*, messages_base::catalog);
226*38fd1498Szrj 
227*38fd1498Szrj   namespace // unnamed
228*38fd1498Szrj   {
229*38fd1498Szrj     struct __shim_accessor : facet
230*38fd1498Szrj     {
231*38fd1498Szrj       using facet::__shim;  // Redeclare protected member as public.
232*38fd1498Szrj     };
233*38fd1498Szrj     using __shim = __shim_accessor::__shim;
234*38fd1498Szrj 
235*38fd1498Szrj     template<typename _CharT>
236*38fd1498Szrj       struct numpunct_shim : std::numpunct<_CharT>, __shim
237*38fd1498Szrj       {
238*38fd1498Szrj 	typedef typename numpunct<_CharT>::__cache_type __cache_type;
239*38fd1498Szrj 
240*38fd1498Szrj 	// f must point to a type derived from numpunct<C>[abi:other]
numpunct_shimstd::__facet_shims::__anonc8a7b0500411::numpunct_shim241*38fd1498Szrj 	numpunct_shim(const facet* f, __cache_type* c = new __cache_type)
242*38fd1498Szrj 	: std::numpunct<_CharT>(c), __shim(f), _M_cache(c)
243*38fd1498Szrj 	{
244*38fd1498Szrj 	  __numpunct_fill_cache(other_abi{}, f, c);
245*38fd1498Szrj 	}
246*38fd1498Szrj 
~numpunct_shimstd::__facet_shims::__anonc8a7b0500411::numpunct_shim247*38fd1498Szrj 	~numpunct_shim()
248*38fd1498Szrj 	{
249*38fd1498Szrj 	  // Stop GNU locale's ~numpunct() from freeing the cached string.
250*38fd1498Szrj 	  _M_cache->_M_grouping_size = 0;
251*38fd1498Szrj 	}
252*38fd1498Szrj 
253*38fd1498Szrj 	// No need to override any virtual functions, the base definitions
254*38fd1498Szrj 	// will return the cached data.
255*38fd1498Szrj 
256*38fd1498Szrj 	__cache_type* _M_cache;
257*38fd1498Szrj       };
258*38fd1498Szrj 
259*38fd1498Szrj     template<typename _CharT>
260*38fd1498Szrj       struct collate_shim : std::collate<_CharT>, __shim
261*38fd1498Szrj       {
262*38fd1498Szrj 	typedef basic_string<_CharT>	string_type;
263*38fd1498Szrj 
264*38fd1498Szrj 	// f must point to a type derived from collate<C>[abi:other]
collate_shimstd::__facet_shims::__anonc8a7b0500411::collate_shim265*38fd1498Szrj 	collate_shim(const facet* f) : __shim(f) { }
266*38fd1498Szrj 
267*38fd1498Szrj 	virtual int
do_comparestd::__facet_shims::__anonc8a7b0500411::collate_shim268*38fd1498Szrj 	do_compare(const _CharT* lo1, const _CharT* hi1,
269*38fd1498Szrj 		   const _CharT* lo2, const _CharT* hi2) const
270*38fd1498Szrj 	{
271*38fd1498Szrj 	  return __collate_compare(other_abi{}, _M_get(),
272*38fd1498Szrj 				   lo1, hi1, lo2, hi2);
273*38fd1498Szrj 	}
274*38fd1498Szrj 
275*38fd1498Szrj 	virtual string_type
do_transformstd::__facet_shims::__anonc8a7b0500411::collate_shim276*38fd1498Szrj 	do_transform(const _CharT* lo, const _CharT* hi) const
277*38fd1498Szrj 	{
278*38fd1498Szrj 	  __any_string st;
279*38fd1498Szrj 	  __collate_transform(other_abi{}, _M_get(), st, lo, hi);
280*38fd1498Szrj 	  return st;
281*38fd1498Szrj 	}
282*38fd1498Szrj       };
283*38fd1498Szrj 
284*38fd1498Szrj     template<typename _CharT>
285*38fd1498Szrj       struct time_get_shim : std::time_get<_CharT>, __shim
286*38fd1498Szrj       {
287*38fd1498Szrj 	typedef typename std::time_get<_CharT>::iter_type iter_type;
288*38fd1498Szrj 	typedef typename std::time_get<_CharT>::char_type char_type;
289*38fd1498Szrj 
290*38fd1498Szrj 	// f must point to a type derived from time_get<C>[abi:other]
time_get_shimstd::__facet_shims::__anonc8a7b0500411::time_get_shim291*38fd1498Szrj 	time_get_shim(const facet* f) : __shim(f) { }
292*38fd1498Szrj 
293*38fd1498Szrj 	virtual time_base::dateorder
do_date_orderstd::__facet_shims::__anonc8a7b0500411::time_get_shim294*38fd1498Szrj 	do_date_order() const
295*38fd1498Szrj 	{ return __time_get_dateorder<_CharT>(other_abi{}, _M_get()); }
296*38fd1498Szrj 
297*38fd1498Szrj 	virtual iter_type
do_get_timestd::__facet_shims::__anonc8a7b0500411::time_get_shim298*38fd1498Szrj 	do_get_time(iter_type beg, iter_type end, ios_base& io,
299*38fd1498Szrj 		    ios_base::iostate& err, tm* t) const
300*38fd1498Szrj 	{
301*38fd1498Szrj 	  return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
302*38fd1498Szrj 			    't');
303*38fd1498Szrj 	}
304*38fd1498Szrj 
305*38fd1498Szrj 	virtual iter_type
do_get_datestd::__facet_shims::__anonc8a7b0500411::time_get_shim306*38fd1498Szrj 	do_get_date(iter_type beg, iter_type end, ios_base& io,
307*38fd1498Szrj 		    ios_base::iostate& err, tm* t) const
308*38fd1498Szrj 	{
309*38fd1498Szrj 	  return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
310*38fd1498Szrj 			    'd');
311*38fd1498Szrj 	}
312*38fd1498Szrj 
313*38fd1498Szrj 	virtual iter_type
do_get_weekdaystd::__facet_shims::__anonc8a7b0500411::time_get_shim314*38fd1498Szrj 	do_get_weekday(iter_type beg, iter_type end, ios_base& io,
315*38fd1498Szrj 		       ios_base::iostate& err, tm* t) const
316*38fd1498Szrj 	{
317*38fd1498Szrj 	  return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
318*38fd1498Szrj 			    'w');
319*38fd1498Szrj 	}
320*38fd1498Szrj 
321*38fd1498Szrj 	virtual iter_type
do_get_monthnamestd::__facet_shims::__anonc8a7b0500411::time_get_shim322*38fd1498Szrj 	do_get_monthname(iter_type beg, iter_type end, ios_base& io,
323*38fd1498Szrj 			 ios_base::iostate& err, tm* t) const
324*38fd1498Szrj 	{
325*38fd1498Szrj 	  return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
326*38fd1498Szrj 			    'm');
327*38fd1498Szrj 	}
328*38fd1498Szrj 
329*38fd1498Szrj 	virtual iter_type
do_get_yearstd::__facet_shims::__anonc8a7b0500411::time_get_shim330*38fd1498Szrj 	do_get_year(iter_type beg, iter_type end, ios_base& io,
331*38fd1498Szrj 		    ios_base::iostate& err, tm* t) const
332*38fd1498Szrj 	{
333*38fd1498Szrj 	  return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
334*38fd1498Szrj 			    'y');
335*38fd1498Szrj 	}
336*38fd1498Szrj       };
337*38fd1498Szrj 
338*38fd1498Szrj     template<typename _CharT, bool _Intl>
339*38fd1498Szrj       struct moneypunct_shim : std::moneypunct<_CharT, _Intl>, __shim
340*38fd1498Szrj       {
341*38fd1498Szrj 	typedef typename moneypunct<_CharT, _Intl>::__cache_type __cache_type;
342*38fd1498Szrj 
343*38fd1498Szrj 	// f must point to a type derived from moneypunct<C>[abi:other]
moneypunct_shimstd::__facet_shims::__anonc8a7b0500411::moneypunct_shim344*38fd1498Szrj 	moneypunct_shim(const facet* f, __cache_type* c = new __cache_type)
345*38fd1498Szrj 	: std::moneypunct<_CharT, _Intl>(c), __shim(f), _M_cache(c)
346*38fd1498Szrj 	{
347*38fd1498Szrj 	  __moneypunct_fill_cache(other_abi{}, f, c);
348*38fd1498Szrj 	}
349*38fd1498Szrj 
~moneypunct_shimstd::__facet_shims::__anonc8a7b0500411::moneypunct_shim350*38fd1498Szrj 	~moneypunct_shim()
351*38fd1498Szrj 	{
352*38fd1498Szrj 	  // Stop GNU locale's ~moneypunct() from freeing the cached strings.
353*38fd1498Szrj 	  _M_cache->_M_grouping_size = 0;
354*38fd1498Szrj 	  _M_cache->_M_curr_symbol_size = 0;
355*38fd1498Szrj 	  _M_cache->_M_positive_sign_size = 0;
356*38fd1498Szrj 	  _M_cache->_M_negative_sign_size = 0;
357*38fd1498Szrj 	}
358*38fd1498Szrj 
359*38fd1498Szrj 	// No need to override any virtual functions, the base definitions
360*38fd1498Szrj 	// will return the cached data.
361*38fd1498Szrj 
362*38fd1498Szrj 	__cache_type* _M_cache;
363*38fd1498Szrj       };
364*38fd1498Szrj 
365*38fd1498Szrj     template<typename _CharT>
366*38fd1498Szrj       struct money_get_shim : std::money_get<_CharT>, __shim
367*38fd1498Szrj       {
368*38fd1498Szrj 	typedef typename std::money_get<_CharT>::iter_type iter_type;
369*38fd1498Szrj 	typedef typename std::money_get<_CharT>::char_type char_type;
370*38fd1498Szrj 	typedef typename std::money_get<_CharT>::string_type string_type;
371*38fd1498Szrj 
372*38fd1498Szrj 	// f must point to a type derived from money_get<C>[abi:other]
money_get_shimstd::__facet_shims::__anonc8a7b0500411::money_get_shim373*38fd1498Szrj 	money_get_shim(const facet* f) : __shim(f) { }
374*38fd1498Szrj 
375*38fd1498Szrj 	virtual iter_type
do_getstd::__facet_shims::__anonc8a7b0500411::money_get_shim376*38fd1498Szrj 	do_get(iter_type s, iter_type end, bool intl, ios_base& io,
377*38fd1498Szrj 	       ios_base::iostate& err, long double& units) const
378*38fd1498Szrj 	{
379*38fd1498Szrj 	  ios_base::iostate err2 = ios_base::goodbit;
380*38fd1498Szrj 	  long double units2;
381*38fd1498Szrj 	  s = __money_get(other_abi{}, _M_get(), s, end, intl, io, err2,
382*38fd1498Szrj 			  &units2, nullptr);
383*38fd1498Szrj 	  if (err2 == ios_base::goodbit)
384*38fd1498Szrj 	    units = units2;
385*38fd1498Szrj 	  else
386*38fd1498Szrj 	    err = err2;
387*38fd1498Szrj 	  return s;
388*38fd1498Szrj 	}
389*38fd1498Szrj 
390*38fd1498Szrj 	virtual iter_type
do_getstd::__facet_shims::__anonc8a7b0500411::money_get_shim391*38fd1498Szrj 	do_get(iter_type s, iter_type end, bool intl, ios_base& io,
392*38fd1498Szrj 	       ios_base::iostate& err, string_type& digits) const
393*38fd1498Szrj 	{
394*38fd1498Szrj 	  __any_string st;
395*38fd1498Szrj 	  ios_base::iostate err2 = ios_base::goodbit;
396*38fd1498Szrj 	  s = __money_get(other_abi{}, _M_get(), s, end, intl, io, err2,
397*38fd1498Szrj 			  nullptr, &st);
398*38fd1498Szrj 	  if (err2 == ios_base::goodbit)
399*38fd1498Szrj 	    digits = st;
400*38fd1498Szrj 	  else
401*38fd1498Szrj 	    err = err2;
402*38fd1498Szrj 	  return s;
403*38fd1498Szrj 	}
404*38fd1498Szrj       };
405*38fd1498Szrj 
406*38fd1498Szrj     template<typename _CharT>
407*38fd1498Szrj       struct money_put_shim : std::money_put<_CharT>, __shim
408*38fd1498Szrj       {
409*38fd1498Szrj 	typedef typename std::money_put<_CharT>::iter_type iter_type;
410*38fd1498Szrj 	typedef typename std::money_put<_CharT>::char_type char_type;
411*38fd1498Szrj 	typedef typename std::money_put<_CharT>::string_type string_type;
412*38fd1498Szrj 
413*38fd1498Szrj 	// f must point to a type derived from money_put<C>[abi:other]
money_put_shimstd::__facet_shims::__anonc8a7b0500411::money_put_shim414*38fd1498Szrj 	money_put_shim(const facet* f) : __shim(f) { }
415*38fd1498Szrj 
416*38fd1498Szrj 	virtual iter_type
do_putstd::__facet_shims::__anonc8a7b0500411::money_put_shim417*38fd1498Szrj 	do_put(iter_type s, bool intl, ios_base& io,
418*38fd1498Szrj 	       char_type fill, long double units) const
419*38fd1498Szrj 	{
420*38fd1498Szrj 	  return __money_put(other_abi{}, _M_get(), s, intl, io, fill, units,
421*38fd1498Szrj 			     nullptr);
422*38fd1498Szrj 	}
423*38fd1498Szrj 
424*38fd1498Szrj 	virtual iter_type
do_putstd::__facet_shims::__anonc8a7b0500411::money_put_shim425*38fd1498Szrj 	do_put(iter_type s, bool intl, ios_base& io,
426*38fd1498Szrj 	       char_type fill, const string_type& digits) const
427*38fd1498Szrj 	{
428*38fd1498Szrj 	  __any_string st;
429*38fd1498Szrj 	  st = digits;
430*38fd1498Szrj 	  return __money_put(other_abi{}, _M_get(), s, intl, io, fill, 0.L,
431*38fd1498Szrj 			     &st);
432*38fd1498Szrj 	}
433*38fd1498Szrj       };
434*38fd1498Szrj 
435*38fd1498Szrj     template<typename _CharT>
436*38fd1498Szrj       struct messages_shim : std::messages<_CharT>, __shim
437*38fd1498Szrj       {
438*38fd1498Szrj 	typedef messages_base::catalog  catalog;
439*38fd1498Szrj 	typedef basic_string<_CharT>	string_type;
440*38fd1498Szrj 
441*38fd1498Szrj 	// f must point to a type derived from messages<C>[abi:other]
messages_shimstd::__facet_shims::__anonc8a7b0500411::messages_shim442*38fd1498Szrj 	messages_shim(const facet* f) : __shim(f) { }
443*38fd1498Szrj 
444*38fd1498Szrj 	virtual catalog
do_openstd::__facet_shims::__anonc8a7b0500411::messages_shim445*38fd1498Szrj 	do_open(const basic_string<char>& s, const locale& l) const
446*38fd1498Szrj 	{
447*38fd1498Szrj 	  return __messages_open<_CharT>(other_abi{}, _M_get(),
448*38fd1498Szrj 					 s.c_str(), s.size(), l);
449*38fd1498Szrj 	}
450*38fd1498Szrj 
451*38fd1498Szrj 	virtual string_type
do_getstd::__facet_shims::__anonc8a7b0500411::messages_shim452*38fd1498Szrj 	do_get(catalog c, int set, int msgid, const string_type& dfault) const
453*38fd1498Szrj 	{
454*38fd1498Szrj 	  __any_string st;
455*38fd1498Szrj 	  __messages_get(other_abi{}, _M_get(), st, c, set, msgid,
456*38fd1498Szrj 			 dfault.c_str(), dfault.size());
457*38fd1498Szrj 	  return st;
458*38fd1498Szrj 	}
459*38fd1498Szrj 
460*38fd1498Szrj 	virtual void
do_closestd::__facet_shims::__anonc8a7b0500411::messages_shim461*38fd1498Szrj 	do_close(catalog c) const
462*38fd1498Szrj 	{
463*38fd1498Szrj 	  __messages_close<_CharT>(other_abi{}, _M_get(), c);
464*38fd1498Szrj 	}
465*38fd1498Szrj       };
466*38fd1498Szrj 
467*38fd1498Szrj     template class numpunct_shim<char>;
468*38fd1498Szrj     template class collate_shim<char>;
469*38fd1498Szrj     template class moneypunct_shim<char, true>;
470*38fd1498Szrj     template class moneypunct_shim<char, false>;
471*38fd1498Szrj     template class money_get_shim<char>;
472*38fd1498Szrj     template class money_put_shim<char>;
473*38fd1498Szrj     template class messages_shim<char>;
474*38fd1498Szrj #ifdef _GLIBCXX_USE_WCHAR_T
475*38fd1498Szrj     template class numpunct_shim<wchar_t>;
476*38fd1498Szrj     template class collate_shim<wchar_t>;
477*38fd1498Szrj     template class moneypunct_shim<wchar_t, true>;
478*38fd1498Szrj     template class moneypunct_shim<wchar_t, false>;
479*38fd1498Szrj     template class money_get_shim<wchar_t>;
480*38fd1498Szrj     template class money_put_shim<wchar_t>;
481*38fd1498Szrj     template class messages_shim<wchar_t>;
482*38fd1498Szrj #endif
483*38fd1498Szrj 
484*38fd1498Szrj     template<typename C>
485*38fd1498Szrj       inline size_t
__copy(const C * & dest,const basic_string<C> & s)486*38fd1498Szrj       __copy(const C*& dest, const basic_string<C>& s)
487*38fd1498Szrj       {
488*38fd1498Szrj 	auto len = s.length();
489*38fd1498Szrj 	C* p = new C[len+1];
490*38fd1498Szrj 	s.copy(p, len);
491*38fd1498Szrj 	p[len] = '\0';
492*38fd1498Szrj 	dest = p;
493*38fd1498Szrj 	return len;
494*38fd1498Szrj       }
495*38fd1498Szrj 
496*38fd1498Szrj   } // namespace
497*38fd1498Szrj 
498*38fd1498Szrj   // Now define and instantiate the functions that will be called by the
499*38fd1498Szrj   // shim facets defined when this file is recompiled for the other ABI.
500*38fd1498Szrj 
501*38fd1498Szrj   // Cache the values returned by the numpunct facet f.
502*38fd1498Szrj   // Sets c->_M_allocated so that the __numpunct_cache destructor will
503*38fd1498Szrj   // delete[] the strings allocated by this function.
504*38fd1498Szrj   template<typename C>
505*38fd1498Szrj     void
__numpunct_fill_cache(current_abi,const facet * f,__numpunct_cache<C> * c)506*38fd1498Szrj     __numpunct_fill_cache(current_abi, const facet* f, __numpunct_cache<C>* c)
507*38fd1498Szrj     {
508*38fd1498Szrj       auto* m = static_cast<const numpunct<C>*>(f);
509*38fd1498Szrj 
510*38fd1498Szrj       c->_M_decimal_point = m->decimal_point();
511*38fd1498Szrj       c->_M_thousands_sep = m->thousands_sep();
512*38fd1498Szrj 
513*38fd1498Szrj       c->_M_grouping = nullptr;
514*38fd1498Szrj       c->_M_truename = nullptr;
515*38fd1498Szrj       c->_M_falsename = nullptr;
516*38fd1498Szrj       // set _M_allocated so that if any allocation fails the previously
517*38fd1498Szrj       // allocated strings will be deleted in ~__numpunct_cache()
518*38fd1498Szrj       c->_M_allocated = true;
519*38fd1498Szrj 
520*38fd1498Szrj       c->_M_grouping_size = __copy(c->_M_grouping, m->grouping());
521*38fd1498Szrj       c->_M_truename_size = __copy(c->_M_truename, m->truename());
522*38fd1498Szrj       c->_M_falsename_size = __copy(c->_M_falsename, m->falsename());
523*38fd1498Szrj     }
524*38fd1498Szrj 
525*38fd1498Szrj   template void
526*38fd1498Szrj   __numpunct_fill_cache(current_abi, const facet*, __numpunct_cache<char>*);
527*38fd1498Szrj 
528*38fd1498Szrj #ifdef _GLIBCXX_USE_WCHAR_T
529*38fd1498Szrj   template void
530*38fd1498Szrj   __numpunct_fill_cache(current_abi, const facet*, __numpunct_cache<wchar_t>*);
531*38fd1498Szrj #endif
532*38fd1498Szrj 
533*38fd1498Szrj   template<typename C>
534*38fd1498Szrj     int
__collate_compare(current_abi,const facet * f,const C * lo1,const C * hi1,const C * lo2,const C * hi2)535*38fd1498Szrj     __collate_compare(current_abi, const facet* f, const C* lo1, const C* hi1,
536*38fd1498Szrj 		      const C* lo2, const C* hi2)
537*38fd1498Szrj     {
538*38fd1498Szrj       return static_cast<const collate<C>*>(f)->compare(lo1, hi1, lo2, hi2);
539*38fd1498Szrj     }
540*38fd1498Szrj 
541*38fd1498Szrj   template int
542*38fd1498Szrj   __collate_compare(current_abi, const facet*, const char*, const char*,
543*38fd1498Szrj 		    const char*, const char*);
544*38fd1498Szrj 
545*38fd1498Szrj #ifdef _GLIBCXX_USE_WCHAR_T
546*38fd1498Szrj   template int
547*38fd1498Szrj   __collate_compare(current_abi, const facet*, const wchar_t*, const wchar_t*,
548*38fd1498Szrj 		    const wchar_t*, const wchar_t*);
549*38fd1498Szrj #endif
550*38fd1498Szrj 
551*38fd1498Szrj   template<typename C>
552*38fd1498Szrj     void
__collate_transform(current_abi,const facet * f,__any_string & st,const C * __lo,const C * __hi)553*38fd1498Szrj     __collate_transform(current_abi, const facet* f, __any_string& st,
554*38fd1498Szrj 			const C* __lo, const C* __hi)
555*38fd1498Szrj     {
556*38fd1498Szrj       auto* c = static_cast<const collate<C>*>(f);
557*38fd1498Szrj       st = c->transform(__lo, __hi);
558*38fd1498Szrj     }
559*38fd1498Szrj 
560*38fd1498Szrj   template void
561*38fd1498Szrj   __collate_transform(current_abi, const facet*, __any_string&,
562*38fd1498Szrj 		      const char*, const char*);
563*38fd1498Szrj 
564*38fd1498Szrj #ifdef _GLIBCXX_USE_WCHAR_T
565*38fd1498Szrj   template void
566*38fd1498Szrj   __collate_transform(current_abi, const facet*, __any_string&,
567*38fd1498Szrj 		      const wchar_t*, const wchar_t*);
568*38fd1498Szrj #endif
569*38fd1498Szrj 
570*38fd1498Szrj   // Cache the values returned by the moneypunct facet, f.
571*38fd1498Szrj   // Sets c->_M_allocated so that the __moneypunct_cache destructor will
572*38fd1498Szrj   // delete[] the strings allocated by this function.
573*38fd1498Szrj   template<typename C, bool Intl>
574*38fd1498Szrj     void
__moneypunct_fill_cache(current_abi,const facet * f,__moneypunct_cache<C,Intl> * c)575*38fd1498Szrj     __moneypunct_fill_cache(current_abi, const facet* f,
576*38fd1498Szrj 			    __moneypunct_cache<C, Intl>* c)
577*38fd1498Szrj     {
578*38fd1498Szrj       auto* m = static_cast<const moneypunct<C, Intl>*>(f);
579*38fd1498Szrj 
580*38fd1498Szrj       c->_M_decimal_point = m->decimal_point();
581*38fd1498Szrj       c->_M_thousands_sep = m->thousands_sep();
582*38fd1498Szrj       c->_M_frac_digits = m->frac_digits();
583*38fd1498Szrj 
584*38fd1498Szrj       c->_M_grouping = nullptr;
585*38fd1498Szrj       c->_M_curr_symbol = nullptr;
586*38fd1498Szrj       c->_M_positive_sign = nullptr;
587*38fd1498Szrj       c->_M_negative_sign = nullptr;
588*38fd1498Szrj       // Set _M_allocated so that if any allocation fails the previously
589*38fd1498Szrj       // allocated strings will be deleted in ~__moneypunct_cache().
590*38fd1498Szrj       c->_M_allocated = true;
591*38fd1498Szrj 
592*38fd1498Szrj       c->_M_grouping_size = __copy(c->_M_grouping, m->grouping());
593*38fd1498Szrj       c->_M_curr_symbol_size = __copy(c->_M_curr_symbol, m->curr_symbol());
594*38fd1498Szrj       c->_M_positive_sign_size
595*38fd1498Szrj 	= __copy(c->_M_positive_sign, m->positive_sign());
596*38fd1498Szrj       c->_M_negative_sign_size
597*38fd1498Szrj 	= __copy(c->_M_negative_sign, m->negative_sign());
598*38fd1498Szrj 
599*38fd1498Szrj       c->_M_pos_format = m->pos_format();
600*38fd1498Szrj       c->_M_neg_format = m->neg_format();
601*38fd1498Szrj     }
602*38fd1498Szrj 
603*38fd1498Szrj   template void
604*38fd1498Szrj   __moneypunct_fill_cache(current_abi, const facet*,
605*38fd1498Szrj 			  __moneypunct_cache<char, true>*);
606*38fd1498Szrj 
607*38fd1498Szrj   template void
608*38fd1498Szrj   __moneypunct_fill_cache(current_abi, const facet*,
609*38fd1498Szrj 			  __moneypunct_cache<char, false>*);
610*38fd1498Szrj 
611*38fd1498Szrj #ifdef _GLIBCXX_USE_WCHAR_T
612*38fd1498Szrj   template void
613*38fd1498Szrj   __moneypunct_fill_cache(current_abi, const facet*,
614*38fd1498Szrj 			  __moneypunct_cache<wchar_t, true>*);
615*38fd1498Szrj 
616*38fd1498Szrj   template void
617*38fd1498Szrj   __moneypunct_fill_cache(current_abi, const facet*,
618*38fd1498Szrj 			  __moneypunct_cache<wchar_t, false>*);
619*38fd1498Szrj #endif
620*38fd1498Szrj 
621*38fd1498Szrj   template<typename C>
622*38fd1498Szrj     messages_base::catalog
__messages_open(current_abi,const facet * f,const char * s,size_t n,const locale & l)623*38fd1498Szrj     __messages_open(current_abi, const facet* f, const char* s, size_t n,
624*38fd1498Szrj 		    const locale& l)
625*38fd1498Szrj     {
626*38fd1498Szrj       auto* m = static_cast<const messages<C>*>(f);
627*38fd1498Szrj       string str(s, n);
628*38fd1498Szrj       return m->open(str, l);
629*38fd1498Szrj     }
630*38fd1498Szrj 
631*38fd1498Szrj   template messages_base::catalog
632*38fd1498Szrj   __messages_open<char>(current_abi, const facet*, const char*, size_t,
633*38fd1498Szrj 			const locale&);
634*38fd1498Szrj 
635*38fd1498Szrj #ifdef _GLIBCXX_USE_WCHAR_T
636*38fd1498Szrj   template messages_base::catalog
637*38fd1498Szrj   __messages_open<wchar_t>(current_abi, const facet*, const char*, size_t,
638*38fd1498Szrj 			   const locale&);
639*38fd1498Szrj #endif
640*38fd1498Szrj 
641*38fd1498Szrj   template<typename C>
642*38fd1498Szrj     void
__messages_get(current_abi,const facet * f,__any_string & st,messages_base::catalog c,int set,int msgid,const C * s,size_t n)643*38fd1498Szrj     __messages_get(current_abi, const facet* f, __any_string& st,
644*38fd1498Szrj 		   messages_base::catalog c, int set, int msgid,
645*38fd1498Szrj 		   const C* s, size_t n)
646*38fd1498Szrj     {
647*38fd1498Szrj       auto* m = static_cast<const messages<C>*>(f);
648*38fd1498Szrj       st = m->get(c, set, msgid, basic_string<C>(s, n));
649*38fd1498Szrj     }
650*38fd1498Szrj 
651*38fd1498Szrj   template void
652*38fd1498Szrj   __messages_get(current_abi, const facet*, __any_string&,
653*38fd1498Szrj 		 messages_base::catalog, int, int, const char*, size_t);
654*38fd1498Szrj 
655*38fd1498Szrj #ifdef _GLIBCXX_USE_WCHAR_T
656*38fd1498Szrj   template void
657*38fd1498Szrj   __messages_get(current_abi, const facet*, __any_string&,
658*38fd1498Szrj 		 messages_base::catalog, int, int, const wchar_t*, size_t);
659*38fd1498Szrj #endif
660*38fd1498Szrj 
661*38fd1498Szrj   template<typename C>
662*38fd1498Szrj     void
__messages_close(current_abi,const facet * f,messages_base::catalog c)663*38fd1498Szrj     __messages_close(current_abi, const facet* f, messages_base::catalog c)
664*38fd1498Szrj     {
665*38fd1498Szrj       static_cast<const messages<C>*>(f)->close(c);
666*38fd1498Szrj     }
667*38fd1498Szrj 
668*38fd1498Szrj   template void
669*38fd1498Szrj   __messages_close<char>(current_abi, const facet*, messages_base::catalog c);
670*38fd1498Szrj 
671*38fd1498Szrj #ifdef _GLIBCXX_USE_WCHAR_T
672*38fd1498Szrj   template void
673*38fd1498Szrj   __messages_close<wchar_t>(current_abi, const facet*,
674*38fd1498Szrj 			    messages_base::catalog c);
675*38fd1498Szrj #endif
676*38fd1498Szrj 
677*38fd1498Szrj   template<typename C>
678*38fd1498Szrj     time_base::dateorder
__time_get_dateorder(current_abi,const facet * f)679*38fd1498Szrj     __time_get_dateorder(current_abi, const facet* f)
680*38fd1498Szrj     { return static_cast<const time_get<C>*>(f)->date_order(); }
681*38fd1498Szrj 
682*38fd1498Szrj   template time_base::dateorder
683*38fd1498Szrj   __time_get_dateorder<char>(current_abi, const facet*);
684*38fd1498Szrj 
685*38fd1498Szrj #ifdef _GLIBCXX_USE_WCHAR_T
686*38fd1498Szrj   template time_base::dateorder
687*38fd1498Szrj   __time_get_dateorder<wchar_t>(current_abi, const facet*);
688*38fd1498Szrj #endif
689*38fd1498Szrj 
690*38fd1498Szrj   template<typename C>
691*38fd1498Szrj     istreambuf_iterator<C>
__time_get(current_abi,const facet * f,istreambuf_iterator<C> beg,istreambuf_iterator<C> end,ios_base & io,ios_base::iostate & err,tm * t,char which)692*38fd1498Szrj     __time_get(current_abi, const facet* f,
693*38fd1498Szrj 	       istreambuf_iterator<C> beg, istreambuf_iterator<C> end,
694*38fd1498Szrj 	       ios_base& io, ios_base::iostate& err, tm* t, char which)
695*38fd1498Szrj     {
696*38fd1498Szrj       auto* g = static_cast<const time_get<C>*>(f);
697*38fd1498Szrj       switch(which)
698*38fd1498Szrj       {
699*38fd1498Szrj       case 't':
700*38fd1498Szrj 	return g->get_time(beg, end, io, err, t);
701*38fd1498Szrj       case 'd':
702*38fd1498Szrj 	return g->get_date(beg, end, io, err, t);
703*38fd1498Szrj       case 'w':
704*38fd1498Szrj 	return g->get_weekday(beg, end, io, err, t);
705*38fd1498Szrj       case 'm':
706*38fd1498Szrj 	return g->get_monthname(beg, end, io, err, t);
707*38fd1498Szrj       case 'y':
708*38fd1498Szrj 	return g->get_year(beg, end, io, err, t);
709*38fd1498Szrj       default:
710*38fd1498Szrj 	__builtin_unreachable();
711*38fd1498Szrj       }
712*38fd1498Szrj     }
713*38fd1498Szrj 
714*38fd1498Szrj   template istreambuf_iterator<char>
715*38fd1498Szrj   __time_get(current_abi, const facet*,
716*38fd1498Szrj 	     istreambuf_iterator<char>, istreambuf_iterator<char>,
717*38fd1498Szrj 	     ios_base&, ios_base::iostate&, tm*, char);
718*38fd1498Szrj 
719*38fd1498Szrj #ifdef _GLIBCXX_USE_WCHAR_T
720*38fd1498Szrj   template istreambuf_iterator<wchar_t>
721*38fd1498Szrj   __time_get(current_abi, const facet*,
722*38fd1498Szrj 	     istreambuf_iterator<wchar_t>, istreambuf_iterator<wchar_t>,
723*38fd1498Szrj 	     ios_base&, ios_base::iostate&, tm*, char);
724*38fd1498Szrj #endif
725*38fd1498Szrj 
726*38fd1498Szrj   template<typename C>
727*38fd1498Szrj     istreambuf_iterator<C>
__money_get(current_abi,const facet * f,istreambuf_iterator<C> s,istreambuf_iterator<C> end,bool intl,ios_base & str,ios_base::iostate & err,long double * units,__any_string * digits)728*38fd1498Szrj     __money_get(current_abi, const facet* f,
729*38fd1498Szrj 		istreambuf_iterator<C> s, istreambuf_iterator<C> end,
730*38fd1498Szrj 		bool intl, ios_base& str, ios_base::iostate& err,
731*38fd1498Szrj 		long double* units, __any_string* digits)
732*38fd1498Szrj     {
733*38fd1498Szrj       auto* m = static_cast<const money_get<C>*>(f);
734*38fd1498Szrj       if (units)
735*38fd1498Szrj 	return m->get(s, end, intl, str, err, *units);
736*38fd1498Szrj       basic_string<C> digits2;
737*38fd1498Szrj       s = m->get(s, end, intl, str, err, digits2);
738*38fd1498Szrj       if (err == ios_base::goodbit)
739*38fd1498Szrj 	*digits = digits2;
740*38fd1498Szrj       return s;
741*38fd1498Szrj     }
742*38fd1498Szrj 
743*38fd1498Szrj   template istreambuf_iterator<char>
744*38fd1498Szrj   __money_get(current_abi, const facet*,
745*38fd1498Szrj 	      istreambuf_iterator<char>, istreambuf_iterator<char>,
746*38fd1498Szrj 	      bool, ios_base&, ios_base::iostate&,
747*38fd1498Szrj 	      long double*, __any_string*);
748*38fd1498Szrj 
749*38fd1498Szrj #ifdef _GLIBCXX_USE_WCHAR_T
750*38fd1498Szrj   template istreambuf_iterator<wchar_t>
751*38fd1498Szrj   __money_get(current_abi, const facet*,
752*38fd1498Szrj 	      istreambuf_iterator<wchar_t>, istreambuf_iterator<wchar_t>,
753*38fd1498Szrj 	      bool, ios_base&, ios_base::iostate&,
754*38fd1498Szrj 	      long double*, __any_string*);
755*38fd1498Szrj #endif
756*38fd1498Szrj 
757*38fd1498Szrj   template<typename C>
758*38fd1498Szrj     ostreambuf_iterator<C>
__money_put(current_abi,const facet * f,ostreambuf_iterator<C> s,bool intl,ios_base & io,C fill,long double units,const __any_string * digits)759*38fd1498Szrj     __money_put(current_abi, const facet* f, ostreambuf_iterator<C> s,
760*38fd1498Szrj 		bool intl, ios_base& io, C fill, long double units,
761*38fd1498Szrj 		const __any_string* digits)
762*38fd1498Szrj     {
763*38fd1498Szrj       auto* m = static_cast<const money_put<C>*>(f);
764*38fd1498Szrj       if (digits)
765*38fd1498Szrj 	return m->put(s, intl, io, fill, *digits);
766*38fd1498Szrj       else
767*38fd1498Szrj 	return m->put(s, intl, io, fill, units);
768*38fd1498Szrj     }
769*38fd1498Szrj 
770*38fd1498Szrj   template ostreambuf_iterator<char>
771*38fd1498Szrj   __money_put(current_abi, const facet*, ostreambuf_iterator<char>,
772*38fd1498Szrj 		bool, ios_base&, char, long double, const __any_string*);
773*38fd1498Szrj 
774*38fd1498Szrj #ifdef _GLIBCXX_USE_WCHAR_T
775*38fd1498Szrj   template ostreambuf_iterator<wchar_t>
776*38fd1498Szrj   __money_put(current_abi, const facet*, ostreambuf_iterator<wchar_t>,
777*38fd1498Szrj 		bool, ios_base&, wchar_t, long double, const __any_string*);
778*38fd1498Szrj #endif
779*38fd1498Szrj 
780*38fd1498Szrj } // namespace __facet_shims
781*38fd1498Szrj 
782*38fd1498Szrj   // Create a new shim facet of type WHICH that forwards calls to F.
783*38fd1498Szrj   // F is the replacement facet provided by the user, WHICH is the ID of
784*38fd1498Szrj   // F's "other ABI twin" which we are replacing with a shim.
785*38fd1498Szrj   const locale::facet*
786*38fd1498Szrj #if _GLIBCXX_USE_CXX11_ABI
_M_sso_shim(const locale::id * which) const787*38fd1498Szrj   locale::facet::_M_sso_shim(const locale::id* which) const
788*38fd1498Szrj #else
789*38fd1498Szrj   locale::facet::_M_cow_shim(const locale::id* which) const
790*38fd1498Szrj #endif
791*38fd1498Szrj   {
792*38fd1498Szrj     using namespace __facet_shims;
793*38fd1498Szrj 
794*38fd1498Szrj #if __cpp_rtti
795*38fd1498Szrj     // If this is already a shim just use its underlying facet.
796*38fd1498Szrj     if (auto* p = dynamic_cast<const __shim*>(this))
797*38fd1498Szrj       return p->_M_get();
798*38fd1498Szrj #endif
799*38fd1498Szrj 
800*38fd1498Szrj     if (which == &numpunct<char>::id)
801*38fd1498Szrj       return new numpunct_shim<char>{this};
802*38fd1498Szrj     if (which == &std::collate<char>::id)
803*38fd1498Szrj       return new collate_shim<char>{this};
804*38fd1498Szrj     if (which == &time_get<char>::id)
805*38fd1498Szrj       return new time_get_shim<char>{this};
806*38fd1498Szrj     if (which == &money_get<char>::id)
807*38fd1498Szrj       return new money_get_shim<char>{this};
808*38fd1498Szrj     if (which == &money_put<char>::id)
809*38fd1498Szrj       return new money_put_shim<char>{this};
810*38fd1498Szrj     if (which == &moneypunct<char, true>::id)
811*38fd1498Szrj       return new moneypunct_shim<char, true>{this};
812*38fd1498Szrj     if (which == &moneypunct<char, false>::id)
813*38fd1498Szrj       return new moneypunct_shim<char, false>{this};
814*38fd1498Szrj     if (which == &std::messages<char>::id)
815*38fd1498Szrj       return new messages_shim<char>{this};
816*38fd1498Szrj #ifdef _GLIBCXX_USE_WCHAR_T
817*38fd1498Szrj     if (which == &numpunct<wchar_t>::id)
818*38fd1498Szrj       return new numpunct_shim<wchar_t>{this};
819*38fd1498Szrj     if (which == &std::collate<wchar_t>::id)
820*38fd1498Szrj       return new collate_shim<wchar_t>{this};
821*38fd1498Szrj     if (which == &time_get<wchar_t>::id)
822*38fd1498Szrj       return new time_get_shim<wchar_t>{this};
823*38fd1498Szrj     if (which == &money_get<wchar_t>::id)
824*38fd1498Szrj       return new money_get_shim<wchar_t>{this};
825*38fd1498Szrj     if (which == &money_put<wchar_t>::id)
826*38fd1498Szrj       return new money_put_shim<wchar_t>{this};
827*38fd1498Szrj     if (which == &moneypunct<wchar_t, true>::id)
828*38fd1498Szrj       return new moneypunct_shim<wchar_t, true>{this};
829*38fd1498Szrj     if (which == &moneypunct<wchar_t, false>::id)
830*38fd1498Szrj       return new moneypunct_shim<wchar_t, false>{this};
831*38fd1498Szrj     if (which == &std::messages<wchar_t>::id)
832*38fd1498Szrj       return new messages_shim<wchar_t>{this};
833*38fd1498Szrj #endif
834*38fd1498Szrj     __throw_logic_error("cannot create shim for unknown locale::facet");
835*38fd1498Szrj   }
836*38fd1498Szrj 
837*38fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
838*38fd1498Szrj } // namespace std
839