This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch] Start splitting out the facets


Hi,

the below starts on the idea, mentioned a few days ago, of splitting the large locale_facets to separate files, in order to minimize the size of the iostreams headers. As is, removes about 70 KB of unused code from the pre-processed <ios>, <iostream>, <fstream>, ... Of course further tweaks seem possible, finer grained splits, etc, but we want to proceed incrementally, to be safe. Benjamin, looks good to you? Other proposals for the names of the new files?

Tested x86_64-linux, without PCHs, both locale models.

Paolo.

///////////////////
2007-04-23  Paolo Carlini  <pcarlini@suse.de>

	* include/bits/locale_facets.h (class time_base,
	struct __timepunct_cache, class __timepunct, class time_get,
	class time_get_byname, class time_put, class time_put_byname,
	class money_base, struct __moneypunct_cache, class moneypunct,
	class moneypunct_byname, class money_get, class money_put,
	struct messages_base, class messages, class messages_byname): Move...
	* include/bits/non_io_facets.h: ... here.
	* include/bits/locale_facets.tcc
	(struct __use_cache<__moneypunct_cache<> >,
	__moneypunct_cache<>::_M_cache, money_get<>::_M_extract,
	money_get<>::__do_get, money_get<>::do_get, money_put<>::_M_insert,
	money_put<>::__do_put, money_put<>::do_put, time_get<>::do_date_order,
	time_get<>::_M_extract_via_format, time_get<>::_M_extract_num,
	time_get<>::_M_extract_name, time_get<>::do_get_time,
	time_get<>::do_get_date, time_get<>::do_get_weekday,
	time_get<>::do_get_monthname, time_get<>::do_get_year, time_put<>::put,
	time_put<>::do_put): Move...
	* include/bits/non_io_facets.tcc: ... here.
	* include/Makefile.am: Add.
	* include/std/locale: Adjust includes.
	* include/std/fstream: Likewise.
	* include/std/istream: Likewise.
	* include/std/ostream: Likewise.
	* include/Makefile.in: Regenerate.
Index: include/bits/locale_facets.tcc
===================================================================
--- include/bits/locale_facets.tcc	(revision 124039)
+++ include/bits/locale_facets.tcc	(working copy)
@@ -39,10 +39,6 @@
 
 #pragma GCC system_header
 
-#include <ext/type_traits.h>
-#include <ext/numeric_traits.h>
-#include <bits/streambuf_iterator.h>
-
 _GLIBCXX_BEGIN_NAMESPACE(std)
 
   template<typename _Facet>
@@ -154,34 +150,6 @@
       }
     };
 
-  template<typename _CharT, bool _Intl>
-    struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
-    {
-      const __moneypunct_cache<_CharT, _Intl>*
-      operator() (const locale& __loc) const
-      {
-	const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
-	const locale::facet** __caches = __loc._M_impl->_M_caches;
-	if (!__caches[__i])
-	  {
-	    __moneypunct_cache<_CharT, _Intl>* __tmp = NULL;
-	    try
-	      {
-		__tmp = new __moneypunct_cache<_CharT, _Intl>;
-		__tmp->_M_cache(__loc);
-	      }
-	    catch(...)
-	      {
-		delete __tmp;
-		__throw_exception_again;
-	      }
-	    __loc._M_impl->_M_install_cache(__tmp, __i);
-	  }
-	return static_cast<
-	  const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
-      }
-    };
-
   template<typename _CharT>
     void
     __numpunct_cache<_CharT>::_M_cache(const locale& __loc)
@@ -217,50 +185,6 @@
 		 __num_base::_S_atoms_in + __num_base::_S_iend, _M_atoms_in);
     }
 
-  template<typename _CharT, bool _Intl>
-    void
-    __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
-    {
-      _M_allocated = true;
-
-      const moneypunct<_CharT, _Intl>& __mp =
-	use_facet<moneypunct<_CharT, _Intl> >(__loc);
-
-      _M_grouping_size = __mp.grouping().size();
-      char* __grouping = new char[_M_grouping_size];
-      __mp.grouping().copy(__grouping, _M_grouping_size);
-      _M_grouping = __grouping;
-      _M_use_grouping = (_M_grouping_size
-			 && static_cast<signed char>(__mp.grouping()[0]) > 0);
-      
-      _M_decimal_point = __mp.decimal_point();
-      _M_thousands_sep = __mp.thousands_sep();
-      _M_frac_digits = __mp.frac_digits();
-      
-      _M_curr_symbol_size = __mp.curr_symbol().size();
-      _CharT* __curr_symbol = new _CharT[_M_curr_symbol_size];
-      __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size);
-      _M_curr_symbol = __curr_symbol;
-      
-      _M_positive_sign_size = __mp.positive_sign().size();
-      _CharT* __positive_sign = new _CharT[_M_positive_sign_size];
-      __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size);
-      _M_positive_sign = __positive_sign;
-
-      _M_negative_sign_size = __mp.negative_sign().size();
-      _CharT* __negative_sign = new _CharT[_M_negative_sign_size];
-      __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size);
-      _M_negative_sign = __negative_sign;
-      
-      _M_pos_format = __mp.pos_format();
-      _M_neg_format = __mp.neg_format();
-
-      const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
-      __ct.widen(money_base::_S_atoms,
-		 money_base::_S_atoms + money_base::_S_end, _M_atoms);
-    }
-
-
   // Used by both numeric and monetary facets.
   // Check to make sure that the __grouping_tmp string constructed in
   // money_get or num_get matches the canonical grouping for a given
@@ -502,10 +426,6 @@
       return __beg;
     }
 
-_GLIBCXX_END_LDBL_NAMESPACE
-
-_GLIBCXX_BEGIN_LDBL_NAMESPACE
-
   template<typename _CharT, typename _InIter>
     template<typename _ValueT>
       _InIter
@@ -1330,1064 +1250,8 @@
       return __s;
     }
 
-  template<typename _CharT, typename _InIter>
-    template<bool _Intl>
-      _InIter
-      money_get<_CharT, _InIter>::
-      _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
-		 ios_base::iostate& __err, string& __units) const
-      {
-	typedef char_traits<_CharT>			  __traits_type;
-	typedef typename string_type::size_type	          size_type;	
-	typedef money_base::part			  part;
-	typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
-	
-	const locale& __loc = __io._M_getloc();
-	const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
-
-	__use_cache<__cache_type> __uc;
-	const __cache_type* __lc = __uc(__loc);
-	const char_type* __lit = __lc->_M_atoms;
-
-	// Deduced sign.
-	bool __negative = false;
-	// Sign size.
-	size_type __sign_size = 0;
-	// True if sign is mandatory.
-	const bool __mandatory_sign = (__lc->_M_positive_sign_size
-				       && __lc->_M_negative_sign_size);
-	// String of grouping info from thousands_sep plucked from __units.
-	string __grouping_tmp;
-	if (__lc->_M_use_grouping)
-	  __grouping_tmp.reserve(32);
-	// Last position before the decimal point.
-	int __last_pos = 0;
-	// Separator positions, then, possibly, fractional digits.
-	int __n = 0;
-	// If input iterator is in a valid state.
-	bool __testvalid = true;
-	// Flag marking when a decimal point is found.
-	bool __testdecfound = false;
-
-	// The tentative returned string is stored here.
-	string __res;
-	__res.reserve(32);
-
-	const char_type* __lit_zero = __lit + money_base::_S_zero;
-	const money_base::pattern __p = __lc->_M_neg_format;
-	for (int __i = 0; __i < 4 && __testvalid; ++__i)
-	  {
-	    const part __which = static_cast<part>(__p.field[__i]);
-	    switch (__which)
-	      {
-	      case money_base::symbol:
-		// According to 22.2.6.1.2, p2, symbol is required
-		// if (__io.flags() & ios_base::showbase), otherwise
-		// is optional and consumed only if other characters
-		// are needed to complete the format.
-		if (__io.flags() & ios_base::showbase || __sign_size > 1
-		    || __i == 0
-		    || (__i == 1 && (__mandatory_sign
-				     || (static_cast<part>(__p.field[0])
-					 == money_base::sign)
-				     || (static_cast<part>(__p.field[2])
-					 == money_base::space)))
-		    || (__i == 2 && ((static_cast<part>(__p.field[3])
-				      == money_base::value)
-				     || (__mandatory_sign
-					 && (static_cast<part>(__p.field[3])
-					     == money_base::sign)))))
-		  {
-		    const size_type __len = __lc->_M_curr_symbol_size;
-		    size_type __j = 0;
-		    for (; __beg != __end && __j < __len
-			   && *__beg == __lc->_M_curr_symbol[__j];
-			 ++__beg, ++__j);
-		    if (__j != __len
-			&& (__j || __io.flags() & ios_base::showbase))
-		      __testvalid = false;
-		  }
-		break;
-	      case money_base::sign:
-		// Sign might not exist, or be more than one character long.
-		if (__lc->_M_positive_sign_size && __beg != __end
-		    && *__beg == __lc->_M_positive_sign[0])
-		  {
-		    __sign_size = __lc->_M_positive_sign_size;
-		    ++__beg;
-		  }
-		else if (__lc->_M_negative_sign_size && __beg != __end
-			 && *__beg == __lc->_M_negative_sign[0])
-		  {
-		    __negative = true;
-		    __sign_size = __lc->_M_negative_sign_size;
-		    ++__beg;
-		  }
-		else if (__lc->_M_positive_sign_size
-			 && !__lc->_M_negative_sign_size)
-		  // "... if no sign is detected, the result is given the sign
-		  // that corresponds to the source of the empty string"
-		  __negative = true;
-		else if (__mandatory_sign)
-		  __testvalid = false;
-		break;
-	      case money_base::value:
-		// Extract digits, remove and stash away the
-		// grouping of found thousands separators.
-		for (; __beg != __end; ++__beg)
-		  {
-		    const char_type __c = *__beg;
-		    const char_type* __q = __traits_type::find(__lit_zero, 
-							       10, __c);
-		    if (__q != 0)
-		      {
-			__res += money_base::_S_atoms[__q - __lit];
-			++__n;
-		      }
-		    else if (__c == __lc->_M_decimal_point 
-			     && !__testdecfound)
-		      {
-			__last_pos = __n;
-			__n = 0;
-			__testdecfound = true;
-		      }
-		    else if (__lc->_M_use_grouping
-			     && __c == __lc->_M_thousands_sep
-			     && !__testdecfound)
-		      {
-			if (__n)
-			  {
-			    // Mark position for later analysis.
-			    __grouping_tmp += static_cast<char>(__n);
-			    __n = 0;
-			  }
-			else
-			  {
-			    __testvalid = false;
-			    break;
-			  }
-		      }
-		    else
-		      break;
-		  }
-		if (__res.empty())
-		  __testvalid = false;
-		break;
-	      case money_base::space:
-		// At least one space is required.
-		if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
-		  ++__beg;
-		else
-		  __testvalid = false;
-	      case money_base::none:
-		// Only if not at the end of the pattern.
-		if (__i != 3)
-		  for (; __beg != __end
-			 && __ctype.is(ctype_base::space, *__beg); ++__beg);
-		break;
-	      }
-	  }
-
-	// Need to get the rest of the sign characters, if they exist.
-	if (__sign_size > 1 && __testvalid)
-	  {
-	    const char_type* __sign = __negative ? __lc->_M_negative_sign
-	                                         : __lc->_M_positive_sign;
-	    size_type __i = 1;
-	    for (; __beg != __end && __i < __sign_size
-		   && *__beg == __sign[__i]; ++__beg, ++__i);
-	    
-	    if (__i != __sign_size)
-	      __testvalid = false;
-	  }
-
-	if (__testvalid)
-	  {
-	    // Strip leading zeros.
-	    if (__res.size() > 1)
-	      {
-		const size_type __first = __res.find_first_not_of('0');
-		const bool __only_zeros = __first == string::npos;
-		if (__first)
-		  __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
-	      }
-
-	    // 22.2.6.1.2, p4
-	    if (__negative && __res[0] != '0')
-	      __res.insert(__res.begin(), '-');
-	    
-	    // Test for grouping fidelity.
-	    if (__grouping_tmp.size())
-	      {
-		// Add the ending grouping.
-		__grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
-						                   : __n);
-		if (!std::__verify_grouping(__lc->_M_grouping,
-					    __lc->_M_grouping_size,
-					    __grouping_tmp))
-		  __err |= ios_base::failbit;
-	      }
-	    
-	    // Iff not enough digits were supplied after the decimal-point.
-	    if (__testdecfound && __lc->_M_frac_digits > 0
-		&& __n != __lc->_M_frac_digits)
-	      __testvalid = false;
-	  }
-	
-	// Iff valid sequence is not recognized.
-	if (!__testvalid)
-	  __err |= ios_base::failbit;
-	else
-	  __units.swap(__res);
-	
-	// Iff no more characters are available.
-	if (__beg == __end)
-	  __err |= ios_base::eofbit;
-	return __beg;
-      }
-
-#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
-  template<typename _CharT, typename _InIter>
-    _InIter
-    money_get<_CharT, _InIter>::
-    __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
-	     ios_base::iostate& __err, double& __units) const
-    {
-      string __str;
-      __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
-                     : _M_extract<false>(__beg, __end, __io, __err, __str);
-      std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
-      return __beg;
-    }
-#endif
-
-  template<typename _CharT, typename _InIter>
-    _InIter
-    money_get<_CharT, _InIter>::
-    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
-	   ios_base::iostate& __err, long double& __units) const
-    {
-      string __str;
-      __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
-	             : _M_extract<false>(__beg, __end, __io, __err, __str);
-      std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
-      return __beg;
-    }
-
-  template<typename _CharT, typename _InIter>
-    _InIter
-    money_get<_CharT, _InIter>::
-    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
-	   ios_base::iostate& __err, string_type& __digits) const
-    {
-      typedef typename string::size_type                  size_type;
-
-      const locale& __loc = __io._M_getloc();
-      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
-
-      string __str;
-      __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
-	             : _M_extract<false>(__beg, __end, __io, __err, __str);
-      const size_type __len = __str.size();
-      if (__len)
-	{
-	  __digits.resize(__len);
-	  __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]);
-	}
-      return __beg;
-    }
-
-  template<typename _CharT, typename _OutIter>
-    template<bool _Intl>
-      _OutIter
-      money_put<_CharT, _OutIter>::
-      _M_insert(iter_type __s, ios_base& __io, char_type __fill,
-		const string_type& __digits) const
-      {
-	typedef typename string_type::size_type	          size_type;
-	typedef money_base::part                          part;
-	typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
-      
-	const locale& __loc = __io._M_getloc();
-	const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
-
-	__use_cache<__cache_type> __uc;
-	const __cache_type* __lc = __uc(__loc);
-	const char_type* __lit = __lc->_M_atoms;
-
-	// Determine if negative or positive formats are to be used, and
-	// discard leading negative_sign if it is present.
-	const char_type* __beg = __digits.data();
-
-	money_base::pattern __p;
-	const char_type* __sign;
-	size_type __sign_size;
-	if (!(*__beg == __lit[money_base::_S_minus]))
-	  {
-	    __p = __lc->_M_pos_format;
-	    __sign = __lc->_M_positive_sign;
-	    __sign_size = __lc->_M_positive_sign_size;
-	  }
-	else
-	  {
-	    __p = __lc->_M_neg_format;
-	    __sign = __lc->_M_negative_sign;
-	    __sign_size = __lc->_M_negative_sign_size;
-	    if (__digits.size())
-	      ++__beg;
-	  }
-       
-	// Look for valid numbers in the ctype facet within input digits.
-	size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
-					   __beg + __digits.size()) - __beg;
-	if (__len)
-	  {
-	    // Assume valid input, and attempt to format.
-	    // Break down input numbers into base components, as follows:
-	    //   final_value = grouped units + (decimal point) + (digits)
-	    string_type __value;
-	    __value.reserve(2 * __len);
-
-	    // Add thousands separators to non-decimal digits, per
-	    // grouping rules.
-	    long __paddec = __len - __lc->_M_frac_digits;
-	    if (__paddec > 0)
-  	      {
-		if (__lc->_M_frac_digits < 0)
-		  __paddec = __len;
-  		if (__lc->_M_grouping_size)
-  		  {
-		    __value.assign(2 * __paddec, char_type());
- 		    _CharT* __vend = 
-		      std::__add_grouping(&__value[0], __lc->_M_thousands_sep,
-					  __lc->_M_grouping,
-					  __lc->_M_grouping_size,
-					  __beg, __beg + __paddec);
-		    __value.erase(__vend - &__value[0]);
-  		  }
-  		else
-		  __value.assign(__beg, __paddec);
-	      }
-
-	    // Deal with decimal point, decimal digits.
-	    if (__lc->_M_frac_digits > 0)
-	      {
-		__value += __lc->_M_decimal_point;
-		if (__paddec >= 0)
-		  __value.append(__beg + __paddec, __lc->_M_frac_digits);
-		else
-		  {
-		    // Have to pad zeros in the decimal position.
-		    __value.append(-__paddec, __lit[money_base::_S_zero]);
-		    __value.append(__beg, __len);
-		  }
-  	      }
-  
-	    // Calculate length of resulting string.
-	    const ios_base::fmtflags __f = __io.flags() 
-	                                   & ios_base::adjustfield;
-	    __len = __value.size() + __sign_size;
-	    __len += ((__io.flags() & ios_base::showbase)
-		      ? __lc->_M_curr_symbol_size : 0);
-
-	    string_type __res;
-	    __res.reserve(2 * __len);
-	    
-	    const size_type __width = static_cast<size_type>(__io.width());  
-	    const bool __testipad = (__f == ios_base::internal
-				     && __len < __width);
-	    // Fit formatted digits into the required pattern.
-	    for (int __i = 0; __i < 4; ++__i)
-	      {
-		const part __which = static_cast<part>(__p.field[__i]);
-		switch (__which)
-		  {
-		  case money_base::symbol:
-		    if (__io.flags() & ios_base::showbase)
-		      __res.append(__lc->_M_curr_symbol,
-				   __lc->_M_curr_symbol_size);
-		    break;
-		  case money_base::sign:
-		    // Sign might not exist, or be more than one
-		    // charater long. In that case, add in the rest
-		    // below.
-		    if (__sign_size)
-		      __res += __sign[0];
-		    break;
-		  case money_base::value:
-		    __res += __value;
-		    break;
-		  case money_base::space:
-		    // At least one space is required, but if internal
-		    // formatting is required, an arbitrary number of
-		    // fill spaces will be necessary.
-		    if (__testipad)
-		      __res.append(__width - __len, __fill);
-		    else
-		      __res += __fill;
-		    break;
-		  case money_base::none:
-		    if (__testipad)
-		      __res.append(__width - __len, __fill);
-		    break;
-		  }
-	      }
-	    
-	    // Special case of multi-part sign parts.
-	    if (__sign_size > 1)
-	      __res.append(__sign + 1, __sign_size - 1);
-	    
-	    // Pad, if still necessary.
-	    __len = __res.size();
-	    if (__width > __len)
-	      {
-		if (__f == ios_base::left)
-		  // After.
-		  __res.append(__width - __len, __fill);
-		else
-		  // Before.
-		  __res.insert(0, __width - __len, __fill);
-		__len = __width;
-	      }
-	    
-	    // Write resulting, fully-formatted string to output iterator.
-	    __s = std::__write(__s, __res.data(), __len);
-	  }
-	__io.width(0);
-	return __s;    
-      }
-
-#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
-  template<typename _CharT, typename _OutIter>
-    _OutIter
-    money_put<_CharT, _OutIter>::
-    __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
-	     double __units) const
-    { return this->do_put(__s, __intl, __io, __fill, (long double) __units); }
-#endif
-
-  template<typename _CharT, typename _OutIter>
-    _OutIter
-    money_put<_CharT, _OutIter>::
-    do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
-	   long double __units) const
-    {
-      const locale __loc = __io.getloc();
-      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
-#ifdef _GLIBCXX_USE_C99
-      // First try a buffer perhaps big enough.
-      int __cs_size = 64;
-      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
-      // _GLIBCXX_RESOLVE_LIB_DEFECTS
-      // 328. Bad sprintf format modifier in money_put<>::do_put()
-      int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
-					"%.*Lf", 0, __units);
-      // If the buffer was not large enough, try again with the correct size.
-      if (__len >= __cs_size)
-	{
-	  __cs_size = __len + 1;
-	  __cs = static_cast<char*>(__builtin_alloca(__cs_size));
-	  __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
-					"%.*Lf", 0, __units);
-	}
-#else
-      // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
-      const int __cs_size =
-	__gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
-      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
-      int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf", 
-					0, __units);
-#endif
-      string_type __digits(__len, char_type());
-      __ctype.widen(__cs, __cs + __len, &__digits[0]);
-      return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
-	            : _M_insert<false>(__s, __io, __fill, __digits);
-    }
-
-  template<typename _CharT, typename _OutIter>
-    _OutIter
-    money_put<_CharT, _OutIter>::
-    do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
-	   const string_type& __digits) const
-    { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
-	            : _M_insert<false>(__s, __io, __fill, __digits); }
-
 _GLIBCXX_END_LDBL_NAMESPACE
 
