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