bug-gnulib@gnu.org mirror (unofficial)
 help / color / mirror / Atom feed
From: Paul Eggert <eggert@cs.ucla.edu>
To: "Daniel Richard G." <skunk@iSKUNK.ORG>, bug-gnulib@gnu.org
Subject: Re: [PATCH] IBM z/OS + EBCDIC support
Date: Tue, 22 Sep 2015 12:32:05 -0700	[thread overview]
Message-ID: <5601ACB5.3010005@cs.ucla.edu> (raw)
In-Reply-To: <1442888927.2328038.389926169.50DB0133@webmail.messagingengine.com>

[-- Attachment #1: Type: text/plain, Size: 1647 bytes --]

Thanks for looking into this.  I have some questions about the c-ctype 
changes.  It appears that the proposed patch defers to the system 
functions (which use the current locale), but that's not the intent of 
c-ctype: it's supposed to correspond to a stripped down POSIX "C" locale 
regardless of the current locale settings.  Is there something special 
in z/OS that requires using the system functions?  (E.g., does the "C" 
locale behave differently depending on some *other* setting regarding 
character set?)

With the above in mind, it's not clear what c_isascii should do. Should 
it return 1 for bytes in the range 0..127, or for bytes that correspond 
to ASCII bytes if one assumes the standard translation from EBCDIC code 
page 037 to ASCII?  (Is there a standard?)  If the former, the current 
code is OK; if the latter, does the system isascii always return the 
same results regardless of locale and do these results make sense?

Anyway, in looking through the code I see that it's hard to test a port 
to EBCDIC because it uses ifdef rather than if, and I do see some 
promotion bugs that you noted but we can fix these with inline functions 
rather than macros (cleaner and safer nowadays), and there are a few 
other style glitches (e.g., boolean values, overuse of >=) so I 
installed the attached patch.  This patch assumes EBCDIC control 
characters are either less than ' ' or are all 1 bits, which I think is 
right.  The patch also tightens up the tests a bit.

This patch doesn't address the isascii problem, nor the "something 
special in z/OS" problem, so quite possibly further patches will be 
needed to this module.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-c-ctype-port-better-to-EBCDIC.patch --]
[-- Type: text/x-patch; name="0001-c-ctype-port-better-to-EBCDIC.patch", Size: 20517 bytes --]

>From 1b0f778e32f73c8601e7c517a0b83098996363a9 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Tue, 22 Sep 2015 12:17:06 -0700
Subject: [PATCH] c-ctype: port better to EBCDIC

Problems reported by Daniel Richard G. in
http://lists.gnu.org/archive/html/bug-gnulib/2015-09/msg00020.html
* lib/c-ctype.c: Include <limits.h>, for CHAR_MIN and CHAR_MAX.
Include "verify.h".
(C_CTYPE_ASCII, C_CTYPE_CONSECUTIVE_DIGITS)
(C_CTYPE_CONSECUTIVE_LOWERCASE, C_CTYPE_CONSECUTIVE_UPPERCASE):
Define as enum constants with value false, if not defined, so that
code can use 'if' instead of 'ifdef'.  Using 'if' helps make the
code more portable, as both branches of the 'if' are compiled on
all platforms.
(C_CTYPE_EBCDIC): New constant.
(to_char): New static function.
(c_isalnum, c_isalpha, c_isdigit, c_islower, c_isgraph, c_isprint)
(c_ispunct, c_isupper, c_isxdigit, c_tolower, c_toupper):
Rewrite to use 'if' instead of 'ifdef'.
Use to_char if non-ASCII.  Prefer <= to >=.
Prefer true and false to 1 and 0, for booleans.
(c_iscntrl): Use 'if', not 'ifdef'.  Special case for EBCDIC.
Verify that the character set is either ASCII or EBCDIC.
* tests/test-c-ctype.c: Include <limits.h>, for CHAR_MIN
(to_char): New function.
(test_all): Port to EBCDIC.  Add some more tests, e.g., for c_ispunct.
---
 ChangeLog            |  26 ++++++
 lib/c-ctype.c        | 253 ++++++++++++++++++++++++++-------------------------
 tests/test-c-ctype.c | 106 +++++++++++----------
 3 files changed, 216 insertions(+), 169 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index c552225..8723b38 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2015-09-22  Paul Eggert  <eggert@cs.ucla.edu>