-  // NB: Not especially useful. Without an ios_base object or some
-  // kind of locale reference, we are left clawing at the air where
-  // the side of the mountain used to be...
-  template<typename _CharT, typename _InIter>
-    time_base::dateorder
-    time_get<_CharT, _InIter>::do_date_order() const
-    { return time_base::no_order; }
-
-  // Expand a strftime format string and parse it.  E.g., do_get_date() may
-  // pass %m/%d/%Y => extracted characters.
-  template<typename _CharT, typename _InIter>
-    _InIter
-    time_get<_CharT, _InIter>::
-    _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
-			  ios_base::iostate& __err, tm* __tm,
-			  const _CharT* __format) const
-    {
-      const locale& __loc = __io._M_getloc();
-      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
-      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
-      const size_t __len = char_traits<_CharT>::length(__format);
-
-      ios_base::iostate __tmperr = ios_base::goodbit;
-      for (size_t __i = 0; __beg != __end && __i < __len && !__tmperr; ++__i)
-	{
-	  if (__ctype.narrow(__format[__i], 0) == '%')
-	    {
-	      // Verify valid formatting code, attempt to extract.
-	      char __c = __ctype.narrow(__format[++__i], 0);
-	      int __mem = 0;
-	      if (__c == 'E' || __c == 'O')
-		__c = __ctype.narrow(__format[++__i], 0);
-	      switch (__c)
-		{
-		  const char* __cs;
-		  _CharT __wcs[10];
-		case 'a':
-		  // Abbreviated weekday name [tm_wday]
-		  const char_type*  __days1[7];
-		  __tp._M_days_abbreviated(__days1);
-		  __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
-					  7, __io, __tmperr);
-		  break;
-		case 'A':
-		  // Weekday name [tm_wday].
-		  const char_type*  __days2[7];
-		  __tp._M_days(__days2);
-		  __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
-					  7, __io, __tmperr);
-		  break;
-		case 'h':
-		case 'b':
-		  // Abbreviated month name [tm_mon]
-		  const char_type*  __months1[12];
-		  __tp._M_months_abbreviated(__months1);
-		  __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
-					  __months1, 12, __io, __tmperr);
-		  break;
-		case 'B':
-		  // Month name [tm_mon].
-		  const char_type*  __months2[12];
-		  __tp._M_months(__months2);
-		  __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
-					  __months2, 12, __io, __tmperr);
-		  break;
-		case 'c':
-		  // Default time and date representation.
-		  const char_type*  __dt[2];
-		  __tp._M_date_time_formats(__dt);
-		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
-						__tm, __dt[0]);
-		  break;
-		case 'd':
-		  // Day [01, 31]. [tm_mday]
-		  __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
-					 __io, __tmperr);
-		  break;
-		case 'e':
-		  // Day [1, 31], with single digits preceded by
-		  // space. [tm_mday]
-		  if (__ctype.is(ctype_base::space, *__beg))
-		    __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
-					   1, __io, __tmperr);
-		  else
-		    __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
-					   2, __io, __tmperr);
-		  break;
-		case 'D':
-		  // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
-		  __cs = "%m/%d/%y";
-		  __ctype.widen(__cs, __cs + 9, __wcs);
-		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
-						__tm, __wcs);
-		  break;
-		case 'H':
-		  // Hour [00, 23]. [tm_hour]
-		  __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
-					 __io, __tmperr);
-		  break;
-		case 'I':
-		  // Hour [01, 12]. [tm_hour]
-		  __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
-					 __io, __tmperr);
-		  break;
-		case 'm':
-		  // Month [01, 12]. [tm_mon]
-		  __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 
-					 __io, __tmperr);
-		  if (!__tmperr)
-		    __tm->tm_mon = __mem - 1;
-		  break;
-		case 'M':
-		  // Minute [00, 59]. [tm_min]
-		  __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
-					 __io, __tmperr);
-		  break;
-		case 'n':
-		  if (__ctype.narrow(*__beg, 0) == '\n')
-		    ++__beg;
-		  else
-		    __tmperr |= ios_base::failbit;
-		  break;
-		case 'R':
-		  // Equivalent to (%H:%M).
-		  __cs = "%H:%M";
-		  __ctype.widen(__cs, __cs + 6, __wcs);
-		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
-						__tm, __wcs);
-		  break;
-		case 'S':
-		  // Seconds. [tm_sec]
-		  // [00, 60] in C99 (one leap-second), [00, 61] in C89.
-#ifdef _GLIBCXX_USE_C99
-		  __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2,
-#else
-		  __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
-#endif
-					 __io, __tmperr);
-		  break;
-		case 't':
-		  if (__ctype.narrow(*__beg, 0) == '\t')
-		    ++__beg;
-		  else
-		    __tmperr |= ios_base::failbit;
-		  break;
-		case 'T':
-		  // Equivalent to (%H:%M:%S).
-		  __cs = "%H:%M:%S";
-		  __ctype.widen(__cs, __cs + 9, __wcs);
-		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
-						__tm, __wcs);
-		  break;
-		case 'x':
-		  // Locale's date.
-		  const char_type*  __dates[2];
-		  __tp._M_date_formats(__dates);
-		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
-						__tm, __dates[0]);
-		  break;
-		case 'X':
-		  // Locale's time.
-		  const char_type*  __times[2];
-		  __tp._M_time_formats(__times);
-		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
-						__tm, __times[0]);
-		  break;
-		case 'y':
-		case 'C': // C99
-		  // Two digit year. [tm_year]
-		  __beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
-					 __io, __tmperr);
-		  break;
-		case 'Y':
-		  // Year [1900). [tm_year]
-		  __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
-					 __io, __tmperr);
-		  if (!__tmperr)
-		    __tm->tm_year = __mem - 1900;
-		  break;
-		case 'Z':
-		  // Timezone info.
-		  if (__ctype.is(ctype_base::upper, *__beg))
-		    {
-		      int __tmp;
-		      __beg = _M_extract_name(__beg, __end, __tmp,
-				       __timepunct_cache<_CharT>::_S_timezones,
-					      14, __io, __tmperr);
-
-		      // GMT requires special effort.
-		      if (__beg != __end && !__tmperr && __tmp == 0
-			  && (*__beg == __ctype.widen('-')
-			      || *__beg == __ctype.widen('+')))
-			{
-			  __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
-						 __io, __tmperr);
-			  __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
-						 __io, __tmperr);
-			}
-		    }
-		  else
-		    __tmperr |= ios_base::failbit;
-		  break;
-		default:
-		  // Not recognized.
-		  __tmperr |= ios_base::failbit;
-		}
-	    }
-	  else
-	    {
-	      // Verify format and input match, extract and discard.
-	      if (__format[__i] == *__beg)
-		++__beg;
-	      else
-		__tmperr |= ios_base::failbit;
-	    }
-	}
-
-      if (__tmperr)
-	__err |= ios_base::failbit;
-  
-      return __beg;
-    }
-
-  template<typename _CharT, typename _InIter>
-    _InIter
-    time_get<_CharT, _InIter>::
-    _M_extract_num(iter_type __beg, iter_type __end, int& __member,
-		   int __min, int __max, size_t __len,
-		   ios_base& __io, ios_base::iostate& __err) const
-    {
-      const locale& __loc = __io._M_getloc();
-      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
-
-      // As-is works for __len = 1, 2, 4, the values actually used.
-      int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
-
-      ++__min;
-      size_t __i = 0;
-      int __value = 0;
-      for (; __beg != __end && __i < __len; ++__beg, ++__i)
-	{
-	  const char __c = __ctype.narrow(*__beg, '*');
-	  if (__c >= '0' && __c <= '9')
-	    {
-	      __value = __value * 10 + (__c - '0');
-	      const int __valuec = __value * __mult;
-	      if (__valuec > __max || __valuec + __mult < __min)
-		break;
-	      __mult /= 10;
-	    }
-	  else
-	    break;
-	}
-      if (__i == __len)
-	__member = __value;
-      else
-	__err |= ios_base::failbit;
-
-      return __beg;
-    }
-
-  // Assumptions:
-  // All elements in __names are unique.
-  template<typename _CharT, typename _InIter>
-    _InIter
-    time_get<_CharT, _InIter>::
-    _M_extract_name(iter_type __beg, iter_type __end, int& __member,
-		    const _CharT** __names, size_t __indexlen,
-		    ios_base& __io, ios_base::iostate& __err) const
-    {
-      typedef char_traits<_CharT>		__traits_type;
-      const locale& __loc = __io._M_getloc();
-      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
-
-      int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
-							  * __indexlen));
-      size_t __nmatches = 0;
-      size_t __pos = 0;
-      bool __testvalid = true;
-      const char_type* __name;
-
-      // Look for initial matches.
-      // NB: Some of the locale data is in the form of all lowercase
-      // names, and some is in the form of initially-capitalized
-      // names. Look for both.
-      if (__beg != __end)
-	{
-	  const char_type __c = *__beg;
-	  for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
-	    if (__c == __names[__i1][0]
-		|| __c == __ctype.toupper(__names[__i1][0]))
-	      __matches[__nmatches++] = __i1;
-	}
-
-      while (__nmatches > 1)
-	{
-	  // Find smallest matching string.
-	  size_t __minlen = __traits_type::length(__names[__matches[0]]);
-	  for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
-	    __minlen = std::min(__minlen,
-			      __traits_type::length(__names[__matches[__i2]]));
-	  ++__beg, ++__pos;
-	  if (__pos < __minlen && __beg != __end)
-	    for (size_t __i3 = 0; __i3 < __nmatches;)
-	      {
-		__name = __names[__matches[__i3]];
-		if (!(__name[__pos] == *__beg))
-		  __matches[__i3] = __matches[--__nmatches];
-		else
-		  ++__i3;
-	      }
-	  else
-	    break;
-	}
-
-      if (__nmatches == 1)
-	{
-	  // Make sure found name is completely extracted.
-	  ++__beg, ++__pos;
-	  __name = __names[__matches[0]];
-	  const size_t __len = __traits_type::length(__name);
-	  while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
-	    ++__beg, ++__pos;
-
-	  if (__len == __pos)
-	    __member = __matches[0];
-	  else
-	    __testvalid = false;
-	}
-      else
-	__testvalid = false;
-      if (!__testvalid)
-	__err |= ios_base::failbit;
-
-      return __beg;
-    }
-
-  template<typename _CharT, typename _InIter>
-    _InIter
-    time_get<_CharT, _InIter>::
-    do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
-		ios_base::iostate& __err, tm* __tm) const
-    {
-      const locale& __loc = __io._M_getloc();
-      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
-      const char_type*  __times[2];
-      __tp._M_time_formats(__times);
-      __beg = _M_extract_via_format(__beg, __end, __io, __err, 
-				    __tm, __times[0]);
-      if (__beg == __end)
-	__err |= ios_base::eofbit;
-      return __beg;
-    }
-
-  template<typename _CharT, typename _InIter>
-    _InIter
-    time_get<_CharT, _InIter>::
-    do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
-		ios_base::iostate& __err, tm* __tm) const
-    {
-      const locale& __loc = __io._M_getloc();
-      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
-      const char_type*  __dates[2];
-      __tp._M_date_formats(__dates);
-      __beg = _M_extract_via_format(__beg, __end, __io, __err, 
-				    __tm, __dates[0]);
-      if (__beg == __end)
-	__err |= ios_base::eofbit;
-      return __beg;
-    }
-
-  template<typename _CharT, typename _InIter>
-    _InIter
-    time_get<_CharT, _InIter>::
-    do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
-		   ios_base::iostate& __err, tm* __tm) const
-    {
-      typedef char_traits<_CharT>		__traits_type;
-      const locale& __loc = __io._M_getloc();
-      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
-      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
-      const char_type*  __days[7];
-      __tp._M_days_abbreviated(__days);
-      int __tmpwday;
-      ios_base::iostate __tmperr = ios_base::goodbit;
-      __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7,
-			      __io, __tmperr);
-
-      // Check to see if non-abbreviated name exists, and extract.
-      // NB: Assumes both _M_days and _M_days_abbreviated organized in
-      // exact same order, first to last, such that the resulting
-      // __days array with the same index points to a day, and that
-      // day's abbreviated form.
-      // NB: Also assumes that an abbreviated name is a subset of the name.
-      if (!__tmperr && __beg != __end)
-	{
-	  size_t __pos = __traits_type::length(__days[__tmpwday]);
-	  __tp._M_days(__days);
-	  const char_type* __name = __days[__tmpwday];
-	  if (__name[__pos] == *__beg)
-	    {
-	      // Extract the rest of it.
-	      const size_t __len = __traits_type::length(__name);
-	      while (__pos < __len && __beg != __end
-		     && __name[__pos] == *__beg)
-		++__beg, ++__pos;
-	      if (__len != __pos)
-		__tmperr |= ios_base::failbit;
-	    }
-	}
-      if (!__tmperr)
-	__tm->tm_wday = __tmpwday;
-      else
-	__err |= ios_base::failbit;
-
-      if (__beg == __end)
-	__err |= ios_base::eofbit;
-      return __beg;
-     }
-
-  template<typename _CharT, typename _InIter>
-    _InIter
-    time_get<_CharT, _InIter>::
-    do_get_monthname(iter_type __beg, iter_type __end,
-                     ios_base& __io, ios_base::iostate& __err, tm* __tm) const
-    {
-      typedef char_traits<_CharT>		__traits_type;
-      const locale& __loc = __io._M_getloc();
-      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
-      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
-      const char_type*  __months[12];
-      __tp._M_months_abbreviated(__months);
-      int __tmpmon;
-      ios_base::iostate __tmperr = ios_base::goodbit;
-      __beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12, 
-			      __io, __tmperr);
-
-      // Check to see if non-abbreviated name exists, and extract.
-      // NB: Assumes both _M_months and _M_months_abbreviated organized in
-      // exact same order, first to last, such that the resulting
-      // __months array with the same index points to a month, and that
-      // month's abbreviated form.
-      // NB: Also assumes that an abbreviated name is a subset of the name.
-      if (!__tmperr && __beg != __end)
-	{
-	  size_t __pos = __traits_type::length(__months[__tmpmon]);
-	  __tp._M_months(__months);
-	  const char_type* __name = __months[__tmpmon];
-	  if (__name[__pos] == *__beg)
-	    {
-	      // Extract the rest of it.
-	      const size_t __len = __traits_type::length(__name);
-	      while (__pos < __len && __beg != __end
-		     && __name[__pos] == *__beg)
-		++__beg, ++__pos;
-	      if (__len != __pos)
-		__tmperr |= ios_base::failbit;
-	    }
-	}
-      if (!__tmperr)
-	__tm->tm_mon = __tmpmon;
-      else
-	__err |= ios_base::failbit;
-
-      if (__beg == __end)
-	__err |= ios_base::eofbit;
-      return __beg;
-    }
-
-  template<typename _CharT, typename _InIter>
-    _InIter
-    time_get<_CharT, _InIter>::
-    do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
-		ios_base::iostate& __err, tm* __tm) const
-    {
-      const locale& __loc = __io._M_getloc();
-      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
-
-      size_t __i = 0;
-      int __value = 0;
-      for (; __beg != __end && __i < 4; ++__beg, ++__i)
-	{
-	  const char __c = __ctype.narrow(*__beg, '*');
-	  if (__c >= '0' && __c <= '9')
-	    __value = __value * 10 + (__c - '0');
-	  else
-	    break;
-	}
-      if (__i == 2 || __i == 4)
-	__tm->tm_year = __i == 2 ? __value : __value - 1900;
-      else
-	__err |= ios_base::failbit;
-
-      if (__beg == __end)
-	__err |= ios_base::eofbit;
-      return __beg;
-    }
-
-  template<typename _CharT, typename _OutIter>
-    _OutIter
-    time_put<_CharT, _OutIter>::
-    put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
-	const _CharT* __beg, const _CharT* __end) const
-    {
-      const locale& __loc = __io._M_getloc();
-      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
-      for (; __beg != __end; ++__beg)
-	if (__ctype.narrow(*__beg, 0) != '%')
-	  {
-	    *__s = *__beg;
-	    ++__s;
-	  }
-	else if (++__beg != __end)
-	  {
-	    char __format;
-	    char __mod = 0;
-	    const char __c = __ctype.narrow(*__beg, 0);
-	    if (__c != 'E' && __c != 'O')
-	      __format = __c;
-	    else if (++__beg != __end)
-	      {
-		__mod = __c;
-		__format = __ctype.narrow(*__beg, 0);
-	      }
-	    else
-	      break;
-	    __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
-	  }
-	else
-	  break;
-      return __s;
-    }
-
-  template<typename _CharT, typename _OutIter>
-    _OutIter
-    time_put<_CharT, _OutIter>::
-    do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
-	   char __format, char __mod) const
-    {
-      const locale& __loc = __io._M_getloc();
-      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
-      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
-
-      // NB: This size is arbitrary. Should this be a data member,
-      // initialized at construction?
-      const size_t __maxlen = 128;
-      char_type* __res = 
-       static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
-
-      // NB: In IEE 1003.1-200x, and perhaps other locale models, it
-      // is possible that the format character will be longer than one
-      // character. Possibilities include 'E' or 'O' followed by a
-      // format character: if __mod is not the default argument, assume
-      // it's a valid modifier.
-      char_type __fmt[4];
-      __fmt[0] = __ctype.widen('%');
-      if (!__mod)
-	{
-	  __fmt[1] = __format;
-	  __fmt[2] = char_type();
-	}
-      else
-	{
-	  __fmt[1] = __mod;
-	  __fmt[2] = __format;
-	  __fmt[3] = char_type();
-	}
-
-      __tp._M_put(__res, __maxlen, __fmt, __tm);
-
-      // Write resulting, fully-formatted string to output iterator.
-      return std::__write(__s, __res, char_traits<char_type>::length(__res));
-    }
-
   // Generic version does nothing.
   template<typename _CharT>
     int
@@ -2633,23 +1497,10 @@
   // which are defined via explicit instantiations elsewhere.
   // NB: This syntax is a GNU extension.
 #if _GLIBCXX_EXTERN_TEMPLATE
-  extern template class moneypunct<char, false>;
-  extern template class moneypunct<char, true>;
-  extern template class moneypunct_byname<char, false>;
-  extern template class moneypunct_byname<char, true>;
-  extern template class _GLIBCXX_LDBL_NAMESPACE money_get<char>;
-  extern template class _GLIBCXX_LDBL_NAMESPACE money_put<char>;
   extern template class numpunct<char>;
   extern template class numpunct_byname<char>;
   extern template class _GLIBCXX_LDBL_NAMESPACE num_get<char>;
   extern template class _GLIBCXX_LDBL_NAMESPACE num_put<char>;
-  extern template class __timepunct<char>;
-  extern template class time_put<char>;
-  extern template class time_put_byname<char>;
-  extern template class time_get<char>;
-  extern template class time_get_byname<char>;
-  extern template class messages<char>;
-  extern template class messages_byname<char>;
   extern template class ctype_byname<char>;
   extern template class codecvt_byname<char, char, mbstate_t>;
   extern template class collate<char>;
@@ -2676,38 +1527,6 @@
     use_facet<num_get<char> >(const locale&);
 
   extern template
-    const moneypunct<char, true>&
-    use_facet<moneypunct<char, true> >(const locale&);
-
-  extern template
-    const moneypunct<char, false>&
-    use_facet<moneypunct<char, false> >(const locale&);
-
-  extern template
-    const money_put<char>&
-    use_facet<money_put<char> >(const locale&);
-
-  extern template
-    const money_get<char>&
-    use_facet<money_get<char> >(const locale&);
-
-  extern template
-    const __timepunct<char>&
-    use_facet<__timepunct<char> >(const locale&);
-
-  extern template
-    const time_put<char>&
-    use_facet<time_put<char> >(const locale&);
-
-  extern template
-    const time_get<char>&
-    use_facet<time_get<char> >(const locale&);
-
-  extern template
-    const messages<char>&
-    use_facet<messages<char> >(const locale&);
-
-  extern template
     bool
     has_facet<ctype<char> >(const locale&);
 
@@ -2731,52 +1550,11 @@
     bool
     has_facet<num_get<char> >(const locale&);
 
-  extern template
-    bool
-    has_facet<moneypunct<char> >(const locale&);
-
-  extern template
-    bool
-    has_facet<money_put<char> >(const locale&);
-
-  extern template
-    bool
-    has_facet<money_get<char> >(const locale&);
-
-  extern template
-    bool
-    has_facet<__timepunct<char> >(const locale&);
-
-  extern template
-    bool
-    has_facet<time_put<char> >(const locale&);
-
-  extern template
-    bool
-    has_facet<time_get<char> >(const locale&);
-
-  extern template
-    bool
-    has_facet<messages<char> >(const locale&);
-
 #ifdef _GLIBCXX_USE_WCHAR_T
-  extern template class moneypunct<wchar_t, false>;
-  extern template class moneypunct<wchar_t, true>;
-  extern template class moneypunct_byname<wchar_t, false>;
-  extern template class moneypunct_byname<wchar_t, true>;
-  extern template class _GLIBCXX_LDBL_NAMESPACE money_get<wchar_t>;
-  extern template class _GLIBCXX_LDBL_NAMESPACE money_put<wchar_t>;
   extern template class numpunct<wchar_t>;
   extern template class numpunct_byname<wchar_t>;
   extern template class _GLIBCXX_LDBL_NAMESPACE num_get<wchar_t>;
   extern template class _GLIBCXX_LDBL_NAMESPACE num_put<wchar_t>;
-  extern template class __timepunct<wchar_t>;
-  extern template class time_put<wchar_t>;
-  extern template class time_put_byname<wchar_t>;
-  extern template class time_get<wchar_t>;
-  extern template class time_get_byname<wchar_t>;
-  extern template class messages<wchar_t>;
-  extern template class messages_byname<wchar_t>;
   extern template class ctype_byname<wchar_t>;
   extern template class codecvt_byname<wchar_t, char, mbstate_t>;
   extern template class collate<wchar_t>;
@@ -2802,38 +1580,6 @@
     const num_get<wchar_t>&
     use_facet<num_get<wchar_t> >(const locale&);
 
-  extern template
-    const moneypunct<wchar_t, true>&
-    use_facet<moneypunct<wchar_t, true> >(const locale&);
-
-  extern template
-    const moneypunct<wchar_t, false>&
-    use_facet<moneypunct<wchar_t, false> >(const locale&);
-
-  extern template
-    const money_put<wchar_t>&
-    use_facet<money_put<wchar_t> >(const locale&);
-
-  extern template
-    const money_get<wchar_t>&
-    use_facet<money_get<wchar_t> >(const locale&);
-
-  extern template
-    const __timepunct<wchar_t>&
-    use_facet<__timepunct<wchar_t> >(const locale&);
-
-  extern template
-    const time_put<wchar_t>&
-    use_facet<time_put<wchar_t> >(const locale&);
-
-  extern template
-    const time_get<wchar_t>&
-    use_facet<time_get<wchar_t> >(const locale&);
-
-  extern template
-    const messages<wchar_t>&
-    use_facet<messages<wchar_t> >(const locale&);
-
  extern template
     bool
     has_facet<ctype<wchar_t> >(const locale&);
@@ -2857,34 +1603,6 @@
   extern template
     bool
     has_facet<num_get<wchar_t> >(const locale&);
-
-  extern template
-    bool
-    has_facet<moneypunct<wchar_t> >(const locale&);
-
-  extern template
-    bool
-    has_facet<money_put<wchar_t> >(const locale&);
-
-  extern template
-    bool
-    has_facet<money_get<wchar_t> >(const locale&);
-
-  extern template
-    bool
-    has_facet<__timepunct<wchar_t> >(const locale&);
-
-  extern template
-    bool
-    has_facet<time_put<wchar_t> >(const locale&);
-
-  extern template
-    bool
-    has_facet<time_get<wchar_t> >(const locale&);
-
-  extern template
-    bool
-    has_facet<messages<wchar_t> >(const locale&);
 #endif
 #endif
 
Index: include/bits/locale_facets.h
===================================================================
--- include/bits/locale_facets.h	(revision 124038)
+++ include/bits/locale_facets.h	(working copy)
@@ -43,7 +43,6 @@
 
 #pragma GCC system_header
 
-#include <ctime>	// For struct tm
 #include <cwctype>	// For wctype_t
 #include <cctype>
 #include <bits/ctype_base.h>	
@@ -51,6 +50,9 @@
 #include <bits/ios_base.h>  // For ios_base, ios_base::iostate
 #include <streambuf>
 #include <bits/cpp_type_traits.h>
+#include <ext/type_traits.h>
+#include <ext/numeric_traits.h>
+#include <bits/streambuf_iterator.h>
 
 _GLIBCXX_BEGIN_NAMESPACE(std)
 
@@ -1938,6 +1940,7 @@
     };
 
 _GLIBCXX_BEGIN_LDBL_NAMESPACE
