This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix libstdc++ usage of __ctype_b/__ctype_to*


On Sun, Sep 01, 2002 at 12:28:50PM -0700, Ulrich Drepper wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Jakub Jelinek wrote:
> 
> > Well, I don't think it is that clear, since libstdc++-v3's private use
> > of __uselocale will not be in the way and if uselocale(NULL) != LC_GLOBAL_LOCALE,
>  > [...]
> 
> Let's do this:
> 
> revert the changes to the ctype.h headers.  Users will see possibly 
> incorrect results for th ectype functions if uselocale is used.  This is 
> temporarily and can easily be worked around by the use of the _l variants.
> 
> Once we have __thread support in the exported headers we will provide 
> appropriate replacements for __ctype_b etc with will work transparently 
> in most cases.  Maybe some code in libstdc++ has to change but that's a 
> separate issue.

Ok, I finally looked into the standard.

>From what I can read in ISO C++98, ctype<char>::classic_table() is supposed to
return LC_CTYPE __ctype_b mask table for the "C" locale (22.2.1.3.3), ie. my
reading of the source is that the current implementation is wrong.
It should return _S_c_locale->__ctype_b and if newlocale is not
supported it should either play with setlocale, or return its own array.
Returning __ctype_b is correct only if setlocale hasn't been called yet or
last has been called with LC_CTYPE or LC_ALL, "C".

And ctype<char>::ctype(const mask* __table, bool __del, size_t __refs)
constructor looks like it is supposed to use the user provided __table
if non-NULL, otherwise classic_table() (that's just a guess, I actually
couldn't find the exact wording anywhere, but it makes sense
to me, especially in the presence of ctype_byname and
ctype(__c_locale, ...)). So, all in all, I think really nothing has to
change in glibc CVS to make libstdc++-v3 happy (ie. __ctype_b doesn't
really have to be exported as default symver, at least not for
libstdc++-v3).

The following patch (on top of my 2002-08-30 and earlier 2002-09-01
patch) builds with current CVS glibc and passes its testsuite
with the expected:
# of expected passes            408
# of unexpected failures        1
# of unexpected successes       26

Ok to commit?

2002-09-01  Jakub Jelinek  <jakub@redhat.com>

	* config/os/gnu-linux/bits/ctype_noninline.h
	(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}.

--- libstdc++-v3/config/os/gnu-linux/bits/ctype_noninline.h.jj	2002-04-23 20:30:31.000000000 +0200
+++ libstdc++-v3/config/os/gnu-linux/bits/ctype_noninline.h	2002-09-01 22:32:32.000000000 +0200
@@ -34,16 +34,34 @@
   
 // Information as gleaned from /usr/include/ctype.h
 
-#if _GLIBCPP_USE_SHADOW_HEADERS
+#if _GLIBCPP_C_LOCALE_GNU
+  const ctype_base::mask*
+  ctype<char>::classic_table() throw()
+  {
+    if (!_S_c_locale)
+      _S_create_c_locale(_S_c_locale, "C");
+    return _S_c_locale->__ctype_b;
+  }
+#else
+# if _GLIBCPP_USE_SHADOW_HEADERS
   using _C_legacy::__ctype_toupper;
   using _C_legacy::__ctype_tolower;
   using _C_legacy::__ctype_b;
-#endif
+# endif
 
   const ctype_base::mask*
   ctype<char>::classic_table() throw()
-  { return __ctype_b; }  
-  
+  {
+    const ctype_base::mask* __ret;
+    char* __old = strdup(setlocale(LC_CTYPE, NULL));
+    setlocale(LC_CTYPE, "C");
+    __ret = __ctype_b;
+    setlocale(__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 +75,43 @@
 #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");
+    _M_toupper = __ctype_toupper;
+    _M_tolower = __ctype_tolower;
+    _M_table = __table ? __table : __ctype_b;
+    setlocale(__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_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)
+  {
+    _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(__c_locale, const mask* __table, bool __del,
+		     size_t __refs) 
+  : __ctype_abstract_base<char>(__refs), _M_del(__table != 0 && __del)
+  {
+    char* __old=strdup(setlocale(LC_CTYPE, NULL));
+    setlocale(LC_CTYPE, "C");
+    _M_toupper = __ctype_toupper;
+    _M_tolower = __ctype_tolower;
+    _M_table = __table ? __table : __ctype_b;
+    setlocale(__old);
+    free(__old);
+    _M_c_locale_ctype = _S_c_locale;
+  }
+#endif
 
   char
   ctype<char>::do_toupper(char __c) const


	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]