round three

Benjamin Kosnik bkoz@redhat.com
Tue Feb 11 21:53:00 GMT 2003


Here is this part of Jerry Quinn's patch that removes snprintf calls
in __convert_from_v for num_put integer routines. Something that does
the equivalent for floating point routines would be welcome.

tested x86/linux

2003-02-11 Jerry Quinn  <jlquinn@optonline.net>
           Benjamin Kosnik  <benjamin@redhat.com>
	
	* include/bits/locale_facets.h (__num_base): Add _S_atoms_out.
	Add indexes into this array.
	(__num_base::_S_atoms): To _S_atoms_in.
	(num_put::_M_insert): Rename to _M_pad.
	(num_put::_M_convert_int): Adjust remove __mod, __modl arguments.
	(num_put::_M_widen_int): Rename to _M_group_int.
	(num_put::_M_widen_float): Rename to _M_group_float.	
	* include/bits/locale_facets.tcc (__int_to_char): New inline
	function and adapter functions.
	(num_put::_M_group_int): Streamline.
	(num_put::_M_group_float): Streamline.	
	(num_put::_M_convert_int): Remove unused parameter names. Choose
	large enough buffer for text.  Use __int_to_char instead of
	__convert_from_v.  Formatted text is now at the end of the buffer.
	(num_put::_M_convert_float): Preliminary fixups.
	* src/locale-inst.cc (__convert_from_v<long long>): Add ifdef.
	(__int_to_char<unsigned long long>): Same.
	(__int_to_char<char, unsigned long>): New.
	(__int_to_char<char, unsigned long long>): New.
	(__int_to_char<wchar_t, unsigned long>): New.
	(__int_to_char<wchar_t, unsigned long long>): New.

Index: include/bits/locale_facets.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/locale_facets.h,v
retrieving revision 1.54
diff -c -p -r1.54 locale_facets.h
*** include/bits/locale_facets.h	6 Feb 2003 18:08:50 -0000	1.54
--- include/bits/locale_facets.h	11 Feb 2003 18:17:41 -0000
*************** namespace std
*** 527,540 ****
    // 22.2.1.5  Template class codecvt
    #include <bits/codecvt.h>
  
- 
    // 22.2.2  The numeric category.
    class __num_base 
    {
    protected:
      // String literal of acceptable (narrow) input, for num_get.
      // "0123456789eEabcdfABCDF"
!     static const char _S_atoms[];
  
      enum 
      {  
--- 527,563 ----
    // 22.2.1.5  Template class codecvt
    #include <bits/codecvt.h>
  
    // 22.2.2  The numeric category.
    class __num_base 
    {
+   public:
+     // NB: Code depends on the order of _M_atoms_out elements.
+     // Below are the indices into _M_atoms_out.
+     enum 
+       {  
+         _S_minus, 
+         _S_plus, 
+         _S_x, 
+         _S_X, 
+         _S_digits,
+         _S_digits_end = _S_digits + 16,
+         _S_udigits = _S_digits_end,  
+         _S_udigits_end = _S_udigits + 16,
+         _S_e = _S_digits + 14, // For scientific notation, 'e'
+         _S_E = _S_udigits + 14 // For scientific notation, 'E'
+       };
+     
+     // A list of valid numeric literals for output. 
+     // This array contains the chars after having been passed through
+     // the current locale's ctype<_CharT>.widen().
+     // For the standard "C" locale, this is 
+     // "-+xX0123456789abcdef0123456789ABCDEF".
+     static const char* _S_atoms_out;
+ 
    protected:
      // String literal of acceptable (narrow) input, for num_get.
      // "0123456789eEabcdfABCDF"
!     static const char* _S_atoms_in;
  
      enum 
      {  
*************** namespace std
*** 827,833 ****
        // Types:
        typedef _CharT       	char_type;
        typedef _OutIter     	iter_type;
- 
        static locale::id		id;
  
        explicit 
--- 850,855 ----
*************** namespace std
*** 877,898 ****
          _M_convert_float(iter_type, ios_base& __io, char_type __fill, 
  			 char __mod, _ValueT __v) const;
  
        template<typename _ValueT>
          iter_type
          _M_convert_int(iter_type, ios_base& __io, char_type __fill, 
! 		       char __mod, char __modl, _ValueT __v) const;
  
!       iter_type
!       _M_widen_float(iter_type, ios_base& __io, char_type __fill, char* __cs, 
! 		     int __len) const;
! 
!       iter_type
!       _M_widen_int(iter_type, ios_base& __io, char_type __fill, char* __cs, 
! 		   int __len) const;
! 
!       iter_type
!       _M_insert(iter_type, ios_base& __io, char_type __fill, 
! 		const char_type* __ws, int __len) const;
  
        virtual 
        ~num_put() { };
--- 899,922 ----
          _M_convert_float(iter_type, ios_base& __io, char_type __fill, 
  			 char __mod, _ValueT __v) const;
  
+       void
+       _M_group_float(const string& __grouping, char_type __sep, 
+ 		     const char_type* __p, char_type* __new, char_type* __cs,
+ 		     int& __len) const;
+ 
        template<typename _ValueT>
          iter_type
          _M_convert_int(iter_type, ios_base& __io, char_type __fill, 
! 		       _ValueT __v) const;
  
!       void
!       _M_group_int(const string& __grouping, char_type __sep, 
! 		   ios_base& __io, char_type* __new, char_type* __cs, 
! 		   int& __len) const;
! 
!       void
!       _M_pad(char_type __fill, streamsize __w, ios_base& __io, 
! 	     char_type* __new, const char_type* __cs, int& __len) const;
  
        virtual 
        ~num_put() { };
Index: include/bits/locale_facets.tcc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/locale_facets.tcc,v
retrieving revision 1.88
diff -c -p -r1.88 locale_facets.tcc
*** include/bits/locale_facets.tcc	6 Feb 2003 18:08:50 -0000	1.88
--- include/bits/locale_facets.tcc	11 Feb 2003 18:17:44 -0000
*************** namespace std
*** 113,119 ****
  	}
  
        // Next, strip leading zeros.
!       const char_type __zero = __ctype.widen(_S_atoms[_M_zero]);
        bool __found_zero = false;
        while (__traits_type::eq(__c, __zero) && __beg != __end)
  	{
--- 113,119 ----
  	}
  
        // Next, strip leading zeros.
!       const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]);
        bool __found_zero = false;
        while (__traits_type::eq(__c, __zero) && __beg != __end)
  	{
*************** namespace std
*** 122,135 ****
  	}
        if (__found_zero)
  	{
! 	  __xtrc += _S_atoms[_M_zero];
  	  ++__pos;
  	}
  
        // Only need acceptable digits for floating point numbers.
        const size_t __len = _M_E - _M_zero + 1;
        char_type  __watoms[__len];
!       __ctype.widen(_S_atoms, _S_atoms + __len, __watoms);
        bool __found_dec = false;
        bool __found_sci = false;
        const char_type __dec = __np.decimal_point();
--- 122,135 ----
  	}
        if (__found_zero)
  	{
! 	  __xtrc += _S_atoms_in[_M_zero];
  	  ++__pos;
  	}
  
        // Only need acceptable digits for floating point numbers.
        const size_t __len = _M_E - _M_zero + 1;
        char_type  __watoms[__len];
