OSDN Git Service

hidden_def/hidden_proto: convert all users (I hope) termios split, add some missing...
[uclinux-h8/uClibc.git] / libc / misc / wctype / wctype.c
1 /*  Copyright (C) 2002, 2003     Manuel Novoa III
2  *
3  *  This library is free software; you can redistribute it and/or
4  *  modify it under the terms of the GNU Library General Public
5  *  License as published by the Free Software Foundation; either
6  *  version 2 of the License, or (at your option) any later version.
7  *
8  *  This library is distributed in the hope that it will be useful,
9  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  *  Library General Public License for more details.
12  *
13  *  You should have received a copy of the GNU Library General Public
14  *  License along with this library; if not, write to the Free
15  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16  */
17
18 /*  ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!
19  *
20  *  Besides uClibc, I'm using this code in my libc for elks, which is
21  *  a 16-bit environment with a fairly limited compiler.  It would make
22  *  things much easier for me if this file isn't modified unnecessarily.
23  *  In particular, please put any new or replacement functions somewhere
24  *  else, and modify the makefile to use your version instead.
25  *  Thanks.  Manuel
26  *
27  *  ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION!   ATTENTION! */
28
29 #define _GNU_SOURCE
30 #define __NO_CTYPE
31
32 #include <wctype.h>
33 #include <assert.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <locale.h>
37 #include <ctype.h>
38 #include <stdint.h>
39 #include <bits/uClibc_uwchar.h>
40
41 libc_hidden_proto(strcmp)
42 libc_hidden_proto(towlower)
43 libc_hidden_proto(towupper)
44 libc_hidden_proto(towctrans)
45 libc_hidden_proto(iswctype)
46
47 #if defined(__LOCALE_C_ONLY) && defined(__UCLIBC_DO_XLOCALE)
48 #error xlocale functionality is not supported in stub locale mode.
49 #endif
50
51 #ifdef __UCLIBC_HAS_XLOCALE__
52 #include <xlocale.h>
53 libc_hidden_proto(towlower_l)
54 libc_hidden_proto(towupper_l)
55 libc_hidden_proto(towctrans_l)
56 libc_hidden_proto(iswctype_l)
57 #endif /* __UCLIBC_HAS_XLOCALE__ */
58
59 /* We know wide char support is enabled.  We wouldn't be here otherwise. */
60
61 /* Define this if you want to unify the towupper and towlower code in the
62  * towctrans function. */
63 /* #define SMALL_UPLOW */
64
65 /**********************************************************************/
66 #ifdef __UCLIBC_MJN3_ONLY__
67 #ifdef L_iswspace
68 /* generates one warning */
69 #warning TODO: Fix the __CTYPE_* codes!
70 #endif
71 #endif /* __UCLIBC_MJN3_ONLY__ */
72
73 #if 1
74 /* Taking advantage of the C99 mutual-exclusion guarantees for the various
75  * (w)ctype classes, including the descriptions of printing and control
76  * (w)chars, we can place each in one of the following mutually-exlusive
77  * subsets.  Since there are less than 16, we can store the data for
78  * each (w)chars in a nibble. In contrast, glibc uses an unsigned int
79  * per (w)char, with one bit flag for each is* type.  While this allows
80  * a simple '&' operation to determine the type vs. a range test and a
81  * little special handling for the "blank" and "xdigit" types in my
82  * approach, it also uses 8 times the space for the tables on the typical
83  * 32-bit archs we supported.*/
84 enum {
85         __CTYPE_unclassified = 0,
86         __CTYPE_alpha_nonupper_nonlower,
87         __CTYPE_alpha_lower,
88         __CTYPE_alpha_upper_lower,
89         __CTYPE_alpha_upper,
90         __CTYPE_digit,
91         __CTYPE_punct,
92         __CTYPE_graph,
93         __CTYPE_print_space_nonblank,
94         __CTYPE_print_space_blank,
95         __CTYPE_space_nonblank_noncntrl,
96         __CTYPE_space_blank_noncntrl,
97         __CTYPE_cntrl_space_nonblank,
98         __CTYPE_cntrl_space_blank,
99         __CTYPE_cntrl_nonspace
100 };
101 #endif
102
103
104 /* The following is used to implement wctype(), but it is defined
105  * here because the ordering must agree with that of the enumeration
106  * below (ignoring unclassified). */
107 #define __CTYPE_TYPESTRING \
108         "\6alnum\0\6alpha\0\6blank\0\6cntrl\0\6digit\0\6graph\0\6lower\0" \
109         "\6print\0\6punct\0\6space\0\6upper\0\7xdigit\0\0"
110
111
112 /* The values for wctype_t. */
113 enum {
114         _CTYPE_unclassified = 0,
115         _CTYPE_isalnum,
116         _CTYPE_isalpha,
117         _CTYPE_isblank,
118         _CTYPE_iscntrl,
119         _CTYPE_isdigit,
120         _CTYPE_isgraph,
121         _CTYPE_islower,
122         _CTYPE_isprint,
123         _CTYPE_ispunct,
124         _CTYPE_isspace,
125         _CTYPE_isupper,
126         _CTYPE_isxdigit                         /* _MUST_ be last of the standard classes! */
127 };
128
129 /* The following is used to implement wctrans(). */
130
131 #define __CTYPE_TRANSTRING      "\10tolower\0\10toupper\0\10totitle\0\0"
132
133 enum {
134         _CTYPE_tolower = 1,
135         _CTYPE_toupper,
136         _CTYPE_totitle
137 };
138
139 /*--------------------------------------------------------------------*/
140
141 #define _CTYPE_iswxdigit (_CTYPE_isxdigit)
142
143 /*--------------------------------------------------------------------*/
144
145 #ifdef __UCLIBC_MJN3_ONLY__
146 #ifdef L_iswspace
147 /* generates one warning */
148 #warning TODO: Fix WC* defines!
149 #endif
150 #endif /* __UCLIBC_MJN3_ONLY__ */
151
152 #define ENCODING                ((__UCLIBC_CURLOCALE_DATA).encoding)
153
154 #define WCctype                 ((__UCLIBC_CURLOCALE_DATA).tblwctype)
155 #define WCuplow                 ((__UCLIBC_CURLOCALE_DATA).tblwuplow)
156 #define WCcmob                  ((__UCLIBC_CURLOCALE_DATA).tblwcomb)
157 #define WCuplow_diff    ((__UCLIBC_CURLOCALE_DATA).tblwuplow_diff)
158
159
160 #define WC_TABLE_DOMAIN_MAX   __LOCALE_DATA_WC_TABLE_DOMAIN_MAX
161
162 #define WCctype_II_LEN        __LOCALE_DATA_WCctype_II_LEN
163 #define WCctype_TI_LEN        __LOCALE_DATA_WCctype_TI_LEN
164 #define WCctype_UT_LEN        __LOCALE_DATA_WCctype_UT_LEN
165 #define WCctype_II_SHIFT      __LOCALE_DATA_WCctype_II_SHIFT
166 #define WCctype_TI_SHIFT      __LOCALE_DATA_WCctype_TI_SHIFT
167
168 #define WCuplow_II_LEN        __LOCALE_DATA_WCuplow_II_LEN
169 #define WCuplow_TI_LEN        __LOCALE_DATA_WCuplow_TI_LEN
170 #define WCuplow_UT_LEN        __LOCALE_DATA_WCuplow_UT_LEN
171 #define WCuplow_II_SHIFT      __LOCALE_DATA_WCuplow_II_SHIFT
172 #define WCuplow_TI_SHIFT      __LOCALE_DATA_WCuplow_TI_SHIFT
173
174
175 #define WCctype_TI_MASK         ((1 << (WCctype_TI_SHIFT)) - 1)
176 #define WCctype_II_MASK         ((1 << (WCctype_II_SHIFT)) - 1)
177
178 /**********************************************************************/
179
180 #undef __PASTE2
181 #undef __PASTE3
182 #define __PASTE2(X,Y)           X ## Y
183 #define __PASTE3(X,Y,Z)         X ## Y ## Z
184
185 #ifdef __UCLIBC_DO_XLOCALE
186
187 #define ISW_FUNC_BODY(NAME) \
188 int __PASTE3(isw,NAME,_l) (wint_t wc, __locale_t l) \
189 { \
190         return iswctype_l(wc, __PASTE2(_CTYPE_is,NAME), l); \
191 } \
192 libc_hidden_proto(__PASTE3(isw,NAME,_l)); \
193 libc_hidden_def(__PASTE3(isw,NAME,_l))
194
195 #else  /* __UCLIBC_DO_XLOCALE */
196
197 #define ISW_FUNC_BODY(NAME) \
198 int __PASTE2(isw,NAME) (wint_t wc) \
199 { \
200         return iswctype(wc, __PASTE2(_CTYPE_is,NAME)); \
201 } \
202 libc_hidden_proto(__PASTE2(isw,NAME)); \
203 libc_hidden_def(__PASTE2(isw,NAME))
204
205 #endif /* __UCLIBC_DO_XLOCALE */
206 /**********************************************************************/
207 #if defined(L_iswalnum) || defined(L_iswalnum_l)
208
209 ISW_FUNC_BODY(alnum);
210
211 #endif
212 /**********************************************************************/
213 #if defined(L_iswalpha) || defined(L_iswalpha_l)
214
215 ISW_FUNC_BODY(alpha);
216
217 #endif
218 /**********************************************************************/
219 #if defined(L_iswblank) || defined(L_iswblank_l)
220
221 ISW_FUNC_BODY(blank);
222
223 #endif
224 /**********************************************************************/
225 #if defined(L_iswcntrl) || defined(L_iswcntrl_l)
226
227 ISW_FUNC_BODY(cntrl);
228
229 #endif
230 /**********************************************************************/
231 #if defined(L_iswdigit) || defined(L_iswdigit_l)
232
233 ISW_FUNC_BODY(digit);
234
235 #endif
236 /**********************************************************************/
237 #if defined(L_iswgraph) || defined(L_iswgraph_l)
238
239 ISW_FUNC_BODY(graph);
240
241 #endif
242 /**********************************************************************/
243 #if defined(L_iswlower) || defined(L_iswlower_l)
244
245 ISW_FUNC_BODY(lower);
246
247 #endif
248 /**********************************************************************/
249 #if defined(L_iswprint) || defined(L_iswprint_l)
250
251 ISW_FUNC_BODY(print);
252
253 #endif
254 /**********************************************************************/
255 #if defined(L_iswpunct) || defined(L_iswpunct_l)
256
257 ISW_FUNC_BODY(punct);
258
259 #endif
260 /**********************************************************************/
261 #if defined(L_iswspace) || defined(L_iswspace_l)
262
263 ISW_FUNC_BODY(space);
264
265 #endif
266 /**********************************************************************/
267 #if defined(L_iswupper) || defined(L_iswupper_l)
268
269 ISW_FUNC_BODY(upper);
270
271 #endif
272 /**********************************************************************/
273 #if defined(L_iswxdigit) || defined(L_iswxdigit_l)
274
275 ISW_FUNC_BODY(xdigit);
276
277 #endif
278 /**********************************************************************/
279 #if defined(L_towlower) || defined(L_towlower_l)
280
281 #ifdef L_towlower
282 #define TOWLOWER(w) towlower(w)
283 #else  /* L_towlower */
284 #define TOWLOWER(w) towlower_l(w, __locale_t locale)
285 #undef __UCLIBC_CURLOCALE_DATA
286 #undef __UCLIBC_CURLOCALE
287 #define __UCLIBC_CURLOCALE_DATA (*locale)
288 #define __UCLIBC_CURLOCALE (locale)
289 #endif /* L_towlower */
290
291 #ifdef __UCLIBC_HAS_XLOCALE__
292 #define TOWCTRANS(w,d) towctrans_l(w,d, __UCLIBC_CURLOCALE)
293 #else  /* __UCLIBC_HAS_XLOCALE__ */
294 #define TOWCTRANS(w,d) towctrans(w,d)
295 #endif /* __UCLIBC_HAS_XLOCALE__ */
296
297 #define __C_towlower(wc) \
298         ((((__uwchar_t)(wc)) <= 0x7f) ? (__C_ctype_tolower)[(wc)] : (wc))
299
300 #ifdef __LOCALE_C_ONLY
301
302 wint_t towlower(wint_t wc)
303 {
304 #ifdef __UCLIBC_HAS_CTYPE_TABLES__
305         return __C_towlower(wc);
306 #else
307         return (wc == ((unsigned int)(wc)))
308                 ? __C_tolower(((unsigned int)(wc)))
309                 : 0;
310 #endif
311 }
312
313 #else  /* __LOCALE_C_ONLY */
314
315 #ifdef SMALL_UPLOW
316
317 #if defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__)
318
319 wint_t towlower(wint_t wc)
320 {
321         return towctrans_l(wc, _CTYPE_tolower, __UCLIBC_CURLOCALE);
322 }
323
324 #else  /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */
325
326 wint_t TOWLOWER(wint_t wc)
327 {
328         return TOWCTRANS(wc, _CTYPE_tolower);
329 }
330
331 #endif /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */
332
333 #else  /* SMALL_UPLOW */
334
335 #if defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__)
336
337 wint_t towlower(wint_t wc)
338 {
339         return towlower_l(wc, __UCLIBC_CURLOCALE);
340 }
341
342 #else  /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */
343
344 wint_t TOWLOWER(wint_t wc)
345 {
346         unsigned int sc, n, i;
347         __uwchar_t u = wc;
348
349         if (ENCODING == __ctype_encoding_7_bit) {
350                 /* We're in the C/POSIX locale, so ignore the tables. */
351                 return __C_towlower(wc);
352         }
353
354         if (u <= WC_TABLE_DOMAIN_MAX) {
355                 sc = u & ((1 << WCuplow_TI_SHIFT) - 1);
356                 u >>= WCuplow_TI_SHIFT;
357                 n = u & ((1 << WCuplow_II_SHIFT) - 1);
358                 u >>= WCuplow_II_SHIFT;
359
360                 i = ((unsigned int) WCuplow[u]) << WCuplow_II_SHIFT;
361                 i = ((unsigned int) WCuplow[WCuplow_II_LEN + i + n])
362                         << WCuplow_TI_SHIFT;
363                 i = ((unsigned int) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN
364                                                                                 + i + sc]) << 1;
365                 wc += WCuplow_diff[i + 1];
366         }
367         return wc;
368 }
369
370 #endif /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */
371
372 #endif /* SMALL_UPLOW */
373
374 #ifdef L_towlower_l
375 //libc_hidden_proto(towlower_l)
376 libc_hidden_def(towlower_l)
377 #endif /* L_towlower_l */
378
379 #endif /* __LOCALE_C_ONLY */
380
381 #ifndef L_towlower_l
382 //libc_hidden_proto(towlower)
383 libc_hidden_def(towlower)
384 #endif
385
386 #endif
387 /**********************************************************************/
388 #if defined(L_towupper) || defined(L_towupper_l)
389
390 #ifdef L_towupper
391 #define TOWUPPER(w) towupper(w)
392 #else  /* L_towupper */
393 #define TOWUPPER(w) towupper_l(w, __locale_t locale)
394 #undef __UCLIBC_CURLOCALE_DATA
395 #undef __UCLIBC_CURLOCALE
396 #define __UCLIBC_CURLOCALE_DATA (*locale)
397 #define __UCLIBC_CURLOCALE (locale)
398 #endif /* L_towupper */
399
400 #ifdef __UCLIBC_HAS_XLOCALE__
401 #define TOWCTRANS(w,d) towctrans_l(w,d, __UCLIBC_CURLOCALE)
402 #else  /* __UCLIBC_HAS_XLOCALE__ */
403 #define TOWCTRANS(w,d) towctrans(w,d)
404 #endif /* __UCLIBC_HAS_XLOCALE__ */
405
406 #define __C_towupper(wc) \
407         ((((__uwchar_t)(wc)) <= 0x7f) ? (__C_ctype_toupper)[(wc)] : (wc))
408
409 #ifdef __LOCALE_C_ONLY
410
411 wint_t towupper(wint_t wc)
412 {
413 #ifdef __UCLIBC_HAS_CTYPE_TABLES__
414         return __C_towupper(wc);
415 #else
416         return (wc == ((unsigned int)(wc)))
417                 ? __C_toupper(((unsigned int)(wc)))
418                 : 0;
419 #endif
420
421 }
422
423 #else  /* __LOCALE_C_ONLY */
424
425 #ifdef SMALL_UPLOW
426
427 #if defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__)
428
429 wint_t towupper(wint_t wc)
430 {
431         return towctrans_l(wc, _CTYPE_toupper, __UCLIBC_CURLOCALE);
432 }
433
434 #else  /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */
435
436 wint_t TOWUPPER(wint_t wc)
437 {
438         return TOWCTRANS(wc, _CTYPE_toupper);
439 }
440
441 #endif /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */
442
443 #else  /* SMALL_UPLOW */
444
445 #if defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__)
446
447 wint_t towupper(wint_t wc)
448 {
449         return towupper_l(wc, __UCLIBC_CURLOCALE);
450 }
451
452 #else  /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */
453
454 wint_t TOWUPPER(wint_t wc)
455 {
456         unsigned int sc, n, i;
457         __uwchar_t u = wc;
458
459         if (ENCODING == __ctype_encoding_7_bit) {
460                 /* We're in the C/POSIX locale, so ignore the tables. */
461                 return __C_towupper(wc);
462         }
463
464         if (u <= WC_TABLE_DOMAIN_MAX) {
465                 sc = u & ((1 << WCuplow_TI_SHIFT) - 1);
466                 u >>= WCuplow_TI_SHIFT;
467                 n = u & ((1 << WCuplow_II_SHIFT) - 1);
468                 u >>= WCuplow_II_SHIFT;
469
470                 i = ((unsigned int) WCuplow[u]) << WCuplow_II_SHIFT;
471                 i = ((unsigned int) WCuplow[WCuplow_II_LEN + i + n])
472                         << WCuplow_TI_SHIFT;
473                 i = ((unsigned int) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN
474                                                                                 + i + sc]) << 1;
475                 wc += WCuplow_diff[i];
476         }
477         return wc;
478 }
479
480 #endif /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */
481
482 #endif /* SMALL_UPLOW */
483
484 #ifdef L_towupper_l
485 //libc_hidden_proto(towupper_l)
486 libc_hidden_def(towupper_l)
487 #endif /* L_towupper_l */
488
489 #endif /* __LOCALE_C_ONLY */
490
491 #ifndef L_towupper_l
492 //libc_hidden_proto(towupper)
493 libc_hidden_def(towupper)
494 #endif
495
496 #endif
497 /**********************************************************************/
498 #ifdef L_wctype
499
500 static const unsigned char typestring[] = __CTYPE_TYPESTRING;
501 /*  extern const unsigned char typestring[]; */
502
503 wctype_t wctype(const char *property)
504 {
505         const unsigned char *p;
506         int i;
507
508         p = typestring;
509         i = 1;
510         do {
511                 if (!strcmp(property, ++p)) {
512                         return i;
513                 }
514                 ++i;
515                 p += p[-1];
516         } while (*p);
517
518         /* TODO - Add locale-specific classifications. */
519         return 0;
520 }
521 libc_hidden_proto(wctype)
522 libc_hidden_def(wctype)
523
524 #endif
525 /**********************************************************************/
526 #ifdef L_wctype_l
527
528 #ifdef __UCLIBC_MJN3_ONLY__
529 #warning REMINDER: Currently wctype_l simply calls wctype.
530 #endif /* __UCLIBC_MJN3_ONLY__ */
531
532 libc_hidden_proto(wctype)
533
534 wctype_t wctype_l (const char *property, __locale_t locale)
535 {
536         return wctype(property);
537 }
538 libc_hidden_proto(wctype_l)
539 libc_hidden_def(wctype_l)
540
541 #endif
542 /**********************************************************************/
543 #if defined(L_iswctype) || defined(L_iswctype_l)
544
545 #define __C_iswdigit(c) \
546         ((sizeof(c) == sizeof(char)) \
547          ? (((unsigned char)((c) - '0')) < 10) \
548          : (((__uwchar_t)((c) - '0')) < 10))
549 #define __C_iswxdigit(c) \
550         (__C_iswdigit(c) \
551          || ((sizeof(c) == sizeof(char)) \
552                  ? (((unsigned char)((((c)) | 0x20) - 'a')) < 6) \
553                  : (((__uwchar_t)((((c)) | 0x20) - 'a')) < 6)))
554
555 #ifdef __UCLIBC_MJN3_ONLY__
556 #ifdef L_iswctype
557 #warning CONSIDER: Change to bit shift?  would need to sync with wctype.h
558 #endif
559 #endif /* __UCLIBC_MJN3_ONLY__ */
560
561
562 #ifdef __UCLIBC_HAS_CTYPE_TABLES__
563 #if !defined(__UCLIBC_HAS_XLOCALE__) || defined(L_iswctype_l)
564
565 static const unsigned short int desc2flag[] = {
566         [_CTYPE_unclassified] = 0,
567         [_CTYPE_isalnum] = (unsigned short int) _ISwalnum,
568         [_CTYPE_isalpha] = (unsigned short int) _ISwalpha,
569         [_CTYPE_isblank] = (unsigned short int) _ISwblank,
570         [_CTYPE_iscntrl] = (unsigned short int) _ISwcntrl,
571         [_CTYPE_isdigit] = (unsigned short int) _ISwdigit,
572         [_CTYPE_isgraph] = (unsigned short int) _ISwgraph,
573         [_CTYPE_islower] = (unsigned short int) _ISwlower,
574         [_CTYPE_isprint] = (unsigned short int) _ISwprint,
575         [_CTYPE_ispunct] = (unsigned short int) _ISwpunct,
576         [_CTYPE_isspace] = (unsigned short int) _ISwspace,
577         [_CTYPE_isupper] = (unsigned short int) _ISwupper,
578         [_CTYPE_isxdigit] = (unsigned short int) _ISwxdigit,
579 };
580
581 #endif /* defined(L_iswctype_L) || defined(__LOCALE_C_ONLY) */
582 #endif /* __UCLIBC_HAS_CTYPE_TABLES__ */
583
584 #ifdef __LOCALE_C_ONLY
585
586 #ifdef __UCLIBC_HAS_CTYPE_TABLES__
587
588 int iswctype(wint_t wc, wctype_t desc)
589 {
590         /* Note... wctype_t is unsigned. */
591
592         if ((((__uwchar_t) wc) <= 0x7f)
593                 && (desc < (sizeof(desc2flag)/sizeof(desc2flag[0])))
594                 ) {
595                 return __isctype(wc, desc2flag[desc]);
596         }
597         return 0;
598 }
599
600 #else  /* __UCLIBC_HAS_CTYPE_TABLES__ */
601
602 int iswctype(wint_t wc, wctype_t desc)
603 {
604         /* This is lame, but it is here just to get it working for now. */
605
606         if (wc == ((unsigned int)(wc))) {
607                 switch(desc) {
608                         case _CTYPE_isupper:
609                                 return __C_isupper((unsigned int)(wc));
610                         case _CTYPE_islower:
611                                 return __C_islower((unsigned int)(wc));
612                         case _CTYPE_isalpha:
613                                 return __C_isalpha((unsigned int)(wc));
614                         case _CTYPE_isdigit:
615                                 return __C_isdigit((unsigned int)(wc));
616                         case _CTYPE_isxdigit:
617                                 return __C_isxdigit((unsigned int)(wc));
618                         case _CTYPE_isspace:
619                                 return __C_isspace((unsigned int)(wc));
620                         case _CTYPE_isprint:
621                                 return __C_isprint((unsigned int)(wc));
622                         case _CTYPE_isgraph:
623                                 return __C_isgraph((unsigned int)(wc));
624                         case _CTYPE_isblank:
625                                 return __C_isblank((unsigned int)(wc));
626                         case _CTYPE_iscntrl:
627                                 return __C_iscntrl((unsigned int)(wc));
628                         case _CTYPE_ispunct:
629                                 return __C_ispunct((unsigned int)(wc));
630                         case _CTYPE_isalnum:
631                                 return __C_isalnum((unsigned int)(wc));
632                         default:
633                                 break;
634                 }
635         }
636         return 0;
637 }
638
639 #endif /* __UCLIBC_HAS_CTYPE_TABLES__ */
640
641 #else  /* __LOCALE_C_ONLY */
642
643 #ifdef __UCLIBC_MJN3_ONLY__
644 #ifdef L_iswctype
645 #warning CONSIDER: Handle combining class?
646 #endif
647 #endif /* __UCLIBC_MJN3_ONLY__ */
648
649 #ifdef L_iswctype
650 #define ISWCTYPE(w,d) iswctype(w,d)
651 #else  /* L_iswctype */
652 #define ISWCTYPE(w,d) iswctype_l(w,d, __locale_t locale)
653 #undef __UCLIBC_CURLOCALE_DATA
654 #undef __UCLIBC_CURLOCALE
655 #define __UCLIBC_CURLOCALE_DATA (*locale)
656 #define __UCLIBC_CURLOCALE (locale)
657 #endif /* L_iswctype */
658
659 #if defined(L_iswctype) && defined(__UCLIBC_HAS_XLOCALE__)
660
661 int iswctype(wint_t wc, wctype_t desc)
662 {
663         return iswctype_l(wc, desc, __UCLIBC_CURLOCALE);
664 }
665
666 #else  /* defined(L_iswctype) && defined(__UCLIBC_HAS_XLOCALE__) */
667
668 int ISWCTYPE(wint_t wc, wctype_t desc)
669 {
670         unsigned int sc, n, i0, i1;
671         unsigned char d = __CTYPE_unclassified;
672
673         if ((ENCODING != __ctype_encoding_7_bit) || (((__uwchar_t) wc) <= 0x7f)){
674                 if (desc < _CTYPE_iswxdigit) {
675                         if (((__uwchar_t) wc) <= WC_TABLE_DOMAIN_MAX) {
676                                 /* From here on, we know wc > 0. */
677                                 sc = wc & WCctype_TI_MASK;
678                                 wc >>= WCctype_TI_SHIFT;
679                                 n = wc & WCctype_II_MASK;
680                                 wc >>= WCctype_II_SHIFT;
681
682                                 i0 = WCctype[wc];
683                                 i0 <<= WCctype_II_SHIFT;
684                                 i1 = WCctype[WCctype_II_LEN + i0 + n];
685                                 i1 <<= (WCctype_TI_SHIFT-1);
686                                 d = WCctype[WCctype_II_LEN + WCctype_TI_LEN + i1 + (sc >> 1)];
687
688                                 d = (sc & 1) ? (d >> 4) : (d & 0xf);
689                         } else if ( ((((__uwchar_t)(wc - 0xe0020UL)) <= 0x5f)
690                                                  || (wc == 0xe0001UL))
691                                                 || ( (((__uwchar_t)(wc - 0xf0000UL)) < 0x20000UL)
692                                                          && ((wc & 0xffffU) <= 0xfffdU))
693                                                 ) {
694                                 d = __CTYPE_punct;
695                         }
696
697 #if 0
698                         return ( ((unsigned char)(d - ctype_range[2*desc]))
699                                          <= ctype_range[2*desc + 1] )
700                                 && ((desc != _CTYPE_iswblank) || (d & 1));
701 #else
702                         return (__UCLIBC_CURLOCALE_DATA).code2flag[d] & desc2flag[desc];
703 #endif
704                 }
705
706 #ifdef __UCLIBC_MJN3_ONLY__
707 #warning TODO: xdigit really needs to be handled better.  Remember only for ascii!
708 #endif /* __UCLIBC_MJN3_ONLY__ */
709                 /* TODO - Add locale-specific classifications. */
710                 return (desc == _CTYPE_iswxdigit) ? __C_iswxdigit(wc) : 0;
711         }
712         return 0;
713 }
714
715 #endif /* defined(L_iswctype) && defined(__UCLIBC_HAS_XLOCALE__) */
716
717 #ifdef L_iswctype_l
718 //libc_hidden_proto(iswctype_l)
719 libc_hidden_def(iswctype_l)
720 #endif /* L_iswctype_l */
721
722 #endif /* __LOCALE_C_ONLY */
723
724 #ifdef L_iswctype
725 //libc_hidden_proto(iswctype)
726 libc_hidden_def(iswctype)
727 #endif /* L_iswctype */
728
729 #endif
730 /**********************************************************************/
731 #if defined(L_towctrans) || defined(L_towctrans_l)
732
733 #ifdef __LOCALE_C_ONLY
734
735 /* Minimal support for C/POSIX locale. */
736
737 #ifndef _tolower
738 #warning _tolower is undefined!
739 #define _tolower(c)    tolower(c)
740 #endif
741 #ifndef _toupper
742 #warning _toupper is undefined!
743 #define _toupper(c)    toupper(c)
744 #endif
745
746 wint_t towctrans(wint_t wc, wctrans_t desc)
747 {
748         if (((unsigned int)(desc - _CTYPE_tolower))
749                 <= (_CTYPE_toupper - _CTYPE_tolower)
750                 ) {
751                 /* Transliteration is either tolower or toupper. */
752                 if (((__uwchar_t) wc) <= 0x7f) {
753                         return (desc == _CTYPE_tolower) ? _tolower(wc) : _toupper(wc);
754                 }
755         } else {
756                 __set_errno(EINVAL);    /* Invalid transliteration. */
757         }
758         return wc;
759 }
760
761 #else  /* __LOCALE_C_ONLY */
762
763 #ifdef L_towctrans
764 #define TOWCTRANS(w,d) towctrans(w,d)
765 #else  /* L_towctrans */
766 #define TOWCTRANS(w,d) towctrans_l(w,d, __locale_t locale)
767 #undef __UCLIBC_CURLOCALE_DATA
768 #undef __UCLIBC_CURLOCALE
769 #define __UCLIBC_CURLOCALE_DATA (*locale)
770 #define __UCLIBC_CURLOCALE (locale)
771 #endif /* L_towctrans */
772
773 #ifdef __UCLIBC_HAS_XLOCALE__
774 #define TOWLOWER(w,l) towlower_l(w,l)
775 #define TOWUPPER(w,l) towupper_l(w,l)
776 #else  /* __UCLIBC_HAS_XLOCALE__ */
777 #define TOWLOWER(w,l) towlower(w)
778 #define TOWUPPER(w,l) towupper(w)
779 #endif /* __UCLIBC_HAS_XLOCALE__ */
780
781 #if defined(L_towctrans) && defined(__UCLIBC_HAS_XLOCALE__)
782
783 wint_t towctrans(wint_t wc, wctrans_t desc)
784 {
785         return towctrans_l(wc, desc, __UCLIBC_CURLOCALE);
786 }
787
788 #else  /* defined(L_towctrans) && defined(__UCLIBC_HAS_XLOCALE__) */
789
790 #ifdef SMALL_UPLOW
791
792 wint_t TOWCTRANS(wint_t wc, wctrans_t desc)
793 {
794         unsigned int sc, n, i;
795         __uwchar_t u = wc;
796
797         /* TODO - clean up */
798         if (ENCODING == __ctype_encoding_7_bit) {
799                 if ((((__uwchar_t) wc) > 0x7f)
800                         || (((unsigned int)(desc - _CTYPE_tolower))
801                                 > (_CTYPE_toupper - _CTYPE_tolower))
802                         ){
803                         /* We're in the C/POSIX locale, so ignore non-ASCII values
804                          * as well an any mappings other than toupper or tolower. */
805                         return wc;
806                 }
807         }
808
809         if (((unsigned int)(desc - _CTYPE_tolower))
810                 <= (_CTYPE_totitle - _CTYPE_tolower)
811                 ) {
812                 if (u <= WC_TABLE_DOMAIN_MAX) {
813                         sc = u & ((1 << WCuplow_TI_SHIFT) - 1);
814                         u >>= WCuplow_TI_SHIFT;
815                         n = u & ((1 << WCuplow_II_SHIFT) - 1);
816                         u >>= WCuplow_II_SHIFT;
817
818                         i = ((unsigned int) WCuplow[u]) << WCuplow_II_SHIFT;
819                         i = ((unsigned int) WCuplow[WCuplow_II_LEN + i + n])
820                                 << WCuplow_TI_SHIFT;
821                         i = ((unsigned int) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN
822                                                                                         + i + sc]) << 1;
823                         if (desc == _CTYPE_tolower) {
824                                 ++i;
825                         }
826                         wc += WCuplow_diff[i];
827                         if (desc == _CTYPE_totitle) {
828 #ifdef __UCLIBC_MJN3_ONLY__
829 #warning TODO: Verify totitle special cases!
830 #endif /* __UCLIBC_MJN3_ONLY__ */
831                                 /* WARNING! These special cases work for glibc 2.2.4.  Changes
832                                  * may be needed if the glibc locale tables are updated. */
833                                 if ( (((__uwchar_t)(wc - 0x1c4)) <= (0x1cc - 0x1c4))
834                                          || (wc == 0x1f1)
835                                          ) {
836                                         ++wc;
837                                 }
838                         }
839                 }
840         } else {
841                 /* TODO - Deal with other transliterations. */
842                 __set_errno(EINVAL);
843         }
844
845         return wc;
846 }
847
848 #else  /* SMALL_UPLOW */
849
850 wint_t TOWCTRANS(wint_t wc, wctrans_t desc)
851 {
852         if (ENCODING == __ctype_encoding_7_bit) {
853                 if ((((__uwchar_t) wc) > 0x7f)
854                         || (((unsigned int)(desc - _CTYPE_tolower))
855                                 > (_CTYPE_toupper - _CTYPE_tolower))
856                         ){
857                         /* We're in the C/POSIX locale, so ignore non-ASCII values
858                          * as well an any mappings other than toupper or tolower. */
859                         return wc;
860                 }
861         }
862
863         if (desc == _CTYPE_tolower) {
864                 return TOWLOWER(wc, __UCLIBC_CURLOCALE);
865         } else if (((unsigned int)(desc - _CTYPE_toupper))
866                 <= (_CTYPE_totitle - _CTYPE_toupper)
867                 ) {
868                 wc = TOWUPPER(wc, __UCLIBC_CURLOCALE);
869                 if (desc == _CTYPE_totitle) {
870 #ifdef __UCLIBC_MJN3_ONLY__
871 #warning TODO: Verify totitle special cases!
872 #endif /* __UCLIBC_MJN3_ONLY__ */
873                         /* WARNING! These special cases work for glibc 2.2.4.  Changes
874                          * may be needed if the glibc locale tables are updated. */
875                         if ( (((__uwchar_t)(wc - 0x1c4)) <= (0x1cc - 0x1c4))
876                                  || (wc == 0x1f1)
877                                  ) {
878                                 ++wc;
879                         }
880                 }
881         } else {
882                 /* TODO - Deal with other transliterations. */
883                 __set_errno(EINVAL);
884         }
885         return wc;
886 }
887
888 #endif /* SMALL_UPLOW */
889
890 #endif /* defined(L_towctrans) && defined(__UCLIBC_HAS_XLOCALE__) */
891
892 #ifdef L_towctrans_l
893 //libc_hidden_proto(towctrans_l)
894 libc_hidden_def(towctrans_l)
895 #endif /* L_towctrans_l */
896
897 #endif /* __LOCALE_C_ONLY */
898
899 #ifndef L_towctrans_l
900 //libc_hidden_proto(towctrans)
901 libc_hidden_def(towctrans)
902 #endif
903
904 #endif
905 /**********************************************************************/
906 #ifdef L_wctrans
907
908 static const char transstring[] = __CTYPE_TRANSTRING;
909
910 wctrans_t wctrans(const char *property)
911 {
912         const unsigned char *p;
913         int i;
914
915         p = transstring;
916         i = 1;
917         do {
918                 if (!strcmp(property, ++p)) {
919                         return i;
920                 }
921                 ++i;
922                 p += p[-1];
923         } while (*p);
924
925         /* TODO - Add locale-specific translations. */
926         return 0;
927 }
928 libc_hidden_proto(wctrans)
929 libc_hidden_def(wctrans)
930
931 #endif
932 /**********************************************************************/
933 #ifdef L_wctrans_l
934
935 #ifdef __UCLIBC_MJN3_ONLY__
936 #warning REMINDER: Currently wctrans_l simply calls wctrans.
937 #endif /* __UCLIBC_MJN3_ONLY__ */
938
939 libc_hidden_proto(wctrans)
940
941 wctrans_t wctrans_l(const char *property, __locale_t locale)
942 {
943         return wctrans(property);
944 }
945
946 #endif
947 /**********************************************************************/