OSDN Git Service

2006-09-18 Paolo Carlini <pcarlini@suse.de>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / bits / locale_facets.tcc
index b558237..6cf2933 100644 (file)
@@ -1,6 +1,6 @@
 // Locale support -*- C++ -*-
 
-// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
 // Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
@@ -16,7 +16,7 @@
 
 // You should have received a copy of the GNU General Public License along
 // with this library; see the file COPYING.  If not, write to the Free
-// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
 // USA.
 
 // As a special exception, you may use this file as part of a free software
 #include <limits>              // For numeric_limits
 #include <typeinfo>            // For bad_cast.
 #include <bits/streambuf_iterator.h>
+#include <ext/type_traits.h>
+
+_GLIBCXX_BEGIN_NAMESPACE(std)
 
-namespace std
-{
   template<typename _Facet>
     locale
     locale::combine(const locale& __other) const
@@ -193,7 +194,8 @@ namespace std
       char* __grouping = new char[_M_grouping_size];
       __np.grouping().copy(__grouping, _M_grouping_size);
       _M_grouping = __grouping;
-      _M_use_grouping = _M_grouping_size && __np.grouping()[0] != 0;
+      _M_use_grouping = (_M_grouping_size
+                        && static_cast<signed char>(__np.grouping()[0]) > 0);
 
       _M_truename_size = __np.truename().size();
       _CharT* __truename = new _CharT[_M_truename_size];
@@ -228,7 +230,8 @@ namespace std
       char* __grouping = new char[_M_grouping_size];
       __mp.grouping().copy(__grouping, _M_grouping_size);
       _M_grouping = __grouping;
-      _M_use_grouping = _M_grouping_size && __mp.grouping()[0] != 0;
+      _M_use_grouping = (_M_grouping_size
+                        && static_cast<signed char>(__mp.grouping()[0]) > 0);
       
       _M_decimal_point = __mp.decimal_point();
       _M_thousands_sep = __mp.thousands_sep();
@@ -270,6 +273,8 @@ namespace std
   __verify_grouping(const char* __grouping, size_t __grouping_size,
                    const string& __grouping_tmp);
 
+_GLIBCXX_BEGIN_LDBL_NAMESPACE
+
   template<typename _CharT, typename _InIter>
     _InIter
     num_get<_CharT, _InIter>::
@@ -277,7 +282,7 @@ namespace std
                     ios_base::iostate& __err, string& __xtrc) const
     {
       typedef char_traits<_CharT>                      __traits_type;
-      typedef typename numpunct<_CharT>::__cache_type  __cache_type;
+      typedef __numpunct_cache<_CharT>                  __cache_type;
       __use_cache<__cache_type> __uc;
       const locale& __loc = __io._M_getloc();
       const __cache_type* __lc = __uc(__loc);
@@ -306,6 +311,7 @@ namespace std
 
       // Next, look for leading zeros.
       bool __found_mantissa = false;
+      int __sep_pos = 0;
       while (!__testeof)
        {
          if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep
@@ -318,6 +324,8 @@ namespace std
                  __xtrc += '0';
                  __found_mantissa = true;
                }
+             ++__sep_pos;
+
              if (++__beg != __end)
                __c = *__beg;
              else
@@ -333,92 +341,146 @@ namespace std
       string __found_grouping;
       if (__lc->_M_use_grouping)
        __found_grouping.reserve(32);
-      int __sep_pos = 0;
-      const char_type* __q;
       const char_type* __lit_zero = __lit + __num_base::_S_izero;
-      while (!__testeof)
-        {
-         // According to 22.2.2.1.2, p8-9, first look for thousands_sep
-         // and decimal_point.
-          if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
-           {
-             if (!__found_dec && !__found_sci)
-               {
-                 // NB: Thousands separator at the beginning of a string
-                 // is a no-no, as is two consecutive thousands separators.
-                 if (__sep_pos)
-                   {
-                     __found_grouping += static_cast<char>(__sep_pos);
-                     __sep_pos = 0;
-                   }
-                 else
-                   {
-                     __err |= ios_base::failbit;
-                     break;
-                   }
-               }
-             else
-               break;
-            }
-         else if (__c == __lc->_M_decimal_point)
-           {
-             if (!__found_dec && !__found_sci)
-               {
-                 // If no grouping chars are seen, no grouping check
-                 // is applied. Therefore __found_grouping is adjusted
-                 // only if decimal_point comes after some thousands_sep.
-                 if (__found_grouping.size())
-                   __found_grouping += static_cast<char>(__sep_pos);
-                 __xtrc += '.';
-                 __found_dec = true;
-               }
-             else
-               break;
-           }
-          else if ((__q = __traits_type::find(__lit_zero, 10, __c)))
-           {
-             __xtrc += __num_base::_S_atoms_in[__q - __lit];
-             __found_mantissa = true;
-             ++__sep_pos;
-           }
-         else if ((__c == __lit[__num_base::_S_ie] 
-                   || __c == __lit[__num_base::_S_iE])
-                  && __found_mantissa && !__found_sci)
-           {
-             // Scientific notation.
-             if (__found_grouping.size() && !__found_dec)
-               __found_grouping += static_cast<char>(__sep_pos);
-             __xtrc += 'e';
-             __found_sci = true;
 
-             // Remove optional plus or minus sign, if they exist.
-             if (++__beg != __end)
-               {
-                 __c = *__beg;
-                 const bool __plus = __c == __lit[__num_base::_S_iplus];
-                 if ((__plus || __c == __lit[__num_base::_S_iminus])
-                     && !(__lc->_M_use_grouping
-                          && __c == __lc->_M_thousands_sep)
-                     && !(__c == __lc->_M_decimal_point))
-                   __xtrc += __plus ? '+' : '-';
-                 else
-                   continue;
-               }
-             else
-               {
-                 __testeof = true;
-                 break;
-               }
-           }
-         else
-           // Not a valid input item.
-           break;
+      if (!__lc->_M_allocated)
+       // "C" locale
+       while (!__testeof)
+         {
+           const int __digit = _M_find(__lit_zero, 10, __c);
+           if (__digit != -1)
+             {
+               __xtrc += '0' + __digit;
+               __found_mantissa = true;
+             }
+           else if (__c == __lc->_M_decimal_point
+                    && !__found_dec && !__found_sci)
+             {
+               __xtrc += '.';
+               __found_dec = true;
+             }
+           else if ((__c == __lit[__num_base::_S_ie] 
+                     || __c == __lit[__num_base::_S_iE])
+                    && !__found_sci && __found_mantissa)
+             {
+               // Scientific notation.
+               __xtrc += 'e';
+               __found_sci = true;
+               
+               // Remove optional plus or minus sign, if they exist.
+               if (++__beg != __end)
+                 {
+                   __c = *__beg;
+                   const bool __plus = __c == __lit[__num_base::_S_iplus];
+                   if (__plus || __c == __lit[__num_base::_S_iminus])
+                     __xtrc += __plus ? '+' : '-';
+                   else
+                     continue;
+                 }
+               else
+                 {
+                   __testeof = true;
+                   break;
+                 }
+             }
+           else
+             break;
 
-         if (++__beg != __end)
-           __c = *__beg;
-         else
-           __testeof = true;
-        }
+           if (++__beg != __end)
+             __c = *__beg;
+           else
+             __testeof = true;
+         }
+      else
+       while (!__testeof)
+         {
+           // According to 22.2.2.1.2, p8-9, first look for thousands_sep
+           // and decimal_point.
+           if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
+             {
+               if (!__found_dec && !__found_sci)
+                 {
+                   // NB: Thousands separator at the beginning of a string
+                   // is a no-no, as is two consecutive thousands separators.
+                   if (__sep_pos)
+                     {
+                       __found_grouping += static_cast<char>(__sep_pos);
+                       __sep_pos = 0;
+                     }
+                   else
+                     {
+                       // NB: __convert_to_v will not assign __v and will
+                       // set the failbit.
+                       __xtrc.clear();
+                       break;
+                     }
+                 }
+               else
+                 break;
+             }
+           else if (__c == __lc->_M_decimal_point)
+             {
+               if (!__found_dec && !__found_sci)
+                 {
+                   // If no grouping chars are seen, no grouping check
+                   // is applied. Therefore __found_grouping is adjusted
+                   // only if decimal_point comes after some thousands_sep.
+                   if (__found_grouping.size())
+                     __found_grouping += static_cast<char>(__sep_pos);
+                   __xtrc += '.';
+                   __found_dec = true;
+                 }
+               else
+                 break;
+             }
+           else
+             {
+               const char_type* __q =
+                 __traits_type::find(__lit_zero, 10, __c);
+               if (__q)
+                 {
+                   __xtrc += '0' + (__q - __lit_zero);
+                   __found_mantissa = true;
+                   ++__sep_pos;
+                 }
+               else if ((__c == __lit[__num_base::_S_ie] 
+                         || __c == __lit[__num_base::_S_iE])
+                        && !__found_sci && __found_mantissa)
+                 {
+                   // Scientific notation.
+                   if (__found_grouping.size() && !__found_dec)
+                     __found_grouping += static_cast<char>(__sep_pos);
+                   __xtrc += 'e';
+                   __found_sci = true;
+                   
+                   // Remove optional plus or minus sign, if they exist.
+                   if (++__beg != __end)
+                     {
+                       __c = *__beg;
+                       const bool __plus = __c == __lit[__num_base::_S_iplus];
+                       if ((__plus || __c == __lit[__num_base::_S_iminus])
+                           && !(__lc->_M_use_grouping
+                                && __c == __lc->_M_thousands_sep)
+                           && !(__c == __lc->_M_decimal_point))
+                     __xtrc += __plus ? '+' : '-';
+                       else
+                         continue;
+                     }
+                   else
+                     {
+                       __testeof = true;
+                       break;
+                     }
+                 }
+               else
+                 break;
+             }
+           
+           if (++__beg != __end)
+             __c = *__beg;
+           else
+             __testeof = true;
+         }
 
       // Digit grouping is checked. If grouping and found_grouping don't
       // match, then get very very upset, and set failbit.
@@ -440,6 +502,10 @@ namespace std
       return __beg;
     }
 