!       __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms);
        bool __found_dec = false;
        bool __found_sci = false;
        const char_type __dec = __np.decimal_point();
*************** namespace std
*** 150,156 ****
  	    {
  	      // Try first for acceptable digit; record it if found.
  	      ++__pos;
! 	      __xtrc += _S_atoms[__p - __watoms];
  	      ++__sep_pos;
  	      __c = *(++__beg);
  	    }
--- 150,156 ----
  	    {
  	      // Try first for acceptable digit; record it if found.
  	      ++__pos;
! 	      __xtrc += _S_atoms_in[__p - __watoms];
  	      ++__sep_pos;
  	      __c = *(++__beg);
  	    }
*************** namespace std
*** 261,267 ****
  	}
  
        // Next, strip leading zeros and check required digits for base formats.
!       const char_type __zero = __ctype.widen(_S_atoms[_M_zero]);
        const char_type __x = __ctype.widen('x');
        const char_type __X = __ctype.widen('X');
        if (__base == 10)
--- 261,267 ----
  	}
  
        // Next, strip leading zeros and check required digits for base formats.
!       const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]);
        const char_type __x = __ctype.widen('x');
        const char_type __X = __ctype.widen('X');
        if (__base == 10)
*************** namespace std
*** 274,280 ****
  	    }
  	  if (__found_zero)
  	    {
! 	      __xtrc += _S_atoms[_M_zero];
  	      ++__pos;
  	      if (__basefield == 0)
  		{	      
--- 274,280 ----
  	    }
  	  if (__found_zero)
  	    {
! 	      __xtrc += _S_atoms_in[_M_zero];
  	      ++__pos;
  	      if (__basefield == 0)
  		{	      
*************** namespace std
*** 296,302 ****
  	{
  	  if (__traits_type::eq(__c, __zero) && __beg != __end)
  	    {
! 	      __xtrc += _S_atoms[_M_zero];
  	      ++__pos;
  	      __c = *(++__beg); 
  	      if ((__traits_type::eq(__c, __x) || __traits_type::eq(__c, __X))
--- 296,302 ----
  	{
  	  if (__traits_type::eq(__c, __zero) && __beg != __end)
  	    {
! 	      __xtrc += _S_atoms_in[_M_zero];
  	      ++__pos;
  	      __c = *(++__beg); 
  	      if ((__traits_type::eq(__c, __x) || __traits_type::eq(__c, __X))
*************** namespace std
*** 319,325 ****
  
        // Extract.
        char_type __watoms[_M_size];
!       __ctype.widen(_S_atoms, _S_atoms + __len, __watoms);
        string __found_grouping;
        const string __grouping = __np.grouping();
        bool __check_grouping = __grouping.size();
--- 319,325 ----
  
        // Extract.
        char_type __watoms[_M_size];
!       __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms);
        string __found_grouping;
        const string __grouping = __np.grouping();
        bool __check_grouping = __grouping.size();
*************** namespace std
*** 333,339 ****
            if (__p && !__traits_type::eq(__c, char_type()))
  	    {
  	      // Try first for acceptable digit; record it if found.
! 	      __xtrc += _S_atoms[__p - __watoms];
  	      ++__pos;
  	      ++__sep_pos;
  	      __c = *(++__beg);
--- 333,339 ----
            if (__p && !__traits_type::eq(__c, char_type()))
  	    {
  	      // Try first for acceptable digit; record it if found.
! 	      __xtrc += _S_atoms_in[__p - __watoms];
  	      ++__pos;
  	      ++__sep_pos;
  	      __c = *(++__beg);
*************** namespace std
*** 606,619 ****
        return __beg;
      }
  
!   // The following code uses snprintf (or sprintf(), when _GLIBCPP_USE_C99
!   // is not defined) to convert floating point values for insertion into a
!   // stream.  An optimization would be to replace them with code that works
!   // directly on a wide buffer and then use __pad to do the padding.
!   // It would be good to replace them anyway to gain back the efficiency
!   // that C++ provides by knowing up front the type of the values to insert.
!   // Also, sprintf is dangerous since may lead to accidental buffer overruns.
!   // This implementation follows the C++ standard fairly directly as
    // outlined in 22.2.2.2 [lib.locale.num.put]
    template<typename _CharT, typename _OutIter>
      template<typename _ValueT>
--- 606,861 ----
        return __beg;
      }
  
!   // For use by integer and floating-point types after they have been
!   // converted into a char_type string.
!   template<typename _CharT, typename _OutIter>
!     void
!     num_put<_CharT, _OutIter>::
!     _M_pad(_CharT __fill, streamsize __w, ios_base& __io, 
! 	   _CharT* __new, const _CharT* __cs, int& __len) const
!     {
!       // [22.2.2.2.2] Stage 3.
!       // If necessary, pad.
!       __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs, 
! 						  __w, __len, true);
!       __len = static_cast<int>(__w);
!     }
! 
!   // Forwarding functions to peel signed from unsigned integer types.
!   template<typename _CharT>
!     inline int
!     __int_to_char(_CharT* __out, const int __size, long __v,
! 		       const _CharT* __lit, ios_base::fmtflags __flags)
!     {
!       unsigned long __ul = static_cast<unsigned long>(__v);
!       bool __neg = false;
!       if (__v < 0) 
! 	{
! 	  __ul = -__ul;
! 	  __neg = true;
! 	}
!       return __int_to_char(__out, __size, __ul, __lit, __flags, __neg); 
!     }
! 
!   template<typename _CharT>
!     inline int
!     __int_to_char(_CharT* __out, const int __size, unsigned long __v,
! 		       const _CharT* __lit, ios_base::fmtflags __flags)
!     { return __int_to_char(__out, __size, __v, __lit, __flags, false); }
! 
! #ifdef _GLIBCPP_USE_LONG_LONG
!   template<typename _CharT>
!     inline int
!     __int_to_char(_CharT* __out, const int __size, long long __v,
! 		       const _CharT* __lit, ios_base::fmtflags __flags)
!     { 
!       unsigned long long __ull = static_cast<unsigned long long>(__v);
!       bool __neg = false;
!       if (__v < 0) 
! 	{
! 	  __ull = -__ull;
! 	  __neg = true;
! 	}
!       return __int_to_char(__out, __size, __ull, __lit, __flags, __neg); 
!     }
! 
!   template<typename _CharT>
!     inline int
!     __int_to_char(_CharT* __out, const int __size, unsigned long long __v,
! 		       const _CharT* __lit, ios_base::fmtflags __flags)
!     { return __int_to_char(__out, __size, __v, __lit, __flags, false); }
! #endif
!       
!   template<typename _CharT, typename _ValueT>
!     int
!     __int_to_char(_CharT* __out, const int __size, _ValueT __v,
! 		  const _CharT* __lit, ios_base::fmtflags __flags, bool __neg)
!     {
!       // Don't write base if already 0.
!       const bool __showbase = (__flags & ios_base::showbase) && __v;
!       const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
!       _CharT* __buf = __out + __size - 1;
!       _CharT* __bufend = __out + __size;
! 
!       if (__builtin_expect(__basefield == ios_base::oct, false))
! 	{
! 	  // Octal.
! 	  do 
! 	    {
! 	      *__buf-- = __lit[(__v & 0x7) + __num_base::_S_digits];
! 	      __v >>= 3;
! 	    } 
! 	  while (__v != 0);
! 	  if (__showbase)
! 	    *__buf-- = __lit[__num_base::_S_digits];
! 	}
!       else if (__builtin_expect(__basefield == ios_base::hex, false))
! 	{
! 	  // Hex.
! 	  const bool __uppercase = __flags & ios_base::uppercase;
! 	  int __case_offset = __uppercase
! 	                      ? __num_base::_S_udigits : __num_base::_S_digits;
! 	  do 
! 	    {
! 	      *__buf-- = __lit[(__v & 0xf) + __case_offset];
! 	      __v >>= 4;
! 	    } 
! 	  while (__v != 0);
! 	  if (__showbase)
! 	    {
! 	      // 'x' or 'X'
! 	      *__buf-- = __lit[__num_base::_S_x + __uppercase];
! 	      // '0'
! 	      *__buf-- = __lit[__num_base::_S_digits];
! 	    }
! 	}
!       else
! 	{
! 	  // Decimal.
! 	  do 
! 	    {
! 	      *__buf-- = __lit[(__v % 10) + __num_base::_S_digits];
! 	      __v /= 10;
! 	    } 
! 	  while (__v != 0);
! 	  if (__neg)
! 	    *__buf-- = __lit[__num_base::_S_minus];
! 	  else if (__flags & ios_base::showpos)
! 	    *__buf-- = __lit[__num_base::_S_plus];
! 	}
!       int __ret = __bufend - __buf - 1;
!       return __ret;
!     }
! 
!   template<typename _CharT, typename _OutIter>
!     void
!     num_put<_CharT, _OutIter>::
!     _M_group_int(const string& __grouping, _CharT __sep, ios_base& __io, 
! 		 _CharT* __new, _CharT* __cs, int& __len) const
!     {
!       // By itself __add_grouping cannot deal correctly with __ws when
!       // ios::showbase is set and ios_base::oct || ios_base::hex.
!       // Therefore we take care "by hand" of the initial 0, 0x or 0X.
!       // However, remember that the latter do not occur if the number
!       // printed is '0' (__len == 1).
!       streamsize __off = 0;
!       const ios_base::fmtflags __basefield = __io.flags() 
! 	                                     & ios_base::basefield;
!       if ((__io.flags() & ios_base::showbase) && __len > 1)
! 	if (__basefield == ios_base::oct)
! 	  {
! 	    __off = 1;
! 	    *__new = *__cs;
! 	  }
! 	else if (__basefield == ios_base::hex)
! 	  {
! 	    __off = 2;
! 	    *__new = *__cs;
! 	    *(__new + 1) = *(__cs + 1);
! 	  }
!       _CharT* __p;
!       __p = __add_grouping(__new + __off, __sep, 
! 			   __grouping.c_str(),
! 			   __grouping.c_str() + __grouping.size(),
! 			   __cs + __off, __cs + __len);
!       __len = __p - __new;
!     }
! 
!   template<typename _CharT, typename _OutIter>
!     template<typename _ValueT>
!       _OutIter
!       num_put<_CharT, _OutIter>::
!       _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, 
! 		     _ValueT __v) const
!       {
! 	// Buildup list of digits given the current ctype.
! 	_CharT __lit[_S_udigits_end];
! 	const locale __loc = __io.getloc();
! 	if (__builtin_expect(has_facet< ctype<_CharT> >(__loc), true))
! 	  {
! 	    const ctype<_CharT>& __ct = use_facet< ctype<_CharT> >(__loc);
! 	    __ct.widen(_S_atoms_out, _S_atoms_out + _S_udigits_end, __lit);
! 	  }
! 
! 	// Long enough to hold hex, dec, and octal representations.
! 	int __ilen = 4 * sizeof(_ValueT);
! 	_CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
! 							     * __ilen));
! 
! 	// [22.2.2.2.2] Stage 1, numeric conversion to character.
! 	// Result is returned right-justified in the buffer.
! 	int __len;
! 	__len = __int_to_char(&__cs[0], __ilen, __v, __lit, __io.flags());
! 	__cs = __cs + __ilen - __len;
! 	
! 	// Add grouping, if necessary. 
! 	_CharT* __cs2;
! 	const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
! 	const string __grouping = __np.grouping();
! 	if (__grouping.size())
! 	  {
! 	    // Grouping can add (almost) as many separators as the
! 	    // number of digits, but no more.
! 	    __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
! 							  * __len * 2));
! 	    _M_group_int(__grouping, __np.thousands_sep(), __io, 
! 			 __cs2, __cs, __len);
! 	    __cs = __cs2;
! 	  }
! 	
! 	// Pad.
! 	_CharT* __cs3;
! 	streamsize __w = __io.width();
! 	if (__w > static_cast<streamsize>(__len))
! 	  {
! 	    __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
! 							  * __w));
! 	    _M_pad(__fill, __w, __io, __cs3, __cs, __len);
! 	    __cs = __cs3;
! 	  }
! 	__io.width(0);
! 
! 	// [22.2.2.2.2] Stage 4.
! 	// Write resulting, fully-formatted string to output iterator.
! 	return __write(__s, __cs, __len);
!       } 
! 
!   template<typename _CharT, typename _OutIter>
!     void
!     num_put<_CharT, _OutIter>::
!     _M_group_float(const string& __grouping, _CharT __sep, const _CharT* __p, 
! 		   _CharT* __new, _CharT* __cs, int& __len) const
!     {
! #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
!       //282. What types does numpunct grouping refer to?
!       // Add grouping, if necessary. 
!       _CharT* __p2;
!       int __declen = __p ? __p - __cs : __len;
!       __p2 = __add_grouping(__new, __sep, 
! 			    __grouping.c_str(),
! 			    __grouping.c_str() + __grouping.size(),
! 			    __cs, __cs + __declen);
!       
!       // Tack on decimal part.
!       int __newlen = __p2 - __new;
!       if (__p)
! 	{
! 	  char_traits<_CharT>::copy(__p2, __p, __len - __declen);
! 	  __newlen += __len - __declen;
! 	}    
!       __len = __newlen;
! #endif
!     }
! 
!   // The following code uses snprintf (or sprintf(), when
!   // _GLIBCPP_USE_C99 is not defined) to convert floating point values
!   // for insertion into a stream.  An optimization would be to replace
!   // them with code that works directly on a wide buffer and then use
!   // __pad to do the padding.  It would be good to replace them anyway
!   // to gain back the efficiency that C++ provides by knowing up front
!   // the type of the values to insert.  Also, sprintf is dangerous
!   // since may lead to accidental buffer overruns.  This
!   // implementation follows the C++ standard fairly directly as
    // outlined in 22.2.2.2 [lib.locale.num.put]
    template<typename _CharT, typename _OutIter>
      template<typename _ValueT>
