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