+_GLIBCXX_END_LDBL_NAMESPACE
+
+_GLIBCXX_BEGIN_LDBL_NAMESPACE
+
   template<typename _CharT, typename _InIter>
     template<typename _ValueT>
       _InIter
@@ -447,8 +513,10 @@ namespace std
       _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
                     ios_base::iostate& __err, _ValueT& __v) const
       {
-        typedef char_traits<_CharT>                    __traits_type;
-       typedef typename numpunct<_CharT>::__cache_type __cache_type;
+        typedef char_traits<_CharT>                         __traits_type;
+       using __gnu_cxx::__add_unsigned;
+       typedef typename __add_unsigned<_ValueT>::__type __unsigned_type;
+       typedef __numpunct_cache<_CharT>                     __cache_type;
        __use_cache<__cache_type> __uc;
        const locale& __loc = __io._M_getloc();
        const __cache_type* __lc = __uc(__loc);
@@ -485,6 +553,7 @@ namespace std
        // Next, look for leading zeros and check required digits
        // for base formats.
        bool __found_zero = false;
+       int __sep_pos = 0;
        while (!__testeof)
          {
            if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep
@@ -492,25 +561,27 @@ namespace std
              break;
            else if (__c == __lit[__num_base::_S_izero] 
                     && (!__found_zero || __base == 10))
-             __found_zero = true;
-           else if (__found_zero)
              {
-               if (__c == __lit[__num_base::_S_ix] 
-                   || __c == __lit[__num_base::_S_iX])
+               __found_zero = true;
+               ++__sep_pos;
+               if (__basefield == 0)
+                 __base = 8;
+               if (__base == 8)
+                 __sep_pos = 0;
+             }
+           else if (__found_zero
+                    && (__c == __lit[__num_base::_S_ix]
+                        || __c == __lit[__num_base::_S_iX]))
+             {
+               if (__basefield == 0)
+                 __base = 16;
+               if (__base == 16)
                  {
-                   if (__basefield == 0)
-                     __base = 16;
-                   if (__base == 16)
-                     __found_zero = false;
-                   else
-                     break;
+                   __found_zero = false;
+                   __sep_pos = 0;
                  }
                else
-                 {
-                   if (__basefield == 0)
-                     __base = 8;
-                   break;
-                 }
+                 break;
              }
            else
              break;
@@ -534,107 +605,86 @@ namespace std
        string __found_grouping;
        if (__lc->_M_use_grouping)
          __found_grouping.reserve(32);
-       int __sep_pos = 0;
-       bool __overflow = false;
-       _ValueT __result = 0;
-       const char_type* __q;
+       bool __testfail = false;
+       const __unsigned_type __max = __negative ?
+         -numeric_limits<_ValueT>::min() : numeric_limits<_ValueT>::max();
+       const __unsigned_type __smax = __max / __base;
+       __unsigned_type __result = 0;
+       int __digit = 0;
        const char_type* __lit_zero = __lit + __num_base::_S_izero;
-       if (__negative)
-         {
-           const _ValueT __min = numeric_limits<_ValueT>::min() / __base;
-           while (!__testeof)
-             {
-               // According to 22.2.2.1.2, p8-9, first look for thousands_sep
-               // and decimal_point.
-               if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
-                 {
-                   // NB: Thousands separator at the beginning of a string
-                   // is a no-no, as is two consecutive thousands separators.
-                   if (__sep_pos)
-                     {
-                       __found_grouping += static_cast<char>(__sep_pos);
-                       __sep_pos = 0;
-                     }
-                   else
-                     {
-                       __err |= ios_base::failbit;
-                       break;
-                     }
-                 }
-               else if (__c == __lc->_M_decimal_point)
-                 break;
-               else if ((__q = __traits_type::find(__lit_zero, __len, __c)))
-                 {
-                   int __digit = __q - __lit_zero;
-                   if (__digit > 15)
-                     __digit -= 6;
-                   if (__result < __min)
-                     __overflow = true;
-                   else
-                     {
-                       const _ValueT __new_result = (__result * __base
-                                                     - __digit);
-                       __overflow |= __new_result > __result;
-                       __result = __new_result;
-                       ++__sep_pos;
-                     }
-                 }
-               else
-                 // Not a valid input item.
-                 break;
 
-               if (++__beg != __end)
-                 __c = *__beg;
-               else
-                 __testeof = true;
-             }
-         }
+       if (!__lc->_M_allocated)
+         // "C" locale
+         while (!__testeof)
+           {
+             __digit = _M_find(__lit_zero, __len, __c);
+             if (__digit == -1)
+               break;
+             
+             if (__result > __smax)
+               __testfail = true;
+             else
+               {
+                 __result *= __base;
+                 __testfail |= __result > __max - __digit;
+                 __result += __digit;
+                 ++__sep_pos;
+               }
+             
+             if (++__beg != __end)
+               __c = *__beg;
+             else
+               __testeof = true;
+           }
        else
-         {
-           const _ValueT __max = numeric_limits<_ValueT>::max() / __base;
-           while (!__testeof)
-             {
-               if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
-                 {
-                   if (__sep_pos)
-                     {
-                       __found_grouping += static_cast<char>(__sep_pos);
-                       __sep_pos = 0;
-                     }
-                   else
-                     {
-                       __err |= ios_base::failbit;
-                       break;
-                     }
-                 }
-               else if (__c == __lc->_M_decimal_point)
-                 break;
-               else if ((__q = __traits_type::find(__lit_zero, __len, __c)))
-                 {
-                   int __digit = __q - __lit_zero;
-                   if (__digit > 15)
-                     __digit -= 6;
-                   if (__result > __max)
-                     __overflow = true;
-                   else
-                     {
-                       const _ValueT __new_result = (__result * __base
-                                                     + __digit);
-                       __overflow |= __new_result < __result;
-                       __result = __new_result;
-                       ++__sep_pos;
-                     }
-                 }
-               else
-                 break;
-
-               if (++__beg != __end)
-                 __c = *__beg;
-               else
-                 __testeof = true;
-             }
-         }
-
+         while (!__testeof)
+           {
+             // According to 22.2.2.1.2, p8-9, first look for thousands_sep
+             // and decimal_point.
+             if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
+               {
+                 // NB: Thousands separator at the beginning of a string
+                 // is a no-no, as is two consecutive thousands separators.
+                 if (__sep_pos)
+                   {
+                     __found_grouping += static_cast<char>(__sep_pos);
+                     __sep_pos = 0;
+                   }
+                 else
+                   {
+                     __testfail = true;
+                     break;
+                   }
+               }
+             else if (__c == __lc->_M_decimal_point)
+               break;
+             else
+               {
+                 const char_type* __q =
+                   __traits_type::find(__lit_zero, __len, __c);
+                 if (!__q)
+                   break;
+                 
+                 __digit = __q - __lit_zero;
+                 if (__digit > 15)
+                   __digit -= 6;
+                 if (__result > __smax)
+                   __testfail = true;
+                 else
+                   {
+                     __result *= __base;
+                     __testfail |= __result > __max - __digit;
+                     __result += __digit;
+                     ++__sep_pos;
+                   }
+               }
+             
+             if (++__beg != __end)
+               __c = *__beg;
+             else
+               __testeof = true;
+           }
+       
        // Digit grouping is checked. If grouping and found_grouping don't
        // match, then get very very upset, and set failbit.
        if (__found_grouping.size())
@@ -648,9 +698,9 @@ namespace std
              __err |= ios_base::failbit;
          }
 
-       if (!(__err & ios_base::failbit) && !__overflow
-           && (__sep_pos || __found_zero || __found_grouping.size()))
-         __v = __result;
+       if (!__testfail && (__sep_pos || __found_zero 
+                           || __found_grouping.size()))
+         __v = __negative ? -__result : __result;
        else
          __err |= ios_base::failbit;
 
@@ -682,7 +732,7 @@ namespace std
       else
         {
          // Parse bool values as alphanumeric.
-         typedef typename numpunct<_CharT>::__cache_type __cache_type;
+         typedef __numpunct_cache<_CharT>              __cache_type;
          __use_cache<__cache_type> __uc;
          const locale& __loc = __io._M_getloc();
          const __cache_type* __lc = __uc(__loc);
@@ -796,6 +846,21 @@ namespace std
       return __beg;
     }
 
+#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
+  template<typename _CharT, typename _InIter>
+    _InIter
+    num_get<_CharT, _InIter>::
+    __do_get(iter_type __beg, iter_type __end, ios_base& __io,
+            ios_base::iostate& __err, double& __v) const
+    {
+      string __xtrc;
+      __xtrc.reserve(32);
+      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
+      std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
+      return __beg;
+    }
+#endif
+
   template<typename _CharT, typename _InIter>
     _InIter
     num_get<_CharT, _InIter>::
@@ -846,54 +911,15 @@ namespace std
       __len = static_cast<int>(__w);
     }
 
