bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] c-ctype: rewrite to use inline functions


From: Paul Eggert
Subject: [PATCH] c-ctype: rewrite to use inline functions
Date: Fri, 25 Sep 2015 00:16:25 -0700

This simplifies maintenance, since it makes for just one
implementation of each function, letting the compiler have the fun
of optimization.  In practice this works well nowadays with GCC.
E.g., c_isascii might need only three instructions even though the
source code lists every ASCII character individually in a large
switch statement.
Also, fix some z/OS porting bugs reported by Daniel Richard G. in:
http://lists.gnu.org/archive/html/bug-gnulib/2015-09/msg00037.html
* NEWS: Document the API change.
* lib/c-ctype.c: Drastically simplify, since this now just expands
inline functions.
* lib/c-ctype.h: Use _GL_INLINE_HEADER_BEGIN, _GL_INLINE_HEADER_END.
(C_CTYPE_INLINE): New macro.
(C_CTYPE_CONSECUTIVE_DIGITS, C_CTYPE_CONSECUTIVE_LOWERCASE)
(C_CTYPE_CONSECUTIVE_UPPERCASE): Remove.
Verify that either ASCII or EBCDIC is being used.
(_C_CTYPE_SIGNED_EBCDIC, _C_CTYPE_CNTRL, _C_CTYPE_A_THRU_F_N)
(_C_CTYPE_DIGIT_N, _C_CTYPE_LOWER_N, _C_CTYPE_UPPER_N)
(_C_CTYPE_CASES, _C_CTYPE_A_THRU_F, _C_CTYPE_DIGIT, _C_CTYPE_LOWER)
(_C_CTYPE_UPPER, _C_CTYPE_PUNCT_PLAIN):
New private macros.
(_C_CTYPE_CNTRL): In EBCDIC, '\x07' is a control, not '\xff'.
(c_isalnum, c_isalpha, c_isascii, c_isblank, c_iscntrl, c_isdigit)
(c_isgraph, c_islower, c_isprint, c_ispunct, c_isspace, c_isupper)
(c_isxdigit, c_tolower, c_toupper): Now inline functions.
(c_tolower, c_toupper): When converting, return the unsigned char,
as that is what z/OS does.
* lib/c-strcaseeq.h (CASEEQ): Simplify in the light of the removal
of some c-ctype.h macros.
* modules/c-ctype (Depends-on): Add extern-inline; remove verify.
* tests/test-c-ctype.c (test_all): Fix test for c_toupper and
c_tolower promotion to be compatible with z/OS.
---
 ChangeLog            |  36 +++
 NEWS                 |   5 +
 lib/c-ctype.c        | 458 +--------------------------
 lib/c-ctype.h        | 850 ++++++++++++++++++++++++++++++++++++++++-----------
 lib/c-strcaseeq.h    |   3 -
 modules/c-ctype      |   2 +-
 tests/test-c-ctype.c | 270 ++++------------
 7 files changed, 772 insertions(+), 852 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 81a5326..3768f3d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,39 @@
