OSDN Git Service

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