*************** namespace std
*** 622,651 ****
        _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
  		       _ValueT __v) const
        {
! 	// Note: digits10 is rounded down: we need to add 1 to ensure
! 	// we get the full available precision.
! 	// Then, in general, one more 1 needs to be added since, when the
! 	// %{g,G} conversion specifiers are chosen inside _S_format_float, the
! 	// precision field is "the maximum number of significant digits", *not*
! 	// the "number of digits to appear after the decimal point", as happens
! 	// for %{e,E,f,F} (C99, 7.19.6.1,4).
  	const int __max_digits = numeric_limits<_ValueT>::digits10 + 2;
- 	streamsize __prec = __io.precision();
  
  	if (__prec > static_cast<streamsize>(__max_digits))
  	  __prec = static_cast<streamsize>(__max_digits);
  	else if (__prec < static_cast<streamsize>(0))
- 	  // Default precision.
  	  __prec = static_cast<streamsize>(6);
  
  	// Long enough for the max format spec.
  	char __fbuf[16];
  
- 	// [22.2.2.2.2] Stage 1, numeric conversion to character.
- 	int __len;
  #ifdef _GLIBCPP_USE_C99
! 	// First try a buffer perhaps big enough (for sure sufficient for
! 	// non-ios_base::fixed outputs)
  	int __cs_size = __max_digits * 3;
  	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
  
--- 864,893 ----
        _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
  		       _ValueT __v) const
        {
! 	// Note: digits10 is rounded down: add 1 to ensure the maximum
! 	// available precision.  Then, in general, one more 1 needs to
! 	// be added since, when the %{g,G} conversion specifiers are
! 	// chosen inside _S_format_float, the precision field is "the
! 	// maximum number of significant digits", *not* the "number of
! 	// digits to appear after the decimal point", as happens for
! 	// %{e,E,f,F} (C99, 7.19.6.1,4).
  	const int __max_digits = numeric_limits<_ValueT>::digits10 + 2;
  
+ 	// Use default precision if out of range.
+ 	streamsize __prec = __io.precision();
  	if (__prec > static_cast<streamsize>(__max_digits))
  	  __prec = static_cast<streamsize>(__max_digits);
  	else if (__prec < static_cast<streamsize>(0))
  	  __prec = static_cast<streamsize>(6);
  
+ 	// [22.2.2.2.2] Stage 1, numeric conversion to character.
+ 	int __len;
  	// Long enough for the max format spec.
  	char __fbuf[16];
  
  #ifdef _GLIBCPP_USE_C99
! 	// First try a buffer perhaps big enough (for sure sufficient
! 	// for non-ios_base::fixed outputs)
  	int __cs_size = __max_digits * 3;
  	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
  
*************** namespace std
*** 665,670 ****
--- 907,913 ----
  	// Consider the possibility of long ios_base::fixed outputs
  	const bool __fixed = __io.flags() & ios_base::fixed;
  	const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
+ 
  	// ios_base::fixed outputs may need up to __max_exp+1 chars
  	// for the integer part + up to __max_digits chars for the
  	// fractional part + 3 chars for sign, decimal point, '\0'. On
*************** namespace std
*** 677,857 ****
  	_S_format_float(__io, __fbuf, __mod);
  	__len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec);
  #endif