+2015-09-25  Paul Eggert  <address@hidden>
+
+       c-ctype: rewrite to use inline functions
+       This simplifies maintenance, since it makes for just one
+       implementation of each function, letting the compiler have the fun
+       of optimization.  In practice this works well nowadays with GCC.
+       E.g., c_isascii might need only three instructions even though the
+       source code lists every ASCII character individually in a large
+       switch statement.
+       Also, fix some z/OS porting bugs reported by Daniel Richard G. in:
+       http://lists.gnu.org/archive/html/bug-gnulib/2015-09/msg00037.html
+       * NEWS: Document the API change.
+       * lib/c-ctype.c: Drastically simplify, since this now just expands
+       inline functions.
+       * lib/c-ctype.h: Use _GL_INLINE_HEADER_BEGIN, _GL_INLINE_HEADER_END.
+       (C_CTYPE_INLINE): New macro.
+       (C_CTYPE_CONSECUTIVE_DIGITS, C_CTYPE_CONSECUTIVE_LOWERCASE)
+       (C_CTYPE_CONSECUTIVE_UPPERCASE): Remove.
+       Verify that either ASCII or EBCDIC is being used.
+       (_C_CTYPE_SIGNED_EBCDIC, _C_CTYPE_CNTRL, _C_CTYPE_A_THRU_F_N)
+       (_C_CTYPE_DIGIT_N, _C_CTYPE_LOWER_N, _C_CTYPE_UPPER_N)
+       (_C_CTYPE_CASES, _C_CTYPE_A_THRU_F, _C_CTYPE_DIGIT, _C_CTYPE_LOWER)
+       (_C_CTYPE_UPPER, _C_CTYPE_PUNCT_PLAIN):
+       New private macros.
+       (_C_CTYPE_CNTRL): In EBCDIC, '\x07' is a control, not '\xff'.
+       (c_isalnum, c_isalpha, c_isascii, c_isblank, c_iscntrl, c_isdigit)
+       (c_isgraph, c_islower, c_isprint, c_ispunct, c_isspace, c_isupper)
+       (c_isxdigit, c_tolower, c_toupper): Now inline functions.
+       (c_tolower, c_toupper): When converting, return the unsigned char,
+       as that is what z/OS does.
+       * lib/c-strcaseeq.h (CASEEQ): Simplify in the light of the removal
+       of some c-ctype.h macros.
+       * modules/c-ctype (Depends-on): Add extern-inline; remove verify.
+       * tests/test-c-ctype.c (test_all): Fix test for c_toupper and
+       c_tolower promotion to be compatible with z/OS.
+
 2015-09-24  Pavel Raiskup  <address@hidden>
 
        gitlog-to-changelog: trim only trailing whitespaces
diff --git a/NEWS b/NEWS
index 55f60fd..122abf5 100644
--- a/NEWS
+++ b/NEWS
@@ -42,6 +42,11 @@ User visible incompatible changes
 
 Date        Modules         Changes
 
+2015-09-25  c-ctype         The following macros were removed:
+                            C_CTYPE_CONSECUTIVE_DIGITS
+                            C_CTYPE_CONSECUTIVE_LOWERCASE
+                            C_CTYPE_CONSECUTIVE_UPPERCASE
+
 2015-09-22  savewd          SAVEWD_CHDIR_READABLE constant removed.
 
 2015-07-24  fprintftime     Exported functions' time zone arguments are now of
diff --git a/lib/c-ctype.c b/lib/c-ctype.c
index a3913a1..5d9d4d8 100644
--- a/lib/c-ctype.c
+++ b/lib/c-ctype.c
@@ -1,459 +1,3 @@
-/* Character handling in C locale.
-
-   Copyright 2000-2003, 2006, 2009-2015 Free Software Foundation, Inc.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, see <http://www.gnu.org/licenses/>.  */
-
 #include <config.h>
-
-/* Specification.  */
-#define NO_C_CTYPE_MACROS
+#define C_CTYPE_INLINE _GL_EXTERN_INLINE
 #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
