locale_facets.tcc revision 107606
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	const int __max_digits = numeric_limits<_ValueT>::digits10 + 1;
628	streamsize __prec = __io.precision();
629
630	if (__prec > static_cast<streamsize>(__max_digits))
631	  __prec = static_cast<streamsize>(__max_digits);
632
633	// Long enough for the max format spec.
634	char __fbuf[16];
635
636	// [22.2.2.2.2] Stage 1, numeric conversion to character.
637	int __len;
638#ifdef _GLIBCPP_USE_C99
639	// First try a buffer perhaps big enough (for sure sufficient for
640	// non-ios_base::fixed outputs)
641	int __cs_size = __max_digits * 3;
642	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
643
644	const bool __fp = _S_format_float(__io, __fbuf, __mod, __prec);
645	if (__fp)
646	  __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
647				   _S_c_locale, __prec);
648	else
649	  __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale);
650
651	// If the buffer was not large enough, try again with the correct size.
652	if (__len >= __cs_size)
653	  {
654	    __cs_size = __len + 1; 
655	    __cs = static_cast<char*>(__builtin_alloca(__cs_size));
656	    if (__fp)
657	      __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
658				       _S_c_locale, __prec);
659	    else
660	      __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
661				       _S_c_locale);
662	  }
663#else
664	// Consider the possibility of long ios_base::fixed outputs
665	const bool __fixed = __io.flags() & ios_base::fixed;
666	const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
667	// ios_base::fixed outputs may need up to __max_exp+1 chars
668	// for the integer part + up to __max_digits chars for the
669	// fractional part + 3 chars for sign, decimal point, '\0'. On
670	// the other hand, for non-fixed outputs __max_digits*3 chars
671	// are largely sufficient.
672	const int __cs_size = __fixed ? __max_exp + __max_digits + 4 
673	                              : __max_digits * 3;
674	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
675
676	if (_S_format_float(__io, __fbuf, __mod, __prec))
677	  __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec);
678	else
679	  __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale);
680#endif
681	return _M_widen_float(__s, __io, __fill, __cs, __len);
682      }
683
684  template<typename _CharT, typename _OutIter>
685    template<typename _ValueT>
686      _OutIter
687      num_put<_CharT, _OutIter>::
688      _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
689		     char __modl, _ValueT __v) const
690      {
691	// [22.2.2.2.2] Stage 1, numeric conversion to character.
692
693	// Long enough for the max format spec.
694	char __fbuf[16];
695	_S_format_int(__io, __fbuf, __mod, __modl);
696#ifdef _GLIBCPP_USE_C99
697	// First try a buffer perhaps big enough.
698	int __cs_size = 64;
699	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
700	int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
701				     _S_c_locale);
702	// If the buffer was not large enough, try again with the correct size.
703	if (__len >= __cs_size)
704	  {
705	    __cs_size = __len + 1;
706	    __cs = static_cast<char*>(__builtin_alloca(__cs_size));
707	    __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
708				     _S_c_locale);
709	  }
710#else
711	// Leave room for "+/-," "0x," and commas. This size is
712	// arbitrary, but should be largely sufficient.
713	char __cs[128];
714	int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale);
715#endif
716	return _M_widen_int(__s, __io, __fill, __cs, __len);
717      }
718
719  template<typename _CharT, typename _OutIter>
720    _OutIter
721    num_put<_CharT, _OutIter>::
722    _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 
723		   int __len) const
724    {
725      typedef char_traits<_CharT> 		__traits_type;
726      // [22.2.2.2.2] Stage 2, convert to char_type, using correct
727      // numpunct.decimal_point() values for '.' and adding grouping.
728      const locale __loc = __io.getloc();
729      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
730      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
731							   * __len));
732      // Grouping can add (almost) as many separators as the number of
733      // digits, but no more.
734      _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
735			 				    * __len * 2));
736      __ctype.widen(__cs, __cs + __len, __ws);
737      
738      // Replace decimal point.
739      const _CharT* __p;
740      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
741      if (__p = __traits_type::find(__ws, __len, __ctype.widen('.')))
742	__ws[__p - __ws] = __np.decimal_point();
743
744#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
745//282. What types does numpunct grouping refer to?
746      // Add grouping, if necessary. 
747      const string __grouping = __np.grouping();
748      ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
749      if (__grouping.size())
750	{
751	  _CharT* __p2;
752	  int __declen = __p ? __p - __ws : __len;
753	  __p2 = __add_grouping(__ws2, __np.thousands_sep(), 
754				__grouping.c_str(),
755				__grouping.c_str() + __grouping.size(),
756				__ws, __ws + __declen);
757	  int __newlen = __p2 - __ws2;
758	
759	  // Tack on decimal part.
760	  if (__p)
761	    {
762	      __traits_type::copy(__p2, __p, __len - __declen);
763	      __newlen += __len - __declen;
764	    }    
765
766	  // Switch strings, establish correct new length.
767	  __ws = __ws2;
768	  __len = __newlen;
769	}
770#endif
771      return _M_insert(__s, __io, __fill, __ws, __len);
772    }
773
774  template<typename _CharT, typename _OutIter>
775    _OutIter
776    num_put<_CharT, _OutIter>::
777    _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 
778		 int __len) const
779    {
780      // [22.2.2.2.2] Stage 2, convert to char_type, using correct
781      // numpunct.decimal_point() values for '.' and adding grouping.
782      const locale __loc = __io.getloc();
783      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
784      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
785							   * __len));
786      // Grouping can add (almost) as many separators as the number of
787      // digits, but no more.
788      _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
789							    * __len * 2));
790      __ctype.widen(__cs, __cs + __len, __ws);
791
792      // Add grouping, if necessary. 
793      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
794      const string __grouping = __np.grouping();
795      const ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
796      if (__grouping.size())
797	{
798	  // By itself __add_grouping cannot deal correctly with __ws when
799	  // ios::showbase is set and ios_base::oct || ios_base::hex.
800	  // Therefore we take care "by hand" of the initial 0, 0x or 0X.
801	  // However, remember that the latter do not occur if the number
802	  // printed is '0' (__len == 1).
803	  streamsize __off = 0;
804	  if ((__io.flags() & ios_base::showbase) && __len > 1)
805	    if (__basefield == ios_base::oct)
806	      {
807		__off = 1;
808		*__ws2 = *__ws;
809	      }
810	    else if (__basefield == ios_base::hex)
811	      {
812		__off = 2;
813		*__ws2 = *__ws;
814		*(__ws2 + 1) = *(__ws + 1);
815	      }
816	  _CharT* __p;
817	  __p = __add_grouping(__ws2 + __off, __np.thousands_sep(), 
818			       __grouping.c_str(),
819			       __grouping.c_str() + __grouping.size(),
820			       __ws + __off, __ws + __len);
821	  __len = __p - __ws2;
822	  // Switch strings.
823	  __ws = __ws2;
824	}
825      return _M_insert(__s, __io, __fill, __ws, __len);
826    }
827
828  // For use by integer and floating-point types after they have been
829  // converted into a char_type string.
830  template<typename _CharT, typename _OutIter>
831    _OutIter
832    num_put<_CharT, _OutIter>::
833    _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, 
834	      int __len) const
835    {
836      typedef char_traits<_CharT> 		__traits_type;
837      // [22.2.2.2.2] Stage 3.
838      streamsize __w = __io.width();
839      _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
840							    * __w));
841      if (__w > static_cast<streamsize>(__len))
842	{
843	  __pad<_CharT, __traits_type>::_S_pad(__io, __fill, __ws2, __ws, 
844					       __w, __len, true);
845	  __len = static_cast<int>(__w);
846	  // Switch strings.
847	  __ws = __ws2;
848	}
849      __io.width(0);
850
851      // [22.2.2.2.2] Stage 4.
852      // Write resulting, fully-formatted string to output iterator.
853      for (int __j = 0; __j < __len; ++__j, ++__s)
854	*__s = __ws[__j];
855      return __s;
856    }
857
858  template<typename _CharT, typename _OutIter>
859    _OutIter
860    num_put<_CharT, _OutIter>::
861    do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
862    {
863      ios_base::fmtflags __flags = __io.flags();
864      if ((__flags & ios_base::boolalpha) == 0)
865        {
866          unsigned long __uv = __v;
867          __s = _M_convert_int(__s, __io, __fill, 'u', char(), __uv);
868        }
869      else
870        {
871	  typedef basic_string<_CharT> __string_type;
872          locale __loc = __io.getloc();
873	  const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 
874	  __string_type __name;
875          if (__v)
876	    __name = __np.truename();
877          else
878	    __name = __np.falsename();
879	  __s = _M_insert(__s, __io, __fill, __name.c_str(), __name.size()); 
880	}
881      return __s;
882    }
883
884  template<typename _CharT, typename _OutIter>
885    _OutIter
886    num_put<_CharT, _OutIter>::
887    do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
888    { return _M_convert_int(__s, __io, __fill, 'd', char(), __v); }
889
890  template<typename _CharT, typename _OutIter>
891    _OutIter
892    num_put<_CharT, _OutIter>::
893    do_put(iter_type __s, ios_base& __io, char_type __fill,
894           unsigned long __v) const
895    { return _M_convert_int(__s, __io, __fill, 'u', char(), __v); }
896
897#ifdef _GLIBCPP_USE_LONG_LONG
898  template<typename _CharT, typename _OutIter>
899    _OutIter
900    num_put<_CharT, _OutIter>::
901    do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
902    { return _M_convert_int(__s, __b, __fill, 'd', 'l', __v); }
903
904  template<typename _CharT, typename _OutIter>
905    _OutIter
906    num_put<_CharT, _OutIter>::
907    do_put(iter_type __s, ios_base& __io, char_type __fill,
908           unsigned long long __v) const
909    { return _M_convert_int(__s, __io, __fill, 'u', 'l', __v); }
910#endif
911
912  template<typename _CharT, typename _OutIter>
913    _OutIter
914    num_put<_CharT, _OutIter>::
915    do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
916    { return _M_convert_float(__s, __io, __fill, char(), __v); }
917
918  template<typename _CharT, typename _OutIter>
919    _OutIter
920    num_put<_CharT, _OutIter>::
921    do_put(iter_type __s, ios_base& __io, char_type __fill, 
922	   long double __v) const
923    { return _M_convert_float(__s, __io, __fill, 'L', __v); }
924
925  template<typename _CharT, typename _OutIter>
926    _OutIter
927    num_put<_CharT, _OutIter>::
928    do_put(iter_type __s, ios_base& __io, char_type __fill,
929           const void* __v) const
930    {
931      ios_base::fmtflags __flags = __io.flags();
932      ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield
933				   | ios_base::uppercase | ios_base::internal);
934      __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
935      try 
936	{
937	  __s = _M_convert_int(__s, __io, __fill, 'u', char(),
938			       reinterpret_cast<unsigned long>(__v));
939	  __io.flags(__flags);
940	}
941      catch (...) 
942	{
943	  __io.flags(__flags);
944	  __throw_exception_again;
945	}
946      return __s;
947    }
948
949
950  template<typename _CharT, typename _InIter>
951    _InIter
952    money_get<_CharT, _InIter>::
953    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 
954	   ios_base::iostate& __err, long double& __units) const
955    { 
956      string_type __str;
957      __beg = this->do_get(__beg, __end, __intl, __io, __err, __str); 
958
959      const int __n = numeric_limits<long double>::digits10;
960      char* __cs = static_cast<char*>(__builtin_alloca(__n));
961      const locale __loc = __io.getloc();
962      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
963      const _CharT* __wcs = __str.c_str();
964      __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs);      
965      __convert_to_v(__cs, __units, __err, _S_c_locale);
966      return __beg;
967    }
968
969  template<typename _CharT, typename _InIter>
970    _InIter
971    money_get<_CharT, _InIter>::
972    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 
973	   ios_base::iostate& __err, string_type& __units) const
974    { 
975      // These contortions are quite unfortunate.
976      typedef moneypunct<_CharT, true> 		__money_true;
977      typedef moneypunct<_CharT, false> 	__money_false;
978      typedef money_base::part 			part;
979      typedef typename string_type::size_type 	size_type;
980
981      const locale __loc = __io.getloc();
982      const __money_true& __mpt = use_facet<__money_true>(__loc); 
983      const __money_false& __mpf = use_facet<__money_false>(__loc); 
984      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
985
986      const money_base::pattern __p = __intl ? __mpt.neg_format() 
987					     : __mpf.neg_format();
988
989      const string_type __pos_sign =__intl ? __mpt.positive_sign() 
990					   : __mpf.positive_sign();
991      const string_type __neg_sign =__intl ? __mpt.negative_sign() 
992					   : __mpf.negative_sign();
993      const char_type __d = __intl ? __mpt.decimal_point() 
994  	    	       		   : __mpf.decimal_point();
995      const char_type __sep = __intl ? __mpt.thousands_sep() 
996		    		     : __mpf.thousands_sep();
997
998      const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping();
999
1000      // Set to deduced positive or negative sign, depending.
1001      string_type __sign;
1002      // String of grouping info from thousands_sep plucked from __units.
1003      string __grouping_tmp; 
1004      // Marker for thousands_sep position.
1005      int __sep_pos = 0;
1006      // If input iterator is in a valid state.
1007      bool __testvalid = true;
1008      // Flag marking when a decimal point is found.
1009      bool __testdecfound = false; 
1010
1011      // The tentative returned string is stored here.
1012      string_type __temp_units;
1013
1014      char_type __c = *__beg;
1015      char_type __eof = static_cast<char_type>(char_traits<char_type>::eof());
1016      for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i)
1017	{
1018	  part __which = static_cast<part>(__p.field[__i]);
1019	  switch (__which)
1020		{
1021		case money_base::symbol:
1022		  if (__io.flags() & ios_base::showbase 
1023		      || __i < 2 || __sign.size() > 1
1024		      || ((static_cast<part>(__p.field[3]) != money_base::none)
1025			  && __i == 2)) 
1026		    {
1027		      // According to 22.2.6.1.2.2, symbol is required
1028		      // if (__io.flags() & ios_base::showbase),
1029		      // otherwise is optional and consumed only if
1030		      // other characters are needed to complete the
1031		      // format.
1032		      const string_type __symbol = __intl ? __mpt.curr_symbol()
1033						    	 : __mpf.curr_symbol();
1034		      size_type __len = __symbol.size();
1035		      size_type __j = 0;
1036		      while (__beg != __end 
1037			     && __j < __len && __symbol[__j] == __c)
1038			{
1039			  __c = *(++__beg);
1040			  ++__j;
1041			}
1042		      // When (__io.flags() & ios_base::showbase)
1043		      // symbol is required.
1044		      if (__j != __len && (__io.flags() & ios_base::showbase))
1045			__testvalid = false;
1046		    }
1047		  break;
1048		case money_base::sign:		    
1049		  // Sign might not exist, or be more than one character long. 
1050		  if (__pos_sign.size() && __neg_sign.size())
1051		  {
1052		    // Sign is mandatory.
1053		    if (__c == __pos_sign[0])
1054		      {
1055			__sign = __pos_sign;
1056			__c = *(++__beg);
1057		      }
1058		    else if (__c == __neg_sign[0])
1059		      {
1060			__sign = __neg_sign;
1061			__c = *(++__beg);
1062		      }
1063		    else
1064		      __testvalid = false;
1065		  }
1066		  else if (__pos_sign.size() && __c == __pos_sign[0])
1067		    {
1068		      __sign = __pos_sign;
1069		      __c = *(++__beg);
1070		    }
1071		  else if (__neg_sign.size() && __c == __neg_sign[0])
1072		    {
1073		      __sign = __neg_sign;
1074		      __c = *(++__beg);
1075		    }
1076		  break;
1077		case money_base::value:
1078		  // Extract digits, remove and stash away the
1079		  // grouping of found thousands separators.
1080		  while (__beg != __end 
1081			 && (__ctype.is(ctype_base::digit, __c) 
1082			     || (__c == __d && !__testdecfound)
1083			     || __c == __sep))
1084		    {
1085		      if (__c == __d)
1086			{
1087			  __grouping_tmp += static_cast<char>(__sep_pos);
1088			  __sep_pos = 0;
1089			  __testdecfound = true;
1090			}
1091		      else if (__c == __sep)
1092			{
1093			  if (__grouping.size())
1094			    {
1095			      // Mark position for later analysis.
1096			      __grouping_tmp += static_cast<char>(__sep_pos);
1097			      __sep_pos = 0;
1098			    }
1099			  else
1100			    {
1101			      __testvalid = false;
1102			      break;
1103			    }
1104			}
1105		      else
1106			{
1107			  __temp_units += __c;
1108			  ++__sep_pos;
1109			}
1110		      __c = *(++__beg);
1111		    }
1112		  break;
1113		case money_base::space:
1114		case money_base::none:
1115		  // Only if not at the end of the pattern.
1116		  if (__i != 3)
1117		    while (__beg != __end 
1118			   && __ctype.is(ctype_base::space, __c))
1119		      __c = *(++__beg);
1120		  break;
1121		}
1122	}
1123
1124      // Need to get the rest of the sign characters, if they exist.
1125      if (__sign.size() > 1)
1126	{
1127	  size_type __len = __sign.size();
1128	  size_type __i = 1;
1129	  for (; __c != __eof && __i < __len; ++__i)
1130	    while (__beg != __end && __c != __sign[__i])
1131	      __c = *(++__beg);
1132	  
1133	  if (__i != __len)
1134	    __testvalid = false;
1135	}
1136
1137      // Strip leading zeros.
1138      while (__temp_units[0] == __ctype.widen('0'))
1139	__temp_units.erase(__temp_units.begin());
1140
1141      if (__sign.size() && __sign == __neg_sign)
1142	__temp_units.insert(__temp_units.begin(), __ctype.widen('-'));
1143
1144      // Test for grouping fidelity.
1145      if (__grouping.size() && __grouping_tmp.size())
1146	{
1147	  if (!__verify_grouping(__grouping, __grouping_tmp))
1148	    __testvalid = false;
1149	}
1150
1151      // Iff no more characters are available.      
1152      if (__c == __eof)
1153	__err |= ios_base::eofbit;
1154
1155      // Iff valid sequence is not recognized.
1156      if (!__testvalid || !__temp_units.size())
1157	__err |= ios_base::failbit;
1158      else
1159	// Use the "swap trick" to copy __temp_units into __units.
1160	__temp_units.swap(__units);
1161
1162      return __beg; 
1163    }
1164
1165  template<typename _CharT, typename _OutIter>
1166    _OutIter
1167    money_put<_CharT, _OutIter>::
1168    do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1169	   long double __units) const
1170    { 
1171      const locale __loc = __io.getloc();
1172      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1173#ifdef _GLIBCPP_USE_C99
1174      // First try a buffer perhaps big enough.
1175      int __cs_size = 64;
1176      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1177      int __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 
1178				   _S_c_locale);
1179      // If the buffer was not large enough, try again with the correct size.
1180      if (__len >= __cs_size)
1181	{
1182	  __cs_size = __len + 1;
1183	  __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1184	  __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 
1185				   _S_c_locale);
1186	}
1187#else
1188      // max_exponent10 + 1 for the integer part, + 4 for sign, decimal point,
1189      // decimal digit, '\0'. 
1190      const int __cs_size = numeric_limits<long double>::max_exponent10 + 5;
1191      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1192      int __len = __convert_from_v(__cs, 0, "%.01Lf", __units, _S_c_locale);
1193#endif
1194      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __cs_size));
1195      __ctype.widen(__cs, __cs + __len, __ws);
1196      string_type __digits(__ws);
1197      return this->do_put(__s, __intl, __io, __fill, __digits); 
1198    }
1199
1200  template<typename _CharT, typename _OutIter>
1201    _OutIter
1202    money_put<_CharT, _OutIter>::
1203    do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1204	   const string_type& __digits) const
1205    { 
1206      typedef typename string_type::size_type 	size_type;
1207      typedef money_base::part 			part;
1208
1209      const locale __loc = __io.getloc();
1210      const size_type __width = static_cast<size_type>(__io.width());
1211
1212      // These contortions are quite unfortunate.
1213      typedef moneypunct<_CharT, true> __money_true;
1214      typedef moneypunct<_CharT, false> __money_false;
1215      const __money_true& __mpt = use_facet<__money_true>(__loc); 
1216      const __money_false& __mpf = use_facet<__money_false>(__loc); 
1217      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
1218
1219      // Determine if negative or positive formats are to be used, and
1220      // discard leading negative_sign if it is present.
1221      const char_type* __beg = __digits.data();
1222      const char_type* __end = __beg + __digits.size();
1223      money_base::pattern __p;
1224      string_type __sign;
1225      if (*__beg != __ctype.widen('-'))
1226	{
1227	  __p = __intl ? __mpt.pos_format() : __mpf.pos_format();
1228	  __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign();
1229	}
1230      else
1231	{
1232	  __p = __intl ? __mpt.neg_format() : __mpf.neg_format();
1233	  __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign();
1234	  ++__beg;
1235	}
1236      
1237      // Look for valid numbers in the current ctype facet within input digits.
1238      __end = __ctype.scan_not(ctype_base::digit, __beg, __end);
1239      if (__beg != __end)
1240	{
1241	  // Assume valid input, and attempt to format.
1242	  // Break down input numbers into base components, as follows:
1243	  //   final_value = grouped units + (decimal point) + (digits)
1244	  string_type __res;
1245	  string_type __value;
1246	  const string_type __symbol = __intl ? __mpt.curr_symbol() 
1247	    				      : __mpf.curr_symbol();
1248
1249	  // Deal with decimal point, decimal digits.
1250	  const int __frac = __intl ? __mpt.frac_digits() 
1251	    			    : __mpf.frac_digits();
1252	  if (__frac > 0)
1253	    {
1254	      const char_type __d = __intl ? __mpt.decimal_point() 
1255					   : __mpf.decimal_point();
1256	      if (__end - __beg >= __frac)
1257		{
1258		  __value = string_type(__end - __frac, __end);
1259		  __value.insert(__value.begin(), __d);
1260		  __end -= __frac;
1261		}
1262	      else
1263		{
1264		  // Have to pad zeros in the decimal position.
1265		  __value = string_type(__beg, __end);
1266		  int __paddec = __frac - (__end - __beg);
1267		  char_type __zero = __ctype.widen('0');
1268		  __value.insert(__value.begin(), __paddec, __zero);
1269		  __value.insert(__value.begin(), __d);
1270		  __beg = __end;
1271		}
1272	    }
1273
1274	  // Add thousands separators to non-decimal digits, per
1275	  // grouping rules.
1276	  if (__beg != __end)
1277	    {
1278	      const string __grouping = __intl ? __mpt.grouping() 
1279					       : __mpf.grouping();
1280	      if (__grouping.size())
1281		{
1282		  const char_type __sep = __intl ? __mpt.thousands_sep() 
1283		    			         : __mpf.thousands_sep();
1284		  const char* __gbeg = __grouping.c_str();
1285		  const char* __gend = __gbeg + __grouping.size();
1286		  const int __n = (__end - __beg) * 2;
1287		  _CharT* __ws2 =
1288		    static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
1289		  _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg, 
1290						    __gend, __beg, __end);
1291		  __value.insert(0, __ws2, __ws_end - __ws2);
1292		}
1293	      else
1294		__value.insert(0, string_type(__beg, __end));
1295	    }
1296
1297	  // Calculate length of resulting string.
1298	  ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield;
1299	  size_type __len = __value.size() + __sign.size();
1300	  __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0;
1301	  bool __testipad = __f == ios_base::internal && __len < __width;
1302
1303	  // Fit formatted digits into the required pattern.
1304	  for (int __i = 0; __i < 4; ++__i)
1305	    {
1306	      part __which = static_cast<part>(__p.field[__i]);
1307	      switch (__which)
1308		{
1309		case money_base::symbol:
1310		  if (__io.flags() & ios_base::showbase)
1311		    __res += __symbol;
1312		  break;
1313		case money_base::sign:		    
1314		  // Sign might not exist, or be more than one
1315		  // charater long. In that case, add in the rest
1316		  // below.
1317		  if (__sign.size())
1318		    __res += __sign[0];
1319		  break;
1320		case money_base::value:
1321		  __res += __value;
1322		  break;
1323		case money_base::space:
1324		  // At least one space is required, but if internal
1325		  // formatting is required, an arbitrary number of
1326		  // fill spaces will be necessary.
1327		  if (__testipad)
1328		    __res += string_type(__width - __len, __fill);
1329		  else
1330		    __res += __ctype.widen(__fill);
1331		  break;
1332		case money_base::none:
1333		  if (__testipad)
1334		    __res += string_type(__width - __len, __fill);
1335		  break;
1336		}
1337	    }
1338
1339	  // Special case of multi-part sign parts.
1340	  if (__sign.size() > 1)
1341	    __res += string_type(__sign.begin() + 1, __sign.end());
1342
1343	  // Pad, if still necessary.
1344	  __len = __res.size();
1345	  if (__width > __len)
1346	    {
1347	      if (__f == ios_base::left)
1348		// After.
1349		__res.append(__width - __len, __fill);
1350	      else
1351		// Before.
1352		__res.insert(0, string_type(__width - __len, __fill));
1353	      __len = __width;
1354	    }
1355
1356	  // Write resulting, fully-formatted string to output iterator.
1357	  for (size_type __j = 0; __j < __len; ++__j, ++__s)
1358	    *__s = __res[__j];
1359	}
1360      __io.width(0);
1361      return __s; 
1362    }
1363
1364
1365  // NB: Not especially useful. Without an ios_base object or some
1366  // kind of locale reference, we are left clawing at the air where
1367  // the side of the mountain used to be...
1368  template<typename _CharT, typename _InIter>
1369    time_base::dateorder
1370    time_get<_CharT, _InIter>::do_date_order() const
1371    { return time_base::no_order; }
1372
1373  template<typename _CharT, typename _InIter>
1374    void
1375    time_get<_CharT, _InIter>::
1376    _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io,
1377			  ios_base::iostate& __err, tm* __tm, 
1378			  const _CharT* __format) const
1379    {  
1380      locale __loc = __io.getloc();
1381      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1382      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
1383      size_t __len = char_traits<_CharT>::length(__format);
1384
1385      for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
1386	{
1387	  char __c = __format[__i];
1388	  if (__c == '%')
1389	    {
1390	      // Verify valid formatting code, attempt to extract.
1391	      __c = __format[++__i];
1392	      char __mod = 0;
1393	      int __mem = 0; 
1394	      if (__c == 'E' || __c == 'O')
1395		{
1396		  __mod = __c;
1397		  __c = __format[++__i];
1398		}
1399	      switch (__c)
1400		{
1401		  const char* __cs;
1402		  _CharT __wcs[10];
1403		case 'a':
1404		  // Abbreviated weekday name [tm_wday]
1405		  const char_type*  __days1[7];
1406		  __tp._M_days_abbreviated(__days1);
1407		  _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7, 
1408				  __err);
1409		  break;
1410		case 'A':
1411		  // Weekday name [tm_wday].
1412		  const char_type*  __days2[7];
1413		  __tp._M_days(__days2);
1414		  _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7, 
1415				  __err);
1416		  break;
1417		case 'h':
1418		case 'b':
1419		  // Abbreviated month name [tm_mon]
1420		  const char_type*  __months1[12];
1421		  __tp._M_months_abbreviated(__months1);
1422		  _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12, 
1423				  __err);
1424		  break;
1425		case 'B':
1426		  // Month name [tm_mon].
1427		  const char_type*  __months2[12];
1428		  __tp._M_months(__months2);
1429		  _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12, 
1430				  __err);
1431		  break;
1432		case 'c':
1433		  // Default time and date representation.
1434		  const char_type*  __dt[2];
1435		  __tp._M_date_time_formats(__dt);
1436		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
1437					__dt[0]);
1438		  break;
1439		case 'd':
1440		  // Day [01, 31]. [tm_mday]
1441		  _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, 
1442				 __ctype, __err);
1443		  break;
1444		case 'D':
1445		  // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
1446		  __cs = "%m/%d/%y";
1447		  __ctype.widen(__cs, __cs + 9, __wcs);
1448		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
1449					__wcs);
1450		  break;
1451		case 'H':
1452		  // Hour [00, 23]. [tm_hour]
1453		  _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
1454				 __ctype, __err);
1455		  break;
1456		case 'I':
1457		  // Hour [01, 12]. [tm_hour]
1458		  _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, 
1459				 __ctype, __err);
1460		  break;
1461		case 'm':
1462		  // Month [01, 12]. [tm_mon]
1463		  _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype, 
1464				 __err);
1465		  if (!__err)
1466		    __tm->tm_mon = __mem - 1;
1467		  break;
1468		case 'M':
1469		  // Minute [00, 59]. [tm_min]
1470		  _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
1471				 __ctype, __err);
1472		  break;
1473		case 'n':
1474		  if (__ctype.narrow(*__beg, 0) == '\n')
1475		    ++__beg;
1476		  else
1477		    __err |= ios_base::failbit;
1478		  break;
1479		case 'R':
1480		  // Equivalent to (%H:%M).
1481		  __cs = "%H:%M";
1482		  __ctype.widen(__cs, __cs + 6, __wcs);
1483		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
1484					__wcs);
1485		  break;
1486		case 'S':
1487		  // Seconds.
1488		  _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2,
1489				 __ctype, __err);
1490		  break;
1491		case 't':
1492		  if (__ctype.narrow(*__beg, 0) == '\t')
1493		    ++__beg;
1494		  else
1495		__err |= ios_base::failbit;
1496		  break;
1497		case 'T':
1498		  // Equivalent to (%H:%M:%S).
1499		  __cs = "%H:%M:%S";
1500		  __ctype.widen(__cs, __cs + 9, __wcs);
1501		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
1502					__wcs);
1503		  break;
1504		case 'x':
1505		  // Locale's date.
1506		  const char_type*  __dates[2];
1507		  __tp._M_date_formats(__dates);
1508		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
1509					__dates[0]);
1510		  break;
1511		case 'X':
1512		  // Locale's time.
1513		  const char_type*  __times[2];
1514		  __tp._M_time_formats(__times);
1515		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
1516					__times[0]);
1517		  break;
1518		case 'y':
1519		  // Two digit year. [tm_year]
1520		  _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, 
1521				 __ctype, __err);
1522		  break;
1523		case 'Y':
1524		  // Year [1900). [tm_year]
1525		  _M_extract_num(__beg, __end, __mem, 0, 
1526				 numeric_limits<int>::max(), 4, 
1527				 __ctype, __err);
1528		  if (!__err)
1529		    __tm->tm_year = __mem - 1900;
1530		  break;
1531		case 'Z':
1532		  // Timezone info.
1533		  if (__ctype.is(ctype_base::upper, *__beg))
1534		    {
1535		      int __tmp;
1536		      _M_extract_name(__beg, __end, __tmp, 
1537				      __timepunct<_CharT>::_S_timezones, 
1538				      14, __err);
1539		      
1540		      // GMT requires special effort.
1541		      char_type __c = *__beg;
1542		      if (!__err && __tmp == 0 
1543			  && (__c == __ctype.widen('-') 
1544			      || __c == __ctype.widen('+')))
1545			{
1546			  _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
1547					  __ctype, __err);
1548			  _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
1549					  __ctype, __err);
1550			}	    
1551			  }
1552		      else
1553			__err |= ios_base::failbit;
1554		      break;
1555		    default:
1556		      // Not recognized.
1557		      __err |= ios_base::failbit;
1558		    }
1559		}
1560	      else
1561		{
1562		  // Verify format and input match, extract and discard.
1563		  if (__c == __ctype.narrow(*__beg, 0))
1564		    ++__beg;
1565		  else
1566		    __err |= ios_base::failbit;
1567		}
1568	}
1569    }
1570
1571  template<typename _CharT, typename _InIter>
1572    void
1573    time_get<_CharT, _InIter>::
1574    _M_extract_num(iter_type& __beg, iter_type& __end, int& __member,
1575		   int __min, int __max, size_t __len, 
1576		   const ctype<_CharT>& __ctype, 
1577		   ios_base::iostate& __err) const
1578    {
1579      size_t __i = 0;
1580      string __digits;
1581      bool __testvalid = true;
1582      char_type __c = *__beg;
1583      while (__beg != __end && __i < __len 
1584	     && __ctype.is(ctype_base::digit, __c)) 
1585	{
1586	  __digits += __ctype.narrow(__c, 0);
1587	  __c = *(++__beg);
1588	  ++__i;
1589	}
1590      if (__i == __len)
1591	{
1592	  int __value = atoi(__digits.c_str());
1593	  if (__min <= __value && __value <= __max)
1594	    __member = __value;
1595	  else
1596	    __testvalid = false;
1597	}
1598      else
1599	__testvalid = false;
1600      if (!__testvalid)
1601	__err |= ios_base::failbit;
1602    }
1603
1604  // Assumptions:
1605  // All elements in __names are unique.
1606  template<typename _CharT, typename _InIter>
1607    void
1608    time_get<_CharT, _InIter>::
1609    _M_extract_name(iter_type& __beg, iter_type& __end, int& __member,
1610		    const _CharT** __names, size_t __indexlen, 
1611		    ios_base::iostate& __err) const
1612    {
1613      typedef char_traits<_CharT> 		__traits_type;
1614      int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) * __indexlen));
1615      size_t __nmatches = 0;
1616      size_t __pos = 0;
1617      bool __testvalid = true;
1618      const char_type* __name;
1619
1620      char_type __c = *__beg;
1621      // Look for initial matches.
1622      for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
1623	if (__c == __names[__i1][0])
1624	  __matches[__nmatches++] = __i1;
1625      
1626      while(__nmatches > 1)
1627	{
1628	  // Find smallest matching string.
1629	  size_t __minlen = 10;
1630	  for (size_t __i2 = 0; __i2 < __nmatches; ++__i2)
1631	    __minlen = min(__minlen, 
1632			   __traits_type::length(__names[__matches[__i2]]));
1633	  
1634	  if (__pos < __minlen && __beg != __end)
1635	    {
1636	      ++__pos;
1637	      __c = *(++__beg);
1638	      for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
1639		{
1640		  __name = __names[__matches[__i3]];
1641		  if (__name[__pos] != __c)
1642		    __matches[__i3] = __matches[--__nmatches];
1643		}
1644	    }
1645	  else
1646	    break;
1647	}
1648
1649      if (__nmatches == 1)
1650	{
1651	  // Make sure found name is completely extracted.
1652	  __name = __names[__matches[0]];
1653	  const size_t __len = __traits_type::length(__name);
1654	  while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
1655	    ++__beg, ++__pos;
1656
1657	  if (__len == __pos)
1658	    __member = __matches[0];
1659	  else
1660	    __testvalid = false;
1661	}
1662      else
1663	__testvalid = false;
1664      if (!__testvalid)
1665	__err |= ios_base::failbit;
1666    }
1667
1668  template<typename _CharT, typename _InIter>
1669    _InIter
1670    time_get<_CharT, _InIter>::
1671    do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
1672		ios_base::iostate& __err, tm* __tm) const
1673    {
1674      _CharT __wcs[3];
1675      const char* __cs = "%X";
1676      locale __loc = __io.getloc();
1677      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1678      __ctype.widen(__cs, __cs + 3, __wcs);
1679      _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
1680      if (__beg == __end)
1681	__err |= ios_base::eofbit;
1682      return __beg;
1683    }
1684
1685  template<typename _CharT, typename _InIter>
1686    _InIter
1687    time_get<_CharT, _InIter>::
1688    do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
1689		ios_base::iostate& __err, tm* __tm) const
1690    {
1691      _CharT __wcs[3];
1692      const char* __cs = "%x";
1693      locale __loc = __io.getloc();
1694      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1695      __ctype.widen(__cs, __cs + 3, __wcs);
1696      _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
1697      if (__beg == __end)
1698	__err |= ios_base::eofbit;
1699      return __beg;
1700    }
1701
1702  template<typename _CharT, typename _InIter>
1703    _InIter
1704    time_get<_CharT, _InIter>::
1705    do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 
1706		   ios_base::iostate& __err, tm* __tm) const
1707    {
1708      typedef char_traits<_CharT> 		__traits_type;
1709      locale __loc = __io.getloc();
1710      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1711      const char_type*  __days[7];
1712      __tp._M_days_abbreviated(__days);
1713      int __tmpwday;
1714      _M_extract_name(__beg, __end, __tmpwday, __days, 7, __err);
1715
1716      // Check to see if non-abbreviated name exists, and extract.
1717      // NB: Assumes both _M_days and _M_days_abbreviated organized in
1718      // exact same order, first to last, such that the resulting
1719      // __days array with the same index points to a day, and that
1720      // day's abbreviated form.
1721      // NB: Also assumes that an abbreviated name is a subset of the name. 
1722      if (!__err)
1723	{
1724	  size_t __pos = __traits_type::length(__days[__tmpwday]);
1725	  __tp._M_days(__days);
1726	  const char_type* __name = __days[__tmpwday];
1727	  if (__name[__pos] == *__beg)
1728	    {
1729	      // Extract the rest of it.
1730	      const size_t __len = __traits_type::length(__name);
1731	      while (__pos < __len && __beg != __end 
1732		     && __name[__pos] == *__beg)
1733		++__beg, ++__pos;
1734	      if (__len != __pos)
1735		__err |= ios_base::failbit;
1736	    }
1737	  if (!__err)
1738	    __tm->tm_wday = __tmpwday;
1739	}
1740      if (__beg == __end)
1741	__err |= ios_base::eofbit;
1742      return __beg;
1743     }
1744
1745  template<typename _CharT, typename _InIter>
1746    _InIter
1747    time_get<_CharT, _InIter>::
1748    do_get_monthname(iter_type __beg, iter_type __end,
1749                     ios_base& __io, ios_base::iostate& __err, tm* __tm) const
1750    {
1751      typedef char_traits<_CharT> 		__traits_type;
1752      locale __loc = __io.getloc();
1753      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1754      const char_type*  __months[12];
1755      __tp._M_months_abbreviated(__months);
1756      int __tmpmon;
1757      _M_extract_name(__beg, __end, __tmpmon, __months, 12, __err);
1758
1759      // Check to see if non-abbreviated name exists, and extract.
1760      // NB: Assumes both _M_months and _M_months_abbreviated organized in
1761      // exact same order, first to last, such that the resulting
1762      // __months array with the same index points to a month, and that
1763      // month's abbreviated form.
1764      // NB: Also assumes that an abbreviated name is a subset of the name. 
1765      if (!__err)
1766	{
1767	  size_t __pos = __traits_type::length(__months[__tmpmon]);
1768	  __tp._M_months(__months);
1769	  const char_type* __name = __months[__tmpmon];
1770	  if (__name[__pos] == *__beg)
1771	    {
1772	      // Extract the rest of it.
1773	      const size_t __len = __traits_type::length(__name);
1774	      while (__pos < __len && __beg != __end 
1775		     && __name[__pos] == *__beg)
1776		++__beg, ++__pos;
1777	      if (__len != __pos)
1778		__err |= ios_base::failbit;
1779	    }
1780	  if (!__err)
1781	    __tm->tm_mon = __tmpmon;
1782	}
1783 
1784      if (__beg == __end)
1785	__err |= ios_base::eofbit;
1786      return __beg;
1787    }
1788
1789  template<typename _CharT, typename _InIter>
1790    _InIter
1791    time_get<_CharT, _InIter>::
1792    do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 
1793		ios_base::iostate& __err, tm* __tm) const
1794    {
1795      locale __loc = __io.getloc();
1796      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
1797
1798      char_type __c = *__beg;
1799      size_t __i = 0;
1800      string __digits;
1801      while (__i < 4 && __beg != __end && __ctype.is(ctype_base::digit, __c))
1802	{
1803	  __digits += __ctype.narrow(__c, 0);
1804	  __c = *(++__beg);
1805	  ++__i;
1806	}
1807      if (__i == 2 || __i == 4)
1808	{
1809	  long __l;
1810	  __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale);
1811	  if (!(__err & ios_base::failbit) && __l <= INT_MAX)
1812	    {
1813	      __l = __i == 2 ? __l : __l - 1900; 
1814	      __tm->tm_year = static_cast<int>(__l);
1815	    }
1816	}
1817      else
1818	__err |= ios_base::failbit;
1819      if (__beg == __end)
1820	__err |= ios_base::eofbit;
1821      return __beg;
1822    }
1823
1824  template<typename _CharT, typename _OutIter>
1825    _OutIter
1826    time_put<_CharT, _OutIter>::
1827    put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 
1828	const _CharT* __beg, const _CharT* __end) const
1829    {
1830      locale __loc = __io.getloc();
1831      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1832      while (__beg != __end)
1833	{
1834	  char __c = __ctype.narrow(*__beg, 0);
1835	  ++__beg;
1836	  if (__c == '%')
1837	    {
1838	      char __format;
1839	      char __mod = 0;
1840	      size_t __len = 1; 
1841	      __c = __ctype.narrow(*__beg, 0);
1842	      ++__beg;
1843	      if (__c == 'E' || __c == 'O')
1844		{
1845		  __mod = __c;
1846		  __format = __ctype.narrow(*__beg, 0);
1847		  ++__beg;
1848		}
1849	      else
1850		__format = __c;
1851	      __s = this->do_put(__s, __io, char_type(), __tm, __format, 
1852				 __mod);
1853	    }
1854	  else
1855	    {
1856	      *__s = __c;
1857	      ++__s;
1858	    }
1859	}
1860      return __s;
1861    }
1862
1863  template<typename _CharT, typename _OutIter>
1864    _OutIter
1865    time_put<_CharT, _OutIter>::
1866    do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 
1867	   char __format, char __mod) const
1868    { 
1869      locale __loc = __io.getloc();
1870      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1871      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1872
1873      // NB: This size is arbitrary. Should this be a data member,
1874      // initialized at construction?
1875      const size_t __maxlen = 64;
1876      char_type* __res =
1877	static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
1878
1879      // NB: In IEE 1003.1-200x, and perhaps other locale models, it
1880      // is possible that the format character will be longer than one
1881      // character. Possibilities include 'E' or 'O' followed by a
1882      // format character: if __mod is not the default argument, assume
1883      // it's a valid modifier.
1884      char_type __fmt[4];
1885      __fmt[0] = __ctype.widen('%'); 
1886      if (!__mod)
1887	{
1888	  __fmt[1] = __format;
1889	  __fmt[2] = char_type();
1890	}
1891      else
1892	{
1893	  __fmt[1] = __mod;
1894	  __fmt[2] = __format;
1895	  __fmt[3] = char_type();
1896	}
1897
1898      __tp._M_put(__res, __maxlen, __fmt, __tm);
1899
1900      // Write resulting, fully-formatted string to output iterator.
1901      size_t __len = char_traits<char_type>::length(__res);
1902      for (size_t __i = 0; __i < __len; ++__i, ++__s)
1903	*__s = __res[__i];
1904      return __s;
1905    }
1906
1907
1908  // Generic version does nothing.
1909  template<typename _CharT>
1910    int
1911    collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const
1912    { return 0; }
1913
1914  // Generic version does nothing.
1915  template<typename _CharT>
1916    size_t
1917    collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const
1918    { return 0; }
1919
1920  template<typename _CharT>
1921    int
1922    collate<_CharT>::
1923    do_compare(const _CharT* __lo1, const _CharT* __hi1, 
1924	       const _CharT* __lo2, const _CharT* __hi2) const
1925    { 
1926      const string_type __one(__lo1, __hi1);
1927      const string_type __two(__lo2, __hi2);
1928      return _M_compare(__one.c_str(), __two.c_str());
1929    }
1930
1931 template<typename _CharT>
1932    typename collate<_CharT>::string_type
1933    collate<_CharT>::
1934    do_transform(const _CharT* __lo, const _CharT* __hi) const
1935    {
1936      size_t __len = (__hi - __lo) * 2;
1937      // First try a buffer perhaps big enough.
1938      _CharT* __c =
1939	static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
1940      size_t __res = _M_transform(__c, __lo, __len);
1941      // If the buffer was not large enough, try again with the correct size.
1942      if (__res >= __len)
1943	{
1944	  __c =
1945	    static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * (__res + 1)));
1946	  _M_transform(__c, __lo, __res + 1);
1947	}
1948      return string_type(__c);
1949    }
1950
1951 template<typename _CharT>
1952    long
1953    collate<_CharT>::
1954    do_hash(const _CharT* __lo, const _CharT* __hi) const
1955    { 
1956      unsigned long __val = 0;
1957      for (; __lo < __hi; ++__lo)
1958	__val = *__lo + ((__val << 7) | 
1959		       (__val >> (numeric_limits<unsigned long>::digits - 7)));
1960      return static_cast<long>(__val);
1961    }
1962
1963  // Convert string to numeric value of type _Tv and store results.  
1964  // NB: This is specialized for all required types, there is no
1965  // generic definition.
1966  template<typename _Tv>
1967    void
1968    __convert_to_v(const char* __in, _Tv& __out, ios_base::iostate& __err, 
1969		   const __c_locale& __cloc, int __base = 10);
1970
1971  // Convert numeric value of type _Tv to string and return length of string.
1972  // If snprintf is available use it, otherwise fall back to the unsafe sprintf
1973  // which, in general, can be dangerous and should be avoided.
1974  template<typename _Tv>
1975    int
1976    __convert_from_v(char* __out, const int __size, const char* __fmt,
1977		     _Tv __v, const __c_locale&, int __prec = -1);
1978
1979  // Construct correctly padded string, as per 22.2.2.2.2
1980  // Assumes 
1981  // __newlen > __oldlen
1982  // __news is allocated for __newlen size
1983  // Used by both num_put and ostream inserters: if __num,
1984  // internal-adjusted objects are padded according to the rules below
1985  // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
1986  // ones are.
1987
1988  // NB: Of the two parameters, _CharT can be deduced from the
1989  // function arguments. The other (_Traits) has to be explicitly specified.
1990  template<typename _CharT, typename _Traits>
1991    struct __pad
1992    {
1993      static void
1994      _S_pad(ios_base& __io, _CharT __fill, _CharT* __news, 
1995	     const _CharT* __olds, const streamsize __newlen, 
1996	     const streamsize __oldlen, const bool __num);
1997    };
1998
1999  template<typename _CharT, typename _Traits>
2000    void 
2001    __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, 
2002				   _CharT* __news, const _CharT* __olds, 
2003				   const streamsize __newlen, 
2004				   const streamsize __oldlen, const bool __num)
2005    {
2006      size_t __plen = static_cast<size_t>(__newlen - __oldlen);
2007      _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __plen));
2008      _Traits::assign(__pads, __plen, __fill); 
2009
2010      _CharT* __beg;
2011      _CharT* __end;
2012      size_t __mod = 0;
2013      size_t __beglen; //either __plen or __oldlen
2014      ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
2015
2016      if (__adjust == ios_base::left)
2017	{
2018	  // Padding last.
2019	  __beg = const_cast<_CharT*>(__olds);
2020	  __beglen = __oldlen;
2021	  __end = __pads;
2022	}
2023      else if (__adjust == ios_base::internal && __num)
2024	{
2025	  // Pad after the sign, if there is one.
2026	  // Pad after 0[xX], if there is one.
2027	  // Who came up with these rules, anyway? Jeeze.
2028          locale __loc = __io.getloc();
2029	  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
2030	  const _CharT __minus = __ctype.widen('-');
2031	  const _CharT __plus = __ctype.widen('+');
2032	  bool __testsign = _Traits::eq(__olds[0], __minus)
2033	    		    || _Traits::eq(__olds[0], __plus);
2034
2035	  bool __testhex = _Traits::eq(__ctype.widen('0'), __olds[0]) 
2036	    		   && (_Traits::eq(__ctype.widen('x'), __olds[1]) 
2037			       || _Traits::eq(__ctype.widen('X'), __olds[1]));
2038	  if (__testhex)
2039	    {
2040	      __news[0] = __olds[0]; 
2041	      __news[1] = __olds[1];
2042	      __mod += 2;
2043	      __news += 2;
2044	      __beg = __pads;
2045	      __beglen = __plen;
2046	      __end = const_cast<_CharT*>(__olds + __mod);
2047	    }
2048	  else if (__testsign)
2049	    {
2050	      _Traits::eq((__news[0] = __olds[0]), __plus) ? __plus : __minus;
2051	      ++__mod;
2052	      ++__news;
2053	      __beg = __pads;
2054	      __beglen = __plen;
2055	      __end = const_cast<_CharT*>(__olds + __mod);
2056	    }
2057	  else
2058	    {
2059	      // Padding first.
2060	      __beg = __pads;
2061	      __beglen = __plen;
2062	      __end = const_cast<_CharT*>(__olds);
2063	    }
2064	}
2065      else
2066	{
2067	  // Padding first.
2068	  __beg = __pads;
2069	  __beglen = __plen;
2070	  __end = const_cast<_CharT*>(__olds);
2071	}
2072      _Traits::copy(__news, __beg, __beglen);
2073      _Traits::copy(__news + __beglen, __end, 
2074			  __newlen - __beglen - __mod);
2075    }
2076
2077  // Used by both numeric and monetary facets.
2078  // Check to make sure that the __grouping_tmp string constructed in
2079  // money_get or num_get matches the canonical grouping for a given
2080  // locale.
2081  // __grouping_tmp is parsed L to R
2082  // 1,222,444 == __grouping_tmp of "/1/3/3"
2083  // __grouping is parsed R to L
2084  // 1,222,444 == __grouping of "/3" == "/3/3/3"
2085  template<typename _CharT>
2086    bool
2087    __verify_grouping(const basic_string<_CharT>& __grouping, 
2088		      basic_string<_CharT>& __grouping_tmp)
2089    {         
2090      int __i = 0;
2091      int __j = 0;
2092      const int __len = __grouping.size();
2093      const int __n = __grouping_tmp.size();
2094      bool __test = true;
2095      
2096      // Parsed number groupings have to match the
2097      // numpunct::grouping string exactly, starting at the
2098      // right-most point of the parsed sequence of elements ...
2099      while (__test && __i < __n - 1)
2100	for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i)
2101	  __test &= __grouping[__j] == __grouping_tmp[__n - __i - 1];
2102      // ... but the last parsed grouping can be <= numpunct
2103      // grouping.
2104      __j == __len ? __j = 0 : __j;
2105      __test &= __grouping[__j] >= __grouping_tmp[__n - __i - 1];
2106      return __test;
2107    }
2108
2109  // Used by both numeric and monetary facets.
2110  // Inserts "group separator" characters into an array of characters.
2111  // It's recursive, one iteration per group.  It moves the characters
2112  // in the buffer this way: "xxxx12345" -> "12,345xxx".  Call this
2113  // only with __gbeg != __gend.
2114  template<typename _CharT>
2115    _CharT*
2116    __add_grouping(_CharT* __s, _CharT __sep,  
2117		   const char* __gbeg, const char* __gend, 
2118		   const _CharT* __first, const _CharT* __last)
2119    {
2120      if (__last - __first > *__gbeg)
2121        {
2122          __s = __add_grouping(__s,  __sep, 
2123			       (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1),
2124			       __gend, __first, __last - *__gbeg);
2125          __first = __last - *__gbeg;
2126          *__s++ = __sep;
2127        }
2128      do
2129	*__s++ = *__first++;
2130      while (__first != __last);
2131      return __s;
2132    }
2133
2134  // Inhibit implicit instantiations for required instantiations,
2135  // which are defined via explicit instantiations elsewhere.  
2136  // NB: This syntax is a GNU extension.
2137  extern template class moneypunct<char, false>;
2138  extern template class moneypunct<char, true>;
2139  extern template class moneypunct_byname<char, false>;
2140  extern template class moneypunct_byname<char, true>;
2141  extern template class money_get<char>;
2142  extern template class money_put<char>;
2143  extern template class numpunct<char>;
2144  extern template class numpunct_byname<char>;
2145  extern template class num_get<char>;
2146  extern template class num_put<char>; 
2147  extern template class __timepunct<char>;
2148  extern template class time_put<char>;
2149  extern template class time_put_byname<char>;
2150  extern template class time_get<char>;
2151  extern template class time_get_byname<char>;
2152  extern template class messages<char>;
2153  extern template class messages_byname<char>;
2154  extern template class ctype_byname<char>;
2155  extern template class codecvt_byname<char, char, mbstate_t>;
2156  extern template class collate<char>;
2157  extern template class collate_byname<char>;
2158
2159  extern template
2160    const codecvt<char, char, mbstate_t>& 
2161    use_facet<codecvt<char, char, mbstate_t> >(const locale&);
2162
2163  extern template
2164    const collate<char>& 
2165    use_facet<collate<char> >(const locale&);
2166
2167  extern template
2168    const numpunct<char>& 
2169    use_facet<numpunct<char> >(const locale&);
2170
2171  extern template 
2172    const num_put<char>& 
2173    use_facet<num_put<char> >(const locale&);
2174
2175  extern template 
2176    const num_get<char>& 
2177    use_facet<num_get<char> >(const locale&);
2178
2179  extern template
2180    const moneypunct<char, true>& 
2181    use_facet<moneypunct<char, true> >(const locale&);
2182
2183  extern template
2184    const moneypunct<char, false>& 
2185    use_facet<moneypunct<char, false> >(const locale&);
2186
2187  extern template 
2188    const money_put<char>& 
2189    use_facet<money_put<char> >(const locale&);
2190
2191  extern template 
2192    const money_get<char>& 
2193    use_facet<money_get<char> >(const locale&);
2194
2195  extern template
2196    const __timepunct<char>& 
2197    use_facet<__timepunct<char> >(const locale&);
2198
2199  extern template 
2200    const time_put<char>& 
2201    use_facet<time_put<char> >(const locale&);
2202
2203  extern template 
2204    const time_get<char>& 
2205    use_facet<time_get<char> >(const locale&);
2206
2207  extern template 
2208    const messages<char>& 
2209    use_facet<messages<char> >(const locale&);
2210
2211  extern template 
2212    bool
2213    has_facet<ctype<char> >(const locale&);
2214
2215  extern template 
2216    bool
2217    has_facet<codecvt<char, char, mbstate_t> >(const locale&);
2218
2219  extern template 
2220    bool
2221    has_facet<collate<char> >(const locale&);
2222
2223  extern template 
2224    bool
2225    has_facet<numpunct<char> >(const locale&);
2226
2227  extern template 
2228    bool
2229    has_facet<num_put<char> >(const locale&);
2230
2231  extern template 
2232    bool
2233    has_facet<num_get<char> >(const locale&);
2234
2235  extern template 
2236    bool
2237    has_facet<moneypunct<char> >(const locale&);
2238
2239  extern template 
2240    bool
2241    has_facet<money_put<char> >(const locale&);
2242
2243  extern template 
2244    bool
2245    has_facet<money_get<char> >(const locale&);
2246
2247  extern template 
2248    bool
2249    has_facet<__timepunct<char> >(const locale&);
2250
2251  extern template 
2252    bool
2253    has_facet<time_put<char> >(const locale&);
2254
2255  extern template 
2256    bool
2257    has_facet<time_get<char> >(const locale&);
2258
2259  extern template 
2260    bool
2261    has_facet<messages<char> >(const locale&);
2262
2263#ifdef _GLIBCPP_USE_WCHAR_T
2264  extern template class moneypunct<wchar_t, false>;
2265  extern template class moneypunct<wchar_t, true>;
2266  extern template class moneypunct_byname<wchar_t, false>;
2267  extern template class moneypunct_byname<wchar_t, true>;
2268  extern template class money_get<wchar_t>;
2269  extern template class money_put<wchar_t>;
2270  extern template class numpunct<wchar_t>;
2271  extern template class numpunct_byname<wchar_t>;
2272  extern template class num_get<wchar_t>;
2273  extern template class num_put<wchar_t>;
2274  extern template class __timepunct<wchar_t>;
2275  extern template class time_put<wchar_t>;
2276  extern template class time_put_byname<wchar_t>;
2277  extern template class time_get<wchar_t>;
2278  extern template class time_get_byname<wchar_t>;
2279  extern template class messages<wchar_t>;
2280  extern template class messages_byname<wchar_t>;
2281  extern template class ctype_byname<wchar_t>;
2282  extern template class codecvt_byname<wchar_t, char, mbstate_t>;
2283  extern template class collate<wchar_t>;
2284  extern template class collate_byname<wchar_t>;
2285
2286  extern template
2287    const codecvt<wchar_t, char, mbstate_t>& 
2288    use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&);
2289
2290  extern template
2291    const collate<wchar_t>& 
2292    use_facet<collate<wchar_t> >(const locale&);
2293
2294  extern template
2295    const numpunct<wchar_t>& 
2296    use_facet<numpunct<wchar_t> >(const locale&);
2297
2298  extern template 
2299    const num_put<wchar_t>& 
2300    use_facet<num_put<wchar_t> >(const locale&);
2301
2302  extern template 
2303    const num_get<wchar_t>& 
2304    use_facet<num_get<wchar_t> >(const locale&);
2305
2306  extern template
2307    const moneypunct<wchar_t, true>& 
2308    use_facet<moneypunct<wchar_t, true> >(const locale&);
2309
2310  extern template
2311    const moneypunct<wchar_t, false>& 
2312    use_facet<moneypunct<wchar_t, false> >(const locale&);
2313 
2314  extern template 
2315    const money_put<wchar_t>& 
2316    use_facet<money_put<wchar_t> >(const locale&);
2317
2318  extern template 
2319    const money_get<wchar_t>& 
2320    use_facet<money_get<wchar_t> >(const locale&);
2321
2322  extern template
2323    const __timepunct<wchar_t>& 
2324    use_facet<__timepunct<wchar_t> >(const locale&);
2325
2326  extern template 
2327    const time_put<wchar_t>& 
2328    use_facet<time_put<wchar_t> >(const locale&);
2329
2330  extern template 
2331    const time_get<wchar_t>& 
2332    use_facet<time_get<wchar_t> >(const locale&);
2333
2334  extern template 
2335    const messages<wchar_t>& 
2336    use_facet<messages<wchar_t> >(const locale&);
2337
2338 extern template 
2339    bool
2340    has_facet<ctype<wchar_t> >(const locale&);
2341
2342  extern template 
2343    bool
2344    has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
2345
2346  extern template 
2347    bool
2348    has_facet<collate<wchar_t> >(const locale&);
2349
2350  extern template 
2351    bool
2352    has_facet<numpunct<wchar_t> >(const locale&);
2353
2354  extern template 
2355    bool
2356    has_facet<num_put<wchar_t> >(const locale&);
2357
2358  extern template 
2359    bool
2360    has_facet<num_get<wchar_t> >(const locale&);
2361
2362  extern template 
2363    bool
2364    has_facet<moneypunct<wchar_t> >(const locale&);
2365
2366  extern template 
2367    bool
2368    has_facet<money_put<wchar_t> >(const locale&);
2369
2370  extern template 
2371    bool
2372    has_facet<money_get<wchar_t> >(const locale&);
2373
2374  extern template 
2375    bool
2376    has_facet<__timepunct<wchar_t> >(const locale&);
2377
2378  extern template 
2379    bool
2380    has_facet<time_put<wchar_t> >(const locale&);
2381
2382  extern template 
2383    bool
2384    has_facet<time_get<wchar_t> >(const locale&);
2385
2386  extern template 
2387    bool
2388    has_facet<messages<wchar_t> >(const locale&);
2389#endif
2390} // namespace std
2391
2392#endif
2393