locale_facets.tcc revision 146897
1// Locale support -*- C++ -*-
2
3// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
4// Free Software Foundation, Inc.
5//
6// This file is part of the GNU ISO C++ Library.  This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 2, or (at your option)
10// any later version.
11
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16
17// You should have received a copy of the GNU General Public License along
18// with this library; see the file COPYING.  If not, write to the Free
19// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20// USA.
21
22// As a special exception, you may use this file as part of a free software
23// library without restriction.  Specifically, if other files instantiate
24// templates or use macros or inline functions from this file, or you compile
25// this file and link it with other files to produce an executable, this
26// file does not by itself cause the resulting executable to be covered by
27// the GNU General Public License.  This exception does not however
28// invalidate any other reasons why the executable file might be covered by
29// the GNU General Public License.
30
31// Warning: this file is not meant for user inclusion. Use <locale>.
32
33#ifndef _LOCALE_FACETS_TCC
34#define _LOCALE_FACETS_TCC 1
35
36#pragma GCC system_header
37
38#include <limits>		// For numeric_limits
39#include <typeinfo>		// For bad_cast.
40#include <bits/streambuf_iterator.h>
41
42namespace std
43{
44  template<typename _Facet>
45    locale
46    locale::combine(const locale& __other) const
47    {
48      _Impl* __tmp = new _Impl(*_M_impl, 1);
49      try
50	{
51	  __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
52	}
53      catch(...)
54	{
55	  __tmp->_M_remove_reference();
56	  __throw_exception_again;
57	}
58      return locale(__tmp);
59    }
60
61  template<typename _CharT, typename _Traits, typename _Alloc>
62    bool
63    locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
64                       const basic_string<_CharT, _Traits, _Alloc>& __s2) const
65    {
66      typedef std::collate<_CharT> __collate_type;
67      const __collate_type& __collate = use_facet<__collate_type>(*this);
68      return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
69				__s2.data(), __s2.data() + __s2.length()) < 0);
70    }
71
72  /**
73   *  @brief  Test for the presence of a facet.
74   *
75   *  has_facet tests the locale argument for the presence of the facet type
76   *  provided as the template parameter.  Facets derived from the facet
77   *  parameter will also return true.
78   *
79   *  @param  Facet  The facet type to test the presence of.
80   *  @param  locale  The locale to test.
81   *  @return  true if locale contains a facet of type Facet, else false.
82  */
83  template<typename _Facet>
84    inline bool
85    has_facet(const locale& __loc) throw()
86    {
87      const size_t __i = _Facet::id._M_id();
88      const locale::facet** __facets = __loc._M_impl->_M_facets;
89      return (__i < __loc._M_impl->_M_facets_size && __facets[__i]);
90    }
91
92  /**
93   *  @brief  Return a facet.
94   *
95   *  use_facet looks for and returns a reference to a facet of type Facet
96   *  where Facet is the template parameter.  If has_facet(locale) is true,
97   *  there is a suitable facet to return.  It throws std::bad_cast if the
98   *  locale doesn't contain a facet of type Facet.
99   *
100   *  @param  Facet  The facet type to access.
101   *  @param  locale  The locale to use.
102   *  @return  Reference to facet of type Facet.
103   *  @throw  std::bad_cast if locale doesn't contain a facet of type Facet.
104  */
105  template<typename _Facet>
106    inline const _Facet&
107    use_facet(const locale& __loc)
108    {
109      const size_t __i = _Facet::id._M_id();
110      const locale::facet** __facets = __loc._M_impl->_M_facets;
111      if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i]))
112        __throw_bad_cast();
113      return static_cast<const _Facet&>(*__facets[__i]);
114    }
115
116  // Routine to access a cache for the facet.  If the cache didn't
117  // exist before, it gets constructed on the fly.
118  template<typename _Facet>
119    struct __use_cache
120    {
121      const _Facet*
122      operator() (const locale& __loc) const;
123    };
124
125  // Specializations.
126  template<typename _CharT>
127    struct __use_cache<__numpunct_cache<_CharT> >
128    {
129      const __numpunct_cache<_CharT>*
130      operator() (const locale& __loc) const
131      {
132	const size_t __i = numpunct<_CharT>::id._M_id();
133	const locale::facet** __caches = __loc._M_impl->_M_caches;
134	if (!__caches[__i])
135	  {
136	    __numpunct_cache<_CharT>* __tmp = NULL;
137	    try
138	      {
139		__tmp = new __numpunct_cache<_CharT>;
140		__tmp->_M_cache(__loc);
141	      }
142	    catch(...)
143	      {
144		delete __tmp;
145		__throw_exception_again;
146	      }
147	    __loc._M_impl->_M_install_cache(__tmp, __i);
148	  }
149	return static_cast<const __numpunct_cache<_CharT>*>(__caches[__i]);
150      }
151    };
152
153  template<typename _CharT, bool _Intl>
154    struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
155    {
156      const __moneypunct_cache<_CharT, _Intl>*
157      operator() (const locale& __loc) const
158      {
159	const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
160	const locale::facet** __caches = __loc._M_impl->_M_caches;
161	if (!__caches[__i])
162	  {
163	    __moneypunct_cache<_CharT, _Intl>* __tmp = NULL;
164	    try
165	      {
166		__tmp = new __moneypunct_cache<_CharT, _Intl>;
167		__tmp->_M_cache(__loc);
168	      }
169	    catch(...)
170	      {
171		delete __tmp;
172		__throw_exception_again;
173	      }
174	    __loc._M_impl->_M_install_cache(__tmp, __i);
175	  }
176	return static_cast<
177	  const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
178      }
179    };
180
181  template<typename _CharT>
182    void
183    __numpunct_cache<_CharT>::_M_cache(const locale& __loc)
184    {
185      _M_allocated = true;
186
187      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
188
189      _M_grouping_size = __np.grouping().size();
190      char* __grouping = new char[_M_grouping_size];
191      __np.grouping().copy(__grouping, _M_grouping_size);
192      _M_grouping = __grouping;
193      _M_use_grouping = _M_grouping_size && __np.grouping()[0] != 0;
194
195      _M_truename_size = __np.truename().size();
196      _CharT* __truename = new _CharT[_M_truename_size];
197      __np.truename().copy(__truename, _M_truename_size);
198      _M_truename = __truename;
199
200      _M_falsename_size = __np.falsename().size();
201      _CharT* __falsename = new _CharT[_M_falsename_size];
202      __np.falsename().copy(__falsename, _M_falsename_size);
203      _M_falsename = __falsename;
204
205      _M_decimal_point = __np.decimal_point();
206      _M_thousands_sep = __np.thousands_sep();
207
208      const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
209      __ct.widen(__num_base::_S_atoms_out,
210		 __num_base::_S_atoms_out + __num_base::_S_oend, _M_atoms_out);
211      __ct.widen(__num_base::_S_atoms_in,
212		 __num_base::_S_atoms_in + __num_base::_S_iend, _M_atoms_in);
213    }
214
215  template<typename _CharT, bool _Intl>
216    void
217    __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
218    {
219      _M_allocated = true;
220
221      const moneypunct<_CharT, _Intl>& __mp =
222	use_facet<moneypunct<_CharT, _Intl> >(__loc);
223
224      _M_grouping_size = __mp.grouping().size();
225      char* __grouping = new char[_M_grouping_size];
226      __mp.grouping().copy(__grouping, _M_grouping_size);
227      _M_grouping = __grouping;
228      _M_use_grouping = _M_grouping_size && __mp.grouping()[0] != 0;
229      
230      _M_decimal_point = __mp.decimal_point();
231      _M_thousands_sep = __mp.thousands_sep();
232      _M_frac_digits = __mp.frac_digits();
233      
234      _M_curr_symbol_size = __mp.curr_symbol().size();
235      _CharT* __curr_symbol = new _CharT[_M_curr_symbol_size];
236      __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size);
237      _M_curr_symbol = __curr_symbol;
238      
239      _M_positive_sign_size = __mp.positive_sign().size();
240      _CharT* __positive_sign = new _CharT[_M_positive_sign_size];
241      __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size);
242      _M_positive_sign = __positive_sign;
243
244      _M_negative_sign_size = __mp.negative_sign().size();
245      _CharT* __negative_sign = new _CharT[_M_negative_sign_size];
246      __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size);
247      _M_negative_sign = __negative_sign;
248      
249      _M_pos_format = __mp.pos_format();
250      _M_neg_format = __mp.neg_format();
251
252      const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
253      __ct.widen(money_base::_S_atoms,
254		 money_base::_S_atoms + money_base::_S_end, _M_atoms);
255    }
256
257
258  // Used by both numeric and monetary facets.
259  // Check to make sure that the __grouping_tmp string constructed in
260  // money_get or num_get matches the canonical grouping for a given
261  // locale.
262  // __grouping_tmp is parsed L to R
263  // 1,222,444 == __grouping_tmp of "\1\3\3"
264  // __grouping is parsed R to L
265  // 1,222,444 == __grouping of "\3" == "\3\3\3"
266  static bool
267  __verify_grouping(const char* __grouping, size_t __grouping_size,
268		    const string& __grouping_tmp);
269
270  template<typename _CharT, typename _InIter>
271    _InIter
272    num_get<_CharT, _InIter>::
273    _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
274		     ios_base::iostate& __err, string& __xtrc) const
275    {
276      typedef char_traits<_CharT>			__traits_type;
277      typedef typename numpunct<_CharT>::__cache_type	__cache_type;
278      __use_cache<__cache_type> __uc;
279      const locale& __loc = __io._M_getloc();
280      const __cache_type* __lc = __uc(__loc);
281      const _CharT* __lit = __lc->_M_atoms_in;
282
283      // True if a mantissa is found.
284      bool __found_mantissa = false;
285
286      // First check for sign.
287      if (__beg != __end)
288	{
289	  const char_type __c = *__beg;
290	  const bool __plus = __c == __lit[__num_base::_S_iplus];
291	  if ((__plus || __c == __lit[__num_base::_S_iminus])
292	      && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
293	      && !(__c == __lc->_M_decimal_point))
294	    {
295	      __xtrc += __plus ? '+' : '-';
296	      ++__beg;
297	    }
298	}
299
300      // Next, look for leading zeros.
301      while (__beg != __end)
302	{
303	  const char_type __c = *__beg;
304	  if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep
305	      || __c == __lc->_M_decimal_point)
306	    break;
307	  else if (__c == __lit[__num_base::_S_izero])
308	    {
309	      if (!__found_mantissa)
310		{
311		  __xtrc += '0';
312		  __found_mantissa = true;
313		}
314	      ++__beg;
315	    }
316	  else
317	    break;
318	}
319
320      // Only need acceptable digits for floating point numbers.
321      bool __found_dec = false;
322      bool __found_sci = false;
323      string __found_grouping;
324      if (__lc->_M_use_grouping)
325	__found_grouping.reserve(32);
326      int __sep_pos = 0;
327      const char_type* __lit_zero = __lit + __num_base::_S_izero;
328      const char_type* __q;
329      while (__beg != __end)
330        {
331	  // According to 22.2.2.1.2, p8-9, first look for thousands_sep
332	  // and decimal_point.
333	  const char_type __c = *__beg;
334          if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
335	    {
336	      if (!__found_dec && !__found_sci)
337		{
338		  // NB: Thousands separator at the beginning of a string
339		  // is a no-no, as is two consecutive thousands separators.
340		  if (__sep_pos)
341		    {
342		      __found_grouping += static_cast<char>(__sep_pos);
343		      __sep_pos = 0;
344		      ++__beg;
345		    }
346		  else
347		    {
348		      __err |= ios_base::failbit;
349		      break;
350		    }
351		}
352	      else
353		break;
354            }
355	  else if (__c == __lc->_M_decimal_point)
356	    {
357	      if (!__found_dec && !__found_sci)
358		{
359		  // If no grouping chars are seen, no grouping check
360		  // is applied. Therefore __found_grouping is adjusted
361		  // only if decimal_point comes after some thousands_sep.
362		  if (__found_grouping.size())
363		    __found_grouping += static_cast<char>(__sep_pos);
364		  __xtrc += '.';
365		  __found_dec = true;
366		  ++__beg;
367		}
368	      else
369		break;
370	    }
371          else if (__q = __traits_type::find(__lit_zero, 10, __c))
372	    {
373	      __xtrc += __num_base::_S_atoms_in[__q - __lit];
374	      __found_mantissa = true;
375	      ++__sep_pos;
376	      ++__beg;
377	    }
378	  else if ((__c == __lit[__num_base::_S_ie] 
379		    || __c == __lit[__num_base::_S_iE])
380		   && __found_mantissa && !__found_sci)
381	    {
382	      // Scientific notation.
383	      if (__found_grouping.size() && !__found_dec)
384		__found_grouping += static_cast<char>(__sep_pos);
385	      __xtrc += 'e';
386	      __found_sci = true;
387
388	      // Remove optional plus or minus sign, if they exist.
389	      if (++__beg != __end)
390		{
391		  const bool __plus = *__beg == __lit[__num_base::_S_iplus];
392		  if ((__plus || *__beg == __lit[__num_base::_S_iminus])
393		      && !(__lc->_M_use_grouping
394			   && *__beg == __lc->_M_thousands_sep)
395		      && !(*__beg == __lc->_M_decimal_point))
396		    {
397		      __xtrc += __plus ? '+' : '-';
398		      ++__beg;
399		    }
400		}
401	    }
402	  else
403	    // Not a valid input item.
404	    break;
405        }
406
407      // Digit grouping is checked. If grouping and found_grouping don't
408      // match, then get very very upset, and set failbit.
409      if (__lc->_M_use_grouping && __found_grouping.size())
410        {
411          // Add the ending grouping if a decimal or 'e'/'E' wasn't found.
412	  if (!__found_dec && !__found_sci)
413	    __found_grouping += static_cast<char>(__sep_pos);
414
415          if (!std::__verify_grouping(__lc->_M_grouping, 
416				      __lc->_M_grouping_size,
417				      __found_grouping))
418	    __err |= ios_base::failbit;
419        }
420
421      // Finish up.
422      if (__beg == __end)
423        __err |= ios_base::eofbit;
424      return __beg;
425    }
426
427  template<typename _CharT, typename _InIter>
428    template<typename _ValueT>
429      _InIter
430      num_get<_CharT, _InIter>::
431      _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
432		     ios_base::iostate& __err, _ValueT& __v) const
433      {
434        typedef char_traits<_CharT>			__traits_type;
435	typedef typename numpunct<_CharT>::__cache_type __cache_type;
436	__use_cache<__cache_type> __uc;
437	const locale& __loc = __io._M_getloc();
438	const __cache_type* __lc = __uc(__loc);
439	const _CharT* __lit = __lc->_M_atoms_in;
440
441	// NB: Iff __basefield == 0, __base can change based on contents.
442	const ios_base::fmtflags __basefield = __io.flags()
443	                                       & ios_base::basefield;
444	const bool __oct = __basefield == ios_base::oct;
445	int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10);
446
447	// True if numeric digits are found.
448	bool __found_num = false;
449
450	// First check for sign.
451	bool __negative = false;
452	if (__beg != __end)
453	  {
454	    const char_type __c = *__beg;
455	    if (numeric_limits<_ValueT>::is_signed)
456	      __negative = __c == __lit[__num_base::_S_iminus];
457	    if ((__negative || __c == __lit[__num_base::_S_iplus])
458		&& !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
459		&& !(__c == __lc->_M_decimal_point))
460	      ++__beg;
461	  }
462
463	// Next, look for leading zeros and check required digits
464	// for base formats.
465	while (__beg != __end)
466	  {
467	    const char_type __c = *__beg;
468	    if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep
469		|| __c == __lc->_M_decimal_point)
470	      break;
471	    else if (__c == __lit[__num_base::_S_izero] 
472		     && (!__found_num || __base == 10))
473	      {
474		__found_num = true;
475		++__beg;
476	      }
477	    else if (__found_num)
478	      {
479		if (__c == __lit[__num_base::_S_ix] 
480		    || __c == __lit[__num_base::_S_iX])
481		  {
482		    if (__basefield == 0)
483		      __base = 16;
484		    if (__base == 16)
485		      {
486			__found_num = false;
487			++__beg;
488		      }
489		  }
490		else if (__basefield == 0)
491		  __base = 8;
492		break;
493	      }
494	    else
495	      break;
496	  }
497
498	// At this point, base is determined. If not hex, only allow
499	// base digits as valid input.
500	const size_t __len = __base == 16 ? (__num_base::_S_iend
501					     - __num_base::_S_izero)
502	                                  : __base;
503
504	// Extract.
505	string __found_grouping;
506	if (__lc->_M_use_grouping)
507	  __found_grouping.reserve(32);
508	int __sep_pos = 0;
509	bool __overflow = false;
510	_ValueT __result = 0;
511	const char_type* __lit_zero = __lit + __num_base::_S_izero;
512	const char_type* __q;
513	if (__negative)
514	  {
515	    const _ValueT __min = numeric_limits<_ValueT>::min() / __base;
516	    for (; __beg != __end; ++__beg)
517	      {
518		// According to 22.2.2.1.2, p8-9, first look for thousands_sep
519		// and decimal_point.
520		const char_type __c = *__beg;
521		if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
522		  {
523		    // NB: Thousands separator at the beginning of a string
524		    // is a no-no, as is two consecutive thousands separators.
525		    if (__sep_pos)
526		      {
527			__found_grouping += static_cast<char>(__sep_pos);
528			__sep_pos = 0;
529		      }
530		    else
531		      {
532			__err |= ios_base::failbit;
533			break;
534		      }
535		  }
536		else if (__c == __lc->_M_decimal_point)
537		  break;
538		else if (__q = __traits_type::find(__lit_zero, __len, __c))
539		  {
540		    int __digit = __q - __lit_zero;
541		    if (__digit > 15)
542		      __digit -= 6;
543		    if (__result < __min)
544		      __overflow = true;
545		    else
546		      {
547			const _ValueT __new_result = __result * __base
548			                             - __digit;
549			__overflow |= __new_result > __result;
550			__result = __new_result;
551			++__sep_pos;
552			__found_num = true;
553		      }
554		  }
555		else
556		  // Not a valid input item.
557		  break;
558	      }
559	  }
560	else
561	  {
562	    const _ValueT __max = numeric_limits<_ValueT>::max() / __base;
563	    for (; __beg != __end; ++__beg)
564	      {
565		const char_type __c = *__beg;
566		if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
567		  {
568		    if (__sep_pos)
569		      {
570			__found_grouping += static_cast<char>(__sep_pos);
571			__sep_pos = 0;
572		      }
573		    else
574		      {
575			__err |= ios_base::failbit;
576			break;
577		      }
578		  }
579		else if (__c == __lc->_M_decimal_point)
580		  break;
581		else if (__q = __traits_type::find(__lit_zero, __len, __c))
582		  {
583		    int __digit = __q - __lit_zero;
584		    if (__digit > 15)
585		      __digit -= 6;
586		    if (__result > __max)
587		      __overflow = true;
588		    else
589		      {
590			const _ValueT __new_result = __result * __base
591			                             + __digit;
592			__overflow |= __new_result < __result;
593			__result = __new_result;
594			++__sep_pos;
595			__found_num = true;
596		      }
597		  }
598		else
599		  break;
600	      }
601	  }
602
603	// Digit grouping is checked. If grouping and found_grouping don't
604	// match, then get very very upset, and set failbit.
605	if (__lc->_M_use_grouping && __found_grouping.size())
606	  {
607	    // Add the ending grouping.
608	    __found_grouping += static_cast<char>(__sep_pos);
609
610	    if (!std::__verify_grouping(__lc->_M_grouping,
611					__lc->_M_grouping_size,
612					__found_grouping))
613	      __err |= ios_base::failbit;
614	  }
615
616	if (!(__err & ios_base::failbit) && !__overflow
617	    && __found_num)
618	  __v = __result;
619	else
620	  __err |= ios_base::failbit;
621
622	if (__beg == __end)
623	  __err |= ios_base::eofbit;
624	return __beg;
625      }
626
627  // _GLIBCXX_RESOLVE_LIB_DEFECTS
628  // 17.  Bad bool parsing
629  template<typename _CharT, typename _InIter>
630    _InIter
631    num_get<_CharT, _InIter>::
632    do_get(iter_type __beg, iter_type __end, ios_base& __io,
633           ios_base::iostate& __err, bool& __v) const
634    {
635      if (!(__io.flags() & ios_base::boolalpha))
636        {
637	  // Parse bool values as long.
638          // NB: We can't just call do_get(long) here, as it might
639          // refer to a derived class.
640	  long __l = -1;
641          __beg = _M_extract_int(__beg, __end, __io, __err, __l);
642	  if (__l == 0 || __l == 1)
643	    __v = __l;
644	  else
645            __err |= ios_base::failbit;
646        }
647      else
648        {
649	  // Parse bool values as alphanumeric.
650	  typedef char_traits<_CharT>                     __traits_type;
651	  typedef typename numpunct<_CharT>::__cache_type __cache_type;
652	  __use_cache<__cache_type> __uc;
653	  const locale& __loc = __io._M_getloc();
654	  const __cache_type* __lc = __uc(__loc);
655
656	  bool __testf = true;
657	  bool __testt = true;
658	  size_t __n;
659          for (__n = 0; __beg != __end; ++__n, ++__beg)
660            {
661	      if (__testf)
662		if (__n < __lc->_M_falsename_size)
663		  __testf = *__beg == __lc->_M_falsename[__n];
664		else
665		  break;
666
667	      if (__testt)
668		if (__n < __lc->_M_truename_size)
669		  __testt = *__beg == __lc->_M_truename[__n];
670		else
671		  break;
672
673	      if (!__testf && !__testt)
674		break;
675            }
676	  if (__testf && __n == __lc->_M_falsename_size)
677	    __v = 0;
678	  else if (__testt && __n == __lc->_M_truename_size)
679	    __v = 1;
680	  else
681	    __err |= ios_base::failbit;
682
683          if (__beg == __end)
684            __err |= ios_base::eofbit;
685        }
686      return __beg;
687    }
688
689  template<typename _CharT, typename _InIter>
690    _InIter
691    num_get<_CharT, _InIter>::
692    do_get(iter_type __beg, iter_type __end, ios_base& __io,
693           ios_base::iostate& __err, long& __v) const
694    { return _M_extract_int(__beg, __end, __io, __err, __v); }
695
696  template<typename _CharT, typename _InIter>
697    _InIter
698    num_get<_CharT, _InIter>::
699    do_get(iter_type __beg, iter_type __end, ios_base& __io,
700           ios_base::iostate& __err, unsigned short& __v) const
701    { return _M_extract_int(__beg, __end, __io, __err, __v); }
702
703  template<typename _CharT, typename _InIter>
704    _InIter
705    num_get<_CharT, _InIter>::
706    do_get(iter_type __beg, iter_type __end, ios_base& __io,
707           ios_base::iostate& __err, unsigned int& __v) const
708    { return _M_extract_int(__beg, __end, __io, __err, __v); }
709
710  template<typename _CharT, typename _InIter>
711    _InIter
712    num_get<_CharT, _InIter>::
713    do_get(iter_type __beg, iter_type __end, ios_base& __io,
714           ios_base::iostate& __err, unsigned long& __v) const
715    { return _M_extract_int(__beg, __end, __io, __err, __v); }
716
717#ifdef _GLIBCXX_USE_LONG_LONG
718  template<typename _CharT, typename _InIter>
719    _InIter
720    num_get<_CharT, _InIter>::
721    do_get(iter_type __beg, iter_type __end, ios_base& __io,
722           ios_base::iostate& __err, long long& __v) const
723    { return _M_extract_int(__beg, __end, __io, __err, __v); }
724
725  template<typename _CharT, typename _InIter>
726    _InIter
727    num_get<_CharT, _InIter>::
728    do_get(iter_type __beg, iter_type __end, ios_base& __io,
729           ios_base::iostate& __err, unsigned long long& __v) const
730    { return _M_extract_int(__beg, __end, __io, __err, __v); }
731#endif
732
733  template<typename _CharT, typename _InIter>
734    _InIter
735    num_get<_CharT, _InIter>::
736    do_get(iter_type __beg, iter_type __end, ios_base& __io,
737	   ios_base::iostate& __err, float& __v) const
738    {
739      string __xtrc;
740      __xtrc.reserve(32);
741      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
742      std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
743      return __beg;
744    }
745
746  template<typename _CharT, typename _InIter>
747    _InIter
748    num_get<_CharT, _InIter>::
749    do_get(iter_type __beg, iter_type __end, ios_base& __io,
750           ios_base::iostate& __err, double& __v) const
751    {
752      string __xtrc;
753      __xtrc.reserve(32);
754      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
755      std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
756      return __beg;
757    }
758
759  template<typename _CharT, typename _InIter>
760    _InIter
761    num_get<_CharT, _InIter>::
762    do_get(iter_type __beg, iter_type __end, ios_base& __io,
763           ios_base::iostate& __err, long double& __v) const
764    {
765      string __xtrc;
766      __xtrc.reserve(32);
767      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
768      std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
769      return __beg;
770    }
771
772  template<typename _CharT, typename _InIter>
773    _InIter
774    num_get<_CharT, _InIter>::
775    do_get(iter_type __beg, iter_type __end, ios_base& __io,
776           ios_base::iostate& __err, void*& __v) const
777    {
778      // Prepare for hex formatted input.
779      typedef ios_base::fmtflags        fmtflags;
780      const fmtflags __fmt = __io.flags();
781      __io.flags(__fmt & ~ios_base::basefield | ios_base::hex);
782
783      unsigned long __ul;
784      __beg = _M_extract_int(__beg, __end, __io, __err, __ul);
785
786      // Reset from hex formatted input.
787      __io.flags(__fmt);
788
789      if (!(__err & ios_base::failbit))
790	__v = reinterpret_cast<void*>(__ul);
791      else
792	__err |= ios_base::failbit;
793      return __beg;
794    }
795
796  // For use by integer and floating-point types after they have been
797  // converted into a char_type string.
798  template<typename _CharT, typename _OutIter>
799    void
800    num_put<_CharT, _OutIter>::
801    _M_pad(_CharT __fill, streamsize __w, ios_base& __io,
802	   _CharT* __new, const _CharT* __cs, int& __len) const
803    {
804      // [22.2.2.2.2] Stage 3.
805      // If necessary, pad.
806      __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs,
807						  __w, __len, true);
808      __len = static_cast<int>(__w);
809    }
810
811  // Forwarding functions to peel signed from unsigned integer types.
812  template<typename _CharT>
813    inline int
814    __int_to_char(_CharT* __bufend, long __v, const _CharT* __lit,
815		  ios_base::fmtflags __flags)
816    {
817      unsigned long __ul = static_cast<unsigned long>(__v);
818      bool __neg = false;
819      if (__v < 0)
820	{
821	  __ul = -__ul;
822	  __neg = true;
823	}
824      return __int_to_char(__bufend, __ul, __lit, __flags, __neg);
825    }
826
827  template<typename _CharT>
828    inline int
829    __int_to_char(_CharT* __bufend, unsigned long __v, const _CharT* __lit,
830		  ios_base::fmtflags __flags)
831    {
832      // About showpos, see Table 60 and C99 7.19.6.1, p6 (+).
833      return __int_to_char(__bufend, __v, __lit,
834			   __flags & ~ios_base::showpos, false);
835    }
836
837#ifdef _GLIBCXX_USE_LONG_LONG
838  template<typename _CharT>
839    inline int
840    __int_to_char(_CharT* __bufend, long long __v, const _CharT* __lit,
841		  ios_base::fmtflags __flags)
842    {
843      unsigned long long __ull = static_cast<unsigned long long>(__v);
844      bool __neg = false;
845      if (__v < 0)
846	{
847	  __ull = -__ull;
848	  __neg = true;
849	}
850      return __int_to_char(__bufend, __ull, __lit, __flags, __neg);
851    }
852
853  template<typename _CharT>
854    inline int
855    __int_to_char(_CharT* __bufend, unsigned long long __v, 
856		  const _CharT* __lit, ios_base::fmtflags __flags)
857    { return __int_to_char(__bufend, __v, __lit,
858			   __flags & ~ios_base::showpos, false); }
859#endif
860
861  template<typename _CharT, typename _ValueT>
862    int
863    __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
864		  ios_base::fmtflags __flags, bool __neg)
865    {
866      // Don't write base if already 0.
867      const bool __showbase = (__flags & ios_base::showbase) && __v;
868      const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
869      _CharT* __buf = __bufend - 1;
870
871      if (__builtin_expect(__basefield != ios_base::oct &&
872			   __basefield != ios_base::hex, true))
873	{
874	  // Decimal.
875	  do
876	    {
877	      *__buf-- = __lit[(__v % 10) + __num_base::_S_odigits];
878	      __v /= 10;
879	    }
880	  while (__v != 0);
881	  if (__neg)
882	    *__buf-- = __lit[__num_base::_S_ominus];
883	  else if (__flags & ios_base::showpos)
884	    *__buf-- = __lit[__num_base::_S_oplus];
885	}
886      else if (__basefield == ios_base::oct)
887	{
888	  // Octal.
889	  do
890	    {
891	      *__buf-- = __lit[(__v & 0x7) + __num_base::_S_odigits];
892	      __v >>= 3;
893	    }
894	  while (__v != 0);
895	  if (__showbase)
896	    *__buf-- = __lit[__num_base::_S_odigits];
897	}
898      else
899	{
900	  // Hex.
901	  const bool __uppercase = __flags & ios_base::uppercase;
902	  const int __case_offset = __uppercase ? __num_base::_S_oudigits
903	                                        : __num_base::_S_odigits;
904	  do
905	    {
906	      *__buf-- = __lit[(__v & 0xf) + __case_offset];
907	      __v >>= 4;
908	    }
909	  while (__v != 0);
910	  if (__showbase)
911	    {
912	      // 'x' or 'X'
913	      *__buf-- = __lit[__num_base::_S_ox + __uppercase];
914	      // '0'
915	      *__buf-- = __lit[__num_base::_S_odigits];
916	    }
917	}
918      return __bufend - __buf - 1;
919    }
920
921  template<typename _CharT, typename _OutIter>
922    void
923    num_put<_CharT, _OutIter>::
924    _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep,
925		 ios_base& __io, _CharT* __new, _CharT* __cs, int& __len) const
926    {
927      // By itself __add_grouping cannot deal correctly with __cs when
928      // ios::showbase is set and ios_base::oct || ios_base::hex.
929      // Therefore we take care "by hand" of the initial 0, 0x or 0X.
930      // However, remember that the latter do not occur if the number
931      // printed is '0' (__len == 1).
932      streamsize __off = 0;
933      const ios_base::fmtflags __basefield = __io.flags()
934	                                     & ios_base::basefield;
935      if ((__io.flags() & ios_base::showbase) && __len > 1)
936	if (__basefield == ios_base::oct)
937	  {
938	    __off = 1;
939	    __new[0] = __cs[0];
940	  }
941	else if (__basefield == ios_base::hex)
942	  {
943	    __off = 2;
944	    __new[0] = __cs[0];
945	    __new[1] = __cs[1];
946	  }
947      _CharT* __p;
948      __p = std::__add_grouping(__new + __off, __sep, __grouping,
949				__grouping_size, __cs + __off,
950				__cs + __len);
951      __len = __p - __new;
952    }
953
954  template<typename _CharT, typename _OutIter>
955    template<typename _ValueT>
956      _OutIter
957      num_put<_CharT, _OutIter>::
958      _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill,
959		    _ValueT __v) const
960      {
961	typedef typename numpunct<_CharT>::__cache_type	__cache_type;
962	__use_cache<__cache_type> __uc;
963	const locale& __loc = __io._M_getloc();
964	const __cache_type* __lc = __uc(__loc);
965	const _CharT* __lit = __lc->_M_atoms_out;
966
967	// Long enough to hold hex, dec, and octal representations.
968	const int __ilen = 4 * sizeof(_ValueT);
969	_CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
970							     * __ilen));
971
972	// [22.2.2.2.2] Stage 1, numeric conversion to character.
973	// Result is returned right-justified in the buffer.
974	int __len;
975	__len = __int_to_char(__cs + __ilen, __v, __lit, __io.flags());
976	__cs += __ilen - __len;
977
978	// Add grouping, if necessary.
979	if (__lc->_M_use_grouping)
980	  {
981	    // Grouping can add (almost) as many separators as the
982	    // number of digits, but no more.
983	    _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
984								  * __len * 2));
985	    _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size,
986			 __lc->_M_thousands_sep, __io, __cs2, __cs, __len);
987	    __cs = __cs2;
988	  }
989
990	// Pad.
991	const streamsize __w = __io.width();
992	if (__w > static_cast<streamsize>(__len))
993	  {
994	    _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
995								  * __w));
996	    _M_pad(__fill, __w, __io, __cs3, __cs, __len);
997	    __cs = __cs3;
998	  }
999	__io.width(0);
1000
1001	// [22.2.2.2.2] Stage 4.
1002	// Write resulting, fully-formatted string to output iterator.
1003	return std::__write(__s, __cs, __len);
1004      }
1005
1006  template<typename _CharT, typename _OutIter>
1007    void
1008    num_put<_CharT, _OutIter>::
1009    _M_group_float(const char* __grouping, size_t __grouping_size,
1010		   _CharT __sep, const _CharT* __p, _CharT* __new,
1011		   _CharT* __cs, int& __len) const
1012    {
1013      // _GLIBCXX_RESOLVE_LIB_DEFECTS
1014      // 282. What types does numpunct grouping refer to?
1015      // Add grouping, if necessary.
1016      _CharT* __p2;
1017      const int __declen = __p ? __p - __cs : __len;
1018      __p2 = std::__add_grouping(__new, __sep, __grouping, __grouping_size,
1019				 __cs, __cs + __declen);
1020
1021      // Tack on decimal part.
1022      int __newlen = __p2 - __new;
1023      if (__p)
1024	{
1025	  char_traits<_CharT>::copy(__p2, __p, __len - __declen);
1026	  __newlen += __len - __declen;
1027	}
1028      __len = __newlen;
1029    }
1030
1031  // The following code uses snprintf (or sprintf(), when
1032  // _GLIBCXX_USE_C99 is not defined) to convert floating point values
1033  // for insertion into a stream.  An optimization would be to replace
1034  // them with code that works directly on a wide buffer and then use
1035  // __pad to do the padding.  It would be good to replace them anyway
1036  // to gain back the efficiency that C++ provides by knowing up front
1037  // the type of the values to insert.  Also, sprintf is dangerous
1038  // since may lead to accidental buffer overruns.  This
1039  // implementation follows the C++ standard fairly directly as
1040  // outlined in 22.2.2.2 [lib.locale.num.put]
1041  template<typename _CharT, typename _OutIter>
1042    template<typename _ValueT>
1043      _OutIter
1044      num_put<_CharT, _OutIter>::
1045      _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
1046		       _ValueT __v) const
1047      {
1048	typedef typename numpunct<_CharT>::__cache_type	__cache_type;
1049	__use_cache<__cache_type> __uc;
1050	const locale& __loc = __io._M_getloc();
1051	const __cache_type* __lc = __uc(__loc);
1052
1053	// Use default precision if out of range.
1054	streamsize __prec = __io.precision();
1055	if (__prec < static_cast<streamsize>(0))
1056	  __prec = static_cast<streamsize>(6);
1057
1058	const int __max_digits = numeric_limits<_ValueT>::digits10;
1059
1060	// [22.2.2.2.2] Stage 1, numeric conversion to character.
1061	int __len;
1062	// Long enough for the max format spec.
1063	char __fbuf[16];
1064
1065#ifdef _GLIBCXX_USE_C99
1066	// First try a buffer perhaps big enough (most probably sufficient
1067	// for non-ios_base::fixed outputs)
1068	int __cs_size = __max_digits * 3;
1069	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1070
1071	__num_base::_S_format_float(__io, __fbuf, __mod);
1072	__len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
1073				      _S_get_c_locale(), __prec);
1074
1075	// If the buffer was not large enough, try again with the correct size.
1076	if (__len >= __cs_size)
1077	  {
1078	    __cs_size = __len + 1;
1079	    __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1080	    __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
1081					  _S_get_c_locale(), __prec);
1082	  }
1083#else
1084	// Consider the possibility of long ios_base::fixed outputs
1085	const bool __fixed = __io.flags() & ios_base::fixed;
1086	const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
1087
1088	// The size of the output string is computed as follows.
1089	// ios_base::fixed outputs may need up to __max_exp + 1 chars
1090	// for the integer part + __prec chars for the fractional part
1091	// + 3 chars for sign, decimal point, '\0'. On the other hand,
1092	// for non-fixed outputs __max_digits * 2 + __prec chars are
1093	// largely sufficient.
1094	const int __cs_size = __fixed ? __max_exp + __prec + 4
1095	                              : __max_digits * 2 + __prec;
1096	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1097
1098	__num_base::_S_format_float(__io, __fbuf, __mod);
1099	__len = std::__convert_from_v(__cs, 0, __fbuf, __v,
1100				      _S_get_c_locale(), __prec);
1101#endif
1102
1103      // [22.2.2.2.2] Stage 2, convert to char_type, using correct
1104      // numpunct.decimal_point() values for '.' and adding grouping.
1105      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1106
1107      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1108							   * __len));
1109      __ctype.widen(__cs, __cs + __len, __ws);
1110
1111      // Replace decimal point.
1112      const _CharT __cdec = __ctype.widen('.');
1113      const _CharT __dec = __lc->_M_decimal_point;
1114      const _CharT* __p;
1115      if (__p = char_traits<_CharT>::find(__ws, __len, __cdec))
1116	__ws[__p - __ws] = __dec;
1117
1118      // Add grouping, if necessary.
1119      if (__lc->_M_use_grouping)
1120	{
1121	  // Grouping can add (almost) as many separators as the
1122	  // number of digits, but no more.
1123	  _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1124								* __len * 2));
1125	  _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size,
1126			 __lc->_M_thousands_sep, __p, __ws2, __ws, __len);
1127	  __ws = __ws2;
1128	}
1129
1130      // Pad.
1131      const streamsize __w = __io.width();
1132      if (__w > static_cast<streamsize>(__len))
1133	{
1134	  _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1135								* __w));
1136	  _M_pad(__fill, __w, __io, __ws3, __ws, __len);
1137	  __ws = __ws3;
1138	}
1139      __io.width(0);
1140
1141      // [22.2.2.2.2] Stage 4.
1142      // Write resulting, fully-formatted string to output iterator.
1143      return std::__write(__s, __ws, __len);
1144      }
1145
1146  template<typename _CharT, typename _OutIter>
1147    _OutIter
1148    num_put<_CharT, _OutIter>::
1149    do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
1150    {
1151      const ios_base::fmtflags __flags = __io.flags();
1152      if ((__flags & ios_base::boolalpha) == 0)
1153        {
1154          const long __l = __v;
1155          __s = _M_insert_int(__s, __io, __fill, __l);
1156        }
1157      else
1158        {
1159	  typedef typename numpunct<_CharT>::__cache_type __cache_type;
1160	  __use_cache<__cache_type> __uc;
1161	  const locale& __loc = __io._M_getloc();
1162	  const __cache_type* __lc = __uc(__loc);
1163
1164	  const _CharT* __name = __v ? __lc->_M_truename
1165	                             : __lc->_M_falsename;
1166	  int __len = __v ? __lc->_M_truename_size
1167	                  : __lc->_M_falsename_size;
1168
1169	  const streamsize __w = __io.width();
1170	  if (__w > static_cast<streamsize>(__len))
1171	    {
1172	      _CharT* __cs
1173		= static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1174							* __w));
1175	      _M_pad(__fill, __w, __io, __cs, __name, __len);
1176	      __name = __cs;
1177	    }
1178	  __io.width(0);
1179	  __s = std::__write(__s, __name, __len);
1180	}
1181      return __s;
1182    }
1183
1184  template<typename _CharT, typename _OutIter>
1185    _OutIter
1186    num_put<_CharT, _OutIter>::
1187    do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
1188    { return _M_insert_int(__s, __io, __fill, __v); }
1189
1190  template<typename _CharT, typename _OutIter>
1191    _OutIter
1192    num_put<_CharT, _OutIter>::
1193    do_put(iter_type __s, ios_base& __io, char_type __fill,
1194           unsigned long __v) const
1195    { return _M_insert_int(__s, __io, __fill, __v); }
1196
1197#ifdef _GLIBCXX_USE_LONG_LONG
1198  template<typename _CharT, typename _OutIter>
1199    _OutIter
1200    num_put<_CharT, _OutIter>::
1201    do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
1202    { return _M_insert_int(__s, __b, __fill, __v); }
1203
1204  template<typename _CharT, typename _OutIter>
1205    _OutIter
1206    num_put<_CharT, _OutIter>::
1207    do_put(iter_type __s, ios_base& __io, char_type __fill,
1208           unsigned long long __v) const
1209    { return _M_insert_int(__s, __io, __fill, __v); }
1210#endif
1211
1212  template<typename _CharT, typename _OutIter>
1213    _OutIter
1214    num_put<_CharT, _OutIter>::
1215    do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
1216    { return _M_insert_float(__s, __io, __fill, char(), __v); }
1217
1218  template<typename _CharT, typename _OutIter>
1219    _OutIter
1220    num_put<_CharT, _OutIter>::
1221    do_put(iter_type __s, ios_base& __io, char_type __fill,
1222	   long double __v) const
1223    { return _M_insert_float(__s, __io, __fill, 'L', __v); }
1224
1225  template<typename _CharT, typename _OutIter>
1226    _OutIter
1227    num_put<_CharT, _OutIter>::
1228    do_put(iter_type __s, ios_base& __io, char_type __fill,
1229           const void* __v) const
1230    {
1231      const ios_base::fmtflags __flags = __io.flags();
1232      const ios_base::fmtflags __fmt = ~(ios_base::basefield
1233					 | ios_base::uppercase
1234					 | ios_base::internal);
1235      __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
1236
1237      __s = _M_insert_int(__s, __io, __fill,
1238			  reinterpret_cast<unsigned long>(__v));
1239      __io.flags(__flags);
1240      return __s;
1241    }
1242
1243  template<typename _CharT, typename _InIter>
1244    template<bool _Intl>
1245      _InIter
1246      money_get<_CharT, _InIter>::
1247      _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
1248		 ios_base::iostate& __err, string& __units) const
1249      {
1250	typedef char_traits<_CharT>			  __traits_type;
1251	typedef typename string_type::size_type	          size_type;	
1252	typedef money_base::part			  part;
1253	typedef moneypunct<_CharT, _Intl>		  __moneypunct_type;
1254	typedef typename __moneypunct_type::__cache_type  __cache_type;
1255	
1256	const locale& __loc = __io._M_getloc();
1257	const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1258
1259	__use_cache<__cache_type> __uc;
1260	const __cache_type* __lc = __uc(__loc);
1261	const char_type* __lit = __lc->_M_atoms;
1262
1263	// Deduced sign.
1264	bool __negative = false;
1265	// Sign size.
1266	size_type __sign_size = 0;
1267	// True if sign is mandatory.
1268	const bool __mandatory_sign = (__lc->_M_positive_sign_size
1269				       && __lc->_M_negative_sign_size);
1270	// String of grouping info from thousands_sep plucked from __units.
1271	string __grouping_tmp;
1272	if (__lc->_M_use_grouping)
1273	  __grouping_tmp.reserve(32);
1274	// Last position before the decimal point.
1275	int __last_pos = 0;
1276	// Separator positions, then, possibly, fractional digits.
1277	int __n = 0;
1278	// If input iterator is in a valid state.
1279	bool __testvalid = true;
1280	// Flag marking when a decimal point is found.
1281	bool __testdecfound = false;
1282
1283	// The tentative returned string is stored here.
1284	string __res;
1285	__res.reserve(32);
1286
1287	const char_type* __lit_zero = __lit + money_base::_S_zero;
1288	const char_type* __q;
1289	const money_base::pattern __p = __lc->_M_neg_format;	
1290	for (int __i = 0; __i < 4 && __testvalid; ++__i)
1291	  {
1292	    const part __which = static_cast<part>(__p.field[__i]);
1293	    switch (__which)
1294	      {
1295	      case money_base::symbol:
1296		// According to 22.2.6.1.2, p2, symbol is required
1297		// if (__io.flags() & ios_base::showbase), otherwise
1298		// is optional and consumed only if other characters
1299		// are needed to complete the format.
1300		if (__io.flags() & ios_base::showbase || __sign_size > 1
1301		    || __i == 0
1302		    || (__i == 1 && (__mandatory_sign
1303				     || (static_cast<part>(__p.field[0])
1304					 == money_base::sign)
1305				     || (static_cast<part>(__p.field[2])
1306					 == money_base::space)))
1307		    || (__i == 2 && ((static_cast<part>(__p.field[3])
1308				      == money_base::value)
1309				     || __mandatory_sign
1310				     && (static_cast<part>(__p.field[3])
1311					 == money_base::sign))))
1312		  {
1313		    const size_type __len = __lc->_M_curr_symbol_size;
1314		    size_type __j = 0;
1315		    for (; __beg != __end && __j < __len
1316			   && *__beg == __lc->_M_curr_symbol[__j];
1317			 ++__beg, ++__j);
1318		    if (__j != __len
1319			&& (__j || __io.flags() & ios_base::showbase))
1320		      __testvalid = false;
1321		  }
1322		break;
1323	      case money_base::sign:
1324		// Sign might not exist, or be more than one character long.
1325		if (__lc->_M_positive_sign_size && __beg != __end
1326		    && *__beg == __lc->_M_positive_sign[0])
1327		  {
1328		    __sign_size = __lc->_M_positive_sign_size;
1329		    ++__beg;
1330		  }
1331		else if (__lc->_M_negative_sign_size && __beg != __end
1332			 && *__beg == __lc->_M_negative_sign[0])
1333		  {
1334		    __negative = true;
1335		    __sign_size = __lc->_M_negative_sign_size;
1336		    ++__beg;
1337		  }
1338		else if (__lc->_M_positive_sign_size
1339			 && !__lc->_M_negative_sign_size)
1340		  // "... if no sign is detected, the result is given the sign
1341		  // that corresponds to the source of the empty string"
1342		  __negative = true;
1343		else if (__mandatory_sign)
1344		  __testvalid = false;
1345		break;
1346	      case money_base::value:
1347		// Extract digits, remove and stash away the
1348		// grouping of found thousands separators.
1349		for (; __beg != __end; ++__beg)
1350		  if (__q = __traits_type::find(__lit_zero, 10, *__beg))
1351		    {
1352		      __res += money_base::_S_atoms[__q - __lit];
1353		      ++__n;
1354		    }
1355		  else if (*__beg == __lc->_M_decimal_point && !__testdecfound)
1356		    {
1357		      __last_pos = __n;
1358		      __n = 0;
1359		      __testdecfound = true;
1360		    }
1361		  else if (__lc->_M_use_grouping
1362			   && *__beg == __lc->_M_thousands_sep
1363			   && !__testdecfound)
1364		    {
1365		      if (__n)
1366			{
1367			  // Mark position for later analysis.
1368			  __grouping_tmp += static_cast<char>(__n);
1369			  __n = 0;
1370			}
1371		      else
1372			{
1373			  __testvalid = false;
1374			  break;
1375			}
1376		    }
1377		  else
1378		    break;
1379		if (__res.empty())
1380		  __testvalid = false;
1381		break;
1382	      case money_base::space:
1383		// At least one space is required.
1384		if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
1385		  ++__beg;
1386		else
1387		  __testvalid = false;
1388	      case money_base::none:
1389		// Only if not at the end of the pattern.
1390		if (__i != 3)
1391		  for (; __beg != __end
1392			 && __ctype.is(ctype_base::space, *__beg); ++__beg);
1393		break;
1394	      }
1395	  }
1396
1397	// Need to get the rest of the sign characters, if they exist.
1398	if (__sign_size > 1 && __testvalid)
1399	  {
1400	    const char_type* __sign = __negative ? __lc->_M_negative_sign
1401	                                         : __lc->_M_positive_sign;
1402	    size_type __i = 1;
1403	    for (; __beg != __end && __i < __sign_size
1404		   && *__beg == __sign[__i]; ++__beg, ++__i);
1405	    
1406	    if (__i != __sign_size)
1407	      __testvalid = false;
1408	  }
1409
1410	if (__testvalid)
1411	  {
1412	    // Strip leading zeros.
1413	    if (__res.size() > 1)
1414	      {
1415		const size_type __first = __res.find_first_not_of('0');
1416		const bool __only_zeros = __first == string::npos;
1417		if (__first)
1418		  __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
1419	      }
1420
1421	    // 22.2.6.1.2, p4
1422	    if (__negative && __res[0] != '0')
1423	      __res.insert(__res.begin(), '-');
1424	    
1425	    // Test for grouping fidelity.
1426	    if (__grouping_tmp.size())
1427	      {
1428		// Add the ending grouping.
1429		__grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
1430						                   : __n);
1431		if (!std::__verify_grouping(__lc->_M_grouping,
1432					    __lc->_M_grouping_size,
1433					    __grouping_tmp))
1434		  __testvalid = false;
1435	      }
1436	    
1437	    // Iff not enough digits were supplied after the decimal-point.
1438	    if (__testdecfound && __lc->_M_frac_digits > 0
1439		&& __n != __lc->_M_frac_digits)
1440	      __testvalid = false;
1441	  }
1442	
1443	// Iff no more characters are available.
1444	if (__beg == __end)
1445	  __err |= ios_base::eofbit;
1446	
1447	// Iff valid sequence is not recognized.
1448	if (!__testvalid)
1449	  __err |= ios_base::failbit;
1450	else
1451	  __units.swap(__res);
1452	
1453	return __beg;
1454      }
1455
1456  template<typename _CharT, typename _InIter>
1457    _InIter
1458    money_get<_CharT, _InIter>::
1459    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
1460	   ios_base::iostate& __err, long double& __units) const
1461    {
1462      string __str;
1463      if (__intl)
1464	__beg = _M_extract<true>(__beg, __end, __io, __err, __str);
1465      else
1466	__beg = _M_extract<false>(__beg, __end, __io, __err, __str);
1467      std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
1468      return __beg;
1469    }
1470
1471  template<typename _CharT, typename _InIter>
1472    _InIter
1473    money_get<_CharT, _InIter>::
1474    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
1475	   ios_base::iostate& __err, string_type& __units) const
1476    {
1477      typedef typename string::size_type                  size_type;
1478
1479      const locale& __loc = __io._M_getloc();
1480      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1481
1482      string __str;
1483      const iter_type __ret = __intl ? _M_extract<true>(__beg, __end, __io,
1484							__err, __str)
1485	                             : _M_extract<false>(__beg, __end, __io,
1486							 __err, __str);
1487      const size_type __len = __str.size();
1488      if (__len)
1489	{
1490	  _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1491							       * __len));
1492	  __ctype.widen(__str.data(), __str.data() + __len, __ws);
1493	  __units.assign(__ws, __len);
1494	}
1495
1496      return __ret;
1497    }
1498
1499  template<typename _CharT, typename _OutIter>
1500    template<bool _Intl>
1501      _OutIter
1502      money_put<_CharT, _OutIter>::
1503      _M_insert(iter_type __s, ios_base& __io, char_type __fill,
1504		const string_type& __digits) const
1505      {
1506	typedef typename string_type::size_type	          size_type;
1507	typedef money_base::part                          part;
1508	typedef moneypunct<_CharT, _Intl>                 __moneypunct_type;
1509	typedef typename __moneypunct_type::__cache_type  __cache_type;
1510      
1511	const locale& __loc = __io._M_getloc();
1512	const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1513
1514	__use_cache<__cache_type> __uc;
1515	const __cache_type* __lc = __uc(__loc);
1516	const char_type* __lit = __lc->_M_atoms;
1517
1518	// Determine if negative or positive formats are to be used, and
1519	// discard leading negative_sign if it is present.
1520	const char_type* __beg = __digits.data();
1521
1522	money_base::pattern __p;
1523	const char_type* __sign;
1524	size_type __sign_size;
1525	if (*__beg != __lit[money_base::_S_minus])
1526	  {
1527	    __p = __lc->_M_pos_format;
1528	    __sign = __lc->_M_positive_sign;
1529	    __sign_size = __lc->_M_positive_sign_size;
1530	  }
1531	else
1532	  {
1533	    __p = __lc->_M_neg_format;
1534	    __sign = __lc->_M_negative_sign;
1535	    __sign_size = __lc->_M_negative_sign_size;
1536	    if (__digits.size())
1537	      ++__beg;
1538	  }
1539       
1540	// Look for valid numbers in the ctype facet within input digits.
1541	size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
1542					   __beg + __digits.size()) - __beg;
1543	if (__len)
1544	  {
1545	    // Assume valid input, and attempt to format.
1546	    // Break down input numbers into base components, as follows:
1547	    //   final_value = grouped units + (decimal point) + (digits)
1548	    string_type __value;
1549	    __value.reserve(2 * __len);
1550
1551	    // Add thousands separators to non-decimal digits, per
1552	    // grouping rules.
1553	    int __paddec = __len - __lc->_M_frac_digits;
1554	    if (__paddec > 0)
1555  	      {
1556		if (__lc->_M_frac_digits < 0)
1557		  __paddec = __len;
1558  		if (__lc->_M_grouping_size)
1559  		  {
1560		    _CharT* __ws =
1561  		      static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1562  							    * 2 * __len));
1563  		    _CharT* __ws_end =
1564		      std::__add_grouping(__ws, __lc->_M_thousands_sep,
1565					  __lc->_M_grouping,
1566					  __lc->_M_grouping_size,
1567					  __beg, __beg + __paddec);
1568		    __value.assign(__ws, __ws_end - __ws);
1569  		  }
1570  		else
1571		  __value.assign(__beg, __paddec);
1572	      }
1573
1574	    // Deal with decimal point, decimal digits.
1575	    if (__lc->_M_frac_digits > 0)
1576	      {
1577		__value += __lc->_M_decimal_point;
1578		if (__paddec >= 0)
1579		  __value.append(__beg + __paddec, __lc->_M_frac_digits);
1580		else
1581		  {
1582		    // Have to pad zeros in the decimal position.
1583		    __value.append(-__paddec, __lit[money_base::_S_zero]);
1584		    __value.append(__beg, __len);
1585		  }
1586  	      }
1587  
1588	    // Calculate length of resulting string.
1589	    const ios_base::fmtflags __f = __io.flags() 
1590	                                   & ios_base::adjustfield;
1591	    __len = __value.size() + __sign_size;
1592	    __len += ((__io.flags() & ios_base::showbase)
1593		      ? __lc->_M_curr_symbol_size : 0);
1594
1595	    string_type __res;
1596	    __res.reserve(2 * __len);
1597	    
1598	    const size_type __width = static_cast<size_type>(__io.width());  
1599	    const bool __testipad = (__f == ios_base::internal
1600				     && __len < __width);
1601	    // Fit formatted digits into the required pattern.
1602	    for (int __i = 0; __i < 4; ++__i)
1603	      {
1604		const part __which = static_cast<part>(__p.field[__i]);
1605		switch (__which)
1606		  {
1607		  case money_base::symbol:
1608		    if (__io.flags() & ios_base::showbase)
1609		      __res.append(__lc->_M_curr_symbol,
1610				   __lc->_M_curr_symbol_size);
1611		    break;
1612		  case money_base::sign:
1613		    // Sign might not exist, or be more than one
1614		    // charater long. In that case, add in the rest
1615		    // below.
1616		    if (__sign_size)
1617		      __res += __sign[0];
1618		    break;
1619		  case money_base::value:
1620		    __res += __value;
1621		    break;
1622		  case money_base::space:
1623		    // At least one space is required, but if internal
1624		    // formatting is required, an arbitrary number of
1625		    // fill spaces will be necessary.
1626		    if (__testipad)
1627		      __res.append(__width - __len, __fill);
1628		    else
1629		      __res += __fill;
1630		    break;
1631		  case money_base::none:
1632		    if (__testipad)
1633		      __res.append(__width - __len, __fill);
1634		    break;
1635		  }
1636	      }
1637	    
1638	    // Special case of multi-part sign parts.
1639	    if (__sign_size > 1)
1640	      __res.append(__sign + 1, __sign_size - 1);
1641	    
1642	    // Pad, if still necessary.
1643	    __len = __res.size();
1644	    if (__width > __len)
1645	      {
1646		if (__f == ios_base::left)
1647		  // After.
1648		  __res.append(__width - __len, __fill);
1649		else
1650		  // Before.
1651		  __res.insert(0, __width - __len, __fill);
1652		__len = __width;
1653	      }
1654	    
1655	    // Write resulting, fully-formatted string to output iterator.
1656	    __s = std::__write(__s, __res.data(), __len);
1657	  }
1658	__io.width(0);
1659	return __s;    
1660      }
1661  
1662  template<typename _CharT, typename _OutIter>
1663    _OutIter
1664    money_put<_CharT, _OutIter>::
1665    do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1666	   long double __units) const
1667    {
1668      const locale __loc = __io.getloc();
1669      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1670#ifdef _GLIBCXX_USE_C99
1671      // First try a buffer perhaps big enough.
1672      int __cs_size = 64;
1673      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1674      // _GLIBCXX_RESOLVE_LIB_DEFECTS
1675      // 328. Bad sprintf format modifier in money_put<>::do_put()
1676      int __len = std::__convert_from_v(__cs, __cs_size, "%.*Lf", __units,
1677					_S_get_c_locale(), 0);
1678      // If the buffer was not large enough, try again with the correct size.
1679      if (__len >= __cs_size)
1680	{
1681	  __cs_size = __len + 1;
1682	  __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1683	  __len = std::__convert_from_v(__cs, __cs_size, "%.*Lf", __units,
1684					_S_get_c_locale(), 0);
1685	}
1686#else
1687      // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
1688      const int __cs_size = numeric_limits<long double>::max_exponent10 + 3;
1689      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1690      int __len = std::__convert_from_v(__cs, 0, "%.*Lf", __units,
1691					_S_get_c_locale(), 0);
1692#endif
1693      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1694							   * __cs_size));
1695      __ctype.widen(__cs, __cs + __len, __ws);
1696      const string_type __digits(__ws, __len);
1697      return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
1698	            : _M_insert<false>(__s, __io, __fill, __digits);
1699    }
1700
1701  template<typename _CharT, typename _OutIter>
1702    _OutIter
1703    money_put<_CharT, _OutIter>::
1704    do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1705	   const string_type& __digits) const
1706    { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
1707	            : _M_insert<false>(__s, __io, __fill, __digits); }
1708
1709
1710  // NB: Not especially useful. Without an ios_base object or some
1711  // kind of locale reference, we are left clawing at the air where
1712  // the side of the mountain used to be...
1713  template<typename _CharT, typename _InIter>
1714    time_base::dateorder
1715    time_get<_CharT, _InIter>::do_date_order() const
1716    { return time_base::no_order; }
1717
1718  // Expand a strftime format string and parse it.  E.g., do_get_date() may
1719  // pass %m/%d/%Y => extracted characters.
1720  template<typename _CharT, typename _InIter>
1721    _InIter
1722    time_get<_CharT, _InIter>::
1723    _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
1724			  ios_base::iostate& __err, tm* __tm,
1725			  const _CharT* __format) const
1726    {
1727      const locale& __loc = __io._M_getloc();
1728      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1729      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1730      const size_t __len = char_traits<_CharT>::length(__format);
1731
1732      for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
1733	{
1734	  if (__ctype.narrow(__format[__i], 0) == '%')
1735	    {
1736	      // Verify valid formatting code, attempt to extract.
1737	      char __c = __ctype.narrow(__format[++__i], 0);
1738	      int __mem = 0;
1739	      if (__c == 'E' || __c == 'O')
1740		__c = __ctype.narrow(__format[++__i], 0);
1741	      switch (__c)
1742		{
1743		  const char* __cs;
1744		  _CharT __wcs[10];
1745		case 'a':
1746		  // Abbreviated weekday name [tm_wday]
1747		  const char_type*  __days1[7];
1748		  __tp._M_days_abbreviated(__days1);
1749		  __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
1750					  7, __io, __err);
1751		  break;
1752		case 'A':
1753		  // Weekday name [tm_wday].
1754		  const char_type*  __days2[7];
1755		  __tp._M_days(__days2);
1756		  __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
1757					  7, __io, __err);
1758		  break;
1759		case 'h':
1760		case 'b':
1761		  // Abbreviated month name [tm_mon]
1762		  const char_type*  __months1[12];
1763		  __tp._M_months_abbreviated(__months1);
1764		  __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
1765					  __months1, 12, __io, __err);
1766		  break;
1767		case 'B':
1768		  // Month name [tm_mon].
1769		  const char_type*  __months2[12];
1770		  __tp._M_months(__months2);
1771		  __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
1772					  __months2, 12, __io, __err);
1773		  break;
1774		case 'c':
1775		  // Default time and date representation.
1776		  const char_type*  __dt[2];
1777		  __tp._M_date_time_formats(__dt);
1778		  __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1779						__tm, __dt[0]);
1780		  break;
1781		case 'd':
1782		  // Day [01, 31]. [tm_mday]
1783		  __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
1784					 __io, __err);
1785		  break;
1786		case 'e':
1787		  // Day [1, 31], with single digits preceded by
1788		  // space. [tm_mday]
1789		  if (__ctype.is(ctype_base::space, *__beg))
1790		    __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
1791					   1, __io, __err);
1792		  else
1793		    __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
1794					   2, __io, __err);
1795		  break;
1796		case 'D':
1797		  // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
1798		  __cs = "%m/%d/%y";
1799		  __ctype.widen(__cs, __cs + 9, __wcs);
1800		  __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1801						__tm, __wcs);
1802		  break;
1803		case 'H':
1804		  // Hour [00, 23]. [tm_hour]
1805		  __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
1806					 __io, __err);
1807		  break;
1808		case 'I':
1809		  // Hour [01, 12]. [tm_hour]
1810		  __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
1811					 __io, __err);
1812		  break;
1813		case 'm':
1814		  // Month [01, 12]. [tm_mon]
1815		  __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 
1816					 __io, __err);
1817		  if (!__err)
1818		    __tm->tm_mon = __mem - 1;
1819		  break;
1820		case 'M':
1821		  // Minute [00, 59]. [tm_min]
1822		  __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
1823					 __io, __err);
1824		  break;
1825		case 'n':
1826		  if (__ctype.narrow(*__beg, 0) == '\n')
1827		    ++__beg;
1828		  else
1829		    __err |= ios_base::failbit;
1830		  break;
1831		case 'R':
1832		  // Equivalent to (%H:%M).
1833		  __cs = "%H:%M";
1834		  __ctype.widen(__cs, __cs + 6, __wcs);
1835		  __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1836						__tm, __wcs);
1837		  break;
1838		case 'S':
1839		  // Seconds. [tm_sec]
1840		  // [00, 60] in C99 (one leap-second), [00, 61] in C89.
1841#ifdef _GLIBCXX_USE_C99
1842		  __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2,
1843#else
1844		  __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
1845#endif
1846					 __io, __err);
1847		  break;
1848		case 't':
1849		  if (__ctype.narrow(*__beg, 0) == '\t')
1850		    ++__beg;
1851		  else
1852		    __err |= ios_base::failbit;
1853		  break;
1854		case 'T':
1855		  // Equivalent to (%H:%M:%S).
1856		  __cs = "%H:%M:%S";
1857		  __ctype.widen(__cs, __cs + 9, __wcs);
1858		  __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1859						__tm, __wcs);
1860		  break;
1861		case 'x':
1862		  // Locale's date.
1863		  const char_type*  __dates[2];
1864		  __tp._M_date_formats(__dates);
1865		  __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1866						__tm, __dates[0]);
1867		  break;
1868		case 'X':
1869		  // Locale's time.
1870		  const char_type*  __times[2];
1871		  __tp._M_time_formats(__times);
1872		  __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1873						__tm, __times[0]);
1874		  break;
1875		case 'y':
1876		case 'C': // C99
1877		  // Two digit year. [tm_year]
1878		  __beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
1879					 __io, __err);
1880		  break;
1881		case 'Y':
1882		  // Year [1900). [tm_year]
1883		  __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
1884					 __io, __err);
1885		  if (!__err)
1886		    __tm->tm_year = __mem - 1900;
1887		  break;
1888		case 'Z':
1889		  // Timezone info.
1890		  if (__ctype.is(ctype_base::upper, *__beg))
1891		    {
1892		      int __tmp;
1893		      __beg = _M_extract_name(__beg, __end, __tmp,
1894				       __timepunct_cache<_CharT>::_S_timezones,
1895					      14, __io, __err);
1896
1897		      // GMT requires special effort.
1898		      if (__beg != __end && !__err && __tmp == 0
1899			  && (*__beg == __ctype.widen('-')
1900			      || *__beg == __ctype.widen('+')))
1901			{
1902			  __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
1903						 __io, __err);
1904			  __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
1905						 __io, __err);
1906			}
1907		    }
1908		  else
1909		    __err |= ios_base::failbit;
1910		  break;
1911		default:
1912		  // Not recognized.
1913		  __err |= ios_base::failbit;
1914		}
1915	    }
1916	  else
1917	    {
1918	      // Verify format and input match, extract and discard.
1919	      if (__format[__i] == *__beg)
1920		++__beg;
1921	      else
1922		__err |= ios_base::failbit;
1923	    }
1924	}
1925      return __beg;
1926    }
1927
1928  template<typename _CharT, typename _InIter>
1929    _InIter
1930    time_get<_CharT, _InIter>::
1931    _M_extract_num(iter_type __beg, iter_type __end, int& __member,
1932		   int __min, int __max, size_t __len,
1933		   ios_base& __io, ios_base::iostate& __err) const
1934    {
1935      const locale& __loc = __io._M_getloc();
1936      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1937
1938      // As-is works for __len = 1, 2, 4, the values actually used.
1939      int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
1940
1941      ++__min;
1942      size_t __i = 0;
1943      int __value = 0;
1944      for (; __beg != __end && __i < __len; ++__beg, ++__i)
1945	{
1946	  const char __c = __ctype.narrow(*__beg, '*');
1947	  if (__c >= '0' && __c <= '9')
1948	    {
1949	      __value = __value * 10 + (__c - '0');
1950	      const int __valuec = __value * __mult;
1951	      if (__valuec > __max || __valuec + __mult < __min)
1952		break;
1953	      __mult /= 10;
1954	    }
1955	  else
1956	    break;
1957	}
1958      if (__i == __len)
1959	__member = __value;
1960      else
1961	__err |= ios_base::failbit;
1962      return __beg;
1963    }
1964
1965  // Assumptions:
1966  // All elements in __names are unique.
1967  template<typename _CharT, typename _InIter>
1968    _InIter
1969    time_get<_CharT, _InIter>::
1970    _M_extract_name(iter_type __beg, iter_type __end, int& __member,
1971		    const _CharT** __names, size_t __indexlen,
1972		    ios_base& __io, ios_base::iostate& __err) const
1973    {
1974      typedef char_traits<_CharT>		__traits_type;
1975      const locale& __loc = __io._M_getloc();
1976      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1977
1978      int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
1979							  * __indexlen));
1980      size_t __nmatches = 0;
1981      size_t __pos = 0;
1982      bool __testvalid = true;
1983      const char_type* __name;
1984
1985      // Look for initial matches.
1986      // NB: Some of the locale data is in the form of all lowercase
1987      // names, and some is in the form of initially-capitalized
1988      // names. Look for both.
1989      if (__beg != __end)
1990	{
1991	  const char_type __c = *__beg;
1992	  for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
1993	    if (__c == __names[__i1][0]
1994		|| __c == __ctype.toupper(__names[__i1][0]))
1995	      __matches[__nmatches++] = __i1;
1996	}
1997
1998      while (__nmatches > 1)
1999	{
2000	  // Find smallest matching string.
2001	  size_t __minlen = __traits_type::length(__names[__matches[0]]);
2002	  for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
2003	    __minlen = std::min(__minlen,
2004			      __traits_type::length(__names[__matches[__i2]]));
2005	  ++__beg, ++__pos;
2006	  if (__pos < __minlen && __beg != __end)
2007	    for (size_t __i3 = 0; __i3 < __nmatches;)
2008	      {
2009		__name = __names[__matches[__i3]];
2010		if (__name[__pos] != *__beg)
2011		  __matches[__i3] = __matches[--__nmatches];
2012		else
2013		  ++__i3;
2014	      }
2015	  else
2016	    break;
2017	}
2018
2019      if (__nmatches == 1)
2020	{
2021	  // Make sure found name is completely extracted.
2022	  ++__beg, ++__pos;
2023	  __name = __names[__matches[0]];
2024	  const size_t __len = __traits_type::length(__name);
2025	  while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
2026	    ++__beg, ++__pos;
2027
2028	  if (__len == __pos)
2029	    __member = __matches[0];
2030	  else
2031	    __testvalid = false;
2032	}
2033      else
2034	__testvalid = false;
2035      if (!__testvalid)
2036	__err |= ios_base::failbit;
2037      return __beg;
2038    }
2039
2040  template<typename _CharT, typename _InIter>
2041    _InIter
2042    time_get<_CharT, _InIter>::
2043    do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
2044		ios_base::iostate& __err, tm* __tm) const
2045    {
2046      const locale& __loc = __io._M_getloc();
2047      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
2048      const char_type*  __times[2];
2049      __tp._M_time_formats(__times);
2050      __beg = _M_extract_via_format(__beg, __end, __io, __err, 
2051				    __tm, __times[0]);
2052      if (__beg == __end)
2053	__err |= ios_base::eofbit;
2054      return __beg;
2055    }
2056
2057  template<typename _CharT, typename _InIter>
2058    _InIter
2059    time_get<_CharT, _InIter>::
2060    do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
2061		ios_base::iostate& __err, tm* __tm) const
2062    {
2063      const locale& __loc = __io._M_getloc();
2064      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
2065      const char_type*  __dates[2];
2066      __tp._M_date_formats(__dates);
2067      __beg = _M_extract_via_format(__beg, __end, __io, __err,
2068				    __tm, __dates[0]);
2069      if (__beg == __end)
2070	__err |= ios_base::eofbit;
2071      return __beg;
2072    }
2073
2074  template<typename _CharT, typename _InIter>
2075    _InIter
2076    time_get<_CharT, _InIter>::
2077    do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
2078		   ios_base::iostate& __err, tm* __tm) const
2079    {
2080      typedef char_traits<_CharT>		__traits_type;
2081      const locale& __loc = __io._M_getloc();
2082      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
2083      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2084      const char_type*  __days[7];
2085      __tp._M_days_abbreviated(__days);
2086      int __tmpwday;
2087      __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7, __io, __err);
2088
2089      // Check to see if non-abbreviated name exists, and extract.
2090      // NB: Assumes both _M_days and _M_days_abbreviated organized in
2091      // exact same order, first to last, such that the resulting
2092      // __days array with the same index points to a day, and that
2093      // day's abbreviated form.
2094      // NB: Also assumes that an abbreviated name is a subset of the name.
2095      if (!__err && __beg != __end)
2096	{
2097	  size_t __pos = __traits_type::length(__days[__tmpwday]);
2098	  __tp._M_days(__days);
2099	  const char_type* __name = __days[__tmpwday];
2100	  if (__name[__pos] == *__beg)
2101	    {
2102	      // Extract the rest of it.
2103	      const size_t __len = __traits_type::length(__name);
2104	      while (__pos < __len && __beg != __end
2105		     && __name[__pos] == *__beg)
2106		++__beg, ++__pos;
2107	      if (__len != __pos)
2108		__err |= ios_base::failbit;
2109	    }
2110	}
2111      if (!__err)
2112	__tm->tm_wday = __tmpwday;
2113      
2114      if (__beg == __end)
2115	__err |= ios_base::eofbit;
2116      return __beg;
2117     }
2118
2119  template<typename _CharT, typename _InIter>
2120    _InIter
2121    time_get<_CharT, _InIter>::
2122    do_get_monthname(iter_type __beg, iter_type __end,
2123                     ios_base& __io, ios_base::iostate& __err, tm* __tm) const
2124    {
2125      typedef char_traits<_CharT>		__traits_type;
2126      const locale& __loc = __io._M_getloc();
2127      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
2128      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2129      const char_type*  __months[12];
2130      __tp._M_months_abbreviated(__months);
2131      int __tmpmon;
2132      __beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12, 
2133			      __io, __err);
2134
2135      // Check to see if non-abbreviated name exists, and extract.
2136      // NB: Assumes both _M_months and _M_months_abbreviated organized in
2137      // exact same order, first to last, such that the resulting
2138      // __months array with the same index points to a month, and that
2139      // month's abbreviated form.
2140      // NB: Also assumes that an abbreviated name is a subset of the name.
2141      if (!__err && __beg != __end)
2142	{
2143	  size_t __pos = __traits_type::length(__months[__tmpmon]);
2144	  __tp._M_months(__months);
2145	  const char_type* __name = __months[__tmpmon];
2146	  if (__name[__pos] == *__beg)
2147	    {
2148	      // Extract the rest of it.
2149	      const size_t __len = __traits_type::length(__name);
2150	      while (__pos < __len && __beg != __end
2151		     && __name[__pos] == *__beg)
2152		++__beg, ++__pos;
2153	      if (__len != __pos)
2154		__err |= ios_base::failbit;
2155	    }
2156	}
2157      if (!__err)
2158	__tm->tm_mon = __tmpmon;
2159
2160      if (__beg == __end)
2161	__err |= ios_base::eofbit;
2162      return __beg;
2163    }
2164
2165  template<typename _CharT, typename _InIter>
2166    _InIter
2167    time_get<_CharT, _InIter>::
2168    do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
2169		ios_base::iostate& __err, tm* __tm) const
2170    {
2171      const locale& __loc = __io._M_getloc();
2172      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2173
2174      size_t __i = 0;
2175      int __value = 0;
2176      for (; __beg != __end && __i < 4; ++__beg, ++__i)
2177	{
2178	  const char __c = __ctype.narrow(*__beg, '*');
2179	  if (__c >= '0' && __c <= '9')
2180	    __value = __value * 10 + (__c - '0');
2181	  else
2182	    break;
2183	}
2184      if (__i == 2 || __i == 4)
2185	__tm->tm_year = __i == 2 ? __value : __value - 1900;
2186      else
2187	__err |= ios_base::failbit;
2188      if (__beg == __end)
2189	__err |= ios_base::eofbit;
2190      return __beg;
2191    }
2192
2193  template<typename _CharT, typename _OutIter>
2194    _OutIter
2195    time_put<_CharT, _OutIter>::
2196    put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
2197	const _CharT* __beg, const _CharT* __end) const
2198    {
2199      const locale& __loc = __io._M_getloc();
2200      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
2201      for (; __beg != __end; ++__beg)
2202	if (__ctype.narrow(*__beg, 0) != '%')
2203	  {
2204	    *__s = *__beg;
2205	    ++__s;
2206	  }
2207	else if (++__beg != __end)
2208	  {
2209	    char __format;
2210	    char __mod = 0;
2211	    const char __c = __ctype.narrow(*__beg, 0);
2212	    if (__c != 'E' && __c != 'O')
2213	      __format = __c;
2214	    else if (++__beg != __end)
2215	      {
2216		__mod = __c;
2217		__format = __ctype.narrow(*__beg, 0);
2218	      }
2219	    else
2220	      break;
2221	    __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
2222	  }
2223	else
2224	  break;
2225      return __s;
2226    }
2227
2228  template<typename _CharT, typename _OutIter>
2229    _OutIter
2230    time_put<_CharT, _OutIter>::
2231    do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
2232	   char __format, char __mod) const
2233    {
2234      const locale& __loc = __io._M_getloc();
2235      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
2236      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
2237
2238      // NB: This size is arbitrary. Should this be a data member,
2239      // initialized at construction?
2240      const size_t __maxlen = 128;
2241      char_type* __res = 
2242       static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
2243
2244      // NB: In IEE 1003.1-200x, and perhaps other locale models, it
2245      // is possible that the format character will be longer than one
2246      // character. Possibilities include 'E' or 'O' followed by a
2247      // format character: if __mod is not the default argument, assume
2248      // it's a valid modifier.
2249      char_type __fmt[4];
2250      __fmt[0] = __ctype.widen('%');
2251      if (!__mod)
2252	{
2253	  __fmt[1] = __format;
2254	  __fmt[2] = char_type();
2255	}
2256      else
2257	{
2258	  __fmt[1] = __mod;
2259	  __fmt[2] = __format;
2260	  __fmt[3] = char_type();
2261	}
2262
2263      __tp._M_put(__res, __maxlen, __fmt, __tm);
2264
2265      // Write resulting, fully-formatted string to output iterator.
2266      return std::__write(__s, __res, char_traits<char_type>::length(__res));
2267    }
2268
2269
2270  // Generic version does nothing.
2271  template<typename _CharT>
2272    int
2273    collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const
2274    { return 0; }
2275
2276  // Generic version does nothing.
2277  template<typename _CharT>
2278    size_t
2279    collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const
2280    { return 0; }
2281
2282  template<typename _CharT>
2283    int
2284    collate<_CharT>::
2285    do_compare(const _CharT* __lo1, const _CharT* __hi1,
2286	       const _CharT* __lo2, const _CharT* __hi2) const
2287    {
2288      // strcoll assumes zero-terminated strings so we make a copy
2289      // and then put a zero at the end.
2290      const string_type __one(__lo1, __hi1);
2291      const string_type __two(__lo2, __hi2);
2292
2293      const _CharT* __p = __one.c_str();
2294      const _CharT* __pend = __one.data() + __one.length();
2295      const _CharT* __q = __two.c_str();
2296      const _CharT* __qend = __two.data() + __two.length();
2297
2298      // strcoll stops when it sees a nul character so we break
2299      // the strings into zero-terminated substrings and pass those
2300      // to strcoll.
2301      for (;;)
2302	{
2303	  const int __res = _M_compare(__p, __q);
2304	  if (__res)
2305	    return __res;
2306
2307	  __p += char_traits<_CharT>::length(__p);
2308	  __q += char_traits<_CharT>::length(__q);
2309	  if (__p == __pend && __q == __qend)
2310	    return 0;
2311	  else if (__p == __pend)
2312	    return -1;
2313	  else if (__q == __qend)
2314	    return 1;
2315
2316	  __p++;
2317	  __q++;
2318	}
2319    }
2320
2321  template<typename _CharT>
2322    typename collate<_CharT>::string_type
2323    collate<_CharT>::
2324    do_transform(const _CharT* __lo, const _CharT* __hi) const
2325    {
2326      // strxfrm assumes zero-terminated strings so we make a copy
2327      string_type __str(__lo, __hi);
2328
2329      const _CharT* __p = __str.c_str();
2330      const _CharT* __pend = __str.data() + __str.length();
2331
2332      size_t __len = (__hi - __lo) * 2;
2333
2334      string_type __ret;
2335
2336      // strxfrm stops when it sees a nul character so we break
2337      // the string into zero-terminated substrings and pass those
2338      // to strxfrm.
2339      for (;;)
2340	{
2341	  // First try a buffer perhaps big enough.
2342	  _CharT* __c =
2343	    static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
2344	  size_t __res = _M_transform(__c, __p, __len);
2345	  // If the buffer was not large enough, try again with the
2346	  // correct size.
2347	  if (__res >= __len)
2348	    {
2349	      __len = __res + 1;
2350	      __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
2351							  * __len));
2352	      __res = _M_transform(__c, __p, __res + 1);
2353	    }
2354
2355	  __ret.append(__c, __res);
2356	  __p += char_traits<_CharT>::length(__p);
2357	  if (__p == __pend)
2358	    return __ret;
2359
2360	  __p++;
2361	  __ret.push_back(_CharT());
2362	}
2363    }
2364
2365  template<typename _CharT>
2366    long
2367    collate<_CharT>::
2368    do_hash(const _CharT* __lo, const _CharT* __hi) const
2369    {
2370      unsigned long __val = 0;
2371      for (; __lo < __hi; ++__lo)
2372	__val = *__lo + ((__val << 7) |
2373		       (__val >> (numeric_limits<unsigned long>::digits - 7)));
2374      return static_cast<long>(__val);
2375    }
2376
2377  // Construct correctly padded string, as per 22.2.2.2.2
2378  // Assumes
2379  // __newlen > __oldlen
2380  // __news is allocated for __newlen size
2381  // Used by both num_put and ostream inserters: if __num,
2382  // internal-adjusted objects are padded according to the rules below
2383  // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
2384  // ones are.
2385
2386  // NB: Of the two parameters, _CharT can be deduced from the
2387  // function arguments. The other (_Traits) has to be explicitly specified.
2388  template<typename _CharT, typename _Traits>
2389    void
2390    __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill,
2391				   _CharT* __news, const _CharT* __olds,
2392				   const streamsize __newlen,
2393				   const streamsize __oldlen, const bool __num)
2394    {
2395      const size_t __plen = static_cast<size_t>(__newlen - __oldlen);
2396      const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
2397
2398      // Padding last.
2399      if (__adjust == ios_base::left)
2400	{
2401	  _Traits::copy(__news, const_cast<_CharT*>(__olds), __oldlen);
2402	  _Traits::assign(__news + __oldlen, __plen, __fill);
2403	  return;
2404	}
2405
2406      size_t __mod = 0;
2407      if (__adjust == ios_base::internal && __num)
2408	{
2409	  // Pad after the sign, if there is one.
2410	  // Pad after 0[xX], if there is one.
2411	  // Who came up with these rules, anyway? Jeeze.
2412          const locale& __loc = __io._M_getloc();
2413	  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2414
2415	  const bool __testsign = (__ctype.widen('-') == __olds[0]
2416				   || __ctype.widen('+') == __olds[0]);
2417	  const bool __testhex = (__ctype.widen('0') == __olds[0]
2418				  && __oldlen > 1
2419				  && (__ctype.widen('x') == __olds[1]
2420				      || __ctype.widen('X') == __olds[1]));
2421	  if (__testhex)
2422	    {
2423	      __news[0] = __olds[0];
2424	      __news[1] = __olds[1];
2425	      __mod = 2;
2426	      __news += 2;
2427	    }
2428	  else if (__testsign)
2429	    {
2430	      __news[0] = __olds[0];
2431	      __mod = 1;
2432	      ++__news;
2433	    }
2434	  // else Padding first.
2435	}
2436      _Traits::assign(__news, __plen, __fill);
2437      _Traits::copy(__news + __plen, const_cast<_CharT*>(__olds + __mod),
2438		    __oldlen - __mod);
2439    }
2440
2441  bool
2442  __verify_grouping(const char* __grouping, size_t __grouping_size,
2443		    const string& __grouping_tmp)
2444  {
2445    const size_t __n = __grouping_tmp.size() - 1;
2446    const size_t __min = std::min(__n, __grouping_size - 1);
2447    size_t __i = __n;
2448    bool __test = true;
2449    
2450    // Parsed number groupings have to match the
2451    // numpunct::grouping string exactly, starting at the
2452    // right-most point of the parsed sequence of elements ...
2453    for (size_t __j = 0; __j < __min && __test; --__i, ++__j)
2454      __test = __grouping_tmp[__i] == __grouping[__j];
2455    for (; __i && __test; --__i)
2456      __test = __grouping_tmp[__i] == __grouping[__min];
2457    // ... but the last parsed grouping can be <= numpunct
2458    // grouping.
2459    __test &= __grouping_tmp[0] <= __grouping[__min];
2460    return __test;
2461  }
2462
2463  template<typename _CharT>
2464    _CharT*
2465    __add_grouping(_CharT* __s, _CharT __sep,
2466		   const char* __gbeg, size_t __gsize,
2467		   const _CharT* __first, const _CharT* __last)
2468    {
2469      if (__last - __first > *__gbeg)
2470	{
2471	  const bool __bump = __gsize != 1;
2472	  __s = std::__add_grouping(__s,  __sep, __gbeg + __bump,
2473				    __gsize - __bump, __first,
2474				    __last - *__gbeg);
2475	  __first = __last - *__gbeg;
2476	  *__s++ = __sep;
2477	}
2478      do
2479	*__s++ = *__first++;
2480      while (__first != __last);
2481      return __s;
2482    }
2483
2484  // Inhibit implicit instantiations for required instantiations,
2485  // which are defined via explicit instantiations elsewhere.
2486  // NB: This syntax is a GNU extension.
2487#if _GLIBCXX_EXTERN_TEMPLATE
2488  extern template class moneypunct<char, false>;
2489  extern template class moneypunct<char, true>;
2490  extern template class moneypunct_byname<char, false>;
2491  extern template class moneypunct_byname<char, true>;
2492  extern template class money_get<char>;
2493  extern template class money_put<char>;
2494  extern template class numpunct<char>;
2495  extern template class numpunct_byname<char>;
2496  extern template class num_get<char>;
2497  extern template class num_put<char>;
2498  extern template class __timepunct<char>;
2499  extern template class time_put<char>;
2500  extern template class time_put_byname<char>;
2501  extern template class time_get<char>;
2502  extern template class time_get_byname<char>;
2503  extern template class messages<char>;
2504  extern template class messages_byname<char>;
2505  extern template class ctype_byname<char>;
2506  extern template class codecvt_byname<char, char, mbstate_t>;
2507  extern template class collate<char>;
2508  extern template class collate_byname<char>;
2509
2510  extern template
2511    const codecvt<char, char, mbstate_t>&
2512    use_facet<codecvt<char, char, mbstate_t> >(const locale&);
2513
2514  extern template
2515    const collate<char>&
2516    use_facet<collate<char> >(const locale&);
2517
2518  extern template
2519    const numpunct<char>&
2520    use_facet<numpunct<char> >(const locale&);
2521
2522  extern template
2523    const num_put<char>&
2524    use_facet<num_put<char> >(const locale&);
2525
2526  extern template
2527    const num_get<char>&
2528    use_facet<num_get<char> >(const locale&);
2529
2530  extern template
2531    const moneypunct<char, true>&
2532    use_facet<moneypunct<char, true> >(const locale&);
2533
2534  extern template
2535    const moneypunct<char, false>&
2536    use_facet<moneypunct<char, false> >(const locale&);
2537
2538  extern template
2539    const money_put<char>&
2540    use_facet<money_put<char> >(const locale&);
2541
2542  extern template
2543    const money_get<char>&
2544    use_facet<money_get<char> >(const locale&);
2545
2546  extern template
2547    const __timepunct<char>&
2548    use_facet<__timepunct<char> >(const locale&);
2549
2550  extern template
2551    const time_put<char>&
2552    use_facet<time_put<char> >(const locale&);
2553
2554  extern template
2555    const time_get<char>&
2556    use_facet<time_get<char> >(const locale&);
2557
2558  extern template
2559    const messages<char>&
2560    use_facet<messages<char> >(const locale&);
2561
2562  extern template
2563    bool
2564    has_facet<ctype<char> >(const locale&);
2565
2566  extern template
2567    bool
2568    has_facet<codecvt<char, char, mbstate_t> >(const locale&);
2569
2570  extern template
2571    bool
2572    has_facet<collate<char> >(const locale&);
2573
2574  extern template
2575    bool
2576    has_facet<numpunct<char> >(const locale&);
2577
2578  extern template
2579    bool
2580    has_facet<num_put<char> >(const locale&);
2581
2582  extern template
2583    bool
2584    has_facet<num_get<char> >(const locale&);
2585
2586  extern template
2587    bool
2588    has_facet<moneypunct<char> >(const locale&);
2589
2590  extern template
2591    bool
2592    has_facet<money_put<char> >(const locale&);
2593
2594  extern template
2595    bool
2596    has_facet<money_get<char> >(const locale&);
2597
2598  extern template
2599    bool
2600    has_facet<__timepunct<char> >(const locale&);
2601
2602  extern template
2603    bool
2604    has_facet<time_put<char> >(const locale&);
2605
2606  extern template
2607    bool
2608    has_facet<time_get<char> >(const locale&);
2609
2610  extern template
2611    bool
2612    has_facet<messages<char> >(const locale&);
2613
2614#ifdef _GLIBCXX_USE_WCHAR_T
2615  extern template class moneypunct<wchar_t, false>;
2616  extern template class moneypunct<wchar_t, true>;
2617  extern template class moneypunct_byname<wchar_t, false>;
2618  extern template class moneypunct_byname<wchar_t, true>;
2619  extern template class money_get<wchar_t>;
2620  extern template class money_put<wchar_t>;
2621  extern template class numpunct<wchar_t>;
2622  extern template class numpunct_byname<wchar_t>;
2623  extern template class num_get<wchar_t>;
2624  extern template class num_put<wchar_t>;
2625  extern template class __timepunct<wchar_t>;
2626  extern template class time_put<wchar_t>;
2627  extern template class time_put_byname<wchar_t>;
2628  extern template class time_get<wchar_t>;
2629  extern template class time_get_byname<wchar_t>;
2630  extern template class messages<wchar_t>;
2631  extern template class messages_byname<wchar_t>;
2632  extern template class ctype_byname<wchar_t>;
2633  extern template class codecvt_byname<wchar_t, char, mbstate_t>;
2634  extern template class collate<wchar_t>;
2635  extern template class collate_byname<wchar_t>;
2636
2637  extern template
2638    const codecvt<wchar_t, char, mbstate_t>&
2639    use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&);
2640
2641  extern template
2642    const collate<wchar_t>&
2643    use_facet<collate<wchar_t> >(const locale&);
2644
2645  extern template
2646    const numpunct<wchar_t>&
2647    use_facet<numpunct<wchar_t> >(const locale&);
2648
2649  extern template
2650    const num_put<wchar_t>&
2651    use_facet<num_put<wchar_t> >(const locale&);
2652
2653  extern template
2654    const num_get<wchar_t>&
2655    use_facet<num_get<wchar_t> >(const locale&);
2656
2657  extern template
2658    const moneypunct<wchar_t, true>&
2659    use_facet<moneypunct<wchar_t, true> >(const locale&);
2660
2661  extern template
2662    const moneypunct<wchar_t, false>&
2663    use_facet<moneypunct<wchar_t, false> >(const locale&);
2664
2665  extern template
2666    const money_put<wchar_t>&
2667    use_facet<money_put<wchar_t> >(const locale&);
2668
2669  extern template
2670    const money_get<wchar_t>&
2671    use_facet<money_get<wchar_t> >(const locale&);
2672
2673  extern template
2674    const __timepunct<wchar_t>&
2675    use_facet<__timepunct<wchar_t> >(const locale&);
2676
2677  extern template
2678    const time_put<wchar_t>&
2679    use_facet<time_put<wchar_t> >(const locale&);
2680
2681  extern template
2682    const time_get<wchar_t>&
2683    use_facet<time_get<wchar_t> >(const locale&);
2684
2685  extern template
2686    const messages<wchar_t>&
2687    use_facet<messages<wchar_t> >(const locale&);
2688
2689 extern template
2690    bool
2691    has_facet<ctype<wchar_t> >(const locale&);
2692
2693  extern template
2694    bool
2695    has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
2696
2697  extern template
2698    bool
2699    has_facet<collate<wchar_t> >(const locale&);
2700
2701  extern template
2702    bool
2703    has_facet<numpunct<wchar_t> >(const locale&);
2704
2705  extern template
2706    bool
2707    has_facet<num_put<wchar_t> >(const locale&);
2708
2709  extern template
2710    bool
2711    has_facet<num_get<wchar_t> >(const locale&);
2712
2713  extern template
2714    bool
2715    has_facet<moneypunct<wchar_t> >(const locale&);
2716
2717  extern template
2718    bool
2719    has_facet<money_put<wchar_t> >(const locale&);
2720
2721  extern template
2722    bool
2723    has_facet<money_get<wchar_t> >(const locale&);
2724
2725  extern template
2726    bool
2727    has_facet<__timepunct<wchar_t> >(const locale&);
2728
2729  extern template
2730    bool
2731    has_facet<time_put<wchar_t> >(const locale&);
2732
2733  extern template
2734    bool
2735    has_facet<time_get<wchar_t> >(const locale&);
2736
2737  extern template
2738    bool
2739    has_facet<messages<wchar_t> >(const locale&);
2740#endif
2741#endif
2742} // namespace std
2743
2744#endif
2745