- 	return _M_widen_float(__s, __io, __fill, __cs, __len);
-       }
- 
-   template<typename _CharT, typename _OutIter>
-     template<typename _ValueT>
-       _OutIter
-       num_put<_CharT, _OutIter>::
-       _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
- 		     char __modl, _ValueT __v) const
-       {
- 	// [22.2.2.2.2] Stage 1, numeric conversion to character.
  
- 	// Long enough for the max format spec.
- 	char __fbuf[16];
- 	_S_format_int(__io, __fbuf, __mod, __modl);
- #ifdef _GLIBCPP_USE_C99
- 	// First try a buffer perhaps big enough.
- 	int __cs_size = 64;
- 	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
- 	int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
- 				     _S_c_locale);
- 	// If the buffer was not large enough, try again with the correct size.
- 	if (__len >= __cs_size)
- 	  {
- 	    __cs_size = __len + 1;
- 	    __cs = static_cast<char*>(__builtin_alloca(__cs_size));
- 	    __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
- 				     _S_c_locale);
- 	  }
- #else
- 	// Leave room for "+/-," "0x," and commas. This size is
- 	// arbitrary, but should be largely sufficient.
- 	char __cs[128];
- 	int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale);
- #endif
- 	return _M_widen_int(__s, __io, __fill, __cs, __len);
-       }
- 
-   template<typename _CharT, typename _OutIter>
-     _OutIter
-     num_put<_CharT, _OutIter>::
-     _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 
- 		   int __len) const
-     {
-       typedef char_traits<_CharT> 		__traits_type;
        // [22.2.2.2.2] Stage 2, convert to char_type, using correct
        // numpunct.decimal_point() values for '.' and adding grouping.
        const locale __loc = __io.getloc();
        const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
        _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
  							   * __len));
