changeset 37796:145459a7a273

c-ctype: do not worry about EBCDIC + char signed Drop support for EBCDIC with char being signed, as this breaks too many programs. Problem reported by Ben Pfaff in: http://lists.gnu.org/archive/html/bug-gnulib/2015-09/msg00053.html * lib/c-ctype.h: Verify that we are not using EBCDIC with char being signed. (_C_CTYPE_LOWER_A_THRU_F_N): New macro. (_C_CTYPE_LOWER_N, _C_CTYPE_A_THRU_F): Use it. (_C_CTYPE_DIGIT, _C_CTYPE_LOWER, _C_CTYPE_PUNCT, _C_CTYPE_UPPER): (c_isascii, c_isgraph, c_isprint, c_ispunct, c_tolower, c_toupper): * tests/test-c-ctype.c (test_all): Simplify by assuming standard char values cannot be negative. * tests/test-c-ctype.c (NCHARS, to_char): Remove; all uses removed.
author Paul Eggert <eggert@cs.ucla.edu>
date Sat, 26 Sep 2015 23:55:07 -0700
parents 792fb9e8b55b
children c43a8498ce0a
files ChangeLog lib/c-ctype.h tests/test-c-ctype.c
diffstat 3 files changed, 87 insertions(+), 554 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Sep 25 19:45:59 2015 -0700
+++ b/ChangeLog	Sat Sep 26 23:55:07 2015 -0700
@@ -1,3 +1,19 @@
+2015-09-26  Paul Eggert  <eggert@cs.ucla.edu>
+
+	c-ctype: do not worry about EBCDIC + char signed
+	Drop support for EBCDIC with char being signed, as this breaks too
+	many programs.  Problem reported by Ben Pfaff in:
+	http://lists.gnu.org/archive/html/bug-gnulib/2015-09/msg00053.html
+	* lib/c-ctype.h: Verify that we are not using EBCDIC with
+	char being signed.
+	(_C_CTYPE_LOWER_A_THRU_F_N): New macro.
+	(_C_CTYPE_LOWER_N, _C_CTYPE_A_THRU_F): Use it.
+	(_C_CTYPE_DIGIT, _C_CTYPE_LOWER, _C_CTYPE_PUNCT, _C_CTYPE_UPPER):
+	(c_isascii, c_isgraph, c_isprint, c_ispunct, c_tolower, c_toupper):
+	* tests/test-c-ctype.c (test_all):
+	Simplify by assuming standard char values cannot be negative.
+	* tests/test-c-ctype.c (NCHARS, to_char): Remove; all uses removed.
+
 2015-09-25  Paul Eggert  <eggert@cs.ucla.edu>
 
 	c-ctype: port better to z/OS EBCDIC
--- a/lib/c-ctype.h	Fri Sep 25 19:45:59 2015 -0700
+++ b/lib/c-ctype.h	Sat Sep 26 23:55:07 2015 -0700
@@ -78,7 +78,9 @@
 # error "Only ASCII and EBCDIC are supported"
 #endif
 
-#define _C_CTYPE_SIGNED_EBCDIC ('A' < 0)
+#if 'A' < 0
+# error "EBCDIC and char is signed -- not supported"
+#endif
 
 /* Cases for control characters.  */
 
@@ -111,54 +113,30 @@
     case '\x3d': case '\x3f'
 #endif
 
-/* Cases for hex letter digits, digits, lower, and upper, offset by N.  */
+/* Cases for lowercase hex letters, and lowercase letters, all offset by N.  */
 
-#define _C_CTYPE_A_THRU_F_N(n) \
-   case 'a' + (n): case 'b' + (n): case 'c' + (n): case 'd' + (n): \
-   case 'e' + (n): case 'f' + (n): \
-   case 'A' + (n): case 'B' + (n): case 'C' + (n): case 'D' + (n): \
-   case 'E' + (n): case 'F' + (n)
-#define _C_CTYPE_DIGIT_N(n) \
-   case '0' + (n): case '1' + (n): case '2' + (n): case '3' + (n): \
-   case '4' + (n): case '5' + (n): case '6' + (n): case '7' + (n): \
-   case '8' + (n): case '9' + (n)
-#define _C_CTYPE_LOWER_N(n) \
+#define _C_CTYPE_LOWER_A_THRU_F_N(n) \
    case 'a' + (n): case 'b' + (n): case 'c' + (n): case 'd' + (n): \
