Back to index

glibc  2.9
tst-ctype.c
Go to the documentation of this file.
00001 /* Copyright (C) 2000,02, 05 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Ulrich Drepper <drepper@gnu.org>, 2000.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <ctype.h>
00021 #include <locale.h>
00022 #include <langinfo.h>
00023 #include <stdio.h>
00024 #include <string.h>
00025 
00026 
00027 static const char lower[] = "abcdefghijklmnopqrstuvwxyz";
00028 static const char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
00029 static const char digits[] = "0123456789";
00030 static const char cntrl[] = "\
00031 \x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\
00032 \x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f ";
00033 
00034 
00035 static struct classes
00036 {
00037   const char *name;
00038   int mask;
00039 } classes[] =
00040 {
00041 #define ENTRY(name) { #name, _IS##name }
00042   ENTRY (upper),
00043   ENTRY (lower),
00044   ENTRY (alpha),
00045   ENTRY (digit),
00046   ENTRY (xdigit),
00047   ENTRY (space),
00048   ENTRY (print),
00049   ENTRY (graph),
00050   ENTRY (blank),
00051   ENTRY (cntrl),
00052   ENTRY (punct),
00053   ENTRY (alnum)
00054 };
00055 #define nclasses (sizeof (classes) / sizeof (classes[0]))
00056 
00057 
00058 #define FAIL(str, args...) \
00059   {                                                                  \
00060     printf ("      " str "\n", ##args);                                     \
00061     ++errors;                                                        \
00062   }
00063 
00064 
00065 int
00066 main (void)
00067 {
00068   const char *cp;
00069   const char *cp2;
00070   int errors = 0;
00071   char *inpline = NULL;
00072   size_t inplinelen = 0;
00073   char *resline = NULL;
00074   size_t reslinelen = 0;
00075   size_t n;
00076   const unsigned short int *__ctype_b;
00077 
00078   setlocale (LC_ALL, "");
00079 
00080   printf ("Testing the ctype data of the `%s' locale\n",
00081          setlocale (LC_CTYPE, NULL));
00082 
00083   __ctype_b = ((const unsigned short *) nl_langinfo (_NL_CTYPE_CLASS)) + 128;
00084 
00085 #if 0
00086   /* Just for debugging.  */
00087 
00088   /* Contents of the class array.  */
00089   printf ("\
00090 upper = %04x  lower = %04x  alpha = %04x  digit = %04x  xdigit = %04x\n\
00091 space = %04x  print = %04x  graph = %04x  blank = %04x  cntrl  = %04x\n\
00092 punct = %04x  alnum = %04x\n",
00093          _ISupper, _ISlower, _ISalpha, _ISdigit, _ISxdigit,
00094          _ISspace, _ISprint, _ISgraph, _ISblank, _IScntrl,
00095          _ISpunct, _ISalnum);
00096 
00097   while (n < 256)
00098     {
00099       if (n % 8 == 0)
00100        printf ("%02x: ", n);
00101       printf ("%04x%s", __ctype_b[n], (n + 1) % 8 == 0 ? "\n" : " ");
00102       ++n;
00103     }
00104 #endif
00105 
00106   puts ("  Test of ASCII character range\n    special NUL byte handling");
00107   if (isupper ('\0'))
00108     FAIL ("isupper ('\\0') is true");
00109   if (islower ('\0'))
00110     FAIL ("islower ('\\0') is true");
00111   if (isalpha ('\0'))
00112     FAIL ("isalpha ('\\0') is true");
00113   if (isdigit ('\0'))
00114     FAIL ("isdigit ('\\0') is true");
00115   if (isxdigit ('\0'))
00116     FAIL ("isxdigit ('\\0') is true");
00117   if (isspace ('\0'))
00118     FAIL ("isspace ('\\0') is true");
00119   if (isprint ('\0'))
00120     FAIL ("isprint ('\\0') is true");
00121   if (isgraph ('\0'))
00122     FAIL ("isgraph ('\\0') is true");
00123   if (isblank ('\0'))
00124     FAIL ("isblank ('\\0') is true");
00125   if (! iscntrl ('\0'))
00126     FAIL ("iscntrl ('\\0') not true");
00127   if (ispunct ('\0'))
00128     FAIL ("ispunct ('\\0') is true");
00129   if (isalnum ('\0'))
00130     FAIL ("isalnum ('\\0') is true");
00131 
00132   puts ("    islower()");
00133   for (cp = lower; *cp != '\0'; ++cp)
00134     if (! islower (*cp))
00135       FAIL ("islower ('%c') not true", *cp);
00136   for (cp = upper; *cp != '\0'; ++cp)
00137     if (islower (*cp))
00138       FAIL ("islower ('%c') is true", *cp);
00139   for (cp = digits; *cp != '\0'; ++cp)
00140     if (islower (*cp))
00141       FAIL ("islower ('%c') is true", *cp);
00142   for (cp = cntrl; *cp != '\0'; ++cp)
00143     if (islower (*cp))
00144       FAIL ("islower ('\\x%02x') is true", *cp);
00145 
00146   puts ("    isupper()");
00147   for (cp = lower; *cp != '\0'; ++cp)
00148     if (isupper (*cp))
00149       FAIL ("isupper ('%c') is true", *cp);
00150   for (cp = upper; *cp != '\0'; ++cp)
00151     if (! isupper (*cp))
00152       FAIL ("isupper ('%c') not true", *cp);
00153   for (cp = digits; *cp != '\0'; ++cp)
00154     if (isupper (*cp))
00155       FAIL ("isupper ('%c') is true", *cp);
00156   for (cp = cntrl; *cp != '\0'; ++cp)
00157     if (isupper (*cp))
00158       FAIL ("isupper ('\\x%02x') is true", *cp);
00159 
00160   puts ("    isalpha()");
00161   for (cp = lower; *cp != '\0'; ++cp)
00162     if (! isalpha (*cp))
00163       FAIL ("isalpha ('%c') not true", *cp);
00164   for (cp = upper; *cp != '\0'; ++cp)
00165     if (! isalpha (*cp))
00166       FAIL ("isalpha ('%c') not true", *cp);
00167   for (cp = digits; *cp != '\0'; ++cp)
00168     if (isalpha (*cp))
00169       FAIL ("isalpha ('%c') is true", *cp);
00170   for (cp = cntrl; *cp != '\0'; ++cp)
00171     if (isalpha (*cp))
00172       FAIL ("isalpha ('\\x%02x') is true", *cp);
00173 
00174   puts ("    isdigit()");
00175   for (cp = lower; *cp != '\0'; ++cp)
00176     if (isdigit (*cp))
00177       FAIL ("isdigit ('%c') is true", *cp);
00178   for (cp = upper; *cp != '\0'; ++cp)
00179     if (isdigit (*cp))
00180       FAIL ("isdigit ('%c') is true", *cp);
00181   for (cp = digits; *cp != '\0'; ++cp)
00182     if (! isdigit (*cp))
00183       FAIL ("isdigit ('%c') not true", *cp);
00184   for (cp = cntrl; *cp != '\0'; ++cp)
00185     if (isdigit (*cp))
00186       FAIL ("isdigit ('\\x%02x') is true", *cp);
00187 
00188   puts ("    isxdigit()");
00189   for (cp = lower; *cp != '\0'; ++cp)
00190     if ((! isxdigit (*cp) && cp - lower < 6)
00191        || (isxdigit (*cp) && cp - lower >= 6))
00192       FAIL ("isxdigit ('%c') %s true", *cp, cp - upper < 6 ? "not" : "is");
00193   for (cp = upper; *cp != '\0'; ++cp)
00194     if ((! isxdigit (*cp) && cp - upper < 6)
00195        || (isxdigit (*cp) && cp - upper >= 6))
00196       FAIL ("isxdigit ('%c') %s true", *cp, cp - upper < 6 ? "not" : "is");
00197   for (cp = digits; *cp != '\0'; ++cp)
00198     if (! isxdigit (*cp))
00199       FAIL ("isxdigit ('%c') not true", *cp);
00200   for (cp = cntrl; *cp != '\0'; ++cp)
00201     if (isxdigit (*cp))
00202       FAIL ("isxdigit ('\\x%02x') is true", *cp);
00203 
00204   puts ("    isspace()");
00205   for (cp = lower; *cp != '\0'; ++cp)
00206     if (isspace (*cp))
00207       FAIL ("isspace ('%c') is true", *cp);
00208   for (cp = upper; *cp != '\0'; ++cp)
00209     if (isspace (*cp))
00210       FAIL ("isspace ('%c') is true", *cp);
00211   for (cp = digits; *cp != '\0'; ++cp)
00212     if (isspace (*cp))
00213       FAIL ("isspace ('%c') is true", *cp);
00214   for (cp = cntrl; *cp != '\0'; ++cp)
00215     if ((isspace (*cp) && ((*cp < '\x09' || *cp > '\x0d') && *cp != ' '))
00216        || (! isspace (*cp)
00217            && ((*cp >= '\x09' && *cp <= '\x0d') || *cp == ' ')))
00218       FAIL ("isspace ('\\x%02x') %s true", *cp,
00219            (*cp < '\x09' || *cp > '\x0d') ? "is" : "not");
00220 
00221   puts ("    isprint()");
00222   for (cp = lower; *cp != '\0'; ++cp)
00223     if (! isprint (*cp))
00224       FAIL ("isprint ('%c') not true", *cp);
00225   for (cp = upper; *cp != '\0'; ++cp)
00226     if (! isprint (*cp))
00227       FAIL ("isprint ('%c') not true", *cp);
00228   for (cp = digits; *cp != '\0'; ++cp)
00229     if (! isprint (*cp))
00230       FAIL ("isprint ('%c') not true", *cp);
00231   for (cp = cntrl; *cp != '\0'; ++cp)
00232     if ((isprint (*cp) && *cp != ' ')
00233        || (! isprint (*cp) && *cp == ' '))
00234       FAIL ("isprint ('\\x%02x') is true", *cp);
00235 
00236   puts ("    isgraph()");
00237   for (cp = lower; *cp != '\0'; ++cp)
00238     if (! isgraph (*cp))
00239       FAIL ("isgraph ('%c') not true", *cp);
00240   for (cp = upper; *cp != '\0'; ++cp)
00241     if (! isgraph (*cp))
00242       FAIL ("isgraph ('%c') not true", *cp);
00243   for (cp = digits; *cp != '\0'; ++cp)
00244     if (! isgraph (*cp))
00245       FAIL ("isgraph ('%c') not true", *cp);
00246   for (cp = cntrl; *cp != '\0'; ++cp)
00247     if (isgraph (*cp))
00248       FAIL ("isgraph ('\\x%02x') is true", *cp);
00249 
00250   puts ("    isblank()");
00251   for (cp = lower; *cp != '\0'; ++cp)
00252     if (isblank (*cp))
00253       FAIL ("isblank ('%c') is true", *cp);
00254   for (cp = upper; *cp != '\0'; ++cp)
00255     if (isblank (*cp))
00256       FAIL ("isblank ('%c') is true", *cp);
00257   for (cp = digits; *cp != '\0'; ++cp)
00258     if (isblank (*cp))
00259       FAIL ("isblank ('%c') is true", *cp);
00260   for (cp = cntrl; *cp != '\0'; ++cp)
00261     if ((isblank (*cp) && *cp != '\x09' && *cp != ' ')
00262        || (! isblank (*cp) && (*cp == '\x09' || *cp == ' ')))
00263       FAIL ("isblank ('\\x%02x') %s true", *cp, *cp != '\x09' ? "is" : "not");
00264 
00265   puts ("    iscntrl()");
00266   for (cp = lower; *cp != '\0'; ++cp)
00267     if (iscntrl (*cp))
00268       FAIL ("iscntrl ('%c') is true", *cp);
00269   for (cp = upper; *cp != '\0'; ++cp)
00270     if (iscntrl (*cp))
00271       FAIL ("iscntrl ('%c') is true", *cp);
00272   for (cp = digits; *cp != '\0'; ++cp)
00273     if (iscntrl (*cp))
00274       FAIL ("iscntrl ('%c') is true", *cp);
00275   for (cp = cntrl; *cp != '\0'; ++cp)
00276     if ((iscntrl (*cp) && *cp == ' ')
00277        || (! iscntrl (*cp) && *cp != ' '))
00278       FAIL ("iscntrl ('\\x%02x') not true", *cp);
00279 
00280   puts ("    ispunct()");
00281   for (cp = lower; *cp != '\0'; ++cp)
00282     if (ispunct (*cp))
00283       FAIL ("ispunct ('%c') is true", *cp);
00284   for (cp = upper; *cp != '\0'; ++cp)
00285     if (ispunct (*cp))
00286       FAIL ("ispunct ('%c') is true", *cp);
00287   for (cp = digits; *cp != '\0'; ++cp)
00288     if (ispunct (*cp))
00289       FAIL ("ispunct ('%c') is true", *cp);
00290   for (cp = cntrl; *cp != '\0'; ++cp)
00291     if (ispunct (*cp))
00292       FAIL ("ispunct ('\\x%02x') is true", *cp);
00293 
00294   puts ("    isalnum()");
00295   for (cp = lower; *cp != '\0'; ++cp)
00296     if (! isalnum (*cp))
00297       FAIL ("isalnum ('%c') not true", *cp);
00298   for (cp = upper; *cp != '\0'; ++cp)
00299     if (! isalnum (*cp))
00300       FAIL ("isalnum ('%c') not true", *cp);
00301   for (cp = digits; *cp != '\0'; ++cp)
00302     if (! isalnum (*cp))
00303       FAIL ("isalnum ('%c') not true", *cp);
00304   for (cp = cntrl; *cp != '\0'; ++cp)
00305     if (isalnum (*cp))
00306       FAIL ("isalnum ('\\x%02x') is true", *cp);
00307 
00308 
00309   puts ("    tolower()");
00310   for (cp = lower; *cp != '\0'; ++cp)
00311     if (tolower (*cp) != *cp)
00312       FAIL ("tolower ('%c') != '%c'", *cp, *cp);
00313   for (cp = upper, cp2 = lower; *cp != '\0'; ++cp, ++cp2)
00314     if (tolower (*cp) != *cp2)
00315       FAIL ("tolower ('%c') != '%c'", *cp, *cp2);
00316   for (cp = digits; *cp != '\0'; ++cp)
00317     if (tolower (*cp) != *cp)
00318       FAIL ("tolower ('%c') != '%c'", *cp, *cp);
00319   for (cp = cntrl; *cp != '\0'; ++cp)
00320     if (tolower (*cp) != *cp)
00321       FAIL ("tolower ('\\x%02x') != '\\x%02x'", *cp, *cp);
00322 
00323   puts ("    toupper()");
00324   for (cp = lower, cp2 = upper; *cp != '\0'; ++cp, ++cp2)
00325     if (toupper (*cp) != *cp2)
00326       FAIL ("toupper ('%c') != '%c'", *cp, *cp2);
00327   for (cp = upper; *cp != '\0'; ++cp)
00328     if (toupper (*cp) != *cp)
00329       FAIL ("toupper ('%c') != '%c'", *cp, *cp);
00330   for (cp = digits; *cp != '\0'; ++cp)
00331     if (toupper (*cp) != *cp)
00332       FAIL ("toupper ('%c') != '%c'", *cp, *cp);
00333   for (cp = cntrl; *cp != '\0'; ++cp)
00334     if (toupper (*cp) != *cp)
00335       FAIL ("toupper ('\\x%02x') != '\\x%02x'", *cp, *cp);
00336 
00337 
00338   /* Now some locale specific tests.  */
00339   while (! feof (stdin))
00340     {
00341       unsigned char *inp;
00342       unsigned char *resp;
00343 
00344       if (getline (&inpline, &inplinelen, stdin) <= 0
00345          || getline (&resline, &reslinelen, stdin) <= 0)
00346        break;
00347 
00348       inp = (unsigned char *) strchr (inpline, '\n');
00349       if (inp != NULL)
00350        *inp = '\0';
00351       resp = (unsigned char *) strchr (resline, '\n');
00352       if (resp != NULL)
00353        *resp = '\0';
00354 
00355       inp = (unsigned char *) inpline;
00356       while (*inp != ' ' && *inp != '\t' && *inp && *inp != '\n'
00357             && *inp != '\0')
00358        ++inp;
00359 
00360       if (*inp == '\0')
00361        {
00362          printf ("line \"%s\" is without content\n", inpline);
00363          continue;
00364        }
00365       *inp++ = '\0';
00366       while (*inp == ' ' || *inp == '\t')
00367        ++inp;
00368 
00369       /* Try all classes.  */
00370       for (n = 0; n < nclasses; ++n)
00371        if (strcmp (inpline, classes[n].name) == 0)
00372          break;
00373 
00374       resp = (unsigned char *) resline;
00375       while (*resp == ' ' || *resp == '\t')
00376        ++resp;
00377 
00378       if (strlen ((char *) inp) != strlen ((char *) resp))
00379        {
00380          printf ("lines \"%.20s\"... and \"%.20s\" have not the same length\n",
00381                 inp, resp);
00382          continue;
00383        }
00384 
00385       if (n < nclasses)
00386        {
00387          if (strspn ((char *) resp, "01") != strlen ((char *) resp))
00388            {
00389              printf ("result string \"%s\" malformed\n", resp);
00390              continue;
00391            }
00392 
00393          printf ("  Locale-specific tests for `%s'\n", inpline);
00394 
00395          while (*inp != '\0' && *inp != '\n')
00396            {
00397              if (((__ctype_b[(unsigned int) *inp] & classes[n].mask) != 0)
00398                 != (*resp != '0'))
00399               {
00400                 printf ("    is%s('%c' = '\\x%02x') %s true\n", inpline,
00401                        *inp, *inp, *resp == '1' ? "not" : "is");
00402                 ++errors;
00403               }
00404              ++inp;
00405              ++resp;
00406            }
00407        }
00408       else if (strcmp (inpline, "tolower") == 0)
00409        {
00410          while (*inp != '\0')
00411            {
00412              if (tolower (*inp) != *resp)
00413               {
00414                 printf ("    tolower('%c' = '\\x%02x') != '%c'\n",
00415                        *inp, *inp, *resp);
00416                 ++errors;
00417               }
00418              ++inp;
00419              ++resp;
00420            }
00421        }
00422       else if (strcmp (inpline, "toupper") == 0)
00423        {
00424          while (*inp != '\0')
00425            {
00426              if (toupper (*inp) != *resp)
00427               {
00428                 printf ("    toupper('%c' = '\\x%02x') != '%c'\n",
00429                        *inp, *inp, *resp);
00430                 ++errors;
00431               }
00432              ++inp;
00433              ++resp;
00434            }
00435        }
00436       else
00437        printf ("\"%s\": unknown class or map\n", inpline);
00438     }
00439 
00440 
00441   if (errors != 0)
00442     {
00443       printf ("  %d error%s for `%s' locale\n\n\n", errors,
00444              errors == 1 ? "" : "s", setlocale (LC_ALL, NULL));
00445       return 1;
00446     }
00447 
00448   printf ("  No errors for `%s' locale\n\n\n", setlocale (LC_ALL, NULL));
00449   return 0;
00450 }