-
-enum
-  {
-    /* True if this appears to be a host using EBCDIC.  */
-    C_CTYPE_EBCDIC = (' ' == '\x40' && '0' == '\xf0'
-                      && 'A' == '\xc1' && 'J' == '\xd1' && 'S' == '\xe2'
-                      && 'a' == '\x81' && 'j' == '\x91' && 's' == '\xa2')
-  };
-
-/* The implementation currently supports ASCII and EBCDIC.  */
-verify (C_CTYPE_ASCII || C_CTYPE_EBCDIC);
-
-/* 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
-c_isascii (int c)
-{
-  if (C_CTYPE_ASCII)
-    return 0 <= c && c <= 0x7f;
-
-  /* Use EBCDIC code page 1047's assignments for ASCII control chars;
-     assume all EBCDIC code pages agree about these assignments.  */
-  switch (to_char (c))
-    {
-    case '\x00': case '\x01': case '\x02': case '\x03': case '\x05':
-    case '\x0b': case '\x0c': case '\x0d': case '\x0e': case '\x0f':
-    case '\x10': case '\x11': case '\x12': case '\x13': case '\x15':
-    case '\x16': case '\x18': case '\x19': case '\x1c': case '\x1d':
-    case '\x1e': case '\x1f': case '\x26': case '\x27': case '\x2d':
-    case '\x2e': case '\x2f': case '\x32': case '\x37': case '\x3c':
-    case '\x3d': case '\x3f': case '\xff':
-    case '\xff' < 0 ? 0xff : -1:
-
-    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 true;
-    default:
-      return false;
-    }
-}
-
-bool
-c_isalnum (int 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':
-    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':
-      return true;
-    default:
-      return false;
-    }
-}
-
-bool
-c_isalpha (int 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':
-    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':
-      return true;
-    default:
-      return false;
-    }
-}
-
-bool
-c_isblank (int c)
-{
-  return (c == ' ' || c == '\t');
-}
-
-bool
-c_iscntrl (int c)
-{
-  if (C_CTYPE_ASCII)
-    return (0 <= c && c < ' ') || c == 0x7f;
-
-  /* Use EBCDIC code page 1047's assignments for ASCII control chars;
-     assume all EBCDIC code pages agree about these assignments.  */
-  switch (c)
-    {
-    case '\x00': case '\x01': case '\x02': case '\x03': case '\x05':
-    case '\x0b': case '\x0c': case '\x0d': case '\x0e': case '\x0f':
-    case '\x10': case '\x11': case '\x12': case '\x13': case '\x15':
-    case '\x16': case '\x18': case '\x19': case '\x1c': case '\x1d':
-    case '\x1e': case '\x1f': case '\x26': case '\x27': case '\x2d':
-    case '\x2e': case '\x2f': case '\x32': case '\x37': case '\x3c':
-    case '\x3d': case '\x3f': case '\xff':
-    case '\xff' < 0 ? 0xff : -1:
-      return true;
-    default:
-      return false;
-    }
-}
-
-bool
-c_isdigit (int c)
-{
-  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 true;
-    default:
-      return false;
-    }
-}
-
-bool
-c_islower (int 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 true;
-    default:
-      return false;
-    }
-}
-
-bool
-c_isgraph (int c)
-{
-  if (C_CTYPE_ASCII)
-    return '!' <= c && c <= '~';
-
-  switch (to_char (c))
-    {
-    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 true;
-    default:
-      return false;
-    }
-}
-
-bool
-c_isprint (int c)
-{
-  if (C_CTYPE_ASCII)
-    return ' ' <= c && c <= '~';
-
-  switch (to_char (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 true;
-    default:
-      return false;
-    }
-}
-
-bool
-c_ispunct (int 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 ',':
-    case '-': case '.': case '/':
-    case ':': case ';': case '<': case '=': case '>': case '?':
-    case '@':
-    case '[': case '\\': case ']': case '^': case '_': case '`':
-    case '{': case '|': case '}': case '~':
-      return true;
-    default:
-      return false;
-    }
-}
-
-bool
-c_isspace (int c)
-{
-  return (c == ' ' || c == '\t'
-          || c == '\n' || c == '\v' || c == '\f' || c == '\r');
-}
-
-bool
-c_isupper (int 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 true;
-    default:
-      return false;
-    }
-}
-
-bool
-c_isxdigit (int 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 true;
-    default:
-      return false;
-    }
-}
-
-int
-c_tolower (int 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';
-    case 'C': return 'c';
-    case 'D': return 'd';
-    case 'E': return 'e';
-    case 'F': return 'f';
-    case 'G': return 'g';
-    case 'H': return 'h';
-    case 'I': return 'i';
-    case 'J': return 'j';
-    case 'K': return 'k';
-    case 'L': return 'l';
-    case 'M': return 'm';
-    case 'N': return 'n';
-    case 'O': return 'o';
-    case 'P': return 'p';
-    case 'Q': return 'q';
-    case 'R': return 'r';
-    case 'S': return 's';
-    case 'T': return 't';
-    case 'U': return 'u';
-    case 'V': return 'v';
-    case 'W': return 'w';
-    case 'X': return 'x';
-    case 'Y': return 'y';
-    case 'Z': return 'z';
-    default: return c;
-    }
-}
-
-int
-c_toupper (int 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';
-    case 'c': return 'C';
-    case 'd': return 'D';
-    case 'e': return 'E';
-    case 'f': return 'F';
-    case 'g': return 'G';
-    case 'h': return 'H';
-    case 'i': return 'I';
-    case 'j': return 'J';
-    case 'k': return 'K';
-    case 'l': return 'L';
-    case 'm': return 'M';
-    case 'n': return 'N';
-    case 'o': return 'O';
-    case 'p': return 'P';
-    case 'q': return 'Q';
-    case 'r': return 'R';
-    case 's': return 'S';
-    case 't': return 'T';
-    case 'u': return 'U';
-    case 'v': return 'V';
-    case 'w': return 'W';
-    case 'x': return 'X';
-    case 'y': return 'Y';
-    case 'z': return 'Z';
-    default: return c;
-    }
-}
diff --git a/lib/c-ctype.h b/lib/c-ctype.h
index d622973..1292fc8 100644
--- a/lib/c-ctype.h
+++ b/lib/c-ctype.h
@@ -25,6 +25,13 @@ along with this program; if not, see 
<http://www.gnu.org/licenses/>.  */
 
 #include <stdbool.h>
 
