locale_facets.tcc revision 132720
197403Sobrien// Locale support -*- C++ -*-
297403Sobrien
3132720Skan// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
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
33132720Skan#ifndef _LOCALE_FACETS_TCC
34132720Skan#define _LOCALE_FACETS_TCC 1
3597403Sobrien
3697403Sobrien#pragma GCC system_header
3797403Sobrien
38132720Skan#include <limits>		// For numeric_limits
39132720Skan#include <typeinfo>		// For bad_cast.
4097403Sobrien#include <bits/streambuf_iterator.h>
4197403Sobrien
4297403Sobriennamespace std
4397403Sobrien{
4497403Sobrien  template<typename _Facet>
4597403Sobrien    locale
4697403Sobrien    locale::combine(const locale& __other) const
4797403Sobrien    {
4897403Sobrien      _Impl* __tmp = new _Impl(*_M_impl, 1);
49132720Skan      try
50132720Skan	{
51132720Skan	  __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
52132720Skan	}
53132720Skan      catch(...)
54132720Skan	{
55132720Skan	  __tmp->_M_remove_reference();
56132720Skan	  __throw_exception_again;
57132720Skan	}
5897403Sobrien      return locale(__tmp);
5997403Sobrien    }
6097403Sobrien
6197403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
6297403Sobrien    bool
6397403Sobrien    locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
6497403Sobrien                       const basic_string<_CharT, _Traits, _Alloc>& __s2) const
6597403Sobrien    {
6697403Sobrien      typedef std::collate<_CharT> __collate_type;
6797403Sobrien      const __collate_type& __collate = use_facet<__collate_type>(*this);
6897403Sobrien      return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
6997403Sobrien				__s2.data(), __s2.data() + __s2.length()) < 0);
7097403Sobrien    }
7197403Sobrien
72132720Skan  /**
73132720Skan   *  @brief  Test for the presence of a facet.
74132720Skan   *
75132720Skan   *  has_facet tests the locale argument for the presence of the facet type
76132720Skan   *  provided as the template parameter.  Facets derived from the facet
77132720Skan   *  parameter will also return true.
78132720Skan   *
79132720Skan   *  @param  Facet  The facet type to test the presence of.
80132720Skan   *  @param  locale  The locale to test.
81132720Skan   *  @return  true if locale contains a facet of type Facet, else false.
82132720Skan  */
8397403Sobrien  template<typename _Facet>
84132720Skan    inline bool
85132720Skan    has_facet(const locale& __loc) throw()
86132720Skan    {
87132720Skan      const size_t __i = _Facet::id._M_id();
88132720Skan      const locale::facet** __facets = __loc._M_impl->_M_facets;
89132720Skan      return (__i < __loc._M_impl->_M_facets_size && __facets[__i]);
90132720Skan    }
91132720Skan
92132720Skan  /**
93132720Skan   *  @brief  Return a facet.
94132720Skan   *
95132720Skan   *  use_facet looks for and returns a reference to a facet of type Facet
96132720Skan   *  where Facet is the template parameter.  If has_facet(locale) is true,
97132720Skan   *  there is a suitable facet to return.  It throws std::bad_cast if the
98132720Skan   *  locale doesn't contain a facet of type Facet.
99132720Skan   *
100132720Skan   *  @param  Facet  The facet type to access.
101132720Skan   *  @param  locale  The locale to use.
102132720Skan   *  @return  Reference to facet of type Facet.
103132720Skan   *  @throw  std::bad_cast if locale doesn't contain a facet of type Facet.
104132720Skan  */
105132720Skan  template<typename _Facet>
106132720Skan    inline const _Facet&
10797403Sobrien    use_facet(const locale& __loc)
10897403Sobrien    {
109132720Skan      const size_t __i = _Facet::id._M_id();
110132720Skan      const locale::facet** __facets = __loc._M_impl->_M_facets;
11197403Sobrien      if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i]))
11297403Sobrien        __throw_bad_cast();
11397403Sobrien      return static_cast<const _Facet&>(*__facets[__i]);
11497403Sobrien    }
11597403Sobrien
116132720Skan  // Routine to access a cache for the facet.  If the cache didn't
117132720Skan  // exist before, it gets constructed on the fly.
11897403Sobrien  template<typename _Facet>
119132720Skan    struct __use_cache
12097403Sobrien    {
121132720Skan      const _Facet*
122132720Skan      operator() (const locale& __loc) const;
123132720Skan    };
124132720Skan
125132720Skan  // Specializations.
126132720Skan  template<typename _CharT>
127132720Skan    struct __use_cache<__numpunct_cache<_CharT> >
128132720Skan    {
129132720Skan      const __numpunct_cache<_CharT>*
130132720Skan      operator() (const locale& __loc) const
131132720Skan      {
132132720Skan	const size_t __i = numpunct<_CharT>::id._M_id();
133132720Skan	const locale::facet** __caches = __loc._M_impl->_M_caches;
134132720Skan	if (!__caches[__i])
135132720Skan	  {
136132720Skan	    __numpunct_cache<_CharT>* __tmp = NULL;
137132720Skan	    try
138132720Skan	      {
139132720Skan		__tmp = new __numpunct_cache<_CharT>;
140132720Skan		__tmp->_M_cache(__loc);
141132720Skan	      }
142132720Skan	    catch(...)
143132720Skan	      {
144132720Skan		delete __tmp;
145132720Skan		__throw_exception_again;
146132720Skan	      }
147132720Skan	    __loc._M_impl->_M_install_cache(__tmp, __i);
148132720Skan	  }
149132720Skan	return static_cast<const __numpunct_cache<_CharT>*>(__caches[__i]);
150132720Skan      }
151132720Skan    };
152132720Skan
153132720Skan  template<typename _CharT, bool _Intl>
154132720Skan    struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
155132720Skan    {
156132720Skan      const __moneypunct_cache<_CharT, _Intl>*
157132720Skan      operator() (const locale& __loc) const
158132720Skan      {
159132720Skan	const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
160132720Skan	const locale::facet** __caches = __loc._M_impl->_M_caches;
161132720Skan	if (!__caches[__i])
162132720Skan	  {
163132720Skan	    __moneypunct_cache<_CharT, _Intl>* __tmp = NULL;
164132720Skan	    try
165132720Skan	      {
166132720Skan		__tmp = new __moneypunct_cache<_CharT, _Intl>;
167132720Skan		__tmp->_M_cache(__loc);
168132720Skan	      }
169132720Skan	    catch(...)
170132720Skan	      {
171132720Skan		delete __tmp;
172132720Skan		__throw_exception_again;
173132720Skan	      }
174132720Skan	    __loc._M_impl->_M_install_cache(__tmp, __i);
175132720Skan	  }
176132720Skan	return static_cast<
177132720Skan	  const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
178132720Skan      }
179132720Skan    };
180132720Skan
181132720Skan  template<typename _CharT>
182132720Skan    void
183132720Skan    __numpunct_cache<_CharT>::_M_cache(const locale& __loc)
184132720Skan    {
185132720Skan      _M_allocated = true;
186132720Skan
187132720Skan      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
188132720Skan
189132720Skan      _M_grouping_size = __np.grouping().size();
190132720Skan      char* __grouping = new char[_M_grouping_size];
191132720Skan      __np.grouping().copy(__grouping, _M_grouping_size);
192132720Skan      _M_grouping = __grouping;
193132720Skan      _M_use_grouping = _M_grouping_size && __np.grouping()[0] != 0;
194132720Skan
195132720Skan      _M_truename_size = __np.truename().size();
196132720Skan      _CharT* __truename = new _CharT[_M_truename_size];
197132720Skan      __np.truename().copy(__truename, _M_truename_size);
198132720Skan      _M_truename = __truename;
199132720Skan
200132720Skan      _M_falsename_size = __np.falsename().size();
201132720Skan      _CharT* __falsename = new _CharT[_M_falsename_size];
202132720Skan      __np.falsename().copy(__falsename, _M_falsename_size);
203132720Skan      _M_falsename = __falsename;
204132720Skan
205132720Skan      _M_decimal_point = __np.decimal_point();
206132720Skan      _M_thousands_sep = __np.thousands_sep();
207132720Skan
208132720Skan      const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
209132720Skan      __ct.widen(__num_base::_S_atoms_out,
210132720Skan		 __num_base::_S_atoms_out + __num_base::_S_oend, _M_atoms_out);
211132720Skan      __ct.widen(__num_base::_S_atoms_in,
212132720Skan		 __num_base::_S_atoms_in + __num_base::_S_iend, _M_atoms_in);
21397403Sobrien    }
21497403Sobrien
215132720Skan  template<typename _CharT, bool _Intl>
216132720Skan    void
217132720Skan    __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
218117397Skan    {
219132720Skan      _M_allocated = true;
220132720Skan
221132720Skan      const moneypunct<_CharT, _Intl>& __mp =
222132720Skan	use_facet<moneypunct<_CharT, _Intl> >(__loc);
223132720Skan
224132720Skan      _M_grouping_size = __mp.grouping().size();
225132720Skan      char* __grouping = new char[_M_grouping_size];
226132720Skan      __mp.grouping().copy(__grouping, _M_grouping_size);
227132720Skan      _M_grouping = __grouping;
228132720Skan      _M_use_grouping = _M_grouping_size && __mp.grouping()[0] != 0;
229132720Skan      
230132720Skan      _M_decimal_point = __mp.decimal_point();
231132720Skan      _M_thousands_sep = __mp.thousands_sep();
232132720Skan      _M_frac_digits = __mp.frac_digits();
233132720Skan      
234132720Skan      _M_curr_symbol_size = __mp.curr_symbol().size();
235132720Skan      _CharT* __curr_symbol = new _CharT[_M_curr_symbol_size];
236132720Skan      __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size);
237132720Skan      _M_curr_symbol = __curr_symbol;
238132720Skan      
239132720Skan      _M_positive_sign_size = __mp.positive_sign().size();
240132720Skan      _CharT* __positive_sign = new _CharT[_M_positive_sign_size];
241132720Skan      __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size);
242132720Skan      _M_positive_sign = __positive_sign;
243132720Skan
244132720Skan      _M_negative_sign_size = __mp.negative_sign().size();
245132720Skan      _CharT* __negative_sign = new _CharT[_M_negative_sign_size];
246132720Skan      __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size);
247132720Skan      _M_negative_sign = __negative_sign;
248132720Skan      
249132720Skan      _M_pos_format = __mp.pos_format();
250132720Skan      _M_neg_format = __mp.neg_format();
251132720Skan
252132720Skan      const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
253132720Skan      __ct.widen(money_base::_S_atoms,
254132720Skan		 money_base::_S_atoms + money_base::_S_end, _M_atoms);
255117397Skan    }
25697403Sobrien
257132720Skan
258132720Skan  // Used by both numeric and monetary facets.
259132720Skan  // Check to make sure that the __grouping_tmp string constructed in
260132720Skan  // money_get or num_get matches the canonical grouping for a given
261132720Skan  // locale.
262132720Skan  // __grouping_tmp is parsed L to R
263132720Skan  // 1,222,444 == __grouping_tmp of "\1\3\3"
264132720Skan  // __grouping is parsed R to L
265132720Skan  // 1,222,444 == __grouping of "\3" == "\3\3\3"
266132720Skan  static bool
267132720Skan  __verify_grouping(const char* __grouping, size_t __grouping_size,
268132720Skan		    const string& __grouping_tmp);
269132720Skan
27097403Sobrien  template<typename _CharT, typename _InIter>
27197403Sobrien    _InIter
27297403Sobrien    num_get<_CharT, _InIter>::
27397403Sobrien    _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
27497403Sobrien		     ios_base::iostate& __err, string& __xtrc) const
27597403Sobrien    {
276132720Skan      typedef char_traits<_CharT>			__traits_type;
277132720Skan      typedef typename numpunct<_CharT>::__cache_type	__cache_type;
278132720Skan      __use_cache<__cache_type> __uc;
279132720Skan      const locale& __loc = __io._M_getloc();
280132720Skan      const __cache_type* __lc = __uc(__loc);
281132720Skan      const _CharT* __lit = __lc->_M_atoms_in;
28297403Sobrien
283132720Skan      // True if a mantissa is found.
284132720Skan      bool __found_mantissa = false;
285132720Skan
28697403Sobrien      // First check for sign.
287132720Skan      if (__beg != __end)
28897403Sobrien	{
289132720Skan	  const char_type __c = *__beg;
290132720Skan	  const bool __plus = __c == __lit[__num_base::_S_iplus];
291132720Skan	  if ((__plus || __c == __lit[__num_base::_S_iminus])
292132720Skan	      && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
293132720Skan	      && !(__c == __lc->_M_decimal_point))
294132720Skan	    {
295132720Skan	      __xtrc += __plus ? '+' : '-';
296132720Skan	      ++__beg;
297132720Skan	    }
29897403Sobrien	}
29997403Sobrien
300132720Skan      // Next, look for leading zeros.
301132720Skan      while (__beg != __end)
30297403Sobrien	{
303132720Skan	  const char_type __c = *__beg;
304132720Skan	  if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep
305132720Skan	      || __c == __lc->_M_decimal_point)
306132720Skan	    break;
307132720Skan	  else if (__c == __lit[__num_base::_S_izero])
308132720Skan	    {
309132720Skan	      if (!__found_mantissa)
310132720Skan		{
311132720Skan		  __xtrc += '0';
312132720Skan		  __found_mantissa = true;
313132720Skan		}
314132720Skan	      ++__beg;
315132720Skan	    }
316132720Skan	  else
317132720Skan	    break;
31897403Sobrien	}
31997403Sobrien
32097403Sobrien      // Only need acceptable digits for floating point numbers.
32197403Sobrien      bool __found_dec = false;
32297403Sobrien      bool __found_sci = false;
32397403Sobrien      string __found_grouping;
324132720Skan      if (__lc->_M_use_grouping)
325132720Skan	__found_grouping.reserve(32);
32697403Sobrien      int __sep_pos = 0;
327132720Skan      const char_type* __lit_zero = __lit + __num_base::_S_izero;
328132720Skan      const char_type* __q;
32997403Sobrien      while (__beg != __end)
33097403Sobrien        {
331132720Skan	  // According to 22.2.2.1.2, p8-9, first look for thousands_sep
332132720Skan	  // and decimal_point.
333132720Skan	  const char_type __c = *__beg;
334132720Skan          if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
33597403Sobrien	    {
336132720Skan	      if (!__found_dec && !__found_sci)
33797403Sobrien		{
338132720Skan		  // NB: Thousands separator at the beginning of a string
339132720Skan		  // is a no-no, as is two consecutive thousands separators.
340132720Skan		  if (__sep_pos)
341132720Skan		    {
342132720Skan		      __found_grouping += static_cast<char>(__sep_pos);
343132720Skan		      __sep_pos = 0;
344132720Skan		      ++__beg;
345132720Skan		    }
346132720Skan		  else
347132720Skan		    {
348132720Skan		      __err |= ios_base::failbit;
349132720Skan		      break;
350132720Skan		    }
35197403Sobrien		}
352132720Skan	      else
353132720Skan		break;
35497403Sobrien            }
355132720Skan	  else if (__c == __lc->_M_decimal_point)
35697403Sobrien	    {
357132720Skan	      if (!__found_dec && !__found_sci)
358132720Skan		{
359132720Skan		  // If no grouping chars are seen, no grouping check
360132720Skan		  // is applied. Therefore __found_grouping is adjusted
361132720Skan		  // only if decimal_point comes after some thousands_sep.
362132720Skan		  if (__found_grouping.size())
363132720Skan		    __found_grouping += static_cast<char>(__sep_pos);
364132720Skan		  __xtrc += '.';
365132720Skan		  __found_dec = true;
366132720Skan		  ++__beg;
367132720Skan		}
368132720Skan	      else
369132720Skan		break;
37097403Sobrien	    }
371132720Skan          else if (__q = __traits_type::find(__lit_zero, 10, __c))
37297403Sobrien	    {
373132720Skan	      __xtrc += __num_base::_S_atoms_in[__q - __lit];
374132720Skan	      __found_mantissa = true;
375132720Skan	      ++__sep_pos;
376132720Skan	      ++__beg;
377132720Skan	    }
378132720Skan	  else if ((__c == __lit[__num_base::_S_ie] 
379132720Skan		    || __c == __lit[__num_base::_S_iE])
380132720Skan		   && __found_mantissa && !__found_sci)
381132720Skan	    {
38297403Sobrien	      // Scientific notation.
383132720Skan	      if (__found_grouping.size() && !__found_dec)
384132720Skan		__found_grouping += static_cast<char>(__sep_pos);
385132720Skan	      __xtrc += 'e';
386132720Skan	      __found_sci = true;
38797403Sobrien
38897403Sobrien	      // Remove optional plus or minus sign, if they exist.
389132720Skan	      if (++__beg != __end)
39097403Sobrien		{
391132720Skan		  const bool __plus = *__beg == __lit[__num_base::_S_iplus];
392132720Skan		  if ((__plus || *__beg == __lit[__num_base::_S_iminus])
393132720Skan		      && !(__lc->_M_use_grouping
394132720Skan			   && *__beg == __lc->_M_thousands_sep)
395132720Skan		      && !(*__beg == __lc->_M_decimal_point))
396132720Skan		    {
397132720Skan		      __xtrc += __plus ? '+' : '-';
398132720Skan		      ++__beg;
399132720Skan		    }
40097403Sobrien		}
40197403Sobrien	    }
40297403Sobrien	  else
40397403Sobrien	    // Not a valid input item.
40497403Sobrien	    break;
40597403Sobrien        }
40697403Sobrien
40797403Sobrien      // Digit grouping is checked. If grouping and found_grouping don't
40897403Sobrien      // match, then get very very upset, and set failbit.
409132720Skan      if (__lc->_M_use_grouping && __found_grouping.size())
41097403Sobrien        {
411132720Skan          // Add the ending grouping if a decimal or 'e'/'E' wasn't found.
412132720Skan	  if (!__found_dec && !__found_sci)
41397403Sobrien	    __found_grouping += static_cast<char>(__sep_pos);
414132720Skan
415132720Skan          if (!std::__verify_grouping(__lc->_M_grouping, 
416132720Skan				      __lc->_M_grouping_size,
417132720Skan				      __found_grouping))
41897403Sobrien	    __err |= ios_base::failbit;
41997403Sobrien        }
42097403Sobrien
421132720Skan      // Finish up.
42297403Sobrien      if (__beg == __end)
42397403Sobrien        __err |= ios_base::eofbit;
42497403Sobrien      return __beg;
42597403Sobrien    }
42697403Sobrien
42797403Sobrien  template<typename _CharT, typename _InIter>
428132720Skan    template<typename _ValueT>
429132720Skan      _InIter
430132720Skan      num_get<_CharT, _InIter>::
431132720Skan      _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
432132720Skan		     ios_base::iostate& __err, _ValueT& __v) const
433132720Skan      {
434132720Skan        typedef char_traits<_CharT>			__traits_type;
435132720Skan	typedef typename numpunct<_CharT>::__cache_type __cache_type;
436132720Skan	__use_cache<__cache_type> __uc;
437132720Skan	const locale& __loc = __io._M_getloc();
438132720Skan	const __cache_type* __lc = __uc(__loc);
439132720Skan	const _CharT* __lit = __lc->_M_atoms_in;
44097403Sobrien
441132720Skan	// NB: Iff __basefield == 0, __base can change based on contents.
442132720Skan	const ios_base::fmtflags __basefield = __io.flags()
443132720Skan	                                       & ios_base::basefield;
444132720Skan	const bool __oct = __basefield == ios_base::oct;
445132720Skan	int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10);
446102782Skan
447132720Skan	// True if numeric digits are found.
448132720Skan	bool __found_num = false;
44997403Sobrien
450132720Skan	// First check for sign.
451132720Skan	bool __negative = false;
452132720Skan	if (__beg != __end)
453132720Skan	  {
454132720Skan	    const char_type __c = *__beg;
455132720Skan	    if (numeric_limits<_ValueT>::is_signed)
456132720Skan	      __negative = __c == __lit[__num_base::_S_iminus];
457132720Skan	    if ((__negative || __c == __lit[__num_base::_S_iplus])
458132720Skan		&& !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
459132720Skan		&& !(__c == __lc->_M_decimal_point))
460132720Skan	      ++__beg;
461132720Skan	  }
462132720Skan
463132720Skan	// Next, look for leading zeros and check required digits
464132720Skan	// for base formats.
465132720Skan	while (__beg != __end)
466132720Skan	  {
467132720Skan	    const char_type __c = *__beg;
468132720Skan	    if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep
469132720Skan		|| __c == __lc->_M_decimal_point)
470132720Skan	      break;
471132720Skan	    else if (__c == __lit[__num_base::_S_izero] 
472132720Skan		     && (!__found_num || __base == 10))
473132720Skan	      {
474132720Skan		__found_num = true;
475132720Skan		++__beg;
476132720Skan	      }
477132720Skan	    else if (__found_num)
478132720Skan	      {
479132720Skan		if (__c == __lit[__num_base::_S_ix] 
480132720Skan		    || __c == __lit[__num_base::_S_iX])
481132720Skan		  {
482132720Skan		    if (__basefield == 0)
48397403Sobrien		      __base = 16;
484132720Skan		    if (__base == 16)
485132720Skan		      {
486132720Skan			__found_num = false;
487132720Skan			++__beg;
488132720Skan		      }
489132720Skan		  }
490132720Skan		else if (__basefield == 0)
491132720Skan		  __base = 8;
492132720Skan		break;
493132720Skan	      }
494132720Skan	    else
495132720Skan	      break;
496132720Skan	  }
49797403Sobrien
498132720Skan	// At this point, base is determined. If not hex, only allow
499132720Skan	// base digits as valid input.
500132720Skan	const size_t __len = __base == 16 ? (__num_base::_S_iend
501132720Skan					     - __num_base::_S_izero)
502132720Skan	                                  : __base;
50397403Sobrien
504132720Skan	// Extract.
505132720Skan	string __found_grouping;
506132720Skan	if (__lc->_M_use_grouping)
507132720Skan	  __found_grouping.reserve(32);
508132720Skan	int __sep_pos = 0;
509132720Skan	bool __overflow = false;
510132720Skan	_ValueT __result = 0;
511132720Skan	const char_type* __lit_zero = __lit + __num_base::_S_izero;
512132720Skan	const char_type* __q;
513132720Skan	if (__negative)
514132720Skan	  {
515132720Skan	    const _ValueT __min = numeric_limits<_ValueT>::min() / __base;
516132720Skan	    for (; __beg != __end; ++__beg)
517132720Skan	      {
518132720Skan		// According to 22.2.2.1.2, p8-9, first look for thousands_sep
519132720Skan		// and decimal_point.
520132720Skan		const char_type __c = *__beg;
521132720Skan		if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
522132720Skan		  {
523132720Skan		    // NB: Thousands separator at the beginning of a string
524132720Skan		    // is a no-no, as is two consecutive thousands separators.
525132720Skan		    if (__sep_pos)
526132720Skan		      {
527132720Skan			__found_grouping += static_cast<char>(__sep_pos);
528132720Skan			__sep_pos = 0;
529132720Skan		      }
530132720Skan		    else
531132720Skan		      {
532132720Skan			__err |= ios_base::failbit;
533132720Skan			break;
534132720Skan		      }
535132720Skan		  }
536132720Skan		else if (__c == __lc->_M_decimal_point)
53797403Sobrien		  break;
538132720Skan		else if (__q = __traits_type::find(__lit_zero, __len, __c))
539132720Skan		  {
540132720Skan		    int __digit = __q - __lit_zero;
541132720Skan		    if (__digit > 15)
542132720Skan		      __digit -= 6;
543132720Skan		    if (__result < __min)
544132720Skan		      __overflow = true;
545132720Skan		    else
546132720Skan		      {
547132720Skan			const _ValueT __new_result = __result * __base
548132720Skan			                             - __digit;
549132720Skan			__overflow |= __new_result > __result;
550132720Skan			__result = __new_result;
551132720Skan			++__sep_pos;
552132720Skan			__found_num = true;
553132720Skan		      }
554132720Skan		  }
555132720Skan		else
556132720Skan		  // Not a valid input item.
557132720Skan		  break;
558132720Skan	      }
559132720Skan	  }
560132720Skan	else
561132720Skan	  {
562132720Skan	    const _ValueT __max = numeric_limits<_ValueT>::max() / __base;
563132720Skan	    for (; __beg != __end; ++__beg)
564132720Skan	      {
565132720Skan		const char_type __c = *__beg;
566132720Skan		if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
567132720Skan		  {
568132720Skan		    if (__sep_pos)
569132720Skan		      {
570132720Skan			__found_grouping += static_cast<char>(__sep_pos);
571132720Skan			__sep_pos = 0;
572132720Skan		      }
573132720Skan		    else
574132720Skan		      {
575132720Skan			__err |= ios_base::failbit;
576132720Skan			break;
577132720Skan		      }
578132720Skan		  }
579132720Skan		else if (__c == __lc->_M_decimal_point)
580132720Skan		  break;
581132720Skan		else if (__q = __traits_type::find(__lit_zero, __len, __c))
582132720Skan		  {
583132720Skan		    int __digit = __q - __lit_zero;
584132720Skan		    if (__digit > 15)
585132720Skan		      __digit -= 6;
586132720Skan		    if (__result > __max)
587132720Skan		      __overflow = true;
588132720Skan		    else
589132720Skan		      {
590132720Skan			const _ValueT __new_result = __result * __base
591132720Skan			                             + __digit;
592132720Skan			__overflow |= __new_result < __result;
593132720Skan			__result = __new_result;
594132720Skan			++__sep_pos;
595132720Skan			__found_num = true;
596132720Skan		      }
597132720Skan		  }
598132720Skan		else
599132720Skan		  break;
600132720Skan	      }
601132720Skan	  }
60297403Sobrien
603132720Skan	// Digit grouping is checked. If grouping and found_grouping don't
604132720Skan	// match, then get very very upset, and set failbit.
605132720Skan	if (__lc->_M_use_grouping && __found_grouping.size())
606132720Skan	  {
607132720Skan	    // Add the ending grouping.
608132720Skan	    __found_grouping += static_cast<char>(__sep_pos);
60997403Sobrien
610132720Skan	    if (!std::__verify_grouping(__lc->_M_grouping,
611132720Skan					__lc->_M_grouping_size,
612132720Skan					__found_grouping))
613132720Skan	      __err |= ios_base::failbit;
614132720Skan	  }
61597403Sobrien
616132720Skan	if (!(__err & ios_base::failbit) && !__overflow
617132720Skan	    && __found_num)
618132720Skan	  __v = __result;
619132720Skan	else
620132720Skan	  __err |= ios_base::failbit;
621132720Skan
622132720Skan	if (__beg == __end)
623132720Skan	  __err |= ios_base::eofbit;
624132720Skan	return __beg;
625132720Skan      }
626132720Skan
627132720Skan  // _GLIBCXX_RESOLVE_LIB_DEFECTS
628132720Skan  // 17.  Bad bool parsing
62997403Sobrien  template<typename _CharT, typename _InIter>
63097403Sobrien    _InIter
63197403Sobrien    num_get<_CharT, _InIter>::
63297403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
63397403Sobrien           ios_base::iostate& __err, bool& __v) const
63497403Sobrien    {
63597403Sobrien      if (!(__io.flags() & ios_base::boolalpha))
63697403Sobrien        {
637132720Skan	  // Parse bool values as long.
63897403Sobrien          // NB: We can't just call do_get(long) here, as it might
63997403Sobrien          // refer to a derived class.
640132720Skan	  long __l = -1;
641132720Skan          __beg = _M_extract_int(__beg, __end, __io, __err, __l);
642132720Skan	  if (__l == 0 || __l == 1)
643132720Skan	    __v = __l;
644132720Skan	  else
64597403Sobrien            __err |= ios_base::failbit;
64697403Sobrien        }
64797403Sobrien      else
64897403Sobrien        {
649132720Skan	  // Parse bool values as alphanumeric.
650132720Skan	  typedef char_traits<_CharT>                     __traits_type;
651132720Skan	  typedef typename numpunct<_CharT>::__cache_type __cache_type;
652132720Skan	  __use_cache<__cache_type> __uc;
653132720Skan	  const locale& __loc = __io._M_getloc();
654132720Skan	  const __cache_type* __lc = __uc(__loc);
655102782Skan
656132720Skan	  bool __testf = true;
657132720Skan	  bool __testt = true;
658132720Skan	  size_t __n;
659132720Skan          for (__n = 0; __beg != __end; ++__n, ++__beg)
660132720Skan            {
661132720Skan	      if (__testf)
662132720Skan		if (__n < __lc->_M_falsename_size)
663132720Skan		  __testf = *__beg == __lc->_M_falsename[__n];
664132720Skan		else
665132720Skan		  break;
66697403Sobrien
667132720Skan	      if (__testt)
668132720Skan		if (__n < __lc->_M_truename_size)
669132720Skan		  __testt = *__beg == __lc->_M_truename[__n];
670132720Skan		else
671132720Skan		  break;
672132720Skan
673132720Skan	      if (!__testf && !__testt)
674132720Skan		break;
67597403Sobrien            }
676132720Skan	  if (__testf && __n == __lc->_M_falsename_size)
677132720Skan	    __v = 0;
678132720Skan	  else if (__testt && __n == __lc->_M_truename_size)
679132720Skan	    __v = 1;
680132720Skan	  else
681132720Skan	    __err |= ios_base::failbit;
682132720Skan
68397403Sobrien          if (__beg == __end)
68497403Sobrien            __err |= ios_base::eofbit;
68597403Sobrien        }
68697403Sobrien      return __beg;
68797403Sobrien    }
68897403Sobrien
68997403Sobrien  template<typename _CharT, typename _InIter>
69097403Sobrien    _InIter
69197403Sobrien    num_get<_CharT, _InIter>::
69297403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
69397403Sobrien           ios_base::iostate& __err, long& __v) const
694132720Skan    { return _M_extract_int(__beg, __end, __io, __err, __v); }
69597403Sobrien
69697403Sobrien  template<typename _CharT, typename _InIter>
69797403Sobrien    _InIter
69897403Sobrien    num_get<_CharT, _InIter>::
69997403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
70097403Sobrien           ios_base::iostate& __err, unsigned short& __v) const
701132720Skan    { return _M_extract_int(__beg, __end, __io, __err, __v); }
70297403Sobrien
70397403Sobrien  template<typename _CharT, typename _InIter>
70497403Sobrien    _InIter
70597403Sobrien    num_get<_CharT, _InIter>::
70697403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
70797403Sobrien           ios_base::iostate& __err, unsigned int& __v) const
708132720Skan    { return _M_extract_int(__beg, __end, __io, __err, __v); }
70997403Sobrien
71097403Sobrien  template<typename _CharT, typename _InIter>
71197403Sobrien    _InIter
71297403Sobrien    num_get<_CharT, _InIter>::
71397403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
71497403Sobrien           ios_base::iostate& __err, unsigned long& __v) const
715132720Skan    { return _M_extract_int(__beg, __end, __io, __err, __v); }
71697403Sobrien
717132720Skan#ifdef _GLIBCXX_USE_LONG_LONG
71897403Sobrien  template<typename _CharT, typename _InIter>
71997403Sobrien    _InIter
72097403Sobrien    num_get<_CharT, _InIter>::
72197403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
72297403Sobrien           ios_base::iostate& __err, long long& __v) const
723132720Skan    { return _M_extract_int(__beg, __end, __io, __err, __v); }
72497403Sobrien
72597403Sobrien  template<typename _CharT, typename _InIter>
72697403Sobrien    _InIter
72797403Sobrien    num_get<_CharT, _InIter>::
72897403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
72997403Sobrien           ios_base::iostate& __err, unsigned long long& __v) const
730132720Skan    { return _M_extract_int(__beg, __end, __io, __err, __v); }
73197403Sobrien#endif
73297403Sobrien
73397403Sobrien  template<typename _CharT, typename _InIter>
73497403Sobrien    _InIter
73597403Sobrien    num_get<_CharT, _InIter>::
736132720Skan    do_get(iter_type __beg, iter_type __end, ios_base& __io,
73797403Sobrien	   ios_base::iostate& __err, float& __v) const
73897403Sobrien    {
73997403Sobrien      string __xtrc;
74097403Sobrien      __xtrc.reserve(32);
74197403Sobrien      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
742132720Skan      std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
74397403Sobrien      return __beg;
74497403Sobrien    }
74597403Sobrien
74697403Sobrien  template<typename _CharT, typename _InIter>
74797403Sobrien    _InIter
74897403Sobrien    num_get<_CharT, _InIter>::
74997403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
75097403Sobrien           ios_base::iostate& __err, double& __v) const
75197403Sobrien    {
75297403Sobrien      string __xtrc;
75397403Sobrien      __xtrc.reserve(32);
75497403Sobrien      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
755132720Skan      std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
75697403Sobrien      return __beg;
75797403Sobrien    }
75897403Sobrien
75997403Sobrien  template<typename _CharT, typename _InIter>
76097403Sobrien    _InIter
76197403Sobrien    num_get<_CharT, _InIter>::
76297403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
76397403Sobrien           ios_base::iostate& __err, long double& __v) const
76497403Sobrien    {
76597403Sobrien      string __xtrc;
76697403Sobrien      __xtrc.reserve(32);
76797403Sobrien      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
768132720Skan      std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
76997403Sobrien      return __beg;
77097403Sobrien    }
77197403Sobrien
77297403Sobrien  template<typename _CharT, typename _InIter>
77397403Sobrien    _InIter
77497403Sobrien    num_get<_CharT, _InIter>::
77597403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
77697403Sobrien           ios_base::iostate& __err, void*& __v) const
77797403Sobrien    {
778132720Skan      // Prepare for hex formatted input.
77997403Sobrien      typedef ios_base::fmtflags        fmtflags;
780132720Skan      const fmtflags __fmt = __io.flags();
781132720Skan      __io.flags(__fmt & ~ios_base::basefield | ios_base::hex);
78297403Sobrien
783132720Skan      unsigned long __ul;
784132720Skan      __beg = _M_extract_int(__beg, __end, __io, __err, __ul);
78597403Sobrien
786132720Skan      // Reset from hex formatted input.
78797403Sobrien      __io.flags(__fmt);
78897403Sobrien
78997403Sobrien      if (!(__err & ios_base::failbit))
79097403Sobrien	__v = reinterpret_cast<void*>(__ul);
791132720Skan      else
79297403Sobrien	__err |= ios_base::failbit;
79397403Sobrien      return __beg;
79497403Sobrien    }
79597403Sobrien
796117397Skan  // For use by integer and floating-point types after they have been
797117397Skan  // converted into a char_type string.
798117397Skan  template<typename _CharT, typename _OutIter>
799117397Skan    void
800117397Skan    num_put<_CharT, _OutIter>::
801132720Skan    _M_pad(_CharT __fill, streamsize __w, ios_base& __io,
802117397Skan	   _CharT* __new, const _CharT* __cs, int& __len) const
803117397Skan    {
804117397Skan      // [22.2.2.2.2] Stage 3.
805117397Skan      // If necessary, pad.
806132720Skan      __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs,
807117397Skan						  __w, __len, true);
808117397Skan      __len = static_cast<int>(__w);
809117397Skan    }
810117397Skan
811117397Skan  // Forwarding functions to peel signed from unsigned integer types.
812117397Skan  template<typename _CharT>
813117397Skan    inline int
814132720Skan    __int_to_char(_CharT* __bufend, long __v, const _CharT* __lit,
815132720Skan		  ios_base::fmtflags __flags)
816117397Skan    {
817117397Skan      unsigned long __ul = static_cast<unsigned long>(__v);
818117397Skan      bool __neg = false;
819132720Skan      if (__v < 0)
820117397Skan	{
821117397Skan	  __ul = -__ul;
822117397Skan	  __neg = true;
823117397Skan	}
824132720Skan      return __int_to_char(__bufend, __ul, __lit, __flags, __neg);
825117397Skan    }
826117397Skan
827117397Skan  template<typename _CharT>
828117397Skan    inline int
829132720Skan    __int_to_char(_CharT* __bufend, unsigned long __v, const _CharT* __lit,
830132720Skan		  ios_base::fmtflags __flags)
831132720Skan    {
832132720Skan      // About showpos, see Table 60 and C99 7.19.6.1, p6 (+).
833132720Skan      return __int_to_char(__bufend, __v, __lit,
834132720Skan			   __flags & ~ios_base::showpos, false);
835132720Skan    }
836117397Skan
837132720Skan#ifdef _GLIBCXX_USE_LONG_LONG
838117397Skan  template<typename _CharT>
839117397Skan    inline int
840132720Skan    __int_to_char(_CharT* __bufend, long long __v, const _CharT* __lit,
841132720Skan		  ios_base::fmtflags __flags)
842132720Skan    {
843117397Skan      unsigned long long __ull = static_cast<unsigned long long>(__v);
844117397Skan      bool __neg = false;
845132720Skan      if (__v < 0)
846117397Skan	{
847117397Skan	  __ull = -__ull;
848117397Skan	  __neg = true;
849117397Skan	}
850132720Skan      return __int_to_char(__bufend, __ull, __lit, __flags, __neg);
851117397Skan    }
852117397Skan
853117397Skan  template<typename _CharT>
854117397Skan    inline int
855132720Skan    __int_to_char(_CharT* __bufend, unsigned long long __v, 
856132720Skan		  const _CharT* __lit, ios_base::fmtflags __flags)
857132720Skan    { return __int_to_char(__bufend, __v, __lit,
858132720Skan			   __flags & ~ios_base::showpos, false); }
859117397Skan#endif
860132720Skan
861117397Skan  template<typename _CharT, typename _ValueT>
862117397Skan    int
863132720Skan    __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
864132720Skan		  ios_base::fmtflags __flags, bool __neg)
865117397Skan    {
866117397Skan      // Don't write base if already 0.
867117397Skan      const bool __showbase = (__flags & ios_base::showbase) && __v;
868117397Skan      const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
869132720Skan      _CharT* __buf = __bufend - 1;
870117397Skan
871117397Skan      if (__builtin_expect(__basefield != ios_base::oct &&
872117397Skan			   __basefield != ios_base::hex, true))
873117397Skan	{
874117397Skan	  // Decimal.
875132720Skan	  do
876117397Skan	    {
877132720Skan	      *__buf-- = __lit[(__v % 10) + __num_base::_S_odigits];
878117397Skan	      __v /= 10;
879132720Skan	    }
880117397Skan	  while (__v != 0);
881117397Skan	  if (__neg)
882132720Skan	    *__buf-- = __lit[__num_base::_S_ominus];
883117397Skan	  else if (__flags & ios_base::showpos)
884132720Skan	    *__buf-- = __lit[__num_base::_S_oplus];
885117397Skan	}
886117397Skan      else if (__basefield == ios_base::oct)
887117397Skan	{
888117397Skan	  // Octal.
889132720Skan	  do
890117397Skan	    {
891132720Skan	      *__buf-- = __lit[(__v & 0x7) + __num_base::_S_odigits];
892117397Skan	      __v >>= 3;
893132720Skan	    }
894117397Skan	  while (__v != 0);
895117397Skan	  if (__showbase)
896132720Skan	    *__buf-- = __lit[__num_base::_S_odigits];
897117397Skan	}
898117397Skan      else
899117397Skan	{
900117397Skan	  // Hex.
901117397Skan	  const bool __uppercase = __flags & ios_base::uppercase;
902132720Skan	  const int __case_offset = __uppercase ? __num_base::_S_oudigits
903132720Skan	                                        : __num_base::_S_odigits;
904132720Skan	  do
905117397Skan	    {
906117397Skan	      *__buf-- = __lit[(__v & 0xf) + __case_offset];
907117397Skan	      __v >>= 4;
908132720Skan	    }
909117397Skan	  while (__v != 0);
910117397Skan	  if (__showbase)
911117397Skan	    {
912117397Skan	      // 'x' or 'X'
913132720Skan	      *__buf-- = __lit[__num_base::_S_ox + __uppercase];
914117397Skan	      // '0'
915132720Skan	      *__buf-- = __lit[__num_base::_S_odigits];
916117397Skan	    }
917117397Skan	}
918132720Skan      return __bufend - __buf - 1;
919117397Skan    }
920117397Skan
921117397Skan  template<typename _CharT, typename _OutIter>
922117397Skan    void
923117397Skan    num_put<_CharT, _OutIter>::
924132720Skan    _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep,
925132720Skan		 ios_base& __io, _CharT* __new, _CharT* __cs, int& __len) const
926117397Skan    {
927132720Skan      // By itself __add_grouping cannot deal correctly with __cs when
928117397Skan      // ios::showbase is set and ios_base::oct || ios_base::hex.
929117397Skan      // Therefore we take care "by hand" of the initial 0, 0x or 0X.
930117397Skan      // However, remember that the latter do not occur if the number
931117397Skan      // printed is '0' (__len == 1).
932117397Skan      streamsize __off = 0;
933132720Skan      const ios_base::fmtflags __basefield = __io.flags()
934117397Skan	                                     & ios_base::basefield;
935117397Skan      if ((__io.flags() & ios_base::showbase) && __len > 1)
936117397Skan	if (__basefield == ios_base::oct)
937117397Skan	  {
938117397Skan	    __off = 1;
939132720Skan	    __new[0] = __cs[0];
940117397Skan	  }
941117397Skan	else if (__basefield == ios_base::hex)
942117397Skan	  {
943117397Skan	    __off = 2;
944132720Skan	    __new[0] = __cs[0];
945132720Skan	    __new[1] = __cs[1];
946117397Skan	  }
947117397Skan      _CharT* __p;
948132720Skan      __p = std::__add_grouping(__new + __off, __sep, __grouping,
949132720Skan				__grouping_size, __cs + __off,
950132720Skan				__cs + __len);
951117397Skan      __len = __p - __new;
952117397Skan    }
953117397Skan
954117397Skan  template<typename _CharT, typename _OutIter>
955117397Skan    template<typename _ValueT>
956117397Skan      _OutIter
957117397Skan      num_put<_CharT, _OutIter>::
958132720Skan      _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill,
959132720Skan		    _ValueT __v) const
960117397Skan      {
961132720Skan	typedef typename numpunct<_CharT>::__cache_type	__cache_type;
962132720Skan	__use_cache<__cache_type> __uc;
963132720Skan	const locale& __loc = __io._M_getloc();
964132720Skan	const __cache_type* __lc = __uc(__loc);
965132720Skan	const _CharT* __lit = __lc->_M_atoms_out;
966117397Skan
967117397Skan	// Long enough to hold hex, dec, and octal representations.
968132720Skan	const int __ilen = 4 * sizeof(_ValueT);
969132720Skan	_CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
970117397Skan							     * __ilen));
971132720Skan
972117397Skan	// [22.2.2.2.2] Stage 1, numeric conversion to character.
973117397Skan	// Result is returned right-justified in the buffer.
974117397Skan	int __len;
975132720Skan	__len = __int_to_char(__cs + __ilen, __v, __lit, __io.flags());
976132720Skan	__cs += __ilen - __len;
977132720Skan
978132720Skan	// Add grouping, if necessary.
979132720Skan	if (__lc->_M_use_grouping)
980117397Skan	  {
981117397Skan	    // Grouping can add (almost) as many separators as the
982117397Skan	    // number of digits, but no more.
983132720Skan	    _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
984132720Skan								  * __len * 2));
985132720Skan	    _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size,
986132720Skan			 __lc->_M_thousands_sep, __io, __cs2, __cs, __len);
987117397Skan	    __cs = __cs2;
988117397Skan	  }
989132720Skan
990117397Skan	// Pad.
991132720Skan	const streamsize __w = __io.width();
992117397Skan	if (__w > static_cast<streamsize>(__len))
993117397Skan	  {
994132720Skan	    _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
995132720Skan								  * __w));
996117397Skan	    _M_pad(__fill, __w, __io, __cs3, __cs, __len);
997117397Skan	    __cs = __cs3;
998117397Skan	  }
999117397Skan	__io.width(0);
1000117397Skan
1001117397Skan	// [22.2.2.2.2] Stage 4.
1002117397Skan	// Write resulting, fully-formatted string to output iterator.
1003132720Skan	return std::__write(__s, __cs, __len);
1004132720Skan      }
1005117397Skan
1006117397Skan  template<typename _CharT, typename _OutIter>
1007117397Skan    void
1008117397Skan    num_put<_CharT, _OutIter>::
1009132720Skan    _M_group_float(const char* __grouping, size_t __grouping_size,
1010132720Skan		   _CharT __sep, const _CharT* __p, _CharT* __new,
1011132720Skan		   _CharT* __cs, int& __len) const
1012117397Skan    {
1013132720Skan      // _GLIBCXX_RESOLVE_LIB_DEFECTS
1014132720Skan      // 282. What types does numpunct grouping refer to?
1015132720Skan      // Add grouping, if necessary.
1016117397Skan      _CharT* __p2;
1017132720Skan      const int __declen = __p ? __p - __cs : __len;
1018132720Skan      __p2 = std::__add_grouping(__new, __sep, __grouping, __grouping_size,
1019132720Skan				 __cs, __cs + __declen);
1020132720Skan
1021117397Skan      // Tack on decimal part.
1022117397Skan      int __newlen = __p2 - __new;
1023117397Skan      if (__p)
1024117397Skan	{
1025117397Skan	  char_traits<_CharT>::copy(__p2, __p, __len - __declen);
1026117397Skan	  __newlen += __len - __declen;
1027132720Skan	}
1028117397Skan      __len = __newlen;
1029117397Skan    }
1030117397Skan
1031117397Skan  // The following code uses snprintf (or sprintf(), when
1032132720Skan  // _GLIBCXX_USE_C99 is not defined) to convert floating point values
1033117397Skan  // for insertion into a stream.  An optimization would be to replace
1034117397Skan  // them with code that works directly on a wide buffer and then use
1035117397Skan  // __pad to do the padding.  It would be good to replace them anyway
1036117397Skan  // to gain back the efficiency that C++ provides by knowing up front
1037117397Skan  // the type of the values to insert.  Also, sprintf is dangerous
1038117397Skan  // since may lead to accidental buffer overruns.  This
1039117397Skan  // implementation follows the C++ standard fairly directly as
104097403Sobrien  // outlined in 22.2.2.2 [lib.locale.num.put]
104197403Sobrien  template<typename _CharT, typename _OutIter>
104297403Sobrien    template<typename _ValueT>
104397403Sobrien      _OutIter
104497403Sobrien      num_put<_CharT, _OutIter>::
1045132720Skan      _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
104697403Sobrien		       _ValueT __v) const
104797403Sobrien      {
1048132720Skan	typedef typename numpunct<_CharT>::__cache_type	__cache_type;
1049132720Skan	__use_cache<__cache_type> __uc;
1050132720Skan	const locale& __loc = __io._M_getloc();
1051132720Skan	const __cache_type* __lc = __uc(__loc);
1052117397Skan
1053117397Skan	// Use default precision if out of range.
105497403Sobrien	streamsize __prec = __io.precision();
1055132720Skan	if (__prec < static_cast<streamsize>(0))
1056117397Skan	  __prec = static_cast<streamsize>(6);
105797403Sobrien
1058132720Skan	const int __max_digits = numeric_limits<_ValueT>::digits10;
1059117397Skan
1060117397Skan	// [22.2.2.2.2] Stage 1, numeric conversion to character.
1061117397Skan	int __len;
106297403Sobrien	// Long enough for the max format spec.
106397403Sobrien	char __fbuf[16];
106497403Sobrien
1065132720Skan#ifdef _GLIBCXX_USE_C99
1066132720Skan	// First try a buffer perhaps big enough (most probably sufficient
1067117397Skan	// for non-ios_base::fixed outputs)
106897403Sobrien	int __cs_size = __max_digits * 3;
106997403Sobrien	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
107097403Sobrien
1071132720Skan	__num_base::_S_format_float(__io, __fbuf, __mod);
1072132720Skan	__len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
1073132720Skan				      _S_get_c_locale(), __prec);
107497403Sobrien
107597403Sobrien	// If the buffer was not large enough, try again with the correct size.
107697403Sobrien	if (__len >= __cs_size)
107797403Sobrien	  {
1078132720Skan	    __cs_size = __len + 1;
107997403Sobrien	    __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1080132720Skan	    __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
1081132720Skan					  _S_get_c_locale(), __prec);
108297403Sobrien	  }
108397403Sobrien#else
108497403Sobrien	// Consider the possibility of long ios_base::fixed outputs
108597403Sobrien	const bool __fixed = __io.flags() & ios_base::fixed;
108697403Sobrien	const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
1087117397Skan
1088132720Skan	// The size of the output string is computed as follows.
1089132720Skan	// ios_base::fixed outputs may need up to __max_exp + 1 chars
1090132720Skan	// for the integer part + __prec chars for the fractional part
1091132720Skan	// + 3 chars for sign, decimal point, '\0'. On the other hand,
1092132720Skan	// for non-fixed outputs __max_digits * 2 + __prec chars are
1093132720Skan	// largely sufficient.
1094132720Skan	const int __cs_size = __fixed ? __max_exp + __prec + 4
1095132720Skan	                              : __max_digits * 2 + __prec;
109697403Sobrien	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
109797403Sobrien
1098132720Skan	__num_base::_S_format_float(__io, __fbuf, __mod);
1099132720Skan	__len = std::__convert_from_v(__cs, 0, __fbuf, __v,
1100132720Skan				      _S_get_c_locale(), __prec);
110197403Sobrien#endif
110297403Sobrien
110397403Sobrien      // [22.2.2.2.2] Stage 2, convert to char_type, using correct
110497403Sobrien      // numpunct.decimal_point() values for '.' and adding grouping.
110597403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1106117397Skan
1107132720Skan      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
110897403Sobrien							   * __len));
110997403Sobrien      __ctype.widen(__cs, __cs + __len, __ws);
1110132720Skan
111197403Sobrien      // Replace decimal point.
1112117397Skan      const _CharT __cdec = __ctype.widen('.');
1113132720Skan      const _CharT __dec = __lc->_M_decimal_point;
111497403Sobrien      const _CharT* __p;
1115117397Skan      if (__p = char_traits<_CharT>::find(__ws, __len, __cdec))
1116117397Skan	__ws[__p - __ws] = __dec;
111797403Sobrien
1118132720Skan      // Add grouping, if necessary.
1119132720Skan      if (__lc->_M_use_grouping)
112097403Sobrien	{
1121132720Skan	  // Grouping can add (almost) as many separators as the
1122132720Skan	  // number of digits, but no more.
1123132720Skan	  _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1124132720Skan								* __len * 2));
1125132720Skan	  _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size,
1126132720Skan			 __lc->_M_thousands_sep, __p, __ws2, __ws, __len);
1127132720Skan	  __ws = __ws2;
112897403Sobrien	}
112997403Sobrien
1130117397Skan      // Pad.
1131132720Skan      const streamsize __w = __io.width();
113297403Sobrien      if (__w > static_cast<streamsize>(__len))
113397403Sobrien	{
1134132720Skan	  _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1135132720Skan								* __w));
1136117397Skan	  _M_pad(__fill, __w, __io, __ws3, __ws, __len);
1137117397Skan	  __ws = __ws3;
113897403Sobrien	}
113997403Sobrien      __io.width(0);
1140132720Skan
114197403Sobrien      // [22.2.2.2.2] Stage 4.
114297403Sobrien      // Write resulting, fully-formatted string to output iterator.
1143132720Skan      return std::__write(__s, __ws, __len);
1144117397Skan      }
114597403Sobrien
114697403Sobrien  template<typename _CharT, typename _OutIter>
114797403Sobrien    _OutIter
114897403Sobrien    num_put<_CharT, _OutIter>::
114997403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
115097403Sobrien    {
1151132720Skan      const ios_base::fmtflags __flags = __io.flags();
115297403Sobrien      if ((__flags & ios_base::boolalpha) == 0)
115397403Sobrien        {
115497403Sobrien          unsigned long __uv = __v;
1155132720Skan          __s = _M_insert_int(__s, __io, __fill, __uv);
115697403Sobrien        }
115797403Sobrien      else
115897403Sobrien        {
1159132720Skan	  typedef typename numpunct<_CharT>::__cache_type __cache_type;
1160132720Skan	  __use_cache<__cache_type> __uc;
1161132720Skan	  const locale& __loc = __io._M_getloc();
1162132720Skan	  const __cache_type* __lc = __uc(__loc);
1163117397Skan
1164132720Skan	  const _CharT* __name = __v ? __lc->_M_truename
1165132720Skan	                             : __lc->_M_falsename;
1166132720Skan	  int __len = __v ? __lc->_M_truename_size
1167132720Skan	                  : __lc->_M_falsename_size;
1168117397Skan
1169132720Skan	  const streamsize __w = __io.width();
1170117397Skan	  if (__w > static_cast<streamsize>(__len))
1171117397Skan	    {
1172132720Skan	      _CharT* __cs
1173132720Skan		= static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1174132720Skan							* __w));
1175132720Skan	      _M_pad(__fill, __w, __io, __cs, __name, __len);
1176132720Skan	      __name = __cs;
1177117397Skan	    }
1178117397Skan	  __io.width(0);
1179132720Skan	  __s = std::__write(__s, __name, __len);
118097403Sobrien	}
118197403Sobrien      return __s;
118297403Sobrien    }
118397403Sobrien
118497403Sobrien  template<typename _CharT, typename _OutIter>
118597403Sobrien    _OutIter
118697403Sobrien    num_put<_CharT, _OutIter>::
118797403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
1188132720Skan    { return _M_insert_int(__s, __io, __fill, __v); }
118997403Sobrien
119097403Sobrien  template<typename _CharT, typename _OutIter>
119197403Sobrien    _OutIter
119297403Sobrien    num_put<_CharT, _OutIter>::
119397403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill,
119497403Sobrien           unsigned long __v) const
1195132720Skan    { return _M_insert_int(__s, __io, __fill, __v); }
119697403Sobrien
1197132720Skan#ifdef _GLIBCXX_USE_LONG_LONG
119897403Sobrien  template<typename _CharT, typename _OutIter>
119997403Sobrien    _OutIter
120097403Sobrien    num_put<_CharT, _OutIter>::
120197403Sobrien    do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
1202132720Skan    { return _M_insert_int(__s, __b, __fill, __v); }
120397403Sobrien
120497403Sobrien  template<typename _CharT, typename _OutIter>
120597403Sobrien    _OutIter
120697403Sobrien    num_put<_CharT, _OutIter>::
120797403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill,
120897403Sobrien           unsigned long long __v) const
1209132720Skan    { return _M_insert_int(__s, __io, __fill, __v); }
121097403Sobrien#endif
121197403Sobrien
121297403Sobrien  template<typename _CharT, typename _OutIter>
121397403Sobrien    _OutIter
121497403Sobrien    num_put<_CharT, _OutIter>::
121597403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
1216132720Skan    { return _M_insert_float(__s, __io, __fill, char(), __v); }
121797403Sobrien
121897403Sobrien  template<typename _CharT, typename _OutIter>
121997403Sobrien    _OutIter
122097403Sobrien    num_put<_CharT, _OutIter>::
1221132720Skan    do_put(iter_type __s, ios_base& __io, char_type __fill,
122297403Sobrien	   long double __v) const
1223132720Skan    { return _M_insert_float(__s, __io, __fill, 'L', __v); }
122497403Sobrien
122597403Sobrien  template<typename _CharT, typename _OutIter>
122697403Sobrien    _OutIter
122797403Sobrien    num_put<_CharT, _OutIter>::
122897403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill,
122997403Sobrien           const void* __v) const
123097403Sobrien    {
1231132720Skan      const ios_base::fmtflags __flags = __io.flags();
1232132720Skan      const ios_base::fmtflags __fmt = ~(ios_base::showpos
1233132720Skan					 | ios_base::basefield
1234132720Skan					 | ios_base::uppercase
1235132720Skan					 | ios_base::internal);
123697403Sobrien      __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
1237132720Skan
1238132720Skan      __s = _M_insert_int(__s, __io, __fill,
1239132720Skan			  reinterpret_cast<unsigned long>(__v));
1240132720Skan      __io.flags(__flags);
124197403Sobrien      return __s;
124297403Sobrien    }
124397403Sobrien
124497403Sobrien  template<typename _CharT, typename _InIter>
1245132720Skan    template<bool _Intl>
1246132720Skan      _InIter
1247132720Skan      money_get<_CharT, _InIter>::
1248132720Skan      _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
1249132720Skan		 ios_base::iostate& __err, string& __units) const
1250132720Skan      {
1251132720Skan	typedef char_traits<_CharT>			  __traits_type;
1252132720Skan	typedef typename string_type::size_type	          size_type;	
1253132720Skan	typedef money_base::part			  part;
1254132720Skan	typedef moneypunct<_CharT, _Intl>		  __moneypunct_type;
1255132720Skan	typedef typename __moneypunct_type::__cache_type  __cache_type;
1256132720Skan	
1257132720Skan	const locale& __loc = __io._M_getloc();
1258132720Skan	const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
125997403Sobrien
1260132720Skan	__use_cache<__cache_type> __uc;
1261132720Skan	const __cache_type* __lc = __uc(__loc);
1262132720Skan	const char_type* __lit = __lc->_M_atoms;
126397403Sobrien
1264132720Skan	// Deduced sign.
1265132720Skan	bool __negative = false;
1266132720Skan	// Sign size.
1267132720Skan	size_type __sign_size = 0;
1268132720Skan	// True if sign is mandatory.
1269132720Skan	const bool __mandatory_sign = (__lc->_M_positive_sign_size
1270132720Skan				       && __lc->_M_negative_sign_size);
1271132720Skan	// String of grouping info from thousands_sep plucked from __units.
1272132720Skan	string __grouping_tmp;
1273132720Skan	if (__lc->_M_use_grouping)
1274132720Skan	  __grouping_tmp.reserve(32);
1275132720Skan	// Last position before the decimal point.
1276132720Skan	int __last_pos = 0;
1277132720Skan	// Separator positions, then, possibly, fractional digits.
1278132720Skan	int __n = 0;
1279132720Skan	// If input iterator is in a valid state.
1280132720Skan	bool __testvalid = true;
1281132720Skan	// Flag marking when a decimal point is found.
1282132720Skan	bool __testdecfound = false;
128397403Sobrien
1284132720Skan	// The tentative returned string is stored here.
1285132720Skan	string __res;
1286132720Skan	__res.reserve(32);
128797403Sobrien
1288132720Skan	const char_type* __lit_zero = __lit + money_base::_S_zero;
1289132720Skan	const char_type* __q;
1290132720Skan	const money_base::pattern __p = __lc->_M_neg_format;	
1291132720Skan	for (int __i = 0; __i < 4 && __testvalid; ++__i)
1292132720Skan	  {
1293132720Skan	    const part __which = static_cast<part>(__p.field[__i]);
1294132720Skan	    switch (__which)
1295132720Skan	      {
1296132720Skan	      case money_base::symbol:
1297132720Skan		// According to 22.2.6.1.2, p2, symbol is required
1298132720Skan		// if (__io.flags() & ios_base::showbase), otherwise
1299132720Skan		// is optional and consumed only if other characters
1300132720Skan		// are needed to complete the format.
1301132720Skan		if (__io.flags() & ios_base::showbase || __sign_size > 1
1302132720Skan		    || __i == 0
1303132720Skan		    || (__i == 1 && (__mandatory_sign
1304132720Skan				     || (static_cast<part>(__p.field[0])
1305132720Skan					 == money_base::sign)
1306132720Skan				     || (static_cast<part>(__p.field[2])
1307132720Skan					 == money_base::space)))
1308132720Skan		    || (__i == 2 && ((static_cast<part>(__p.field[3])
1309132720Skan				      == money_base::value)
1310132720Skan				     || __mandatory_sign
1311132720Skan				     && (static_cast<part>(__p.field[3])
1312132720Skan					 == money_base::sign))))
131397403Sobrien		  {
1314132720Skan		    const size_type __len = __lc->_M_curr_symbol_size;
1315132720Skan		    size_type __j = 0;
1316132720Skan		    for (; __beg != __end && __j < __len
1317132720Skan			   && *__beg == __lc->_M_curr_symbol[__j];
1318132720Skan			 ++__beg, ++__j);
1319132720Skan		    if (__j != __len
1320132720Skan			&& (__j || __io.flags() & ios_base::showbase))
132197403Sobrien		      __testvalid = false;
132297403Sobrien		  }
1323132720Skan		break;
1324132720Skan	      case money_base::sign:
1325132720Skan		// Sign might not exist, or be more than one character long.
1326132720Skan		if (__lc->_M_positive_sign_size && __beg != __end
1327132720Skan		    && *__beg == __lc->_M_positive_sign[0])
1328132720Skan		  {
1329132720Skan		    __sign_size = __lc->_M_positive_sign_size;
1330132720Skan		    ++__beg;
1331132720Skan		  }
1332132720Skan		else if (__lc->_M_negative_sign_size && __beg != __end
1333132720Skan			 && *__beg == __lc->_M_negative_sign[0])
1334132720Skan		  {
1335132720Skan		    __negative = true;
1336132720Skan		    __sign_size = __lc->_M_negative_sign_size;
1337132720Skan		    ++__beg;
1338132720Skan		  }
1339132720Skan		else if (__lc->_M_positive_sign_size
1340132720Skan			 && !__lc->_M_negative_sign_size)
1341132720Skan		  // "... if no sign is detected, the result is given the sign
1342132720Skan		  // that corresponds to the source of the empty string"
1343132720Skan		  __negative = true;
1344132720Skan		else if (__mandatory_sign)
1345132720Skan		  __testvalid = false;
1346132720Skan		break;
1347132720Skan	      case money_base::value:
1348132720Skan		// Extract digits, remove and stash away the
1349132720Skan		// grouping of found thousands separators.
1350132720Skan		for (; __beg != __end; ++__beg)
1351132720Skan		  if (__q = __traits_type::find(__lit_zero, 10, *__beg))
135297403Sobrien		    {
1353132720Skan		      __res += money_base::_S_atoms[__q - __lit];
1354132720Skan		      ++__n;
135597403Sobrien		    }
1356132720Skan		  else if (*__beg == __lc->_M_decimal_point && !__testdecfound)
135797403Sobrien		    {
1358132720Skan		      __last_pos = __n;
1359132720Skan		      __n = 0;
1360132720Skan		      __testdecfound = true;
136197403Sobrien		    }
1362132720Skan		  else if (__lc->_M_use_grouping
1363132720Skan			   && *__beg == __lc->_M_thousands_sep
1364132720Skan			   && !__testdecfound)
136597403Sobrien		    {
1366132720Skan		      if (__n)
136797403Sobrien			{
1368132720Skan			  // Mark position for later analysis.
1369132720Skan			  __grouping_tmp += static_cast<char>(__n);
1370132720Skan			  __n = 0;
137197403Sobrien			}
137297403Sobrien		      else
137397403Sobrien			{
1374132720Skan			  __testvalid = false;
1375132720Skan			  break;
137697403Sobrien			}
137797403Sobrien		    }
1378132720Skan		  else
1379132720Skan		    break;
1380132720Skan		if (__res.empty())
1381132720Skan		  __testvalid = false;
1382132720Skan		break;
1383132720Skan	      case money_base::space:
1384132720Skan		// At least one space is required.
1385132720Skan		if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
1386132720Skan		  ++__beg;
1387132720Skan		else
1388132720Skan		  __testvalid = false;
1389132720Skan	      case money_base::none:
1390132720Skan		// Only if not at the end of the pattern.
1391132720Skan		if (__i != 3)
1392132720Skan		  for (; __beg != __end
1393132720Skan			 && __ctype.is(ctype_base::space, *__beg); ++__beg);
1394132720Skan		break;
1395132720Skan	      }
1396132720Skan	  }
139797403Sobrien
1398132720Skan	// Need to get the rest of the sign characters, if they exist.
1399132720Skan	if (__sign_size > 1 && __testvalid)
1400132720Skan	  {
1401132720Skan	    const char_type* __sign = __negative ? __lc->_M_negative_sign
1402132720Skan	                                         : __lc->_M_positive_sign;
1403132720Skan	    size_type __i = 1;
1404132720Skan	    for (; __beg != __end && __i < __sign_size
1405132720Skan		   && *__beg == __sign[__i]; ++__beg, ++__i);
1406132720Skan	    
1407132720Skan	    if (__i != __sign_size)
1408132720Skan	      __testvalid = false;
1409132720Skan	  }
141097403Sobrien
1411132720Skan	if (__testvalid)
1412132720Skan	  {
1413132720Skan	    // Strip leading zeros.
1414132720Skan	    if (__res.size() > 1)
1415132720Skan	      {
1416132720Skan		const size_type __first = __res.find_first_not_of('0');
1417132720Skan		const bool __only_zeros = __first == string::npos;
1418132720Skan		if (__first)
1419132720Skan		  __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
1420132720Skan	      }
142197403Sobrien
1422132720Skan	    // 22.2.6.1.2, p4
1423132720Skan	    if (__negative && __res[0] != '0')
1424132720Skan	      __res.insert(__res.begin(), '-');
1425132720Skan	    
1426132720Skan	    // Test for grouping fidelity.
1427132720Skan	    if (__grouping_tmp.size())
1428132720Skan	      {
1429132720Skan		// Add the ending grouping.
1430132720Skan		__grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
1431132720Skan						                   : __n);
1432132720Skan		if (!std::__verify_grouping(__lc->_M_grouping,
1433132720Skan					    __lc->_M_grouping_size,
1434132720Skan					    __grouping_tmp))
1435132720Skan		  __testvalid = false;
1436132720Skan	      }
1437132720Skan	    
1438132720Skan	    // Iff not enough digits were supplied after the decimal-point.
1439132720Skan	    if (__testdecfound && __lc->_M_frac_digits > 0
1440132720Skan		&& __n != __lc->_M_frac_digits)
1441132720Skan	      __testvalid = false;
1442132720Skan	  }
1443132720Skan	
1444132720Skan	// Iff no more characters are available.
1445132720Skan	if (__beg == __end)
1446132720Skan	  __err |= ios_base::eofbit;
1447132720Skan	
1448132720Skan	// Iff valid sequence is not recognized.
1449132720Skan	if (!__testvalid)
1450132720Skan	  __err |= ios_base::failbit;
1451132720Skan	else
1452132720Skan	  __units.swap(__res);
1453132720Skan	
1454132720Skan	return __beg;
1455132720Skan      }
145697403Sobrien
1457132720Skan  template<typename _CharT, typename _InIter>
1458132720Skan    _InIter
1459132720Skan    money_get<_CharT, _InIter>::
1460132720Skan    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
1461132720Skan	   ios_base::iostate& __err, long double& __units) const
1462132720Skan    {
1463132720Skan      string __str;
1464132720Skan      if (__intl)
1465132720Skan	__beg = _M_extract<true>(__beg, __end, __io, __err, __str);
1466132720Skan      else
1467132720Skan	__beg = _M_extract<false>(__beg, __end, __io, __err, __str);
1468132720Skan      std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
1469132720Skan      return __beg;
1470132720Skan    }
1471132720Skan
1472132720Skan  template<typename _CharT, typename _InIter>
1473132720Skan    _InIter
1474132720Skan    money_get<_CharT, _InIter>::
1475132720Skan    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
1476132720Skan	   ios_base::iostate& __err, string_type& __units) const
1477132720Skan    {
1478132720Skan      typedef typename string::size_type                  size_type;
1479132720Skan
1480132720Skan      const locale& __loc = __io._M_getloc();
1481132720Skan      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1482132720Skan
1483132720Skan      string __str;
1484132720Skan      const iter_type __ret = __intl ? _M_extract<true>(__beg, __end, __io,
1485132720Skan							__err, __str)
1486132720Skan	                             : _M_extract<false>(__beg, __end, __io,
1487132720Skan							 __err, __str);
1488132720Skan      const size_type __len = __str.size();
1489132720Skan      if (__len)
149097403Sobrien	{
1491132720Skan	  _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1492132720Skan							       * __len));
1493132720Skan	  __ctype.widen(__str.data(), __str.data() + __len, __ws);
1494132720Skan	  __units.assign(__ws, __len);
149597403Sobrien	}
149697403Sobrien
1497132720Skan      return __ret;
1498132720Skan    }
149997403Sobrien
1500132720Skan  template<typename _CharT, typename _OutIter>
1501132720Skan    template<bool _Intl>
1502132720Skan      _OutIter
1503132720Skan      money_put<_CharT, _OutIter>::
1504132720Skan      _M_insert(iter_type __s, ios_base& __io, char_type __fill,
1505132720Skan		const string_type& __digits) const
1506132720Skan      {
1507132720Skan	typedef typename string_type::size_type	          size_type;
1508132720Skan	typedef money_base::part                          part;
1509132720Skan	typedef moneypunct<_CharT, _Intl>                 __moneypunct_type;
1510132720Skan	typedef typename __moneypunct_type::__cache_type  __cache_type;
1511132720Skan      
1512132720Skan	const locale& __loc = __io._M_getloc();
1513132720Skan	const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
151497403Sobrien
1515132720Skan	__use_cache<__cache_type> __uc;
1516132720Skan	const __cache_type* __lc = __uc(__loc);
1517132720Skan	const char_type* __lit = __lc->_M_atoms;
151897403Sobrien
1519132720Skan	// Determine if negative or positive formats are to be used, and
1520132720Skan	// discard leading negative_sign if it is present.
1521132720Skan	const char_type* __beg = __digits.data();
1522132720Skan
1523132720Skan	money_base::pattern __p;
1524132720Skan	const char_type* __sign;
1525132720Skan	size_type __sign_size;
1526132720Skan	if (*__beg != __lit[money_base::_S_minus])
1527132720Skan	  {
1528132720Skan	    __p = __lc->_M_pos_format;
1529132720Skan	    __sign = __lc->_M_positive_sign;
1530132720Skan	    __sign_size = __lc->_M_positive_sign_size;
1531132720Skan	  }
1532132720Skan	else
1533132720Skan	  {
1534132720Skan	    __p = __lc->_M_neg_format;
1535132720Skan	    __sign = __lc->_M_negative_sign;
1536132720Skan	    __sign_size = __lc->_M_negative_sign_size;
1537132720Skan	    if (__digits.size())
1538132720Skan	      ++__beg;
1539132720Skan	  }
1540132720Skan       
1541132720Skan	// Look for valid numbers in the ctype facet within input digits.
1542132720Skan	size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
1543132720Skan					   __beg + __digits.size()) - __beg;
1544132720Skan	if (__len)
1545132720Skan	  {
1546132720Skan	    // Assume valid input, and attempt to format.
1547132720Skan	    // Break down input numbers into base components, as follows:
1548132720Skan	    //   final_value = grouped units + (decimal point) + (digits)
1549132720Skan	    string_type __value;
1550132720Skan	    __value.reserve(2 * __len);
1551132720Skan
1552132720Skan	    // Add thousands separators to non-decimal digits, per
1553132720Skan	    // grouping rules.
1554132720Skan	    int __paddec = __len - __lc->_M_frac_digits;
1555132720Skan	    if (__paddec > 0)
1556132720Skan  	      {
1557132720Skan		if (__lc->_M_frac_digits < 0)
1558132720Skan		  __paddec = __len;
1559132720Skan  		if (__lc->_M_grouping_size)
1560132720Skan  		  {
1561132720Skan		    _CharT* __ws =
1562132720Skan  		      static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1563132720Skan  							    * 2 * __len));
1564132720Skan  		    _CharT* __ws_end =
1565132720Skan		      std::__add_grouping(__ws, __lc->_M_thousands_sep,
1566132720Skan					  __lc->_M_grouping,
1567132720Skan					  __lc->_M_grouping_size,
1568132720Skan					  __beg, __beg + __paddec);
1569132720Skan		    __value.assign(__ws, __ws_end - __ws);
1570132720Skan  		  }
1571132720Skan  		else
1572132720Skan		  __value.assign(__beg, __paddec);
1573132720Skan	      }
1574132720Skan
1575132720Skan	    // Deal with decimal point, decimal digits.
1576132720Skan	    if (__lc->_M_frac_digits > 0)
1577132720Skan	      {
1578132720Skan		__value += __lc->_M_decimal_point;
1579132720Skan		if (__paddec >= 0)
1580132720Skan		  __value.append(__beg + __paddec, __lc->_M_frac_digits);
1581132720Skan		else
1582132720Skan		  {
1583132720Skan		    // Have to pad zeros in the decimal position.
1584132720Skan		    __value.append(-__paddec, __lit[money_base::_S_zero]);
1585132720Skan		    __value.append(__beg, __len);
1586132720Skan		  }
1587132720Skan  	      }
1588132720Skan  
1589132720Skan	    // Calculate length of resulting string.
1590132720Skan	    const ios_base::fmtflags __f = __io.flags() 
1591132720Skan	                                   & ios_base::adjustfield;
1592132720Skan	    __len = __value.size() + __sign_size;
1593132720Skan	    __len += ((__io.flags() & ios_base::showbase)
1594132720Skan		      ? __lc->_M_curr_symbol_size : 0);
1595132720Skan
1596132720Skan	    string_type __res;
1597132720Skan	    __res.reserve(2 * __len);
1598132720Skan	    
1599132720Skan	    const size_type __width = static_cast<size_type>(__io.width());  
1600132720Skan	    const bool __testipad = (__f == ios_base::internal
1601132720Skan				     && __len < __width);
1602132720Skan	    // Fit formatted digits into the required pattern.
1603132720Skan	    for (int __i = 0; __i < 4; ++__i)
1604132720Skan	      {
1605132720Skan		const part __which = static_cast<part>(__p.field[__i]);
1606132720Skan		switch (__which)
1607132720Skan		  {
1608132720Skan		  case money_base::symbol:
1609132720Skan		    if (__io.flags() & ios_base::showbase)
1610132720Skan		      __res.append(__lc->_M_curr_symbol,
1611132720Skan				   __lc->_M_curr_symbol_size);
1612132720Skan		    break;
1613132720Skan		  case money_base::sign:
1614132720Skan		    // Sign might not exist, or be more than one
1615132720Skan		    // charater long. In that case, add in the rest
1616132720Skan		    // below.
1617132720Skan		    if (__sign_size)
1618132720Skan		      __res += __sign[0];
1619132720Skan		    break;
1620132720Skan		  case money_base::value:
1621132720Skan		    __res += __value;
1622132720Skan		    break;
1623132720Skan		  case money_base::space:
1624132720Skan		    // At least one space is required, but if internal
1625132720Skan		    // formatting is required, an arbitrary number of
1626132720Skan		    // fill spaces will be necessary.
1627132720Skan		    if (__testipad)
1628132720Skan		      __res.append(__width - __len, __fill);
1629132720Skan		    else
1630132720Skan		      __res += __fill;
1631132720Skan		    break;
1632132720Skan		  case money_base::none:
1633132720Skan		    if (__testipad)
1634132720Skan		      __res.append(__width - __len, __fill);
1635132720Skan		    break;
1636132720Skan		  }
1637132720Skan	      }
1638132720Skan	    
1639132720Skan	    // Special case of multi-part sign parts.
1640132720Skan	    if (__sign_size > 1)
1641132720Skan	      __res.append(__sign + 1, __sign_size - 1);
1642132720Skan	    
1643132720Skan	    // Pad, if still necessary.
1644132720Skan	    __len = __res.size();
1645132720Skan	    if (__width > __len)
1646132720Skan	      {
1647132720Skan		if (__f == ios_base::left)
1648132720Skan		  // After.
1649132720Skan		  __res.append(__width - __len, __fill);
1650132720Skan		else
1651132720Skan		  // Before.
1652132720Skan		  __res.insert(0, __width - __len, __fill);
1653132720Skan		__len = __width;
1654132720Skan	      }
1655132720Skan	    
1656132720Skan	    // Write resulting, fully-formatted string to output iterator.
1657132720Skan	    __s = std::__write(__s, __res.data(), __len);
1658132720Skan	  }
1659132720Skan	__io.width(0);
1660132720Skan	return __s;    
1661132720Skan      }
1662132720Skan  
166397403Sobrien  template<typename _CharT, typename _OutIter>
166497403Sobrien    _OutIter
166597403Sobrien    money_put<_CharT, _OutIter>::
166697403Sobrien    do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
166797403Sobrien	   long double __units) const
1668132720Skan    {
166997403Sobrien      const locale __loc = __io.getloc();
167097403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1671132720Skan#ifdef _GLIBCXX_USE_C99
167297403Sobrien      // First try a buffer perhaps big enough.
167397403Sobrien      int __cs_size = 64;
167497403Sobrien      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1675132720Skan      // _GLIBCXX_RESOLVE_LIB_DEFECTS
1676132720Skan      // 328. Bad sprintf format modifier in money_put<>::do_put()
1677132720Skan      int __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units,
1678132720Skan					_S_get_c_locale());
167997403Sobrien      // If the buffer was not large enough, try again with the correct size.
168097403Sobrien      if (__len >= __cs_size)
168197403Sobrien	{
168297403Sobrien	  __cs_size = __len + 1;
168397403Sobrien	  __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1684132720Skan	  __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units,
1685132720Skan					_S_get_c_locale());
168697403Sobrien	}
168797403Sobrien#else
1688132720Skan      // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
1689132720Skan      const int __cs_size = numeric_limits<long double>::max_exponent10 + 3;
169097403Sobrien      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1691132720Skan      int __len = std::__convert_from_v(__cs, 0, "%.0Lf", __units,
1692132720Skan					_S_get_c_locale());
169397403Sobrien#endif
1694132720Skan      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1695117397Skan							   * __cs_size));
169697403Sobrien      __ctype.widen(__cs, __cs + __len, __ws);
1697132720Skan      const string_type __digits(__ws, __len);
1698132720Skan      return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
1699132720Skan	            : _M_insert<false>(__s, __io, __fill, __digits);
170097403Sobrien    }
170197403Sobrien
170297403Sobrien  template<typename _CharT, typename _OutIter>
170397403Sobrien    _OutIter
170497403Sobrien    money_put<_CharT, _OutIter>::
170597403Sobrien    do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
170697403Sobrien	   const string_type& __digits) const
1707132720Skan    { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
1708132720Skan	            : _M_insert<false>(__s, __io, __fill, __digits); }
170997403Sobrien
171097403Sobrien
171197403Sobrien  // NB: Not especially useful. Without an ios_base object or some
171297403Sobrien  // kind of locale reference, we are left clawing at the air where
171397403Sobrien  // the side of the mountain used to be...
171497403Sobrien  template<typename _CharT, typename _InIter>
171597403Sobrien    time_base::dateorder
171697403Sobrien    time_get<_CharT, _InIter>::do_date_order() const
171797403Sobrien    { return time_base::no_order; }
171897403Sobrien
1719132720Skan  // Expand a strftime format string and parse it.  E.g., do_get_date() may
1720132720Skan  // pass %m/%d/%Y => extracted characters.
172197403Sobrien  template<typename _CharT, typename _InIter>
1722132720Skan    _InIter
172397403Sobrien    time_get<_CharT, _InIter>::
1724132720Skan    _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
1725132720Skan			  ios_base::iostate& __err, tm* __tm,
172697403Sobrien			  const _CharT* __format) const
1727132720Skan    {
1728132720Skan      const locale& __loc = __io._M_getloc();
1729132720Skan      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1730132720Skan      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1731132720Skan      const size_t __len = char_traits<_CharT>::length(__format);
173297403Sobrien
173397403Sobrien      for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
173497403Sobrien	{
1735132720Skan	  if (__ctype.narrow(__format[__i], 0) == '%')
173697403Sobrien	    {
173797403Sobrien	      // Verify valid formatting code, attempt to extract.
1738132720Skan	      char __c = __ctype.narrow(__format[++__i], 0);
1739132720Skan	      int __mem = 0;
174097403Sobrien	      if (__c == 'E' || __c == 'O')
1741132720Skan		__c = __ctype.narrow(__format[++__i], 0);
174297403Sobrien	      switch (__c)
174397403Sobrien		{
174497403Sobrien		  const char* __cs;
174597403Sobrien		  _CharT __wcs[10];
174697403Sobrien		case 'a':
174797403Sobrien		  // Abbreviated weekday name [tm_wday]
174897403Sobrien		  const char_type*  __days1[7];
174997403Sobrien		  __tp._M_days_abbreviated(__days1);
1750132720Skan		  __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
1751132720Skan					  7, __io, __err);
175297403Sobrien		  break;
175397403Sobrien		case 'A':
175497403Sobrien		  // Weekday name [tm_wday].
175597403Sobrien		  const char_type*  __days2[7];
175697403Sobrien		  __tp._M_days(__days2);
1757132720Skan		  __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
1758132720Skan					  7, __io, __err);
175997403Sobrien		  break;
176097403Sobrien		case 'h':
176197403Sobrien		case 'b':
176297403Sobrien		  // Abbreviated month name [tm_mon]
176397403Sobrien		  const char_type*  __months1[12];
176497403Sobrien		  __tp._M_months_abbreviated(__months1);
1765132720Skan		  __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
1766132720Skan					  __months1, 12, __io, __err);
176797403Sobrien		  break;
176897403Sobrien		case 'B':
176997403Sobrien		  // Month name [tm_mon].
177097403Sobrien		  const char_type*  __months2[12];
177197403Sobrien		  __tp._M_months(__months2);
1772132720Skan		  __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
1773132720Skan					  __months2, 12, __io, __err);
177497403Sobrien		  break;
177597403Sobrien		case 'c':
177697403Sobrien		  // Default time and date representation.
177797403Sobrien		  const char_type*  __dt[2];
177897403Sobrien		  __tp._M_date_time_formats(__dt);
1779132720Skan		  __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1780132720Skan						__tm, __dt[0]);
178197403Sobrien		  break;
178297403Sobrien		case 'd':
178397403Sobrien		  // Day [01, 31]. [tm_mday]
1784132720Skan		  __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
1785132720Skan					 __io, __err);
178697403Sobrien		  break;
1787132720Skan		case 'e':
1788132720Skan		  // Day [1, 31], with single digits preceded by
1789132720Skan		  // space. [tm_mday]
1790132720Skan		  if (__ctype.is(ctype_base::space, *__beg))
1791132720Skan		    __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
1792132720Skan					   1, __io, __err);
1793132720Skan		  else
1794132720Skan		    __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
1795132720Skan					   2, __io, __err);
1796132720Skan		  break;
179797403Sobrien		case 'D':
179897403Sobrien		  // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
179997403Sobrien		  __cs = "%m/%d/%y";
180097403Sobrien		  __ctype.widen(__cs, __cs + 9, __wcs);
1801132720Skan		  __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1802132720Skan						__tm, __wcs);
180397403Sobrien		  break;
180497403Sobrien		case 'H':
180597403Sobrien		  // Hour [00, 23]. [tm_hour]
1806132720Skan		  __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
1807132720Skan					 __io, __err);
180897403Sobrien		  break;
180997403Sobrien		case 'I':
181097403Sobrien		  // Hour [01, 12]. [tm_hour]
1811132720Skan		  __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
1812132720Skan					 __io, __err);
181397403Sobrien		  break;
181497403Sobrien		case 'm':
181597403Sobrien		  // Month [01, 12]. [tm_mon]
1816132720Skan		  __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 
1817132720Skan					 __io, __err);
181897403Sobrien		  if (!__err)
181997403Sobrien		    __tm->tm_mon = __mem - 1;
182097403Sobrien		  break;
182197403Sobrien		case 'M':
182297403Sobrien		  // Minute [00, 59]. [tm_min]
1823132720Skan		  __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
1824132720Skan					 __io, __err);
182597403Sobrien		  break;
182697403Sobrien		case 'n':
182797403Sobrien		  if (__ctype.narrow(*__beg, 0) == '\n')
182897403Sobrien		    ++__beg;
182997403Sobrien		  else
183097403Sobrien		    __err |= ios_base::failbit;
183197403Sobrien		  break;
183297403Sobrien		case 'R':
183397403Sobrien		  // Equivalent to (%H:%M).
183497403Sobrien		  __cs = "%H:%M";
183597403Sobrien		  __ctype.widen(__cs, __cs + 6, __wcs);
1836132720Skan		  __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1837132720Skan						__tm, __wcs);
183897403Sobrien		  break;
183997403Sobrien		case 'S':
184097403Sobrien		  // Seconds.
1841132720Skan		  __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2,
1842132720Skan					 __io, __err);
184397403Sobrien		  break;
184497403Sobrien		case 't':
184597403Sobrien		  if (__ctype.narrow(*__beg, 0) == '\t')
184697403Sobrien		    ++__beg;
184797403Sobrien		  else
1848132720Skan		    __err |= ios_base::failbit;
184997403Sobrien		  break;
185097403Sobrien		case 'T':
185197403Sobrien		  // Equivalent to (%H:%M:%S).
185297403Sobrien		  __cs = "%H:%M:%S";
185397403Sobrien		  __ctype.widen(__cs, __cs + 9, __wcs);
1854132720Skan		  __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1855132720Skan						__tm, __wcs);
185697403Sobrien		  break;
185797403Sobrien		case 'x':
185897403Sobrien		  // Locale's date.
185997403Sobrien		  const char_type*  __dates[2];
186097403Sobrien		  __tp._M_date_formats(__dates);
1861132720Skan		  __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1862132720Skan						__tm, __dates[0]);
186397403Sobrien		  break;
186497403Sobrien		case 'X':
186597403Sobrien		  // Locale's time.
186697403Sobrien		  const char_type*  __times[2];
186797403Sobrien		  __tp._M_time_formats(__times);
1868132720Skan		  __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1869132720Skan						__tm, __times[0]);
187097403Sobrien		  break;
187197403Sobrien		case 'y':
1872132720Skan		case 'C': // C99
187397403Sobrien		  // Two digit year. [tm_year]
1874132720Skan		  __beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
1875132720Skan					 __io, __err);
187697403Sobrien		  break;
187797403Sobrien		case 'Y':
187897403Sobrien		  // Year [1900). [tm_year]
1879132720Skan		  __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
1880132720Skan					 __io, __err);
188197403Sobrien		  if (!__err)
188297403Sobrien		    __tm->tm_year = __mem - 1900;
188397403Sobrien		  break;
188497403Sobrien		case 'Z':
188597403Sobrien		  // Timezone info.
188697403Sobrien		  if (__ctype.is(ctype_base::upper, *__beg))
188797403Sobrien		    {
188897403Sobrien		      int __tmp;
1889132720Skan		      __beg = _M_extract_name(__beg, __end, __tmp,
1890132720Skan				       __timepunct_cache<_CharT>::_S_timezones,
1891132720Skan					      14, __io, __err);
1892132720Skan
189397403Sobrien		      // GMT requires special effort.
1894132720Skan		      if (__beg != __end && !__err && __tmp == 0
1895132720Skan			  && (*__beg == __ctype.widen('-')
1896132720Skan			      || *__beg == __ctype.widen('+')))
189797403Sobrien			{
1898132720Skan			  __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
1899132720Skan						 __io, __err);
1900132720Skan			  __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
1901132720Skan						 __io, __err);
1902132720Skan			}
190397403Sobrien		    }
190497403Sobrien		  else
190597403Sobrien		    __err |= ios_base::failbit;
1906132720Skan		  break;
1907132720Skan		default:
1908132720Skan		  // Not recognized.
1909132720Skan		  __err |= ios_base::failbit;
191097403Sobrien		}
1911132720Skan	    }
1912132720Skan	  else
1913132720Skan	    {
1914132720Skan	      // Verify format and input match, extract and discard.
1915132720Skan	      if (__format[__i] == *__beg)
1916132720Skan		++__beg;
1917132720Skan	      else
1918132720Skan		__err |= ios_base::failbit;
1919132720Skan	    }
192097403Sobrien	}
1921132720Skan      return __beg;
192297403Sobrien    }
192397403Sobrien
192497403Sobrien  template<typename _CharT, typename _InIter>
1925132720Skan    _InIter
192697403Sobrien    time_get<_CharT, _InIter>::
1927132720Skan    _M_extract_num(iter_type __beg, iter_type __end, int& __member,
1928132720Skan		   int __min, int __max, size_t __len,
1929132720Skan		   ios_base& __io, ios_base::iostate& __err) const
193097403Sobrien    {
1931132720Skan      const locale& __loc = __io._M_getloc();
1932132720Skan      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1933132720Skan
1934132720Skan      // As-is works for __len = 1, 2, 4, the values actually used.
1935132720Skan      int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
1936132720Skan
1937132720Skan      ++__min;
193897403Sobrien      size_t __i = 0;
1939132720Skan      int __value = 0;
1940132720Skan      for (; __beg != __end && __i < __len; ++__beg, ++__i)
194197403Sobrien	{
1942132720Skan	  const char __c = __ctype.narrow(*__beg, '*');
1943132720Skan	  if (__c >= '0' && __c <= '9')
1944132720Skan	    {
1945132720Skan	      __value = __value * 10 + (__c - '0');
1946132720Skan	      const int __valuec = __value * __mult;
1947132720Skan	      if (__valuec > __max || __valuec + __mult < __min)
1948132720Skan		break;
1949132720Skan	      __mult /= 10;
1950132720Skan	    }
1951132720Skan	  else
1952132720Skan	    break;
195397403Sobrien	}
195497403Sobrien      if (__i == __len)
1955132720Skan	__member = __value;
195697403Sobrien      else
195797403Sobrien	__err |= ios_base::failbit;
1958132720Skan      return __beg;
195997403Sobrien    }
196097403Sobrien
196197403Sobrien  // Assumptions:
196297403Sobrien  // All elements in __names are unique.
196397403Sobrien  template<typename _CharT, typename _InIter>
1964132720Skan    _InIter
196597403Sobrien    time_get<_CharT, _InIter>::
1966132720Skan    _M_extract_name(iter_type __beg, iter_type __end, int& __member,
1967132720Skan		    const _CharT** __names, size_t __indexlen,
1968132720Skan		    ios_base& __io, ios_base::iostate& __err) const
196997403Sobrien    {
1970132720Skan      typedef char_traits<_CharT>		__traits_type;
1971132720Skan      const locale& __loc = __io._M_getloc();
1972132720Skan      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1973132720Skan
1974132720Skan      int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
1975117397Skan							  * __indexlen));
197697403Sobrien      size_t __nmatches = 0;
197797403Sobrien      size_t __pos = 0;
197897403Sobrien      bool __testvalid = true;
197997403Sobrien      const char_type* __name;
198097403Sobrien
198197403Sobrien      // Look for initial matches.
1982132720Skan      // NB: Some of the locale data is in the form of all lowercase
1983132720Skan      // names, and some is in the form of initially-capitalized
1984132720Skan      // names. Look for both.
1985132720Skan      if (__beg != __end)
1986132720Skan	{
1987132720Skan	  const char_type __c = *__beg;
1988132720Skan	  for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
1989132720Skan	    if (__c == __names[__i1][0]
1990132720Skan		|| __c == __ctype.toupper(__names[__i1][0]))
1991132720Skan	      __matches[__nmatches++] = __i1;
1992132720Skan	}
1993132720Skan
1994117397Skan      while (__nmatches > 1)
199597403Sobrien	{
199697403Sobrien	  // Find smallest matching string.
1997132720Skan	  size_t __minlen = __traits_type::length(__names[__matches[0]]);
1998132720Skan	  for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
1999132720Skan	    __minlen = std::min(__minlen,
2000132720Skan			      __traits_type::length(__names[__matches[__i2]]));
2001132720Skan	  ++__pos;
2002132720Skan	  ++__beg;
200397403Sobrien	  if (__pos < __minlen && __beg != __end)
2004132720Skan	    for (size_t __i3 = 0; __i3 < __nmatches;)
2005132720Skan	      {
2006132720Skan		__name = __names[__matches[__i3]];
2007132720Skan		if (__name[__pos] != *__beg)
2008132720Skan		  __matches[__i3] = __matches[--__nmatches];
2009132720Skan		else
2010132720Skan		  ++__i3;
2011132720Skan	      }
201297403Sobrien	  else
201397403Sobrien	    break;
201497403Sobrien	}
201597403Sobrien
201697403Sobrien      if (__nmatches == 1)
201797403Sobrien	{
201897403Sobrien	  // Make sure found name is completely extracted.
2019132720Skan	  ++__pos;
2020132720Skan	  ++__beg;
202197403Sobrien	  __name = __names[__matches[0]];
202297403Sobrien	  const size_t __len = __traits_type::length(__name);
202397403Sobrien	  while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
202497403Sobrien	    ++__beg, ++__pos;
202597403Sobrien
202697403Sobrien	  if (__len == __pos)
202797403Sobrien	    __member = __matches[0];
202897403Sobrien	  else
202997403Sobrien	    __testvalid = false;
203097403Sobrien	}
203197403Sobrien      else
203297403Sobrien	__testvalid = false;
203397403Sobrien      if (!__testvalid)
203497403Sobrien	__err |= ios_base::failbit;
2035132720Skan      return __beg;
203697403Sobrien    }
203797403Sobrien
203897403Sobrien  template<typename _CharT, typename _InIter>
203997403Sobrien    _InIter
204097403Sobrien    time_get<_CharT, _InIter>::
204197403Sobrien    do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
204297403Sobrien		ios_base::iostate& __err, tm* __tm) const
204397403Sobrien    {
2044132720Skan      const locale& __loc = __io._M_getloc();
2045132720Skan      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
2046132720Skan      const char_type*  __times[2];
2047132720Skan      __tp._M_time_formats(__times);
2048132720Skan      __beg = _M_extract_via_format(__beg, __end, __io, __err, 
2049132720Skan				    __tm, __times[0]);
205097403Sobrien      if (__beg == __end)
205197403Sobrien	__err |= ios_base::eofbit;
205297403Sobrien      return __beg;
205397403Sobrien    }
205497403Sobrien
205597403Sobrien  template<typename _CharT, typename _InIter>
205697403Sobrien    _InIter
205797403Sobrien    time_get<_CharT, _InIter>::
205897403Sobrien    do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
205997403Sobrien		ios_base::iostate& __err, tm* __tm) const
206097403Sobrien    {
2061132720Skan      const locale& __loc = __io._M_getloc();
2062132720Skan      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
2063132720Skan      const char_type*  __dates[2];
2064132720Skan      __tp._M_date_formats(__dates);
2065132720Skan      __beg = _M_extract_via_format(__beg, __end, __io, __err,
2066132720Skan				    __tm, __dates[0]);
206797403Sobrien      if (__beg == __end)
206897403Sobrien	__err |= ios_base::eofbit;
206997403Sobrien      return __beg;
207097403Sobrien    }
207197403Sobrien
207297403Sobrien  template<typename _CharT, typename _InIter>
207397403Sobrien    _InIter
207497403Sobrien    time_get<_CharT, _InIter>::
2075132720Skan    do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
207697403Sobrien		   ios_base::iostate& __err, tm* __tm) const
207797403Sobrien    {
2078132720Skan      typedef char_traits<_CharT>		__traits_type;
2079132720Skan      const locale& __loc = __io._M_getloc();
2080132720Skan      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
2081132720Skan      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
208297403Sobrien      const char_type*  __days[7];
208397403Sobrien      __tp._M_days_abbreviated(__days);
208497403Sobrien      int __tmpwday;
2085132720Skan      __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7, __io, __err);
208697403Sobrien
208797403Sobrien      // Check to see if non-abbreviated name exists, and extract.
208897403Sobrien      // NB: Assumes both _M_days and _M_days_abbreviated organized in
208997403Sobrien      // exact same order, first to last, such that the resulting
209097403Sobrien      // __days array with the same index points to a day, and that
209197403Sobrien      // day's abbreviated form.
2092132720Skan      // NB: Also assumes that an abbreviated name is a subset of the name.
209397403Sobrien      if (!__err)
209497403Sobrien	{
209597403Sobrien	  size_t __pos = __traits_type::length(__days[__tmpwday]);
209697403Sobrien	  __tp._M_days(__days);
209797403Sobrien	  const char_type* __name = __days[__tmpwday];
209897403Sobrien	  if (__name[__pos] == *__beg)
209997403Sobrien	    {
210097403Sobrien	      // Extract the rest of it.
210197403Sobrien	      const size_t __len = __traits_type::length(__name);
2102132720Skan	      while (__pos < __len && __beg != __end
210397403Sobrien		     && __name[__pos] == *__beg)
210497403Sobrien		++__beg, ++__pos;
210597403Sobrien	      if (__len != __pos)
210697403Sobrien		__err |= ios_base::failbit;
210797403Sobrien	    }
210897403Sobrien	  if (!__err)
210997403Sobrien	    __tm->tm_wday = __tmpwday;
211097403Sobrien	}
211197403Sobrien      if (__beg == __end)
211297403Sobrien	__err |= ios_base::eofbit;
211397403Sobrien      return __beg;
211497403Sobrien     }
211597403Sobrien
211697403Sobrien  template<typename _CharT, typename _InIter>
211797403Sobrien    _InIter
211897403Sobrien    time_get<_CharT, _InIter>::
211997403Sobrien    do_get_monthname(iter_type __beg, iter_type __end,
212097403Sobrien                     ios_base& __io, ios_base::iostate& __err, tm* __tm) const
212197403Sobrien    {
2122132720Skan      typedef char_traits<_CharT>		__traits_type;
2123132720Skan      const locale& __loc = __io._M_getloc();
2124132720Skan      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
2125132720Skan      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
212697403Sobrien      const char_type*  __months[12];
212797403Sobrien      __tp._M_months_abbreviated(__months);
212897403Sobrien      int __tmpmon;
2129132720Skan      __beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12, 
2130132720Skan			      __io, __err);
213197403Sobrien
213297403Sobrien      // Check to see if non-abbreviated name exists, and extract.
213397403Sobrien      // NB: Assumes both _M_months and _M_months_abbreviated organized in
213497403Sobrien      // exact same order, first to last, such that the resulting
213597403Sobrien      // __months array with the same index points to a month, and that
213697403Sobrien      // month's abbreviated form.
2137132720Skan      // NB: Also assumes that an abbreviated name is a subset of the name.
213897403Sobrien      if (!__err)
213997403Sobrien	{
214097403Sobrien	  size_t __pos = __traits_type::length(__months[__tmpmon]);
214197403Sobrien	  __tp._M_months(__months);
214297403Sobrien	  const char_type* __name = __months[__tmpmon];
214397403Sobrien	  if (__name[__pos] == *__beg)
214497403Sobrien	    {
214597403Sobrien	      // Extract the rest of it.
214697403Sobrien	      const size_t __len = __traits_type::length(__name);
2147132720Skan	      while (__pos < __len && __beg != __end
214897403Sobrien		     && __name[__pos] == *__beg)
214997403Sobrien		++__beg, ++__pos;
215097403Sobrien	      if (__len != __pos)
215197403Sobrien		__err |= ios_base::failbit;
215297403Sobrien	    }
215397403Sobrien	  if (!__err)
215497403Sobrien	    __tm->tm_mon = __tmpmon;
215597403Sobrien	}
2156132720Skan
215797403Sobrien      if (__beg == __end)
215897403Sobrien	__err |= ios_base::eofbit;
215997403Sobrien      return __beg;
216097403Sobrien    }
216197403Sobrien
216297403Sobrien  template<typename _CharT, typename _InIter>
216397403Sobrien    _InIter
216497403Sobrien    time_get<_CharT, _InIter>::
2165132720Skan    do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
216697403Sobrien		ios_base::iostate& __err, tm* __tm) const
216797403Sobrien    {
2168132720Skan      const locale& __loc = __io._M_getloc();
2169132720Skan      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
217097403Sobrien
217197403Sobrien      size_t __i = 0;
2172132720Skan      int __value = 0;
2173132720Skan      for (; __beg != __end && __i < 4; ++__beg, ++__i)
217497403Sobrien	{
2175132720Skan	  const char __c = __ctype.narrow(*__beg, '*');
2176132720Skan	  if (__c >= '0' && __c <= '9')
2177132720Skan	    __value = __value * 10 + (__c - '0');
2178132720Skan	  else
2179132720Skan	    break;
218097403Sobrien	}
218197403Sobrien      if (__i == 2 || __i == 4)
2182132720Skan	__tm->tm_year = __i == 2 ? __value : __value - 1900;
218397403Sobrien      else
218497403Sobrien	__err |= ios_base::failbit;
218597403Sobrien      if (__beg == __end)
218697403Sobrien	__err |= ios_base::eofbit;
218797403Sobrien      return __beg;
218897403Sobrien    }
218997403Sobrien
219097403Sobrien  template<typename _CharT, typename _OutIter>
219197403Sobrien    _OutIter
219297403Sobrien    time_put<_CharT, _OutIter>::
2193132720Skan    put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
219497403Sobrien	const _CharT* __beg, const _CharT* __end) const
219597403Sobrien    {
2196132720Skan      const locale& __loc = __io._M_getloc();
219797403Sobrien      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
2198132720Skan      for (; __beg != __end; ++__beg)
2199132720Skan	if (__ctype.narrow(*__beg, 0) != '%')
2200132720Skan	  {
2201132720Skan	    *__s = *__beg;
2202132720Skan	    ++__s;
2203132720Skan	  }
2204132720Skan	else if (++__beg != __end)
2205132720Skan	  {
2206132720Skan	    char __format;
2207132720Skan	    char __mod = 0;
2208132720Skan	    const char __c = __ctype.narrow(*__beg, 0);
2209132720Skan	    if (__c != 'E' && __c != 'O')
2210132720Skan	      __format = __c;
2211132720Skan	    else if (++__beg != __end)
2212132720Skan	      {
2213132720Skan		__mod = __c;
2214132720Skan		__format = __ctype.narrow(*__beg, 0);
2215132720Skan	      }
2216132720Skan	    else
2217132720Skan	      break;
2218132720Skan	    __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
2219132720Skan	  }
2220132720Skan	else
2221132720Skan	  break;
222297403Sobrien      return __s;
222397403Sobrien    }
222497403Sobrien
222597403Sobrien  template<typename _CharT, typename _OutIter>
222697403Sobrien    _OutIter
222797403Sobrien    time_put<_CharT, _OutIter>::
2228132720Skan    do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
222997403Sobrien	   char __format, char __mod) const
2230132720Skan    {
2231132720Skan      const locale& __loc = __io._M_getloc();
223297403Sobrien      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
223397403Sobrien      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
223497403Sobrien
223597403Sobrien      // NB: This size is arbitrary. Should this be a data member,
223697403Sobrien      // initialized at construction?
223797403Sobrien      const size_t __maxlen = 64;
2238132720Skan      char_type* __res = 
2239132720Skan       static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
224097403Sobrien
224197403Sobrien      // NB: In IEE 1003.1-200x, and perhaps other locale models, it
224297403Sobrien      // is possible that the format character will be longer than one
224397403Sobrien      // character. Possibilities include 'E' or 'O' followed by a
224497403Sobrien      // format character: if __mod is not the default argument, assume
224597403Sobrien      // it's a valid modifier.
224697403Sobrien      char_type __fmt[4];
2247132720Skan      __fmt[0] = __ctype.widen('%');
224897403Sobrien      if (!__mod)
224997403Sobrien	{
225097403Sobrien	  __fmt[1] = __format;
225197403Sobrien	  __fmt[2] = char_type();
225297403Sobrien	}
225397403Sobrien      else
225497403Sobrien	{
225597403Sobrien	  __fmt[1] = __mod;
225697403Sobrien	  __fmt[2] = __format;
225797403Sobrien	  __fmt[3] = char_type();
225897403Sobrien	}
225997403Sobrien
226097403Sobrien      __tp._M_put(__res, __maxlen, __fmt, __tm);
226197403Sobrien
226297403Sobrien      // Write resulting, fully-formatted string to output iterator.
2263132720Skan      return std::__write(__s, __res, char_traits<char_type>::length(__res));
226497403Sobrien    }
226597403Sobrien
226697403Sobrien
226797403Sobrien  // Generic version does nothing.
226897403Sobrien  template<typename _CharT>
226997403Sobrien    int
227097403Sobrien    collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const
227197403Sobrien    { return 0; }
227297403Sobrien
227397403Sobrien  // Generic version does nothing.
227497403Sobrien  template<typename _CharT>
227597403Sobrien    size_t
227697403Sobrien    collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const
227797403Sobrien    { return 0; }
227897403Sobrien
227997403Sobrien  template<typename _CharT>
228097403Sobrien    int
228197403Sobrien    collate<_CharT>::
2282132720Skan    do_compare(const _CharT* __lo1, const _CharT* __hi1,
228397403Sobrien	       const _CharT* __lo2, const _CharT* __hi2) const
2284132720Skan    {
2285117397Skan      // strcoll assumes zero-terminated strings so we make a copy
2286117397Skan      // and then put a zero at the end.
228797403Sobrien      const string_type __one(__lo1, __hi1);
228897403Sobrien      const string_type __two(__lo2, __hi2);
2289117397Skan
2290117397Skan      const _CharT* __p = __one.c_str();
2291132720Skan      const _CharT* __pend = __one.data() + __one.length();
2292117397Skan      const _CharT* __q = __two.c_str();
2293132720Skan      const _CharT* __qend = __two.data() + __two.length();
2294117397Skan
2295117397Skan      // strcoll stops when it sees a nul character so we break
2296117397Skan      // the strings into zero-terminated substrings and pass those
2297117397Skan      // to strcoll.
2298117397Skan      for (;;)
2299117397Skan	{
2300132720Skan	  const int __res = _M_compare(__p, __q);
2301117397Skan	  if (__res)
2302117397Skan	    return __res;
2303117397Skan
2304117397Skan	  __p += char_traits<_CharT>::length(__p);
2305117397Skan	  __q += char_traits<_CharT>::length(__q);
2306117397Skan	  if (__p == __pend && __q == __qend)
2307117397Skan	    return 0;
2308117397Skan	  else if (__p == __pend)
2309117397Skan	    return -1;
2310117397Skan	  else if (__q == __qend)
2311117397Skan	    return 1;
2312117397Skan
2313117397Skan	  __p++;
2314117397Skan	  __q++;
2315117397Skan	}
231697403Sobrien    }
231797403Sobrien
2318132720Skan  template<typename _CharT>
231997403Sobrien    typename collate<_CharT>::string_type
232097403Sobrien    collate<_CharT>::
232197403Sobrien    do_transform(const _CharT* __lo, const _CharT* __hi) const
232297403Sobrien    {
2323117397Skan      // strxfrm assumes zero-terminated strings so we make a copy
2324117397Skan      string_type __str(__lo, __hi);
2325117397Skan
2326117397Skan      const _CharT* __p = __str.c_str();
2327132720Skan      const _CharT* __pend = __str.data() + __str.length();
2328117397Skan
232997403Sobrien      size_t __len = (__hi - __lo) * 2;
2330117397Skan
2331117397Skan      string_type __ret;
2332117397Skan
2333117397Skan      // strxfrm stops when it sees a nul character so we break
2334117397Skan      // the string into zero-terminated substrings and pass those
2335117397Skan      // to strxfrm.
2336117397Skan      for (;;)
233797403Sobrien	{
2338117397Skan	  // First try a buffer perhaps big enough.
2339117397Skan	  _CharT* __c =
2340117397Skan	    static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
2341117397Skan	  size_t __res = _M_transform(__c, __p, __len);
2342117397Skan	  // If the buffer was not large enough, try again with the
2343117397Skan	  // correct size.
2344117397Skan	  if (__res >= __len)
2345117397Skan	    {
2346117397Skan	      __len = __res + 1;
2347132720Skan	      __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
2348117397Skan							  * __len));
2349117397Skan	      __res = _M_transform(__c, __p, __res + 1);
2350117397Skan	    }
2351117397Skan
2352117397Skan	  __ret.append(__c, __res);
2353117397Skan	  __p += char_traits<_CharT>::length(__p);
2354117397Skan	  if (__p == __pend)
2355117397Skan	    return __ret;
2356117397Skan
2357117397Skan	  __p++;
2358117397Skan	  __ret.push_back(_CharT());
235997403Sobrien	}
236097403Sobrien    }
236197403Sobrien
2362132720Skan  template<typename _CharT>
236397403Sobrien    long
236497403Sobrien    collate<_CharT>::
236597403Sobrien    do_hash(const _CharT* __lo, const _CharT* __hi) const
2366132720Skan    {
236797403Sobrien      unsigned long __val = 0;
236897403Sobrien      for (; __lo < __hi; ++__lo)
2369132720Skan	__val = *__lo + ((__val << 7) |
237097403Sobrien		       (__val >> (numeric_limits<unsigned long>::digits - 7)));
237197403Sobrien      return static_cast<long>(__val);
237297403Sobrien    }
237397403Sobrien
237497403Sobrien  // Construct correctly padded string, as per 22.2.2.2.2
2375132720Skan  // Assumes
237697403Sobrien  // __newlen > __oldlen
237797403Sobrien  // __news is allocated for __newlen size
237897403Sobrien  // Used by both num_put and ostream inserters: if __num,
237997403Sobrien  // internal-adjusted objects are padded according to the rules below
238097403Sobrien  // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
238197403Sobrien  // ones are.
2382102782Skan
2383102782Skan  // NB: Of the two parameters, _CharT can be deduced from the
2384102782Skan  // function arguments. The other (_Traits) has to be explicitly specified.
238597403Sobrien  template<typename _CharT, typename _Traits>
2386132720Skan    void
2387132720Skan    __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill,
2388132720Skan				   _CharT* __news, const _CharT* __olds,
2389132720Skan				   const streamsize __newlen,
2390102782Skan				   const streamsize __oldlen, const bool __num)
2391102782Skan    {
2392132720Skan      const size_t __plen = static_cast<size_t>(__newlen - __oldlen);
2393132720Skan      const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
2394102782Skan
2395132720Skan      // Padding last.
239697403Sobrien      if (__adjust == ios_base::left)
239797403Sobrien	{
2398132720Skan	  _Traits::copy(__news, const_cast<_CharT*>(__olds), __oldlen);
2399132720Skan	  _Traits::assign(__news + __oldlen, __plen, __fill);
2400132720Skan	  return;
240197403Sobrien	}
2402132720Skan
2403132720Skan      size_t __mod = 0;
2404132720Skan      if (__adjust == ios_base::internal && __num)
240597403Sobrien	{
240697403Sobrien	  // Pad after the sign, if there is one.
240797403Sobrien	  // Pad after 0[xX], if there is one.
240897403Sobrien	  // Who came up with these rules, anyway? Jeeze.
2409132720Skan          const locale& __loc = __io._M_getloc();
2410132720Skan	  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2411102782Skan
2412132720Skan	  const bool __testsign = (__ctype.widen('-') == __olds[0]
2413132720Skan				   || __ctype.widen('+') == __olds[0]);
2414132720Skan	  const bool __testhex = (__ctype.widen('0') == __olds[0]
2415132720Skan				  && __oldlen > 1
2416132720Skan				  && (__ctype.widen('x') == __olds[1]
2417132720Skan				      || __ctype.widen('X') == __olds[1]));
241897403Sobrien	  if (__testhex)
241997403Sobrien	    {
2420132720Skan	      __news[0] = __olds[0];
242197403Sobrien	      __news[1] = __olds[1];
2422132720Skan	      __mod = 2;
242397403Sobrien	      __news += 2;
242497403Sobrien	    }
242597403Sobrien	  else if (__testsign)
242697403Sobrien	    {
2427132720Skan	      __news[0] = __olds[0];
2428132720Skan	      __mod = 1;
242997403Sobrien	      ++__news;
243097403Sobrien	    }
2431132720Skan	  // else Padding first.
243297403Sobrien	}
2433132720Skan      _Traits::assign(__news, __plen, __fill);
2434132720Skan      _Traits::copy(__news + __plen, const_cast<_CharT*>(__olds + __mod),
2435132720Skan		    __oldlen - __mod);
243697403Sobrien    }
243797403Sobrien
2438132720Skan  bool
2439132720Skan  __verify_grouping(const char* __grouping, size_t __grouping_size,
2440132720Skan		    const string& __grouping_tmp)
2441132720Skan  {
2442132720Skan    const size_t __n = __grouping_tmp.size() - 1;
2443132720Skan    const size_t __min = std::min(__n, __grouping_size - 1);
2444132720Skan    size_t __i = __n;
2445132720Skan    bool __test = true;
2446132720Skan    
2447132720Skan    // Parsed number groupings have to match the
2448132720Skan    // numpunct::grouping string exactly, starting at the
2449132720Skan    // right-most point of the parsed sequence of elements ...
2450132720Skan    for (size_t __j = 0; __j < __min && __test; --__i, ++__j)
2451132720Skan      __test = __grouping_tmp[__i] == __grouping[__j];
2452132720Skan    for (; __i && __test; --__i)
2453132720Skan      __test = __grouping_tmp[__i] == __grouping[__min];
2454132720Skan    // ... but the last parsed grouping can be <= numpunct
2455132720Skan    // grouping.
2456132720Skan    __test &= __grouping_tmp[0] <= __grouping[__min];
2457132720Skan    return __test;
2458132720Skan  }
245997403Sobrien
246097403Sobrien  template<typename _CharT>
246197403Sobrien    _CharT*
2462132720Skan    __add_grouping(_CharT* __s, _CharT __sep,
2463132720Skan		   const char* __gbeg, size_t __gsize,
246497403Sobrien		   const _CharT* __first, const _CharT* __last)
246597403Sobrien    {
246697403Sobrien      if (__last - __first > *__gbeg)
2467132720Skan	{
2468132720Skan	  const bool __bump = __gsize != 1;
2469132720Skan	  __s = std::__add_grouping(__s,  __sep, __gbeg + __bump,
2470132720Skan				    __gsize - __bump, __first,
2471132720Skan				    __last - *__gbeg);
2472132720Skan	  __first = __last - *__gbeg;
2473132720Skan	  *__s++ = __sep;
2474132720Skan	}
247597403Sobrien      do
247697403Sobrien	*__s++ = *__first++;
247797403Sobrien      while (__first != __last);
247897403Sobrien      return __s;
247997403Sobrien    }
248097403Sobrien
248197403Sobrien  // Inhibit implicit instantiations for required instantiations,
2482132720Skan  // which are defined via explicit instantiations elsewhere.
248397403Sobrien  // NB: This syntax is a GNU extension.
2484132720Skan#if _GLIBCXX_EXTERN_TEMPLATE
248597403Sobrien  extern template class moneypunct<char, false>;
248697403Sobrien  extern template class moneypunct<char, true>;
248797403Sobrien  extern template class moneypunct_byname<char, false>;
248897403Sobrien  extern template class moneypunct_byname<char, true>;
248997403Sobrien  extern template class money_get<char>;
249097403Sobrien  extern template class money_put<char>;
249197403Sobrien  extern template class numpunct<char>;
249297403Sobrien  extern template class numpunct_byname<char>;
249397403Sobrien  extern template class num_get<char>;
2494132720Skan  extern template class num_put<char>;
249597403Sobrien  extern template class __timepunct<char>;
249697403Sobrien  extern template class time_put<char>;
249797403Sobrien  extern template class time_put_byname<char>;
249897403Sobrien  extern template class time_get<char>;
249997403Sobrien  extern template class time_get_byname<char>;
250097403Sobrien  extern template class messages<char>;
250197403Sobrien  extern template class messages_byname<char>;
250297403Sobrien  extern template class ctype_byname<char>;
250397403Sobrien  extern template class codecvt_byname<char, char, mbstate_t>;
250497403Sobrien  extern template class collate<char>;
250597403Sobrien  extern template class collate_byname<char>;
250697403Sobrien
250797403Sobrien  extern template
2508132720Skan    const codecvt<char, char, mbstate_t>&
250997403Sobrien    use_facet<codecvt<char, char, mbstate_t> >(const locale&);
251097403Sobrien
251197403Sobrien  extern template
2512132720Skan    const collate<char>&
251397403Sobrien    use_facet<collate<char> >(const locale&);
251497403Sobrien
251597403Sobrien  extern template
2516132720Skan    const numpunct<char>&
251797403Sobrien    use_facet<numpunct<char> >(const locale&);
251897403Sobrien
2519132720Skan  extern template
2520132720Skan    const num_put<char>&
252197403Sobrien    use_facet<num_put<char> >(const locale&);
252297403Sobrien
2523132720Skan  extern template
2524132720Skan    const num_get<char>&
252597403Sobrien    use_facet<num_get<char> >(const locale&);
252697403Sobrien
252797403Sobrien  extern template
2528132720Skan    const moneypunct<char, true>&
252997403Sobrien    use_facet<moneypunct<char, true> >(const locale&);
253097403Sobrien
253197403Sobrien  extern template
2532132720Skan    const moneypunct<char, false>&
253397403Sobrien    use_facet<moneypunct<char, false> >(const locale&);
253497403Sobrien
2535132720Skan  extern template
2536132720Skan    const money_put<char>&
253797403Sobrien    use_facet<money_put<char> >(const locale&);
253897403Sobrien
2539132720Skan  extern template
2540132720Skan    const money_get<char>&
254197403Sobrien    use_facet<money_get<char> >(const locale&);
254297403Sobrien
254397403Sobrien  extern template
2544132720Skan    const __timepunct<char>&
254597403Sobrien    use_facet<__timepunct<char> >(const locale&);
254697403Sobrien
2547132720Skan  extern template
2548132720Skan    const time_put<char>&
254997403Sobrien    use_facet<time_put<char> >(const locale&);
255097403Sobrien
2551132720Skan  extern template
2552132720Skan    const time_get<char>&
255397403Sobrien    use_facet<time_get<char> >(const locale&);
255497403Sobrien
2555132720Skan  extern template
2556132720Skan    const messages<char>&
255797403Sobrien    use_facet<messages<char> >(const locale&);
255897403Sobrien
2559132720Skan  extern template
2560107606Sobrien    bool
2561107606Sobrien    has_facet<ctype<char> >(const locale&);
2562107606Sobrien
2563132720Skan  extern template
2564107606Sobrien    bool
2565107606Sobrien    has_facet<codecvt<char, char, mbstate_t> >(const locale&);
2566107606Sobrien
2567132720Skan  extern template
2568107606Sobrien    bool
2569107606Sobrien    has_facet<collate<char> >(const locale&);
2570107606Sobrien
2571132720Skan  extern template
2572107606Sobrien    bool
2573107606Sobrien    has_facet<numpunct<char> >(const locale&);
2574107606Sobrien
2575132720Skan  extern template
2576107606Sobrien    bool
2577107606Sobrien    has_facet<num_put<char> >(const locale&);
2578107606Sobrien
2579132720Skan  extern template
2580107606Sobrien    bool
2581107606Sobrien    has_facet<num_get<char> >(const locale&);
2582107606Sobrien
2583132720Skan  extern template
2584107606Sobrien    bool
2585107606Sobrien    has_facet<moneypunct<char> >(const locale&);
2586107606Sobrien
2587132720Skan  extern template
2588107606Sobrien    bool
2589107606Sobrien    has_facet<money_put<char> >(const locale&);
2590107606Sobrien
2591132720Skan  extern template
2592107606Sobrien    bool
2593107606Sobrien    has_facet<money_get<char> >(const locale&);
2594107606Sobrien
2595132720Skan  extern template
2596107606Sobrien    bool
2597107606Sobrien    has_facet<__timepunct<char> >(const locale&);
2598107606Sobrien
2599132720Skan  extern template
2600107606Sobrien    bool
2601107606Sobrien    has_facet<time_put<char> >(const locale&);
2602107606Sobrien
2603132720Skan  extern template
2604107606Sobrien    bool
2605107606Sobrien    has_facet<time_get<char> >(const locale&);
2606107606Sobrien
2607132720Skan  extern template
2608107606Sobrien    bool
2609107606Sobrien    has_facet<messages<char> >(const locale&);
2610107606Sobrien
2611132720Skan#ifdef _GLIBCXX_USE_WCHAR_T
2612107606Sobrien  extern template class moneypunct<wchar_t, false>;
2613107606Sobrien  extern template class moneypunct<wchar_t, true>;
2614107606Sobrien  extern template class moneypunct_byname<wchar_t, false>;
2615107606Sobrien  extern template class moneypunct_byname<wchar_t, true>;
2616107606Sobrien  extern template class money_get<wchar_t>;
2617107606Sobrien  extern template class money_put<wchar_t>;
2618107606Sobrien  extern template class numpunct<wchar_t>;
2619107606Sobrien  extern template class numpunct_byname<wchar_t>;
2620107606Sobrien  extern template class num_get<wchar_t>;
2621107606Sobrien  extern template class num_put<wchar_t>;
2622107606Sobrien  extern template class __timepunct<wchar_t>;
2623107606Sobrien  extern template class time_put<wchar_t>;
2624107606Sobrien  extern template class time_put_byname<wchar_t>;
2625107606Sobrien  extern template class time_get<wchar_t>;
2626107606Sobrien  extern template class time_get_byname<wchar_t>;
2627107606Sobrien  extern template class messages<wchar_t>;
2628107606Sobrien  extern template class messages_byname<wchar_t>;
2629107606Sobrien  extern template class ctype_byname<wchar_t>;
2630107606Sobrien  extern template class codecvt_byname<wchar_t, char, mbstate_t>;
2631107606Sobrien  extern template class collate<wchar_t>;
2632107606Sobrien  extern template class collate_byname<wchar_t>;
2633107606Sobrien
263497403Sobrien  extern template
2635132720Skan    const codecvt<wchar_t, char, mbstate_t>&
263697403Sobrien    use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&);
263797403Sobrien
263897403Sobrien  extern template
2639132720Skan    const collate<wchar_t>&
264097403Sobrien    use_facet<collate<wchar_t> >(const locale&);
264197403Sobrien
264297403Sobrien  extern template
2643132720Skan    const numpunct<wchar_t>&
264497403Sobrien    use_facet<numpunct<wchar_t> >(const locale&);
264597403Sobrien
2646132720Skan  extern template
2647132720Skan    const num_put<wchar_t>&
264897403Sobrien    use_facet<num_put<wchar_t> >(const locale&);
264997403Sobrien
2650132720Skan  extern template
2651132720Skan    const num_get<wchar_t>&
265297403Sobrien    use_facet<num_get<wchar_t> >(const locale&);
265397403Sobrien
265497403Sobrien  extern template
2655132720Skan    const moneypunct<wchar_t, true>&
265697403Sobrien    use_facet<moneypunct<wchar_t, true> >(const locale&);
265797403Sobrien
265897403Sobrien  extern template
2659132720Skan    const moneypunct<wchar_t, false>&
266097403Sobrien    use_facet<moneypunct<wchar_t, false> >(const locale&);
2661132720Skan
2662132720Skan  extern template
2663132720Skan    const money_put<wchar_t>&
266497403Sobrien    use_facet<money_put<wchar_t> >(const locale&);
266597403Sobrien
2666132720Skan  extern template
2667132720Skan    const money_get<wchar_t>&
266897403Sobrien    use_facet<money_get<wchar_t> >(const locale&);
266997403Sobrien
267097403Sobrien  extern template
2671132720Skan    const __timepunct<wchar_t>&
267297403Sobrien    use_facet<__timepunct<wchar_t> >(const locale&);
267397403Sobrien
2674132720Skan  extern template
2675132720Skan    const time_put<wchar_t>&
267697403Sobrien    use_facet<time_put<wchar_t> >(const locale&);
267797403Sobrien
2678132720Skan  extern template
2679132720Skan    const time_get<wchar_t>&
268097403Sobrien    use_facet<time_get<wchar_t> >(const locale&);
268197403Sobrien
2682132720Skan  extern template
2683132720Skan    const messages<wchar_t>&
268497403Sobrien    use_facet<messages<wchar_t> >(const locale&);
268597403Sobrien
2686132720Skan extern template
268797403Sobrien    bool
268897403Sobrien    has_facet<ctype<wchar_t> >(const locale&);
268997403Sobrien
2690132720Skan  extern template
269197403Sobrien    bool
269297403Sobrien    has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
269397403Sobrien
2694132720Skan  extern template
269597403Sobrien    bool
269697403Sobrien    has_facet<collate<wchar_t> >(const locale&);
269797403Sobrien
2698132720Skan  extern template
269997403Sobrien    bool
270097403Sobrien    has_facet<numpunct<wchar_t> >(const locale&);
270197403Sobrien
2702132720Skan  extern template
270397403Sobrien    bool
270497403Sobrien    has_facet<num_put<wchar_t> >(const locale&);
270597403Sobrien
2706132720Skan  extern template
270797403Sobrien    bool
270897403Sobrien    has_facet<num_get<wchar_t> >(const locale&);
270997403Sobrien
2710132720Skan  extern template
271197403Sobrien    bool
271297403Sobrien    has_facet<moneypunct<wchar_t> >(const locale&);
271397403Sobrien
2714132720Skan  extern template
271597403Sobrien    bool
271697403Sobrien    has_facet<money_put<wchar_t> >(const locale&);
271797403Sobrien
2718132720Skan  extern template
271997403Sobrien    bool
272097403Sobrien    has_facet<money_get<wchar_t> >(const locale&);
272197403Sobrien
2722132720Skan  extern template
272397403Sobrien    bool
272497403Sobrien    has_facet<__timepunct<wchar_t> >(const locale&);
272597403Sobrien
2726132720Skan  extern template
272797403Sobrien    bool
272897403Sobrien    has_facet<time_put<wchar_t> >(const locale&);
272997403Sobrien
2730132720Skan  extern template
273197403Sobrien    bool
273297403Sobrien    has_facet<time_get<wchar_t> >(const locale&);
273397403Sobrien
2734132720Skan  extern template
273597403Sobrien    bool
273697403Sobrien    has_facet<messages<wchar_t> >(const locale&);
2737107606Sobrien#endif
2738117397Skan#endif
273997403Sobrien} // namespace std
274097403Sobrien
274197403Sobrien#endif
2742