1 /* Test of c32iscntrl() function.
2    Copyright (C) 2020-2021 Free Software Foundation, Inc.
3 
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8 
9    This program 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
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
16 
17 #include <config.h>
18 
19 #include <uchar.h>
20 
21 #include "signature.h"
22 SIGNATURE_CHECK (c32iscntrl, int, (wint_t));
23 
24 #include <locale.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <wchar.h>
28 
29 #include "macros.h"
30 
31 /* Returns the value of c32iscntrl for the multibyte character s[0..n-1].  */
32 static int
for_character(const char * s,size_t n)33 for_character (const char *s, size_t n)
34 {
35   mbstate_t state;
36   char32_t wc;
37   size_t ret;
38 
39   memset (&state, '\0', sizeof (mbstate_t));
40   wc = (char32_t) 0xBADFACE;
41   ret = mbrtoc32 (&wc, s, n, &state);
42   ASSERT (ret == n);
43 
44   return c32iscntrl (wc);
45 }
46 
47 int
main(int argc,char * argv[])48 main (int argc, char *argv[])
49 {
50   int is;
51   char buf[4];
52 
53   /* configure should already have checked that the locale is supported.  */
54   if (setlocale (LC_ALL, "") == NULL)
55     return 1;
56 
57   /* Test WEOF.  */
58   is = c32iscntrl (WEOF);
59   ASSERT (is == 0);
60 
61   /* Test single-byte characters.
62      POSIX specifies in
63        <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html>
64      no explicit list of control characters.  */
65   {
66     int c;
67 
68     for (c = 0; c < 0x100; c++)
69       switch (c)
70         {
71         case '\t': case '\v': case '\f':
72         case ' ': case '!': case '"': case '#': case '%':
73         case '&': case '\'': case '(': case ')': case '*':
74         case '+': case ',': case '-': case '.': case '/':
75         case '0': case '1': case '2': case '3': case '4':
76         case '5': case '6': case '7': case '8': case '9':
77         case ':': case ';': case '<': case '=': case '>':
78         case '?':
79         case 'A': case 'B': case 'C': case 'D': case 'E':
80         case 'F': case 'G': case 'H': case 'I': case 'J':
81         case 'K': case 'L': case 'M': case 'N': case 'O':
82         case 'P': case 'Q': case 'R': case 'S': case 'T':
83         case 'U': case 'V': case 'W': case 'X': case 'Y':
84         case 'Z':
85         case '[': case '\\': case ']': case '^': case '_':
86         case 'a': case 'b': case 'c': case 'd': case 'e':
87         case 'f': case 'g': case 'h': case 'i': case 'j':
88         case 'k': case 'l': case 'm': case 'n': case 'o':
89         case 'p': case 'q': case 'r': case 's': case 't':
90         case 'u': case 'v': case 'w': case 'x': case 'y':
91         case 'z': case '{': case '|': case '}': case '~':
92           /* c is in the ISO C "basic character set".  */
93           buf[0] = (unsigned char) c;
94           is = for_character (buf, 1);
95           switch (c)
96             {
97             case '\t': case '\v': case '\f':
98               ASSERT (is != 0);
99               break;
100             default:
101               ASSERT (is == 0);
102               break;
103             }
104           break;
105         }
106   }
107 
108   if (argc > 1)
109     switch (argv[1][0])
110       {
111       case '0':
112         /* C locale; tested above.  */
113         return 0;
114 
115       case '1':
116         /* Locale encoding is ISO-8859-1 or ISO-8859-15.  */
117         {
118           /* U+007F <control> */
119           is = for_character ("\177", 1);
120           ASSERT (is != 0);
121           /* U+00A0 NO-BREAK SPACE */
122           is = for_character ("\240", 1);
123           ASSERT (is == 0);
124         }
125         return 0;
126 
127       case '2':
128         /* Locale encoding is EUC-JP.  */
129         {
130           /* U+007F <control> */
131           is = for_character ("\177", 1);
132           ASSERT (is != 0);
133           /* U+3000 IDEOGRAPHIC SPACE */
134           is = for_character ("\241\241", 2);
135           ASSERT (is == 0);
136         }
137         return 0;
138 
139       case '3':
140         /* Locale encoding is UTF-8.  */
141         {
142           /* U+007F <control> */
143           is = for_character ("\177", 1);
144           ASSERT (is != 0);
145           /* U+00A0 NO-BREAK SPACE */
146           is = for_character ("\302\240", 2);
147           ASSERT (is == 0);
148         #if !(defined __GLIBC__ || defined __FreeBSD__ || defined __DragonFly__ || defined _AIX || defined __sun || defined __CYGWIN__)
149           /* U+202E RIGHT-TO-LEFT OVERRIDE */
150           is = for_character ("\342\200\256", 3);
151           ASSERT (is != 0);
152         #endif
153           /* U+3000 IDEOGRAPHIC SPACE */
154           is = for_character ("\343\200\200", 3);
155           ASSERT (is == 0);
156         #if !(defined __GLIBC__ || defined __FreeBSD__ || defined __DragonFly__ || defined _AIX || defined __sun || defined __CYGWIN__)
157           /* U+FEFF ZERO WIDTH NO-BREAK SPACE */
158           is = for_character ("\357\273\277", 3);
159           ASSERT (is != 0);
160         #endif
161           /* U+20000 <CJK Ideograph> */
162           is = for_character ("\360\240\200\200", 4);
163           ASSERT (is == 0);
164         #if !(defined __GLIBC__ || defined __FreeBSD__ || defined __DragonFly__ || defined _AIX || defined __sun || defined __CYGWIN__ || (defined _WIN32 && !defined __CYGWIN__))
165           /* U+E0001 LANGUAGE TAG */
166           is = for_character ("\363\240\200\201", 4);
167           ASSERT (is != 0);
168         #endif
169         }
170         return 0;
171 
172       case '4':
173         /* Locale encoding is GB18030.  */
174         {
175           /* U+007F <control> */
176           is = for_character ("\177", 1);
177           ASSERT (is != 0);
178           /* U+00A0 NO-BREAK SPACE */
179           is = for_character ("\201\060\204\062", 4);
180           ASSERT (is == 0);
181         #if !(defined __GLIBC__ || defined __FreeBSD__ || defined __DragonFly__ || defined __sun)
182           /* U+202E RIGHT-TO-LEFT OVERRIDE */
183           is = for_character ("\201\066\247\061", 4);
184           ASSERT (is != 0);
185         #endif
186           /* U+3000 IDEOGRAPHIC SPACE */
187           is = for_character ("\241\241", 2);
188           ASSERT (is == 0);
189         #if !(defined __GLIBC__ || defined __FreeBSD__ || defined __DragonFly__ || defined __sun)
190           /* U+FEFF ZERO WIDTH NO-BREAK SPACE */
191           is = for_character ("\204\061\225\063", 4);
192           ASSERT (is != 0);
193         #endif
194           /* U+20000 <CJK Ideograph> */
195           is = for_character ("\225\062\202\066", 4);
196           ASSERT (is == 0);
197         #if !(defined __GLIBC__ || (defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || defined __DragonFly__ || defined __NetBSD__ || defined __sun)
198           /* U+E0001 LANGUAGE TAG */
199           is = for_character ("\323\066\225\071", 4);
200           ASSERT (is != 0);
201         #endif
202         }
203         return 0;
204 
205       }
206 
207   return 1;
208 }
209