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