locale_facets.tcc revision 117397
11590Srgrimes// Locale support -*- C++ -*-
21590Srgrimes
31590Srgrimes// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
41590Srgrimes// Free Software Foundation, Inc.
51590Srgrimes//
61590Srgrimes// This file is part of the GNU ISO C++ Library.  This library is free
71590Srgrimes// software; you can redistribute it and/or modify it under the
81590Srgrimes// terms of the GNU General Public License as published by the
91590Srgrimes// Free Software Foundation; either version 2, or (at your option)
101590Srgrimes// any later version.
111590Srgrimes
121590Srgrimes// This library is distributed in the hope that it will be useful,
131590Srgrimes// but WITHOUT ANY WARRANTY; without even the implied warranty of
141590Srgrimes// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
151590Srgrimes// GNU General Public License for more details.
161590Srgrimes
171590Srgrimes// You should have received a copy of the GNU General Public License along
181590Srgrimes// with this library; see the file COPYING.  If not, write to the Free
191590Srgrimes// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
201590Srgrimes// USA.
211590Srgrimes
221590Srgrimes// As a special exception, you may use this file as part of a free software
231590Srgrimes// library without restriction.  Specifically, if other files instantiate
241590Srgrimes// templates or use macros or inline functions from this file, or you compile
251590Srgrimes// this file and link it with other files to produce an executable, this
261590Srgrimes// file does not by itself cause the resulting executable to be covered by
271590Srgrimes// the GNU General Public License.  This exception does not however
281590Srgrimes// invalidate any other reasons why the executable file might be covered by
291590Srgrimes// the GNU General Public License.
301590Srgrimes
311590Srgrimes// Warning: this file is not meant for user inclusion. Use <locale>.
321590Srgrimes
331590Srgrimes#ifndef _CPP_BITS_LOCFACETS_TCC
3423246Swosch#define _CPP_BITS_LOCFACETS_TCC 1
351590Srgrimes
361590Srgrimes#pragma GCC system_header
371590Srgrimes
3823246Swosch#include <cerrno>
391590Srgrimes#include <clocale>   		// For localeconv
401590Srgrimes#include <cstdlib>   		// For strof, strtold
4127605Scharnier#include <cmath>     		// For ceil
421590Srgrimes#include <cctype>    		// For isspace
4327605Scharnier#include <limits>    		// For numeric_limits
4427605Scharnier#include <typeinfo>  		// For bad_cast.
4550477Speter#include <bits/streambuf_iterator.h>
461590Srgrimes
471590Srgrimesnamespace std
481590Srgrimes{
491590Srgrimes  template<typename _Facet>
501590Srgrimes    locale
511590Srgrimes    locale::combine(const locale& __other) const
521590Srgrimes    {
531590Srgrimes      _Impl* __tmp = new _Impl(*_M_impl, 1);
5423246Swosch      __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
551590Srgrimes      return locale(__tmp);
561590Srgrimes    }
5757339Sshin
581590Srgrimes  template<typename _CharT, typename _Traits, typename _Alloc>
591590Srgrimes    bool
601590Srgrimes    locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
6116423Sache                       const basic_string<_CharT, _Traits, _Alloc>& __s2) const
6216423Sache    {
631590Srgrimes      typedef std::collate<_CharT> __collate_type;
641590Srgrimes      const __collate_type& __collate = use_facet<__collate_type>(*this);
651590Srgrimes      return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
661590Srgrimes				__s2.data(), __s2.data() + __s2.length()) < 0);
6740102Smarkm    }
6841079Sjdp
6916423Sache  template<typename _Facet>
701590Srgrimes    const _Facet&
711590Srgrimes    use_facet(const locale& __loc)
721590Srgrimes    {
731590Srgrimes      size_t __i = _Facet::id._M_id();
741590Srgrimes      locale::facet** __facets = __loc._M_impl->_M_facets;
751590Srgrimes      if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i]))
761590Srgrimes        __throw_bad_cast();
771590Srgrimes      return static_cast<const _Facet&>(*__facets[__i]);
781590Srgrimes    }
791590Srgrimes
801590Srgrimes  template<typename _Facet>
8174874Smarkm    bool
8241279Sjdp    has_facet(const locale& __loc) throw()
8341279Sjdp    {
8474874Smarkm      size_t __i = _Facet::id._M_id();
8574874Smarkm      locale::facet** __facets = __loc._M_impl->_M_facets;
863702Spst      return (__i < __loc._M_impl->_M_facets_size && __facets[__i]);
871590Srgrimes    }
881590Srgrimes
8957339Sshin  // Routine to access a cache for the locale.  If the cache didn't
9057339Sshin  // exist before, it gets constructed on the fly.
9157339Sshin  template<typename _Facet>
9257339Sshin    inline const __locale_cache<_Facet>&
9357339Sshin    __use_cache(const locale& __loc)
941590Srgrimes    {
951590Srgrimes      size_t __i = _Facet::id._M_id();
961590Srgrimes      if (__builtin_expect(__i >= __loc._M_impl->_M_facets_size,false))
971590Srgrimes	__throw_bad_cast();
9821528Sdavidn      __locale_cache_base* __cache = __loc._M_impl->_M_get_cache(__i);
991590Srgrimes      if (__builtin_expect(!__cache, false))
1001590Srgrimes	{
1011590Srgrimes	  __cache = new __locale_cache<_Facet>(__loc);
10223985Sdavidn	  __loc._M_impl->_M_install_cache(__cache, __i);
1031590Srgrimes	}
1041590Srgrimes      return static_cast<const __locale_cache<_Facet>&>(*__cache);
10529922Smarkm    }
1062224Sguido
1071590Srgrimes  // Stage 1: Determine a conversion specifier.
10874874Smarkm  template<typename _CharT, typename _InIter>
10941279Sjdp    _InIter
11072215Snectar    num_get<_CharT, _InIter>::
11172215Snectar    _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
11274874Smarkm		     ios_base::iostate& __err, string& __xtrc) const
11374874Smarkm    {
11474874Smarkm      typedef char_traits<_CharT>		__traits_type;
11574874Smarkm      const locale __loc = __io.getloc();
11674874Smarkm      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
11774874Smarkm      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
11874874Smarkm
11974874Smarkm      // First check for sign.
12074874Smarkm      const char_type __plus = __ctype.widen('+');
12174874Smarkm      const char_type __minus = __ctype.widen('-');
12274874Smarkm      int __pos = 0;
12374874Smarkm      char_type  __c = *__beg;
12474874Smarkm      if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus))
12541279Sjdp	  && __beg != __end)
1261590Srgrimes	{
12727605Scharnier	  __xtrc += __ctype.narrow(__c, char());
1281590Srgrimes	  ++__pos;
1291590Srgrimes	  __c = *(++__beg);
13023985Sdavidn	}
13123985Sdavidn
13276786Sobrien      // Next, strip leading zeros.
13376786Sobrien      const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]);
1341590Srgrimes      bool __found_zero = false;
1351590Srgrimes      while (__traits_type::eq(__c, __zero) && __beg != __end)
1361590Srgrimes	{
1371590Srgrimes	  __c = *(++__beg);
1381590Srgrimes	  __found_zero = true;
1391590Srgrimes	}
1401590Srgrimes      if (__found_zero)
14142272Seivind	{
14242272Seivind	  __xtrc += _S_atoms_in[_M_zero];
14342272Seivind	  ++__pos;
1441590Srgrimes	}
1451590Srgrimes
14676786Sobrien      // Only need acceptable digits for floating point numbers.
14716423Sache      const size_t __len = _M_E - _M_zero + 1;
1481590Srgrimes      char_type  __watoms[__len];
1491590Srgrimes      __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms);
1501590Srgrimes      bool __found_dec = false;
1511590Srgrimes      bool __found_sci = false;
1521590Srgrimes      const char_type __dec = __np.decimal_point();
1531590Srgrimes
1541590Srgrimes      string __found_grouping;
1551590Srgrimes      const string __grouping = __np.grouping();
1561590Srgrimes      bool __check_grouping = __grouping.size();
1571590Srgrimes      int __sep_pos = 0;
1581590Srgrimes      const char_type __sep = __np.thousands_sep();
15923985Sdavidn
1601590Srgrimes      while (__beg != __end)
1614878Sugen        {
16223985Sdavidn	  // Only look in digits.
16335559Speter          const char_type* __p = __traits_type::find(__watoms, 10,  __c);
16446007Sache
16545431Sbrian          // NB: strchr returns true for __c == 0x0
16642272Seivind          if (__p && !__traits_type::eq(__c, char_type()))
16742272Seivind	    {
16823985Sdavidn	      // Try first for acceptable digit; record it if found.
16921528Sdavidn	      ++__pos;
17074874Smarkm	      __xtrc += _S_atoms_in[__p - __watoms];
17174874Smarkm	      ++__sep_pos;
17274874Smarkm	      __c = *(++__beg);
17374874Smarkm	    }
1741590Srgrimes          else if (__traits_type::eq(__c, __sep) 
17542272Seivind		   && __check_grouping && !__found_dec)
17642272Seivind	    {
17776942Sguido              // NB: Thousands separator at the beginning of a string
17842272Seivind              // is a no-no, as is two consecutive thousands separators.
17942272Seivind              if (__sep_pos)
18042272Seivind                {
18176788Sobrien                  __found_grouping += static_cast<char>(__sep_pos);
18276788Sobrien                  __sep_pos = 0;
18342272Seivind		  __c = *(++__beg);
18442272Seivind                }
1851590Srgrimes              else
1861590Srgrimes		{
1871590Srgrimes		  __err |= ios_base::failbit;
1881590Srgrimes		  break;
1891590Srgrimes		}
1901590Srgrimes            }
1911590Srgrimes	  else if (__traits_type::eq(__c, __dec) && !__found_dec)
1921590Srgrimes	    {
1931590Srgrimes	      // According to the standard, if no grouping chars are seen,
1941590Srgrimes	      // no grouping check is applied. Therefore __found_grouping
1951590Srgrimes	      // must be adjusted only if __dec comes after some __sep.
1961590Srgrimes	      if (__found_grouping.size())
1973205Spst		__found_grouping += static_cast<char>(__sep_pos);
19823985Sdavidn	      ++__pos;
1991590Srgrimes	      __xtrc += '.';
2001590Srgrimes	      __c = *(++__beg);
2011590Srgrimes	      __found_dec = true;
20235557Speter	    }
20346007Sache	  else if ((__traits_type::eq(__c, __watoms[_M_e]) 
20424360Simp		    || __traits_type::eq(__c, __watoms[_M_E])) 
2051590Srgrimes		   && !__found_sci && __pos)
2061590Srgrimes	    {
2071590Srgrimes	      // Scientific notation.
2081590Srgrimes	      ++__pos;
2091590Srgrimes	      __xtrc += __ctype.narrow(__c, char());
2101590Srgrimes	      __c = *(++__beg);
2111590Srgrimes
2121590Srgrimes	      // Remove optional plus or minus sign, if they exist.
2133205Spst	      if (__traits_type::eq(__c, __plus) 
21436559Samurai		  || __traits_type::eq(__c, __minus))
21545431Sbrian		{
21636559Samurai		  ++__pos;
21716423Sache		  __xtrc += __ctype.narrow(__c, char());
21857339Sshin		  __c = *(++__beg);
21957339Sshin		}
22057339Sshin	      __found_sci = true;
22157339Sshin	    }
22257339Sshin	  else
22357339Sshin	    // Not a valid input item.
22476788Sobrien	    break;
22557339Sshin        }
22657339Sshin
22716423Sache      // Digit grouping is checked. If grouping and found_grouping don't
22857339Sshin      // match, then get very very upset, and set failbit.
22976788Sobrien      if (__check_grouping && __found_grouping.size())
23076788Sobrien        {
23176788Sobrien          // Add the ending grouping if a decimal wasn't found.
23276788Sobrien	  if (!__found_dec)
23376788Sobrien	    __found_grouping += static_cast<char>(__sep_pos);
23457339Sshin          if (!__verify_grouping(__grouping, __found_grouping))
23516423Sache	    __err |= ios_base::failbit;
23616423Sache        }
23757339Sshin
23857339Sshin      // Finish up
23916423Sache      __xtrc += char();
2401590Srgrimes      if (__beg == __end)
2411590Srgrimes        __err |= ios_base::eofbit;
2421590Srgrimes      return __beg;
2431590Srgrimes    }
2441590Srgrimes
2451590Srgrimes  // Stage 1: Determine a conversion specifier.
2461590Srgrimes  template<typename _CharT, typename _InIter>
2471590Srgrimes    _InIter
2481590Srgrimes    num_get<_CharT, _InIter>::
24927605Scharnier    _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
2501590Srgrimes		   ios_base::iostate& __err, string& __xtrc, int& __base) const
2511590Srgrimes    {
2521590Srgrimes      typedef char_traits<_CharT>		__traits_type;
2531590Srgrimes      const locale __loc = __io.getloc();
2541590Srgrimes      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2551590Srgrimes      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
2561590Srgrimes 
2571590Srgrimes      // NB: Iff __basefield == 0, this can change based on contents.
2581590Srgrimes      ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
2591590Srgrimes      if (__basefield == ios_base::oct)
2601590Srgrimes        __base = 8;
2611590Srgrimes      else if (__basefield == ios_base::hex)
2621590Srgrimes        __base = 16;
2631590Srgrimes      else
2641590Srgrimes	__base = 10;
2651590Srgrimes
2661590Srgrimes      // First check for sign.
2671590Srgrimes      int __pos = 0;
26823985Sdavidn      char_type  __c = *__beg;
2691590Srgrimes      const char_type __plus = __ctype.widen('+');
2701590Srgrimes      const char_type __minus = __ctype.widen('-');
2711590Srgrimes
2721590Srgrimes      if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus))
27323985Sdavidn	  && __beg != __end)
27423985Sdavidn	{
27523985Sdavidn	  __xtrc += __ctype.narrow(__c, char());
27623985Sdavidn	  ++__pos;
27776786Sobrien	  __c = *(++__beg);
27876786Sobrien	}
27976786Sobrien
28076788Sobrien      // Next, strip leading zeros and check required digits for base formats.
28176788Sobrien      const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]);
28276788Sobrien      const char_type __x = __ctype.widen('x');
28376788Sobrien      const char_type __X = __ctype.widen('X');
28423985Sdavidn      if (__base == 10)
28523985Sdavidn	{
28621528Sdavidn	  bool __found_zero = false;
2871590Srgrimes	  while (__traits_type::eq(__c, __zero) && __beg != __end)
2881590Srgrimes	    {
2891590Srgrimes	      __c = *(++__beg);
2901590Srgrimes	      __found_zero = true;
2911590Srgrimes	    }
2921590Srgrimes	  if (__found_zero)
29321528Sdavidn	    {
29421528Sdavidn	      __xtrc += _S_atoms_in[_M_zero];
2951590Srgrimes	      ++__pos;
2961590Srgrimes	      if (__basefield == 0)
2971590Srgrimes		{	      
2981590Srgrimes		  if ((__traits_type::eq(__c, __x) 
2991590Srgrimes		       || __traits_type::eq(__c, __X))
3001590Srgrimes		      && __beg != __end)
3011590Srgrimes		    {
3021590Srgrimes		      __xtrc += __ctype.narrow(__c, char());
3031590Srgrimes		      ++__pos;
3041590Srgrimes		      __c = *(++__beg);
3051590Srgrimes		      __base = 16;
3061590Srgrimes		    }
30727605Scharnier		  else 
30827605Scharnier		    __base = 8;
3091590Srgrimes		}
31041279Sjdp	    }
31123985Sdavidn	}
31223985Sdavidn      else if (__base == 16)
3131590Srgrimes	{
3141590Srgrimes	  if (__traits_type::eq(__c, __zero) && __beg != __end)
3151590Srgrimes	    {
3161590Srgrimes	      __xtrc += _S_atoms_in[_M_zero];
3171590Srgrimes	      ++__pos;
31821528Sdavidn	      __c = *(++__beg); 
3193205Spst	      if ((__traits_type::eq(__c, __x) || __traits_type::eq(__c, __X))
3203205Spst		  && __beg != __end)
3213205Spst		{
32223985Sdavidn		  __xtrc += __ctype.narrow(__c, char());
32376788Sobrien		  ++__pos;
3243205Spst		  __c = *(++__beg);
3253205Spst		}
3263205Spst	    }
32724321Sdavidn	}
32824251Sdavidn
32924251Sdavidn      // At this point, base is determined. If not hex, only allow
33024251Sdavidn      // base digits as valid input.
33124251Sdavidn      size_t __len;
3323205Spst      if (__base == 16)
3333205Spst	__len = _M_size;
3343205Spst      else
3351590Srgrimes	__len = __base;
3361590Srgrimes
3371590Srgrimes      // Extract.
3381590Srgrimes      char_type __watoms[_M_size];
33974874Smarkm      __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms);
34041279Sjdp      string __found_grouping;
34141279Sjdp      const string __grouping = __np.grouping();
34241279Sjdp      bool __check_grouping = __grouping.size();
34341279Sjdp      int __sep_pos = 0;
34441279Sjdp      const char_type __sep = __np.thousands_sep();
34541279Sjdp      while (__beg != __end)
34674874Smarkm        {
34741279Sjdp          const char_type* __p = __traits_type::find(__watoms, __len,  __c);
34823985Sdavidn
34941279Sjdp          // NB: strchr returns true for __c == 0x0
35023985Sdavidn          if (__p && !__traits_type::eq(__c, char_type()))
35174874Smarkm	    {
35241279Sjdp	      // Try first for acceptable digit; record it if found.
35341279Sjdp	      __xtrc += _S_atoms_in[__p - __watoms];
35441279Sjdp	      ++__pos;
35541279Sjdp	      ++__sep_pos;
35641279Sjdp	      __c = *(++__beg);
35741279Sjdp	    }
35841279Sjdp          else if (__traits_type::eq(__c, __sep) && __check_grouping)
35974874Smarkm	    {
3601590Srgrimes              // NB: Thousands separator at the beginning of a string
3613205Spst              // is a no-no, as is two consecutive thousands separators.
3621590Srgrimes              if (__sep_pos)
3631590Srgrimes                {
3641590Srgrimes                  __found_grouping += static_cast<char>(__sep_pos);
3651590Srgrimes                  __sep_pos = 0;
36624222Sdavidn		  __c = *(++__beg);
36724222Sdavidn                }
36824222Sdavidn              else
36924222Sdavidn		{
37024222Sdavidn		  __err |= ios_base::failbit;
3711590Srgrimes		  break;
3721590Srgrimes		}
3731590Srgrimes            }
3741590Srgrimes	  else
37523985Sdavidn	    // Not a valid input item.
37623985Sdavidn	    break;
37723985Sdavidn        }
37823985Sdavidn
37923985Sdavidn      // Digit grouping is checked. If grouping and found_grouping don't
38023985Sdavidn      // match, then get very very upset, and set failbit.
38123985Sdavidn      if (__check_grouping && __found_grouping.size())
3821590Srgrimes        {
3831590Srgrimes          // Add the ending grouping.
3841590Srgrimes          __found_grouping += static_cast<char>(__sep_pos);
38538374Sjkoshy          if (!__verify_grouping(__grouping, __found_grouping))
3861590Srgrimes	    __err |= ios_base::failbit;
3871590Srgrimes        }
3881590Srgrimes
3891590Srgrimes      // Finish up.
3901590Srgrimes      __xtrc += char();
39176942Sguido      if (__beg == __end)
3921590Srgrimes        __err |= ios_base::eofbit;
3931590Srgrimes      return __beg;
3941590Srgrimes    }
39541279Sjdp
39641279Sjdp#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
39741279Sjdp  //17.  Bad bool parsing
39841279Sjdp  template<typename _CharT, typename _InIter>
39941279Sjdp    _InIter
4001590Srgrimes    num_get<_CharT, _InIter>::
4011590Srgrimes    do_get(iter_type __beg, iter_type __end, ios_base& __io,
40221528Sdavidn           ios_base::iostate& __err, bool& __v) const
4031590Srgrimes    {
40421528Sdavidn      // Parse bool values as unsigned long
40546007Sache      if (!(__io.flags() & ios_base::boolalpha))
40646007Sache        {
40735557Speter          // NB: We can't just call do_get(long) here, as it might
40821528Sdavidn          // refer to a derived class.
40926021Spst          string __xtrc;
41023985Sdavidn          int __base;
41124485Sdavidn          __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
41223985Sdavidn
41323985Sdavidn	  unsigned long __ul; 
41423985Sdavidn	  __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
41557546Sache	  if (!(__err & ios_base::failbit) && __ul <= 1)
4161590Srgrimes	    __v = __ul;
41735557Speter	  else 
41846007Sache            __err |= ios_base::failbit;
41921528Sdavidn        }
42021528Sdavidn
4211590Srgrimes      // Parse bool values as alphanumeric
4221590Srgrimes      else
4231590Srgrimes        {
4242532Sjkh	  typedef char_traits<_CharT>	      	__traits_type;
42576791Sobrien	  typedef basic_string<_CharT>   	__string_type;
42621528Sdavidn
42776710Seric          locale __loc = __io.getloc();
42876788Sobrien	  const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 
42976788Sobrien	  const __string_type __true = __np.truename();
43076710Seric	  const __string_type __false = __np.falsename();
43176710Seric          const char_type* __trues = __true.c_str();
43276710Seric          const char_type* __falses = __false.c_str();
43376788Sobrien          const size_t __truen =  __true.size() - 1;
43476788Sobrien          const size_t __falsen =  __false.size() - 1;
43576710Seric
43676788Sobrien          for (size_t __n = 0; __beg != __end; ++__n)
43776788Sobrien            {
43876710Seric              char_type __c = *__beg++;
43976710Seric              bool __testf = __n <= __falsen 
44076788Sobrien		             ? __traits_type::eq(__c, __falses[__n]) : false;
44176788Sobrien              bool __testt = __n <= __truen 
44223985Sdavidn		             ? __traits_type::eq(__c, __trues[__n]) : false;
44376791Sobrien              if (!(__testf || __testt))
44421528Sdavidn                {
4451590Srgrimes                  __err |= ios_base::failbit;
4461590Srgrimes                  break;
44776791Sobrien                }
44876788Sobrien              else if (__testf && __n == __falsen)
44976788Sobrien                {
45023985Sdavidn                  __v = 0;
45176788Sobrien                  break;
45276788Sobrien                }
45323985Sdavidn              else if (__testt && __n == __truen)
45423985Sdavidn                {
45521528Sdavidn                  __v = 1;
45621528Sdavidn                  break;
45757339Sshin                }
45857339Sshin            }
45921528Sdavidn          if (__beg == __end)
46057339Sshin            __err |= ios_base::eofbit;
46157339Sshin        }
46257339Sshin      return __beg;
46357339Sshin    }
46457339Sshin#endif
46557339Sshin
46657339Sshin  template<typename _CharT, typename _InIter>
46757339Sshin    _InIter
46876788Sobrien    num_get<_CharT, _InIter>::
46976788Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
47057339Sshin           ios_base::iostate& __err, long& __v) const
47157339Sshin    {
47221528Sdavidn      string __xtrc;
47357339Sshin      int __base;
47457339Sshin      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
47523985Sdavidn      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
47623985Sdavidn      return __beg;
47721528Sdavidn    }
47821528Sdavidn
47923985Sdavidn  template<typename _CharT, typename _InIter>
48023985Sdavidn    _InIter
48121528Sdavidn    num_get<_CharT, _InIter>::
48223985Sdavidn    do_get(iter_type __beg, iter_type __end, ios_base& __io,
48323985Sdavidn           ios_base::iostate& __err, unsigned short& __v) const
48421528Sdavidn    {
48576788Sobrien      string __xtrc;
48623985Sdavidn      int __base;
48723985Sdavidn      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
48823985Sdavidn      unsigned long __ul;
48923985Sdavidn      __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
49023985Sdavidn      if (!(__err & ios_base::failbit) 
49123985Sdavidn	  && __ul <= numeric_limits<unsigned short>::max())
49223985Sdavidn	__v = static_cast<unsigned short>(__ul);
49323985Sdavidn      else 
49421528Sdavidn	__err |= ios_base::failbit;
49521528Sdavidn      return __beg;
49623985Sdavidn    }
49723985Sdavidn
49821528Sdavidn  template<typename _CharT, typename _InIter>
49921528Sdavidn    _InIter
5001590Srgrimes    num_get<_CharT, _InIter>::
5011590Srgrimes    do_get(iter_type __beg, iter_type __end, ios_base& __io,
5021590Srgrimes           ios_base::iostate& __err, unsigned int& __v) const
5031590Srgrimes    {
5041590Srgrimes      string __xtrc;
5051590Srgrimes      int __base;
5061590Srgrimes      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
5071590Srgrimes      unsigned long __ul;
5081590Srgrimes      __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
5091590Srgrimes      if (!(__err & ios_base::failbit) 
5101590Srgrimes	  && __ul <= numeric_limits<unsigned int>::max())
5112224Sguido	__v = static_cast<unsigned int>(__ul);
5122224Sguido      else 
5132224Sguido	__err |= ios_base::failbit;
5142224Sguido      return __beg;
5152224Sguido    }
5162224Sguido
5172224Sguido  template<typename _CharT, typename _InIter>
51850124Simp    _InIter
51950124Simp    num_get<_CharT, _InIter>::
52050124Simp    do_get(iter_type __beg, iter_type __end, ios_base& __io,
52150124Simp           ios_base::iostate& __err, unsigned long& __v) const
52250124Simp    {
52350124Simp      string __xtrc;
52459621Ssheldonh      int __base;
52550124Simp      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
52650124Simp      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
52750124Simp      return __beg;
52850124Simp    }
5291590Srgrimes
53050124Simp#ifdef _GLIBCPP_USE_LONG_LONG
53123985Sdavidn  template<typename _CharT, typename _InIter>
53223985Sdavidn    _InIter
53323985Sdavidn    num_get<_CharT, _InIter>::
53424222Sdavidn    do_get(iter_type __beg, iter_type __end, ios_base& __io,
53524222Sdavidn           ios_base::iostate& __err, long long& __v) const
5361590Srgrimes    {
53723985Sdavidn      string __xtrc;
53823985Sdavidn      int __base;
53923985Sdavidn      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
54023985Sdavidn      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
54123985Sdavidn      return __beg;
54224894Sdavidn    }
5431590Srgrimes
5441590Srgrimes  template<typename _CharT, typename _InIter>
5453205Spst    _InIter
5463205Spst    num_get<_CharT, _InIter>::
5473205Spst    do_get(iter_type __beg, iter_type __end, ios_base& __io,
5483205Spst           ios_base::iostate& __err, unsigned long long& __v) const
5493205Spst    {
55023985Sdavidn      string __xtrc;
55123985Sdavidn      int __base;
55223985Sdavidn      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
55323985Sdavidn      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
55423985Sdavidn      return __beg;
55523985Sdavidn    }
55621528Sdavidn#endif
55721528Sdavidn
55823985Sdavidn  template<typename _CharT, typename _InIter>
55923985Sdavidn    _InIter
56023985Sdavidn    num_get<_CharT, _InIter>::
56123985Sdavidn    do_get(iter_type __beg, iter_type __end, ios_base& __io, 
56223985Sdavidn	   ios_base::iostate& __err, float& __v) const
56323985Sdavidn    {
56423985Sdavidn      string __xtrc;
56576788Sobrien      __xtrc.reserve(32);
56623985Sdavidn      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
56723985Sdavidn      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
56876788Sobrien      return __beg;
56923985Sdavidn    }
57023985Sdavidn
57123985Sdavidn  template<typename _CharT, typename _InIter>
57223985Sdavidn    _InIter
57323985Sdavidn    num_get<_CharT, _InIter>::
57423985Sdavidn    do_get(iter_type __beg, iter_type __end, ios_base& __io,
57523985Sdavidn           ios_base::iostate& __err, double& __v) const
57621528Sdavidn    {
57721528Sdavidn      string __xtrc;
57821528Sdavidn      __xtrc.reserve(32);
57974874Smarkm      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
58023985Sdavidn      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
58172215Snectar      return __beg;
58272215Snectar    }
58372215Snectar
58474874Smarkm  template<typename _CharT, typename _InIter>
58574874Smarkm    _InIter
58674874Smarkm    num_get<_CharT, _InIter>::
58774874Smarkm    do_get(iter_type __beg, iter_type __end, ios_base& __io,
58874874Smarkm           ios_base::iostate& __err, long double& __v) const
58974874Smarkm    {
59072215Snectar      string __xtrc;
59172215Snectar      __xtrc.reserve(32);
59274874Smarkm      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
59374874Smarkm      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
59474874Smarkm      return __beg;
59574874Smarkm    }
59674874Smarkm
59774874Smarkm  template<typename _CharT, typename _InIter>
59874874Smarkm    _InIter
59974874Smarkm    num_get<_CharT, _InIter>::
60074874Smarkm    do_get(iter_type __beg, iter_type __end, ios_base& __io,
60174874Smarkm           ios_base::iostate& __err, void*& __v) const
60276788Sobrien    {
60376788Sobrien      // Prepare for hex formatted input
60476788Sobrien      typedef ios_base::fmtflags        fmtflags;
60576788Sobrien      fmtflags __fmt = __io.flags();
60676788Sobrien      fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield
60776788Sobrien                             | ios_base::uppercase | ios_base::internal);
60874874Smarkm      __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase));
60974874Smarkm
61074874Smarkm      string __xtrc;
61174874Smarkm      int __base;
61274874Smarkm      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
61374874Smarkm
61474874Smarkm      // Reset from hex formatted input
61574874Smarkm      __io.flags(__fmt);
61674874Smarkm
61774874Smarkm      unsigned long __ul;
61874874Smarkm      __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
61974874Smarkm      if (!(__err & ios_base::failbit))
62076788Sobrien	__v = reinterpret_cast<void*>(__ul);
62176788Sobrien      else 
62274874Smarkm	__err |= ios_base::failbit;
62374874Smarkm      return __beg;
62474874Smarkm    }
62574874Smarkm
62674874Smarkm  // For use by integer and floating-point types after they have been
62776788Sobrien  // converted into a char_type string.
62876788Sobrien  template<typename _CharT, typename _OutIter>
62974874Smarkm    void
63074874Smarkm    num_put<_CharT, _OutIter>::
63174874Smarkm    _M_pad(_CharT __fill, streamsize __w, ios_base& __io, 
63274874Smarkm	   _CharT* __new, const _CharT* __cs, int& __len) const
63374874Smarkm    {
63423985Sdavidn      // [22.2.2.2.2] Stage 3.
63521528Sdavidn      // If necessary, pad.
63621528Sdavidn      __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs, 
63741279Sjdp						  __w, __len, true);
63841279Sjdp      __len = static_cast<int>(__w);
63941279Sjdp    }
64041279Sjdp
64141279Sjdp  // Forwarding functions to peel signed from unsigned integer types.
64274874Smarkm  template<typename _CharT>
64321528Sdavidn    inline int
64421528Sdavidn    __int_to_char(_CharT* __out, const int __size, long __v,
6453205Spst		       const _CharT* __lit, ios_base::fmtflags __flags)
64621528Sdavidn    {
64723148Sache      unsigned long __ul = static_cast<unsigned long>(__v);
64821528Sdavidn      bool __neg = false;
64923985Sdavidn      if (__v < 0) 
65076788Sobrien	{
65121528Sdavidn	  __ul = -__ul;
65223985Sdavidn	  __neg = true;
65321528Sdavidn	}
65441279Sjdp      return __int_to_char(__out, __size, __ul, __lit, __flags, __neg); 
65541279Sjdp    }
65621528Sdavidn
65721528Sdavidn  template<typename _CharT>
6581590Srgrimes    inline int
65923985Sdavidn    __int_to_char(_CharT* __out, const int __size, unsigned long __v,
66023985Sdavidn		       const _CharT* __lit, ios_base::fmtflags __flags)
66123985Sdavidn    { return __int_to_char(__out, __size, __v, __lit, __flags, false); }
66221528Sdavidn
66321528Sdavidn#ifdef _GLIBCPP_USE_LONG_LONG
66421528Sdavidn  template<typename _CharT>
66523985Sdavidn    inline int
66623985Sdavidn    __int_to_char(_CharT* __out, const int __size, long long __v,
66723985Sdavidn		       const _CharT* __lit, ios_base::fmtflags __flags)
66823985Sdavidn    { 
66923985Sdavidn      unsigned long long __ull = static_cast<unsigned long long>(__v);
67023985Sdavidn      bool __neg = false;
67123985Sdavidn      if (__v < 0) 
67221528Sdavidn	{
67321528Sdavidn	  __ull = -__ull;
67421528Sdavidn	  __neg = true;
67521528Sdavidn	}
67623985Sdavidn      return __int_to_char(__out, __size, __ull, __lit, __flags, __neg); 
67721528Sdavidn    }
67821528Sdavidn
67921528Sdavidn  template<typename _CharT>
68021528Sdavidn    inline int
68121528Sdavidn    __int_to_char(_CharT* __out, const int __size, unsigned long long __v,
68276788Sobrien		       const _CharT* __lit, ios_base::fmtflags __flags)
68376788Sobrien    { return __int_to_char(__out, __size, __v, __lit, __flags, false); }
6841590Srgrimes#endif
68523985Sdavidn      
68676788Sobrien  template<typename _CharT, typename _ValueT>
6871590Srgrimes    int
6881590Srgrimes    __int_to_char(_CharT* __out, const int __size, _ValueT __v,
68921528Sdavidn		  const _CharT* __lit, ios_base::fmtflags __flags, bool __neg)
6903205Spst    {
6911590Srgrimes      // Don't write base if already 0.
6921590Srgrimes      const bool __showbase = (__flags & ios_base::showbase) && __v;
6931590Srgrimes      const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
6941590Srgrimes      _CharT* __buf = __out + __size - 1;
6951590Srgrimes      _CharT* __bufend = __out + __size;
6964878Sugen
69721528Sdavidn      if (__builtin_expect(__basefield != ios_base::oct &&
6984878Sugen			   __basefield != ios_base::hex, true))
6994878Sugen	{
7004878Sugen	  // Decimal.
70123985Sdavidn	  do 
70223985Sdavidn	    {
70323985Sdavidn	      *__buf-- = __lit[(__v % 10) + __num_base::_S_digits];
70423985Sdavidn	      __v /= 10;
70576788Sobrien	    } 
70676788Sobrien	  while (__v != 0);
70723985Sdavidn	  if (__neg)
70821528Sdavidn	    *__buf-- = __lit[__num_base::_S_minus];
70921528Sdavidn	  else if (__flags & ios_base::showpos)
7101590Srgrimes	    *__buf-- = __lit[__num_base::_S_plus];
7111590Srgrimes	}
71241279Sjdp      else if (__basefield == ios_base::oct)
71341279Sjdp	{
71441279Sjdp	  // Octal.
71541279Sjdp	  do 
71641279Sjdp	    {
71741279Sjdp	      *__buf-- = __lit[(__v & 0x7) + __num_base::_S_digits];
71841279Sjdp	      __v >>= 3;
71941279Sjdp	    } 
72041279Sjdp	  while (__v != 0);
72141279Sjdp	  if (__showbase)
72241279Sjdp	    *__buf-- = __lit[__num_base::_S_digits];
72376786Sobrien	}
72441279Sjdp      else
72541279Sjdp	{
72641279Sjdp	  // Hex.
72741279Sjdp	  const bool __uppercase = __flags & ios_base::uppercase;
72841279Sjdp	  int __case_offset = __uppercase
72941279Sjdp	                      ? __num_base::_S_udigits : __num_base::_S_digits;
73041279Sjdp	  do 
73141279Sjdp	    {
73241279Sjdp	      *__buf-- = __lit[(__v & 0xf) + __case_offset];
73341279Sjdp	      __v >>= 4;
73441279Sjdp	    } 
73541279Sjdp	  while (__v != 0);
73641279Sjdp	  if (__showbase)
73741279Sjdp	    {
73874874Smarkm	      // 'x' or 'X'
73941279Sjdp	      *__buf-- = __lit[__num_base::_S_x + __uppercase];
74041279Sjdp	      // '0'
74141279Sjdp	      *__buf-- = __lit[__num_base::_S_digits];
74241279Sjdp	    }
74341279Sjdp	}
74441279Sjdp      int __ret = __bufend - __buf - 1;
74541279Sjdp      return __ret;
74641279Sjdp    }
74741279Sjdp
74841279Sjdp  template<typename _CharT, typename _OutIter>
74941279Sjdp    void
75041279Sjdp    num_put<_CharT, _OutIter>::
75141279Sjdp    _M_group_int(const string& __grouping, _CharT __sep, ios_base& __io, 
75241279Sjdp		 _CharT* __new, _CharT* __cs, int& __len) const
75341279Sjdp    {
75441279Sjdp      // By itself __add_grouping cannot deal correctly with __ws when
75541279Sjdp      // ios::showbase is set and ios_base::oct || ios_base::hex.
75641279Sjdp      // Therefore we take care "by hand" of the initial 0, 0x or 0X.
75741279Sjdp      // However, remember that the latter do not occur if the number
75841279Sjdp      // printed is '0' (__len == 1).
75941279Sjdp      streamsize __off = 0;
76041279Sjdp      const ios_base::fmtflags __basefield = __io.flags() 
76141279Sjdp	                                     & ios_base::basefield;
76241279Sjdp      if ((__io.flags() & ios_base::showbase) && __len > 1)
76341279Sjdp	if (__basefield == ios_base::oct)
76441279Sjdp	  {
76541279Sjdp	    __off = 1;
76641279Sjdp	    *__new = *__cs;
76741279Sjdp	  }
76841279Sjdp	else if (__basefield == ios_base::hex)
76941279Sjdp	  {
77041279Sjdp	    __off = 2;
77141279Sjdp	    *__new = *__cs;
77241279Sjdp	    *(__new + 1) = *(__cs + 1);
77341279Sjdp	  }
77441279Sjdp      _CharT* __p;
77541279Sjdp      __p = __add_grouping(__new + __off, __sep, 
77641279Sjdp			   __grouping.c_str(),
77741279Sjdp			   __grouping.c_str() + __grouping.size(),
77841279Sjdp			   __cs + __off, __cs + __len);
77941279Sjdp      __len = __p - __new;
78041279Sjdp    }
78141279Sjdp
78241279Sjdp  template<typename _CharT, typename _OutIter>
78341279Sjdp    template<typename _ValueT>
78441279Sjdp      _OutIter
78541279Sjdp      num_put<_CharT, _OutIter>::
78641279Sjdp      _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, 
78741279Sjdp		     _ValueT __v) const
78841279Sjdp      {
78941279Sjdp	typedef numpunct<_CharT>  __facet_type;
79041279Sjdp	typedef __locale_cache<numpunct<_CharT> > __cache_type;
79141279Sjdp 	const locale& __loc = __io._M_getloc();
79241279Sjdp	const __cache_type& __lc = __use_cache<__facet_type>(__loc);
79341279Sjdp	const _CharT* __lit = __lc._M_atoms_out;
79441279Sjdp
79541279Sjdp	// Long enough to hold hex, dec, and octal representations.
79641279Sjdp	int __ilen = 4 * sizeof(_ValueT);
79741279Sjdp	_CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
79841279Sjdp							     * __ilen));
79941279Sjdp	// [22.2.2.2.2] Stage 1, numeric conversion to character.
80041279Sjdp	// Result is returned right-justified in the buffer.
80141279Sjdp	int __len;
80241279Sjdp	__len = __int_to_char(&__cs[0], __ilen, __v, __lit, __io.flags());
80341279Sjdp	__cs = __cs + __ilen - __len;
80441279Sjdp	
80541279Sjdp	// Add grouping, if necessary. 
80641279Sjdp	_CharT* __cs2;
80741279Sjdp	if (__lc._M_use_grouping)
80841279Sjdp	  {
80974874Smarkm	    // Grouping can add (almost) as many separators as the
81041279Sjdp	    // number of digits, but no more.
81141279Sjdp	    __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
81241279Sjdp							  * __len * 2));
81374874Smarkm	    _M_group_int(__lc._M_grouping, __lc._M_thousands_sep, __io, 
81474874Smarkm			 __cs2, __cs, __len);
81574874Smarkm	    __cs = __cs2;
81674874Smarkm	  }
81774874Smarkm	
81874874Smarkm	// Pad.
81976788Sobrien	_CharT* __cs3;
82076788Sobrien	streamsize __w = __io.width();
82174874Smarkm	if (__w > static_cast<streamsize>(__len))
82274874Smarkm	  {
82374874Smarkm	    __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
82474874Smarkm							  * __w));
82574874Smarkm	    _M_pad(__fill, __w, __io, __cs3, __cs, __len);
82641279Sjdp	    __cs = __cs3;
82774874Smarkm	  }
82874874Smarkm	__io.width(0);
82974874Smarkm
83074874Smarkm	// [22.2.2.2.2] Stage 4.
83174874Smarkm	// Write resulting, fully-formatted string to output iterator.
83274874Smarkm	return __write(__s, __cs, __len);
83374874Smarkm      } 
83441279Sjdp
83541279Sjdp  template<typename _CharT, typename _OutIter>
83672215Snectar    void
83772215Snectar    num_put<_CharT, _OutIter>::
83872215Snectar    _M_group_float(const string& __grouping, _CharT __sep, const _CharT* __p, 
83972215Snectar		   _CharT* __new, _CharT* __cs, int& __len) const
84072215Snectar    {
84172215Snectar#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
84272215Snectar      //282. What types does numpunct grouping refer to?
84372215Snectar      // Add grouping, if necessary. 
84472215Snectar      _CharT* __p2;
84572215Snectar      int __declen = __p ? __p - __cs : __len;
84672215Snectar      __p2 = __add_grouping(__new, __sep, 
84772215Snectar			    __grouping.c_str(),
84872215Snectar			    __grouping.c_str() + __grouping.size(),
84972215Snectar			    __cs, __cs + __declen);
85072215Snectar      
85172215Snectar      // Tack on decimal part.
85272215Snectar      int __newlen = __p2 - __new;
85372215Snectar      if (__p)
85472215Snectar	{
85572215Snectar	  char_traits<_CharT>::copy(__p2, __p, __len - __declen);
85672215Snectar	  __newlen += __len - __declen;
85772215Snectar	}    
85872215Snectar      __len = __newlen;
85972215Snectar#endif
86072215Snectar    }
86172215Snectar
86272215Snectar  // The following code uses snprintf (or sprintf(), when
86372215Snectar  // _GLIBCPP_USE_C99 is not defined) to convert floating point values
86472215Snectar  // for insertion into a stream.  An optimization would be to replace
86572215Snectar  // them with code that works directly on a wide buffer and then use
86672215Snectar  // __pad to do the padding.  It would be good to replace them anyway
86772215Snectar  // to gain back the efficiency that C++ provides by knowing up front
86872215Snectar  // the type of the values to insert.  Also, sprintf is dangerous
86972215Snectar  // since may lead to accidental buffer overruns.  This
87072215Snectar  // implementation follows the C++ standard fairly directly as
87172215Snectar  // outlined in 22.2.2.2 [lib.locale.num.put]
87272215Snectar  template<typename _CharT, typename _OutIter>
87372215Snectar    template<typename _ValueT>
87472215Snectar      _OutIter
87572215Snectar      num_put<_CharT, _OutIter>::
87672215Snectar      _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
87772215Snectar		       _ValueT __v) const
87872215Snectar      {
87974874Smarkm	// Note: digits10 is rounded down: add 1 to ensure the maximum
88041279Sjdp	// available precision.  Then, in general, one more 1 needs to
88127605Scharnier	// be added since, when the %{g,G} conversion specifiers are
88227605Scharnier	// chosen inside _S_format_float, the precision field is "the
88327605Scharnier	// maximum number of significant digits", *not* the "number of
88476791Sobrien	// digits to appear after the decimal point", as happens for
88527605Scharnier	// %{e,E,f,F} (C99, 7.19.6.1,4).
88627605Scharnier	const int __max_digits = numeric_limits<_ValueT>::digits10 + 2;
88727605Scharnier
8881590Srgrimes	// Use default precision if out of range.
88923985Sdavidn	streamsize __prec = __io.precision();
89023985Sdavidn	if (__prec > static_cast<streamsize>(__max_digits))
89174874Smarkm	  __prec = static_cast<streamsize>(__max_digits);
89221528Sdavidn	else if (__prec < static_cast<streamsize>(0))
89321528Sdavidn	  __prec = static_cast<streamsize>(6);
89421528Sdavidn
8951590Srgrimes	typedef numpunct<_CharT>  __facet_type;
8961590Srgrimes	typedef __locale_cache<numpunct<_CharT> > __cache_type;
8971590Srgrimes	const locale __loc = __io._M_getloc();
8981590Srgrimes	const __cache_type& __lc = __use_cache<__facet_type>(__loc);
8991590Srgrimes
9001590Srgrimes	// [22.2.2.2.2] Stage 1, numeric conversion to character.
9011590Srgrimes	int __len;
9021590Srgrimes	// Long enough for the max format spec.
90376786Sobrien	char __fbuf[16];
9041590Srgrimes
9051590Srgrimes#ifdef _GLIBCPP_USE_C99
9061590Srgrimes	// First try a buffer perhaps big enough (for sure sufficient
9071590Srgrimes	// for non-ios_base::fixed outputs)
9081590Srgrimes	int __cs_size = __max_digits * 3;
9091590Srgrimes	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
9101590Srgrimes
9111590Srgrimes	_S_format_float(__io, __fbuf, __mod, __prec);
91259645Ssheldonh	__len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
9131590Srgrimes				 _S_c_locale, __prec);
9141590Srgrimes
9151590Srgrimes	// If the buffer was not large enough, try again with the correct size.
9161590Srgrimes	if (__len >= __cs_size)
9171590Srgrimes	  {
9181590Srgrimes	    __cs_size = __len + 1; 
9191590Srgrimes	    __cs = static_cast<char*>(__builtin_alloca(__cs_size));
9201590Srgrimes	    __len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
92159645Ssheldonh				     _S_c_locale, __prec);
9221590Srgrimes	  }
9231590Srgrimes#else
9241590Srgrimes	// Consider the possibility of long ios_base::fixed outputs
9251590Srgrimes	const bool __fixed = __io.flags() & ios_base::fixed;
9261590Srgrimes	const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
9271590Srgrimes
9281590Srgrimes	// ios_base::fixed outputs may need up to __max_exp+1 chars
9291590Srgrimes	// for the integer part + up to __max_digits chars for the
93023985Sdavidn	// fractional part + 3 chars for sign, decimal point, '\0'. On
9311590Srgrimes	// the other hand, for non-fixed outputs __max_digits*3 chars
9321590Srgrimes	// are largely sufficient.
9331590Srgrimes	const int __cs_size = __fixed ? __max_exp + __max_digits + 4 
93421528Sdavidn	                              : __max_digits * 3;
9351590Srgrimes	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
93621528Sdavidn
9371590Srgrimes	_S_format_float(__io, __fbuf, __mod, __prec);
93821528Sdavidn	__len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec);
93921528Sdavidn#endif
9401590Srgrimes
94121528Sdavidn      // [22.2.2.2.2] Stage 2, convert to char_type, using correct
94221528Sdavidn      // numpunct.decimal_point() values for '.' and adding grouping.
94321528Sdavidn      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
94421528Sdavidn
94521528Sdavidn      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
94621528Sdavidn							   * __len));
94721528Sdavidn      __ctype.widen(__cs, __cs + __len, __ws);
9481590Srgrimes      
9491590Srgrimes      // Replace decimal point.
95021528Sdavidn      const _CharT __cdec = __ctype.widen('.');
9511590Srgrimes      const _CharT __dec = __lc._M_decimal_point;
95221528Sdavidn      const _CharT* __p;
9531590Srgrimes      if (__p = char_traits<_CharT>::find(__ws, __len, __cdec))
95421528Sdavidn	__ws[__p - __ws] = __dec;
9551590Srgrimes
95621528Sdavidn      // Add grouping, if necessary. 
95721528Sdavidn      _CharT* __ws2;
9581590Srgrimes      if (__lc._M_use_grouping)
9591590Srgrimes	{
9601590Srgrimes	    // Grouping can add (almost) as many separators as the
9611590Srgrimes	    // number of digits, but no more.
9621590Srgrimes	    __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
9631590Srgrimes							  * __len * 2));
9641590Srgrimes	    _M_group_float(__lc._M_grouping, __lc._M_thousands_sep, __p,
9651590Srgrimes			   __ws2, __ws, __len);
9661590Srgrimes	    __ws = __ws2;
96776788Sobrien	}
96842272Seivind
9691590Srgrimes      // Pad.
9701590Srgrimes      _CharT* __ws3;
9711590Srgrimes      streamsize __w = __io.width();
9721590Srgrimes      if (__w > static_cast<streamsize>(__len))
9731590Srgrimes	{
9741590Srgrimes	  __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __w));
9751590Srgrimes	  _M_pad(__fill, __w, __io, __ws3, __ws, __len);
9761590Srgrimes	  __ws = __ws3;
9771590Srgrimes	}
9781590Srgrimes      __io.width(0);
9791590Srgrimes      
9801590Srgrimes      // [22.2.2.2.2] Stage 4.
9811590Srgrimes      // Write resulting, fully-formatted string to output iterator.
9821590Srgrimes      return __write(__s, __ws, __len);
9831590Srgrimes      }
9841590Srgrimes
9851590Srgrimes  template<typename _CharT, typename _OutIter>
9861590Srgrimes    _OutIter
9871590Srgrimes    num_put<_CharT, _OutIter>::
9881590Srgrimes    do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
9891590Srgrimes    {
9901590Srgrimes      ios_base::fmtflags __flags = __io.flags();
9911590Srgrimes      if ((__flags & ios_base::boolalpha) == 0)
9921590Srgrimes        {
9931590Srgrimes          unsigned long __uv = __v;
9941590Srgrimes          __s = _M_convert_int(__s, __io, __fill, __uv);
9951590Srgrimes        }
9961590Srgrimes      else
9971590Srgrimes        {
9981590Srgrimes	  typedef numpunct<_CharT>  __facet_type;
9991590Srgrimes	  typedef __locale_cache<numpunct<_CharT> > __cache_type;
10001590Srgrimes	  const locale __loc = __io._M_getloc();
10011590Srgrimes	  const __cache_type& __lc = __use_cache<__facet_type>(__loc);
10021590Srgrimes
10031590Srgrimes	  typedef basic_string<_CharT> 	__string_type;
10041590Srgrimes	  __string_type __name;
10051590Srgrimes          if (__v)
10061590Srgrimes	    __name = __lc._M_truename;
10071590Srgrimes          else
10081590Srgrimes	    __name = __lc._M_falsename;
10091590Srgrimes
10101590Srgrimes	  const _CharT* __cs = __name.c_str();
10111590Srgrimes	  int __len = __name.size();
10121590Srgrimes	  _CharT* __cs3;
10131590Srgrimes	  streamsize __w = __io.width();
10141590Srgrimes	  if (__w > static_cast<streamsize>(__len))
10151590Srgrimes	    {
101616423Sache	      __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
10171590Srgrimes							    * __w));
10181590Srgrimes	      _M_pad(__fill, __w, __io, __cs3, __cs, __len);
101916423Sache	      __cs = __cs3;
10201590Srgrimes	    }
10211590Srgrimes	  __io.width(0);
10221590Srgrimes	  __s = __write(__s, __cs, __len);
10231590Srgrimes	}
10241590Srgrimes      return __s;
10251590Srgrimes    }
10261590Srgrimes
102742272Seivind  template<typename _CharT, typename _OutIter>
10281590Srgrimes    _OutIter
10291590Srgrimes    num_put<_CharT, _OutIter>::
10301590Srgrimes    do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
10311590Srgrimes    { return _M_convert_int(__s, __io, __fill, __v); }
10321590Srgrimes
10331590Srgrimes  template<typename _CharT, typename _OutIter>
10341590Srgrimes    _OutIter
10351590Srgrimes    num_put<_CharT, _OutIter>::
10361590Srgrimes    do_put(iter_type __s, ios_base& __io, char_type __fill,
10371590Srgrimes           unsigned long __v) const
103823985Sdavidn    { return _M_convert_int(__s, __io, __fill, __v); }
10391590Srgrimes
10401590Srgrimes#ifdef _GLIBCPP_USE_LONG_LONG
10411590Srgrimes  template<typename _CharT, typename _OutIter>
10421590Srgrimes    _OutIter
104323985Sdavidn    num_put<_CharT, _OutIter>::
104423985Sdavidn    do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
104523985Sdavidn    { return _M_convert_int(__s, __b, __fill, __v); }
104623985Sdavidn
104723985Sdavidn  template<typename _CharT, typename _OutIter>
104823985Sdavidn    _OutIter
104923985Sdavidn    num_put<_CharT, _OutIter>::
105023985Sdavidn    do_put(iter_type __s, ios_base& __io, char_type __fill,
105123985Sdavidn           unsigned long long __v) const
105223985Sdavidn    { return _M_convert_int(__s, __io, __fill, __v); }
105376788Sobrien#endif
105423985Sdavidn
105523985Sdavidn  template<typename _CharT, typename _OutIter>
105676788Sobrien    _OutIter
105723985Sdavidn    num_put<_CharT, _OutIter>::
105823985Sdavidn    do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
105923985Sdavidn    { return _M_convert_float(__s, __io, __fill, char(), __v); }
106023985Sdavidn
106123985Sdavidn  template<typename _CharT, typename _OutIter>
10621590Srgrimes    _OutIter
10631590Srgrimes    num_put<_CharT, _OutIter>::
10641590Srgrimes    do_put(iter_type __s, ios_base& __io, char_type __fill, 
106523985Sdavidn	   long double __v) const
10661590Srgrimes    { return _M_convert_float(__s, __io, __fill, 'L', __v); }
10671590Srgrimes
10681590Srgrimes  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 __n = numeric_limits<long double>::digits10;
1103      char* __cs = static_cast<char*>(__builtin_alloca(__n));
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 + __str.size() + 1, 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[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