-  // Forwarding functions to peel signed from unsigned integer types.
-  template<typename _CharT>
-    inline int
-    __int_to_char(_CharT* __bufend, long __v, const _CharT* __lit,
-                 ios_base::fmtflags __flags)
-    {
-      unsigned long __ul = static_cast<unsigned long>(__v);
-      if (__v < 0)
-       __ul = -__ul;
-      return __int_to_char(__bufend, __ul, __lit, __flags, false);
-    }
-
-  template<typename _CharT>
-    inline int
-    __int_to_char(_CharT* __bufend, unsigned long __v, const _CharT* __lit,
-                 ios_base::fmtflags __flags)
-    { return __int_to_char(__bufend, __v, __lit, __flags, false); }
+_GLIBCXX_END_LDBL_NAMESPACE
 
-#ifdef _GLIBCXX_USE_LONG_LONG
-  template<typename _CharT>
-    inline int
-    __int_to_char(_CharT* __bufend, long long __v, const _CharT* __lit,
-                 ios_base::fmtflags __flags)
-    {
-      unsigned long long __ull = static_cast<unsigned long long>(__v);
-      if (__v < 0)
-       __ull = -__ull;
-      return __int_to_char(__bufend, __ull, __lit, __flags, false);
-    }
-
-  template<typename _CharT>
-    inline int
-    __int_to_char(_CharT* __bufend, unsigned long long __v, 
-                 const _CharT* __lit, ios_base::fmtflags __flags)
-    { return __int_to_char(__bufend, __v, __lit, __flags, false); }
-#endif
-
-  // N.B. The last argument is currently unused (see libstdc++/20914).
   template<typename _CharT, typename _ValueT>
     int
     __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