-   case 'e' + (n): case 'f' + (n): case 'g' + (n): case 'h' + (n): \
-   case 'i' + (n): case 'j' + (n): case 'k' + (n): case 'l' + (n): \
-   case 'm' + (n): case 'n' + (n): case 'o' + (n): case 'p' + (n): \
-   case 'q' + (n): case 'r' + (n): case 's' + (n): case 't' + (n): \
-   case 'u' + (n): case 'v' + (n): case 'w' + (n): case 'x' + (n): \
-   case 'y' + (n): case 'z' + (n)
-#define _C_CTYPE_UPPER_N(n) \
-   case 'A' + (n): case 'B' + (n): case 'C' + (n): case 'D' + (n): \
-   case 'E' + (n): case 'F' + (n): case 'G' + (n): case 'H' + (n): \
-   case 'I' + (n): case 'J' + (n): case 'K' + (n): case 'L' + (n): \
-   case 'M' + (n): case 'N' + (n): case 'O' + (n): case 'P' + (n): \
-   case 'Q' + (n): case 'R' + (n): case 'S' + (n): case 'T' + (n): \
-   case 'U' + (n): case 'V' + (n): case 'W' + (n): case 'X' + (n): \
-   case 'Y' + (n): case 'Z' + (n)
+   case 'e' + (n): case 'f' + (n)
+#define _C_CTYPE_LOWER_N(n) \
+   _C_CTYPE_LOWER_A_THRU_F_N(n): \
+   case 'g' + (n): case 'h' + (n): case 'i' + (n): case 'j' + (n): \
+   case 'k' + (n): case 'l' + (n): case 'm' + (n): case 'n' + (n): \
+   case 'o' + (n): case 'p' + (n): case 'q' + (n): case 'r' + (n): \
+   case 's' + (n): case 't' + (n): case 'u' + (n): case 'v' + (n): \
+   case 'w' + (n): case 'x' + (n): case 'y' + (n): case 'z' + (n)
 
-/* Given MACRO_N, expand to all the cases for the corresponding class.  */
-#if _C_CTYPE_SIGNED_EBCDIC
-# define _C_CTYPE_CASES(macro_n) macro_n (0): macro_n (256)
-#else
-# define _C_CTYPE_CASES(macro_n) macro_n (0)
-#endif
-
-/* Cases for hex letter digits, digits, lower, and upper, with another
-   case for unsigned char if the original char is negative.  */
+/* Cases for hex letters, digits, lower, punct, and upper.  */
 
-#define _C_CTYPE_A_THRU_F _C_CTYPE_CASES (_C_CTYPE_A_THRU_F_N)
-#define _C_CTYPE_DIGIT _C_CTYPE_CASES (_C_CTYPE_DIGIT_N)
-#define _C_CTYPE_LOWER _C_CTYPE_CASES (_C_CTYPE_LOWER_N)
-#define _C_CTYPE_UPPER _C_CTYPE_CASES (_C_CTYPE_UPPER_N)
-
-/* The punct class differs because some punctuation characters may be
-   negative while others are nonnegative.  Instead of attempting to
-   define _C_CTYPE_PUNCT, define just the plain chars here, and do any
-   cases-plus-256 by hand after using this macro.  */
-#define _C_CTYPE_PUNCT_PLAIN \
+#define _C_CTYPE_A_THRU_F \
+   _C_CTYPE_LOWER_A_THRU_F_N (0): \
+   _C_CTYPE_LOWER_A_THRU_F_N ('A' - 'a')
+#define _C_CTYPE_DIGIT                     \
+   case '0': case '1': case '2': case '3': \
+   case '4': case '5': case '6': case '7': \
+   case '8': case '9'
+#define _C_CTYPE_LOWER _C_CTYPE_LOWER_N (0)
+#define _C_CTYPE_PUNCT \
    case '!': case '"': case '#': case '$':  \
    case '%': case '&': case '\'': case '(': \
    case ')': case '*': case '+': case ',':  \
@@ -167,6 +145,8 @@
    case '?': case '@': case '[': case '\\': \
    case ']': case '^': case '_': case '`':  \
    case '{': case '|': case '}': case '~'
+#define _C_CTYPE_UPPER _C_CTYPE_LOWER_N ('A' - 'a')
+
 
 /* Function definitions.  */
 
