OSDN Git Service

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