Read in more tests from stdin.
[kopensolaris-gnu/glibc.git] / localedata / tst-ctype.c
1 /* Copyright (C) 2000 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@gnu.org>, 2000.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, USA.  */
19
20 #include <ctype.h>
21 #include <locale.h>
22 #include <stdio.h>
23 #include <string.h>
24
25
26 static const char lower[] = "abcdefghijklmnopqrstuvwxyz";
27 static const char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
28 static const char digits[] = "0123456789";
29
30
31 static struct classes
32 {
33   const char *name;
34   int mask;
35 } classes[] =
36 {
37 #define ENTRY(name) { #name, _IS##name }
38   ENTRY (upper),
39   ENTRY (lower),
40   ENTRY (alpha),
41   ENTRY (digit),
42   ENTRY (xdigit),
43   ENTRY (space),
44   ENTRY (print),
45   ENTRY (graph),
46   ENTRY (blank),
47   ENTRY (cntrl),
48   ENTRY (punct),
49   ENTRY (alnum)
50 };
51 #define nclasses (sizeof (classes) / sizeof (classes[0]))
52
53
54 #define FAIL(str, args...) \
55   {                                                                           \
56     printf ("      " str "\n", ##args);                                       \
57     ++errors;                                                                 \
58   }
59
60
61 int
62 main (void)
63 {
64   const char *cp;
65   const char *cp2;
66   int errors = 0;
67   char *inpline = NULL;
68   size_t inplinelen = 0;
69   char *resline = NULL;
70   size_t reslinelen = 0;
71   int n;
72
73   setlocale (LC_ALL, "");
74
75   printf ("Testing the ctype data of the `%s' locale\n",
76           setlocale (LC_CTYPE, NULL));
77
78 #if 0
79   /* Just for debugging.  */
80
81   /* Contents of the class array.  */
82   printf ("\
83 upper = %04x  lower = %04x  alpha = %04x  digit = %04x  xdigit = %04x\n\
84 space = %04x  print = %04x  graph = %04x  blank = %04x  cntrl  = %04x\n\
85 punct = %04x  alnum = %04x\n",
86           _ISupper, _ISlower, _ISalpha, _ISdigit, _ISxdigit,
87           _ISspace, _ISprint, _ISgraph, _ISblank, _IScntrl,
88           _ISpunct, _ISalnum);
89
90   while (n < 256)
91     {
92       if (n % 8 == 0)
93         printf ("%02x: ", n);
94       printf ("%04x%s", __ctype_b[n], (n + 1) % 8 == 0 ? "\n" : " ");
95       ++n;
96     }
97 #endif
98
99   puts ("  Test of ASCII character range\n    special NUL byte handling");
100   if (isupper ('\0'))
101     FAIL ("isupper ('\\0') is true");
102   if (islower ('\0'))
103     FAIL ("islower ('\\0') is true");
104   if (isalpha ('\0'))
105     FAIL ("isalpha ('\\0') is true");
106   if (isdigit ('\0'))
107     FAIL ("isdigit ('\\0') is true");
108   if (isxdigit ('\0'))
109     FAIL ("isxdigit ('\\0') is true");
110   if (isspace ('\0'))
111     FAIL ("isspace ('\\0') is true");
112   if (isprint ('\0'))
113     FAIL ("isprint ('\\0') is true");
114   if (isgraph ('\0'))
115     FAIL ("isgraph ('\\0') is true");
116   if (isblank ('\0'))
117     FAIL ("isblank ('\\0') is true");
118   if (iscntrl ('\0'))
119     FAIL ("iscntrl ('\\0') is true");
120   if (ispunct ('\0'))
121     FAIL ("ispunct ('\\0') is true");
122   if (isalnum ('\0'))
123     FAIL ("isalnum ('\\0') is true");
124
125   puts ("    islower()");
126   for (cp = lower; *cp != '\0'; ++cp)
127     if (! islower (*cp))
128       FAIL ("islower ('%c') not true", *cp);
129   for (cp = upper; *cp != '\0'; ++cp)
130     if (islower (*cp))
131       FAIL ("islower ('%c') is true", *cp);
132   for (cp = digits; *cp != '\0'; ++cp)
133     if (islower (*cp))
134       FAIL ("islower ('%c') is true", *cp);
135
136   puts ("    isupper()");
137   for (cp = lower; *cp != '\0'; ++cp)
138     if (isupper (*cp))
139       FAIL ("isupper ('%c') is true", *cp);
140   for (cp = upper; *cp != '\0'; ++cp)
141     if (! isupper (*cp))
142       FAIL ("isupper ('%c') not true", *cp);
143   for (cp = digits; *cp != '\0'; ++cp)
144     if (isupper (*cp))
145       FAIL ("isupper ('%c') is true", *cp);
146
147   puts ("    isalpha()");
148   for (cp = lower; *cp != '\0'; ++cp)
149     if (! isalpha (*cp))
150       FAIL ("isalpha ('%c') not true", *cp);
151   for (cp = upper; *cp != '\0'; ++cp)
152     if (! isalpha (*cp))
153       FAIL ("isalpha ('%c') not true", *cp);
154   for (cp = digits; *cp != '\0'; ++cp)
155     if (isalpha (*cp))
156       FAIL ("isalpha ('%c') is true", *cp);
157
158   puts ("    isdigit()");
159   for (cp = lower; *cp != '\0'; ++cp)
160     if (isdigit (*cp))
161       FAIL ("isdigit ('%c') is true", *cp);
162   for (cp = upper; *cp != '\0'; ++cp)
163     if (isdigit (*cp))
164       FAIL ("isdigit ('%c') is true", *cp);
165   for (cp = digits; *cp != '\0'; ++cp)
166     if (! isdigit (*cp))
167       FAIL ("isdigit ('%c') not true", *cp);
168
169   puts ("    isxdigit()");
170   for (cp = lower; *cp != '\0'; ++cp)
171     if ((! isxdigit (*cp) && cp - lower < 6)
172         || (isxdigit (*cp) && cp - lower >= 6))
173       FAIL ("isxdigit ('%c') %s true", *cp, cp - upper < 6 ? "not" : "is");
174   for (cp = upper; *cp != '\0'; ++cp)
175     if ((! isxdigit (*cp) && cp - upper < 6)
176         || (isxdigit (*cp) && cp - upper >= 6))
177       FAIL ("isxdigit ('%c') %s true", *cp, cp - upper < 6 ? "not" : "is");
178   for (cp = digits; *cp != '\0'; ++cp)
179     if (! isxdigit (*cp))
180       FAIL ("isxdigit ('%c') not true", *cp);
181
182   puts ("    isspace()");
183   for (cp = lower; *cp != '\0'; ++cp)
184     if (isspace (*cp))
185       FAIL ("isspace ('%c') is true", *cp);
186   for (cp = upper; *cp != '\0'; ++cp)
187     if (isspace (*cp))
188       FAIL ("isspace ('%c') is true", *cp);
189   for (cp = digits; *cp != '\0'; ++cp)
190     if (isspace (*cp))
191       FAIL ("isspace ('%c') is true", *cp);
192
193   puts ("    isprint()");
194   for (cp = lower; *cp != '\0'; ++cp)
195     if (! isprint (*cp))
196       FAIL ("isprint ('%c') not true", *cp);
197   for (cp = upper; *cp != '\0'; ++cp)
198     if (! isprint (*cp))
199       FAIL ("isprint ('%c') not true", *cp);
200   for (cp = digits; *cp != '\0'; ++cp)
201     if (! isprint (*cp))
202       FAIL ("isprint ('%c') not true", *cp);
203
204   puts ("    isgraph()");
205   for (cp = lower; *cp != '\0'; ++cp)
206     if (! isgraph (*cp))
207       FAIL ("isgraph ('%c') not true", *cp);
208   for (cp = upper; *cp != '\0'; ++cp)
209     if (! isgraph (*cp))
210       FAIL ("isgraph ('%c') not true", *cp);
211   for (cp = digits; *cp != '\0'; ++cp)
212     if (! isgraph (*cp))
213       FAIL ("isgraph ('%c') not true", *cp);
214
215   puts ("    isblank()");
216   for (cp = lower; *cp != '\0'; ++cp)
217     if (isblank (*cp))
218       FAIL ("isblank ('%c') is true", *cp);
219   for (cp = upper; *cp != '\0'; ++cp)
220     if (isblank (*cp))
221       FAIL ("isblank ('%c') is true", *cp);
222   for (cp = digits; *cp != '\0'; ++cp)
223     if (isblank (*cp))
224       FAIL ("isblank ('%c') is true", *cp);
225
226   puts ("    iscntrl()");
227   for (cp = lower; *cp != '\0'; ++cp)
228     if (iscntrl (*cp))
229       FAIL ("iscntrl ('%c') is true", *cp);
230   for (cp = upper; *cp != '\0'; ++cp)
231     if (iscntrl (*cp))
232       FAIL ("iscntrl ('%c') is true", *cp);
233   for (cp = digits; *cp != '\0'; ++cp)
234     if (iscntrl (*cp))
235       FAIL ("iscntrl ('%c') is true", *cp);
236
237   puts ("    ispunct()");
238   for (cp = lower; *cp != '\0'; ++cp)
239     if (ispunct (*cp))
240       FAIL ("ispunct ('%c') is true", *cp);
241   for (cp = upper; *cp != '\0'; ++cp)
242     if (ispunct (*cp))
243       FAIL ("ispunct ('%c') is true", *cp);
244   for (cp = digits; *cp != '\0'; ++cp)
245     if (ispunct (*cp))
246       FAIL ("ispunct ('%c') is true", *cp);
247
248   puts ("    isalnum()");
249   for (cp = lower; *cp != '\0'; ++cp)
250     if (! isalnum (*cp))
251       FAIL ("isalnum ('%c') not true", *cp);
252   for (cp = upper; *cp != '\0'; ++cp)
253     if (! isalnum (*cp))
254       FAIL ("isalnum ('%c') not true", *cp);
255   for (cp = digits; *cp != '\0'; ++cp)
256     if (! isalnum (*cp))
257       FAIL ("isalnum ('%c') not true", *cp);
258
259
260   puts ("    tolower()");
261   for (cp = lower; *cp != '\0'; ++cp)
262     if (tolower (*cp) != *cp)
263       FAIL ("tolower ('%c') != '%c'", *cp, *cp);
264   for (cp = upper, cp2 = lower; *cp != '\0'; ++cp, ++cp2)
265     if (tolower (*cp) != *cp2)
266       FAIL ("tolower ('%c') != '%c'", *cp, *cp2);
267   for (cp = digits; *cp != '\0'; ++cp)
268     if (tolower (*cp) != *cp)
269       FAIL ("tolower ('%c') != '%c'", *cp, *cp);
270
271   puts ("    toupper()");
272   for (cp = lower, cp2 = upper; *cp != '\0'; ++cp, ++cp2)
273     if (toupper (*cp) != *cp2)
274       FAIL ("toupper ('%c') != '%c'", *cp, *cp2);
275   for (cp = upper; *cp != '\0'; ++cp)
276     if (toupper (*cp) != *cp)
277       FAIL ("toupper ('%c') != '%c'", *cp, *cp);
278   for (cp = digits; *cp != '\0'; ++cp)
279     if (toupper (*cp) != *cp)
280       FAIL ("toupper ('%c') != '%c'", *cp, *cp);
281
282
283   /* Now some locale specific tests.  */
284   while (! feof (stdin))
285     {
286       unsigned char *inp;
287       unsigned char *resp;
288
289       if (getline (&inpline, &inplinelen, stdin) <= 0
290           || getline (&resline, &reslinelen, stdin) <= 0)
291         break;
292
293       inp = strchr (inpline, '\n');
294       if (inp != NULL)
295         *inp = '\0';
296       resp = strchr (resline, '\n');
297       if (resp != NULL)
298         *resp = '\0';
299
300       inp = inpline;
301       while (*inp != ' ' && *inp != '\t' && *inp && *inp != '\n'
302              && *inp != '\0')
303         ++inp;
304
305       if (*inp == '\0')
306         {
307           printf ("line \"%s\" is without content\n", inpline);
308           continue;
309         }
310       *inp++ = '\0';
311       while (*inp == ' ' || *inp == '\t')
312         ++inp;
313
314       /* Try all classes.  */
315       for (n = 0; n < nclasses; ++n)
316         if (strcmp (inpline, classes[n].name) == 0)
317           break;
318
319       resp = resline;
320       while (*resp == ' ' || *resp == '\t')
321         ++resp;
322
323       if (strlen (inp) != strlen (resp))
324         {
325           printf ("lines \"%.20s\"... and \"%.20s\" have not the same length\n",
326                   inp, resp);
327           continue;
328         }
329
330       if (n < nclasses)
331         {
332           if (strspn (resp, "01") != strlen (resp))
333             {
334               printf ("result string \"%s\" malformed\n", resp);
335               continue;
336             }
337
338           printf ("  Locale-specific tests for `%s'\n", inpline);
339
340           while (*inp != '\0' && *inp != '\n')
341             {
342               if (((__ctype_b[(unsigned int) *inp] & classes[n].mask) != 0)
343                   != (*resp != '0'))
344                 {
345                   printf ("    is%s('%c' = '\\x%02x') %s true\n", inpline,
346                           *inp, *inp, *resp == '1' ? "not" : "is");
347                   ++errors;
348                 }
349               ++inp;
350               ++resp;
351             }
352         }
353       else if (strcmp (inpline, "tolower") == 0)
354         {
355           while (*inp != '\0')
356             {
357               if (tolower (*inp) != *resp)
358                 {
359                   printf ("    tolower('%c' = '\\x%02x') != '%c'\n",
360                           *inp, *inp, *resp);
361                   ++errors;
362                 }
363               ++inp;
364               ++resp;
365             }
366         }
367       else if (strcmp (inpline, "toupper") == 0)
368         {
369           while (*inp != '\0')
370             {
371               if (toupper (*inp) != *resp)
372                 {
373                   printf ("    toupper('%c' = '\\x%02x') != '%c'\n",
374                           *inp, *inp, *resp);
375                   ++errors;
376                 }
377               ++inp;
378               ++resp;
379             }
380         }
381       else
382         printf ("\"%s\": unknown class or map\n", inpline);
383     }
384
385
386   if (errors != 0)
387     {
388       printf ("  %d error%s for `%s' locale\n\n\n", errors,
389               errors == 1 ? "" : "s", setlocale (LC_ALL, NULL));
390       return 1;
391     }
392
393   printf ("  No errors for `%s' locale\n\n\n", setlocale (LC_ALL, NULL));
394   return 0;
395 }