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