libstdc++
locale_facets_nonio.tcc
Go to the documentation of this file.
00001 // Locale support -*- C++ -*-
00002 
00003 // Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file bits/locale_facets_nonio.tcc
00026  *  This is an internal header file, included by other library headers.
00027  *  Do not attempt to use it directly. @headername{locale}
00028  */
00029 
00030 #ifndef _LOCALE_FACETS_NONIO_TCC
00031 #define _LOCALE_FACETS_NONIO_TCC 1
00032 
00033 #pragma GCC system_header
00034 
00035 namespace std _GLIBCXX_VISIBILITY(default)
00036 {
00037 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00038 
00039   template<typename _CharT, bool _Intl>
00040     struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
00041     {
00042       const __moneypunct_cache<_CharT, _Intl>*
00043       operator() (const locale& __loc) const
00044       {
00045     const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
00046     const locale::facet** __caches = __loc._M_impl->_M_caches;
00047     if (!__caches[__i])
00048       {
00049         __moneypunct_cache<_CharT, _Intl>* __tmp = 0;
00050         __try
00051           {
00052         __tmp = new __moneypunct_cache<_CharT, _Intl>;
00053         __tmp->_M_cache(__loc);
00054           }
00055         __catch(...)
00056           {
00057         delete __tmp;
00058         __throw_exception_again;
00059           }
00060         __loc._M_impl->_M_install_cache(__tmp, __i);
00061       }
00062     return static_cast<
00063       const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
00064       }
00065     };
00066 
00067   template<typename _CharT, bool _Intl>
00068     void
00069     __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
00070     {
00071       _M_allocated = true;
00072 
00073       const moneypunct<_CharT, _Intl>& __mp =
00074     use_facet<moneypunct<_CharT, _Intl> >(__loc);
00075 
00076       _M_decimal_point = __mp.decimal_point();
00077       _M_thousands_sep = __mp.thousands_sep();
00078       _M_frac_digits = __mp.frac_digits();
00079 
00080       char* __grouping = 0;
00081       _CharT* __curr_symbol = 0;
00082       _CharT* __positive_sign = 0;
00083       _CharT* __negative_sign = 0;     
00084       __try
00085     {
00086       _M_grouping_size = __mp.grouping().size();
00087       __grouping = new char[_M_grouping_size];
00088       __mp.grouping().copy(__grouping, _M_grouping_size);
00089       _M_grouping = __grouping;
00090       _M_use_grouping = (_M_grouping_size
00091                  && static_cast<signed char>(_M_grouping[0]) > 0
00092                  && (_M_grouping[0]
00093                  != __gnu_cxx::__numeric_traits<char>::__max));
00094 
00095       _M_curr_symbol_size = __mp.curr_symbol().size();
00096       __curr_symbol = new _CharT[_M_curr_symbol_size];
00097       __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size);
00098       _M_curr_symbol = __curr_symbol;
00099 
00100       _M_positive_sign_size = __mp.positive_sign().size();
00101       __positive_sign = new _CharT[_M_positive_sign_size];
00102       __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size);
00103       _M_positive_sign = __positive_sign;
00104 
00105       _M_negative_sign_size = __mp.negative_sign().size();
00106       __negative_sign = new _CharT[_M_negative_sign_size];
00107       __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size);
00108       _M_negative_sign = __negative_sign;
00109 
00110       _M_pos_format = __mp.pos_format();
00111       _M_neg_format = __mp.neg_format();
00112 
00113       const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
00114       __ct.widen(money_base::_S_atoms,
00115              money_base::_S_atoms + money_base::_S_end, _M_atoms);
00116     }
00117       __catch(...)
00118     {
00119       delete [] __grouping;
00120       delete [] __curr_symbol;
00121       delete [] __positive_sign;
00122       delete [] __negative_sign;
00123       __throw_exception_again;
00124     }
00125     }
00126 
00127 _GLIBCXX_BEGIN_NAMESPACE_LDBL
00128 
00129   template<typename _CharT, typename _InIter>
00130     template<bool _Intl>
00131       _InIter
00132       money_get<_CharT, _InIter>::
00133       _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
00134          ios_base::iostate& __err, string& __units) const
00135       {
00136     typedef char_traits<_CharT>           __traits_type;
00137     typedef typename string_type::size_type           size_type;    
00138     typedef money_base::part              part;
00139     typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
00140     
00141     const locale& __loc = __io._M_getloc();
00142     const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
00143 
00144     __use_cache<__cache_type> __uc;
00145     const __cache_type* __lc = __uc(__loc);
00146     const char_type* __lit = __lc->_M_atoms;
00147 
00148     // Deduced sign.
00149     bool __negative = false;
00150     // Sign size.
00151     size_type __sign_size = 0;
00152     // True if sign is mandatory.
00153     const bool __mandatory_sign = (__lc->_M_positive_sign_size
00154                        && __lc->_M_negative_sign_size);
00155     // String of grouping info from thousands_sep plucked from __units.
00156     string __grouping_tmp;
00157     if (__lc->_M_use_grouping)
00158       __grouping_tmp.reserve(32);
00159     // Last position before the decimal point.
00160     int __last_pos = 0;
00161     // Separator positions, then, possibly, fractional digits.
00162     int __n = 0;
00163     // If input iterator is in a valid state.
00164     bool __testvalid = true;
00165     // Flag marking when a decimal point is found.
00166     bool __testdecfound = false;
00167 
00168     // The tentative returned string is stored here.
00169     string __res;
00170     __res.reserve(32);
00171 
00172     const char_type* __lit_zero = __lit + money_base::_S_zero;
00173     const money_base::pattern __p = __lc->_M_neg_format;
00174     for (int __i = 0; __i < 4 && __testvalid; ++__i)
00175       {
00176         const part __which = static_cast<part>(__p.field[__i]);
00177         switch (__which)
00178           {
00179           case money_base::symbol:
00180         // According to 22.2.6.1.2, p2, symbol is required
00181         // if (__io.flags() & ios_base::showbase), otherwise
00182         // is optional and consumed only if other characters
00183         // are needed to complete the format.
00184         if (__io.flags() & ios_base::showbase || __sign_size > 1
00185             || __i == 0
00186             || (__i == 1 && (__mandatory_sign
00187                      || (static_cast<part>(__p.field[0])
00188                      == money_base::sign)
00189                      || (static_cast<part>(__p.field[2])
00190                      == money_base::space)))
00191             || (__i == 2 && ((static_cast<part>(__p.field[3])
00192                       == money_base::value)
00193                      || (__mandatory_sign
00194                      && (static_cast<part>(__p.field[3])
00195                          == money_base::sign)))))
00196           {
00197             const size_type __len = __lc->_M_curr_symbol_size;
00198             size_type __j = 0;
00199             for (; __beg != __end && __j < __len
00200                && *__beg == __lc->_M_curr_symbol[__j];
00201              ++__beg, ++__j);
00202             if (__j != __len
00203             && (__j || __io.flags() & ios_base::showbase))
00204               __testvalid = false;
00205           }
00206         break;
00207           case money_base::sign:
00208         // Sign might not exist, or be more than one character long.
00209         if (__lc->_M_positive_sign_size && __beg != __end
00210             && *__beg == __lc->_M_positive_sign[0])
00211           {
00212             __sign_size = __lc->_M_positive_sign_size;
00213             ++__beg;
00214           }
00215         else if (__lc->_M_negative_sign_size && __beg != __end
00216              && *__beg == __lc->_M_negative_sign[0])
00217           {
00218             __negative = true;
00219             __sign_size = __lc->_M_negative_sign_size;
00220             ++__beg;
00221           }
00222         else if (__lc->_M_positive_sign_size
00223              && !__lc->_M_negative_sign_size)
00224           // "... if no sign is detected, the result is given the sign
00225           // that corresponds to the source of the empty string"
00226           __negative = true;
00227         else if (__mandatory_sign)
00228           __testvalid = false;
00229         break;
00230           case money_base::value:
00231         // Extract digits, remove and stash away the
00232         // grouping of found thousands separators.
00233         for (; __beg != __end; ++__beg)
00234           {
00235             const char_type __c = *__beg;
00236             const char_type* __q = __traits_type::find(__lit_zero, 
00237                                    10, __c);
00238             if (__q != 0)
00239               {
00240             __res += money_base::_S_atoms[__q - __lit];
00241             ++__n;
00242               }
00243             else if (__c == __lc->_M_decimal_point 
00244                  && !__testdecfound)
00245               {
00246             if (__lc->_M_frac_digits <= 0)
00247               break;
00248 
00249             __last_pos = __n;
00250             __n = 0;
00251             __testdecfound = true;
00252               }
00253             else if (__lc->_M_use_grouping
00254                  && __c == __lc->_M_thousands_sep
00255                  && !__testdecfound)
00256               {
00257             if (__n)
00258               {
00259                 // Mark position for later analysis.
00260                 __grouping_tmp += static_cast<char>(__n);
00261                 __n = 0;
00262               }
00263             else
00264               {
00265                 __testvalid = false;
00266                 break;
00267               }
00268               }
00269             else
00270               break;
00271           }
00272         if (__res.empty())
00273           __testvalid = false;
00274         break;
00275           case money_base::space:
00276         // At least one space is required.
00277         if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
00278           ++__beg;
00279         else
00280           __testvalid = false;
00281           case money_base::none:
00282         // Only if not at the end of the pattern.
00283         if (__i != 3)
00284           for (; __beg != __end
00285              && __ctype.is(ctype_base::space, *__beg); ++__beg);
00286         break;
00287           }
00288       }
00289 
00290     // Need to get the rest of the sign characters, if they exist.
00291     if (__sign_size > 1 && __testvalid)
00292       {
00293         const char_type* __sign = __negative ? __lc->_M_negative_sign
00294                                              : __lc->_M_positive_sign;
00295         size_type __i = 1;
00296         for (; __beg != __end && __i < __sign_size
00297            && *__beg == __sign[__i]; ++__beg, ++__i);
00298         
00299         if (__i != __sign_size)
00300           __testvalid = false;
00301       }
00302 
00303     if (__testvalid)
00304       {
00305         // Strip leading zeros.
00306         if (__res.size() > 1)
00307           {
00308         const size_type __first = __res.find_first_not_of('0');
00309         const bool __only_zeros = __first == string::npos;
00310         if (__first)
00311           __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
00312           }
00313 
00314         // 22.2.6.1.2, p4
00315         if (__negative && __res[0] != '0')
00316           __res.insert(__res.begin(), '-');
00317         
00318         // Test for grouping fidelity.
00319         if (__grouping_tmp.size())
00320           {
00321         // Add the ending grouping.
00322         __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
00323                                            : __n);
00324         if (!std::__verify_grouping(__lc->_M_grouping,
00325                         __lc->_M_grouping_size,
00326                         __grouping_tmp))
00327           __err |= ios_base::failbit;
00328           }
00329         
00330         // Iff not enough digits were supplied after the decimal-point.
00331         if (__testdecfound && __n != __lc->_M_frac_digits)
00332           __testvalid = false;
00333       }
00334 
00335     // Iff valid sequence is not recognized.
00336     if (!__testvalid)
00337       __err |= ios_base::failbit;
00338     else
00339       __units.swap(__res);
00340     
00341     // Iff no more characters are available.
00342     if (__beg == __end)
00343       __err |= ios_base::eofbit;
00344     return __beg;
00345       }
00346 
00347 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
00348   template<typename _CharT, typename _InIter>
00349     _InIter
00350     money_get<_CharT, _InIter>::
00351     __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
00352          ios_base::iostate& __err, double& __units) const
00353     {
00354       string __str;
00355       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
00356                      : _M_extract<false>(__beg, __end, __io, __err, __str);
00357       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
00358       return __beg;
00359     }
00360 #endif
00361 
00362   template<typename _CharT, typename _InIter>
00363     _InIter
00364     money_get<_CharT, _InIter>::
00365     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
00366        ios_base::iostate& __err, long double& __units) const
00367     {
00368       string __str;
00369       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
00370                  : _M_extract<false>(__beg, __end, __io, __err, __str);
00371       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
00372       return __beg;
00373     }
00374 
00375   template<typename _CharT, typename _InIter>
00376     _InIter
00377     money_get<_CharT, _InIter>::
00378     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
00379        ios_base::iostate& __err, string_type& __digits) const
00380     {
00381       typedef typename string::size_type                  size_type;
00382 
00383       const locale& __loc = __io._M_getloc();
00384       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
00385 
00386       string __str;
00387       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
00388                  : _M_extract<false>(__beg, __end, __io, __err, __str);
00389       const size_type __len = __str.size();
00390       if (__len)
00391     {
00392       __digits.resize(__len);
00393       __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]);
00394     }
00395       return __beg;
00396     }
00397 
00398   template<typename _CharT, typename _OutIter>
00399     template<bool _Intl>
00400       _OutIter
00401       money_put<_CharT, _OutIter>::
00402       _M_insert(iter_type __s, ios_base& __io, char_type __fill,
00403         const string_type& __digits) const
00404       {
00405     typedef typename string_type::size_type           size_type;
00406     typedef money_base::part                          part;
00407     typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
00408       
00409     const locale& __loc = __io._M_getloc();
00410     const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
00411 
00412     __use_cache<__cache_type> __uc;
00413     const __cache_type* __lc = __uc(__loc);
00414     const char_type* __lit = __lc->_M_atoms;
00415 
00416     // Determine if negative or positive formats are to be used, and
00417     // discard leading negative_sign if it is present.
00418     const char_type* __beg = __digits.data();
00419 
00420     money_base::pattern __p;
00421     const char_type* __sign;
00422     size_type __sign_size;
00423     if (!(*__beg == __lit[money_base::_S_minus]))
00424       {
00425         __p = __lc->_M_pos_format;
00426         __sign = __lc->_M_positive_sign;
00427         __sign_size = __lc->_M_positive_sign_size;
00428       }
00429     else
00430       {
00431         __p = __lc->_M_neg_format;
00432         __sign = __lc->_M_negative_sign;
00433         __sign_size = __lc->_M_negative_sign_size;
00434         if (__digits.size())
00435           ++__beg;
00436       }
00437        
00438     // Look for valid numbers in the ctype facet within input digits.
00439     size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
00440                        __beg + __digits.size()) - __beg;
00441     if (__len)
00442       {
00443         // Assume valid input, and attempt to format.
00444         // Break down input numbers into base components, as follows:
00445         //   final_value = grouped units + (decimal point) + (digits)
00446         string_type __value;
00447         __value.reserve(2 * __len);
00448 
00449         // Add thousands separators to non-decimal digits, per
00450         // grouping rules.
00451         long __paddec = __len - __lc->_M_frac_digits;
00452         if (__paddec > 0)
00453           {
00454         if (__lc->_M_frac_digits < 0)
00455           __paddec = __len;
00456         if (__lc->_M_grouping_size)
00457           {
00458             __value.assign(2 * __paddec, char_type());
00459             _CharT* __vend = 
00460               std::__add_grouping(&__value[0], __lc->_M_thousands_sep,
00461                       __lc->_M_grouping,
00462                       __lc->_M_grouping_size,
00463                       __beg, __beg + __paddec);
00464             __value.erase(__vend - &__value[0]);
00465           }
00466         else
00467           __value.assign(__beg, __paddec);
00468           }
00469 
00470         // Deal with decimal point, decimal digits.
00471         if (__lc->_M_frac_digits > 0)
00472           {
00473         __value += __lc->_M_decimal_point;
00474         if (__paddec >= 0)
00475           __value.append(__beg + __paddec, __lc->_M_frac_digits);
00476         else
00477           {
00478             // Have to pad zeros in the decimal position.
00479             __value.append(-__paddec, __lit[money_base::_S_zero]);
00480             __value.append(__beg, __len);
00481           }
00482           }
00483   
00484         // Calculate length of resulting string.
00485         const ios_base::fmtflags __f = __io.flags() 
00486                                        & ios_base::adjustfield;
00487         __len = __value.size() + __sign_size;
00488         __len += ((__io.flags() & ios_base::showbase)
00489               ? __lc->_M_curr_symbol_size : 0);
00490 
00491         string_type __res;
00492         __res.reserve(2 * __len);
00493         
00494         const size_type __width = static_cast<size_type>(__io.width());  
00495         const bool __testipad = (__f == ios_base::internal
00496                      && __len < __width);
00497         // Fit formatted digits into the required pattern.
00498         for (int __i = 0; __i < 4; ++__i)
00499           {
00500         const part __which = static_cast<part>(__p.field[__i]);
00501         switch (__which)
00502           {
00503           case money_base::symbol:
00504             if (__io.flags() & ios_base::showbase)
00505               __res.append(__lc->_M_curr_symbol,
00506                    __lc->_M_curr_symbol_size);
00507             break;
00508           case money_base::sign:
00509             // Sign might not exist, or be more than one
00510             // character long. In that case, add in the rest
00511             // below.
00512             if (__sign_size)
00513               __res += __sign[0];
00514             break;
00515           case money_base::value:
00516             __res += __value;
00517             break;
00518           case money_base::space:
00519             // At least one space is required, but if internal
00520             // formatting is required, an arbitrary number of
00521             // fill spaces will be necessary.
00522             if (__testipad)
00523               __res.append(__width - __len, __fill);
00524             else
00525               __res += __fill;
00526             break;
00527           case money_base::none:
00528             if (__testipad)
00529               __res.append(__width - __len, __fill);
00530             break;
00531           }
00532           }
00533         
00534         // Special case of multi-part sign parts.
00535         if (__sign_size > 1)
00536           __res.append(__sign + 1, __sign_size - 1);
00537         
00538         // Pad, if still necessary.
00539         __len = __res.size();
00540         if (__width > __len)
00541           {
00542         if (__f == ios_base::left)
00543           // After.
00544           __res.append(__width - __len, __fill);
00545         else
00546           // Before.
00547           __res.insert(0, __width - __len, __fill);
00548         __len = __width;
00549           }
00550         
00551         // Write resulting, fully-formatted string to output iterator.
00552         __s = std::__write(__s, __res.data(), __len);
00553       }
00554     __io.width(0);
00555     return __s;    
00556       }
00557 
00558 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
00559   template<typename _CharT, typename _OutIter>
00560     _OutIter
00561     money_put<_CharT, _OutIter>::
00562     __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
00563          double __units) const
00564     { return this->do_put(__s, __intl, __io, __fill, (long double) __units); }
00565 #endif
00566 
00567   template<typename _CharT, typename _OutIter>
00568     _OutIter
00569     money_put<_CharT, _OutIter>::
00570     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
00571        long double __units) const
00572     {
00573       const locale __loc = __io.getloc();
00574       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
00575 #ifdef _GLIBCXX_USE_C99
00576       // First try a buffer perhaps big enough.
00577       int __cs_size = 64;
00578       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
00579       // _GLIBCXX_RESOLVE_LIB_DEFECTS
00580       // 328. Bad sprintf format modifier in money_put<>::do_put()
00581       int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
00582                     "%.*Lf", 0, __units);
00583       // If the buffer was not large enough, try again with the correct size.
00584       if (__len >= __cs_size)
00585     {
00586       __cs_size = __len + 1;
00587       __cs = static_cast<char*>(__builtin_alloca(__cs_size));
00588       __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
00589                     "%.*Lf", 0, __units);
00590     }
00591 #else
00592       // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
00593       const int __cs_size =
00594     __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
00595       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
00596       int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf", 
00597                     0, __units);
00598 #endif
00599       string_type __digits(__len, char_type());
00600       __ctype.widen(__cs, __cs + __len, &__digits[0]);
00601       return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
00602                 : _M_insert<false>(__s, __io, __fill, __digits);
00603     }
00604 
00605   template<typename _CharT, typename _OutIter>
00606     _OutIter
00607     money_put<_CharT, _OutIter>::
00608     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
00609        const string_type& __digits) const
00610     { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
00611                 : _M_insert<false>(__s, __io, __fill, __digits); }
00612 
00613 _GLIBCXX_END_NAMESPACE_LDBL
00614 
00615   // NB: Not especially useful. Without an ios_base object or some
00616   // kind of locale reference, we are left clawing at the air where
00617   // the side of the mountain used to be...
00618   template<typename _CharT, typename _InIter>
00619     time_base::dateorder
00620     time_get<_CharT, _InIter>::do_date_order() const
00621     { return time_base::no_order; }
00622 
00623   // Expand a strftime format string and parse it.  E.g., do_get_date() may
00624   // pass %m/%d/%Y => extracted characters.
00625   template<typename _CharT, typename _InIter>
00626     _InIter
00627     time_get<_CharT, _InIter>::
00628     _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
00629               ios_base::iostate& __err, tm* __tm,
00630               const _CharT* __format) const
00631     {
00632       const locale& __loc = __io._M_getloc();
00633       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
00634       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
00635       const size_t __len = char_traits<_CharT>::length(__format);
00636 
00637       ios_base::iostate __tmperr = ios_base::goodbit;
00638       size_t __i = 0;
00639       for (; __beg != __end && __i < __len && !__tmperr; ++__i)
00640     {
00641       if (__ctype.narrow(__format[__i], 0) == '%')
00642         {
00643           // Verify valid formatting code, attempt to extract.
00644           char __c = __ctype.narrow(__format[++__i], 0);
00645           int __mem = 0;
00646           if (__c == 'E' || __c == 'O')
00647         __c = __ctype.narrow(__format[++__i], 0);
00648           switch (__c)
00649         {
00650           const char* __cs;
00651           _CharT __wcs[10];
00652         case 'a':
00653           // Abbreviated weekday name [tm_wday]
00654           const char_type*  __days1[7];
00655           __tp._M_days_abbreviated(__days1);
00656           __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
00657                       7, __io, __tmperr);
00658           break;
00659         case 'A':
00660           // Weekday name [tm_wday].
00661           const char_type*  __days2[7];
00662           __tp._M_days(__days2);
00663           __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
00664                       7, __io, __tmperr);
00665           break;
00666         case 'h':
00667         case 'b':
00668           // Abbreviated month name [tm_mon]
00669           const char_type*  __months1[12];
00670           __tp._M_months_abbreviated(__months1);
00671           __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
00672                       __months1, 12, __io, __tmperr);
00673           break;
00674         case 'B':
00675           // Month name [tm_mon].
00676           const char_type*  __months2[12];
00677           __tp._M_months(__months2);
00678           __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
00679                       __months2, 12, __io, __tmperr);
00680           break;
00681         case 'c':
00682           // Default time and date representation.
00683           const char_type*  __dt[2];
00684           __tp._M_date_time_formats(__dt);
00685           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
00686                         __tm, __dt[0]);
00687           break;
00688         case 'd':
00689           // Day [01, 31]. [tm_mday]
00690           __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
00691                      __io, __tmperr);
00692           break;
00693         case 'e':
00694           // Day [1, 31], with single digits preceded by
00695           // space. [tm_mday]
00696           if (__ctype.is(ctype_base::space, *__beg))
00697             __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
00698                        1, __io, __tmperr);
00699           else
00700             __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
00701                        2, __io, __tmperr);
00702           break;
00703         case 'D':
00704           // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
00705           __cs = "%m/%d/%y";
00706           __ctype.widen(__cs, __cs + 9, __wcs);
00707           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
00708                         __tm, __wcs);
00709           break;
00710         case 'H':
00711           // Hour [00, 23]. [tm_hour]
00712           __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
00713                      __io, __tmperr);
00714           break;
00715         case 'I':
00716           // Hour [01, 12]. [tm_hour]
00717           __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
00718                      __io, __tmperr);
00719           break;
00720         case 'm':
00721           // Month [01, 12]. [tm_mon]
00722           __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 
00723                      __io, __tmperr);
00724           if (!__tmperr)
00725             __tm->tm_mon = __mem - 1;
00726           break;
00727         case 'M':
00728           // Minute [00, 59]. [tm_min]
00729           __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
00730                      __io, __tmperr);
00731           break;
00732         case 'n':
00733           if (__ctype.narrow(*__beg, 0) == '\n')
00734             ++__beg;
00735           else
00736             __tmperr |= ios_base::failbit;
00737           break;
00738         case 'R':
00739           // Equivalent to (%H:%M).
00740           __cs = "%H:%M";
00741           __ctype.widen(__cs, __cs + 6, __wcs);
00742           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
00743                         __tm, __wcs);
00744           break;
00745         case 'S':
00746           // Seconds. [tm_sec]
00747           // [00, 60] in C99 (one leap-second), [00, 61] in C89.
00748 #ifdef _GLIBCXX_USE_C99
00749           __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2,
00750 #else
00751           __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
00752 #endif
00753                      __io, __tmperr);
00754           break;
00755         case 't':
00756           if (__ctype.narrow(*__beg, 0) == '\t')
00757             ++__beg;
00758           else
00759             __tmperr |= ios_base::failbit;
00760           break;
00761         case 'T':
00762           // Equivalent to (%H:%M:%S).
00763           __cs = "%H:%M:%S";
00764           __ctype.widen(__cs, __cs + 9, __wcs);
00765           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
00766                         __tm, __wcs);
00767           break;
00768         case 'x':
00769           // Locale's date.
00770           const char_type*  __dates[2];
00771           __tp._M_date_formats(__dates);
00772           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
00773                         __tm, __dates[0]);
00774           break;
00775         case 'X':
00776           // Locale's time.
00777           const char_type*  __times[2];
00778           __tp._M_time_formats(__times);
00779           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
00780                         __tm, __times[0]);
00781           break;
00782         case 'y':
00783         case 'C': // C99
00784           // Two digit year.
00785         case 'Y':
00786           // Year [1900).
00787           // NB: We parse either two digits, implicitly years since
00788           // 1900, or 4 digits, full year.  In both cases we can 
00789           // reconstruct [tm_year].  See also libstdc++/26701.
00790           __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
00791                      __io, __tmperr);
00792           if (!__tmperr)
00793             __tm->tm_year = __mem < 0 ? __mem + 100 : __mem - 1900;
00794           break;
00795         case 'Z':
00796           // Timezone info.
00797           if (__ctype.is(ctype_base::upper, *__beg))
00798             {
00799               int __tmp;
00800               __beg = _M_extract_name(__beg, __end, __tmp,
00801                        __timepunct_cache<_CharT>::_S_timezones,
00802                           14, __io, __tmperr);
00803 
00804               // GMT requires special effort.
00805               if (__beg != __end && !__tmperr && __tmp == 0
00806               && (*__beg == __ctype.widen('-')
00807                   || *__beg == __ctype.widen('+')))
00808             {
00809               __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
00810                          __io, __tmperr);
00811               __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
00812                          __io, __tmperr);
00813             }
00814             }
00815           else
00816             __tmperr |= ios_base::failbit;
00817           break;
00818         default:
00819           // Not recognized.
00820           __tmperr |= ios_base::failbit;
00821         }
00822         }
00823       else
00824         {
00825           // Verify format and input match, extract and discard.
00826           if (__format[__i] == *__beg)
00827         ++__beg;
00828           else
00829         __tmperr |= ios_base::failbit;
00830         }
00831     }
00832 
00833       if (__tmperr || __i != __len)
00834     __err |= ios_base::failbit;
00835   
00836       return __beg;
00837     }
00838 
00839   template<typename _CharT, typename _InIter>
00840     _InIter
00841     time_get<_CharT, _InIter>::
00842     _M_extract_num(iter_type __beg, iter_type __end, int& __member,
00843            int __min, int __max, size_t __len,
00844            ios_base& __io, ios_base::iostate& __err) const
00845     {
00846       const locale& __loc = __io._M_getloc();
00847       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
00848 
00849       // As-is works for __len = 1, 2, 4, the values actually used.
00850       int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
00851 
00852       ++__min;
00853       size_t __i = 0;
00854       int __value = 0;
00855       for (; __beg != __end && __i < __len; ++__beg, ++__i)
00856     {
00857       const char __c = __ctype.narrow(*__beg, '*');
00858       if (__c >= '0' && __c <= '9')
00859         {
00860           __value = __value * 10 + (__c - '0');
00861           const int __valuec = __value * __mult;
00862           if (__valuec > __max || __valuec + __mult < __min)
00863         break;
00864           __mult /= 10;
00865         }
00866       else
00867         break;
00868     }
00869       if (__i == __len)
00870     __member = __value;
00871       // Special encoding for do_get_year, 'y', and 'Y' above.
00872       else if (__len == 4 && __i == 2)
00873     __member = __value - 100;
00874       else
00875     __err |= ios_base::failbit;
00876 
00877       return __beg;
00878     }
00879 
00880   // Assumptions:
00881   // All elements in __names are unique.
00882   template<typename _CharT, typename _InIter>
00883     _InIter
00884     time_get<_CharT, _InIter>::
00885     _M_extract_name(iter_type __beg, iter_type __end, int& __member,
00886             const _CharT** __names, size_t __indexlen,
00887             ios_base& __io, ios_base::iostate& __err) const
00888     {
00889       typedef char_traits<_CharT>       __traits_type;
00890       const locale& __loc = __io._M_getloc();
00891       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
00892 
00893       int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
00894                               * __indexlen));
00895       size_t __nmatches = 0;
00896       size_t __pos = 0;
00897       bool __testvalid = true;
00898       const char_type* __name;
00899 
00900       // Look for initial matches.
00901       // NB: Some of the locale data is in the form of all lowercase
00902       // names, and some is in the form of initially-capitalized
00903       // names. Look for both.
00904       if (__beg != __end)
00905     {
00906       const char_type __c = *__beg;
00907       for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
00908         if (__c == __names[__i1][0]
00909         || __c == __ctype.toupper(__names[__i1][0]))
00910           __matches[__nmatches++] = __i1;
00911     }
00912 
00913       while (__nmatches > 1)
00914     {
00915       // Find smallest matching string.
00916       size_t __minlen = __traits_type::length(__names[__matches[0]]);
00917       for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
00918         __minlen = std::min(__minlen,
00919                   __traits_type::length(__names[__matches[__i2]]));
00920       ++__beg, ++__pos;
00921       if (__pos < __minlen && __beg != __end)
00922         for (size_t __i3 = 0; __i3 < __nmatches;)
00923           {
00924         __name = __names[__matches[__i3]];
00925         if (!(__name[__pos] == *__beg))
00926           __matches[__i3] = __matches[--__nmatches];
00927         else
00928           ++__i3;
00929           }
00930       else
00931         break;
00932     }
00933 
00934       if (__nmatches == 1)
00935     {
00936       // Make sure found name is completely extracted.
00937       ++__beg, ++__pos;
00938       __name = __names[__matches[0]];
00939       const size_t __len = __traits_type::length(__name);
00940       while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
00941         ++__beg, ++__pos;
00942 
00943       if (__len == __pos)
00944         __member = __matches[0];
00945       else
00946         __testvalid = false;
00947     }
00948       else
00949     __testvalid = false;
00950       if (!__testvalid)
00951     __err |= ios_base::failbit;
00952 
00953       return __beg;
00954     }
00955 
00956   template<typename _CharT, typename _InIter>
00957     _InIter
00958     time_get<_CharT, _InIter>::
00959     _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
00960                  const _CharT** __names, size_t __indexlen,
00961                  ios_base& __io, ios_base::iostate& __err) const
00962     {
00963       typedef char_traits<_CharT>       __traits_type;
00964       const locale& __loc = __io._M_getloc();
00965       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
00966 
00967       int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int)
00968                               * __indexlen));
00969       size_t __nmatches = 0;
00970       size_t* __matches_lengths = 0;
00971       size_t __pos = 0;
00972 
00973       if (__beg != __end)
00974     {
00975       const char_type __c = *__beg;
00976       for (size_t __i = 0; __i < 2 * __indexlen; ++__i)
00977         if (__c == __names[__i][0]
00978         || __c == __ctype.toupper(__names[__i][0]))
00979           __matches[__nmatches++] = __i;
00980     }
00981 
00982       if (__nmatches)
00983     {
00984       ++__beg, ++__pos;
00985 
00986       __matches_lengths
00987         = static_cast<size_t*>(__builtin_alloca(sizeof(size_t)
00988                             * __nmatches));
00989       for (size_t __i = 0; __i < __nmatches; ++__i)
00990         __matches_lengths[__i]
00991           = __traits_type::length(__names[__matches[__i]]);
00992     }
00993 
00994       for (; __beg != __end; ++__beg, ++__pos)
00995     {
00996       size_t __nskipped = 0;
00997       const char_type __c = *__beg;
00998       for (size_t __i = 0; __i < __nmatches;)
00999         {
01000           const char_type* __name = __names[__matches[__i]];
01001           if (__pos >= __matches_lengths[__i])
01002         ++__nskipped, ++__i;
01003           else if (!(__name[__pos] == __c))
01004         {
01005           --__nmatches;
01006           __matches[__i] = __matches[__nmatches];
01007           __matches_lengths[__i] = __matches_lengths[__nmatches];
01008         }
01009           else
01010         ++__i;
01011         }
01012       if (__nskipped == __nmatches)
01013         break;
01014     }
01015 
01016       if ((__nmatches == 1 && __matches_lengths[0] == __pos)
01017       || (__nmatches == 2 && (__matches_lengths[0] == __pos
01018                   || __matches_lengths[1] == __pos)))
01019     __member = (__matches[0] >= __indexlen
01020             ? __matches[0] - __indexlen : __matches[0]);
01021       else
01022     __err |= ios_base::failbit;
01023 
01024       return __beg;
01025     }
01026 
01027   template<typename _CharT, typename _InIter>
01028     _InIter
01029     time_get<_CharT, _InIter>::
01030     do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
01031         ios_base::iostate& __err, tm* __tm) const
01032     {
01033       const locale& __loc = __io._M_getloc();
01034       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
01035       const char_type*  __times[2];
01036       __tp._M_time_formats(__times);
01037       __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01038                     __tm, __times[0]);
01039       if (__beg == __end)
01040     __err |= ios_base::eofbit;
01041       return __beg;
01042     }
01043 
01044   template<typename _CharT, typename _InIter>
01045     _InIter
01046     time_get<_CharT, _InIter>::
01047     do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
01048         ios_base::iostate& __err, tm* __tm) const
01049     {
01050       const locale& __loc = __io._M_getloc();
01051       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
01052       const char_type*  __dates[2];
01053       __tp._M_date_formats(__dates);
01054       __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01055                     __tm, __dates[0]);
01056       if (__beg == __end)
01057     __err |= ios_base::eofbit;
01058       return __beg;
01059     }
01060 
01061   template<typename _CharT, typename _InIter>
01062     _InIter
01063     time_get<_CharT, _InIter>::
01064     do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
01065            ios_base::iostate& __err, tm* __tm) const
01066     {
01067       typedef char_traits<_CharT>       __traits_type;
01068       const locale& __loc = __io._M_getloc();
01069       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
01070       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01071       const char_type* __days[14];
01072       __tp._M_days_abbreviated(__days);
01073       __tp._M_days(__days + 7);
01074       int __tmpwday;
01075       ios_base::iostate __tmperr = ios_base::goodbit;
01076 
01077       __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7,
01078                        __io, __tmperr);
01079       if (!__tmperr)
01080     __tm->tm_wday = __tmpwday;
01081       else
01082     __err |= ios_base::failbit;
01083 
01084       if (__beg == __end)
01085     __err |= ios_base::eofbit;
01086       return __beg;
01087      }
01088 
01089   template<typename _CharT, typename _InIter>
01090     _InIter
01091     time_get<_CharT, _InIter>::
01092     do_get_monthname(iter_type __beg, iter_type __end,
01093                      ios_base& __io, ios_base::iostate& __err, tm* __tm) const
01094     {
01095       typedef char_traits<_CharT>       __traits_type;
01096       const locale& __loc = __io._M_getloc();
01097       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
01098       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01099       const char_type*  __months[24];
01100       __tp._M_months_abbreviated(__months);
01101       __tp._M_months(__months + 12);
01102       int __tmpmon;
01103       ios_base::iostate __tmperr = ios_base::goodbit;
01104 
01105       __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12,
01106                        __io, __tmperr);
01107       if (!__tmperr)
01108     __tm->tm_mon = __tmpmon;
01109       else
01110     __err |= ios_base::failbit;
01111 
01112       if (__beg == __end)
01113     __err |= ios_base::eofbit;
01114       return __beg;
01115     }
01116 
01117   template<typename _CharT, typename _InIter>
01118     _InIter
01119     time_get<_CharT, _InIter>::
01120     do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
01121         ios_base::iostate& __err, tm* __tm) const
01122     {
01123       const locale& __loc = __io._M_getloc();
01124       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01125       int __tmpyear;
01126       ios_base::iostate __tmperr = ios_base::goodbit;
01127 
01128       __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 9999, 4,
01129                  __io, __tmperr);
01130       if (!__tmperr)
01131     __tm->tm_year = __tmpyear < 0 ? __tmpyear + 100 : __tmpyear - 1900;
01132       else
01133     __err |= ios_base::failbit;
01134 
01135       if (__beg == __end)
01136     __err |= ios_base::eofbit;
01137       return __beg;
01138     }
01139 
01140   template<typename _CharT, typename _OutIter>
01141     _OutIter
01142     time_put<_CharT, _OutIter>::
01143     put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
01144     const _CharT* __beg, const _CharT* __end) const
01145     {
01146       const locale& __loc = __io._M_getloc();
01147       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
01148       for (; __beg != __end; ++__beg)
01149     if (__ctype.narrow(*__beg, 0) != '%')
01150       {
01151         *__s = *__beg;
01152         ++__s;
01153       }
01154     else if (++__beg != __end)
01155       {
01156         char __format;
01157         char __mod = 0;
01158         const char __c = __ctype.narrow(*__beg, 0);
01159         if (__c != 'E' && __c != 'O')
01160           __format = __c;
01161         else if (++__beg != __end)
01162           {
01163         __mod = __c;
01164         __format = __ctype.narrow(*__beg, 0);
01165           }
01166         else
01167           break;
01168         __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
01169       }
01170     else
01171       break;
01172       return __s;
01173     }
01174 
01175   template<typename _CharT, typename _OutIter>
01176     _OutIter
01177     time_put<_CharT, _OutIter>::
01178     do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
01179        char __format, char __mod) const
01180     {
01181       const locale& __loc = __io._M_getloc();
01182       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
01183       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
01184 
01185       // NB: This size is arbitrary. Should this be a data member,
01186       // initialized at construction?
01187       const size_t __maxlen = 128;
01188       char_type __res[__maxlen];
01189 
01190       // NB: In IEE 1003.1-200x, and perhaps other locale models, it
01191       // is possible that the format character will be longer than one
01192       // character. Possibilities include 'E' or 'O' followed by a
01193       // format character: if __mod is not the default argument, assume
01194       // it's a valid modifier.
01195       char_type __fmt[4];
01196       __fmt[0] = __ctype.widen('%');
01197       if (!__mod)
01198     {
01199       __fmt[1] = __format;
01200       __fmt[2] = char_type();
01201     }
01202       else
01203     {
01204       __fmt[1] = __mod;
01205       __fmt[2] = __format;
01206       __fmt[3] = char_type();
01207     }
01208 
01209       __tp._M_put(__res, __maxlen, __fmt, __tm);
01210 
01211       // Write resulting, fully-formatted string to output iterator.
01212       return std::__write(__s, __res, char_traits<char_type>::length(__res));
01213     }
01214 
01215 
01216   // Inhibit implicit instantiations for required instantiations,
01217   // which are defined via explicit instantiations elsewhere.
01218 #if _GLIBCXX_EXTERN_TEMPLATE
01219   extern template class moneypunct<char, false>;
01220   extern template class moneypunct<char, true>;
01221   extern template class moneypunct_byname<char, false>;
01222   extern template class moneypunct_byname<char, true>;
01223   extern template class _GLIBCXX_NAMESPACE_LDBL money_get<char>;
01224   extern template class _GLIBCXX_NAMESPACE_LDBL money_put<char>;
01225   extern template class __timepunct<char>;
01226   extern template class time_put<char>;
01227   extern template class time_put_byname<char>;
01228   extern template class time_get<char>;
01229   extern template class time_get_byname<char>;
01230   extern template class messages<char>;
01231   extern template class messages_byname<char>;
01232 
01233   extern template
01234     const moneypunct<char, true>&
01235     use_facet<moneypunct<char, true> >(const locale&);
01236 
01237   extern template
01238     const moneypunct<char, false>&
01239     use_facet<moneypunct<char, false> >(const locale&);
01240 
01241   extern template
01242     const money_put<char>&
01243     use_facet<money_put<char> >(const locale&);
01244 
01245   extern template
01246     const money_get<char>&
01247     use_facet<money_get<char> >(const locale&);
01248 
01249   extern template
01250     const __timepunct<char>&
01251     use_facet<__timepunct<char> >(const locale&);
01252 
01253   extern template
01254     const time_put<char>&
01255     use_facet<time_put<char> >(const locale&);
01256 
01257   extern template
01258     const time_get<char>&
01259     use_facet<time_get<char> >(const locale&);
01260 
01261   extern template
01262     const messages<char>&
01263     use_facet<messages<char> >(const locale&);
01264 
01265   extern template
01266     bool
01267     has_facet<moneypunct<char> >(const locale&);
01268 
01269   extern template
01270     bool
01271     has_facet<money_put<char> >(const locale&);
01272 
01273   extern template
01274     bool
01275     has_facet<money_get<char> >(const locale&);
01276 
01277   extern template
01278     bool
01279     has_facet<__timepunct<char> >(const locale&);
01280 
01281   extern template
01282     bool
01283     has_facet<time_put<char> >(const locale&);
01284 
01285   extern template
01286     bool
01287     has_facet<time_get<char> >(const locale&);
01288 
01289   extern template
01290     bool
01291     has_facet<messages<char> >(const locale&);
01292 
01293 #ifdef _GLIBCXX_USE_WCHAR_T
01294   extern template class moneypunct<wchar_t, false>;
01295   extern template class moneypunct<wchar_t, true>;
01296   extern template class moneypunct_byname<wchar_t, false>;
01297   extern template class moneypunct_byname<wchar_t, true>;
01298   extern template class _GLIBCXX_NAMESPACE_LDBL money_get<wchar_t>;
01299   extern template class _GLIBCXX_NAMESPACE_LDBL money_put<wchar_t>;
01300   extern template class __timepunct<wchar_t>;
01301   extern template class time_put<wchar_t>;
01302   extern template class time_put_byname<wchar_t>;
01303   extern template class time_get<wchar_t>;
01304   extern template class time_get_byname<wchar_t>;
01305   extern template class messages<wchar_t>;
01306   extern template class messages_byname<wchar_t>;
01307 
01308   extern template
01309     const moneypunct<wchar_t, true>&
01310     use_facet<moneypunct<wchar_t, true> >(const locale&);
01311 
01312   extern template
01313     const moneypunct<wchar_t, false>&
01314     use_facet<moneypunct<wchar_t, false> >(const locale&);
01315 
01316   extern template
01317     const money_put<wchar_t>&
01318     use_facet<money_put<wchar_t> >(const locale&);
01319 
01320   extern template
01321     const money_get<wchar_t>&
01322     use_facet<money_get<wchar_t> >(const locale&);
01323 
01324   extern template
01325     const __timepunct<wchar_t>&
01326     use_facet<__timepunct<wchar_t> >(const locale&);
01327 
01328   extern template
01329     const time_put<wchar_t>&
01330     use_facet<time_put<wchar_t> >(const locale&);
01331 
01332   extern template
01333     const time_get<wchar_t>&
01334     use_facet<time_get<wchar_t> >(const locale&);
01335 
01336   extern template
01337     const messages<wchar_t>&
01338     use_facet<messages<wchar_t> >(const locale&);
01339 
01340   extern template
01341     bool
01342     has_facet<moneypunct<wchar_t> >(const locale&);
01343 
01344   extern template
01345     bool
01346     has_facet<money_put<wchar_t> >(const locale&);
01347 
01348   extern template
01349     bool
01350     has_facet<money_get<wchar_t> >(const locale&);
01351 
01352   extern template
01353     bool
01354     has_facet<__timepunct<wchar_t> >(const locale&);
01355 
01356   extern template
01357     bool
01358     has_facet<time_put<wchar_t> >(const locale&);
01359 
01360   extern template
01361     bool
01362     has_facet<time_get<wchar_t> >(const locale&);
01363 
01364   extern template
01365     bool
01366     has_facet<messages<wchar_t> >(const locale&);
01367 #endif
01368 #endif
01369 
01370 _GLIBCXX_END_NAMESPACE_VERSION
01371 } // namespace std
01372 
01373 #endif