From 4b9aaf6379db36f4ab90875a8aaef4e3c98269b7 Mon Sep 17 00:00:00 2001
From: Benjamin Kosnik <bkoz@redhat.com>
Date: Tue, 22 Jan 2002 23:09:04 +0000
Subject: [PATCH] Audit for LANG independence.

2002-01-22  Benjamin Kosnik  <bkoz@redhat.com>

	Audit for LANG independence.
	* include/bits/localefwd.h: Tweaks.
	* include/bits/locale_facets.tcc (money_get::do_get(long double)):
	Use __convert_to_v.
	(time_get::do_get_year): Same.
	(__convert_from_v): Add.
	(num_put::_M_convert_float): Use.
	(num_put::_M_convert_int): Same.
	(money_put::do_put): Same.

	* src/locale-inst.cc: Add instantiations for __convert_from_v.
	* config/locale/time_members_gnu.cc: Cleanup setlocale usage.
	* config/locale/time_members_generic.cc:
	* config/locale/messages_members_gnu.cc: Same.
	* config/locale/messages_members_gnu.h: Same.

	* testsuite/22_locale/codecvt_members_wchar_t_char.cc (test02): New.
	* testsuite/22_locale/codecvt_members_char_char.cc (test02): New.
	* testsuite/22_locale/collate_members_wchar_t.cc (test02): New.
	* testsuite/22_locale/collate_members_char.cc (test02): New.
	* testsuite/22_locale/ctype_members_wchar_t.cc (test03): New.
	* testsuite/22_locale/ctype_members_char.cc (test03): New.
	* testsuite/22_locale/messages_members_char.cc (test02): New.
	* testsuite/22_locale/moneypunct_members_wchar_t.cc (test02): New.
	* testsuite/22_locale/moneypunct_members_char.cc (test02): New.
	* testsuite/22_locale/money_get_members_wchar_t.cc (test04): New.
	* testsuite/22_locale/money_get_members_char.cc (test04): New.
	* testsuite/22_locale/money_put_members_wchar_t.cc (test04): New.
	* testsuite/22_locale/money_put_members_char.cc (test04): New.
	* testsuite/22_locale/numpunct_members_wchar_t.cc (test02): New.
	* testsuite/22_locale/numpunct_members_char.cc (test02): New.
	* testsuite/22_locale/time_put_members_wchar_t.cc (test03): New.
	* testsuite/22_locale/time_put_members_char.cc (test03): New.
	* testsuite/22_locale/time_get_members_wchar_t.cc (test07): New.
	* testsuite/22_locale/time_get_members_char.cc (test07): New.
	* testsuite/22_locale/num_get_members_wchar_t.cc (test03): New.
	* testsuite/22_locale/num_get_members_char.cc (test03): New.
	* testsuite/22_locale/num_put_members_wchar_t.cc (test03): New.
	* testsuite/22_locale/num_put_members_char.cc (test03): New.

	* testsuite/22_locale/time_get_members_char.cc: Fixups for global
	locale issues.
	* testsuite/22_locale/time_get_members_char.cc: Same.

2002-01-22  Benjamin Kosnik  <bkoz@redhat.com>

	libstdc++/5280
	* include/bits/localefwd.h: Tweak comments.
	* include/bits/locale_facets.h (__convert_to_v): Add.
	* include/bits/locale_facets.tcc (num_get::do_get(double)): Use it.
	(num_get::do_get(float)): Same.
	(num_get::do_get(long double)): Same.
	(num_get::do_get(bool)): Same.
	(num_get::do_get(long)): Same.
	(num_get::do_get(long long)): Same.
	(num_get::do_get(unsigned int)): Same.
	(num_get::do_get(unsigned short)): Same.
	(num_get::do_get(unsigned long)): Same.
	(num_get::do_get(unsigned long long)): Same.
	* config/locale/c_locale_gnu.cc (__convert_to_v): Specialize.
	* config/locale/c_locale_generic.cc: Same.

From-SVN: r49108
---
 libstdc++-v3/ChangeLog                        |  64 +++++
 .../config/locale/c_locale_generic.cc         | 145 +++++++++-
 libstdc++-v3/config/locale/c_locale_gnu.cc    | 126 ++++++++-
 .../config/locale/messages_members_gnu.cc     |   5 +-
 .../config/locale/messages_members_gnu.h      |   5 +-
 .../config/locale/numpunct_members_generic.cc |   2 +-
 .../config/locale/numpunct_members_gnu.cc     |   2 +-
 .../config/locale/time_members_generic.cc     |   8 +-
 .../config/locale/time_members_gnu.cc         |   8 +-
 libstdc++-v3/include/bits/locale_facets.h     |  15 +-
 libstdc++-v3/include/bits/locale_facets.tcc   | 254 ++++++------------
 libstdc++-v3/include/bits/localefwd.h         |  24 +-
 libstdc++-v3/src/locale-inst.cc               |  28 +-
 .../22_locale/codecvt_members_char_char.cc    |  20 +-
 .../22_locale/codecvt_members_wchar_t_char.cc |  19 +-
 .../22_locale/collate_members_char.cc         |  20 +-
 .../22_locale/collate_members_wchar_t.cc      |  19 +-
 .../testsuite/22_locale/ctype_members_char.cc |  19 +-
 .../22_locale/ctype_members_wchar_t.cc        |  19 +-
 .../22_locale/messages_members_char.cc        |  21 +-
 .../22_locale/money_get_members_char.cc       |  19 ++
 .../22_locale/money_get_members_wchar_t.cc    |  19 ++
 .../22_locale/money_put_members_char.cc       |  19 ++
 .../22_locale/money_put_members_wchar_t.cc    |  19 ++
 .../22_locale/moneypunct_members_char.cc      |  20 +-
 .../22_locale/moneypunct_members_wchar_t.cc   |  19 +-
 .../22_locale/num_get_members_char.cc         |  18 ++
 .../22_locale/num_get_members_wchar_t.cc      |  18 ++
 .../22_locale/num_put_members_char.cc         |  20 ++
 .../22_locale/num_put_members_wchar_t.cc      |  19 ++
 .../22_locale/numpunct_members_char.cc        |  20 +-
 .../22_locale/numpunct_members_wchar_t.cc     |  19 +-
 .../22_locale/time_get_members_char.cc        |  27 ++
 .../22_locale/time_get_members_wchar_t.cc     |  27 ++
 .../22_locale/time_put_members_char.cc        |  18 ++
 .../22_locale/time_put_members_wchar_t.cc     |  18 ++
 36 files changed, 915 insertions(+), 227 deletions(-)

diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index b1b5e8e16840..d039be95c084 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,67 @@
+2002-01-22  Benjamin Kosnik  <bkoz@redhat.com>
+
+	Audit for LANG independence.
+	* include/bits/localefwd.h: Tweaks.
+	* include/bits/locale_facets.tcc (money_get::do_get(long double)):
+	Use __convert_to_v.
+	(time_get::do_get_year): Same.
+	(__convert_from_v): Add.
+	(num_put::_M_convert_float): Use.
+	(num_put::_M_convert_int): Same.
+	(money_put::do_put): Same.
+	
+	* src/locale-inst.cc: Add instantiations for __convert_from_v.
+	* config/locale/time_members_gnu.cc: Cleanup setlocale usage.
+	* config/locale/time_members_generic.cc: 
+	* config/locale/messages_members_gnu.cc: Same.
+	* config/locale/messages_members_gnu.h: Same.
+	
+	* testsuite/22_locale/codecvt_members_wchar_t_char.cc (test02): New.
+	* testsuite/22_locale/codecvt_members_char_char.cc (test02): New.
+	* testsuite/22_locale/collate_members_wchar_t.cc (test02): New.
+	* testsuite/22_locale/collate_members_char.cc (test02): New.
+	* testsuite/22_locale/ctype_members_wchar_t.cc (test03): New.
+	* testsuite/22_locale/ctype_members_char.cc (test03): New.
+	* testsuite/22_locale/messages_members_char.cc (test02): New.
+	* testsuite/22_locale/moneypunct_members_wchar_t.cc (test02): New.
+	* testsuite/22_locale/moneypunct_members_char.cc (test02): New.
+	* testsuite/22_locale/money_get_members_wchar_t.cc (test04): New.
+	* testsuite/22_locale/money_get_members_char.cc (test04): New.
+	* testsuite/22_locale/money_put_members_wchar_t.cc (test04): New.
+	* testsuite/22_locale/money_put_members_char.cc (test04): New.
+	* testsuite/22_locale/numpunct_members_wchar_t.cc (test02): New.
+	* testsuite/22_locale/numpunct_members_char.cc (test02): New.
+	* testsuite/22_locale/time_put_members_wchar_t.cc (test03): New.
+	* testsuite/22_locale/time_put_members_char.cc (test03): New.
+	* testsuite/22_locale/time_get_members_wchar_t.cc (test07): New.
+	* testsuite/22_locale/time_get_members_char.cc (test07): New.
+	* testsuite/22_locale/num_get_members_wchar_t.cc (test03): New.
+	* testsuite/22_locale/num_get_members_char.cc (test03): New.
+	* testsuite/22_locale/num_put_members_wchar_t.cc (test03): New.
+	* testsuite/22_locale/num_put_members_char.cc (test03): New.
+
+	* testsuite/22_locale/time_get_members_char.cc: Fixups for global
+	locale issues.
+	* testsuite/22_locale/time_get_members_char.cc: Same.
+	
+2002-01-22  Benjamin Kosnik  <bkoz@redhat.com>
+
+	libstdc++/5280
+	* include/bits/localefwd.h: Tweak comments.
+	* include/bits/locale_facets.h (__convert_to_v): Add.
+	* include/bits/locale_facets.tcc (num_get::do_get(double)): Use it.
+	(num_get::do_get(float)): Same.
+	(num_get::do_get(long double)): Same.
+	(num_get::do_get(bool)): Same.
+	(num_get::do_get(long)): Same.
+	(num_get::do_get(long long)): Same.
+	(num_get::do_get(unsigned int)): Same.
+	(num_get::do_get(unsigned short)): Same.
+	(num_get::do_get(unsigned long)): Same.
+	(num_get::do_get(unsigned long long)): Same.
+	* config/locale/c_locale_gnu.cc (__convert_to_v): Specialize.
+	* config/locale/c_locale_generic.cc: Same.
+	
 2002-01-22  Loren Rittle <ljrittle@acm.org>
 
 	* include/Makefile.am (c_base_builddir): Remove redundant slash.
