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

source code of glibc/localedata/tst-ctype.c