-                 ios_base::fmtflags __flags, bool)
+                 ios_base::fmtflags __flags, bool __dec)
     {
-      const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
       _CharT* __buf = __bufend;
-
-      if (__builtin_expect(__basefield != ios_base::oct
-                          && __basefield != ios_base::hex, true))
+      if (__builtin_expect(__dec, true))
        {
          // Decimal.
          do
@@ -903,7 +929,7 @@ namespace std
            }
          while (__v != 0);
        }
-      else if (__basefield == ios_base::oct)
+      else if ((__flags & ios_base::basefield) == ios_base::oct)
        {
          // Octal.
          do
@@ -929,6 +955,8 @@ namespace std
       return __bufend - __buf;
     }
 
+_GLIBCXX_BEGIN_LDBL_NAMESPACE
+
   template<typename _CharT, typename _OutIter>
     void
     num_put<_CharT, _OutIter>::
@@ -947,7 +975,9 @@ namespace std
       _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill,
                    _ValueT __v) const
       {
-       typedef typename numpunct<_CharT>::__cache_type __cache_type;
+       using __gnu_cxx::__add_unsigned;
+       typedef typename __add_unsigned<_ValueT>::__type __unsigned_type;
+       typedef __numpunct_cache<_CharT>                     __cache_type;
        __use_cache<__cache_type> __uc;
        const locale& __loc = __io._M_getloc();
        const __cache_type* __lc = __uc(__loc);
@@ -961,7 +991,11 @@ namespace std
 
        // [22.2.2.2.2] Stage 1, numeric conversion to character.
        // Result is returned right-justified in the buffer.
-       int __len = __int_to_char(__cs + __ilen, __v, __lit, __flags);
+       const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
+       const bool __dec = (__basefield != ios_base::oct
+                           && __basefield != ios_base::hex);
+       const __unsigned_type __u = (__v > 0 || !__dec) ? __v : -__v;
+       int __len = __int_to_char(__cs + __ilen, __u, __lit, __flags, __dec);
        __cs += __ilen - __len;
 
        // Add grouping, if necessary.
@@ -978,9 +1012,7 @@ namespace std
          }
 
        // Complete Stage 1, prepend numeric base or sign.
-       const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
-       if (__builtin_expect(__basefield != ios_base::oct
-                            && __basefield != ios_base::hex, true))
+       if (__builtin_expect(__dec, true))
          {
            // Decimal.
            if (__v > 0)
@@ -992,16 +1024,11 @@ namespace std
            else if (__v)
              *--__cs = __lit[__num_base::_S_ominus], ++__len;
          }