diff --git a/libstdc++-v3/config/locale/c_locale_generic.cc b/libstdc++-v3/config/locale/c_locale_generic.cc
index 46fdc2887a99..7133cd33edb3 100644
--- a/libstdc++-v3/config/locale/c_locale_generic.cc
+++ b/libstdc++-v3/config/locale/c_locale_generic.cc
@@ -1,6 +1,6 @@
 // Wrapper for underlying C-language localization -*- C++ -*-
 
-// Copyright (C) 2001 Free Software Foundation, Inc.
+// Copyright (C) 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
@@ -37,6 +37,149 @@
 
 namespace std 
 {
+  // Specializations for all types used in num_get.
+  template<>
+    void
+    __convert_to_v(const char* __s, long& __v, ios_base::iostate& __err, 
+		   const __c_locale&, int __base)
+    {
+      if (!(__err & ios_base::failbit))
+      {
+	char* __sanity;
+	errno = 0;
+	long __l = strtol(__s, &__sanity, __base);
+	if (__sanity != __s && *__sanity == '\0' && errno == 0)
+	  __v = __l;
+	else
+	  __err |= ios_base::failbit;
+      }
+    }
+
+  template<>
+    void
+    __convert_to_v(const char* __s, unsigned long& __v, 
+		   ios_base::iostate& __err, const __c_locale&, int __base)
+    {
+      if (!(__err & ios_base::failbit))
+	{
+	  char* __sanity;
+	  errno = 0;
+	  unsigned long __ul = strtoul(__s, &__sanity, __base);
+          if (__sanity != __s && *__sanity == '\0' && errno == 0)
+	    __v = __ul;
+	  else
+	    __err |= ios_base::failbit;
+	}
+    }
+
+#ifdef _GLIBCPP_USE_LONG_LONG
+  template<>
+    void
+    __convert_to_v(const char* __s, long long& __v, ios_base::iostate& __err, 
+		   const __c_locale&, int __base)
+    {
+      if (!(__err & ios_base::failbit))
+	{
+	  char* __sanity;
+	  errno = 0;
+	  long long __ll = strtoll(__s, &__sanity, __base);
+          if (__sanity != __s && *__sanity == '\0' && errno == 0)
+	    __v = __ll;
+	  else
+	    __err |= ios_base::failbit;
+	}
+    }
+
+  template<>
+    void
+    __convert_to_v(const char* __s, unsigned long long& __v, 
+		   ios_base::iostate& __err, const __c_locale&, int __base)
+    {
+      if (!(__err & ios_base::failbit))
+	{      
+	  char* __sanity;
+	  errno = 0;
+	  unsigned long long __ull = strtoull(__s, &__sanity, __base);
+          if (__sanity != __s && *__sanity == '\0' && errno == 0)
+	    __v = __ull;
+	  else
+	    __err |= ios_base::failbit;
+	}  
+    }
+#endif
+
+  template<>
+    void
+    __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err, 
+		   const __c_locale&, int) 	      
+    {
+      if (!(__err & ios_base::failbit))
+	{
+	  // Assumes __s formatted for "C" locale.
+	  const char* __old = setlocale(LC_ALL, "C");
+	  char* __sanity;
+	  errno = 0;
+#ifdef _GLIBCPP_USE_C99
+	  float __f = strtof(__s, &__sanity);
+#else
+	  float __f = static_cast<float>(strtod(__s, &__sanity));
+#endif
+          if (__sanity != __s && *__sanity == '\0' && errno == 0)
+	    __v = __f;
+	  else
+	    __err |= ios_base::failbit;
+	  setlocale(LC_ALL, __old);
+	}
+    }
+
+  template<>
+    void
+    __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err, 
+		   const __c_locale&, int) 
+    {
+      if (!(__err & ios_base::failbit))
+	{
+	  // Assumes __s formatted for "C" locale.
+	  const char* __old = setlocale(LC_ALL, "C");
+	  char* __sanity;
+	  errno = 0;
+	  double __d = strtod(__s, &__sanity);
+          if (__sanity != __s && *__sanity == '\0' && errno == 0)
+	    __v = __d;
+	  else
+	    __err |= ios_base::failbit;
+	  setlocale(LC_ALL, __old);
+	}
+    }
+
+  template<>
+    void
+    __convert_to_v(const char* __s, long double& __v, 
+		   ios_base::iostate& __err, const __c_locale&, int) 
+    {
+      if (!(__err & ios_base::failbit))
+	{
+	  // Assumes __s formatted for "C" locale.
+	  const char* __old = setlocale(LC_ALL, "C");
+#if defined(_GLIBCPP_USE_C99) && !defined(__hpux)
+	  char* __sanity;
+	  errno = 0;
+	  long double __ld = strtold(__s, &__sanity);
+          if (__sanity != __s && *__sanity == '\0' && errno == 0)
+	    __v = __ld;
+#else
+	  typedef typename char_traits<_CharT>::int_type int_type;
+	  long double __ld;
+	  int __p = sscanf(__s, "%Lf", &__ld);
+	  if (__p && static_cast<int_type>(__p) != char_traits<_CharT>::eof())
+	    __v = __ld;
+#endif
+	  else
+	    __err |= ios_base::failbit;
+	  setlocale(LC_ALL, __old);
+	}
+    }
+
   void
   locale::facet::_S_create_c_locale(__c_locale& __cloc, const char*)
   { __cloc = NULL; }
diff --git a/libstdc++-v3/config/locale/c_locale_gnu.cc b/libstdc++-v3/config/locale/c_locale_gnu.cc
index ba0c597e47cd..1129f872ca9f 100644
--- a/libstdc++-v3/config/locale/c_locale_gnu.cc
+++ b/libstdc++-v3/config/locale/c_locale_gnu.cc
@@ -1,6 +1,6 @@
 // Wrapper for underlying C-language localization -*- C++ -*-
 