+#ifndef _GL_INLINE_HEADER_BEGIN
+ #error "Please include config.h first."
+#endif
+_GL_INLINE_HEADER_BEGIN
+#ifndef C_CTYPE_INLINE
+# define C_CTYPE_INLINE _GL_INLINE
+#endif
 
 #ifdef __cplusplus
 extern "C" {
@@ -39,38 +46,6 @@ extern "C" {
    characters.  */
 
 
-/* Check whether the ASCII optimizations apply. */
-
-/* ANSI C89 (and ISO C99 5.2.1.3 too) already guarantees that
-   '0', '1', ..., '9' have consecutive integer values.  */
-#define C_CTYPE_CONSECUTIVE_DIGITS 1
-
-#if ('A' <= 'Z') \
-    && ('A' + 1 == 'B') && ('B' + 1 == 'C') && ('C' + 1 == 'D') \
-    && ('D' + 1 == 'E') && ('E' + 1 == 'F') && ('F' + 1 == 'G') \
-    && ('G' + 1 == 'H') && ('H' + 1 == 'I') && ('I' + 1 == 'J') \
-    && ('J' + 1 == 'K') && ('K' + 1 == 'L') && ('L' + 1 == 'M') \
-    && ('M' + 1 == 'N') && ('N' + 1 == 'O') && ('O' + 1 == 'P') \
-    && ('P' + 1 == 'Q') && ('Q' + 1 == 'R') && ('R' + 1 == 'S') \
-    && ('S' + 1 == 'T') && ('T' + 1 == 'U') && ('U' + 1 == 'V') \
-    && ('V' + 1 == 'W') && ('W' + 1 == 'X') && ('X' + 1 == 'Y') \
-    && ('Y' + 1 == 'Z')
-#define C_CTYPE_CONSECUTIVE_UPPERCASE 1
-#endif
-
-#if ('a' <= 'z') \
-    && ('a' + 1 == 'b') && ('b' + 1 == 'c') && ('c' + 1 == 'd') \
-    && ('d' + 1 == 'e') && ('e' + 1 == 'f') && ('f' + 1 == 'g') \
-    && ('g' + 1 == 'h') && ('h' + 1 == 'i') && ('i' + 1 == 'j') \
-    && ('j' + 1 == 'k') && ('k' + 1 == 'l') && ('l' + 1 == 'm') \
-    && ('m' + 1 == 'n') && ('n' + 1 == 'o') && ('o' + 1 == 'p') \
-    && ('p' + 1 == 'q') && ('q' + 1 == 'r') && ('r' + 1 == 's') \
-    && ('s' + 1 == 't') && ('t' + 1 == 'u') && ('u' + 1 == 'v') \
-    && ('v' + 1 == 'w') && ('w' + 1 == 'x') && ('x' + 1 == 'y') \
-    && ('y' + 1 == 'z')
-#define C_CTYPE_CONSECUTIVE_LOWERCASE 1
-#endif
-
 #if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
     && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
     && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
@@ -96,11 +71,99 @@ extern "C" {
     && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)
 /* The character set is ASCII or one of its variants or extensions, not EBCDIC.
    Testing the value of '\n' and '\r' is not relevant.  */
-#define C_CTYPE_ASCII 1
+# define C_CTYPE_ASCII 1
+#elif ! (' ' == '\x40' && '0' == '\xf0'                     \
+         && 'A' == '\xc1' && 'J' == '\xd1' && 'S' == '\xe2' \
+         && 'a' == '\x81' && 'j' == '\x91' && 's' == '\xa2')
+# error "Only ASCII and EBCDIC are supported"
+#endif
+
+#define _C_CTYPE_SIGNED_EBCDIC ('A' < 0)
+
+#if C_CTYPE_ASCII
+# define _C_CTYPE_CNTRL \
+    case '\x00': case '\x01': case '\x02': case '\x03': \
+    case '\x04': case '\x05': case '\x06': case '\x07': \
+    case '\x08': case '\x09': case '\x0a': case '\x0b': \
+    case '\x0c': case '\x0d': case '\x0e': case '\x0f': \
+    case '\x10': case '\x11': case '\x12': case '\x13': \
+    case '\x14': case '\x15': case '\x16': case '\x17': \
+    case '\x18': case '\x19': case '\x1a': case '\x1b': \
+    case '\x1c': case '\x1d': case '\x1e': case '\x1f': \
+    case '\x7f'
+#else
+   /* Use EBCDIC code page 1047's assignments for ASCII control chars;
+      assume all EBCDIC code pages agree about these assignments.  */
+# define _C_CTYPE_CNTRL \
+    case '\x00': case '\x01': case '\x02': case '\x03': \
+    case '\x05': case '\x07': case '\x0b': case '\x0c': \
+    case '\x0d': case '\x0e': case '\x0f': case '\x10': \
+    case '\x11': case '\x12': case '\x13': case '\x16': \
+    case '\x18': case '\x19': case '\x1c': case '\x1d': \
+    case '\x1e': case '\x1f': case '\x25': case '\x26': \
+    case '\x27': case '\x2d': case '\x2e': case '\x2f': \
+    case '\x32': case '\x37': case '\x3c': case '\x3d': \
+    case '\x3f'
 #endif
 
+/* Cases for hex letter digits, digits, lower, and upper, 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) \
+   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)
+
+/* 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
 
-/* Function declarations. */
+/* Cases for hex letter digits, digits, lower, and upper, with another
+   case for unsigned char if the original char is negative.  */
+
+#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 \
+   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 '~'
+
+/* Function definitions.  */
 
 /* Unlike the functions in <ctype.h>, which require an argument in the range
    of the 'unsigned char' type, the functions here operate on values that are
@@ -117,179 +180,608 @@ extern "C" {
          if (c_isalpha (*s)) ...
  */
 
-extern bool c_isascii (int c) _GL_ATTRIBUTE_CONST; /* not locale dependent */
+C_CTYPE_INLINE bool
+c_isalnum (int c)
+{
+  switch (c)
+    {
+    _C_CTYPE_DIGIT:
+    _C_CTYPE_LOWER:
+    _C_CTYPE_UPPER:
+      return true;
+
+    default:
+      return false;
+    }
+}
 
-extern bool c_isalnum (int c) _GL_ATTRIBUTE_CONST;
-extern bool c_isalpha (int c) _GL_ATTRIBUTE_CONST;
-extern bool c_isblank (int c) _GL_ATTRIBUTE_CONST;
-extern bool c_iscntrl (int c) _GL_ATTRIBUTE_CONST;
-extern bool c_isdigit (int c) _GL_ATTRIBUTE_CONST;
-extern bool c_islower (int c) _GL_ATTRIBUTE_CONST;
-extern bool c_isgraph (int c) _GL_ATTRIBUTE_CONST;
-extern bool c_isprint (int c) _GL_ATTRIBUTE_CONST;
-extern bool c_ispunct (int c) _GL_ATTRIBUTE_CONST;
-extern bool c_isspace (int c) _GL_ATTRIBUTE_CONST;
-extern bool c_isupper (int c) _GL_ATTRIBUTE_CONST;
-extern bool c_isxdigit (int c) _GL_ATTRIBUTE_CONST;
+C_CTYPE_INLINE bool
+c_isalpha (int c)
+{
+  switch (c)
+    {
+    _C_CTYPE_LOWER:
+    _C_CTYPE_UPPER:
+      return true;
+
+    default:
+      return false;
+    }
+}
 
-extern int c_tolower (int c) _GL_ATTRIBUTE_CONST;
-extern int c_toupper (int c) _GL_ATTRIBUTE_CONST;
+/* The function isascii is not locale dependent.
+   Its use in EBCDIC is questionable. */
+C_CTYPE_INLINE bool
+c_isascii (int c)
+{
+  switch (c)
+    {
+    case ' ':
+    _C_CTYPE_CNTRL:
+    _C_CTYPE_DIGIT:
+    _C_CTYPE_LOWER:
+    _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;
+    }
+}
 
-#if (defined __GNUC__ && !defined __STRICT_ANSI__ && defined __OPTIMIZE__ \
-     && !defined __OPTIMIZE_SIZE__ && !defined NO_C_CTYPE_MACROS)
+C_CTYPE_INLINE bool
+c_isblank (int c)
+{
+  return c == ' ' || c == '\t';
+}
 