-       // Grouping can add (almost) as many separators as the number of
-       // digits, but no more.
-       _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
- 			 				    * __len * 2));
        __ctype.widen(__cs, __cs + __len, __ws);
        
        // Replace decimal point.
        const _CharT* __p;
!       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
!       if (__p = __traits_type::find(__ws, __len, __ctype.widen('.')))
! 	__ws[__p - __ws] = __np.decimal_point();
  
- #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
- //282. What types does numpunct grouping refer to?
        // Add grouping, if necessary. 
        const string __grouping = __np.grouping();
        if (__grouping.size())
  	{
! 	  _CharT* __p2;
! 	  int __declen = __p ? __p - __ws : __len;
! 	  __p2 = __add_grouping(__ws2, __np.thousands_sep(), 
! 				__grouping.c_str(),
! 				__grouping.c_str() + __grouping.size(),
! 				__ws, __ws + __declen);
! 	  int __newlen = __p2 - __ws2;
! 	
! 	  // Tack on decimal part.
! 	  if (__p)
! 	    {
! 	      __traits_type::copy(__p2, __p, __len - __declen);
! 	      __newlen += __len - __declen;
! 	    }    
! 
! 	  // Switch strings, establish correct new length.
! 	  __ws = __ws2;
! 	  __len = __newlen;
  	}
- #endif
-       return _M_insert(__s, __io, __fill, __ws, __len);
-     }
  