-// Copyright (C) 2001 Free Software Foundation, Inc.
+// Copyright (C) 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
@@ -39,6 +39,130 @@
 
 namespace std 
 {
+  template<>
+    void
+    __convert_to_v(const char* __s, long& __v, ios_base::iostate& __err, 
+		   const __c_locale& __cloc, int __base)
+    {
+      if (!(__err & ios_base::failbit))
+      {
+	char* __sanity;
+	errno = 0;
+	long __l = __strtol_l(__s, &__sanity, __base, __cloc);
+	if (__sanity != __s && *__sanity == '\0' && errno == 0)
+	  __v = __l;
+	else
+	  __err |= ios_base::failbit;
+      }
+    }
+
+  template<>
+    void
+    __convert_to_v(const char* __s, unsigned long& __v, 
+		   ios_base::iostate& __err, const __c_locale& __cloc, 
+		   int __base)
+    {
+      if (!(__err & ios_base::failbit))
+	{
+	  char* __sanity;
+	  errno = 0;
+	  unsigned long __ul = __strtoul_l(__s, &__sanity, __base, __cloc);
+          if (__sanity != __s && *__sanity == '\0' && errno == 0)
+	    __v = __ul;
+	  else
+	    __err |= ios_base::failbit;
+	}
+    }
+
+#ifdef _GLIBCPP_USE_LONG_LONG
+  template<>
+    void
+    __convert_to_v(const char* __s, long long& __v, ios_base::iostate& __err, 
+		   const __c_locale& __cloc, int __base)
+    {
+      if (!(__err & ios_base::failbit))
+	{
+	  char* __sanity;
+	  errno = 0;
+	  long long __ll = __strtoll_l(__s, &__sanity, __base, __cloc);
+          if (__sanity != __s && *__sanity == '\0' && errno == 0)
+	    __v = __ll;
+	  else
+	    __err |= ios_base::failbit;
+	}
+    }
+
+  template<>
+    void
+    __convert_to_v(const char* __s, unsigned long long& __v, 
+		   ios_base::iostate& __err, const __c_locale& __cloc, 
+		   int __base)
+    {
+      if (!(__err & ios_base::failbit))
+	{      
+	  char* __sanity;
+	  errno = 0;
+	  unsigned long long __ull = __strtoull_l(__s, &__sanity, __base, 
+						  __cloc);
+          if (__sanity != __s && *__sanity == '\0' && errno == 0)
+	    __v = __ull;
+	  else
+	    __err |= ios_base::failbit;
+	}  
+    }
+#endif
+
+  template<>
+    void
+    __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err, 
+		   const __c_locale& __cloc, int)
+    {
+      if (!(__err & ios_base::failbit))
+	{
+	  char* __sanity;
+	  errno = 0;
+	  float __f = __strtof_l(__s, &__sanity, __cloc);
+          if (__sanity != __s && *__sanity == '\0' && errno == 0)
+	    __v = __f;
+	  else
+	    __err |= ios_base::failbit;
+	}
+    }
+
+  template<>
+    void
+    __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err, 
+		   const __c_locale& __cloc, int)
+    {
+      if (!(__err & ios_base::failbit))
+	{
+	  char* __sanity;
+	  errno = 0;
+	  double __d = __strtod_l(__s, &__sanity, __cloc);
+          if (__sanity != __s && *__sanity == '\0' && errno == 0)
+	    __v = __d;
+	  else
+	    __err |= ios_base::failbit;
+	}
+    }
+
+  template<>
+    void
+    __convert_to_v(const char* __s, long double& __v, ios_base::iostate& __err,
+		   const __c_locale& __cloc, int)
+    {
+      if (!(__err & ios_base::failbit))
+	{
+	  char* __sanity;
+	  errno = 0;
+	  long double __ld = __strtold_l(__s, &__sanity, __cloc);
+          if (__sanity != __s && *__sanity == '\0' && errno == 0)
+	    __v = __ld;
+	  else
+	    __err |= ios_base::failbit;
+	}
+    }
+
   void
   locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s)
   {
diff --git a/libstdc++-v3/config/locale/messages_members_gnu.cc b/libstdc++-v3/config/locale/messages_members_gnu.cc
index ef1a5a360eb4..bd2252d0537a 100644
--- a/libstdc++-v3/config/locale/messages_members_gnu.cc
+++ b/libstdc++-v3/config/locale/messages_members_gnu.cc
@@ -1,6 +1,6 @@
 // std::messages implementation details, GNU version -*- C++ -*-
 
-// Copyright (C) 2001 Free Software Foundation, Inc.
+// Copyright (C) 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
@@ -49,8 +49,9 @@ namespace std
       uselocale(__old);
       return string(__msg);
 #else
-      setlocale(LC_ALL, _M_name_messages);
+      const char* __old = setlocale(LC_ALL, _M_name_messages);
       const char* __msg = gettext(__dfault.c_str());
+      setlocale(LC_ALL, __old);
       return string(__msg);
 #endif
     }
diff --git a/libstdc++-v3/config/locale/messages_members_gnu.h b/libstdc++-v3/config/locale/messages_members_gnu.h
index 07d2195f2c00..a83bafff5f10 100644
--- a/libstdc++-v3/config/locale/messages_members_gnu.h
+++ b/libstdc++-v3/config/locale/messages_members_gnu.h
@@ -1,6 +1,6 @@
 // std::messages implementation details, GNU version -*- C++ -*-
 
-// Copyright (C) 2001 Free Software Foundation, Inc.
+// Copyright (C) 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
@@ -66,8 +66,9 @@
       uselocale(__old);
       return _M_convert_from_char(__msg);
 #else
-      setlocale(LC_ALL, _M_name_messages);
+      const char* __old = setlocale(LC_ALL, _M_name_messages);
       char* __msg = gettext(_M_convert_to_char(__dfault));
+      setlocale(LC_ALL, __old);
       return _M_convert_from_char(__msg);
 #endif
     }
diff --git a/libstdc++-v3/config/locale/numpunct_members_generic.cc b/libstdc++-v3/config/locale/numpunct_members_generic.cc
index 23acb7693889..7a511e3a36a4 100644
--- a/libstdc++-v3/config/locale/numpunct_members_generic.cc
+++ b/libstdc++-v3/config/locale/numpunct_members_generic.cc
@@ -1,6 +1,6 @@
 // std::numpunct implementation details, generic version -*- C++ -*-
 
-// Copyright (C) 2001 Free Software Foundation, Inc.
+// Copyright (C) 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
diff --git a/libstdc++-v3/config/locale/numpunct_members_gnu.cc b/libstdc++-v3/config/locale/numpunct_members_gnu.cc
index 5a423b50a780..de9e386fd467 100644
--- a/libstdc++-v3/config/locale/numpunct_members_gnu.cc
+++ b/libstdc++-v3/config/locale/numpunct_members_gnu.cc
@@ -1,6 +1,6 @@
 // std::numpunct implementation details, GNU version -*- C++ -*-
 
-// Copyright (C) 2001 Free Software Foundation, Inc.
+// Copyright (C) 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
diff --git a/libstdc++-v3/config/locale/time_members_generic.cc b/libstdc++-v3/config/locale/time_members_generic.cc
index 16788d40f3da..e546f30a0dbb 100644
--- a/libstdc++-v3/config/locale/time_members_generic.cc
+++ b/libstdc++-v3/config/locale/time_members_generic.cc
@@ -1,6 +1,6 @@
 // std::time_get, std::time_put implementation, GNU version -*- C++ -*-
 
-// Copyright (C) 2001 Free Software Foundation, Inc.
+// Copyright (C) 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
@@ -44,8 +44,9 @@ namespace std
     _M_put_helper(char* __s, size_t __maxlen, const char* __format, 
 		  const tm* __tm) const
     {
-      setlocale(LC_ALL, _M_name_timepunct);
+      const char* __old = setlocale(LC_ALL, _M_name_timepunct);
       strftime(__s, __maxlen, __format, __tm);
+      setlocale(LC_ALL, __old);
     }
 
   template<> 
@@ -117,8 +118,9 @@ namespace std
     _M_put_helper(wchar_t* __s, size_t __maxlen, const wchar_t* __format, 
 		  const tm* __tm) const
     {
-      setlocale(LC_ALL, _M_name_timepunct);
+      const char* __old = setlocale(LC_ALL, _M_name_timepunct);
       wcsftime(__s, __maxlen, __format, __tm);
+      setlocale(LC_ALL, __old);
     }
 
   template<> 
diff --git a/libstdc++-v3/config/locale/time_members_gnu.cc b/libstdc++-v3/config/locale/time_members_gnu.cc
index 74d89992095d..f00ec4a89c81 100644
--- a/libstdc++-v3/config/locale/time_members_gnu.cc
+++ b/libstdc++-v3/config/locale/time_members_gnu.cc
@@ -1,6 +1,6 @@
 // std::time_get, std::time_put implementation, GNU version -*- C++ -*-
 
-// Copyright (C) 2001 Free Software Foundation, Inc.
+// Copyright (C) 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
@@ -51,8 +51,9 @@ namespace std
       else
 	strftime(__s, __maxlen, __format, __tm);
 #else
-      setlocale(LC_ALL, _M_name_timepunct);
+      const char* __old = setlocale(LC_ALL, _M_name_timepunct);
       strftime(__s, __maxlen, __format, __tm);
+      setlocale(LC_ALL, __old);
 #endif
     }
 
@@ -195,8 +196,9 @@ namespace std
       else
 	wcsftime(__s, __maxlen, __format, __tm);
 #else
-      setlocale(LC_ALL, _M_name_timepunct);
+      const char* __old = setlocale(LC_ALL, _M_name_timepunct);
       wcsftime(__s, __maxlen, __format, __tm);
+      setlocale(LC_ALL, __old);
 #endif
     }
 
diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h
index 9f435be5774f..98e1c073d572 100644
--- a/libstdc++-v3/include/bits/locale_facets.h
+++ b/libstdc++-v3/include/bits/locale_facets.h
@@ -1,6 +1,7 @@
 // Locale support -*- C++ -*-
 
-// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+// Copyright (C) 1997, 1998, 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
@@ -45,7 +46,7 @@
 #ifdef _GLIBCPP_USE_WCHAR_T
 # include <cwctype>	// For wctype_t
 #endif 
