libstdc++ PATCH: Fix failure in 22_locale/ctype_char_members.cc

Loren James Rittle rittle@latour.rsch.comm.mot.com
Thu Dec 28 16:40:00 GMT 2000


Note: Both replacement compile-time code paths in this patch were
completely and independently rebuilt and checked on
i386-unknown-freebsd4.2 in an already bootstrapped tree.  As usual, I
also hand-checked all important changes made to /usr/include/ctype.h
over the years on this system to ensure no dumb assumptions were made
by this new code.  Although it produced no noticeable testsuite errors
on this platform, the code to force all digit and xdigit mask lookups
to occur in the C locale is not proper C++ and matches no other port.

The primary bug: FreeBSD does indeed have 11 mask bits of interest.
The problem is that those 11 bits actually start in position 8 not 0
and go to 18.  There is the obvious fix of adding 8 to both
__bitmasksize's and __i's initializer.  However, I rewrote the code to
rely only on the symbolic constants.  Thus, the loop was unrolled but
not for performance reasons, rather correctness reasons (one less
thing to track against future system header changes).  Recent versions
of FreeBSD allow the lookup and masking of a table entry in one step,
thus avoiding a loop or unrolled version of same.  I also provide a
code path which uses that interface, if available (found in FreeBSD
3.5+ and 4.0+), since it makes the inline code both smaller and faster.

This FreeBSD configuration-only patch fixes:

+       +       22_locale/ctype_char_members.cc

Remaining failures (thus it appears we are at parity with most ports again):

-b      -b      23_containers/map_operators.cc
-b      -b      23_containers/set_operators.cc
-r      -r      27_io/filebuf_members.cc
	[...]/egcs/libstdc++-v3/testsuite/27_io/filebuf_members.cc:58:
	failed assertion `close_num == 0' (which I think matches AIX.)
FAIL: g++.jason/2371.C (test for excess errors)
FAIL: g++.other/crash32.C (test for excess errors)
FAIL: g++.other/loop2.C caused compiler crash

Reminder: I don't have CVS write access so I can't apply if approved.

Other libstdc++-v3 status: alpha-unknown-freebsd4.2 looks as good as
i386-unknown-freebsd4.2 for -static; nothing works with -g shared;
stripped shared looks better but still with many failures (I think I
read another alpha user, different OS with a similar report where
stripping reduced the number of failures).

I will take a look at 27_io/filebuf_members.cc's failure next year.

Regards,
Loren

2000-12-28  Loren J. Rittle  <ljrittle@acm.org>

	* config/os/bsd/freebsd/bits/ctype_inline.h (is): (Make right
	code path:) Remove magic constants and restructure to handle
	ctype.h bit mask layout changes more gracefully.  (Make fast
	code path:) Use __maskrune (), if available.
	(is): Remove special case for digit and xdigit masks.

Index: config/os/bsd/freebsd/bits/ctype_inline.h
===================================================================
RCS file: /cvs/gcc/egcs/libstdc++-v3/config/os/bsd/freebsd/bits/ctype_inline.h,v
retrieving revision 1.4
diff -c -r1.4 ctype_inline.h
*** ctype_inline.h	2000/12/19 19:48:59	1.4
--- ctype_inline.h	2000/12/28 22:57:33
***************
*** 38,65 ****
    ctype<char>::
    is(mask __m, char __c) const
    { 
!     if (__m & (digit | xdigit))
!       return __isctype(__c, __m);
!     else
!       return __istype(__c, __m);
    }
  
    const char*
    ctype<char>::
    is(const char* __low, const char* __high, mask* __vec) const
    {
-     const int __bitmasksize = 11; // Highest bitmask in ctype_base == 10
      for (;__low < __high; ++__vec, ++__low)
        {
  	mask __m = 0;
! 	int __i = 0; // Lowest bitmask in ctype_base == 0
! 	for (;__i < __bitmasksize; ++__i)
! 	  {
! 	    mask __bit = static_cast<mask>(1 << __i);
! 	    if (this->is(__bit, *__low))
! 	      __m |= __bit;
! 	  }
  	*__vec = __m;
        }
      return __high;
    }
--- 38,71 ----
    ctype<char>::
    is(mask __m, char __c) const
    { 
!     return __istype(__c, __m);
    }
  
    const char*
    ctype<char>::
    is(const char* __low, const char* __high, mask* __vec) const
    {
      for (;__low < __high; ++__vec, ++__low)
        {
+ #if defined (_CTYPE_S) || defined (__istype)
+ 	*__vec = __maskrune (*__low, upper | lower | alpha | digit | xdigit
+ 			     | space | print | graph | cntrl | punct | alnum);
+ #else
  	mask __m = 0;
! 	if (this->is(upper, *__low)) __m |= upper;
! 	if (this->is(lower, *__low)) __m |= lower;
! 	if (this->is(alpha, *__low)) __m |= alpha;
! 	if (this->is(digit, *__low)) __m |= digit;
! 	if (this->is(xdigit, *__low)) __m |= xdigit;
! 	if (this->is(space, *__low)) __m |= space;
! 	if (this->is(print, *__low)) __m |= print;
! 	if (this->is(graph, *__low)) __m |= graph;
! 	if (this->is(cntrl, *__low)) __m |= cntrl;
! 	if (this->is(punct, *__low)) __m |= punct;
! 	// Do not include explicit line for alnum mask since it is a
! 	// pure composite of masks on FreeBSD.
  	*__vec = __m;
+ #endif
        }
      return __high;
    }


More information about the Gcc-patches mailing list