OSDN Git Service

Fix isalpha(0x100000001LL) and friends on 64-bit machines.
authorericb <ericb>
Sat, 24 Oct 2009 22:24:28 +0000 (22:24 +0000)
committerericb <ericb>
Sat, 24 Oct 2009 22:24:28 +0000 (22:24 +0000)
* libc/include/ctype.h (__ctype_lookup): New macro.
(isalpha, isupper, islower, isdigit, isxdigit, isspace, ispunct)
(isalnum, isprint, isgraph, iscntrl, isblank): Use it to fix bug
on 64-bit machines.

newlib/ChangeLog
newlib/libc/include/ctype.h

index d384933..34eb79f 100644 (file)
@@ -1,3 +1,10 @@
+2009-10-24  Eric Blake  <ebb9@byu.net>
+
+       * libc/include/ctype.h (__ctype_lookup): New macro.
+       (isalpha, isupper, islower, isdigit, isxdigit, isspace, ispunct)
+       (isalnum, isprint, isgraph, iscntrl, isblank): Use it to fix bug
+       on 64-bit machines.
+
 2009-10-20  Jeff Johnston  <jjohnstn@redhat.com>
 
        * configure.host: Don't set -O2 flag in newlib_cflags.  Leave
@@ -27,7 +34,7 @@
 
        * libc/include/sys/config.h[__CYGWIN__]: Set __USE_XOPEN2K flag
        if not __STRICT_ANSI__ or stdc version C99 or greater.
-       * libc/include/stdio.h[__STRICT_ANSI__]: Add __USE_XOPEN2K check 
+       * libc/include/stdio.h[__STRICT_ANSI__]: Add __USE_XOPEN2K check
        for fseeko and ftello prototypes.
 
 2009-10-15  Corinna Vinschen  <corinna@vinschen.de>
 
 2009-09-22  Ralf Corsépius <ralf.corsepius@rtems.org>
 
-       * configure.host (m32c): Move setting -DABORT_PROVIDED to second 
+       * configure.host (m32c): Move setting -DABORT_PROVIDED to second
        "case $host".
 
 2009-09-18  Christopher Faylor  <me+cygwin@cgf.cx>
index e1d2d01..75e1c48 100644 (file)
@@ -47,24 +47,32 @@ extern      __IMPORT char   *__ctype_ptr__;
 #ifndef __cplusplus
 /* These macros are intentionally written in a manner that will trigger
    a gcc -Wall warning if the user mistakenly passes a 'char' instead
-   of an int containing an 'unsigned char'.  */
-#define        isalpha(__c)    ((__ctype_ptr__+1)[__c]&(_U|_L))
-#define        isupper(__c)    (((__ctype_ptr__+1)[__c]&(_U|_L))==_U)
-#define        islower(__c)    (((__ctype_ptr__+1)[__c]&(_U|_L))==_L)
-#define        isdigit(__c)    ((__ctype_ptr__+1)[__c]&_N)
-#define        isxdigit(__c)   ((__ctype_ptr__+1)[__c]&(_X|_N))
-#define        isspace(__c)    ((__ctype_ptr__+1)[__c]&_S)
-#define ispunct(__c)   ((__ctype_ptr__+1)[__c]&_P)
-#define isalnum(__c)   ((__ctype_ptr__+1)[__c]&(_U|_L|_N))
-#define isprint(__c)   ((__ctype_ptr__+1)[__c]&(_P|_U|_L|_N|_B))
-#define        isgraph(__c)    ((__ctype_ptr__+1)[__c]&(_P|_U|_L|_N))
-#define iscntrl(__c)   ((__ctype_ptr__+1)[__c]&_C)
+   of an int containing an 'unsigned char'.  Note that the sizeof will
+   always be 1, which is what we want for mapping EOF to __ctype_ptr__[0];
+   the use of a raw index inside the sizeof triggers the gcc warning if
+   __c was of type char, and sizeof masks side effects of the extra __c.
+   Meanwhile, the real index to __ctype_ptr__+1 must be cast to int,
+   since isalpha(0x100000001LL) must equal isalpha(1), rather than being
+   an out-of-bounds reference on a 64-bit machine.  */
+#define __ctype_lookup(__c) ((__ctype_ptr__+sizeof(""[__c]))[(int)__c])
+
+#define        isalpha(__c)    (__ctype_lookup(__c)&(_U|_L))
+#define        isupper(__c)    ((__ctype_lookup(__c)&(_U|_L))==_U)
+#define        islower(__c)    ((__ctype_lookup(__c)&(_U|_L))==_L)
+#define        isdigit(__c)    (__ctype_lookup(__c)&_N)
+#define        isxdigit(__c)   (__ctype_lookup(__c)&(_X|_N))
+#define        isspace(__c)    (__ctype_lookup(__c)&_S)
+#define ispunct(__c)   (__ctype_lookup(__c)&_P)
+#define isalnum(__c)   (__ctype_lookup(__c)&(_U|_L|_N))
+#define isprint(__c)   (__ctype_lookup(__c)&(_P|_U|_L|_N|_B))
+#define        isgraph(__c)    (__ctype_lookup(__c)&(_P|_U|_L|_N))
+#define iscntrl(__c)   (__ctype_lookup(__c)&_C)
 
 #if defined(__GNUC__) && \
     (!defined(__STRICT_ANSI__) || __STDC_VERSION__ >= 199901L)
 #define isblank(__c) \
   __extension__ ({ __typeof__ (__c) __x = (__c);               \
-      ((__ctype_ptr__+1)[__x]&_B) || (__x) == '\t';})
+        (__ctype_lookup(__x)&_B) || (int) (__x) == '\t';})
 #endif