1 // Locale support -*- C++ -*-
2 
3 // Copyright (C) 2007, 2008, 2009, 2010, 2011 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>*
43       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
69     __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
70     {
71       _M_allocated = true;
72 
73       const moneypunct<_CharT, _Intl>& __mp =
74 	use_facet<moneypunct<_CharT, _Intl> >(__loc);
75 
76       _M_decimal_point = __mp.decimal_point();
77       _M_thousands_sep = __mp.thousands_sep();
78       _M_frac_digits = __mp.frac_digits();
79 
80       char* __grouping = 0;
81       _CharT* __curr_symbol = 0;
82       _CharT* __positive_sign = 0;
83       _CharT* __negative_sign = 0;
84       __try
85 	{
86 	  _M_grouping_size = __mp.grouping().size();
87 	  __grouping = new char[_M_grouping_size];
88 	  __mp.grouping().copy(__grouping, _M_grouping_size);
89 	  _M_grouping = __grouping;
90 	  _M_use_grouping = (_M_grouping_size
91 			     && static_cast<signed char>(_M_grouping[0]) > 0
92 			     && (_M_grouping[0]
93 				 != __gnu_cxx::__numeric_traits<char>::__max));
94 
95 	  _M_curr_symbol_size = __mp.curr_symbol().size();
96 	  __curr_symbol = new _CharT[_M_curr_symbol_size];
97 	  __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size);
98 	  _M_curr_symbol = __curr_symbol;
99 
100 	  _M_positive_sign_size = __mp.positive_sign().size();
101 	  __positive_sign = new _CharT[_M_positive_sign_size];
102 	  __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size);
103 	  _M_positive_sign = __positive_sign;
104 
105 	  _M_negative_sign_size = __mp.negative_sign().size();
106 	  __negative_sign = new _CharT[_M_negative_sign_size];
107 	  __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size);
108 	  _M_negative_sign = __negative_sign;
109 
110 	  _M_pos_format = __mp.pos_format();
111 	  _M_neg_format = __mp.neg_format();
112 
113 	  const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
114 	  __ct.widen(money_base::_S_atoms,
115 		     money_base::_S_atoms + money_base::_S_end, _M_atoms);
116 	}
117       __catch(...)
118 	{
119 	  delete [] __grouping;
120 	  delete [] __curr_symbol;
121 	  delete [] __positive_sign;
122 	  delete [] __negative_sign;
123 	  __throw_exception_again;
124 	}
125     }
126 
127 _GLIBCXX_BEGIN_NAMESPACE_LDBL
128 
129   template<typename _CharT, typename _InIter>
130     template<bool _Intl>
131       _InIter
132       money_get<_CharT, _InIter>::
133       _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
134 		 ios_base::iostate& __err, string& __units) const
135       {
136 	typedef char_traits<_CharT>			  __traits_type;
137 	typedef typename string_type::size_type	          size_type;
138 	typedef money_base::part			  part;
139 	typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
140 
141 	const locale& __loc = __io._M_getloc();
142 	const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
143 
144 	__use_cache<__cache_type> __uc;
145 	const __cache_type* __lc = __uc(__loc);
146 	const char_type* __lit = __lc->_M_atoms;
147 
148 	// Deduced sign.
149 	bool __negative = false;
150 	// Sign size.
151 	size_type __sign_size = 0;
152 	// True if sign is mandatory.
153 	const bool __mandatory_sign = (__lc->_M_positive_sign_size
154 				       && __lc->_M_negative_sign_size);
155 	// String of grouping info from thousands_sep plucked from __units.
156 	string __grouping_tmp;
157 	if (__lc->_M_use_grouping)
158 	  __grouping_tmp.reserve(32);
159 	// Last position before the decimal point.
160 	int __last_pos = 0;
161 	// Separator positions, then, possibly, fractional digits.
162 	int __n = 0;
163 	// If input iterator is in a valid state.
164 	bool __testvalid = true;
165 	// Flag marking when a decimal point is found.
166 	bool __testdecfound = false;
167 
168 	// The tentative returned string is stored here.
169 	string __res;
170 	__res.reserve(32);
171 
172 	const char_type* __lit_zero = __lit + money_base::_S_zero;
173 	const money_base::pattern __p = __lc->_M_neg_format;
174 	for (int __i = 0; __i < 4 && __testvalid; ++__i)
175 	  {
176 	    const part __which = static_cast<part>(__p.field[__i]);
177 	    switch (__which)
178 	      {
179 	      case money_base::symbol:
180 		// According to 22.2.6.1.2, p2, symbol is required
181 		// if (__io.flags() & ios_base::showbase), otherwise
182 		// is optional and consumed only if other characters
183 		// are needed to complete the format.
184 		if (__io.flags() & ios_base::showbase || __sign_size > 1
185 		    || __i == 0
186 		    || (__i == 1 && (__mandatory_sign
187 				     || (static_cast<part>(__p.field[0])
188 					 == money_base::sign)
189 				     || (static_cast<part>(__p.field[2])
190 					 == money_base::space)))
191 		    || (__i == 2 && ((static_cast<part>(__p.field[3])
192 				      == money_base::value)
193 				     || (__mandatory_sign
194 					 && (static_cast<part>(__p.field[3])
195 					     == money_base::sign)))))
196 		  {
197 		    const size_type __len = __lc->_M_curr_symbol_size;
198 		    size_type __j = 0;
199 		    for (; __beg != __end && __j < __len
200 			   && *__beg == __lc->_M_curr_symbol[__j];
201 			 ++__beg, ++__j);
202 		    if (__j != __len
203 			&& (__j || __io.flags() & ios_base::showbase))
204 		      __testvalid = false;
205 		  }
206 		break;
207 	      case money_base::sign:
208 		// Sign might not exist, or be more than one character long.
209 		if (__lc->_M_positive_sign_size && __beg != __end
210 		    && *__beg == __lc->_M_positive_sign[0])
211 		  {
212 		    __sign_size = __lc->_M_positive_sign_size;
213 		    ++__beg;
214 		  }
215 		else if (__lc->_M_negative_sign_size && __beg != __end
216 			 && *__beg == __lc->_M_negative_sign[0])
217 		  {
218 		    __negative = true;
219 		    __sign_size = __lc->_M_negative_sign_size;
220 		    ++__beg;
221 		  }
222 		else if (__lc->_M_positive_sign_size
223 			 && !__lc->_M_negative_sign_size)
224 		  // "... if no sign is detected, the result is given the sign
225 		  // that corresponds to the source of the empty string"
226 		  __negative = true;
227 		else if (__mandatory_sign)
228 		  __testvalid = false;
229 		break;
230 	      case money_base::value:
231 		// Extract digits, remove and stash away the
232 		// grouping of found thousands separators.
233 		for (; __beg != __end; ++__beg)
234 		  {
235 		    const char_type __c = *__beg;
236 		    const char_type* __q = __traits_type::find(__lit_zero,
237 							       10, __c);
238 		    if (__q != 0)
239 		      {
240 			__res += money_base::_S_atoms[__q - __lit];
241 			++__n;
242 		      }
243 		    else if (__c == __lc->_M_decimal_point
244 			     && !__testdecfound)
245 		      {
246 			if (__lc->_M_frac_digits <= 0)
247 			  break;
248 
249 			__last_pos = __n;
250 			__n = 0;
251 			__testdecfound = true;
252 		      }
253 		    else if (__lc->_M_use_grouping
254 			     && __c == __lc->_M_thousands_sep
255 			     && !__testdecfound)
256 		      {
257 			if (__n)
258 			  {
259 			    // Mark position for later analysis.
260 			    __grouping_tmp += static_cast<char>(__n);
261 			    __n = 0;
262 			  }
263 			else
264 			  {
265 			    __testvalid = false;
266 			    break;
267 			  }
268 		      }
269 		    else
270 		      break;
271 		  }
272 		if (__res.empty())
273 		  __testvalid = false;
274 		break;
275 	      case money_base::space:
276 		// At least one space is required.
277 		if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
278 		  ++__beg;
279 		else
280 		  __testvalid = false;
281 	      case money_base::none:
282 		// Only if not at the end of the pattern.
283 		if (__i != 3)
284 		  for (; __beg != __end
285 			 && __ctype.is(ctype_base::space, *__beg); ++__beg);
286 		break;
287 	      }
288 	  }
289 
290 	// Need to get the rest of the sign characters, if they exist.
291 	if (__sign_size > 1 && __testvalid)
292 	  {
293 	    const char_type* __sign = __negative ? __lc->_M_negative_sign
294 	                                         : __lc->_M_positive_sign;
295 	    size_type __i = 1;
296 	    for (; __beg != __end && __i < __sign_size
297 		   && *__beg == __sign[__i]; ++__beg, ++__i);
298 
299 	    if (__i != __sign_size)
300 	      __testvalid = false;
301 	  }
302 
303 	if (__testvalid)
304 	  {
305 	    // Strip leading zeros.
306 	    if (__res.size() > 1)
307 	      {
308 		const size_type __first = __res.find_first_not_of('0');
309 		const bool __only_zeros = __first == string::npos;
310 		if (__first)
311 		  __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
312 	      }
313 
314 	    // 22.2.6.1.2, p4
315 	    if (__negative && __res[0] != '0')
316 	      __res.insert(__res.begin(), '-');
317 
318 	    // Test for grouping fidelity.
319 	    if (__grouping_tmp.size())
320 	      {
321 		// Add the ending grouping.
322 		__grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
323 						                   : __n);
324 		if (!std::__verify_grouping(__lc->_M_grouping,
325 					    __lc->_M_grouping_size,
326 					    __grouping_tmp))
327 		  __err |= ios_base::failbit;
328 	      }
329 
330 	    // Iff not enough digits were supplied after the decimal-point.
331 	    if (__testdecfound && __n != __lc->_M_frac_digits)
332 	      __testvalid = false;
333 	  }
334 
335 	// Iff valid sequence is not recognized.
336 	if (!__testvalid)
337 	  __err |= ios_base::failbit;
338 	else
339 	  __units.swap(__res);
340 
341 	// Iff no more characters are available.
342 	if (__beg == __end)
343 	  __err |= ios_base::eofbit;
344 	return __beg;
345       }
346 
347 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
348   template<typename _CharT, typename _InIter>
349     _InIter
350     money_get<_CharT, _InIter>::
351     __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
352 	     ios_base::iostate& __err, double& __units) const
353     {
354       string __str;
355       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
356                      : _M_extract<false>(__beg, __end, __io, __err, __str);
357       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
358       return __beg;
359     }
360 #endif
361 
362   template<typename _CharT, typename _InIter>
363     _InIter
364     money_get<_CharT, _InIter>::
365     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
366 	   ios_base::iostate& __err, long double& __units) const
367     {
368       string __str;
369       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
370 	             : _M_extract<false>(__beg, __end, __io, __err, __str);
371       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
372       return __beg;
373     }
374 
375   template<typename _CharT, typename _InIter>
376     _InIter
377     money_get<_CharT, _InIter>::
378     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
379 	   ios_base::iostate& __err, string_type& __digits) const
380     {
381       typedef typename string::size_type                  size_type;
382 
383       const locale& __loc = __io._M_getloc();
384       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
385 
386       string __str;
387       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
388 	             : _M_extract<false>(__beg, __end, __io, __err, __str);
389       const size_type __len = __str.size();
390       if (__len)
391 	{
392 	  __digits.resize(__len);
393 	  __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]);
394 	}
395       return __beg;
396     }
397 
398   template<typename _CharT, typename _OutIter>
399     template<bool _Intl>
400       _OutIter
401       money_put<_CharT, _OutIter>::
402       _M_insert(iter_type __s, ios_base& __io, char_type __fill,
403 		const string_type& __digits) const
404       {
405 	typedef typename string_type::size_type	          size_type;
406 	typedef money_base::part                          part;
407 	typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
408 
409 	const locale& __loc = __io._M_getloc();
410 	const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
411 
412 	__use_cache<__cache_type> __uc;
413 	const __cache_type* __lc = __uc(__loc);
414 	const char_type* __lit = __lc->_M_atoms;
415 
416 	// Determine if negative or positive formats are to be used, and
417 	// discard leading negative_sign if it is present.
418 	const char_type* __beg = __digits.data();
419 
420 	money_base::pattern __p;
421 	const char_type* __sign;
422 	size_type __sign_size;
423 	if (!(*__beg == __lit[money_base::_S_minus]))
424 	  {
425 	    __p = __lc->_M_pos_format;
426 	    __sign = __lc->_M_positive_sign;
427 	    __sign_size = __lc->_M_positive_sign_size;
428 	  }
429 	else
430 	  {
431 	    __p = __lc->_M_neg_format;
432 	    __sign = __lc->_M_negative_sign;
433 	    __sign_size = __lc->_M_negative_sign_size;
434 	    if (__digits.size())
435 	      ++__beg;
436 	  }
437 
438 	// Look for valid numbers in the ctype facet within input digits.
439 	size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
440 					   __beg + __digits.size()) - __beg;
441 	if (__len)
442 	  {
443 	    // Assume valid input, and attempt to format.
444 	    // Break down input numbers into base components, as follows:
445 	    //   final_value = grouped units + (decimal point) + (digits)
446 	    string_type __value;
447 	    __value.reserve(2 * __len);
448 
449 	    // Add thousands separators to non-decimal digits, per
450 	    // grouping rules.
451 	    long __paddec = __len - __lc->_M_frac_digits;
452 	    if (__paddec > 0)
453   	      {
454 		if (__lc->_M_frac_digits < 0)
455 		  __paddec = __len;
456   		if (__lc->_M_grouping_size)
457   		  {
458 		    __value.assign(2 * __paddec, char_type());
459  		    _CharT* __vend =
460 		      std::__add_grouping(&__value[0], __lc->_M_thousands_sep,
461 					  __lc->_M_grouping,
462 					  __lc->_M_grouping_size,
463 					  __beg, __beg + __paddec);
464 		    __value.erase(__vend - &__value[0]);
465   		  }
466   		else
467 		  __value.assign(__beg, __paddec);
468 	      }
469 
470 	    // Deal with decimal point, decimal digits.
471 	    if (__lc->_M_frac_digits > 0)
472 	      {
473 		__value += __lc->_M_decimal_point;
474 		if (__paddec >= 0)
475 		  __value.append(__beg + __paddec, __lc->_M_frac_digits);
476 		else
477 		  {
478 		    // Have to pad zeros in the decimal position.
479 		    __value.append(-__paddec, __lit[money_base::_S_zero]);
480 		    __value.append(__beg, __len);
481 		  }
482   	      }
483 
484 	    // Calculate length of resulting string.
485 	    const ios_base::fmtflags __f = __io.flags()
486 	                                   & ios_base::adjustfield;
487 	    __len = __value.size() + __sign_size;
488 	    __len += ((__io.flags() & ios_base::showbase)
489 		      ? __lc->_M_curr_symbol_size : 0);
490 
491 	    string_type __res;
492 	    __res.reserve(2 * __len);
493 
494 	    const size_type __width = static_cast<size_type>(__io.width());
495 	    const bool __testipad = (__f == ios_base::internal
496 				     && __len < __width);
497 	    // Fit formatted digits into the required pattern.
498 	    for (int __i = 0; __i < 4; ++__i)
499 	      {
500 		const part __which = static_cast<part>(__p.field[__i]);
501 		switch (__which)
502 		  {
503 		  case money_base::symbol:
504 		    if (__io.flags() & ios_base::showbase)
505 		      __res.append(__lc->_M_curr_symbol,
506 				   __lc->_M_curr_symbol_size);
507 		    break;
508 		  case money_base::sign:
509 		    // Sign might not exist, or be more than one
510 		    // character long. In that case, add in the rest
511 		    // below.
512 		    if (__sign_size)
513 		      __res += __sign[0];
514 		    break;
515 		  case money_base::value:
516 		    __res += __value;
517 		    break;
518 		  case money_base::space:
519 		    // At least one space is required, but if internal
520 		    // formatting is required, an arbitrary number of
521 		    // fill spaces will be necessary.
522 		    if (__testipad)
523 		      __res.append(__width - __len, __fill);
524 		    else
525 		      __res += __fill;
526 		    break;
527 		  case money_base::none:
528 		    if (__testipad)
529 		      __res.append(__width - __len, __fill);
530 		    break;
531 		  }
532 	      }
533 
534 	    // Special case of multi-part sign parts.
535 	    if (__sign_size > 1)
536 	      __res.append(__sign + 1, __sign_size - 1);
537 
538 	    // Pad, if still necessary.
539 	    __len = __res.size();
540 	    if (__width > __len)
541 	      {
542 		if (__f == ios_base::left)
543 		  // After.
544 		  __res.append(__width - __len, __fill);
545 		else
546 		  // Before.
547 		  __res.insert(0, __width - __len, __fill);
548 		__len = __width;
549 	      }
550 
551 	    // Write resulting, fully-formatted string to output iterator.
552 	    __s = std::__write(__s, __res.data(), __len);
553 	  }
554 	__io.width(0);
555 	return __s;
556       }
557 
558 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
559   template<typename _CharT, typename _OutIter>
560     _OutIter
561     money_put<_CharT, _OutIter>::
562     __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
563 	     double __units) const
564     { return this->do_put(__s, __intl, __io, __fill, (long double) __units); }
565 #endif
566 
567   template<typename _CharT, typename _OutIter>
568     _OutIter
569     money_put<_CharT, _OutIter>::
570     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
571 	   long double __units) const
572     {
573       const locale __loc = __io.getloc();
574       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
575 #ifdef _GLIBCXX_USE_C99
576       // First try a buffer perhaps big enough.
577       int __cs_size = 64;
578       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
579       // _GLIBCXX_RESOLVE_LIB_DEFECTS
580       // 328. Bad sprintf format modifier in money_put<>::do_put()
581       int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
582 					"%.*Lf", 0, __units);
583       // If the buffer was not large enough, try again with the correct size.
584       if (__len >= __cs_size)
585 	{
586 	  __cs_size = __len + 1;
587 	  __cs = static_cast<char*>(__builtin_alloca(__cs_size));
588 	  __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
589 					"%.*Lf", 0, __units);
590 	}
591 #else
592       // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
593       const int __cs_size =
594 	__gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
595       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
596       int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf",
597 					0, __units);
598 #endif
599       string_type __digits(__len, char_type());
600       __ctype.widen(__cs, __cs + __len, &__digits[0]);
601       return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
602 	            : _M_insert<false>(__s, __io, __fill, __digits);
603     }
604 
605   template<typename _CharT, typename _OutIter>
606     _OutIter
607     money_put<_CharT, _OutIter>::
608     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
609 	   const string_type& __digits) const
610     { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
611 	            : _M_insert<false>(__s, __io, __fill, __digits); }
612 
613 _GLIBCXX_END_NAMESPACE_LDBL
614 
615   // NB: Not especially useful. Without an ios_base object or some
616   // kind of locale reference, we are left clawing at the air where
617   // the side of the mountain used to be...
618   template<typename _CharT, typename _InIter>
619     time_base::dateorder
620     time_get<_CharT, _InIter>::do_date_order() const
621     { return time_base::no_order; }
622 
623   // Expand a strftime format string and parse it.  E.g., do_get_date() may
624   // pass %m/%d/%Y => extracted characters.
625   template<typename _CharT, typename _InIter>
626     _InIter
627     time_get<_CharT, _InIter>::
628     _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
629 			  ios_base::iostate& __err, tm* __tm,
630 			  const _CharT* __format) const
631     {
632       const locale& __loc = __io._M_getloc();
633       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
634       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
635       const size_t __len = char_traits<_CharT>::length(__format);
636 
637       ios_base::iostate __tmperr = ios_base::goodbit;
638       size_t __i = 0;
639       for (; __beg != __end && __i < __len && !__tmperr; ++__i)
640 	{
641 	  if (__ctype.narrow(__format[__i], 0) == '%')
642 	    {
643 	      // Verify valid formatting code, attempt to extract.
644 	      char __c = __ctype.narrow(__format[++__i], 0);
645 	      int __mem = 0;
646 	      if (__c == 'E' || __c == 'O')
647 		__c = __ctype.narrow(__format[++__i], 0);
648 	      switch (__c)
649 		{
650 		  const char* __cs;
651 		  _CharT __wcs[10];
652 		case 'a':
653 		  // Abbreviated weekday name [tm_wday]
654 		  const char_type*  __days1[7];
655 		  __tp._M_days_abbreviated(__days1);
656 		  __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
657 					  7, __io, __tmperr);
658 		  break;
659 		case 'A':
660 		  // Weekday name [tm_wday].
661 		  const char_type*  __days2[7];
662 		  __tp._M_days(__days2);
663 		  __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
664 					  7, __io, __tmperr);
665 		  break;
666 		case 'h':
667 		case 'b':
668 		  // Abbreviated month name [tm_mon]
669 		  const char_type*  __months1[12];
670 		  __tp._M_months_abbreviated(__months1);
671 		  __beg = _M_extract_name(__beg, __end, __tm->tm_mon,
672 					  __months1, 12, __io, __tmperr);
673 		  break;
674 		case 'B':
675 		  // Month name [tm_mon].
676 		  const char_type*  __months2[12];
677 		  __tp._M_months(__months2);
678 		  __beg = _M_extract_name(__beg, __end, __tm->tm_mon,
679 					  __months2, 12, __io, __tmperr);
680 		  break;
681 		case 'c':
682 		  // Default time and date representation.
683 		  const char_type*  __dt[2];
684 		  __tp._M_date_time_formats(__dt);
685 		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
686 						__tm, __dt[0]);
687 		  break;
688 		case 'd':
689 		  // Day [01, 31]. [tm_mday]
690 		  __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
691 					 __io, __tmperr);
692 		  break;
693 		case 'e':
694 		  // Day [1, 31], with single digits preceded by
695 		  // space. [tm_mday]
696 		  if (__ctype.is(ctype_base::space, *__beg))
697 		    __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
698 					   1, __io, __tmperr);
699 		  else
700 		    __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
701 					   2, __io, __tmperr);
702 		  break;
703 		case 'D':
704 		  // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
705 		  __cs = "%m/%d/%y";
706 		  __ctype.widen(__cs, __cs + 9, __wcs);
707 		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
708 						__tm, __wcs);
709 		  break;
710 		case 'H':
711 		  // Hour [00, 23]. [tm_hour]
712 		  __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
713 					 __io, __tmperr);
714 		  break;
715 		case 'I':
716 		  // Hour [01, 12]. [tm_hour]
717 		  __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
718 					 __io, __tmperr);
719 		  break;
720 		case 'm':
721 		  // Month [01, 12]. [tm_mon]
722 		  __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2,
723 					 __io, __tmperr);
724 		  if (!__tmperr)
725 		    __tm->tm_mon = __mem - 1;
726 		  break;
727 		case 'M':
728 		  // Minute [00, 59]. [tm_min]
729 		  __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
730 					 __io, __tmperr);
731 		  break;
732 		case 'n':
733 		  if (__ctype.narrow(*__beg, 0) == '\n')
734 		    ++__beg;
735 		  else
736 		    __tmperr |= ios_base::failbit;
737 		  break;
738 		case 'R':
739 		  // Equivalent to (%H:%M).
740 		  __cs = "%H:%M";
741 		  __ctype.widen(__cs, __cs + 6, __wcs);
742 		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
743 						__tm, __wcs);
744 		  break;
745 		case 'S':
746 		  // Seconds. [tm_sec]
747 		  // [00, 60] in C99 (one leap-second), [00, 61] in C89.
748 #ifdef _GLIBCXX_USE_C99
749 		  __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2,
750 #else
751 		  __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
752 #endif
753 					 __io, __tmperr);
754 		  break;
755 		case 't':
756 		  if (__ctype.narrow(*__beg, 0) == '\t')
757 		    ++__beg;
758 		  else
759 		    __tmperr |= ios_base::failbit;
760 		  break;
761 		case 'T':
762 		  // Equivalent to (%H:%M:%S).
763 		  __cs = "%H:%M:%S";
764 		  __ctype.widen(__cs, __cs + 9, __wcs);
765 		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
766 						__tm, __wcs);
767 		  break;
768 		case 'x':
769 		  // Locale's date.
770 		  const char_type*  __dates[2];
771 		  __tp._M_date_formats(__dates);
772 		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
773 						__tm, __dates[0]);
774 		  break;
775 		case 'X':
776 		  // Locale's time.
777 		  const char_type*  __times[2];
778 		  __tp._M_time_formats(__times);
779 		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
780 						__tm, __times[0]);
781 		  break;
782 		case 'y':
783 		case 'C': // C99
784 		  // Two digit year.
785 		case 'Y':
786 		  // Year [1900).
787 		  // NB: We parse either two digits, implicitly years since
788 		  // 1900, or 4 digits, full year.  In both cases we can
789 		  // reconstruct [tm_year].  See also libstdc++/26701.
790 		  __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
791 					 __io, __tmperr);
792 		  if (!__tmperr)
793 		    __tm->tm_year = __mem < 0 ? __mem + 100 : __mem - 1900;
794 		  break;
795 		case 'Z':
796 		  // Timezone info.
797 		  if (__ctype.is(ctype_base::upper, *__beg))
798 		    {
799 		      int __tmp;
800 		      __beg = _M_extract_name(__beg, __end, __tmp,
801 				       __timepunct_cache<_CharT>::_S_timezones,
802 					      14, __io, __tmperr);
803 
804 		      // GMT requires special effort.
805 		      if (__beg != __end && !__tmperr && __tmp == 0
806 			  && (*__beg == __ctype.widen('-')
807 			      || *__beg == __ctype.widen('+')))
808 			{
809 			  __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
810 						 __io, __tmperr);
811 			  __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
812 						 __io, __tmperr);
813 			}
814 		    }
815 		  else
816 		    __tmperr |= ios_base::failbit;
817 		  break;
818 		default:
819 		  // Not recognized.
820 		  __tmperr |= ios_base::failbit;
821 		}
822 	    }
823 	  else
824 	    {
825 	      // Verify format and input match, extract and discard.
826 	      if (__format[__i] == *__beg)
827 		++__beg;
828 	      else
829 		__tmperr |= ios_base::failbit;
830 	    }
831 	}
832 
833       if (__tmperr || __i != __len)
834 	__err |= ios_base::failbit;
835 
836       return __beg;
837     }
838 
839   template<typename _CharT, typename _InIter>
840     _InIter
841     time_get<_CharT, _InIter>::
842     _M_extract_num(iter_type __beg, iter_type __end, int& __member,
843 		   int __min, int __max, size_t __len,
844 		   ios_base& __io, ios_base::iostate& __err) const
845     {
846       const locale& __loc = __io._M_getloc();
847       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
848 
849       // As-is works for __len = 1, 2, 4, the values actually used.
850       int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
851 
852       ++__min;
853       size_t __i = 0;
854       int __value = 0;
855       for (; __beg != __end && __i < __len; ++__beg, ++__i)
856 	{
857 	  const char __c = __ctype.narrow(*__beg, '*');
858 	  if (__c >= '0' && __c <= '9')
859 	    {
860 	      __value = __value * 10 + (__c - '0');
861 	      const int __valuec = __value * __mult;
862 	      if (__valuec > __max || __valuec + __mult < __min)
863 		break;
864 	      __mult /= 10;
865 	    }
866 	  else
867 	    break;
868 	}
869       if (__i == __len)
870 	__member = __value;
871       // Special encoding for do_get_year, 'y', and 'Y' above.
872       else if (__len == 4 && __i == 2)
873 	__member = __value - 100;
874       else
875 	__err |= ios_base::failbit;
876 
877       return __beg;
878     }
879 
880   // Assumptions:
881   // All elements in __names are unique.
882   template<typename _CharT, typename _InIter>
883     _InIter
884     time_get<_CharT, _InIter>::
885     _M_extract_name(iter_type __beg, iter_type __end, int& __member,
886 		    const _CharT** __names, size_t __indexlen,
887 		    ios_base& __io, ios_base::iostate& __err) const
888     {
889       typedef char_traits<_CharT>		__traits_type;
890       const locale& __loc = __io._M_getloc();
891       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
892 
893       int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
894 							  * __indexlen));
895       size_t __nmatches = 0;
896       size_t __pos = 0;
897       bool __testvalid = true;
898       const char_type* __name;
899 
900       // Look for initial matches.
901       // NB: Some of the locale data is in the form of all lowercase
902       // names, and some is in the form of initially-capitalized
903       // names. Look for both.
904       if (__beg != __end)
905 	{
906 	  const char_type __c = *__beg;
907 	  for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
908 	    if (__c == __names[__i1][0]
909 		|| __c == __ctype.toupper(__names[__i1][0]))
910 	      __matches[__nmatches++] = __i1;
911 	}
912 
913       while (__nmatches > 1)
914 	{
915 	  // Find smallest matching string.
916 	  size_t __minlen = __traits_type::length(__names[__matches[0]]);
917 	  for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
918 	    __minlen = std::min(__minlen,
919 			      __traits_type::length(__names[__matches[__i2]]));
920 	  ++__beg, ++__pos;
921 	  if (__pos < __minlen && __beg != __end)
922 	    for (size_t __i3 = 0; __i3 < __nmatches;)
923 	      {
924 		__name = __names[__matches[__i3]];
925 		if (!(__name[__pos] == *__beg))
926 		  __matches[__i3] = __matches[--__nmatches];
927 		else
928 		  ++__i3;
929 	      }
930 	  else
931 	    break;
932 	}
933 
934       if (__nmatches == 1)
935 	{
936 	  // Make sure found name is completely extracted.
937 	  ++__beg, ++__pos;
938 	  __name = __names[__matches[0]];
939 	  const size_t __len = __traits_type::length(__name);
940 	  while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
941 	    ++__beg, ++__pos;
942 
943 	  if (__len == __pos)
944 	    __member = __matches[0];
945 	  else
946 	    __testvalid = false;
947 	}
948       else
949 	__testvalid = false;
950       if (!__testvalid)
951 	__err |= ios_base::failbit;
952 
953       return __beg;
954     }
955 
956   template<typename _CharT, typename _InIter>
957     _InIter
958     time_get<_CharT, _InIter>::
959     _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
960 			     const _CharT** __names, size_t __indexlen,
961 			     ios_base& __io, ios_base::iostate& __err) const
962     {
963       typedef char_traits<_CharT>		__traits_type;
964       const locale& __loc = __io._M_getloc();
965       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
966 
967       int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int)
968 							  * __indexlen));
969       size_t __nmatches = 0;
970       size_t* __matches_lengths = 0;
971       size_t __pos = 0;
972 
973       if (__beg != __end)
974 	{
975 	  const char_type __c = *__beg;
976 	  for (size_t __i = 0; __i < 2 * __indexlen; ++__i)
977 	    if (__c == __names[__i][0]
978 		|| __c == __ctype.toupper(__names[__i][0]))
979 	      __matches[__nmatches++] = __i;
980 	}
981 
982       if (__nmatches)
983 	{
984 	  ++__beg, ++__pos;
985 
986 	  __matches_lengths
987 	    = static_cast<size_t*>(__builtin_alloca(sizeof(size_t)
988 						    * __nmatches));
989 	  for (size_t __i = 0; __i < __nmatches; ++__i)
990 	    __matches_lengths[__i]
991 	      = __traits_type::length(__names[__matches[__i]]);
992 	}
993 
994       for (; __beg != __end; ++__beg, ++__pos)
995 	{
996 	  size_t __nskipped = 0;
997 	  const char_type __c = *__beg;
998 	  for (size_t __i = 0; __i < __nmatches;)
999 	    {
1000 	      const char_type* __name = __names[__matches[__i]];
1001 	      if (__pos >= __matches_lengths[__i])
1002 		++__nskipped, ++__i;
1003 	      else if (!(__name[__pos] == __c))
1004 		{
1005 		  --__nmatches;
1006 		  __matches[__i] = __matches[__nmatches];
1007 		  __matches_lengths[__i] = __matches_lengths[__nmatches];
1008 		}
1009 	      else
1010 		++__i;
1011 	    }
1012 	  if (__nskipped == __nmatches)
1013 	    break;
1014 	}
1015 
1016       if ((__nmatches == 1 && __matches_lengths[0] == __pos)
1017 	  || (__nmatches == 2 && (__matches_lengths[0] == __pos
1018 				  || __matches_lengths[1] == __pos)))
1019 	__member = (__matches[0] >= __indexlen
1020 		    ? __matches[0] - __indexlen : __matches[0]);
1021       else
1022 	__err |= ios_base::failbit;
1023 
1024       return __beg;
1025     }
1026 
1027   template<typename _CharT, typename _InIter>
1028     _InIter
1029     time_get<_CharT, _InIter>::
1030     do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
1031 		ios_base::iostate& __err, tm* __tm) const
1032     {
1033       const locale& __loc = __io._M_getloc();
1034       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1035       const char_type*  __times[2];
1036       __tp._M_time_formats(__times);
1037       __beg = _M_extract_via_format(__beg, __end, __io, __err,
1038 				    __tm, __times[0]);
1039       if (__beg == __end)
1040 	__err |= ios_base::eofbit;
1041       return __beg;
1042     }
1043 
1044   template<typename _CharT, typename _InIter>
1045     _InIter
1046     time_get<_CharT, _InIter>::
1047     do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
1048 		ios_base::iostate& __err, tm* __tm) const
1049     {
1050       const locale& __loc = __io._M_getloc();
1051       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1052       const char_type*  __dates[2];
1053       __tp._M_date_formats(__dates);
1054       __beg = _M_extract_via_format(__beg, __end, __io, __err,
1055 				    __tm, __dates[0]);
1056       if (__beg == __end)
1057 	__err |= ios_base::eofbit;
1058       return __beg;
1059     }
1060 
1061   template<typename _CharT, typename _InIter>
1062     _InIter
1063     time_get<_CharT, _InIter>::
1064     do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
1065 		   ios_base::iostate& __err, tm* __tm) const
1066     {
1067       typedef char_traits<_CharT>		__traits_type;
1068       const locale& __loc = __io._M_getloc();
1069       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1070       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1071       const char_type* __days[14];
1072       __tp._M_days_abbreviated(__days);
1073       __tp._M_days(__days + 7);
1074       int __tmpwday;
1075       ios_base::iostate __tmperr = ios_base::goodbit;
1076 
1077       __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7,
1078 				       __io, __tmperr);
1079       if (!__tmperr)
1080 	__tm->tm_wday = __tmpwday;
1081       else
1082 	__err |= ios_base::failbit;
1083 
1084       if (__beg == __end)
1085 	__err |= ios_base::eofbit;
1086       return __beg;
1087      }
1088 
1089   template<typename _CharT, typename _InIter>
1090     _InIter
1091     time_get<_CharT, _InIter>::
1092     do_get_monthname(iter_type __beg, iter_type __end,
1093                      ios_base& __io, ios_base::iostate& __err, tm* __tm) const
1094     {
1095       typedef char_traits<_CharT>		__traits_type;
1096       const locale& __loc = __io._M_getloc();
1097       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1098       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1099       const char_type*  __months[24];
1100       __tp._M_months_abbreviated(__months);
1101       __tp._M_months(__months + 12);
1102       int __tmpmon;
1103       ios_base::iostate __tmperr = ios_base::goodbit;
1104 
1105       __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12,
1106 				       __io, __tmperr);
1107       if (!__tmperr)
1108 	__tm->tm_mon = __tmpmon;
1109       else
1110 	__err |= ios_base::failbit;
1111 
1112       if (__beg == __end)
1113 	__err |= ios_base::eofbit;
1114       return __beg;
1115     }
1116 
1117   template<typename _CharT, typename _InIter>
1118     _InIter
1119     time_get<_CharT, _InIter>::
1120     do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
1121 		ios_base::iostate& __err, tm* __tm) const
1122     {
1123       const locale& __loc = __io._M_getloc();
1124       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1125       int __tmpyear;
1126       ios_base::iostate __tmperr = ios_base::goodbit;
1127 
1128       __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 9999, 4,
1129 			     __io, __tmperr);
1130       if (!__tmperr)
1131 	__tm->tm_year = __tmpyear < 0 ? __tmpyear + 100 : __tmpyear - 1900;
1132       else
1133 	__err |= ios_base::failbit;
1134 
1135       if (__beg == __end)
1136 	__err |= ios_base::eofbit;
1137       return __beg;
1138     }
1139 
1140   template<typename _CharT, typename _OutIter>
1141     _OutIter
1142     time_put<_CharT, _OutIter>::
1143     put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
1144 	const _CharT* __beg, const _CharT* __end) const
1145     {
1146       const locale& __loc = __io._M_getloc();
1147       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1148       for (; __beg != __end; ++__beg)
1149 	if (__ctype.narrow(*__beg, 0) != '%')
1150 	  {
1151 	    *__s = *__beg;
1152 	    ++__s;
1153 	  }
1154 	else if (++__beg != __end)
1155 	  {
1156 	    char __format;
1157 	    char __mod = 0;
1158 	    const char __c = __ctype.narrow(*__beg, 0);
1159 	    if (__c != 'E' && __c != 'O')
1160 	      __format = __c;
1161 	    else if (++__beg != __end)
1162 	      {
1163 		__mod = __c;
1164 		__format = __ctype.narrow(*__beg, 0);
1165 	      }
1166 	    else
1167 	      break;
1168 	    __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
1169 	  }
1170 	else
1171 	  break;
1172       return __s;
1173     }
1174 
1175   template<typename _CharT, typename _OutIter>
1176     _OutIter
1177     time_put<_CharT, _OutIter>::
1178     do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1179 	   char __format, char __mod) const
1180     {
1181       const locale& __loc = __io._M_getloc();
1182       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1183       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1184 
1185       // NB: This size is arbitrary. Should this be a data member,
1186       // initialized at construction?
1187       const size_t __maxlen = 128;
1188       char_type __res[__maxlen];
1189 
1190       // NB: In IEE 1003.1-200x, and perhaps other locale models, it
1191       // is possible that the format character will be longer than one
1192       // character. Possibilities include 'E' or 'O' followed by a
1193       // format character: if __mod is not the default argument, assume
1194       // it's a valid modifier.
1195       char_type __fmt[4];
1196       __fmt[0] = __ctype.widen('%');
1197       if (!__mod)
1198 	{
1199 	  __fmt[1] = __format;
1200 	  __fmt[2] = char_type();
1201 	}
1202       else
1203 	{
1204 	  __fmt[1] = __mod;
1205 	  __fmt[2] = __format;
1206 	  __fmt[3] = char_type();
1207 	}
1208 
1209       __tp._M_put(__res, __maxlen, __fmt, __tm);
1210 
1211       // Write resulting, fully-formatted string to output iterator.
1212       return std::__write(__s, __res, char_traits<char_type>::length(__res));
1213     }
1214 
1215 
1216   // Inhibit implicit instantiations for required instantiations,
1217   // which are defined via explicit instantiations elsewhere.
1218 #if _GLIBCXX_EXTERN_TEMPLATE
1219   extern template class moneypunct<char, false>;
1220   extern template class moneypunct<char, true>;
1221   extern template class moneypunct_byname<char, false>;
1222   extern template class moneypunct_byname<char, true>;
1223   extern template class _GLIBCXX_NAMESPACE_LDBL money_get<char>;
1224   extern template class _GLIBCXX_NAMESPACE_LDBL money_put<char>;
1225   extern template class __timepunct<char>;
1226   extern template class time_put<char>;
1227   extern template class time_put_byname<char>;
1228   extern template class time_get<char>;
1229   extern template class time_get_byname<char>;
1230   extern template class messages<char>;
1231   extern template class messages_byname<char>;
1232 
1233   extern template
1234     const moneypunct<char, true>&
1235     use_facet<moneypunct<char, true> >(const locale&);
1236 
1237   extern template
1238     const moneypunct<char, false>&
1239     use_facet<moneypunct<char, false> >(const locale&);
1240 
1241   extern template
1242     const money_put<char>&
1243     use_facet<money_put<char> >(const locale&);
1244 
1245   extern template
1246     const money_get<char>&
1247     use_facet<money_get<char> >(const locale&);
1248 
1249   extern template
1250     const __timepunct<char>&
1251     use_facet<__timepunct<char> >(const locale&);
1252 
1253   extern template
1254     const time_put<char>&
1255     use_facet<time_put<char> >(const locale&);
1256 
1257   extern template
1258     const time_get<char>&
1259     use_facet<time_get<char> >(const locale&);
1260 
1261   extern template
1262     const messages<char>&
1263     use_facet<messages<char> >(const locale&);
1264 
1265   extern template
1266     bool
1267     has_facet<moneypunct<char> >(const locale&);
1268 
1269   extern template
1270     bool
1271     has_facet<money_put<char> >(const locale&);
1272 
1273   extern template
1274     bool
1275     has_facet<money_get<char> >(const locale&);
1276 
1277   extern template
1278     bool
1279     has_facet<__timepunct<char> >(const locale&);
1280 
1281   extern template
1282     bool
1283     has_facet<time_put<char> >(const locale&);
1284 
1285   extern template
1286     bool
1287     has_facet<time_get<char> >(const locale&);
1288 
1289   extern template
1290     bool
1291     has_facet<messages<char> >(const locale&);
1292 
1293 #ifdef _GLIBCXX_USE_WCHAR_T
1294   extern template class moneypunct<wchar_t, false>;
1295   extern template class moneypunct<wchar_t, true>;
1296   extern template class moneypunct_byname<wchar_t, false>;
1297   extern template class moneypunct_byname<wchar_t, true>;
1298   extern template class _GLIBCXX_NAMESPACE_LDBL money_get<wchar_t>;
1299   extern template class _GLIBCXX_NAMESPACE_LDBL money_put<wchar_t>;
1300   extern template class __timepunct<wchar_t>;
1301   extern template class time_put<wchar_t>;
1302   extern template class time_put_byname<wchar_t>;
1303   extern template class time_get<wchar_t>;
1304   extern template class time_get_byname<wchar_t>;
1305   extern template class messages<wchar_t>;
1306   extern template class messages_byname<wchar_t>;
1307 
1308   extern template
1309     const moneypunct<wchar_t, true>&
1310     use_facet<moneypunct<wchar_t, true> >(const locale&);
1311 
1312   extern template
1313     const moneypunct<wchar_t, false>&
1314     use_facet<moneypunct<wchar_t, false> >(const locale&);
1315 
1316   extern template
1317     const money_put<wchar_t>&
1318     use_facet<money_put<wchar_t> >(const locale&);
1319 
1320   extern template
1321     const money_get<wchar_t>&
1322     use_facet<money_get<wchar_t> >(const locale&);
1323 
1324   extern template
1325     const __timepunct<wchar_t>&
1326     use_facet<__timepunct<wchar_t> >(const locale&);
1327 
1328   extern template
1329     const time_put<wchar_t>&
1330     use_facet<time_put<wchar_t> >(const locale&);
1331 
1332   extern template
1333     const time_get<wchar_t>&
1334     use_facet<time_get<wchar_t> >(const locale&);
1335 
1336   extern template
1337     const messages<wchar_t>&
1338     use_facet<messages<wchar_t> >(const locale&);
1339 
1340   extern template
1341     bool
1342     has_facet<moneypunct<wchar_t> >(const locale&);
1343 
1344   extern template
1345     bool
1346     has_facet<money_put<wchar_t> >(const locale&);
1347 
1348   extern template
1349     bool
1350     has_facet<money_get<wchar_t> >(const locale&);
1351 
1352   extern template
1353     bool
1354     has_facet<__timepunct<wchar_t> >(const locale&);
1355 
1356   extern template
1357     bool
1358     has_facet<time_put<wchar_t> >(const locale&);
1359 
1360   extern template
1361     bool
1362     has_facet<time_get<wchar_t> >(const locale&);
1363 
1364   extern template
1365     bool
1366     has_facet<messages<wchar_t> >(const locale&);
1367 #endif
1368 #endif
1369 
1370 _GLIBCXX_END_NAMESPACE_VERSION
1371 } // namespace std
1372 
1373 #endif
1374