OSDN Git Service

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