Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <eblake@redhat.com>2009-10-24 17:24:29 +0400
committerEric Blake <eblake@redhat.com>2009-10-24 17:24:29 +0400
commit9b2b7c4a6ba898e98ef6c7bfb6cdf1fb3b887d5e (patch)
treeae654d919d7b0490d49c8843e1ee93c910a982ff /newlib/libc/include/ctype.h
parente83fef9d351462b7b5046ae054eb56724d704c30 (diff)
Fix isalpha(0x100000001LL) and friends on 64-bit machines.
* 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.
Diffstat (limited to 'newlib/libc/include/ctype.h')
-rw-r--r--newlib/libc/include/ctype.h34
1 files changed, 21 insertions, 13 deletions
diff --git a/newlib/libc/include/ctype.h b/newlib/libc/include/ctype.h
index e1d2d01c8..75e1c48b3 100644
--- a/newlib/libc/include/ctype.h
+++ b/newlib/libc/include/ctype.h
@@ -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