-#include <ios>	// For ios_base
+#include <ios>		// For ios_base
 
 namespace std
 {
@@ -53,7 +54,7 @@ namespace std
   // Include host and configuration specific ctype enums for ctype_base.
   #include <bits/ctype_base.h>
 
-  // __ctype_abstract_base is the common base for ctype<_CharT>.  
+  // Common base for ctype<_CharT>.  
   template<typename _CharT>
     class __ctype_abstract_base : public locale::facet, public ctype_base
     {
@@ -417,9 +418,9 @@ namespace std
 
 
   // 22.2.2  The numeric category.
-  class __num_base
+  class __num_base 
   {
-  public:
+  protected:
     // Used to establish gating factor for base 16 input.
     static const double _S_scale_hex;
     
@@ -438,6 +439,7 @@ namespace std
       _M_size = 21 + 1
     };
 
+    // num_put
     // Construct and return valid scanf format for floating point types.
     static bool
     _S_format_float(const ios_base& __io, char* __fptr, char __mod, 
@@ -448,6 +450,7 @@ namespace std
     _S_format_int(const ios_base& __io, char* __fptr, char __mod, char __modl);
   };
 
+
   template<typename _CharT>
     class numpunct : public locale::facet
     {
@@ -885,7 +888,7 @@ namespace std
 
   template<>
     size_t
-    collate<wchar_t>::_M_transform_helper(wchar_t*, const wchar_t*, 
+    collate<wchar_t>::_M_transform_helper(wchar_t*, const wchar_t*,
 					  size_t) const;
 #endif
 
diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc
index 083cb63c5ad8..64c92ec1ca1a 100644
--- a/libstdc++-v3/include/bits/locale_facets.tcc
+++ b/libstdc++-v3/include/bits/locale_facets.tcc
@@ -1,6 +1,7 @@
 // Locale support -*- C++ -*-
 
-// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+// Copyright (C) 1997, 1998, 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
@@ -39,9 +40,9 @@
 #include <cctype>    // For isspace
 #include <limits>    // For numeric_limits
 #include <memory>    // For auto_ptr
-#include <bits/streambuf_iterator.h>     // For streambuf_iterators
-#include <typeinfo> 		// For bad_cast
+#include <bits/streambuf_iterator.h>
 #include <vector>	
+#include <typeinfo>  // For bad_cast.
 
 namespace std
 {
@@ -87,6 +88,7 @@ namespace std
     }
 
 
+  // Stage 1: Determine a conversion specifier.
   template<typename _CharT, typename _InIter>
     _InIter
     num_get<_CharT, _InIter>::
@@ -97,7 +99,7 @@ namespace std
       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
 
-      // Check first for sign.
+      // First check for sign.
       const char_type __plus = __ctype.widen('+');
       const char_type __minus = __ctype.widen('-');
       int __pos = 0;
@@ -216,6 +218,7 @@ namespace std
       return __beg;
     }
 
+  // Stage 1: Determine a conversion specifier.
   template<typename _CharT, typename _InIter>
     _InIter
     num_get<_CharT, _InIter>::
@@ -227,7 +230,6 @@ namespace std
       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
  
-      // Stage 1: determine a conversion specifier.
       // NB: Iff __basefield == 0, this can change based on contents.
       ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
       if (__basefield == ios_base::oct)
@@ -381,13 +383,12 @@ namespace std
     do_get(iter_type __beg, iter_type __end, ios_base& __io,
            ios_base::iostate& __err, bool& __v) const
     {
-      // Parse bool values as long
+      // Parse bool values as unsigned long
       if (!(__io.flags() & ios_base::boolalpha))
         {
           // NB: We can't just call do_get(long) here, as it might
           // refer to a derived class.
 
-          // Stage 1: extract and determine the conversion specifier.
           // Assuming leading zeros eliminated, thus the size of 32 for
           // integral types
           char __xtrc[32];
@@ -399,15 +400,11 @@ namespace std
           __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, 
 				 numeric_limits<bool>::digits10 + 1, __base);
 
-          // Stage 2: convert and store results.
-          char* __sanity;
-          errno = 0;
-          long __l = strtol(__xtrc, &__sanity, __base);
-          if (!(__err & ios_base::failbit)
-              && __l <= 1
-              && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
-            __v = __l;
-          else
+	  unsigned long __ul; 
+	  __convert_to_v(__xtrc, __ul, __err, _S_c_locale, __base);
+	  if (!(__err & ios_base::failbit) && __ul <= 1)
+	    __v = __ul;
+	  else 
             __err |= ios_base::failbit;
         }
 
@@ -415,7 +412,7 @@ namespace std
       else
         {
           locale __loc = __io.getloc();
-	  const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__loc); 
+	  const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 
           const char_type* __true = __np.truename().c_str();
           const char_type* __false = __np.falsename().c_str();
 
@@ -456,23 +453,13 @@ namespace std
     do_get(iter_type __beg, iter_type __end, ios_base& __io,
            ios_base::iostate& __err, long& __v) const
     {
-      // Stage 1: extract and determine the conversion specifier.
       // Assuming leading zeros eliminated, thus the size of 32 for
       // integral types.
       char __xtrc[32];
       int __base;
       __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, 
 			     numeric_limits<long>::digits10 + 1, __base);
-
-      // Stage 2: convert and store results.
-      char* __sanity;
-      errno = 0;
-      long __l = strtol(__xtrc, &__sanity, __base);
-      if (!(__err & ios_base::failbit)
-          && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
-        __v = __l;
-      else
-        __err |= ios_base::failbit;
+      __convert_to_v(__xtrc, __v, __err, _S_c_locale, __base);
       return __beg;
     }
 
@@ -482,7 +469,6 @@ namespace std
     do_get(iter_type __beg, iter_type __end, ios_base& __io,
            ios_base::iostate& __err, unsigned short& __v) const
     {
-      // Stage 1: extract and determine the conversion specifier.
       // Assuming leading zeros eliminated, thus the size of 32 for
       // integral types.
       char __xtrc[32];
@@ -490,17 +476,12 @@ namespace std
       __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, 
 			     numeric_limits<unsigned short>::digits10 + 1,
 			     __base);
-
-      // Stage 2: convert and store results.
-      char* __sanity;
-      errno = 0;
-      unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
-      if (!(__err & ios_base::failbit)
-          && __sanity != __xtrc && *__sanity == '\0' && errno == 0
-          && __ul <= USHRT_MAX)
-        __v = static_cast<unsigned short>(__ul);
-      else
-        __err |= ios_base::failbit;
+      unsigned long __ul;
+      __convert_to_v(__xtrc, __ul, __err, _S_c_locale, __base);
+      if (!(__err & ios_base::failbit) && __ul <= USHRT_MAX)
+	__v = static_cast<unsigned short>(__ul);
+      else 
+	__err |= ios_base::failbit;
       return __beg;
     }
 
@@ -510,7 +491,6 @@ namespace std
     do_get(iter_type __beg, iter_type __end, ios_base& __io,
            ios_base::iostate& __err, unsigned int& __v) const
     {
-      // Stage 1: extract and determine the conversion specifier.
       // Assuming leading zeros eliminated, thus the size of 32 for
       // integral types.
       char __xtrc[32];
@@ -518,17 +498,12 @@ namespace std
       __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, 
 			     numeric_limits<unsigned int>::digits10 + 1,
 			     __base);
-
-      // Stage 2: convert and store results.
-      char* __sanity;
-      errno = 0;
-      unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
-      if (!(__err & ios_base::failbit)
-          && __sanity != __xtrc && *__sanity == '\0' && errno == 0
-          && __ul <= UINT_MAX)
-        __v = static_cast<unsigned int>(__ul);
-      else
-        __err |= ios_base::failbit;
+      unsigned long __ul;
+      __convert_to_v(__xtrc, __ul, __err, _S_c_locale, __base);
+      if (!(__err & ios_base::failbit) && __ul <= UINT_MAX)
+	__v = static_cast<unsigned int>(__ul);
+      else 
+	__err |= ios_base::failbit;
       return __beg;
     }
 
@@ -538,7 +513,6 @@ namespace std
     do_get(iter_type __beg, iter_type __end, ios_base& __io,
            ios_base::iostate& __err, unsigned long& __v) const
     {
-      // Stage 1: extract and determine the conversion specifier.
       // Assuming leading zeros eliminated, thus the size of 32 for
       // integral types.
       char __xtrc[32];
@@ -546,16 +520,7 @@ namespace std
       __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, 
 			     numeric_limits<unsigned long>::digits10 + 1,
 			     __base);
-
-      // Stage 2: convert and store results.
-      char* __sanity;
-      errno = 0;
-      unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
-      if (!(__err & ios_base::failbit)
-          && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
-        __v = __ul;
-      else
-        __err |= ios_base::failbit;
+      __convert_to_v(__xtrc, __v, __err, _S_c_locale, __base);
       return __beg;
     }
 
@@ -566,23 +531,13 @@ namespace std
     do_get(iter_type __beg, iter_type __end, ios_base& __io,
            ios_base::iostate& __err, long long& __v) const
     {
-      // Stage 1: extract and determine the conversion specifier.
       // Assuming leading zeros eliminated, thus the size of 32 for
       // integral types.
       char __xtrc[32];
       int __base;
       __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, 
 			     numeric_limits<long long>::digits10 + 1, __base);
-
-      // Stage 2: convert and store results.
-      char* __sanity;
-      errno = 0;
-      long long __ll = strtoll(__xtrc, &__sanity, __base);
-      if (!(__err & ios_base::failbit)
-          && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
-        __v = __ll;
-      else
-        __err |= ios_base::failbit;
+      __convert_to_v(__xtrc, __v, __err, _S_c_locale, __base);
       return __beg;
     }
 
@@ -592,7 +547,6 @@ namespace std
     do_get(iter_type __beg, iter_type __end, ios_base& __io,
            ios_base::iostate& __err, unsigned long long& __v) const
     {
-      // Stage 1: extract and determine the conversion specifier.
       // Assuming leading zeros eliminated, thus the size of 32 for
       // integral types.
       char __xtrc[32];
@@ -600,16 +554,7 @@ namespace std
       __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc,
 			     numeric_limits<unsigned long long>::digits10 + 1,
 			     __base);
-
-      // Stage 2: convert and store results.
-      char* __sanity;
-      errno = 0;
-      unsigned long long __ull = strtoull(__xtrc, &__sanity, __base);
-      if (!(__err & ios_base::failbit)
-          && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
-        __v = __ull;
-      else
-        __err |= ios_base::failbit;
+      __convert_to_v(__xtrc, __v, __err, _S_c_locale, __base);
       return __beg;
     }
 #endif
@@ -620,24 +565,10 @@ namespace std
     do_get(iter_type __beg, iter_type __end, ios_base& __io, 
 	   ios_base::iostate& __err, float& __v) const
     {
-      // Stage 1: extract and determine the conversion specifier.
       string __xtrc;
       __xtrc.reserve(32);
       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
-
-      // Stage 2: convert and store results.
-      char* __sanity;
-      errno = 0;
-#ifdef _GLIBCPP_USE_C99
-      float __f = strtof(__xtrc.c_str(), &__sanity);
-#else
-      float __f = static_cast<float>(strtod(__xtrc.c_str(), &__sanity));
-#endif
-      if (!(__err & ios_base::failbit)
-          && __sanity != __xtrc.c_str() && *__sanity == '\0' && errno == 0)
-        __v = __f;
-      else
-        __err |= ios_base::failbit;
+      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
       return __beg;
     }
 
@@ -647,20 +578,10 @@ namespace std
     do_get(iter_type __beg, iter_type __end, ios_base& __io,
            ios_base::iostate& __err, double& __v) const
     {
-      // Stage 1: extract and determine the conversion specifier.
       string __xtrc;
       __xtrc.reserve(32);
       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
-
-      // Stage 2: convert and store results.
-      char* __sanity;
-      errno = 0;
-      double __d = strtod(__xtrc.c_str(), &__sanity);
-      if (!(__err & ios_base::failbit)
-          && __sanity != __xtrc.c_str() && *__sanity == '\0' && errno == 0)
-        __v = __d;
-      else
-        __err |= ios_base::failbit;
+      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
       return __beg;
     }
 
@@ -670,42 +591,10 @@ namespace std
     do_get(iter_type __beg, iter_type __end, ios_base& __io,
            ios_base::iostate& __err, long double& __v) const
     {
-      // Stage 1: extract and determine the conversion specifier.
       string __xtrc;
       __xtrc.reserve(32);
       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
-
-#if defined(_GLIBCPP_USE_C99) && !defined(__hpux)
-      // Stage 2: convert and store results.
-      char* __sanity;
-      errno = 0;
-      long double __ld = strtold(__xtrc.c_str(), &__sanity);
-      if (!(__err & ios_base::failbit)
-          && __sanity != __xtrc.c_str() && *__sanity == '\0' && errno == 0)
-        __v = __ld;
-#else
-      // Stage 2: determine a conversion specifier.
-      ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
-      const char* __conv;
-      if (__basefield == ios_base::oct)
-        __conv = "%Lo";
-      else if (__basefield == ios_base::hex)
-        __conv = "%LX";
-      else if (__basefield == 0)
-        __conv = "%Li";
-      else
-        __conv = "%Lf";
-
-      // Stage 3: store results.
-      typedef typename char_traits<_CharT>::int_type int_type;
-      long double __ld;
-      int __p = sscanf(__xtrc.c_str(), __conv, &__ld);
-      if (!(__err & ios_base::failbit) && __p 
-	  && static_cast<int_type>(__p) != char_traits<_CharT>::eof())
-        __v = __ld;
-#endif
-      else
-        __err |= ios_base::failbit;
+      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
       return __beg;
     }
 
@@ -722,7 +611,6 @@ namespace std
                              | ios_base::uppercase | ios_base::internal);
       __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase));
 
