Home | History | Annotate | Download | only in bits
      1 // Locale support -*- C++ -*-
      2 
      3 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
      4 // 2006, 2007, 2008, 2009, 2010, 2011
      5 // Free Software Foundation, Inc.
      6 //
      7 // This file is part of the GNU ISO C++ Library.  This library is free
      8 // software; you can redistribute it and/or modify it under the
      9 // terms of the GNU General Public License as published by the
     10 // Free Software Foundation; either version 3, or (at your option)
     11 // any later version.
     12 
     13 // This library is distributed in the hope that it will be useful,
     14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 // GNU General Public License for more details.
     17 
     18 // Under Section 7 of GPL version 3, you are granted additional
     19 // permissions described in the GCC Runtime Library Exception, version
     20 // 3.1, as published by the Free Software Foundation.
     21 
     22 // You should have received a copy of the GNU General Public License and
     23 // a copy of the GCC Runtime Library Exception along with this program;
     24 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     25 // <http://www.gnu.org/licenses/>.
     26 
     27 /** @file bits/locale_facets.tcc
     28  *  This is an internal header file, included by other library headers.
     29  *  Do not attempt to use it directly. @headername{locale}
     30  */
     31 
     32 #ifndef _LOCALE_FACETS_TCC
     33 #define _LOCALE_FACETS_TCC 1
     34 
     35 #pragma GCC system_header
     36 
     37 namespace std _GLIBCXX_VISIBILITY(default)
     38 {
     39 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     40 
     41   // Routine to access a cache for the facet.  If the cache didn't
     42   // exist before, it gets constructed on the fly.
     43   template<typename _Facet>
     44     struct __use_cache
     45     {
     46       const _Facet*
     47       operator() (const locale& __loc) const;
     48     };
     49 
     50   // Specializations.
     51   template<typename _CharT>
     52     struct __use_cache<__numpunct_cache<_CharT> >
     53     {
     54       const __numpunct_cache<_CharT>*
     55       operator() (const locale& __loc) const
     56       {
     57 	const size_t __i = numpunct<_CharT>::id._M_id();
     58 	const locale::facet** __caches = __loc._M_impl->_M_caches;
     59 	if (!__caches[__i])
     60 	  {
     61 	    __numpunct_cache<_CharT>* __tmp = 0;
     62 	    __try
     63 	      {
     64 		__tmp = new __numpunct_cache<_CharT>;
     65 		__tmp->_M_cache(__loc);
     66 	      }
     67 	    __catch(...)
     68 	      {
     69 		delete __tmp;
     70 		__throw_exception_again;
     71 	      }
     72 	    __loc._M_impl->_M_install_cache(__tmp, __i);
     73 	  }
     74 	return static_cast<const __numpunct_cache<_CharT>*>(__caches[__i]);
     75       }
     76     };
     77 
     78   template<typename _CharT>
     79     void
     80     __numpunct_cache<_CharT>::_M_cache(const locale& __loc)
     81     {
     82       _M_allocated = true;
     83 
     84       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
     85 
     86       char* __grouping = 0;
     87       _CharT* __truename = 0;
     88       _CharT* __falsename = 0;
     89       __try
     90 	{
     91 	  _M_grouping_size = __np.grouping().size();
     92 	  __grouping = new char[_M_grouping_size];
     93 	  __np.grouping().copy(__grouping, _M_grouping_size);
     94 	  _M_grouping = __grouping;
     95 	  _M_use_grouping = (_M_grouping_size
     96 			     && static_cast<signed char>(_M_grouping[0]) > 0
     97 			     && (_M_grouping[0]
     98 				 != __gnu_cxx::__numeric_traits<char>::__max));
     99 
    100 	  _M_truename_size = __np.truename().size();
    101 	  __truename = new _CharT[_M_truename_size];
    102 	  __np.truename().copy(__truename, _M_truename_size);
    103 	  _M_truename = __truename;
    104 
    105 	  _M_falsename_size = __np.falsename().size();
    106 	  __falsename = new _CharT[_M_falsename_size];
    107 	  __np.falsename().copy(__falsename, _M_falsename_size);
    108 	  _M_falsename = __falsename;
    109 
    110 	  _M_decimal_point = __np.decimal_point();
    111 	  _M_thousands_sep = __np.thousands_sep();
    112 
    113 	  const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
    114 	  __ct.widen(__num_base::_S_atoms_out,
    115 		     __num_base::_S_atoms_out
    116 		     + __num_base::_S_oend, _M_atoms_out);
    117 	  __ct.widen(__num_base::_S_atoms_in,
    118 		     __num_base::_S_atoms_in
    119 		     + __num_base::_S_iend, _M_atoms_in);
    120 	}
    121       __catch(...)
    122 	{
    123 	  delete [] __grouping;
    124 	  delete [] __truename;
    125 	  delete [] __falsename;
    126 	  __throw_exception_again;
    127 	}
    128     }
    129 
    130   // Used by both numeric and monetary facets.
    131   // Check to make sure that the __grouping_tmp string constructed in
    132   // money_get or num_get matches the canonical grouping for a given
    133   // locale.
    134   // __grouping_tmp is parsed L to R
    135   // 1,222,444 == __grouping_tmp of "\1\3\3"
    136   // __grouping is parsed R to L
    137   // 1,222,444 == __grouping of "\3" == "\3\3\3"
    138   _GLIBCXX_PURE bool
    139   __verify_grouping(const char* __grouping, size_t __grouping_size,
    140 		    const string& __grouping_tmp) throw ();
    141 
    142 _GLIBCXX_BEGIN_NAMESPACE_LDBL
    143 
    144   template<typename _CharT, typename _InIter>
    145     _InIter
    146     num_get<_CharT, _InIter>::
    147     _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
    148 		     ios_base::iostate& __err, string& __xtrc) const
    149     {
    150       typedef char_traits<_CharT>			__traits_type;
    151       typedef __numpunct_cache<_CharT>                  __cache_type;
    152       __use_cache<__cache_type> __uc;
    153       const locale& __loc = __io._M_getloc();
    154       const __cache_type* __lc = __uc(__loc);
    155       const _CharT* __lit = __lc->_M_atoms_in;
    156       char_type __c = char_type();
    157 
    158       // True if __beg becomes equal to __end.
    159       bool __testeof = __beg == __end;
    160 
    161       // First check for sign.
    162       if (!__testeof)
    163 	{
    164 	  __c = *__beg;
    165 	  const bool __plus = __c == __lit[__num_base::_S_iplus];
    166 	  if ((__plus || __c == __lit[__num_base::_S_iminus])
    167 	      && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
    168 	      && !(__c == __lc->_M_decimal_point))
    169 	    {
    170 	      __xtrc += __plus ? '+' : '-';
    171 	      if (++__beg != __end)
    172 		__c = *__beg;
    173 	      else
    174 		__testeof = true;
    175 	    }
    176 	}
    177 
    178       // Next, look for leading zeros.
    179       bool __found_mantissa = false;
    180       int __sep_pos = 0;
    181       while (!__testeof)
    182 	{
    183 	  if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
    184 	      || __c == __lc->_M_decimal_point)
    185 	    break;
    186 	  else if (__c == __lit[__num_base::_S_izero])
    187 	    {
    188 	      if (!__found_mantissa)
    189 		{
    190 		  __xtrc += '0';
    191 		  __found_mantissa = true;
    192 		}
    193 	      ++__sep_pos;
    194 
    195 	      if (++__beg != __end)
    196 		__c = *__beg;
    197 	      else
    198 		__testeof = true;
    199 	    }
    200 	  else
    201 	    break;
    202 	}
    203 
    204       // Only need acceptable digits for floating point numbers.
    205       bool __found_dec = false;
    206       bool __found_sci = false;
    207       string __found_grouping;
    208       if (__lc->_M_use_grouping)
    209 	__found_grouping.reserve(32);
    210       const char_type* __lit_zero = __lit + __num_base::_S_izero;
    211 
    212       if (!__lc->_M_allocated)
    213 	// "C" locale
    214 	while (!__testeof)
    215 	  {
    216 	    const int __digit = _M_find(__lit_zero, 10, __c);
    217 	    if (__digit != -1)
    218 	      {
    219 		__xtrc += '0' + __digit;
    220 		__found_mantissa = true;
    221 	      }
    222 	    else if (__c == __lc->_M_decimal_point
    223 		     && !__found_dec && !__found_sci)
    224 	      {
    225 		__xtrc += '.';
    226 		__found_dec = true;
    227 	      }
    228 	    else if ((__c == __lit[__num_base::_S_ie] 
    229 		      || __c == __lit[__num_base::_S_iE])
    230 		     && !__found_sci && __found_mantissa)
    231 	      {
    232 		// Scientific notation.
    233 		__xtrc += 'e';
    234 		__found_sci = true;
    235 		
    236 		// Remove optional plus or minus sign, if they exist.
    237 		if (++__beg != __end)
    238 		  {
    239 		    __c = *__beg;
    240 		    const bool __plus = __c == __lit[__num_base::_S_iplus];
    241 		    if (__plus || __c == __lit[__num_base::_S_iminus])
    242 		      __xtrc += __plus ? '+' : '-';
    243 		    else
    244 		      continue;
    245 		  }
    246 		else
    247 		  {
    248 		    __testeof = true;
    249 		    break;
    250 		  }
    251 	      }
    252 	    else
    253 	      break;
    254 
    255 	    if (++__beg != __end)
    256 	      __c = *__beg;
    257 	    else
    258 	      __testeof = true;
    259 	  }
    260       else
    261 	while (!__testeof)
    262 	  {
    263 	    // According to 22.2.2.1.2, p8-9, first look for thousands_sep
    264 	    // and decimal_point.
    265 	    if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
    266 	      {
    267 		if (!__found_dec && !__found_sci)
    268 		  {
    269 		    // NB: Thousands separator at the beginning of a string
    270 		    // is a no-no, as is two consecutive thousands separators.
    271 		    if (__sep_pos)
    272 		      {
    273 			__found_grouping += static_cast<char>(__sep_pos);
    274 			__sep_pos = 0;
    275 		      }
    276 		    else
    277 		      {
    278 			// NB: __convert_to_v will not assign __v and will
    279 			// set the failbit.
    280 			__xtrc.clear();
    281 			break;
    282 		      }
    283 		  }
    284 		else
    285 		  break;
    286 	      }
    287 	    else if (__c == __lc->_M_decimal_point)
    288 	      {
    289 		if (!__found_dec && !__found_sci)
    290 		  {
    291 		    // If no grouping chars are seen, no grouping check
    292 		    // is applied. Therefore __found_grouping is adjusted
    293 		    // only if decimal_point comes after some thousands_sep.
    294 		    if (__found_grouping.size())
    295 		      __found_grouping += static_cast<char>(__sep_pos);
    296 		    __xtrc += '.';
    297 		    __found_dec = true;
    298 		  }
    299 		else
    300 		  break;
    301 	      }
    302 	    else
    303 	      {
    304 		const char_type* __q =
    305 		  __traits_type::find(__lit_zero, 10, __c);
    306 		if (__q)
    307 		  {
    308 		    __xtrc += '0' + (__q - __lit_zero);
    309 		    __found_mantissa = true;
    310 		    ++__sep_pos;
    311 		  }
    312 		else if ((__c == __lit[__num_base::_S_ie] 
    313 			  || __c == __lit[__num_base::_S_iE])
    314 			 && !__found_sci && __found_mantissa)
    315 		  {
    316 		    // Scientific notation.
    317 		    if (__found_grouping.size() && !__found_dec)
    318 		      __found_grouping += static_cast<char>(__sep_pos);
    319 		    __xtrc += 'e';
    320 		    __found_sci = true;
    321 		    
    322 		    // Remove optional plus or minus sign, if they exist.
    323 		    if (++__beg != __end)
    324 		      {
    325 			__c = *__beg;
    326 			const bool __plus = __c == __lit[__num_base::_S_iplus];
    327 			if ((__plus || __c == __lit[__num_base::_S_iminus])
    328 			    && !(__lc->_M_use_grouping
    329 				 && __c == __lc->_M_thousands_sep)
    330 			    && !(__c == __lc->_M_decimal_point))
    331 		      __xtrc += __plus ? '+' : '-';
    332 			else
    333 			  continue;
    334 		      }
    335 		    else
    336 		      {
    337 			__testeof = true;
    338 			break;
    339 		      }
    340 		  }
    341 		else
    342 		  break;
    343 	      }
    344 	    
    345 	    if (++__beg != __end)
    346 	      __c = *__beg;
    347 	    else
    348 	      __testeof = true;
    349 	  }
    350 
    351       // Digit grouping is checked. If grouping and found_grouping don't
    352       // match, then get very very upset, and set failbit.
    353       if (__found_grouping.size())
    354         {
    355           // Add the ending grouping if a decimal or 'e'/'E' wasn't found.
    356 	  if (!__found_dec && !__found_sci)
    357 	    __found_grouping += static_cast<char>(__sep_pos);
    358 
    359           if (!std::__verify_grouping(__lc->_M_grouping, 
    360 				      __lc->_M_grouping_size,
    361 				      __found_grouping))
    362 	    __err = ios_base::failbit;
    363         }
    364 
    365       return __beg;
    366     }
    367 
    368   template<typename _CharT, typename _InIter>
    369     template<typename _ValueT>
    370       _InIter
    371       num_get<_CharT, _InIter>::
    372       _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
    373 		     ios_base::iostate& __err, _ValueT& __v) const
    374       {
    375         typedef char_traits<_CharT>			     __traits_type;
    376 	using __gnu_cxx::__add_unsigned;
    377 	typedef typename __add_unsigned<_ValueT>::__type __unsigned_type;
    378 	typedef __numpunct_cache<_CharT>                     __cache_type;
    379 	__use_cache<__cache_type> __uc;
    380 	const locale& __loc = __io._M_getloc();
    381 	const __cache_type* __lc = __uc(__loc);
    382 	const _CharT* __lit = __lc->_M_atoms_in;
    383 	char_type __c = char_type();
    384 
    385 	// NB: Iff __basefield == 0, __base can change based on contents.
    386 	const ios_base::fmtflags __basefield = __io.flags()
    387 	                                       & ios_base::basefield;
    388 	const bool __oct = __basefield == ios_base::oct;
    389 	int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10);
    390 
    391 	// True if __beg becomes equal to __end.
    392 	bool __testeof = __beg == __end;
    393 
    394 	// First check for sign.
    395 	bool __negative = false;
    396 	if (!__testeof)
    397 	  {
    398 	    __c = *__beg;
    399 	    __negative = __c == __lit[__num_base::_S_iminus];
    400 	    if ((__negative || __c == __lit[__num_base::_S_iplus])
    401 		&& !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
    402 		&& !(__c == __lc->_M_decimal_point))
    403 	      {
    404 		if (++__beg != __end)
    405 		  __c = *__beg;
    406 		else
    407 		  __testeof = true;
    408 	      }
    409 	  }
    410 
    411 	// Next, look for leading zeros and check required digits
    412 	// for base formats.
    413 	bool __found_zero = false;
    414 	int __sep_pos = 0;
    415 	while (!__testeof)
    416 	  {
    417 	    if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
    418 		|| __c == __lc->_M_decimal_point)
    419 	      break;
    420 	    else if (__c == __lit[__num_base::_S_izero] 
    421 		     && (!__found_zero || __base == 10))
    422 	      {
    423 		__found_zero = true;
    424 		++__sep_pos;
    425 		if (__basefield == 0)
    426 		  __base = 8;
    427 		if (__base == 8)
    428 		  __sep_pos = 0;
    429 	      }
    430 	    else if (__found_zero
    431 		     && (__c == __lit[__num_base::_S_ix]
    432 			 || __c == __lit[__num_base::_S_iX]))
    433 	      {
    434 		if (__basefield == 0)
    435 		  __base = 16;
    436 		if (__base == 16)
    437 		  {
    438 		    __found_zero = false;
    439 		    __sep_pos = 0;
    440 		  }
    441 		else
    442 		  break;
    443 	      }
    444 	    else
    445 	      break;
    446 
    447 	    if (++__beg != __end)
    448 	      {
    449 		__c = *__beg;
    450 		if (!__found_zero)
    451 		  break;
    452 	      }
    453 	    else
    454 	      __testeof = true;
    455 	  }
    456 	
    457 	// At this point, base is determined. If not hex, only allow
    458 	// base digits as valid input.
    459 	const size_t __len = (__base == 16 ? __num_base::_S_iend
    460 			      - __num_base::_S_izero : __base);
    461 
    462 	// Extract.
    463 	string __found_grouping;
    464 	if (__lc->_M_use_grouping)
    465 	  __found_grouping.reserve(32);
    466 	bool __testfail = false;
    467 	bool __testoverflow = false;
    468 	const __unsigned_type __max =
    469 	  (__negative && __gnu_cxx::__numeric_traits<_ValueT>::__is_signed)
    470 	  ? -__gnu_cxx::__numeric_traits<_ValueT>::__min
    471 	  : __gnu_cxx::__numeric_traits<_ValueT>::__max;
    472 	const __unsigned_type __smax = __max / __base;
    473 	__unsigned_type __result = 0;
    474 	int __digit = 0;
    475 	const char_type* __lit_zero = __lit + __num_base::_S_izero;
    476 
    477 	if (!__lc->_M_allocated)
    478 	  // "C" locale
    479 	  while (!__testeof)
    480 	    {
    481 	      __digit = _M_find(__lit_zero, __len, __c);
    482 	      if (__digit == -1)
    483 		break;
    484 	      
    485 	      if (__result > __smax)
    486 		__testoverflow = true;
    487 	      else
    488 		{
    489 		  __result *= __base;
    490 		  __testoverflow |= __result > __max - __digit;
    491 		  __result += __digit;
    492 		  ++__sep_pos;
    493 		}
    494 	      
    495 	      if (++__beg != __end)
    496 		__c = *__beg;
    497 	      else
    498 		__testeof = true;
    499 	    }
    500 	else
    501 	  while (!__testeof)
    502 	    {
    503 	      // According to 22.2.2.1.2, p8-9, first look for thousands_sep
    504 	      // and decimal_point.
    505 	      if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
    506 		{
    507 		  // NB: Thousands separator at the beginning of a string
    508 		  // is a no-no, as is two consecutive thousands separators.
    509 		  if (__sep_pos)
    510 		    {
    511 		      __found_grouping += static_cast<char>(__sep_pos);
    512 		      __sep_pos = 0;
    513 		    }
    514 		  else
    515 		    {
    516 		      __testfail = true;
    517 		      break;
    518 		    }
    519 		}
    520 	      else if (__c == __lc->_M_decimal_point)
    521 		break;
    522 	      else
    523 		{
    524 		  const char_type* __q =
    525 		    __traits_type::find(__lit_zero, __len, __c);
    526 		  if (!__q)
    527 		    break;
    528 		  
    529 		  __digit = __q - __lit_zero;
    530 		  if (__digit > 15)
    531 		    __digit -= 6;
    532 		  if (__result > __smax)
    533 		    __testoverflow = true;
    534 		  else
    535 		    {
    536 		      __result *= __base;
    537 		      __testoverflow |= __result > __max - __digit;
    538 		      __result += __digit;
    539 		      ++__sep_pos;
    540 		    }
    541 		}
    542 	      
    543 	      if (++__beg != __end)
    544 		__c = *__beg;
    545 	      else
    546 		__testeof = true;
    547 	    }
    548 	
    549 	// Digit grouping is checked. If grouping and found_grouping don't
    550 	// match, then get very very upset, and set failbit.
    551 	if (__found_grouping.size())
    552 	  {
    553 	    // Add the ending grouping.
    554 	    __found_grouping += static_cast<char>(__sep_pos);
    555 
    556 	    if (!std::__verify_grouping(__lc->_M_grouping,
    557 					__lc->_M_grouping_size,
    558 					__found_grouping))
    559 	      __err = ios_base::failbit;
    560 	  }
    561 
    562 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
    563 	// 23. Num_get overflow result.
    564 	if ((!__sep_pos && !__found_zero && !__found_grouping.size())
    565 	    || __testfail)
    566 	  {
    567 	    __v = 0;
    568 	    __err = ios_base::failbit;
    569 	  }
    570 	else if (__testoverflow)
    571 	  {
    572 	    if (__negative
    573 		&& __gnu_cxx::__numeric_traits<_ValueT>::__is_signed)
    574 	      __v = __gnu_cxx::__numeric_traits<_ValueT>::__min;
    575 	    else
    576 	      __v = __gnu_cxx::__numeric_traits<_ValueT>::__max;
    577 	    __err = ios_base::failbit;
    578 	  }
    579 	else
    580 	  __v = __negative ? -__result : __result;
    581 
    582 	if (__testeof)
    583 	  __err |= ios_base::eofbit;
    584 	return __beg;
    585       }
    586 
    587   // _GLIBCXX_RESOLVE_LIB_DEFECTS
    588   // 17.  Bad bool parsing
    589   template<typename _CharT, typename _InIter>
    590     _InIter
    591     num_get<_CharT, _InIter>::
    592     do_get(iter_type __beg, iter_type __end, ios_base& __io,
    593            ios_base::iostate& __err, bool& __v) const
    594     {
    595       if (!(__io.flags() & ios_base::boolalpha))
    596         {
    597 	  // Parse bool values as long.
    598           // NB: We can't just call do_get(long) here, as it might
    599           // refer to a derived class.
    600 	  long __l = -1;
    601           __beg = _M_extract_int(__beg, __end, __io, __err, __l);
    602 	  if (__l == 0 || __l == 1)
    603 	    __v = bool(__l);
    604 	  else
    605 	    {
    606 	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
    607 	      // 23. Num_get overflow result.
    608 	      __v = true;
    609 	      __err = ios_base::failbit;
    610 	      if (__beg == __end)
    611 		__err |= ios_base::eofbit;
    612 	    }
    613         }
    614       else
    615         {
    616 	  // Parse bool values as alphanumeric.
    617 	  typedef __numpunct_cache<_CharT>  __cache_type;
    618 	  __use_cache<__cache_type> __uc;
    619 	  const locale& __loc = __io._M_getloc();
    620 	  const __cache_type* __lc = __uc(__loc);
    621 
    622 	  bool __testf = true;
    623 	  bool __testt = true;
    624 	  bool __donef = __lc->_M_falsename_size == 0;
    625 	  bool __donet = __lc->_M_truename_size == 0;
    626 	  bool __testeof = false;
    627 	  size_t __n = 0;
    628 	  while (!__donef || !__donet)
    629 	    {
    630 	      if (__beg == __end)
    631 		{
    632 		  __testeof = true;
    633 		  break;
    634 		}
    635 
    636 	      const char_type __c = *__beg;
    637 
    638 	      if (!__donef)
    639 		__testf = __c == __lc->_M_falsename[__n];
    640 
    641 	      if (!__testf && __donet)
    642 		break;
    643 
    644 	      if (!__donet)
    645 		__testt = __c == __lc->_M_truename[__n];
    646 
    647 	      if (!__testt && __donef)
    648 		break;
    649 
    650 	      if (!__testt && !__testf)
    651 		break;
    652 
    653 	      ++__n;
    654 	      ++__beg;
    655 
    656 	      __donef = !__testf || __n >= __lc->_M_falsename_size;
    657 	      __donet = !__testt || __n >= __lc->_M_truename_size;
    658 	    }
    659 	  if (__testf && __n == __lc->_M_falsename_size && __n)
    660 	    {
    661 	      __v = false;
    662 	      if (__testt && __n == __lc->_M_truename_size)
    663 		__err = ios_base::failbit;
    664 	      else
    665 		__err = __testeof ? ios_base::eofbit : ios_base::goodbit;
    666 	    }
    667 	  else if (__testt && __n == __lc->_M_truename_size && __n)
    668 	    {
    669 	      __v = true;
    670 	      __err = __testeof ? ios_base::eofbit : ios_base::goodbit;
    671 	    }
    672 	  else
    673 	    {
    674 	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
    675 	      // 23. Num_get overflow result.
    676 	      __v = false;
    677 	      __err = ios_base::failbit;
    678 	      if (__testeof)
    679 		__err |= ios_base::eofbit;
    680 	    }
    681 	}
    682       return __beg;
    683     }
    684 
    685   template<typename _CharT, typename _InIter>
    686     _InIter
    687     num_get<_CharT, _InIter>::
    688     do_get(iter_type __beg, iter_type __end, ios_base& __io,
    689 	   ios_base::iostate& __err, float& __v) const
    690     {
    691       string __xtrc;
    692       __xtrc.reserve(32);
    693       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
    694       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
    695       if (__beg == __end)
    696 	__err |= ios_base::eofbit;
    697       return __beg;
    698     }
    699 
    700   template<typename _CharT, typename _InIter>
    701     _InIter
    702     num_get<_CharT, _InIter>::
    703     do_get(iter_type __beg, iter_type __end, ios_base& __io,
    704            ios_base::iostate& __err, double& __v) const
    705     {
    706       string __xtrc;
    707       __xtrc.reserve(32);
    708       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
    709       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
    710       if (__beg == __end)
    711 	__err |= ios_base::eofbit;
    712       return __beg;
    713     }
    714 
    715 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
    716   template<typename _CharT, typename _InIter>
    717     _InIter
    718     num_get<_CharT, _InIter>::
    719     __do_get(iter_type __beg, iter_type __end, ios_base& __io,
    720 	     ios_base::iostate& __err, double& __v) const
    721     {
    722       string __xtrc;
    723       __xtrc.reserve(32);
    724       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
    725       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
    726       if (__beg == __end)
    727 	__err |= ios_base::eofbit;
    728       return __beg;
    729     }
    730 #endif
    731 
    732   template<typename _CharT, typename _InIter>
    733     _InIter
    734     num_get<_CharT, _InIter>::
    735     do_get(iter_type __beg, iter_type __end, ios_base& __io,
    736            ios_base::iostate& __err, long double& __v) const
    737     {
    738       string __xtrc;
    739       __xtrc.reserve(32);
    740       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
    741       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
    742       if (__beg == __end)
    743 	__err |= ios_base::eofbit;
    744       return __beg;
    745     }
    746 
    747   template<typename _CharT, typename _InIter>
    748     _InIter
    749     num_get<_CharT, _InIter>::
    750     do_get(iter_type __beg, iter_type __end, ios_base& __io,
    751            ios_base::iostate& __err, void*& __v) const
    752     {
    753       // Prepare for hex formatted input.
    754       typedef ios_base::fmtflags        fmtflags;
    755       const fmtflags __fmt = __io.flags();
    756       __io.flags((__fmt & ~ios_base::basefield) | ios_base::hex);
    757 
    758       typedef __gnu_cxx::__conditional_type<(sizeof(void*)
    759 					     <= sizeof(unsigned long)),
    760 	unsigned long, unsigned long long>::__type _UIntPtrType;       
    761 
    762       _UIntPtrType __ul;
    763       __beg = _M_extract_int(__beg, __end, __io, __err, __ul);
    764 
    765       // Reset from hex formatted input.
    766       __io.flags(__fmt);
    767 
    768       __v = reinterpret_cast<void*>(__ul);
    769       return __beg;
    770     }
    771 
    772   // For use by integer and floating-point types after they have been
    773   // converted into a char_type string.
    774   template<typename _CharT, typename _OutIter>
    775     void
    776     num_put<_CharT, _OutIter>::
    777     _M_pad(_CharT __fill, streamsize __w, ios_base& __io,
    778 	   _CharT* __new, const _CharT* __cs, int& __len) const
    779     {
    780       // [22.2.2.2.2] Stage 3.
    781       // If necessary, pad.
    782       __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new,
    783 						  __cs, __w, __len);
    784       __len = static_cast<int>(__w);
    785     }
    786 
    787 _GLIBCXX_END_NAMESPACE_LDBL
    788 
    789   template<typename _CharT, typename _ValueT>
    790     int
    791     __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
    792 		  ios_base::fmtflags __flags, bool __dec)
    793     {
    794       _CharT* __buf = __bufend;
    795       if (__builtin_expect(__dec, true))
    796 	{
    797 	  // Decimal.
    798 	  do
    799 	    {
    800 	      *--__buf = __lit[(__v % 10) + __num_base::_S_odigits];
    801 	      __v /= 10;
    802 	    }
    803 	  while (__v != 0);
    804 	}
    805       else if ((__flags & ios_base::basefield) == ios_base::oct)
    806 	{
    807 	  // Octal.
    808 	  do
    809 	    {
    810 	      *--__buf = __lit[(__v & 0x7) + __num_base::_S_odigits];
    811 	      __v >>= 3;
    812 	    }
    813 	  while (__v != 0);
    814 	}
    815       else
    816 	{
    817 	  // Hex.
    818 	  const bool __uppercase = __flags & ios_base::uppercase;
    819 	  const int __case_offset = __uppercase ? __num_base::_S_oudigits
    820 	                                        : __num_base::_S_odigits;
    821 	  do
    822 	    {
    823 	      *--__buf = __lit[(__v & 0xf) + __case_offset];
    824 	      __v >>= 4;
    825 	    }
    826 	  while (__v != 0);
    827 	}
    828       return __bufend - __buf;
    829     }
    830 
    831 _GLIBCXX_BEGIN_NAMESPACE_LDBL
    832 
    833   template<typename _CharT, typename _OutIter>
    834     void
    835     num_put<_CharT, _OutIter>::
    836     _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep,
    837 		 ios_base&, _CharT* __new, _CharT* __cs, int& __len) const
    838     {
    839       _CharT* __p = std::__add_grouping(__new, __sep, __grouping,
    840 					__grouping_size, __cs, __cs + __len);
    841       __len = __p - __new;
    842     }
    843   
    844   template<typename _CharT, typename _OutIter>
    845     template<typename _ValueT>
    846       _OutIter
    847       num_put<_CharT, _OutIter>::
    848       _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill,
    849 		    _ValueT __v) const
    850       {
    851 	using __gnu_cxx::__add_unsigned;
    852 	typedef typename __add_unsigned<_ValueT>::__type __unsigned_type;
    853 	typedef __numpunct_cache<_CharT>	             __cache_type;
    854 	__use_cache<__cache_type> __uc;
    855 	const locale& __loc = __io._M_getloc();
    856 	const __cache_type* __lc = __uc(__loc);
    857 	const _CharT* __lit = __lc->_M_atoms_out;
    858 	const ios_base::fmtflags __flags = __io.flags();
    859 
    860 	// Long enough to hold hex, dec, and octal representations.
    861 	const int __ilen = 5 * sizeof(_ValueT);
    862 	_CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
    863 							     * __ilen));
    864 
    865 	// [22.2.2.2.2] Stage 1, numeric conversion to character.
    866 	// Result is returned right-justified in the buffer.
    867 	const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
    868 	const bool __dec = (__basefield != ios_base::oct
    869 			    && __basefield != ios_base::hex);
    870 	const __unsigned_type __u = ((__v > 0 || !__dec)
    871 				     ? __unsigned_type(__v)
    872 				     : -__unsigned_type(__v));
    873  	int __len = __int_to_char(__cs + __ilen, __u, __lit, __flags, __dec);
    874 	__cs += __ilen - __len;
    875 
    876 	// Add grouping, if necessary.
    877 	if (__lc->_M_use_grouping)
    878 	  {
    879 	    // Grouping can add (almost) as many separators as the number
    880 	    // of digits + space is reserved for numeric base or sign.
    881 	    _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
    882 								  * (__len + 1)
    883 								  * 2));
    884 	    _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size,
    885 			 __lc->_M_thousands_sep, __io, __cs2 + 2, __cs, __len);
    886 	    __cs = __cs2 + 2;
    887 	  }
    888 
    889 	// Complete Stage 1, prepend numeric base or sign.
    890 	if (__builtin_expect(__dec, true))
    891 	  {
    892 	    // Decimal.
    893 	    if (__v >= 0)
    894 	      {
    895 		if (bool(__flags & ios_base::showpos)
    896 		    && __gnu_cxx::__numeric_traits<_ValueT>::__is_signed)
    897 		  *--__cs = __lit[__num_base::_S_oplus], ++__len;
    898 	      }
    899 	    else
    900 	      *--__cs = __lit[__num_base::_S_ominus], ++__len;
    901 	  }
    902 	else if (bool(__flags & ios_base::showbase) && __v)
    903 	  {
    904 	    if (__basefield == ios_base::oct)
    905 	      *--__cs = __lit[__num_base::_S_odigits], ++__len;
    906 	    else
    907 	      {
    908 		// 'x' or 'X'
    909 		const bool __uppercase = __flags & ios_base::uppercase;
    910 		*--__cs = __lit[__num_base::_S_ox + __uppercase];
    911 		// '0'
    912 		*--__cs = __lit[__num_base::_S_odigits];
    913 		__len += 2;
    914 	      }
    915 	  }
    916 
    917 	// Pad.
    918 	const streamsize __w = __io.width();
    919 	if (__w > static_cast<streamsize>(__len))
    920 	  {
    921 	    _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
    922 								  * __w));
    923 	    _M_pad(__fill, __w, __io, __cs3, __cs, __len);
    924 	    __cs = __cs3;
    925 	  }
    926 	__io.width(0);
    927 
    928 	// [22.2.2.2.2] Stage 4.
    929 	// Write resulting, fully-formatted string to output iterator.
    930 	return std::__write(__s, __cs, __len);
    931       }
    932 
    933   template<typename _CharT, typename _OutIter>
    934     void
    935     num_put<_CharT, _OutIter>::
    936     _M_group_float(const char* __grouping, size_t __grouping_size,
    937 		   _CharT __sep, const _CharT* __p, _CharT* __new,
    938 		   _CharT* __cs, int& __len) const
    939     {
    940       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    941       // 282. What types does numpunct grouping refer to?
    942       // Add grouping, if necessary.
    943       const int __declen = __p ? __p - __cs : __len;
    944       _CharT* __p2 = std::__add_grouping(__new, __sep, __grouping,
    945 					 __grouping_size,
    946 					 __cs, __cs + __declen);
    947 
    948       // Tack on decimal part.
    949       int __newlen = __p2 - __new;
    950       if (__p)
    951 	{
    952 	  char_traits<_CharT>::copy(__p2, __p, __len - __declen);
    953 	  __newlen += __len - __declen;
    954 	}
    955       __len = __newlen;
    956     }
    957 
    958   // The following code uses vsnprintf (or vsprintf(), when
    959   // _GLIBCXX_USE_C99 is not defined) to convert floating point values
    960   // for insertion into a stream.  An optimization would be to replace
    961   // them with code that works directly on a wide buffer and then use
    962   // __pad to do the padding.  It would be good to replace them anyway
    963   // to gain back the efficiency that C++ provides by knowing up front
    964   // the type of the values to insert.  Also, sprintf is dangerous
    965   // since may lead to accidental buffer overruns.  This
    966   // implementation follows the C++ standard fairly directly as
    967   // outlined in 22.2.2.2 [lib.locale.num.put]
    968   template<typename _CharT, typename _OutIter>
    969     template<typename _ValueT>
    970       _OutIter
    971       num_put<_CharT, _OutIter>::
    972       _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
    973 		       _ValueT __v) const
    974       {
    975 	typedef __numpunct_cache<_CharT>                __cache_type;
    976 	__use_cache<__cache_type> __uc;
    977 	const locale& __loc = __io._M_getloc();
    978 	const __cache_type* __lc = __uc(__loc);
    979 
    980 	// Use default precision if out of range.
    981 	const streamsize __prec = __io.precision() < 0 ? 6 : __io.precision();
    982 
    983 	const int __max_digits =
    984 	  __gnu_cxx::__numeric_traits<_ValueT>::__digits10;
    985 
    986 	// [22.2.2.2.2] Stage 1, numeric conversion to character.
    987 	int __len;
    988 	// Long enough for the max format spec.
    989 	char __fbuf[16];
    990 	__num_base::_S_format_float(__io, __fbuf, __mod);
    991 
    992 #ifdef _GLIBCXX_USE_C99
    993 	// First try a buffer perhaps big enough (most probably sufficient
    994 	// for non-ios_base::fixed outputs)
    995 	int __cs_size = __max_digits * 3;
    996 	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
    997 	__len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
    998 				      __fbuf, __prec, __v);
    999 
   1000 	// If the buffer was not large enough, try again with the correct size.
   1001 	if (__len >= __cs_size)
   1002 	  {
   1003 	    __cs_size = __len + 1;
   1004 	    __cs = static_cast<char*>(__builtin_alloca(__cs_size));
   1005 	    __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
   1006 					  __fbuf, __prec, __v);
   1007 	  }
   1008 #else
   1009 	// Consider the possibility of long ios_base::fixed outputs
   1010 	const bool __fixed = __io.flags() & ios_base::fixed;
   1011 	const int __max_exp =
   1012 	  __gnu_cxx::__numeric_traits<_ValueT>::__max_exponent10;
   1013 
   1014 	// The size of the output string is computed as follows.
   1015 	// ios_base::fixed outputs may need up to __max_exp + 1 chars
   1016 	// for the integer part + __prec chars for the fractional part
   1017 	// + 3 chars for sign, decimal point, '\0'. On the other hand,
   1018 	// for non-fixed outputs __max_digits * 2 + __prec chars are
   1019 	// largely sufficient.
   1020 	const int __cs_size = __fixed ? __max_exp + __prec + 4
   1021 	                              : __max_digits * 2 + __prec;
   1022 	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
   1023 	__len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, __fbuf, 
   1024 				      __prec, __v);
   1025 #endif
   1026 
   1027 	// [22.2.2.2.2] Stage 2, convert to char_type, using correct
   1028 	// numpunct.decimal_point() values for '.' and adding grouping.
   1029 	const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
   1030 	
   1031 	_CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
   1032 							     * __len));
   1033 	__ctype.widen(__cs, __cs + __len, __ws);
   1034 	
   1035 	// Replace decimal point.
   1036 	_CharT* __wp = 0;
   1037 	const char* __p = char_traits<char>::find(__cs, __len, '.');
   1038 	if (__p)
   1039 	  {
   1040 	    __wp = __ws + (__p - __cs);
   1041 	    *__wp = __lc->_M_decimal_point;
   1042 	  }
   1043 	
   1044 	// Add grouping, if necessary.
   1045 	// N.B. Make sure to not group things like 2e20, i.e., no decimal
   1046 	// point, scientific notation.
   1047 	if (__lc->_M_use_grouping
   1048 	    && (__wp || __len < 3 || (__cs[1] <= '9' && __cs[2] <= '9'
   1049 				      && __cs[1] >= '0' && __cs[2] >= '0')))
   1050 	  {
   1051 	    // Grouping can add (almost) as many separators as the
   1052 	    // number of digits, but no more.
   1053 	    _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
   1054 								  * __len * 2));
   1055 	    
   1056 	    streamsize __off = 0;
   1057 	    if (__cs[0] == '-' || __cs[0] == '+')
   1058 	      {
   1059 		__off = 1;
   1060 		__ws2[0] = __ws[0];
   1061 		__len -= 1;
   1062 	      }
   1063 	    
   1064 	    _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size,
   1065 			   __lc->_M_thousands_sep, __wp, __ws2 + __off,
   1066 			   __ws + __off, __len);
   1067 	    __len += __off;
   1068 	    
   1069 	    __ws = __ws2;
   1070 	  }
   1071 
   1072 	// Pad.
   1073 	const streamsize __w = __io.width();
   1074 	if (__w > static_cast<streamsize>(__len))
   1075 	  {
   1076 	    _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
   1077 								  * __w));
   1078 	    _M_pad(__fill, __w, __io, __ws3, __ws, __len);
   1079 	    __ws = __ws3;
   1080 	  }
   1081 	__io.width(0);
   1082 	
   1083 	// [22.2.2.2.2] Stage 4.
   1084 	// Write resulting, fully-formatted string to output iterator.
   1085 	return std::__write(__s, __ws, __len);
   1086       }
   1087   
   1088   template<typename _CharT, typename _OutIter>
   1089     _OutIter
   1090     num_put<_CharT, _OutIter>::
   1091     do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
   1092     {
   1093       const ios_base::fmtflags __flags = __io.flags();
   1094       if ((__flags & ios_base::boolalpha) == 0)
   1095         {
   1096           const long __l = __v;
   1097           __s = _M_insert_int(__s, __io, __fill, __l);
   1098         }
   1099       else
   1100         {
   1101 	  typedef __numpunct_cache<_CharT>              __cache_type;
   1102 	  __use_cache<__cache_type> __uc;
   1103 	  const locale& __loc = __io._M_getloc();
   1104 	  const __cache_type* __lc = __uc(__loc);
   1105 
   1106 	  const _CharT* __name = __v ? __lc->_M_truename
   1107 	                             : __lc->_M_falsename;
   1108 	  int __len = __v ? __lc->_M_truename_size
   1109 	                  : __lc->_M_falsename_size;
   1110 
   1111 	  const streamsize __w = __io.width();
   1112 	  if (__w > static_cast<streamsize>(__len))
   1113 	    {
   1114 	      const streamsize __plen = __w - __len;
   1115 	      _CharT* __ps
   1116 		= static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
   1117 							* __plen));
   1118 
   1119 	      char_traits<_CharT>::assign(__ps, __plen, __fill);
   1120 	      __io.width(0);
   1121 
   1122 	      if ((__flags & ios_base::adjustfield) == ios_base::left)
   1123 		{
   1124 		  __s = std::__write(__s, __name, __len);
   1125 		  __s = std::__write(__s, __ps, __plen);
   1126 		}
   1127 	      else
   1128 		{
   1129 		  __s = std::__write(__s, __ps, __plen);
   1130 		  __s = std::__write(__s, __name, __len);
   1131 		}
   1132 	      return __s;
   1133 	    }
   1134 	  __io.width(0);
   1135 	  __s = std::__write(__s, __name, __len);
   1136 	}
   1137       return __s;
   1138     }
   1139 
   1140   template<typename _CharT, typename _OutIter>
   1141     _OutIter
   1142     num_put<_CharT, _OutIter>::
   1143     do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
   1144     { return _M_insert_float(__s, __io, __fill, char(), __v); }
   1145 
   1146 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
   1147   template<typename _CharT, typename _OutIter>
   1148     _OutIter
   1149     num_put<_CharT, _OutIter>::
   1150     __do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
   1151     { return _M_insert_float(__s, __io, __fill, char(), __v); }
   1152 #endif
   1153 
   1154   template<typename _CharT, typename _OutIter>
   1155     _OutIter
   1156     num_put<_CharT, _OutIter>::
   1157     do_put(iter_type __s, ios_base& __io, char_type __fill,
   1158 	   long double __v) const
   1159     { return _M_insert_float(__s, __io, __fill, 'L', __v); }
   1160 
   1161   template<typename _CharT, typename _OutIter>
   1162     _OutIter
   1163     num_put<_CharT, _OutIter>::
   1164     do_put(iter_type __s, ios_base& __io, char_type __fill,
   1165            const void* __v) const
   1166     {
   1167       const ios_base::fmtflags __flags = __io.flags();
   1168       const ios_base::fmtflags __fmt = ~(ios_base::basefield
   1169 					 | ios_base::uppercase);
   1170       __io.flags((__flags & __fmt) | (ios_base::hex | ios_base::showbase));
   1171 
   1172       typedef __gnu_cxx::__conditional_type<(sizeof(const void*)
   1173 					     <= sizeof(unsigned long)),
   1174 	unsigned long, unsigned long long>::__type _UIntPtrType;       
   1175 
   1176       __s = _M_insert_int(__s, __io, __fill,
   1177 			  reinterpret_cast<_UIntPtrType>(__v));
   1178       __io.flags(__flags);
   1179       return __s;
   1180     }
   1181 
   1182 _GLIBCXX_END_NAMESPACE_LDBL
   1183 
   1184   // Construct correctly padded string, as per 22.2.2.2.2
   1185   // Assumes
   1186   // __newlen > __oldlen
   1187   // __news is allocated for __newlen size
   1188 
   1189   // NB: Of the two parameters, _CharT can be deduced from the
   1190   // function arguments. The other (_Traits) has to be explicitly specified.
   1191   template<typename _CharT, typename _Traits>
   1192     void
   1193     __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill,
   1194 				   _CharT* __news, const _CharT* __olds,
   1195 				   streamsize __newlen, streamsize __oldlen)
   1196     {
   1197       const size_t __plen = static_cast<size_t>(__newlen - __oldlen);
   1198       const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
   1199 
   1200       // Padding last.
   1201       if (__adjust == ios_base::left)
   1202 	{
   1203 	  _Traits::copy(__news, __olds, __oldlen);
   1204 	  _Traits::assign(__news + __oldlen, __plen, __fill);
   1205 	  return;
   1206 	}
   1207 
   1208       size_t __mod = 0;
   1209       if (__adjust == ios_base::internal)
   1210 	{
   1211 	  // Pad after the sign, if there is one.
   1212 	  // Pad after 0[xX], if there is one.
   1213 	  // Who came up with these rules, anyway? Jeeze.
   1214           const locale& __loc = __io._M_getloc();
   1215 	  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
   1216 
   1217 	  if (__ctype.widen('-') == __olds[0]
   1218 	      || __ctype.widen('+') == __olds[0])
   1219 	    {
   1220 	      __news[0] = __olds[0];
   1221 	      __mod = 1;
   1222 	      ++__news;
   1223 	    }
   1224 	  else if (__ctype.widen('0') == __olds[0]
   1225 		   && __oldlen > 1
   1226 		   && (__ctype.widen('x') == __olds[1]
   1227 		       || __ctype.widen('X') == __olds[1]))
   1228 	    {
   1229 	      __news[0] = __olds[0];
   1230 	      __news[1] = __olds[1];
   1231 	      __mod = 2;
   1232 	      __news += 2;
   1233 	    }
   1234 	  // else Padding first.
   1235 	}
   1236       _Traits::assign(__news, __plen, __fill);
   1237       _Traits::copy(__news + __plen, __olds + __mod, __oldlen - __mod);
   1238     }
   1239 
   1240   template<typename _CharT>
   1241     _CharT*
   1242     __add_grouping(_CharT* __s, _CharT __sep,
   1243 		   const char* __gbeg, size_t __gsize,
   1244 		   const _CharT* __first, const _CharT* __last)
   1245     {
   1246       size_t __idx = 0;
   1247       size_t __ctr = 0;
   1248 
   1249       while (__last - __first > __gbeg[__idx]
   1250 	     && static_cast<signed char>(__gbeg[__idx]) > 0
   1251 	     && __gbeg[__idx] != __gnu_cxx::__numeric_traits<char>::__max)
   1252 	{
   1253 	  __last -= __gbeg[__idx];
   1254 	  __idx < __gsize - 1 ? ++__idx : ++__ctr;
   1255 	}
   1256 
   1257       while (__first != __last)
   1258 	*__s++ = *__first++;
   1259 
   1260       while (__ctr--)
   1261 	{
   1262 	  *__s++ = __sep;	  
   1263 	  for (char __i = __gbeg[__idx]; __i > 0; --__i)
   1264 	    *__s++ = *__first++;
   1265 	}
   1266 
   1267       while (__idx--)
   1268 	{
   1269 	  *__s++ = __sep;	  
   1270 	  for (char __i = __gbeg[__idx]; __i > 0; --__i)
   1271 	    *__s++ = *__first++;
   1272 	}
   1273 
   1274       return __s;
   1275     }
   1276 
   1277   // Inhibit implicit instantiations for required instantiations,
   1278   // which are defined via explicit instantiations elsewhere.
   1279 #if _GLIBCXX_EXTERN_TEMPLATE
   1280   extern template class numpunct<char>;
   1281   extern template class numpunct_byname<char>;
   1282   extern template class _GLIBCXX_NAMESPACE_LDBL num_get<char>;
   1283   extern template class _GLIBCXX_NAMESPACE_LDBL num_put<char>;
   1284   extern template class ctype_byname<char>;
   1285 
   1286   extern template
   1287     const ctype<char>&
   1288     use_facet<ctype<char> >(const locale&);
   1289 
   1290   extern template
   1291     const numpunct<char>&
   1292     use_facet<numpunct<char> >(const locale&);
   1293 
   1294   extern template
   1295     const num_put<char>&
   1296     use_facet<num_put<char> >(const locale&);
   1297 
   1298   extern template
   1299     const num_get<char>&
   1300     use_facet<num_get<char> >(const locale&);
   1301 
   1302   extern template
   1303     bool
   1304     has_facet<ctype<char> >(const locale&);
   1305 
   1306   extern template
   1307     bool
   1308     has_facet<numpunct<char> >(const locale&);
   1309 
   1310   extern template
   1311     bool
   1312     has_facet<num_put<char> >(const locale&);
   1313 
   1314   extern template
   1315     bool
   1316     has_facet<num_get<char> >(const locale&);
   1317 
   1318 #ifdef _GLIBCXX_USE_WCHAR_T
   1319   extern template class numpunct<wchar_t>;
   1320   extern template class numpunct_byname<wchar_t>;
   1321   extern template class _GLIBCXX_NAMESPACE_LDBL num_get<wchar_t>;
   1322   extern template class _GLIBCXX_NAMESPACE_LDBL num_put<wchar_t>;
   1323   extern template class ctype_byname<wchar_t>;
   1324 
   1325   extern template
   1326     const ctype<wchar_t>&
   1327     use_facet<ctype<wchar_t> >(const locale&);
   1328 
   1329   extern template
   1330     const numpunct<wchar_t>&
   1331     use_facet<numpunct<wchar_t> >(const locale&);
   1332 
   1333   extern template
   1334     const num_put<wchar_t>&
   1335     use_facet<num_put<wchar_t> >(const locale&);
   1336 
   1337   extern template
   1338     const num_get<wchar_t>&
   1339     use_facet<num_get<wchar_t> >(const locale&);
   1340 
   1341  extern template
   1342     bool
   1343     has_facet<ctype<wchar_t> >(const locale&);
   1344 
   1345   extern template
   1346     bool
   1347     has_facet<numpunct<wchar_t> >(const locale&);
   1348 
   1349   extern template
   1350     bool
   1351     has_facet<num_put<wchar_t> >(const locale&);
   1352 
   1353   extern template
   1354     bool
   1355     has_facet<num_get<wchar_t> >(const locale&);
   1356 #endif
   1357 #endif
   1358 
   1359 _GLIBCXX_END_NAMESPACE_VERSION
   1360 } // namespace
   1361 
   1362 #endif
   1363