diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 89804df52952fd53912968da100ff7e0b866d28b..b86ca41f4cc5e92c8a6620e5dbfe9429040fab21 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,18 @@
+2002-09-06  Jakub Jelinek  <jakub@redhat.com>
+
+	* config/os/gnu-linux/ctype_noninline.h
+	[_GLIBCPP_USE_SHADOW_HEADERS]: Remove using _C_legacy::__ctype_*.
+	(ctype<char>::classic_table): If _GLIBCPP_C_LOCALE_GNU, return
+	_S_c_locale->__ctype_b, otherwise temporarily switch to "C" locale
+	and return __ctype_b.
+	(ctype<char>::ctype(__c_locale, const mask*, bool, size_t)): If not
+	_GLIBCPP_C_LOCALE_GNU, temporarily switch to "C" locale and
+	initialize using __ctype_{b,tolower,toupper}.
+	(ctype<char>::ctype(const mask*, bool, size_t)): If
+	_GLIBCPP_C_LOCALE_GNU, initialize using
+	_S_c_locale->__ctype_{b,tolower,toupper}, otherwise temporarily
+	switch to "C" locale and initialize using __ctype_{b,tolower,toupper}.
+
 2002-09-05  Paolo Carlini  <pcarlini@unitus.it>
             Roland McGrath  <roland@redhat.com>
 
diff --git a/libstdc++-v3/config/os/gnu-linux/ctype_noninline.h b/libstdc++-v3/config/os/gnu-linux/ctype_noninline.h
index ee70ab46c3b94af44eb2912bab950df03d489bb6..1578828ccedd5c55711edc789a994d73f063bc88 100644
--- a/libstdc++-v3/config/os/gnu-linux/ctype_noninline.h
+++ b/libstdc++-v3/config/os/gnu-linux/ctype_noninline.h
@@ -34,16 +34,32 @@
   
 // Information as gleaned from /usr/include/ctype.h
 
-#if _GLIBCPP_USE_SHADOW_HEADERS
-  using _C_legacy::__ctype_toupper;
-  using _C_legacy::__ctype_tolower;
-  using _C_legacy::__ctype_b;
-#endif
-
+#if _GLIBCPP_C_LOCALE_GNU
   const ctype_base::mask*
   ctype<char>::classic_table() throw()
-  { return __ctype_b; }  
-  
+  {
+    if (!_S_c_locale)
+      _S_create_c_locale(_S_c_locale, "C");
+    return _S_c_locale->__ctype_b;
+  }
+#else
+  const ctype_base::mask*
+  ctype<char>::classic_table() throw()
+  {
+    const ctype_base::mask* __ret;
+    char* __old = strdup(setlocale(LC_CTYPE, NULL));
+    setlocale(LC_CTYPE, "C");
+#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
+    __ret = *__ctype_b_loc();
+#else
+    __ret = __ctype_b;
+#endif
+    setlocale(LC_CTYPE, __old);
+    free(__old);
+    return __ret;
+  }
+#endif
+
 #if _GLIBCPP_C_LOCALE_GNU
   ctype<char>::ctype(__c_locale __cloc, const mask* __table, bool __del, 
 		     size_t __refs) 
@@ -57,17 +73,54 @@
 #else
   ctype<char>::ctype(__c_locale, const mask* __table, bool __del, 
 		     size_t __refs) 
-  : __ctype_abstract_base<char>(__refs), _M_del(__table != 0 && __del), 
-  _M_toupper(__ctype_toupper), _M_tolower(__ctype_tolower),
-  _M_table(__table ? __table : classic_table())
-  { _M_c_locale_ctype = _S_c_locale; }
+  : __ctype_abstract_base<char>(__refs), _M_del(__table != 0 && __del)
+  {
+    char* __old=strdup(setlocale(LC_CTYPE, NULL));
+    setlocale(LC_CTYPE, "C");
+#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
+    _M_toupper = *__ctype_toupper_loc();
+    _M_tolower = *__ctype_tolower_loc();
+    _M_table = __table ? __table : *__ctype_b_loc();
+#else
+    _M_toupper = __ctype_toupper;
+    _M_tolower = __ctype_tolower;
+    _M_table = __table ? __table : __ctype_b;
+#endif
+    setlocale(LC_CTYPE, __old);
+    free(__old);
+    _M_c_locale_ctype = _S_c_locale;
+  }
 #endif
 
+#if _GLIBCPP_C_LOCALE_GNU
+  ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) : 
+  __ctype_abstract_base<char>(__refs), _M_del(__table != 0 && __del)
+  {
+    _M_c_locale_ctype = _S_c_locale;
+    _M_toupper = _M_c_locale_ctype->__ctype_toupper;
+    _M_tolower = _M_c_locale_ctype->__ctype_tolower;
+    _M_table = __table ? __table : _M_c_locale_ctype->__ctype_b;
+  }
+#else
   ctype<char>::ctype(const mask* __table, bool __del, size_t __refs) : 
-  __ctype_abstract_base<char>(__refs), _M_del(__table != 0 && __del), 
-  _M_toupper(__ctype_toupper), _M_tolower(__ctype_tolower),
-  _M_table(__table ? __table : classic_table())
-  { _M_c_locale_ctype = _S_c_locale; }
+  __ctype_abstract_base<char>(__refs), _M_del(__table != 0 && __del)
+  {
+    char* __old=strdup(setlocale(LC_CTYPE, NULL));
+    setlocale(LC_CTYPE, "C");
+#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
+    _M_toupper = *__ctype_toupper_loc();
+    _M_tolower = *__ctype_tolower_loc();
+    _M_table = __table ? __table : *__ctype_b_loc();
+#else
+    _M_toupper = __ctype_toupper;
+    _M_tolower = __ctype_tolower;
+    _M_table = __table ? __table : __ctype_b;
+#endif
+    setlocale(LC_CTYPE, __old);
+    free(__old);
+    _M_c_locale_ctype = _S_c_locale;
+  }
+#endif
 
   char
   ctype<char>::do_toupper(char __c) const