-       else if (__basefield == ios_base::oct)
+       else if (__flags & ios_base::showbase && __v)
          {
-           // Octal.
-           if (__flags & ios_base::showbase && __v)
+           if (__basefield == ios_base::oct)
              *--__cs = __lit[__num_base::_S_odigits], ++__len;
-         }
-       else
-         {
-           // Hex.
-           if (__flags & ios_base::showbase && __v)
+           else
              {
                // 'x' or 'X'
                const bool __uppercase = __flags & ios_base::uppercase;
@@ -1053,7 +1080,7 @@ namespace std
       __len = __newlen;
     }
 
-  // The following code uses snprintf (or sprintf(), when
+  // The following code uses vsnprintf (or vsprintf(), when
   // _GLIBCXX_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
@@ -1070,15 +1097,13 @@ namespace std
       _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
                       _ValueT __v) const
       {
-       typedef typename numpunct<_CharT>::__cache_type __cache_type;
+       typedef __numpunct_cache<_CharT>                __cache_type;
        __use_cache<__cache_type> __uc;
        const locale& __loc = __io._M_getloc();
        const __cache_type* __lc = __uc(__loc);
 
        // Use default precision if out of range.
-       streamsize __prec = __io.precision();
-       if (__prec < static_cast<streamsize>(0))
-         __prec = static_cast<streamsize>(6);
+       const streamsize __prec = __io.precision() < 0 ? 6 : __io.precision();
 
        const int __max_digits = numeric_limits<_ValueT>::digits10;
 
@@ -1086,24 +1111,23 @@ namespace std
        int __len;
        // Long enough for the max format spec.
        char __fbuf[16];
+       __num_base::_S_format_float(__io, __fbuf, __mod);
 
 #ifdef _GLIBCXX_USE_C99
        // First try a buffer perhaps big enough (most probably sufficient
        // for non-ios_base::fixed outputs)
        int __cs_size = __max_digits * 3;
        char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
-
-       __num_base::_S_format_float(__io, __fbuf, __mod);
-       __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
-                                     _S_get_c_locale(), __prec);
+       __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+                                     __fbuf, __prec, __v);
 
        // 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 = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
-                                         _S_get_c_locale(), __prec);
+           __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+                                         __fbuf, __prec, __v);
          }
 #else
        // Consider the possibility of long ios_base::fixed outputs
@@ -1119,10 +1143,8 @@ namespace std
        const int __cs_size = __fixed ? __max_exp + __prec + 4
                                      : __max_digits * 2 + __prec;
        char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
-
-       __num_base::_S_format_float(__io, __fbuf, __mod);
-       __len = std::__convert_from_v(__cs, 0, __fbuf, __v,
-                                     _S_get_c_locale(), __prec);
+       __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, __fbuf, 
+                                     __prec, __v);
 #endif
 
        // [22.2.2.2.2] Stage 2, convert to char_type, using correct
@@ -1134,18 +1156,20 @@ namespace std
        __ctype.widen(__cs, __cs + __len, __ws);
        
        // Replace decimal point.
-       const _CharT __cdec = __ctype.widen('.');
-       const _CharT __dec = __lc->_M_decimal_point;
-       const _CharT* __p = char_traits<_CharT>::find(__ws, __len, __cdec);
+       _CharT* __wp = 0;
+       const char* __p = char_traits<char>::find(__cs, __len, '.');
        if (__p)
-         __ws[__p - __ws] = __dec;
+         {
+           __wp = __ws + (__p - __cs);
+           *__wp = __lc->_M_decimal_point;
+         }
        
        // Add grouping, if necessary.
        // N.B. Make sure to not group things like 2e20, i.e., no decimal
        // point, scientific notation.
        if (__lc->_M_use_grouping
-           && (__p || __len < 3 || (__cs[1] <= '9' && __cs[2] <= '9'
-                                    && __cs[1] >= '0' && __cs[2] >= '0')))
+           && (__wp || __len < 3 || (__cs[1] <= '9' && __cs[2] <= '9'
+                                     && __cs[1] >= '0' && __cs[2] >= '0')))
          {
            // Grouping can add (almost) as many separators as the
            // number of digits, but no more.
@@ -1161,7 +1185,7 @@ namespace std
              }
            
            _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size,
-                          __lc->_M_thousands_sep, __p, __ws2 + __off,
+                          __lc->_M_thousands_sep, __wp, __ws2 + __off,
                           __ws + __off, __len);
            __len += __off;
            
@@ -1197,7 +1221,7 @@ namespace std
         }
       else
         {
-         typedef typename numpunct<_CharT>::__cache_type __cache_type;
+         typedef __numpunct_cache<_CharT>              __cache_type;
          __use_cache<__cache_type> __uc;
          const locale& __loc = __io._M_getloc();
          const __cache_type* __lc = __uc(__loc);
@@ -1239,8 +1263,8 @@ namespace std
   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_insert_int(__s, __b, __fill, __v); }
+    do_put(iter_type __s, ios_base& __io, char_type __fill, long long __v) const
+    { return _M_insert_int(__s, __io, __fill, __v); }
 
   template<typename _CharT, typename _OutIter>
     _OutIter
@@ -1256,6 +1280,14 @@ namespace std
     do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
     { return _M_insert_float(__s, __io, __fill, char(), __v); }
 
+#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
+  template<typename _CharT, typename _OutIter>
+    _OutIter
+    num_put<_CharT, _OutIter>::
+    __do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
+    { return _M_insert_float(__s, __io, __fill, char(), __v); }
+#endif
+
   template<typename _CharT, typename _OutIter>
     _OutIter
     num_put<_CharT, _OutIter>::
@@ -1291,8 +1323,7 @@ namespace std
        typedef char_traits<_CharT>                       __traits_type;
        typedef typename string_type::size_type           size_type;    
        typedef money_base::part                          part;
-       typedef moneypunct<_CharT, _Intl>                 __moneypunct_type;
-       typedef typename __moneypunct_type::__cache_type  __cache_type;
+       typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
        
        const locale& __loc = __io._M_getloc();
        const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
@@ -1477,7 +1508,7 @@ namespace std
                if (!std::__verify_grouping(__lc->_M_grouping,
                                            __lc->_M_grouping_size,
                                            __grouping_tmp))
-                 __testvalid = false;
+                 __err |= ios_base::failbit;
              }
            
            // Iff not enough digits were supplied after the decimal-point.
@@ -1498,6 +1529,23 @@ namespace std
        return __beg;
       }
 
+#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
+  template<typename _CharT, typename _InIter>
+    _InIter
+    money_get<_CharT, _InIter>::
+    __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
+            ios_base::iostate& __err, double& __units) const
+    {
+      string __str;
+      if (__intl)
+       __beg = _M_extract<true>(__beg, __end, __io, __err, __str);
+      else
+       __beg = _M_extract<false>(__beg, __end, __io, __err, __str);
+      std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
+      return __beg;
+    }
+#endif
+
   template<typename _CharT, typename _InIter>
     _InIter
     money_get<_CharT, _InIter>::
