xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/bits/locale_facets_nonio.tcc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 // Locale support -*- C++ -*-
2 
3 // Copyright (C) 2007-2022 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 /** @file bits/locale_facets_nonio.tcc
26  *  This is an internal header file, included by other library headers.
27  *  Do not attempt to use it directly. @headername{locale}
28  */
29 
30 #ifndef _LOCALE_FACETS_NONIO_TCC
31 #define _LOCALE_FACETS_NONIO_TCC 1
32 
33 #pragma GCC system_header
34 
35 namespace std _GLIBCXX_VISIBILITY(default)
36 {
37 _GLIBCXX_BEGIN_NAMESPACE_VERSION
38 
39   template<typename _CharT, bool _Intl>
40     struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
41     {
42       const __moneypunct_cache<_CharT, _Intl>*
operator ()std::__use_cache43       operator() (const locale& __loc) const
44       {
45 	const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
46 	const locale::facet** __caches = __loc._M_impl->_M_caches;
47 	if (!__caches[__i])
48 	  {
49 	    __moneypunct_cache<_CharT, _Intl>* __tmp = 0;
50 	    __try
51 	      {
52 		__tmp = new __moneypunct_cache<_CharT, _Intl>;
53 		__tmp->_M_cache(__loc);
54 	      }
55 	    __catch(...)
56 	      {
57 		delete __tmp;
58 		__throw_exception_again;
59 	      }
60 	    __loc._M_impl->_M_install_cache(__tmp, __i);
61 	  }
62 	return static_cast<
63 	  const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
64       }
65     };
66 
67   template<typename _CharT, bool _Intl>
68     void
_M_cache(const locale & __loc)69     __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
70     {
71       const moneypunct<_CharT, _Intl>& __mp =
72 	use_facet<moneypunct<_CharT, _Intl> >(__loc);
73 
74       struct _Scoped_str
75       {
76 	size_t _M_len;
77 	_CharT* _M_str;
78 
79 	explicit
80 	_Scoped_str(const basic_string<_CharT>& __str)
81 	: _M_len(__str.size()), _M_str(new _CharT[_M_len])
82 	{ __str.copy(_M_str, _M_len); }
83 
84 	~_Scoped_str() { delete[] _M_str; }
85 
86 	void
87 	_M_release(const _CharT*& __p, size_t& __n)
88 	{
89 	  __p = _M_str;
90 	  __n = _M_len;
91 	  _M_str = 0;
92 	}
93       };
94 
95       _Scoped_str __curr_symbol(__mp.curr_symbol());
96       _Scoped_str __positive_sign(__mp.positive_sign());
97       _Scoped_str __negative_sign(__mp.negative_sign());
98 
99       const string& __g = __mp.grouping();
100       const size_t __g_size = __g.size();
101       char* const __grouping = new char[__g_size];
102       __g.copy(__grouping, __g_size);
103 
104       // All allocations succeeded without throwing, OK to modify *this now.
105 
106       _M_grouping = __grouping;
107       _M_grouping_size = __g_size;
108       _M_use_grouping = (__g_size
109 			 && static_cast<signed char>(__grouping[0]) > 0
110 			 && (__grouping[0]
111 			     != __gnu_cxx::__numeric_traits<char>::__max));
112 
113       _M_decimal_point = __mp.decimal_point();
114       _M_thousands_sep = __mp.thousands_sep();
115 
116       __curr_symbol._M_release(_M_curr_symbol, _M_curr_symbol_size);
117       __positive_sign._M_release(_M_positive_sign, _M_positive_sign_size);
118       __negative_sign._M_release(_M_negative_sign, _M_negative_sign_size);
119 
120       _M_frac_digits = __mp.frac_digits();
121       _M_pos_format = __mp.pos_format();
122       _M_neg_format = __mp.neg_format();
123 
124       const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
125       __ct.widen(money_base::_S_atoms,
126 		 money_base::_S_atoms + money_base::_S_end, _M_atoms);
127 
128       _M_allocated = true;
129     }
130 
131 _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
132 
133   template<typename _CharT, typename _InIter>
134     template<bool _Intl>
135       _InIter
136       money_get<_CharT, _InIter>::
_M_extract(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,string & __units) const137       _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
138 		 ios_base::iostate& __err, string& __units) const
139       {
140 	typedef char_traits<_CharT>			  __traits_type;
141 	typedef typename string_type::size_type	          size_type;
142 	typedef money_base::part			  part;
143 	typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
144 
145 	const locale& __loc = __io._M_getloc();
146 	const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
147 
148 	__use_cache<__cache_type> __uc;
149 	const __cache_type* __lc = __uc(__loc);
150 	const char_type* __lit = __lc->_M_atoms;
151 
152 	// Deduced sign.
153 	bool __negative = false;
154 	// Sign size.
155 	size_type __sign_size = 0;
156 	// True if sign is mandatory.
157 	const bool __mandatory_sign = (__lc->_M_positive_sign_size
158 				       && __lc->_M_negative_sign_size);
159 	// String of grouping info from thousands_sep plucked from __units.
160 	string __grouping_tmp;
161 	if (__lc->_M_use_grouping)
162 	  __grouping_tmp.reserve(32);
163 	// Last position before the decimal point.
164 	int __last_pos = 0;
165 	// Separator positions, then, possibly, fractional digits.
166 	int __n = 0;
167 	// If input iterator is in a valid state.
168 	bool __testvalid = true;
169 	// Flag marking when a decimal point is found.
170 	bool __testdecfound = false;
171 
172 	// The tentative returned string is stored here.
173 	string __res;
174 	__res.reserve(32);
175 
176 	const char_type* __lit_zero = __lit + money_base::_S_zero;
177 	const money_base::pattern __p = __lc->_M_neg_format;
178 	for (int __i = 0; __i < 4 && __testvalid; ++__i)
179 	  {
180 	    const part __which = static_cast<part>(__p.field[__i]);
181 	    switch (__which)
182 	      {
183 	      case money_base::symbol:
184 		// According to 22.2.6.1.2, p2, symbol is required
185 		// if (__io.flags() & ios_base::showbase), otherwise
186 		// is optional and consumed only if other characters
187 		// are needed to complete the format.
188 		if (__io.flags() & ios_base::showbase || __sign_size > 1
189 		    || __i == 0
190 		    || (__i == 1 && (__mandatory_sign
191 				     || (static_cast<part>(__p.field[0])
192 					 == money_base::sign)
193 				     || (static_cast<part>(__p.field[2])
194 					 == money_base::space)))
195 		    || (__i == 2 && ((static_cast<part>(__p.field[3])
196 				      == money_base::value)
197 				     || (__mandatory_sign
198 					 && (static_cast<part>(__p.field[3])
199 					     == money_base::sign)))))
200 		  {
201 		    const size_type __len = __lc->_M_curr_symbol_size;
202 		    size_type __j = 0;
203 		    for (; __beg != __end && __j < __len
204 			   && *__beg == __lc->_M_curr_symbol[__j];
205 			 ++__beg, (void)++__j);
206 		    if (__j != __len
207 			&& (__j || __io.flags() & ios_base::showbase))
208 		      __testvalid = false;
209 		  }
210 		break;
211 	      case money_base::sign:
212 		// Sign might not exist, or be more than one character long.
213 		if (__lc->_M_positive_sign_size && __beg != __end
214 		    && *__beg == __lc->_M_positive_sign[0])
215 		  {
216 		    __sign_size = __lc->_M_positive_sign_size;
217 		    ++__beg;
218 		  }
219 		else if (__lc->_M_negative_sign_size && __beg != __end
220 			 && *__beg == __lc->_M_negative_sign[0])
221 		  {
222 		    __negative = true;
223 		    __sign_size = __lc->_M_negative_sign_size;
224 		    ++__beg;
225 		  }
226 		else if (__lc->_M_positive_sign_size
227 			 && !__lc->_M_negative_sign_size)
228 		  // "... if no sign is detected, the result is given the sign
229 		  // that corresponds to the source of the empty string"
230 		  __negative = true;
231 		else if (__mandatory_sign)
232 		  __testvalid = false;
233 		break;
234 	      case money_base::value:
235 		// Extract digits, remove and stash away the
236 		// grouping of found thousands separators.
237 		for (; __beg != __end; ++__beg)
238 		  {
239 		    const char_type __c = *__beg;
240 		    const char_type* __q = __traits_type::find(__lit_zero,
241 							       10, __c);
242 		    if (__q != 0)
243 		      {
244 			__res += money_base::_S_atoms[__q - __lit];
245 			++__n;
246 		      }
247 		    else if (__c == __lc->_M_decimal_point
248 			     && !__testdecfound)
249 		      {
250 			if (__lc->_M_frac_digits <= 0)
251 			  break;
252 
253 			__last_pos = __n;
254 			__n = 0;
255 			__testdecfound = true;
256 		      }
257 		    else if (__lc->_M_use_grouping
258 			     && __c == __lc->_M_thousands_sep
259 			     && !__testdecfound)
260 		      {
261 			if (__n)
262 			  {
263 			    // Mark position for later analysis.
264 			    __grouping_tmp += static_cast<char>(__n);
265 			    __n = 0;
266 			  }
267 			else
268 			  {
269 			    __testvalid = false;
270 			    break;
271 			  }
272 		      }
273 		    else
274 		      break;
275 		  }
276 		if (__res.empty())
277 		  __testvalid = false;
278 		break;
279 	      case money_base::space:
280 		// At least one space is required.
281 		if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
282 		  ++__beg;
283 		else
284 		  __testvalid = false;
285 		// fallthrough
286 	      case money_base::none:
287 		// Only if not at the end of the pattern.
288 		if (__i != 3)
289 		  for (; __beg != __end
290 			 && __ctype.is(ctype_base::space, *__beg); ++__beg);
291 		break;
292 	      }
293 	  }
294 
295 	// Need to get the rest of the sign characters, if they exist.
296 	if (__sign_size > 1 && __testvalid)
297 	  {
298 	    const char_type* __sign = __negative ? __lc->_M_negative_sign
299 	                                         : __lc->_M_positive_sign;
300 	    size_type __i = 1;
301 	    for (; __beg != __end && __i < __sign_size
302 		   && *__beg == __sign[__i]; ++__beg, (void)++__i);
303 
304 	    if (__i != __sign_size)
305 	      __testvalid = false;
306 	  }
307 
308 	if (__testvalid)
309 	  {
310 	    // Strip leading zeros.
311 	    if (__res.size() > 1)
312 	      {
313 		const size_type __first = __res.find_first_not_of('0');
314 		const bool __only_zeros = __first == string::npos;
315 		if (__first)
316 		  __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
317 	      }
318 
319 	    // 22.2.6.1.2, p4
320 	    if (__negative && __res[0] != '0')
321 	      __res.insert(__res.begin(), '-');
322 
323 	    // Test for grouping fidelity.
324 	    if (__grouping_tmp.size())
325 	      {
326 		// Add the ending grouping.
327 		__grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
328 						                   : __n);
329 		if (!std::__verify_grouping(__lc->_M_grouping,
330 					    __lc->_M_grouping_size,
331 					    __grouping_tmp))
332 		  __err |= ios_base::failbit;
333 	      }
334 
335 	    // Iff not enough digits were supplied after the decimal-point.
336 	    if (__testdecfound && __n != __lc->_M_frac_digits)
337 	      __testvalid = false;
338 	  }
339 
340 	// Iff valid sequence is not recognized.
341 	if (!__testvalid)
342 	  __err |= ios_base::failbit;
343 	else
344 	  __units.swap(__res);
345 
346 	// Iff no more characters are available.
347 	if (__beg == __end)
348 	  __err |= ios_base::eofbit;
349 	return __beg;
350       }
351 
352 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
353       && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
354   template<typename _CharT, typename _InIter>
355     _InIter
356     money_get<_CharT, _InIter>::
__do_get(iter_type __beg,iter_type __end,bool __intl,ios_base & __io,ios_base::iostate & __err,double & __units) const357     __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
358 	     ios_base::iostate& __err, double& __units) const
359     {
360       string __str;
361       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
362                      : _M_extract<false>(__beg, __end, __io, __err, __str);
363       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
364       return __beg;
365     }
366 #endif
367 
368   template<typename _CharT, typename _InIter>
369     _InIter
370     money_get<_CharT, _InIter>::
do_get(iter_type __beg,iter_type __end,bool __intl,ios_base & __io,ios_base::iostate & __err,long double & __units) const371     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
372 	   ios_base::iostate& __err, long double& __units) const
373     {
374       string __str;
375       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
376 	             : _M_extract<false>(__beg, __end, __io, __err, __str);
377       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
378       return __beg;
379     }
380 
381   template<typename _CharT, typename _InIter>
382     _InIter
383     money_get<_CharT, _InIter>::
do_get(iter_type __beg,iter_type __end,bool __intl,ios_base & __io,ios_base::iostate & __err,string_type & __digits) const384     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
385 	   ios_base::iostate& __err, string_type& __digits) const
386     {
387       typedef typename string::size_type                  size_type;
388 
389       const locale& __loc = __io._M_getloc();
390       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
391 
392       string __str;
393       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
394 	             : _M_extract<false>(__beg, __end, __io, __err, __str);
395       const size_type __len = __str.size();
396       if (__len)
397 	{
398 	  __digits.resize(__len);
399 	  __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]);
400 	}
401       return __beg;
402     }
403 
404 #if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
405       && defined __LONG_DOUBLE_IEEE128__
406   template<typename _CharT, typename _InIter>
407     _InIter
408     money_get<_CharT, _InIter>::
__do_get(iter_type __beg,iter_type __end,bool __intl,ios_base & __io,ios_base::iostate & __err,__ibm128 & __units) const409     __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
410 	     ios_base::iostate& __err, __ibm128& __units) const
411     {
412       string __str;
413       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
414 	             : _M_extract<false>(__beg, __end, __io, __err, __str);
415       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
416       return __beg;
417     }
418 #endif
419 
420   template<typename _CharT, typename _OutIter>
421     template<bool _Intl>
422       _OutIter
423       money_put<_CharT, _OutIter>::
_M_insert(iter_type __s,ios_base & __io,char_type __fill,const string_type & __digits) const424       _M_insert(iter_type __s, ios_base& __io, char_type __fill,
425 		const string_type& __digits) const
426       {
427 	typedef typename string_type::size_type	          size_type;
428 	typedef money_base::part                          part;
429 	typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
430 
431 	const locale& __loc = __io._M_getloc();
432 	const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
433 
434 	__use_cache<__cache_type> __uc;
435 	const __cache_type* __lc = __uc(__loc);
436 	const char_type* __lit = __lc->_M_atoms;
437 
438 	// Determine if negative or positive formats are to be used, and
439 	// discard leading negative_sign if it is present.
440 	const char_type* __beg = __digits.data();
441 
442 	money_base::pattern __p;
443 	const char_type* __sign;
444 	size_type __sign_size;
445 	if (!(*__beg == __lit[money_base::_S_minus]))
446 	  {
447 	    __p = __lc->_M_pos_format;
448 	    __sign = __lc->_M_positive_sign;
449 	    __sign_size = __lc->_M_positive_sign_size;
450 	  }
451 	else
452 	  {
453 	    __p = __lc->_M_neg_format;
454 	    __sign = __lc->_M_negative_sign;
455 	    __sign_size = __lc->_M_negative_sign_size;
456 	    if (__digits.size())
457 	      ++__beg;
458 	  }
459 
460 	// Look for valid numbers in the ctype facet within input digits.
461 	size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
462 					   __beg + __digits.size()) - __beg;
463 	if (__len)
464 	  {
465 	    // Assume valid input, and attempt to format.
466 	    // Break down input numbers into base components, as follows:
467 	    //   final_value = grouped units + (decimal point) + (digits)
468 	    string_type __value;
469 	    __value.reserve(2 * __len);
470 
471 	    // Add thousands separators to non-decimal digits, per
472 	    // grouping rules.
473 	    long __paddec = __len - __lc->_M_frac_digits;
474 	    if (__paddec > 0)
475 	      {
476 		if (__lc->_M_frac_digits < 0)
477 		  __paddec = __len;
478 		if (__lc->_M_grouping_size)
479 		  {
480 		    __value.assign(2 * __paddec, char_type());
481 		    _CharT* __vend =
482 		      std::__add_grouping(&__value[0], __lc->_M_thousands_sep,
483 					  __lc->_M_grouping,
484 					  __lc->_M_grouping_size,
485 					  __beg, __beg + __paddec);
486 		    __value.erase(__vend - &__value[0]);
487 		  }
488 		else
489 		  __value.assign(__beg, __paddec);
490 	      }
491 
492 	    // Deal with decimal point, decimal digits.
493 	    if (__lc->_M_frac_digits > 0)
494 	      {
495 		__value += __lc->_M_decimal_point;
496 		if (__paddec >= 0)
497 		  __value.append(__beg + __paddec, __lc->_M_frac_digits);
498 		else
499 		  {
500 		    // Have to pad zeros in the decimal position.
501 		    __value.append(-__paddec, __lit[money_base::_S_zero]);
502 		    __value.append(__beg, __len);
503 		  }
504 	      }
505 
506 	    // Calculate length of resulting string.
507 	    const ios_base::fmtflags __f = __io.flags()
508 	                                   & ios_base::adjustfield;
509 	    __len = __value.size() + __sign_size;
510 	    __len += ((__io.flags() & ios_base::showbase)
511 		      ? __lc->_M_curr_symbol_size : 0);
512 
513 	    string_type __res;
514 	    __res.reserve(2 * __len);
515 
516 	    const size_type __width = static_cast<size_type>(__io.width());
517 	    const bool __testipad = (__f == ios_base::internal
518 				     && __len < __width);
519 	    // Fit formatted digits into the required pattern.
520 	    for (int __i = 0; __i < 4; ++__i)
521 	      {
522 		const part __which = static_cast<part>(__p.field[__i]);
523 		switch (__which)
524 		  {
525 		  case money_base::symbol:
526 		    if (__io.flags() & ios_base::showbase)
527 		      __res.append(__lc->_M_curr_symbol,
528 				   __lc->_M_curr_symbol_size);
529 		    break;
530 		  case money_base::sign:
531 		    // Sign might not exist, or be more than one
532 		    // character long. In that case, add in the rest
533 		    // below.
534 		    if (__sign_size)
535 		      __res += __sign[0];
536 		    break;
537 		  case money_base::value:
538 		    __res += __value;
539 		    break;
540 		  case money_base::space:
541 		    // At least one space is required, but if internal
542 		    // formatting is required, an arbitrary number of
543 		    // fill spaces will be necessary.
544 		    if (__testipad)
545 		      __res.append(__width - __len, __fill);
546 		    else
547 		      __res += __fill;
548 		    break;
549 		  case money_base::none:
550 		    if (__testipad)
551 		      __res.append(__width - __len, __fill);
552 		    break;
553 		  }
554 	      }
555 
556 	    // Special case of multi-part sign parts.
557 	    if (__sign_size > 1)
558 	      __res.append(__sign + 1, __sign_size - 1);
559 
560 	    // Pad, if still necessary.
561 	    __len = __res.size();
562 	    if (__width > __len)
563 	      {
564 		if (__f == ios_base::left)
565 		  // After.
566 		  __res.append(__width - __len, __fill);
567 		else
568 		  // Before.
569 		  __res.insert(0, __width - __len, __fill);
570 		__len = __width;
571 	      }
572 
573 	    // Write resulting, fully-formatted string to output iterator.
574 	    __s = std::__write(__s, __res.data(), __len);
575 	  }
576 	__io.width(0);
577 	return __s;
578       }
579 
580 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
581       && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
582   template<typename _CharT, typename _OutIter>
583     _OutIter
584     money_put<_CharT, _OutIter>::
__do_put(iter_type __s,bool __intl,ios_base & __io,char_type __fill,double __units) const585     __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
586 	     double __units) const
587     { return this->do_put(__s, __intl, __io, __fill, (long double) __units); }
588 #endif
589 
590   template<typename _CharT, typename _OutIter>
591     _OutIter
592     money_put<_CharT, _OutIter>::
do_put(iter_type __s,bool __intl,ios_base & __io,char_type __fill,long double __units) const593     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
594 	   long double __units) const
595     {
596       const locale __loc = __io.getloc();
597       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
598 #if _GLIBCXX_USE_C99_STDIO
599       // First try a buffer perhaps big enough.
600       int __cs_size = 64;
601       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
602       // _GLIBCXX_RESOLVE_LIB_DEFECTS
603       // 328. Bad sprintf format modifier in money_put<>::do_put()
604       int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
605 					"%.*Lf", 0, __units);
606       // If the buffer was not large enough, try again with the correct size.
607       if (__len >= __cs_size)
608 	{
609 	  __cs_size = __len + 1;
610 	  __cs = static_cast<char*>(__builtin_alloca(__cs_size));
611 	  __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
612 					"%.*Lf", 0, __units);
613 	}
614 #else
615       // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
616       const int __cs_size =
617 	__gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
618       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
619       int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf",
620 					0, __units);
621 #endif
622       string_type __digits(__len, char_type());
623       __ctype.widen(__cs, __cs + __len, &__digits[0]);
624       return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
625 	            : _M_insert<false>(__s, __io, __fill, __digits);
626     }
627 
628   template<typename _CharT, typename _OutIter>
629     _OutIter
630     money_put<_CharT, _OutIter>::
do_put(iter_type __s,bool __intl,ios_base & __io,char_type __fill,const string_type & __digits) const631     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
632 	   const string_type& __digits) const
633     { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
634 	            : _M_insert<false>(__s, __io, __fill, __digits); }
635 
636 #if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
637       && defined __LONG_DOUBLE_IEEE128__
638 extern "C"
639 __typeof__(__builtin_snprintf) __glibcxx_snprintfibm128 __asm__("snprintf");
640 
641   template<typename _CharT, typename _OutIter>
642     _OutIter
643     money_put<_CharT, _OutIter>::
__do_put(iter_type __s,bool __intl,ios_base & __io,char_type __fill,__ibm128 __units) const644     __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
645 	     __ibm128 __units) const
646     {
647       const locale __loc = __io.getloc();
648       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
649       // First try a buffer perhaps big enough.
650       int __cs_size = 64;
651       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
652       const __c_locale __old = __gnu_cxx::__uselocale(_S_get_c_locale());
653 
654       // _GLIBCXX_RESOLVE_LIB_DEFECTS
655       // 328. Bad sprintf format modifier in money_put<>::do_put()
656       int __len = __glibcxx_snprintfibm128(__cs, __cs_size, "%.*Lf", 0,
657 					     __units);
658       // If the buffer was not large enough, try again with the correct size.
659       if (__len >= __cs_size)
660 	{
661 	  __cs_size = __len + 1;
662 	  __cs = static_cast<char*>(__builtin_alloca(__cs_size));
663 	  __len = __glibcxx_snprintfibm128(__cs, __cs_size, "%.*Lf", 0,
664 					     __units);
665 	}
666       __gnu_cxx::__uselocale(__old);
667       string_type __digits(__len, char_type());
668       __ctype.widen(__cs, __cs + __len, &__digits[0]);
669       return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
670 	            : _M_insert<false>(__s, __io, __fill, __digits);
671     }
672 #endif
673 
674 _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
675 
676   // NB: Not especially useful. Without an ios_base object or some
677   // kind of locale reference, we are left clawing at the air where
678   // the side of the mountain used to be...
679   template<typename _CharT, typename _InIter>
680     time_base::dateorder
do_date_order() const681     time_get<_CharT, _InIter>::do_date_order() const
682     { return time_base::no_order; }
683 
684   // Expand a strptime format string and parse it.  E.g., do_get_date() may
685   // pass %m/%d/%Y => extracted characters.
686   template<typename _CharT, typename _InIter>
687     _InIter
688     time_get<_CharT, _InIter>::
_M_extract_via_format(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm,const _CharT * __format,__time_get_state & __state) const689     _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
690 			  ios_base::iostate& __err, tm* __tm,
691 			  const _CharT* __format,
692 			  __time_get_state &__state) const
693     {
694       const locale& __loc = __io._M_getloc();
695       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
696       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
697       const size_t __len = char_traits<_CharT>::length(__format);
698 
699       ios_base::iostate __tmperr = ios_base::goodbit;
700       size_t __i = 0;
701       for (; __beg != __end && __i < __len && !__tmperr; ++__i)
702 	{
703 	  if (__ctype.narrow(__format[__i], 0) == '%')
704 	    {
705 	      // Verify valid formatting code, attempt to extract.
706 	      char __c = __ctype.narrow(__format[++__i], 0);
707 	      int __mem = 0;
708 	      if (__c == 'E' || __c == 'O')
709 		__c = __ctype.narrow(__format[++__i], 0);
710 	      switch (__c)
711 		{
712 		  const char* __cs;
713 		  _CharT __wcs[10];
714 		case 'a':
715 		case 'A':
716 		  // Weekday name (possibly abbreviated) [tm_wday]
717 		  const char_type*  __days[14];
718 		  __tp._M_days(&__days[0]);
719 		  __tp._M_days_abbreviated(&__days[7]);
720 		  __beg = _M_extract_name(__beg, __end, __mem, __days,
721 					  14, __io, __tmperr);
722 		  if (!__tmperr)
723 		    {
724 		      __tm->tm_wday = __mem % 7;
725 		      __state._M_have_wday = 1;
726 		    }
727 		  break;
728 		case 'h':
729 		case 'b':
730 		case 'B':
731 		  // Month name (possibly abbreviated) [tm_mon]
732 		  const char_type*  __months[24];
733 		  __tp._M_months(&__months[0]);
734 		  __tp._M_months_abbreviated(&__months[12]);
735 		  __beg = _M_extract_name(__beg, __end, __mem,
736 					  __months, 24, __io, __tmperr);
737 		  if (!__tmperr)
738 		    {
739 		      __tm->tm_mon = __mem % 12;
740 		      __state._M_have_mon = 1;
741 		      __state._M_want_xday = 1;
742 		    }
743 		  break;
744 		case 'c':
745 		  // Default time and date representation.
746 		  const char_type*  __dt[2];
747 		  __tp._M_date_time_formats(__dt);
748 		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
749 						__tm, __dt[0], __state);
750 		  if (!__tmperr)
751 		    __state._M_want_xday = 1;
752 		  break;
753 		case 'C':
754 		  // Century.
755 		  __beg = _M_extract_num(__beg, __end, __mem, 0, 99, 2,
756 					 __io, __tmperr);
757 		  if (!__tmperr)
758 		    {
759 		      __state._M_century = __mem;
760 		      __state._M_have_century = 1;
761 		      __state._M_want_xday = 1;
762 		    }
763 		  break;
764 		case 'd':
765 		case 'e':
766 		  // Day [1, 31]. [tm_mday]
767 		  if (__ctype.is(ctype_base::space, *__beg))
768 		    ++__beg;
769 		  __beg = _M_extract_num(__beg, __end, __mem, 1, 31, 2,
770 					 __io, __tmperr);
771 		  if (!__tmperr)
772 		    {
773 		      __tm->tm_mday = __mem;
774 		      __state._M_have_mday = 1;
775 		      __state._M_want_xday = 1;
776 		    }
777 		  break;
778 		case 'D':
779 		  // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
780 		  __cs = "%m/%d/%y";
781 		  __ctype.widen(__cs, __cs + 9, __wcs);
782 		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
783 						__tm, __wcs, __state);
784 		  if (!__tmperr)
785 		    __state._M_want_xday = 1;
786 		  break;
787 		case 'H':
788 		  // Hour [00, 23]. [tm_hour]
789 		  __beg = _M_extract_num(__beg, __end, __mem, 0, 23, 2,
790 					 __io, __tmperr);
791 		  if (!__tmperr)
792 		    {
793 		      __tm->tm_hour = __mem;
794 		      __state._M_have_I = 0;
795 		    }
796 		  break;
797 		case 'I':
798 		  // Hour [01, 12]. [tm_hour]
799 		  __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2,
800 					 __io, __tmperr);
801 		  if (!__tmperr)
802 		    {
803 		      __tm->tm_hour = __mem % 12;
804 		      __state._M_have_I = 1;
805 		    }
806 		  break;
807 		case 'j':
808 		  // Day number of year.
809 		  __beg = _M_extract_num(__beg, __end, __mem, 1, 366, 3,
810 					 __io, __tmperr);
811 		  if (!__tmperr)
812 		    {
813 		      __tm->tm_yday = __mem - 1;
814 		      __state._M_have_yday = 1;
815 		    }
816 		  break;
817 		case 'm':
818 		  // Month [01, 12]. [tm_mon]
819 		  __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2,
820 					 __io, __tmperr);
821 		  if (!__tmperr)
822 		    {
823 		      __tm->tm_mon = __mem - 1;
824 		      __state._M_have_mon = 1;
825 		    }
826 		  break;
827 		case 'M':
828 		  // Minute [00, 59]. [tm_min]
829 		  __beg = _M_extract_num(__beg, __end, __mem, 0, 59, 2,
830 					 __io, __tmperr);
831 		  if (!__tmperr)
832 		    __tm->tm_min = __mem;
833 		  break;
834 		case 'n':
835 		case 't':
836 		  while (__beg != __end
837 			 && __ctype.is(ctype_base::space, *__beg))
838 		    ++__beg;
839 		  break;
840 		case 'p':
841 		  // Locale's a.m. or p.m.
842 		  const char_type*  __ampm[2];
843 		  __tp._M_am_pm(&__ampm[0]);
844 		  if (!__ampm[0][0] || !__ampm[1][0])
845 		    break;
846 		  __beg = _M_extract_name(__beg, __end, __mem, __ampm,
847 					  2, __io, __tmperr);
848 		  if (!__tmperr && __mem)
849 		    __state._M_is_pm = 1;
850 		  break;
851 		case 'r':
852 		  // Locale's 12-hour clock time format (in C %I:%M:%S %p).
853 		  const char_type*  __ampm_format;
854 		  __tp._M_am_pm_format(&__ampm_format);
855 		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
856 						__tm, __ampm_format, __state);
857 		  break;
858 		case 'R':
859 		  // Equivalent to (%H:%M).
860 		  __cs = "%H:%M";
861 		  __ctype.widen(__cs, __cs + 6, __wcs);
862 		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
863 						__tm, __wcs, __state);
864 		  break;
865 		case 'S':
866 		  // Seconds. [tm_sec]
867 		  // [00, 60] in C99 (one leap-second), [00, 61] in C89.
868 #if _GLIBCXX_USE_C99
869 		  __beg = _M_extract_num(__beg, __end, __mem, 0, 60, 2,
870 #else
871 		  __beg = _M_extract_num(__beg, __end, __mem, 0, 61, 2,
872 #endif
873 					 __io, __tmperr);
874 		  if (!__tmperr)
875 		    __tm->tm_sec = __mem;
876 		  break;
877 		case 'T':
878 		  // Equivalent to (%H:%M:%S).
879 		  __cs = "%H:%M:%S";
880 		  __ctype.widen(__cs, __cs + 9, __wcs);
881 		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
882 						__tm, __wcs, __state);
883 		  break;
884 		case 'U':
885 		  // Week number of the year (Sunday as first day of week).
886 		  __beg = _M_extract_num(__beg, __end, __mem, 0, 53, 2,
887 					 __io, __tmperr);
888 		  if (!__tmperr)
889 		    {
890 		      __state._M_week_no = __mem;
891 		      __state._M_have_uweek = 1;
892 		    }
893 		  break;
894 		case 'w':
895 		  // Weekday [tm_wday]
896 		  __beg = _M_extract_num(__beg, __end, __mem, 0, 6, 1,
897 					 __io, __tmperr);
898 		  if (!__tmperr)
899 		    {
900 		      __tm->tm_wday = __mem;
901 		      __state._M_have_wday = 1;
902 		    }
903 		  break;
904 		case 'W':
905 		  // Week number of the year (Monday as first day of week).
906 		  __beg = _M_extract_num(__beg, __end, __mem, 0, 53, 2,
907 					 __io, __tmperr);
908 		  if (!__tmperr)
909 		    {
910 		      __state._M_week_no = __mem;
911 		      __state._M_have_wweek = 1;
912 		    }
913 		  break;
914 		case 'x':
915 		  // Locale's date.
916 		  const char_type*  __dates[2];
917 		  __tp._M_date_formats(__dates);
918 		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
919 						__tm, __dates[0], __state);
920 		  break;
921 		case 'X':
922 		  // Locale's time.
923 		  const char_type*  __times[2];
924 		  __tp._M_time_formats(__times);
925 		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
926 						__tm, __times[0], __state);
927 		  break;
928 		case 'y':
929 		  // The last 2 digits of year.
930 		  __beg = _M_extract_num(__beg, __end, __mem, 0, 99, 2,
931 					 __io, __tmperr);
932 		  if (!__tmperr)
933 		    {
934 		      __state._M_want_century = 1;
935 		      __state._M_want_xday = 1;
936 		      // As an extension, if the 2 digits are followed by
937 		      // 1-2 further digits, treat it like %Y.
938 		      __c = 0;
939 		      if (__beg != __end)
940 			__c = __ctype.narrow(*__beg, '*');
941 		      if (__c >= '0' && __c <= '9')
942 			{
943 			  ++__beg;
944 			  __mem = __mem * 10 + (__c - '0');
945 			  if (__beg != __end)
946 			    {
947 			      __c = __ctype.narrow(*__beg, '*');
948 			      if (__c >= '0' && __c <= '9')
949 				{
950 				  ++__beg;
951 				  __mem = __mem * 10 + (__c - '0');
952 				}
953 			    }
954 			  __mem -= 1900;
955 			  __state._M_want_century = 0;
956 			}
957 		      // Otherwise, as per POSIX 2008, 00-68 is 2000-2068,
958 		      // while 69-99 is 1969-1999.
959 		      else if (__mem < 69)
960 			__mem += 100;
961 		      __tm->tm_year = __mem;
962 		    }
963 		  break;
964 		case 'Y':
965 		  // Year.
966 		  __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
967 					 __io, __tmperr);
968 		  if (!__tmperr)
969 		    {
970 		      __tm->tm_year = __mem - 1900;
971 		      __state._M_want_century = 0;
972 		      __state._M_want_xday = 1;
973 		    }
974 		  break;
975 		case 'Z':
976 		  // Timezone info.
977 		  if (__ctype.is(ctype_base::upper, *__beg))
978 		    {
979 		      int __tmp;
980 		      __beg = _M_extract_name(__beg, __end, __tmp,
981 				       __timepunct_cache<_CharT>::_S_timezones,
982 					      14, __io, __tmperr);
983 
984 		      // GMT requires special effort.
985 		      if (__beg != __end && !__tmperr && __tmp == 0
986 			  && (*__beg == __ctype.widen('-')
987 			      || *__beg == __ctype.widen('+')))
988 			{
989 			  __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
990 						 __io, __tmperr);
991 			  __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
992 						 __io, __tmperr);
993 			}
994 		    }
995 		  else
996 		    __tmperr |= ios_base::failbit;
997 		  break;
998 		case '%':
999 		  if (*__beg == __ctype.widen('%'))
1000 		    ++__beg;
1001 		  else
1002 		    __tmperr |= ios_base::failbit;
1003 		  break;
1004 		default:
1005 		  // Not recognized.
1006 		  __tmperr |= ios_base::failbit;
1007 		}
1008 	    }
1009 	  else if (__ctype.is(ctype_base::space, __format[__i]))
1010 	    {
1011 	      // Skip any whitespace.
1012 	      while (__beg != __end
1013 		     && __ctype.is(ctype_base::space, *__beg))
1014 		++__beg;
1015 	    }
1016 	  else
1017 	    {
1018 	      // Verify format and input match, extract and discard.
1019 	      // TODO real case-insensitive comparison
1020 	      if (__ctype.tolower(__format[__i]) == __ctype.tolower(*__beg)
1021 		  || __ctype.toupper(__format[__i]) == __ctype.toupper(*__beg))
1022 		++__beg;
1023 	      else
1024 		__tmperr |= ios_base::failbit;
1025 	    }
1026 	}
1027 
1028       if (__tmperr || __i != __len)
1029 	__err |= ios_base::failbit;
1030 
1031       return __beg;
1032     }
1033 
1034   template<typename _CharT, typename _InIter>
1035     _InIter
1036     time_get<_CharT, _InIter>::
_M_extract_via_format(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm,const _CharT * __format) const1037     _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
1038 			  ios_base::iostate& __err, tm* __tm,
1039 			  const _CharT* __format) const
1040     {
1041       __time_get_state __state = __time_get_state();
1042       return _M_extract_via_format(__beg, __end, __io, __err, __tm,
1043 				   __format, __state);
1044     }
1045 
1046   template<typename _CharT, typename _InIter>
1047     _InIter
1048     time_get<_CharT, _InIter>::
_M_extract_num(iter_type __beg,iter_type __end,int & __member,int __min,int __max,size_t __len,ios_base & __io,ios_base::iostate & __err) const1049     _M_extract_num(iter_type __beg, iter_type __end, int& __member,
1050 		   int __min, int __max, size_t __len,
1051 		   ios_base& __io, ios_base::iostate& __err) const
1052     {
1053       const locale& __loc = __io._M_getloc();
1054       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1055 
1056       size_t __i = 0;
1057       int __value = 0;
1058       for (; __beg != __end && __i < __len; ++__beg, (void)++__i)
1059 	{
1060 	  const char __c = __ctype.narrow(*__beg, '*');
1061 	  if (__c >= '0' && __c <= '9')
1062 	    {
1063 	      __value = __value * 10 + (__c - '0');
1064 	      if (__value > __max)
1065 		break;
1066 	    }
1067 	  else
1068 	    break;
1069 	}
1070       if (__i && __value >= __min && __value <= __max)
1071 	__member = __value;
1072       else
1073 	__err |= ios_base::failbit;
1074 
1075       return __beg;
1076     }
1077 
1078   // Assumptions:
1079   // All elements in __names are unique, except if __indexlen is
1080   // even __names in the first half could be the same as corresponding
1081   // __names in the second half (May is abbreviated as May).  Some __names
1082   // elements could be prefixes of other __names elements.
1083   template<typename _CharT, typename _InIter>
1084     _InIter
1085     time_get<_CharT, _InIter>::
_M_extract_name(iter_type __beg,iter_type __end,int & __member,const _CharT ** __names,size_t __indexlen,ios_base & __io,ios_base::iostate & __err) const1086     _M_extract_name(iter_type __beg, iter_type __end, int& __member,
1087 		    const _CharT** __names, size_t __indexlen,
1088 		    ios_base& __io, ios_base::iostate& __err) const
1089     {
1090       typedef char_traits<_CharT>		__traits_type;
1091       const locale& __loc = __io._M_getloc();
1092       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1093 
1094       size_t* __matches
1095 	= static_cast<size_t*>(__builtin_alloca(2 * sizeof(size_t)
1096 						* __indexlen));
1097       size_t* __lengths = __matches + __indexlen;
1098       size_t __nmatches = 0;
1099       size_t __pos = 0;
1100       bool __testvalid = true;
1101       const char_type* __name;
1102       bool __begupdated = false;
1103 
1104       // Look for initial matches.
1105       if (__beg != __end)
1106 	{
1107 	  const char_type __c = *__beg;
1108 	  // TODO real case-insensitive comparison
1109 	  const char_type __cl = __ctype.tolower(__c);
1110 	  const char_type __cu = __ctype.toupper(__c);
1111 	  for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
1112 	    if (__cl == __ctype.tolower(__names[__i1][0])
1113 		|| __cu == __ctype.toupper(__names[__i1][0]))
1114 	      {
1115 		__lengths[__nmatches]
1116 		  = __traits_type::length(__names[__i1]);
1117 		__matches[__nmatches++] = __i1;
1118 	      }
1119 	}
1120 
1121       while (__nmatches > 1)
1122 	{
1123 	  // Find smallest matching string.
1124 	  size_t __minlen = __lengths[0];
1125 	  for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
1126 	    __minlen = std::min(__minlen, __lengths[__i2]);
1127 	  ++__pos;
1128 	  ++__beg;
1129 	  if (__pos == __minlen)
1130 	    {
1131 	      // If some match has remaining length of 0,
1132 	      // need to decide if any match with remaining
1133 	      // length non-zero matches the next character.
1134 	      // If so, remove all matches with remaining length
1135 	      // 0 from consideration, otherwise keep only matches
1136 	      // with remaining length 0.
1137 	      bool __match_longer = false;
1138 
1139 	      if (__beg != __end)
1140 		{
1141 		  // TODO real case-insensitive comparison
1142 		  const char_type __cl = __ctype.tolower(*__beg);
1143 		  const char_type __cu = __ctype.toupper(*__beg);
1144 		  for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
1145 		    {
1146 		      __name = __names[__matches[__i3]];
1147 		      if (__lengths[__i3] > __pos
1148 			  && (__ctype.tolower(__name[__pos]) == __cl
1149 			      || __ctype.toupper(__name[__pos]) == __cu))
1150 			{
1151 			  __match_longer = true;
1152 			  break;
1153 			}
1154 		    }
1155 		}
1156 	      for (size_t __i4 = 0; __i4 < __nmatches;)
1157 		if (__match_longer == (__lengths[__i4] == __pos))
1158 		  {
1159 		    __matches[__i4] = __matches[--__nmatches];
1160 		    __lengths[__i4] = __lengths[__nmatches];
1161 		  }
1162 		else
1163 		  ++__i4;
1164 	      if (__match_longer)
1165 		{
1166 		  __minlen = __lengths[0];
1167 		  for (size_t __i5 = 1; __i5 < __nmatches; ++__i5)
1168 		    __minlen = std::min(__minlen, __lengths[__i5]);
1169 		}
1170 	      else
1171 		{
1172 		  // Deal with May being full as well as abbreviated month
1173 		  // name.  Pick the smaller index.
1174 		  if (__nmatches == 2 && (__indexlen & 1) == 0)
1175 		    {
1176 		      if (__matches[0] < __indexlen / 2)
1177 			{
1178 			  if (__matches[1] == __matches[0] + __indexlen / 2)
1179 			    __nmatches = 1;
1180 			}
1181 		      else if (__matches[1] == __matches[0] - __indexlen / 2)
1182 			{
1183 			  __matches[0] = __matches[1];
1184 			  __lengths[0] = __lengths[1];
1185 			  __nmatches = 1;
1186 			}
1187 		    }
1188 		  __begupdated = true;
1189 		  break;
1190 		}
1191 	    }
1192 	  if (__pos < __minlen && __beg != __end)
1193 	    {
1194 	      // TODO real case-insensitive comparison
1195 	      const char_type __cl = __ctype.tolower(*__beg);
1196 	      const char_type __cu = __ctype.toupper(*__beg);
1197 	      for (size_t __i6 = 0; __i6 < __nmatches;)
1198 		{
1199 		  __name = __names[__matches[__i6]];
1200 		  if (__ctype.tolower(__name[__pos]) != __cl
1201 		      && __ctype.toupper(__name[__pos]) != __cu)
1202 		    {
1203 		      __matches[__i6] = __matches[--__nmatches];
1204 		      __lengths[__i6] = __lengths[__nmatches];
1205 		    }
1206 		  else
1207 		    ++__i6;
1208 		}
1209 	    }
1210 	  else
1211 	    break;
1212 	}
1213 
1214       if (__nmatches == 1)
1215 	{
1216 	  // Make sure found name is completely extracted.
1217 	  if (!__begupdated)
1218 	    {
1219 	      ++__beg;
1220 	      ++__pos;
1221 	    }
1222 	  __name = __names[__matches[0]];
1223 	  const size_t __len = __lengths[0];
1224 	  while (__pos < __len
1225 		 && __beg != __end
1226 		 // TODO real case-insensitive comparison
1227 		 && (__ctype.tolower(__name[__pos]) == __ctype.tolower(*__beg)
1228 		     || (__ctype.toupper(__name[__pos])
1229 			 == __ctype.toupper(*__beg))))
1230 	    ++__beg, (void)++__pos;
1231 
1232 	  if (__len == __pos)
1233 	    __member = __matches[0];
1234 	  else
1235 	    __testvalid = false;
1236 	}
1237       else
1238 	__testvalid = false;
1239       if (!__testvalid)
1240 	__err |= ios_base::failbit;
1241 
1242       return __beg;
1243     }
1244 
1245   template<typename _CharT, typename _InIter>
1246     _InIter
1247     time_get<_CharT, _InIter>::
_M_extract_wday_or_month(iter_type __beg,iter_type __end,int & __member,const _CharT ** __names,size_t __indexlen,ios_base & __io,ios_base::iostate & __err) const1248     _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
1249 			     const _CharT** __names, size_t __indexlen,
1250 			     ios_base& __io, ios_base::iostate& __err) const
1251     {
1252       typedef char_traits<_CharT>		__traits_type;
1253       const locale& __loc = __io._M_getloc();
1254       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1255 
1256       int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int)
1257 							  * __indexlen));
1258       size_t __nmatches = 0;
1259       size_t* __matches_lengths = 0;
1260       size_t __pos = 0;
1261 
1262       if (__beg != __end)
1263 	{
1264 	  const char_type __c = *__beg;
1265 	  for (size_t __i = 0; __i < 2 * __indexlen; ++__i)
1266 	    if (__c == __names[__i][0]
1267 		|| __c == __ctype.toupper(__names[__i][0]))
1268 	      __matches[__nmatches++] = __i;
1269 	}
1270 
1271       if (__nmatches)
1272 	{
1273 	  ++__beg;
1274 	  ++__pos;
1275 
1276 	  __matches_lengths
1277 	    = static_cast<size_t*>(__builtin_alloca(sizeof(size_t)
1278 						    * __nmatches));
1279 	  for (size_t __i = 0; __i < __nmatches; ++__i)
1280 	    __matches_lengths[__i]
1281 	      = __traits_type::length(__names[__matches[__i]]);
1282 	}
1283 
1284       for (; __beg != __end; ++__beg, (void)++__pos)
1285 	{
1286 	  size_t __nskipped = 0;
1287 	  const char_type __c = *__beg;
1288 	  for (size_t __i = 0; __i < __nmatches;)
1289 	    {
1290 	      const char_type* __name = __names[__matches[__i]];
1291 	      if (__pos >= __matches_lengths[__i])
1292 		++__nskipped, ++__i;
1293 	      else if (!(__name[__pos] == __c))
1294 		{
1295 		  --__nmatches;
1296 		  __matches[__i] = __matches[__nmatches];
1297 		  __matches_lengths[__i] = __matches_lengths[__nmatches];
1298 		}
1299 	      else
1300 		++__i;
1301 	    }
1302 	  if (__nskipped == __nmatches)
1303 	    break;
1304 	}
1305 
1306       if ((__nmatches == 1 && __matches_lengths[0] == __pos)
1307 	  || (__nmatches == 2 && (__matches_lengths[0] == __pos
1308 				  || __matches_lengths[1] == __pos)))
1309 	__member = (__matches[0] >= (int)__indexlen
1310 		    ? __matches[0] - (int)__indexlen : __matches[0]);
1311       else
1312 	__err |= ios_base::failbit;
1313 
1314       return __beg;
1315     }
1316 
1317   template<typename _CharT, typename _InIter>
1318     _InIter
1319     time_get<_CharT, _InIter>::
do_get_time(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1320     do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
1321 		ios_base::iostate& __err, tm* __tm) const
1322     {
1323       const locale& __loc = __io._M_getloc();
1324       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1325       const char_type*  __times[2];
1326       __tp._M_time_formats(__times);
1327       __time_get_state __state = __time_get_state();
1328       __beg = _M_extract_via_format(__beg, __end, __io, __err,
1329 				    __tm, __times[0], __state);
1330       __state._M_finalize_state(__tm);
1331       if (__beg == __end)
1332 	__err |= ios_base::eofbit;
1333       return __beg;
1334     }
1335 
1336   template<typename _CharT, typename _InIter>
1337     _InIter
1338     time_get<_CharT, _InIter>::
do_get_date(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1339     do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
1340 		ios_base::iostate& __err, tm* __tm) const
1341     {
1342       const locale& __loc = __io._M_getloc();
1343       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1344       const char_type*  __dates[2];
1345       __tp._M_date_formats(__dates);
1346       __time_get_state __state = __time_get_state();
1347       __beg = _M_extract_via_format(__beg, __end, __io, __err,
1348 				    __tm, __dates[0], __state);
1349       __state._M_finalize_state(__tm);
1350       if (__beg == __end)
1351 	__err |= ios_base::eofbit;
1352       return __beg;
1353     }
1354 
1355   template<typename _CharT, typename _InIter>
1356     _InIter
1357     time_get<_CharT, _InIter>::
do_get_weekday(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1358     do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
1359 		   ios_base::iostate& __err, tm* __tm) const
1360     {
1361       const locale& __loc = __io._M_getloc();
1362       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1363       const char_type* __days[14];
1364       __tp._M_days_abbreviated(__days);
1365       __tp._M_days(__days + 7);
1366       int __tmpwday;
1367       ios_base::iostate __tmperr = ios_base::goodbit;
1368 
1369       __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7,
1370 				       __io, __tmperr);
1371       if (!__tmperr)
1372 	__tm->tm_wday = __tmpwday;
1373       else
1374 	__err |= ios_base::failbit;
1375 
1376       if (__beg == __end)
1377 	__err |= ios_base::eofbit;
1378       return __beg;
1379      }
1380 
1381   template<typename _CharT, typename _InIter>
1382     _InIter
1383     time_get<_CharT, _InIter>::
do_get_monthname(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1384     do_get_monthname(iter_type __beg, iter_type __end,
1385                      ios_base& __io, ios_base::iostate& __err, tm* __tm) const
1386     {
1387       const locale& __loc = __io._M_getloc();
1388       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1389       const char_type*  __months[24];
1390       __tp._M_months_abbreviated(__months);
1391       __tp._M_months(__months + 12);
1392       int __tmpmon;
1393       ios_base::iostate __tmperr = ios_base::goodbit;
1394 
1395       __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12,
1396 				       __io, __tmperr);
1397       if (!__tmperr)
1398 	__tm->tm_mon = __tmpmon;
1399       else
1400 	__err |= ios_base::failbit;
1401 
1402       if (__beg == __end)
1403 	__err |= ios_base::eofbit;
1404       return __beg;
1405     }
1406 
1407   template<typename _CharT, typename _InIter>
1408     _InIter
1409     time_get<_CharT, _InIter>::
do_get_year(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1410     do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
1411 		ios_base::iostate& __err, tm* __tm) const
1412     {
1413       int __tmpyear;
1414       ios_base::iostate __tmperr = ios_base::goodbit;
1415       const locale& __loc = __io._M_getloc();
1416       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1417 
1418       __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 99, 2,
1419 			     __io, __tmperr);
1420       if (!__tmperr)
1421 	{
1422 	  char __c = 0;
1423 	  if (__beg != __end)
1424 	    __c = __ctype.narrow(*__beg, '*');
1425 	  // For 1-2 digit year, assume 69-99 is 1969-1999, 0-68 is 2000-2068.
1426 	  // For 3-4 digit year, use it as year.
1427 	  // __tm->tm_year needs year - 1900 though.
1428 	  if (__c >= '0' && __c <= '9')
1429 	    {
1430 	      ++__beg;
1431 	      __tmpyear = __tmpyear * 10 + (__c - '0');
1432 	      if (__beg != __end)
1433 		{
1434 		  __c = __ctype.narrow(*__beg, '*');
1435 		  if (__c >= '0' && __c <= '9')
1436 		    {
1437 		      ++__beg;
1438 		      __tmpyear = __tmpyear * 10 + (__c - '0');
1439 		    }
1440 		}
1441 	      __tmpyear -= 1900;
1442 	    }
1443 	  else if (__tmpyear < 69)
1444 	    __tmpyear += 100;
1445 	  __tm->tm_year = __tmpyear;
1446 	}
1447       else
1448 	__err |= ios_base::failbit;
1449 
1450       if (__beg == __end)
1451 	__err |= ios_base::eofbit;
1452       return __beg;
1453     }
1454 
1455 #if __cplusplus >= 201103L
1456   template<typename _CharT, typename _InIter>
1457     inline
1458     _InIter
1459     time_get<_CharT, _InIter>::
get(iter_type __s,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm,const char_type * __fmt,const char_type * __fmtend) const1460     get(iter_type __s, iter_type __end, ios_base& __io,
1461         ios_base::iostate& __err, tm* __tm, const char_type* __fmt,
1462         const char_type* __fmtend) const
1463     {
1464       const locale& __loc = __io._M_getloc();
1465       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1466       __err = ios_base::goodbit;
1467       bool __use_state = false;
1468 #if __GNUC__ >= 5 && !defined(__clang__)
1469 #pragma GCC diagnostic push
1470 #pragma GCC diagnostic ignored "-Wpmf-conversions"
1471       // Nasty hack.  The C++ standard mandates that get invokes the do_get
1472       // virtual method, but unfortunately at least without an ABI change
1473       // for the facets we can't keep state across the different do_get
1474       // calls.  So e.g. if __fmt is "%p %I:%M:%S", we can't handle it
1475       // properly, because we first handle the %p am/pm specifier and only
1476       // later the 12-hour format specifier.
1477       if ((void*)(this->*(&time_get::do_get)) == (void*)(&time_get::do_get))
1478 	__use_state = true;
1479 #pragma GCC diagnostic pop
1480 #endif
1481       __time_get_state __state = __time_get_state();
1482       while (__fmt != __fmtend &&
1483              __err == ios_base::goodbit)
1484         {
1485           if (__s == __end)
1486             {
1487               __err = ios_base::eofbit | ios_base::failbit;
1488               break;
1489             }
1490           else if (__ctype.narrow(*__fmt, 0) == '%')
1491             {
1492 	      const char_type* __fmt_start = __fmt;
1493               char __format;
1494               char __mod = 0;
1495               if (++__fmt == __fmtend)
1496                 {
1497                   __err = ios_base::failbit;
1498                   break;
1499                 }
1500               const char __c = __ctype.narrow(*__fmt, 0);
1501               if (__c != 'E' && __c != 'O')
1502                 __format = __c;
1503               else if (++__fmt != __fmtend)
1504                 {
1505                   __mod = __c;
1506                   __format = __ctype.narrow(*__fmt, 0);
1507                 }
1508               else
1509                 {
1510                   __err = ios_base::failbit;
1511                   break;
1512                 }
1513 	      if (__use_state)
1514 		{
1515 		  char_type __new_fmt[4];
1516 		  __new_fmt[0] = __fmt_start[0];
1517 		  __new_fmt[1] = __fmt_start[1];
1518 		  if (__mod)
1519 		    {
1520 		      __new_fmt[2] = __fmt_start[2];
1521 		      __new_fmt[3] = char_type();
1522 		    }
1523 		  else
1524 		    __new_fmt[2] = char_type();
1525 		  __s = _M_extract_via_format(__s, __end, __io, __err, __tm,
1526 					      __new_fmt, __state);
1527 		  if (__s == __end)
1528 		    __err |= ios_base::eofbit;
1529 		}
1530 	      else
1531 		__s = this->do_get(__s, __end, __io, __err, __tm, __format,
1532 				   __mod);
1533               ++__fmt;
1534             }
1535           else if (__ctype.is(ctype_base::space, *__fmt))
1536             {
1537               ++__fmt;
1538               while (__fmt != __fmtend &&
1539                      __ctype.is(ctype_base::space, *__fmt))
1540                 ++__fmt;
1541 
1542               while (__s != __end &&
1543                      __ctype.is(ctype_base::space, *__s))
1544                 ++__s;
1545             }
1546           // TODO real case-insensitive comparison
1547           else if (__ctype.tolower(*__s) == __ctype.tolower(*__fmt) ||
1548                    __ctype.toupper(*__s) == __ctype.toupper(*__fmt))
1549             {
1550               ++__s;
1551               ++__fmt;
1552             }
1553           else
1554             {
1555               __err = ios_base::failbit;
1556               break;
1557             }
1558         }
1559       if (__use_state)
1560 	__state._M_finalize_state(__tm);
1561       return __s;
1562     }
1563 
1564   template<typename _CharT, typename _InIter>
1565     inline
1566     _InIter
1567     time_get<_CharT, _InIter>::
do_get(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm,char __format,char __mod) const1568     do_get(iter_type __beg, iter_type __end, ios_base& __io,
1569            ios_base::iostate& __err, tm* __tm,
1570            char __format, char __mod) const
1571     {
1572       const locale& __loc = __io._M_getloc();
1573       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1574       __err = ios_base::goodbit;
1575 
1576       char_type __fmt[4];
1577       __fmt[0] = __ctype.widen('%');
1578       if (!__mod)
1579         {
1580           __fmt[1] = __format;
1581           __fmt[2] = char_type();
1582         }
1583       else
1584         {
1585           __fmt[1] = __mod;
1586           __fmt[2] = __format;
1587           __fmt[3] = char_type();
1588         }
1589 
1590       __time_get_state __state = __time_get_state();
1591       __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, __fmt,
1592 				    __state);
1593       __state._M_finalize_state(__tm);
1594       if (__beg == __end)
1595 	__err |= ios_base::eofbit;
1596       return __beg;
1597     }
1598 
1599 #endif // __cplusplus >= 201103L
1600 
1601   template<typename _CharT, typename _OutIter>
1602     _OutIter
1603     time_put<_CharT, _OutIter>::
put(iter_type __s,ios_base & __io,char_type __fill,const tm * __tm,const _CharT * __beg,const _CharT * __end) const1604     put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
1605 	const _CharT* __beg, const _CharT* __end) const
1606     {
1607       const locale& __loc = __io._M_getloc();
1608       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1609       for (; __beg != __end; ++__beg)
1610 	if (__ctype.narrow(*__beg, 0) != '%')
1611 	  {
1612 	    *__s = *__beg;
1613 	    ++__s;
1614 	  }
1615 	else if (++__beg != __end)
1616 	  {
1617 	    char __format;
1618 	    char __mod = 0;
1619 	    const char __c = __ctype.narrow(*__beg, 0);
1620 	    if (__c != 'E' && __c != 'O')
1621 	      __format = __c;
1622 	    else if (++__beg != __end)
1623 	      {
1624 		__mod = __c;
1625 		__format = __ctype.narrow(*__beg, 0);
1626 	      }
1627 	    else
1628 	      break;
1629 	    __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
1630 	  }
1631 	else
1632 	  break;
1633       return __s;
1634     }
1635 
1636   template<typename _CharT, typename _OutIter>
1637     _OutIter
1638     time_put<_CharT, _OutIter>::
do_put(iter_type __s,ios_base & __io,char_type,const tm * __tm,char __format,char __mod) const1639     do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1640 	   char __format, char __mod) const
1641     {
1642       const locale& __loc = __io._M_getloc();
1643       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1644       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1645 
1646       // NB: This size is arbitrary. Should this be a data member,
1647       // initialized at construction?
1648       const size_t __maxlen = 128;
1649       char_type __res[__maxlen];
1650 
1651       // NB: In IEE 1003.1-200x, and perhaps other locale models, it
1652       // is possible that the format character will be longer than one
1653       // character. Possibilities include 'E' or 'O' followed by a
1654       // format character: if __mod is not the default argument, assume
1655       // it's a valid modifier.
1656       char_type __fmt[4];
1657       __fmt[0] = __ctype.widen('%');
1658       if (!__mod)
1659 	{
1660 	  __fmt[1] = __format;
1661 	  __fmt[2] = char_type();
1662 	}
1663       else
1664 	{
1665 	  __fmt[1] = __mod;
1666 	  __fmt[2] = __format;
1667 	  __fmt[3] = char_type();
1668 	}
1669 
1670       __tp._M_put(__res, __maxlen, __fmt, __tm);
1671 
1672       // Write resulting, fully-formatted string to output iterator.
1673       return std::__write(__s, __res, char_traits<char_type>::length(__res));
1674     }
1675 
1676 
1677   // Inhibit implicit instantiations for required instantiations,
1678   // which are defined via explicit instantiations elsewhere.
1679 #if _GLIBCXX_EXTERN_TEMPLATE
1680   extern template class moneypunct<char, false>;
1681   extern template class moneypunct<char, true>;
1682   extern template class moneypunct_byname<char, false>;
1683   extern template class moneypunct_byname<char, true>;
1684   extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<char>;
1685   extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<char>;
1686   extern template class __timepunct<char>;
1687   extern template class time_put<char>;
1688   extern template class time_put_byname<char>;
1689   extern template class time_get<char>;
1690   extern template class time_get_byname<char>;
1691   extern template class messages<char>;
1692   extern template class messages_byname<char>;
1693 
1694   extern template
1695     const moneypunct<char, true>&
1696     use_facet<moneypunct<char, true> >(const locale&);
1697 
1698   extern template
1699     const moneypunct<char, false>&
1700     use_facet<moneypunct<char, false> >(const locale&);
1701 
1702   extern template
1703     const money_put<char>&
1704     use_facet<money_put<char> >(const locale&);
1705 
1706   extern template
1707     const money_get<char>&
1708     use_facet<money_get<char> >(const locale&);
1709 
1710   extern template
1711     const __timepunct<char>&
1712     use_facet<__timepunct<char> >(const locale&);
1713 
1714   extern template
1715     const time_put<char>&
1716     use_facet<time_put<char> >(const locale&);
1717 
1718   extern template
1719     const time_get<char>&
1720     use_facet<time_get<char> >(const locale&);
1721 
1722   extern template
1723     const messages<char>&
1724     use_facet<messages<char> >(const locale&);
1725 
1726   extern template
1727     bool
1728     has_facet<moneypunct<char> >(const locale&);
1729 
1730   extern template
1731     bool
1732     has_facet<money_put<char> >(const locale&);
1733 
1734   extern template
1735     bool
1736     has_facet<money_get<char> >(const locale&);
1737 
1738   extern template
1739     bool
1740     has_facet<__timepunct<char> >(const locale&);
1741 
1742   extern template
1743     bool
1744     has_facet<time_put<char> >(const locale&);
1745 
1746   extern template
1747     bool
1748     has_facet<time_get<char> >(const locale&);
1749 
1750   extern template
1751     bool
1752     has_facet<messages<char> >(const locale&);
1753 
1754 #ifdef _GLIBCXX_USE_WCHAR_T
1755   extern template class moneypunct<wchar_t, false>;
1756   extern template class moneypunct<wchar_t, true>;
1757   extern template class moneypunct_byname<wchar_t, false>;
1758   extern template class moneypunct_byname<wchar_t, true>;
1759   extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<wchar_t>;
1760   extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<wchar_t>;
1761   extern template class __timepunct<wchar_t>;
1762   extern template class time_put<wchar_t>;
1763   extern template class time_put_byname<wchar_t>;
1764   extern template class time_get<wchar_t>;
1765   extern template class time_get_byname<wchar_t>;
1766   extern template class messages<wchar_t>;
1767   extern template class messages_byname<wchar_t>;
1768 
1769   extern template
1770     const moneypunct<wchar_t, true>&
1771     use_facet<moneypunct<wchar_t, true> >(const locale&);
1772 
1773   extern template
1774     const moneypunct<wchar_t, false>&
1775     use_facet<moneypunct<wchar_t, false> >(const locale&);
1776 
1777   extern template
1778     const money_put<wchar_t>&
1779     use_facet<money_put<wchar_t> >(const locale&);
1780 
1781   extern template
1782     const money_get<wchar_t>&
1783     use_facet<money_get<wchar_t> >(const locale&);
1784 
1785   extern template
1786     const __timepunct<wchar_t>&
1787     use_facet<__timepunct<wchar_t> >(const locale&);
1788 
1789   extern template
1790     const time_put<wchar_t>&
1791     use_facet<time_put<wchar_t> >(const locale&);
1792 
1793   extern template
1794     const time_get<wchar_t>&
1795     use_facet<time_get<wchar_t> >(const locale&);
1796 
1797   extern template
1798     const messages<wchar_t>&
1799     use_facet<messages<wchar_t> >(const locale&);
1800 
1801   extern template
1802     bool
1803     has_facet<moneypunct<wchar_t> >(const locale&);
1804 
1805   extern template
1806     bool
1807     has_facet<money_put<wchar_t> >(const locale&);
1808 
1809   extern template
1810     bool
1811     has_facet<money_get<wchar_t> >(const locale&);
1812 
1813   extern template
1814     bool
1815     has_facet<__timepunct<wchar_t> >(const locale&);
1816 
1817   extern template
1818     bool
1819     has_facet<time_put<wchar_t> >(const locale&);
1820 
1821   extern template
1822     bool
1823     has_facet<time_get<wchar_t> >(const locale&);
1824 
1825   extern template
1826     bool
1827     has_facet<messages<wchar_t> >(const locale&);
1828 #endif
1829 #endif
1830 
1831 _GLIBCXX_END_NAMESPACE_VERSION
1832 } // namespace std
1833 
1834 #endif
1835