-/* ASCII optimizations. */
+C_CTYPE_INLINE bool
+c_iscntrl (int c)
+{
+  switch (c)
+    {
+    _C_CTYPE_CNTRL:
+      return true;
+    default:
+      return false;
+    }
+}
 
-#undef c_isascii
-#define c_isascii(c) \
-  ({ int __c = (c); \
-     (__c >= 0x00 && __c <= 0x7f); \
-   })
+C_CTYPE_INLINE bool
+c_isdigit (int c)
+{
+  switch (c)
+    {
+    _C_CTYPE_DIGIT:
+      return true;
+    default:
+      return false;
+    }
+}
 
-#if C_CTYPE_CONSECUTIVE_DIGITS \
-    && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
-#if C_CTYPE_ASCII
-#undef c_isalnum
-#define c_isalnum(c) \
-  ({ int __c = (c); \
-     ((__c >= '0' && __c <= '9') \
-      || ((__c & ~0x20) >= 'A' && (__c & ~0x20) <= 'Z')); \
-   })
-#else
-#undef c_isalnum
-#define c_isalnum(c) \
-  ({ int __c = (c); \
-     ((__c >= '0' && __c <= '9') \
-      || (__c >= 'A' && __c <= 'Z') \
-      || (__c >= 'a' && __c <= 'z')); \
-   })
+C_CTYPE_INLINE bool
+c_isgraph (int c)
+{
+  switch (c)
+    {
+    _C_CTYPE_DIGIT:
+    _C_CTYPE_LOWER:
+    _C_CTYPE_UPPER:
+
+    _C_CTYPE_PUNCT_PLAIN:
+#if '!' < 0
+    case '!' + 256:
 #endif
+#if '"' < 0
+    case '"' + 256:
 #endif
-
-#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
-#if C_CTYPE_ASCII
-#undef c_isalpha
-#define c_isalpha(c) \
-  ({ int __c = (c); \
-     ((__c & ~0x20) >= 'A' && (__c & ~0x20) <= 'Z'); \
-   })
-#else
-#undef c_isalpha
-#define c_isalpha(c) \
-  ({ int __c = (c); \
-     ((__c >= 'A' && __c <= 'Z') || (__c >= 'a' && __c <= 'z')); \
-   })
+#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;
 
-#undef c_isblank
-#define c_isblank(c) \
-  ({ int __c = (c); \
-     (__c == ' ' || __c == '\t'); \
-   })
+    default:
+      return false;
+    }
+}
 
