locale_facets.tcc revision 117397
197403Sobrien// Locale support -*- C++ -*-
297403Sobrien
3117397Skan// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
497403Sobrien// Free Software Foundation, Inc.
597403Sobrien//
697403Sobrien// This file is part of the GNU ISO C++ Library.  This library is free
797403Sobrien// software; you can redistribute it and/or modify it under the
897403Sobrien// terms of the GNU General Public License as published by the
997403Sobrien// Free Software Foundation; either version 2, or (at your option)
1097403Sobrien// any later version.
1197403Sobrien
1297403Sobrien// This library is distributed in the hope that it will be useful,
1397403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of
1497403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1597403Sobrien// GNU General Public License for more details.
1697403Sobrien
1797403Sobrien// You should have received a copy of the GNU General Public License along
1897403Sobrien// with this library; see the file COPYING.  If not, write to the Free
1997403Sobrien// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
2097403Sobrien// USA.
2197403Sobrien
2297403Sobrien// As a special exception, you may use this file as part of a free software
2397403Sobrien// library without restriction.  Specifically, if other files instantiate
2497403Sobrien// templates or use macros or inline functions from this file, or you compile
2597403Sobrien// this file and link it with other files to produce an executable, this
2697403Sobrien// file does not by itself cause the resulting executable to be covered by
2797403Sobrien// the GNU General Public License.  This exception does not however
2897403Sobrien// invalidate any other reasons why the executable file might be covered by
2997403Sobrien// the GNU General Public License.
3097403Sobrien
3197403Sobrien// Warning: this file is not meant for user inclusion. Use <locale>.
3297403Sobrien
3397403Sobrien#ifndef _CPP_BITS_LOCFACETS_TCC
3497403Sobrien#define _CPP_BITS_LOCFACETS_TCC 1
3597403Sobrien
3697403Sobrien#pragma GCC system_header
3797403Sobrien
3897403Sobrien#include <cerrno>
39117397Skan#include <clocale>   		// For localeconv
40117397Skan#include <cstdlib>   		// For strof, strtold
41117397Skan#include <cmath>     		// For ceil
42117397Skan#include <cctype>    		// For isspace
43117397Skan#include <limits>    		// For numeric_limits
44117397Skan#include <typeinfo>  		// For bad_cast.
4597403Sobrien#include <bits/streambuf_iterator.h>
4697403Sobrien
4797403Sobriennamespace std
4897403Sobrien{
4997403Sobrien  template<typename _Facet>
5097403Sobrien    locale
5197403Sobrien    locale::combine(const locale& __other) const
5297403Sobrien    {
5397403Sobrien      _Impl* __tmp = new _Impl(*_M_impl, 1);
5497403Sobrien      __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
5597403Sobrien      return locale(__tmp);
5697403Sobrien    }
5797403Sobrien
5897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
5997403Sobrien    bool
6097403Sobrien    locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
6197403Sobrien                       const basic_string<_CharT, _Traits, _Alloc>& __s2) const
6297403Sobrien    {
6397403Sobrien      typedef std::collate<_CharT> __collate_type;
6497403Sobrien      const __collate_type& __collate = use_facet<__collate_type>(*this);
6597403Sobrien      return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
6697403Sobrien				__s2.data(), __s2.data() + __s2.length()) < 0);
6797403Sobrien    }
6897403Sobrien
6997403Sobrien  template<typename _Facet>
7097403Sobrien    const _Facet&
7197403Sobrien    use_facet(const locale& __loc)
7297403Sobrien    {
7397403Sobrien      size_t __i = _Facet::id._M_id();
7497403Sobrien      locale::facet** __facets = __loc._M_impl->_M_facets;
7597403Sobrien      if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i]))
7697403Sobrien        __throw_bad_cast();
7797403Sobrien      return static_cast<const _Facet&>(*__facets[__i]);
7897403Sobrien    }
7997403Sobrien
8097403Sobrien  template<typename _Facet>
8197403Sobrien    bool
8297403Sobrien    has_facet(const locale& __loc) throw()
8397403Sobrien    {
8497403Sobrien      size_t __i = _Facet::id._M_id();
8597403Sobrien      locale::facet** __facets = __loc._M_impl->_M_facets;
8697403Sobrien      return (__i < __loc._M_impl->_M_facets_size && __facets[__i]);
8797403Sobrien    }
8897403Sobrien
89117397Skan  // Routine to access a cache for the locale.  If the cache didn't
90117397Skan  // exist before, it gets constructed on the fly.
91117397Skan  template<typename _Facet>
92117397Skan    inline const __locale_cache<_Facet>&
93117397Skan    __use_cache(const locale& __loc)
94117397Skan    {
95117397Skan      size_t __i = _Facet::id._M_id();
96117397Skan      if (__builtin_expect(__i >= __loc._M_impl->_M_facets_size,false))
97117397Skan	__throw_bad_cast();
98117397Skan      __locale_cache_base* __cache = __loc._M_impl->_M_get_cache(__i);
99117397Skan      if (__builtin_expect(!__cache, false))
100117397Skan	{
101117397Skan	  __cache = new __locale_cache<_Facet>(__loc);
102117397Skan	  __loc._M_impl->_M_install_cache(__cache, __i);
103117397Skan	}
104117397Skan      return static_cast<const __locale_cache<_Facet>&>(*__cache);
105117397Skan    }
10697403Sobrien
10797403Sobrien  // Stage 1: Determine a conversion specifier.
10897403Sobrien  template<typename _CharT, typename _InIter>
10997403Sobrien    _InIter
11097403Sobrien    num_get<_CharT, _InIter>::
11197403Sobrien    _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
11297403Sobrien		     ios_base::iostate& __err, string& __xtrc) const
11397403Sobrien    {
114102782Skan      typedef char_traits<_CharT>		__traits_type;
11597403Sobrien      const locale __loc = __io.getloc();
11697403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
11797403Sobrien      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
11897403Sobrien
11997403Sobrien      // First check for sign.
12097403Sobrien      const char_type __plus = __ctype.widen('+');
12197403Sobrien      const char_type __minus = __ctype.widen('-');
12297403Sobrien      int __pos = 0;
12397403Sobrien      char_type  __c = *__beg;
124102782Skan      if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus))
125102782Skan	  && __beg != __end)
12697403Sobrien	{
12797403Sobrien	  __xtrc += __ctype.narrow(__c, char());
12897403Sobrien	  ++__pos;
12997403Sobrien	  __c = *(++__beg);
13097403Sobrien	}
13197403Sobrien
13297403Sobrien      // Next, strip leading zeros.
133117397Skan      const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]);
13497403Sobrien      bool __found_zero = false;
135102782Skan      while (__traits_type::eq(__c, __zero) && __beg != __end)
13697403Sobrien	{
13797403Sobrien	  __c = *(++__beg);
13897403Sobrien	  __found_zero = true;
13997403Sobrien	}
14097403Sobrien      if (__found_zero)
14197403Sobrien	{
142117397Skan	  __xtrc += _S_atoms_in[_M_zero];
14397403Sobrien	  ++__pos;
14497403Sobrien	}
14597403Sobrien
14697403Sobrien      // Only need acceptable digits for floating point numbers.
14797403Sobrien      const size_t __len = _M_E - _M_zero + 1;
14897403Sobrien      char_type  __watoms[__len];
149117397Skan      __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms);
15097403Sobrien      bool __found_dec = false;
15197403Sobrien      bool __found_sci = false;
15297403Sobrien      const char_type __dec = __np.decimal_point();
15397403Sobrien
15497403Sobrien      string __found_grouping;
15597403Sobrien      const string __grouping = __np.grouping();
15697403Sobrien      bool __check_grouping = __grouping.size();
15797403Sobrien      int __sep_pos = 0;
15897403Sobrien      const char_type __sep = __np.thousands_sep();
15997403Sobrien
16097403Sobrien      while (__beg != __end)
16197403Sobrien        {
16297403Sobrien	  // Only look in digits.
16397403Sobrien          const char_type* __p = __traits_type::find(__watoms, 10,  __c);
16497403Sobrien
16597403Sobrien          // NB: strchr returns true for __c == 0x0
166102782Skan          if (__p && !__traits_type::eq(__c, char_type()))
16797403Sobrien	    {
16897403Sobrien	      // Try first for acceptable digit; record it if found.
16997403Sobrien	      ++__pos;
170117397Skan	      __xtrc += _S_atoms_in[__p - __watoms];
17197403Sobrien	      ++__sep_pos;
17297403Sobrien	      __c = *(++__beg);
17397403Sobrien	    }
174102782Skan          else if (__traits_type::eq(__c, __sep) 
175102782Skan		   && __check_grouping && !__found_dec)
17697403Sobrien	    {
17797403Sobrien              // NB: Thousands separator at the beginning of a string
17897403Sobrien              // is a no-no, as is two consecutive thousands separators.
17997403Sobrien              if (__sep_pos)
18097403Sobrien                {
18197403Sobrien                  __found_grouping += static_cast<char>(__sep_pos);
18297403Sobrien                  __sep_pos = 0;
18397403Sobrien		  __c = *(++__beg);
18497403Sobrien                }
18597403Sobrien              else
18697403Sobrien		{
18797403Sobrien		  __err |= ios_base::failbit;
18897403Sobrien		  break;
18997403Sobrien		}
19097403Sobrien            }
191102782Skan	  else if (__traits_type::eq(__c, __dec) && !__found_dec)
19297403Sobrien	    {
19397403Sobrien	      // According to the standard, if no grouping chars are seen,
19497403Sobrien	      // no grouping check is applied. Therefore __found_grouping
19597403Sobrien	      // must be adjusted only if __dec comes after some __sep.
19697403Sobrien	      if (__found_grouping.size())
19797403Sobrien		__found_grouping += static_cast<char>(__sep_pos);
19897403Sobrien	      ++__pos;
19997403Sobrien	      __xtrc += '.';
20097403Sobrien	      __c = *(++__beg);
20197403Sobrien	      __found_dec = true;
20297403Sobrien	    }
203102782Skan	  else if ((__traits_type::eq(__c, __watoms[_M_e]) 
204102782Skan		    || __traits_type::eq(__c, __watoms[_M_E])) 
20597403Sobrien		   && !__found_sci && __pos)
20697403Sobrien	    {
20797403Sobrien	      // Scientific notation.
20897403Sobrien	      ++__pos;
20997403Sobrien	      __xtrc += __ctype.narrow(__c, char());
21097403Sobrien	      __c = *(++__beg);
21197403Sobrien
21297403Sobrien	      // Remove optional plus or minus sign, if they exist.
213102782Skan	      if (__traits_type::eq(__c, __plus) 
214102782Skan		  || __traits_type::eq(__c, __minus))
21597403Sobrien		{
21697403Sobrien		  ++__pos;
21797403Sobrien		  __xtrc += __ctype.narrow(__c, char());
21897403Sobrien		  __c = *(++__beg);
21997403Sobrien		}
22097403Sobrien	      __found_sci = true;
22197403Sobrien	    }
22297403Sobrien	  else
22397403Sobrien	    // Not a valid input item.
22497403Sobrien	    break;
22597403Sobrien        }
22697403Sobrien
22797403Sobrien      // Digit grouping is checked. If grouping and found_grouping don't
22897403Sobrien      // match, then get very very upset, and set failbit.
22997403Sobrien      if (__check_grouping && __found_grouping.size())
23097403Sobrien        {
23197403Sobrien          // Add the ending grouping if a decimal wasn't found.
23297403Sobrien	  if (!__found_dec)
23397403Sobrien	    __found_grouping += static_cast<char>(__sep_pos);
23497403Sobrien          if (!__verify_grouping(__grouping, __found_grouping))
23597403Sobrien	    __err |= ios_base::failbit;
23697403Sobrien        }
23797403Sobrien
23897403Sobrien      // Finish up
23997403Sobrien      __xtrc += char();
24097403Sobrien      if (__beg == __end)
24197403Sobrien        __err |= ios_base::eofbit;
24297403Sobrien      return __beg;
24397403Sobrien    }
24497403Sobrien
24597403Sobrien  // Stage 1: Determine a conversion specifier.
24697403Sobrien  template<typename _CharT, typename _InIter>
24797403Sobrien    _InIter
24897403Sobrien    num_get<_CharT, _InIter>::
24997403Sobrien    _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
25097403Sobrien		   ios_base::iostate& __err, string& __xtrc, int& __base) const
25197403Sobrien    {
252102782Skan      typedef char_traits<_CharT>		__traits_type;
25397403Sobrien      const locale __loc = __io.getloc();
25497403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
25597403Sobrien      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
25697403Sobrien 
25797403Sobrien      // NB: Iff __basefield == 0, this can change based on contents.
25897403Sobrien      ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
25997403Sobrien      if (__basefield == ios_base::oct)
26097403Sobrien        __base = 8;
26197403Sobrien      else if (__basefield == ios_base::hex)
26297403Sobrien        __base = 16;
26397403Sobrien      else
26497403Sobrien	__base = 10;
26597403Sobrien
266102782Skan      // First check for sign.
26797403Sobrien      int __pos = 0;
26897403Sobrien      char_type  __c = *__beg;
269102782Skan      const char_type __plus = __ctype.widen('+');
270102782Skan      const char_type __minus = __ctype.widen('-');
271102782Skan
272102782Skan      if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus))
27397403Sobrien	  && __beg != __end)
27497403Sobrien	{
27597403Sobrien	  __xtrc += __ctype.narrow(__c, char());
27697403Sobrien	  ++__pos;
27797403Sobrien	  __c = *(++__beg);
27897403Sobrien	}
27997403Sobrien
28097403Sobrien      // Next, strip leading zeros and check required digits for base formats.
281117397Skan      const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]);
28297403Sobrien      const char_type __x = __ctype.widen('x');
28397403Sobrien      const char_type __X = __ctype.widen('X');
28497403Sobrien      if (__base == 10)
28597403Sobrien	{
28697403Sobrien	  bool __found_zero = false;
287102782Skan	  while (__traits_type::eq(__c, __zero) && __beg != __end)
28897403Sobrien	    {
28997403Sobrien	      __c = *(++__beg);
29097403Sobrien	      __found_zero = true;
29197403Sobrien	    }
29297403Sobrien	  if (__found_zero)
29397403Sobrien	    {
294117397Skan	      __xtrc += _S_atoms_in[_M_zero];
29597403Sobrien	      ++__pos;
29697403Sobrien	      if (__basefield == 0)
29797403Sobrien		{	      
298102782Skan		  if ((__traits_type::eq(__c, __x) 
299102782Skan		       || __traits_type::eq(__c, __X))
300102782Skan		      && __beg != __end)
30197403Sobrien		    {
30297403Sobrien		      __xtrc += __ctype.narrow(__c, char());
30397403Sobrien		      ++__pos;
30497403Sobrien		      __c = *(++__beg);
30597403Sobrien		      __base = 16;
30697403Sobrien		    }
30797403Sobrien		  else 
30897403Sobrien		    __base = 8;
30997403Sobrien		}
31097403Sobrien	    }
31197403Sobrien	}
31297403Sobrien      else if (__base == 16)
31397403Sobrien	{
314102782Skan	  if (__traits_type::eq(__c, __zero) && __beg != __end)
31597403Sobrien	    {
316117397Skan	      __xtrc += _S_atoms_in[_M_zero];
31797403Sobrien	      ++__pos;
31897403Sobrien	      __c = *(++__beg); 
319102782Skan	      if ((__traits_type::eq(__c, __x) || __traits_type::eq(__c, __X))
320102782Skan		  && __beg != __end)
32197403Sobrien		{
32297403Sobrien		  __xtrc += __ctype.narrow(__c, char());
32397403Sobrien		  ++__pos;
32497403Sobrien		  __c = *(++__beg);
32597403Sobrien		}
32697403Sobrien	    }
32797403Sobrien	}
32897403Sobrien
32997403Sobrien      // At this point, base is determined. If not hex, only allow
33097403Sobrien      // base digits as valid input.
33197403Sobrien      size_t __len;
33297403Sobrien      if (__base == 16)
33397403Sobrien	__len = _M_size;
33497403Sobrien      else
33597403Sobrien	__len = __base;
33697403Sobrien
33797403Sobrien      // Extract.
33897403Sobrien      char_type __watoms[_M_size];
339117397Skan      __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms);
34097403Sobrien      string __found_grouping;
34197403Sobrien      const string __grouping = __np.grouping();
34297403Sobrien      bool __check_grouping = __grouping.size();
34397403Sobrien      int __sep_pos = 0;
34497403Sobrien      const char_type __sep = __np.thousands_sep();
34597403Sobrien      while (__beg != __end)
34697403Sobrien        {
34797403Sobrien          const char_type* __p = __traits_type::find(__watoms, __len,  __c);
34897403Sobrien
34997403Sobrien          // NB: strchr returns true for __c == 0x0
350102782Skan          if (__p && !__traits_type::eq(__c, char_type()))
35197403Sobrien	    {
35297403Sobrien	      // Try first for acceptable digit; record it if found.
353117397Skan	      __xtrc += _S_atoms_in[__p - __watoms];
35497403Sobrien	      ++__pos;
35597403Sobrien	      ++__sep_pos;
35697403Sobrien	      __c = *(++__beg);
35797403Sobrien	    }
358102782Skan          else if (__traits_type::eq(__c, __sep) && __check_grouping)
35997403Sobrien	    {
36097403Sobrien              // NB: Thousands separator at the beginning of a string
36197403Sobrien              // is a no-no, as is two consecutive thousands separators.
36297403Sobrien              if (__sep_pos)
36397403Sobrien                {
36497403Sobrien                  __found_grouping += static_cast<char>(__sep_pos);
36597403Sobrien                  __sep_pos = 0;
36697403Sobrien		  __c = *(++__beg);
36797403Sobrien                }
36897403Sobrien              else
36997403Sobrien		{
37097403Sobrien		  __err |= ios_base::failbit;
37197403Sobrien		  break;
37297403Sobrien		}
37397403Sobrien            }
37497403Sobrien	  else
37597403Sobrien	    // Not a valid input item.
37697403Sobrien	    break;
37797403Sobrien        }
37897403Sobrien
37997403Sobrien      // Digit grouping is checked. If grouping and found_grouping don't
38097403Sobrien      // match, then get very very upset, and set failbit.
38197403Sobrien      if (__check_grouping && __found_grouping.size())
38297403Sobrien        {
38397403Sobrien          // Add the ending grouping.
38497403Sobrien          __found_grouping += static_cast<char>(__sep_pos);
38597403Sobrien          if (!__verify_grouping(__grouping, __found_grouping))
38697403Sobrien	    __err |= ios_base::failbit;
38797403Sobrien        }
38897403Sobrien
38997403Sobrien      // Finish up.
39097403Sobrien      __xtrc += char();
39197403Sobrien      if (__beg == __end)
39297403Sobrien        __err |= ios_base::eofbit;
39397403Sobrien      return __beg;
39497403Sobrien    }
39597403Sobrien
39697403Sobrien#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
39797403Sobrien  //17.  Bad bool parsing
39897403Sobrien  template<typename _CharT, typename _InIter>
39997403Sobrien    _InIter
40097403Sobrien    num_get<_CharT, _InIter>::
40197403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
40297403Sobrien           ios_base::iostate& __err, bool& __v) const
40397403Sobrien    {
40497403Sobrien      // Parse bool values as unsigned long
40597403Sobrien      if (!(__io.flags() & ios_base::boolalpha))
40697403Sobrien        {
40797403Sobrien          // NB: We can't just call do_get(long) here, as it might
40897403Sobrien          // refer to a derived class.
40997403Sobrien          string __xtrc;
41097403Sobrien          int __base;
41197403Sobrien          __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
41297403Sobrien
41397403Sobrien	  unsigned long __ul; 
41497403Sobrien	  __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
41597403Sobrien	  if (!(__err & ios_base::failbit) && __ul <= 1)
41697403Sobrien	    __v = __ul;
41797403Sobrien	  else 
41897403Sobrien            __err |= ios_base::failbit;
41997403Sobrien        }
42097403Sobrien
42197403Sobrien      // Parse bool values as alphanumeric
42297403Sobrien      else
42397403Sobrien        {
424102782Skan	  typedef char_traits<_CharT>	      	__traits_type;
425102782Skan	  typedef basic_string<_CharT>   	__string_type;
426102782Skan
42797403Sobrien          locale __loc = __io.getloc();
42897403Sobrien	  const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 
42997403Sobrien	  const __string_type __true = __np.truename();
43097403Sobrien	  const __string_type __false = __np.falsename();
43197403Sobrien          const char_type* __trues = __true.c_str();
43297403Sobrien          const char_type* __falses = __false.c_str();
43397403Sobrien          const size_t __truen =  __true.size() - 1;
43497403Sobrien          const size_t __falsen =  __false.size() - 1;
43597403Sobrien
43697403Sobrien          for (size_t __n = 0; __beg != __end; ++__n)
43797403Sobrien            {
43897403Sobrien              char_type __c = *__beg++;
439102782Skan              bool __testf = __n <= __falsen 
440102782Skan		             ? __traits_type::eq(__c, __falses[__n]) : false;
441102782Skan              bool __testt = __n <= __truen 
442102782Skan		             ? __traits_type::eq(__c, __trues[__n]) : false;
44397403Sobrien              if (!(__testf || __testt))
44497403Sobrien                {
44597403Sobrien                  __err |= ios_base::failbit;
44697403Sobrien                  break;
44797403Sobrien                }
44897403Sobrien              else if (__testf && __n == __falsen)
44997403Sobrien                {
45097403Sobrien                  __v = 0;
45197403Sobrien                  break;
45297403Sobrien                }
45397403Sobrien              else if (__testt && __n == __truen)
45497403Sobrien                {
45597403Sobrien                  __v = 1;
45697403Sobrien                  break;
45797403Sobrien                }
45897403Sobrien            }
45997403Sobrien          if (__beg == __end)
46097403Sobrien            __err |= ios_base::eofbit;
46197403Sobrien        }
46297403Sobrien      return __beg;
46397403Sobrien    }
46497403Sobrien#endif
46597403Sobrien
46697403Sobrien  template<typename _CharT, typename _InIter>
46797403Sobrien    _InIter
46897403Sobrien    num_get<_CharT, _InIter>::
46997403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
47097403Sobrien           ios_base::iostate& __err, long& __v) const
47197403Sobrien    {
47297403Sobrien      string __xtrc;
47397403Sobrien      int __base;
47497403Sobrien      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
47597403Sobrien      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
47697403Sobrien      return __beg;
47797403Sobrien    }
47897403Sobrien
47997403Sobrien  template<typename _CharT, typename _InIter>
48097403Sobrien    _InIter
48197403Sobrien    num_get<_CharT, _InIter>::
48297403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
48397403Sobrien           ios_base::iostate& __err, unsigned short& __v) const
48497403Sobrien    {
48597403Sobrien      string __xtrc;
48697403Sobrien      int __base;
48797403Sobrien      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
48897403Sobrien      unsigned long __ul;
48997403Sobrien      __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
49097403Sobrien      if (!(__err & ios_base::failbit) 
49197403Sobrien	  && __ul <= numeric_limits<unsigned short>::max())
49297403Sobrien	__v = static_cast<unsigned short>(__ul);
49397403Sobrien      else 
49497403Sobrien	__err |= ios_base::failbit;
49597403Sobrien      return __beg;
49697403Sobrien    }
49797403Sobrien
49897403Sobrien  template<typename _CharT, typename _InIter>
49997403Sobrien    _InIter
50097403Sobrien    num_get<_CharT, _InIter>::
50197403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
50297403Sobrien           ios_base::iostate& __err, unsigned int& __v) const
50397403Sobrien    {
50497403Sobrien      string __xtrc;
50597403Sobrien      int __base;
50697403Sobrien      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
50797403Sobrien      unsigned long __ul;
50897403Sobrien      __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
50997403Sobrien      if (!(__err & ios_base::failbit) 
51097403Sobrien	  && __ul <= numeric_limits<unsigned int>::max())
51197403Sobrien	__v = static_cast<unsigned int>(__ul);
51297403Sobrien      else 
51397403Sobrien	__err |= ios_base::failbit;
51497403Sobrien      return __beg;
51597403Sobrien    }
51697403Sobrien
51797403Sobrien  template<typename _CharT, typename _InIter>
51897403Sobrien    _InIter
51997403Sobrien    num_get<_CharT, _InIter>::
52097403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
52197403Sobrien           ios_base::iostate& __err, unsigned long& __v) const
52297403Sobrien    {
52397403Sobrien      string __xtrc;
52497403Sobrien      int __base;
52597403Sobrien      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
52697403Sobrien      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
52797403Sobrien      return __beg;
52897403Sobrien    }
52997403Sobrien
53097403Sobrien#ifdef _GLIBCPP_USE_LONG_LONG
53197403Sobrien  template<typename _CharT, typename _InIter>
53297403Sobrien    _InIter
53397403Sobrien    num_get<_CharT, _InIter>::
53497403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
53597403Sobrien           ios_base::iostate& __err, long long& __v) const
53697403Sobrien    {
53797403Sobrien      string __xtrc;
53897403Sobrien      int __base;
53997403Sobrien      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
54097403Sobrien      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
54197403Sobrien      return __beg;
54297403Sobrien    }
54397403Sobrien
54497403Sobrien  template<typename _CharT, typename _InIter>
54597403Sobrien    _InIter
54697403Sobrien    num_get<_CharT, _InIter>::
54797403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
54897403Sobrien           ios_base::iostate& __err, unsigned long long& __v) const
54997403Sobrien    {
55097403Sobrien      string __xtrc;
55197403Sobrien      int __base;
55297403Sobrien      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
55397403Sobrien      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
55497403Sobrien      return __beg;
55597403Sobrien    }
55697403Sobrien#endif
55797403Sobrien
55897403Sobrien  template<typename _CharT, typename _InIter>
55997403Sobrien    _InIter
56097403Sobrien    num_get<_CharT, _InIter>::
56197403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io, 
56297403Sobrien	   ios_base::iostate& __err, float& __v) const
56397403Sobrien    {
56497403Sobrien      string __xtrc;
56597403Sobrien      __xtrc.reserve(32);
56697403Sobrien      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
56797403Sobrien      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
56897403Sobrien      return __beg;
56997403Sobrien    }
57097403Sobrien
57197403Sobrien  template<typename _CharT, typename _InIter>
57297403Sobrien    _InIter
57397403Sobrien    num_get<_CharT, _InIter>::
57497403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
57597403Sobrien           ios_base::iostate& __err, double& __v) const
57697403Sobrien    {
57797403Sobrien      string __xtrc;
57897403Sobrien      __xtrc.reserve(32);
57997403Sobrien      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
58097403Sobrien      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
58197403Sobrien      return __beg;
58297403Sobrien    }
58397403Sobrien
58497403Sobrien  template<typename _CharT, typename _InIter>
58597403Sobrien    _InIter
58697403Sobrien    num_get<_CharT, _InIter>::
58797403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
58897403Sobrien           ios_base::iostate& __err, long double& __v) const
58997403Sobrien    {
59097403Sobrien      string __xtrc;
59197403Sobrien      __xtrc.reserve(32);
59297403Sobrien      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
59397403Sobrien      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
59497403Sobrien      return __beg;
59597403Sobrien    }
59697403Sobrien
59797403Sobrien  template<typename _CharT, typename _InIter>
59897403Sobrien    _InIter
59997403Sobrien    num_get<_CharT, _InIter>::
60097403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
60197403Sobrien           ios_base::iostate& __err, void*& __v) const
60297403Sobrien    {
60397403Sobrien      // Prepare for hex formatted input
60497403Sobrien      typedef ios_base::fmtflags        fmtflags;
60597403Sobrien      fmtflags __fmt = __io.flags();
60697403Sobrien      fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield
60797403Sobrien                             | ios_base::uppercase | ios_base::internal);
60897403Sobrien      __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase));
60997403Sobrien
61097403Sobrien      string __xtrc;
61197403Sobrien      int __base;
61297403Sobrien      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
61397403Sobrien
61497403Sobrien      // Reset from hex formatted input
61597403Sobrien      __io.flags(__fmt);
61697403Sobrien
61797403Sobrien      unsigned long __ul;
61897403Sobrien      __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
61997403Sobrien      if (!(__err & ios_base::failbit))
62097403Sobrien	__v = reinterpret_cast<void*>(__ul);
62197403Sobrien      else 
62297403Sobrien	__err |= ios_base::failbit;
62397403Sobrien      return __beg;
62497403Sobrien    }
62597403Sobrien
626117397Skan  // For use by integer and floating-point types after they have been
627117397Skan  // converted into a char_type string.
628117397Skan  template<typename _CharT, typename _OutIter>
629117397Skan    void
630117397Skan    num_put<_CharT, _OutIter>::
631117397Skan    _M_pad(_CharT __fill, streamsize __w, ios_base& __io, 
632117397Skan	   _CharT* __new, const _CharT* __cs, int& __len) const
633117397Skan    {
634117397Skan      // [22.2.2.2.2] Stage 3.
635117397Skan      // If necessary, pad.
636117397Skan      __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs, 
637117397Skan						  __w, __len, true);
638117397Skan      __len = static_cast<int>(__w);
639117397Skan    }
640117397Skan
641117397Skan  // Forwarding functions to peel signed from unsigned integer types.
642117397Skan  template<typename _CharT>
643117397Skan    inline int
644117397Skan    __int_to_char(_CharT* __out, const int __size, long __v,
645117397Skan		       const _CharT* __lit, ios_base::fmtflags __flags)
646117397Skan    {
647117397Skan      unsigned long __ul = static_cast<unsigned long>(__v);
648117397Skan      bool __neg = false;
649117397Skan      if (__v < 0) 
650117397Skan	{
651117397Skan	  __ul = -__ul;
652117397Skan	  __neg = true;
653117397Skan	}
654117397Skan      return __int_to_char(__out, __size, __ul, __lit, __flags, __neg); 
655117397Skan    }
656117397Skan
657117397Skan  template<typename _CharT>
658117397Skan    inline int
659117397Skan    __int_to_char(_CharT* __out, const int __size, unsigned long __v,
660117397Skan		       const _CharT* __lit, ios_base::fmtflags __flags)
661117397Skan    { return __int_to_char(__out, __size, __v, __lit, __flags, false); }
662117397Skan
663117397Skan#ifdef _GLIBCPP_USE_LONG_LONG
664117397Skan  template<typename _CharT>
665117397Skan    inline int
666117397Skan    __int_to_char(_CharT* __out, const int __size, long long __v,
667117397Skan		       const _CharT* __lit, ios_base::fmtflags __flags)
668117397Skan    { 
669117397Skan      unsigned long long __ull = static_cast<unsigned long long>(__v);
670117397Skan      bool __neg = false;
671117397Skan      if (__v < 0) 
672117397Skan	{
673117397Skan	  __ull = -__ull;
674117397Skan	  __neg = true;
675117397Skan	}
676117397Skan      return __int_to_char(__out, __size, __ull, __lit, __flags, __neg); 
677117397Skan    }
678117397Skan
679117397Skan  template<typename _CharT>
680117397Skan    inline int
681117397Skan    __int_to_char(_CharT* __out, const int __size, unsigned long long __v,
682117397Skan		       const _CharT* __lit, ios_base::fmtflags __flags)
683117397Skan    { return __int_to_char(__out, __size, __v, __lit, __flags, false); }
684117397Skan#endif
685117397Skan      
686117397Skan  template<typename _CharT, typename _ValueT>
687117397Skan    int
688117397Skan    __int_to_char(_CharT* __out, const int __size, _ValueT __v,
689117397Skan		  const _CharT* __lit, ios_base::fmtflags __flags, bool __neg)
690117397Skan    {
691117397Skan      // Don't write base if already 0.
692117397Skan      const bool __showbase = (__flags & ios_base::showbase) && __v;
693117397Skan      const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
694117397Skan      _CharT* __buf = __out + __size - 1;
695117397Skan      _CharT* __bufend = __out + __size;
696117397Skan
697117397Skan      if (__builtin_expect(__basefield != ios_base::oct &&
698117397Skan			   __basefield != ios_base::hex, true))
699117397Skan	{
700117397Skan	  // Decimal.
701117397Skan	  do 
702117397Skan	    {
703117397Skan	      *__buf-- = __lit[(__v % 10) + __num_base::_S_digits];
704117397Skan	      __v /= 10;
705117397Skan	    } 
706117397Skan	  while (__v != 0);
707117397Skan	  if (__neg)
708117397Skan	    *__buf-- = __lit[__num_base::_S_minus];
709117397Skan	  else if (__flags & ios_base::showpos)
710117397Skan	    *__buf-- = __lit[__num_base::_S_plus];
711117397Skan	}
712117397Skan      else if (__basefield == ios_base::oct)
713117397Skan	{
714117397Skan	  // Octal.
715117397Skan	  do 
716117397Skan	    {
717117397Skan	      *__buf-- = __lit[(__v & 0x7) + __num_base::_S_digits];
718117397Skan	      __v >>= 3;
719117397Skan	    } 
720117397Skan	  while (__v != 0);
721117397Skan	  if (__showbase)
722117397Skan	    *__buf-- = __lit[__num_base::_S_digits];
723117397Skan	}
724117397Skan      else
725117397Skan	{
726117397Skan	  // Hex.
727117397Skan	  const bool __uppercase = __flags & ios_base::uppercase;
728117397Skan	  int __case_offset = __uppercase
729117397Skan	                      ? __num_base::_S_udigits : __num_base::_S_digits;
730117397Skan	  do 
731117397Skan	    {
732117397Skan	      *__buf-- = __lit[(__v & 0xf) + __case_offset];
733117397Skan	      __v >>= 4;
734117397Skan	    } 
735117397Skan	  while (__v != 0);
736117397Skan	  if (__showbase)
737117397Skan	    {
738117397Skan	      // 'x' or 'X'
739117397Skan	      *__buf-- = __lit[__num_base::_S_x + __uppercase];
740117397Skan	      // '0'
741117397Skan	      *__buf-- = __lit[__num_base::_S_digits];
742117397Skan	    }
743117397Skan	}
744117397Skan      int __ret = __bufend - __buf - 1;
745117397Skan      return __ret;
746117397Skan    }
747117397Skan
748117397Skan  template<typename _CharT, typename _OutIter>
749117397Skan    void
750117397Skan    num_put<_CharT, _OutIter>::
751117397Skan    _M_group_int(const string& __grouping, _CharT __sep, ios_base& __io, 
752117397Skan		 _CharT* __new, _CharT* __cs, int& __len) const
753117397Skan    {
754117397Skan      // By itself __add_grouping cannot deal correctly with __ws when
755117397Skan      // ios::showbase is set and ios_base::oct || ios_base::hex.
756117397Skan      // Therefore we take care "by hand" of the initial 0, 0x or 0X.
757117397Skan      // However, remember that the latter do not occur if the number
758117397Skan      // printed is '0' (__len == 1).
759117397Skan      streamsize __off = 0;
760117397Skan      const ios_base::fmtflags __basefield = __io.flags() 
761117397Skan	                                     & ios_base::basefield;
762117397Skan      if ((__io.flags() & ios_base::showbase) && __len > 1)
763117397Skan	if (__basefield == ios_base::oct)
764117397Skan	  {
765117397Skan	    __off = 1;
766117397Skan	    *__new = *__cs;
767117397Skan	  }
768117397Skan	else if (__basefield == ios_base::hex)
769117397Skan	  {
770117397Skan	    __off = 2;
771117397Skan	    *__new = *__cs;
772117397Skan	    *(__new + 1) = *(__cs + 1);
773117397Skan	  }
774117397Skan      _CharT* __p;
775117397Skan      __p = __add_grouping(__new + __off, __sep, 
776117397Skan			   __grouping.c_str(),
777117397Skan			   __grouping.c_str() + __grouping.size(),
778117397Skan			   __cs + __off, __cs + __len);
779117397Skan      __len = __p - __new;
780117397Skan    }
781117397Skan
782117397Skan  template<typename _CharT, typename _OutIter>
783117397Skan    template<typename _ValueT>
784117397Skan      _OutIter
785117397Skan      num_put<_CharT, _OutIter>::
786117397Skan      _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, 
787117397Skan		     _ValueT __v) const
788117397Skan      {
789117397Skan	typedef numpunct<_CharT>  __facet_type;
790117397Skan	typedef __locale_cache<numpunct<_CharT> > __cache_type;
791117397Skan 	const locale& __loc = __io._M_getloc();
792117397Skan	const __cache_type& __lc = __use_cache<__facet_type>(__loc);
793117397Skan	const _CharT* __lit = __lc._M_atoms_out;
794117397Skan
795117397Skan	// Long enough to hold hex, dec, and octal representations.
796117397Skan	int __ilen = 4 * sizeof(_ValueT);
797117397Skan	_CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
798117397Skan							     * __ilen));
799117397Skan	// [22.2.2.2.2] Stage 1, numeric conversion to character.
800117397Skan	// Result is returned right-justified in the buffer.
801117397Skan	int __len;
802117397Skan	__len = __int_to_char(&__cs[0], __ilen, __v, __lit, __io.flags());
803117397Skan	__cs = __cs + __ilen - __len;
804117397Skan	
805117397Skan	// Add grouping, if necessary. 
806117397Skan	_CharT* __cs2;
807117397Skan	if (__lc._M_use_grouping)
808117397Skan	  {
809117397Skan	    // Grouping can add (almost) as many separators as the
810117397Skan	    // number of digits, but no more.
811117397Skan	    __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
812117397Skan							  * __len * 2));
813117397Skan	    _M_group_int(__lc._M_grouping, __lc._M_thousands_sep, __io, 
814117397Skan			 __cs2, __cs, __len);
815117397Skan	    __cs = __cs2;
816117397Skan	  }
817117397Skan	
818117397Skan	// Pad.
819117397Skan	_CharT* __cs3;
820117397Skan	streamsize __w = __io.width();
821117397Skan	if (__w > static_cast<streamsize>(__len))
822117397Skan	  {
823117397Skan	    __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
824117397Skan							  * __w));
825117397Skan	    _M_pad(__fill, __w, __io, __cs3, __cs, __len);
826117397Skan	    __cs = __cs3;
827117397Skan	  }
828117397Skan	__io.width(0);
829117397Skan
830117397Skan	// [22.2.2.2.2] Stage 4.
831117397Skan	// Write resulting, fully-formatted string to output iterator.
832117397Skan	return __write(__s, __cs, __len);
833117397Skan      } 
834117397Skan
835117397Skan  template<typename _CharT, typename _OutIter>
836117397Skan    void
837117397Skan    num_put<_CharT, _OutIter>::
838117397Skan    _M_group_float(const string& __grouping, _CharT __sep, const _CharT* __p, 
839117397Skan		   _CharT* __new, _CharT* __cs, int& __len) const
840117397Skan    {
841117397Skan#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
842117397Skan      //282. What types does numpunct grouping refer to?
843117397Skan      // Add grouping, if necessary. 
844117397Skan      _CharT* __p2;
845117397Skan      int __declen = __p ? __p - __cs : __len;
846117397Skan      __p2 = __add_grouping(__new, __sep, 
847117397Skan			    __grouping.c_str(),
848117397Skan			    __grouping.c_str() + __grouping.size(),
849117397Skan			    __cs, __cs + __declen);
850117397Skan      
851117397Skan      // Tack on decimal part.
852117397Skan      int __newlen = __p2 - __new;
853117397Skan      if (__p)
854117397Skan	{
855117397Skan	  char_traits<_CharT>::copy(__p2, __p, __len - __declen);
856117397Skan	  __newlen += __len - __declen;
857117397Skan	}    
858117397Skan      __len = __newlen;
859117397Skan#endif
860117397Skan    }
861117397Skan
862117397Skan  // The following code uses snprintf (or sprintf(), when
863117397Skan  // _GLIBCPP_USE_C99 is not defined) to convert floating point values
864117397Skan  // for insertion into a stream.  An optimization would be to replace
865117397Skan  // them with code that works directly on a wide buffer and then use
866117397Skan  // __pad to do the padding.  It would be good to replace them anyway
867117397Skan  // to gain back the efficiency that C++ provides by knowing up front
868117397Skan  // the type of the values to insert.  Also, sprintf is dangerous
869117397Skan  // since may lead to accidental buffer overruns.  This
870117397Skan  // implementation follows the C++ standard fairly directly as
87197403Sobrien  // outlined in 22.2.2.2 [lib.locale.num.put]
87297403Sobrien  template<typename _CharT, typename _OutIter>
87397403Sobrien    template<typename _ValueT>
87497403Sobrien      _OutIter
87597403Sobrien      num_put<_CharT, _OutIter>::
87697403Sobrien      _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
87797403Sobrien		       _ValueT __v) const
87897403Sobrien      {
879117397Skan	// Note: digits10 is rounded down: add 1 to ensure the maximum
880117397Skan	// available precision.  Then, in general, one more 1 needs to
881117397Skan	// be added since, when the %{g,G} conversion specifiers are
882117397Skan	// chosen inside _S_format_float, the precision field is "the
883117397Skan	// maximum number of significant digits", *not* the "number of
884117397Skan	// digits to appear after the decimal point", as happens for
885117397Skan	// %{e,E,f,F} (C99, 7.19.6.1,4).
886110614Skan	const int __max_digits = numeric_limits<_ValueT>::digits10 + 2;
887117397Skan
888117397Skan	// Use default precision if out of range.
88997403Sobrien	streamsize __prec = __io.precision();
89097403Sobrien	if (__prec > static_cast<streamsize>(__max_digits))
89197403Sobrien	  __prec = static_cast<streamsize>(__max_digits);
892117397Skan	else if (__prec < static_cast<streamsize>(0))
893117397Skan	  __prec = static_cast<streamsize>(6);
89497403Sobrien
895117397Skan	typedef numpunct<_CharT>  __facet_type;
896117397Skan	typedef __locale_cache<numpunct<_CharT> > __cache_type;
897117397Skan	const locale __loc = __io._M_getloc();
898117397Skan	const __cache_type& __lc = __use_cache<__facet_type>(__loc);
899117397Skan
900117397Skan	// [22.2.2.2.2] Stage 1, numeric conversion to character.
901117397Skan	int __len;
90297403Sobrien	// Long enough for the max format spec.
90397403Sobrien	char __fbuf[16];
90497403Sobrien
90597403Sobrien#ifdef _GLIBCPP_USE_C99
906117397Skan	// First try a buffer perhaps big enough (for sure sufficient
907117397Skan	// for non-ios_base::fixed outputs)
90897403Sobrien	int __cs_size = __max_digits * 3;
90997403Sobrien	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
91097403Sobrien
911117397Skan	_S_format_float(__io, __fbuf, __mod, __prec);
912117397Skan	__len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
913117397Skan				 _S_c_locale, __prec);
91497403Sobrien
91597403Sobrien	// If the buffer was not large enough, try again with the correct size.
91697403Sobrien	if (__len >= __cs_size)
91797403Sobrien	  {
91897403Sobrien	    __cs_size = __len + 1; 
91997403Sobrien	    __cs = static_cast<char*>(__builtin_alloca(__cs_size));
920117397Skan	    __len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
921117397Skan				     _S_c_locale, __prec);
92297403Sobrien	  }
92397403Sobrien#else
92497403Sobrien	// Consider the possibility of long ios_base::fixed outputs
92597403Sobrien	const bool __fixed = __io.flags() & ios_base::fixed;
92697403Sobrien	const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
927117397Skan
92897403Sobrien	// ios_base::fixed outputs may need up to __max_exp+1 chars
92997403Sobrien	// for the integer part + up to __max_digits chars for the
93097403Sobrien	// fractional part + 3 chars for sign, decimal point, '\0'. On
93197403Sobrien	// the other hand, for non-fixed outputs __max_digits*3 chars
93297403Sobrien	// are largely sufficient.
93397403Sobrien	const int __cs_size = __fixed ? __max_exp + __max_digits + 4 
93497403Sobrien	                              : __max_digits * 3;
93597403Sobrien	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
93697403Sobrien
937117397Skan	_S_format_float(__io, __fbuf, __mod, __prec);
938117397Skan	__len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec);
93997403Sobrien#endif
94097403Sobrien
94197403Sobrien      // [22.2.2.2.2] Stage 2, convert to char_type, using correct
94297403Sobrien      // numpunct.decimal_point() values for '.' and adding grouping.
94397403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
944117397Skan
94597403Sobrien      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
94697403Sobrien							   * __len));
94797403Sobrien      __ctype.widen(__cs, __cs + __len, __ws);
94897403Sobrien      
94997403Sobrien      // Replace decimal point.
950117397Skan      const _CharT __cdec = __ctype.widen('.');
951117397Skan      const _CharT __dec = __lc._M_decimal_point;
95297403Sobrien      const _CharT* __p;
953117397Skan      if (__p = char_traits<_CharT>::find(__ws, __len, __cdec))
954117397Skan	__ws[__p - __ws] = __dec;
95597403Sobrien
95697403Sobrien      // Add grouping, if necessary. 
957117397Skan      _CharT* __ws2;
958117397Skan      if (__lc._M_use_grouping)
95997403Sobrien	{
960117397Skan	    // Grouping can add (almost) as many separators as the
961117397Skan	    // number of digits, but no more.
962117397Skan	    __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
963117397Skan							  * __len * 2));
964117397Skan	    _M_group_float(__lc._M_grouping, __lc._M_thousands_sep, __p,
965117397Skan			   __ws2, __ws, __len);
966117397Skan	    __ws = __ws2;
96797403Sobrien	}
96897403Sobrien
969117397Skan      // Pad.
970117397Skan      _CharT* __ws3;
97197403Sobrien      streamsize __w = __io.width();
97297403Sobrien      if (__w > static_cast<streamsize>(__len))
97397403Sobrien	{
974117397Skan	  __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __w));
975117397Skan	  _M_pad(__fill, __w, __io, __ws3, __ws, __len);
976117397Skan	  __ws = __ws3;
97797403Sobrien	}
97897403Sobrien      __io.width(0);
979117397Skan      
98097403Sobrien      // [22.2.2.2.2] Stage 4.
98197403Sobrien      // Write resulting, fully-formatted string to output iterator.
982117397Skan      return __write(__s, __ws, __len);
983117397Skan      }
98497403Sobrien
98597403Sobrien  template<typename _CharT, typename _OutIter>
98697403Sobrien    _OutIter
98797403Sobrien    num_put<_CharT, _OutIter>::
98897403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
98997403Sobrien    {
99097403Sobrien      ios_base::fmtflags __flags = __io.flags();
99197403Sobrien      if ((__flags & ios_base::boolalpha) == 0)
99297403Sobrien        {
99397403Sobrien          unsigned long __uv = __v;
994117397Skan          __s = _M_convert_int(__s, __io, __fill, __uv);
99597403Sobrien        }
99697403Sobrien      else
99797403Sobrien        {
998117397Skan	  typedef numpunct<_CharT>  __facet_type;
999117397Skan	  typedef __locale_cache<numpunct<_CharT> > __cache_type;
1000117397Skan	  const locale __loc = __io._M_getloc();
1001117397Skan	  const __cache_type& __lc = __use_cache<__facet_type>(__loc);
1002117397Skan
1003117397Skan	  typedef basic_string<_CharT> 	__string_type;
100497403Sobrien	  __string_type __name;
100597403Sobrien          if (__v)
1006117397Skan	    __name = __lc._M_truename;
100797403Sobrien          else
1008117397Skan	    __name = __lc._M_falsename;
1009117397Skan
1010117397Skan	  const _CharT* __cs = __name.c_str();
1011117397Skan	  int __len = __name.size();
1012117397Skan	  _CharT* __cs3;
1013117397Skan	  streamsize __w = __io.width();
1014117397Skan	  if (__w > static_cast<streamsize>(__len))
1015117397Skan	    {
1016117397Skan	      __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
1017117397Skan							    * __w));
1018117397Skan	      _M_pad(__fill, __w, __io, __cs3, __cs, __len);
1019117397Skan	      __cs = __cs3;
1020117397Skan	    }
1021117397Skan	  __io.width(0);
1022117397Skan	  __s = __write(__s, __cs, __len);
102397403Sobrien	}
102497403Sobrien      return __s;
102597403Sobrien    }
102697403Sobrien
102797403Sobrien  template<typename _CharT, typename _OutIter>
102897403Sobrien    _OutIter
102997403Sobrien    num_put<_CharT, _OutIter>::
103097403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
1031117397Skan    { return _M_convert_int(__s, __io, __fill, __v); }
103297403Sobrien
103397403Sobrien  template<typename _CharT, typename _OutIter>
103497403Sobrien    _OutIter
103597403Sobrien    num_put<_CharT, _OutIter>::
103697403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill,
103797403Sobrien           unsigned long __v) const
1038117397Skan    { return _M_convert_int(__s, __io, __fill, __v); }
103997403Sobrien
104097403Sobrien#ifdef _GLIBCPP_USE_LONG_LONG
104197403Sobrien  template<typename _CharT, typename _OutIter>
104297403Sobrien    _OutIter
104397403Sobrien    num_put<_CharT, _OutIter>::
104497403Sobrien    do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
1045117397Skan    { return _M_convert_int(__s, __b, __fill, __v); }
104697403Sobrien
104797403Sobrien  template<typename _CharT, typename _OutIter>
104897403Sobrien    _OutIter
104997403Sobrien    num_put<_CharT, _OutIter>::
105097403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill,
105197403Sobrien           unsigned long long __v) const
1052117397Skan    { return _M_convert_int(__s, __io, __fill, __v); }
105397403Sobrien#endif
105497403Sobrien
105597403Sobrien  template<typename _CharT, typename _OutIter>
105697403Sobrien    _OutIter
105797403Sobrien    num_put<_CharT, _OutIter>::
105897403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
1059102782Skan    { return _M_convert_float(__s, __io, __fill, char(), __v); }
106097403Sobrien
106197403Sobrien  template<typename _CharT, typename _OutIter>
106297403Sobrien    _OutIter
106397403Sobrien    num_put<_CharT, _OutIter>::
106497403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill, 
106597403Sobrien	   long double __v) const
106697403Sobrien    { return _M_convert_float(__s, __io, __fill, 'L', __v); }
106797403Sobrien
106897403Sobrien  template<typename _CharT, typename _OutIter>
106997403Sobrien    _OutIter
107097403Sobrien    num_put<_CharT, _OutIter>::
107197403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill,
107297403Sobrien           const void* __v) const
107397403Sobrien    {
107497403Sobrien      ios_base::fmtflags __flags = __io.flags();
107597403Sobrien      ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield
107697403Sobrien				   | ios_base::uppercase | ios_base::internal);
107797403Sobrien      __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
107897403Sobrien      try 
107997403Sobrien	{
1080117397Skan	  __s = _M_convert_int(__s, __io, __fill, 
108197403Sobrien			       reinterpret_cast<unsigned long>(__v));
108297403Sobrien	  __io.flags(__flags);
108397403Sobrien	}
108497403Sobrien      catch (...) 
108597403Sobrien	{
108697403Sobrien	  __io.flags(__flags);
108797403Sobrien	  __throw_exception_again;
108897403Sobrien	}
108997403Sobrien      return __s;
109097403Sobrien    }
109197403Sobrien
109297403Sobrien
109397403Sobrien  template<typename _CharT, typename _InIter>
109497403Sobrien    _InIter
109597403Sobrien    money_get<_CharT, _InIter>::
109697403Sobrien    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 
109797403Sobrien	   ios_base::iostate& __err, long double& __units) const
109897403Sobrien    { 
109997403Sobrien      string_type __str;
110097403Sobrien      __beg = this->do_get(__beg, __end, __intl, __io, __err, __str); 
110197403Sobrien
110297403Sobrien      const int __n = numeric_limits<long double>::digits10;
110397403Sobrien      char* __cs = static_cast<char*>(__builtin_alloca(__n));
110497403Sobrien      const locale __loc = __io.getloc();
110597403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
110697403Sobrien      const _CharT* __wcs = __str.c_str();
110797403Sobrien      __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs);      
110897403Sobrien      __convert_to_v(__cs, __units, __err, _S_c_locale);
110997403Sobrien      return __beg;
111097403Sobrien    }
111197403Sobrien
111297403Sobrien  template<typename _CharT, typename _InIter>
111397403Sobrien    _InIter
111497403Sobrien    money_get<_CharT, _InIter>::
111597403Sobrien    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 
111697403Sobrien	   ios_base::iostate& __err, string_type& __units) const
111797403Sobrien    { 
111897403Sobrien      // These contortions are quite unfortunate.
111997403Sobrien      typedef moneypunct<_CharT, true> 		__money_true;
112097403Sobrien      typedef moneypunct<_CharT, false> 	__money_false;
112197403Sobrien      typedef money_base::part 			part;
112297403Sobrien      typedef typename string_type::size_type 	size_type;
112397403Sobrien
112497403Sobrien      const locale __loc = __io.getloc();
112597403Sobrien      const __money_true& __mpt = use_facet<__money_true>(__loc); 
112697403Sobrien      const __money_false& __mpf = use_facet<__money_false>(__loc); 
112797403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
112897403Sobrien
112997403Sobrien      const money_base::pattern __p = __intl ? __mpt.neg_format() 
113097403Sobrien					     : __mpf.neg_format();
113197403Sobrien
113297403Sobrien      const string_type __pos_sign =__intl ? __mpt.positive_sign() 
113397403Sobrien					   : __mpf.positive_sign();
113497403Sobrien      const string_type __neg_sign =__intl ? __mpt.negative_sign() 
113597403Sobrien					   : __mpf.negative_sign();
113697403Sobrien      const char_type __d = __intl ? __mpt.decimal_point() 
113797403Sobrien  	    	       		   : __mpf.decimal_point();
113897403Sobrien      const char_type __sep = __intl ? __mpt.thousands_sep() 
113997403Sobrien		    		     : __mpf.thousands_sep();
114097403Sobrien
114197403Sobrien      const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping();
114297403Sobrien
114397403Sobrien      // Set to deduced positive or negative sign, depending.
114497403Sobrien      string_type __sign;
114597403Sobrien      // String of grouping info from thousands_sep plucked from __units.
114697403Sobrien      string __grouping_tmp; 
114797403Sobrien      // Marker for thousands_sep position.
114897403Sobrien      int __sep_pos = 0;
114997403Sobrien      // If input iterator is in a valid state.
115097403Sobrien      bool __testvalid = true;
115197403Sobrien      // Flag marking when a decimal point is found.
115297403Sobrien      bool __testdecfound = false; 
115397403Sobrien
115497403Sobrien      // The tentative returned string is stored here.
115597403Sobrien      string_type __temp_units;
115697403Sobrien
115797403Sobrien      char_type __c = *__beg;
115897403Sobrien      char_type __eof = static_cast<char_type>(char_traits<char_type>::eof());
115997403Sobrien      for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i)
116097403Sobrien	{
116197403Sobrien	  part __which = static_cast<part>(__p.field[__i]);
116297403Sobrien	  switch (__which)
116397403Sobrien		{
116497403Sobrien		case money_base::symbol:
116597403Sobrien		  if (__io.flags() & ios_base::showbase 
116697403Sobrien		      || __i < 2 || __sign.size() > 1
116797403Sobrien		      || ((static_cast<part>(__p.field[3]) != money_base::none)
116897403Sobrien			  && __i == 2)) 
116997403Sobrien		    {
117097403Sobrien		      // According to 22.2.6.1.2.2, symbol is required
117197403Sobrien		      // if (__io.flags() & ios_base::showbase),
117297403Sobrien		      // otherwise is optional and consumed only if
117397403Sobrien		      // other characters are needed to complete the
117497403Sobrien		      // format.
117597403Sobrien		      const string_type __symbol = __intl ? __mpt.curr_symbol()
117697403Sobrien						    	 : __mpf.curr_symbol();
117797403Sobrien		      size_type __len = __symbol.size();
117897403Sobrien		      size_type __j = 0;
117997403Sobrien		      while (__beg != __end 
118097403Sobrien			     && __j < __len && __symbol[__j] == __c)
118197403Sobrien			{
118297403Sobrien			  __c = *(++__beg);
118397403Sobrien			  ++__j;
118497403Sobrien			}
118597403Sobrien		      // When (__io.flags() & ios_base::showbase)
118697403Sobrien		      // symbol is required.
118797403Sobrien		      if (__j != __len && (__io.flags() & ios_base::showbase))
118897403Sobrien			__testvalid = false;
118997403Sobrien		    }
119097403Sobrien		  break;
119197403Sobrien		case money_base::sign:		    
119297403Sobrien		  // Sign might not exist, or be more than one character long. 
119397403Sobrien		  if (__pos_sign.size() && __neg_sign.size())
119497403Sobrien		  {
119597403Sobrien		    // Sign is mandatory.
119697403Sobrien		    if (__c == __pos_sign[0])
119797403Sobrien		      {
119897403Sobrien			__sign = __pos_sign;
119997403Sobrien			__c = *(++__beg);
120097403Sobrien		      }
120197403Sobrien		    else if (__c == __neg_sign[0])
120297403Sobrien		      {
120397403Sobrien			__sign = __neg_sign;
120497403Sobrien			__c = *(++__beg);
120597403Sobrien		      }
120697403Sobrien		    else
120797403Sobrien		      __testvalid = false;
120897403Sobrien		  }
120997403Sobrien		  else if (__pos_sign.size() && __c == __pos_sign[0])
121097403Sobrien		    {
121197403Sobrien		      __sign = __pos_sign;
121297403Sobrien		      __c = *(++__beg);
121397403Sobrien		    }
121497403Sobrien		  else if (__neg_sign.size() && __c == __neg_sign[0])
121597403Sobrien		    {
121697403Sobrien		      __sign = __neg_sign;
121797403Sobrien		      __c = *(++__beg);
121897403Sobrien		    }
121997403Sobrien		  break;
122097403Sobrien		case money_base::value:
122197403Sobrien		  // Extract digits, remove and stash away the
122297403Sobrien		  // grouping of found thousands separators.
122397403Sobrien		  while (__beg != __end 
122497403Sobrien			 && (__ctype.is(ctype_base::digit, __c) 
122597403Sobrien			     || (__c == __d && !__testdecfound)
122697403Sobrien			     || __c == __sep))
122797403Sobrien		    {
122897403Sobrien		      if (__c == __d)
122997403Sobrien			{
123097403Sobrien			  __grouping_tmp += static_cast<char>(__sep_pos);
123197403Sobrien			  __sep_pos = 0;
123297403Sobrien			  __testdecfound = true;
123397403Sobrien			}
123497403Sobrien		      else if (__c == __sep)
123597403Sobrien			{
123697403Sobrien			  if (__grouping.size())
123797403Sobrien			    {
123897403Sobrien			      // Mark position for later analysis.
123997403Sobrien			      __grouping_tmp += static_cast<char>(__sep_pos);
124097403Sobrien			      __sep_pos = 0;
124197403Sobrien			    }
124297403Sobrien			  else
124397403Sobrien			    {
124497403Sobrien			      __testvalid = false;
124597403Sobrien			      break;
124697403Sobrien			    }
124797403Sobrien			}
124897403Sobrien		      else
124997403Sobrien			{
125097403Sobrien			  __temp_units += __c;
125197403Sobrien			  ++__sep_pos;
125297403Sobrien			}
125397403Sobrien		      __c = *(++__beg);
125497403Sobrien		    }
125597403Sobrien		  break;
125697403Sobrien		case money_base::space:
125797403Sobrien		case money_base::none:
125897403Sobrien		  // Only if not at the end of the pattern.
125997403Sobrien		  if (__i != 3)
126097403Sobrien		    while (__beg != __end 
126197403Sobrien			   && __ctype.is(ctype_base::space, __c))
126297403Sobrien		      __c = *(++__beg);
126397403Sobrien		  break;
126497403Sobrien		}
126597403Sobrien	}
126697403Sobrien
126797403Sobrien      // Need to get the rest of the sign characters, if they exist.
126897403Sobrien      if (__sign.size() > 1)
126997403Sobrien	{
127097403Sobrien	  size_type __len = __sign.size();
127197403Sobrien	  size_type __i = 1;
127297403Sobrien	  for (; __c != __eof && __i < __len; ++__i)
127397403Sobrien	    while (__beg != __end && __c != __sign[__i])
127497403Sobrien	      __c = *(++__beg);
127597403Sobrien	  
127697403Sobrien	  if (__i != __len)
127797403Sobrien	    __testvalid = false;
127897403Sobrien	}
127997403Sobrien
128097403Sobrien      // Strip leading zeros.
128197403Sobrien      while (__temp_units[0] == __ctype.widen('0'))
128297403Sobrien	__temp_units.erase(__temp_units.begin());
128397403Sobrien
128497403Sobrien      if (__sign.size() && __sign == __neg_sign)
128597403Sobrien	__temp_units.insert(__temp_units.begin(), __ctype.widen('-'));
128697403Sobrien
128797403Sobrien      // Test for grouping fidelity.
128897403Sobrien      if (__grouping.size() && __grouping_tmp.size())
128997403Sobrien	{
129097403Sobrien	  if (!__verify_grouping(__grouping, __grouping_tmp))
129197403Sobrien	    __testvalid = false;
129297403Sobrien	}
129397403Sobrien
129497403Sobrien      // Iff no more characters are available.      
129597403Sobrien      if (__c == __eof)
129697403Sobrien	__err |= ios_base::eofbit;
129797403Sobrien
129897403Sobrien      // Iff valid sequence is not recognized.
129997403Sobrien      if (!__testvalid || !__temp_units.size())
130097403Sobrien	__err |= ios_base::failbit;
130197403Sobrien      else
130297403Sobrien	// Use the "swap trick" to copy __temp_units into __units.
130397403Sobrien	__temp_units.swap(__units);
130497403Sobrien
130597403Sobrien      return __beg; 
130697403Sobrien    }
130797403Sobrien
130897403Sobrien  template<typename _CharT, typename _OutIter>
130997403Sobrien    _OutIter
131097403Sobrien    money_put<_CharT, _OutIter>::
131197403Sobrien    do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
131297403Sobrien	   long double __units) const
131397403Sobrien    { 
131497403Sobrien      const locale __loc = __io.getloc();
131597403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
131697403Sobrien#ifdef _GLIBCPP_USE_C99
131797403Sobrien      // First try a buffer perhaps big enough.
131897403Sobrien      int __cs_size = 64;
131997403Sobrien      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
132097403Sobrien      int __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 
132197403Sobrien				   _S_c_locale);
132297403Sobrien      // If the buffer was not large enough, try again with the correct size.
132397403Sobrien      if (__len >= __cs_size)
132497403Sobrien	{
132597403Sobrien	  __cs_size = __len + 1;
132697403Sobrien	  __cs = static_cast<char*>(__builtin_alloca(__cs_size));
132797403Sobrien	  __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 
132897403Sobrien				   _S_c_locale);
132997403Sobrien	}
133097403Sobrien#else
133197403Sobrien      // max_exponent10 + 1 for the integer part, + 4 for sign, decimal point,
133297403Sobrien      // decimal digit, '\0'. 
133397403Sobrien      const int __cs_size = numeric_limits<long double>::max_exponent10 + 5;
133497403Sobrien      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
133597403Sobrien      int __len = __convert_from_v(__cs, 0, "%.01Lf", __units, _S_c_locale);
133697403Sobrien#endif
1337117397Skan      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
1338117397Skan							   * __cs_size));
133997403Sobrien      __ctype.widen(__cs, __cs + __len, __ws);
134097403Sobrien      string_type __digits(__ws);
134197403Sobrien      return this->do_put(__s, __intl, __io, __fill, __digits); 
134297403Sobrien    }
134397403Sobrien
134497403Sobrien  template<typename _CharT, typename _OutIter>
134597403Sobrien    _OutIter
134697403Sobrien    money_put<_CharT, _OutIter>::
134797403Sobrien    do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
134897403Sobrien	   const string_type& __digits) const
134997403Sobrien    { 
135097403Sobrien      typedef typename string_type::size_type 	size_type;
135197403Sobrien      typedef money_base::part 			part;
135297403Sobrien
135397403Sobrien      const locale __loc = __io.getloc();
135497403Sobrien      const size_type __width = static_cast<size_type>(__io.width());
135597403Sobrien
135697403Sobrien      // These contortions are quite unfortunate.
135797403Sobrien      typedef moneypunct<_CharT, true> __money_true;
135897403Sobrien      typedef moneypunct<_CharT, false> __money_false;
135997403Sobrien      const __money_true& __mpt = use_facet<__money_true>(__loc); 
136097403Sobrien      const __money_false& __mpf = use_facet<__money_false>(__loc); 
136197403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
136297403Sobrien
136397403Sobrien      // Determine if negative or positive formats are to be used, and
136497403Sobrien      // discard leading negative_sign if it is present.
136597403Sobrien      const char_type* __beg = __digits.data();
136697403Sobrien      const char_type* __end = __beg + __digits.size();
136797403Sobrien      money_base::pattern __p;
136897403Sobrien      string_type __sign;
136997403Sobrien      if (*__beg != __ctype.widen('-'))
137097403Sobrien	{
137197403Sobrien	  __p = __intl ? __mpt.pos_format() : __mpf.pos_format();
137297403Sobrien	  __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign();
137397403Sobrien	}
137497403Sobrien      else
137597403Sobrien	{
137697403Sobrien	  __p = __intl ? __mpt.neg_format() : __mpf.neg_format();
137797403Sobrien	  __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign();
137897403Sobrien	  ++__beg;
137997403Sobrien	}
138097403Sobrien      
138197403Sobrien      // Look for valid numbers in the current ctype facet within input digits.
138297403Sobrien      __end = __ctype.scan_not(ctype_base::digit, __beg, __end);
138397403Sobrien      if (__beg != __end)
138497403Sobrien	{
138597403Sobrien	  // Assume valid input, and attempt to format.
138697403Sobrien	  // Break down input numbers into base components, as follows:
138797403Sobrien	  //   final_value = grouped units + (decimal point) + (digits)
138897403Sobrien	  string_type __res;
138997403Sobrien	  string_type __value;
139097403Sobrien	  const string_type __symbol = __intl ? __mpt.curr_symbol() 
139197403Sobrien	    				      : __mpf.curr_symbol();
139297403Sobrien
139397403Sobrien	  // Deal with decimal point, decimal digits.
139497403Sobrien	  const int __frac = __intl ? __mpt.frac_digits() 
139597403Sobrien	    			    : __mpf.frac_digits();
139697403Sobrien	  if (__frac > 0)
139797403Sobrien	    {
139897403Sobrien	      const char_type __d = __intl ? __mpt.decimal_point() 
139997403Sobrien					   : __mpf.decimal_point();
140097403Sobrien	      if (__end - __beg >= __frac)
140197403Sobrien		{
140297403Sobrien		  __value = string_type(__end - __frac, __end);
140397403Sobrien		  __value.insert(__value.begin(), __d);
140497403Sobrien		  __end -= __frac;
140597403Sobrien		}
140697403Sobrien	      else
140797403Sobrien		{
140897403Sobrien		  // Have to pad zeros in the decimal position.
140997403Sobrien		  __value = string_type(__beg, __end);
141097403Sobrien		  int __paddec = __frac - (__end - __beg);
141197403Sobrien		  char_type __zero = __ctype.widen('0');
141297403Sobrien		  __value.insert(__value.begin(), __paddec, __zero);
141397403Sobrien		  __value.insert(__value.begin(), __d);
141497403Sobrien		  __beg = __end;
141597403Sobrien		}
141697403Sobrien	    }
141797403Sobrien
141897403Sobrien	  // Add thousands separators to non-decimal digits, per
141997403Sobrien	  // grouping rules.
142097403Sobrien	  if (__beg != __end)
142197403Sobrien	    {
142297403Sobrien	      const string __grouping = __intl ? __mpt.grouping() 
142397403Sobrien					       : __mpf.grouping();
142497403Sobrien	      if (__grouping.size())
142597403Sobrien		{
142697403Sobrien		  const char_type __sep = __intl ? __mpt.thousands_sep() 
142797403Sobrien		    			         : __mpf.thousands_sep();
142897403Sobrien		  const char* __gbeg = __grouping.c_str();
142997403Sobrien		  const char* __gend = __gbeg + __grouping.size();
143097403Sobrien		  const int __n = (__end - __beg) * 2;
143197403Sobrien		  _CharT* __ws2 =
1432117397Skan       	          static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
143397403Sobrien		  _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg, 
143497403Sobrien						    __gend, __beg, __end);
143597403Sobrien		  __value.insert(0, __ws2, __ws_end - __ws2);
143697403Sobrien		}
143797403Sobrien	      else
143897403Sobrien		__value.insert(0, string_type(__beg, __end));
143997403Sobrien	    }
144097403Sobrien
144197403Sobrien	  // Calculate length of resulting string.
144297403Sobrien	  ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield;
144397403Sobrien	  size_type __len = __value.size() + __sign.size();
144497403Sobrien	  __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0;
144597403Sobrien	  bool __testipad = __f == ios_base::internal && __len < __width;
144697403Sobrien
144797403Sobrien	  // Fit formatted digits into the required pattern.
144897403Sobrien	  for (int __i = 0; __i < 4; ++__i)
144997403Sobrien	    {
145097403Sobrien	      part __which = static_cast<part>(__p.field[__i]);
145197403Sobrien	      switch (__which)
145297403Sobrien		{
145397403Sobrien		case money_base::symbol:
145497403Sobrien		  if (__io.flags() & ios_base::showbase)
145597403Sobrien		    __res += __symbol;
145697403Sobrien		  break;
145797403Sobrien		case money_base::sign:		    
145897403Sobrien		  // Sign might not exist, or be more than one
145997403Sobrien		  // charater long. In that case, add in the rest
146097403Sobrien		  // below.
146197403Sobrien		  if (__sign.size())
146297403Sobrien		    __res += __sign[0];
146397403Sobrien		  break;
146497403Sobrien		case money_base::value:
146597403Sobrien		  __res += __value;
146697403Sobrien		  break;
146797403Sobrien		case money_base::space:
146897403Sobrien		  // At least one space is required, but if internal
146997403Sobrien		  // formatting is required, an arbitrary number of
147097403Sobrien		  // fill spaces will be necessary.
147197403Sobrien		  if (__testipad)
147297403Sobrien		    __res += string_type(__width - __len, __fill);
147397403Sobrien		  else
147497403Sobrien		    __res += __ctype.widen(__fill);
147597403Sobrien		  break;
147697403Sobrien		case money_base::none:
147797403Sobrien		  if (__testipad)
147897403Sobrien		    __res += string_type(__width - __len, __fill);
147997403Sobrien		  break;
148097403Sobrien		}
148197403Sobrien	    }
148297403Sobrien
148397403Sobrien	  // Special case of multi-part sign parts.
148497403Sobrien	  if (__sign.size() > 1)
148597403Sobrien	    __res += string_type(__sign.begin() + 1, __sign.end());
148697403Sobrien
148797403Sobrien	  // Pad, if still necessary.
148897403Sobrien	  __len = __res.size();
148997403Sobrien	  if (__width > __len)
149097403Sobrien	    {
149197403Sobrien	      if (__f == ios_base::left)
149297403Sobrien		// After.
149397403Sobrien		__res.append(__width - __len, __fill);
149497403Sobrien	      else
149597403Sobrien		// Before.
149697403Sobrien		__res.insert(0, string_type(__width - __len, __fill));
149797403Sobrien	      __len = __width;
149897403Sobrien	    }
149997403Sobrien
150097403Sobrien	  // Write resulting, fully-formatted string to output iterator.
1501117397Skan	  __s = __write(__s, __res.c_str(), __len);
150297403Sobrien	}
150397403Sobrien      __io.width(0);
150497403Sobrien      return __s; 
150597403Sobrien    }
150697403Sobrien
150797403Sobrien
150897403Sobrien  // NB: Not especially useful. Without an ios_base object or some
150997403Sobrien  // kind of locale reference, we are left clawing at the air where
151097403Sobrien  // the side of the mountain used to be...
151197403Sobrien  template<typename _CharT, typename _InIter>
151297403Sobrien    time_base::dateorder
151397403Sobrien    time_get<_CharT, _InIter>::do_date_order() const
151497403Sobrien    { return time_base::no_order; }
151597403Sobrien
151697403Sobrien  template<typename _CharT, typename _InIter>
151797403Sobrien    void
151897403Sobrien    time_get<_CharT, _InIter>::
151997403Sobrien    _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io,
152097403Sobrien			  ios_base::iostate& __err, tm* __tm, 
152197403Sobrien			  const _CharT* __format) const
152297403Sobrien    {  
152397403Sobrien      locale __loc = __io.getloc();
152497403Sobrien      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
152597403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
152697403Sobrien      size_t __len = char_traits<_CharT>::length(__format);
152797403Sobrien
152897403Sobrien      for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
152997403Sobrien	{
153097403Sobrien	  char __c = __format[__i];
153197403Sobrien	  if (__c == '%')
153297403Sobrien	    {
153397403Sobrien	      // Verify valid formatting code, attempt to extract.
153497403Sobrien	      __c = __format[++__i];
153597403Sobrien	      char __mod = 0;
153697403Sobrien	      int __mem = 0; 
153797403Sobrien	      if (__c == 'E' || __c == 'O')
153897403Sobrien		{
153997403Sobrien		  __mod = __c;
154097403Sobrien		  __c = __format[++__i];
154197403Sobrien		}
154297403Sobrien	      switch (__c)
154397403Sobrien		{
154497403Sobrien		  const char* __cs;
154597403Sobrien		  _CharT __wcs[10];
154697403Sobrien		case 'a':
154797403Sobrien		  // Abbreviated weekday name [tm_wday]
154897403Sobrien		  const char_type*  __days1[7];
154997403Sobrien		  __tp._M_days_abbreviated(__days1);
155097403Sobrien		  _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7, 
155197403Sobrien				  __err);
155297403Sobrien		  break;
155397403Sobrien		case 'A':
155497403Sobrien		  // Weekday name [tm_wday].
155597403Sobrien		  const char_type*  __days2[7];
155697403Sobrien		  __tp._M_days(__days2);
155797403Sobrien		  _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7, 
155897403Sobrien				  __err);
155997403Sobrien		  break;
156097403Sobrien		case 'h':
156197403Sobrien		case 'b':
156297403Sobrien		  // Abbreviated month name [tm_mon]
156397403Sobrien		  const char_type*  __months1[12];
156497403Sobrien		  __tp._M_months_abbreviated(__months1);
156597403Sobrien		  _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12, 
156697403Sobrien				  __err);
156797403Sobrien		  break;
156897403Sobrien		case 'B':
156997403Sobrien		  // Month name [tm_mon].
157097403Sobrien		  const char_type*  __months2[12];
157197403Sobrien		  __tp._M_months(__months2);
157297403Sobrien		  _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12, 
157397403Sobrien				  __err);
157497403Sobrien		  break;
157597403Sobrien		case 'c':
157697403Sobrien		  // Default time and date representation.
157797403Sobrien		  const char_type*  __dt[2];
157897403Sobrien		  __tp._M_date_time_formats(__dt);
157997403Sobrien		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
158097403Sobrien					__dt[0]);
158197403Sobrien		  break;
158297403Sobrien		case 'd':
158397403Sobrien		  // Day [01, 31]. [tm_mday]
158497403Sobrien		  _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, 
158597403Sobrien				 __ctype, __err);
158697403Sobrien		  break;
158797403Sobrien		case 'D':
158897403Sobrien		  // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
158997403Sobrien		  __cs = "%m/%d/%y";
159097403Sobrien		  __ctype.widen(__cs, __cs + 9, __wcs);
159197403Sobrien		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
159297403Sobrien					__wcs);
159397403Sobrien		  break;
159497403Sobrien		case 'H':
159597403Sobrien		  // Hour [00, 23]. [tm_hour]
159697403Sobrien		  _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
159797403Sobrien				 __ctype, __err);
159897403Sobrien		  break;
159997403Sobrien		case 'I':
160097403Sobrien		  // Hour [01, 12]. [tm_hour]
160197403Sobrien		  _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, 
160297403Sobrien				 __ctype, __err);
160397403Sobrien		  break;
160497403Sobrien		case 'm':
160597403Sobrien		  // Month [01, 12]. [tm_mon]
160697403Sobrien		  _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype, 
160797403Sobrien				 __err);
160897403Sobrien		  if (!__err)
160997403Sobrien		    __tm->tm_mon = __mem - 1;
161097403Sobrien		  break;
161197403Sobrien		case 'M':
161297403Sobrien		  // Minute [00, 59]. [tm_min]
161397403Sobrien		  _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
161497403Sobrien				 __ctype, __err);
161597403Sobrien		  break;
161697403Sobrien		case 'n':
161797403Sobrien		  if (__ctype.narrow(*__beg, 0) == '\n')
161897403Sobrien		    ++__beg;
161997403Sobrien		  else
162097403Sobrien		    __err |= ios_base::failbit;
162197403Sobrien		  break;
162297403Sobrien		case 'R':
162397403Sobrien		  // Equivalent to (%H:%M).
162497403Sobrien		  __cs = "%H:%M";
162597403Sobrien		  __ctype.widen(__cs, __cs + 6, __wcs);
162697403Sobrien		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
162797403Sobrien					__wcs);
162897403Sobrien		  break;
162997403Sobrien		case 'S':
163097403Sobrien		  // Seconds.
163197403Sobrien		  _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2,
163297403Sobrien				 __ctype, __err);
163397403Sobrien		  break;
163497403Sobrien		case 't':
163597403Sobrien		  if (__ctype.narrow(*__beg, 0) == '\t')
163697403Sobrien		    ++__beg;
163797403Sobrien		  else
163897403Sobrien		__err |= ios_base::failbit;
163997403Sobrien		  break;
164097403Sobrien		case 'T':
164197403Sobrien		  // Equivalent to (%H:%M:%S).
164297403Sobrien		  __cs = "%H:%M:%S";
164397403Sobrien		  __ctype.widen(__cs, __cs + 9, __wcs);
164497403Sobrien		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
164597403Sobrien					__wcs);
164697403Sobrien		  break;
164797403Sobrien		case 'x':
164897403Sobrien		  // Locale's date.
164997403Sobrien		  const char_type*  __dates[2];
165097403Sobrien		  __tp._M_date_formats(__dates);
165197403Sobrien		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
165297403Sobrien					__dates[0]);
165397403Sobrien		  break;
165497403Sobrien		case 'X':
165597403Sobrien		  // Locale's time.
165697403Sobrien		  const char_type*  __times[2];
165797403Sobrien		  __tp._M_time_formats(__times);
165897403Sobrien		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
165997403Sobrien					__times[0]);
166097403Sobrien		  break;
166197403Sobrien		case 'y':
166297403Sobrien		  // Two digit year. [tm_year]
166397403Sobrien		  _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, 
166497403Sobrien				 __ctype, __err);
166597403Sobrien		  break;
166697403Sobrien		case 'Y':
166797403Sobrien		  // Year [1900). [tm_year]
166897403Sobrien		  _M_extract_num(__beg, __end, __mem, 0, 
166997403Sobrien				 numeric_limits<int>::max(), 4, 
167097403Sobrien				 __ctype, __err);
167197403Sobrien		  if (!__err)
167297403Sobrien		    __tm->tm_year = __mem - 1900;
167397403Sobrien		  break;
167497403Sobrien		case 'Z':
167597403Sobrien		  // Timezone info.
167697403Sobrien		  if (__ctype.is(ctype_base::upper, *__beg))
167797403Sobrien		    {
167897403Sobrien		      int __tmp;
167997403Sobrien		      _M_extract_name(__beg, __end, __tmp, 
168097403Sobrien				      __timepunct<_CharT>::_S_timezones, 
168197403Sobrien				      14, __err);
168297403Sobrien		      
168397403Sobrien		      // GMT requires special effort.
168497403Sobrien		      char_type __c = *__beg;
168597403Sobrien		      if (!__err && __tmp == 0 
168697403Sobrien			  && (__c == __ctype.widen('-') 
168797403Sobrien			      || __c == __ctype.widen('+')))
168897403Sobrien			{
168997403Sobrien			  _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
169097403Sobrien					  __ctype, __err);
169197403Sobrien			  _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
169297403Sobrien					  __ctype, __err);
169397403Sobrien			}	    
169497403Sobrien			  }
169597403Sobrien		      else
169697403Sobrien			__err |= ios_base::failbit;
169797403Sobrien		      break;
169897403Sobrien		    default:
169997403Sobrien		      // Not recognized.
170097403Sobrien		      __err |= ios_base::failbit;
170197403Sobrien		    }
170297403Sobrien		}
170397403Sobrien	      else
170497403Sobrien		{
170597403Sobrien		  // Verify format and input match, extract and discard.
170697403Sobrien		  if (__c == __ctype.narrow(*__beg, 0))
170797403Sobrien		    ++__beg;
170897403Sobrien		  else
170997403Sobrien		    __err |= ios_base::failbit;
171097403Sobrien		}
171197403Sobrien	}
171297403Sobrien    }
171397403Sobrien
171497403Sobrien  template<typename _CharT, typename _InIter>
171597403Sobrien    void
171697403Sobrien    time_get<_CharT, _InIter>::
171797403Sobrien    _M_extract_num(iter_type& __beg, iter_type& __end, int& __member,
171897403Sobrien		   int __min, int __max, size_t __len, 
171997403Sobrien		   const ctype<_CharT>& __ctype, 
172097403Sobrien		   ios_base::iostate& __err) const
172197403Sobrien    {
172297403Sobrien      size_t __i = 0;
172397403Sobrien      string __digits;
172497403Sobrien      bool __testvalid = true;
172597403Sobrien      char_type __c = *__beg;
172697403Sobrien      while (__beg != __end && __i < __len 
172797403Sobrien	     && __ctype.is(ctype_base::digit, __c)) 
172897403Sobrien	{
172997403Sobrien	  __digits += __ctype.narrow(__c, 0);
173097403Sobrien	  __c = *(++__beg);
173197403Sobrien	  ++__i;
173297403Sobrien	}
173397403Sobrien      if (__i == __len)
173497403Sobrien	{
173597403Sobrien	  int __value = atoi(__digits.c_str());
173697403Sobrien	  if (__min <= __value && __value <= __max)
173797403Sobrien	    __member = __value;
173897403Sobrien	  else
173997403Sobrien	    __testvalid = false;
174097403Sobrien	}
174197403Sobrien      else
174297403Sobrien	__testvalid = false;
174397403Sobrien      if (!__testvalid)
174497403Sobrien	__err |= ios_base::failbit;
174597403Sobrien    }
174697403Sobrien
174797403Sobrien  // Assumptions:
174897403Sobrien  // All elements in __names are unique.
174997403Sobrien  template<typename _CharT, typename _InIter>
175097403Sobrien    void
175197403Sobrien    time_get<_CharT, _InIter>::
175297403Sobrien    _M_extract_name(iter_type& __beg, iter_type& __end, int& __member,
175397403Sobrien		    const _CharT** __names, size_t __indexlen, 
175497403Sobrien		    ios_base::iostate& __err) const
175597403Sobrien    {
1756102782Skan      typedef char_traits<_CharT> 		__traits_type;
1757117397Skan      int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) 
1758117397Skan							  * __indexlen));
175997403Sobrien      size_t __nmatches = 0;
176097403Sobrien      size_t __pos = 0;
176197403Sobrien      bool __testvalid = true;
176297403Sobrien      const char_type* __name;
176397403Sobrien
176497403Sobrien      char_type __c = *__beg;
176597403Sobrien      // Look for initial matches.
176697403Sobrien      for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
176797403Sobrien	if (__c == __names[__i1][0])
176897403Sobrien	  __matches[__nmatches++] = __i1;
176997403Sobrien      
1770117397Skan      while (__nmatches > 1)
177197403Sobrien	{
177297403Sobrien	  // Find smallest matching string.
177397403Sobrien	  size_t __minlen = 10;
177497403Sobrien	  for (size_t __i2 = 0; __i2 < __nmatches; ++__i2)
1775110614Skan	    __minlen = min(__minlen,
177697403Sobrien			   __traits_type::length(__names[__matches[__i2]]));
177797403Sobrien	  
177897403Sobrien	  if (__pos < __minlen && __beg != __end)
177997403Sobrien	    {
178097403Sobrien	      ++__pos;
178197403Sobrien	      __c = *(++__beg);
178297403Sobrien	      for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
178397403Sobrien		{
178497403Sobrien		  __name = __names[__matches[__i3]];
178597403Sobrien		  if (__name[__pos] != __c)
178697403Sobrien		    __matches[__i3] = __matches[--__nmatches];
178797403Sobrien		}
178897403Sobrien	    }
178997403Sobrien	  else
179097403Sobrien	    break;
179197403Sobrien	}
179297403Sobrien
179397403Sobrien      if (__nmatches == 1)
179497403Sobrien	{
179597403Sobrien	  // Make sure found name is completely extracted.
179697403Sobrien	  __name = __names[__matches[0]];
179797403Sobrien	  const size_t __len = __traits_type::length(__name);
179897403Sobrien	  while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
179997403Sobrien	    ++__beg, ++__pos;
180097403Sobrien
180197403Sobrien	  if (__len == __pos)
180297403Sobrien	    __member = __matches[0];
180397403Sobrien	  else
180497403Sobrien	    __testvalid = false;
180597403Sobrien	}
180697403Sobrien      else
180797403Sobrien	__testvalid = false;
180897403Sobrien      if (!__testvalid)
180997403Sobrien	__err |= ios_base::failbit;
181097403Sobrien    }
181197403Sobrien
181297403Sobrien  template<typename _CharT, typename _InIter>
181397403Sobrien    _InIter
181497403Sobrien    time_get<_CharT, _InIter>::
181597403Sobrien    do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
181697403Sobrien		ios_base::iostate& __err, tm* __tm) const
181797403Sobrien    {
181897403Sobrien      _CharT __wcs[3];
181997403Sobrien      const char* __cs = "%X";
182097403Sobrien      locale __loc = __io.getloc();
182197403Sobrien      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
182297403Sobrien      __ctype.widen(__cs, __cs + 3, __wcs);
182397403Sobrien      _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
182497403Sobrien      if (__beg == __end)
182597403Sobrien	__err |= ios_base::eofbit;
182697403Sobrien      return __beg;
182797403Sobrien    }
182897403Sobrien
182997403Sobrien  template<typename _CharT, typename _InIter>
183097403Sobrien    _InIter
183197403Sobrien    time_get<_CharT, _InIter>::
183297403Sobrien    do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
183397403Sobrien		ios_base::iostate& __err, tm* __tm) const
183497403Sobrien    {
183597403Sobrien      _CharT __wcs[3];
183697403Sobrien      const char* __cs = "%x";
183797403Sobrien      locale __loc = __io.getloc();
183897403Sobrien      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
183997403Sobrien      __ctype.widen(__cs, __cs + 3, __wcs);
184097403Sobrien      _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
184197403Sobrien      if (__beg == __end)
184297403Sobrien	__err |= ios_base::eofbit;
184397403Sobrien      return __beg;
184497403Sobrien    }
184597403Sobrien
184697403Sobrien  template<typename _CharT, typename _InIter>
184797403Sobrien    _InIter
184897403Sobrien    time_get<_CharT, _InIter>::
184997403Sobrien    do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 
185097403Sobrien		   ios_base::iostate& __err, tm* __tm) const
185197403Sobrien    {
1852102782Skan      typedef char_traits<_CharT> 		__traits_type;
185397403Sobrien      locale __loc = __io.getloc();
185497403Sobrien      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
185597403Sobrien      const char_type*  __days[7];
185697403Sobrien      __tp._M_days_abbreviated(__days);
185797403Sobrien      int __tmpwday;
185897403Sobrien      _M_extract_name(__beg, __end, __tmpwday, __days, 7, __err);
185997403Sobrien
186097403Sobrien      // Check to see if non-abbreviated name exists, and extract.
186197403Sobrien      // NB: Assumes both _M_days and _M_days_abbreviated organized in
186297403Sobrien      // exact same order, first to last, such that the resulting
186397403Sobrien      // __days array with the same index points to a day, and that
186497403Sobrien      // day's abbreviated form.
186597403Sobrien      // NB: Also assumes that an abbreviated name is a subset of the name. 
186697403Sobrien      if (!__err)
186797403Sobrien	{
186897403Sobrien	  size_t __pos = __traits_type::length(__days[__tmpwday]);
186997403Sobrien	  __tp._M_days(__days);
187097403Sobrien	  const char_type* __name = __days[__tmpwday];
187197403Sobrien	  if (__name[__pos] == *__beg)
187297403Sobrien	    {
187397403Sobrien	      // Extract the rest of it.
187497403Sobrien	      const size_t __len = __traits_type::length(__name);
187597403Sobrien	      while (__pos < __len && __beg != __end 
187697403Sobrien		     && __name[__pos] == *__beg)
187797403Sobrien		++__beg, ++__pos;
187897403Sobrien	      if (__len != __pos)
187997403Sobrien		__err |= ios_base::failbit;
188097403Sobrien	    }
188197403Sobrien	  if (!__err)
188297403Sobrien	    __tm->tm_wday = __tmpwday;
188397403Sobrien	}
188497403Sobrien      if (__beg == __end)
188597403Sobrien	__err |= ios_base::eofbit;
188697403Sobrien      return __beg;
188797403Sobrien     }
188897403Sobrien
188997403Sobrien  template<typename _CharT, typename _InIter>
189097403Sobrien    _InIter
189197403Sobrien    time_get<_CharT, _InIter>::
189297403Sobrien    do_get_monthname(iter_type __beg, iter_type __end,
189397403Sobrien                     ios_base& __io, ios_base::iostate& __err, tm* __tm) const
189497403Sobrien    {
1895102782Skan      typedef char_traits<_CharT> 		__traits_type;
189697403Sobrien      locale __loc = __io.getloc();
189797403Sobrien      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
189897403Sobrien      const char_type*  __months[12];
189997403Sobrien      __tp._M_months_abbreviated(__months);
190097403Sobrien      int __tmpmon;
190197403Sobrien      _M_extract_name(__beg, __end, __tmpmon, __months, 12, __err);
190297403Sobrien
190397403Sobrien      // Check to see if non-abbreviated name exists, and extract.
190497403Sobrien      // NB: Assumes both _M_months and _M_months_abbreviated organized in
190597403Sobrien      // exact same order, first to last, such that the resulting
190697403Sobrien      // __months array with the same index points to a month, and that
190797403Sobrien      // month's abbreviated form.
190897403Sobrien      // NB: Also assumes that an abbreviated name is a subset of the name. 
190997403Sobrien      if (!__err)
191097403Sobrien	{
191197403Sobrien	  size_t __pos = __traits_type::length(__months[__tmpmon]);
191297403Sobrien	  __tp._M_months(__months);
191397403Sobrien	  const char_type* __name = __months[__tmpmon];
191497403Sobrien	  if (__name[__pos] == *__beg)
191597403Sobrien	    {
191697403Sobrien	      // Extract the rest of it.
191797403Sobrien	      const size_t __len = __traits_type::length(__name);
191897403Sobrien	      while (__pos < __len && __beg != __end 
191997403Sobrien		     && __name[__pos] == *__beg)
192097403Sobrien		++__beg, ++__pos;
192197403Sobrien	      if (__len != __pos)
192297403Sobrien		__err |= ios_base::failbit;
192397403Sobrien	    }
192497403Sobrien	  if (!__err)
192597403Sobrien	    __tm->tm_mon = __tmpmon;
192697403Sobrien	}
192797403Sobrien 
192897403Sobrien      if (__beg == __end)
192997403Sobrien	__err |= ios_base::eofbit;
193097403Sobrien      return __beg;
193197403Sobrien    }
193297403Sobrien
193397403Sobrien  template<typename _CharT, typename _InIter>
193497403Sobrien    _InIter
193597403Sobrien    time_get<_CharT, _InIter>::
193697403Sobrien    do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 
193797403Sobrien		ios_base::iostate& __err, tm* __tm) const
193897403Sobrien    {
193997403Sobrien      locale __loc = __io.getloc();
194097403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
194197403Sobrien
194297403Sobrien      char_type __c = *__beg;
194397403Sobrien      size_t __i = 0;
194497403Sobrien      string __digits;
194597403Sobrien      while (__i < 4 && __beg != __end && __ctype.is(ctype_base::digit, __c))
194697403Sobrien	{
194797403Sobrien	  __digits += __ctype.narrow(__c, 0);
194897403Sobrien	  __c = *(++__beg);
194997403Sobrien	  ++__i;
195097403Sobrien	}
195197403Sobrien      if (__i == 2 || __i == 4)
195297403Sobrien	{
195397403Sobrien	  long __l;
195497403Sobrien	  __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale);
195597403Sobrien	  if (!(__err & ios_base::failbit) && __l <= INT_MAX)
195697403Sobrien	    {
195797403Sobrien	      __l = __i == 2 ? __l : __l - 1900; 
195897403Sobrien	      __tm->tm_year = static_cast<int>(__l);
195997403Sobrien	    }
196097403Sobrien	}
196197403Sobrien      else
196297403Sobrien	__err |= ios_base::failbit;
196397403Sobrien      if (__beg == __end)
196497403Sobrien	__err |= ios_base::eofbit;
196597403Sobrien      return __beg;
196697403Sobrien    }
196797403Sobrien
196897403Sobrien  template<typename _CharT, typename _OutIter>
196997403Sobrien    _OutIter
197097403Sobrien    time_put<_CharT, _OutIter>::
197197403Sobrien    put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 
197297403Sobrien	const _CharT* __beg, const _CharT* __end) const
197397403Sobrien    {
197497403Sobrien      locale __loc = __io.getloc();
197597403Sobrien      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
197697403Sobrien      while (__beg != __end)
197797403Sobrien	{
197897403Sobrien	  char __c = __ctype.narrow(*__beg, 0);
197997403Sobrien	  ++__beg;
198097403Sobrien	  if (__c == '%')
198197403Sobrien	    {
198297403Sobrien	      char __format;
198397403Sobrien	      char __mod = 0;
198497403Sobrien	      size_t __len = 1; 
198597403Sobrien	      __c = __ctype.narrow(*__beg, 0);
198697403Sobrien	      ++__beg;
198797403Sobrien	      if (__c == 'E' || __c == 'O')
198897403Sobrien		{
198997403Sobrien		  __mod = __c;
199097403Sobrien		  __format = __ctype.narrow(*__beg, 0);
199197403Sobrien		  ++__beg;
199297403Sobrien		}
199397403Sobrien	      else
199497403Sobrien		__format = __c;
1995117397Skan	      __s = this->do_put(__s, __io, _CharT(), __tm, __format, __mod);
199697403Sobrien	    }
199797403Sobrien	  else
199897403Sobrien	    {
199997403Sobrien	      *__s = __c;
200097403Sobrien	      ++__s;
200197403Sobrien	    }
200297403Sobrien	}
200397403Sobrien      return __s;
200497403Sobrien    }
200597403Sobrien
200697403Sobrien  template<typename _CharT, typename _OutIter>
200797403Sobrien    _OutIter
200897403Sobrien    time_put<_CharT, _OutIter>::
200997403Sobrien    do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 
201097403Sobrien	   char __format, char __mod) const
201197403Sobrien    { 
201297403Sobrien      locale __loc = __io.getloc();
201397403Sobrien      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
201497403Sobrien      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
201597403Sobrien
201697403Sobrien      // NB: This size is arbitrary. Should this be a data member,
201797403Sobrien      // initialized at construction?
201897403Sobrien      const size_t __maxlen = 64;
2019117397Skan      char_type* __res = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
202097403Sobrien
202197403Sobrien      // NB: In IEE 1003.1-200x, and perhaps other locale models, it
202297403Sobrien      // is possible that the format character will be longer than one
202397403Sobrien      // character. Possibilities include 'E' or 'O' followed by a
202497403Sobrien      // format character: if __mod is not the default argument, assume
202597403Sobrien      // it's a valid modifier.
202697403Sobrien      char_type __fmt[4];
202797403Sobrien      __fmt[0] = __ctype.widen('%'); 
202897403Sobrien      if (!__mod)
202997403Sobrien	{
203097403Sobrien	  __fmt[1] = __format;
203197403Sobrien	  __fmt[2] = char_type();
203297403Sobrien	}
203397403Sobrien      else
203497403Sobrien	{
203597403Sobrien	  __fmt[1] = __mod;
203697403Sobrien	  __fmt[2] = __format;
203797403Sobrien	  __fmt[3] = char_type();
203897403Sobrien	}
203997403Sobrien
204097403Sobrien      __tp._M_put(__res, __maxlen, __fmt, __tm);
204197403Sobrien
204297403Sobrien      // Write resulting, fully-formatted string to output iterator.
2043117397Skan      return __write(__s, __res, char_traits<char_type>::length(__res));
204497403Sobrien    }
204597403Sobrien
204697403Sobrien
204797403Sobrien  // Generic version does nothing.
204897403Sobrien  template<typename _CharT>
204997403Sobrien    int
205097403Sobrien    collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const
205197403Sobrien    { return 0; }
205297403Sobrien
205397403Sobrien  // Generic version does nothing.
205497403Sobrien  template<typename _CharT>
205597403Sobrien    size_t
205697403Sobrien    collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const
205797403Sobrien    { return 0; }
205897403Sobrien
205997403Sobrien  template<typename _CharT>
206097403Sobrien    int
206197403Sobrien    collate<_CharT>::
206297403Sobrien    do_compare(const _CharT* __lo1, const _CharT* __hi1, 
206397403Sobrien	       const _CharT* __lo2, const _CharT* __hi2) const
206497403Sobrien    { 
2065117397Skan      // strcoll assumes zero-terminated strings so we make a copy
2066117397Skan      // and then put a zero at the end.
206797403Sobrien      const string_type __one(__lo1, __hi1);
206897403Sobrien      const string_type __two(__lo2, __hi2);
2069117397Skan
2070117397Skan      const _CharT* __p = __one.c_str();
2071117397Skan      const _CharT* __pend = __one.c_str() + __one.length();
2072117397Skan      const _CharT* __q = __two.c_str();
2073117397Skan      const _CharT* __qend = __two.c_str() + __two.length();
2074117397Skan
2075117397Skan      // strcoll stops when it sees a nul character so we break
2076117397Skan      // the strings into zero-terminated substrings and pass those
2077117397Skan      // to strcoll.
2078117397Skan      for (;;)
2079117397Skan	{
2080117397Skan	  int __res = _M_compare(__p, __q);
2081117397Skan	  if (__res)
2082117397Skan	    return __res;
2083117397Skan
2084117397Skan	  __p += char_traits<_CharT>::length(__p);
2085117397Skan	  __q += char_traits<_CharT>::length(__q);
2086117397Skan	  if (__p == __pend && __q == __qend)
2087117397Skan	    return 0;
2088117397Skan	  else if (__p == __pend)
2089117397Skan	    return -1;
2090117397Skan	  else if (__q == __qend)
2091117397Skan	    return 1;
2092117397Skan
2093117397Skan	  __p++;
2094117397Skan	  __q++;
2095117397Skan	}
209697403Sobrien    }
209797403Sobrien
209897403Sobrien template<typename _CharT>
209997403Sobrien    typename collate<_CharT>::string_type
210097403Sobrien    collate<_CharT>::
210197403Sobrien    do_transform(const _CharT* __lo, const _CharT* __hi) const
210297403Sobrien    {
2103117397Skan      // strxfrm assumes zero-terminated strings so we make a copy
2104117397Skan      string_type __str(__lo, __hi);
2105117397Skan
2106117397Skan      const _CharT* __p = __str.c_str();
2107117397Skan      const _CharT* __pend = __str.c_str() + __str.length();
2108117397Skan
210997403Sobrien      size_t __len = (__hi - __lo) * 2;
2110117397Skan
2111117397Skan      string_type __ret;
2112117397Skan
2113117397Skan      // strxfrm stops when it sees a nul character so we break
2114117397Skan      // the string into zero-terminated substrings and pass those
2115117397Skan      // to strxfrm.
2116117397Skan      for (;;)
211797403Sobrien	{
2118117397Skan	  // First try a buffer perhaps big enough.
2119117397Skan	  _CharT* __c =
2120117397Skan	    static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
2121117397Skan	  size_t __res = _M_transform(__c, __p, __len);
2122117397Skan	  // If the buffer was not large enough, try again with the
2123117397Skan	  // correct size.
2124117397Skan	  if (__res >= __len)
2125117397Skan	    {
2126117397Skan	      __len = __res + 1;
2127117397Skan	      __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
2128117397Skan							  * __len));
2129117397Skan	      __res = _M_transform(__c, __p, __res + 1);
2130117397Skan	    }
2131117397Skan
2132117397Skan	  __ret.append(__c, __res);
2133117397Skan	  __p += char_traits<_CharT>::length(__p);
2134117397Skan	  if (__p == __pend)
2135117397Skan	    return __ret;
2136117397Skan
2137117397Skan	  __p++;
2138117397Skan	  __ret.push_back(_CharT());
213997403Sobrien	}
214097403Sobrien    }
214197403Sobrien
214297403Sobrien template<typename _CharT>
214397403Sobrien    long
214497403Sobrien    collate<_CharT>::
214597403Sobrien    do_hash(const _CharT* __lo, const _CharT* __hi) const
214697403Sobrien    { 
214797403Sobrien      unsigned long __val = 0;
214897403Sobrien      for (; __lo < __hi; ++__lo)
214997403Sobrien	__val = *__lo + ((__val << 7) | 
215097403Sobrien		       (__val >> (numeric_limits<unsigned long>::digits - 7)));
215197403Sobrien      return static_cast<long>(__val);
215297403Sobrien    }
215397403Sobrien
215497403Sobrien  // Construct correctly padded string, as per 22.2.2.2.2
215597403Sobrien  // Assumes 
215697403Sobrien  // __newlen > __oldlen
215797403Sobrien  // __news is allocated for __newlen size
215897403Sobrien  // Used by both num_put and ostream inserters: if __num,
215997403Sobrien  // internal-adjusted objects are padded according to the rules below
216097403Sobrien  // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
216197403Sobrien  // ones are.
2162102782Skan
2163102782Skan  // NB: Of the two parameters, _CharT can be deduced from the
2164102782Skan  // function arguments. The other (_Traits) has to be explicitly specified.
216597403Sobrien  template<typename _CharT, typename _Traits>
2166102782Skan    void 
2167102782Skan    __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, 
2168102782Skan				   _CharT* __news, const _CharT* __olds, 
2169102782Skan				   const streamsize __newlen, 
2170102782Skan				   const streamsize __oldlen, const bool __num)
2171102782Skan    {
2172102782Skan      size_t __plen = static_cast<size_t>(__newlen - __oldlen);
2173117397Skan      _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
2174117397Skan							     * __plen));
2175102782Skan      _Traits::assign(__pads, __plen, __fill); 
2176102782Skan
2177102782Skan      _CharT* __beg;
2178102782Skan      _CharT* __end;
217997403Sobrien      size_t __mod = 0;
218097403Sobrien      size_t __beglen; //either __plen or __oldlen
218197403Sobrien      ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
218297403Sobrien
218397403Sobrien      if (__adjust == ios_base::left)
218497403Sobrien	{
218597403Sobrien	  // Padding last.
2186102782Skan	  __beg = const_cast<_CharT*>(__olds);
218797403Sobrien	  __beglen = __oldlen;
218897403Sobrien	  __end = __pads;
218997403Sobrien	}
219097403Sobrien      else if (__adjust == ios_base::internal && __num)
219197403Sobrien	{
219297403Sobrien	  // Pad after the sign, if there is one.
219397403Sobrien	  // Pad after 0[xX], if there is one.
219497403Sobrien	  // Who came up with these rules, anyway? Jeeze.
219597403Sobrien          locale __loc = __io.getloc();
219697403Sobrien	  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
2197102782Skan	  const _CharT __minus = __ctype.widen('-');
2198102782Skan	  const _CharT __plus = __ctype.widen('+');
2199102782Skan	  bool __testsign = _Traits::eq(__olds[0], __minus)
2200102782Skan	    		    || _Traits::eq(__olds[0], __plus);
2201102782Skan
2202102782Skan	  bool __testhex = _Traits::eq(__ctype.widen('0'), __olds[0]) 
2203102782Skan	    		   && (_Traits::eq(__ctype.widen('x'), __olds[1]) 
2204102782Skan			       || _Traits::eq(__ctype.widen('X'), __olds[1]));
220597403Sobrien	  if (__testhex)
220697403Sobrien	    {
220797403Sobrien	      __news[0] = __olds[0]; 
220897403Sobrien	      __news[1] = __olds[1];
220997403Sobrien	      __mod += 2;
221097403Sobrien	      __news += 2;
221197403Sobrien	      __beg = __pads;
221297403Sobrien	      __beglen = __plen;
2213102782Skan	      __end = const_cast<_CharT*>(__olds + __mod);
221497403Sobrien	    }
221597403Sobrien	  else if (__testsign)
221697403Sobrien	    {
2217102782Skan	      _Traits::eq((__news[0] = __olds[0]), __plus) ? __plus : __minus;
221897403Sobrien	      ++__mod;
221997403Sobrien	      ++__news;
222097403Sobrien	      __beg = __pads;
222197403Sobrien	      __beglen = __plen;
2222102782Skan	      __end = const_cast<_CharT*>(__olds + __mod);
222397403Sobrien	    }
222497403Sobrien	  else
222597403Sobrien	    {
222697403Sobrien	      // Padding first.
222797403Sobrien	      __beg = __pads;
222897403Sobrien	      __beglen = __plen;
2229102782Skan	      __end = const_cast<_CharT*>(__olds);
223097403Sobrien	    }
223197403Sobrien	}
223297403Sobrien      else
223397403Sobrien	{
223497403Sobrien	  // Padding first.
223597403Sobrien	  __beg = __pads;
223697403Sobrien	  __beglen = __plen;
2237102782Skan	  __end = const_cast<_CharT*>(__olds);
223897403Sobrien	}
2239102782Skan      _Traits::copy(__news, __beg, __beglen);
2240102782Skan      _Traits::copy(__news + __beglen, __end, 
2241102782Skan			  __newlen - __beglen - __mod);
224297403Sobrien    }
224397403Sobrien
224497403Sobrien  template<typename _CharT>
224597403Sobrien    bool
224697403Sobrien    __verify_grouping(const basic_string<_CharT>& __grouping, 
224797403Sobrien		      basic_string<_CharT>& __grouping_tmp)
224897403Sobrien    {         
224997403Sobrien      int __i = 0;
225097403Sobrien      int __j = 0;
225197403Sobrien      const int __len = __grouping.size();
225297403Sobrien      const int __n = __grouping_tmp.size();
225397403Sobrien      bool __test = true;
225497403Sobrien      
225597403Sobrien      // Parsed number groupings have to match the
225697403Sobrien      // numpunct::grouping string exactly, starting at the
225797403Sobrien      // right-most point of the parsed sequence of elements ...
225897403Sobrien      while (__test && __i < __n - 1)
225997403Sobrien	for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i)
226097403Sobrien	  __test &= __grouping[__j] == __grouping_tmp[__n - __i - 1];
226197403Sobrien      // ... but the last parsed grouping can be <= numpunct
226297403Sobrien      // grouping.
226397403Sobrien      __j == __len ? __j = 0 : __j;
226497403Sobrien      __test &= __grouping[__j] >= __grouping_tmp[__n - __i - 1];
226597403Sobrien      return __test;
226697403Sobrien    }
226797403Sobrien
226897403Sobrien  template<typename _CharT>
226997403Sobrien    _CharT*
227097403Sobrien    __add_grouping(_CharT* __s, _CharT __sep,  
227197403Sobrien		   const char* __gbeg, const char* __gend, 
227297403Sobrien		   const _CharT* __first, const _CharT* __last)
227397403Sobrien    {
227497403Sobrien      if (__last - __first > *__gbeg)
227597403Sobrien        {
227697403Sobrien          __s = __add_grouping(__s,  __sep, 
227797403Sobrien			       (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1),
227897403Sobrien			       __gend, __first, __last - *__gbeg);
227997403Sobrien          __first = __last - *__gbeg;
228097403Sobrien          *__s++ = __sep;
228197403Sobrien        }
228297403Sobrien      do
228397403Sobrien	*__s++ = *__first++;
228497403Sobrien      while (__first != __last);
228597403Sobrien      return __s;
228697403Sobrien    }
228797403Sobrien
2288117397Skan#if 1
2289117397Skan      // XXX GLIBCXX_ABI Deprecated, compatibility only.
2290117397Skan  template<typename _CharT, typename _OutIter>
2291117397Skan    template<typename _ValueT>
2292117397Skan      _OutIter
2293117397Skan      num_put<_CharT, _OutIter>::
2294117397Skan      _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
2295117397Skan		     char __modl, _ValueT __v) const
2296117397Skan      {
2297117397Skan	// [22.2.2.2.2] Stage 1, numeric conversion to character.
2298117397Skan
2299117397Skan	// Long enough for the max format spec.
2300117397Skan	char __fbuf[16];
2301117397Skan	_S_format_int(__io, __fbuf, __mod, __modl);
2302117397Skan#ifdef _GLIBCPP_USE_C99
2303117397Skan	// First try a buffer perhaps big enough.
2304117397Skan	int __cs_size = 64;
2305117397Skan	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
2306117397Skan	int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
2307117397Skan				     _S_c_locale);
2308117397Skan	// If the buffer was not large enough, try again with the correct size.
2309117397Skan	if (__len >= __cs_size)
2310117397Skan	  {
2311117397Skan	    __cs_size = __len + 1;
2312117397Skan	    __cs = static_cast<char*>(__builtin_alloca(__cs_size));
2313117397Skan	    __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
2314117397Skan				     _S_c_locale);
2315117397Skan	  }
2316117397Skan#else
2317117397Skan	// Leave room for "+/-," "0x," and commas. This size is
2318117397Skan	// arbitrary, but should be largely sufficient.
2319117397Skan	char __cs[128];
2320117397Skan	int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale);
2321117397Skan#endif
2322117397Skan	return _M_widen_int(__s, __io, __fill, __cs, __len);
2323117397Skan      }
2324117397Skan
2325117397Skan  template<typename _CharT, typename _OutIter>
2326117397Skan    _OutIter
2327117397Skan    num_put<_CharT, _OutIter>::
2328117397Skan    _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 
2329117397Skan		   int __len) const
2330117397Skan    {
2331117397Skan      typedef char_traits<_CharT> 		__traits_type;
2332117397Skan      // [22.2.2.2.2] Stage 2, convert to char_type, using correct
2333117397Skan      // numpunct.decimal_point() values for '.' and adding grouping.
2334117397Skan      const locale __loc = __io.getloc();
2335117397Skan      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2336117397Skan      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
2337117397Skan							   * __len));
2338117397Skan      // Grouping can add (almost) as many separators as the number of
2339117397Skan      // digits, but no more.
2340117397Skan      _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
2341117397Skan			 				    * __len * 2));
2342117397Skan      __ctype.widen(__cs, __cs + __len, __ws);
2343117397Skan      
2344117397Skan      // Replace decimal point.
2345117397Skan      const _CharT* __p;
2346117397Skan      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
2347117397Skan      if (__p = __traits_type::find(__ws, __len, __ctype.widen('.')))
2348117397Skan	__ws[__p - __ws] = __np.decimal_point();
2349117397Skan
2350117397Skan#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
2351117397Skan//282. What types does numpunct grouping refer to?
2352117397Skan      // Add grouping, if necessary. 
2353117397Skan      const string __grouping = __np.grouping();
2354117397Skan      if (__grouping.size())
2355117397Skan	{
2356117397Skan	  _CharT* __p2;
2357117397Skan	  int __declen = __p ? __p - __ws : __len;
2358117397Skan	  __p2 = __add_grouping(__ws2, __np.thousands_sep(), 
2359117397Skan				__grouping.c_str(),
2360117397Skan				__grouping.c_str() + __grouping.size(),
2361117397Skan				__ws, __ws + __declen);
2362117397Skan	  int __newlen = __p2 - __ws2;
2363117397Skan	
2364117397Skan	  // Tack on decimal part.
2365117397Skan	  if (__p)
2366117397Skan	    {
2367117397Skan	      __traits_type::copy(__p2, __p, __len - __declen);
2368117397Skan	      __newlen += __len - __declen;
2369117397Skan	    }    
2370117397Skan
2371117397Skan	  // Switch strings, establish correct new length.
2372117397Skan	  __ws = __ws2;
2373117397Skan	  __len = __newlen;
2374117397Skan	}
2375117397Skan#endif
2376117397Skan      return _M_insert(__s, __io, __fill, __ws, __len);
2377117397Skan    }
2378117397Skan
2379117397Skan  template<typename _CharT, typename _OutIter>
2380117397Skan    _OutIter
2381117397Skan    num_put<_CharT, _OutIter>::
2382117397Skan    _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 
2383117397Skan		 int __len) const
2384117397Skan    {
2385117397Skan      // [22.2.2.2.2] Stage 2, convert to char_type, using correct
2386117397Skan      // numpunct.decimal_point() values for '.' and adding grouping.
2387117397Skan      const locale __loc = __io.getloc();
2388117397Skan      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2389117397Skan      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
2390117397Skan							   * __len));
2391117397Skan      // Grouping can add (almost) as many separators as the number of
2392117397Skan      // digits, but no more.
2393117397Skan      _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
2394117397Skan							    * __len * 2));
2395117397Skan      __ctype.widen(__cs, __cs + __len, __ws);
2396117397Skan
2397117397Skan      // Add grouping, if necessary. 
2398117397Skan      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
2399117397Skan      const string __grouping = __np.grouping();
2400117397Skan      if (__grouping.size())
2401117397Skan	{
2402117397Skan	  // By itself __add_grouping cannot deal correctly with __ws when
2403117397Skan	  // ios::showbase is set and ios_base::oct || ios_base::hex.
2404117397Skan	  // Therefore we take care "by hand" of the initial 0, 0x or 0X.
2405117397Skan	  // However, remember that the latter do not occur if the number
2406117397Skan	  // printed is '0' (__len == 1).
2407117397Skan	  streamsize __off = 0;
2408117397Skan	  const ios_base::fmtflags __basefield = __io.flags() 
2409117397Skan	    					 & ios_base::basefield;
2410117397Skan	  if ((__io.flags() & ios_base::showbase) && __len > 1)
2411117397Skan	    if (__basefield == ios_base::oct)
2412117397Skan	      {
2413117397Skan		__off = 1;
2414117397Skan		*__ws2 = *__ws;
2415117397Skan	      }
2416117397Skan	    else if (__basefield == ios_base::hex)
2417117397Skan	      {
2418117397Skan		__off = 2;
2419117397Skan		*__ws2 = *__ws;
2420117397Skan		*(__ws2 + 1) = *(__ws + 1);
2421117397Skan	      }
2422117397Skan	  _CharT* __p;
2423117397Skan	  __p = __add_grouping(__ws2 + __off, __np.thousands_sep(), 
2424117397Skan			       __grouping.c_str(),
2425117397Skan			       __grouping.c_str() + __grouping.size(),
2426117397Skan			       __ws + __off, __ws + __len);
2427117397Skan	  __len = __p - __ws2;
2428117397Skan	  // Switch strings.
2429117397Skan	  __ws = __ws2;
2430117397Skan	}
2431117397Skan      return _M_insert(__s, __io, __fill, __ws, __len);
2432117397Skan    }
2433117397Skan
2434117397Skan  // For use by integer and floating-point types after they have been
2435117397Skan  // converted into a char_type string.
2436117397Skan  template<typename _CharT, typename _OutIter>
2437117397Skan    _OutIter
2438117397Skan    num_put<_CharT, _OutIter>::
2439117397Skan    _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, 
2440117397Skan	      int __len) const
2441117397Skan    {
2442117397Skan      typedef char_traits<_CharT> 		__traits_type;
2443117397Skan      // [22.2.2.2.2] Stage 3.
2444117397Skan      // If necessary, pad.
2445117397Skan      streamsize __w = __io.width();
2446117397Skan      _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
2447117397Skan							    * __w));
2448117397Skan      if (__w > static_cast<streamsize>(__len))
2449117397Skan	{
2450117397Skan	  __pad<_CharT, __traits_type>::_S_pad(__io, __fill, __ws2, __ws, 
2451117397Skan					       __w, __len, true);
2452117397Skan	  __len = static_cast<int>(__w);
2453117397Skan	  // Switch strings.
2454117397Skan	  __ws = __ws2;
2455117397Skan	}
2456117397Skan      __io.width(0);
2457117397Skan
2458117397Skan      // [22.2.2.2.2] Stage 4.
2459117397Skan      // Write resulting, fully-formatted string to output iterator.
2460117397Skan      return __write(__s, __ws, __len);
2461117397Skan    }
2462117397Skan#endif
2463117397Skan
2464117397Skan  template<typename _CharT>
2465117397Skan    __locale_cache<numpunct<_CharT> >::__locale_cache(const locale& __loc)
2466117397Skan      : _M_truename(0), _M_falsename(0), _M_use_grouping(false),
2467117397Skan	_M_grouping(0)
2468117397Skan    {
2469117397Skan      if (has_facet<numpunct<_CharT> >(__loc))
2470117397Skan	{
2471117397Skan	  const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
2472117397Skan	  _M_decimal_point = __np.decimal_point();
2473117397Skan	  _M_thousands_sep = __np.thousands_sep();
2474117397Skan
2475117397Skan	  string_type __false = __np.falsename();
2476117397Skan	  _CharT* __falsename = new _CharT[__false.length() + 1];
2477117397Skan	  __false.copy(__falsename, __false.length());
2478117397Skan	  __falsename[__false.length()] = _CharT();
2479117397Skan	  _M_falsename = __falsename;
2480117397Skan
2481117397Skan	  string_type __true = __np.truename();
2482117397Skan	  _CharT* __truename = new _CharT[__true.length() + 1];
2483117397Skan	  __true.copy(__truename, __true.length());
2484117397Skan	  __truename[__true.length()] = _CharT();
2485117397Skan	  _M_truename = __truename;
2486117397Skan
2487117397Skan	  string __grouping = __np.grouping();
2488117397Skan	  char* __group = new char[__grouping.length() + 1];
2489117397Skan	  __grouping.copy(__group, __grouping.length());
2490117397Skan	  __group[__grouping.length()] = 0;
2491117397Skan	  _M_grouping = __group;
2492117397Skan
2493117397Skan	  _M_use_grouping = __grouping.length() != 0 
2494117397Skan	    && __grouping.data()[0] != 0;
2495117397Skan	}
2496117397Skan
2497117397Skan      if (has_facet<ctype<_CharT> >(__loc))
2498117397Skan	{
2499117397Skan	  const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
2500117397Skan	  __ct.widen(__num_base::_S_atoms_out,
2501117397Skan		     __num_base::_S_atoms_out + __num_base::_S_end, 
2502117397Skan		     _M_atoms_out);
2503117397Skan	}
2504117397Skan    }
2505117397Skan
2506117397Skan  // Static locale cache initialization.  Only instantiated with char
2507117397Skan  // and wchar_t, so no need to check has_facet.
2508117397Skan  template<typename _CharT>
2509117397Skan    __locale_cache<numpunct<_CharT> >::
2510117397Skan    __locale_cache(const locale& __loc, bool)
2511117397Skan    {
2512117397Skan      // Grab pointers to numpunct static strings
2513117397Skan      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
2514117397Skan      _M_thousands_sep = __np._M_thousands_sep;
2515117397Skan      _M_decimal_point = __np._M_decimal_point;
2516117397Skan      _M_falsename = __np._M_falsename;
2517117397Skan      _M_truename = __np._M_truename;
2518117397Skan      _M_grouping = __np._M_grouping;
2519117397Skan      _M_use_grouping = false;
2520117397Skan
2521117397Skan      const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
2522117397Skan      __ct.widen(__num_base::_S_atoms_out,
2523117397Skan		 __num_base::_S_atoms_out + __num_base::_S_end, 
2524117397Skan		 _M_atoms_out);
2525117397Skan    }
2526117397Skan
252797403Sobrien  // Inhibit implicit instantiations for required instantiations,
252897403Sobrien  // which are defined via explicit instantiations elsewhere.  
252997403Sobrien  // NB: This syntax is a GNU extension.
2530117397Skan#if _GLIBCPP_EXTERN_TEMPLATE
253197403Sobrien  extern template class moneypunct<char, false>;
253297403Sobrien  extern template class moneypunct<char, true>;
253397403Sobrien  extern template class moneypunct_byname<char, false>;
253497403Sobrien  extern template class moneypunct_byname<char, true>;
253597403Sobrien  extern template class money_get<char>;
253697403Sobrien  extern template class money_put<char>;
253797403Sobrien  extern template class numpunct<char>;
253897403Sobrien  extern template class numpunct_byname<char>;
253997403Sobrien  extern template class num_get<char>;
254097403Sobrien  extern template class num_put<char>; 
254197403Sobrien  extern template class __timepunct<char>;
254297403Sobrien  extern template class time_put<char>;
254397403Sobrien  extern template class time_put_byname<char>;
254497403Sobrien  extern template class time_get<char>;
254597403Sobrien  extern template class time_get_byname<char>;
254697403Sobrien  extern template class messages<char>;
254797403Sobrien  extern template class messages_byname<char>;
254897403Sobrien  extern template class ctype_byname<char>;
254997403Sobrien  extern template class codecvt_byname<char, char, mbstate_t>;
255097403Sobrien  extern template class collate<char>;
255197403Sobrien  extern template class collate_byname<char>;
255297403Sobrien
255397403Sobrien  extern template
255497403Sobrien    const codecvt<char, char, mbstate_t>& 
255597403Sobrien    use_facet<codecvt<char, char, mbstate_t> >(const locale&);
255697403Sobrien
255797403Sobrien  extern template
255897403Sobrien    const collate<char>& 
255997403Sobrien    use_facet<collate<char> >(const locale&);
256097403Sobrien
256197403Sobrien  extern template
256297403Sobrien    const numpunct<char>& 
256397403Sobrien    use_facet<numpunct<char> >(const locale&);
256497403Sobrien
256597403Sobrien  extern template 
256697403Sobrien    const num_put<char>& 
256797403Sobrien    use_facet<num_put<char> >(const locale&);
256897403Sobrien
256997403Sobrien  extern template 
257097403Sobrien    const num_get<char>& 
257197403Sobrien    use_facet<num_get<char> >(const locale&);
257297403Sobrien
257397403Sobrien  extern template
257497403Sobrien    const moneypunct<char, true>& 
257597403Sobrien    use_facet<moneypunct<char, true> >(const locale&);
257697403Sobrien
257797403Sobrien  extern template
257897403Sobrien    const moneypunct<char, false>& 
257997403Sobrien    use_facet<moneypunct<char, false> >(const locale&);
258097403Sobrien
258197403Sobrien  extern template 
258297403Sobrien    const money_put<char>& 
258397403Sobrien    use_facet<money_put<char> >(const locale&);
258497403Sobrien
258597403Sobrien  extern template 
258697403Sobrien    const money_get<char>& 
258797403Sobrien    use_facet<money_get<char> >(const locale&);
258897403Sobrien
258997403Sobrien  extern template
259097403Sobrien    const __timepunct<char>& 
259197403Sobrien    use_facet<__timepunct<char> >(const locale&);
259297403Sobrien
259397403Sobrien  extern template 
259497403Sobrien    const time_put<char>& 
259597403Sobrien    use_facet<time_put<char> >(const locale&);
259697403Sobrien
259797403Sobrien  extern template 
259897403Sobrien    const time_get<char>& 
259997403Sobrien    use_facet<time_get<char> >(const locale&);
260097403Sobrien
260197403Sobrien  extern template 
260297403Sobrien    const messages<char>& 
260397403Sobrien    use_facet<messages<char> >(const locale&);
260497403Sobrien
2605107606Sobrien  extern template 
2606107606Sobrien    bool
2607107606Sobrien    has_facet<ctype<char> >(const locale&);
2608107606Sobrien
2609107606Sobrien  extern template 
2610107606Sobrien    bool
2611107606Sobrien    has_facet<codecvt<char, char, mbstate_t> >(const locale&);
2612107606Sobrien
2613107606Sobrien  extern template 
2614107606Sobrien    bool
2615107606Sobrien    has_facet<collate<char> >(const locale&);
2616107606Sobrien
2617107606Sobrien  extern template 
2618107606Sobrien    bool
2619107606Sobrien    has_facet<numpunct<char> >(const locale&);
2620107606Sobrien
2621107606Sobrien  extern template 
2622107606Sobrien    bool
2623107606Sobrien    has_facet<num_put<char> >(const locale&);
2624107606Sobrien
2625107606Sobrien  extern template 
2626107606Sobrien    bool
2627107606Sobrien    has_facet<num_get<char> >(const locale&);
2628107606Sobrien
2629107606Sobrien  extern template 
2630107606Sobrien    bool
2631107606Sobrien    has_facet<moneypunct<char> >(const locale&);
2632107606Sobrien
2633107606Sobrien  extern template 
2634107606Sobrien    bool
2635107606Sobrien    has_facet<money_put<char> >(const locale&);
2636107606Sobrien
2637107606Sobrien  extern template 
2638107606Sobrien    bool
2639107606Sobrien    has_facet<money_get<char> >(const locale&);
2640107606Sobrien
2641107606Sobrien  extern template 
2642107606Sobrien    bool
2643107606Sobrien    has_facet<__timepunct<char> >(const locale&);
2644107606Sobrien
2645107606Sobrien  extern template 
2646107606Sobrien    bool
2647107606Sobrien    has_facet<time_put<char> >(const locale&);
2648107606Sobrien
2649107606Sobrien  extern template 
2650107606Sobrien    bool
2651107606Sobrien    has_facet<time_get<char> >(const locale&);
2652107606Sobrien
2653107606Sobrien  extern template 
2654107606Sobrien    bool
2655107606Sobrien    has_facet<messages<char> >(const locale&);
2656107606Sobrien
2657107606Sobrien#ifdef _GLIBCPP_USE_WCHAR_T
2658107606Sobrien  extern template class moneypunct<wchar_t, false>;
2659107606Sobrien  extern template class moneypunct<wchar_t, true>;
2660107606Sobrien  extern template class moneypunct_byname<wchar_t, false>;
2661107606Sobrien  extern template class moneypunct_byname<wchar_t, true>;
2662107606Sobrien  extern template class money_get<wchar_t>;
2663107606Sobrien  extern template class money_put<wchar_t>;
2664107606Sobrien  extern template class numpunct<wchar_t>;
2665107606Sobrien  extern template class numpunct_byname<wchar_t>;
2666107606Sobrien  extern template class num_get<wchar_t>;
2667107606Sobrien  extern template class num_put<wchar_t>;
2668107606Sobrien  extern template class __timepunct<wchar_t>;
2669107606Sobrien  extern template class time_put<wchar_t>;
2670107606Sobrien  extern template class time_put_byname<wchar_t>;
2671107606Sobrien  extern template class time_get<wchar_t>;
2672107606Sobrien  extern template class time_get_byname<wchar_t>;
2673107606Sobrien  extern template class messages<wchar_t>;
2674107606Sobrien  extern template class messages_byname<wchar_t>;
2675107606Sobrien  extern template class ctype_byname<wchar_t>;
2676107606Sobrien  extern template class codecvt_byname<wchar_t, char, mbstate_t>;
2677107606Sobrien  extern template class collate<wchar_t>;
2678107606Sobrien  extern template class collate_byname<wchar_t>;
2679107606Sobrien
268097403Sobrien  extern template
268197403Sobrien    const codecvt<wchar_t, char, mbstate_t>& 
268297403Sobrien    use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&);
268397403Sobrien
268497403Sobrien  extern template
268597403Sobrien    const collate<wchar_t>& 
268697403Sobrien    use_facet<collate<wchar_t> >(const locale&);
268797403Sobrien
268897403Sobrien  extern template
268997403Sobrien    const numpunct<wchar_t>& 
269097403Sobrien    use_facet<numpunct<wchar_t> >(const locale&);
269197403Sobrien
269297403Sobrien  extern template 
269397403Sobrien    const num_put<wchar_t>& 
269497403Sobrien    use_facet<num_put<wchar_t> >(const locale&);
269597403Sobrien
269697403Sobrien  extern template 
269797403Sobrien    const num_get<wchar_t>& 
269897403Sobrien    use_facet<num_get<wchar_t> >(const locale&);
269997403Sobrien
270097403Sobrien  extern template
270197403Sobrien    const moneypunct<wchar_t, true>& 
270297403Sobrien    use_facet<moneypunct<wchar_t, true> >(const locale&);
270397403Sobrien
270497403Sobrien  extern template
270597403Sobrien    const moneypunct<wchar_t, false>& 
270697403Sobrien    use_facet<moneypunct<wchar_t, false> >(const locale&);
270797403Sobrien 
270897403Sobrien  extern template 
270997403Sobrien    const money_put<wchar_t>& 
271097403Sobrien    use_facet<money_put<wchar_t> >(const locale&);
271197403Sobrien
271297403Sobrien  extern template 
271397403Sobrien    const money_get<wchar_t>& 
271497403Sobrien    use_facet<money_get<wchar_t> >(const locale&);
271597403Sobrien
271697403Sobrien  extern template
271797403Sobrien    const __timepunct<wchar_t>& 
271897403Sobrien    use_facet<__timepunct<wchar_t> >(const locale&);
271997403Sobrien
272097403Sobrien  extern template 
272197403Sobrien    const time_put<wchar_t>& 
272297403Sobrien    use_facet<time_put<wchar_t> >(const locale&);
272397403Sobrien
272497403Sobrien  extern template 
272597403Sobrien    const time_get<wchar_t>& 
272697403Sobrien    use_facet<time_get<wchar_t> >(const locale&);
272797403Sobrien
272897403Sobrien  extern template 
272997403Sobrien    const messages<wchar_t>& 
273097403Sobrien    use_facet<messages<wchar_t> >(const locale&);
273197403Sobrien
273297403Sobrien extern template 
273397403Sobrien    bool
273497403Sobrien    has_facet<ctype<wchar_t> >(const locale&);
273597403Sobrien
273697403Sobrien  extern template 
273797403Sobrien    bool
273897403Sobrien    has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
273997403Sobrien
274097403Sobrien  extern template 
274197403Sobrien    bool
274297403Sobrien    has_facet<collate<wchar_t> >(const locale&);
274397403Sobrien
274497403Sobrien  extern template 
274597403Sobrien    bool
274697403Sobrien    has_facet<numpunct<wchar_t> >(const locale&);
274797403Sobrien
274897403Sobrien  extern template 
274997403Sobrien    bool
275097403Sobrien    has_facet<num_put<wchar_t> >(const locale&);
275197403Sobrien
275297403Sobrien  extern template 
275397403Sobrien    bool
275497403Sobrien    has_facet<num_get<wchar_t> >(const locale&);
275597403Sobrien
275697403Sobrien  extern template 
275797403Sobrien    bool
275897403Sobrien    has_facet<moneypunct<wchar_t> >(const locale&);
275997403Sobrien
276097403Sobrien  extern template 
276197403Sobrien    bool
276297403Sobrien    has_facet<money_put<wchar_t> >(const locale&);
276397403Sobrien
276497403Sobrien  extern template 
276597403Sobrien    bool
276697403Sobrien    has_facet<money_get<wchar_t> >(const locale&);
276797403Sobrien
276897403Sobrien  extern template 
276997403Sobrien    bool
277097403Sobrien    has_facet<__timepunct<wchar_t> >(const locale&);
277197403Sobrien
277297403Sobrien  extern template 
277397403Sobrien    bool
277497403Sobrien    has_facet<time_put<wchar_t> >(const locale&);
277597403Sobrien
277697403Sobrien  extern template 
277797403Sobrien    bool
277897403Sobrien    has_facet<time_get<wchar_t> >(const locale&);
277997403Sobrien
278097403Sobrien  extern template 
278197403Sobrien    bool
278297403Sobrien    has_facet<messages<wchar_t> >(const locale&);
2783107606Sobrien#endif
2784117397Skan#endif
278597403Sobrien} // namespace std
278697403Sobrien
278797403Sobrien#endif
2788