+
   /**
    *  @brief  Facet for parsing number strings.
    *
@@ -2757,1871 +2760,6 @@
       ~collate_byname() { }
     };
 
-
-  /**
-   *  @brief  Time format ordering data.
-   *
-   *  This class provides an enum representing different orderings of day,
-   *  month, and year.
-  */
-  class time_base
-  {
-  public:
-    enum dateorder { no_order, dmy, mdy, ymd, ydm };
-  };
-
-  template<typename _CharT>
-    struct __timepunct_cache : public locale::facet
-    {
-      // List of all known timezones, with GMT first.
-      static const _CharT*		_S_timezones[14];
-
-      const _CharT*			_M_date_format;
-      const _CharT*			_M_date_era_format;
-      const _CharT*			_M_time_format;
-      const _CharT*			_M_time_era_format;
-      const _CharT*			_M_date_time_format;
-      const _CharT*			_M_date_time_era_format;
-      const _CharT*			_M_am;
-      const _CharT*			_M_pm;
-      const _CharT*			_M_am_pm_format;
-
-      // Day names, starting with "C"'s Sunday.
-      const _CharT*			_M_day1;
-      const _CharT*			_M_day2;
-      const _CharT*			_M_day3;
-      const _CharT*			_M_day4;
-      const _CharT*			_M_day5;
-      const _CharT*			_M_day6;
-      const _CharT*			_M_day7;
-
-      // Abbreviated day names, starting with "C"'s Sun.
-      const _CharT*			_M_aday1;
-      const _CharT*			_M_aday2;
-      const _CharT*			_M_aday3;
-      const _CharT*			_M_aday4;
-      const _CharT*			_M_aday5;
-      const _CharT*			_M_aday6;
-      const _CharT*			_M_aday7;
-
-      // Month names, starting with "C"'s January.
-      const _CharT*			_M_month01;
-      const _CharT*			_M_month02;
-      const _CharT*			_M_month03;
-      const _CharT*			_M_month04;
-      const _CharT*			_M_month05;
-      const _CharT*			_M_month06;
-      const _CharT*			_M_month07;
-      const _CharT*			_M_month08;
-      const _CharT*			_M_month09;
-      const _CharT*			_M_month10;
-      const _CharT*			_M_month11;
-      const _CharT*			_M_month12;
-
-      // Abbreviated month names, starting with "C"'s Jan.
-      const _CharT*			_M_amonth01;
-      const _CharT*			_M_amonth02;
-      const _CharT*			_M_amonth03;
-      const _CharT*			_M_amonth04;
-      const _CharT*			_M_amonth05;
-      const _CharT*			_M_amonth06;
-      const _CharT*			_M_amonth07;
-      const _CharT*			_M_amonth08;
-      const _CharT*			_M_amonth09;
-      const _CharT*			_M_amonth10;
-      const _CharT*			_M_amonth11;
-      const _CharT*			_M_amonth12;
-
-      bool				_M_allocated;
-
-      __timepunct_cache(size_t __refs = 0) : facet(__refs),
-      _M_date_format(NULL), _M_date_era_format(NULL), _M_time_format(NULL),
-      _M_time_era_format(NULL), _M_date_time_format(NULL),
-      _M_date_time_era_format(NULL), _M_am(NULL), _M_pm(NULL),
-      _M_am_pm_format(NULL), _M_day1(NULL), _M_day2(NULL), _M_day3(NULL),
-      _M_day4(NULL), _M_day5(NULL), _M_day6(NULL), _M_day7(NULL),
-      _M_aday1(NULL), _M_aday2(NULL), _M_aday3(NULL), _M_aday4(NULL),
-      _M_aday5(NULL), _M_aday6(NULL), _M_aday7(NULL), _M_month01(NULL),
-      _M_month02(NULL), _M_month03(NULL), _M_month04(NULL), _M_month05(NULL),
-      _M_month06(NULL), _M_month07(NULL), _M_month08(NULL), _M_month09(NULL),
-      _M_month10(NULL), _M_month11(NULL), _M_month12(NULL), _M_amonth01(NULL),
-      _M_amonth02(NULL), _M_amonth03(NULL), _M_amonth04(NULL),
-      _M_amonth05(NULL), _M_amonth06(NULL), _M_amonth07(NULL),
-      _M_amonth08(NULL), _M_amonth09(NULL), _M_amonth10(NULL),
-      _M_amonth11(NULL), _M_amonth12(NULL), _M_allocated(false)
-      { }
-
-      ~__timepunct_cache();
-
-      void
-      _M_cache(const locale& __loc);
-
-    private:
-      __timepunct_cache&
-      operator=(const __timepunct_cache&);
-      
-      explicit
-      __timepunct_cache(const __timepunct_cache&);
-    };
-
-  template<typename _CharT>
-    __timepunct_cache<_CharT>::~__timepunct_cache()
-    {
-      if (_M_allocated)
-	{
-	  // Unused.
-	}
-    }
-
-  // Specializations.
-  template<>
-    const char*
-    __timepunct_cache<char>::_S_timezones[14];
-
-#ifdef _GLIBCXX_USE_WCHAR_T
-  template<>
-    const wchar_t*
-    __timepunct_cache<wchar_t>::_S_timezones[14];
-#endif
-
-  // Generic.
-  template<typename _CharT>
-    const _CharT* __timepunct_cache<_CharT>::_S_timezones[14];
-
-  template<typename _CharT>
-    class __timepunct : public locale::facet
-    {
-    public:
-      // Types:
-      typedef _CharT			__char_type;
-      typedef basic_string<_CharT>	__string_type;
-      typedef __timepunct_cache<_CharT>	__cache_type;
-
-    protected:
-      __cache_type*			_M_data;
-      __c_locale			_M_c_locale_timepunct;
-      const char*			_M_name_timepunct;
-
-    public:
-      /// Numpunct facet id.
-      static locale::id			id;
-
-      explicit
-      __timepunct(size_t __refs = 0);
-
-      explicit
-      __timepunct(__cache_type* __cache, size_t __refs = 0);
-
-      /**
-       *  @brief  Internal constructor. Not for general use.
-       *
-       *  This is a constructor for use by the library itself to set up new
-       *  locales.
-       *
-       *  @param cloc  The "C" locale.
-       *  @param s  The name of a locale.
-       *  @param refs  Passed to the base facet class.
-      */
-      explicit
-      __timepunct(__c_locale __cloc, const char* __s, size_t __refs = 0);
-
-      // FIXME: for error checking purposes _M_put should return the return
-      // value of strftime/wcsftime.
-      void
-      _M_put(_CharT* __s, size_t __maxlen, const _CharT* __format,
-	     const tm* __tm) const;
-
-      void
-      _M_date_formats(const _CharT** __date) const
-      {
-	// Always have default first.
-	__date[0] = _M_data->_M_date_format;
-	__date[1] = _M_data->_M_date_era_format;
-      }
-
-      void
-      _M_time_formats(const _CharT** __time) const
-      {
-	// Always have default first.
-	__time[0] = _M_data->_M_time_format;
-	__time[1] = _M_data->_M_time_era_format;
-      }
-
-      void
-      _M_date_time_formats(const _CharT** __dt) const
-      {
-	// Always have default first.
-	__dt[0] = _M_data->_M_date_time_format;
-	__dt[1] = _M_data->_M_date_time_era_format;
-      }
-
-      void
-      _M_am_pm_format(const _CharT* __ampm) const
-      { __ampm = _M_data->_M_am_pm_format; }
-
-      void
-      _M_am_pm(const _CharT** __ampm) const
-      {
-	__ampm[0] = _M_data->_M_am;
-	__ampm[1] = _M_data->_M_pm;
-      }
-
-      void
-      _M_days(const _CharT** __days) const
-      {
-	__days[0] = _M_data->_M_day1;
-	__days[1] = _M_data->_M_day2;
-	__days[2] = _M_data->_M_day3;
-	__days[3] = _M_data->_M_day4;
-	__days[4] = _M_data->_M_day5;
-	__days[5] = _M_data->_M_day6;
-	__days[6] = _M_data->_M_day7;
-      }
-
-      void
-      _M_days_abbreviated(const _CharT** __days) const
-      {
-	__days[0] = _M_data->_M_aday1;
-	__days[1] = _M_data->_M_aday2;
-	__days[2] = _M_data->_M_aday3;
-	__days[3] = _M_data->_M_aday4;
-	__days[4] = _M_data->_M_aday5;
-	__days[5] = _M_data->_M_aday6;
-	__days[6] = _M_data->_M_aday7;
-      }
-
-      void
-      _M_months(const _CharT** __months) const
-      {
-	__months[0] = _M_data->_M_month01;
-	__months[1] = _M_data->_M_month02;
-	__months[2] = _M_data->_M_month03;
-	__months[3] = _M_data->_M_month04;
-	__months[4] = _M_data->_M_month05;
-	__months[5] = _M_data->_M_month06;
-	__months[6] = _M_data->_M_month07;
-	__months[7] = _M_data->_M_month08;
-	__months[8] = _M_data->_M_month09;
-	__months[9] = _M_data->_M_month10;
-	__months[10] = _M_data->_M_month11;
-	__months[11] = _M_data->_M_month12;
-      }
-
-      void
-      _M_months_abbreviated(const _CharT** __months) const
-      {
-	__months[0] = _M_data->_M_amonth01;
-	__months[1] = _M_data->_M_amonth02;
-	__months[2] = _M_data->_M_amonth03;
-	__months[3] = _M_data->_M_amonth04;
-	__months[4] = _M_data->_M_amonth05;
-	__months[5] = _M_data->_M_amonth06;
-	__months[6] = _M_data->_M_amonth07;
-	__months[7] = _M_data->_M_amonth08;
-	__months[8] = _M_data->_M_amonth09;
-	__months[9] = _M_data->_M_amonth10;
-	__months[10] = _M_data->_M_amonth11;
-	__months[11] = _M_data->_M_amonth12;
-      }
-
-    protected:
-      virtual
-      ~__timepunct();
-
-      // For use at construction time only.
-      void
-      _M_initialize_timepunct(__c_locale __cloc = NULL);
-    };
-
-  template<typename _CharT>
-    locale::id __timepunct<_CharT>::id;
-
-  // Specializations.
-  template<>
-    void
-    __timepunct<char>::_M_initialize_timepunct(__c_locale __cloc);
-
-  template<>
-    void
-    __timepunct<char>::_M_put(char*, size_t, const char*, const tm*) const;
-
-#ifdef _GLIBCXX_USE_WCHAR_T
-  template<>
-    void
-    __timepunct<wchar_t>::_M_initialize_timepunct(__c_locale __cloc);
-
-  template<>
-    void
-    __timepunct<wchar_t>::_M_put(wchar_t*, size_t, const wchar_t*,
-				 const tm*) const;
-#endif
-
-_GLIBCXX_END_NAMESPACE
-
-  // Include host and configuration specific timepunct functions.
-  #include <bits/time_members.h>
-
-_GLIBCXX_BEGIN_NAMESPACE(std)
-
-  /**
-   *  @brief  Facet for parsing dates and times.
-   *
-   *  This facet encapsulates the code to parse and return a date or
-   *  time from a string.  It is used by the istream numeric
-   *  extraction operators.
-   *
-   *  The time_get template uses protected virtual functions to provide the
-   *  actual results.  The public accessors forward the call to the virtual
-   *  functions.  These virtual functions are hooks for developers to
-   *  implement the behavior they require from the time_get facet.
-  */
-  template<typename _CharT, typename _InIter>
-    class time_get : public locale::facet, public time_base
-    {
-    public:
-      // Types:
-      //@{
-      /// Public typedefs
-      typedef _CharT			char_type;
-      typedef _InIter			iter_type;
-      //@}
-      typedef basic_string<_CharT>	__string_type;
-
-      /// Numpunct facet id.
-      static locale::id			id;
-
-      /**
-       *  @brief  Constructor performs initialization.
-       *
-       *  This is the constructor provided by the standard.
-       *
-       *  @param refs  Passed to the base facet class.
-      */
-      explicit
-      time_get(size_t __refs = 0)
-      : facet (__refs) { }
-
-      /**
-       *  @brief  Return preferred order of month, day, and year.
-       *
-       *  This function returns an enum from timebase::dateorder giving the
-       *  preferred ordering if the format "x" given to time_put::put() only
-       *  uses month, day, and year.  If the format "x" for the associated
-       *  locale uses other fields, this function returns
-       *  timebase::dateorder::noorder.
-       *
-       *  NOTE: The library always returns noorder at the moment.
-       *
-       *  @return  A member of timebase::dateorder.
-      */
-      dateorder
-      date_order()  const
-      { return this->do_date_order(); }
-
-      /**
-       *  @brief  Parse input time string.
-       *
-       *  This function parses a time according to the format "x" and puts the
-       *  results into a user-supplied struct tm.  The result is returned by
-       *  calling time_get::do_get_time().
-       *
-       *  If there is a valid time string according to format "x", @a tm will
-       *  be filled in accordingly and the returned iterator will point to the
-       *  first character beyond the time string.  If an error occurs before
-       *  the end, err |= ios_base::failbit.  If parsing reads all the
-       *  characters, err |= ios_base::eofbit.
-       *
-       *  @param  beg  Start of string to parse.
-       *  @param  end  End of string to parse.
-       *  @param  io  Source of the locale.
-       *  @param  err  Error flags to set.
-       *  @param  tm  Pointer to struct tm to fill in.
-       *  @return  Iterator to first char beyond time string.
-      */
-      iter_type
-      get_time(iter_type __beg, iter_type __end, ios_base& __io,
-	       ios_base::iostate& __err, tm* __tm)  const
-      { return this->do_get_time(__beg, __end, __io, __err, __tm); }
-
-      /**
-       *  @brief  Parse input date string.
-       *
-       *  This function parses a date according to the format "X" and puts the
-       *  results into a user-supplied struct tm.  The result is returned by
-       *  calling time_get::do_get_date().
-       *
-       *  If there is a valid date string according to format "X", @a tm will
-       *  be filled in accordingly and the returned iterator will point to the
-       *  first character beyond the date string.  If an error occurs before
-       *  the end, err |= ios_base::failbit.  If parsing reads all the
-       *  characters, err |= ios_base::eofbit.
-       *
-       *  @param  beg  Start of string to parse.
-       *  @param  end  End of string to parse.
-       *  @param  io  Source of the locale.
-       *  @param  err  Error flags to set.
-       *  @param  tm  Pointer to struct tm to fill in.
-       *  @return  Iterator to first char beyond date string.
-      */
-      iter_type
-      get_date(iter_type __beg, iter_type __end, ios_base& __io,
-	       ios_base::iostate& __err, tm* __tm)  const
-      { return this->do_get_date(__beg, __end, __io, __err, __tm); }
-
-      /**
-       *  @brief  Parse input weekday string.
-       *
-       *  This function parses a weekday name and puts the results into a
-       *  user-supplied struct tm.  The result is returned by calling
-       *  time_get::do_get_weekday().
-       *
-       *  Parsing starts by parsing an abbreviated weekday name.  If a valid
-       *  abbreviation is followed by a character that would lead to the full
-       *  weekday name, parsing continues until the full name is found or an
-       *  error occurs.  Otherwise parsing finishes at the end of the
-       *  abbreviated name.
-       *
-       *  If an error occurs before the end, err |= ios_base::failbit.  If
-       *  parsing reads all the characters, err |= ios_base::eofbit.
-       *
-       *  @param  beg  Start of string to parse.
-       *  @param  end  End of string to parse.
-       *  @param  io  Source of the locale.
-       *  @param  err  Error flags to set.
-       *  @param  tm  Pointer to struct tm to fill in.
-       *  @return  Iterator to first char beyond weekday name.
-      */
-      iter_type
-      get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
-		  ios_base::iostate& __err, tm* __tm) const
-      { return this->do_get_weekday(__beg, __end, __io, __err, __tm); }
-
-      /**
-       *  @brief  Parse input month string.
-       *
-       *  This function parses a month name and puts the results into a
-       *  user-supplied struct tm.  The result is returned by calling
-       *  time_get::do_get_monthname().
-       *
-       *  Parsing starts by parsing an abbreviated month name.  If a valid
-       *  abbreviation is followed by a character that would lead to the full
-       *  month name, parsing continues until the full name is found or an
-       *  error occurs.  Otherwise parsing finishes at the end of the
-       *  abbreviated name.
-       *
-       *  If an error occurs before the end, err |= ios_base::failbit.  If
-       *  parsing reads all the characters, err |=
-       *  ios_base::eofbit.
-       *
-       *  @param  beg  Start of string to parse.
-       *  @param  end  End of string to parse.
-       *  @param  io  Source of the locale.
-       *  @param  err  Error flags to set.
-       *  @param  tm  Pointer to struct tm to fill in.
-       *  @return  Iterator to first char beyond month name.
-      */
-      iter_type
-      get_monthname(iter_type __beg, iter_type __end, ios_base& __io,
-		    ios_base::iostate& __err, tm* __tm) const
-      { return this->do_get_monthname(__beg, __end, __io, __err, __tm); }
-
-      /**
-       *  @brief  Parse input year string.
-       *
-       *  This function reads up to 4 characters to parse a year string and
-       *  puts the results into a user-supplied struct tm.  The result is
-       *  returned by calling time_get::do_get_year().
-       *
-       *  4 consecutive digits are interpreted as a full year.  If there are
-       *  exactly 2 consecutive digits, the library interprets this as the
-       *  number of years since 1900.
-       *
-       *  If an error occurs before the end, err |= ios_base::failbit.  If
-       *  parsing reads all the characters, err |= ios_base::eofbit.
-       *
-       *  @param  beg  Start of string to parse.
-       *  @param  end  End of string to parse.
-       *  @param  io  Source of the locale.
-       *  @param  err  Error flags to set.
-       *  @param  tm  Pointer to struct tm to fill in.
-       *  @return  Iterator to first char beyond year.
-      */
-      iter_type
-      get_year(iter_type __beg, iter_type __end, ios_base& __io,
-	       ios_base::iostate& __err, tm* __tm) const
-      { return this->do_get_year(__beg, __end, __io, __err, __tm); }
-
-    protected:
-      /// Destructor.
-      virtual
-      ~time_get() { }
-
-      /**
-       *  @brief  Return preferred order of month, day, and year.
-       *
-       *  This function returns an enum from timebase::dateorder giving the
-       *  preferred ordering if the format "x" given to time_put::put() only
-       *  uses month, day, and year.  This function is a hook for derived
-       *  classes to change the value returned.
-       *
-       *  @return  A member of timebase::dateorder.
-      */
-      virtual dateorder
-      do_date_order() const;
-
-      /**
-       *  @brief  Parse input time string.
-       *
-       *  This function parses a time according to the format "x" and puts the
-       *  results into a user-supplied struct tm.  This function is a hook for
-       *  derived classes to change the value returned.  @see get_time() for
-       *  details.
-       *
-       *  @param  beg  Start of string to parse.
-       *  @param  end  End of string to parse.
-       *  @param  io  Source of the locale.
-       *  @param  err  Error flags to set.
-       *  @param  tm  Pointer to struct tm to fill in.
-       *  @return  Iterator to first char beyond time string.
-      */
-      virtual iter_type
-      do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
-		  ios_base::iostate& __err, tm* __tm) const;
-
-      /**
-       *  @brief  Parse input date string.
-       *
-       *  This function parses a date according to the format "X" and puts the
-       *  results into a user-supplied struct tm.  This function is a hook for
-       *  derived classes to change the value returned.  @see get_date() for
-       *  details.
-       *
-       *  @param  beg  Start of string to parse.
-       *  @param  end  End of string to parse.
-       *  @param  io  Source of the locale.
-       *  @param  err  Error flags to set.
-       *  @param  tm  Pointer to struct tm to fill in.
-       *  @return  Iterator to first char beyond date string.
-      */
-      virtual iter_type
-      do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
-		  ios_base::iostate& __err, tm* __tm) const;
-
-      /**
-       *  @brief  Parse input weekday string.
-       *
-       *  This function parses a weekday name and puts the results into a
-       *  user-supplied struct tm.  This function is a hook for derived
-       *  classes to change the value returned.  @see get_weekday() for
-       *  details.
-       *
-       *  @param  beg  Start of string to parse.
-       *  @param  end  End of string to parse.
-       *  @param  io  Source of the locale.
-       *  @param  err  Error flags to set.
-       *  @param  tm  Pointer to struct tm to fill in.
-       *  @return  Iterator to first char beyond weekday name.
-      */
-      virtual iter_type
-      do_get_weekday(iter_type __beg, iter_type __end, ios_base&,
-		     ios_base::iostate& __err, tm* __tm) const;
-
-      /**
-       *  @brief  Parse input month string.
-       *
-       *  This function parses a month name and puts the results into a
-       *  user-supplied struct tm.  This function is a hook for derived
-       *  classes to change the value returned.  @see get_monthname() for
-       *  details.
-       *
-       *  @param  beg  Start of string to parse.
-       *  @param  end  End of string to parse.
-       *  @param  io  Source of the locale.
-       *  @param  err  Error flags to set.
-       *  @param  tm  Pointer to struct tm to fill in.
-       *  @return  Iterator to first char beyond month name.
-      */
-      virtual iter_type
-      do_get_monthname(iter_type __beg, iter_type __end, ios_base&,
-		       ios_base::iostate& __err, tm* __tm) const;
-
-      /**
-       *  @brief  Parse input year string.
-       *
-       *  This function reads up to 4 characters to parse a year string and
-       *  puts the results into a user-supplied struct tm.  This function is a
-       *  hook for derived classes to change the value returned.  @see
-       *  get_year() for details.
-       *
-       *  @param  beg  Start of string to parse.
-       *  @param  end  End of string to parse.
-       *  @param  io  Source of the locale.
-       *  @param  err  Error flags to set.
-       *  @param  tm  Pointer to struct tm to fill in.
-       *  @return  Iterator to first char beyond year.
-      */
-      virtual iter_type
-      do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
-		  ios_base::iostate& __err, tm* __tm) const;
-
-      // Extract numeric component of length __len.
-      iter_type
-      _M_extract_num(iter_type __beg, iter_type __end, int& __member,
-		     int __min, int __max, size_t __len,
-		     ios_base& __io, ios_base::iostate& __err) const;
-
-      // Extract day or month name, or any unique array of string
-      // literals in a const _CharT* array.
-      iter_type
-      _M_extract_name(iter_type __beg, iter_type __end, int& __member,
-		      const _CharT** __names, size_t __indexlen,
-		      ios_base& __io, ios_base::iostate& __err) const;
-
-      // Extract on a component-by-component basis, via __format argument.
-      iter_type
-      _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
-			    ios_base::iostate& __err, tm* __tm,
-			    const _CharT* __format) const;
-    };
-
-  template<typename _CharT, typename _InIter>
-    locale::id time_get<_CharT, _InIter>::id;
-
-  /// @brief  class time_get_byname [22.2.5.2].
-  template<typename _CharT, typename _InIter>
-    class time_get_byname : public time_get<_CharT, _InIter>
-    {
-    public:
-      // Types:
-      typedef _CharT			char_type;
-      typedef _InIter			iter_type;
-
-      explicit
-      time_get_byname(const char*, size_t __refs = 0)
-      : time_get<_CharT, _InIter>(__refs) { }
-
-    protected:
-      virtual
-      ~time_get_byname() { }
-    };
-
-  /**
-   *  @brief  Facet for outputting dates and times.
-   *
-   *  This facet encapsulates the code to format and output dates and times
-   *  according to formats used by strftime().
-   *
-   *  The time_put template uses protected virtual functions to provide the
-   *  actual results.  The public accessors forward the call to the virtual
-   *  functions.  These virtual functions are hooks for developers to
-   *  implement the behavior they require from the time_put facet.
-  */
-  template<typename _CharT, typename _OutIter>
-    class time_put : public locale::facet
-    {
-    public:
-      // Types:
-      //@{
-      /// Public typedefs
-      typedef _CharT			char_type;
-      typedef _OutIter			iter_type;
-      //@}
-
-      /// Numpunct facet id.
-      static locale::id			id;
-
-      /**
-       *  @brief  Constructor performs initialization.
-       *
-       *  This is the constructor provided by the standard.
-       *
-       *  @param refs  Passed to the base facet class.
-      */
-      explicit
-      time_put(size_t __refs = 0)
-      : facet(__refs) { }
-
-      /**
-       *  @brief  Format and output a time or date.
-       *
-       *  This function formats the data in struct tm according to the
-       *  provided format string.  The format string is interpreted as by
-       *  strftime().
-       *
-       *  @param  s  The stream to write to.
-       *  @param  io  Source of locale.
-       *  @param  fill  char_type to use for padding.
-       *  @param  tm  Struct tm with date and time info to format.
-       *  @param  beg  Start of format string.
-       *  @param  end  End of format string.
-       *  @return  Iterator after writing.
-       */
-      iter_type
-      put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
-	  const _CharT* __beg, const _CharT* __end) const;
-
-      /**
-       *  @brief  Format and output a time or date.
-       *
-       *  This function formats the data in struct tm according to the
-       *  provided format char and optional modifier.  The format and modifier
-       *  are interpreted as by strftime().  It does so by returning
-       *  time_put::do_put().
-       *
-       *  @param  s  The stream to write to.
-       *  @param  io  Source of locale.
-       *  @param  fill  char_type to use for padding.
-       *  @param  tm  Struct tm with date and time info to format.
-       *  @param  format  Format char.
-       *  @param  mod  Optional modifier char.
-       *  @return  Iterator after writing.
-       */
-      iter_type
-      put(iter_type __s, ios_base& __io, char_type __fill,
-	  const tm* __tm, char __format, char __mod = 0) const
-      { return this->do_put(__s, __io, __fill, __tm, __format, __mod); }
-
-    protected:
-      /// Destructor.
-      virtual
-      ~time_put()
-      { }
-
-      /**
-       *  @brief  Format and output a time or date.
-       *
-       *  This function formats the data in struct tm according to the
-       *  provided format char and optional modifier.  This function is a hook
-       *  for derived classes to change the value returned.  @see put() for
-       *  more details.
-       *
-       *  @param  s  The stream to write to.
-       *  @param  io  Source of locale.
-       *  @param  fill  char_type to use for padding.
-       *  @param  tm  Struct tm with date and time info to format.
-       *  @param  format  Format char.
-       *  @param  mod  Optional modifier char.
-       *  @return  Iterator after writing.
-       */
-      virtual iter_type
-      do_put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
-	     char __format, char __mod) const;
-    };
-
-  template<typename _CharT, typename _OutIter>
-    locale::id time_put<_CharT, _OutIter>::id;
-
-  /// @brief  class time_put_byname [22.2.5.4].
-  template<typename _CharT, typename _OutIter>
-    class time_put_byname : public time_put<_CharT, _OutIter>
-    {
-    public:
-      // Types:
-      typedef _CharT			char_type;
-      typedef _OutIter			iter_type;
-
-      explicit
-      time_put_byname(const char*, size_t __refs = 0)
-      : time_put<_CharT, _OutIter>(__refs)
-      { };
-
-    protected:
-      virtual
-      ~time_put_byname() { }
-    };
-
-
-  /**
-   *  @brief  Money format ordering data.
-   *
-   *  This class contains an ordered array of 4 fields to represent the
-   *  pattern for formatting a money amount.  Each field may contain one entry
-   *  from the part enum.  symbol, sign, and value must be present and the
-   *  remaining field must contain either none or space.  @see
-   *  moneypunct::pos_format() and moneypunct::neg_format() for details of how
-   *  these fields are interpreted.
-  */
-  class money_base
-  {
-  public:
-    enum part { none, space, symbol, sign, value };
-    struct pattern { char field[4]; };
-
-    static const pattern _S_default_pattern;
-
-    enum
-    {
-      _S_minus,
-      _S_zero,
-      _S_end = 11
-    };
-
-    // String literal of acceptable (narrow) input/output, for
-    // money_get/money_put. "-0123456789"
-    static const char* _S_atoms;
-
-    // Construct and return valid pattern consisting of some combination of:
-    // space none symbol sign value
-    static pattern
-    _S_construct_pattern(char __precedes, char __space, char __posn);
-  };
-
-  template<typename _CharT, bool _Intl>
-    struct __moneypunct_cache : public locale::facet
-    {
-      const char*			_M_grouping;
-      size_t                            _M_grouping_size;
-      bool				_M_use_grouping;
-      _CharT				_M_decimal_point;
-      _CharT				_M_thousands_sep;
-      const _CharT*			_M_curr_symbol;
-      size_t                            _M_curr_symbol_size;
-      const _CharT*			_M_positive_sign;
-      size_t                            _M_positive_sign_size;
-      const _CharT*			_M_negative_sign;
-      size_t                            _M_negative_sign_size;
-      int				_M_frac_digits;
-      money_base::pattern		_M_pos_format;
-      money_base::pattern	        _M_neg_format;
-
-      // A list of valid numeric literals for input and output: in the standard
-      // "C" locale, this is "-0123456789". This array contains the chars after
-      // having been passed through the current locale's ctype<_CharT>.widen().
-      _CharT				_M_atoms[money_base::_S_end];
-
-      bool				_M_allocated;
-
-      __moneypunct_cache(size_t __refs = 0) : facet(__refs),
-      _M_grouping(NULL), _M_grouping_size(0), _M_use_grouping(false),
-      _M_decimal_point(_CharT()), _M_thousands_sep(_CharT()),
-      _M_curr_symbol(NULL), _M_curr_symbol_size(0),
-      _M_positive_sign(NULL), _M_positive_sign_size(0),
-      _M_negative_sign(NULL), _M_negative_sign_size(0),
-      _M_frac_digits(0),
-      _M_pos_format(money_base::pattern()),
-      _M_neg_format(money_base::pattern()), _M_allocated(false)
-      { }
-
-      ~__moneypunct_cache();
-
-      void
-      _M_cache(const locale& __loc);
-
-    private:
-      __moneypunct_cache&
-      operator=(const __moneypunct_cache&);
-      
-      explicit
-      __moneypunct_cache(const __moneypunct_cache&);
-    };
-
-  template<typename _CharT, bool _Intl>
-    __moneypunct_cache<_CharT, _Intl>::~__moneypunct_cache()
-    {
-      if (_M_allocated)
-	{
-	  delete [] _M_grouping;
-	  delete [] _M_curr_symbol;
-	  delete [] _M_positive_sign;
-	  delete [] _M_negative_sign;
-	}
-    }
-
-  /**
-   *  @brief  Facet for formatting data for money amounts.
-   *
-   *  This facet encapsulates the punctuation, grouping and other formatting
-   *  features of money amount string representations.
-  */
-  template<typename _CharT, bool _Intl>
-    class moneypunct : public locale::facet, public money_base
-    {
-    public:
-      // Types:
-      //@{
-      /// Public typedefs
-      typedef _CharT			char_type;
-      typedef basic_string<_CharT>	string_type;
-      //@}
-      typedef __moneypunct_cache<_CharT, _Intl>     __cache_type;
-
-    private:
-      __cache_type*			_M_data;
-
-    public:
-      /// This value is provided by the standard, but no reason for its
-      /// existence.
-      static const bool			intl = _Intl;
-      /// Numpunct facet id.
-      static locale::id			id;
-
-      /**
-       *  @brief  Constructor performs initialization.
-       *
-       *  This is the constructor provided by the standard.
-       *
-       *  @param refs  Passed to the base facet class.
-      */
-      explicit
-      moneypunct(size_t __refs = 0) : facet(__refs), _M_data(NULL)
-      { _M_initialize_moneypunct(); }
-
-      /**
-       *  @brief  Constructor performs initialization.
-       *
-       *  This is an internal constructor.
-       *
-       *  @param cache  Cache for optimization.
-       *  @param refs  Passed to the base facet class.
-      */
-      explicit
-      moneypunct(__cache_type* __cache, size_t __refs = 0)
-      : facet(__refs), _M_data(__cache)
-      { _M_initialize_moneypunct(); }
-
-      /**
-       *  @brief  Internal constructor. Not for general use.
-       *
-       *  This is a constructor for use by the library itself to set up new
-       *  locales.
-       *
-       *  @param cloc  The "C" locale.
-       *  @param s  The name of a locale.
-       *  @param refs  Passed to the base facet class.
-      */
-      explicit
-      moneypunct(__c_locale __cloc, const char* __s, size_t __refs = 0)
-      : facet(__refs), _M_data(NULL)
-      { _M_initialize_moneypunct(__cloc, __s); }
-
-      /**
-       *  @brief  Return decimal point character.
-       *
-       *  This function returns a char_type to use as a decimal point.  It
-       *  does so by returning returning
-       *  moneypunct<char_type>::do_decimal_point().
-       *
-       *  @return  @a char_type representing a decimal point.
-      */
-      char_type
-      decimal_point() const
-      { return this->do_decimal_point(); }
-
-      /**
-       *  @brief  Return thousands separator character.
-       *
-       *  This function returns a char_type to use as a thousands
-       *  separator.  It does so by returning returning
-       *  moneypunct<char_type>::do_thousands_sep().
-       *
-       *  @return  char_type representing a thousands separator.
-      */
-      char_type
-      thousands_sep() const
-      { return this->do_thousands_sep(); }
-
-      /**
-       *  @brief  Return grouping specification.
-       *
-       *  This function returns a string representing groupings for the
-       *  integer part of an amount.  Groupings indicate where thousands
-       *  separators should be inserted.
-       *
-       *  Each char in the return string is interpret as an integer rather
-       *  than a character.  These numbers represent the number of digits in a
-       *  group.  The first char in the string represents the number of digits
-       *  in the least significant group.  If a char is negative, it indicates
-       *  an unlimited number of digits for the group.  If more chars from the
-       *  string are required to group a number, the last char is used
-       *  repeatedly.
-       *
-       *  For example, if the grouping() returns "\003\002" and is applied to
-       *  the number 123456789, this corresponds to 12,34,56,789.  Note that
-       *  if the string was "32", this would put more than 50 digits into the
-       *  least significant group if the character set is ASCII.
-       *
-       *  The string is returned by calling
-       *  moneypunct<char_type>::do_grouping().
-       *
-       *  @return  string representing grouping specification.
-      */
-      string
-      grouping() const
-      { return this->do_grouping(); }
-
-      /**
-       *  @brief  Return currency symbol string.
-       *
-       *  This function returns a string_type to use as a currency symbol.  It
-       *  does so by returning returning
-       *  moneypunct<char_type>::do_curr_symbol().
-       *
-       *  @return  @a string_type representing a currency symbol.
-      */
-      string_type
-      curr_symbol() const
-      { return this->do_curr_symbol(); }
-
-      /**
-       *  @brief  Return positive sign string.
-       *
-       *  This function returns a string_type to use as a sign for positive
-       *  amounts.  It does so by returning returning
-       *  moneypunct<char_type>::do_positive_sign().
-       *
-       *  If the return value contains more than one character, the first
-       *  character appears in the position indicated by pos_format() and the
-       *  remainder appear at the end of the formatted string.
-       *
-       *  @return  @a string_type representing a positive sign.
-      */
-      string_type
-      positive_sign() const
-      { return this->do_positive_sign(); }
-
-      /**
-       *  @brief  Return negative sign string.
-       *
-       *  This function returns a string_type to use as a sign for negative
-       *  amounts.  It does so by returning returning
-       *  moneypunct<char_type>::do_negative_sign().
-       *
-       *  If the return value contains more than one character, the first
-       *  character appears in the position indicated by neg_format() and the
-       *  remainder appear at the end of the formatted string.
-       *
-       *  @return  @a string_type representing a negative sign.
-      */
-      string_type
-      negative_sign() const
-      { return this->do_negative_sign(); }
-
-      /**
-       *  @brief  Return number of digits in fraction.
-       *
-       *  This function returns the exact number of digits that make up the
-       *  fractional part of a money amount.  It does so by returning
-       *  returning moneypunct<char_type>::do_frac_digits().
-       *
-       *  The fractional part of a money amount is optional.  But if it is
-       *  present, there must be frac_digits() digits.
-       *
-       *  @return  Number of digits in amount fraction.
-      */
-      int
-      frac_digits() const
-      { return this->do_frac_digits(); }
-
-      //@{
-      /**
-       *  @brief  Return pattern for money values.
-       *
-       *  This function returns a pattern describing the formatting of a
-       *  positive or negative valued money amount.  It does so by returning
-       *  returning moneypunct<char_type>::do_pos_format() or
-       *  moneypunct<char_type>::do_neg_format().
-       *
-       *  The pattern has 4 fields describing the ordering of symbol, sign,
-       *  value, and none or space.  There must be one of each in the pattern.
-       *  The none and space enums may not appear in the first field and space
-       *  may not appear in the final field.
-       *
-       *  The parts of a money string must appear in the order indicated by
-       *  the fields of the pattern.  The symbol field indicates that the
-       *  value of curr_symbol() may be present.  The sign field indicates
-       *  that the value of positive_sign() or negative_sign() must be
-       *  present.  The value field indicates that the absolute value of the
-       *  money amount is present.  none indicates 0 or more whitespace
-       *  characters, except at the end, where it permits no whitespace.
-       *  space indicates that 1 or more whitespace characters must be
-       *  present.
-       *
-       *  For example, for the US locale and pos_format() pattern
-       *  {symbol,sign,value,none}, curr_symbol() == '$' positive_sign() ==
-       *  '+', and value 10.01, and options set to force the symbol, the
-       *  corresponding string is "$+10.01".
-       *
-       *  @return  Pattern for money values.
-      */
-      pattern
-      pos_format() const
-      { return this->do_pos_format(); }
-
-      pattern
-      neg_format() const
-      { return this->do_neg_format(); }
-      //@}
-
-    protected:
-      /// Destructor.
-      virtual
-      ~moneypunct();
-
-      /**
-       *  @brief  Return decimal point character.
-       *
-       *  Returns a char_type to use as a decimal point.  This function is a
-       *  hook for derived classes to change the value returned.
-       *
-       *  @return  @a char_type representing a decimal point.
-      */
-      virtual char_type
-      do_decimal_point() const
-      { return _M_data->_M_decimal_point; }
-
-      /**
-       *  @brief  Return thousands separator character.
-       *
-       *  Returns a char_type to use as a thousands separator.  This function
-       *  is a hook for derived classes to change the value returned.
-       *
-       *  @return  @a char_type representing a thousands separator.
-      */
-      virtual char_type
-      do_thousands_sep() const
-      { return _M_data->_M_thousands_sep; }
-
-      /**
-       *  @brief  Return grouping specification.
-       *
-       *  Returns a string representing groupings for the integer part of a
-       *  number.  This function is a hook for derived classes to change the
-       *  value returned.  @see grouping() for details.
-       *
-       *  @return  String representing grouping specification.
-      */
-      virtual string
-      do_grouping() const
-      { return _M_data->_M_grouping; }
-
-      /**
-       *  @brief  Return currency symbol string.
-       *
-       *  This function returns a string_type to use as a currency symbol.
-       *  This function is a hook for derived classes to change the value
-       *  returned.  @see curr_symbol() for details.
-       *
-       *  @return  @a string_type representing a currency symbol.
-      */
-      virtual string_type
-      do_curr_symbol()   const
-      { return _M_data->_M_curr_symbol; }
-
-      /**
-       *  @brief  Return positive sign string.
-       *
-       *  This function returns a string_type to use as a sign for positive
-       *  amounts.  This function is a hook for derived classes to change the
-       *  value returned.  @see positive_sign() for details.
-       *
-       *  @return  @a string_type representing a positive sign.
-      */
-      virtual string_type
-      do_positive_sign() const
-      { return _M_data->_M_positive_sign; }
-
-      /**
-       *  @brief  Return negative sign string.
-       *
-       *  This function returns a string_type to use as a sign for negative
-       *  amounts.  This function is a hook for derived classes to change the
-       *  value returned.  @see negative_sign() for details.
-       *
-       *  @return  @a string_type representing a negative sign.
-      */
-      virtual string_type
-      do_negative_sign() const
-      { return _M_data->_M_negative_sign; }
-
-      /**
-       *  @brief  Return number of digits in fraction.
-       *
-       *  This function returns the exact number of digits that make up the
-       *  fractional part of a money amount.  This function is a hook for
-       *  derived classes to change the value returned.  @see frac_digits()
-       *  for details.
-       *
-       *  @return  Number of digits in amount fraction.
-      */
-      virtual int
-      do_frac_digits() const
-      { return _M_data->_M_frac_digits; }
-
-      /**
-       *  @brief  Return pattern for money values.
-       *
-       *  This function returns a pattern describing the formatting of a
-       *  positive valued money amount.  This function is a hook for derived
-       *  classes to change the value returned.  @see pos_format() for
-       *  details.
-       *
-       *  @return  Pattern for money values.
-      */
-      virtual pattern
-      do_pos_format() const
-      { return _M_data->_M_pos_format; }
-
-      /**
-       *  @brief  Return pattern for money values.
-       *
-       *  This function returns a pattern describing the formatting of a
-       *  negative valued money amount.  This function is a hook for derived
-       *  classes to change the value returned.  @see neg_format() for
-       *  details.
-       *
-       *  @return  Pattern for money values.
-      */
-      virtual pattern
-      do_neg_format() const
-      { return _M_data->_M_neg_format; }
-
-      // For use at construction time only.
-       void
-       _M_initialize_moneypunct(__c_locale __cloc = NULL,
-				const char* __name = NULL);
-    };
-
-  template<typename _CharT, bool _Intl>
-    locale::id moneypunct<_CharT, _Intl>::id;
-
-  template<typename _CharT, bool _Intl>
-    const bool moneypunct<_CharT, _Intl>::intl;
-
-  template<>
-    moneypunct<char, true>::~moneypunct();
-
-  template<>
-    moneypunct<char, false>::~moneypunct();
-
-  template<>
-    void
-    moneypunct<char, true>::_M_initialize_moneypunct(__c_locale, const char*);
-
-  template<>
-    void
-    moneypunct<char, false>::_M_initialize_moneypunct(__c_locale, const char*);
-
-#ifdef _GLIBCXX_USE_WCHAR_T
-  template<>
-    moneypunct<wchar_t, true>::~moneypunct();
-
-  template<>
-    moneypunct<wchar_t, false>::~moneypunct();
-
-  template<>
-    void
-    moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale,
-							const char*);
-
-  template<>
-    void
-    moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale,
-							 const char*);
-#endif
-
-  /// @brief  class moneypunct_byname [22.2.6.4].
-  template<typename _CharT, bool _Intl>
-    class moneypunct_byname : public moneypunct<_CharT, _Intl>
-    {
-    public:
-      typedef _CharT			char_type;
-      typedef basic_string<_CharT>	string_type;
-
-      static const bool intl = _Intl;
-
-      explicit
-      moneypunct_byname(const char* __s, size_t __refs = 0)
-      : moneypunct<_CharT, _Intl>(__refs)
-      {
-	if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
-	  {
-	    __c_locale __tmp;
-	    this->_S_create_c_locale(__tmp, __s);
-	    this->_M_initialize_moneypunct(__tmp);
-	    this->_S_destroy_c_locale(__tmp);
-	  }
-      }
-
-    protected:
-      virtual
-      ~moneypunct_byname() { }
-    };
-
-  template<typename _CharT, bool _Intl>
-    const bool moneypunct_byname<_CharT, _Intl>::intl;
-
-_GLIBCXX_BEGIN_LDBL_NAMESPACE
-  /**
-   *  @brief  Facet for parsing monetary amounts.
-   *
-   *  This facet encapsulates the code to parse and return a monetary
-   *  amount from a string.
-   *
-   *  The money_get template uses protected virtual functions to
-   *  provide the actual results.  The public accessors forward the
-   *  call to the virtual functions.  These virtual functions are
-   *  hooks for developers to implement the behavior they require from
-   *  the money_get facet.
-  */
-  template<typename _CharT, typename _InIter>
-    class money_get : public locale::facet
-    {
-    public:
-      // Types:
-      //@{
-      /// Public typedefs
-      typedef _CharT			char_type;
-      typedef _InIter			iter_type;
-      typedef basic_string<_CharT>	string_type;
-      //@}
-
-      /// Numpunct facet id.
-      static locale::id			id;
-
-      /**
-       *  @brief  Constructor performs initialization.
-       *
-       *  This is the constructor provided by the standard.
-       *
-       *  @param refs  Passed to the base facet class.
-      */
-      explicit
-      money_get(size_t __refs = 0) : facet(__refs) { }
-
-      /**
-       *  @brief  Read and parse a monetary value.
-       *
-       *  This function reads characters from @a s, interprets them as a
-       *  monetary value according to moneypunct and ctype facets retrieved
-       *  from io.getloc(), and returns the result in @a units as an integral
-       *  value moneypunct::frac_digits() * the actual amount.  For example,
-       *  the string $10.01 in a US locale would store 1001 in @a units.
-       *
-       *  Any characters not part of a valid money amount are not consumed.
-       *
-       *  If a money value cannot be parsed from the input stream, sets
-       *  err=(err|io.failbit).  If the stream is consumed before finishing
-       *  parsing,  sets err=(err|io.failbit|io.eofbit).  @a units is
-       *  unchanged if parsing fails.
-       *
-       *  This function works by returning the result of do_get().
-       *
-       *  @param  s  Start of characters to parse.
-       *  @param  end  End of characters to parse.
-       *  @param  intl  Parameter to use_facet<moneypunct<CharT,intl> >.
-       *  @param  io  Source of facets and io state.
-       *  @param  err  Error field to set if parsing fails.
-       *  @param  units  Place to store result of parsing.
-       *  @return  Iterator referencing first character beyond valid money
-       *	   amount.
-       */
-      iter_type
-      get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
-	  ios_base::iostate& __err, long double& __units) const
-      { return this->do_get(__s, __end, __intl, __io, __err, __units); }
-
-      /**
-       *  @brief  Read and parse a monetary value.
-       *
-       *  This function reads characters from @a s, interprets them as a
-       *  monetary value according to moneypunct and ctype facets retrieved
-       *  from io.getloc(), and returns the result in @a digits.  For example,
-       *  the string $10.01 in a US locale would store "1001" in @a digits.
-       *
-       *  Any characters not part of a valid money amount are not consumed.
-       *
-       *  If a money value cannot be parsed from the input stream, sets
-       *  err=(err|io.failbit).  If the stream is consumed before finishing
-       *  parsing,  sets err=(err|io.failbit|io.eofbit).
-       *
-       *  This function works by returning the result of do_get().
-       *
-       *  @param  s  Start of characters to parse.
-       *  @param  end  End of characters to parse.
-       *  @param  intl  Parameter to use_facet<moneypunct<CharT,intl> >.
-       *  @param  io  Source of facets and io state.
-       *  @param  err  Error field to set if parsing fails.
-       *  @param  digits  Place to store result of parsing.
-       *  @return  Iterator referencing first character beyond valid money
-       *	   amount.
-       */
-      iter_type
-      get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
-	  ios_base::iostate& __err, string_type& __digits) const
-      { return this->do_get(__s, __end, __intl, __io, __err, __digits); }
-
-    protected:
-      /// Destructor.
-      virtual
-      ~money_get() { }
-
-      /**
-       *  @brief  Read and parse a monetary value.
-       *
-       *  This function reads and parses characters representing a monetary
-       *  value.  This function is a hook for derived classes to change the
-       *  value returned.  @see get() for details.
-       */
-      // XXX GLIBCXX_ABI Deprecated
-#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
-      virtual iter_type
-      __do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
-	       ios_base::iostate& __err, double& __units) const;
-#else
-      virtual iter_type
-      do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
-	     ios_base::iostate& __err, long double& __units) const;
-#endif
-
-      /**
-       *  @brief  Read and parse a monetary value.
-       *
-       *  This function reads and parses characters representing a monetary
-       *  value.  This function is a hook for derived classes to change the
-       *  value returned.  @see get() for details.
-       */
-      virtual iter_type
-      do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
-	     ios_base::iostate& __err, string_type& __digits) const;
-
-      // XXX GLIBCXX_ABI Deprecated
-#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
-      virtual iter_type
-      do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
-	     ios_base::iostate& __err, long double& __units) const;
-#endif
-
-      template<bool _Intl>
-        iter_type
-        _M_extract(iter_type __s, iter_type __end, ios_base& __io,
-		   ios_base::iostate& __err, string& __digits) const;     
-    };
-
-  template<typename _CharT, typename _InIter>
-    locale::id money_get<_CharT, _InIter>::id;
-
-  /**
-   *  @brief  Facet for outputting monetary amounts.
-   *
-   *  This facet encapsulates the code to format and output a monetary
-   *  amount.
-   *
-   *  The money_put template uses protected virtual functions to
-   *  provide the actual results.  The public accessors forward the
-   *  call to the virtual functions.  These virtual functions are
-   *  hooks for developers to implement the behavior they require from
-   *  the money_put facet.
-  */
-  template<typename _CharT, typename _OutIter>
-    class money_put : public locale::facet
-    {
-    public:
-      //@{
-      /// Public typedefs
-      typedef _CharT			char_type;
-      typedef _OutIter			iter_type;
-      typedef basic_string<_CharT>	string_type;
-      //@}
-
-      /// Numpunct facet id.
-      static locale::id			id;
-
-      /**
-       *  @brief  Constructor performs initialization.
-       *
-       *  This is the constructor provided by the standard.
-       *
-       *  @param refs  Passed to the base facet class.
-      */
-      explicit
-      money_put(size_t __refs = 0) : facet(__refs) { }
-
-      /**
-       *  @brief  Format and output a monetary value.
-       *
-       *  This function formats @a units as a monetary value according to
-       *  moneypunct and ctype facets retrieved from io.getloc(), and writes
-       *  the resulting characters to @a s.  For example, the value 1001 in a
-       *  US locale would write "$10.01" to @a s.
-       *
-       *  This function works by returning the result of do_put().
-       *
-       *  @param  s  The stream to write to.
-       *  @param  intl  Parameter to use_facet<moneypunct<CharT,intl> >.
-       *  @param  io  Source of facets and io state.
-       *  @param  fill  char_type to use for padding.
-       *  @param  units  Place to store result of parsing.
-       *  @return  Iterator after writing.
-       */
-      iter_type
-      put(iter_type __s, bool __intl, ios_base& __io,
-	  char_type __fill, long double __units) const
-      { return this->do_put(__s, __intl, __io, __fill, __units); }
-
-      /**
-       *  @brief  Format and output a monetary value.
-       *
-       *  This function formats @a digits as a monetary value according to
-       *  moneypunct and ctype facets retrieved from io.getloc(), and writes
-       *  the resulting characters to @a s.  For example, the string "1001" in
-       *  a US locale would write "$10.01" to @a s.
-       *
-       *  This function works by returning the result of do_put().
-       *
-       *  @param  s  The stream to write to.
-       *  @param  intl  Parameter to use_facet<moneypunct<CharT,intl> >.
-       *  @param  io  Source of facets and io state.
-       *  @param  fill  char_type to use for padding.
-       *  @param  units  Place to store result of parsing.
-       *  @return  Iterator after writing.
-       */
-      iter_type
-      put(iter_type __s, bool __intl, ios_base& __io,
-	  char_type __fill, const string_type& __digits) const
-      { return this->do_put(__s, __intl, __io, __fill, __digits); }
-
-    protected:
-      /// Destructor.
-      virtual
-      ~money_put() { }
-
-      /**
-       *  @brief  Format and output a monetary value.
-       *
-       *  This function formats @a units as a monetary value according to
-       *  moneypunct and ctype facets retrieved from io.getloc(), and writes
-       *  the resulting characters to @a s.  For example, the value 1001 in a
-       *  US locale would write "$10.01" to @a s.
-       *
-       *  This function is a hook for derived classes to change the value
-       *  returned.  @see put().
-       *
-       *  @param  s  The stream to write to.
-       *  @param  intl  Parameter to use_facet<moneypunct<CharT,intl> >.
-       *  @param  io  Source of facets and io state.
-       *  @param  fill  char_type to use for padding.
-       *  @param  units  Place to store result of parsing.
-       *  @return  Iterator after writing.
-       */
-      // XXX GLIBCXX_ABI Deprecated
-#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
-      virtual iter_type
-      __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
-	       double __units) const;
-#else
-      virtual iter_type
-      do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
-	     long double __units) const;
-#endif
-
-      /**
-       *  @brief  Format and output a monetary value.
-       *
-       *  This function formats @a digits as a monetary value according to
-       *  moneypunct and ctype facets retrieved from io.getloc(), and writes
-       *  the resulting characters to @a s.  For example, the string "1001" in
-       *  a US locale would write "$10.01" to @a s.
-       *
-       *  This function is a hook for derived classes to change the value
-       *  returned.  @see put().
-       *
-       *  @param  s  The stream to write to.
-       *  @param  intl  Parameter to use_facet<moneypunct<CharT,intl> >.
-       *  @param  io  Source of facets and io state.
-       *  @param  fill  char_type to use for padding.
-       *  @param  units  Place to store result of parsing.
-       *  @return  Iterator after writing.
-       */
-      virtual iter_type
-      do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
-	     const string_type& __digits) const;
-
-      // XXX GLIBCXX_ABI Deprecated
-#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
-      virtual iter_type
-      do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
-	     long double __units) const;
-#endif
-
-      template<bool _Intl>
-        iter_type
-        _M_insert(iter_type __s, ios_base& __io, char_type __fill,
-		  const string_type& __digits) const;
-    };
-
-  template<typename _CharT, typename _OutIter>
-    locale::id money_put<_CharT, _OutIter>::id;
-
-_GLIBCXX_END_LDBL_NAMESPACE
-
-  /**
-   *  @brief  Messages facet base class providing catalog typedef.
-   */
-  struct messages_base
-  {
-    typedef int catalog;
-  };
-
-  /**
-   *  @brief  Facet for handling message catalogs
-   *
-   *  This facet encapsulates the code to retrieve messages from
-   *  message catalogs.  The only thing defined by the standard for this facet
-   *  is the interface.  All underlying functionality is
-   *  implementation-defined.
-   *
-   *  This library currently implements 3 versions of the message facet.  The
-   *  first version (gnu) is a wrapper around gettext, provided by libintl.
-   *  The second version (ieee) is a wrapper around catgets.  The final
-   *  version (default) does no actual translation.  These implementations are
-   *  only provided for char and wchar_t instantiations.
-   *
-   *  The messages template uses protected virtual functions to
-   *  provide the actual results.  The public accessors forward the
-   *  call to the virtual functions.  These virtual functions are
-   *  hooks for developers to implement the behavior they require from
-   *  the messages facet.
-  */
-  template<typename _CharT>
-    class messages : public locale::facet, public messages_base
-    {
-    public:
-      // Types:
-      //@{
-      /// Public typedefs
-      typedef _CharT			char_type;
-      typedef basic_string<_CharT>	string_type;
-      //@}
-
-    protected:
-      // Underlying "C" library locale information saved from
-      // initialization, needed by messages_byname as well.
-      __c_locale			_M_c_locale_messages;
-      const char*			_M_name_messages;
-
-    public:
-      /// Numpunct facet id.
-      static locale::id			id;
-
-      /**
-       *  @brief  Constructor performs initialization.
-       *
-       *  This is the constructor provided by the standard.
-       *
-       *  @param refs  Passed to the base facet class.
-      */
-      explicit
-      messages(size_t __refs = 0);
-
-      // Non-standard.
-      /**
-       *  @brief  Internal constructor.  Not for general use.
-       *
-       *  This is a constructor for use by the library itself to set up new
-       *  locales.
-       *
-       *  @param  cloc  The "C" locale.
-       *  @param  s  The name of a locale.
-       *  @param  refs  Refcount to pass to the base class.
-       */
-      explicit
-      messages(__c_locale __cloc, const char* __s, size_t __refs = 0);
-
-      /*
-       *  @brief  Open a message catalog.
-       *
-       *  This function opens and returns a handle to a message catalog by
-       *  returning do_open(s, loc).
-       *
-       *  @param  s  The catalog to open.
-       *  @param  loc  Locale to use for character set conversions.
-       *  @return  Handle to the catalog or value < 0 if open fails.
-      */
-      catalog
-      open(const basic_string<char>& __s, const locale& __loc) const
-      { return this->do_open(__s, __loc); }
-
-      // Non-standard and unorthodox, yet effective.
-      /*
-       *  @brief  Open a message catalog.
-       *
-       *  This non-standard function opens and returns a handle to a message
-       *  catalog by returning do_open(s, loc).  The third argument provides a
-       *  message catalog root directory for gnu gettext and is ignored
-       *  otherwise.
-       *
-       *  @param  s  The catalog to open.
-       *  @param  loc  Locale to use for character set conversions.
-       *  @param  dir  Message catalog root directory.
-       *  @return  Handle to the catalog or value < 0 if open fails.
-      */
-      catalog
-      open(const basic_string<char>&, const locale&, const char*) const;
-
-      /*
-       *  @brief  Look up a string in a message catalog.
-       *
-       *  This function retrieves and returns a message from a catalog by
-       *  returning do_get(c, set, msgid, s).
-       *
-       *  For gnu, @a set and @a msgid are ignored.  Returns gettext(s).
-       *  For default, returns s. For ieee, returns catgets(c,set,msgid,s).
-       *
-       *  @param  c  The catalog to access.
-       *  @param  set  Implementation-defined.
-       *  @param  msgid  Implementation-defined.
-       *  @param  s  Default return value if retrieval fails.
-       *  @return  Retrieved message or @a s if get fails.
-      */
-      string_type
-      get(catalog __c, int __set, int __msgid, const string_type& __s) const
-      { return this->do_get(__c, __set, __msgid, __s); }
-
-      /*
-       *  @brief  Close a message catalog.
-       *
-       *  Closes catalog @a c by calling do_close(c).
-       *
-       *  @param  c  The catalog to close.
-      */
-      void
-      close(catalog __c) const
-      { return this->do_close(__c); }
-
-    protected:
-      /// Destructor.
-      virtual
-      ~messages();
-
-      /*
-       *  @brief  Open a message catalog.
-       *
-       *  This function opens and returns a handle to a message catalog in an
-       *  implementation-defined manner.  This function is a hook for derived
-       *  classes to change the value returned.
-       *
-       *  @param  s  The catalog to open.
-       *  @param  loc  Locale to use for character set conversions.
-       *  @return  Handle to the opened catalog, value < 0 if open failed.
-      */
-      virtual catalog
-      do_open(const basic_string<char>&, const locale&) const;
-
-      /*
-       *  @brief  Look up a string in a message catalog.
-       *
-       *  This function retrieves and returns a message from a catalog in an
-       *  implementation-defined manner.  This function is a hook for derived
-       *  classes to change the value returned.
-       *
-       *  For gnu, @a set and @a msgid are ignored.  Returns gettext(s).
-       *  For default, returns s. For ieee, returns catgets(c,set,msgid,s).
-       *
-       *  @param  c  The catalog to access.
-       *  @param  set  Implementation-defined.
-       *  @param  msgid  Implementation-defined.
-       *  @param  s  Default return value if retrieval fails.
-       *  @return  Retrieved message or @a s if get fails.
-      */
-      virtual string_type
-      do_get(catalog, int, int, const string_type& __dfault) const;
-
-      /*
-       *  @brief  Close a message catalog.
-       *
-       *  @param  c  The catalog to close.
-      */
-      virtual void
-      do_close(catalog) const;
-
-      // Returns a locale and codeset-converted string, given a char* message.
-      char*
-      _M_convert_to_char(const string_type& __msg) const
-      {
-	// XXX
-	return reinterpret_cast<char*>(const_cast<_CharT*>(__msg.c_str()));
-      }
-
-      // Returns a locale and codeset-converted string, given a char* message.
-      string_type
-      _M_convert_from_char(char*) const
-      {
-#if 0
-	// Length of message string without terminating null.
-	size_t __len = char_traits<char>::length(__msg) - 1;
-
-	// "everybody can easily convert the string using
-	// mbsrtowcs/wcsrtombs or with iconv()"
-
-	// Convert char* to _CharT in locale used to open catalog.
-	// XXX need additional template parameter on messages class for this..
-	// typedef typename codecvt<char, _CharT, _StateT> __codecvt_type;
-	typedef typename codecvt<char, _CharT, mbstate_t> __codecvt_type;
-
-	__codecvt_type::state_type __state;
-	// XXX may need to initialize state.
-	//initialize_state(__state._M_init());
-
-	char* __from_next;
-	// XXX what size for this string?
-	_CharT* __to = static_cast<_CharT*>(__builtin_alloca(__len + 1));
-	const __codecvt_type& __cvt = use_facet<__codecvt_type>(_M_locale_conv);
-	__cvt.out(__state, __msg, __msg + __len, __from_next,
-		  __to, __to + __len + 1, __to_next);
-	return string_type(__to);
-#endif
-#if 0
-	typedef ctype<_CharT> __ctype_type;
-	// const __ctype_type& __cvt = use_facet<__ctype_type>(_M_locale_msg);
-	const __ctype_type& __cvt = use_facet<__ctype_type>(locale());
-	// XXX Again, proper length of converted string an issue here.
-	// For now, assume the converted length is not larger.
-	_CharT* __dest = static_cast<_CharT*>(__builtin_alloca(__len + 1));
-	__cvt.widen(__msg, __msg + __len, __dest);
-	return basic_string<_CharT>(__dest);
-#endif
-	return string_type();
-      }
-     };
-
-  template<typename _CharT>
-    locale::id messages<_CharT>::id;
-
-  // Specializations for required instantiations.
-  template<>
-    string
-    messages<char>::do_get(catalog, int, int, const string&) const;
-
-#ifdef _GLIBCXX_USE_WCHAR_T
-  template<>
-    wstring
-    messages<wchar_t>::do_get(catalog, int, int, const wstring&) const;
-#endif
-
-   /// @brief class messages_byname [22.2.7.2].
-   template<typename _CharT>
-    class messages_byname : public messages<_CharT>
-    {
-    public:
-      typedef _CharT			char_type;
-      typedef basic_string<_CharT>	string_type;
-
-      explicit
-      messages_byname(const char* __s, size_t __refs = 0);
-
-    protected:
-      virtual
-      ~messages_byname()
-      { }
-    };
-
-_GLIBCXX_END_NAMESPACE
-
-  // Include host and configuration specific messages functions.
-  #include <bits/messages_members.h>
-
-_GLIBCXX_BEGIN_NAMESPACE(std)
-
   // Subclause convenience interfaces, inlines.
   // NB: These are inline because, when used in a loop, some compilers
   // can hoist the body out of the loop; then it's just as fast as the