@@ -194,7 +174,6 @@
     _C_CTYPE_LOWER:
     _C_CTYPE_UPPER:
       return true;
-
     default:
       return false;
     }
@@ -208,7 +187,6 @@
     _C_CTYPE_LOWER:
     _C_CTYPE_UPPER:
       return true;
-
     default:
       return false;
     }
@@ -225,107 +203,9 @@
     _C_CTYPE_CNTRL:
     _C_CTYPE_DIGIT:
     _C_CTYPE_LOWER:
+    _C_CTYPE_PUNCT:
     _C_CTYPE_UPPER:
-
-    _C_CTYPE_PUNCT_PLAIN:
-#if '!' < 0
-    case '!' + 256:
-#endif
-#if '"' < 0
-    case '"' + 256:
-#endif
-#if '#' < 0
-    case '#' + 256:
-#endif
-#if '$' < 0
-    case '$' + 256:
-#endif
-#if '%' < 0
-    case '%' + 256:
-#endif
-#if '&' < 0
-    case '&' + 256:
-#endif
-#if '\'' < 0
-    case '\'' + 256:
-#endif
-#if '(' < 0
-    case '(' + 256:
-#endif
-#if ')' < 0
-    case ')' + 256:
-#endif
-#if '*' < 0
-    case '*' + 256:
-#endif
-#if '+' < 0
-    case '+' + 256:
-#endif
-#if ',' < 0
-    case ',' + 256:
-#endif
-#if '-' < 0
-    case '-' + 256:
-#endif
-#if '.' < 0
-    case '.' + 256:
-#endif
-#if '/' < 0
-    case '/' + 256:
-#endif
-#if ':' < 0
-    case ':' + 256:
-#endif
-#if ';' < 0
-    case ';' + 256:
-#endif
-#if '<' < 0
-    case '<' + 256:
-#endif
-#if '=' < 0
-    case '=' + 256:
-#endif
-#if '>' < 0
-    case '>' + 256:
-#endif
-#if '?' < 0
-    case '?' + 256:
-#endif
-#if '@' < 0
-    case '@' + 256:
-#endif
-#if '[' < 0
-    case '[' + 256:
-#endif
-#if '\\' < 0
-    case '\\' + 256:
-#endif
-#if ']' < 0
-    case ']' + 256:
-#endif
-#if '^' < 0
-    case '^' + 256:
-#endif
-#if '_' < 0
-    case '_' + 256:
-#endif
-#if '`' < 0
-    case '`' + 256:
-#endif
-#if '{' < 0
-    case '{' + 256:
-#endif
-#if '|' < 0
-    case '|' + 256:
-#endif
-#if '}' < 0
-    case '}' + 256:
-#endif
-#if '~' < 0
-    case '~' + 256:
-#endif
       return true;
-
     default:
       return false;
     }
@@ -368,107 +248,9 @@
     {
     _C_CTYPE_DIGIT:
     _C_CTYPE_LOWER:
+    _C_CTYPE_PUNCT:
     _C_CTYPE_UPPER:
-
-    _C_CTYPE_PUNCT_PLAIN:
-#if '!' < 0
-    case '!' + 256:
-#endif
-#if '"' < 0
-    case '"' + 256:
-#endif
-#if '#' < 0
-    case '#' + 256:
-#endif
-#if '$' < 0
-    case '$' + 256:
-#endif
-#if '%' < 0
-    case '%' + 256:
-#endif
-#if '&' < 0
-    case '&' + 256:
-#endif
-#if '\'' < 0
-    case '\'' + 256:
-#endif
-#if '(' < 0
-    case '(' + 256:
-#endif
-#if ')' < 0
-    case ')' + 256:
-#endif
-#if '*' < 0
-    case '*' + 256:
-#endif
-#if '+' < 0
-    case '+' + 256:
-#endif
-#if ',' < 0
-    case ',' + 256:
-#endif
-#if '-' < 0
-    case '-' + 256:
-#endif
-#if '.' < 0
-    case '.' + 256:
-#endif
-#if '/' < 0
-    case '/' + 256:
-#endif
-#if ':' < 0
-    case ':' + 256:
-#endif
-#if ';' < 0
-    case ';' + 256:
-#endif
-#if '<' < 0
-    case '<' + 256:
-#endif
-#if '=' < 0
-    case '=' + 256:
-#endif
-#if '>' < 0
-    case '>' + 256:
-#endif
-#if '?' < 0
-    case '?' + 256:
-#endif
-#if '@' < 0
-    case '@' + 256:
-#endif
-#if '[' < 0
-    case '[' + 256:
-#endif
-#if '\\' < 0
-    case '\\' + 256:
-#endif
-#if ']' < 0
-    case ']' + 256:
-#endif
-#if '^' < 0
-    case '^' + 256:
-#endif
-#if '_' < 0
-    case '_' + 256:
-#endif
-#if '`' < 0
-    case '`' + 256:
-#endif
-#if '{' < 0
-    case '{' + 256:
-#endif
-#if '|' < 0
-    case '|' + 256:
-#endif
-#if '}' < 0
-    case '}' + 256:
-#endif
-#if '~' < 0
-    case '~' + 256:
-#endif
       return true;
-
     default:
       return false;
     }