!   template<typename _CharT, typename _OutIter>
!     _OutIter
!     num_put<_CharT, _OutIter>::
!     _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 
! 		 int __len) const
!     {
!       // [22.2.2.2.2] Stage 2, convert to char_type, using correct
!       // numpunct.decimal_point() values for '.' and adding grouping.
!       const locale __loc = __io.getloc();
!       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
!       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
! 							   * __len));
!       // Grouping can add (almost) as many separators as the number of
!       // digits, but no more.
!       _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
! 							    * __len * 2));
!       __ctype.widen(__cs, __cs + __len, __ws);
! 
!       // Add grouping, if necessary. 
!       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
!       const string __grouping = __np.grouping();
!       if (__grouping.size())
! 	{
! 	  // By itself __add_grouping cannot deal correctly with __ws when
! 	  // ios::showbase is set and ios_base::oct || ios_base::hex.
! 	  // Therefore we take care "by hand" of the initial 0, 0x or 0X.
! 	  // However, remember that the latter do not occur if the number
! 	  // printed is '0' (__len == 1).
! 	  streamsize __off = 0;
! 	  const ios_base::fmtflags __basefield = __io.flags() 
! 	    					 & ios_base::basefield;
! 	  if ((__io.flags() & ios_base::showbase) && __len > 1)
! 	    if (__basefield == ios_base::oct)
! 	      {
! 		__off = 1;
! 		*__ws2 = *__ws;
! 	      }
! 	    else if (__basefield == ios_base::hex)
! 	      {
! 		__off = 2;
! 		*__ws2 = *__ws;
! 		*(__ws2 + 1) = *(__ws + 1);
! 	      }
! 	  _CharT* __p;
! 	  __p = __add_grouping(__ws2 + __off, __np.thousands_sep(), 
! 			       __grouping.c_str(),
! 			       __grouping.c_str() + __grouping.size(),
! 			       __ws + __off, __ws + __len);
! 	  __len = __p - __ws2;
! 	  // Switch strings.
! 	  __ws = __ws2;
! 	}
!       return _M_insert(__s, __io, __fill, __ws, __len);
!     }
! 
!   // For use by integer and floating-point types after they have been
!   // converted into a char_type string.
!   template<typename _CharT, typename _OutIter>
!     _OutIter
!     num_put<_CharT, _OutIter>::
!     _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, 
! 	      int __len) const
!     {
!       typedef char_traits<_CharT> 		__traits_type;
!       // [22.2.2.2.2] Stage 3.
!       // If necessary, pad.
        streamsize __w = __io.width();
-       _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
- 							    * __w));
        if (__w > static_cast<streamsize>(__len))
  	{
! 	  __pad<_CharT, __traits_type>::_S_pad(__io, __fill, __ws2, __ws, 
! 					       __w, __len, true);
! 	  __len = static_cast<int>(__w);
! 	  // Switch strings.
! 	  __ws = __ws2;
  	}
        __io.width(0);
! 
        // [22.2.2.2.2] Stage 4.
        // Write resulting, fully-formatted string to output iterator.
        return __write(__s, __ws, __len);
!     }
  
    template<typename _CharT, typename _OutIter>
      _OutIter
--- 920,972 ----
  	_S_format_float(__io, __fbuf, __mod);
  	__len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec);
  #endif
  
        // [22.2.2.2.2] Stage 2, convert to char_type, using correct
        // numpunct.decimal_point() values for '.' and adding grouping.
        const locale __loc = __io.getloc();
        const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
+ 
        _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
  							   * __len));
        __ctype.widen(__cs, __cs + __len, __ws);
        
        // Replace decimal point.
+       const _CharT __cdec = __ctype.widen('.');
+       const _CharT __dec = __np.decimal_point();
        const _CharT* __p;
!       if (__p = char_traits<_CharT>::find(__ws, __len, __cdec))
! 	__ws[__p - __ws] = __dec;
  
        // Add grouping, if necessary. 
+       _CharT* __ws2;
        const string __grouping = __np.grouping();
        if (__grouping.size())
  	{
! 	    // Grouping can add (almost) as many separators as the
! 	    // number of digits, but no more.
! 	    __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
! 							  * __len * 2));
! 	    _M_group_float(__grouping, __np.thousands_sep(), __p, 
! 			   __ws2, __ws, __len);
! 	    __ws = __ws2;
  	}
  
!       // Pad.
!       _CharT* __ws3;
        streamsize __w = __io.width();
        if (__w > static_cast<streamsize>(__len))
  	{
! 	  __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __w));
! 	  _M_pad(__fill, __w, __io, __ws3, __ws, __len);
! 	  __ws = __ws3;
  	}
        __io.width(0);
!       
        // [22.2.2.2.2] Stage 4.
        // Write resulting, fully-formatted string to output iterator.
        return __write(__s, __ws, __len);
!       }
  
    template<typename _CharT, typename _OutIter>
      _OutIter
*************** namespace std
*** 862,880 ****
        if ((__flags & ios_base::boolalpha) == 0)
          {
            unsigned long __uv = __v;
!           __s = _M_convert_int(__s, __io, __fill, 'u', char(), __uv);
          }
        else
          {
- 	  typedef basic_string<_CharT> __string_type;
            locale __loc = __io.getloc();
  	  const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 
  	  __string_type __name;
            if (__v)
  	    __name = __np.truename();
            else
  	    __name = __np.falsename();
! 	  __s = _M_insert(__s, __io, __fill, __name.c_str(), __name.size()); 
  	}
        return __s;
      }
--- 977,1008 ----
        if ((__flags & ios_base::boolalpha) == 0)
          {
            unsigned long __uv = __v;
!           __s = _M_convert_int(__s, __io, __fill, __uv);
          }
        else
          {
            locale __loc = __io.getloc();
  	  const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 
+ 	  typedef basic_string<_CharT> 	__string_type;
  	  __string_type __name;
            if (__v)
  	    __name = __np.truename();
            else
  	    __name = __np.falsename();
! 
! 	  const _CharT* __cs = __name.c_str();
! 	  int __len = __name.size();
! 	  _CharT* __cs3;
! 	  streamsize __w = __io.width();
! 	  if (__w > static_cast<streamsize>(__len))
! 	    {
! 	      __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
! 							    * __w));
! 	      _M_pad(__fill, __w, __io, __cs3, __cs, __len);
! 	      __cs = __cs3;
! 	    }
! 	  __io.width(0);
! 	  __s = __write(__s, __cs, __len);
  	}
        return __s;
      }
*************** namespace std
*** 883,910 ****
      _OutIter
      num_put<_CharT, _OutIter>::
      do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
!     { return _M_convert_int(__s, __io, __fill, 'd', char(), __v); }
  
    template<typename _CharT, typename _OutIter>
      _OutIter
      num_put<_CharT, _OutIter>::
      do_put(iter_type __s, ios_base& __io, char_type __fill,
             unsigned long __v) const
!     { return _M_convert_int(__s, __io, __fill, 'u', char(), __v); }
  
  #ifdef _GLIBCPP_USE_LONG_LONG
    template<typename _CharT, typename _OutIter>
      _OutIter
      num_put<_CharT, _OutIter>::
      do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
