locale_facets.tcc revision 132720
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          unsigned long __uv = __v;
1155          __s = _M_insert_int(__s, __io, __fill, __uv);
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::showpos
1233					 | ios_base::basefield
1234					 | ios_base::uppercase
1235					 | ios_base::internal);
1236      __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
1237
1238      __s = _M_insert_int(__s, __io, __fill,
1239			  reinterpret_cast<unsigned long>(__v));
1240      __io.flags(__flags);
1241      return __s;
1242    }
1243
1244  template<typename _CharT, typename _InIter>
1245    template<bool _Intl>
1246      _InIter
1247      money_get<_CharT, _InIter>::
1248      _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
1249		 ios_base::iostate& __err, string& __units) const
1250      {
1251	typedef char_traits<_CharT>			  __traits_type;
1252	typedef typename string_type::size_type	          size_type;	
1253	typedef money_base::part			  part;
1254	typedef moneypunct<_CharT, _Intl>		  __moneypunct_type;
1255	typedef typename __moneypunct_type::__cache_type  __cache_type;
1256	
1257	const locale& __loc = __io._M_getloc();
1258	const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1259
1260	__use_cache<__cache_type> __uc;
1261	const __cache_type* __lc = __uc(__loc);
1262	const char_type* __lit = __lc->_M_atoms;
1263
1264	// Deduced sign.
1265	bool __negative = false;
1266	// Sign size.
1267	size_type __sign_size = 0;
1268	// True if sign is mandatory.
1269	const bool __mandatory_sign = (__lc->_M_positive_sign_size
1270				       && __lc->_M_negative_sign_size);
1271	// String of grouping info from thousands_sep plucked from __units.
1272	string __grouping_tmp;
1273	if (__lc->_M_use_grouping)
1274	  __grouping_tmp.reserve(32);
1275	// Last position before the decimal point.
1276	int __last_pos = 0;
1277	// Separator positions, then, possibly, fractional digits.
1278	int __n = 0;
1279	// If input iterator is in a valid state.
1280	bool __testvalid = true;
1281	// Flag marking when a decimal point is found.
1282	bool __testdecfound = false;
1283
1284	// The tentative returned string is stored here.
1285	string __res;
1286	__res.reserve(32);
1287
1288	const char_type* __lit_zero = __lit + money_base::_S_zero;
1289	const char_type* __q;
1290	const money_base::pattern __p = __lc->_M_neg_format;	
1291	for (int __i = 0; __i < 4 && __testvalid; ++__i)
1292	  {
1293	    const part __which = static_cast<part>(__p.field[__i]);
1294	    switch (__which)
1295	      {
1296	      case money_base::symbol:
1297		// According to 22.2.6.1.2, p2, symbol is required
1298		// if (__io.flags() & ios_base::showbase), otherwise
1299		// is optional and consumed only if other characters
1300		// are needed to complete the format.
1301		if (__io.flags() & ios_base::showbase || __sign_size > 1
1302		    || __i == 0
1303		    || (__i == 1 && (__mandatory_sign
1304				     || (static_cast<part>(__p.field[0])
1305					 == money_base::sign)
1306				     || (static_cast<part>(__p.field[2])
1307					 == money_base::space)))
1308		    || (__i == 2 && ((static_cast<part>(__p.field[3])
1309				      == money_base::value)
1310				     || __mandatory_sign
1311				     && (static_cast<part>(__p.field[3])
1312					 == money_base::sign))))
1313		  {
1314		    const size_type __len = __lc->_M_curr_symbol_size;
1315		    size_type __j = 0;
1316		    for (; __beg != __end && __j < __len
1317			   && *__beg == __lc->_M_curr_symbol[__j];
1318			 ++__beg, ++__j);
1319		    if (__j != __len
1320			&& (__j || __io.flags() & ios_base::showbase))
1321		      __testvalid = false;
1322		  }
1323		break;
1324	      case money_base::sign:
1325		// Sign might not exist, or be more than one character long.
1326		if (__lc->_M_positive_sign_size && __beg != __end
1327		    && *__beg == __lc->_M_positive_sign[0])
1328		  {
1329		    __sign_size = __lc->_M_positive_sign_size;
1330		    ++__beg;
1331		  }
1332		else if (__lc->_M_negative_sign_size && __beg != __end
1333			 && *__beg == __lc->_M_negative_sign[0])
1334		  {
1335		    __negative = true;
1336		    __sign_size = __lc->_M_negative_sign_size;
1337		    ++__beg;
1338		  }
1339		else if (__lc->_M_positive_sign_size
1340			 && !__lc->_M_negative_sign_size)
1341		  // "... if no sign is detected, the result is given the sign
1342		  // that corresponds to the source of the empty string"
1343		  __negative = true;
1344		else if (__mandatory_sign)
1345		  __testvalid = false;
1346		break;
1347	      case money_base::value:
1348		// Extract digits, remove and stash away the
1349		// grouping of found thousands separators.
1350		for (; __beg != __end; ++__beg)
1351		  if (__q = __traits_type::find(__lit_zero, 10, *__beg))
1352		    {
1353		      __res += money_base::_S_atoms[__q - __lit];
1354		      ++__n;
1355		    }
1356		  else if (*__beg == __lc->_M_decimal_point && !__testdecfound)
1357		    {
1358		      __last_pos = __n;
1359		      __n = 0;
1360		      __testdecfound = true;
1361		    }
1362		  else if (__lc->_M_use_grouping
1363			   && *__beg == __lc->_M_thousands_sep
1364			   && !__testdecfound)
1365		    {
1366		      if (__n)
1367			{
1368			  // Mark position for later analysis.
1369			  __grouping_tmp += static_cast<char>(__n);
1370			  __n = 0;
1371			}
1372		      else
1373			{
1374			  __testvalid = false;
1375			  break;
1376			}
1377		    }
1378		  else
1379		    break;
1380		if (__res.empty())
1381		  __testvalid = false;
1382		break;
1383	      case money_base::space:
1384		// At least one space is required.
1385		if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
1386		  ++__beg;
1387		else
1388		  __testvalid = false;
1389	      case money_base::none:
1390		// Only if not at the end of the pattern.
1391		if (__i != 3)
1392		  for (; __beg != __end
1393			 && __ctype.is(ctype_base::space, *__beg); ++__beg);
1394		break;
1395	      }
1396	  }
1397
1398	// Need to get the rest of the sign characters, if they exist.
1399	if (__sign_size > 1 && __testvalid)
1400	  {
1401	    const char_type* __sign = __negative ? __lc->_M_negative_sign
1402	                                         : __lc->_M_positive_sign;
1403	    size_type __i = 1;
1404	    for (; __beg != __end && __i < __sign_size
1405		   && *__beg == __sign[__i]; ++__beg, ++__i);
1406	    
1407	    if (__i != __sign_size)
1408	      __testvalid = false;
1409	  }
1410
1411	if (__testvalid)
1412	  {
1413	    // Strip leading zeros.
1414	    if (__res.size() > 1)
1415	      {
1416		const size_type __first = __res.find_first_not_of('0');
1417		const bool __only_zeros = __first == string::npos;
1418		if (__first)
1419		  __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
1420	      }
1421
1422	    // 22.2.6.1.2, p4
1423	    if (__negative && __res[0] != '0')
1424	      __res.insert(__res.begin(), '-');
1425	    
1426	    // Test for grouping fidelity.
1427	    if (__grouping_tmp.size())
1428	      {
1429		// Add the ending grouping.
1430		__grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
1431						                   : __n);
1432		if (!std::__verify_grouping(__lc->_M_grouping,
1433					    __lc->_M_grouping_size,
1434					    __grouping_tmp))
1435		  __testvalid = false;
1436	      }
1437	    
1438	    // Iff not enough digits were supplied after the decimal-point.
1439	    if (__testdecfound && __lc->_M_frac_digits > 0
1440		&& __n != __lc->_M_frac_digits)
1441	      __testvalid = false;
1442	  }
1443	
1444	// Iff no more characters are available.
1445	if (__beg == __end)
1446	  __err |= ios_base::eofbit;
1447	
1448	// Iff valid sequence is not recognized.
1449	if (!__testvalid)
1450	  __err |= ios_base::failbit;
1451	else
1452	  __units.swap(__res);
1453	
1454	return __beg;
1455      }
1456
1457  template<typename _CharT, typename _InIter>
1458    _InIter
1459    money_get<_CharT, _InIter>::
1460    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
1461	   ios_base::iostate& __err, long double& __units) const
1462    {
1463      string __str;
1464      if (__intl)
1465	__beg = _M_extract<true>(__beg, __end, __io, __err, __str);
1466      else
1467	__beg = _M_extract<false>(__beg, __end, __io, __err, __str);
1468      std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
1469      return __beg;
1470    }
1471
1472  template<typename _CharT, typename _InIter>
1473    _InIter
1474    money_get<_CharT, _InIter>::
1475    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
1476	   ios_base::iostate& __err, string_type& __units) const
1477    {
1478      typedef typename string::size_type                  size_type;
1479
1480      const locale& __loc = __io._M_getloc();
1481      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1482
1483      string __str;
1484      const iter_type __ret = __intl ? _M_extract<true>(__beg, __end, __io,
1485							__err, __str)
1486	                             : _M_extract<false>(__beg, __end, __io,
1487							 __err, __str);
1488      const size_type __len = __str.size();
1489      if (__len)
1490	{
1491	  _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1492							       * __len));
1493	  __ctype.widen(__str.data(), __str.data() + __len, __ws);
1494	  __units.assign(__ws, __len);
1495	}
1496
1497      return __ret;
1498    }
1499
1500  template<typename _CharT, typename _OutIter>
1501    template<bool _Intl>
1502      _OutIter
1503      money_put<_CharT, _OutIter>::
1504      _M_insert(iter_type __s, ios_base& __io, char_type __fill,
1505		const string_type& __digits) const
1506      {
1507	typedef typename string_type::size_type	          size_type;
1508	typedef money_base::part                          part;
1509	typedef moneypunct<_CharT, _Intl>                 __moneypunct_type;
1510	typedef typename __moneypunct_type::__cache_type  __cache_type;
1511      
1512	const locale& __loc = __io._M_getloc();
1513	const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1514
1515	__use_cache<__cache_type> __uc;
1516	const __cache_type* __lc = __uc(__loc);
1517	const char_type* __lit = __lc->_M_atoms;
1518
1519	// Determine if negative or positive formats are to be used, and
1520	// discard leading negative_sign if it is present.
1521	const char_type* __beg = __digits.data();
1522
1523	money_base::pattern __p;
1524	const char_type* __sign;
1525	size_type __sign_size;
1526	if (*__beg != __lit[money_base::_S_minus])
1527	  {
1528	    __p = __lc->_M_pos_format;
1529	    __sign = __lc->_M_positive_sign;
1530	    __sign_size = __lc->_M_positive_sign_size;
1531	  }
1532	else
1533	  {
1534	    __p = __lc->_M_neg_format;
1535	    __sign = __lc->_M_negative_sign;
1536	    __sign_size = __lc->_M_negative_sign_size;
1537	    if (__digits.size())
1538	      ++__beg;
1539	  }
1540       
1541	// Look for valid numbers in the ctype facet within input digits.
1542	size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
1543					   __beg + __digits.size()) - __beg;
1544	if (__len)
1545	  {
1546	    // Assume valid input, and attempt to format.
1547	    // Break down input numbers into base components, as follows:
1548	    //   final_value = grouped units + (decimal point) + (digits)
1549	    string_type __value;
1550	    __value.reserve(2 * __len);
1551
1552	    // Add thousands separators to non-decimal digits, per
1553	    // grouping rules.
1554	    int __paddec = __len - __lc->_M_frac_digits;
1555	    if (__paddec > 0)
1556  	      {
1557		if (__lc->_M_frac_digits < 0)
1558		  __paddec = __len;
1559  		if (__lc->_M_grouping_size)
1560  		  {
1561		    _CharT* __ws =
1562  		      static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1563  							    * 2 * __len));
1564  		    _CharT* __ws_end =
1565		      std::__add_grouping(__ws, __lc->_M_thousands_sep,
1566					  __lc->_M_grouping,
1567					  __lc->_M_grouping_size,
1568					  __beg, __beg + __paddec);
1569		    __value.assign(__ws, __ws_end - __ws);
1570  		  }
1571  		else
1572		  __value.assign(__beg, __paddec);
1573	      }
1574
1575	    // Deal with decimal point, decimal digits.
1576	    if (__lc->_M_frac_digits > 0)
1577	      {
1578		__value += __lc->_M_decimal_point;
1579		if (__paddec >= 0)
1580		  __value.append(__beg + __paddec, __lc->_M_frac_digits);
1581		else
1582		  {
1583		    // Have to pad zeros in the decimal position.
1584		    __value.append(-__paddec, __lit[money_base::_S_zero]);
1585		    __value.append(__beg, __len);
1586		  }
1587  	      }
1588  
1589	    // Calculate length of resulting string.
1590	    const ios_base::fmtflags __f = __io.flags() 
1591	                                   & ios_base::adjustfield;
1592	    __len = __value.size() + __sign_size;
1593	    __len += ((__io.flags() & ios_base::showbase)
1594		      ? __lc->_M_curr_symbol_size : 0);
1595
1596	    string_type __res;
1597	    __res.reserve(2 * __len);
1598	    
1599	    const size_type __width = static_cast<size_type>(__io.width());  
1600	    const bool __testipad = (__f == ios_base::internal
1601				     && __len < __width);
1602	    // Fit formatted digits into the required pattern.
1603	    for (int __i = 0; __i < 4; ++__i)
1604	      {
1605		const part __which = static_cast<part>(__p.field[__i]);
1606		switch (__which)
1607		  {
1608		  case money_base::symbol:
1609		    if (__io.flags() & ios_base::showbase)
1610		      __res.append(__lc->_M_curr_symbol,
1611				   __lc->_M_curr_symbol_size);
1612		    break;
1613		  case money_base::sign:
1614		    // Sign might not exist, or be more than one
1615		    // charater long. In that case, add in the rest
1616		    // below.
1617		    if (__sign_size)
1618		      __res += __sign[0];
1619		    break;
1620		  case money_base::value:
1621		    __res += __value;
1622		    break;
1623		  case money_base::space:
1624		    // At least one space is required, but if internal
1625		    // formatting is required, an arbitrary number of
1626		    // fill spaces will be necessary.
1627		    if (__testipad)
1628		      __res.append(__width - __len, __fill);
1629		    else
1630		      __res += __fill;
1631		    break;
1632		  case money_base::none:
1633		    if (__testipad)
1634		      __res.append(__width - __len, __fill);
1635		    break;
1636		  }
1637	      }
1638	    
1639	    // Special case of multi-part sign parts.
1640	    if (__sign_size > 1)
1641	      __res.append(__sign + 1, __sign_size - 1);
1642	    
1643	    // Pad, if still necessary.
1644	    __len = __res.size();
1645	    if (__width > __len)
1646	      {
1647		if (__f == ios_base::left)
1648		  // After.
1649		  __res.append(__width - __len, __fill);
1650		else
1651		  // Before.
1652		  __res.insert(0, __width - __len, __fill);
1653		__len = __width;
1654	      }
1655	    
1656	    // Write resulting, fully-formatted string to output iterator.
1657	    __s = std::__write(__s, __res.data(), __len);
1658	  }
1659	__io.width(0);
1660	return __s;    
1661      }
1662  
1663  template<typename _CharT, typename _OutIter>
1664    _OutIter
1665    money_put<_CharT, _OutIter>::
1666    do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1667	   long double __units) const
1668    {
1669      const locale __loc = __io.getloc();
1670      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1671#ifdef _GLIBCXX_USE_C99
1672      // First try a buffer perhaps big enough.
1673      int __cs_size = 64;
1674      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1675      // _GLIBCXX_RESOLVE_LIB_DEFECTS
1676      // 328. Bad sprintf format modifier in money_put<>::do_put()
1677      int __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units,
1678					_S_get_c_locale());
1679      // If the buffer was not large enough, try again with the correct size.
1680      if (__len >= __cs_size)
1681	{
1682	  __cs_size = __len + 1;
1683	  __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1684	  __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units,
1685					_S_get_c_locale());
1686	}
1687#else
1688      // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
1689      const int __cs_size = numeric_limits<long double>::max_exponent10 + 3;
1690      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1691      int __len = std::__convert_from_v(__cs, 0, "%.0Lf", __units,
1692					_S_get_c_locale());
1693#endif
1694      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1695							   * __cs_size));
1696      __ctype.widen(__cs, __cs + __len, __ws);
1697      const string_type __digits(__ws, __len);
1698      return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
1699	            : _M_insert<false>(__s, __io, __fill, __digits);
1700    }
1701
1702  template<typename _CharT, typename _OutIter>
1703    _OutIter
1704    money_put<_CharT, _OutIter>::
1705    do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1706	   const string_type& __digits) const
1707    { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
1708	            : _M_insert<false>(__s, __io, __fill, __digits); }
1709
1710
1711  // NB: Not especially useful. Without an ios_base object or some
1712  // kind of locale reference, we are left clawing at the air where
1713  // the side of the mountain used to be...
1714  template<typename _CharT, typename _InIter>
1715    time_base::dateorder
1716    time_get<_CharT, _InIter>::do_date_order() const
1717    { return time_base::no_order; }
1718
1719  // Expand a strftime format string and parse it.  E.g., do_get_date() may
1720  // pass %m/%d/%Y => extracted characters.
1721  template<typename _CharT, typename _InIter>
1722    _InIter
1723    time_get<_CharT, _InIter>::
1724    _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
1725			  ios_base::iostate& __err, tm* __tm,
1726			  const _CharT* __format) const
1727    {
1728      const locale& __loc = __io._M_getloc();
1729      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1730      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1731      const size_t __len = char_traits<_CharT>::length(__format);
1732
1733      for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
1734	{
1735	  if (__ctype.narrow(__format[__i], 0) == '%')
1736	    {
1737	      // Verify valid formatting code, attempt to extract.
1738	      char __c = __ctype.narrow(__format[++__i], 0);
1739	      int __mem = 0;
1740	      if (__c == 'E' || __c == 'O')
1741		__c = __ctype.narrow(__format[++__i], 0);
1742	      switch (__c)
1743		{
1744		  const char* __cs;
1745		  _CharT __wcs[10];
1746		case 'a':
1747		  // Abbreviated weekday name [tm_wday]
1748		  const char_type*  __days1[7];
1749		  __tp._M_days_abbreviated(__days1);
1750		  __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
1751					  7, __io, __err);
1752		  break;
1753		case 'A':
1754		  // Weekday name [tm_wday].
1755		  const char_type*  __days2[7];
1756		  __tp._M_days(__days2);
1757		  __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
1758					  7, __io, __err);
1759		  break;
1760		case 'h':
1761		case 'b':
1762		  // Abbreviated month name [tm_mon]
1763		  const char_type*  __months1[12];
1764		  __tp._M_months_abbreviated(__months1);
1765		  __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
1766					  __months1, 12, __io, __err);
1767		  break;
1768		case 'B':
1769		  // Month name [tm_mon].
1770		  const char_type*  __months2[12];
1771		  __tp._M_months(__months2);
1772		  __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
1773					  __months2, 12, __io, __err);
1774		  break;
1775		case 'c':
1776		  // Default time and date representation.
1777		  const char_type*  __dt[2];
1778		  __tp._M_date_time_formats(__dt);
1779		  __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1780						__tm, __dt[0]);
1781		  break;
1782		case 'd':
1783		  // Day [01, 31]. [tm_mday]
1784		  __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
1785					 __io, __err);
1786		  break;
1787		case 'e':
1788		  // Day [1, 31], with single digits preceded by
1789		  // space. [tm_mday]
1790		  if (__ctype.is(ctype_base::space, *__beg))
1791		    __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
1792					   1, __io, __err);
1793		  else
1794		    __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
1795					   2, __io, __err);
1796		  break;
1797		case 'D':
1798		  // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
1799		  __cs = "%m/%d/%y";
1800		  __ctype.widen(__cs, __cs + 9, __wcs);
1801		  __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1802						__tm, __wcs);
1803		  break;
1804		case 'H':
1805		  // Hour [00, 23]. [tm_hour]
1806		  __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
1807					 __io, __err);
1808		  break;
1809		case 'I':
1810		  // Hour [01, 12]. [tm_hour]
1811		  __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
1812					 __io, __err);
1813		  break;
1814		case 'm':
1815		  // Month [01, 12]. [tm_mon]
1816		  __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 
1817					 __io, __err);
1818		  if (!__err)
1819		    __tm->tm_mon = __mem - 1;
1820		  break;
1821		case 'M':
1822		  // Minute [00, 59]. [tm_min]
1823		  __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
1824					 __io, __err);
1825		  break;
1826		case 'n':
1827		  if (__ctype.narrow(*__beg, 0) == '\n')
1828		    ++__beg;
1829		  else
1830		    __err |= ios_base::failbit;
1831		  break;
1832		case 'R':
1833		  // Equivalent to (%H:%M).
1834		  __cs = "%H:%M";
1835		  __ctype.widen(__cs, __cs + 6, __wcs);
1836		  __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1837						__tm, __wcs);
1838		  break;
1839		case 'S':
1840		  // Seconds.
1841		  __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2,
1842					 __io, __err);
1843		  break;
1844		case 't':
1845		  if (__ctype.narrow(*__beg, 0) == '\t')
1846		    ++__beg;
1847		  else
1848		    __err |= ios_base::failbit;
1849		  break;
1850		case 'T':
1851		  // Equivalent to (%H:%M:%S).
1852		  __cs = "%H:%M:%S";
1853		  __ctype.widen(__cs, __cs + 9, __wcs);
1854		  __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1855						__tm, __wcs);
1856		  break;
1857		case 'x':
1858		  // Locale's date.
1859		  const char_type*  __dates[2];
1860		  __tp._M_date_formats(__dates);
1861		  __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1862						__tm, __dates[0]);
1863		  break;
1864		case 'X':
1865		  // Locale's time.
1866		  const char_type*  __times[2];
1867		  __tp._M_time_formats(__times);
1868		  __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1869						__tm, __times[0]);
1870		  break;
1871		case 'y':
1872		case 'C': // C99
1873		  // Two digit year. [tm_year]
1874		  __beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
1875					 __io, __err);
1876		  break;
1877		case 'Y':
1878		  // Year [1900). [tm_year]
1879		  __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
1880					 __io, __err);
1881		  if (!__err)
1882		    __tm->tm_year = __mem - 1900;
1883		  break;
1884		case 'Z':
1885		  // Timezone info.
1886		  if (__ctype.is(ctype_base::upper, *__beg))
1887		    {
1888		      int __tmp;
1889		      __beg = _M_extract_name(__beg, __end, __tmp,
1890				       __timepunct_cache<_CharT>::_S_timezones,
1891					      14, __io, __err);
1892
1893		      // GMT requires special effort.
1894		      if (__beg != __end && !__err && __tmp == 0
1895			  && (*__beg == __ctype.widen('-')
1896			      || *__beg == __ctype.widen('+')))
1897			{
1898			  __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
1899						 __io, __err);
1900			  __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
1901						 __io, __err);
1902			}
1903		    }
1904		  else
1905		    __err |= ios_base::failbit;
1906		  break;
1907		default:
1908		  // Not recognized.
1909		  __err |= ios_base::failbit;
1910		}
1911	    }
1912	  else
1913	    {
1914	      // Verify format and input match, extract and discard.
1915	      if (__format[__i] == *__beg)
1916		++__beg;
1917	      else
1918		__err |= ios_base::failbit;
1919	    }
1920	}
1921      return __beg;
1922    }
1923
1924  template<typename _CharT, typename _InIter>
1925    _InIter
1926    time_get<_CharT, _InIter>::
1927    _M_extract_num(iter_type __beg, iter_type __end, int& __member,
1928		   int __min, int __max, size_t __len,
1929		   ios_base& __io, ios_base::iostate& __err) const
1930    {
1931      const locale& __loc = __io._M_getloc();
1932      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1933
1934      // As-is works for __len = 1, 2, 4, the values actually used.
1935      int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
1936
1937      ++__min;
1938      size_t __i = 0;
1939      int __value = 0;
1940      for (; __beg != __end && __i < __len; ++__beg, ++__i)
1941	{
1942	  const char __c = __ctype.narrow(*__beg, '*');
1943	  if (__c >= '0' && __c <= '9')
1944	    {
1945	      __value = __value * 10 + (__c - '0');
1946	      const int __valuec = __value * __mult;
1947	      if (__valuec > __max || __valuec + __mult < __min)
1948		break;
1949	      __mult /= 10;
1950	    }
1951	  else
1952	    break;
1953	}
1954      if (__i == __len)
1955	__member = __value;
1956      else
1957	__err |= ios_base::failbit;
1958      return __beg;
1959    }
1960
1961  // Assumptions:
1962  // All elements in __names are unique.
1963  template<typename _CharT, typename _InIter>
1964    _InIter
1965    time_get<_CharT, _InIter>::
1966    _M_extract_name(iter_type __beg, iter_type __end, int& __member,
1967		    const _CharT** __names, size_t __indexlen,
1968		    ios_base& __io, ios_base::iostate& __err) const
1969    {
1970      typedef char_traits<_CharT>		__traits_type;
1971      const locale& __loc = __io._M_getloc();
1972      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1973
1974      int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
1975							  * __indexlen));
1976      size_t __nmatches = 0;
1977      size_t __pos = 0;
1978      bool __testvalid = true;
1979      const char_type* __name;
1980
1981      // Look for initial matches.
1982      // NB: Some of the locale data is in the form of all lowercase
1983      // names, and some is in the form of initially-capitalized
1984      // names. Look for both.
1985      if (__beg != __end)
1986	{
1987	  const char_type __c = *__beg;
1988	  for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
1989	    if (__c == __names[__i1][0]
1990		|| __c == __ctype.toupper(__names[__i1][0]))
1991	      __matches[__nmatches++] = __i1;
1992	}
1993
1994      while (__nmatches > 1)
1995	{
1996	  // Find smallest matching string.
1997	  size_t __minlen = __traits_type::length(__names[__matches[0]]);
1998	  for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
1999	    __minlen = std::min(__minlen,
2000			      __traits_type::length(__names[__matches[__i2]]));
2001	  ++__pos;
2002	  ++__beg;
2003	  if (__pos < __minlen && __beg != __end)
2004	    for (size_t __i3 = 0; __i3 < __nmatches;)
2005	      {
2006		__name = __names[__matches[__i3]];
2007		if (__name[__pos] != *__beg)
2008		  __matches[__i3] = __matches[--__nmatches];
2009		else
2010		  ++__i3;
2011	      }
2012	  else
2013	    break;
2014	}
2015
2016      if (__nmatches == 1)
2017	{
2018	  // Make sure found name is completely extracted.
2019	  ++__pos;
2020	  ++__beg;
2021	  __name = __names[__matches[0]];
2022	  const size_t __len = __traits_type::length(__name);
2023	  while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
2024	    ++__beg, ++__pos;
2025
2026	  if (__len == __pos)
2027	    __member = __matches[0];
2028	  else
2029	    __testvalid = false;
2030	}
2031      else
2032	__testvalid = false;
2033      if (!__testvalid)
2034	__err |= ios_base::failbit;
2035      return __beg;
2036    }
2037
2038  template<typename _CharT, typename _InIter>
2039    _InIter
2040    time_get<_CharT, _InIter>::
2041    do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
2042		ios_base::iostate& __err, tm* __tm) const
2043    {
2044      const locale& __loc = __io._M_getloc();
2045      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
2046      const char_type*  __times[2];
2047      __tp._M_time_formats(__times);
2048      __beg = _M_extract_via_format(__beg, __end, __io, __err, 
2049				    __tm, __times[0]);
2050      if (__beg == __end)
2051	__err |= ios_base::eofbit;
2052      return __beg;
2053    }
2054
2055  template<typename _CharT, typename _InIter>
2056    _InIter
2057    time_get<_CharT, _InIter>::
2058    do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
2059		ios_base::iostate& __err, tm* __tm) const
2060    {
2061      const locale& __loc = __io._M_getloc();
2062      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
2063      const char_type*  __dates[2];
2064      __tp._M_date_formats(__dates);
2065      __beg = _M_extract_via_format(__beg, __end, __io, __err,
2066				    __tm, __dates[0]);
2067      if (__beg == __end)
2068	__err |= ios_base::eofbit;
2069      return __beg;
2070    }
2071
2072  template<typename _CharT, typename _InIter>
2073    _InIter
2074    time_get<_CharT, _InIter>::
2075    do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
2076		   ios_base::iostate& __err, tm* __tm) const
2077    {
2078      typedef char_traits<_CharT>		__traits_type;
2079      const locale& __loc = __io._M_getloc();
2080      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
2081      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2082      const char_type*  __days[7];
2083      __tp._M_days_abbreviated(__days);
2084      int __tmpwday;
2085      __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7, __io, __err);
2086
2087      // Check to see if non-abbreviated name exists, and extract.
2088      // NB: Assumes both _M_days and _M_days_abbreviated organized in
2089      // exact same order, first to last, such that the resulting
2090      // __days array with the same index points to a day, and that
2091      // day's abbreviated form.
2092      // NB: Also assumes that an abbreviated name is a subset of the name.
2093      if (!__err)
2094	{
2095	  size_t __pos = __traits_type::length(__days[__tmpwday]);
2096	  __tp._M_days(__days);
2097	  const char_type* __name = __days[__tmpwday];
2098	  if (__name[__pos] == *__beg)
2099	    {
2100	      // Extract the rest of it.
2101	      const size_t __len = __traits_type::length(__name);
2102	      while (__pos < __len && __beg != __end
2103		     && __name[__pos] == *__beg)
2104		++__beg, ++__pos;
2105	      if (__len != __pos)
2106		__err |= ios_base::failbit;
2107	    }
2108	  if (!__err)
2109	    __tm->tm_wday = __tmpwday;
2110	}
2111      if (__beg == __end)
2112	__err |= ios_base::eofbit;
2113      return __beg;
2114     }
2115
2116  template<typename _CharT, typename _InIter>
2117    _InIter
2118    time_get<_CharT, _InIter>::
2119    do_get_monthname(iter_type __beg, iter_type __end,
2120                     ios_base& __io, ios_base::iostate& __err, tm* __tm) const
2121    {
2122      typedef char_traits<_CharT>		__traits_type;
2123      const locale& __loc = __io._M_getloc();
2124      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
2125      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2126      const char_type*  __months[12];
2127      __tp._M_months_abbreviated(__months);
2128      int __tmpmon;
2129      __beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12, 
2130			      __io, __err);
2131
2132      // Check to see if non-abbreviated name exists, and extract.
2133      // NB: Assumes both _M_months and _M_months_abbreviated organized in
2134      // exact same order, first to last, such that the resulting
2135      // __months array with the same index points to a month, and that
2136      // month's abbreviated form.
2137      // NB: Also assumes that an abbreviated name is a subset of the name.
2138      if (!__err)
2139	{
2140	  size_t __pos = __traits_type::length(__months[__tmpmon]);
2141	  __tp._M_months(__months);
2142	  const char_type* __name = __months[__tmpmon];
2143	  if (__name[__pos] == *__beg)
2144	    {
2145	      // Extract the rest of it.
2146	      const size_t __len = __traits_type::length(__name);
2147	      while (__pos < __len && __beg != __end
2148		     && __name[__pos] == *__beg)
2149		++__beg, ++__pos;
2150	      if (__len != __pos)
2151		__err |= ios_base::failbit;
2152	    }
2153	  if (!__err)
2154	    __tm->tm_mon = __tmpmon;
2155	}
2156
2157      if (__beg == __end)
2158	__err |= ios_base::eofbit;
2159      return __beg;
2160    }
2161
2162  template<typename _CharT, typename _InIter>
2163    _InIter
2164    time_get<_CharT, _InIter>::
2165    do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
2166		ios_base::iostate& __err, tm* __tm) const
2167    {
2168      const locale& __loc = __io._M_getloc();
2169      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2170
2171      size_t __i = 0;
2172      int __value = 0;
2173      for (; __beg != __end && __i < 4; ++__beg, ++__i)
2174	{
2175	  const char __c = __ctype.narrow(*__beg, '*');
2176	  if (__c >= '0' && __c <= '9')
2177	    __value = __value * 10 + (__c - '0');
2178	  else
2179	    break;
2180	}
2181      if (__i == 2 || __i == 4)
2182	__tm->tm_year = __i == 2 ? __value : __value - 1900;
2183      else
2184	__err |= ios_base::failbit;
2185      if (__beg == __end)
2186	__err |= ios_base::eofbit;
2187      return __beg;
2188    }
2189
2190  template<typename _CharT, typename _OutIter>
2191    _OutIter
2192    time_put<_CharT, _OutIter>::
2193    put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
2194	const _CharT* __beg, const _CharT* __end) const
2195    {
2196      const locale& __loc = __io._M_getloc();
2197      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
2198      for (; __beg != __end; ++__beg)
2199	if (__ctype.narrow(*__beg, 0) != '%')
2200	  {
2201	    *__s = *__beg;
2202	    ++__s;
2203	  }
2204	else if (++__beg != __end)
2205	  {
2206	    char __format;
2207	    char __mod = 0;
2208	    const char __c = __ctype.narrow(*__beg, 0);
2209	    if (__c != 'E' && __c != 'O')
2210	      __format = __c;
2211	    else if (++__beg != __end)
2212	      {
2213		__mod = __c;
2214		__format = __ctype.narrow(*__beg, 0);
2215	      }
2216	    else
2217	      break;
2218	    __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
2219	  }
2220	else
2221	  break;
2222      return __s;
2223    }
2224
2225  template<typename _CharT, typename _OutIter>
2226    _OutIter
2227    time_put<_CharT, _OutIter>::
2228    do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
2229	   char __format, char __mod) const
2230    {
2231      const locale& __loc = __io._M_getloc();
2232      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
2233      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
2234
2235      // NB: This size is arbitrary. Should this be a data member,
2236      // initialized at construction?
2237      const size_t __maxlen = 64;
2238      char_type* __res = 
2239       static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
2240
2241      // NB: In IEE 1003.1-200x, and perhaps other locale models, it
2242      // is possible that the format character will be longer than one
2243      // character. Possibilities include 'E' or 'O' followed by a
2244      // format character: if __mod is not the default argument, assume
2245      // it's a valid modifier.
2246      char_type __fmt[4];
2247      __fmt[0] = __ctype.widen('%');
2248      if (!__mod)
2249	{
2250	  __fmt[1] = __format;
2251	  __fmt[2] = char_type();
2252	}
2253      else
2254	{
2255	  __fmt[1] = __mod;
2256	  __fmt[2] = __format;
2257	  __fmt[3] = char_type();
2258	}
2259
2260      __tp._M_put(__res, __maxlen, __fmt, __tm);
2261
2262      // Write resulting, fully-formatted string to output iterator.
2263      return std::__write(__s, __res, char_traits<char_type>::length(__res));
2264    }
2265
2266
2267  // Generic version does nothing.
2268  template<typename _CharT>
2269    int
2270    collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const
2271    { return 0; }
2272
2273  // Generic version does nothing.
2274  template<typename _CharT>
2275    size_t
2276    collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const
2277    { return 0; }
2278
2279  template<typename _CharT>
2280    int
2281    collate<_CharT>::
2282    do_compare(const _CharT* __lo1, const _CharT* __hi1,
2283	       const _CharT* __lo2, const _CharT* __hi2) const
2284    {
2285      // strcoll assumes zero-terminated strings so we make a copy
2286      // and then put a zero at the end.
2287      const string_type __one(__lo1, __hi1);
2288      const string_type __two(__lo2, __hi2);
2289
2290      const _CharT* __p = __one.c_str();
2291      const _CharT* __pend = __one.data() + __one.length();
2292      const _CharT* __q = __two.c_str();
2293      const _CharT* __qend = __two.data() + __two.length();
2294
2295      // strcoll stops when it sees a nul character so we break
2296      // the strings into zero-terminated substrings and pass those
2297      // to strcoll.
2298      for (;;)
2299	{
2300	  const int __res = _M_compare(__p, __q);
2301	  if (__res)
2302	    return __res;
2303
2304	  __p += char_traits<_CharT>::length(__p);
2305	  __q += char_traits<_CharT>::length(__q);
2306	  if (__p == __pend && __q == __qend)
2307	    return 0;
2308	  else if (__p == __pend)
2309	    return -1;
2310	  else if (__q == __qend)
2311	    return 1;
2312
2313	  __p++;
2314	  __q++;
2315	}
2316    }
2317
2318  template<typename _CharT>
2319    typename collate<_CharT>::string_type
2320    collate<_CharT>::
2321    do_transform(const _CharT* __lo, const _CharT* __hi) const
2322    {
2323      // strxfrm assumes zero-terminated strings so we make a copy
2324      string_type __str(__lo, __hi);
2325
2326      const _CharT* __p = __str.c_str();
2327      const _CharT* __pend = __str.data() + __str.length();
2328
2329      size_t __len = (__hi - __lo) * 2;
2330
2331      string_type __ret;
2332
2333      // strxfrm stops when it sees a nul character so we break
2334      // the string into zero-terminated substrings and pass those
2335      // to strxfrm.
2336      for (;;)
2337	{
2338	  // First try a buffer perhaps big enough.
2339	  _CharT* __c =
2340	    static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
2341	  size_t __res = _M_transform(__c, __p, __len);
2342	  // If the buffer was not large enough, try again with the
2343	  // correct size.
2344	  if (__res >= __len)
2345	    {
2346	      __len = __res + 1;
2347	      __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
2348							  * __len));
2349	      __res = _M_transform(__c, __p, __res + 1);
2350	    }
2351
2352	  __ret.append(__c, __res);
2353	  __p += char_traits<_CharT>::length(__p);
2354	  if (__p == __pend)
2355	    return __ret;
2356
2357	  __p++;
2358	  __ret.push_back(_CharT());
2359	}
2360    }
2361
2362  template<typename _CharT>
2363    long
2364    collate<_CharT>::
2365    do_hash(const _CharT* __lo, const _CharT* __hi) const
2366    {
2367      unsigned long __val = 0;
2368      for (; __lo < __hi; ++__lo)
2369	__val = *__lo + ((__val << 7) |
2370		       (__val >> (numeric_limits<unsigned long>::digits - 7)));
2371      return static_cast<long>(__val);
2372    }
2373
2374  // Construct correctly padded string, as per 22.2.2.2.2
2375  // Assumes
2376  // __newlen > __oldlen
2377  // __news is allocated for __newlen size
2378  // Used by both num_put and ostream inserters: if __num,
2379  // internal-adjusted objects are padded according to the rules below
2380  // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
2381  // ones are.
2382
2383  // NB: Of the two parameters, _CharT can be deduced from the
2384  // function arguments. The other (_Traits) has to be explicitly specified.
2385  template<typename _CharT, typename _Traits>
2386    void
2387    __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill,
2388				   _CharT* __news, const _CharT* __olds,
2389				   const streamsize __newlen,
2390				   const streamsize __oldlen, const bool __num)
2391    {
2392      const size_t __plen = static_cast<size_t>(__newlen - __oldlen);
2393      const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
2394
2395      // Padding last.
2396      if (__adjust == ios_base::left)
2397	{
2398	  _Traits::copy(__news, const_cast<_CharT*>(__olds), __oldlen);
2399	  _Traits::assign(__news + __oldlen, __plen, __fill);
2400	  return;
2401	}
2402
2403      size_t __mod = 0;
2404      if (__adjust == ios_base::internal && __num)
2405	{
2406	  // Pad after the sign, if there is one.
2407	  // Pad after 0[xX], if there is one.
2408	  // Who came up with these rules, anyway? Jeeze.
2409          const locale& __loc = __io._M_getloc();
2410	  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2411
2412	  const bool __testsign = (__ctype.widen('-') == __olds[0]
2413				   || __ctype.widen('+') == __olds[0]);
2414	  const bool __testhex = (__ctype.widen('0') == __olds[0]
2415				  && __oldlen > 1
2416				  && (__ctype.widen('x') == __olds[1]
2417				      || __ctype.widen('X') == __olds[1]));
2418	  if (__testhex)
2419	    {
2420	      __news[0] = __olds[0];
2421	      __news[1] = __olds[1];
2422	      __mod = 2;
2423	      __news += 2;
2424	    }
2425	  else if (__testsign)
2426	    {
2427	      __news[0] = __olds[0];
2428	      __mod = 1;
2429	      ++__news;
2430	    }
2431	  // else Padding first.
2432	}
2433      _Traits::assign(__news, __plen, __fill);
2434      _Traits::copy(__news + __plen, const_cast<_CharT*>(__olds + __mod),
2435		    __oldlen - __mod);
2436    }
2437
2438  bool
2439  __verify_grouping(const char* __grouping, size_t __grouping_size,
2440		    const string& __grouping_tmp)
2441  {
2442    const size_t __n = __grouping_tmp.size() - 1;
2443    const size_t __min = std::min(__n, __grouping_size - 1);
2444    size_t __i = __n;
2445    bool __test = true;
2446    
2447    // Parsed number groupings have to match the
2448    // numpunct::grouping string exactly, starting at the
2449    // right-most point of the parsed sequence of elements ...
2450    for (size_t __j = 0; __j < __min && __test; --__i, ++__j)
2451      __test = __grouping_tmp[__i] == __grouping[__j];
2452    for (; __i && __test; --__i)
2453      __test = __grouping_tmp[__i] == __grouping[__min];
2454    // ... but the last parsed grouping can be <= numpunct
2455    // grouping.
2456    __test &= __grouping_tmp[0] <= __grouping[__min];
2457    return __test;
2458  }
2459
2460  template<typename _CharT>
2461    _CharT*
2462    __add_grouping(_CharT* __s, _CharT __sep,
2463		   const char* __gbeg, size_t __gsize,
2464		   const _CharT* __first, const _CharT* __last)
2465    {
2466      if (__last - __first > *__gbeg)
2467	{
2468	  const bool __bump = __gsize != 1;
2469	  __s = std::__add_grouping(__s,  __sep, __gbeg + __bump,
2470				    __gsize - __bump, __first,
2471				    __last - *__gbeg);
2472	  __first = __last - *__gbeg;
2473	  *__s++ = __sep;
2474	}
2475      do
2476	*__s++ = *__first++;
2477      while (__first != __last);
2478      return __s;
2479    }
2480
2481  // Inhibit implicit instantiations for required instantiations,
2482  // which are defined via explicit instantiations elsewhere.
2483  // NB: This syntax is a GNU extension.
2484#if _GLIBCXX_EXTERN_TEMPLATE
2485  extern template class moneypunct<char, false>;
2486  extern template class moneypunct<char, true>;
2487  extern template class moneypunct_byname<char, false>;
2488  extern template class moneypunct_byname<char, true>;
2489  extern template class money_get<char>;
2490  extern template class money_put<char>;
2491  extern template class numpunct<char>;
2492  extern template class numpunct_byname<char>;
2493  extern template class num_get<char>;
2494  extern template class num_put<char>;
2495  extern template class __timepunct<char>;
2496  extern template class time_put<char>;
2497  extern template class time_put_byname<char>;
2498  extern template class time_get<char>;
2499  extern template class time_get_byname<char>;
2500  extern template class messages<char>;
2501  extern template class messages_byname<char>;
2502  extern template class ctype_byname<char>;
2503  extern template class codecvt_byname<char, char, mbstate_t>;
2504  extern template class collate<char>;
2505  extern template class collate_byname<char>;
2506
2507  extern template
2508    const codecvt<char, char, mbstate_t>&
2509    use_facet<codecvt<char, char, mbstate_t> >(const locale&);
2510
2511  extern template
2512    const collate<char>&
2513    use_facet<collate<char> >(const locale&);
2514
2515  extern template
2516    const numpunct<char>&
2517    use_facet<numpunct<char> >(const locale&);
2518
2519  extern template
2520    const num_put<char>&
2521    use_facet<num_put<char> >(const locale&);
2522
2523  extern template
2524    const num_get<char>&
2525    use_facet<num_get<char> >(const locale&);
2526
2527  extern template
2528    const moneypunct<char, true>&
2529    use_facet<moneypunct<char, true> >(const locale&);
2530
2531  extern template
2532    const moneypunct<char, false>&
2533    use_facet<moneypunct<char, false> >(const locale&);
2534
2535  extern template
2536    const money_put<char>&
2537    use_facet<money_put<char> >(const locale&);
2538
2539  extern template
2540    const money_get<char>&
2541    use_facet<money_get<char> >(const locale&);
2542
2543  extern template
2544    const __timepunct<char>&
2545    use_facet<__timepunct<char> >(const locale&);
2546
2547  extern template
2548    const time_put<char>&
2549    use_facet<time_put<char> >(const locale&);
2550
2551  extern template
2552    const time_get<char>&
2553    use_facet<time_get<char> >(const locale&);
2554
2555  extern template
2556    const messages<char>&
2557    use_facet<messages<char> >(const locale&);
2558
2559  extern template
2560    bool
2561    has_facet<ctype<char> >(const locale&);
2562
2563  extern template
2564    bool
2565    has_facet<codecvt<char, char, mbstate_t> >(const locale&);
2566
2567  extern template
2568    bool
2569    has_facet<collate<char> >(const locale&);
2570
2571  extern template
2572    bool
2573    has_facet<numpunct<char> >(const locale&);
2574
2575  extern template
2576    bool
2577    has_facet<num_put<char> >(const locale&);
2578
2579  extern template
2580    bool
2581    has_facet<num_get<char> >(const locale&);
2582
2583  extern template
2584    bool
2585    has_facet<moneypunct<char> >(const locale&);
2586
2587  extern template
2588    bool
2589    has_facet<money_put<char> >(const locale&);
2590
2591  extern template
2592    bool
2593    has_facet<money_get<char> >(const locale&);
2594
2595  extern template
2596    bool
2597    has_facet<__timepunct<char> >(const locale&);
2598
2599  extern template
2600    bool
2601    has_facet<time_put<char> >(const locale&);
2602
2603  extern template
2604    bool
2605    has_facet<time_get<char> >(const locale&);
2606
2607  extern template
2608    bool
2609    has_facet<messages<char> >(const locale&);
2610
2611#ifdef _GLIBCXX_USE_WCHAR_T
2612  extern template class moneypunct<wchar_t, false>;
2613  extern template class moneypunct<wchar_t, true>;
2614  extern template class moneypunct_byname<wchar_t, false>;
2615  extern template class moneypunct_byname<wchar_t, true>;
2616  extern template class money_get<wchar_t>;
2617  extern template class money_put<wchar_t>;
2618  extern template class numpunct<wchar_t>;
2619  extern template class numpunct_byname<wchar_t>;
2620  extern template class num_get<wchar_t>;
2621  extern template class num_put<wchar_t>;
2622  extern template class __timepunct<wchar_t>;
2623  extern template class time_put<wchar_t>;
2624  extern template class time_put_byname<wchar_t>;
2625  extern template class time_get<wchar_t>;
2626  extern template class time_get_byname<wchar_t>;
2627  extern template class messages<wchar_t>;
2628  extern template class messages_byname<wchar_t>;
2629  extern template class ctype_byname<wchar_t>;
2630  extern template class codecvt_byname<wchar_t, char, mbstate_t>;
2631  extern template class collate<wchar_t>;
2632  extern template class collate_byname<wchar_t>;
2633
2634  extern template
2635    const codecvt<wchar_t, char, mbstate_t>&
2636    use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&);
2637
2638  extern template
2639    const collate<wchar_t>&
2640    use_facet<collate<wchar_t> >(const locale&);
2641
2642  extern template
2643    const numpunct<wchar_t>&
2644    use_facet<numpunct<wchar_t> >(const locale&);
2645
2646  extern template
2647    const num_put<wchar_t>&
2648    use_facet<num_put<wchar_t> >(const locale&);
2649
2650  extern template
2651    const num_get<wchar_t>&
2652    use_facet<num_get<wchar_t> >(const locale&);
2653
2654  extern template
2655    const moneypunct<wchar_t, true>&
2656    use_facet<moneypunct<wchar_t, true> >(const locale&);
2657
2658  extern template
2659    const moneypunct<wchar_t, false>&
2660    use_facet<moneypunct<wchar_t, false> >(const locale&);
2661
2662  extern template
2663    const money_put<wchar_t>&
2664    use_facet<money_put<wchar_t> >(const locale&);
2665
2666  extern template
2667    const money_get<wchar_t>&
2668    use_facet<money_get<wchar_t> >(const locale&);
2669
2670  extern template
2671    const __timepunct<wchar_t>&
2672    use_facet<__timepunct<wchar_t> >(const locale&);
2673
2674  extern template
2675    const time_put<wchar_t>&
2676    use_facet<time_put<wchar_t> >(const locale&);
2677
2678  extern template
2679    const time_get<wchar_t>&
2680    use_facet<time_get<wchar_t> >(const locale&);
2681
2682  extern template
2683    const messages<wchar_t>&
2684    use_facet<messages<wchar_t> >(const locale&);
2685
2686 extern template
2687    bool
2688    has_facet<ctype<wchar_t> >(const locale&);
2689
2690  extern template
2691    bool
2692    has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
2693
2694  extern template
2695    bool
2696    has_facet<collate<wchar_t> >(const locale&);
2697
2698  extern template
2699    bool
2700    has_facet<numpunct<wchar_t> >(const locale&);
2701
2702  extern template
2703    bool
2704    has_facet<num_put<wchar_t> >(const locale&);
2705
2706  extern template
2707    bool
2708    has_facet<num_get<wchar_t> >(const locale&);
2709
2710  extern template
2711    bool
2712    has_facet<moneypunct<wchar_t> >(const locale&);
2713
2714  extern template
2715    bool
2716    has_facet<money_put<wchar_t> >(const locale&);
2717
2718  extern template
2719    bool
2720    has_facet<money_get<wchar_t> >(const locale&);
2721
2722  extern template
2723    bool
2724    has_facet<__timepunct<wchar_t> >(const locale&);
2725
2726  extern template
2727    bool
2728    has_facet<time_put<wchar_t> >(const locale&);
2729
2730  extern template
2731    bool
2732    has_facet<time_get<wchar_t> >(const locale&);
2733
2734  extern template
2735    bool
2736    has_facet<messages<wchar_t> >(const locale&);
2737#endif
2738#endif
2739} // namespace std
2740
2741#endif
2742