@@ -494,107 +276,9 @@
     case ' ':
     _C_CTYPE_DIGIT:
     _C_CTYPE_LOWER:
+    _C_CTYPE_PUNCT:
     _C_CTYPE_UPPER:
-
-    _C_CTYPE_PUNCT_PLAIN:
-#if '!' < 0
-    case '!' + 256:
-#endif
-#if '"' < 0
-    case '"' + 256:
-#endif
-#if '#' < 0
-    case '#' + 256:
-#endif
-#if '$' < 0
-    case '$' + 256:
-#endif
-#if '%' < 0
-    case '%' + 256:
-#endif
-#if '&' < 0
-    case '&' + 256:
-#endif
-#if '\'' < 0
-    case '\'' + 256:
-#endif
-#if '(' < 0
-    case '(' + 256:
-#endif
-#if ')' < 0
-    case ')' + 256:
-#endif
-#if '*' < 0
-    case '*' + 256:
-#endif
-#if '+' < 0
-    case '+' + 256:
-#endif
-#if ',' < 0
-    case ',' + 256:
-#endif
-#if '-' < 0
-    case '-' + 256:
-#endif
-#if '.' < 0
-    case '.' + 256:
-#endif
-#if '/' < 0
-    case '/' + 256:
-#endif
-#if ':' < 0
-    case ':' + 256:
-#endif
-#if ';' < 0
-    case ';' + 256:
-#endif
-#if '<' < 0
-    case '<' + 256:
-#endif
-#if '=' < 0
-    case '=' + 256:
-#endif
-#if '>' < 0
-    case '>' + 256:
-#endif
-#if '?' < 0
-    case '?' + 256:
-#endif
-#if '@' < 0
-    case '@' + 256:
-#endif
-#if '[' < 0
-    case '[' + 256:
-#endif
-#if '\\' < 0
-    case '\\' + 256:
-#endif
-#if ']' < 0
-    case ']' + 256:
-#endif
-#if '^' < 0
-    case '^' + 256:
-#endif
-#if '_' < 0
-    case '_' + 256:
-#endif
-#if '`' < 0
-    case '`' + 256:
-#endif
-#if '{' < 0
-    case '{' + 256:
-#endif
-#if '|' < 0
-    case '|' + 256:
-#endif
-#if '}' < 0
-    case '}' + 256:
-#endif
-#if '~' < 0
-    case '~' + 256:
-#endif
       return true;
-
     default:
       return false;
     }