-      // Stage 1: extract and determine the conversion specifier.
       // Assuming leading zeros eliminated, thus the size of 32 for
       // integral types.
       char __xtrc[32];
@@ -731,18 +619,15 @@ namespace std
 			     numeric_limits<unsigned long>::digits10 + 1,
 			     __base);
 
-      // Stage 2: convert and store results.
-      char* __sanity;
-      errno = 0;
-      void* __vp = reinterpret_cast<void*>(strtoul(__xtrc, &__sanity, __base));
-      if (!(__err & ios_base::failbit)
-          && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
-        __v = __vp;
-      else
-        __err |= ios_base::failbit;
-
       // Reset from hex formatted input
       __io.flags(__fmt);
+
+      unsigned long __ul;
+      __convert_to_v(__xtrc, __ul, __err, _S_c_locale, __base);
+      if (!(__err & ios_base::failbit))
+	__v = reinterpret_cast<void*>(__ul);
+      else 
+	__err |= ios_base::failbit;
       return __beg;
     }
 
@@ -787,9 +672,9 @@ namespace std
 	int __len;
 	// [22.2.2.2.2] Stage 1, numeric conversion to character.
 	if (_S_format_float(__io, __fbuf, __mod, __prec))
-	  __len = sprintf(__cs, __fbuf, __prec, __v);
+	  __len = __convert_from_v(__cs, __fbuf, __v, _S_c_locale, __prec);
 	else
-	  __len = sprintf(__cs, __fbuf, __v);
+	  __len = __convert_from_v(__cs, __fbuf, __v, _S_c_locale);
 	return _M_widen_float(__s, __io, __fill, __cs, __len);
       }
 
@@ -807,7 +692,7 @@ namespace std
 	// Long enough for the max format spec.
 	char __fbuf[16];
 	_S_format_int(__io, __fbuf, __mod, __modl);
-	int __len = sprintf(__cs, __fbuf, __v);
+	int __len = __convert_from_v(__cs, __fbuf, __v, _S_c_locale);
 	return _M_widen_int(__s, __io, __fill, __cs, __len);
       }
 
@@ -1043,22 +928,7 @@ namespace std
       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
       const _CharT* __wcs = __str.c_str();
       __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs);      
-
-#if defined(_GLIBCPP_USE_C99) && !defined(__hpux)
-      char* __sanity;
-      errno = 0;
-      long double __ld = strtold(__cs, &__sanity);
-      if (!(__err & ios_base::failbit)
-          && __sanity != __cs && *__sanity == '\0' && errno == 0)
-        __units = __ld;
-#else
-      typedef typename char_traits<_CharT>::int_type int_type;
-      long double __ld;
-      int __p = sscanf(__cs, "%Lf", &__ld);
-      if (!(__err & ios_base::failbit)
-	  && __p && static_cast<int_type>(__p) != char_traits<_CharT>::eof())
-        __units = __ld;
-#endif
+      __convert_to_v(__cs, __units, __err, _S_c_locale);
       return __beg;
     }
 
@@ -1253,7 +1123,7 @@ namespace std
       const int __n = numeric_limits<long double>::digits10;
       char* __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __n));
       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
-      int __len = sprintf(__cs, "%.01Lf", __units);
+      int __len = __convert_from_v(__cs, "%.01Lf", __units, _S_c_locale);
       __ctype.widen(__cs, __cs + __len, __ws);
       string_type __digits(__ws);
       return this->do_put(__s, __intl, __io, __fill, __digits); 
@@ -1867,9 +1737,13 @@ namespace std
 	}
       if (__i == 2 || __i == 4)
 	{
-	  int __year = atoi(__digits.c_str());
-	  __year = __i == 2 ? __year : __year - 1900; 
-	  __tm->tm_year = __year;
+	  long __l;
+	  __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale);
+	  if (!(__err & ios_base::failbit) && __l <= INT_MAX)
+	    {
+	      __l = __i == 2 ? __l : __l - 1900; 
+	      __tm->tm_year = static_cast<int>(__l);
+	    }
 	}
       else
 	__err |= ios_base::failbit;
@@ -2015,6 +1889,30 @@ namespace std
       return static_cast<long>(__val);
     }
 