Index: include/bits/non_io_facets.tcc
===================================================================
--- include/bits/non_io_facets.tcc	(revision 0)
+++ include/bits/non_io_facets.tcc	(revision 0)
@@ -0,0 +1,1328 @@
+// Locale support -*- C++ -*-
+
+// Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+/** @file non_io_facets.tcc
+ *  This is an internal header file, included by other library headers.
+ *  You should not attempt to use it directly.
+ */
+
+#ifndef _NON_IO_FACETS_TCC
+#define _NON_IO_FACETS_TCC 1
+
+_GLIBCXX_BEGIN_NAMESPACE(std)
+
+  template<typename _CharT, bool _Intl>
+    struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
+    {
+      const __moneypunct_cache<_CharT, _Intl>*
+      operator() (const locale& __loc) const
+      {
+	const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
+	const locale::facet** __caches = __loc._M_impl->_M_caches;
+	if (!__caches[__i])
+	  {
+	    __moneypunct_cache<_CharT, _Intl>* __tmp = NULL;
+	    try
+	      {
+		__tmp = new __moneypunct_cache<_CharT, _Intl>;
+		__tmp->_M_cache(__loc);
+	      }
+	    catch(...)
+	      {
+		delete __tmp;
+		__throw_exception_again;
+	      }
+	    __loc._M_impl->_M_install_cache(__tmp, __i);
+	  }
+	return static_cast<
+	  const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
+      }
+    };
+
+  template<typename _CharT, bool _Intl>
+    void
+    __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
+    {
+      _M_allocated = true;
+
+      const moneypunct<_CharT, _Intl>& __mp =
+	use_facet<moneypunct<_CharT, _Intl> >(__loc);
+
+      _M_grouping_size = __mp.grouping().size();
+      char* __grouping = new char[_M_grouping_size];
+      __mp.grouping().copy(__grouping, _M_grouping_size);
+      _M_grouping = __grouping;
+      _M_use_grouping = (_M_grouping_size
+			 && static_cast<signed char>(__mp.grouping()[0]) > 0);
+      
+      _M_decimal_point = __mp.decimal_point();
+      _M_thousands_sep = __mp.thousands_sep();
+      _M_frac_digits = __mp.frac_digits();
+      
+      _M_curr_symbol_size = __mp.curr_symbol().size();
+      _CharT* __curr_symbol = new _CharT[_M_curr_symbol_size];
+      __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size);
+      _M_curr_symbol = __curr_symbol;
+      
+      _M_positive_sign_size = __mp.positive_sign().size();
+      _CharT* __positive_sign = new _CharT[_M_positive_sign_size];
+      __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size);
+      _M_positive_sign = __positive_sign;
+
+      _M_negative_sign_size = __mp.negative_sign().size();
+      _CharT* __negative_sign = new _CharT[_M_negative_sign_size];
+      __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size);
+      _M_negative_sign = __negative_sign;
+      
+      _M_pos_format = __mp.pos_format();
+      _M_neg_format = __mp.neg_format();
+
+      const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
+      __ct.widen(money_base::_S_atoms,
+		 money_base::_S_atoms + money_base::_S_end, _M_atoms);
+    }
+
+_GLIBCXX_BEGIN_LDBL_NAMESPACE
+
+  template<typename _CharT, typename _InIter>
+    template<bool _Intl>
+      _InIter
+      money_get<_CharT, _InIter>::
+      _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
+		 ios_base::iostate& __err, string& __units) const
+      {
+	typedef char_traits<_CharT>			  __traits_type;
+	typedef typename string_type::size_type	          size_type;	
+	typedef money_base::part			  part;
+	typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
+	
+	const locale& __loc = __io._M_getloc();
+	const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+
+	__use_cache<__cache_type> __uc;
+	const __cache_type* __lc = __uc(__loc);
+	const char_type* __lit = __lc->_M_atoms;
+
+	// Deduced sign.
+	bool __negative = false;
+	// Sign size.
+	size_type __sign_size = 0;
+	// True if sign is mandatory.
+	const bool __mandatory_sign = (__lc->_M_positive_sign_size
+				       && __lc->_M_negative_sign_size);
+	// String of grouping info from thousands_sep plucked from __units.
+	string __grouping_tmp;
+	if (__lc->_M_use_grouping)
+	  __grouping_tmp.reserve(32);
+	// Last position before the decimal point.
+	int __last_pos = 0;
+	// Separator positions, then, possibly, fractional digits.
+	int __n = 0;
+	// If input iterator is in a valid state.
+	bool __testvalid = true;
+	// Flag marking when a decimal point is found.
+	bool __testdecfound = false;
+
+	// The tentative returned string is stored here.
+	string __res;
+	__res.reserve(32);
+
+	const char_type* __lit_zero = __lit + money_base::_S_zero;
+	const money_base::pattern __p = __lc->_M_neg_format;
+	for (int __i = 0; __i < 4 && __testvalid; ++__i)
+	  {
+	    const part __which = static_cast<part>(__p.field[__i]);
+	    switch (__which)
+	      {
+	      case money_base::symbol:
+		// According to 22.2.6.1.2, p2, symbol is required
+		// if (__io.flags() & ios_base::showbase), otherwise
+		// is optional and consumed only if other characters
+		// are needed to complete the format.
+		if (__io.flags() & ios_base::showbase || __sign_size > 1
+		    || __i == 0
+		    || (__i == 1 && (__mandatory_sign
+				     || (static_cast<part>(__p.field[0])
+					 == money_base::sign)
+				     || (static_cast<part>(__p.field[2])
+					 == money_base::space)))
+		    || (__i == 2 && ((static_cast<part>(__p.field[3])
+				      == money_base::value)
+				     || (__mandatory_sign
+					 && (static_cast<part>(__p.field[3])
+					     == money_base::sign)))))
+		  {
+		    const size_type __len = __lc->_M_curr_symbol_size;
+		    size_type __j = 0;
+		    for (; __beg != __end && __j < __len
+			   && *__beg == __lc->_M_curr_symbol[__j];
+			 ++__beg, ++__j);
+		    if (__j != __len
+			&& (__j || __io.flags() & ios_base::showbase))
+		      __testvalid = false;
+		  }
+		break;
+	      case money_base::sign:
+		// Sign might not exist, or be more than one character long.
+		if (__lc->_M_positive_sign_size && __beg != __end
+		    && *__beg == __lc->_M_positive_sign[0])
+		  {
+		    __sign_size = __lc->_M_positive_sign_size;
+		    ++__beg;
+		  }
+		else if (__lc->_M_negative_sign_size && __beg != __end
+			 && *__beg == __lc->_M_negative_sign[0])
+		  {
+		    __negative = true;
+		    __sign_size = __lc->_M_negative_sign_size;
+		    ++__beg;
+		  }
+		else if (__lc->_M_positive_sign_size
+			 && !__lc->_M_negative_sign_size)
+		  // "... if no sign is detected, the result is given the sign
+		  // that corresponds to the source of the empty string"
+		  __negative = true;
+		else if (__mandatory_sign)
+		  __testvalid = false;
+		break;
+	      case money_base::value:
+		// Extract digits, remove and stash away the
+		// grouping of found thousands separators.
+		for (; __beg != __end; ++__beg)
+		  {
+		    const char_type __c = *__beg;
+		    const char_type* __q = __traits_type::find(__lit_zero, 
+							       10, __c);
+		    if (__q != 0)
+		      {
+			__res += money_base::_S_atoms[__q - __lit];
+			++__n;
+		      }
+		    else if (__c == __lc->_M_decimal_point 
+			     && !__testdecfound)
+		      {
+			__last_pos = __n;
+			__n = 0;
+			__testdecfound = true;
+		      }
+		    else if (__lc->_M_use_grouping
+			     && __c == __lc->_M_thousands_sep
+			     && !__testdecfound)
+		      {
+			if (__n)
+			  {
+			    // Mark position for later analysis.
+			    __grouping_tmp += static_cast<char>(__n);
+			    __n = 0;
+			  }
+			else
+			  {
+			    __testvalid = false;
+			    break;
+			  }
+		      }
+		    else
+		      break;
+		  }
+		if (__res.empty())
+		  __testvalid = false;
+		break;
+	      case money_base::space:
+		// At least one space is required.
+		if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
+		  ++__beg;
+		else
+		  __testvalid = false;
+	      case money_base::none:
+		// Only if not at the end of the pattern.
+		if (__i != 3)
+		  for (; __beg != __end
+			 && __ctype.is(ctype_base::space, *__beg); ++__beg);
+		break;
+	      }
+	  }
+
+	// Need to get the rest of the sign characters, if they exist.
+	if (__sign_size > 1 && __testvalid)
+	  {
+	    const char_type* __sign = __negative ? __lc->_M_negative_sign
+	                                         : __lc->_M_positive_sign;
+	    size_type __i = 1;
+	    for (; __beg != __end && __i < __sign_size
+		   && *__beg == __sign[__i]; ++__beg, ++__i);
+	    
+	    if (__i != __sign_size)
+	      __testvalid = false;
+	  }
+
+	if (__testvalid)
+	  {
+	    // Strip leading zeros.
+	    if (__res.size() > 1)
+	      {
+		const size_type __first = __res.find_first_not_of('0');
+		const bool __only_zeros = __first == string::npos;
+		if (__first)
+		  __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
+	      }
+
+	    // 22.2.6.1.2, p4
+	    if (__negative && __res[0] != '0')
+	      __res.insert(__res.begin(), '-');
+	    
+	    // Test for grouping fidelity.
+	    if (__grouping_tmp.size())
+	      {
+		// Add the ending grouping.
+		__grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
+						                   : __n);
+		if (!std::__verify_grouping(__lc->_M_grouping,
+					    __lc->_M_grouping_size,
+					    __grouping_tmp))
+		  __err |= ios_base::failbit;
+	      }
+	    
+	    // Iff not enough digits were supplied after the decimal-point.
+	    if (__testdecfound && __lc->_M_frac_digits > 0
+		&& __n != __lc->_M_frac_digits)
+	      __testvalid = false;
+	  }
+	
+	// Iff valid sequence is not recognized.
+	if (!__testvalid)
+	  __err |= ios_base::failbit;
+	else
+	  __units.swap(__res);
+	
+	// Iff no more characters are available.
+	if (__beg == __end)
+	  __err |= ios_base::eofbit;
+	return __beg;
+      }
+
+#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
+  template<typename _CharT, typename _InIter>
+    _InIter
+    money_get<_CharT, _InIter>::
+    __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
+	     ios_base::iostate& __err, double& __units) const
+    {
+      string __str;
+      __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
+                     : _M_extract<false>(__beg, __end, __io, __err, __str);
+      std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
+      return __beg;
+    }
+#endif
+
+  template<typename _CharT, typename _InIter>
+    _InIter
+    money_get<_CharT, _InIter>::
+    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
+	   ios_base::iostate& __err, long double& __units) const
+    {
+      string __str;
+      __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
+	             : _M_extract<false>(__beg, __end, __io, __err, __str);
+      std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
+      return __beg;
+    }
+
+  template<typename _CharT, typename _InIter>
+    _InIter
+    money_get<_CharT, _InIter>::
+    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
+	   ios_base::iostate& __err, string_type& __digits) const
+    {
+      typedef typename string::size_type                  size_type;
+
+      const locale& __loc = __io._M_getloc();
+      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+
+      string __str;
+      __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
+	             : _M_extract<false>(__beg, __end, __io, __err, __str);
+      const size_type __len = __str.size();
+      if (__len)
+	{
+	  __digits.resize(__len);
+	  __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]);
+	}
+      return __beg;
+    }
+
+  template<typename _CharT, typename _OutIter>
+    template<bool _Intl>
+      _OutIter
+      money_put<_CharT, _OutIter>::
+      _M_insert(iter_type __s, ios_base& __io, char_type __fill,
+		const string_type& __digits) const
+      {
+	typedef typename string_type::size_type	          size_type;
+	typedef money_base::part                          part;
+	typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
+      
+	const locale& __loc = __io._M_getloc();
+	const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+
+	__use_cache<__cache_type> __uc;
+	const __cache_type* __lc = __uc(__loc);
+	const char_type* __lit = __lc->_M_atoms;
+
+	// Determine if negative or positive formats are to be used, and
+	// discard leading negative_sign if it is present.
+	const char_type* __beg = __digits.data();
+
+	money_base::pattern __p;
+	const char_type* __sign;
+	size_type __sign_size;
+	if (!(*__beg == __lit[money_base::_S_minus]))
+	  {
+	    __p = __lc->_M_pos_format;
+	    __sign = __lc->_M_positive_sign;
+	    __sign_size = __lc->_M_positive_sign_size;
+	  }
+	else
+	  {
+	    __p = __lc->_M_neg_format;
+	    __sign = __lc->_M_negative_sign;
+	    __sign_size = __lc->_M_negative_sign_size;
+	    if (__digits.size())
+	      ++__beg;
+	  }
+       
+	// Look for valid numbers in the ctype facet within input digits.
+	size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
+					   __beg + __digits.size()) - __beg;
+	if (__len)
+	  {
+	    // Assume valid input, and attempt to format.
+	    // Break down input numbers into base components, as follows:
+	    //   final_value = grouped units + (decimal point) + (digits)
+	    string_type __value;
+	    __value.reserve(2 * __len);
+
+	    // Add thousands separators to non-decimal digits, per
+	    // grouping rules.
+	    long __paddec = __len - __lc->_M_frac_digits;
+	    if (__paddec > 0)
+  	      {
+		if (__lc->_M_frac_digits < 0)
+		  __paddec = __len;
+  		if (__lc->_M_grouping_size)
+  		  {
+		    __value.assign(2 * __paddec, char_type());
+ 		    _CharT* __vend = 
+		      std::__add_grouping(&__value[0], __lc->_M_thousands_sep,
+					  __lc->_M_grouping,
+					  __lc->_M_grouping_size,
+					  __beg, __beg + __paddec);
+		    __value.erase(__vend - &__value[0]);
+  		  }
+  		else
+		  __value.assign(__beg, __paddec);
+	      }
+
+	    // Deal with decimal point, decimal digits.
+	    if (__lc->_M_frac_digits > 0)
+	      {
+		__value += __lc->_M_decimal_point;
+		if (__paddec >= 0)
+		  __value.append(__beg + __paddec, __lc->_M_frac_digits);
+		else
+		  {
+		    // Have to pad zeros in the decimal position.
+		    __value.append(-__paddec, __lit[money_base::_S_zero]);
+		    __value.append(__beg, __len);
+		  }
+  	      }
+  
+	    // Calculate length of resulting string.
+	    const ios_base::fmtflags __f = __io.flags() 
+	                                   & ios_base::adjustfield;
+	    __len = __value.size() + __sign_size;
+	    __len += ((__io.flags() & ios_base::showbase)
+		      ? __lc->_M_curr_symbol_size : 0);
+
+	    string_type __res;
+	    __res.reserve(2 * __len);
+	    
+	    const size_type __width = static_cast<size_type>(__io.width());  
+	    const bool __testipad = (__f == ios_base::internal
+				     && __len < __width);
+	    // Fit formatted digits into the required pattern.
+	    for (int __i = 0; __i < 4; ++__i)
+	      {
+		const part __which = static_cast<part>(__p.field[__i]);
+		switch (__which)
+		  {
+		  case money_base::symbol:
+		    if (__io.flags() & ios_base::showbase)
+		      __res.append(__lc->_M_curr_symbol,
+				   __lc->_M_curr_symbol_size);
+		    break;
+		  case money_base::sign:
+		    // Sign might not exist, or be more than one
+		    // charater long. In that case, add in the rest
+		    // below.
+		    if (__sign_size)
+		      __res += __sign[0];
+		    break;
+		  case money_base::value:
+		    __res += __value;
+		    break;
+		  case money_base::space:
+		    // At least one space is required, but if internal
+		    // formatting is required, an arbitrary number of
+		    // fill spaces will be necessary.
+		    if (__testipad)
+		      __res.append(__width - __len, __fill);
+		    else
+		      __res += __fill;
+		    break;
+		  case money_base::none:
+		    if (__testipad)
+		      __res.append(__width - __len, __fill);
+		    break;
+		  }
+	      }
+	    
+	    // Special case of multi-part sign parts.
+	    if (__sign_size > 1)
+	      __res.append(__sign + 1, __sign_size - 1);
+	    
+	    // Pad, if still necessary.
+	    __len = __res.size();
+	    if (__width > __len)
+	      {
+		if (__f == ios_base::left)
+		  // After.
+		  __res.append(__width - __len, __fill);
+		else
+		  // Before.
+		  __res.insert(0, __width - __len, __fill);
+		__len = __width;
+	      }
+	    
+	    // Write resulting, fully-formatted string to output iterator.
+	    __s = std::__write(__s, __res.data(), __len);
+	  }
+	__io.width(0);
+	return __s;    
+      }
+
+#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
+  template<typename _CharT, typename _OutIter>
+    _OutIter
+    money_put<_CharT, _OutIter>::
+    __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
+	     double __units) const
+    { return this->do_put(__s, __intl, __io, __fill, (long double) __units); }
+#endif
+
+  template<typename _CharT, typename _OutIter>
+    _OutIter
+    money_put<_CharT, _OutIter>::
+    do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
+	   long double __units) const
+    {
+      const locale __loc = __io.getloc();
+      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+#ifdef _GLIBCXX_USE_C99
+      // First try a buffer perhaps big enough.
+      int __cs_size = 64;
+      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 328. Bad sprintf format modifier in money_put<>::do_put()
+      int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+					"%.*Lf", 0, __units);
+      // If the buffer was not large enough, try again with the correct size.
+      if (__len >= __cs_size)
+	{
+	  __cs_size = __len + 1;
+	  __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+	  __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+					"%.*Lf", 0, __units);
+	}
+#else
+      // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
+      const int __cs_size =
+	__gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
+      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+      int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf", 
+					0, __units);
+#endif
+      string_type __digits(__len, char_type());
+      __ctype.widen(__cs, __cs + __len, &__digits[0]);
+      return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
+	            : _M_insert<false>(__s, __io, __fill, __digits);
+    }
+
+  template<typename _CharT, typename _OutIter>
+    _OutIter
+    money_put<_CharT, _OutIter>::
+    do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
+	   const string_type& __digits) const
+    { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
+	            : _M_insert<false>(__s, __io, __fill, __digits); }
+
+_GLIBCXX_END_LDBL_NAMESPACE
+
+  // NB: Not especially useful. Without an ios_base object or some
+  // kind of locale reference, we are left clawing at the air where
+  // the side of the mountain used to be...
+  template<typename _CharT, typename _InIter>
+    time_base::dateorder
+    time_get<_CharT, _InIter>::do_date_order() const
+    { return time_base::no_order; }
+
+  // Expand a strftime format string and parse it.  E.g., do_get_date() may
+  // pass %m/%d/%Y => extracted characters.
+  template<typename _CharT, typename _InIter>
+    _InIter
+    time_get<_CharT, _InIter>::
+    _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
+			  ios_base::iostate& __err, tm* __tm,
+			  const _CharT* __format) const
+    {
+      const locale& __loc = __io._M_getloc();
+      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
+      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+      const size_t __len = char_traits<_CharT>::length(__format);
+
+      ios_base::iostate __tmperr = ios_base::goodbit;
+      for (size_t __i = 0; __beg != __end && __i < __len && !__tmperr; ++__i)
+	{
+	  if (__ctype.narrow(__format[__i], 0) == '%')
+	    {
+	      // Verify valid formatting code, attempt to extract.
+	      char __c = __ctype.narrow(__format[++__i], 0);
+	      int __mem = 0;
+	      if (__c == 'E' || __c == 'O')
+		__c = __ctype.narrow(__format[++__i], 0);
+	      switch (__c)
+		{
+		  const char* __cs;
+		  _CharT __wcs[10];
+		case 'a':
+		  // Abbreviated weekday name [tm_wday]
+		  const char_type*  __days1[7];
+		  __tp._M_days_abbreviated(__days1);
+		  __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
+					  7, __io, __tmperr);
+		  break;
+		case 'A':
+		  // Weekday name [tm_wday].
+		  const char_type*  __days2[7];
+		  __tp._M_days(__days2);
+		  __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
+					  7, __io, __tmperr);
+		  break;
+		case 'h':
+		case 'b':
+		  // Abbreviated month name [tm_mon]
+		  const char_type*  __months1[12];
+		  __tp._M_months_abbreviated(__months1);
+		  __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
+					  __months1, 12, __io, __tmperr);
+		  break;
+		case 'B':
+		  // Month name [tm_mon].
+		  const char_type*  __months2[12];
+		  __tp._M_months(__months2);
+		  __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
+					  __months2, 12, __io, __tmperr);
+		  break;
+		case 'c':
+		  // Default time and date representation.
+		  const char_type*  __dt[2];
+		  __tp._M_date_time_formats(__dt);
+		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
+						__tm, __dt[0]);
+		  break;
+		case 'd':
+		  // Day [01, 31]. [tm_mday]
+		  __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
+					 __io, __tmperr);
+		  break;
+		case 'e':
+		  // Day [1, 31], with single digits preceded by
+		  // space. [tm_mday]
+		  if (__ctype.is(ctype_base::space, *__beg))
+		    __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
+					   1, __io, __tmperr);
+		  else
+		    __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
+					   2, __io, __tmperr);
+		  break;
+		case 'D':
+		  // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
+		  __cs = "%m/%d/%y";
+		  __ctype.widen(__cs, __cs + 9, __wcs);
+		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
+						__tm, __wcs);
+		  break;
+		case 'H':
+		  // Hour [00, 23]. [tm_hour]
+		  __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
+					 __io, __tmperr);
+		  break;
+		case 'I':
+		  // Hour [01, 12]. [tm_hour]
+		  __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
+					 __io, __tmperr);
+		  break;
+		case 'm':
+		  // Month [01, 12]. [tm_mon]
+		  __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 
+					 __io, __tmperr);
+		  if (!__tmperr)
+		    __tm->tm_mon = __mem - 1;
+		  break;
+		case 'M':
+		  // Minute [00, 59]. [tm_min]
+		  __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
+					 __io, __tmperr);
+		  break;
+		case 'n':
+		  if (__ctype.narrow(*__beg, 0) == '\n')
+		    ++__beg;
+		  else
+		    __tmperr |= ios_base::failbit;
+		  break;
+		case 'R':
+		  // Equivalent to (%H:%M).
+		  __cs = "%H:%M";
+		  __ctype.widen(__cs, __cs + 6, __wcs);
+		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
+						__tm, __wcs);
+		  break;
+		case 'S':
+		  // Seconds. [tm_sec]
+		  // [00, 60] in C99 (one leap-second), [00, 61] in C89.
+#ifdef _GLIBCXX_USE_C99
+		  __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2,
+#else
+		  __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
+#endif
+					 __io, __tmperr);
+		  break;
+		case 't':
+		  if (__ctype.narrow(*__beg, 0) == '\t')
+		    ++__beg;
+		  else
+		    __tmperr |= ios_base::failbit;
+		  break;
+		case 'T':
+		  // Equivalent to (%H:%M:%S).
+		  __cs = "%H:%M:%S";
+		  __ctype.widen(__cs, __cs + 9, __wcs);
+		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
+						__tm, __wcs);
+		  break;
+		case 'x':
+		  // Locale's date.
+		  const char_type*  __dates[2];
+		  __tp._M_date_formats(__dates);
+		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
+						__tm, __dates[0]);
+		  break;
+		case 'X':
+		  // Locale's time.
+		  const char_type*  __times[2];
+		  __tp._M_time_formats(__times);
+		  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
+						__tm, __times[0]);
+		  break;
+		case 'y':
+		case 'C': // C99
+		  // Two digit year. [tm_year]
+		  __beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
+					 __io, __tmperr);
+		  break;
+		case 'Y':
+		  // Year [1900). [tm_year]
+		  __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
+					 __io, __tmperr);
+		  if (!__tmperr)
+		    __tm->tm_year = __mem - 1900;
+		  break;
+		case 'Z':
+		  // Timezone info.
+		  if (__ctype.is(ctype_base::upper, *__beg))
+		    {
+		      int __tmp;
+		      __beg = _M_extract_name(__beg, __end, __tmp,
+				       __timepunct_cache<_CharT>::_S_timezones,
+					      14, __io, __tmperr);
+
+		      // GMT requires special effort.
+		      if (__beg != __end && !__tmperr && __tmp == 0
+			  && (*__beg == __ctype.widen('-')
+			      || *__beg == __ctype.widen('+')))
+			{
+			  __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
+						 __io, __tmperr);
+			  __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
+						 __io, __tmperr);
+			}
+		    }
+		  else
+		    __tmperr |= ios_base::failbit;
+		  break;
+		default:
+		  // Not recognized.
+		  __tmperr |= ios_base::failbit;
+		}
+	    }
+	  else
+	    {
+	      // Verify format and input match, extract and discard.
+	      if (__format[__i] == *__beg)
+		++__beg;
+	      else
+		__tmperr |= ios_base::failbit;
+	    }
+	}
+
+      if (__tmperr)
+	__err |= ios_base::failbit;
+  
+      return __beg;
+    }
+
+  template<typename _CharT, typename _InIter>
+    _InIter
+    time_get<_CharT, _InIter>::
+    _M_extract_num(iter_type __beg, iter_type __end, int& __member,
+		   int __min, int __max, size_t __len,
+		   ios_base& __io, ios_base::iostate& __err) const
+    {
+      const locale& __loc = __io._M_getloc();
+      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+
+      // As-is works for __len = 1, 2, 4, the values actually used.
+      int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
+
+      ++__min;
+      size_t __i = 0;
+      int __value = 0;
+      for (; __beg != __end && __i < __len; ++__beg, ++__i)
+	{
+	  const char __c = __ctype.narrow(*__beg, '*');
+	  if (__c >= '0' && __c <= '9')
+	    {
+	      __value = __value * 10 + (__c - '0');
+	      const int __valuec = __value * __mult;
+	      if (__valuec > __max || __valuec + __mult < __min)
+		break;
+	      __mult /= 10;
+	    }
+	  else
+	    break;
+	}
+      if (__i == __len)
+	__member = __value;
+      else
+	__err |= ios_base::failbit;
+
+      return __beg;
+    }
+
+  // Assumptions:
+  // All elements in __names are unique.
+  template<typename _CharT, typename _InIter>
+    _InIter
+    time_get<_CharT, _InIter>::
+    _M_extract_name(iter_type __beg, iter_type __end, int& __member,
+		    const _CharT** __names, size_t __indexlen,
+		    ios_base& __io, ios_base::iostate& __err) const
+    {
+      typedef char_traits<_CharT>		__traits_type;
+      const locale& __loc = __io._M_getloc();
+      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+
+      int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
+							  * __indexlen));
+      size_t __nmatches = 0;
+      size_t __pos = 0;
+      bool __testvalid = true;
+      const char_type* __name;
+
+      // Look for initial matches.
+      // NB: Some of the locale data is in the form of all lowercase
+      // names, and some is in the form of initially-capitalized
+      // names. Look for both.
+      if (__beg != __end)
+	{
+	  const char_type __c = *__beg;
+	  for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
+	    if (__c == __names[__i1][0]
+		|| __c == __ctype.toupper(__names[__i1][0]))
+	      __matches[__nmatches++] = __i1;
+	}
+
+      while (__nmatches > 1)
+	{
+	  // Find smallest matching string.
+	  size_t __minlen = __traits_type::length(__names[__matches[0]]);
+	  for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
+	    __minlen = std::min(__minlen,
+			      __traits_type::length(__names[__matches[__i2]]));
+	  ++__beg, ++__pos;
+	  if (__pos < __minlen && __beg != __end)
+	    for (size_t __i3 = 0; __i3 < __nmatches;)
+	      {
+		__name = __names[__matches[__i3]];
+		if (!(__name[__pos] == *__beg))
+		  __matches[__i3] = __matches[--__nmatches];
+		else
+		  ++__i3;
+	      }
+	  else
+	    break;
+	}
+
+      if (__nmatches == 1)
+	{
+	  // Make sure found name is completely extracted.
+	  ++__beg, ++__pos;
+	  __name = __names[__matches[0]];
+	  const size_t __len = __traits_type::length(__name);
+	  while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
+	    ++__beg, ++__pos;
+
+	  if (__len == __pos)
+	    __member = __matches[0];
+	  else
+	    __testvalid = false;
+	}
+      else
+	__testvalid = false;
+      if (!__testvalid)
+	__err |= ios_base::failbit;
+
+      return __beg;
+    }
+
+  template<typename _CharT, typename _InIter>
+    _InIter
+    time_get<_CharT, _InIter>::
+    do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
+		ios_base::iostate& __err, tm* __tm) const
+    {
+      const locale& __loc = __io._M_getloc();
+      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
+      const char_type*  __times[2];
+      __tp._M_time_formats(__times);
+      __beg = _M_extract_via_format(__beg, __end, __io, __err, 
+				    __tm, __times[0]);
+      if (__beg == __end)
+	__err |= ios_base::eofbit;
+      return __beg;
+    }
+
+  template<typename _CharT, typename _InIter>
+    _InIter
+    time_get<_CharT, _InIter>::
+    do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
+		ios_base::iostate& __err, tm* __tm) const
+    {
+      const locale& __loc = __io._M_getloc();
+      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
+      const char_type*  __dates[2];
+      __tp._M_date_formats(__dates);
+      __beg = _M_extract_via_format(__beg, __end, __io, __err, 
+				    __tm, __dates[0]);
+      if (__beg == __end)
+	__err |= ios_base::eofbit;
+      return __beg;
+    }
+
+  template<typename _CharT, typename _InIter>
+    _InIter
+    time_get<_CharT, _InIter>::
+    do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
+		   ios_base::iostate& __err, tm* __tm) const
+    {
+      typedef char_traits<_CharT>		__traits_type;
+      const locale& __loc = __io._M_getloc();
+      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
+      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+      const char_type*  __days[7];
+      __tp._M_days_abbreviated(__days);
+      int __tmpwday;
+      ios_base::iostate __tmperr = ios_base::goodbit;
+      __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7,
+			      __io, __tmperr);
+
+      // Check to see if non-abbreviated name exists, and extract.
+      // NB: Assumes both _M_days and _M_days_abbreviated organized in
+      // exact same order, first to last, such that the resulting
+      // __days array with the same index points to a day, and that
+      // day's abbreviated form.
+      // NB: Also assumes that an abbreviated name is a subset of the name.
+      if (!__tmperr && __beg != __end)
+	{
+	  size_t __pos = __traits_type::length(__days[__tmpwday]);
+	  __tp._M_days(__days);
+	  const char_type* __name = __days[__tmpwday];
+	  if (__name[__pos] == *__beg)
+	    {
+	      // Extract the rest of it.
+	      const size_t __len = __traits_type::length(__name);
+	      while (__pos < __len && __beg != __end
+		     && __name[__pos] == *__beg)
+		++__beg, ++__pos;
+	      if (__len != __pos)
+		__tmperr |= ios_base::failbit;
+	    }
+	}
+      if (!__tmperr)
+	__tm->tm_wday = __tmpwday;
+      else
+	__err |= ios_base::failbit;
+
+      if (__beg == __end)
+	__err |= ios_base::eofbit;
+      return __beg;
+     }
+
+  template<typename _CharT, typename _InIter>
+    _InIter
+    time_get<_CharT, _InIter>::
+    do_get_monthname(iter_type __beg, iter_type __end,
+                     ios_base& __io, ios_base::iostate& __err, tm* __tm) const
+    {
+      typedef char_traits<_CharT>		__traits_type;
+      const locale& __loc = __io._M_getloc();
+      const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
+      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+      const char_type*  __months[12];
+      __tp._M_months_abbreviated(__months);
+      int __tmpmon;
+      ios_base::iostate __tmperr = ios_base::goodbit;
+      __beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12, 
+			      __io, __tmperr);
+
+      // Check to see if non-abbreviated name exists, and extract.
+      // NB: Assumes both _M_months and _M_months_abbreviated organized in
+      // exact same order, first to last, such that the resulting
+      // __months array with the same index points to a month, and that
+      // month's abbreviated form.
+      // NB: Also assumes that an abbreviated name is a subset of the name.
+      if (!__tmperr && __beg != __end)
+	{
+	  size_t __pos = __traits_type::length(__months[__tmpmon]);
+	  __tp._M_months(__months);
+	  const char_type* __name = __months[__tmpmon];
+	  if (__name[__pos] == *__beg)
+	    {
+	      // Extract the rest of it.
+	      const size_t __len = __traits_type::length(__name);
+	      while (__pos < __len && __beg != __end
+		     && __name[__pos] == *__beg)
+		++__beg, ++__pos;
+	      if (__len != __pos)
+		__tmperr |= ios_base::failbit;
+	    }
+	}
+      if (!__tmperr)
+	__tm->tm_mon = __tmpmon;
+      else
+	__err |= ios_base::failbit;
+
+      if (__beg == __end)
+	__err |= ios_base::eofbit;
+      return __beg;
+    }
+
+  template<typename _CharT, typename _InIter>
+    _InIter
+    time_get<_CharT, _InIter>::
+    do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
+		ios_base::iostate& __err, tm* __tm) const
+    {
+      const locale& __loc = __io._M_getloc();
+      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+
+      size_t __i = 0;
+      int __value = 0;
+      for (; __beg != __end && __i < 4; ++__beg, ++__i)
+	{
+	  const char __c = __ctype.narrow(*__beg, '*');
+	  if (__c >= '0' && __c <= '9')
+	    __value = __value * 10 + (__c - '0');
+	  else
+	    break;
+	}
+      if (__i == 2 || __i == 4)
+	__tm->tm_year = __i == 2 ? __value : __value - 1900;
+      else
+	__err |= ios_base::failbit;
+
+      if (__beg == __end)
+	__err |= ios_base::eofbit;
+      return __beg;
+    }
+
+  template<typename _CharT, typename _OutIter>
+    _OutIter
+    time_put<_CharT, _OutIter>::
+    put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
+	const _CharT* __beg, const _CharT* __end) const
+    {
+      const locale& __loc = __io._M_getloc();
+      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
+      for (; __beg != __end; ++__beg)
+	if (__ctype.narrow(*__beg, 0) != '%')
+	  {
+	    *__s = *__beg;
+	    ++__s;
+	  }
+	else if (++__beg != __end)
+	  {
+	    char __format;
+	    char __mod = 0;
+	    const char __c = __ctype.narrow(*__beg, 0);
+	    if (__c != 'E' && __c != 'O')
+	      __format = __c;
+	    else if (++__beg != __end)
+	      {
+		__mod = __c;
+		__format = __ctype.narrow(*__beg, 0);
+	      }
+	    else
+	      break;
+	    __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
+	  }
+	else
+	  break;
+      return __s;
+    }
+
+  template<typename _CharT, typename _OutIter>
+    _OutIter
+    time_put<_CharT, _OutIter>::
+    do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
+	   char __format, char __mod) const
+    {
+      const locale& __loc = __io._M_getloc();
+      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
+      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
+
+      // NB: This size is arbitrary. Should this be a data member,
+      // initialized at construction?
+      const size_t __maxlen = 128;
+      char_type* __res = 
+       static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
+
+      // NB: In IEE 1003.1-200x, and perhaps other locale models, it
+      // is possible that the format character will be longer than one
+      // character. Possibilities include 'E' or 'O' followed by a
+      // format character: if __mod is not the default argument, assume
+      // it's a valid modifier.
+      char_type __fmt[4];
+      __fmt[0] = __ctype.widen('%');
+      if (!__mod)
+	{
+	  __fmt[1] = __format;
+	  __fmt[2] = char_type();
+	}
+      else
+	{
+	  __fmt[1] = __mod;
+	  __fmt[2] = __format;
+	  __fmt[3] = char_type();
+	}
+
+      __tp._M_put(__res, __maxlen, __fmt, __tm);
+
+      // Write resulting, fully-formatted string to output iterator.
+      return std::__write(__s, __res, char_traits<char_type>::length(__res));
+    }
+
+  // Inhibit implicit instantiations for required instantiations,
+  // which are defined via explicit instantiations elsewhere.
+  // NB: This syntax is a GNU extension.
+#if _GLIBCXX_EXTERN_TEMPLATE
+  extern template class moneypunct<char, false>;
+  extern template class moneypunct<char, true>;
+  extern template class moneypunct_byname<char, false>;
+  extern template class moneypunct_byname<char, true>;
+  extern template class _GLIBCXX_LDBL_NAMESPACE money_get<char>;
+  extern template class _GLIBCXX_LDBL_NAMESPACE money_put<char>;
+  extern template class __timepunct<char>;
+  extern template class time_put<char>;
+  extern template class time_put_byname<char>;
+  extern template class time_get<char>;
+  extern template class time_get_byname<char>;
+  extern template class messages<char>;
+  extern template class messages_byname<char>;
+
+  extern template
+    const moneypunct<char, true>&
+    use_facet<moneypunct<char, true> >(const locale&);
+
+  extern template
+    const moneypunct<char, false>&
+    use_facet<moneypunct<char, false> >(const locale&);
+
+  extern template
+    const money_put<char>&
+    use_facet<money_put<char> >(const locale&);
+
+  extern template
+    const money_get<char>&
+    use_facet<money_get<char> >(const locale&);
+
+  extern template
+    const __timepunct<char>&
+    use_facet<__timepunct<char> >(const locale&);
+
+  extern template
+    const time_put<char>&
+    use_facet<time_put<char> >(const locale&);
+
+  extern template
+    const time_get<char>&
+    use_facet<time_get<char> >(const locale&);
+
+  extern template
+    const messages<char>&
+    use_facet<messages<char> >(const locale&);
+
+  extern template
+    bool
+    has_facet<moneypunct<char> >(const locale&);
+
+  extern template
+    bool
+    has_facet<money_put<char> >(const locale&);
+
+  extern template
+    bool
+    has_facet<money_get<char> >(const locale&);
+
+  extern template
+    bool
+    has_facet<__timepunct<char> >(const locale&);
+
+  extern template
+    bool
+    has_facet<time_put<char> >(const locale&);
+
+  extern template
+    bool
+    has_facet<time_get<char> >(const locale&);
+
+  extern template
+    bool
+    has_facet<messages<char> >(const locale&);
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+  extern template class moneypunct<wchar_t, false>;
+  extern template class moneypunct<wchar_t, true>;
+  extern template class moneypunct_byname<wchar_t, false>;
+  extern template class moneypunct_byname<wchar_t, true>;
+  extern template class _GLIBCXX_LDBL_NAMESPACE money_get<wchar_t>;
+  extern template class _GLIBCXX_LDBL_NAMESPACE money_put<wchar_t>;
+  extern template class __timepunct<wchar_t>;
+  extern template class time_put<wchar_t>;
+  extern template class time_put_byname<wchar_t>;
+  extern template class time_get<wchar_t>;
+  extern template class time_get_byname<wchar_t>;
+  extern template class messages<wchar_t>;
+  extern template class messages_byname<wchar_t>;
+
+  extern template
+    const moneypunct<wchar_t, true>&
+    use_facet<moneypunct<wchar_t, true> >(const locale&);
+
+  extern template
+    const moneypunct<wchar_t, false>&
+    use_facet<moneypunct<wchar_t, false> >(const locale&);
+
+  extern template
+    const money_put<wchar_t>&
+    use_facet<money_put<wchar_t> >(const locale&);
+
+  extern template
+    const money_get<wchar_t>&
+    use_facet<money_get<wchar_t> >(const locale&);
+
+  extern template
+    const __timepunct<wchar_t>&
+    use_facet<__timepunct<wchar_t> >(const locale&);
+
+  extern template
+    const time_put<wchar_t>&
+    use_facet<time_put<wchar_t> >(const locale&);
+
+  extern template
+    const time_get<wchar_t>&
+    use_facet<time_get<wchar_t> >(const locale&);
+
+  extern template
+    const messages<wchar_t>&
+    use_facet<messages<wchar_t> >(const locale&);
+
+  extern template
+    bool
+    has_facet<moneypunct<wchar_t> >(const locale&);
+
+  extern template
+    bool
+    has_facet<money_put<wchar_t> >(const locale&);
+
+  extern template
+    bool
+    has_facet<money_get<wchar_t> >(const locale&);
+
+  extern template
+    bool
+    has_facet<__timepunct<wchar_t> >(const locale&);
+
+  extern template
+    bool
+    has_facet<time_put<wchar_t> >(const locale&);
+
+  extern template
+    bool
+    has_facet<time_get<wchar_t> >(const locale&);
+
+  extern template
+    bool
+    has_facet<messages<wchar_t> >(const locale&);
+#endif
+#endif
+
+_GLIBCXX_END_NAMESPACE
+
+#endif
Index: include/bits/non_io_facets.h
===================================================================
--- include/bits/non_io_facets.h	(revision 0)
+++ include/bits/non_io_facets.h	(revision 0)
@@ -0,0 +1,1909 @@
+// Locale support -*- C++ -*-
+
+// Copyright (C) 2007 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+/** @file non_io_facets.h
+ *  This is an internal header file, included by other library headers.
+ *  You should not attempt to use it directly.
+ */
+
+//
+// ISO C++ 14882: 22.1  Locales
+//
+
+#ifndef _NON_IO_FACETS_H
+#define _NON_IO_FACETS_H 1
+
+#include <ctime>	// For struct tm
+
+_GLIBCXX_BEGIN_NAMESPACE(std)
+
+  /**
+   *  @brief  Time format ordering data.
+   *
+   *  This class provides an enum representing different orderings of day,
+   *  month, and year.
+  */
+  class time_base
+  {
+  public:
+    enum dateorder { no_order, dmy, mdy, ymd, ydm };
+  };
+
+  template<typename _CharT>
+    struct __timepunct_cache : public locale::facet
+    {
+      // List of all known timezones, with GMT first.
+      static const _CharT*		_S_timezones[14];
+
+      const _CharT*			_M_date_format;
+      const _CharT*			_M_date_era_format;
+      const _CharT*			_M_time_format;
+      const _CharT*			_M_time_era_format;
+      const _CharT*			_M_date_time_format;
+      const _CharT*			_M_date_time_era_format;
+      const _CharT*			_M_am;
+      const _CharT*			_M_pm;
+      const _CharT*			_M_am_pm_format;
+
+      // Day names, starting with "C"'s Sunday.
+      const _CharT*			_M_day1;
+      const _CharT*			_M_day2;
+      const _CharT*			_M_day3;
+      const _CharT*			_M_day4;
+      const _CharT*			_M_day5;
+      const _CharT*			_M_day6;
+      const _CharT*			_M_day7;
+
+      // Abbreviated day names, starting with "C"'s Sun.
+      const _CharT*			_M_aday1;
+      const _CharT*			_M_aday2;
+      const _CharT*			_M_aday3;
+      const _CharT*			_M_aday4;
+      const _CharT*			_M_aday5;
+      const _CharT*			_M_aday6;
+      const _CharT*			_M_aday7;
+
+      // Month names, starting with "C"'s January.
+      const _CharT*			_M_month01;
+      const _CharT*			_M_month02;
+      const _CharT*			_M_month03;
+      const _CharT*			_M_month04;
+      const _CharT*			_M_month05;
+      const _CharT*			_M_month06;
+      const _CharT*			_M_month07;
+      const _CharT*			_M_month08;
+      const _CharT*			_M_month09;
+      const _CharT*			_M_month10;
+      const _CharT*			_M_month11;
+      const _CharT*			_M_month12;
+
+      // Abbreviated month names, starting with "C"'s Jan.
+      const _CharT*			_M_amonth01;
+      const _CharT*			_M_amonth02;
+      const _CharT*			_M_amonth03;
+      const _CharT*			_M_amonth04;
+      const _CharT*			_M_amonth05;
+      const _CharT*			_M_amonth06;
+      const _CharT*			_M_amonth07;
+      const _CharT*			_M_amonth08;
+      const _CharT*			_M_amonth09;
+      const _CharT*			_M_amonth10;
+      const _CharT*			_M_amonth11;
+      const _CharT*			_M_amonth12;
+
+      bool				_M_allocated;
+
+      __timepunct_cache(size_t __refs = 0) : facet(__refs),
+      _M_date_format(NULL), _M_date_era_format(NULL), _M_time_format(NULL),
+      _M_time_era_format(NULL), _M_date_time_format(NULL),
+      _M_date_time_era_format(NULL), _M_am(NULL), _M_pm(NULL),
+      _M_am_pm_format(NULL), _M_day1(NULL), _M_day2(NULL), _M_day3(NULL),
+      _M_day4(NULL), _M_day5(NULL), _M_day6(NULL), _M_day7(NULL),
+      _M_aday1(NULL), _M_aday2(NULL), _M_aday3(NULL), _M_aday4(NULL),
+      _M_aday5(NULL), _M_aday6(NULL), _M_aday7(NULL), _M_month01(NULL),
+      _M_month02(NULL), _M_month03(NULL), _M_month04(NULL), _M_month05(NULL),
+      _M_month06(NULL), _M_month07(NULL), _M_month08(NULL), _M_month09(NULL),
+      _M_month10(NULL), _M_month11(NULL), _M_month12(NULL), _M_amonth01(NULL),
+      _M_amonth02(NULL), _M_amonth03(NULL), _M_amonth04(NULL),
+      _M_amonth05(NULL), _M_amonth06(NULL), _M_amonth07(NULL),
+      _M_amonth08(NULL), _M_amonth09(NULL), _M_amonth10(NULL),
+      _M_amonth11(NULL), _M_amonth12(NULL), _M_allocated(false)
+      { }
+
+      ~__timepunct_cache();
+
+      void
+      _M_cache(const locale& __loc);
+
+    private:
+      __timepunct_cache&
+      operator=(const __timepunct_cache&);
+      
+      explicit
+      __timepunct_cache(const __timepunct_cache&);
+    };
+
+  template<typename _CharT>
+    __timepunct_cache<_CharT>::~__timepunct_cache()
+    {
+      if (_M_allocated)
+	{
+	  // Unused.
+	}
+    }
+
+  // Specializations.
+  template<>
+    const char*
+    __timepunct_cache<char>::_S_timezones[14];
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+  template<>
+    const wchar_t*
+    __timepunct_cache<wchar_t>::_S_timezones[14];
+#endif
+
+  // Generic.
+  template<typename _CharT>
+    const _CharT* __timepunct_cache<_CharT>::_S_timezones[14];
+
+  template<typename _CharT>
+    class __timepunct : public locale::facet
+    {
+    public:
+      // Types:
+      typedef _CharT			__char_type;
+      typedef basic_string<_CharT>	__string_type;
+      typedef __timepunct_cache<_CharT>	__cache_type;
+
+    protected:
+      __cache_type*			_M_data;
+      __c_locale			_M_c_locale_timepunct;
+      const char*			_M_name_timepunct;
+
+    public:
+      /// Numpunct facet id.
+      static locale::id			id;
+
+      explicit
+      __timepunct(size_t __refs = 0);
+
+      explicit
+      __timepunct(__cache_type* __cache, size_t __refs = 0);
+
+      /**
+       *  @brief  Internal constructor. Not for general use.
+       *
+       *  This is a constructor for use by the library itself to set up new
+       *  locales.
+       *
+       *  @param cloc  The "C" locale.
+       *  @param s  The name of a locale.
+       *  @param refs  Passed to the base facet class.
+      */
+      explicit
+      __timepunct(__c_locale __cloc, const char* __s, size_t __refs = 0);
+
+      // FIXME: for error checking purposes _M_put should return the return
+      // value of strftime/wcsftime.
+      void
+      _M_put(_CharT* __s, size_t __maxlen, const _CharT* __format,
+	     const tm* __tm) const;
+
+      void
+      _M_date_formats(const _CharT** __date) const
+      {
+	// Always have default first.
+	__date[0] = _M_data->_M_date_format;
+	__date[1] = _M_data->_M_date_era_format;
+      }
+
+      void
+      _M_time_formats(const _CharT** __time) const
+      {
+	// Always have default first.
+	__time[0] = _M_data->_M_time_format;
+	__time[1] = _M_data->_M_time_era_format;
+      }
+
+      void
+      _M_date_time_formats(const _CharT** __dt) const
+      {
+	// Always have default first.
+	__dt[0] = _M_data->_M_date_time_format;
+	__dt[1] = _M_data->_M_date_time_era_format;
+      }
+
+      void
+      _M_am_pm_format(const _CharT* __ampm) const
+      { __ampm = _M_data->_M_am_pm_format; }
+
+      void
+      _M_am_pm(const _CharT** __ampm) const
+      {
+	__ampm[0] = _M_data->_M_am;
+	__ampm[1] = _M_data->_M_pm;
+      }
+
+      void
+      _M_days(const _CharT** __days) const
+      {
+	__days[0] = _M_data->_M_day1;
+	__days[1] = _M_data->_M_day2;
+	__days[2] = _M_data->_M_day3;
+	__days[3] = _M_data->_M_day4;
+	__days[4] = _M_data->_M_day5;
+	__days[5] = _M_data->_M_day6;
+	__days[6] = _M_data->_M_day7;
+      }
+
+      void
+      _M_days_abbreviated(const _CharT** __days) const
+      {
+	__days[0] = _M_data->_M_aday1;
+	__days[1] = _M_data->_M_aday2;
+	__days[2] = _M_data->_M_aday3;
+	__days[3] = _M_data->_M_aday4;
+	__days[4] = _M_data->_M_aday5;
+	__days[5] = _M_data->_M_aday6;
+	__days[6] = _M_data->_M_aday7;
+      }
+
+      void
+      _M_months(const _CharT** __months) const
+      {
+	__months[0] = _M_data->_M_month01;
+	__months[1] = _M_data->_M_month02;
+	__months[2] = _M_data->_M_month03;
+	__months[3] = _M_data->_M_month04;
+	__months[4] = _M_data->_M_month05;
+	__months[5] = _M_data->_M_month06;
+	__months[6] = _M_data->_M_month07;
+	__months[7] = _M_data->_M_month08;
+	__months[8] = _M_data->_M_month09;
+	__months[9] = _M_data->_M_month10;
+	__months[10] = _M_data->_M_month11;
+	__months[11] = _M_data->_M_month12;
+      }
+
+      void
+      _M_months_abbreviated(const _CharT** __months) const
+      {
+	__months[0] = _M_data->_M_amonth01;
+	__months[1] = _M_data->_M_amonth02;
+	__months[2] = _M_data->_M_amonth03;
+	__months[3] = _M_data->_M_amonth04;
+	__months[4] = _M_data->_M_amonth05;
+	__months[5] = _M_data->_M_amonth06;
+	__months[6] = _M_data->_M_amonth07;
+	__months[7] = _M_data->_M_amonth08;
+	__months[8] = _M_data->_M_amonth09;
+	__months[9] = _M_data->_M_amonth10;
+	__months[10] = _M_data->_M_amonth11;
+	__months[11] = _M_data->_M_amonth12;
+      }
+
+    protected:
+      virtual
+      ~__timepunct();
+
+      // For use at construction time only.
+      void
+      _M_initialize_timepunct(__c_locale __cloc = NULL);
+    };
+
+  template<typename _CharT>
+    locale::id __timepunct<_CharT>::id;
+
+  // Specializations.
+  template<>
+    void
+    __timepunct<char>::_M_initialize_timepunct(__c_locale __cloc);
+
+  template<>
+    void
+    __timepunct<char>::_M_put(char*, size_t, const char*, const tm*) const;
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+  template<>
+    void
+    __timepunct<wchar_t>::_M_initialize_timepunct(__c_locale __cloc);
+
+  template<>
+    void
+    __timepunct<wchar_t>::_M_put(wchar_t*, size_t, const wchar_t*,
+				 const tm*) const;
+#endif
+
+_GLIBCXX_END_NAMESPACE
+
+  // Include host and configuration specific timepunct functions.
+  #include <bits/time_members.h>
+
+_GLIBCXX_BEGIN_NAMESPACE(std)
+
+  /**
+   *  @brief  Facet for parsing dates and times.
+   *
+   *  This facet encapsulates the code to parse and return a date or
+   *  time from a string.  It is used by the istream numeric
+   *  extraction operators.
+   *
+   *  The time_get template uses protected virtual functions to provide the
+   *  actual results.  The public accessors forward the call to the virtual
+   *  functions.  These virtual functions are hooks for developers to
+   *  implement the behavior they require from the time_get facet.
+  */
+  template<typename _CharT, typename _InIter>
+    class time_get : public locale::facet, public time_base
+    {
+    public:
+      // Types:
+      //@{
+      /// Public typedefs
+      typedef _CharT			char_type;
+      typedef _InIter			iter_type;
+      //@}
+      typedef basic_string<_CharT>	__string_type;
+
+      /// Numpunct facet id.
+      static locale::id			id;
+
+      /**
+       *  @brief  Constructor performs initialization.
+       *
+       *  This is the constructor provided by the standard.
+       *
+       *  @param refs  Passed to the base facet class.
+      */
+      explicit
+      time_get(size_t __refs = 0)
+      : facet (__refs) { }
+
+      /**
+       *  @brief  Return preferred order of month, day, and year.
+       *
+       *  This function returns an enum from timebase::dateorder giving the
+       *  preferred ordering if the format "x" given to time_put::put() only
+       *  uses month, day, and year.  If the format "x" for the associated
+       *  locale uses other fields, this function returns
+       *  timebase::dateorder::noorder.
+       *
+       *  NOTE: The library always returns noorder at the moment.
+       *
+       *  @return  A member of timebase::dateorder.
+      */
+      dateorder
+      date_order()  const
+      { return this->do_date_order(); }
+
+      /**
+       *  @brief  Parse input time string.
+       *
+       *  This function parses a time according to the format "x" and puts the
+       *  results into a user-supplied struct tm.  The result is returned by
+       *  calling time_get::do_get_time().
+       *
+       *  If there is a valid time string according to format "x", @a tm will
+       *  be filled in accordingly and the returned iterator will point to the
+       *  first character beyond the time string.  If an error occurs before
+       *  the end, err |= ios_base::failbit.  If parsing reads all the
+       *  characters, err |= ios_base::eofbit.
+       *
+       *  @param  beg  Start of string to parse.
+       *  @param  end  End of string to parse.
+       *  @param  io  Source of the locale.
+       *  @param  err  Error flags to set.
+       *  @param  tm  Pointer to struct tm to fill in.
+       *  @return  Iterator to first char beyond time string.
+      */
+      iter_type
+      get_time(iter_type __beg, iter_type __end, ios_base& __io,
+	       ios_base::iostate& __err, tm* __tm)  const
+      { return this->do_get_time(__beg, __end, __io, __err, __tm); }
+
+      /**
+       *  @brief  Parse input date string.
+       *
+       *  This function parses a date according to the format "X" and puts the
+       *  results into a user-supplied struct tm.  The result is returned by
+       *  calling time_get::do_get_date().
+       *
+       *  If there is a valid date string according to format "X", @a tm will
+       *  be filled in accordingly and the returned iterator will point to the
+       *  first character beyond the date string.  If an error occurs before
+       *  the end, err |= ios_base::failbit.  If parsing reads all the
+       *  characters, err |= ios_base::eofbit.
+       *
+       *  @param  beg  Start of string to parse.
+       *  @param  end  End of string to parse.
+       *  @param  io  Source of the locale.
+       *  @param  err  Error flags to set.
+       *  @param  tm  Pointer to struct tm to fill in.
+       *  @return  Iterator to first char beyond date string.
+      */
+      iter_type
+      get_date(iter_type __beg, iter_type __end, ios_base& __io,
+	       ios_base::iostate& __err, tm* __tm)  const
+      { return this->do_get_date(__beg, __end, __io, __err, __tm); }
+
+      /**
+       *  @brief  Parse input weekday string.
+       *
+       *  This function parses a weekday name and puts the results into a
+       *  user-supplied struct tm.  The result is returned by calling
+       *  time_get::do_get_weekday().
+       *
+       *  Parsing starts by parsing an abbreviated weekday name.  If a valid
+       *  abbreviation is followed by a character that would lead to the full
+       *  weekday name, parsing continues until the full name is found or an
+       *  error occurs.  Otherwise parsing finishes at the end of the
+       *  abbreviated name.
+       *
+       *  If an error occurs before the end, err |= ios_base::failbit.  If
+       *  parsing reads all the characters, err |= ios_base::eofbit.
+       *
+       *  @param  beg  Start of string to parse.
+       *  @param  end  End of string to parse.
+       *  @param  io  Source of the locale.
+       *  @param  err  Error flags to set.
+       *  @param  tm  Pointer to struct tm to fill in.
+       *  @return  Iterator to first char beyond weekday name.
+      */
+      iter_type
+      get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
+		  ios_base::iostate& __err, tm* __tm) const
+      { return this->do_get_weekday(__beg, __end, __io, __err, __tm); }
+
+      /**
+       *  @brief  Parse input month string.
+       *
+       *  This function parses a month name and puts the results into a
+       *  user-supplied struct tm.  The result is returned by calling
+       *  time_get::do_get_monthname().
+       *
+       *  Parsing starts by parsing an abbreviated month name.  If a valid
+       *  abbreviation is followed by a character that would lead to the full
+       *  month name, parsing continues until the full name is found or an
+       *  error occurs.  Otherwise parsing finishes at the end of the
+       *  abbreviated name.
+       *
+       *  If an error occurs before the end, err |= ios_base::failbit.  If
+       *  parsing reads all the characters, err |=
+       *  ios_base::eofbit.
+       *
+       *  @param  beg  Start of string to parse.
+       *  @param  end  End of string to parse.
+       *  @param  io  Source of the locale.
+       *  @param  err  Error flags to set.
+       *  @param  tm  Pointer to struct tm to fill in.
+       *  @return  Iterator to first char beyond month name.
+      */
+      iter_type
+      get_monthname(iter_type __beg, iter_type __end, ios_base& __io,
+		    ios_base::iostate& __err, tm* __tm) const
+      { return this->do_get_monthname(__beg, __end, __io, __err, __tm); }
+
+      /**
+       *  @brief  Parse input year string.
+       *
+       *  This function reads up to 4 characters to parse a year string and
+       *  puts the results into a user-supplied struct tm.  The result is
+       *  returned by calling time_get::do_get_year().
+       *
+       *  4 consecutive digits are interpreted as a full year.  If there are
+       *  exactly 2 consecutive digits, the library interprets this as the
+       *  number of years since 1900.
+       *
+       *  If an error occurs before the end, err |= ios_base::failbit.  If
+       *  parsing reads all the characters, err |= ios_base::eofbit.
+       *
+       *  @param  beg  Start of string to parse.
+       *  @param  end  End of string to parse.
+       *  @param  io  Source of the locale.
+       *  @param  err  Error flags to set.
+       *  @param  tm  Pointer to struct tm to fill in.
+       *  @return  Iterator to first char beyond year.
+      */
+      iter_type
+      get_year(iter_type __beg, iter_type __end, ios_base& __io,
+	       ios_base::iostate& __err, tm* __tm) const
+      { return this->do_get_year(__beg, __end, __io, __err, __tm); }
+
+    protected:
+      /// Destructor.
+      virtual
+      ~time_get() { }
+
+      /**
+       *  @brief  Return preferred order of month, day, and year.
+       *
+       *  This function returns an enum from timebase::dateorder giving the
+       *  preferred ordering if the format "x" given to time_put::put() only
+       *  uses month, day, and year.  This function is a hook for derived
+       *  classes to change the value returned.
+       *
+       *  @return  A member of timebase::dateorder.
+      */
+      virtual dateorder
+      do_date_order() const;
+
+      /**
+       *  @brief  Parse input time string.
+       *
+       *  This function parses a time according to the format "x" and puts the
+       *  results into a user-supplied struct tm.  This function is a hook for
+       *  derived classes to change the value returned.  @see get_time() for
+       *  details.
+       *
+       *  @param  beg  Start of string to parse.
+       *  @param  end  End of string to parse.
+       *  @param  io  Source of the locale.
+       *  @param  err  Error flags to set.
+       *  @param  tm  Pointer to struct tm to fill in.
+       *  @return  Iterator to first char beyond time string.
+      */
+      virtual iter_type
+      do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
+		  ios_base::iostate& __err, tm* __tm) const;
+
+      /**
+       *  @brief  Parse input date string.
+       *
+       *  This function parses a date according to the format "X" and puts the
+       *  results into a user-supplied struct tm.  This function is a hook for
+       *  derived classes to change the value returned.  @see get_date() for
+       *  details.
+       *
+       *  @param  beg  Start of string to parse.
+       *  @param  end  End of string to parse.
+       *  @param  io  Source of the locale.
+       *  @param  err  Error flags to set.
+       *  @param  tm  Pointer to struct tm to fill in.
+       *  @return  Iterator to first char beyond date string.
+      */
+      virtual iter_type
+      do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
+		  ios_base::iostate& __err, tm* __tm) const;
+
+      /**
+       *  @brief  Parse input weekday string.
+       *
+       *  This function parses a weekday name and puts the results into a
+       *  user-supplied struct tm.  This function is a hook for derived
+       *  classes to change the value returned.  @see get_weekday() for
+       *  details.
+       *
+       *  @param  beg  Start of string to parse.
+       *  @param  end  End of string to parse.
+       *  @param  io  Source of the locale.
+       *  @param  err  Error flags to set.
+       *  @param  tm  Pointer to struct tm to fill in.
+       *  @return  Iterator to first char beyond weekday name.
+      */
+      virtual iter_type
+      do_get_weekday(iter_type __beg, iter_type __end, ios_base&,
+		     ios_base::iostate& __err, tm* __tm) const;
+
+      /**
+       *  @brief  Parse input month string.
+       *
+       *  This function parses a month name and puts the results into a
+       *  user-supplied struct tm.  This function is a hook for derived
+       *  classes to change the value returned.  @see get_monthname() for
+       *  details.
+       *
+       *  @param  beg  Start of string to parse.
+       *  @param  end  End of string to parse.
+       *  @param  io  Source of the locale.
+       *  @param  err  Error flags to set.
+       *  @param  tm  Pointer to struct tm to fill in.
+       *  @return  Iterator to first char beyond month name.
+      */
+      virtual iter_type
+      do_get_monthname(iter_type __beg, iter_type __end, ios_base&,
+		       ios_base::iostate& __err, tm* __tm) const;
+
+      /**
+       *  @brief  Parse input year string.
+       *
+       *  This function reads up to 4 characters to parse a year string and
+       *  puts the results into a user-supplied struct tm.  This function is a
+       *  hook for derived classes to change the value returned.  @see
+       *  get_year() for details.
+       *
+       *  @param  beg  Start of string to parse.
+       *  @param  end  End of string to parse.
+       *  @param  io  Source of the locale.
+       *  @param  err  Error flags to set.
+       *  @param  tm  Pointer to struct tm to fill in.
+       *  @return  Iterator to first char beyond year.
+      */
+      virtual iter_type
+      do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
+		  ios_base::iostate& __err, tm* __tm) const;
+
+      // Extract numeric component of length __len.
+      iter_type
+      _M_extract_num(iter_type __beg, iter_type __end, int& __member,
+		     int __min, int __max, size_t __len,
+		     ios_base& __io, ios_base::iostate& __err) const;
+
+      // Extract day or month name, or any unique array of string
+      // literals in a const _CharT* array.
+      iter_type
+      _M_extract_name(iter_type __beg, iter_type __end, int& __member,
+		      const _CharT** __names, size_t __indexlen,
+		      ios_base& __io, ios_base::iostate& __err) const;
+
+      // Extract on a component-by-component basis, via __format argument.
+      iter_type
+      _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
+			    ios_base::iostate& __err, tm* __tm,
+			    const _CharT* __format) const;
+    };
+
+  template<typename _CharT, typename _InIter>
+    locale::id time_get<_CharT, _InIter>::id;
+
+  /// @brief  class time_get_byname [22.2.5.2].
+  template<typename _CharT, typename _InIter>
+    class time_get_byname : public time_get<_CharT, _InIter>
+    {
+    public:
+      // Types:
+      typedef _CharT			char_type;
+      typedef _InIter			iter_type;
+
+      explicit
+      time_get_byname(const char*, size_t __refs = 0)
+      : time_get<_CharT, _InIter>(__refs) { }
+
+    protected:
+      virtual
+      ~time_get_byname() { }
+    };
+
+  /**
+   *  @brief  Facet for outputting dates and times.
+   *
+   *  This facet encapsulates the code to format and output dates and times
+   *  according to formats used by strftime().
+   *
+   *  The time_put template uses protected virtual functions to provide the
+   *  actual results.  The public accessors forward the call to the virtual
+   *  functions.  These virtual functions are hooks for developers to
+   *  implement the behavior they require from the time_put facet.
+  */
+  template<typename _CharT, typename _OutIter>
+    class time_put : public locale::facet
+    {
+    public:
+      // Types:
+      //@{
+      /// Public typedefs
+      typedef _CharT			char_type;
+      typedef _OutIter			iter_type;
+      //@}
+
+      /// Numpunct facet id.
+      static locale::id			id;
+
+      /**
+       *  @brief  Constructor performs initialization.
+       *
+       *  This is the constructor provided by the standard.
+       *
+       *  @param refs  Passed to the base facet class.
+      */
+      explicit
+      time_put(size_t __refs = 0)
+      : facet(__refs) { }
+
+      /**
+       *  @brief  Format and output a time or date.
+       *
+       *  This function formats the data in struct tm according to the
+       *  provided format string.  The format string is interpreted as by
+       *  strftime().
+       *
+       *  @param  s  The stream to write to.
+       *  @param  io  Source of locale.
+       *  @param  fill  char_type to use for padding.
+       *  @param  tm  Struct tm with date and time info to format.
+       *  @param  beg  Start of format string.
+       *  @param  end  End of format string.
+       *  @return  Iterator after writing.
+       */
+      iter_type
+      put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
+	  const _CharT* __beg, const _CharT* __end) const;
+
+      /**
+       *  @brief  Format and output a time or date.
+       *
+       *  This function formats the data in struct tm according to the
+       *  provided format char and optional modifier.  The format and modifier
+       *  are interpreted as by strftime().  It does so by returning
+       *  time_put::do_put().
+       *
+       *  @param  s  The stream to write to.
+       *  @param  io  Source of locale.
+       *  @param  fill  char_type to use for padding.
+       *  @param  tm  Struct tm with date and time info to format.
+       *  @param  format  Format char.
+       *  @param  mod  Optional modifier char.
+       *  @return  Iterator after writing.
+       */
+      iter_type
+      put(iter_type __s, ios_base& __io, char_type __fill,
+	  const tm* __tm, char __format, char __mod = 0) const
+      { return this->do_put(__s, __io, __fill, __tm, __format, __mod); }
+
+    protected:
+      /// Destructor.
+      virtual
+      ~time_put()
+      { }
+
+      /**
+       *  @brief  Format and output a time or date.
+       *
+       *  This function formats the data in struct tm according to the
+       *  provided format char and optional modifier.  This function is a hook
+       *  for derived classes to change the value returned.  @see put() for
+       *  more details.
+       *
+       *  @param  s  The stream to write to.
+       *  @param  io  Source of locale.
+       *  @param  fill  char_type to use for padding.
+       *  @param  tm  Struct tm with date and time info to format.
+       *  @param  format  Format char.
+       *  @param  mod  Optional modifier char.
+       *  @return  Iterator after writing.
+       */
+      virtual iter_type
+      do_put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
+	     char __format, char __mod) const;
+    };
+
+  template<typename _CharT, typename _OutIter>
+    locale::id time_put<_CharT, _OutIter>::id;
+
+  /// @brief  class time_put_byname [22.2.5.4].
+  template<typename _CharT, typename _OutIter>
+    class time_put_byname : public time_put<_CharT, _OutIter>
+    {
+    public:
+      // Types:
+      typedef _CharT			char_type;
+      typedef _OutIter			iter_type;
+
+      explicit
+      time_put_byname(const char*, size_t __refs = 0)
+      : time_put<_CharT, _OutIter>(__refs)
+      { };
+
+    protected:
+      virtual
+      ~time_put_byname() { }
+    };
+
+
+  /**
+   *  @brief  Money format ordering data.
+   *
+   *  This class contains an ordered array of 4 fields to represent the
+   *  pattern for formatting a money amount.  Each field may contain one entry
+   *  from the part enum.  symbol, sign, and value must be present and the
+   *  remaining field must contain either none or space.  @see
+   *  moneypunct::pos_format() and moneypunct::neg_format() for details of how
+   *  these fields are interpreted.
+  */
+  class money_base
+  {
+  public:
+    enum part { none, space, symbol, sign, value };
+    struct pattern { char field[4]; };
+
+    static const pattern _S_default_pattern;
+
+    enum
+    {
+      _S_minus,
+      _S_zero,
+      _S_end = 11
+    };
+
+    // String literal of acceptable (narrow) input/output, for
+    // money_get/money_put. "-0123456789"
+    static const char* _S_atoms;
+
+    // Construct and return valid pattern consisting of some combination of:
+    // space none symbol sign value
+    static pattern
+    _S_construct_pattern(char __precedes, char __space, char __posn);
+  };
+
+  template<typename _CharT, bool _Intl>
+    struct __moneypunct_cache : public locale::facet
+    {
+      const char*			_M_grouping;
+      size_t                            _M_grouping_size;
+      bool				_M_use_grouping;
+      _CharT				_M_decimal_point;
+      _CharT				_M_thousands_sep;
+      const _CharT*			_M_curr_symbol;
+      size_t                            _M_curr_symbol_size;
+      const _CharT*			_M_positive_sign;
+      size_t                            _M_positive_sign_size;
+      const _CharT*			_M_negative_sign;
+      size_t                            _M_negative_sign_size;
+      int				_M_frac_digits;
+      money_base::pattern		_M_pos_format;
+      money_base::pattern	        _M_neg_format;
+
+      // A list of valid numeric literals for input and output: in the standard
+      // "C" locale, this is "-0123456789". This array contains the chars after
+      // having been passed through the current locale's ctype<_CharT>.widen().
+      _CharT				_M_atoms[money_base::_S_end];
+
+      bool				_M_allocated;
+
+      __moneypunct_cache(size_t __refs = 0) : facet(__refs),
+      _M_grouping(NULL), _M_grouping_size(0), _M_use_grouping(false),
+      _M_decimal_point(_CharT()), _M_thousands_sep(_CharT()),
+      _M_curr_symbol(NULL), _M_curr_symbol_size(0),
+      _M_positive_sign(NULL), _M_positive_sign_size(0),
+      _M_negative_sign(NULL), _M_negative_sign_size(0),
+      _M_frac_digits(0),
+      _M_pos_format(money_base::pattern()),
+      _M_neg_format(money_base::pattern()), _M_allocated(false)
+      { }
+
+      ~__moneypunct_cache();
+
+      void
+      _M_cache(const locale& __loc);
+
+    private:
+      __moneypunct_cache&
+      operator=(const __moneypunct_cache&);
+      
+      explicit
+      __moneypunct_cache(const __moneypunct_cache&);
+    };
+
+  template<typename _CharT, bool _Intl>
+    __moneypunct_cache<_CharT, _Intl>::~__moneypunct_cache()
+    {
+      if (_M_allocated)
+	{
+	  delete [] _M_grouping;
+	  delete [] _M_curr_symbol;
+	  delete [] _M_positive_sign;
+	  delete [] _M_negative_sign;
+	}
+    }
+
+  /**
+   *  @brief  Facet for formatting data for money amounts.
+   *
+   *  This facet encapsulates the punctuation, grouping and other formatting
+   *  features of money amount string representations.
+  */
+  template<typename _CharT, bool _Intl>
+    class moneypunct : public locale::facet, public money_base
+    {
+    public:
+      // Types:
+      //@{
+      /// Public typedefs
+      typedef _CharT			char_type;
+      typedef basic_string<_CharT>	string_type;
+      //@}
+      typedef __moneypunct_cache<_CharT, _Intl>     __cache_type;
+
+    private:
+      __cache_type*			_M_data;
+
+    public:
+      /// This value is provided by the standard, but no reason for its
+      /// existence.
+      static const bool			intl = _Intl;
+      /// Numpunct facet id.
+      static locale::id			id;
+
+      /**
+       *  @brief  Constructor performs initialization.
+       *
+       *  This is the constructor provided by the standard.
+       *
+       *  @param refs  Passed to the base facet class.
+      */
+      explicit
+      moneypunct(size_t __refs = 0) : facet(__refs), _M_data(NULL)
+      { _M_initialize_moneypunct(); }
+
+      /**
+       *  @brief  Constructor performs initialization.
+       *
+       *  This is an internal constructor.
+       *
+       *  @param cache  Cache for optimization.
+       *  @param refs  Passed to the base facet class.
+      */
+      explicit
+      moneypunct(__cache_type* __cache, size_t __refs = 0)
+      : facet(__refs), _M_data(__cache)
+      { _M_initialize_moneypunct(); }
+
+      /**
+       *  @brief  Internal constructor. Not for general use.
+       *
+       *  This is a constructor for use by the library itself to set up new
+       *  locales.
+       *
+       *  @param cloc  The "C" locale.
+       *  @param s  The name of a locale.
+       *  @param refs  Passed to the base facet class.
+      */
+      explicit
+      moneypunct(__c_locale __cloc, const char* __s, size_t __refs = 0)
+      : facet(__refs), _M_data(NULL)
+      { _M_initialize_moneypunct(__cloc, __s); }
+
+      /**
+       *  @brief  Return decimal point character.
+       *
+       *  This function returns a char_type to use as a decimal point.  It
+       *  does so by returning returning
+       *  moneypunct<char_type>::do_decimal_point().
+       *
+       *  @return  @a char_type representing a decimal point.
+      */
+      char_type
+      decimal_point() const
+      { return this->do_decimal_point(); }
+
+      /**
+       *  @brief  Return thousands separator character.
+       *
+       *  This function returns a char_type to use as a thousands
+       *  separator.  It does so by returning returning
+       *  moneypunct<char_type>::do_thousands_sep().
+       *
+       *  @return  char_type representing a thousands separator.
+      */
+      char_type
+      thousands_sep() const
+      { return this->do_thousands_sep(); }
+
+      /**
+       *  @brief  Return grouping specification.
+       *
+       *  This function returns a string representing groupings for the
+       *  integer part of an amount.  Groupings indicate where thousands
+       *  separators should be inserted.
+       *
+       *  Each char in the return string is interpret as an integer rather
+       *  than a character.  These numbers represent the number of digits in a
+       *  group.  The first char in the string represents the number of digits
+       *  in the least significant group.  If a char is negative, it indicates
+       *  an unlimited number of digits for the group.  If more chars from the
+       *  string are required to group a number, the last char is used
+       *  repeatedly.
+       *
+       *  For example, if the grouping() returns "\003\002" and is applied to
+       *  the number 123456789, this corresponds to 12,34,56,789.  Note that
+       *  if the string was "32", this would put more than 50 digits into the
+       *  least significant group if the character set is ASCII.
+       *
+       *  The string is returned by calling
+       *  moneypunct<char_type>::do_grouping().
+       *
+       *  @return  string representing grouping specification.
+      */
+      string
+      grouping() const
+      { return this->do_grouping(); }
+
+      /**
+       *  @brief  Return currency symbol string.
+       *
+       *  This function returns a string_type to use as a currency symbol.  It
+       *  does so by returning returning
+       *  moneypunct<char_type>::do_curr_symbol().
+       *
+       *  @return  @a string_type representing a currency symbol.
+      */
+      string_type
+      curr_symbol() const
+      { return this->do_curr_symbol(); }
+
+      /**
+       *  @brief  Return positive sign string.
+       *
+       *  This function returns a string_type to use as a sign for positive
+       *  amounts.  It does so by returning returning
+       *  moneypunct<char_type>::do_positive_sign().
+       *
+       *  If the return value contains more than one character, the first
+       *  character appears in the position indicated by pos_format() and the
+       *  remainder appear at the end of the formatted string.
+       *
+       *  @return  @a string_type representing a positive sign.
+      */
+      string_type
+      positive_sign() const
+      { return this->do_positive_sign(); }
+
+      /**
+       *  @brief  Return negative sign string.
+       *
+       *  This function returns a string_type to use as a sign for negative
+       *  amounts.  It does so by returning returning
+       *  moneypunct<char_type>::do_negative_sign().
+       *
+       *  If the return value contains more than one character, the first
+       *  character appears in the position indicated by neg_format() and the
+       *  remainder appear at the end of the formatted string.
+       *
+       *  @return  @a string_type representing a negative sign.
+      */
+      string_type
+      negative_sign() const
+      { return this->do_negative_sign(); }
+
+      /**
+       *  @brief  Return number of digits in fraction.
+       *
+       *  This function returns the exact number of digits that make up the
+       *  fractional part of a money amount.  It does so by returning
+       *  returning moneypunct<char_type>::do_frac_digits().
+       *
+       *  The fractional part of a money amount is optional.  But if it is
+       *  present, there must be frac_digits() digits.
+       *
+       *  @return  Number of digits in amount fraction.
+      */
+      int
+      frac_digits() const
+      { return this->do_frac_digits(); }
+
+      //@{
+      /**
+       *  @brief  Return pattern for money values.
+       *
+       *  This function returns a pattern describing the formatting of a
+       *  positive or negative valued money amount.  It does so by returning
+       *  returning moneypunct<char_type>::do_pos_format() or
+       *  moneypunct<char_type>::do_neg_format().
+       *
+       *  The pattern has 4 fields describing the ordering of symbol, sign,
+       *  value, and none or space.  There must be one of each in the pattern.
+       *  The none and space enums may not appear in the first field and space
+       *  may not appear in the final field.
+       *
+       *  The parts of a money string must appear in the order indicated by
+       *  the fields of the pattern.  The symbol field indicates that the
+       *  value of curr_symbol() may be present.  The sign field indicates
+       *  that the value of positive_sign() or negative_sign() must be
+       *  present.  The value field indicates that the absolute value of the
+       *  money amount is present.  none indicates 0 or more whitespace
+       *  characters, except at the end, where it permits no whitespace.
+       *  space indicates that 1 or more whitespace characters must be
+       *  present.
+       *
+       *  For example, for the US locale and pos_format() pattern
+       *  {symbol,sign,value,none}, curr_symbol() == '$' positive_sign() ==
+       *  '+', and value 10.01, and options set to force the symbol, the
+       *  corresponding string is "$+10.01".
+       *
+       *  @return  Pattern for money values.
+      */
+      pattern
+      pos_format() const
+      { return this->do_pos_format(); }
+
+      pattern
+      neg_format() const
+      { return this->do_neg_format(); }
+      //@}
+
+    protected:
+      /// Destructor.
+      virtual
+      ~moneypunct();
+
+      /**
+       *  @brief  Return decimal point character.
+       *
+       *  Returns a char_type to use as a decimal point.  This function is a
+       *  hook for derived classes to change the value returned.
+       *
+       *  @return  @a char_type representing a decimal point.
+      */
+      virtual char_type
+      do_decimal_point() const
+      { return _M_data->_M_decimal_point; }
+
+      /**
+       *  @brief  Return thousands separator character.
+       *
+       *  Returns a char_type to use as a thousands separator.  This function
+       *  is a hook for derived classes to change the value returned.
+       *
+       *  @return  @a char_type representing a thousands separator.
+      */
+      virtual char_type
+      do_thousands_sep() const
+      { return _M_data->_M_thousands_sep; }
+
+      /**
+       *  @brief  Return grouping specification.
+       *
+       *  Returns a string representing groupings for the integer part of a
+       *  number.  This function is a hook for derived classes to change the
+       *  value returned.  @see grouping() for details.
+       *
+       *  @return  String representing grouping specification.
+      */
+      virtual string
+      do_grouping() const
+      { return _M_data->_M_grouping; }
+
+      /**
+       *  @brief  Return currency symbol string.
+       *
+       *  This function returns a string_type to use as a currency symbol.
+       *  This function is a hook for derived classes to change the value
+       *  returned.  @see curr_symbol() for details.
+       *
+       *  @return  @a string_type representing a currency symbol.
+      */
+      virtual string_type
+      do_curr_symbol()   const
+      { return _M_data->_M_curr_symbol; }
+
+      /**
+       *  @brief  Return positive sign string.
+       *
+       *  This function returns a string_type to use as a sign for positive
+       *  amounts.  This function is a hook for derived classes to change the
+       *  value returned.  @see positive_sign() for details.
+       *
+       *  @return  @a string_type representing a positive sign.
+      */
+      virtual string_type
+      do_positive_sign() const
+      { return _M_data->_M_positive_sign; }
+
+      /**
+       *  @brief  Return negative sign string.
+       *
+       *  This function returns a string_type to use as a sign for negative
+       *  amounts.  This function is a hook for derived classes to change the
+       *  value returned.  @see negative_sign() for details.
+       *
+       *  @return  @a string_type representing a negative sign.
+      */
+      virtual string_type
+      do_negative_sign() const
+      { return _M_data->_M_negative_sign; }
+
+      /**
+       *  @brief  Return number of digits in fraction.
+       *
+       *  This function returns the exact number of digits that make up the
+       *  fractional part of a money amount.  This function is a hook for
+       *  derived classes to change the value returned.  @see frac_digits()
+       *  for details.
+       *
+       *  @return  Number of digits in amount fraction.
+      */
+      virtual int
+      do_frac_digits() const
+      { return _M_data->_M_frac_digits; }
+
+      /**
+       *  @brief  Return pattern for money values.
+       *
+       *  This function returns a pattern describing the formatting of a
+       *  positive valued money amount.  This function is a hook for derived
+       *  classes to change the value returned.  @see pos_format() for
+       *  details.
+       *
+       *  @return  Pattern for money values.
+      */
+      virtual pattern
+      do_pos_format() const
+      { return _M_data->_M_pos_format; }
+
+      /**
+       *  @brief  Return pattern for money values.
+       *
+       *  This function returns a pattern describing the formatting of a
+       *  negative valued money amount.  This function is a hook for derived
+       *  classes to change the value returned.  @see neg_format() for
+       *  details.
+       *
+       *  @return  Pattern for money values.
+      */
+      virtual pattern
+      do_neg_format() const
+      { return _M_data->_M_neg_format; }
+
+      // For use at construction time only.
+       void
+       _M_initialize_moneypunct(__c_locale __cloc = NULL,
+				const char* __name = NULL);
+    };
+
+  template<typename _CharT, bool _Intl>
+    locale::id moneypunct<_CharT, _Intl>::id;
+
+  template<typename _CharT, bool _Intl>
+    const bool moneypunct<_CharT, _Intl>::intl;
+
+  template<>
+    moneypunct<char, true>::~moneypunct();
+
+  template<>
+    moneypunct<char, false>::~moneypunct();
+
+  template<>
+    void
+    moneypunct<char, true>::_M_initialize_moneypunct(__c_locale, const char*);
+
+  template<>
+    void
+    moneypunct<char, false>::_M_initialize_moneypunct(__c_locale, const char*);
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+  template<>
+    moneypunct<wchar_t, true>::~moneypunct();
+
+  template<>
+    moneypunct<wchar_t, false>::~moneypunct();
+
+  template<>
+    void
+    moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale,
+							const char*);
+
+  template<>
+    void
+    moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale,
+							 const char*);
+#endif
+
+  /// @brief  class moneypunct_byname [22.2.6.4].
+  template<typename _CharT, bool _Intl>
+    class moneypunct_byname : public moneypunct<_CharT, _Intl>
+    {
+    public:
+      typedef _CharT			char_type;
+      typedef basic_string<_CharT>	string_type;
+
+      static const bool intl = _Intl;
+
+      explicit
+      moneypunct_byname(const char* __s, size_t __refs = 0)
+      : moneypunct<_CharT, _Intl>(__refs)
+      {
+	if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
+	  {
+	    __c_locale __tmp;
+	    this->_S_create_c_locale(__tmp, __s);
+	    this->_M_initialize_moneypunct(__tmp);
+	    this->_S_destroy_c_locale(__tmp);
+	  }
+      }
+
+    protected:
+      virtual
+      ~moneypunct_byname() { }
+    };
+
+  template<typename _CharT, bool _Intl>
+    const bool moneypunct_byname<_CharT, _Intl>::intl;
+
+_GLIBCXX_BEGIN_LDBL_NAMESPACE
+
+  /**
+   *  @brief  Facet for parsing monetary amounts.
+   *
+   *  This facet encapsulates the code to parse and return a monetary
+   *  amount from a string.
+   *
+   *  The money_get template uses protected virtual functions to
+   *  provide the actual results.  The public accessors forward the
+   *  call to the virtual functions.  These virtual functions are
+   *  hooks for developers to implement the behavior they require from
+   *  the money_get facet.
+  */
+  template<typename _CharT, typename _InIter>
+    class money_get : public locale::facet
+    {
+    public:
+      // Types:
+      //@{
+      /// Public typedefs
+      typedef _CharT			char_type;
+      typedef _InIter			iter_type;
+      typedef basic_string<_CharT>	string_type;
+      //@}
+
+      /// Numpunct facet id.
+      static locale::id			id;
+
+      /**
+       *  @brief  Constructor performs initialization.
+       *
+       *  This is the constructor provided by the standard.
+       *
+       *  @param refs  Passed to the base facet class.
+      */
+      explicit
+      money_get(size_t __refs = 0) : facet(__refs) { }
+
+      /**
+       *  @brief  Read and parse a monetary value.
+       *
+       *  This function reads characters from @a s, interprets them as a
+       *  monetary value according to moneypunct and ctype facets retrieved
+       *  from io.getloc(), and returns the result in @a units as an integral
+       *  value moneypunct::frac_digits() * the actual amount.  For example,
+       *  the string $10.01 in a US locale would store 1001 in @a units.
+       *
+       *  Any characters not part of a valid money amount are not consumed.
+       *
+       *  If a money value cannot be parsed from the input stream, sets
+       *  err=(err|io.failbit).  If the stream is consumed before finishing
+       *  parsing,  sets err=(err|io.failbit|io.eofbit).  @a units is
+       *  unchanged if parsing fails.
+       *
+       *  This function works by returning the result of do_get().
+       *
+       *  @param  s  Start of characters to parse.
+       *  @param  end  End of characters to parse.
+       *  @param  intl  Parameter to use_facet<moneypunct<CharT,intl> >.
+       *  @param  io  Source of facets and io state.
+       *  @param  err  Error field to set if parsing fails.
+       *  @param  units  Place to store result of parsing.
+       *  @return  Iterator referencing first character beyond valid money
+       *	   amount.
+       */
+      iter_type
+      get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
+	  ios_base::iostate& __err, long double& __units) const
+      { return this->do_get(__s, __end, __intl, __io, __err, __units); }
+
+      /**
+       *  @brief  Read and parse a monetary value.
+       *
+       *  This function reads characters from @a s, interprets them as a
+       *  monetary value according to moneypunct and ctype facets retrieved
+       *  from io.getloc(), and returns the result in @a digits.  For example,
+       *  the string $10.01 in a US locale would store "1001" in @a digits.
+       *
+       *  Any characters not part of a valid money amount are not consumed.
+       *
+       *  If a money value cannot be parsed from the input stream, sets
+       *  err=(err|io.failbit).  If the stream is consumed before finishing
+       *  parsing,  sets err=(err|io.failbit|io.eofbit).
+       *
+       *  This function works by returning the result of do_get().
+       *
+       *  @param  s  Start of characters to parse.
+       *  @param  end  End of characters to parse.
+       *  @param  intl  Parameter to use_facet<moneypunct<CharT,intl> >.
+       *  @param  io  Source of facets and io state.
+       *  @param  err  Error field to set if parsing fails.
+       *  @param  digits  Place to store result of parsing.
+       *  @return  Iterator referencing first character beyond valid money
+       *	   amount.
+       */
+      iter_type
+      get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
+	  ios_base::iostate& __err, string_type& __digits) const
+      { return this->do_get(__s, __end, __intl, __io, __err, __digits); }
+
+    protected:
+      /// Destructor.
+      virtual
+      ~money_get() { }
+
+      /**
+       *  @brief  Read and parse a monetary value.
+       *
+       *  This function reads and parses characters representing a monetary
+       *  value.  This function is a hook for derived classes to change the
+       *  value returned.  @see get() for details.
+       */
+      // XXX GLIBCXX_ABI Deprecated
+#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
+      virtual iter_type
+      __do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
+	       ios_base::iostate& __err, double& __units) const;
+#else
+      virtual iter_type
+      do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
+	     ios_base::iostate& __err, long double& __units) const;
+#endif
+
+      /**
+       *  @brief  Read and parse a monetary value.
+       *
+       *  This function reads and parses characters representing a monetary
+       *  value.  This function is a hook for derived classes to change the
+       *  value returned.  @see get() for details.
+       */
+      virtual iter_type
+      do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
+	     ios_base::iostate& __err, string_type& __digits) const;
+
+      // XXX GLIBCXX_ABI Deprecated
+#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
+      virtual iter_type
+      do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
+	     ios_base::iostate& __err, long double& __units) const;
+#endif
+
+      template<bool _Intl>
+        iter_type
+        _M_extract(iter_type __s, iter_type __end, ios_base& __io,
+		   ios_base::iostate& __err, string& __digits) const;     
+    };
+
+  template<typename _CharT, typename _InIter>
+    locale::id money_get<_CharT, _InIter>::id;
+
+  /**
+   *  @brief  Facet for outputting monetary amounts.
+   *
+   *  This facet encapsulates the code to format and output a monetary
+   *  amount.
+   *
+   *  The money_put template uses protected virtual functions to
+   *  provide the actual results.  The public accessors forward the
+   *  call to the virtual functions.  These virtual functions are
+   *  hooks for developers to implement the behavior they require from
+   *  the money_put facet.
+  */
+  template<typename _CharT, typename _OutIter>
+    class money_put : public locale::facet
+    {
+    public:
+      //@{
+      /// Public typedefs
+      typedef _CharT			char_type;
+      typedef _OutIter			iter_type;
+      typedef basic_string<_CharT>	string_type;
+      //@}
+
+      /// Numpunct facet id.
+      static locale::id			id;
+
+      /**
+       *  @brief  Constructor performs initialization.
+       *
+       *  This is the constructor provided by the standard.
+       *
+       *  @param refs  Passed to the base facet class.
+      */
+      explicit
+      money_put(size_t __refs = 0) : facet(__refs) { }
+
+      /**
+       *  @brief  Format and output a monetary value.
+       *
+       *  This function formats @a units as a monetary value according to
+       *  moneypunct and ctype facets retrieved from io.getloc(), and writes
+       *  the resulting characters to @a s.  For example, the value 1001 in a
+       *  US locale would write "$10.01" to @a s.
+       *
+       *  This function works by returning the result of do_put().
+       *
+       *  @param  s  The stream to write to.
+       *  @param  intl  Parameter to use_facet<moneypunct<CharT,intl> >.
+       *  @param  io  Source of facets and io state.
+       *  @param  fill  char_type to use for padding.
+       *  @param  units  Place to store result of parsing.
+       *  @return  Iterator after writing.
+       */
+      iter_type
+      put(iter_type __s, bool __intl, ios_base& __io,
+	  char_type __fill, long double __units) const
+      { return this->do_put(__s, __intl, __io, __fill, __units); }
+
+      /**
+       *  @brief  Format and output a monetary value.
+       *
+       *  This function formats @a digits as a monetary value according to
+       *  moneypunct and ctype facets retrieved from io.getloc(), and writes
+       *  the resulting characters to @a s.  For example, the string "1001" in
+       *  a US locale would write "$10.01" to @a s.
+       *
+       *  This function works by returning the result of do_put().
+       *
+       *  @param  s  The stream to write to.
+       *  @param  intl  Parameter to use_facet<moneypunct<CharT,intl> >.
+       *  @param  io  Source of facets and io state.
+       *  @param  fill  char_type to use for padding.
+       *  @param  units  Place to store result of parsing.
+       *  @return  Iterator after writing.
+       */
+      iter_type
+      put(iter_type __s, bool __intl, ios_base& __io,
+	  char_type __fill, const string_type& __digits) const
+      { return this->do_put(__s, __intl, __io, __fill, __digits); }
+
+    protected:
+      /// Destructor.
+      virtual
+      ~money_put() { }
+
+      /**
+       *  @brief  Format and output a monetary value.
+       *
+       *  This function formats @a units as a monetary value according to
+       *  moneypunct and ctype facets retrieved from io.getloc(), and writes
+       *  the resulting characters to @a s.  For example, the value 1001 in a
+       *  US locale would write "$10.01" to @a s.
+       *
+       *  This function is a hook for derived classes to change the value
+       *  returned.  @see put().
+       *
+       *  @param  s  The stream to write to.
+       *  @param  intl  Parameter to use_facet<moneypunct<CharT,intl> >.
+       *  @param  io  Source of facets and io state.
+       *  @param  fill  char_type to use for padding.
+       *  @param  units  Place to store result of parsing.
+       *  @return  Iterator after writing.
+       */
+      // XXX GLIBCXX_ABI Deprecated
+#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
+      virtual iter_type
+      __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
+	       double __units) const;
+#else
+      virtual iter_type
+      do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
+	     long double __units) const;
+#endif
+
+      /**
+       *  @brief  Format and output a monetary value.
+       *
+       *  This function formats @a digits as a monetary value according to
+       *  moneypunct and ctype facets retrieved from io.getloc(), and writes
+       *  the resulting characters to @a s.  For example, the string "1001" in
+       *  a US locale would write "$10.01" to @a s.
+       *
+       *  This function is a hook for derived classes to change the value
+       *  returned.  @see put().
+       *
+       *  @param  s  The stream to write to.
+       *  @param  intl  Parameter to use_facet<moneypunct<CharT,intl> >.
+       *  @param  io  Source of facets and io state.
+       *  @param  fill  char_type to use for padding.
+       *  @param  units  Place to store result of parsing.
+       *  @return  Iterator after writing.
+       */
+      virtual iter_type
+      do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
+	     const string_type& __digits) const;
+
+      // XXX GLIBCXX_ABI Deprecated
+#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
+      virtual iter_type
+      do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
+	     long double __units) const;
+#endif
+
+      template<bool _Intl>
+        iter_type
+        _M_insert(iter_type __s, ios_base& __io, char_type __fill,
+		  const string_type& __digits) const;
+    };
+
+  template<typename _CharT, typename _OutIter>
+    locale::id money_put<_CharT, _OutIter>::id;
+
+_GLIBCXX_END_LDBL_NAMESPACE
+
+  /**
+   *  @brief  Messages facet base class providing catalog typedef.
+   */
+  struct messages_base
+  {
+    typedef int catalog;
+  };
+
+  /**
+   *  @brief  Facet for handling message catalogs
+   *
+   *  This facet encapsulates the code to retrieve messages from
+   *  message catalogs.  The only thing defined by the standard for this facet
+   *  is the interface.  All underlying functionality is
+   *  implementation-defined.
+   *
+   *  This library currently implements 3 versions of the message facet.  The
+   *  first version (gnu) is a wrapper around gettext, provided by libintl.
+   *  The second version (ieee) is a wrapper around catgets.  The final
+   *  version (default) does no actual translation.  These implementations are
+   *  only provided for char and wchar_t instantiations.
+   *
+   *  The messages template uses protected virtual functions to
+   *  provide the actual results.  The public accessors forward the
+   *  call to the virtual functions.  These virtual functions are
+   *  hooks for developers to implement the behavior they require from
+   *  the messages facet.
+  */
+  template<typename _CharT>
+    class messages : public locale::facet, public messages_base
+    {
+    public:
+      // Types:
+      //@{
+      /// Public typedefs
+      typedef _CharT			char_type;
+      typedef basic_string<_CharT>	string_type;
+      //@}
+
+    protected:
+      // Underlying "C" library locale information saved from
+      // initialization, needed by messages_byname as well.
+      __c_locale			_M_c_locale_messages;
+      const char*			_M_name_messages;
+
+    public:
+      /// Numpunct facet id.
+      static locale::id			id;
+
+      /**
+       *  @brief  Constructor performs initialization.
+       *
+       *  This is the constructor provided by the standard.
+       *
+       *  @param refs  Passed to the base facet class.
+      */
+      explicit
+      messages(size_t __refs = 0);
+
+      // Non-standard.
+      /**
+       *  @brief  Internal constructor.  Not for general use.
+       *
+       *  This is a constructor for use by the library itself to set up new
+       *  locales.
+       *
+       *  @param  cloc  The "C" locale.
+       *  @param  s  The name of a locale.
+       *  @param  refs  Refcount to pass to the base class.
+       */
+      explicit
+      messages(__c_locale __cloc, const char* __s, size_t __refs = 0);
+
+      /*
+       *  @brief  Open a message catalog.
+       *
+       *  This function opens and returns a handle to a message catalog by
+       *  returning do_open(s, loc).
+       *
+       *  @param  s  The catalog to open.
+       *  @param  loc  Locale to use for character set conversions.
+       *  @return  Handle to the catalog or value < 0 if open fails.
+      */
+      catalog
+      open(const basic_string<char>& __s, const locale& __loc) const
+      { return this->do_open(__s, __loc); }
+
+      // Non-standard and unorthodox, yet effective.
+      /*
+       *  @brief  Open a message catalog.
+       *
+       *  This non-standard function opens and returns a handle to a message
+       *  catalog by returning do_open(s, loc).  The third argument provides a
+       *  message catalog root directory for gnu gettext and is ignored
+       *  otherwise.
+       *
+       *  @param  s  The catalog to open.
+       *  @param  loc  Locale to use for character set conversions.
+       *  @param  dir  Message catalog root directory.
+       *  @return  Handle to the catalog or value < 0 if open fails.
+      */
+      catalog
+      open(const basic_string<char>&, const locale&, const char*) const;
+
+      /*
+       *  @brief  Look up a string in a message catalog.
+       *
+       *  This function retrieves and returns a message from a catalog by
+       *  returning do_get(c, set, msgid, s).
+       *
+       *  For gnu, @a set and @a msgid are ignored.  Returns gettext(s).
+       *  For default, returns s. For ieee, returns catgets(c,set,msgid,s).
+       *
+       *  @param  c  The catalog to access.
+       *  @param  set  Implementation-defined.
+       *  @param  msgid  Implementation-defined.
+       *  @param  s  Default return value if retrieval fails.
+       *  @return  Retrieved message or @a s if get fails.
+      */
+      string_type
+      get(catalog __c, int __set, int __msgid, const string_type& __s) const
+      { return this->do_get(__c, __set, __msgid, __s); }
+
+      /*
+       *  @brief  Close a message catalog.
+       *
+       *  Closes catalog @a c by calling do_close(c).
+       *
+       *  @param  c  The catalog to close.
+      */
+      void
+      close(catalog __c) const
+      { return this->do_close(__c); }
+
+    protected:
+      /// Destructor.
+      virtual
+      ~messages();
+
+      /*
+       *  @brief  Open a message catalog.
+       *
+       *  This function opens and returns a handle to a message catalog in an
+       *  implementation-defined manner.  This function is a hook for derived
+       *  classes to change the value returned.
+       *
+       *  @param  s  The catalog to open.
+       *  @param  loc  Locale to use for character set conversions.
+       *  @return  Handle to the opened catalog, value < 0 if open failed.
+      */
+      virtual catalog
+      do_open(const basic_string<char>&, const locale&) const;
+
+      /*
+       *  @brief  Look up a string in a message catalog.
+       *
+       *  This function retrieves and returns a message from a catalog in an
+       *  implementation-defined manner.  This function is a hook for derived
+       *  classes to change the value returned.
+       *
+       *  For gnu, @a set and @a msgid are ignored.  Returns gettext(s).
+       *  For default, returns s. For ieee, returns catgets(c,set,msgid,s).
+       *
+       *  @param  c  The catalog to access.
+       *  @param  set  Implementation-defined.
+       *  @param  msgid  Implementation-defined.
+       *  @param  s  Default return value if retrieval fails.
+       *  @return  Retrieved message or @a s if get fails.
+      */
+      virtual string_type
+      do_get(catalog, int, int, const string_type& __dfault) const;
+
+      /*
+       *  @brief  Close a message catalog.
+       *
+       *  @param  c  The catalog to close.
+      */
+      virtual void
+      do_close(catalog) const;
+
+      // Returns a locale and codeset-converted string, given a char* message.
+      char*
+      _M_convert_to_char(const string_type& __msg) const
+      {
+	// XXX
+	return reinterpret_cast<char*>(const_cast<_CharT*>(__msg.c_str()));
+      }
+
+      // Returns a locale and codeset-converted string, given a char* message.
+      string_type
+      _M_convert_from_char(char*) const
+      {
+#if 0
+	// Length of message string without terminating null.
+	size_t __len = char_traits<char>::length(__msg) - 1;
+
+	// "everybody can easily convert the string using
+	// mbsrtowcs/wcsrtombs or with iconv()"
+
+	// Convert char* to _CharT in locale used to open catalog.
+	// XXX need additional template parameter on messages class for this..
+	// typedef typename codecvt<char, _CharT, _StateT> __codecvt_type;
+	typedef typename codecvt<char, _CharT, mbstate_t> __codecvt_type;
+
+	__codecvt_type::state_type __state;
+	// XXX may need to initialize state.
+	//initialize_state(__state._M_init());
+
+	char* __from_next;
+	// XXX what size for this string?
+	_CharT* __to = static_cast<_CharT*>(__builtin_alloca(__len + 1));
+	const __codecvt_type& __cvt = use_facet<__codecvt_type>(_M_locale_conv);
+	__cvt.out(__state, __msg, __msg + __len, __from_next,
+		  __to, __to + __len + 1, __to_next);
+	return string_type(__to);
+#endif
+#if 0
+	typedef ctype<_CharT> __ctype_type;
+	// const __ctype_type& __cvt = use_facet<__ctype_type>(_M_locale_msg);
+	const __ctype_type& __cvt = use_facet<__ctype_type>(locale());
+	// XXX Again, proper length of converted string an issue here.
+	// For now, assume the converted length is not larger.
+	_CharT* __dest = static_cast<_CharT*>(__builtin_alloca(__len + 1));
+	__cvt.widen(__msg, __msg + __len, __dest);
+	return basic_string<_CharT>(__dest);
+#endif
+	return string_type();
+      }
+     };
+
+  template<typename _CharT>
+    locale::id messages<_CharT>::id;
+
+  // Specializations for required instantiations.
+  template<>
+    string
+    messages<char>::do_get(catalog, int, int, const string&) const;
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+  template<>
+    wstring
+    messages<wchar_t>::do_get(catalog, int, int, const wstring&) const;
+#endif
+
+   /// @brief class messages_byname [22.2.7.2].
+   template<typename _CharT>
+    class messages_byname : public messages<_CharT>
+    {
+    public:
+      typedef _CharT			char_type;
+      typedef basic_string<_CharT>	string_type;
+
+      explicit
+      messages_byname(const char* __s, size_t __refs = 0);
+
+    protected:
+      virtual
+      ~messages_byname()
+      { }
+    };
+
+_GLIBCXX_END_NAMESPACE
+
+  // Include host and configuration specific messages functions.
+#include <bits/messages_members.h>
+
+#endif
Index: include/Makefile.in
===================================================================
--- include/Makefile.in	(revision 124038)
+++ include/Makefile.in	(working copy)
@@ -327,6 +327,8 @@
 	${bits_srcdir}/locale_facets.tcc \
 	${bits_srcdir}/localefwd.h \
 	${bits_srcdir}/mask_array.h \
