OSDN Git Service

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