+  // Convert string to numeric value of type T and store results.  
+  // NB: This is specialized for all required types, there is no
+  // generic definition.
+  template <typename _T>
+    void
+    __convert_to_v(const char* __in, _T& __out, ios_base::iostate& __err, 
+		   const __c_locale& __cloc, int __base = 10);
+
+  // Convert numeric value of type T to string and return length of string.
+  template <typename _T>
+    int
+    __convert_from_v(char* __out, const char* __fmt, _T __v, 
+		     const __c_locale&, int __prec = -1)
+    {
+      int __ret;
+      const char* __old = setlocale(LC_ALL, "C");
+      if (__prec >= 0)
+	__ret = sprintf(__out, __fmt, __prec, __v);
+      else
+	__ret = sprintf(__out, __fmt, __v);
+      setlocale(LC_ALL, __old);
+      return __ret;
+    }
+
   // Construct correctly padded string, as per 22.2.2.2.2
   // Assumes 
   // __newlen > __oldlen
diff --git a/libstdc++-v3/include/bits/localefwd.h b/libstdc++-v3/include/bits/localefwd.h
index 558ccabe2dea..be7f7e65e26a 100644
--- a/libstdc++-v3/include/bits/localefwd.h
+++ b/libstdc++-v3/include/bits/localefwd.h
@@ -1,6 +1,7 @@
 // Locale support -*- C++ -*-
 
-// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+// Copyright (C) 1997, 1998, 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
@@ -43,9 +44,9 @@
 
 #include <bits/c++config.h>
 #include <bits/c++locale.h>     // Defines __c_locale, config-specific includes
-#include <climits>	// For CHAR_BIT
-#include <cctype>	// For isspace, etc.
-#include <string> 	// For string
+#include <climits>		// For CHAR_BIT
+#include <cctype>		// For isspace, etc.
+#include <string> 		// For string
 #include <bits/functexcept.h>
 
 namespace std
@@ -295,7 +296,7 @@ namespace std
   };
 
 
-  // locale implementation object
+  // Implementation object for locale 
   class locale::_Impl
   {
   public:
@@ -390,11 +391,14 @@ namespace std
     friend class locale::_Impl;
     friend class __enc_traits;
 
+  private:
+    size_t _M_references;
+
   protected:
     // Contains data from the underlying "C" library for default "C"
-    // and "POSIX" locales.
+    // or "POSIX" locale.
     static __c_locale		     _S_c_locale;
-
+    
     explicit 
     facet(size_t __refs = 0) throw();
 
@@ -411,18 +415,16 @@ namespace std
     _S_destroy_c_locale(__c_locale& __cloc);
 
   private:
-    size_t _M_references;
-
     void 
     _M_add_reference() throw();
 
     void 
     _M_remove_reference() throw();
 
-    facet(const facet&);  // not defined
+    facet(const facet&);  // Not defined.
 
     void 
-    operator=(const facet&);  // not defined
+    operator=(const facet&);  // Not defined.
   };
 
 
diff --git a/libstdc++-v3/src/locale-inst.cc b/libstdc++-v3/src/locale-inst.cc
index e2f6d7764fe6..ff0dfd533f21 100644
--- a/libstdc++-v3/src/locale-inst.cc
+++ b/libstdc++-v3/src/locale-inst.cc
@@ -1,6 +1,6 @@
 // Locale support -*- C++ -*-
 
-// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+// 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
@@ -372,6 +372,32 @@ namespace std
 					  streamsize, const bool);
 #endif // _GLIBCPP_USE_WCHAR_T
 
+  template
+    int
+    __convert_from_v(char*, const char*, double, const __c_locale&, int);
+
+  template
+    int
+    __convert_from_v(char*, const char*, long double, const __c_locale&, int);
+
+  template
+    int
+    __convert_from_v(char*, const char*, long, const __c_locale&, int);
+
+  template
+    int
+    __convert_from_v(char*, const char*, unsigned long, 
+		     const __c_locale&, int);
+
+  template
+    int
+    __convert_from_v(char*, const char*, long long, const __c_locale&, int);
+
+  template
+    int
+    __convert_from_v(char*, const char*, unsigned long long, 
+		     const __c_locale&, int);
+
   template 
     locale::facet** 
     fill_n<locale::facet**, size_t, locale::facet*>
diff --git a/libstdc++-v3/testsuite/22_locale/codecvt_members_char_char.cc b/libstdc++-v3/testsuite/22_locale/codecvt_members_char_char.cc
index 01542666ebe5..ae9301da074f 100644
--- a/libstdc++-v3/testsuite/22_locale/codecvt_members_char_char.cc
+++ b/libstdc++-v3/testsuite/22_locale/codecvt_members_char_char.cc
@@ -1,6 +1,6 @@
 // 2000-08-17 Benjamin Kosnik <bkoz@cygnus.com>
 
-// Copyright (C) 2000 Free Software Foundation
+// Copyright (C) 2000, 2002 Free Software Foundation
 //
 // 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
@@ -79,9 +79,25 @@ void test01()
   delete [] c_arr;
 }
 
+// libstdc++/5280
+void test02()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      setenv("LANG", oldLANG, 1);
+    }
+}
+
 int main ()
 {
   test01();
-
+  test02();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/22_locale/codecvt_members_wchar_t_char.cc b/libstdc++-v3/testsuite/22_locale/codecvt_members_wchar_t_char.cc
index 92235e8486f4..694be81612f1 100644
--- a/libstdc++-v3/testsuite/22_locale/codecvt_members_wchar_t_char.cc
+++ b/libstdc++-v3/testsuite/22_locale/codecvt_members_wchar_t_char.cc
@@ -1,6 +1,6 @@
 // 2000-08-18 Benjamin Kosnik <bkoz@cygnus.com>
 
-// Copyright (C) 2000 Free Software Foundation
+// Copyright (C) 2000, 2002 Free Software Foundation
 //
 // 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
@@ -110,6 +110,22 @@ void test01()
   delete [] e_arr;
   delete [] i_arr;
 }
+
+// libstdc++/5280
+void test02()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      setenv("LANG", oldLANG, 1);
+    }
+}
 #endif /* !defined(_GLIBCPP_USE_WCHAR_T) */
 
 
@@ -117,6 +133,7 @@ int main ()
 {
 #if _GLIBCPP_USE_WCHAR_T
   test01();
+  test02();
 #endif 
 
   return 0;
diff --git a/libstdc++-v3/testsuite/22_locale/collate_members_char.cc b/libstdc++-v3/testsuite/22_locale/collate_members_char.cc
index e4cef5793476..d19948215b50 100644
--- a/libstdc++-v3/testsuite/22_locale/collate_members_char.cc
+++ b/libstdc++-v3/testsuite/22_locale/collate_members_char.cc
@@ -1,6 +1,6 @@
 // 2001-08-15 Benjamin Kosnik  <bkoz@redhat.com>
 
-// Copyright (C) 2001 Free Software Foundation
+// Copyright (C) 2001, 2002 Free Software Foundation
 //
 // 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
@@ -129,10 +129,26 @@ void test01()
   VERIFY(i1 == i2);
 }
 
+// libstdc++/5280
+void test02()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      setenv("LANG", oldLANG, 1);
+    }
+}
+
 int main()
 {
   test01();
-
+  test02();
   return 0;
 }
 
diff --git a/libstdc++-v3/testsuite/22_locale/collate_members_wchar_t.cc b/libstdc++-v3/testsuite/22_locale/collate_members_wchar_t.cc
index 445096cc23fd..d94dca4ea3d2 100644
--- a/libstdc++-v3/testsuite/22_locale/collate_members_wchar_t.cc
+++ b/libstdc++-v3/testsuite/22_locale/collate_members_wchar_t.cc
@@ -1,6 +1,6 @@
 // 2001-08-17 Benjamin Kosnik  <bkoz@redhat.com>
 
-// Copyright (C) 2001 Free Software Foundation
+// Copyright (C) 2001, 2002 Free Software Foundation
 //
 // 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
@@ -128,12 +128,29 @@ void test01()
   i2 = coll_de.compare(strlit3, strlit3 + size3, strlit4, strlit4 + size4);
   VERIFY(i1 == i2);
 }
+
+// libstdc++/5280
+void test02()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      setenv("LANG", oldLANG, 1);
+    }
+}
 #endif
 
 int main()
 {
 #if _GLIBCPP_USE_WCHAR_T
   test01();
+  test02();
 #endif
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/22_locale/ctype_members_char.cc b/libstdc++-v3/testsuite/22_locale/ctype_members_char.cc
index 2ce966851b9c..537f9ec81a9e 100644
--- a/libstdc++-v3/testsuite/22_locale/ctype_members_char.cc
+++ b/libstdc++-v3/testsuite/22_locale/ctype_members_char.cc
@@ -243,10 +243,27 @@ public:
   { classic_table(); }
 };
 
+// libstdc++/5280
+void test03()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      test02();
+      setenv("LANG", oldLANG, 1);
+    }
+}
+
 int main() 
 {
   test01();
   test02();
-
+  test03();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/22_locale/ctype_members_wchar_t.cc b/libstdc++-v3/testsuite/22_locale/ctype_members_wchar_t.cc
index 99ed55e4c77f..3ea8c7548d89 100644
--- a/libstdc++-v3/testsuite/22_locale/ctype_members_wchar_t.cc
+++ b/libstdc++-v3/testsuite/22_locale/ctype_members_wchar_t.cc
@@ -1,6 +1,6 @@
 // 2000-09-01 Benjamin Kosnik <bkoz@redhat.com>
 
-// Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+// Copyright (C) 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
@@ -96,12 +96,29 @@ void test01()
   assert(test);
 #endif
 }