+	${bits_srcdir}/non_io_facets.h \
+	${bits_srcdir}/non_io_facets.tcc \
 	${bits_srcdir}/ostream.tcc \
 	${bits_srcdir}/ostream_insert.h \
 	${bits_srcdir}/postypes.h \
Index: include/Makefile.am
===================================================================
--- include/Makefile.am	(revision 124038)
+++ include/Makefile.am	(working copy)
@@ -93,6 +93,8 @@
 	${bits_srcdir}/locale_facets.tcc \
 	${bits_srcdir}/localefwd.h \
 	${bits_srcdir}/mask_array.h \
+	${bits_srcdir}/non_io_facets.h \
+	${bits_srcdir}/non_io_facets.tcc \
 	${bits_srcdir}/ostream.tcc \
 	${bits_srcdir}/ostream_insert.h \
 	${bits_srcdir}/postypes.h \
Index: include/std/locale
===================================================================
--- include/std/locale	(revision 124038)
+++ include/std/locale	(working copy)
@@ -1,6 +1,7 @@
 // Locale support -*- C++ -*-
 
-// Copyright (C) 1997, 1998, 1999, 2002, 2003 Free Software Foundation, Inc.
+// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+// 2006, 2007 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
@@ -43,6 +44,11 @@
 #include <bits/localefwd.h>
 #include <bits/locale_classes.h>
 #include <bits/locale_facets.h>