-#if C_CTYPE_ASCII
-#undef c_iscntrl
-#define c_iscntrl(c) \
-  ({ int __c = (c); \
-     ((__c & ~0x1f) == 0 || __c == 0x7f); \
-   })
-#endif
+C_CTYPE_INLINE bool
+c_islower (int c)
+{
+  switch (c)
+    {
+    _C_CTYPE_LOWER:
+      return true;
+    default:
+      return false;
+    }
+}
 
-#if C_CTYPE_CONSECUTIVE_DIGITS
-#undef c_isdigit
-#define c_isdigit(c) \
-  ({ int __c = (c); \
-     (__c >= '0' && __c <= '9'); \
-   })
+C_CTYPE_INLINE bool
+c_isprint (int c)
+{
+  switch (c)
+    {
+    case ' ':
+    _C_CTYPE_DIGIT:
+    _C_CTYPE_LOWER:
+    _C_CTYPE_UPPER:
+
+    _C_CTYPE_PUNCT_PLAIN:
+#if '!' < 0
+    case '!' + 256:
 #endif
-
-#if C_CTYPE_CONSECUTIVE_LOWERCASE
-#undef c_islower
-#define c_islower(c) \
-  ({ int __c = (c); \
-     (__c >= 'a' && __c <= 'z'); \
-   })
+#if '"' < 0
+    case '"' + 256:
 #endif
-
-#if C_CTYPE_ASCII
-#undef c_isgraph
-#define c_isgraph(c) \
-  ({ int __c = (c); \
-     (__c >= '!' && __c <= '~'); \
-   })
+#if '#' < 0
+    case '#' + 256:
 #endif
-
-#if C_CTYPE_ASCII
-#undef c_isprint
-#define c_isprint(c) \
-  ({ int __c = (c); \
-     (__c >= ' ' && __c <= '~'); \
-   })
+#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;
 
-#if C_CTYPE_ASCII
-#undef c_ispunct
-#define c_ispunct(c) \
-  ({ int _c = (c); \
-     (c_isgraph (_c) && ! c_isalnum (_c)); \
-   })
-#endif
-
-#undef c_isspace
-#define c_isspace(c) \
-  ({ int __c = (c); \
-     (__c == ' ' || __c == '\t' \
-      || __c == '\n' || __c == '\v' || __c == '\f' || __c == '\r'); \
-   })
-
-#if C_CTYPE_CONSECUTIVE_UPPERCASE
-#undef c_isupper
-#define c_isupper(c) \
-  ({ int __c = (c); \
-     (__c >= 'A' && __c <= 'Z'); \
-   })
-#endif
-
-#if C_CTYPE_CONSECUTIVE_DIGITS \
-    && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
-#if C_CTYPE_ASCII
-#undef c_isxdigit
-#define c_isxdigit(c) \
-  ({ int __c = (c); \
-     ((__c >= '0' && __c <= '9') \
-      || ((__c & ~0x20) >= 'A' && (__c & ~0x20) <= 'F')); \
-   })
-#else
-#undef c_isxdigit
-#define c_isxdigit(c) \
-  ({ int __c = (c); \
-     ((__c >= '0' && __c <= '9') \
-      || (__c >= 'A' && __c <= 'F') \
-      || (__c >= 'a' && __c <= 'f')); \
-   })
+    default:
+      return false;
+    }
+}
+
+C_CTYPE_INLINE bool
+c_ispunct (int c)
+{
+  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
+      return true;
 
-#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
-#undef c_tolower
-#define c_tolower(c) \
-  ({ int __c = (c); \
-     (__c >= 'A' && __c <= 'Z' ? __c - 'A' + 'a' : __c); \
-   })
-#undef c_toupper
-#define c_toupper(c) \
-  ({ int __c = (c); \
-     (__c >= 'a' && __c <= 'z' ? __c - 'a' + 'A' : __c); \
-   })
+    default:
+      return false;
+    }
+}
+
+C_CTYPE_INLINE bool
+c_isspace (int c)
+{
+  switch (c)
+    {
+    case ' ': case '\t': case '\n': case '\v': case '\f': case '\r':
+      return true;
+    default:
+      return false;
+    }
+}
+
+C_CTYPE_INLINE bool
+c_isupper (int c)
+{
+  switch (c)
+    {
+    _C_CTYPE_UPPER:
+      return true;
+    default:
+      return false;
+    }
+}
+
+C_CTYPE_INLINE bool
+c_isxdigit (int c)
+{
+  switch (c)
+    {
+    _C_CTYPE_DIGIT:
+    _C_CTYPE_A_THRU_F:
+      return true;
+
+    default:
+      return false;
+    }
+}
+
+C_CTYPE_INLINE int
+c_tolower (int c)
+{
+  switch (c)
+    {
+    _C_CTYPE_UPPER_N (0):
+#if _C_CTYPE_SIGNED_EBCDIC
+      c += 256;
+      /* Fall through.  */
+    _C_CTYPE_UPPER_N (256):
 #endif
+      return c - 'A' + 'a';
 
-#endif /* optimizing for speed */
+    default:
+      return c;
+    }
+}
 