@@ -605,105 +289,8 @@
 {
   switch (c)
     {
-    _C_CTYPE_PUNCT_PLAIN:
-#if '!' < 0
-    case '!' + 256:
-#endif
-#if '"' < 0
-    case '"' + 256:
-#endif
-#if '#' < 0
-    case '#' + 256:
-#endif
-#if '$' < 0
-    case '$' + 256:
-#endif
-#if '%' < 0
-    case '%' + 256:
-#endif
-#if '&' < 0
-    case '&' + 256:
-#endif
-#if '\'' < 0
-    case '\'' + 256:
-#endif
-#if '(' < 0
-    case '(' + 256:
-#endif
-#if ')' < 0
-    case ')' + 256:
-#endif
-#if '*' < 0
-    case '*' + 256:
-#endif
-#if '+' < 0
-    case '+' + 256:
-#endif
-#if ',' < 0
-    case ',' + 256:
-#endif
-#if '-' < 0
-    case '-' + 256:
-#endif
-#if '.' < 0
-    case '.' + 256:
-#endif
-#if '/' < 0
-    case '/' + 256:
-#endif
-#if ':' < 0
-    case ':' + 256:
-#endif
-#if ';' < 0
-    case ';' + 256:
-#endif
-#if '<' < 0
-    case '<' + 256:
-#endif
-#if '=' < 0
-    case '=' + 256:
-#endif
-#if '>' < 0
-    case '>' + 256:
-#endif
-#if '?' < 0
-    case '?' + 256:
-#endif
-#if '@' < 0
-    case '@' + 256:
-#endif
-#if '[' < 0
-    case '[' + 256:
-#endif
-#if '\\' < 0
-    case '\\' + 256:
-#endif
-#if ']' < 0
-    case ']' + 256:
-#endif
-#if '^' < 0
-    case '^' + 256:
-#endif
-#if '_' < 0
-    case '_' + 256:
-#endif
-#if '`' < 0
-    case '`' + 256:
-#endif
-#if '{' < 0
-    case '{' + 256:
-#endif
-#if '|' < 0
-    case '|' + 256:
-#endif
-#if '}' < 0
-    case '}' + 256:
-#endif
-#if '~' < 0
-    case '~' + 256:
-#endif
+    _C_CTYPE_PUNCT:
       return true;
-
     default:
       return false;
     }
@@ -741,7 +328,6 @@
     _C_CTYPE_DIGIT:
     _C_CTYPE_A_THRU_F:
       return true;
-
     default:
       return false;
     }
