1 /* Copyright (C) 2002, 2003 Manuel Novoa III
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.
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.
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.
18 /* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
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.
27 * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */
39 #include <bits/uClibc_uwchar.h>
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)
47 #if defined(__LOCALE_C_ONLY) && defined(__UCLIBC_DO_XLOCALE)
48 #error xlocale functionality is not supported in stub locale mode.
51 #ifdef __UCLIBC_HAS_XLOCALE__
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__ */
59 /* We know wide char support is enabled. We wouldn't be here otherwise. */
61 /* Define this if you want to unify the towupper and towlower code in the
62 * towctrans function. */
63 /* #define SMALL_UPLOW */
65 /**********************************************************************/
66 #ifdef __UCLIBC_MJN3_ONLY__
68 /* generates one warning */
69 #warning TODO: Fix the __CTYPE_* codes!
71 #endif /* __UCLIBC_MJN3_ONLY__ */
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.*/
85 __CTYPE_unclassified = 0,
86 __CTYPE_alpha_nonupper_nonlower,
88 __CTYPE_alpha_upper_lower,
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
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"
112 /* The values for wctype_t. */
114 _CTYPE_unclassified = 0,
126 _CTYPE_isxdigit /* _MUST_ be last of the standard classes! */
129 /* The following is used to implement wctrans(). */
131 #define __CTYPE_TRANSTRING "\10tolower\0\10toupper\0\10totitle\0\0"
139 /*--------------------------------------------------------------------*/
141 #define _CTYPE_iswxdigit (_CTYPE_isxdigit)
143 /*--------------------------------------------------------------------*/
145 #ifdef __UCLIBC_MJN3_ONLY__
147 /* generates one warning */
148 #warning TODO: Fix WC* defines!
150 #endif /* __UCLIBC_MJN3_ONLY__ */
152 #define ENCODING ((__UCLIBC_CURLOCALE_DATA).encoding)
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)
160 #define WC_TABLE_DOMAIN_MAX __LOCALE_DATA_WC_TABLE_DOMAIN_MAX
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
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
175 #define WCctype_TI_MASK ((1 << (WCctype_TI_SHIFT)) - 1)
176 #define WCctype_II_MASK ((1 << (WCctype_II_SHIFT)) - 1)
178 /**********************************************************************/
182 #define __PASTE2(X,Y) X ## Y
183 #define __PASTE3(X,Y,Z) X ## Y ## Z
185 #ifdef __UCLIBC_DO_XLOCALE
187 #define ISW_FUNC_BODY(NAME) \
188 int __PASTE3(isw,NAME,_l) (wint_t wc, __locale_t l) \
190 return iswctype_l(wc, __PASTE2(_CTYPE_is,NAME), l); \
192 libc_hidden_proto(__PASTE3(isw,NAME,_l)); \
193 libc_hidden_def(__PASTE3(isw,NAME,_l))
195 #else /* __UCLIBC_DO_XLOCALE */
197 #define ISW_FUNC_BODY(NAME) \
198 int __PASTE2(isw,NAME) (wint_t wc) \
200 return iswctype(wc, __PASTE2(_CTYPE_is,NAME)); \
202 libc_hidden_proto(__PASTE2(isw,NAME)); \
203 libc_hidden_def(__PASTE2(isw,NAME))
205 #endif /* __UCLIBC_DO_XLOCALE */
206 /**********************************************************************/
207 #if defined(L_iswalnum) || defined(L_iswalnum_l)
209 ISW_FUNC_BODY(alnum);
212 /**********************************************************************/
213 #if defined(L_iswalpha) || defined(L_iswalpha_l)
215 ISW_FUNC_BODY(alpha);
218 /**********************************************************************/
219 #if defined(L_iswblank) || defined(L_iswblank_l)
221 ISW_FUNC_BODY(blank);
224 /**********************************************************************/
225 #if defined(L_iswcntrl) || defined(L_iswcntrl_l)
227 ISW_FUNC_BODY(cntrl);
230 /**********************************************************************/
231 #if defined(L_iswdigit) || defined(L_iswdigit_l)
233 ISW_FUNC_BODY(digit);
236 /**********************************************************************/
237 #if defined(L_iswgraph) || defined(L_iswgraph_l)
239 ISW_FUNC_BODY(graph);
242 /**********************************************************************/
243 #if defined(L_iswlower) || defined(L_iswlower_l)
245 ISW_FUNC_BODY(lower);
248 /**********************************************************************/
249 #if defined(L_iswprint) || defined(L_iswprint_l)
251 ISW_FUNC_BODY(print);
254 /**********************************************************************/
255 #if defined(L_iswpunct) || defined(L_iswpunct_l)
257 ISW_FUNC_BODY(punct);
260 /**********************************************************************/
261 #if defined(L_iswspace) || defined(L_iswspace_l)
263 ISW_FUNC_BODY(space);
266 /**********************************************************************/
267 #if defined(L_iswupper) || defined(L_iswupper_l)
269 ISW_FUNC_BODY(upper);
272 /**********************************************************************/
273 #if defined(L_iswxdigit) || defined(L_iswxdigit_l)
275 ISW_FUNC_BODY(xdigit);
278 /**********************************************************************/
279 #if defined(L_towlower) || defined(L_towlower_l)
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 */
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__ */
297 #define __C_towlower(wc) \
298 ((((__uwchar_t)(wc)) <= 0x7f) ? (__C_ctype_tolower)[(wc)] : (wc))
300 #ifdef __LOCALE_C_ONLY
302 wint_t towlower(wint_t wc)
304 #ifdef __UCLIBC_HAS_CTYPE_TABLES__
305 return __C_towlower(wc);
307 return (wc == ((unsigned int)(wc)))
308 ? __C_tolower(((unsigned int)(wc)))
313 #else /* __LOCALE_C_ONLY */
317 #if defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__)
319 wint_t towlower(wint_t wc)
321 return towctrans_l(wc, _CTYPE_tolower, __UCLIBC_CURLOCALE);
324 #else /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */
326 wint_t TOWLOWER(wint_t wc)
328 return TOWCTRANS(wc, _CTYPE_tolower);
331 #endif /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */
333 #else /* SMALL_UPLOW */
335 #if defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__)
337 wint_t towlower(wint_t wc)
339 return towlower_l(wc, __UCLIBC_CURLOCALE);
342 #else /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */
344 wint_t TOWLOWER(wint_t wc)
346 unsigned int sc, n, i;
349 if (ENCODING == __ctype_encoding_7_bit) {
350 /* We're in the C/POSIX locale, so ignore the tables. */
351 return __C_towlower(wc);
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;
360 i = ((unsigned int) WCuplow[u]) << WCuplow_II_SHIFT;
361 i = ((unsigned int) WCuplow[WCuplow_II_LEN + i + n])
363 i = ((unsigned int) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN
365 wc += WCuplow_diff[i + 1];
370 #endif /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */
372 #endif /* SMALL_UPLOW */
375 //libc_hidden_proto(towlower_l)
376 libc_hidden_def(towlower_l)
377 #endif /* L_towlower_l */
379 #endif /* __LOCALE_C_ONLY */
382 //libc_hidden_proto(towlower)
383 libc_hidden_def(towlower)
387 /**********************************************************************/
388 #if defined(L_towupper) || defined(L_towupper_l)
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 */
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__ */
406 #define __C_towupper(wc) \
407 ((((__uwchar_t)(wc)) <= 0x7f) ? (__C_ctype_toupper)[(wc)] : (wc))
409 #ifdef __LOCALE_C_ONLY
411 wint_t towupper(wint_t wc)
413 #ifdef __UCLIBC_HAS_CTYPE_TABLES__
414 return __C_towupper(wc);
416 return (wc == ((unsigned int)(wc)))
417 ? __C_toupper(((unsigned int)(wc)))
423 #else /* __LOCALE_C_ONLY */
427 #if defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__)
429 wint_t towupper(wint_t wc)
431 return towctrans_l(wc, _CTYPE_toupper, __UCLIBC_CURLOCALE);
434 #else /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */
436 wint_t TOWUPPER(wint_t wc)
438 return TOWCTRANS(wc, _CTYPE_toupper);
441 #endif /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */
443 #else /* SMALL_UPLOW */
445 #if defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__)
447 wint_t towupper(wint_t wc)
449 return towupper_l(wc, __UCLIBC_CURLOCALE);
452 #else /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */
454 wint_t TOWUPPER(wint_t wc)
456 unsigned int sc, n, i;
459 if (ENCODING == __ctype_encoding_7_bit) {
460 /* We're in the C/POSIX locale, so ignore the tables. */
461 return __C_towupper(wc);
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;
470 i = ((unsigned int) WCuplow[u]) << WCuplow_II_SHIFT;
471 i = ((unsigned int) WCuplow[WCuplow_II_LEN + i + n])
473 i = ((unsigned int) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN
475 wc += WCuplow_diff[i];
480 #endif /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */
482 #endif /* SMALL_UPLOW */
485 //libc_hidden_proto(towupper_l)
486 libc_hidden_def(towupper_l)
487 #endif /* L_towupper_l */
489 #endif /* __LOCALE_C_ONLY */
492 //libc_hidden_proto(towupper)
493 libc_hidden_def(towupper)
497 /**********************************************************************/
500 static const unsigned char typestring[] = __CTYPE_TYPESTRING;
501 /* extern const unsigned char typestring[]; */
503 wctype_t wctype(const char *property)
505 const unsigned char *p;
511 if (!strcmp(property, ++p)) {
518 /* TODO - Add locale-specific classifications. */
521 libc_hidden_proto(wctype)
522 libc_hidden_def(wctype)
525 /**********************************************************************/
528 #ifdef __UCLIBC_MJN3_ONLY__
529 #warning REMINDER: Currently wctype_l simply calls wctype.
530 #endif /* __UCLIBC_MJN3_ONLY__ */
532 libc_hidden_proto(wctype)
534 wctype_t wctype_l (const char *property, __locale_t locale)
536 return wctype(property);
538 libc_hidden_proto(wctype_l)
539 libc_hidden_def(wctype_l)
542 /**********************************************************************/
543 #if defined(L_iswctype) || defined(L_iswctype_l)
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) \
551 || ((sizeof(c) == sizeof(char)) \
552 ? (((unsigned char)((((c)) | 0x20) - 'a')) < 6) \
553 : (((__uwchar_t)((((c)) | 0x20) - 'a')) < 6)))
555 #ifdef __UCLIBC_MJN3_ONLY__
557 #warning CONSIDER: Change to bit shift? would need to sync with wctype.h
559 #endif /* __UCLIBC_MJN3_ONLY__ */
562 #ifdef __UCLIBC_HAS_CTYPE_TABLES__
563 #if !defined(__UCLIBC_HAS_XLOCALE__) || defined(L_iswctype_l)
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,
581 #endif /* defined(L_iswctype_L) || defined(__LOCALE_C_ONLY) */
582 #endif /* __UCLIBC_HAS_CTYPE_TABLES__ */
584 #ifdef __LOCALE_C_ONLY
586 #ifdef __UCLIBC_HAS_CTYPE_TABLES__
588 int iswctype(wint_t wc, wctype_t desc)
590 /* Note... wctype_t is unsigned. */
592 if ((((__uwchar_t) wc) <= 0x7f)
593 && (desc < (sizeof(desc2flag)/sizeof(desc2flag[0])))
595 return __isctype(wc, desc2flag[desc]);
600 #else /* __UCLIBC_HAS_CTYPE_TABLES__ */
602 int iswctype(wint_t wc, wctype_t desc)
604 /* This is lame, but it is here just to get it working for now. */
606 if (wc == ((unsigned int)(wc))) {
609 return __C_isupper((unsigned int)(wc));
611 return __C_islower((unsigned int)(wc));
613 return __C_isalpha((unsigned int)(wc));
615 return __C_isdigit((unsigned int)(wc));
616 case _CTYPE_isxdigit:
617 return __C_isxdigit((unsigned int)(wc));
619 return __C_isspace((unsigned int)(wc));
621 return __C_isprint((unsigned int)(wc));
623 return __C_isgraph((unsigned int)(wc));
625 return __C_isblank((unsigned int)(wc));
627 return __C_iscntrl((unsigned int)(wc));
629 return __C_ispunct((unsigned int)(wc));
631 return __C_isalnum((unsigned int)(wc));
639 #endif /* __UCLIBC_HAS_CTYPE_TABLES__ */
641 #else /* __LOCALE_C_ONLY */
643 #ifdef __UCLIBC_MJN3_ONLY__
645 #warning CONSIDER: Handle combining class?
647 #endif /* __UCLIBC_MJN3_ONLY__ */
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 */
659 #if defined(L_iswctype) && defined(__UCLIBC_HAS_XLOCALE__)
661 int iswctype(wint_t wc, wctype_t desc)
663 return iswctype_l(wc, desc, __UCLIBC_CURLOCALE);
666 #else /* defined(L_iswctype) && defined(__UCLIBC_HAS_XLOCALE__) */
668 int ISWCTYPE(wint_t wc, wctype_t desc)
670 unsigned int sc, n, i0, i1;
671 unsigned char d = __CTYPE_unclassified;
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;
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)];
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))
698 return ( ((unsigned char)(d - ctype_range[2*desc]))
699 <= ctype_range[2*desc + 1] )
700 && ((desc != _CTYPE_iswblank) || (d & 1));
702 return (__UCLIBC_CURLOCALE_DATA).code2flag[d] & desc2flag[desc];
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;
715 #endif /* defined(L_iswctype) && defined(__UCLIBC_HAS_XLOCALE__) */
718 //libc_hidden_proto(iswctype_l)
719 libc_hidden_def(iswctype_l)
720 #endif /* L_iswctype_l */
722 #endif /* __LOCALE_C_ONLY */
725 //libc_hidden_proto(iswctype)
726 libc_hidden_def(iswctype)
727 #endif /* L_iswctype */
730 /**********************************************************************/
731 #if defined(L_towctrans) || defined(L_towctrans_l)
733 #ifdef __LOCALE_C_ONLY
735 /* Minimal support for C/POSIX locale. */
738 #warning _tolower is undefined!
739 #define _tolower(c) tolower(c)
742 #warning _toupper is undefined!
743 #define _toupper(c) toupper(c)
746 wint_t towctrans(wint_t wc, wctrans_t desc)
748 if (((unsigned int)(desc - _CTYPE_tolower))
749 <= (_CTYPE_toupper - _CTYPE_tolower)
751 /* Transliteration is either tolower or toupper. */
752 if (((__uwchar_t) wc) <= 0x7f) {
753 return (desc == _CTYPE_tolower) ? _tolower(wc) : _toupper(wc);
756 __set_errno(EINVAL); /* Invalid transliteration. */
761 #else /* __LOCALE_C_ONLY */
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 */
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__ */
781 #if defined(L_towctrans) && defined(__UCLIBC_HAS_XLOCALE__)
783 wint_t towctrans(wint_t wc, wctrans_t desc)
785 return towctrans_l(wc, desc, __UCLIBC_CURLOCALE);
788 #else /* defined(L_towctrans) && defined(__UCLIBC_HAS_XLOCALE__) */
792 wint_t TOWCTRANS(wint_t wc, wctrans_t desc)
794 unsigned int sc, n, i;
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))
803 /* We're in the C/POSIX locale, so ignore non-ASCII values
804 * as well an any mappings other than toupper or tolower. */
809 if (((unsigned int)(desc - _CTYPE_tolower))
810 <= (_CTYPE_totitle - _CTYPE_tolower)
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;
818 i = ((unsigned int) WCuplow[u]) << WCuplow_II_SHIFT;
819 i = ((unsigned int) WCuplow[WCuplow_II_LEN + i + n])
821 i = ((unsigned int) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN
823 if (desc == _CTYPE_tolower) {
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))
841 /* TODO - Deal with other transliterations. */
848 #else /* SMALL_UPLOW */
850 wint_t TOWCTRANS(wint_t wc, wctrans_t desc)
852 if (ENCODING == __ctype_encoding_7_bit) {
853 if ((((__uwchar_t) wc) > 0x7f)
854 || (((unsigned int)(desc - _CTYPE_tolower))
855 > (_CTYPE_toupper - _CTYPE_tolower))
857 /* We're in the C/POSIX locale, so ignore non-ASCII values
858 * as well an any mappings other than toupper or tolower. */
863 if (desc == _CTYPE_tolower) {
864 return TOWLOWER(wc, __UCLIBC_CURLOCALE);
865 } else if (((unsigned int)(desc - _CTYPE_toupper))
866 <= (_CTYPE_totitle - _CTYPE_toupper)
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))
882 /* TODO - Deal with other transliterations. */
888 #endif /* SMALL_UPLOW */
890 #endif /* defined(L_towctrans) && defined(__UCLIBC_HAS_XLOCALE__) */
893 //libc_hidden_proto(towctrans_l)
894 libc_hidden_def(towctrans_l)
895 #endif /* L_towctrans_l */
897 #endif /* __LOCALE_C_ONLY */
899 #ifndef L_towctrans_l
900 //libc_hidden_proto(towctrans)
901 libc_hidden_def(towctrans)
905 /**********************************************************************/
908 static const char transstring[] = __CTYPE_TRANSTRING;
910 wctrans_t wctrans(const char *property)
912 const unsigned char *p;
918 if (!strcmp(property, ++p)) {
925 /* TODO - Add locale-specific translations. */
928 libc_hidden_proto(wctrans)
929 libc_hidden_def(wctrans)
932 /**********************************************************************/
935 #ifdef __UCLIBC_MJN3_ONLY__
936 #warning REMINDER: Currently wctrans_l simply calls wctrans.
937 #endif /* __UCLIBC_MJN3_ONLY__ */
939 libc_hidden_proto(wctrans)
941 wctrans_t wctrans_l(const char *property, __locale_t locale)
943 return wctrans(property);
947 /**********************************************************************/