locale_facets.tcc

00001 // Locale support -*- C++ -*-
00002 
00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
00004 // Free Software Foundation, Inc.
00005 //
00006 // This file is part of the GNU ISO C++ Library.  This library is free
00007 // software; you can redistribute it and/or modify it under the
00008 // terms of the GNU General Public License as published by the
00009 // Free Software Foundation; either version 2, or (at your option)
00010 // any later version.
00011 
00012 // This library is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 
00017 // You should have received a copy of the GNU General Public License along
00018 // with this library; see the file COPYING.  If not, write to the Free
00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00020 // USA.
00021 
00022 // As a special exception, you may use this file as part of a free software
00023 // library without restriction.  Specifically, if other files instantiate
00024 // templates or use macros or inline functions from this file, or you compile
00025 // this file and link it with other files to produce an executable, this
00026 // file does not by itself cause the resulting executable to be covered by
00027 // the GNU General Public License.  This exception does not however
00028 // invalidate any other reasons why the executable file might be covered by
00029 // the GNU General Public License.
00030 
00031 // Warning: this file is not meant for user inclusion. Use <locale>.
00032 
00033 #ifndef _CPP_BITS_LOCFACETS_TCC
00034 #define _CPP_BITS_LOCFACETS_TCC 1
00035 
00036 #pragma GCC system_header
00037 
00038 #include <cerrno>
00039 #include <clocale>          // For localeconv
00040 #include <cstdlib>          // For strof, strtold
00041 #include <cmath>            // For ceil
00042 #include <cctype>           // For isspace
00043 #include <limits>           // For numeric_limits
00044 #include <typeinfo>         // For bad_cast.
00045 #include <bits/streambuf_iterator.h>
00046 
00047 namespace std
00048 {
00049   template<typename _Facet>
00050     locale
00051     locale::combine(const locale& __other) const
00052     {
00053       _Impl* __tmp = new _Impl(*_M_impl, 1);
00054       try
00055     {
00056       __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
00057     }
00058       catch(...)
00059     {
00060       __tmp->_M_remove_reference();
00061       __throw_exception_again;
00062     }
00063       return locale(__tmp);
00064     }
00065 
00066   template<typename _CharT, typename _Traits, typename _Alloc>
00067     bool
00068     locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
00069                        const basic_string<_CharT, _Traits, _Alloc>& __s2) const
00070     {
00071       typedef std::collate<_CharT> __collate_type;
00072       const __collate_type& __collate = use_facet<__collate_type>(*this);
00073       return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
00074                 __s2.data(), __s2.data() + __s2.length()) < 0);
00075     }
00076 
00077   template<typename _Facet>
00078     const _Facet&
00079     use_facet(const locale& __loc)
00080     {
00081       size_t __i = _Facet::id._M_id();
00082       locale::facet** __facets = __loc._M_impl->_M_facets;
00083       if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i]))
00084         __throw_bad_cast();
00085       return static_cast<const _Facet&>(*__facets[__i]);
00086     }
00087 
00088   template<typename _Facet>
00089     bool
00090     has_facet(const locale& __loc) throw()
00091     {
00092       size_t __i = _Facet::id._M_id();
00093       locale::facet** __facets = __loc._M_impl->_M_facets;
00094       return (__i < __loc._M_impl->_M_facets_size && __facets[__i]);
00095     }
00096 
00097   // Routine to access a cache for the locale.  If the cache didn't
00098   // exist before, it gets constructed on the fly.
00099   template<typename _Facet>
00100     inline const __locale_cache<_Facet>&
00101     __use_cache(const locale& __loc)
00102     {
00103       size_t __i = _Facet::id._M_id();
00104       if (__builtin_expect(__i >= __loc._M_impl->_M_facets_size,false))
00105     __throw_bad_cast();
00106       __locale_cache_base* __cache = __loc._M_impl->_M_get_cache(__i);
00107       if (__builtin_expect(!__cache, false))
00108     {
00109       __cache = new __locale_cache<_Facet>(__loc);
00110       __loc._M_impl->_M_install_cache(__cache, __i);
00111     }
00112       return static_cast<const __locale_cache<_Facet>&>(*__cache);
00113     }
00114 
00115   // Stage 1: Determine a conversion specifier.
00116   template<typename _CharT, typename _InIter>
00117     _InIter
00118     num_get<_CharT, _InIter>::
00119     _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
00120              ios_base::iostate& __err, string& __xtrc) const
00121     {
00122       typedef char_traits<_CharT>       __traits_type;
00123       const locale __loc = __io.getloc();
00124       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
00125       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
00126 
00127       // First check for sign.
00128       const char_type __plus = __ctype.widen('+');
00129       const char_type __minus = __ctype.widen('-');
00130       int __pos = 0;
00131       char_type  __c = *__beg;
00132       if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus))
00133       && __beg != __end)
00134     {
00135       __xtrc += __ctype.narrow(__c, char());
00136       ++__pos;
00137       __c = *(++__beg);
00138     }
00139 
00140       // Next, strip leading zeros.
00141       const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]);
00142       bool __found_zero = false;
00143       while (__traits_type::eq(__c, __zero) && __beg != __end)
00144     {
00145       __c = *(++__beg);
00146       __found_zero = true;
00147     }
00148       if (__found_zero)
00149     {
00150       __xtrc += _S_atoms_in[_M_zero];
00151       ++__pos;
00152     }
00153 
00154       // Only need acceptable digits for floating point numbers.
00155       const size_t __len = _M_E - _M_zero + 1;
00156       char_type  __watoms[__len];
00157       __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms);
00158       bool __found_dec = false;
00159       bool __found_sci = false;
00160       const char_type __dec = __np.decimal_point();
00161 
00162       string __found_grouping;
00163       const string __grouping = __np.grouping();
00164       const bool __check_grouping = __grouping.size();
00165       if (__check_grouping)
00166     __found_grouping.reserve(32);
00167       int __sep_pos = 0;
00168       const char_type __sep = __np.thousands_sep();
00169 
00170       while (__beg != __end)
00171         {
00172       // Only look in digits.
00173           const char_type* __p = __traits_type::find(__watoms, 10,  __c);
00174           if (__p)
00175         {
00176           // Try first for acceptable digit; record it if found.
00177           ++__pos;
00178           __xtrc += _S_atoms_in[__p - __watoms];
00179           ++__sep_pos;
00180           __c = *(++__beg);
00181         }
00182           else if (__traits_type::eq(__c, __sep) 
00183            && __check_grouping && !__found_dec)
00184         {
00185               // NB: Thousands separator at the beginning of a string
00186               // is a no-no, as is two consecutive thousands separators.
00187               if (__sep_pos)
00188                 {
00189                   __found_grouping += static_cast<char>(__sep_pos);
00190                   __sep_pos = 0;
00191           __c = *(++__beg);
00192                 }
00193               else
00194         {
00195           __err |= ios_base::failbit;
00196           break;
00197         }
00198             }
00199       else if (__traits_type::eq(__c, __dec) && !__found_dec)
00200         {
00201           // According to the standard, if no grouping chars are seen,
00202           // no grouping check is applied. Therefore __found_grouping
00203           // must be adjusted only if __dec comes after some __sep.
00204           if (__found_grouping.size())
00205         __found_grouping += static_cast<char>(__sep_pos);
00206           ++__pos;
00207           __xtrc += '.';
00208           __c = *(++__beg);
00209           __found_dec = true;
00210         }
00211       else if ((__traits_type::eq(__c, __watoms[_M_e]) 
00212             || __traits_type::eq(__c, __watoms[_M_E])) 
00213            && !__found_sci && __pos)
00214         {
00215           // Scientific notation.
00216           ++__pos;
00217           __xtrc += __ctype.narrow(__c, char());
00218           __c = *(++__beg);
00219 
00220           // Remove optional plus or minus sign, if they exist.
00221           if (__traits_type::eq(__c, __plus) 
00222           || __traits_type::eq(__c, __minus))
00223         {
00224           ++__pos;
00225           __xtrc += __ctype.narrow(__c, char());
00226           __c = *(++__beg);
00227         }
00228           __found_sci = true;
00229         }
00230       else
00231         // Not a valid input item.
00232         break;
00233         }
00234 
00235       // Digit grouping is checked. If grouping and found_grouping don't
00236       // match, then get very very upset, and set failbit.
00237       if (__check_grouping && __found_grouping.size())
00238         {
00239           // Add the ending grouping if a decimal wasn't found.
00240       if (!__found_dec)
00241         __found_grouping += static_cast<char>(__sep_pos);
00242           if (!__verify_grouping(__grouping, __found_grouping))
00243         __err |= ios_base::failbit;
00244         }
00245 
00246       // Finish up
00247       if (__beg == __end)
00248         __err |= ios_base::eofbit;
00249       return __beg;
00250     }
00251 
00252   // Stage 1: Determine a conversion specifier.
00253   template<typename _CharT, typename _InIter>
00254     _InIter
00255     num_get<_CharT, _InIter>::
00256     _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
00257            ios_base::iostate& __err, string& __xtrc, int& __base) const
00258     {
00259       typedef char_traits<_CharT>       __traits_type;
00260       const locale __loc = __io.getloc();
00261       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
00262       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
00263  
00264       // NB: Iff __basefield == 0, this can change based on contents.
00265       ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
00266       if (__basefield == ios_base::oct)
00267         __base = 8;
00268       else if (__basefield == ios_base::hex)
00269         __base = 16;
00270       else
00271     __base = 10;
00272 
00273       // First check for sign.
00274       int __pos = 0;
00275       char_type  __c = *__beg;
00276       const char_type __plus = __ctype.widen('+');
00277       const char_type __minus = __ctype.widen('-');
00278 
00279       if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus))
00280       && __beg != __end)
00281     {
00282       __xtrc += __ctype.narrow(__c, char());
00283       ++__pos;
00284       __c = *(++__beg);
00285     }
00286 
00287       // Next, strip leading zeros and check required digits for base formats.
00288       const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]);
00289       const char_type __x = __ctype.widen('x');
00290       const char_type __X = __ctype.widen('X');
00291       if (__base == 10)
00292     {
00293       bool __found_zero = false;
00294       while (__traits_type::eq(__c, __zero) && __beg != __end)
00295         {
00296           __c = *(++__beg);
00297           __found_zero = true;
00298         }
00299       if (__found_zero)
00300         {
00301           __xtrc += _S_atoms_in[_M_zero];
00302           ++__pos;
00303           if (__basefield == 0)
00304         {         
00305           if ((__traits_type::eq(__c, __x) 
00306                || __traits_type::eq(__c, __X))
00307               && __beg != __end)
00308             {
00309               __xtrc += __ctype.narrow(__c, char());
00310               ++__pos;
00311               __c = *(++__beg);
00312               __base = 16;
00313             }
00314           else 
00315             __base = 8;
00316         }
00317         }
00318     }
00319       else if (__base == 16)
00320     {
00321       if (__traits_type::eq(__c, __zero) && __beg != __end)
00322         {
00323           __xtrc += _S_atoms_in[_M_zero];
00324           ++__pos;
00325           __c = *(++__beg); 
00326           if ((__traits_type::eq(__c, __x) || __traits_type::eq(__c, __X))
00327           && __beg != __end)
00328         {
00329           __xtrc += __ctype.narrow(__c, char());
00330           ++__pos;
00331           __c = *(++__beg);
00332         }
00333         }
00334     }
00335 
00336       // At this point, base is determined. If not hex, only allow
00337       // base digits as valid input.
00338       size_t __len;
00339       if (__base == 16)
00340     __len = _M_size;
00341       else
00342     __len = __base;
00343 
00344       // Extract.
00345       char_type __watoms[_M_size];
00346       __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms);
00347       string __found_grouping;
00348       const string __grouping = __np.grouping();
00349       const bool __check_grouping = __grouping.size();
00350       if (__check_grouping)
00351     __found_grouping.reserve(32);
00352       int __sep_pos = 0;
00353       const char_type __sep = __np.thousands_sep();
00354       while (__beg != __end)
00355         {
00356           const char_type* __p = __traits_type::find(__watoms, __len,  __c);
00357           if (__p)
00358         {
00359           // Try first for acceptable digit; record it if found.
00360           __xtrc += _S_atoms_in[__p - __watoms];
00361           ++__pos;
00362           ++__sep_pos;
00363           __c = *(++__beg);
00364         }
00365           else if (__traits_type::eq(__c, __sep) && __check_grouping)
00366         {
00367               // NB: Thousands separator at the beginning of a string
00368               // is a no-no, as is two consecutive thousands separators.
00369               if (__sep_pos)
00370                 {
00371                   __found_grouping += static_cast<char>(__sep_pos);
00372                   __sep_pos = 0;
00373           __c = *(++__beg);
00374                 }
00375               else
00376         {
00377           __err |= ios_base::failbit;
00378           break;
00379         }
00380             }
00381       else
00382         // Not a valid input item.
00383         break;
00384         }
00385 
00386       // Digit grouping is checked. If grouping and found_grouping don't
00387       // match, then get very very upset, and set failbit.
00388       if (__check_grouping && __found_grouping.size())
00389         {
00390           // Add the ending grouping.
00391           __found_grouping += static_cast<char>(__sep_pos);
00392           if (!__verify_grouping(__grouping, __found_grouping))
00393         __err |= ios_base::failbit;
00394         }
00395 
00396       // Finish up.
00397       __xtrc += char();
00398       if (__beg == __end)
00399         __err |= ios_base::eofbit;
00400       return __beg;
00401     }
00402 
00403 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
00404   //17.  Bad bool parsing
00405   template<typename _CharT, typename _InIter>
00406     _InIter
00407     num_get<_CharT, _InIter>::
00408     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00409            ios_base::iostate& __err, bool& __v) const
00410     {
00411       if (!(__io.flags() & ios_base::boolalpha))
00412         {
00413       // Parse bool values as unsigned long
00414           // NB: We can't just call do_get(long) here, as it might
00415           // refer to a derived class.
00416           string __xtrc;
00417           int __base;
00418           __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
00419 
00420       unsigned long __ul; 
00421       __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
00422       if (!(__err & ios_base::failbit) && __ul <= 1)
00423         __v = __ul;
00424       else 
00425             __err |= ios_base::failbit;
00426         }
00427       else
00428         {
00429       // Parse bool values as alphanumeric
00430       typedef char_traits<_CharT>           __traits_type;
00431       typedef basic_string<_CharT>      __string_type;
00432 
00433           const locale& __loc = __io._M_getloc();
00434       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 
00435       const __string_type __true = __np.truename();
00436       const __string_type __false = __np.falsename();
00437 
00438       bool __testf = true;
00439       bool __testt = true;
00440       size_t __n;
00441           for (__n = 0; __beg != __end; ++__n, ++__beg)
00442             {
00443           if (__testf)
00444         if (__n < __false.size())
00445           __testf = __traits_type::eq(*__beg, __false[__n]);
00446         else
00447           break;
00448 
00449           if (__testt)
00450         if (__n < __true.size())
00451           __testt = __traits_type::eq(*__beg, __true[__n]);
00452         else
00453           break;
00454 
00455           if (!__testf && !__testt)
00456         break;
00457             }
00458       if (__testf && __n == __false.size())
00459         __v = 0;
00460       else if (__testt && __n == __true.size())
00461         __v = 1;
00462       else
00463         __err |= ios_base::failbit;
00464 
00465           if (__beg == __end)
00466             __err |= ios_base::eofbit;
00467         }
00468       return __beg;
00469     }
00470 #endif
00471 
00472   template<typename _CharT, typename _InIter>
00473     _InIter
00474     num_get<_CharT, _InIter>::
00475     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00476            ios_base::iostate& __err, long& __v) const
00477     {
00478       string __xtrc;
00479       __xtrc.reserve(32);
00480       int __base;
00481       __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
00482       __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
00483       return __beg;
00484     }
00485 
00486   template<typename _CharT, typename _InIter>
00487     _InIter
00488     num_get<_CharT, _InIter>::
00489     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00490            ios_base::iostate& __err, unsigned short& __v) const
00491     {
00492       string __xtrc;
00493       __xtrc.reserve(32);
00494       int __base;
00495       __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
00496       unsigned long __ul;
00497       __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
00498       if (!(__err & ios_base::failbit) 
00499       && __ul <= numeric_limits<unsigned short>::max())
00500     __v = static_cast<unsigned short>(__ul);
00501       else 
00502     __err |= ios_base::failbit;
00503       return __beg;
00504     }
00505 
00506   template<typename _CharT, typename _InIter>
00507     _InIter
00508     num_get<_CharT, _InIter>::
00509     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00510            ios_base::iostate& __err, unsigned int& __v) const
00511     {
00512       string __xtrc;
00513       __xtrc.reserve(32);
00514       int __base;
00515       __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
00516       unsigned long __ul;
00517       __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
00518       if (!(__err & ios_base::failbit) 
00519       && __ul <= numeric_limits<unsigned int>::max())
00520     __v = static_cast<unsigned int>(__ul);
00521       else 
00522     __err |= ios_base::failbit;
00523       return __beg;
00524     }
00525 
00526   template<typename _CharT, typename _InIter>
00527     _InIter
00528     num_get<_CharT, _InIter>::
00529     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00530            ios_base::iostate& __err, unsigned long& __v) const
00531     {
00532       string __xtrc;
00533       __xtrc.reserve(32);
00534       int __base;
00535       __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
00536       __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
00537       return __beg;
00538     }
00539 
00540 #ifdef _GLIBCPP_USE_LONG_LONG
00541   template<typename _CharT, typename _InIter>
00542     _InIter
00543     num_get<_CharT, _InIter>::
00544     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00545            ios_base::iostate& __err, long long& __v) const
00546     {
00547       string __xtrc;
00548       __xtrc.reserve(32);
00549       int __base;
00550       __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
00551       __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
00552       return __beg;
00553     }
00554 
00555   template<typename _CharT, typename _InIter>
00556     _InIter
00557     num_get<_CharT, _InIter>::
00558     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00559            ios_base::iostate& __err, unsigned long long& __v) const
00560     {
00561       string __xtrc;
00562       __xtrc.reserve(32);
00563       int __base;
00564       __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
00565       __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
00566       return __beg;
00567     }
00568 #endif
00569 
00570   template<typename _CharT, typename _InIter>
00571     _InIter
00572     num_get<_CharT, _InIter>::
00573     do_get(iter_type __beg, iter_type __end, ios_base& __io, 
00574        ios_base::iostate& __err, float& __v) const
00575     {
00576       string __xtrc;
00577       __xtrc.reserve(32);
00578       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
00579       __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
00580       return __beg;
00581     }
00582 
00583   template<typename _CharT, typename _InIter>
00584     _InIter
00585     num_get<_CharT, _InIter>::
00586     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00587            ios_base::iostate& __err, double& __v) const
00588     {
00589       string __xtrc;
00590       __xtrc.reserve(32);
00591       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
00592       __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
00593       return __beg;
00594     }
00595 
00596   template<typename _CharT, typename _InIter>
00597     _InIter
00598     num_get<_CharT, _InIter>::
00599     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00600            ios_base::iostate& __err, long double& __v) const
00601     {
00602       string __xtrc;
00603       __xtrc.reserve(32);
00604       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
00605       __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
00606       return __beg;
00607     }
00608 
00609   template<typename _CharT, typename _InIter>
00610     _InIter
00611     num_get<_CharT, _InIter>::
00612     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00613            ios_base::iostate& __err, void*& __v) const
00614     {
00615       // Prepare for hex formatted input
00616       typedef ios_base::fmtflags        fmtflags;
00617       fmtflags __fmt = __io.flags();
00618       __io.flags(__fmt & ~ios_base::basefield | ios_base::hex);
00619 
00620       string __xtrc;
00621       __xtrc.reserve(32);
00622       int __base;
00623       __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
00624 
00625       // Reset from hex formatted input
00626       __io.flags(__fmt);
00627 
00628       unsigned long __ul;
00629       __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
00630       if (!(__err & ios_base::failbit))
00631     __v = reinterpret_cast<void*>(__ul);
00632       else 
00633     __err |= ios_base::failbit;
00634       return __beg;
00635     }
00636 
00637   // For use by integer and floating-point types after they have been
00638   // converted into a char_type string.
00639   template<typename _CharT, typename _OutIter>
00640     void
00641     num_put<_CharT, _OutIter>::
00642     _M_pad(_CharT __fill, streamsize __w, ios_base& __io, 
00643        _CharT* __new, const _CharT* __cs, int& __len) const
00644     {
00645       // [22.2.2.2.2] Stage 3.
00646       // If necessary, pad.
00647       __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs, 
00648                           __w, __len, true);
00649       __len = static_cast<int>(__w);
00650     }
00651 
00652   // Forwarding functions to peel signed from unsigned integer types.
00653   template<typename _CharT>
00654     inline int
00655     __int_to_char(_CharT* __out, const int __size, long __v,
00656                const _CharT* __lit, ios_base::fmtflags __flags)
00657     {
00658       unsigned long __ul = static_cast<unsigned long>(__v);
00659       bool __neg = false;
00660       if (__v < 0) 
00661     {
00662       __ul = -__ul;
00663       __neg = true;
00664     }
00665       return __int_to_char(__out, __size, __ul, __lit, __flags, __neg); 
00666     }
00667 
00668   template<typename _CharT>
00669     inline int
00670     __int_to_char(_CharT* __out, const int __size, unsigned long __v,
00671                const _CharT* __lit, ios_base::fmtflags __flags)
00672     {
00673       // About showpos, see Table 60 and C99 7.19.6.1, p6 (+).
00674       return __int_to_char(__out, __size, __v, __lit,
00675                __flags & ~ios_base::showpos, false);
00676     }
00677 
00678 #ifdef _GLIBCPP_USE_LONG_LONG
00679   template<typename _CharT>
00680     inline int
00681     __int_to_char(_CharT* __out, const int __size, long long __v,
00682                const _CharT* __lit, ios_base::fmtflags __flags)
00683     { 
00684       unsigned long long __ull = static_cast<unsigned long long>(__v);
00685       bool __neg = false;
00686       if (__v < 0) 
00687     {
00688       __ull = -__ull;
00689       __neg = true;
00690     }
00691       return __int_to_char(__out, __size, __ull, __lit, __flags, __neg); 
00692     }
00693 
00694   template<typename _CharT>
00695     inline int
00696     __int_to_char(_CharT* __out, const int __size, unsigned long long __v,
00697                const _CharT* __lit, ios_base::fmtflags __flags)
00698     { return __int_to_char(__out, __size, __v, __lit,
00699                __flags & ~ios_base::showpos, false); }
00700 #endif
00701       
00702   template<typename _CharT, typename _ValueT>
00703     int
00704     __int_to_char(_CharT* __out, const int __size, _ValueT __v,
00705           const _CharT* __lit, ios_base::fmtflags __flags, bool __neg)
00706     {
00707       // Don't write base if already 0.
00708       const bool __showbase = (__flags & ios_base::showbase) && __v;
00709       const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
00710       _CharT* __buf = __out + __size - 1;
00711       _CharT* __bufend = __out + __size;
00712 
00713       if (__builtin_expect(__basefield != ios_base::oct &&
00714                __basefield != ios_base::hex, true))
00715     {
00716       // Decimal.
00717       do 
00718         {
00719           *__buf-- = __lit[(__v % 10) + __num_base::_S_digits];
00720           __v /= 10;
00721         } 
00722       while (__v != 0);
00723       if (__neg)
00724         *__buf-- = __lit[__num_base::_S_minus];
00725       else if (__flags & ios_base::showpos)
00726         *__buf-- = __lit[__num_base::_S_plus];
00727     }
00728       else if (__basefield == ios_base::oct)
00729     {
00730       // Octal.
00731       do 
00732         {
00733           *__buf-- = __lit[(__v & 0x7) + __num_base::_S_digits];
00734           __v >>= 3;
00735         } 
00736       while (__v != 0);
00737       if (__showbase)
00738         *__buf-- = __lit[__num_base::_S_digits];
00739     }
00740       else
00741     {
00742       // Hex.
00743       const bool __uppercase = __flags & ios_base::uppercase;
00744       int __case_offset = __uppercase
00745                           ? __num_base::_S_udigits : __num_base::_S_digits;
00746       do 
00747         {
00748           *__buf-- = __lit[(__v & 0xf) + __case_offset];
00749           __v >>= 4;
00750         } 
00751       while (__v != 0);
00752       if (__showbase)
00753         {
00754           // 'x' or 'X'
00755           *__buf-- = __lit[__num_base::_S_x + __uppercase];
00756           // '0'
00757           *__buf-- = __lit[__num_base::_S_digits];
00758         }
00759     }
00760       int __ret = __bufend - __buf - 1;
00761       return __ret;
00762     }
00763 
00764   template<typename _CharT, typename _OutIter>
00765     void
00766     num_put<_CharT, _OutIter>::
00767     _M_group_int(const string& __grouping, _CharT __sep, ios_base& __io, 
00768          _CharT* __new, _CharT* __cs, int& __len) const
00769     {
00770       // By itself __add_grouping cannot deal correctly with __ws when
00771       // ios::showbase is set and ios_base::oct || ios_base::hex.
00772       // Therefore we take care "by hand" of the initial 0, 0x or 0X.
00773       // However, remember that the latter do not occur if the number
00774       // printed is '0' (__len == 1).
00775       streamsize __off = 0;
00776       const ios_base::fmtflags __basefield = __io.flags() 
00777                                          & ios_base::basefield;
00778       if ((__io.flags() & ios_base::showbase) && __len > 1)
00779     if (__basefield == ios_base::oct)
00780       {
00781         __off = 1;
00782         *__new = *__cs;
00783       }
00784     else if (__basefield == ios_base::hex)
00785       {
00786         __off = 2;
00787         *__new = *__cs;
00788         *(__new + 1) = *(__cs + 1);
00789       }
00790       _CharT* __p;
00791       __p = __add_grouping(__new + __off, __sep, 
00792                __grouping.c_str(),
00793                __grouping.c_str() + __grouping.size(),
00794                __cs + __off, __cs + __len);
00795       __len = __p - __new;
00796     }
00797 
00798   template<typename _CharT, typename _OutIter>
00799     template<typename _ValueT>
00800       _OutIter
00801       num_put<_CharT, _OutIter>::
00802       _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, 
00803              _ValueT __v) const
00804       {
00805     typedef numpunct<_CharT>  __facet_type;
00806     typedef __locale_cache<numpunct<_CharT> > __cache_type;
00807     const locale& __loc = __io._M_getloc();
00808     const __cache_type& __lc = __use_cache<__facet_type>(__loc);
00809     const _CharT* __lit = __lc._M_atoms_out;
00810 
00811     // Long enough to hold hex, dec, and octal representations.
00812     int __ilen = 4 * sizeof(_ValueT);
00813     _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
00814                                  * __ilen));
00815     // [22.2.2.2.2] Stage 1, numeric conversion to character.
00816     // Result is returned right-justified in the buffer.
00817     int __len;
00818     __len = __int_to_char(&__cs[0], __ilen, __v, __lit, __io.flags());
00819     __cs = __cs + __ilen - __len;
00820     
00821     // Add grouping, if necessary. 
00822     _CharT* __cs2;
00823     if (__lc._M_use_grouping)
00824       {
00825         // Grouping can add (almost) as many separators as the
00826         // number of digits, but no more.
00827         __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
00828                               * __len * 2));
00829         _M_group_int(__lc._M_grouping, __lc._M_thousands_sep, __io, 
00830              __cs2, __cs, __len);
00831         __cs = __cs2;
00832       }
00833     
00834     // Pad.
00835     _CharT* __cs3;
00836     streamsize __w = __io.width();
00837     if (__w > static_cast<streamsize>(__len))
00838       {
00839         __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
00840                               * __w));
00841         _M_pad(__fill, __w, __io, __cs3, __cs, __len);
00842         __cs = __cs3;
00843       }
00844     __io.width(0);
00845 
00846     // [22.2.2.2.2] Stage 4.
00847     // Write resulting, fully-formatted string to output iterator.
00848     return __write(__s, __cs, __len);
00849       } 
00850 
00851   template<typename _CharT, typename _OutIter>
00852     void
00853     num_put<_CharT, _OutIter>::
00854     _M_group_float(const string& __grouping, _CharT __sep, const _CharT* __p, 
00855            _CharT* __new, _CharT* __cs, int& __len) const
00856     {
00857 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
00858       //282. What types does numpunct grouping refer to?
00859       // Add grouping, if necessary. 
00860       _CharT* __p2;
00861       int __declen = __p ? __p - __cs : __len;
00862       __p2 = __add_grouping(__new, __sep, 
00863                 __grouping.c_str(),
00864                 __grouping.c_str() + __grouping.size(),
00865                 __cs, __cs + __declen);
00866       
00867       // Tack on decimal part.
00868       int __newlen = __p2 - __new;
00869       if (__p)
00870     {
00871       char_traits<_CharT>::copy(__p2, __p, __len - __declen);
00872       __newlen += __len - __declen;
00873     }    
00874       __len = __newlen;
00875 #endif
00876     }
00877 
00878   // The following code uses snprintf (or sprintf(), when
00879   // _GLIBCPP_USE_C99 is not defined) to convert floating point values
00880   // for insertion into a stream.  An optimization would be to replace
00881   // them with code that works directly on a wide buffer and then use
00882   // __pad to do the padding.  It would be good to replace them anyway
00883   // to gain back the efficiency that C++ provides by knowing up front
00884   // the type of the values to insert.  Also, sprintf is dangerous
00885   // since may lead to accidental buffer overruns.  This
00886   // implementation follows the C++ standard fairly directly as
00887   // outlined in 22.2.2.2 [lib.locale.num.put]
00888   template<typename _CharT, typename _OutIter>
00889     template<typename _ValueT>
00890       _OutIter
00891       num_put<_CharT, _OutIter>::
00892       _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
00893                _ValueT __v) const
00894       {
00895     // Use default precision if out of range.
00896     streamsize __prec = __io.precision();
00897     if (__prec < static_cast<streamsize>(0))
00898       __prec = static_cast<streamsize>(6);
00899     
00900     const int __max_digits = numeric_limits<_ValueT>::digits10;
00901 
00902     typedef numpunct<_CharT>  __facet_type;
00903     typedef __locale_cache<numpunct<_CharT> > __cache_type;
00904     const locale __loc = __io._M_getloc();
00905     const __cache_type& __lc = __use_cache<__facet_type>(__loc);
00906 
00907     // [22.2.2.2.2] Stage 1, numeric conversion to character.
00908     int __len;
00909     // Long enough for the max format spec.
00910     char __fbuf[16];
00911 
00912 #ifdef _GLIBCPP_USE_C99
00913     // First try a buffer perhaps big enough (probably sufficient
00914     // for non-ios_base::fixed outputs)
00915     int __cs_size = __max_digits * 3;
00916     char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
00917 
00918     _S_format_float(__io, __fbuf, __mod, __prec);
00919     __len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
00920                  _S_c_locale, __prec);
00921 
00922     // If the buffer was not large enough, try again with the correct size.
00923     if (__len >= __cs_size)
00924       {
00925         __cs_size = __len + 1; 
00926         __cs = static_cast<char*>(__builtin_alloca(__cs_size));
00927         __len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
00928                      _S_c_locale, __prec);
00929       }
00930 #else
00931     // Consider the possibility of long ios_base::fixed outputs
00932     const bool __fixed = __io.flags() & ios_base::fixed;
00933     const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
00934 
00935     // ios_base::fixed outputs may need up to __max_exp + 1 chars
00936     // for the integer part + __prec chars for the fractional part
00937     // + 3 chars for sign, decimal point, '\0'. On the other hand,
00938     // for non-fixed outputs __max_digits * 2 chars + __prec are
00939     // largely sufficient.
00940     const int __cs_size = __fixed ? __max_exp + __prec + 4 
00941                                   : __max_digits * 2 + __prec;
00942     char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
00943 
00944     _S_format_float(__io, __fbuf, __mod, __prec);
00945     __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec);
00946 #endif
00947 
00948       // [22.2.2.2.2] Stage 2, convert to char_type, using correct
00949       // numpunct.decimal_point() values for '.' and adding grouping.
00950       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
00951 
00952       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
00953                                * __len));
00954       __ctype.widen(__cs, __cs + __len, __ws);
00955       
00956       // Replace decimal point.
00957       const _CharT __cdec = __ctype.widen('.');
00958       const _CharT __dec = __lc._M_decimal_point;
00959       const _CharT* __p;
00960       if (__p = char_traits<_CharT>::find(__ws, __len, __cdec))
00961     __ws[__p - __ws] = __dec;
00962 
00963       // Add grouping, if necessary. 
00964       _CharT* __ws2;
00965       if (__lc._M_use_grouping)
00966     {
00967         // Grouping can add (almost) as many separators as the
00968         // number of digits, but no more.
00969         __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
00970                               * __len * 2));
00971         _M_group_float(__lc._M_grouping, __lc._M_thousands_sep, __p,
00972                __ws2, __ws, __len);
00973         __ws = __ws2;
00974     }
00975 
00976       // Pad.
00977       _CharT* __ws3;
00978       streamsize __w = __io.width();
00979       if (__w > static_cast<streamsize>(__len))
00980     {
00981       __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __w));
00982       _M_pad(__fill, __w, __io, __ws3, __ws, __len);
00983       __ws = __ws3;
00984     }
00985       __io.width(0);
00986       
00987       // [22.2.2.2.2] Stage 4.
00988       // Write resulting, fully-formatted string to output iterator.
00989       return __write(__s, __ws, __len);
00990       }
00991 
00992   template<typename _CharT, typename _OutIter>
00993     _OutIter
00994     num_put<_CharT, _OutIter>::
00995     do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
00996     {
00997       ios_base::fmtflags __flags = __io.flags();
00998       if ((__flags & ios_base::boolalpha) == 0)
00999         {
01000           const long __l = __v;
01001           __s = _M_convert_int(__s, __io, __fill, __l);
01002         }
01003       else
01004         {
01005       typedef numpunct<_CharT>  __facet_type;
01006       typedef __locale_cache<numpunct<_CharT> > __cache_type;
01007       const locale __loc = __io._M_getloc();
01008       const __cache_type& __lc = __use_cache<__facet_type>(__loc);
01009 
01010       typedef basic_string<_CharT>  __string_type;
01011       __string_type __name;
01012           if (__v)
01013         __name = __lc._M_truename;
01014           else
01015         __name = __lc._M_falsename;
01016 
01017       const _CharT* __cs = __name.c_str();
01018       int __len = __name.size();
01019       _CharT* __cs3;
01020       streamsize __w = __io.width();
01021       if (__w > static_cast<streamsize>(__len))
01022         {
01023           __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
01024                                 * __w));
01025           _M_pad(__fill, __w, __io, __cs3, __cs, __len);
01026           __cs = __cs3;
01027         }
01028       __io.width(0);
01029       __s = __write(__s, __cs, __len);
01030     }
01031       return __s;
01032     }
01033 
01034   template<typename _CharT, typename _OutIter>
01035     _OutIter
01036     num_put<_CharT, _OutIter>::
01037     do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
01038     { return _M_convert_int(__s, __io, __fill, __v); }
01039 
01040   template<typename _CharT, typename _OutIter>
01041     _OutIter
01042     num_put<_CharT, _OutIter>::
01043     do_put(iter_type __s, ios_base& __io, char_type __fill,
01044            unsigned long __v) const
01045     { return _M_convert_int(__s, __io, __fill, __v); }
01046 
01047 #ifdef _GLIBCPP_USE_LONG_LONG
01048   template<typename _CharT, typename _OutIter>
01049     _OutIter
01050     num_put<_CharT, _OutIter>::
01051     do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
01052     { return _M_convert_int(__s, __b, __fill, __v); }
01053 
01054   template<typename _CharT, typename _OutIter>
01055     _OutIter
01056     num_put<_CharT, _OutIter>::
01057     do_put(iter_type __s, ios_base& __io, char_type __fill,
01058            unsigned long long __v) const
01059     { return _M_convert_int(__s, __io, __fill, __v); }
01060 #endif
01061 
01062   template<typename _CharT, typename _OutIter>
01063     _OutIter
01064     num_put<_CharT, _OutIter>::
01065     do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
01066     { return _M_convert_float(__s, __io, __fill, char(), __v); }
01067 
01068   template<typename _CharT, typename _OutIter>
01069     _OutIter
01070     num_put<_CharT, _OutIter>::
01071     do_put(iter_type __s, ios_base& __io, char_type __fill, 
01072        long double __v) const
01073     { return _M_convert_float(__s, __io, __fill, 'L', __v); }
01074 
01075   template<typename _CharT, typename _OutIter>
01076     _OutIter
01077     num_put<_CharT, _OutIter>::
01078     do_put(iter_type __s, ios_base& __io, char_type __fill,
01079            const void* __v) const
01080     {
01081       ios_base::fmtflags __flags = __io.flags();
01082       ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield
01083                    | ios_base::uppercase | ios_base::internal);
01084       __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
01085       try 
01086     {
01087       __s = _M_convert_int(__s, __io, __fill, 
01088                    reinterpret_cast<unsigned long>(__v));
01089       __io.flags(__flags);
01090     }
01091       catch (...) 
01092     {
01093       __io.flags(__flags);
01094       __throw_exception_again;
01095     }
01096       return __s;
01097     }
01098 
01099 
01100   template<typename _CharT, typename _InIter>
01101     _InIter
01102     money_get<_CharT, _InIter>::
01103     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 
01104        ios_base::iostate& __err, long double& __units) const
01105     { 
01106       string_type __str;
01107       __beg = this->do_get(__beg, __end, __intl, __io, __err, __str); 
01108 
01109       const int __cs_size = __str.size() + 1;
01110       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01111       const locale __loc = __io.getloc();
01112       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
01113       const _CharT* __wcs = __str.c_str();
01114       __ctype.narrow(__wcs, __wcs + __cs_size, char(), __cs);      
01115       __convert_to_v(__cs, __units, __err, _S_c_locale);
01116       return __beg;
01117     }
01118 
01119   template<typename _CharT, typename _InIter>
01120     _InIter
01121     money_get<_CharT, _InIter>::
01122     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 
01123        ios_base::iostate& __err, string_type& __units) const
01124     { 
01125       // These contortions are quite unfortunate.
01126       typedef moneypunct<_CharT, true>      __money_true;
01127       typedef moneypunct<_CharT, false>     __money_false;
01128       typedef money_base::part          part;
01129       typedef typename string_type::size_type   size_type;
01130 
01131       const locale __loc = __io.getloc();
01132       const __money_true& __mpt = use_facet<__money_true>(__loc); 
01133       const __money_false& __mpf = use_facet<__money_false>(__loc); 
01134       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
01135 
01136       const money_base::pattern __p = __intl ? __mpt.neg_format() 
01137                          : __mpf.neg_format();
01138 
01139       const string_type __pos_sign =__intl ? __mpt.positive_sign() 
01140                        : __mpf.positive_sign();
01141       const string_type __neg_sign =__intl ? __mpt.negative_sign() 
01142                        : __mpf.negative_sign();
01143       const char_type __d = __intl ? __mpt.decimal_point() 
01144                            : __mpf.decimal_point();
01145       const char_type __sep = __intl ? __mpt.thousands_sep() 
01146                          : __mpf.thousands_sep();
01147 
01148       const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping();
01149 
01150       // Set to deduced positive or negative sign, depending.
01151       string_type __sign;
01152       // String of grouping info from thousands_sep plucked from __units.
01153       string __grouping_tmp; 
01154       // Marker for thousands_sep position.
01155       int __sep_pos = 0;
01156       // If input iterator is in a valid state.
01157       bool __testvalid = true;
01158       // Flag marking when a decimal point is found.
01159       bool __testdecfound = false; 
01160 
01161       // The tentative returned string is stored here.
01162       string_type __temp_units;
01163       __temp_units.reserve(20);
01164 
01165       char_type __c = *__beg;
01166       char_type __eof = static_cast<char_type>(char_traits<char_type>::eof());
01167       for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i)
01168     {
01169       part __which = static_cast<part>(__p.field[__i]);
01170       switch (__which)
01171         {
01172         case money_base::symbol:
01173           if (__io.flags() & ios_base::showbase 
01174               || __i < 2 || __sign.size() > 1
01175               || ((static_cast<part>(__p.field[3]) != money_base::none)
01176               && __i == 2)) 
01177             {
01178               // According to 22.2.6.1.2.2, symbol is required
01179               // if (__io.flags() & ios_base::showbase),
01180               // otherwise is optional and consumed only if
01181               // other characters are needed to complete the
01182               // format.
01183               const string_type __symbol = __intl ? __mpt.curr_symbol()
01184                                  : __mpf.curr_symbol();
01185               size_type __len = __symbol.size();
01186               size_type __j = 0;
01187               while (__beg != __end 
01188                  && __j < __len && __symbol[__j] == __c)
01189             {
01190               __c = *(++__beg);
01191               ++__j;
01192             }
01193               // When (__io.flags() & ios_base::showbase)
01194               // symbol is required.
01195               if (__j != __len && (__io.flags() & ios_base::showbase))
01196             __testvalid = false;
01197             }
01198           break;
01199         case money_base::sign:          
01200           // Sign might not exist, or be more than one character long.
01201           if (__pos_sign.size() && __c == __pos_sign[0])
01202             {
01203               __sign = __pos_sign;
01204               __c = *(++__beg);
01205             }
01206           else if (__neg_sign.size() && __c == __neg_sign[0])
01207             {
01208               __sign = __neg_sign;
01209               __c = *(++__beg);
01210             }         
01211           else if (__pos_sign.size() && __neg_sign.size())
01212             {
01213               // Sign is mandatory.
01214               __testvalid = false;
01215             }
01216           break;
01217         case money_base::value:
01218           // Extract digits, remove and stash away the
01219           // grouping of found thousands separators.
01220           while (__beg != __end 
01221              && (__ctype.is(ctype_base::digit, __c) 
01222                  || (__c == __d && !__testdecfound)
01223                  || __c == __sep))
01224             {
01225               if (__c == __d)
01226             {
01227               __grouping_tmp += static_cast<char>(__sep_pos);
01228               __sep_pos = 0;
01229               __testdecfound = true;
01230             }
01231               else if (__c == __sep)
01232             {
01233               if (__grouping.size())
01234                 {
01235                   // Mark position for later analysis.
01236                   __grouping_tmp += static_cast<char>(__sep_pos);
01237                   __sep_pos = 0;
01238                 }
01239               else
01240                 {
01241                   __testvalid = false;
01242                   break;
01243                 }
01244             }
01245               else
01246             {
01247               __temp_units += __c;
01248               ++__sep_pos;
01249             }
01250               __c = *(++__beg);
01251             }
01252           break;
01253         case money_base::space:
01254         case money_base::none:
01255           // Only if not at the end of the pattern.
01256           if (__i != 3)
01257             while (__beg != __end 
01258                && __ctype.is(ctype_base::space, __c))
01259               __c = *(++__beg);
01260           break;
01261         }
01262     }
01263 
01264       // Need to get the rest of the sign characters, if they exist.
01265       if (__sign.size() > 1)
01266     {
01267       size_type __len = __sign.size();
01268       size_type __i = 1;
01269       for (; __c != __eof && __i < __len; ++__i)
01270         while (__beg != __end && __c != __sign[__i])
01271           __c = *(++__beg);
01272       
01273       if (__i != __len)
01274         __testvalid = false;
01275     }
01276 
01277       // Strip leading zeros.
01278       while (__temp_units.size() > 1 && __temp_units[0] == __ctype.widen('0'))
01279     __temp_units.erase(__temp_units.begin());
01280 
01281       if (__sign.size() && __sign == __neg_sign)
01282     __temp_units.insert(__temp_units.begin(), __ctype.widen('-'));
01283 
01284       // Test for grouping fidelity.
01285       if (__grouping.size() && __grouping_tmp.size())
01286     {
01287       if (!__verify_grouping(__grouping, __grouping_tmp))
01288         __testvalid = false;
01289     }
01290 
01291       // Iff no more characters are available.      
01292       if (__c == __eof)
01293     __err |= ios_base::eofbit;
01294 
01295       // Iff valid sequence is not recognized.
01296       if (!__testvalid || !__temp_units.size())
01297     __err |= ios_base::failbit;
01298       else
01299     // Use the "swap trick" to copy __temp_units into __units.
01300     __temp_units.swap(__units);
01301 
01302       return __beg; 
01303     }
01304 
01305   template<typename _CharT, typename _OutIter>
01306     _OutIter
01307     money_put<_CharT, _OutIter>::
01308     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
01309        long double __units) const
01310     { 
01311       const locale __loc = __io.getloc();
01312       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01313 #ifdef _GLIBCPP_USE_C99
01314       // First try a buffer perhaps big enough.
01315       int __cs_size = 64;
01316       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01317       // _GLIBCXX_RESOLVE_LIB_DEFECTS
01318       // 328. Bad sprintf format modifier in money_put<>::do_put()
01319       int __len = __convert_from_v(__cs, __cs_size, "%.0Lf", __units, 
01320                    _S_c_locale);
01321       // If the buffer was not large enough, try again with the correct size.
01322       if (__len >= __cs_size)
01323     {
01324       __cs_size = __len + 1;
01325       __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01326       __len = __convert_from_v(__cs, __cs_size, "%.0Lf", __units, 
01327                    _S_c_locale);
01328     }
01329 #else
01330       // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
01331       const int __cs_size = numeric_limits<long double>::max_exponent10 + 3;
01332       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01333       int __len = __convert_from_v(__cs, 0, "%.0Lf", __units, _S_c_locale);
01334 #endif
01335       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
01336                                * __cs_size));
01337       __ctype.widen(__cs, __cs + __len, __ws);
01338       const string_type __digits(__ws, __len);
01339       return this->do_put(__s, __intl, __io, __fill, __digits); 
01340     }
01341 
01342   template<typename _CharT, typename _OutIter>
01343     _OutIter
01344     money_put<_CharT, _OutIter>::
01345     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
01346        const string_type& __digits) const
01347     { 
01348       typedef typename string_type::size_type   size_type;
01349       typedef money_base::part          part;
01350 
01351       const locale __loc = __io.getloc();
01352       const size_type __width = static_cast<size_type>(__io.width());
01353 
01354       // These contortions are quite unfortunate.
01355       typedef moneypunct<_CharT, true> __money_true;
01356       typedef moneypunct<_CharT, false> __money_false;
01357       const __money_true& __mpt = use_facet<__money_true>(__loc); 
01358       const __money_false& __mpf = use_facet<__money_false>(__loc); 
01359       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
01360 
01361       // Determine if negative or positive formats are to be used, and
01362       // discard leading negative_sign if it is present.
01363       const char_type* __beg = __digits.data();
01364       const char_type* __end = __beg + __digits.size();
01365       money_base::pattern __p;
01366       string_type __sign;
01367       if (*__beg != __ctype.widen('-'))
01368     {
01369       __p = __intl ? __mpt.pos_format() : __mpf.pos_format();
01370       __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign();
01371     }
01372       else
01373     {
01374       __p = __intl ? __mpt.neg_format() : __mpf.neg_format();
01375       __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign();
01376       ++__beg;
01377     }
01378       
01379       // Look for valid numbers in the current ctype facet within input digits.
01380       __end = __ctype.scan_not(ctype_base::digit, __beg, __end);
01381       if (__beg != __end)
01382     {
01383       // Assume valid input, and attempt to format.
01384       // Break down input numbers into base components, as follows:
01385       //   final_value = grouped units + (decimal point) + (digits)
01386       string_type __value;
01387       __value.reserve(20);
01388 
01389       const int __frac = __intl ? __mpt.frac_digits() 
01390                         : __mpf.frac_digits();
01391 
01392       // Add thousands separators to non-decimal digits, per
01393       // grouping rules.
01394       const int __paddec = __frac - (__end - __beg);
01395       if (__paddec < 0)
01396         {
01397           const string __grouping = __intl ? __mpt.grouping() 
01398                            : __mpf.grouping();
01399           if (__grouping.size())
01400         {
01401           const char_type __sep = __intl ? __mpt.thousands_sep() 
01402                                  : __mpf.thousands_sep();
01403           const char* __gbeg = __grouping.data();
01404           const char* __gend = __gbeg + __grouping.size();
01405           const int __n = (__end - __beg) * 2;
01406           _CharT* __ws2 =
01407                   static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
01408           _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg, 
01409                             __gend, __beg,
01410                             __end - __frac);
01411           __value.assign(__ws2, __ws_end - __ws2);
01412         }
01413           else
01414         __value.assign(__beg, -__paddec);
01415         }
01416 
01417       // Deal with decimal point, decimal digits.
01418       if (__frac > 0)
01419         {
01420           const char_type __d = __intl ? __mpt.decimal_point() 
01421                        : __mpf.decimal_point();
01422           __value += __d;
01423           if (__paddec <= 0)
01424         __value.append(__end - __frac, __frac);
01425           else
01426         {
01427           // Have to pad zeros in the decimal position.
01428           const char_type __zero = __ctype.widen('0');
01429           __value.append(__paddec, __zero);
01430           __value.append(__beg, __end - __beg);
01431         }
01432         }
01433 
01434       const string_type __symbol = __intl ? __mpt.curr_symbol() 
01435                               : __mpf.curr_symbol();
01436 
01437       // Calculate length of resulting string.
01438       ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield;
01439       size_type __len = __value.size() + __sign.size();
01440       __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0;
01441 
01442       string_type __res;
01443       __res.reserve(__len);
01444 
01445       bool __testipad = __f == ios_base::internal && __len < __width;
01446 
01447       // Fit formatted digits into the required pattern.
01448       for (int __i = 0; __i < 4; ++__i)
01449         {
01450           part __which = static_cast<part>(__p.field[__i]);
01451           switch (__which)
01452         {
01453         case money_base::symbol:
01454           if (__io.flags() & ios_base::showbase)
01455             __res += __symbol;
01456           break;
01457         case money_base::sign:          
01458           // Sign might not exist, or be more than one
01459           // charater long. In that case, add in the rest
01460           // below.
01461           if (__sign.size())
01462             __res += __sign[0];
01463           break;
01464         case money_base::value:
01465           __res += __value;
01466           break;
01467         case money_base::space:
01468           // At least one space is required, but if internal
01469           // formatting is required, an arbitrary number of
01470           // fill spaces will be necessary.
01471           if (__testipad)
01472             __res += string_type(__width - __len, __fill);
01473           else
01474             __res += __ctype.widen(__fill);
01475           break;
01476         case money_base::none:
01477           if (__testipad)
01478             __res += string_type(__width - __len, __fill);
01479           break;
01480         }
01481         }
01482 
01483       // Special case of multi-part sign parts.
01484       if (__sign.size() > 1)
01485         __res += string_type(__sign.begin() + 1, __sign.end());
01486 
01487       // Pad, if still necessary.
01488       __len = __res.size();
01489       if (__width > __len)
01490         {
01491           if (__f == ios_base::left)
01492         // After.
01493         __res.append(__width - __len, __fill);
01494           else
01495         // Before.
01496         __res.insert(0, string_type(__width - __len, __fill));
01497           __len = __width;
01498         }
01499 
01500       // Write resulting, fully-formatted string to output iterator.
01501       __s = __write(__s, __res.data(), __len);
01502     }
01503       __io.width(0);
01504       return __s; 
01505     }
01506 
01507 
01508   // NB: Not especially useful. Without an ios_base object or some
01509   // kind of locale reference, we are left clawing at the air where
01510   // the side of the mountain used to be...
01511   template<typename _CharT, typename _InIter>
01512     time_base::dateorder
01513     time_get<_CharT, _InIter>::do_date_order() const
01514     { return time_base::no_order; }
01515 
01516   template<typename _CharT, typename _InIter>
01517     void
01518     time_get<_CharT, _InIter>::
01519     _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io,
01520               ios_base::iostate& __err, tm* __tm, 
01521               const _CharT* __format) const
01522     {  
01523       locale __loc = __io.getloc();
01524       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
01525       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
01526       size_t __len = char_traits<_CharT>::length(__format);
01527 
01528       for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
01529     {
01530       if (__ctype.narrow(__format[__i], 0) == '%')
01531         {
01532           // Verify valid formatting code, attempt to extract.
01533           char __c = __ctype.narrow(__format[++__i], 0);
01534           int __mem = 0;
01535           if (__c == 'E' || __c == 'O')
01536         __c = __ctype.narrow(__format[++__i], 0);
01537           switch (__c)
01538         {
01539           const char* __cs;
01540           _CharT __wcs[10];
01541         case 'a':
01542           // Abbreviated weekday name [tm_wday]
01543           const char_type*  __days1[7];
01544           __tp._M_days_abbreviated(__days1);
01545           _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7, 
01546                   __err);
01547           break;
01548         case 'A':
01549           // Weekday name [tm_wday].
01550           const char_type*  __days2[7];
01551           __tp._M_days(__days2);
01552           _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7, 
01553                   __err);
01554           break;
01555         case 'h':
01556         case 'b':
01557           // Abbreviated month name [tm_mon]
01558           const char_type*  __months1[12];
01559           __tp._M_months_abbreviated(__months1);
01560           _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12, 
01561                   __err);
01562           break;
01563         case 'B':
01564           // Month name [tm_mon].
01565           const char_type*  __months2[12];
01566           __tp._M_months(__months2);
01567           _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12, 
01568                   __err);
01569           break;
01570         case 'c':
01571           // Default time and date representation.
01572           const char_type*  __dt[2];
01573           __tp._M_date_time_formats(__dt);
01574           _M_extract_via_format(__beg, __end, __io, __err, __tm, 
01575                     __dt[0]);
01576           break;
01577         case 'd':
01578           // Day [01, 31]. [tm_mday]
01579           _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, 
01580                  __ctype, __err);
01581           break;
01582         case 'e':
01583           // Day [1, 31], with single digits preceded by
01584           // space. [tm_mday]
01585           if (__ctype.is(ctype_base::space, *__beg))
01586             _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
01587                    1, __ctype, __err);
01588           else
01589             _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
01590                    2, __ctype, __err);
01591           break;
01592         case 'D':
01593           // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
01594           __cs = "%m/%d/%y";
01595           __ctype.widen(__cs, __cs + 9, __wcs);
01596           _M_extract_via_format(__beg, __end, __io, __err, __tm, 
01597                     __wcs);
01598           break;
01599         case 'H':
01600           // Hour [00, 23]. [tm_hour]
01601           _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
01602                  __ctype, __err);
01603           break;
01604         case 'I':
01605           // Hour [01, 12]. [tm_hour]
01606           _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, 
01607                  __ctype, __err);
01608           break;
01609         case 'm':
01610           // Month [01, 12]. [tm_mon]
01611           _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype, 
01612                  __err);
01613           if (!__err)
01614             __tm->tm_mon = __mem - 1;
01615           break;
01616         case 'M':
01617           // Minute [00, 59]. [tm_min]
01618           _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
01619                  __ctype, __err);
01620           break;
01621         case 'n':
01622           if (__ctype.narrow(*__beg, 0) == '\n')
01623             ++__beg;
01624           else
01625             __err |= ios_base::failbit;
01626           break;
01627         case 'R':
01628           // Equivalent to (%H:%M).
01629           __cs = "%H:%M";
01630           __ctype.widen(__cs, __cs + 6, __wcs);
01631           _M_extract_via_format(__beg, __end, __io, __err, __tm, 
01632                     __wcs);
01633           break;
01634         case 'S':
01635           // Seconds. [tm_sec]
01636           // [00, 60] in C99 (one leap-second), [00, 61] in C89.
01637 #ifdef _GLIBCXX_USE_C99
01638           _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2,
01639 #else
01640           _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
01641 #endif
01642                  __ctype, __err);
01643           break;
01644         case 't':
01645           if (__ctype.narrow(*__beg, 0) == '\t')
01646             ++__beg;
01647           else
01648         __err |= ios_base::failbit;
01649           break;
01650         case 'T':
01651           // Equivalent to (%H:%M:%S).
01652           __cs = "%H:%M:%S";
01653           __ctype.widen(__cs, __cs + 9, __wcs);
01654           _M_extract_via_format(__beg, __end, __io, __err, __tm, 
01655                     __wcs);
01656           break;
01657         case 'x':
01658           // Locale's date.
01659           const char_type*  __dates[2];
01660           __tp._M_date_formats(__dates);
01661           _M_extract_via_format(__beg, __end, __io, __err, __tm, 
01662                     __dates[0]);
01663           break;
01664         case 'X':
01665           // Locale's time.
01666           const char_type*  __times[2];
01667           __tp._M_time_formats(__times);
01668           _M_extract_via_format(__beg, __end, __io, __err, __tm, 
01669                     __times[0]);
01670           break;
01671         case 'y':
01672           // Two digit year. [tm_year]
01673           _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, 
01674                  __ctype, __err);
01675           break;
01676         case 'Y':
01677           // Year [1900). [tm_year]
01678           _M_extract_num(__beg, __end, __mem, 0, 9999, 4, 
01679                  __ctype, __err);
01680           if (!__err)
01681             __tm->tm_year = __mem - 1900;
01682           break;
01683         case 'Z':
01684           // Timezone info.
01685           if (__ctype.is(ctype_base::upper, *__beg))
01686             {
01687               int __tmp;
01688               _M_extract_name(__beg, __end, __tmp, 
01689                       __timepunct<_CharT>::_S_timezones, 
01690                       14, __err);
01691               
01692               // GMT requires special effort.
01693               char_type __c = *__beg;
01694               if (!__err && __tmp == 0 
01695               && (__c == __ctype.widen('-') 
01696                   || __c == __ctype.widen('+')))
01697             {
01698               _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
01699                       __ctype, __err);
01700               _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
01701                       __ctype, __err);
01702             }       
01703               }
01704               else
01705             __err |= ios_base::failbit;
01706               break;
01707             default:
01708               // Not recognized.
01709               __err |= ios_base::failbit;
01710             }
01711         }
01712           else
01713         {
01714           // Verify format and input match, extract and discard.
01715           if (__format[__i] == *__beg)
01716             ++__beg;
01717           else
01718             __err |= ios_base::failbit;
01719         }
01720     }
01721     }
01722 
01723   template<typename _CharT, typename _InIter>
01724     void
01725     time_get<_CharT, _InIter>::
01726     _M_extract_num(iter_type& __beg, iter_type& __end, int& __member,
01727            int __min, int __max, size_t __len, 
01728            const ctype<_CharT>& __ctype, 
01729            ios_base::iostate& __err) const
01730     {
01731       // As-is works for __len = 1, 2, 4, the values actually used.
01732       int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
01733 
01734       ++__min;
01735       size_t __i = 0;
01736       int __value = 0;
01737       for (; __beg != __end && __i < __len; ++__beg, ++__i)
01738     {
01739       const char __c = __ctype.narrow(*__beg, '*');
01740       if (__c >= '0' && __c <= '9')
01741         {
01742           __value = __value * 10 + (__c - '0');
01743           const int __valuec = __value * __mult;
01744           if (__valuec > __max || __valuec + __mult < __min)
01745         break;
01746           __mult /= 10;
01747         }
01748       else
01749         break;
01750     }
01751       if (__i == __len)
01752     __member = __value;
01753       else
01754     __err |= ios_base::failbit;
01755     }
01756 
01757   // Assumptions:
01758   // All elements in __names are unique.
01759   template<typename _CharT, typename _InIter>
01760     void
01761     time_get<_CharT, _InIter>::
01762     _M_extract_name(iter_type& __beg, iter_type& __end, int& __member,
01763             const _CharT** __names, size_t __indexlen, 
01764             ios_base::iostate& __err) const
01765     {
01766       typedef char_traits<_CharT>       __traits_type;
01767       int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) 
01768                               * __indexlen));
01769       size_t __nmatches = 0;
01770       size_t __pos = 0;
01771       bool __testvalid = true;
01772       const char_type* __name;
01773 
01774       char_type __c = *__beg;
01775       // Look for initial matches.
01776       for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
01777     if (__c == __names[__i1][0])
01778       __matches[__nmatches++] = __i1;
01779       
01780       while (__nmatches > 1)
01781     {
01782       // Find smallest matching string.
01783       size_t __minlen = 10;
01784       for (size_t __i2 = 0; __i2 < __nmatches; ++__i2)
01785         __minlen = min(__minlen,
01786                __traits_type::length(__names[__matches[__i2]]));
01787       
01788       if (__pos < __minlen && __beg != __end)
01789         {
01790           ++__pos;
01791           __c = *(++__beg);
01792           for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
01793         {
01794           __name = __names[__matches[__i3]];
01795           if (__name[__pos] != __c)
01796             __matches[__i3] = __matches[--__nmatches];
01797         }
01798         }
01799       else
01800         break;
01801     }
01802 
01803       if (__nmatches == 1)
01804     {
01805       // Make sure found name is completely extracted.
01806       __name = __names[__matches[0]];
01807       const size_t __len = __traits_type::length(__name);
01808       while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
01809         ++__beg, ++__pos;
01810 
01811       if (__len == __pos)
01812         __member = __matches[0];
01813       else
01814         __testvalid = false;
01815     }
01816       else
01817     __testvalid = false;
01818       if (!__testvalid)
01819     __err |= ios_base::failbit;
01820     }
01821 
01822   template<typename _CharT, typename _InIter>
01823     _InIter
01824     time_get<_CharT, _InIter>::
01825     do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
01826         ios_base::iostate& __err, tm* __tm) const
01827     {
01828       locale __loc = __io.getloc();
01829       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
01830       const char_type*  __times[2];
01831       __tp._M_time_formats(__times);
01832       _M_extract_via_format(__beg, __end, __io, __err, __tm, __times[0]);
01833       if (__beg == __end)
01834     __err |= ios_base::eofbit;
01835       return __beg;
01836     }
01837 
01838   template<typename _CharT, typename _InIter>
01839     _InIter
01840     time_get<_CharT, _InIter>::
01841     do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
01842         ios_base::iostate& __err, tm* __tm) const
01843     {
01844       locale __loc = __io.getloc();
01845       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
01846       const char_type*  __dates[2];
01847       __tp._M_date_formats(__dates);
01848       _M_extract_via_format(__beg, __end, __io, __err, __tm, __dates[0]);
01849       if (__beg == __end)
01850     __err |= ios_base::eofbit;
01851       return __beg;
01852     }
01853 
01854   template<typename _CharT, typename _InIter>
01855     _InIter
01856     time_get<_CharT, _InIter>::
01857     do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 
01858            ios_base::iostate& __err, tm* __tm) const
01859     {
01860       typedef char_traits<_CharT>       __traits_type;
01861       locale __loc = __io.getloc();
01862       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
01863       const char_type*  __days[7];
01864       __tp._M_days_abbreviated(__days);
01865       int __tmpwday;
01866       _M_extract_name(__beg, __end, __tmpwday, __days, 7, __err);
01867 
01868       // Check to see if non-abbreviated name exists, and extract.
01869       // NB: Assumes both _M_days and _M_days_abbreviated organized in
01870       // exact same order, first to last, such that the resulting
01871       // __days array with the same index points to a day, and that
01872       // day's abbreviated form.
01873       // NB: Also assumes that an abbreviated name is a subset of the name. 
01874       if (!__err)
01875     {
01876       size_t __pos = __traits_type::length(__days[__tmpwday]);
01877       __tp._M_days(__days);
01878       const char_type* __name = __days[__tmpwday];
01879       if (__name[__pos] == *__beg)
01880         {
01881           // Extract the rest of it.
01882           const size_t __len = __traits_type::length(__name);
01883           while (__pos < __len && __beg != __end 
01884              && __name[__pos] == *__beg)
01885         ++__beg, ++__pos;
01886           if (__len != __pos)
01887         __err |= ios_base::failbit;
01888         }
01889       if (!__err)
01890         __tm->tm_wday = __tmpwday;
01891     }
01892       if (__beg == __end)
01893     __err |= ios_base::eofbit;
01894       return __beg;
01895      }
01896 
01897   template<typename _CharT, typename _InIter>
01898     _InIter
01899     time_get<_CharT, _InIter>::
01900     do_get_monthname(iter_type __beg, iter_type __end,
01901                      ios_base& __io, ios_base::iostate& __err, tm* __tm) const
01902     {
01903       typedef char_traits<_CharT>       __traits_type;
01904       locale __loc = __io.getloc();
01905       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
01906       const char_type*  __months[12];
01907       __tp._M_months_abbreviated(__months);
01908       int __tmpmon;
01909       _M_extract_name(__beg, __end, __tmpmon, __months, 12, __err);
01910 
01911       // Check to see if non-abbreviated name exists, and extract.
01912       // NB: Assumes both _M_months and _M_months_abbreviated organized in
01913       // exact same order, first to last, such that the resulting
01914       // __months array with the same index points to a month, and that
01915       // month's abbreviated form.
01916       // NB: Also assumes that an abbreviated name is a subset of the name. 
01917       if (!__err)
01918     {
01919       size_t __pos = __traits_type::length(__months[__tmpmon]);
01920       __tp._M_months(__months);
01921       const char_type* __name = __months[__tmpmon];
01922       if (__name[__pos] == *__beg)
01923         {
01924           // Extract the rest of it.
01925           const size_t __len = __traits_type::length(__name);
01926           while (__pos < __len && __beg != __end 
01927              && __name[__pos] == *__beg)
01928         ++__beg, ++__pos;
01929           if (__len != __pos)
01930         __err |= ios_base::failbit;
01931         }
01932       if (!__err)
01933         __tm->tm_mon = __tmpmon;
01934     }
01935  
01936       if (__beg == __end)
01937     __err |= ios_base::eofbit;
01938       return __beg;
01939     }
01940 
01941   template<typename _CharT, typename _InIter>
01942     _InIter
01943     time_get<_CharT, _InIter>::
01944     do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 
01945         ios_base::iostate& __err, tm* __tm) const
01946     {
01947       const locale& __loc = __io._M_getloc();
01948       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
01949 
01950       size_t __i = 0;
01951       int __value = 0;
01952       for (; __beg != __end && __i < 4; ++__beg, ++__i)
01953     {
01954       const char __c = __ctype.narrow(*__beg, '*');
01955       if (__c >= '0' && __c <= '9')
01956         __value = __value * 10 + (__c - '0');
01957       else
01958         break;
01959     }
01960       if (__i == 2 || __i == 4)
01961     __tm->tm_year = __i == 2 ? __value : __value - 1900;
01962       else
01963     __err |= ios_base::failbit;
01964       if (__beg == __end)
01965     __err |= ios_base::eofbit;
01966       return __beg;
01967     }
01968 
01969   template<typename _CharT, typename _OutIter>
01970     _OutIter
01971     time_put<_CharT, _OutIter>::
01972     put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm, 
01973     const _CharT* __beg, const _CharT* __end) const
01974     {
01975       const locale& __loc = __io._M_getloc();
01976       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
01977       for (; __beg != __end; ++__beg)
01978     if (__ctype.narrow(*__beg, 0) != '%')
01979       {
01980         *__s = *__beg;
01981         ++__s;
01982       }
01983     else if (++__beg != __end)
01984       {
01985         char __format;
01986         char __mod = 0;
01987         const char __c = __ctype.narrow(*__beg, 0);
01988         if (__c != 'E' && __c != 'O')
01989           __format = __c;
01990         else if (++__beg != __end)
01991           {
01992         __mod = __c;
01993         __format = __ctype.narrow(*__beg, 0);
01994           }
01995         else
01996           break;
01997         __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
01998       }
01999     else
02000       break;
02001       return __s;
02002     }
02003 
02004   template<typename _CharT, typename _OutIter>
02005     _OutIter
02006     time_put<_CharT, _OutIter>::
02007     do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 
02008        char __format, char __mod) const
02009     { 
02010       locale __loc = __io.getloc();
02011       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
02012       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
02013 
02014       // NB: This size is arbitrary. Should this be a data member,
02015       // initialized at construction?
02016       const size_t __maxlen = 128;
02017       char_type* __res =
02018     static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
02019 
02020       // NB: In IEE 1003.1-200x, and perhaps other locale models, it
02021       // is possible that the format character will be longer than one
02022       // character. Possibilities include 'E' or 'O' followed by a
02023       // format character: if __mod is not the default argument, assume
02024       // it's a valid modifier.
02025       char_type __fmt[4];
02026       __fmt[0] = __ctype.widen('%'); 
02027       if (!__mod)
02028     {
02029       __fmt[1] = __format;
02030       __fmt[2] = char_type();
02031     }
02032       else
02033     {
02034       __fmt[1] = __mod;
02035       __fmt[2] = __format;
02036       __fmt[3] = char_type();
02037     }
02038 
02039       __tp._M_put(__res, __maxlen, __fmt, __tm);
02040 
02041       // Write resulting, fully-formatted string to output iterator.
02042       return __write(__s, __res, char_traits<char_type>::length(__res));
02043     }
02044 
02045   // Generic version does nothing.
02046   template<typename _CharT>
02047     int
02048     collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const
02049     { return 0; }
02050 
02051   // Generic version does nothing.
02052   template<typename _CharT>
02053     size_t
02054     collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const
02055     { return 0; }
02056 
02057   template<typename _CharT>
02058     int
02059     collate<_CharT>::
02060     do_compare(const _CharT* __lo1, const _CharT* __hi1, 
02061            const _CharT* __lo2, const _CharT* __hi2) const
02062     { 
02063       // strcoll assumes zero-terminated strings so we make a copy
02064       // and then put a zero at the end.
02065       const string_type __one(__lo1, __hi1);
02066       const string_type __two(__lo2, __hi2);
02067 
02068       const _CharT* __p = __one.c_str();
02069       const _CharT* __pend = __one.c_str() + __one.length();
02070       const _CharT* __q = __two.c_str();
02071       const _CharT* __qend = __two.c_str() + __two.length();
02072 
02073       // strcoll stops when it sees a nul character so we break
02074       // the strings into zero-terminated substrings and pass those
02075       // to strcoll.
02076       for (;;)
02077     {
02078       int __res = _M_compare(__p, __q);
02079       if (__res)
02080         return __res;
02081 
02082       __p += char_traits<_CharT>::length(__p);
02083       __q += char_traits<_CharT>::length(__q);
02084       if (__p == __pend && __q == __qend)
02085         return 0;
02086       else if (__p == __pend)
02087         return -1;
02088       else if (__q == __qend)
02089         return 1;
02090 
02091       __p++;
02092       __q++;
02093     }
02094     }
02095 
02096  template<typename _CharT>
02097     typename collate<_CharT>::string_type
02098     collate<_CharT>::
02099     do_transform(const _CharT* __lo, const _CharT* __hi) const
02100     {
02101       // strxfrm assumes zero-terminated strings so we make a copy
02102       string_type __str(__lo, __hi);
02103 
02104       const _CharT* __p = __str.c_str();
02105       const _CharT* __pend = __str.c_str() + __str.length();
02106 
02107       size_t __len = (__hi - __lo) * 2;
02108 
02109       string_type __ret;
02110 
02111       // strxfrm stops when it sees a nul character so we break
02112       // the string into zero-terminated substrings and pass those
02113       // to strxfrm.
02114       for (;;)
02115     {
02116       // First try a buffer perhaps big enough.
02117       _CharT* __c =
02118         static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
02119       size_t __res = _M_transform(__c, __p, __len);
02120       // If the buffer was not large enough, try again with the
02121       // correct size.
02122       if (__res >= __len)
02123         {
02124           __len = __res + 1;
02125           __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
02126                               * __len));
02127           __res = _M_transform(__c, __p, __res + 1);
02128         }
02129 
02130       __ret.append(__c, __res);
02131       __p += char_traits<_CharT>::length(__p);
02132       if (__p == __pend)
02133         return __ret;
02134 
02135       __p++;
02136       __ret.push_back(_CharT());
02137     }
02138     }
02139 
02140  template<typename _CharT>
02141     long
02142     collate<_CharT>::
02143     do_hash(const _CharT* __lo, const _CharT* __hi) const
02144     { 
02145       unsigned long __val = 0;
02146       for (; __lo < __hi; ++__lo)
02147     __val = *__lo + ((__val << 7) | 
02148                (__val >> (numeric_limits<unsigned long>::digits - 7)));
02149       return static_cast<long>(__val);
02150     }
02151 
02152   // Construct correctly padded string, as per 22.2.2.2.2
02153   // Assumes 
02154   // __newlen > __oldlen
02155   // __news is allocated for __newlen size
02156   // Used by both num_put and ostream inserters: if __num,
02157   // internal-adjusted objects are padded according to the rules below
02158   // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
02159   // ones are.
02160 
02161   // NB: Of the two parameters, _CharT can be deduced from the
02162   // function arguments. The other (_Traits) has to be explicitly specified.
02163   template<typename _CharT, typename _Traits>
02164     void 
02165     __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, 
02166                    _CharT* __news, const _CharT* __olds, 
02167                    const streamsize __newlen, 
02168                    const streamsize __oldlen, const bool __num)
02169     {
02170       const size_t __plen = static_cast<size_t>(__newlen - __oldlen);
02171       const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
02172 
02173       // Padding last.
02174       if (__adjust == ios_base::left)
02175     {
02176       _Traits::copy(__news, const_cast<_CharT*>(__olds), __oldlen);
02177       _Traits::assign(__news + __oldlen, __plen, __fill);
02178       return;
02179     }
02180 
02181       size_t __mod = 0;
02182       if (__adjust == ios_base::internal && __num)
02183     {
02184       // Pad after the sign, if there is one.
02185       // Pad after 0[xX], if there is one.
02186       // Who came up with these rules, anyway? Jeeze.
02187           const locale& __loc = __io.getloc();
02188       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
02189       const _CharT __minus = __ctype.widen('-');
02190       const _CharT __plus = __ctype.widen('+');
02191       const bool __testsign = _Traits::eq(__olds[0], __minus)
02192                               || _Traits::eq(__olds[0], __plus);
02193 
02194       const bool __testhex = (_Traits::eq(__ctype.widen('0'), __olds[0])
02195                   && __oldlen > 1
02196                   && (_Traits::eq(__ctype.widen('x'), __olds[1])
02197                       || _Traits::eq(__ctype.widen('X'),
02198                              __olds[1])));
02199       if (__testhex)
02200         {
02201           __news[0] = __olds[0]; 
02202           __news[1] = __olds[1];
02203           __mod = 2;
02204           __news += 2;
02205         }
02206       else if (__testsign)
02207         {
02208           __news[0] = __olds[0];
02209           __mod = 1;
02210           ++__news;
02211         }
02212       // else Padding first.
02213     }
02214       _Traits::assign(__news, __plen, __fill);
02215       _Traits::copy(__news + __plen, const_cast<_CharT*>(__olds + __mod),
02216             __oldlen - __mod);
02217     }
02218 
02219   template<typename _CharT>
02220     bool
02221     __verify_grouping(const basic_string<_CharT>& __grouping, 
02222               basic_string<_CharT>& __grouping_tmp)
02223     { 
02224       const size_t __n = __grouping_tmp.size() - 1;
02225       const size_t __min = std::min(__n, __grouping.size() - 1);
02226       size_t __i = __n;
02227       bool __test = true;
02228 
02229       // Parsed number groupings have to match the
02230       // numpunct::grouping string exactly, starting at the
02231       // right-most point of the parsed sequence of elements ...
02232       for (size_t __j = 0; __j < __min && __test; --__i, ++__j)
02233     __test = __grouping_tmp[__i] == __grouping[__j];
02234       for (; __i && __test; --__i)
02235     __test = __grouping_tmp[__i] == __grouping[__min];
02236       // ... but the last parsed grouping can be <= numpunct
02237       // grouping.
02238       __test &= __grouping_tmp[0] <= __grouping[__min];
02239       return __test;
02240     }
02241 
02242   template<typename _CharT>
02243     _CharT*
02244     __add_grouping(_CharT* __s, _CharT __sep,  
02245            const char* __gbeg, const char* __gend, 
02246            const _CharT* __first, const _CharT* __last)
02247     {
02248       if (__last - __first > *__gbeg)
02249         {
02250           __s = __add_grouping(__s,  __sep, 
02251                    (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1),
02252                    __gend, __first, __last - *__gbeg);
02253           __first = __last - *__gbeg;
02254           *__s++ = __sep;
02255         }
02256       do
02257     *__s++ = *__first++;
02258       while (__first != __last);
02259       return __s;
02260     }
02261 
02262 #if 1
02263       // XXX GLIBCXX_ABI Deprecated, compatibility only.
02264   template<typename _CharT, typename _OutIter>
02265     template<typename _ValueT>
02266       _OutIter
02267       num_put<_CharT, _OutIter>::
02268       _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
02269              char __modl, _ValueT __v) const
02270       {
02271     // [22.2.2.2.2] Stage 1, numeric conversion to character.
02272 
02273     // Long enough for the max format spec.
02274     char __fbuf[16];
02275     _S_format_int(__io, __fbuf, __mod, __modl);
02276 #ifdef _GLIBCPP_USE_C99
02277     // First try a buffer perhaps big enough.
02278     int __cs_size = 64;
02279     char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
02280     int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
02281                      _S_c_locale);
02282     // If the buffer was not large enough, try again with the correct size.
02283     if (__len >= __cs_size)
02284       {
02285         __cs_size = __len + 1;
02286         __cs = static_cast<char*>(__builtin_alloca(__cs_size));
02287         __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
02288                      _S_c_locale);
02289       }
02290 #else
02291     // Leave room for "+/-," "0x," and commas. This size is
02292     // arbitrary, but should be largely sufficient.
02293     char __cs[128];
02294     int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale);
02295 #endif
02296     return _M_widen_int(__s, __io, __fill, __cs, __len);
02297       }
02298 
02299   template<typename _CharT, typename _OutIter>
02300     _OutIter
02301     num_put<_CharT, _OutIter>::
02302     _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 
02303            int __len) const
02304     {
02305       typedef char_traits<_CharT>       __traits_type;
02306       // [22.2.2.2.2] Stage 2, convert to char_type, using correct
02307       // numpunct.decimal_point() values for '.' and adding grouping.
02308       const locale __loc = __io.getloc();
02309       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
02310       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
02311                                * __len));
02312       // Grouping can add (almost) as many separators as the number of
02313       // digits, but no more.
02314       _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
02315                                 * __len * 2));
02316       __ctype.widen(__cs, __cs + __len, __ws);
02317       
02318       // Replace decimal point.
02319       const _CharT* __p;
02320       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
02321       if (__p = __traits_type::find(__ws, __len, __ctype.widen('.')))
02322     __ws[__p - __ws] = __np.decimal_point();
02323 
02324 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
02325 //282. What types does numpunct grouping refer to?
02326       // Add grouping, if necessary. 
02327       const string __grouping = __np.grouping();
02328       if (__grouping.size())
02329     {
02330       _CharT* __p2;
02331       int __declen = __p ? __p - __ws : __len;
02332       __p2 = __add_grouping(__ws2, __np.thousands_sep(), 
02333                 __grouping.c_str(),
02334                 __grouping.c_str() + __grouping.size(),
02335                 __ws, __ws + __declen);
02336       int __newlen = __p2 - __ws2;
02337     
02338       // Tack on decimal part.
02339       if (__p)
02340         {
02341           __traits_type::copy(__p2, __p, __len - __declen);
02342           __newlen += __len - __declen;
02343         }    
02344 
02345       // Switch strings, establish correct new length.
02346       __ws = __ws2;
02347       __len = __newlen;
02348     }
02349 #endif
02350       return _M_insert(__s, __io, __fill, __ws, __len);
02351     }
02352 
02353   template<typename _CharT, typename _OutIter>
02354     _OutIter
02355     num_put<_CharT, _OutIter>::
02356     _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 
02357          int __len) const
02358     {
02359       // [22.2.2.2.2] Stage 2, convert to char_type, using correct
02360       // numpunct.decimal_point() values for '.' and adding grouping.
02361       const locale __loc = __io.getloc();
02362       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
02363       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
02364                                * __len));
02365       // Grouping can add (almost) as many separators as the number of
02366       // digits, but no more.
02367       _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
02368                                 * __len * 2));
02369       __ctype.widen(__cs, __cs + __len, __ws);
02370 
02371       // Add grouping, if necessary. 
02372       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
02373       const string __grouping = __np.grouping();
02374       if (__grouping.size())
02375     {
02376       // By itself __add_grouping cannot deal correctly with __ws when
02377       // ios::showbase is set and ios_base::oct || ios_base::hex.
02378       // Therefore we take care "by hand" of the initial 0, 0x or 0X.
02379       // However, remember that the latter do not occur if the number
02380       // printed is '0' (__len == 1).
02381       streamsize __off = 0;
02382       const ios_base::fmtflags __basefield = __io.flags() 
02383                              & ios_base::basefield;
02384       if ((__io.flags() & ios_base::showbase) && __len > 1)
02385         if (__basefield == ios_base::oct)
02386           {
02387         __off = 1;
02388         *__ws2 = *__ws;
02389           }
02390         else if (__basefield == ios_base::hex)
02391           {
02392         __off = 2;
02393         *__ws2 = *__ws;
02394         *(__ws2 + 1) = *(__ws + 1);
02395           }
02396       _CharT* __p;
02397       __p = __add_grouping(__ws2 + __off, __np.thousands_sep(), 
02398                    __grouping.c_str(),
02399                    __grouping.c_str() + __grouping.size(),
02400                    __ws + __off, __ws + __len);
02401       __len = __p - __ws2;
02402       // Switch strings.
02403       __ws = __ws2;
02404     }
02405       return _M_insert(__s, __io, __fill, __ws, __len);
02406     }
02407 
02408   // For use by integer and floating-point types after they have been
02409   // converted into a char_type string.
02410   template<typename _CharT, typename _OutIter>
02411     _OutIter
02412     num_put<_CharT, _OutIter>::
02413     _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, 
02414           int __len) const
02415     {
02416       typedef char_traits<_CharT>       __traits_type;
02417       // [22.2.2.2.2] Stage 3.
02418       // If necessary, pad.
02419       streamsize __w = __io.width();
02420       _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
02421                                 * __w));
02422       if (__w > static_cast<streamsize>(__len))
02423     {
02424       __pad<_CharT, __traits_type>::_S_pad(__io, __fill, __ws2, __ws, 
02425                            __w, __len, true);
02426       __len = static_cast<int>(__w);
02427       // Switch strings.
02428       __ws = __ws2;
02429     }
02430       __io.width(0);
02431 
02432       // [22.2.2.2.2] Stage 4.
02433       // Write resulting, fully-formatted string to output iterator.
02434       return __write(__s, __ws, __len);
02435     }
02436 #endif
02437 
02438   template<typename _CharT>
02439     __locale_cache<numpunct<_CharT> >::__locale_cache(const locale& __loc)
02440       : _M_truename(0), _M_falsename(0), _M_use_grouping(false),
02441     _M_grouping(0)
02442     {
02443       if (has_facet<numpunct<_CharT> >(__loc))
02444     {
02445       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
02446       _M_decimal_point = __np.decimal_point();
02447       _M_thousands_sep = __np.thousands_sep();
02448 
02449       string_type __false = __np.falsename();
02450       _CharT* __falsename = new _CharT[__false.length() + 1];
02451       __false.copy(__falsename, __false.length());
02452       __falsename[__false.length()] = _CharT();
02453       _M_falsename = __falsename;
02454 
02455       string_type __true = __np.truename();
02456       _CharT* __truename = new _CharT[__true.length() + 1];
02457       __true.copy(__truename, __true.length());
02458       __truename[__true.length()] = _CharT();
02459       _M_truename = __truename;
02460 
02461       string __grouping = __np.grouping();
02462       char* __group = new char[__grouping.length() + 1];
02463       __grouping.copy(__group, __grouping.length());
02464       __group[__grouping.length()] = 0;
02465       _M_grouping = __group;
02466 
02467       _M_use_grouping = __grouping.length() != 0 
02468         && __grouping.data()[0] != 0;
02469     }
02470 
02471       if (has_facet<ctype<_CharT> >(__loc))
02472     {
02473       const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
02474       __ct.widen(__num_base::_S_atoms_out,
02475              __num_base::_S_atoms_out + __num_base::_S_end, 
02476              _M_atoms_out);
02477     }
02478     }
02479 
02480   // Static locale cache initialization.  Only instantiated with char
02481   // and wchar_t, so no need to check has_facet.
02482   template<typename _CharT>
02483     __locale_cache<numpunct<_CharT> >::
02484     __locale_cache(const locale& __loc, bool)
02485     {
02486       // Grab pointers to numpunct static strings
02487       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
02488       _M_thousands_sep = __np._M_thousands_sep;
02489       _M_decimal_point = __np._M_decimal_point;
02490       _M_falsename = __np._M_falsename;
02491       _M_truename = __np._M_truename;
02492       _M_grouping = __np._M_grouping;
02493       _M_use_grouping = false;
02494 
02495       const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
02496       __ct.widen(__num_base::_S_atoms_out,
02497          __num_base::_S_atoms_out + __num_base::_S_end, 
02498          _M_atoms_out);
02499     }
02500 
02501   // Inhibit implicit instantiations for required instantiations,
02502   // which are defined via explicit instantiations elsewhere.  
02503   // NB: This syntax is a GNU extension.
02504 #if _GLIBCPP_EXTERN_TEMPLATE
02505   extern template class moneypunct<char, false>;
02506   extern template class moneypunct<char, true>;
02507   extern template class moneypunct_byname<char, false>;
02508   extern template class moneypunct_byname<char, true>;
02509   extern template class money_get<char>;
02510   extern template class money_put<char>;
02511   extern template class numpunct<char>;
02512   extern template class numpunct_byname<char>;
02513   extern template class num_get<char>;
02514   extern template class num_put<char>; 
02515   extern template class __timepunct<char>;
02516   extern template class time_put<char>;
02517   extern template class time_put_byname<char>;
02518   extern template class time_get<char>;
02519   extern template class time_get_byname<char>;
02520   extern template class messages<char>;
02521   extern template class messages_byname<char>;
02522   extern template class ctype_byname<char>;
02523   extern template class codecvt_byname<char, char, mbstate_t>;
02524   extern template class collate<char>;
02525   extern template class collate_byname<char>;
02526 
02527   extern template
02528     const codecvt<char, char, mbstate_t>& 
02529     use_facet<codecvt<char, char, mbstate_t> >(const locale&);
02530 
02531   extern template
02532     const collate<char>& 
02533     use_facet<collate<char> >(const locale&);
02534 
02535   extern template
02536     const numpunct<char>& 
02537     use_facet<numpunct<char> >(const locale&);
02538 
02539   extern template 
02540     const num_put<char>& 
02541     use_facet<num_put<char> >(const locale&);
02542 
02543   extern template 
02544     const num_get<char>& 
02545     use_facet<num_get<char> >(const locale&);
02546 
02547   extern template
02548     const moneypunct<char, true>& 
02549     use_facet<moneypunct<char, true> >(const locale&);
02550 
02551   extern template
02552     const moneypunct<char, false>& 
02553     use_facet<moneypunct<char, false> >(const locale&);
02554 
02555   extern template 
02556     const money_put<char>& 
02557     use_facet<money_put<char> >(const locale&);
02558 
02559   extern template 
02560     const money_get<char>& 
02561     use_facet<money_get<char> >(const locale&);
02562 
02563   extern template
02564     const __timepunct<char>& 
02565     use_facet<__timepunct<char> >(const locale&);
02566 
02567   extern template 
02568     const time_put<char>& 
02569     use_facet<time_put<char> >(const locale&);
02570 
02571   extern template 
02572     const time_get<char>& 
02573     use_facet<time_get<char> >(const locale&);
02574 
02575   extern template 
02576     const messages<char>& 
02577     use_facet<messages<char> >(const locale&);
02578 
02579   extern template 
02580     bool
02581     has_facet<ctype<char> >(const locale&);
02582 
02583   extern template 
02584     bool
02585     has_facet<codecvt<char, char, mbstate_t> >(const locale&);
02586 
02587   extern template 
02588     bool
02589     has_facet<collate<char> >(const locale&);
02590 
02591   extern template 
02592     bool
02593     has_facet<numpunct<char> >(const locale&);
02594 
02595   extern template 
02596     bool
02597     has_facet<num_put<char> >(const locale&);
02598 
02599   extern template 
02600     bool
02601     has_facet<num_get<char> >(const locale&);
02602 
02603   extern template 
02604     bool
02605     has_facet<moneypunct<char> >(const locale&);
02606 
02607   extern template 
02608     bool
02609     has_facet<money_put<char> >(const locale&);
02610 
02611   extern template 
02612     bool
02613     has_facet<money_get<char> >(const locale&);
02614 
02615   extern template 
02616     bool
02617     has_facet<__timepunct<char> >(const locale&);
02618 
02619   extern template 
02620     bool
02621     has_facet<time_put<char> >(const locale&);
02622 
02623   extern template 
02624     bool
02625     has_facet<time_get<char> >(const locale&);
02626 
02627   extern template 
02628     bool
02629     has_facet<messages<char> >(const locale&);
02630 
02631 #ifdef _GLIBCPP_USE_WCHAR_T
02632   extern template class moneypunct<wchar_t, false>;
02633   extern template class moneypunct<wchar_t, true>;
02634   extern template class moneypunct_byname<wchar_t, false>;
02635   extern template class moneypunct_byname<wchar_t, true>;
02636   extern template class money_get<wchar_t>;
02637   extern template class money_put<wchar_t>;
02638   extern template class numpunct<wchar_t>;
02639   extern template class numpunct_byname<wchar_t>;
02640   extern template class num_get<wchar_t>;
02641   extern template class num_put<wchar_t>;
02642   extern template class __timepunct<wchar_t>;
02643   extern template class time_put<wchar_t>;
02644   extern template class time_put_byname<wchar_t>;
02645   extern template class time_get<wchar_t>;
02646   extern template class time_get_byname<wchar_t>;
02647   extern template class messages<wchar_t>;
02648   extern template class messages_byname<wchar_t>;
02649   extern template class ctype_byname<wchar_t>;
02650   extern template class codecvt_byname<wchar_t, char, mbstate_t>;
02651   extern template class collate<wchar_t>;
02652   extern template class collate_byname<wchar_t>;
02653 
02654   extern template
02655     const codecvt<wchar_t, char, mbstate_t>& 
02656     use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&);
02657 
02658   extern template
02659     const collate<wchar_t>& 
02660     use_facet<collate<wchar_t> >(const locale&);
02661 
02662   extern template
02663     const numpunct<wchar_t>& 
02664     use_facet<numpunct<wchar_t> >(const locale&);
02665 
02666   extern template 
02667     const num_put<wchar_t>& 
02668     use_facet<num_put<wchar_t> >(const locale&);
02669 
02670   extern template 
02671     const num_get<wchar_t>& 
02672     use_facet<num_get<wchar_t> >(const locale&);
02673 
02674   extern template
02675     const moneypunct<wchar_t, true>& 
02676     use_facet<moneypunct<wchar_t, true> >(const locale&);
02677 
02678   extern template
02679     const moneypunct<wchar_t, false>& 
02680     use_facet<moneypunct<wchar_t, false> >(const locale&);
02681  
02682   extern template 
02683     const money_put<wchar_t>& 
02684     use_facet<money_put<wchar_t> >(const locale&);
02685 
02686   extern template 
02687     const money_get<wchar_t>& 
02688     use_facet<money_get<wchar_t> >(const locale&);
02689 
02690   extern template
02691     const __timepunct<wchar_t>& 
02692     use_facet<__timepunct<wchar_t> >(const locale&);
02693 
02694   extern template 
02695     const time_put<wchar_t>& 
02696     use_facet<time_put<wchar_t> >(const locale&);
02697 
02698   extern template 
02699     const time_get<wchar_t>& 
02700     use_facet<time_get<wchar_t> >(const locale&);
02701 
02702   extern template 
02703     const messages<wchar_t>& 
02704     use_facet<messages<wchar_t> >(const locale&);
02705 
02706  extern template 
02707     bool
02708     has_facet<ctype<wchar_t> >(const locale&);
02709 
02710   extern template 
02711     bool
02712     has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
02713 
02714   extern template 
02715     bool
02716     has_facet<collate<wchar_t> >(const locale&);
02717 
02718   extern template 
02719     bool
02720     has_facet<numpunct<wchar_t> >(const locale&);
02721 
02722   extern template 
02723     bool
02724     has_facet<num_put<wchar_t> >(const locale&);
02725 
02726   extern template 
02727     bool
02728     has_facet<num_get<wchar_t> >(const locale&);
02729 
02730   extern template 
02731     bool
02732     has_facet<moneypunct<wchar_t> >(const locale&);
02733 
02734   extern template 
02735     bool
02736     has_facet<money_put<wchar_t> >(const locale&);
02737 
02738   extern template 
02739     bool
02740     has_facet<money_get<wchar_t> >(const locale&);
02741 
02742   extern template 
02743     bool
02744     has_facet<__timepunct<wchar_t> >(const locale&);
02745 
02746   extern template 
02747     bool
02748     has_facet<time_put<wchar_t> >(const locale&);
02749 
02750   extern template 
02751     bool
02752     has_facet<time_get<wchar_t> >(const locale&);
02753 
02754   extern template 
02755     bool
02756     has_facet<messages<wchar_t> >(const locale&);
02757 #endif
02758 #endif
02759 } // namespace std
02760 
02761 #endif

Generated on Sat Mar 19 19:39:58 2005 for libstdc++-v3 Source by  doxygen 1.4.1