+C_CTYPE_INLINE int
+c_toupper (int c)
+{
+  switch (c)
+    {
+    _C_CTYPE_LOWER_N (0):
+#if _C_CTYPE_SIGNED_EBCDIC
+      c += 256;
+      /* Fall through.  */
+    _C_CTYPE_LOWER_N (256):
+#endif
+      return c - 'a' + 'A';
+
+    default:
+      return c;
+    }
+}
 
 #ifdef __cplusplus
 }
 #endif
 
+_GL_INLINE_HEADER_END
+
 #endif /* C_CTYPE_H */
diff --git a/lib/c-strcaseeq.h b/lib/c-strcaseeq.h
index 896dbcc..ce4b82d 100644
--- a/lib/c-strcaseeq.h
+++ b/lib/c-strcaseeq.h
@@ -33,9 +33,6 @@
 # if C_CTYPE_ASCII
 #  define CASEEQ(other,upper) \
      (c_isupper (upper) ? ((other) & ~0x20) == (upper) : (other) == (upper))
-# elif C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
-#  define CASEEQ(other,upper) \
-     (c_isupper (upper) ? (other) == (upper) || (other) == (upper) - 'A' + 'a' 
: (other) == (upper))
 # else
 #  define CASEEQ(other,upper) \
      (c_toupper (other) == (upper))