@@ -1550,8 +1598,7 @@ namespace std
       {
        typedef typename string_type::size_type           size_type;
        typedef money_base::part                          part;
-       typedef moneypunct<_CharT, _Intl>                 __moneypunct_type;
-       typedef typename __moneypunct_type::__cache_type  __cache_type;
+       typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
       
        const locale& __loc = __io._M_getloc();
        const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
@@ -1567,7 +1614,7 @@ namespace std
        money_base::pattern __p;
        const char_type* __sign;
        size_type __sign_size;
-       if (*__beg != __lit[money_base::_S_minus])
+       if (!(*__beg == __lit[money_base::_S_minus]))
          {
            __p = __lc->_M_pos_format;
            __sign = __lc->_M_positive_sign;
@@ -1703,7 +1750,18 @@ namespace std
        __io.width(0);
        return __s;    
       }
-  
+
+#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
+  template<typename _CharT, typename _OutIter>
+    _OutIter
+    money_put<_CharT, _OutIter>::
+    __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
+            double __units) const
+    {
+      return this->do_put(__s, __intl, __io, __fill, (long double) __units);
+    }
+#endif
+
   template<typename _CharT, typename _OutIter>
     _OutIter
     money_put<_CharT, _OutIter>::
@@ -1718,22 +1776,22 @@ namespace std
       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // 328. Bad sprintf format modifier in money_put<>::do_put()
-      int __len = std::__convert_from_v(__cs, __cs_size, "%.*Lf", __units,
-                                       _S_get_c_locale(), 0);
+      int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+                                       "%.*Lf", 0, __units);
       // 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 = std::__convert_from_v(__cs, __cs_size, "%.*Lf", __units,
-                                       _S_get_c_locale(), 0);
+         __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+                                       "%.*Lf", 0, __units);
        }
 #else
       // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
       const int __cs_size = numeric_limits<long double>::max_exponent10 + 3;
       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
-      int __len = std::__convert_from_v(__cs, 0, "%.*Lf", __units,
-                                       _S_get_c_locale(), 0);
+      int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf", 
+                                       0, __units);
 #endif
       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
                                                           * __cs_size));
@@ -1751,6 +1809,7 @@ namespace std
     { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
                    : _M_insert<false>(__s, __io, __fill, __digits); }
 
+_GLIBCXX_END_LDBL_NAMESPACE
 
   // NB: Not especially useful. Without an ios_base object or some
   // kind of locale reference, we are left clawing at the air where
@@ -1774,7 +1833,8 @@ namespace std
       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
       const size_t __len = char_traits<_CharT>::length(__format);
 
-      for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
+      ios_base::iostate __tmperr = ios_base::goodbit;
+      for (size_t __i = 0; __beg != __end && __i < __len && !__tmperr; ++__i)
        {
          if (__ctype.narrow(__format[__i], 0) == '%')
            {
@@ -1792,14 +1852,14 @@ namespace std
                  const char_type*  __days1[7];
                  __tp._M_days_abbreviated(__days1);
                  __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
-                                         7, __io, __err);
+                                         7, __io, __tmperr);
                  break;
                case 'A':
                  // Weekday name [tm_wday].
                  const char_type*  __days2[7];
                  __tp._M_days(__days2);
                  __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
-                                         7, __io, __err);
+                                         7, __io, __tmperr);
                  break;
                case 'h':
                case 'b':
@@ -1807,77 +1867,77 @@ namespace std
                  const char_type*  __months1[12];
                  __tp._M_months_abbreviated(__months1);
                  __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
-                                         __months1, 12, __io, __err);
+                                         __months1, 12, __io, __tmperr);
                  break;
                case 'B':
                  // Month name [tm_mon].
                  const char_type*  __months2[12];
                  __tp._M_months(__months2);
                  __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
-                                         __months2, 12, __io, __err);
+                                         __months2, 12, __io, __tmperr);
                  break;
                case 'c':
                  // Default time and date representation.
                  const char_type*  __dt[2];
                  __tp._M_date_time_formats(__dt);
-                 __beg = _M_extract_via_format(__beg, __end, __io, __err, 
+                 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
                                                __tm, __dt[0]);
                  break;
                case 'd':
                  // Day [01, 31]. [tm_mday]
                  __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
-                                        __io, __err);
+                                        __io, __tmperr);
                  break;
                case 'e':
                  // Day [1, 31], with single digits preceded by
                  // space. [tm_mday]
                  if (__ctype.is(ctype_base::space, *__beg))
                    __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
-                                          1, __io, __err);
+                                          1, __io, __tmperr);
                  else
                    __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
-                                          2, __io, __err);
+                                          2, __io, __tmperr);
                  break;
                case 'D':
                  // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
                  __cs = "%m/%d/%y";
                  __ctype.widen(__cs, __cs + 9, __wcs);
-                 __beg = _M_extract_via_format(__beg, __end, __io, __err, 
+                 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
                                                __tm, __wcs);
                  break;
                case 'H':
                  // Hour [00, 23]. [tm_hour]
                  __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
-                                        __io, __err);
+                                        __io, __tmperr);
                  break;
                case 'I':
                  // Hour [01, 12]. [tm_hour]
                  __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
-                                        __io, __err);
+                                        __io, __tmperr);
                  break;
                case 'm':
                  // Month [01, 12]. [tm_mon]
                  __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 
-                                        __io, __err);
-                 if (!__err)
+                                        __io, __tmperr);
+                 if (!__tmperr)
                    __tm->tm_mon = __mem - 1;
                  break;
                case 'M':
                  // Minute [00, 59]. [tm_min]
                  __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
-                                        __io, __err);
+                                        __io, __tmperr);
                  break;
                case 'n':
                  if (__ctype.narrow(*__beg, 0) == '\n')
                    ++__beg;
                  else
-                   __err |= ios_base::failbit;
+                   __tmperr |= ios_base::failbit;
                  break;
                case 'R':
                  // Equivalent to (%H:%M).
                  __cs = "%H:%M";
                  __ctype.widen(__cs, __cs + 6, __wcs);
-                 __beg = _M_extract_via_format(__beg, __end, __io, __err, 
+                 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
                                                __tm, __wcs);
                  break;
                case 'S':