!     { return _M_convert_int(__s, __b, __fill, 'd', 'l', __v); }
  
    template<typename _CharT, typename _OutIter>
      _OutIter
      num_put<_CharT, _OutIter>::
      do_put(iter_type __s, ios_base& __io, char_type __fill,
             unsigned long long __v) const
!     { return _M_convert_int(__s, __io, __fill, 'u', 'l', __v); }
  #endif
  
    template<typename _CharT, typename _OutIter>
--- 1011,1038 ----
      _OutIter
      num_put<_CharT, _OutIter>::
      do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
!     { return _M_convert_int(__s, __io, __fill, __v); }
  
    template<typename _CharT, typename _OutIter>
      _OutIter
      num_put<_CharT, _OutIter>::
      do_put(iter_type __s, ios_base& __io, char_type __fill,
             unsigned long __v) const
!     { return _M_convert_int(__s, __io, __fill, __v); }
  
  #ifdef _GLIBCPP_USE_LONG_LONG
    template<typename _CharT, typename _OutIter>
      _OutIter
      num_put<_CharT, _OutIter>::
      do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
!     { return _M_convert_int(__s, __b, __fill, __v); }
  
    template<typename _CharT, typename _OutIter>
      _OutIter
      num_put<_CharT, _OutIter>::
      do_put(iter_type __s, ios_base& __io, char_type __fill,
             unsigned long long __v) const
!     { return _M_convert_int(__s, __io, __fill, __v); }
  #endif
  
    template<typename _CharT, typename _OutIter>
*************** namespace std
*** 932,938 ****
        __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
        try 
  	{
! 	  __s = _M_convert_int(__s, __io, __fill, 'u', char(),
  			       reinterpret_cast<unsigned long>(__v));
  	  __io.flags(__flags);
  	}
--- 1060,1066 ----
        __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
        try 
  	{
! 	  __s = _M_convert_int(__s, __io, __fill, 
  			       reinterpret_cast<unsigned long>(__v));
  	  __io.flags(__flags);
  	}
*************** namespace std
*** 1622,1628 ****
  	if (__c == __names[__i1][0])
  	  __matches[__nmatches++] = __i1;
        
!       while(__nmatches > 1)
  	{
  	  // Find smallest matching string.
  	  size_t __minlen = 10;
--- 1750,1756 ----
  	if (__c == __names[__i1][0])
  	  __matches[__nmatches++] = __i1;
        
!       while (__nmatches > 1)
  	{
  	  // Find smallest matching string.
  	  size_t __minlen = 10;
*************** namespace std
*** 1847,1854 ****
  		}
  	      else
  		__format = __c;
! 	      __s = this->do_put(__s, __io, char_type(), __tm, __format, 
! 				 __mod);
  	    }
  	  else
  	    {
--- 1975,1981 ----
  		}
  	      else
  		__format = __c;
