1  /* Character handling in C locale.
       2  
       3     These functions work like the corresponding functions in <ctype.h>,
       4     except that they have the C (POSIX) locale hardwired, whereas the
       5     <ctype.h> functions' behaviour depends on the current locale set via
       6     setlocale.
       7  
       8     Copyright (C) 2000-2003, 2006, 2008-2022 Free Software Foundation, Inc.
       9  
      10     This file is free software: you can redistribute it and/or modify
      11     it under the terms of the GNU Lesser General Public License as
      12     published by the Free Software Foundation; either version 2.1 of the
      13     License, or (at your option) any later version.
      14  
      15     This file is distributed in the hope that it will be useful,
      16     but WITHOUT ANY WARRANTY; without even the implied warranty of
      17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18     GNU Lesser General Public License for more details.
      19  
      20     You should have received a copy of the GNU Lesser General Public License
      21     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      22  
      23  #ifndef C_CTYPE_H
      24  #define C_CTYPE_H
      25  
      26  #ifndef _GL_INLINE_HEADER_BEGIN
      27   #error "Please include config.h first."
      28  #endif
      29  _GL_INLINE_HEADER_BEGIN
      30  #ifndef C_CTYPE_INLINE
      31  # define C_CTYPE_INLINE _GL_INLINE
      32  #endif
      33  
      34  #ifdef __cplusplus
      35  extern "C" {
      36  #endif
      37  
      38  
      39  /* The functions defined in this file assume the "C" locale and a character
      40     set without diacritics (ASCII-US or EBCDIC-US or something like that).
      41     Even if the "C" locale on a particular system is an extension of the ASCII
      42     character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it
      43     is ISO-8859-1), the functions in this file recognize only the ASCII
      44     characters.  */
      45  
      46  
      47  #if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
      48      && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
      49      && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
      50      && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
      51      && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
      52      && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
      53      && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
      54      && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
      55      && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
      56      && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
      57      && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
      58      && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
      59      && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
      60      && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
      61      && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
      62      && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
      63      && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
      64      && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
      65      && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
      66      && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
      67      && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
      68      && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
      69      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)
      70  /* The character set is ASCII or one of its variants or extensions, not EBCDIC.
      71     Testing the value of '\n' and '\r' is not relevant.  */
      72  # define C_CTYPE_ASCII 1
      73  #elif ! (' ' == '\x40' && '0' == '\xf0'                     \
      74           && 'A' == '\xc1' && 'J' == '\xd1' && 'S' == '\xe2' \
      75           && 'a' == '\x81' && 'j' == '\x91' && 's' == '\xa2')
      76  # error "Only ASCII and EBCDIC are supported"
      77  #endif
      78  
      79  #if 'A' < 0
      80  # error "EBCDIC and char is signed -- not supported"
      81  #endif
      82  
      83  /* Cases for control characters.  */
      84  
      85  #define _C_CTYPE_CNTRL \
      86     case '\a': case '\b': case '\f': case '\n': \
      87     case '\r': case '\t': case '\v': \
      88     _C_CTYPE_OTHER_CNTRL
      89  
      90  /* ASCII control characters other than those with \-letter escapes.  */
      91  
      92  #if C_CTYPE_ASCII
      93  # define _C_CTYPE_OTHER_CNTRL \
      94      case '\x00': case '\x01': case '\x02': case '\x03': \
      95      case '\x04': case '\x05': case '\x06': case '\x0e': \
      96      case '\x0f': case '\x10': case '\x11': case '\x12': \
      97      case '\x13': case '\x14': case '\x15': case '\x16': \
      98      case '\x17': case '\x18': case '\x19': case '\x1a': \
      99      case '\x1b': case '\x1c': case '\x1d': case '\x1e': \
     100      case '\x1f': case '\x7f'
     101  #else
     102     /* Use EBCDIC code page 1047's assignments for ASCII control chars;
     103        assume all EBCDIC code pages agree about these assignments.  */
     104  # define _C_CTYPE_OTHER_CNTRL \
     105      case '\x00': case '\x01': case '\x02': case '\x03': \
     106      case '\x07': case '\x0e': case '\x0f': case '\x10': \
     107      case '\x11': case '\x12': case '\x13': case '\x18': \
     108      case '\x19': case '\x1c': case '\x1d': case '\x1e': \
     109      case '\x1f': case '\x26': case '\x27': case '\x2d': \
     110      case '\x2e': case '\x32': case '\x37': case '\x3c': \
     111      case '\x3d': case '\x3f'
     112  #endif
     113  
     114  /* Cases for lowercase hex letters, and lowercase letters, all offset by N.  */
     115  
     116  #define _C_CTYPE_LOWER_A_THRU_F_N(N) \
     117     case 'a' + (N): case 'b' + (N): case 'c' + (N): case 'd' + (N): \
     118     case 'e' + (N): case 'f' + (N)
     119  #define _C_CTYPE_LOWER_N(N) \
     120     _C_CTYPE_LOWER_A_THRU_F_N(N): \
     121     case 'g' + (N): case 'h' + (N): case 'i' + (N): case 'j' + (N): \
     122     case 'k' + (N): case 'l' + (N): case 'm' + (N): case 'n' + (N): \
     123     case 'o' + (N): case 'p' + (N): case 'q' + (N): case 'r' + (N): \
     124     case 's' + (N): case 't' + (N): case 'u' + (N): case 'v' + (N): \
     125     case 'w' + (N): case 'x' + (N): case 'y' + (N): case 'z' + (N)
     126  
     127  /* Cases for hex letters, digits, lower, punct, and upper.  */
     128  
     129  #define _C_CTYPE_A_THRU_F \
     130     _C_CTYPE_LOWER_A_THRU_F_N (0): \
     131     _C_CTYPE_LOWER_A_THRU_F_N ('A' - 'a')
     132  #define _C_CTYPE_DIGIT                     \
     133     case '0': case '1': case '2': case '3': \
     134     case '4': case '5': case '6': case '7': \
     135     case '8': case '9'
     136  #define _C_CTYPE_LOWER _C_CTYPE_LOWER_N (0)
     137  #define _C_CTYPE_PUNCT \
     138     case '!': case '"': case '#': case '$':  \
     139     case '%': case '&': case '\'': case '(': \
     140     case ')': case '*': case '+': case ',':  \
     141     case '-': case '.': case '/': case ':':  \
     142     case ';': case '<': case '=': case '>':  \
     143     case '?': case '@': case '[': case '\\': \
     144     case ']': case '^': case '_': case '`':  \
     145     case '{': case '|': case '}': case '~'
     146  #define _C_CTYPE_UPPER _C_CTYPE_LOWER_N ('A' - 'a')
     147  
     148  
     149  /* Function definitions.  */
     150  
     151  /* Unlike the functions in <ctype.h>, which require an argument in the range
     152     of the 'unsigned char' type, the functions here operate on values that are
     153     in the 'unsigned char' range or in the 'char' range.  In other words,
     154     when you have a 'char' value, you need to cast it before using it as
     155     argument to a <ctype.h> function:
     156  
     157           const char *s = ...;
     158           if (isalpha ((unsigned char) *s)) ...
     159  
     160     but you don't need to cast it for the functions defined in this file:
     161  
     162           const char *s = ...;
     163           if (c_isalpha (*s)) ...
     164   */
     165  
     166  C_CTYPE_INLINE bool
     167  c_isalnum (int c)
     168  {
     169    switch (c)
     170      {
     171      _C_CTYPE_DIGIT:
     172      _C_CTYPE_LOWER:
     173      _C_CTYPE_UPPER:
     174        return true;
     175      default:
     176        return false;
     177      }
     178  }
     179  
     180  C_CTYPE_INLINE bool
     181  c_isalpha (int c)
     182  {
     183    switch (c)
     184      {
     185      _C_CTYPE_LOWER:
     186      _C_CTYPE_UPPER:
     187        return true;
     188      default:
     189        return false;
     190      }
     191  }
     192  
     193  /* The function isascii is not locale dependent.
     194     Its use in EBCDIC is questionable. */
     195  C_CTYPE_INLINE bool
     196  c_isascii (int c)
     197  {
     198    switch (c)
     199      {
     200      case ' ':
     201      _C_CTYPE_CNTRL:
     202      _C_CTYPE_DIGIT:
     203      _C_CTYPE_LOWER:
     204      _C_CTYPE_PUNCT:
     205      _C_CTYPE_UPPER:
     206        return true;
     207      default:
     208        return false;
     209      }
     210  }
     211  
     212  C_CTYPE_INLINE bool
     213  c_isblank (int c)
     214  {
     215    return c == ' ' || c == '\t';
     216  }
     217  
     218  C_CTYPE_INLINE bool
     219  c_iscntrl (int c)
     220  {
     221    switch (c)
     222      {
     223      _C_CTYPE_CNTRL:
     224        return true;
     225      default:
     226        return false;
     227      }
     228  }
     229  
     230  C_CTYPE_INLINE bool
     231  c_isdigit (int c)
     232  {
     233    switch (c)
     234      {
     235      _C_CTYPE_DIGIT:
     236        return true;
     237      default:
     238        return false;
     239      }
     240  }
     241  
     242  C_CTYPE_INLINE bool
     243  c_isgraph (int c)
     244  {
     245    switch (c)
     246      {
     247      _C_CTYPE_DIGIT:
     248      _C_CTYPE_LOWER:
     249      _C_CTYPE_PUNCT:
     250      _C_CTYPE_UPPER:
     251        return true;
     252      default:
     253        return false;
     254      }
     255  }
     256  
     257  C_CTYPE_INLINE bool
     258  c_islower (int c)
     259  {
     260    switch (c)
     261      {
     262      _C_CTYPE_LOWER:
     263        return true;
     264      default:
     265        return false;
     266      }
     267  }
     268  
     269  C_CTYPE_INLINE bool
     270  c_isprint (int c)
     271  {
     272    switch (c)
     273      {
     274      case ' ':
     275      _C_CTYPE_DIGIT:
     276      _C_CTYPE_LOWER:
     277      _C_CTYPE_PUNCT:
     278      _C_CTYPE_UPPER:
     279        return true;
     280      default:
     281        return false;
     282      }
     283  }
     284  
     285  C_CTYPE_INLINE bool
     286  c_ispunct (int c)
     287  {
     288    switch (c)
     289      {
     290      _C_CTYPE_PUNCT:
     291        return true;
     292      default:
     293        return false;
     294      }
     295  }
     296  
     297  C_CTYPE_INLINE bool
     298  c_isspace (int c)
     299  {
     300    switch (c)
     301      {
     302      case ' ': case '\t': case '\n': case '\v': case '\f': case '\r':
     303        return true;
     304      default:
     305        return false;
     306      }
     307  }
     308  
     309  C_CTYPE_INLINE bool
     310  c_isupper (int c)
     311  {
     312    switch (c)
     313      {
     314      _C_CTYPE_UPPER:
     315        return true;
     316      default:
     317        return false;
     318      }
     319  }
     320  
     321  C_CTYPE_INLINE bool
     322  c_isxdigit (int c)
     323  {
     324    switch (c)
     325      {
     326      _C_CTYPE_DIGIT:
     327      _C_CTYPE_A_THRU_F:
     328        return true;
     329      default:
     330        return false;
     331      }
     332  }
     333  
     334  C_CTYPE_INLINE int
     335  c_tolower (int c)
     336  {
     337    switch (c)
     338      {
     339      _C_CTYPE_UPPER:
     340        return c - 'A' + 'a';
     341      default:
     342        return c;
     343      }
     344  }
     345  
     346  C_CTYPE_INLINE int
     347  c_toupper (int c)
     348  {
     349    switch (c)
     350      {
     351      _C_CTYPE_LOWER:
     352        return c - 'a' + 'A';
     353      default:
     354        return c;
     355      }
     356  }
     357  
     358  #ifdef __cplusplus
     359  }
     360  #endif
     361  
     362  _GL_INLINE_HEADER_END
     363  
     364  #endif /* C_CTYPE_H */