1 /* Copyright (c) 2002 Red Hat Incorporated.
2    All rights reserved.
3 
4    Redistribution and use in source and binary forms, with or without
5    modification, are permitted provided that the following conditions are met:
6 
7      Redistributions of source code must retain the above copyright
8      notice, this list of conditions and the following disclaimer.
9 
10      Redistributions in binary form must reproduce the above copyright
11      notice, this list of conditions and the following disclaimer in the
12      documentation and/or other materials provided with the distribution.
13 
14      The name of Red Hat Incorporated may not be used to endorse
15      or promote products derived from this software without specific
16      prior written permission.
17 
18    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21    ARE DISCLAIMED.  IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY
22    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 
30 /*
31 FUNCTION
32 	<<iswprint>>---printable wide-character test
33 
34 INDEX
35 	iswprint
36 
37 ANSI_SYNOPSIS
38 	#include <wctype.h>
39 	int iswprint(wint_t <[c]>);
40 
41 TRAD_SYNOPSIS
42 	#include <wctype.h>
43 	int iswprint(<[c]>)
44 	wint_t <[c]>;
45 
46 DESCRIPTION
47 <<iswprint>> is a function which classifies wide-character values that
48 are printable.
49 
50 RETURNS
51 <<iswprint>> returns non-zero if <[c]> is a printable wide-character.
52 
53 PORTABILITY
54 <<iswprint>> is C99.
55 
56 No supporting OS subroutines are required.
57 */
58 #include <_ansi.h>
59 #include <wctype.h>
60 #include <string.h>
61 #include <ctype.h>
62 #include "local.h"
63 
64 #ifdef MB_CAPABLE
65 #include "utf8print.h"
66 #endif /* MB_CAPABLE */
67 
68 int
69 _DEFUN(iswprint,(c), wint_t c)
70 {
71   int unicode = 0;
72   if (__lc_ctype[0] == 'C' && __lc_ctype[1] == '\0')
73     {
74       unicode = 0;
75       /* fall-through */
76     }
77 #ifdef MB_CAPABLE
78   else if (!strcmp (__lc_ctype, "C-JIS"))
79     {
80       c = __jp2uc (c, JP_JIS);
81       unicode = 1;
82     }
83   else if (!strcmp (__lc_ctype, "C-SJIS"))
84     {
85       c = __jp2uc (c, JP_SJIS);
86       unicode = 1;
87     }
88   else if (!strcmp (__lc_ctype, "C-EUCJP"))
89     {
90       c = __jp2uc (c, JP_EUCJP);
91       unicode = 1;
92     }
93   else if (!strcmp (__lc_ctype, "C-UTF-8"))
94     {
95       unicode = 1;
96     }
97 
98   if (unicode)
99     {
100       unsigned const char *table;
101       unsigned char *ptr;
102       unsigned char ctmp;
103       int size;
104       wint_t x = (c >> 8);
105 
106       /* for some large sections, all characters are printuation so handle them here */
107       if ((x >= 0x34 && x <= 0x4c) ||
108 	  (x >= 0x4e && x <= 0x9e) ||
109 	  (x >= 0xac && x <= 0xd6) ||
110 	  (x >= 0xe0 && x <= 0xf9) ||
111 	  (x >= 0x200 && x <= 0x2a5) ||
112 	  (x >= 0xf00 && x <= 0xffe) ||
113 	  (x >= 0x1000 && x <= 0x10fe))
114 	return 1;
115 
116       switch (x)
117 	{
118 	case 0x01:
119 	case 0x15:
120 	case 0x22:
121 	case 0x25:
122 	case 0x28:
123 	case 0x29:
124 	case 0x2a:
125 	case 0xa0:
126 	case 0xa1:
127 	case 0xa2:
128 	case 0xa3:
129 	case 0xfc:
130 	case 0x2f8:
131 	case 0x2f9:
132 	  return 1;
133 	case 0x00:
134 	  table = u0;
135 	  size = sizeof(u0);
136 	  break;
137 	case 0x02:
138 	  table = u2;
139 	  size = sizeof(u2);
140 	  break;
141 	case 0x03:
142 	  table = u3;
143 	  size = sizeof(u3);
144 	  break;
145 	case 0x04:
146 	  table = u4;
147 	  size = sizeof(u4);
148 	  break;
149 	case 0x05:
150 	  table = u5;
151 	  size = sizeof(u5);
152 	  break;
153 	case 0x06:
154 	  table = u6;
155 	  size = sizeof(u6);
156 	  break;
157 	case 0x07:
158 	  table = u7;
159 	  size = sizeof(u7);
160 	  break;
161 	case 0x09:
162 	  table = u9;
163 	  size = sizeof(u9);
164 	  break;
165 	case 0x0a:
166 	  table = ua;
167 	  size = sizeof(ua);
168 	  break;
169 	case 0x0b:
170 	  table = ub;
171 	  size = sizeof(ub);
172 	  break;
173 	case 0x0c:
174 	  table = uc;
175 	  size = sizeof(uc);
176 	  break;
177 	case 0x0d:
178 	  table = ud;
179 	  size = sizeof(ud);
180 	  break;
181 	case 0x0e:
182 	  table = ue;
183 	  size = sizeof(ue);
184 	  break;
185 	case 0x0f:
186 	  table = uf;
187 	  size = sizeof(uf);
188 	  break;
189 	case 0x10:
190 	  table = u10;
191 	  size = sizeof(u10);
192 	  break;
193 	case 0x11:
194 	  table = u11;
195 	  size = sizeof(u11);
196 	  break;
197 	case 0x12:
198 	  table = u12;
199 	  size = sizeof(u12);
200 	  break;
201 	case 0x13:
202 	  table = u13;
203 	  size = sizeof(u13);
204 	  break;
205 	case 0x14:
206 	  table = u14;
207 	  size = sizeof(u14);
208 	  break;
209 	case 0x16:
210 	  table = u16;
211 	  size = sizeof(u16);
212 	  break;
213 	case 0x17:
214 	  table = u17;
215 	  size = sizeof(u17);
216 	  break;
217 	case 0x18:
218 	  table = u18;
219 	  size = sizeof(u18);
220 	  break;
221 	case 0x1e:
222 	  table = u1e;
223 	  size = sizeof(u1e);
224 	  break;
225 	case 0x1f:
226 	  table = u1f;
227 	  size = sizeof(u1f);
228 	  break;
229 	case 0x20:
230 	  table = u20;
231 	  size = sizeof(u20);
232 	  break;
233 	case 0x21:
234 	  table = u21;
235 	  size = sizeof(u21);
236 	  break;
237 	case 0x23:
238 	  table = u23;
239 	  size = sizeof(u23);
240 	  break;
241 	case 0x24:
242 	  table = u24;
243 	  size = sizeof(u24);
244 	  break;
245 	case 0x26:
246 	  table = u26;
247 	  size = sizeof(u26);
248 	  break;
249 	case 0x27:
250 	  table = u27;
251 	  size = sizeof(u27);
252 	  break;
253 	case 0x2e:
254 	  table = u2e;
255 	  size = sizeof(u2e);
256 	  break;
257 	case 0x2f:
258 	  table = u2f;
259 	  size = sizeof(u2f);
260 	  break;
261 	case 0x30:
262 	  table = u30;
263 	  size = sizeof(u30);
264 	  break;
265 	case 0x31:
266 	  table = u31;
267 	  size = sizeof(u31);
268 	  break;
269 	case 0x32:
270 	  table = u32;
271 	  size = sizeof(u32);
272 	  break;
273 	case 0x33:
274 	  table = u33;
275 	  size = sizeof(u33);
276 	  break;
277 	case 0x4d:
278 	  table = u4d;
279 	  size = sizeof(u4d);
280 	  break;
281 	case 0x9f:
282 	  table = u9f;
283 	  size = sizeof(u9f);
284 	  break;
285 	case 0xa4:
286 	  table = ua4;
287 	  size = sizeof(ua4);
288 	  break;
289 	case 0xd7:
290 	  table = ud7;
291 	  size = sizeof(ud7);
292 	  break;
293 	case 0xfa:
294 	  table = ufa;
295 	  size = sizeof(ufa);
296 	  break;
297 	case 0xfb:
298 	  table = ufb;
299 	  size = sizeof(ufb);
300 	  break;
301 	case 0xfd:
302 	  table = ufd;
303 	  size = sizeof(ufd);
304 	  break;
305 	case 0xfe:
306 	  table = ufe;
307 	  size = sizeof(ufe);
308 	  break;
309 	case 0xff:
310 	  table = uff;
311 	  size = sizeof(uff);
312 	  break;
313 	case 0x103:
314 	  table = u103;
315 	  size = sizeof(u103);
316 	  break;
317 	case 0x104:
318 	  table = u104;
319 	  size = sizeof(u104);
320 	  break;
321 	case 0x1d0:
322 	  table = u1d0;
323 	  size = sizeof(u1d0);
324 	  break;
325 	case 0x1d1:
326 	  table = u1d1;
327 	  size = sizeof(u1d1);
328 	  break;
329 	case 0x1d4:
330 	  table = u1d4;
331 	  size = sizeof(u1d4);
332 	  break;
333 	case 0x1d5:
334 	  table = u1d5;
335 	  size = sizeof(u1d5);
336 	  break;
337 	case 0x1d6:
338 	  table = u1d6;
339 	  size = sizeof(u1d6);
340 	  break;
341 	case 0x1d7:
342 	  table = u1d7;
343 	  size = sizeof(u1d7);
344 	  break;
345 	case 0x2a6:
346 	  table = u2a6;
347 	  size = sizeof(u2a6);
348 	  break;
349 	case 0x2fa:
350 	  table = u2fa;
351 	  size = sizeof(u2fa);
352 	  break;
353 	case 0xe00:
354 	  table = ue00;
355 	  size = sizeof(ue00);
356 	  break;
357 	case 0xfff:
358 	  table = ufff;
359 	  size = sizeof(ufff);
360 	  break;
361 	case 0x10ff:
362 	  table = u10ff;
363 	  size = sizeof(u10ff);
364 	  break;
365 	default:
366 	  return 0;
367 	}
368       /* we have narrowed down to a section of 256 characters to check */
369       /* now check if c matches the printuation wide-chars within that section */
370       ptr = (unsigned char *)table;
371       ctmp = (unsigned char)c;
372       while (ptr < table + size)
373 	{
374 	  if (ctmp == *ptr)
375 	    return 1;
376 	  if (ctmp < *ptr)
377 	    return 0;
378 	  /* otherwise c > *ptr */
379 	  /* look for 0x0 as next element which indicates a range */
380 	  ++ptr;
381 	  if (*ptr == 0x0)
382 	    {
383 	      /* we have a range..see if c falls within range */
384 	      ++ptr;
385 	      if (ctmp <= *ptr)
386 		return 1;
387 	      ++ptr;
388 	    }
389 	}
390       /* not in table */
391       return 0;
392     }
393 #endif /* MB_CAPABLE */
394 
395   return (c < (wint_t)0x100 ? isprint (c) : 0);
396 }
397 
398