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 	<<iswpunct>>---punctuation wide-character test
33 
34 INDEX
35 	iswpunct
36 
37 ANSI_SYNOPSIS
38 	#include <wctype.h>
39 	int iswpunct(wint_t <[c]>);
40 
41 TRAD_SYNOPSIS
42 	#include <wctype.h>
43 	int iswpunct(<[c]>)
44 	wint_t <[c]>;
45 
46 DESCRIPTION
47 <<iswpunct>> is a function which classifies wide-character values that
48 are punctuation.
49 
50 RETURNS
51 <<iswpunct>> returns non-zero if <[c]> is a punctuation wide-character.
52 
53 PORTABILITY
54 <<iswpunct>> 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 "utf8punct.h"
66 #endif /* MB_CAPABLE */
67 
68 int
69 _DEFUN(iswpunct,(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 punctuation so handle them here */
107       if ((x >= 0xe0 && x <= 0xf8) ||
108 	  (x >= 0xf00 && x <= 0xffe) ||
109 	  (x >= 0x1000 && x <= 0x10fe))
110 	return 1;
111 
112       switch (x)
113 	{
114 	case 0x22:
115 	case 0x25:
116 	case 0x28:
117 	case 0x29:
118 	case 0x2a:
119 	  return 1;
120 	case 0x00:
121 	  table = u0;
122 	  size = sizeof(u0);
123 	  break;
124 	case 0x02:
125 	  table = u2;
126 	  size = sizeof(u2);
127 	  break;
128 	case 0x03:
129 	  table = u3;
130 	  size = sizeof(u3);
131 	  break;
132 	case 0x04:
133 	  table = u4;
134 	  size = sizeof(u4);
135 	  break;
136 	case 0x05:
137 	  table = u5;
138 	  size = sizeof(u5);
139 	  break;
140 	case 0x06:
141 	  table = u6;
142 	  size = sizeof(u6);
143 	  break;
144 	case 0x07:
145 	  table = u7;
146 	  size = sizeof(u7);
147 	  break;
148 	case 0x09:
149 	  table = u9;
150 	  size = sizeof(u9);
151 	  break;
152 	case 0x0a:
153 	  table = ua;
154 	  size = sizeof(ua);
155 	  break;
156 	case 0x0b:
157 	  table = ub;
158 	  size = sizeof(ub);
159 	  break;
160 	case 0x0c:
161 	  table = uc;
162 	  size = sizeof(uc);
163 	  break;
164 	case 0x0d:
165 	  table = ud;
166 	  size = sizeof(ud);
167 	  break;
168 	case 0x0e:
169 	  table = ue;
170 	  size = sizeof(ue);
171 	  break;
172 	case 0x0f:
173 	  table = uf;
174 	  size = sizeof(uf);
175 	  break;
176 	case 0x10:
177 	  table = u10;
178 	  size = sizeof(u10);
179 	  break;
180 	case 0x13:
181 	  table = u13;
182 	  size = sizeof(u13);
183 	  break;
184 	case 0x16:
185 	  table = u16;
186 	  size = sizeof(u16);
187 	  break;
188 	case 0x17:
189 	  table = u17;
190 	  size = sizeof(u17);
191 	  break;
192 	case 0x18:
193 	  table = u18;
194 	  size = sizeof(u18);
195 	  break;
196 	case 0x1f:
197 	  table = u1f;
198 	  size = sizeof(u1f);
199 	  break;
200 	case 0x20:
201 	  table = u20;
202 	  size = sizeof(u20);
203 	  break;
204 	case 0x21:
205 	  table = u21;
206 	  size = sizeof(u21);
207 	  break;
208 	case 0x23:
209 	  table = u23;
210 	  size = sizeof(u23);
211 	  break;
212 	case 0x24:
213 	  table = u24;
214 	  size = sizeof(u24);
215 	  break;
216 	case 0x26:
217 	  table = u26;
218 	  size = sizeof(u26);
219 	  break;
220 	case 0x27:
221 	  table = u27;
222 	  size = sizeof(u27);
223 	  break;
224 	case 0x2e:
225 	  table = u2e;
226 	  size = sizeof(u2e);
227 	  break;
228 	case 0x2f:
229 	  table = u2f;
230 	  size = sizeof(u2f);
231 	  break;
232 	case 0x30:
233 	  table = u30;
234 	  size = sizeof(u30);
235 	  break;
236 	case 0x31:
237 	  table = u31;
238 	  size = sizeof(u31);
239 	  break;
240 	case 0x32:
241 	  table = u32;
242 	  size = sizeof(u32);
243 	  break;
244 	case 0x33:
245 	  table = u33;
246 	  size = sizeof(u33);
247 	  break;
248 	case 0xa4:
249 	  table = ua4;
250 	  size = sizeof(ua4);
251 	  break;
252 	case 0xfb:
253 	  table = ufb;
254 	  size = sizeof(ufb);
255 	  break;
256 	case 0xfd:
257 	  table = ufd;
258 	  size = sizeof(ufd);
259 	  break;
260 	case 0xfe:
261 	  table = ufe;
262 	  size = sizeof(ufe);
263 	  break;
264 	case 0xff:
265 	  table = uff;
266 	  size = sizeof(uff);
267 	  break;
268 	case 0x103:
269 	  table = u103;
270 	  size = sizeof(u103);
271 	  break;
272 	case 0x1d0:
273 	  table = u1d0;
274 	  size = sizeof(u1d0);
275 	  break;
276 	case 0x1d1:
277 	  table = u1d1;
278 	  size = sizeof(u1d1);
279 	  break;
280 	case 0x1d6:
281 	  table = u1d6;
282 	  size = sizeof(u1d6);
283 	  break;
284 	case 0x1d7:
285 	  table = u1d7;
286 	  size = sizeof(u1d7);
287 	  break;
288 	case 0xe00:
289 	  table = ue00;
290 	  size = sizeof(ue00);
291 	  break;
292 	case 0xfff:
293 	  table = ufff;
294 	  size = sizeof(ufff);
295 	  break;
296 	case 0x10ff:
297 	  table = u10ff;
298 	  size = sizeof(u10ff);
299 	  break;
300 	default:
301 	  return 0;
302 	}
303       /* we have narrowed down to a section of 256 characters to check */
304       /* now check if c matches the punctuation wide-chars within that section */
305       ptr = (unsigned char *)table;
306       ctmp = (unsigned char)c;
307       while (ptr < table + size)
308 	{
309 	  if (ctmp == *ptr)
310 	    return 1;
311 	  if (ctmp < *ptr)
312 	    return 0;
313 	  /* otherwise c > *ptr */
314 	  /* look for 0x0 as next element which indicates a range */
315 	  ++ptr;
316 	  if (*ptr == 0x0)
317 	    {
318 	      /* we have a range..see if c falls within range */
319 	      ++ptr;
320 	      if (ctmp <= *ptr)
321 		return 1;
322 	      ++ptr;
323 	    }
324 	}
325       /* not in table */
326       return 0;
327     }
328 #endif /* MB_CAPABLE */
329 
330   return (c < (wint_t)0x100 ? ispunct (c) : 0);
331 }
332 
333