@@ -1888,46 +1948,46 @@ namespace std
 #else
                  __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
 #endif
-                                        __io, __err);
+                                        __io, __tmperr);
                  break;
                case 't':
                  if (__ctype.narrow(*__beg, 0) == '\t')
                    ++__beg;
                  else
-                   __err |= ios_base::failbit;
+                   __tmperr |= ios_base::failbit;
                  break;
                case 'T':
                  // Equivalent to (%H:%M:%S).
                  __cs = "%H:%M:%S";
                  __ctype.widen(__cs, __cs + 9, __wcs);
-                 __beg = _M_extract_via_format(__beg, __end, __io, __err, 
+                 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
                                                __tm, __wcs);
                  break;
                case 'x':
                  // Locale's date.
                  const char_type*  __dates[2];
                  __tp._M_date_formats(__dates);
-                 __beg = _M_extract_via_format(__beg, __end, __io, __err, 
+                 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
                                                __tm, __dates[0]);
                  break;
                case 'X':
                  // Locale's time.
                  const char_type*  __times[2];
                  __tp._M_time_formats(__times);
-                 __beg = _M_extract_via_format(__beg, __end, __io, __err, 
+                 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
                                                __tm, __times[0]);
                  break;
                case 'y':
                case 'C': // C99
                  // Two digit year. [tm_year]
                  __beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
-                                        __io, __err);
+                                        __io, __tmperr);
                  break;
                case 'Y':
                  // Year [1900). [tm_year]
                  __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
-                                        __io, __err);
-                 if (!__err)
+                                        __io, __tmperr);
+                 if (!__tmperr)
                    __tm->tm_year = __mem - 1900;
                  break;
                case 'Z':
@@ -1937,25 +1997,25 @@ namespace std
                      int __tmp;
                      __beg = _M_extract_name(__beg, __end, __tmp,
                                       __timepunct_cache<_CharT>::_S_timezones,
-                                             14, __io, __err);
+                                             14, __io, __tmperr);
 
                      // GMT requires special effort.
-                     if (__beg != __end && !__err && __tmp == 0
+                     if (__beg != __end && !__tmperr && __tmp == 0
                          && (*__beg == __ctype.widen('-')
                              || *__beg == __ctype.widen('+')))
                        {
                          __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
-                                                __io, __err);
+                                                __io, __tmperr);
                          __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
-                                                __io, __err);
+                                                __io, __tmperr);
                        }
                    }
                  else
-                   __err |= ios_base::failbit;
+                   __tmperr |= ios_base::failbit;
                  break;
                default:
                  // Not recognized.
-                 __err |= ios_base::failbit;
+                 __tmperr |= ios_base::failbit;
                }
            }
          else
@@ -1964,9 +2024,13 @@ namespace std
              if (__format[__i] == *__beg)
                ++__beg;
              else
-               __err |= ios_base::failbit;
+               __tmperr |= ios_base::failbit;
            }
        }
+
+      if (__tmperr)
+       __err |= ios_base::failbit;
+  
       return __beg;
     }
 
@@ -2004,6 +2068,7 @@ namespace std
        __member = __value;
       else
        __err |= ios_base::failbit;
+
       return __beg;
     }
 
@@ -2052,7 +2117,7 @@ namespace std
            for (size_t __i3 = 0; __i3 < __nmatches;)
              {
                __name = __names[__matches[__i3]];
-               if (__name[__pos] != *__beg)
+               if (!(__name[__pos] == *__beg))
                  __matches[__i3] = __matches[--__nmatches];
                else
                  ++__i3;
@@ -2079,6 +2144,7 @@ namespace std
        __testvalid = false;
       if (!__testvalid)
        __err |= ios_base::failbit;
+
       return __beg;
     }
 
@@ -2129,7 +2195,9 @@ namespace std
       const char_type*  __days[7];
       __tp._M_days_abbreviated(__days);
       int __tmpwday;
-      __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7, __io, __err);
+      ios_base::iostate __tmperr = ios_base::goodbit;
+      __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7,
+                             __io, __tmperr);
 
       // Check to see if non-abbreviated name exists, and extract.
       // NB: Assumes both _M_days and _M_days_abbreviated organized in
@@ -2137,7 +2205,7 @@ namespace std
       // __days array with the same index points to a day, and that
       // day's abbreviated form.
       // NB: Also assumes that an abbreviated name is a subset of the name.
-      if (!__err && __beg != __end)
+      if (!__tmperr && __beg != __end)
        {
          size_t __pos = __traits_type::length(__days[__tmpwday]);
          __tp._M_days(__days);
@@ -2150,12 +2218,14 @@ namespace std
                     && __name[__pos] == *__beg)
                ++__beg, ++__pos;
              if (__len != __pos)
-               __err |= ios_base::failbit;
+               __tmperr |= ios_base::failbit;
            }
        }
-      if (!__err)
+      if (!__tmperr)
        __tm->tm_wday = __tmpwday;
-      
+      else
+       __err |= ios_base::failbit;
+
       if (__beg == __end)
        __err |= ios_base::eofbit;
       return __beg;
@@ -2174,8 +2244,9 @@ namespace std
       const char_type*  __months[12];
       __tp._M_months_abbreviated(__months);
       int __tmpmon;
+      ios_base::iostate __tmperr = ios_base::goodbit;
       __beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12, 
-                             __io, __err);
+                             __io, __tmperr);
 
       // Check to see if non-abbreviated name exists, and extract.
       // NB: Assumes both _M_months and _M_months_abbreviated organized in
@@ -2183,7 +2254,7 @@ namespace std
       // __months array with the same index points to a month, and that
       // month's abbreviated form.
       // NB: Also assumes that an abbreviated name is a subset of the name.
-      if (!__err && __beg != __end)
+      if (!__tmperr && __beg != __end)
        {
          size_t __pos = __traits_type::length(__months[__tmpmon]);
          __tp._M_months(__months);
@@ -2196,11 +2267,13 @@ namespace std
                     && __name[__pos] == *__beg)
                ++__beg, ++__pos;
              if (__len != __pos)
-               __err |= ios_base::failbit;
+               __tmperr |= ios_base::failbit;
            }
        }
