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