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