+
+	c-ctype: port better to EBCDIC
+	Problems reported by Daniel Richard G. in
+	http://lists.gnu.org/archive/html/bug-gnulib/2015-09/msg00020.html
+	* lib/c-ctype.c: Include <limits.h>, for CHAR_MIN and CHAR_MAX.
+	Include "verify.h".
+	(C_CTYPE_ASCII, C_CTYPE_CONSECUTIVE_DIGITS)
+	(C_CTYPE_CONSECUTIVE_LOWERCASE, C_CTYPE_CONSECUTIVE_UPPERCASE):
+	Define as enum constants with value false, if not defined, so that
+	code can use 'if' instead of 'ifdef'.  Using 'if' helps make the
+	code more portable, as both branches of the 'if' are compiled on
+	all platforms.
+	(C_CTYPE_EBCDIC): New constant.
+	(to_char): New static function.
+	(c_isalnum, c_isalpha, c_isdigit, c_islower, c_isgraph, c_isprint)
+	(c_ispunct, c_isupper, c_isxdigit, c_tolower, c_toupper):
+	Rewrite to use 'if' instead of 'ifdef'.
+	Use to_char if non-ASCII.  Prefer <= to >=.
+	Prefer true and false to 1 and 0, for booleans.
+	(c_iscntrl): Use 'if', not 'ifdef'.  Special case for EBCDIC.
+	Verify that the character set is either ASCII or EBCDIC.
+	* tests/test-c-ctype.c: Include <limits.h>, for CHAR_MIN
+	(to_char): New function.
+	(test_all): Port to EBCDIC.  Add some more tests, e.g., for c_ispunct.
+
 2015-09-21  Pádraig Brady  <P@draigBrady.com>
 
 	nanosleep: fix return code for interrupted replacement
diff --git a/lib/c-ctype.c b/lib/c-ctype.c
index 6635d34..916d46e 100644
--- a/lib/c-ctype.c
+++ b/lib/c-ctype.c
@@ -21,6 +21,34 @@ along with this program; if not, see <http://www.gnu.org/licenses/>.  */
 #define NO_C_CTYPE_MACROS
 #include "c-ctype.h"
 
+#include <limits.h>
+#include "verify.h"
+
+#ifndef C_CTYPE_ASCII
+enum { C_CTYPE_ASCII = false };
+#endif
+#ifndef C_CTYPE_CONSECUTIVE_DIGITS
+enum { C_CTYPE_CONSECUTIVE_DIGITS = false };
+#endif
+#ifndef C_CTYPE_CONSECUTIVE_LOWERCASE
+enum { C_CTYPE_CONSECUTIVE_LOWERCASE = false };
+#endif
+#ifndef C_CTYPE_CONSECUTIVE_UPPERCASE
+enum { C_CTYPE_CONSECUTIVE_UPPERCASE = false };
+#endif
+
+/* Convert an int, which may be promoted from either an unsigned or a
+   signed char, to the corresponding char.  */
+
+static char
+to_char (int c)
+{
+  enum { nchars = CHAR_MAX - CHAR_MIN + 1 };
+  if (CHAR_MIN < 0 && CHAR_MAX < c && c < nchars)
+    return c - nchars;
+  return c;
+}
+
 /* The function isascii is not locale dependent. Its use in EBCDIC is
    questionable. */
 bool