! 	      __s = this->do_put(__s, __io, _CharT(), __tm, __format, __mod);
  	    }
  	  else
  	    {
Index: src/locale-inst.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/src/locale-inst.cc,v
retrieving revision 1.35
diff -c -p -r1.35 locale-inst.cc
*** src/locale-inst.cc	8 Oct 2002 23:32:23 -0000	1.35
--- src/locale-inst.cc	11 Feb 2003 18:17:44 -0000
***************
*** 1,6 ****
  // Locale support -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
  //
  // This file is part of the GNU ISO C++ Library.  This library is free
  // software; you can redistribute it and/or modify it under the
--- 1,6 ----
  // Locale support -*- C++ -*-
  
! // Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
  //
  // This file is part of the GNU ISO C++ Library.  This library is free
  // software; you can redistribute it and/or modify it under the
*************** namespace std
*** 64,89 ****
    template
      ostreambuf_iterator<char>
      num_put<char, ostreambuf_iterator<char> >::
!     _M_convert_int(ostreambuf_iterator<char>, ios_base&, char, char, char, 
  		   long) const;
  
    template
      ostreambuf_iterator<char>
      num_put<char, ostreambuf_iterator<char> >::
!     _M_convert_int(ostreambuf_iterator<char>, ios_base&, char, char, char, 
  		   unsigned long) const;
  
  #ifdef _GLIBCPP_USE_LONG_LONG
    template
      ostreambuf_iterator<char>
      num_put<char, ostreambuf_iterator<char> >::
!     _M_convert_int(ostreambuf_iterator<char>, ios_base&, char, char, char, 
  		   long long) const;
  
    template
      ostreambuf_iterator<char>
      num_put<char, ostreambuf_iterator<char> >::
!     _M_convert_int(ostreambuf_iterator<char>, ios_base&, char, char, char,
  		   unsigned long long) const;
  #endif
  
--- 64,89 ----
    template
      ostreambuf_iterator<char>
      num_put<char, ostreambuf_iterator<char> >::
!     _M_convert_int(ostreambuf_iterator<char>, ios_base&, char, 
  		   long) const;
  
    template
      ostreambuf_iterator<char>
      num_put<char, ostreambuf_iterator<char> >::
!     _M_convert_int(ostreambuf_iterator<char>, ios_base&, char, 
  		   unsigned long) const;
  
  #ifdef _GLIBCPP_USE_LONG_LONG
    template
      ostreambuf_iterator<char>
      num_put<char, ostreambuf_iterator<char> >::
!     _M_convert_int(ostreambuf_iterator<char>, ios_base&, char, 
  		   long long) const;
  
    template
      ostreambuf_iterator<char>
      num_put<char, ostreambuf_iterator<char> >::
!     _M_convert_int(ostreambuf_iterator<char>, ios_base&, char, 
  		   unsigned long long) const;
  #endif
  
*************** namespace std
*** 97,104 ****
      ostreambuf_iterator<char>
      num_put<char, ostreambuf_iterator<char> >::
      _M_convert_float(ostreambuf_iterator<char>, ios_base&, char, char, 
! 		    long double) const;
! 
  #ifdef _GLIBCPP_USE_WCHAR_T
    template class numpunct<wchar_t>;
    template class numpunct_byname<wchar_t>;
--- 97,104 ----
      ostreambuf_iterator<char>
      num_put<char, ostreambuf_iterator<char> >::
      _M_convert_float(ostreambuf_iterator<char>, ios_base&, char, char, 
! 		     long double) const;
!   
  #ifdef _GLIBCPP_USE_WCHAR_T
    template class numpunct<wchar_t>;
    template class numpunct_byname<wchar_t>;
*************** namespace std
*** 108,134 ****
    template
      ostreambuf_iterator<wchar_t>
      num_put<wchar_t, ostreambuf_iterator<wchar_t> >::
!     _M_convert_int(ostreambuf_iterator<wchar_t>, ios_base&, wchar_t, char, 
! 		   char, long) const;
  
    template
      ostreambuf_iterator<wchar_t>
      num_put<wchar_t, ostreambuf_iterator<wchar_t> >::
!     _M_convert_int(ostreambuf_iterator<wchar_t>, ios_base&, wchar_t, char, 
! 		   char, unsigned long) const;
  
  #ifdef _GLIBCPP_USE_LONG_LONG
    template
      ostreambuf_iterator<wchar_t>
      num_put<wchar_t, ostreambuf_iterator<wchar_t> >::
!     _M_convert_int(ostreambuf_iterator<wchar_t>, ios_base&, wchar_t, char, 
! 		   char, long long) const;
  
    template
      ostreambuf_iterator<wchar_t>
      num_put<wchar_t, ostreambuf_iterator<wchar_t> >::
!     _M_convert_int(ostreambuf_iterator<wchar_t>, ios_base&, wchar_t, char, 
! 		   char, unsigned long long) const;
  #endif
  
    template
--- 108,134 ----
    template
      ostreambuf_iterator<wchar_t>
      num_put<wchar_t, ostreambuf_iterator<wchar_t> >::
!     _M_convert_int(ostreambuf_iterator<wchar_t>, ios_base&, wchar_t, 
! 		   long) const;
  
    template
      ostreambuf_iterator<wchar_t>
      num_put<wchar_t, ostreambuf_iterator<wchar_t> >::
!     _M_convert_int(ostreambuf_iterator<wchar_t>, ios_base&, wchar_t, 
! 		   unsigned long) const;
  
  #ifdef _GLIBCPP_USE_LONG_LONG
    template
      ostreambuf_iterator<wchar_t>
      num_put<wchar_t, ostreambuf_iterator<wchar_t> >::
!     _M_convert_int(ostreambuf_iterator<wchar_t>, ios_base&, wchar_t,
! 		   long long) const;
  
    template
      ostreambuf_iterator<wchar_t>
      num_put<wchar_t, ostreambuf_iterator<wchar_t> >::
!     _M_convert_int(ostreambuf_iterator<wchar_t>, ios_base&, wchar_t,
! 		   unsigned long long) const;
  #endif
  
    template
*************** namespace std
*** 451,456 ****
--- 451,457 ----
      __convert_from_v(char*, const int, const char*, unsigned long, 
  		     const __c_locale&, int);
  
+ #ifdef _GLIBCPP_USE_LONG_LONG
    template
      int
      __convert_from_v(char*, const int, const char*, long long, 
*************** namespace std
*** 460,463 ****
--- 461,491 ----
      int
      __convert_from_v(char*, const int, const char*, unsigned long long, 
  		     const __c_locale&, int);
+ #endif
+ 
+   template
+     int
+     __int_to_char(char*, const int, unsigned long, const char*, 
+ 		  ios_base::fmtflags, bool);
+ 
+ #ifdef _GLIBCPP_USE_WCHAR_T
+   template
+     int
+     __int_to_char(wchar_t*, const int, unsigned long, const wchar_t*, 
+ 		  ios_base::fmtflags, bool);
+ #endif
+ 
+ #ifdef _GLIBCPP_USE_LONG_LONG
+   template
+     int
+     __int_to_char(char*, const int, unsigned long long, const char*, 
+ 		  ios_base::fmtflags, bool);
+ 
+ #ifdef _GLIBCPP_USE_WCHAR_T
+   template
+     int
+     __int_to_char(wchar_t*, const int, unsigned long long, const wchar_t*,
+ 		  ios_base::fmtflags, bool);
+ #endif
+ #endif
  } // namespace std
Index: src/locale.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/src/locale.cc,v
retrieving revision 1.76
diff -c -p -r1.76 locale.cc
*** src/locale.cc	6 Feb 2003 18:08:50 -0000	1.76
--- src/locale.cc	11 Feb 2003 18:17:45 -0000
*************** namespace std 
*** 503,509 ****
    const money_base::pattern 
    money_base::_S_default_pattern =  { {symbol, sign, none, value} };
  
!   const char __num_base::_S_atoms[] = "0123456789eEabcdfABCDF";
  
    // _GLIBCPP_RESOLVE_LIB_DEFECTS
    // According to the resolution of DR 231, about 22.2.2.2.2, p11,
--- 503,510 ----
    const money_base::pattern 
    money_base::_S_default_pattern =  { {symbol, sign, none, value} };
  
!   const char* __num_base::_S_atoms_in = "0123456789eEabcdfABCDF";
!   const char* __num_base::_S_atoms_out ="-+xX0123456789abcdef0123456789ABCDEF";
  
    // _GLIBCPP_RESOLVE_LIB_DEFECTS
    // According to the resolution of DR 231, about 22.2.2.2.2, p11,




More information about the Libstdc++ mailing list