diff --git a/modules/c-ctype b/modules/c-ctype
index b172d13..106050e 100644
--- a/modules/c-ctype
+++ b/modules/c-ctype
@@ -6,8 +6,8 @@ lib/c-ctype.h
 lib/c-ctype.c
 
 Depends-on:
+extern-inline
 stdbool
-verify
 
 configure.ac:
 
diff --git a/tests/test-c-ctype.c b/tests/test-c-ctype.c
index 481cbbb..d25dc03 100644
--- a/tests/test-c-ctype.c
+++ b/tests/test-c-ctype.c
@@ -204,218 +204,64 @@ test_all (void)
 
       switch (to_char (c))
         {
-        case 'A':
-          ASSERT (c_tolower (c) == 'a');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'B':
-          ASSERT (c_tolower (c) == 'b');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'C':
-          ASSERT (c_tolower (c) == 'c');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'D':
-          ASSERT (c_tolower (c) == 'd');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'E':
-          ASSERT (c_tolower (c) == 'e');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'F':
-          ASSERT (c_tolower (c) == 'f');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'G':
-          ASSERT (c_tolower (c) == 'g');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'H':
-          ASSERT (c_tolower (c) == 'h');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'I':
-          ASSERT (c_tolower (c) == 'i');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'J':
-          ASSERT (c_tolower (c) == 'j');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'K':
-          ASSERT (c_tolower (c) == 'k');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'L':
-          ASSERT (c_tolower (c) == 'l');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'M':
-          ASSERT (c_tolower (c) == 'm');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'N':
-          ASSERT (c_tolower (c) == 'n');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'O':
-          ASSERT (c_tolower (c) == 'o');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'P':
-          ASSERT (c_tolower (c) == 'p');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'Q':
-          ASSERT (c_tolower (c) == 'q');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'R':
-          ASSERT (c_tolower (c) == 'r');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'S':
-          ASSERT (c_tolower (c) == 's');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'T':
-          ASSERT (c_tolower (c) == 't');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'U':
-          ASSERT (c_tolower (c) == 'u');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'V':
-          ASSERT (c_tolower (c) == 'v');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'W':
-          ASSERT (c_tolower (c) == 'w');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'X':
-          ASSERT (c_tolower (c) == 'x');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'Y':
-          ASSERT (c_tolower (c) == 'y');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'Z':
-          ASSERT (c_tolower (c) == 'z');
-          ASSERT (c_toupper (c) == c);
-          break;
-        case 'a':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'A');
-          break;
-        case 'b':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'B');
-          break;
-        case 'c':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'C');
-          break;
-        case 'd':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'D');
-          break;
-        case 'e':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'E');
-          break;
-        case 'f':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'F');
-          break;
-        case 'g':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'G');
-          break;
-        case 'h':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'H');
-          break;
-        case 'i':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'I');
-          break;
-        case 'j':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'J');
-          break;
-        case 'k':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'K');
-          break;
-        case 'l':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'L');
-          break;
-        case 'm':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'M');
-          break;
-        case 'n':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'N');
-          break;
-        case 'o':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'O');
-          break;
-        case 'p':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'P');
-          break;
-        case 'q':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'Q');
-          break;
-        case 'r':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'R');
-          break;
-        case 's':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'S');
-          break;
-        case 't':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'T');
-          break;
-        case 'u':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'U');
-          break;
-        case 'v':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'V');
-          break;
-        case 'w':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'W');
-          break;
-        case 'x':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'X');
-          break;
-        case 'y':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'Y');
-          break;
-        case 'z':
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == 'Z');
-          break;
-        default:
-          ASSERT (c_tolower (c) == c);
-          ASSERT (c_toupper (c) == c);
-          break;
+        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;
         }
     }
 
-- 
2.1.0





reply via email to

[Prev in Thread] Current Thread [Next in Thread]