@@ -32,18 +60,20 @@ c_isascii (int c)
 bool
 c_isalnum (int c)
 {
-#if C_CTYPE_CONSECUTIVE_DIGITS \
-    && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
-#if C_CTYPE_ASCII
-  return ((c >= '0' && c <= '9')
-          || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'Z'));
-#else
-  return ((c >= '0' && c <= '9')
-          || (c >= 'A' && c <= 'Z')
-          || (c >= 'a' && c <= 'z'));
-#endif
-#else
-  switch (c)
+  if (C_CTYPE_CONSECUTIVE_DIGITS
+      && C_CTYPE_CONSECUTIVE_UPPERCASE
+      && C_CTYPE_CONSECUTIVE_LOWERCASE)
+    {
+      if (C_CTYPE_ASCII)
+        return (('0' <= c && c <= '9')
+                || ('A' <= (c & ~0x20) && (c & ~0x20) <= 'Z'));
+      else
+        return (('0' <= c && c <= '9')
+                || ('A' <= c && c <= 'Z')
+                || ('a' <= c && c <= 'z'));
+    }
+
+  switch (to_char (c))
     {
     case '0': case '1': case '2': case '3': case '4': case '5':
     case '6': case '7': case '8': case '9':
@@ -57,24 +87,24 @@ c_isalnum (int c)
     case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
     case 's': case 't': case 'u': case 'v': case 'w': case 'x':
     case 'y': case 'z':
-      return 1;
+      return true;
     default:
-      return 0;
+      return false;
     }
-#endif
 }
 
 bool
 c_isalpha (int c)
 {
-#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
-#if C_CTYPE_ASCII
-  return ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'Z');
-#else
-  return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
-#endif
-#else
-  switch (c)
+  if (C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE)
+    {
+      if (C_CTYPE_ASCII)
+        return 'A' <= (c & ~0x20) && (c & ~0x20) <= 'Z';
+      else
+        return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
+    }
+
+  switch (to_char (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':
@@ -86,11 +116,10 @@ c_isalpha (int c)
     case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
     case 's': case 't': case 'u': case 'v': case 'w': case 'x':
     case 'y': case 'z':
-      return 1;
+      return true;
     default:
-      return 0;
+      return false;
     }
-#endif
 }
 
 bool