-      if (!__err)
+      if (!__tmperr)
        __tm->tm_mon = __tmpmon;
+      else
+       __err |= ios_base::failbit;
 
       if (__beg == __end)
        __err |= ios_base::eofbit;
@@ -2230,6 +2303,7 @@ namespace std
        __tm->tm_year = __i == 2 ? __value : __value - 1900;
       else
        __err |= ios_base::failbit;
+
       if (__beg == __end)
        __err |= ios_base::eofbit;
       return __beg;
@@ -2367,43 +2441,55 @@ namespace std
     collate<_CharT>::
     do_transform(const _CharT* __lo, const _CharT* __hi) const
     {
+      string_type __ret;
+
       // strxfrm assumes zero-terminated strings so we make a copy
-      string_type __str(__lo, __hi);
+      const string_type __str(__lo, __hi);
 
       const _CharT* __p = __str.c_str();
       const _CharT* __pend = __str.data() + __str.length();
 
       size_t __len = (__hi - __lo) * 2;
 
-      string_type __ret;
+      _CharT* __c = new _CharT[__len];
 
-      // strxfrm stops when it sees a nul character so we break
-      // the string into zero-terminated substrings and pass those
-      // to strxfrm.
-      for (;;)
+      try
        {
-         // First try a buffer perhaps big enough.
-         _CharT* __c =
-           static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
-         size_t __res = _M_transform(__c, __p, __len);
-         // If the buffer was not large enough, try again with the
-         // correct size.
-         if (__res >= __len)
+         // strxfrm stops when it sees a nul character so we break
+         // the string into zero-terminated substrings and pass those
+         // to strxfrm.
+         for (;;)
            {
-             __len = __res + 1;
-             __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
-                                                         * __len));
-             __res = _M_transform(__c, __p, __len);
-           }
+             // First try a buffer perhaps big enough.
+             size_t __res = _M_transform(__c, __p, __len);
+             // If the buffer was not large enough, try again with the
+             // correct size.
+             if (__res >= __len)
+               {
+                 __len = __res + 1;
+                 delete [] __c, __c = 0;
+                 __c = new _CharT[__len];
+                 __res = _M_transform(__c, __p, __len);
+               }
 
-         __ret.append(__c, __res);
-         __p += char_traits<_CharT>::length(__p);
-         if (__p == __pend)
-           return __ret;
+             __ret.append(__c, __res);
+             __p += char_traits<_CharT>::length(__p);
+             if (__p == __pend)
+               break;
 
-         __p++;
-         __ret.push_back(_CharT());
+             __p++;
+             __ret.push_back(_CharT());
+           }
+       }
+      catch(...)
+       {
+         delete [] __c;
+         __throw_exception_again;
        }
+
+      delete [] __c;
+
+      return __ret;
     }
 
   template<typename _CharT>
@@ -2498,9 +2584,11 @@ namespace std
       __test = __grouping_tmp[__i] == __grouping[__j];
     for (; __i && __test; --__i)
       __test = __grouping_tmp[__i] == __grouping[__min];
-    // ... but the last parsed grouping can be <= numpunct
-    // grouping.
-    __test &= __grouping_tmp[0] <= __grouping[__min];
+    // ... but the first parsed grouping can be <= numpunct
+    // grouping (only do the check if the numpunct char is > 0
+    // because <= 0 means any size is ok).
+    if (static_cast<signed char>(__grouping[__min]) > 0)
+      __test &= __grouping_tmp[0] <= __grouping[__min];
     return __test;
   }
 
@@ -2510,7 +2598,8 @@ namespace std
                   const char* __gbeg, size_t __gsize,
                   const _CharT* __first, const _CharT* __last)
     {
-      if (__last - __first > *__gbeg)
+      if (__last - __first > *__gbeg
+         && static_cast<signed char>(*__gbeg) > 0)
        {
          const bool __bump = __gsize != 1;
          __s = std::__add_grouping(__s,  __sep, __gbeg + __bump,
@@ -2533,12 +2622,12 @@ namespace std
   extern template class moneypunct<char, true>;
   extern template class moneypunct_byname<char, false>;
   extern template class moneypunct_byname<char, true>;
-  extern template class money_get<char>;
-  extern template class money_put<char>;
+  extern template class _GLIBCXX_LDBL_NAMESPACE money_get<char>;
+  extern template class _GLIBCXX_LDBL_NAMESPACE money_put<char>;
   extern template class numpunct<char>;
   extern template class numpunct_byname<char>;
-  extern template class num_get<char>;
-  extern template class num_put<char>;
+  extern template class _GLIBCXX_LDBL_NAMESPACE num_get<char>;
+  extern template class _GLIBCXX_LDBL_NAMESPACE num_put<char>;
   extern template class __timepunct<char>;
   extern template class time_put<char>;
   extern template class time_put_byname<char>;
@@ -2660,12 +2749,12 @@ namespace std
   extern template class moneypunct<wchar_t, true>;
   extern template class moneypunct_byname<wchar_t, false>;
   extern template class moneypunct_byname<wchar_t, true>;
-  extern template class money_get<wchar_t>;
-  extern template class money_put<wchar_t>;
+  extern template class _GLIBCXX_LDBL_NAMESPACE money_get<wchar_t>;
+  extern template class _GLIBCXX_LDBL_NAMESPACE money_put<wchar_t>;
   extern template class numpunct<wchar_t>;
   extern template class numpunct_byname<wchar_t>;
-  extern template class num_get<wchar_t>;
-  extern template class num_put<wchar_t>;
+  extern template class _GLIBCXX_LDBL_NAMESPACE num_get<wchar_t>;
+  extern template class _GLIBCXX_LDBL_NAMESPACE num_put<wchar_t>;
   extern template class __timepunct<wchar_t>;
   extern template class time_put<wchar_t>;
   extern template class time_put_byname<wchar_t>;
@@ -2783,6 +2872,7 @@ namespace std
     has_facet<messages<wchar_t> >(const locale&);
 #endif
 #endif
-} // namespace std
+
+_GLIBCXX_END_NAMESPACE
 
 #endif