@@ -752,14 +338,8 @@
 {
   switch (c)
     {
-    _C_CTYPE_UPPER_N (0):
-#if _C_CTYPE_SIGNED_EBCDIC
-      c += 256;
-      /* Fall through.  */
-    _C_CTYPE_UPPER_N (256):
-#endif
+    _C_CTYPE_UPPER:
       return c - 'A' + 'a';
-
     default:
       return c;
     }
@@ -770,14 +350,8 @@
 {
   switch (c)
     {
-    _C_CTYPE_LOWER_N (0):
-#if _C_CTYPE_SIGNED_EBCDIC
-      c += 256;
-      /* Fall through.  */
-    _C_CTYPE_LOWER_N (256):
-#endif
+    _C_CTYPE_LOWER:
       return c - 'a' + 'A';
-
     default:
       return c;
     }
--- a/tests/test-c-ctype.c	Fri Sep 25 19:45:59 2015 -0700
+++ b/tests/test-c-ctype.c	Sat Sep 26 23:55:07 2015 -0700
@@ -26,16 +26,6 @@
 
 #include "macros.h"
 
-enum { NCHARS = UCHAR_MAX + 1 };
-
-static char
-to_char (int c)
-{
-  if (CHAR_MIN < 0 && CHAR_MAX < c)
-    return c - CHAR_MAX - 1 + CHAR_MIN;
-  return c;
-}
-
 static void
 test_agree_with_C_locale (void)
 {
@@ -72,27 +62,30 @@
 
   for (c = CHAR_MIN; c <= UCHAR_MAX; c++)
     {
-      if (c < 0)
+      if (! (0 <= c && c <= CHAR_MAX))
         {
-          ASSERT (c_isascii (c) == c_isascii (c + NCHARS));
-          ASSERT (c_isalnum (c) == c_isalnum (c + NCHARS));
-          ASSERT (c_isalpha (c) == c_isalpha (c + NCHARS));
-          ASSERT (c_isblank (c) == c_isblank (c + NCHARS));
-          ASSERT (c_iscntrl (c) == c_iscntrl (c + NCHARS));
-          ASSERT (c_isdigit (c) == c_isdigit (c + NCHARS));
-          ASSERT (c_islower (c) == c_islower (c + NCHARS));
-          ASSERT (c_isgraph (c) == c_isgraph (c + NCHARS));
-          ASSERT (c_isprint (c) == c_isprint (c + NCHARS));
-          ASSERT (c_ispunct (c) == c_ispunct (c + NCHARS));
-          ASSERT (c_isspace (c) == c_isspace (c + NCHARS));
-          ASSERT (c_isupper (c) == c_isupper (c + NCHARS));
-          ASSERT (c_isxdigit (c) == c_isxdigit (c + NCHARS));
-          ASSERT (to_char (c_tolower (c)) == to_char (c_tolower (c + NCHARS)));
-          ASSERT (to_char (c_toupper (c)) == to_char (c_toupper (c + NCHARS)));
+          ASSERT (! c_isascii (c));
+          ASSERT (! c_isalnum (c));
+          ASSERT (! c_isalpha (c));
+          ASSERT (! c_isblank (c));
+          ASSERT (! c_iscntrl (c));
+          ASSERT (! c_isdigit (c));
+          ASSERT (! c_islower (c));
+          ASSERT (! c_isgraph (c));
+          ASSERT (! c_isprint (c));
+          ASSERT (! c_ispunct (c));
+          ASSERT (! c_isspace (c));
+          ASSERT (! c_isupper (c));
+          ASSERT (! c_isxdigit (c));
+          ASSERT (c_tolower (c) == c);
+          ASSERT (c_toupper (c) == c);
         }
 
-      if (0 <= c)
-        n_isascii += c_isascii (c);
+      n_isascii += c_isascii (c);
+
+#ifdef C_CTYPE_ASCII
+      ASSERT (c_isascii (c) == (0 <= c && c <= 0x7f));
+#endif
 
       ASSERT (c_isascii (c) == (c_isprint (c) || c_iscntrl (c)));
 
@@ -100,7 +93,7 @@
 
       ASSERT (c_isalpha (c) == (c_islower (c) || c_isupper (c)));
 
-      switch (to_char (c))
+      switch (c)
         {
         case '\t': case ' ':
           ASSERT (c_isblank (c) == 1);
@@ -114,9 +107,17 @@
       ASSERT (c_iscntrl (c) == ((c >= 0 && c < 0x20) || c == 0x7f));
 #endif
 
+      switch (c)
+        {
+        case '\a': case '\b': case '\f': case '\n':
+        case '\r': case '\t': case '\v':
+          ASSERT (c_iscntrl (c));
+          break;
+        }
+
       ASSERT (! (c_iscntrl (c) && c_isprint (c)));
 
-      switch (to_char (c))
+      switch (c)
         {
         case '0': case '1': case '2': case '3': case '4': case '5':
         case '6': case '7': case '8': case '9':
@@ -127,7 +128,7 @@
           break;
         }
 
-      switch (to_char (c))
+      switch (c)
         {
         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
@@ -135,9 +136,11 @@
         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
         case 'y': case 'z':
           ASSERT (c_islower (c) == 1);
+          ASSERT (c_toupper (c) == c - 'a' + 'A');
           break;
         default:
           ASSERT (c_islower (c) == 0);
+          ASSERT (c_toupper (c) == c);
           break;
         }
 
@@ -151,7 +154,7 @@
 
       ASSERT (c_isprint (c) == (c_isgraph (c) || c == ' '));
 
-      switch (to_char (c))
+      switch (c)
         {
         case '!': case '"': case '#': case '$': case '%': case '&': case '\'':
         case '(': case ')': case '*': case '+': case ',': case '-': case '.':
@@ -165,7 +168,7 @@
           break;
         }
 
-      switch (to_char (c))
+      switch (c)
         {
         case ' ': case '\t': case '\n': case '\v': case '\f': case '\r':
           ASSERT (c_isspace (c) == 1);
@@ -175,7 +178,7 @@
           break;
         }
 
-      switch (to_char (c))
+      switch (c)
         {
         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
         case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
@@ -183,13 +186,15 @@
         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
         case 'Y': case 'Z':
           ASSERT (c_isupper (c) == 1);
+          ASSERT (c_tolower (c) == c - 'A' + 'a');
           break;
         default:
           ASSERT (c_isupper (c) == 0);
+          ASSERT (c_tolower (c) == c);
           break;
         }
 
-      switch (to_char (c))
+      switch (c)
         {
         case '0': case '1': case '2': case '3': case '4': case '5':
         case '6': case '7': case '8': case '9':
@@ -201,68 +206,6 @@
           ASSERT (c_isxdigit (c) == 0);
           break;
         }
-
-      switch (to_char (c))
-        {
-        case 'A': ASSERT (to_char (c_tolower (c)) == 'a'); break;
-        case 'B': ASSERT (to_char (c_tolower (c)) == 'b'); break;
-        case 'C': ASSERT (to_char (c_tolower (c)) == 'c'); break;
-        case 'D': ASSERT (to_char (c_tolower (c)) == 'd'); break;
-        case 'E': ASSERT (to_char (c_tolower (c)) == 'e'); break;
-        case 'F': ASSERT (to_char (c_tolower (c)) == 'f'); break;
-        case 'G': ASSERT (to_char (c_tolower (c)) == 'g'); break;
-        case 'H': ASSERT (to_char (c_tolower (c)) == 'h'); break;
-        case 'I': ASSERT (to_char (c_tolower (c)) == 'i'); break;
-        case 'J': ASSERT (to_char (c_tolower (c)) == 'j'); break;
-        case 'K': ASSERT (to_char (c_tolower (c)) == 'k'); break;
-        case 'L': ASSERT (to_char (c_tolower (c)) == 'l'); break;
-        case 'M': ASSERT (to_char (c_tolower (c)) == 'm'); break;
-        case 'N': ASSERT (to_char (c_tolower (c)) == 'n'); break;
-        case 'O': ASSERT (to_char (c_tolower (c)) == 'o'); break;
-        case 'P': ASSERT (to_char (c_tolower (c)) == 'p'); break;
-        case 'Q': ASSERT (to_char (c_tolower (c)) == 'q'); break;
-        case 'R': ASSERT (to_char (c_tolower (c)) == 'r'); break;
-        case 'S': ASSERT (to_char (c_tolower (c)) == 's'); break;
-        case 'T': ASSERT (to_char (c_tolower (c)) == 't'); break;
-        case 'U': ASSERT (to_char (c_tolower (c)) == 'u'); break;
-        case 'V': ASSERT (to_char (c_tolower (c)) == 'v'); break;
-        case 'W': ASSERT (to_char (c_tolower (c)) == 'w'); break;
-        case 'X': ASSERT (to_char (c_tolower (c)) == 'x'); break;
-        case 'Y': ASSERT (to_char (c_tolower (c)) == 'y'); break;
-        case 'Z': ASSERT (to_char (c_tolower (c)) == 'z'); break;
-        default: ASSERT (c_tolower (c) == c); break;
-        }
-
-      switch (to_char (c))
-        {
-        case 'a': ASSERT (to_char (c_toupper (c)) == 'A'); break;
-        case 'b': ASSERT (to_char (c_toupper (c)) == 'B'); break;
-        case 'c': ASSERT (to_char (c_toupper (c)) == 'C'); break;
-        case 'd': ASSERT (to_char (c_toupper (c)) == 'D'); break;
-        case 'e': ASSERT (to_char (c_toupper (c)) == 'E'); break;
-        case 'f': ASSERT (to_char (c_toupper (c)) == 'F'); break;
-        case 'g': ASSERT (to_char (c_toupper (c)) == 'G'); break;
-        case 'h': ASSERT (to_char (c_toupper (c)) == 'H'); break;
-        case 'i': ASSERT (to_char (c_toupper (c)) == 'I'); break;
-        case 'j': ASSERT (to_char (c_toupper (c)) == 'J'); break;
-        case 'k': ASSERT (to_char (c_toupper (c)) == 'K'); break;
-        case 'l': ASSERT (to_char (c_toupper (c)) == 'L'); break;
-        case 'm': ASSERT (to_char (c_toupper (c)) == 'M'); break;
-        case 'n': ASSERT (to_char (c_toupper (c)) == 'N'); break;
-        case 'o': ASSERT (to_char (c_toupper (c)) == 'O'); break;
-        case 'p': ASSERT (to_char (c_toupper (c)) == 'P'); break;
-        case 'q': ASSERT (to_char (c_toupper (c)) == 'Q'); break;
-        case 'r': ASSERT (to_char (c_toupper (c)) == 'R'); break;
-        case 's': ASSERT (to_char (c_toupper (c)) == 'S'); break;
-        case 't': ASSERT (to_char (c_toupper (c)) == 'T'); break;
-        case 'u': ASSERT (to_char (c_toupper (c)) == 'U'); break;
-        case 'v': ASSERT (to_char (c_toupper (c)) == 'V'); break;
-        case 'w': ASSERT (to_char (c_toupper (c)) == 'W'); break;
-        case 'x': ASSERT (to_char (c_toupper (c)) == 'X'); break;
-        case 'y': ASSERT (to_char (c_toupper (c)) == 'Y'); break;
-        case 'z': ASSERT (to_char (c_toupper (c)) == 'Z'); break;
-        default: ASSERT (c_toupper (c) == c); break;
-        }
     }
 
   ASSERT (n_isascii == 128);