@@ -102,81 +131,65 @@ c_isblank (int c)
 bool
 c_iscntrl (int c)
 {
-#if C_CTYPE_ASCII
-  return ((c & ~0x1f) == 0 || c == 0x7f);
-#else
-  switch (c)
-    {
-    case ' ': case '!': case '"': case '#': case '$': case '%':
-    case '&': case '\'': case '(': case ')': case '*': case '+':
-    case ',': case '-': case '.': case '/':
-    case '0': case '1': case '2': case '3': case '4': case '5':
-    case '6': case '7': case '8': case '9':
-    case ':': case ';': case '<': case '=': case '>': case '?':
-    case '@':
-    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
-    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
-    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
-    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
-    case 'Y': case 'Z':
-    case '[': case '\\': case ']': case '^': case '_': case '`':
-    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
-    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
-    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
-    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
-    case 'y': case 'z':
-    case '{': case '|': case '}': case '~':
-      return 0;
-    default:
-      return 1;
-    }
-#endif
+  enum { C_CTYPE_EBCDIC = (' ' == 64 && '0' == 240
+                           && 'A' == 193 && 'J' == 209 && 'S' == 226
+                           && 'A' == 129 && 'J' == 145 && 'S' == 162) };
+  verify (C_CTYPE_ASCII || C_CTYPE_EBCDIC);
+
+  if (0 <= c && c < ' ')
+    return true;
+  if (C_CTYPE_ASCII)
+    return c == 0x7f;
+  else
+    return c == 0xff || c == -1;
 }
 
 bool
 c_isdigit (int c)
 {
-#if C_CTYPE_CONSECUTIVE_DIGITS
-  return (c >= '0' && c <= '9');
-#else
+  if (C_CTYPE_ASCII)
+    return '0' <= c && c <= '9';
+
+  c = to_char (c);
+  if (C_CTYPE_CONSECUTIVE_DIGITS)
+    return '0' <= c && c <= '9';
+
   switch (c)
     {
     case '0': case '1': case '2': case '3': case '4': case '5':
     case '6': case '7': case '8': case '9':
-      return 1;
+      return true;
     default:
-      return 0;
+      return false;
     }
-#endif
 }
 
 bool
 c_islower (int c)
 {
-#if C_CTYPE_CONSECUTIVE_LOWERCASE
-  return (c >= 'a' && c <= 'z');
-#else
-  switch (c)
+  if (C_CTYPE_CONSECUTIVE_LOWERCASE)
+    return 'a' <= c && c <= 'z';
+
+  switch (to_char (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':
     case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
     case 's': case 't': case 'u': case 'v': case 'w': case 'x':
     case 'y': case 'z':
-      return 1;
+      return true;
     default:
-      return 0;
+      return false;
     }
-#endif
 }
 
 bool
 c_isgraph (int c)
 {
-#if C_CTYPE_ASCII
-  return (c >= '!' && c <= '~');
-#else
-  switch (c)
+  if (C_CTYPE_ASCII)
+    return '!' <= c && c <= '~';
+
+  switch (to_char (c))
     {
     case '!': case '"': case '#': case '$': case '%': case '&':
     case '\'': case '(': case ')': case '*': case '+': case ',':
@@ -197,20 +210,19 @@ c_isgraph (int c)
     case 's': case 't': case 'u': case 'v': case 'w': case 'x':
     case 'y': case 'z':
     case '{': case '|': case '}': case '~':
-      return 1;
+      return true;
     default:
-      return 0;
+      return false;
     }
-#endif
 }
 
 bool
 c_isprint (int c)
 {
-#if C_CTYPE_ASCII
-  return (c >= ' ' && c <= '~');
-#else
-  switch (c)
+  if (C_CTYPE_ASCII)
+    return ' ' <= c && c <= '~';
+
+  switch (to_char (c))
     {
     case ' ': case '!': case '"': case '#': case '$': case '%':
     case '&': case '\'': case '(': case ')': case '*': case '+':
@@ -231,22 +243,21 @@ c_isprint (int c)
     case 's': case 't': case 'u': case 'v': case 'w': case 'x':
     case 'y': case 'z':
     case '{': case '|': case '}': case '~':
-      return 1;
+      return true;
     default:
-      return 0;
+      return false;
     }
-#endif
 }
 
 bool
 c_ispunct (int c)
 {
-#if C_CTYPE_ASCII
-  return ((c >= '!' && c <= '~')
-          && !((c >= '0' && c <= '9')
-               || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'Z')));
-#else
-  switch (c)
+  if (C_CTYPE_ASCII)
+    return (('!' <= c && c <= '~')
+            && !(('0' <= c && c <= '9')
+                 || ('A' <= (c & ~0x20) && (c & ~0x20) <= 'Z')));
+
+  switch (to_char (c))
     {
     case '!': case '"': case '#': case '$': case '%': case '&':
     case '\'': case '(': case ')': case '*': case '+': case ',':
@@ -255,11 +266,10 @@ c_ispunct (int c)
     case '@':
     case '[': case '\\': case ']': case '^': case '_': case '`':
     case '{': case '|': case '}': case '~':
-      return 1;
+      return true;
     default:
-      return 0;
+      return false;
     }
-#endif
 }
 
 bool