-#include <bits/locale_facets.tcc>
+#include <bits/non_io_facets.h>
 
+#ifndef _GLIBCXX_EXPORT_TEMPLATE
+# include <bits/locale_facets.tcc>
+# include <bits/non_io_facets.tcc>
+#endif
+
 #endif /* _GLIBCXX_LOCALE */
Index: include/std/fstream
===================================================================
--- include/std/fstream	(revision 124038)
+++ include/std/fstream	(working copy)
@@ -44,7 +44,6 @@
 
 #include <istream>
 #include <ostream>
-#include <locale>	// For codecvt
 #include <cstdio>       // For BUFSIZ     
 #include <bits/basic_file.h>  // For __basic_file, __c_lock
 
Index: include/std/istream
===================================================================
--- include/std/istream	(revision 124038)
+++ include/std/istream	(working copy)
@@ -43,7 +43,6 @@
 #pragma GCC system_header
 
 #include <ios>
-#include <locale>
 #include <ostream>
 
 _GLIBCXX_BEGIN_NAMESPACE(std)
@@ -837,6 +836,7 @@
 
 #ifndef _GLIBCXX_EXPORT_TEMPLATE
 # include <bits/istream.tcc>
+# include <bits/locale_facets.tcc>
 #endif
 
 #endif	/* _GLIBCXX_ISTREAM */
Index: include/std/ostream
===================================================================
--- include/std/ostream	(revision 124038)
+++ include/std/ostream	(working copy)
@@ -43,7 +43,6 @@
 #pragma GCC system_header
 
 #include <ios>
-#include <locale>
 #include <bits/ostream_insert.h>
 
 _GLIBCXX_BEGIN_NAMESPACE(std)
@@ -571,6 +570,7 @@
 
 #ifndef _GLIBCXX_EXPORT_TEMPLATE
 # include <bits/ostream.tcc>
+# include <bits/locale_facets.tcc>
 #endif
 
 #endif	/* _GLIBCXX_OSTREAM */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]