+
+// libstdc++/5280
+void test03()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      setenv("LANG", oldLANG, 1);
+    }
+}
 #endif /* !defined(_GLIBCPP_USE_WCHAR_T) */
 
 int main() 
 {
 #if _GLIBCPP_USE_WCHAR_T
   test01();
+  test03();
 #endif 
 
   return 0;
diff --git a/libstdc++-v3/testsuite/22_locale/messages_members_char.cc b/libstdc++-v3/testsuite/22_locale/messages_members_char.cc
index bb34794c78d5..485c488166d6 100644
--- a/libstdc++-v3/testsuite/22_locale/messages_members_char.cc
+++ b/libstdc++-v3/testsuite/22_locale/messages_members_char.cc
@@ -1,6 +1,6 @@
 // 2001-07-17 Benjamin Kosnik  <bkoz@redhat.com>
 
-// Copyright (C) 2001 Free Software Foundation
+// Copyright (C) 2001, 2002 Free Software Foundation
 //
 // 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
@@ -79,12 +79,27 @@ void test01()
   VERIFY ( s01 == "please" );
   VERIFY ( s02 == "thank you" );
   mssg_us.close(cat_us);
+}
 
- }
+// libstdc++/5280
+void test02()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      setenv("LANG", oldLANG, 1);
+    }
+}
 
 int main()
 {
   test01();
-
+  test02();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/22_locale/money_get_members_char.cc b/libstdc++-v3/testsuite/22_locale/money_get_members_char.cc
index 896e9f5948d7..4288272df6a7 100644
--- a/libstdc++-v3/testsuite/22_locale/money_get_members_char.cc
+++ b/libstdc++-v3/testsuite/22_locale/money_get_members_char.cc
@@ -289,10 +289,29 @@ void test03()
   VERIFY( rem2 == "Eleanor Roosevelt" );
 }
 
+// libstdc++/5280
+void test04()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      test02();
+      test03();
+      setenv("LANG", oldLANG, 1);
+    }
+}
+
 int main()
 {
   test01();
   test02();
   test03();
+  test04();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/22_locale/money_get_members_wchar_t.cc b/libstdc++-v3/testsuite/22_locale/money_get_members_wchar_t.cc
index 4075e81de598..5e25d86fbf03 100644
--- a/libstdc++-v3/testsuite/22_locale/money_get_members_wchar_t.cc
+++ b/libstdc++-v3/testsuite/22_locale/money_get_members_wchar_t.cc
@@ -290,6 +290,24 @@ void test03()
   VERIFY( res2 == 1 );
   VERIFY( rem2 == L"Eleanor Roosevelt" );
 }
+
+// libstdc++/5280
+void test04()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      test02();
+      test03();
+      setenv("LANG", oldLANG, 1);
+    }
+}
 #endif
 
 
@@ -299,6 +317,7 @@ int main()
   test01();
   test02();
   test03();
+  test04();
 #endif
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/22_locale/money_put_members_char.cc b/libstdc++-v3/testsuite/22_locale/money_put_members_char.cc
index a3b5f57e6583..b0edd9ff20c5 100644
--- a/libstdc++-v3/testsuite/22_locale/money_put_members_char.cc
+++ b/libstdc++-v3/testsuite/22_locale/money_put_members_char.cc
@@ -283,10 +283,29 @@ void test03()
   VERIFY( sanity2 == "1943" );
 }
 
+// libstdc++/5280
+void test04()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      test02();
+      test03();
+      setenv("LANG", oldLANG, 1);
+    }
+}
+
 int main()
 {
   test01();
   test02();
   test03();
+  test04();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/22_locale/money_put_members_wchar_t.cc b/libstdc++-v3/testsuite/22_locale/money_put_members_wchar_t.cc
index 19078edf8b95..73890dd182c9 100644
--- a/libstdc++-v3/testsuite/22_locale/money_put_members_wchar_t.cc
+++ b/libstdc++-v3/testsuite/22_locale/money_put_members_wchar_t.cc
@@ -282,6 +282,24 @@ void test03()
   VERIFY( res == L"1943xxxxxxxxxxxxx" );
   VERIFY( sanity2 == L"1943" );
 }
+
+// libstdc++/5280
+void test04()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      test02();
+      test03();
+      setenv("LANG", oldLANG, 1);
+    }
+}
 #endif
 
 int main()
@@ -290,6 +308,7 @@ int main()
   test01();
   test02();
   test03();
+  test04();
 #endif
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/22_locale/moneypunct_members_char.cc b/libstdc++-v3/testsuite/22_locale/moneypunct_members_char.cc
index 97cf3340da60..6023c41d93d7 100644
--- a/libstdc++-v3/testsuite/22_locale/moneypunct_members_char.cc
+++ b/libstdc++-v3/testsuite/22_locale/moneypunct_members_char.cc
@@ -1,6 +1,6 @@
 // 2001-08-23 Benjamin Kosnik  <bkoz@redhat.com>
 
-// Copyright (C) 2001 Free Software Foundation
+// Copyright (C) 2001, 2002 Free Software Foundation
 //
 // 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
@@ -105,9 +105,25 @@ void test01()
   VERIFY(static_cast<part>(neg1.field[3]) != static_cast<part>(neg2.field[3]));
 }
 
+// libstdc++/5280
+void test02()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      setenv("LANG", oldLANG, 1);
+    }
+}
+
 int main()
 {
   test01();
-
+  test02();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/22_locale/moneypunct_members_wchar_t.cc b/libstdc++-v3/testsuite/22_locale/moneypunct_members_wchar_t.cc
index 7470a58c0026..61867b67b3fd 100644
--- a/libstdc++-v3/testsuite/22_locale/moneypunct_members_wchar_t.cc
+++ b/libstdc++-v3/testsuite/22_locale/moneypunct_members_wchar_t.cc
@@ -1,6 +1,6 @@
 // 2001-09-09 Benjamin Kosnik  <bkoz@redhat.com>
 
-// Copyright (C) 2001 Free Software Foundation
+// Copyright (C) 2001, 2002 Free Software Foundation
 //
 // 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
@@ -105,12 +105,29 @@ void test01()
   VERIFY(static_cast<part>(neg1.field[2]) != static_cast<part>(neg2.field[2]));
   VERIFY(static_cast<part>(neg1.field[3]) != static_cast<part>(neg2.field[3]));
 }
+
+// libstdc++/5280
+void test02()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      setenv("LANG", oldLANG, 1);
+    }
+}
 #endif
 
 int main()
 {
 #ifdef _GLIBCPP_USE_WCHAR_T
   test01();
+  test02();
 #endif
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/22_locale/num_get_members_char.cc b/libstdc++-v3/testsuite/22_locale/num_get_members_char.cc
index 04824b048c3d..c3d8f7e61012 100644
--- a/libstdc++-v3/testsuite/22_locale/num_get_members_char.cc
+++ b/libstdc++-v3/testsuite/22_locale/num_get_members_char.cc
@@ -313,10 +313,28 @@ void test02()
   VERIFY( rem5 == " Durack" );
 }
 
+// libstdc++/5280
+void test03()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      test02();
+      setenv("LANG", oldLANG, 1);
+    }
+}
+
 int main()
 {
   test01();
   test02();
+  test03();
   return 0;
 }
 
diff --git a/libstdc++-v3/testsuite/22_locale/num_get_members_wchar_t.cc b/libstdc++-v3/testsuite/22_locale/num_get_members_wchar_t.cc
index cbb27cc62151..97c2b2290648 100644
--- a/libstdc++-v3/testsuite/22_locale/num_get_members_wchar_t.cc
+++ b/libstdc++-v3/testsuite/22_locale/num_get_members_wchar_t.cc
@@ -314,6 +314,23 @@ void test02()
   VERIFY( b == true );
   VERIFY( rem5 == L" Durack" );
 }
+
+// libstdc++/5280
+void test03()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      test02();
+      setenv("LANG", oldLANG, 1);
+    }
+}
 #endif
 
 int main()
@@ -321,6 +338,7 @@ int main()
 #ifdef _GLIBCPP_USE_WCHAR_T
   test01();
   test02();
+  test03();
 #endif
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/22_locale/num_put_members_char.cc b/libstdc++-v3/testsuite/22_locale/num_put_members_char.cc
index 701ee2a0509f..ebbb52da4a18 100644
--- a/libstdc++-v3/testsuite/22_locale/num_put_members_char.cc
+++ b/libstdc++-v3/testsuite/22_locale/num_put_members_char.cc
@@ -291,9 +291,29 @@ void test02()
   VERIFY( sanity5[1] == 'x' );
 }
 
+// libstdc++/5280
+void test03()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      test02();
+      setenv("LANG", oldLANG, 1);
+    }
+}
+
 int main()
 {
   test01();
   test02();
+  test03();
   return 0;
 }