@@ -272,57 +282,56 @@ c_isspace (int c)
 bool
 c_isupper (int c)
 {
-#if C_CTYPE_CONSECUTIVE_UPPERCASE
-  return (c >= 'A' && c <= 'Z');
-#else
-  switch (c)
+  if (C_CTYPE_CONSECUTIVE_UPPERCASE)
+    return 'A' <= c && c <= 'Z';
+
+  switch (to_char (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':
     case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
     case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
     case 'Y': case 'Z':
-      return 1;
+      return true;
     default:
-      return 0;
+      return false;
     }
-#endif
 }
 
 bool
 c_isxdigit (int c)
 {
-#if C_CTYPE_CONSECUTIVE_DIGITS \
-    && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
-#if C_CTYPE_ASCII
-  return ((c >= '0' && c <= '9')
-          || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'F'));
-#else
-  return ((c >= '0' && c <= '9')
-          || (c >= 'A' && c <= 'F')
-          || (c >= 'a' && c <= 'f'));
-#endif
-#else
-  switch (c)
+  if (C_CTYPE_CONSECUTIVE_DIGITS
+      && C_CTYPE_CONSECUTIVE_UPPERCASE
+      && C_CTYPE_CONSECUTIVE_LOWERCASE)
+    {
+      if ('0' <= c && c <= '9')
+        return true;
+      if (C_CTYPE_ASCII)
+        return 'A' <= (c & ~0x20) && (c & ~0x20) <= 'F';
+      return (('A' <= c && c <= 'F')
+              || ('a' <= c && c <= 'f'));
+    }
+
+  switch (to_char (c))
     {
     case '0': case '1': case '2': case '3': case '4': case '5':
     case '6': case '7': case '8': case '9':
     case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
     case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
-      return 1;
+      return true;
     default:
-      return 0;
+      return false;
     }
-#endif
 }
 
 int
 c_tolower (int c)
 {
-#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
-  return (c >= 'A' && c <= 'Z' ? c - 'A' + 'a' : c);
-#else
-  switch (c)
+  if (C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE)
+    return c_isupper (c) ? c - 'A' + 'a' : c;
+
+  switch (to_char (c))
     {
     case 'A': return 'a';
     case 'B': return 'b';
@@ -352,16 +361,15 @@ c_tolower (int c)
     case 'Z': return 'z';
     default: return c;
     }
-#endif
 }
 
 int
 c_toupper (int c)
 {
-#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
-  return (c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c);
-#else
-  switch (c)
+  if (C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE)
+    return c_islower (c) ? c - 'a' + 'A' : c;
+
+  switch (to_char (c))
     {
     case 'a': return 'A';
     case 'b': return 'B';
@@ -391,5 +399,4 @@ c_toupper (int c)
     case 'z': return 'Z';
     default: return c;
     }
-#endif
 }
diff --git a/tests/test-c-ctype.c b/tests/test-c-ctype.c
index 81fe936..63d0af9 100644
--- a/tests/test-c-ctype.c
+++ b/tests/test-c-ctype.c
@@ -20,10 +20,19 @@
 
 #include "c-ctype.h"
 
+#include <limits.h>
 #include <locale.h>
 
 #include "macros.h"
 
