xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/src/c++98/locale.cc (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj // Copyright (C) 1997-2018 Free Software Foundation, Inc.
2*38fd1498Szrj //
3*38fd1498Szrj // This file is part of the GNU ISO C++ Library.  This library is free
4*38fd1498Szrj // software; you can redistribute it and/or modify it under the
5*38fd1498Szrj // terms of the GNU General Public License as published by the
6*38fd1498Szrj // Free Software Foundation; either version 3, or (at your option)
7*38fd1498Szrj // any later version.
8*38fd1498Szrj 
9*38fd1498Szrj // This library is distributed in the hope that it will be useful,
10*38fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
11*38fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12*38fd1498Szrj // GNU General Public License for more details.
13*38fd1498Szrj 
14*38fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional
15*38fd1498Szrj // permissions described in the GCC Runtime Library Exception, version
16*38fd1498Szrj // 3.1, as published by the Free Software Foundation.
17*38fd1498Szrj 
18*38fd1498Szrj // You should have received a copy of the GNU General Public License and
19*38fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program;
20*38fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
21*38fd1498Szrj // <http://www.gnu.org/licenses/>.
22*38fd1498Szrj 
23*38fd1498Szrj #define _GLIBCXX_USE_CXX11_ABI 1
24*38fd1498Szrj #include <clocale>
25*38fd1498Szrj #include <cstring>
26*38fd1498Szrj #include <cctype>
27*38fd1498Szrj #include <cwctype>     // For towupper, etc.
28*38fd1498Szrj #include <locale>
29*38fd1498Szrj #include <ext/concurrence.h>
30*38fd1498Szrj 
31*38fd1498Szrj namespace
32*38fd1498Szrj {
33*38fd1498Szrj   __gnu_cxx::__mutex&
get_locale_cache_mutex()34*38fd1498Szrj   get_locale_cache_mutex()
35*38fd1498Szrj   {
36*38fd1498Szrj     static __gnu_cxx::__mutex locale_cache_mutex;
37*38fd1498Szrj     return locale_cache_mutex;
38*38fd1498Szrj   }
39*38fd1498Szrj } // anonymous namespace
40*38fd1498Szrj 
41*38fd1498Szrj // XXX GLIBCXX_ABI Deprecated
42*38fd1498Szrj #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT
43*38fd1498Szrj # define _GLIBCXX_LOC_ID(mangled) extern std::locale::id mangled
44*38fd1498Szrj _GLIBCXX_LOC_ID (_ZNSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE2idE);
45*38fd1498Szrj _GLIBCXX_LOC_ID (_ZNSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE2idE);
46*38fd1498Szrj _GLIBCXX_LOC_ID (_ZNSt9money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE2idE);
47*38fd1498Szrj _GLIBCXX_LOC_ID (_ZNSt9money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE2idE);
48*38fd1498Szrj # ifdef _GLIBCXX_USE_WCHAR_T
49*38fd1498Szrj _GLIBCXX_LOC_ID (_ZNSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE2idE);
50*38fd1498Szrj _GLIBCXX_LOC_ID (_ZNSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE2idE);
51*38fd1498Szrj _GLIBCXX_LOC_ID (_ZNSt9money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE2idE);
52*38fd1498Szrj _GLIBCXX_LOC_ID (_ZNSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE2idE);
53*38fd1498Szrj # endif
54*38fd1498Szrj #endif
55*38fd1498Szrj 
56*38fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default)
57*38fd1498Szrj {
58*38fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
59*38fd1498Szrj 
60*38fd1498Szrj   // Definitions for static const data members of locale.
61*38fd1498Szrj   const locale::category 	locale::none;
62*38fd1498Szrj   const locale::category 	locale::ctype;
63*38fd1498Szrj   const locale::category 	locale::numeric;
64*38fd1498Szrj   const locale::category 	locale::collate;
65*38fd1498Szrj   const locale::category 	locale::time;
66*38fd1498Szrj   const locale::category 	locale::monetary;
67*38fd1498Szrj   const locale::category 	locale::messages;
68*38fd1498Szrj   const locale::category 	locale::all;
69*38fd1498Szrj 
70*38fd1498Szrj   // These are no longer exported.
71*38fd1498Szrj   locale::_Impl*                locale::_S_classic;
72*38fd1498Szrj   locale::_Impl* 		locale::_S_global;
73*38fd1498Szrj 
74*38fd1498Szrj #ifdef __GTHREADS
75*38fd1498Szrj   __gthread_once_t 		locale::_S_once = __GTHREAD_ONCE_INIT;
76*38fd1498Szrj #endif
77*38fd1498Szrj 
locale(const locale & __other)78*38fd1498Szrj   locale::locale(const locale& __other) throw()
79*38fd1498Szrj   : _M_impl(__other._M_impl)
80*38fd1498Szrj   { _M_impl->_M_add_reference(); }
81*38fd1498Szrj 
82*38fd1498Szrj   // This is used to initialize global and classic locales, and
83*38fd1498Szrj   // assumes that the _Impl objects are constructed correctly.
84*38fd1498Szrj   // The lack of a reference increment is intentional.
locale(_Impl * __ip)85*38fd1498Szrj   locale::locale(_Impl* __ip) throw() : _M_impl(__ip)
86*38fd1498Szrj   { }
87*38fd1498Szrj 
~locale()88*38fd1498Szrj   locale::~locale() throw()
89*38fd1498Szrj   { _M_impl->_M_remove_reference(); }
90*38fd1498Szrj 
91*38fd1498Szrj   bool
operator ==(const locale & __rhs) const92*38fd1498Szrj   locale::operator==(const locale& __rhs) const throw()
93*38fd1498Szrj   {
94*38fd1498Szrj     // Deal first with the common cases, fast to process: refcopies,
95*38fd1498Szrj     // unnamed (i.e., !_M_names[0]), "simple" (!_M_names[1] => all the
96*38fd1498Szrj     // categories same name, i.e., _M_names[0]). Otherwise fall back
97*38fd1498Szrj     // to the general locale::name().
98*38fd1498Szrj     bool __ret;
99*38fd1498Szrj     if (_M_impl == __rhs._M_impl)
100*38fd1498Szrj       __ret = true;
101*38fd1498Szrj     else if (!_M_impl->_M_names[0] || !__rhs._M_impl->_M_names[0]
102*38fd1498Szrj 	     || std::strcmp(_M_impl->_M_names[0],
103*38fd1498Szrj 			    __rhs._M_impl->_M_names[0]) != 0)
104*38fd1498Szrj       __ret = false;
105*38fd1498Szrj     else if (!_M_impl->_M_names[1] && !__rhs._M_impl->_M_names[1])
106*38fd1498Szrj       __ret = true;
107*38fd1498Szrj     else
108*38fd1498Szrj       __ret = this->name() == __rhs.name();
109*38fd1498Szrj     return __ret;
110*38fd1498Szrj   }
111*38fd1498Szrj 
112*38fd1498Szrj   const locale&
operator =(const locale & __other)113*38fd1498Szrj   locale::operator=(const locale& __other) throw()
114*38fd1498Szrj   {
115*38fd1498Szrj     __other._M_impl->_M_add_reference();
116*38fd1498Szrj     _M_impl->_M_remove_reference();
117*38fd1498Szrj     _M_impl = __other._M_impl;
118*38fd1498Szrj     return *this;
119*38fd1498Szrj   }
120*38fd1498Szrj 
121*38fd1498Szrj   _GLIBCXX_DEFAULT_ABI_TAG
122*38fd1498Szrj   string
name() const123*38fd1498Szrj   locale::name() const
124*38fd1498Szrj   {
125*38fd1498Szrj     string __ret;
126*38fd1498Szrj     if (!_M_impl->_M_names[0])
127*38fd1498Szrj       __ret = '*';
128*38fd1498Szrj     else if (_M_impl->_M_check_same_name())
129*38fd1498Szrj       __ret = _M_impl->_M_names[0];
130*38fd1498Szrj     else
131*38fd1498Szrj       {
132*38fd1498Szrj 	__ret.reserve(128);
133*38fd1498Szrj 	__ret += _S_categories[0];
134*38fd1498Szrj 	__ret += '=';
135*38fd1498Szrj 	__ret += _M_impl->_M_names[0];
136*38fd1498Szrj 	for (size_t __i = 1; __i < _S_categories_size; ++__i)
137*38fd1498Szrj 	  {
138*38fd1498Szrj 	    __ret += ';';
139*38fd1498Szrj 	    __ret += _S_categories[__i];
140*38fd1498Szrj 	    __ret += '=';
141*38fd1498Szrj 	    __ret += _M_impl->_M_names[__i];
142*38fd1498Szrj 	  }
143*38fd1498Szrj       }
144*38fd1498Szrj     return __ret;
145*38fd1498Szrj   }
146*38fd1498Szrj 
147*38fd1498Szrj   locale::category
_S_normalize_category(category __cat)148*38fd1498Szrj   locale::_S_normalize_category(category __cat)
149*38fd1498Szrj   {
150*38fd1498Szrj     int __ret = 0;
151*38fd1498Szrj     if (__cat == none || ((__cat & all) && !(__cat & ~all)))
152*38fd1498Szrj       __ret = __cat;
153*38fd1498Szrj     else
154*38fd1498Szrj       {
155*38fd1498Szrj 	// NB: May be a C-style "LC_ALL" category; convert.
156*38fd1498Szrj 	switch (__cat)
157*38fd1498Szrj 	  {
158*38fd1498Szrj 	  case LC_COLLATE:
159*38fd1498Szrj 	    __ret = collate;
160*38fd1498Szrj 	    break;
161*38fd1498Szrj 	  case LC_CTYPE:
162*38fd1498Szrj 	    __ret = ctype;
163*38fd1498Szrj 	    break;
164*38fd1498Szrj 	  case LC_MONETARY:
165*38fd1498Szrj 	    __ret = monetary;
166*38fd1498Szrj 	    break;
167*38fd1498Szrj 	  case LC_NUMERIC:
168*38fd1498Szrj 	    __ret = numeric;
169*38fd1498Szrj 	    break;
170*38fd1498Szrj 	  case LC_TIME:
171*38fd1498Szrj 	    __ret = time;
172*38fd1498Szrj 	    break;
173*38fd1498Szrj #ifdef _GLIBCXX_HAVE_LC_MESSAGES
174*38fd1498Szrj 	  case LC_MESSAGES:
175*38fd1498Szrj 	    __ret = messages;
176*38fd1498Szrj 	    break;
177*38fd1498Szrj #endif
178*38fd1498Szrj 	  case LC_ALL:
179*38fd1498Szrj 	    __ret = all;
180*38fd1498Szrj 	    break;
181*38fd1498Szrj 	  default:
182*38fd1498Szrj 	    __throw_runtime_error(__N("locale::_S_normalize_category "
183*38fd1498Szrj 				  "category not found"));
184*38fd1498Szrj 	  }
185*38fd1498Szrj       }
186*38fd1498Szrj     return __ret;
187*38fd1498Szrj   }
188*38fd1498Szrj 
189*38fd1498Szrj   // locale::facet
190*38fd1498Szrj   __c_locale locale::facet::_S_c_locale;
191*38fd1498Szrj 
192*38fd1498Szrj   const char locale::facet::_S_c_name[2] = "C";
193*38fd1498Szrj 
194*38fd1498Szrj #ifdef __GTHREADS
195*38fd1498Szrj   __gthread_once_t locale::facet::_S_once = __GTHREAD_ONCE_INIT;
196*38fd1498Szrj #endif
197*38fd1498Szrj 
198*38fd1498Szrj   void
_S_initialize_once()199*38fd1498Szrj   locale::facet::_S_initialize_once()
200*38fd1498Szrj   {
201*38fd1498Szrj     // Initialize the underlying locale model.
202*38fd1498Szrj     _S_create_c_locale(_S_c_locale, _S_c_name);
203*38fd1498Szrj   }
204*38fd1498Szrj 
205*38fd1498Szrj   __c_locale
_S_get_c_locale()206*38fd1498Szrj   locale::facet::_S_get_c_locale()
207*38fd1498Szrj   {
208*38fd1498Szrj #ifdef __GTHREADS
209*38fd1498Szrj     if (__gthread_active_p())
210*38fd1498Szrj       __gthread_once(&_S_once, _S_initialize_once);
211*38fd1498Szrj     else
212*38fd1498Szrj #endif
213*38fd1498Szrj       {
214*38fd1498Szrj 	if (!_S_c_locale)
215*38fd1498Szrj 	  _S_initialize_once();
216*38fd1498Szrj       }
217*38fd1498Szrj     return _S_c_locale;
218*38fd1498Szrj   }
219*38fd1498Szrj 
220*38fd1498Szrj   const char*
_S_get_c_name()221*38fd1498Szrj   locale::facet::_S_get_c_name() throw()
222*38fd1498Szrj   { return _S_c_name; }
223*38fd1498Szrj 
224*38fd1498Szrj   locale::facet::
~facet()225*38fd1498Szrj   ~facet() { }
226*38fd1498Szrj 
227*38fd1498Szrj   // locale::_Impl
228*38fd1498Szrj   locale::_Impl::
~_Impl()229*38fd1498Szrj   ~_Impl() throw()
230*38fd1498Szrj   {
231*38fd1498Szrj     if (_M_facets)
232*38fd1498Szrj       for (size_t __i = 0; __i < _M_facets_size; ++__i)
233*38fd1498Szrj 	if (_M_facets[__i])
234*38fd1498Szrj 	  _M_facets[__i]->_M_remove_reference();
235*38fd1498Szrj     delete [] _M_facets;
236*38fd1498Szrj 
237*38fd1498Szrj     if (_M_caches)
238*38fd1498Szrj       for (size_t __i = 0; __i < _M_facets_size; ++__i)
239*38fd1498Szrj 	if (_M_caches[__i])
240*38fd1498Szrj 	  _M_caches[__i]->_M_remove_reference();
241*38fd1498Szrj     delete [] _M_caches;
242*38fd1498Szrj 
243*38fd1498Szrj     if (_M_names)
244*38fd1498Szrj       for (size_t __i = 0; __i < _S_categories_size; ++__i)
245*38fd1498Szrj 	delete [] _M_names[__i];
246*38fd1498Szrj     delete [] _M_names;
247*38fd1498Szrj   }
248*38fd1498Szrj 
249*38fd1498Szrj   // Clone existing _Impl object.
250*38fd1498Szrj   locale::_Impl::
_Impl(const _Impl & __imp,size_t __refs)251*38fd1498Szrj   _Impl(const _Impl& __imp, size_t __refs)
252*38fd1498Szrj   : _M_refcount(__refs), _M_facets(0), _M_facets_size(__imp._M_facets_size),
253*38fd1498Szrj   _M_caches(0), _M_names(0)
254*38fd1498Szrj   {
255*38fd1498Szrj     __try
256*38fd1498Szrj       {
257*38fd1498Szrj 	_M_facets = new const facet*[_M_facets_size];
258*38fd1498Szrj 	for (size_t __i = 0; __i < _M_facets_size; ++__i)
259*38fd1498Szrj 	  {
260*38fd1498Szrj 	    _M_facets[__i] = __imp._M_facets[__i];
261*38fd1498Szrj 	    if (_M_facets[__i])
262*38fd1498Szrj 	      _M_facets[__i]->_M_add_reference();
263*38fd1498Szrj 	  }
264*38fd1498Szrj 	_M_caches = new const facet*[_M_facets_size];
265*38fd1498Szrj 	for (size_t __j = 0; __j < _M_facets_size; ++__j)
266*38fd1498Szrj 	  {
267*38fd1498Szrj 	    _M_caches[__j] = __imp._M_caches[__j];
268*38fd1498Szrj 	    if (_M_caches[__j])
269*38fd1498Szrj 	      _M_caches[__j]->_M_add_reference();
270*38fd1498Szrj 	  }
271*38fd1498Szrj 	_M_names = new char*[_S_categories_size];
272*38fd1498Szrj 	for (size_t __k = 0; __k < _S_categories_size; ++__k)
273*38fd1498Szrj 	  _M_names[__k] = 0;
274*38fd1498Szrj 
275*38fd1498Szrj 	// Name the categories.
276*38fd1498Szrj 	for (size_t __l = 0; (__l < _S_categories_size
277*38fd1498Szrj 			      && __imp._M_names[__l]); ++__l)
278*38fd1498Szrj 	  {
279*38fd1498Szrj 	    const size_t __len = std::strlen(__imp._M_names[__l]) + 1;
280*38fd1498Szrj 	    _M_names[__l] = new char[__len];
281*38fd1498Szrj 	    std::memcpy(_M_names[__l], __imp._M_names[__l], __len);
282*38fd1498Szrj 	  }
283*38fd1498Szrj       }
284*38fd1498Szrj     __catch(...)
285*38fd1498Szrj       {
286*38fd1498Szrj 	this->~_Impl();
287*38fd1498Szrj 	__throw_exception_again;
288*38fd1498Szrj       }
289*38fd1498Szrj   }
290*38fd1498Szrj 
291*38fd1498Szrj   void
292*38fd1498Szrj   locale::_Impl::
_M_replace_category(const _Impl * __imp,const locale::id * const * __idpp)293*38fd1498Szrj   _M_replace_category(const _Impl* __imp,
294*38fd1498Szrj 		      const locale::id* const* __idpp)
295*38fd1498Szrj   {
296*38fd1498Szrj     for (; *__idpp; ++__idpp)
297*38fd1498Szrj       _M_replace_facet(__imp, *__idpp);
298*38fd1498Szrj   }
299*38fd1498Szrj 
300*38fd1498Szrj   void
301*38fd1498Szrj   locale::_Impl::
_M_replace_facet(const _Impl * __imp,const locale::id * __idp)302*38fd1498Szrj   _M_replace_facet(const _Impl* __imp, const locale::id* __idp)
303*38fd1498Szrj   {
304*38fd1498Szrj     size_t __index = __idp->_M_id();
305*38fd1498Szrj     if ((__index > (__imp->_M_facets_size - 1))
306*38fd1498Szrj 	|| !__imp->_M_facets[__index])
307*38fd1498Szrj       __throw_runtime_error(__N("locale::_Impl::_M_replace_facet"));
308*38fd1498Szrj     _M_install_facet(__idp, __imp->_M_facets[__index]);
309*38fd1498Szrj   }
310*38fd1498Szrj 
311*38fd1498Szrj   void
312*38fd1498Szrj   locale::_Impl::
_M_install_facet(const locale::id * __idp,const facet * __fp)313*38fd1498Szrj   _M_install_facet(const locale::id* __idp, const facet* __fp)
314*38fd1498Szrj   {
315*38fd1498Szrj     if (__fp)
316*38fd1498Szrj       {
317*38fd1498Szrj 	size_t __index = __idp->_M_id();
318*38fd1498Szrj 
319*38fd1498Szrj 	// Check size of facet vector to ensure adequate room.
320*38fd1498Szrj 	if (__index > _M_facets_size - 1)
321*38fd1498Szrj 	  {
322*38fd1498Szrj 	    const size_t __new_size = __index + 4;
323*38fd1498Szrj 
324*38fd1498Szrj 	    // New facet array.
325*38fd1498Szrj 	    const facet** __oldf = _M_facets;
326*38fd1498Szrj 	    const facet** __newf;
327*38fd1498Szrj 	    __newf = new const facet*[__new_size];
328*38fd1498Szrj 	    for (size_t __i = 0; __i < _M_facets_size; ++__i)
329*38fd1498Szrj 	      __newf[__i] = _M_facets[__i];
330*38fd1498Szrj 	    for (size_t __l = _M_facets_size; __l < __new_size; ++__l)
331*38fd1498Szrj 	      __newf[__l] = 0;
332*38fd1498Szrj 
333*38fd1498Szrj 	    // New cache array.
334*38fd1498Szrj 	    const facet** __oldc = _M_caches;
335*38fd1498Szrj 	    const facet** __newc;
336*38fd1498Szrj 	    __try
337*38fd1498Szrj 	      {
338*38fd1498Szrj 		__newc = new const facet*[__new_size];
339*38fd1498Szrj 	      }
340*38fd1498Szrj 	    __catch(...)
341*38fd1498Szrj 	      {
342*38fd1498Szrj 		delete [] __newf;
343*38fd1498Szrj 		__throw_exception_again;
344*38fd1498Szrj 	      }
345*38fd1498Szrj 	    for (size_t __j = 0; __j < _M_facets_size; ++__j)
346*38fd1498Szrj 	      __newc[__j] = _M_caches[__j];
347*38fd1498Szrj 	    for (size_t __k = _M_facets_size; __k < __new_size; ++__k)
348*38fd1498Szrj 	      __newc[__k] = 0;
349*38fd1498Szrj 
350*38fd1498Szrj 	    _M_facets_size = __new_size;
351*38fd1498Szrj 	    _M_facets = __newf;
352*38fd1498Szrj 	    _M_caches = __newc;
353*38fd1498Szrj 	    delete [] __oldf;
354*38fd1498Szrj 	    delete [] __oldc;
355*38fd1498Szrj 	  }
356*38fd1498Szrj 
357*38fd1498Szrj 	__fp->_M_add_reference();
358*38fd1498Szrj 	const facet*& __fpr = _M_facets[__index];
359*38fd1498Szrj 	if (__fpr)
360*38fd1498Szrj 	  {
361*38fd1498Szrj #if _GLIBCXX_USE_DUAL_ABI
362*38fd1498Szrj             // If this is a twinned facet replace its twin with a shim.
363*38fd1498Szrj             for (const id* const* p = _S_twinned_facets; *p != 0; p += 2)
364*38fd1498Szrj               {
365*38fd1498Szrj                 if (p[0]->_M_id() == __index)
366*38fd1498Szrj                   {
367*38fd1498Szrj                     // replacing the old ABI facet, also replace new ABI twin
368*38fd1498Szrj                     const facet*& __fpr2 = _M_facets[p[1]->_M_id()];
369*38fd1498Szrj                     if (__fpr2)
370*38fd1498Szrj                       {
371*38fd1498Szrj                         const facet* __fp2 = __fp->_M_sso_shim(p[1]);
372*38fd1498Szrj                         __fp2->_M_add_reference();
373*38fd1498Szrj                         __fpr2->_M_remove_reference();
374*38fd1498Szrj                         __fpr2 = __fp2;
375*38fd1498Szrj                       }
376*38fd1498Szrj                     break;
377*38fd1498Szrj                   }
378*38fd1498Szrj                 else if (p[1]->_M_id() == __index)
379*38fd1498Szrj                   {
380*38fd1498Szrj                     // replacing the new ABI facet, also replace old ABI twin
381*38fd1498Szrj                     const facet*& __fpr2 = _M_facets[p[0]->_M_id()];
382*38fd1498Szrj                     if (__fpr2)
383*38fd1498Szrj                       {
384*38fd1498Szrj                         const facet* __fp2 = __fp->_M_cow_shim(p[0]);
385*38fd1498Szrj                         __fp2->_M_add_reference();
386*38fd1498Szrj                         __fpr2->_M_remove_reference();
387*38fd1498Szrj                         __fpr2 = __fp2;
388*38fd1498Szrj                       }
389*38fd1498Szrj                     break;
390*38fd1498Szrj                   }
391*38fd1498Szrj               }
392*38fd1498Szrj #endif
393*38fd1498Szrj 	    // Replacing an existing facet. Order matters.
394*38fd1498Szrj 	    __fpr->_M_remove_reference();
395*38fd1498Szrj 	    __fpr = __fp;
396*38fd1498Szrj 	  }
397*38fd1498Szrj 	else
398*38fd1498Szrj 	  {
399*38fd1498Szrj 	    // Installing a newly created facet into an empty
400*38fd1498Szrj 	    // _M_facets container, say a newly-constructed,
401*38fd1498Szrj 	    // swanky-fresh _Impl.
402*38fd1498Szrj 	    _M_facets[__index] = __fp;
403*38fd1498Szrj 	  }
404*38fd1498Szrj 
405*38fd1498Szrj 	// Ideally, it would be nice to only remove the caches that
406*38fd1498Szrj 	// are now incorrect. However, some of the caches depend on
407*38fd1498Szrj 	// multiple facets, and we only know about one facet
408*38fd1498Szrj 	// here. It's no great loss: the first use of the new facet
409*38fd1498Szrj 	// will create a new, correctly cached facet anyway.
410*38fd1498Szrj 	for (size_t __i = 0; __i < _M_facets_size; ++__i)
411*38fd1498Szrj 	  {
412*38fd1498Szrj 	    const facet* __cpr = _M_caches[__i];
413*38fd1498Szrj 	    if (__cpr)
414*38fd1498Szrj 	      {
415*38fd1498Szrj 		__cpr->_M_remove_reference();
416*38fd1498Szrj 		_M_caches[__i] = 0;
417*38fd1498Szrj 	      }
418*38fd1498Szrj 	  }
419*38fd1498Szrj       }
420*38fd1498Szrj   }
421*38fd1498Szrj 
422*38fd1498Szrj   void
423*38fd1498Szrj   locale::_Impl::
_M_install_cache(const facet * __cache,size_t __index)424*38fd1498Szrj   _M_install_cache(const facet* __cache, size_t __index)
425*38fd1498Szrj   {
426*38fd1498Szrj     __gnu_cxx::__scoped_lock sentry(get_locale_cache_mutex());
427*38fd1498Szrj #if _GLIBCXX_USE_DUAL_ABI
428*38fd1498Szrj     // If this cache is for one of the facets that is instantiated twice,
429*38fd1498Szrj     // for old and new std::string ABI, install it in both slots.
430*38fd1498Szrj     size_t __index2 = -1;
431*38fd1498Szrj     for (const id* const* p = _S_twinned_facets; *p != 0; p += 2)
432*38fd1498Szrj       {
433*38fd1498Szrj         if (p[0]->_M_id() == __index)
434*38fd1498Szrj           {
435*38fd1498Szrj             __index2 = p[1]->_M_id();
436*38fd1498Szrj             break;
437*38fd1498Szrj           }
438*38fd1498Szrj         else if (p[1]->_M_id() == __index)
439*38fd1498Szrj           {
440*38fd1498Szrj             __index2 = __index;
441*38fd1498Szrj             __index = p[0]->_M_id();
442*38fd1498Szrj             break;
443*38fd1498Szrj           }
444*38fd1498Szrj       }
445*38fd1498Szrj #endif
446*38fd1498Szrj     if (_M_caches[__index] != 0)
447*38fd1498Szrj       {
448*38fd1498Szrj 	// Some other thread got in first.
449*38fd1498Szrj 	delete __cache;
450*38fd1498Szrj       }
451*38fd1498Szrj     else
452*38fd1498Szrj       {
453*38fd1498Szrj 	__cache->_M_add_reference();
454*38fd1498Szrj 	_M_caches[__index] = __cache;
455*38fd1498Szrj #if _GLIBCXX_USE_DUAL_ABI
456*38fd1498Szrj         if (__index2 != size_t(-1))
457*38fd1498Szrj           {
458*38fd1498Szrj             __cache->_M_add_reference();
459*38fd1498Szrj             _M_caches[__index2] = __cache;
460*38fd1498Szrj           }
461*38fd1498Szrj #endif
462*38fd1498Szrj       }
463*38fd1498Szrj   }
464*38fd1498Szrj 
465*38fd1498Szrj   // locale::id
466*38fd1498Szrj   // Definitions for static const data members of locale::id
467*38fd1498Szrj   _Atomic_word locale::id::_S_refcount;  // init'd to 0 by linker
468*38fd1498Szrj 
469*38fd1498Szrj   size_t
_M_id() const470*38fd1498Szrj   locale::id::_M_id() const throw()
471*38fd1498Szrj   {
472*38fd1498Szrj     if (!_M_index)
473*38fd1498Szrj       {
474*38fd1498Szrj 	// XXX GLIBCXX_ABI Deprecated
475*38fd1498Szrj #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT
476*38fd1498Szrj 	locale::id *f = 0;
477*38fd1498Szrj # define _GLIBCXX_SYNC_ID(facet, mangled) \
478*38fd1498Szrj 	if (this == &::mangled)				\
479*38fd1498Szrj 	  f = &facet::id
480*38fd1498Szrj 	_GLIBCXX_SYNC_ID (num_get<char>, _ZNSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE2idE);
481*38fd1498Szrj 	_GLIBCXX_SYNC_ID (num_put<char>, _ZNSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE2idE);
482*38fd1498Szrj 	_GLIBCXX_SYNC_ID (money_get<char>, _ZNSt9money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE2idE);
483*38fd1498Szrj 	_GLIBCXX_SYNC_ID (money_put<char>, _ZNSt9money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE2idE);
484*38fd1498Szrj # ifdef _GLIBCXX_USE_WCHAR_T
485*38fd1498Szrj 	_GLIBCXX_SYNC_ID (num_get<wchar_t>, _ZNSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE2idE);
486*38fd1498Szrj 	_GLIBCXX_SYNC_ID (num_put<wchar_t>, _ZNSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE2idE);
487*38fd1498Szrj 	_GLIBCXX_SYNC_ID (money_get<wchar_t>, _ZNSt9money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE2idE);
488*38fd1498Szrj 	_GLIBCXX_SYNC_ID (money_put<wchar_t>, _ZNSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE2idE);
489*38fd1498Szrj # endif
490*38fd1498Szrj 	if (f)
491*38fd1498Szrj 	  _M_index = 1 + f->_M_id();
492*38fd1498Szrj 	else
493*38fd1498Szrj #endif
494*38fd1498Szrj 	  _M_index = 1 + __gnu_cxx::__exchange_and_add_dispatch(&_S_refcount,
495*38fd1498Szrj 								1);
496*38fd1498Szrj       }
497*38fd1498Szrj     return _M_index - 1;
498*38fd1498Szrj   }
499*38fd1498Szrj 
500*38fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
501*38fd1498Szrj } // namespace
502