]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/libstdc++-v3/contrib/libstdc++-v3-4.3.3/include/bits/locale_facets_nonio.tcc
update
[l4.git] / l4 / pkg / libstdc++-v3 / contrib / libstdc++-v3-4.3.3 / include / bits / locale_facets_nonio.tcc
1 // Locale support -*- C++ -*-
2
3 // Copyright (C) 2007 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 2, or (at your option)
9 // any later version.
10
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING.  If not, write to the Free
18 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19 // USA.
20
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction.  Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License.  This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
29
30 /** @file locale_facets_nonio.tcc
31  *  This is an internal header file, included by other library headers.
32  *  You should not attempt to use it directly.
33  */
34
35 #ifndef _LOCALE_FACETS_NONIO_TCC
36 #define _LOCALE_FACETS_NONIO_TCC 1
37
38 #pragma GCC system_header
39
40 _GLIBCXX_BEGIN_NAMESPACE(std)
41
42   template<typename _CharT, bool _Intl>
43     struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
44     {
45       const __moneypunct_cache<_CharT, _Intl>*
46       operator() (const locale& __loc) const
47       {
48         const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
49         const locale::facet** __caches = __loc._M_impl->_M_caches;
50         if (!__caches[__i])
51           {
52             __moneypunct_cache<_CharT, _Intl>* __tmp = NULL;
53             try
54               {
55                 __tmp = new __moneypunct_cache<_CharT, _Intl>;
56                 __tmp->_M_cache(__loc);
57               }
58             catch(...)
59               {
60                 delete __tmp;
61                 __throw_exception_again;
62               }
63             __loc._M_impl->_M_install_cache(__tmp, __i);
64           }
65         return static_cast<
66           const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
67       }
68     };
69
70   template<typename _CharT, bool _Intl>
71     void
72     __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
73     {
74       _M_allocated = true;
75
76       const moneypunct<_CharT, _Intl>& __mp =
77         use_facet<moneypunct<_CharT, _Intl> >(__loc);
78
79       _M_grouping_size = __mp.grouping().size();
80       char* __grouping = new char[_M_grouping_size];
81       __mp.grouping().copy(__grouping, _M_grouping_size);
82       _M_grouping = __grouping;
83       _M_use_grouping = (_M_grouping_size
84                          && static_cast<signed char>(__mp.grouping()[0]) > 0);
85       
86       _M_decimal_point = __mp.decimal_point();
87       _M_thousands_sep = __mp.thousands_sep();
88       _M_frac_digits = __mp.frac_digits();
89       
90       _M_curr_symbol_size = __mp.curr_symbol().size();
91       _CharT* __curr_symbol = new _CharT[_M_curr_symbol_size];
92       __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size);
93       _M_curr_symbol = __curr_symbol;
94       
95       _M_positive_sign_size = __mp.positive_sign().size();
96       _CharT* __positive_sign = new _CharT[_M_positive_sign_size];
97       __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size);
98       _M_positive_sign = __positive_sign;
99
100       _M_negative_sign_size = __mp.negative_sign().size();
101       _CharT* __negative_sign = new _CharT[_M_negative_sign_size];
102       __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size);
103       _M_negative_sign = __negative_sign;
104       
105       _M_pos_format = __mp.pos_format();
106       _M_neg_format = __mp.neg_format();
107
108       const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
109       __ct.widen(money_base::_S_atoms,
110                  money_base::_S_atoms + money_base::_S_end, _M_atoms);
111     }
112
113 _GLIBCXX_BEGIN_LDBL_NAMESPACE
114
115   template<typename _CharT, typename _InIter>
116     template<bool _Intl>
117       _InIter
118       money_get<_CharT, _InIter>::
119       _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
120                  ios_base::iostate& __err, string& __units) const
121       {
122         typedef char_traits<_CharT>                       __traits_type;
123         typedef typename string_type::size_type           size_type;    
124         typedef money_base::part                          part;
125         typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
126         
127         const locale& __loc = __io._M_getloc();
128         const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
129
130         __use_cache<__cache_type> __uc;
131         const __cache_type* __lc = __uc(__loc);
132         const char_type* __lit = __lc->_M_atoms;
133
134         // Deduced sign.
135         bool __negative = false;
136         // Sign size.
137         size_type __sign_size = 0;
138         // True if sign is mandatory.
139         const bool __mandatory_sign = (__lc->_M_positive_sign_size
140                                        && __lc->_M_negative_sign_size);
141         // String of grouping info from thousands_sep plucked from __units.
142         string __grouping_tmp;
143         if (__lc->_M_use_grouping)
144           __grouping_tmp.reserve(32);
145         // Last position before the decimal point.
146         int __last_pos = 0;
147         // Separator positions, then, possibly, fractional digits.
148         int __n = 0;
149         // If input iterator is in a valid state.
150         bool __testvalid = true;
151         // Flag marking when a decimal point is found.
152         bool __testdecfound = false;
153
154         // The tentative returned string is stored here.
155         string __res;
156         __res.reserve(32);
157
158         const char_type* __lit_zero = __lit + money_base::_S_zero;
159         const money_base::pattern __p = __lc->_M_neg_format;
160         for (int __i = 0; __i < 4 && __testvalid; ++__i)
161           {
162             const part __which = static_cast<part>(__p.field[__i]);
163             switch (__which)
164               {
165               case money_base::symbol:
166                 // According to 22.2.6.1.2, p2, symbol is required
167                 // if (__io.flags() & ios_base::showbase), otherwise
168                 // is optional and consumed only if other characters
169                 // are needed to complete the format.
170                 if (__io.flags() & ios_base::showbase || __sign_size > 1
171                     || __i == 0
172                     || (__i == 1 && (__mandatory_sign
173                                      || (static_cast<part>(__p.field[0])
174                                          == money_base::sign)
175                                      || (static_cast<part>(__p.field[2])
176                                          == money_base::space)))
177                     || (__i == 2 && ((static_cast<part>(__p.field[3])
178                                       == money_base::value)
179                                      || (__mandatory_sign
180                                          && (static_cast<part>(__p.field[3])
181                                              == money_base::sign)))))
182                   {
183                     const size_type __len = __lc->_M_curr_symbol_size;
184                     size_type __j = 0;
185                     for (; __beg != __end && __j < __len
186                            && *__beg == __lc->_M_curr_symbol[__j];
187                          ++__beg, ++__j);
188                     if (__j != __len
189                         && (__j || __io.flags() & ios_base::showbase))
190                       __testvalid = false;
191                   }
192                 break;
193               case money_base::sign:
194                 // Sign might not exist, or be more than one character long.
195                 if (__lc->_M_positive_sign_size && __beg != __end
196                     && *__beg == __lc->_M_positive_sign[0])
197                   {
198                     __sign_size = __lc->_M_positive_sign_size;
199                     ++__beg;
200                   }
201                 else if (__lc->_M_negative_sign_size && __beg != __end
202                          && *__beg == __lc->_M_negative_sign[0])
203                   {
204                     __negative = true;
205                     __sign_size = __lc->_M_negative_sign_size;
206                     ++__beg;
207                   }
208                 else if (__lc->_M_positive_sign_size
209                          && !__lc->_M_negative_sign_size)
210                   // "... if no sign is detected, the result is given the sign
211                   // that corresponds to the source of the empty string"
212                   __negative = true;
213                 else if (__mandatory_sign)
214                   __testvalid = false;
215                 break;
216               case money_base::value:
217                 // Extract digits, remove and stash away the
218                 // grouping of found thousands separators.
219                 for (; __beg != __end; ++__beg)
220                   {
221                     const char_type __c = *__beg;
222                     const char_type* __q = __traits_type::find(__lit_zero, 
223                                                                10, __c);
224                     if (__q != 0)
225                       {
226                         __res += money_base::_S_atoms[__q - __lit];
227                         ++__n;
228                       }
229                     else if (__c == __lc->_M_decimal_point 
230                              && !__testdecfound)
231                       {
232                         __last_pos = __n;
233                         __n = 0;
234                         __testdecfound = true;
235                       }
236                     else if (__lc->_M_use_grouping
237                              && __c == __lc->_M_thousands_sep
238                              && !__testdecfound)
239                       {
240                         if (__n)
241                           {
242                             // Mark position for later analysis.
243                             __grouping_tmp += static_cast<char>(__n);
244                             __n = 0;
245                           }
246                         else
247                           {
248                             __testvalid = false;
249                             break;
250                           }
251                       }
252                     else
253                       break;
254                   }
255                 if (__res.empty())
256                   __testvalid = false;
257                 break;
258               case money_base::space:
259                 // At least one space is required.
260                 if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
261                   ++__beg;
262                 else
263                   __testvalid = false;
264               case money_base::none:
265                 // Only if not at the end of the pattern.
266                 if (__i != 3)
267                   for (; __beg != __end
268                          && __ctype.is(ctype_base::space, *__beg); ++__beg);
269                 break;
270               }
271           }
272
273         // Need to get the rest of the sign characters, if they exist.
274         if (__sign_size > 1 && __testvalid)
275           {
276             const char_type* __sign = __negative ? __lc->_M_negative_sign
277                                                  : __lc->_M_positive_sign;
278             size_type __i = 1;
279             for (; __beg != __end && __i < __sign_size
280                    && *__beg == __sign[__i]; ++__beg, ++__i);
281             
282             if (__i != __sign_size)
283               __testvalid = false;
284           }
285
286         if (__testvalid)
287           {
288             // Strip leading zeros.
289             if (__res.size() > 1)
290               {
291                 const size_type __first = __res.find_first_not_of('0');
292                 const bool __only_zeros = __first == string::npos;
293                 if (__first)
294                   __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
295               }
296
297             // 22.2.6.1.2, p4
298             if (__negative && __res[0] != '0')
299               __res.insert(__res.begin(), '-');
300             
301             // Test for grouping fidelity.
302             if (__grouping_tmp.size())
303               {
304                 // Add the ending grouping.
305                 __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
306                                                                    : __n);
307                 if (!std::__verify_grouping(__lc->_M_grouping,
308                                             __lc->_M_grouping_size,
309                                             __grouping_tmp))
310                   __err |= ios_base::failbit;
311               }
312             
313             // Iff not enough digits were supplied after the decimal-point.
314             if (__testdecfound && __lc->_M_frac_digits > 0
315                 && __n != __lc->_M_frac_digits)
316               __testvalid = false;
317           }
318         
319         // Iff valid sequence is not recognized.
320         if (!__testvalid)
321           __err |= ios_base::failbit;
322         else
323           __units.swap(__res);
324         
325         // Iff no more characters are available.
326         if (__beg == __end)
327           __err |= ios_base::eofbit;
328         return __beg;
329       }
330
331 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
332   template<typename _CharT, typename _InIter>
333     _InIter
334     money_get<_CharT, _InIter>::
335     __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
336              ios_base::iostate& __err, double& __units) const
337     {
338       string __str;
339       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
340                      : _M_extract<false>(__beg, __end, __io, __err, __str);
341       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
342       return __beg;
343     }
344 #endif
345
346   template<typename _CharT, typename _InIter>
347     _InIter
348     money_get<_CharT, _InIter>::
349     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
350            ios_base::iostate& __err, long double& __units) const
351     {
352       string __str;
353       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
354                      : _M_extract<false>(__beg, __end, __io, __err, __str);
355       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
356       return __beg;
357     }
358
359   template<typename _CharT, typename _InIter>
360     _InIter
361     money_get<_CharT, _InIter>::
362     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
363            ios_base::iostate& __err, string_type& __digits) const
364     {
365       typedef typename string::size_type                  size_type;
366
367       const locale& __loc = __io._M_getloc();
368       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
369
370       string __str;
371       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
372                      : _M_extract<false>(__beg, __end, __io, __err, __str);
373       const size_type __len = __str.size();
374       if (__len)
375         {
376           __digits.resize(__len);
377           __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]);
378         }
379       return __beg;
380     }
381
382   template<typename _CharT, typename _OutIter>
383     template<bool _Intl>
384       _OutIter
385       money_put<_CharT, _OutIter>::
386       _M_insert(iter_type __s, ios_base& __io, char_type __fill,
387                 const string_type& __digits) const
388       {
389         typedef typename string_type::size_type           size_type;
390         typedef money_base::part                          part;
391         typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
392       
393         const locale& __loc = __io._M_getloc();
394         const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
395
396         __use_cache<__cache_type> __uc;
397         const __cache_type* __lc = __uc(__loc);
398         const char_type* __lit = __lc->_M_atoms;
399
400         // Determine if negative or positive formats are to be used, and
401         // discard leading negative_sign if it is present.
402         const char_type* __beg = __digits.data();
403
404         money_base::pattern __p;
405         const char_type* __sign;
406         size_type __sign_size;
407         if (!(*__beg == __lit[money_base::_S_minus]))
408           {
409             __p = __lc->_M_pos_format;
410             __sign = __lc->_M_positive_sign;
411             __sign_size = __lc->_M_positive_sign_size;
412           }
413         else
414           {
415             __p = __lc->_M_neg_format;
416             __sign = __lc->_M_negative_sign;
417             __sign_size = __lc->_M_negative_sign_size;
418             if (__digits.size())
419               ++__beg;
420           }
421        
422         // Look for valid numbers in the ctype facet within input digits.
423         size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
424                                            __beg + __digits.size()) - __beg;
425         if (__len)
426           {
427             // Assume valid input, and attempt to format.
428             // Break down input numbers into base components, as follows:
429             //   final_value = grouped units + (decimal point) + (digits)
430             string_type __value;
431             __value.reserve(2 * __len);
432
433             // Add thousands separators to non-decimal digits, per
434             // grouping rules.
435             long __paddec = __len - __lc->_M_frac_digits;
436             if (__paddec > 0)
437               {
438                 if (__lc->_M_frac_digits < 0)
439                   __paddec = __len;
440                 if (__lc->_M_grouping_size)
441                   {
442                     __value.assign(2 * __paddec, char_type());
443                     _CharT* __vend = 
444                       std::__add_grouping(&__value[0], __lc->_M_thousands_sep,
445                                           __lc->_M_grouping,
446                                           __lc->_M_grouping_size,
447                                           __beg, __beg + __paddec);
448                     __value.erase(__vend - &__value[0]);
449                   }
450                 else
451                   __value.assign(__beg, __paddec);
452               }
453
454             // Deal with decimal point, decimal digits.
455             if (__lc->_M_frac_digits > 0)
456               {
457                 __value += __lc->_M_decimal_point;
458                 if (__paddec >= 0)
459                   __value.append(__beg + __paddec, __lc->_M_frac_digits);
460                 else
461                   {
462                     // Have to pad zeros in the decimal position.
463                     __value.append(-__paddec, __lit[money_base::_S_zero]);
464                     __value.append(__beg, __len);
465                   }
466               }
467   
468             // Calculate length of resulting string.
469             const ios_base::fmtflags __f = __io.flags() 
470                                            & ios_base::adjustfield;
471             __len = __value.size() + __sign_size;
472             __len += ((__io.flags() & ios_base::showbase)
473                       ? __lc->_M_curr_symbol_size : 0);
474
475             string_type __res;
476             __res.reserve(2 * __len);
477             
478             const size_type __width = static_cast<size_type>(__io.width());  
479             const bool __testipad = (__f == ios_base::internal
480                                      && __len < __width);
481             // Fit formatted digits into the required pattern.
482             for (int __i = 0; __i < 4; ++__i)
483               {
484                 const part __which = static_cast<part>(__p.field[__i]);
485                 switch (__which)
486                   {
487                   case money_base::symbol:
488                     if (__io.flags() & ios_base::showbase)
489                       __res.append(__lc->_M_curr_symbol,
490                                    __lc->_M_curr_symbol_size);
491                     break;
492                   case money_base::sign:
493                     // Sign might not exist, or be more than one
494                     // character long. In that case, add in the rest
495                     // below.
496                     if (__sign_size)
497                       __res += __sign[0];
498                     break;
499                   case money_base::value:
500                     __res += __value;
501                     break;
502                   case money_base::space:
503                     // At least one space is required, but if internal
504                     // formatting is required, an arbitrary number of
505                     // fill spaces will be necessary.
506                     if (__testipad)
507                       __res.append(__width - __len, __fill);
508                     else
509                       __res += __fill;
510                     break;
511                   case money_base::none:
512                     if (__testipad)
513                       __res.append(__width - __len, __fill);
514                     break;
515                   }
516               }
517             
518             // Special case of multi-part sign parts.
519             if (__sign_size > 1)
520               __res.append(__sign + 1, __sign_size - 1);
521             
522             // Pad, if still necessary.
523             __len = __res.size();
524             if (__width > __len)
525               {
526                 if (__f == ios_base::left)
527                   // After.
528                   __res.append(__width - __len, __fill);
529                 else
530                   // Before.
531                   __res.insert(0, __width - __len, __fill);
532                 __len = __width;
533               }
534             
535             // Write resulting, fully-formatted string to output iterator.
536             __s = std::__write(__s, __res.data(), __len);
537           }
538         __io.width(0);
539         return __s;    
540       }
541
542 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
543   template<typename _CharT, typename _OutIter>
544     _OutIter
545     money_put<_CharT, _OutIter>::
546     __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
547              double __units) const
548     { return this->do_put(__s, __intl, __io, __fill, (long double) __units); }
549 #endif
550
551   template<typename _CharT, typename _OutIter>
552     _OutIter
553     money_put<_CharT, _OutIter>::
554     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
555            long double __units) const
556     {
557       const locale __loc = __io.getloc();
558       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
559 #ifdef _GLIBCXX_USE_C99
560       // First try a buffer perhaps big enough.
561       int __cs_size = 64;
562       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
563       // _GLIBCXX_RESOLVE_LIB_DEFECTS
564       // 328. Bad sprintf format modifier in money_put<>::do_put()
565       int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
566                                         "%.*Lf", 0, __units);
567       // If the buffer was not large enough, try again with the correct size.
568       if (__len >= __cs_size)
569         {
570           __cs_size = __len + 1;
571           __cs = static_cast<char*>(__builtin_alloca(__cs_size));
572           __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
573                                         "%.*Lf", 0, __units);
574         }
575 #else
576       // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
577       const int __cs_size =
578         __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
579       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
580       int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf", 
581                                         0, __units);
582 #endif
583       string_type __digits(__len, char_type());
584       __ctype.widen(__cs, __cs + __len, &__digits[0]);
585       return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
586                     : _M_insert<false>(__s, __io, __fill, __digits);
587     }
588
589   template<typename _CharT, typename _OutIter>
590     _OutIter
591     money_put<_CharT, _OutIter>::
592     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
593            const string_type& __digits) const
594     { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
595                     : _M_insert<false>(__s, __io, __fill, __digits); }
596
597 _GLIBCXX_END_LDBL_NAMESPACE
598
599   // NB: Not especially useful. Without an ios_base object or some
600   // kind of locale reference, we are left clawing at the air where
601   // the side of the mountain used to be...
602   template<typename _CharT, typename _InIter>
603     time_base::dateorder
604     time_get<_CharT, _InIter>::do_date_order() const
605     { return time_base::no_order; }
606
607   // Expand a strftime format string and parse it.  E.g., do_get_date() may
608   // pass %m/%d/%Y => extracted characters.
609   template<typename _CharT, typename _InIter>
610     _InIter
611     time_get<_CharT, _InIter>::
612     _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
613                           ios_base::iostate& __err, tm* __tm,
614                           const _CharT* __format) const
615     {
616       const locale& __loc = __io._M_getloc();
617       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
618       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
619       const size_t __len = char_traits<_CharT>::length(__format);
620
621       ios_base::iostate __tmperr = ios_base::goodbit;
622       for (size_t __i = 0; __beg != __end && __i < __len && !__tmperr; ++__i)
623         {
624           if (__ctype.narrow(__format[__i], 0) == '%')
625             {
626               // Verify valid formatting code, attempt to extract.
627               char __c = __ctype.narrow(__format[++__i], 0);
628               int __mem = 0;
629               if (__c == 'E' || __c == 'O')
630                 __c = __ctype.narrow(__format[++__i], 0);
631               switch (__c)
632                 {
633                   const char* __cs;
634                   _CharT __wcs[10];
635                 case 'a':
636                   // Abbreviated weekday name [tm_wday]
637                   const char_type*  __days1[7];
638                   __tp._M_days_abbreviated(__days1);
639                   __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
640                                           7, __io, __tmperr);
641                   break;
642                 case 'A':
643                   // Weekday name [tm_wday].
644                   const char_type*  __days2[7];
645                   __tp._M_days(__days2);
646                   __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
647                                           7, __io, __tmperr);
648                   break;
649                 case 'h':
650                 case 'b':
651                   // Abbreviated month name [tm_mon]
652                   const char_type*  __months1[12];
653                   __tp._M_months_abbreviated(__months1);
654                   __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
655                                           __months1, 12, __io, __tmperr);
656                   break;
657                 case 'B':
658                   // Month name [tm_mon].
659                   const char_type*  __months2[12];
660                   __tp._M_months(__months2);
661                   __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
662                                           __months2, 12, __io, __tmperr);
663                   break;
664                 case 'c':
665                   // Default time and date representation.
666                   const char_type*  __dt[2];
667                   __tp._M_date_time_formats(__dt);
668                   __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
669                                                 __tm, __dt[0]);
670                   break;
671                 case 'd':
672                   // Day [01, 31]. [tm_mday]
673                   __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
674                                          __io, __tmperr);
675                   break;
676                 case 'e':
677                   // Day [1, 31], with single digits preceded by
678                   // space. [tm_mday]
679                   if (__ctype.is(ctype_base::space, *__beg))
680                     __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
681                                            1, __io, __tmperr);
682                   else
683                     __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
684                                            2, __io, __tmperr);
685                   break;
686                 case 'D':
687                   // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
688                   __cs = "%m/%d/%y";
689                   __ctype.widen(__cs, __cs + 9, __wcs);
690                   __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
691                                                 __tm, __wcs);
692                   break;
693                 case 'H':
694                   // Hour [00, 23]. [tm_hour]
695                   __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
696                                          __io, __tmperr);
697                   break;
698                 case 'I':
699                   // Hour [01, 12]. [tm_hour]
700                   __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
701                                          __io, __tmperr);
702                   break;
703                 case 'm':
704                   // Month [01, 12]. [tm_mon]
705                   __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 
706                                          __io, __tmperr);
707                   if (!__tmperr)
708                     __tm->tm_mon = __mem - 1;
709                   break;
710                 case 'M':
711                   // Minute [00, 59]. [tm_min]
712                   __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
713                                          __io, __tmperr);
714                   break;
715                 case 'n':
716                   if (__ctype.narrow(*__beg, 0) == '\n')
717                     ++__beg;
718                   else
719                     __tmperr |= ios_base::failbit;
720                   break;
721                 case 'R':
722                   // Equivalent to (%H:%M).
723                   __cs = "%H:%M";
724                   __ctype.widen(__cs, __cs + 6, __wcs);
725                   __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
726                                                 __tm, __wcs);
727                   break;
728                 case 'S':
729                   // Seconds. [tm_sec]
730                   // [00, 60] in C99 (one leap-second), [00, 61] in C89.
731 #ifdef _GLIBCXX_USE_C99
732                   __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2,
733 #else
734                   __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
735 #endif
736                                          __io, __tmperr);
737                   break;
738                 case 't':
739                   if (__ctype.narrow(*__beg, 0) == '\t')
740                     ++__beg;
741                   else
742                     __tmperr |= ios_base::failbit;
743                   break;
744                 case 'T':
745                   // Equivalent to (%H:%M:%S).
746                   __cs = "%H:%M:%S";
747                   __ctype.widen(__cs, __cs + 9, __wcs);
748                   __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
749                                                 __tm, __wcs);
750                   break;
751                 case 'x':
752                   // Locale's date.
753                   const char_type*  __dates[2];
754                   __tp._M_date_formats(__dates);
755                   __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
756                                                 __tm, __dates[0]);
757                   break;
758                 case 'X':
759                   // Locale's time.
760                   const char_type*  __times[2];
761                   __tp._M_time_formats(__times);
762                   __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
763                                                 __tm, __times[0]);
764                   break;
765                 case 'y':
766                 case 'C': // C99
767                   // Two digit year. [tm_year]
768                   __beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
769                                          __io, __tmperr);
770                   break;
771                 case 'Y':
772                   // Year [1900). [tm_year]
773                   __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
774                                          __io, __tmperr);
775                   if (!__tmperr)
776                     __tm->tm_year = __mem - 1900;
777                   break;
778                 case 'Z':
779                   // Timezone info.
780                   if (__ctype.is(ctype_base::upper, *__beg))
781                     {
782                       int __tmp;
783                       __beg = _M_extract_name(__beg, __end, __tmp,
784                                        __timepunct_cache<_CharT>::_S_timezones,
785                                               14, __io, __tmperr);
786
787                       // GMT requires special effort.
788                       if (__beg != __end && !__tmperr && __tmp == 0
789                           && (*__beg == __ctype.widen('-')
790                               || *__beg == __ctype.widen('+')))
791                         {
792                           __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
793                                                  __io, __tmperr);
794                           __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
795                                                  __io, __tmperr);
796                         }
797                     }
798                   else
799                     __tmperr |= ios_base::failbit;
800                   break;
801                 default:
802                   // Not recognized.
803                   __tmperr |= ios_base::failbit;
804                 }
805             }
806           else
807             {
808               // Verify format and input match, extract and discard.
809               if (__format[__i] == *__beg)
810                 ++__beg;
811               else
812                 __tmperr |= ios_base::failbit;
813             }
814         }
815
816       if (__tmperr)
817         __err |= ios_base::failbit;
818   
819       return __beg;
820     }
821
822   template<typename _CharT, typename _InIter>
823     _InIter
824     time_get<_CharT, _InIter>::
825     _M_extract_num(iter_type __beg, iter_type __end, int& __member,
826                    int __min, int __max, size_t __len,
827                    ios_base& __io, ios_base::iostate& __err) const
828     {
829       const locale& __loc = __io._M_getloc();
830       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
831
832       // As-is works for __len = 1, 2, 4, the values actually used.
833       int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
834
835       ++__min;
836       size_t __i = 0;
837       int __value = 0;
838       for (; __beg != __end && __i < __len; ++__beg, ++__i)
839         {
840           const char __c = __ctype.narrow(*__beg, '*');
841           if (__c >= '0' && __c <= '9')
842             {
843               __value = __value * 10 + (__c - '0');
844               const int __valuec = __value * __mult;
845               if (__valuec > __max || __valuec + __mult < __min)
846                 break;
847               __mult /= 10;
848             }
849           else
850             break;
851         }
852       if (__i == __len)
853         __member = __value;
854       else
855         __err |= ios_base::failbit;
856
857       return __beg;
858     }
859
860   // Assumptions:
861   // All elements in __names are unique.
862   template<typename _CharT, typename _InIter>
863     _InIter
864     time_get<_CharT, _InIter>::
865     _M_extract_name(iter_type __beg, iter_type __end, int& __member,
866                     const _CharT** __names, size_t __indexlen,
867                     ios_base& __io, ios_base::iostate& __err) const
868     {
869       typedef char_traits<_CharT>               __traits_type;
870       const locale& __loc = __io._M_getloc();
871       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
872
873       int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
874                                                           * __indexlen));
875       size_t __nmatches = 0;
876       size_t __pos = 0;
877       bool __testvalid = true;
878       const char_type* __name;
879
880       // Look for initial matches.
881       // NB: Some of the locale data is in the form of all lowercase
882       // names, and some is in the form of initially-capitalized
883       // names. Look for both.
884       if (__beg != __end)
885         {
886           const char_type __c = *__beg;
887           for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
888             if (__c == __names[__i1][0]
889                 || __c == __ctype.toupper(__names[__i1][0]))
890               __matches[__nmatches++] = __i1;
891         }
892
893       while (__nmatches > 1)
894         {
895           // Find smallest matching string.
896           size_t __minlen = __traits_type::length(__names[__matches[0]]);
897           for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
898             __minlen = std::min(__minlen,
899                               __traits_type::length(__names[__matches[__i2]]));
900           ++__beg, ++__pos;
901           if (__pos < __minlen && __beg != __end)
902             for (size_t __i3 = 0; __i3 < __nmatches;)
903               {
904                 __name = __names[__matches[__i3]];
905                 if (!(__name[__pos] == *__beg))
906                   __matches[__i3] = __matches[--__nmatches];
907                 else
908                   ++__i3;
909               }
910           else
911             break;
912         }
913
914       if (__nmatches == 1)
915         {
916           // Make sure found name is completely extracted.
917           ++__beg, ++__pos;
918           __name = __names[__matches[0]];
919           const size_t __len = __traits_type::length(__name);
920           while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
921             ++__beg, ++__pos;
922
923           if (__len == __pos)
924             __member = __matches[0];
925           else
926             __testvalid = false;
927         }
928       else
929         __testvalid = false;
930       if (!__testvalid)
931         __err |= ios_base::failbit;
932
933       return __beg;
934     }
935
936   template<typename _CharT, typename _InIter>
937     _InIter
938     time_get<_CharT, _InIter>::
939     do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
940                 ios_base::iostate& __err, tm* __tm) const
941     {
942       const locale& __loc = __io._M_getloc();
943       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
944       const char_type*  __times[2];
945       __tp._M_time_formats(__times);
946       __beg = _M_extract_via_format(__beg, __end, __io, __err, 
947                                     __tm, __times[0]);
948       if (__beg == __end)
949         __err |= ios_base::eofbit;
950       return __beg;
951     }
952
953   template<typename _CharT, typename _InIter>
954     _InIter
955     time_get<_CharT, _InIter>::
956     do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
957                 ios_base::iostate& __err, tm* __tm) const
958     {
959       const locale& __loc = __io._M_getloc();
960       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
961       const char_type*  __dates[2];
962       __tp._M_date_formats(__dates);
963       __beg = _M_extract_via_format(__beg, __end, __io, __err, 
964                                     __tm, __dates[0]);
965       if (__beg == __end)
966         __err |= ios_base::eofbit;
967       return __beg;
968     }
969
970   template<typename _CharT, typename _InIter>
971     _InIter
972     time_get<_CharT, _InIter>::
973     do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
974                    ios_base::iostate& __err, tm* __tm) const
975     {
976       typedef char_traits<_CharT>               __traits_type;
977       const locale& __loc = __io._M_getloc();
978       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
979       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
980       const char_type*  __days[7];
981       __tp._M_days_abbreviated(__days);
982       int __tmpwday;
983       ios_base::iostate __tmperr = ios_base::goodbit;
984       __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7,
985                               __io, __tmperr);
986
987       // Check to see if non-abbreviated name exists, and extract.
988       // NB: Assumes both _M_days and _M_days_abbreviated organized in
989       // exact same order, first to last, such that the resulting
990       // __days array with the same index points to a day, and that
991       // day's abbreviated form.
992       // NB: Also assumes that an abbreviated name is a subset of the name.
993       if (!__tmperr && __beg != __end)
994         {
995           size_t __pos = __traits_type::length(__days[__tmpwday]);
996           __tp._M_days(__days);
997           const char_type* __name = __days[__tmpwday];
998           if (__name[__pos] == *__beg)
999             {
1000               // Extract the rest of it.
1001               const size_t __len = __traits_type::length(__name);
1002               while (__pos < __len && __beg != __end
1003                      && __name[__pos] == *__beg)
1004                 ++__beg, ++__pos;
1005               if (__len != __pos)
1006                 __tmperr |= ios_base::failbit;
1007             }
1008         }
1009       if (!__tmperr)
1010         __tm->tm_wday = __tmpwday;
1011       else
1012         __err |= ios_base::failbit;
1013
1014       if (__beg == __end)
1015         __err |= ios_base::eofbit;
1016       return __beg;
1017      }
1018
1019   template<typename _CharT, typename _InIter>
1020     _InIter
1021     time_get<_CharT, _InIter>::
1022     do_get_monthname(iter_type __beg, iter_type __end,
1023                      ios_base& __io, ios_base::iostate& __err, tm* __tm) const
1024     {
1025       typedef char_traits<_CharT>               __traits_type;
1026       const locale& __loc = __io._M_getloc();
1027       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1028       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1029       const char_type*  __months[12];
1030       __tp._M_months_abbreviated(__months);
1031       int __tmpmon;
1032       ios_base::iostate __tmperr = ios_base::goodbit;
1033       __beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12, 
1034                               __io, __tmperr);
1035
1036       // Check to see if non-abbreviated name exists, and extract.
1037       // NB: Assumes both _M_months and _M_months_abbreviated organized in
1038       // exact same order, first to last, such that the resulting
1039       // __months array with the same index points to a month, and that
1040       // month's abbreviated form.
1041       // NB: Also assumes that an abbreviated name is a subset of the name.
1042       if (!__tmperr && __beg != __end)
1043         {
1044           size_t __pos = __traits_type::length(__months[__tmpmon]);
1045           __tp._M_months(__months);
1046           const char_type* __name = __months[__tmpmon];
1047           if (__name[__pos] == *__beg)
1048             {
1049               // Extract the rest of it.
1050               const size_t __len = __traits_type::length(__name);
1051               while (__pos < __len && __beg != __end
1052                      && __name[__pos] == *__beg)
1053                 ++__beg, ++__pos;
1054               if (__len != __pos)
1055                 __tmperr |= ios_base::failbit;
1056             }
1057         }
1058       if (!__tmperr)
1059         __tm->tm_mon = __tmpmon;
1060       else
1061         __err |= ios_base::failbit;
1062
1063       if (__beg == __end)
1064         __err |= ios_base::eofbit;
1065       return __beg;
1066     }
1067
1068   template<typename _CharT, typename _InIter>
1069     _InIter
1070     time_get<_CharT, _InIter>::
1071     do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
1072                 ios_base::iostate& __err, tm* __tm) const
1073     {
1074       const locale& __loc = __io._M_getloc();
1075       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1076
1077       size_t __i = 0;
1078       int __value = 0;
1079       for (; __beg != __end && __i < 4; ++__beg, ++__i)
1080         {
1081           const char __c = __ctype.narrow(*__beg, '*');
1082           if (__c >= '0' && __c <= '9')
1083             __value = __value * 10 + (__c - '0');
1084           else
1085             break;
1086         }
1087       if (__i == 2 || __i == 4)
1088         __tm->tm_year = __i == 2 ? __value : __value - 1900;
1089       else
1090         __err |= ios_base::failbit;
1091
1092       if (__beg == __end)
1093         __err |= ios_base::eofbit;
1094       return __beg;
1095     }
1096
1097   template<typename _CharT, typename _OutIter>
1098     _OutIter
1099     time_put<_CharT, _OutIter>::
1100     put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
1101         const _CharT* __beg, const _CharT* __end) const
1102     {
1103       const locale& __loc = __io._M_getloc();
1104       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1105       for (; __beg != __end; ++__beg)
1106         if (__ctype.narrow(*__beg, 0) != '%')
1107           {
1108             *__s = *__beg;
1109             ++__s;
1110           }
1111         else if (++__beg != __end)
1112           {
1113             char __format;
1114             char __mod = 0;
1115             const char __c = __ctype.narrow(*__beg, 0);
1116             if (__c != 'E' && __c != 'O')
1117               __format = __c;
1118             else if (++__beg != __end)
1119               {
1120                 __mod = __c;
1121                 __format = __ctype.narrow(*__beg, 0);
1122               }
1123             else
1124               break;
1125             __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
1126           }
1127         else
1128           break;
1129       return __s;
1130     }
1131
1132   template<typename _CharT, typename _OutIter>
1133     _OutIter
1134     time_put<_CharT, _OutIter>::
1135     do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1136            char __format, char __mod) const
1137     {
1138       const locale& __loc = __io._M_getloc();
1139       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1140       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1141
1142       // NB: This size is arbitrary. Should this be a data member,
1143       // initialized at construction?
1144       const size_t __maxlen = 128;
1145       char_type* __res = 
1146        static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
1147
1148       // NB: In IEE 1003.1-200x, and perhaps other locale models, it
1149       // is possible that the format character will be longer than one
1150       // character. Possibilities include 'E' or 'O' followed by a
1151       // format character: if __mod is not the default argument, assume
1152       // it's a valid modifier.
1153       char_type __fmt[4];
1154       __fmt[0] = __ctype.widen('%');
1155       if (!__mod)
1156         {
1157           __fmt[1] = __format;
1158           __fmt[2] = char_type();
1159         }
1160       else
1161         {
1162           __fmt[1] = __mod;
1163           __fmt[2] = __format;
1164           __fmt[3] = char_type();
1165         }
1166
1167       __tp._M_put(__res, __maxlen, __fmt, __tm);
1168
1169       // Write resulting, fully-formatted string to output iterator.
1170       return std::__write(__s, __res, char_traits<char_type>::length(__res));
1171     }
1172
1173
1174   // Inhibit implicit instantiations for required instantiations,
1175   // which are defined via explicit instantiations elsewhere.
1176   // NB: This syntax is a GNU extension.
1177 #if _GLIBCXX_EXTERN_TEMPLATE
1178   extern template class moneypunct<char, false>;
1179   extern template class moneypunct<char, true>;
1180   extern template class moneypunct_byname<char, false>;
1181   extern template class moneypunct_byname<char, true>;
1182   extern template class _GLIBCXX_LDBL_NAMESPACE money_get<char>;
1183   extern template class _GLIBCXX_LDBL_NAMESPACE money_put<char>;
1184   extern template class __timepunct<char>;
1185   extern template class time_put<char>;
1186   extern template class time_put_byname<char>;
1187   extern template class time_get<char>;
1188   extern template class time_get_byname<char>;
1189   extern template class messages<char>;
1190   extern template class messages_byname<char>;
1191
1192   extern template
1193     const moneypunct<char, true>&
1194     use_facet<moneypunct<char, true> >(const locale&);
1195
1196   extern template
1197     const moneypunct<char, false>&
1198     use_facet<moneypunct<char, false> >(const locale&);
1199
1200   extern template
1201     const money_put<char>&
1202     use_facet<money_put<char> >(const locale&);
1203
1204   extern template
1205     const money_get<char>&
1206     use_facet<money_get<char> >(const locale&);
1207
1208   extern template
1209     const __timepunct<char>&
1210     use_facet<__timepunct<char> >(const locale&);
1211
1212   extern template
1213     const time_put<char>&
1214     use_facet<time_put<char> >(const locale&);
1215
1216   extern template
1217     const time_get<char>&
1218     use_facet<time_get<char> >(const locale&);
1219
1220   extern template
1221     const messages<char>&
1222     use_facet<messages<char> >(const locale&);
1223
1224   extern template
1225     bool
1226     has_facet<moneypunct<char> >(const locale&);
1227
1228   extern template
1229     bool
1230     has_facet<money_put<char> >(const locale&);
1231
1232   extern template
1233     bool
1234     has_facet<money_get<char> >(const locale&);
1235
1236   extern template
1237     bool
1238     has_facet<__timepunct<char> >(const locale&);
1239
1240   extern template
1241     bool
1242     has_facet<time_put<char> >(const locale&);
1243
1244   extern template
1245     bool
1246     has_facet<time_get<char> >(const locale&);
1247
1248   extern template
1249     bool
1250     has_facet<messages<char> >(const locale&);
1251
1252 #ifdef _GLIBCXX_USE_WCHAR_T
1253   extern template class moneypunct<wchar_t, false>;
1254   extern template class moneypunct<wchar_t, true>;
1255   extern template class moneypunct_byname<wchar_t, false>;
1256   extern template class moneypunct_byname<wchar_t, true>;
1257   extern template class _GLIBCXX_LDBL_NAMESPACE money_get<wchar_t>;
1258   extern template class _GLIBCXX_LDBL_NAMESPACE money_put<wchar_t>;
1259   extern template class __timepunct<wchar_t>;
1260   extern template class time_put<wchar_t>;
1261   extern template class time_put_byname<wchar_t>;
1262   extern template class time_get<wchar_t>;
1263   extern template class time_get_byname<wchar_t>;
1264   extern template class messages<wchar_t>;
1265   extern template class messages_byname<wchar_t>;
1266
1267   extern template
1268     const moneypunct<wchar_t, true>&
1269     use_facet<moneypunct<wchar_t, true> >(const locale&);
1270
1271   extern template
1272     const moneypunct<wchar_t, false>&
1273     use_facet<moneypunct<wchar_t, false> >(const locale&);
1274
1275   extern template
1276     const money_put<wchar_t>&
1277     use_facet<money_put<wchar_t> >(const locale&);
1278
1279   extern template
1280     const money_get<wchar_t>&
1281     use_facet<money_get<wchar_t> >(const locale&);
1282
1283   extern template
1284     const __timepunct<wchar_t>&
1285     use_facet<__timepunct<wchar_t> >(const locale&);
1286
1287   extern template
1288     const time_put<wchar_t>&
1289     use_facet<time_put<wchar_t> >(const locale&);
1290
1291   extern template
1292     const time_get<wchar_t>&
1293     use_facet<time_get<wchar_t> >(const locale&);
1294
1295   extern template
1296     const messages<wchar_t>&
1297     use_facet<messages<wchar_t> >(const locale&);
1298
1299   extern template
1300     bool
1301     has_facet<moneypunct<wchar_t> >(const locale&);
1302
1303   extern template
1304     bool
1305     has_facet<money_put<wchar_t> >(const locale&);
1306
1307   extern template
1308     bool
1309     has_facet<money_get<wchar_t> >(const locale&);
1310
1311   extern template
1312     bool
1313     has_facet<__timepunct<wchar_t> >(const locale&);
1314
1315   extern template
1316     bool
1317     has_facet<time_put<wchar_t> >(const locale&);
1318
1319   extern template
1320     bool
1321     has_facet<time_get<wchar_t> >(const locale&);
1322
1323   extern template
1324     bool
1325     has_facet<messages<wchar_t> >(const locale&);
1326 #endif
1327 #endif
1328
1329 _GLIBCXX_END_NAMESPACE
1330
1331 #endif