+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_all (void)
 {
@@ -31,49 +40,32 @@ test_all (void)
 
   for (c = -0x80; c < 0x100; c++)
     {
-      ASSERT (c_isascii (c) == (c >= 0 && c < 0x80));
-
-      switch (c)
+      if (c < 0)
         {
-        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
-        case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
-        case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
-        case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
-        case 'Y': case 'Z':
-        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
-        case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
-        case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
-        case 's': case 't': case 'u': case 'v': case 'w': case 'x':
-        case 'y': case 'z':
-        case '0': case '1': case '2': case '3': case '4': case '5':
-        case '6': case '7': case '8': case '9':
-          ASSERT (c_isalnum (c) == 1);
-          break;
-        default:
-          ASSERT (c_isalnum (c) == 0);
-          break;
+          ASSERT (c_isascii (c) == c_isascii (c + 0x100));
+          ASSERT (c_isalnum (c) == c_isalnum (c + 0x100));
+          ASSERT (c_isalpha (c) == c_isalpha (c + 0x100));
+          ASSERT (c_isblank (c) == c_isblank (c + 0x100));
+          ASSERT (c_iscntrl (c) == c_iscntrl (c + 0x100));
+          ASSERT (c_isdigit (c) == c_isdigit (c + 0x100));
+          ASSERT (c_islower (c) == c_islower (c + 0x100));
+          ASSERT (c_isgraph (c) == c_isgraph (c + 0x100));
+          ASSERT (c_isprint (c) == c_isprint (c + 0x100));
+          ASSERT (c_ispunct (c) == c_ispunct (c + 0x100));
+          ASSERT (c_isspace (c) == c_isspace (c + 0x100));
+          ASSERT (c_isupper (c) == c_isupper (c + 0x100));
+          ASSERT (c_isxdigit (c) == c_isxdigit (c + 0x100));
+          ASSERT (to_char (c_tolower (c)) == to_char (c_tolower (c + 0x100)));
+          ASSERT (to_char (c_toupper (c)) == to_char (c_toupper (c + 0x100)));
         }
 
-      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':
-        case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
-        case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
-        case 'Y': case 'Z':
-        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
-        case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
-        case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
-        case 's': case 't': case 'u': case 'v': case 'w': case 'x':
-        case 'y': case 'z':
-          ASSERT (c_isalpha (c) == 1);
-          break;
-        default:
-          ASSERT (c_isalpha (c) == 0);
-          break;
-        }
+      ASSERT (c_isascii (c) == (c >= 0 && c < 0x80));
+
+      ASSERT (c_isalnum (c) == (c_isalpha (c) || c_isdigit (c)));
+
+      ASSERT (c_isalpha (c) == (c_islower (c) || c_isupper (c)));
 
-      switch (c)
+      switch (to_char (c))
         {
         case '\t': case ' ':
           ASSERT (c_isblank (c) == 1);
@@ -83,9 +75,13 @@ test_all (void)
           break;
         }
 
+#ifdef C_CTYPE_ASCII
       ASSERT (c_iscntrl (c) == ((c >= 0 && c < 0x20) || c == 0x7f));
+#endif
 
-      switch (c)
+      ASSERT (! (c_iscntrl (c) && c_isprint (c)));
+
+      switch (to_char (c))
         {
         case '0': case '1': case '2': case '3': case '4': case '5':
         case '6': case '7': case '8': case '9':
@@ -96,7 +92,7 @@ test_all (void)
           break;
         }
 
-      switch (c)
+      switch (to_char (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':
@@ -110,13 +106,31 @@ test_all (void)
           break;
         }
 
+#ifdef C_CTYPE_ASCII
       ASSERT (c_isgraph (c) == ((c >= 0x20 && c < 0x7f) && c != ' '));
 
       ASSERT (c_isprint (c) == (c >= 0x20 && c < 0x7f));
+#endif
+
+      ASSERT (c_isgraph (c) == (c_isalnum (c) || c_ispunct (c)));
+
+      ASSERT (c_isprint (c) == (c_isgraph (c) || c == ' '));
 
-      ASSERT (c_ispunct (c) == (c_isgraph (c) && !c_isalnum (c)));
+      switch (to_char (c))
+        {
+        case '!': case '"': case '#': case '$': case '%': case '&': case '\'':
+        case '(': case ')': case '*': case '+': case ',': case '-': case '.':
+        case '/': case ':': case ';': case '<': case '=': case '>': case '?':
+        case '@': case '[': case'\\': case ']': case '^': case '_': case '`':
+        case '{': case '|': case '}': case '~':
+          ASSERT (c_ispunct (c) == 1);
+          break;
+        default:
+          ASSERT (c_ispunct (c) == 0);
+          break;
+        }
 
-      switch (c)
+      switch (to_char (c))
         {
         case ' ': case '\t': case '\n': case '\v': case '\f': case '\r':
           ASSERT (c_isspace (c) == 1);
@@ -126,7 +140,7 @@ test_all (void)
           break;
         }
 
-      switch (c)
+      switch (to_char (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':
@@ -140,7 +154,7 @@ test_all (void)
           break;
         }
 
-      switch (c)
+      switch (to_char (c))
         {
         case '0': case '1': case '2': case '3': case '4': case '5':
         case '6': case '7': case '8': case '9':
@@ -153,7 +167,7 @@ test_all (void)
           break;
         }
 
-      switch (c)
+      switch (to_char (c))
         {
         case 'A':
           ASSERT (c_tolower (c) == 'a');
-- 
2.1.0


  parent reply	other threads:[~2015-09-22 19:32 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-22  2:28 [PATCH] IBM z/OS + EBCDIC support Daniel Richard G.
2015-09-22 15:23 ` Eric Blake
2015-09-22 19:27   ` Daniel Richard G.
2015-09-22 20:00     ` Paul Eggert
2015-09-22 20:08       ` Eric Blake
2015-09-22 20:51         ` Daniel Richard G.
2015-09-22 19:32 ` Paul Eggert [this message]
2015-09-22 19:46   ` Paul Eggert
2015-09-22 20:37   ` Daniel Richard G.
2015-09-22 22:03     ` Paul Eggert
2015-09-22 23:44       ` Daniel Richard G.
2015-09-23  2:02         ` Paul Eggert
2015-09-23  6:58           ` Daniel Richard G.
2015-09-23 19:05             ` Paul Eggert
2015-09-23 19:29             ` Paul Eggert
2015-09-23 21:57               ` Daniel Richard G.
2015-09-25  7:29                 ` Paul Eggert
2015-09-26  0:25                   ` Daniel Richard G.
2015-09-26  2:49                     ` Paul Eggert
2015-09-26  4:39                       ` Daniel Richard G.
2015-09-26 16:08                         ` Ben Pfaff
2015-09-27  6:31                           ` Daniel Richard G.
2015-09-27  6:59                             ` Paul Eggert
2015-09-28  2:09                               ` Daniel Richard G.
2015-10-15  4:49                               ` Daniel Richard G.
2016-08-18  0:47                                 ` Paul Eggert
2016-08-18  8:24                                   ` Daniel Richard G.
2016-08-18  8:53                                     ` Paul Eggert
2016-08-19  8:20                                       ` Daniel Richard G.
2016-08-19 11:03                                         ` Bruno Haible
2016-08-19 19:28                                         ` Paul Eggert
2016-08-19 20:38                                           ` Daniel Richard G.
2019-12-19  4:57                                 ` z/OS configure triple Bruno Haible
2019-12-20  0:22                                   ` Daniel Richard G.
2019-12-20  6:29                                     ` Bruno Haible
2019-12-19  5:16                                 ` z/OS, iconv, and charset aliases Bruno Haible
2019-12-19  5:21                                   ` Bruno Haible
2019-12-20  4:38                                   ` Daniel Richard G.
2019-12-20  8:19                                     ` Bruno Haible
2019-12-20 18:23                                       ` Daniel Richard G.
2019-12-21  5:49                                         ` z/OS, iconv, and gperf Bruno Haible
2020-01-09  5:48                                           ` Daniel Richard G.
2020-01-19 21:52                                             ` Bruno Haible
2020-01-19 21:59                                             ` Bruno Haible
2020-01-19 22:32                                               ` Daniel Richard G.
2020-01-20  0:13                                                 ` Bruno Haible
2020-01-22  6:38                                                   ` Daniel Richard G.
2015-09-22 19:50 ` [PATCH] IBM z/OS + EBCDIC support Paul Eggert
2015-09-22 20:47   ` Daniel Richard G.

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://lists.gnu.org/mailman/listinfo/bug-gnulib

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5601ACB5.3010005@cs.ucla.edu \
    --to=eggert@cs.ucla.edu \
    --cc=bug-gnulib@gnu.org \
    --cc=skunk@iSKUNK.ORG \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).