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