+
+
diff --git a/libstdc++-v3/testsuite/22_locale/num_put_members_wchar_t.cc b/libstdc++-v3/testsuite/22_locale/num_put_members_wchar_t.cc
index f3de2bd25c26..5f263a5fa12d 100644
--- a/libstdc++-v3/testsuite/22_locale/num_put_members_wchar_t.cc
+++ b/libstdc++-v3/testsuite/22_locale/num_put_members_wchar_t.cc
@@ -290,6 +290,23 @@ void test02()
   VERIFY( sanity5.size() );
   VERIFY( sanity5[1] == L'x' );
 }
+
+// libstdc++/5280
+void test03()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      test02();
+      setenv("LANG", oldLANG, 1);
+    }
+}
 #endif
 
 int main()
@@ -297,6 +314,7 @@ int main()
 #ifdef _GLIBCPP_USE_WCHAR_T
   test01();
   test02();
+  test03();
 #endif
   return 0;
 }
@@ -304,3 +322,4 @@ int main()
 
 // Diana D. Brooks, former chief executive of Sotheby's
 // art-thief extraordinaire
+
diff --git a/libstdc++-v3/testsuite/22_locale/numpunct_members_char.cc b/libstdc++-v3/testsuite/22_locale/numpunct_members_char.cc
index 901de4c1f616..862817e482f1 100644
--- a/libstdc++-v3/testsuite/22_locale/numpunct_members_char.cc
+++ b/libstdc++-v3/testsuite/22_locale/numpunct_members_char.cc
@@ -1,6 +1,6 @@
 // 2001-01-17 Benjamin Kosnik  <bkoz@redhat.com>
 
-// Copyright (C) 2001 Free Software Foundation
+// Copyright (C) 2001, 2002 Free Software Foundation
 //
 // 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
@@ -83,9 +83,25 @@ void test01()
   // VERIFY( f2 != f3 );
 }
 
+// libstdc++/5280
+void test02()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      setenv("LANG", oldLANG, 1);
+    }
+}
+
 int main()
 {
   test01();
-
+  test02();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/22_locale/numpunct_members_wchar_t.cc b/libstdc++-v3/testsuite/22_locale/numpunct_members_wchar_t.cc
index 25694f4757ad..032bd397cccd 100644
--- a/libstdc++-v3/testsuite/22_locale/numpunct_members_wchar_t.cc
+++ b/libstdc++-v3/testsuite/22_locale/numpunct_members_wchar_t.cc
@@ -1,6 +1,6 @@
 // 2001-11-20 Benjamin Kosnik  <bkoz@redhat.com>
 
-// Copyright (C) 2001 Free Software Foundation
+// Copyright (C) 2001, 2002 Free Software Foundation
 //
 // 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
@@ -80,12 +80,29 @@ void test01()
   VERIFY( dp2 != dp4 );
   VERIFY( th2 != th4 );
 }
+
+// libstdc++/5280
+void test02()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      setenv("LANG", oldLANG, 1);
+    }
+}
 #endif
 
 int main()
 {
 #ifdef _GLIBCPP_USE_WCHAR_T
   test01();
+  test02();
 #endif
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/22_locale/time_get_members_char.cc b/libstdc++-v3/testsuite/22_locale/time_get_members_char.cc
index 0bcb4c7f0608..f711ab46676f 100644
--- a/libstdc++-v3/testsuite/22_locale/time_get_members_char.cc
+++ b/libstdc++-v3/testsuite/22_locale/time_get_members_char.cc
@@ -193,6 +193,7 @@ void test02()
   //             ios_base::iostate&, tm*) const
 
   // sanity checks for "C" locale
+  iss.imbue(loc_c);
   iss.str("Sunday");
   iterator_type is_it01(iss);
   tm time01;
@@ -315,6 +316,7 @@ void test03()
   //               ios_base::iostate&, tm*) const
 
   // sanity checks for "C" locale
+  iss.imbue(loc_c);
   iss.str("April");
   iterator_type is_it01(iss);
   tm time01;
@@ -436,6 +438,7 @@ void test04()
   // get_year(iter_type, iter_type, ios_base&, ios_base::iostate&, tm*) const
 
   // sanity checks for "C" locale
+  iss.imbue(loc_c);
   iss.str("1971");
   iterator_type is_it01(iss);
   tm time01;
@@ -527,6 +530,7 @@ void test05()
   // get_date(iter_type, iter_type, ios_base&, ios_base::iostate&, tm*) const
 
   // sanity checks for "C" locale
+  iss.imbue(loc_c);
   iss.str("04/04/71");
   iterator_type is_it01(iss);
   tm time01;
@@ -672,6 +676,27 @@ void test06()
   VERIFY( rem5 ==  " Cindy Sherman" );
 }
 
+// libstdc++/5280
+void test07()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      test02();
+      test03();
+      test04();
+      test05();
+      test06();
+      setenv("LANG", oldLANG, 1);
+    }
+}
+
 int main()
 {
   test01();
@@ -681,5 +706,7 @@ int main()
   test05();
   
   test06();
+  
+  test07();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/22_locale/time_get_members_wchar_t.cc b/libstdc++-v3/testsuite/22_locale/time_get_members_wchar_t.cc
index 254461f5e62f..40485a4ce3ce 100644
--- a/libstdc++-v3/testsuite/22_locale/time_get_members_wchar_t.cc
+++ b/libstdc++-v3/testsuite/22_locale/time_get_members_wchar_t.cc
@@ -193,6 +193,7 @@ void test02()
   //             ios_base::iostate&, tm*) const
 
   // sanity checks for "C" locale
+  iss.imbue(loc_c);
   iss.str(L"Sunday");
   iterator_type is_it01(iss);
   tm time01;
@@ -315,6 +316,7 @@ void test03()
   //               ios_base::iostate&, tm*) const
 
   // sanity checks for "C" locale
+  iss.imbue(loc_c);
   iss.str(L"April");
   iterator_type is_it01(iss);
   tm time01;
@@ -436,6 +438,7 @@ void test04()
   // get_year(iter_type, iter_type, ios_base&, ios_base::iostate&, tm*) const
 
   // sanity checks for "C" locale
+  iss.imbue(loc_c);
   iss.str(L"1971");
   iterator_type is_it01(iss);
   tm time01;
@@ -527,6 +530,7 @@ void test05()
   // get_date(iter_type, iter_type, ios_base&, ios_base::iostate&, tm*) const
 
   // sanity checks for "C" locale
+  iss.imbue(loc_c);
   iss.str(L"04/04/71");
   iterator_type is_it01(iss);
   tm time01;
@@ -671,6 +675,27 @@ void test06()
   VERIFY( tm1.tm_year == time_sanity.tm_year );
   VERIFY( rem5 ==  L" Cindy Sherman" );
 }
+
+// libstdc++/5280
+void test07()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      test02();
+      test03();
+      test04();
+      test05();
+      test06();
+      setenv("LANG", oldLANG, 1);
+    }
+}
 #endif
 
 int main()
@@ -683,6 +708,8 @@ int main()
   test05();
 
   test06();
+
+  test07();
 #endif
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/22_locale/time_put_members_char.cc b/libstdc++-v3/testsuite/22_locale/time_put_members_char.cc
index f358548f762f..6051633773b1 100644
--- a/libstdc++-v3/testsuite/22_locale/time_put_members_char.cc
+++ b/libstdc++-v3/testsuite/22_locale/time_put_members_char.cc
@@ -231,9 +231,27 @@ void test02()
   VERIFY( sanity2 == "Tuesday" );
 }
 
+// libstdc++/5280
+void test03()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      test02();
+      setenv("LANG", oldLANG, 1);
+    }
+}
+
 int main()
 {
   test01();
   test02();
+  test03();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/22_locale/time_put_members_wchar_t.cc b/libstdc++-v3/testsuite/22_locale/time_put_members_wchar_t.cc
index 6bd2e3f3410e..863d47f9ace7 100644
--- a/libstdc++-v3/testsuite/22_locale/time_put_members_wchar_t.cc
+++ b/libstdc++-v3/testsuite/22_locale/time_put_members_wchar_t.cc
@@ -232,6 +232,23 @@ void test02()
   VERIFY( res == L"Tuesdayxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" );
   VERIFY( sanity2 == L"Tuesday" );
 }
+
+// libstdc++/5280
+void test03()
+{
+  // Set the global locale to non-"C".
+  std::locale loc_de("de_DE");
+  std::locale::global(loc_de);
+
+  // Set LANG environment variable to de_DE.
+  const char* oldLANG = getenv("LANG");
+  if (!setenv("LANG", "de_DE", 1))
+    {
+      test01();
+      test02();
+      setenv("LANG", oldLANG, 1);
+    }
+}
 #endif
 
 int main()
@@ -239,6 +256,7 @@ int main()
 #ifdef _GLIBCPP_USE_WCHAR_T
   test01();
   test02();
+  test03();
 #endif
   return 0;
 }
-- 
GitLab