OSDN Git Service

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