From 1217289737588e65b088b3535428b27c7287d699 Mon Sep 17 00:00:00 2001 From: Manuel Novoa III Date: Fri, 1 Aug 2003 20:08:59 +0000 Subject: Add a new *scanf implementation, includeing the *wscanf functions. Should be standards compliant and with several optional features, including support for hexadecimal float notation, locale awareness, glibc-like locale-specific digit grouping with the `'' flag, and positional arg support. I tested it pretty well (finding several bugs in glibc's scanf in the process), but it is brand new so be aware. The *wprintf functions now support floating point output. Also, a couple of bugs were squashed. Finally, %a/%A conversions are now implemented. Implement the glibc xlocale interface for thread-specific locale support. Also add the various *_l(args, locale_t loc_arg) funcs. NOTE!!! setlocale() is NOT threadsafe! NOTE!!! The strto{floating point} conversion functions are now locale aware. The also now support hexadecimal floating point notation. Add the wcsto{floating point} conversion functions. Fix a bug in mktime() related to dst. Note that unlike glibc's mktime, uClibc's version always normalizes the struct tm before attempting to determine the correct dst setting if tm_isdst == -1 on entry. Add a stub version of the libintl functions. (untested) Fixed a known memory leak in setlocale() related to the collation data. Add lots of new config options (which Erik agreed to sort out :-), including finally exposing some of the stripped down stdio configs. Be careful with those though, as they haven't been tested in a long time. (temporary) GOTCHAs... The ctype functions are currently incorrect for 8-bit locales. They will be fixed shortly. The ctype functions are now table-based, resulting in larger staticly linked binaries. I'll be adding an option to use the old approach in the stub locale configuration. --- libc/misc/wctype/Makefile | 20 +- libc/misc/wctype/wctype.c | 661 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 477 insertions(+), 204 deletions(-) (limited to 'libc/misc/wctype') diff --git a/libc/misc/wctype/Makefile b/libc/misc/wctype/Makefile index 875ccef56..44734945c 100644 --- a/libc/misc/wctype/Makefile +++ b/libc/misc/wctype/Makefile @@ -25,12 +25,22 @@ TOPDIR=../../../ include $(TOPDIR)Rules.mak MSRC= wctype.c -MOBJ= iswalnum.o iswalpha.o iswcntrl.o iswdigit.o iswgraph.o iswlower.o \ - iswprint.o iswpunct.o iswspace.o iswupper.o iswxdigit.o towlower.o \ - towupper.o iswblank.o wctype.o iswctype.o wctrans.o towctrans.o +MOBJ= iswalnum.o iswalpha.o iswcntrl.o iswdigit.o iswgraph.o \ + iswlower.o iswprint.o iswpunct.o iswspace.o iswupper.o \ + iswxdigit.o iswblank.o wctrans.o towctrans.o \ + wctype.o iswctype.o towlower.o towupper.o + +MOBJx= iswalnum_l.o iswalpha_l.o iswcntrl_l.o iswdigit_l.o iswgraph_l.o \ + iswlower_l.o iswprint_l.o iswpunct_l.o iswspace_l.o iswupper_l.o \ + iswxdigit_l.o iswblank_l.o \ + wctype_l.o iswctype_l.o wctrans_l.o towctrans_l.o towlower_l.o towupper_l.o OBJS=$(MOBJ) +ifeq ($(UCLIBC_HAS_XLOCALE),y) + OBJS += $(MOBJx) +endif + all: $(OBJS) $(LIBC) $(LIBC): ar-target @@ -42,6 +52,10 @@ $(MOBJ): $(MSRC) $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o $(STRIPTOOL) -x -R .note -R .comment $*.o +$(MOBJx): $(MSRC) + $(CC) $(CFLAGS) -DL_$* -D__UCLIBC_DO_XLOCALE $< -c -o $*.o + $(STRIPTOOL) -x -R .note -R .comment $*.o + clean: rm -f *.[oa] *~ core diff --git a/libc/misc/wctype/wctype.c b/libc/misc/wctype/wctype.c index 68b9e4579..e0dde3a1f 100644 --- a/libc/misc/wctype/wctype.c +++ b/libc/misc/wctype/wctype.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Manuel Novoa III +/* Copyright (C) 2002, 2003 Manuel Novoa III * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -35,148 +35,308 @@ #include #include #include +#include +#include + +#if defined(__LOCALE_C_ONLY) && defined(__UCLIBC_DO_XLOCALE) +#error xlocale functionality is not supported in stub locale mode. +#endif + +#ifdef __UCLIBC_HAS_XLOCALE__ +#include + +extern int __iswctype_l (wint_t __wc, wctype_t __desc, __locale_t __locale); + __THROW; +extern wint_t __towlower_l (wint_t __wc, __locale_t __locale) __THROW; + +extern wint_t __towupper_l (wint_t __wc, __locale_t __locale) __THROW; +extern wint_t __towctrans_l (wint_t __wc, wctrans_t __desc, + __locale_t __locale) __THROW; + +#endif /* __UCLIBC_HAS_XLOCALE__ */ /* We know wide char support is enabled. We wouldn't be here otherwise. */ /* Define this if you want to unify the towupper and towlower code in the * towctrans function. */ -/* #define SMALL_UPLOW */ +/* #define SMALL_UPLOW */ -#ifndef __LOCALE_C_ONLY -#define __WCTYPE_WITH_LOCALE +/**********************************************************************/ +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_iswspace +/* generates one warning */ +#warning TODO: Fix the __CTYPE_* codes! +#endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#if 1 +/* Taking advantage of the C99 mutual-exclusion guarantees for the various + * (w)ctype classes, including the descriptions of printing and control + * (w)chars, we can place each in one of the following mutually-exlusive + * subsets. Since there are less than 16, we can store the data for + * each (w)chars in a nibble. In contrast, glibc uses an unsigned int + * per (w)char, with one bit flag for each is* type. While this allows + * a simple '&' operation to determine the type vs. a range test and a + * little special handling for the "blank" and "xdigit" types in my + * approach, it also uses 8 times the space for the tables on the typical + * 32-bit archs we supported.*/ +enum { + __CTYPE_unclassified = 0, + __CTYPE_alpha_nonupper_nonlower, + __CTYPE_alpha_lower, + __CTYPE_alpha_upper_lower, + __CTYPE_alpha_upper, + __CTYPE_digit, + __CTYPE_punct, + __CTYPE_graph, + __CTYPE_print_space_nonblank, + __CTYPE_print_space_blank, + __CTYPE_space_nonblank_noncntrl, + __CTYPE_space_blank_noncntrl, + __CTYPE_cntrl_space_nonblank, + __CTYPE_cntrl_space_blank, + __CTYPE_cntrl_nonspace +}; #endif -/**********************************************************************/ -#ifndef __PASTE -#define __PASTE(X,Y) X ## Y +/* The following is used to implement wctype(), but it is defined + * here because the ordering must agree with that of the enumeration + * below (ignoring unclassified). */ +#define __CTYPE_TYPESTRING \ + "\6alnum\0\6alpha\0\6blank\0\6cntrl\0\6digit\0\6graph\0\6lower\0" \ + "\6print\0\6punct\0\6space\0\6upper\0\7xdigit\0\0" + + +/* The values for wctype_t. */ +enum { + _CTYPE_unclassified = 0, + _CTYPE_isalnum, + _CTYPE_isalpha, + _CTYPE_isblank, + _CTYPE_iscntrl, + _CTYPE_isdigit, + _CTYPE_isgraph, + _CTYPE_islower, + _CTYPE_isprint, + _CTYPE_ispunct, + _CTYPE_isspace, + _CTYPE_isupper, + _CTYPE_isxdigit /* _MUST_ be last of the standard classes! */ +}; + +/* The following is used to implement wctrans(). */ + +#define __CTYPE_TRANSTRING "\10tolower\0\10toupper\0\10totitle\0\0" + +enum { + _CTYPE_tolower = 1, + _CTYPE_toupper, + _CTYPE_totitle +}; + +/*--------------------------------------------------------------------*/ + +#define _CTYPE_iswxdigit (_CTYPE_isxdigit) + +/*--------------------------------------------------------------------*/ + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_iswspace +/* generates one warning */ +#warning TODO: Fix WC* defines! #endif +#endif /* __UCLIBC_MJN3_ONLY__ */ -#define C_MACRO(X) __PASTE(__C_,X)(wc) +#define ENCODING ((__UCLIBC_CURLOCALE_DATA).encoding) -#define CT_MACRO(X) __PASTE(__ctype_,X)(wc) +#define WCctype ((__UCLIBC_CURLOCALE_DATA).tblwctype) +#define WCuplow ((__UCLIBC_CURLOCALE_DATA).tblwuplow) +#define WCcmob ((__UCLIBC_CURLOCALE_DATA).tblwcomb) +#define WCuplow_diff ((__UCLIBC_CURLOCALE_DATA).tblwuplow_diff) + + +#define WC_TABLE_DOMAIN_MAX __LOCALE_DATA_WC_TABLE_DOMAIN_MAX + +#define WCctype_II_LEN __LOCALE_DATA_WCctype_II_LEN +#define WCctype_TI_LEN __LOCALE_DATA_WCctype_TI_LEN +#define WCctype_UT_LEN __LOCALE_DATA_WCctype_UT_LEN +#define WCctype_II_SHIFT __LOCALE_DATA_WCctype_II_SHIFT +#define WCctype_TI_SHIFT __LOCALE_DATA_WCctype_TI_SHIFT + +#define WCuplow_II_LEN __LOCALE_DATA_WCuplow_II_LEN +#define WCuplow_TI_LEN __LOCALE_DATA_WCuplow_TI_LEN +#define WCuplow_UT_LEN __LOCALE_DATA_WCuplow_UT_LEN +#define WCuplow_II_SHIFT __LOCALE_DATA_WCuplow_II_SHIFT +#define WCuplow_TI_SHIFT __LOCALE_DATA_WCuplow_TI_SHIFT + + +#define WCctype_TI_MASK ((1 << (WCctype_TI_SHIFT)) - 1) +#define WCctype_II_MASK ((1 << (WCctype_II_SHIFT)) - 1) /**********************************************************************/ -/* TODO: fix this! */ -#ifdef __WCTYPE_WITH_LOCALE +#undef __PASTE2 +#undef __PASTE3 +#define __PASTE2(X,Y) X ## Y +#define __PASTE3(X,Y,Z) X ## Y ## Z -#define WCctype (__global_locale.tblwctype) -#define WCuplow (__global_locale.tblwuplow) -#define WCcmob (__global_locale.tblwcomb) -#define WCuplow_diff (__global_locale.tblwuplow_diff) +#ifdef __UCLIBC_DO_XLOCALE -#define ENCODING (__global_locale.encoding) +extern int __iswctype_l (wint_t __wc, wctype_t __desc, __locale_t __locale) + __THROW; #define ISW_FUNC_BODY(NAME) \ -int NAME (wint_t wc) \ +int __PASTE3(__isw,NAME,_l) (wint_t wc, __locale_t l) \ { \ - return iswctype(wc, __PASTE(_CTYPE_,NAME)); \ -} + return __iswctype_l(wc, __PASTE2(_CTYPE_is,NAME), l); \ +} \ +weak_alias(__PASTE3(__isw,NAME,_l), __PASTE3(isw,NAME,_l)) + +#else /* __UCLIBC_DO_XLOCALE */ -#else /* __WCTYPE_WITH_LOCALE */ +extern int __iswctype (wint_t __wc, wctype_t __desc) __THROW; #define ISW_FUNC_BODY(NAME) \ -int NAME (wint_t wc) \ +int __PASTE2(isw,NAME) (wint_t wc) \ { \ - return C_MACRO(NAME); \ + return __iswctype(wc, __PASTE2(_CTYPE_is,NAME)); \ } -#endif /* __WCTYPE_WITH_LOCALE */ - +#endif /* __UCLIBC_DO_XLOCALE */ /**********************************************************************/ -#ifdef L_iswalnum +#if defined(L_iswalnum) || defined(L_iswalnum_l) -ISW_FUNC_BODY(iswalnum); +ISW_FUNC_BODY(alnum); #endif /**********************************************************************/ -#ifdef L_iswalpha +#if defined(L_iswalpha) || defined(L_iswalpha_l) -ISW_FUNC_BODY(iswalpha); +ISW_FUNC_BODY(alpha); #endif /**********************************************************************/ -#ifdef L_iswblank +#if defined(L_iswblank) || defined(L_iswblank_l) -ISW_FUNC_BODY(iswblank); +ISW_FUNC_BODY(blank); #endif /**********************************************************************/ -#ifdef L_iswcntrl +#if defined(L_iswcntrl) || defined(L_iswcntrl_l) -ISW_FUNC_BODY(iswcntrl); +ISW_FUNC_BODY(cntrl); #endif /**********************************************************************/ -#ifdef L_iswdigit +#if defined(L_iswdigit) || defined(L_iswdigit_l) -int iswdigit(wint_t wc) -{ - return __C_iswdigit(wc); -} +ISW_FUNC_BODY(digit); #endif /**********************************************************************/ -#ifdef L_iswgraph +#if defined(L_iswgraph) || defined(L_iswgraph_l) -ISW_FUNC_BODY(iswgraph); +ISW_FUNC_BODY(graph); #endif /**********************************************************************/ -#ifdef L_iswlower +#if defined(L_iswlower) || defined(L_iswlower_l) -ISW_FUNC_BODY(iswlower); +ISW_FUNC_BODY(lower); #endif /**********************************************************************/ -#ifdef L_iswprint +#if defined(L_iswprint) || defined(L_iswprint_l) -ISW_FUNC_BODY(iswprint); +ISW_FUNC_BODY(print); #endif /**********************************************************************/ -#ifdef L_iswpunct +#if defined(L_iswpunct) || defined(L_iswpunct_l) -ISW_FUNC_BODY(iswpunct); +ISW_FUNC_BODY(punct); #endif /**********************************************************************/ -#ifdef L_iswspace +#if defined(L_iswspace) || defined(L_iswspace_l) -ISW_FUNC_BODY(iswspace); +ISW_FUNC_BODY(space); #endif /**********************************************************************/ -#ifdef L_iswupper +#if defined(L_iswupper) || defined(L_iswupper_l) -ISW_FUNC_BODY(iswupper); +ISW_FUNC_BODY(upper); #endif /**********************************************************************/ -#ifdef L_iswxdigit +#if defined(L_iswxdigit) || defined(L_iswxdigit_l) -int iswxdigit(wint_t wc) -{ - return __C_iswxdigit(wc); -} +ISW_FUNC_BODY(xdigit); #endif /**********************************************************************/ +#if defined(L_towlower) || defined(L_towlower_l) + #ifdef L_towlower +#define TOWLOWER(w) towlower(w) +#else /* L_towlower */ +#define TOWLOWER(w) __towlower_l(w, __locale_t locale) +#undef __UCLIBC_CURLOCALE_DATA +#undef __UCLIBC_CURLOCALE +#define __UCLIBC_CURLOCALE_DATA (*locale) +#define __UCLIBC_CURLOCALE (locale) +#endif /* L_towlower */ + +#ifdef __UCLIBC_HAS_XLOCALE__ +#define TOWCTRANS(w,d) __towctrans_l(w,d, __UCLIBC_CURLOCALE) +#else /* __UCLIBC_HAS_XLOCALE__ */ +#define TOWCTRANS(w,d) towctrans(w,d) +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +#define __C_towlower(wc) \ + ((((__uwchar_t)(wc)) <= 0x7f) ? (__C_ctype_tolower)[(wc)] : (wc)) + +#ifdef __LOCALE_C_ONLY -#ifdef __WCTYPE_WITH_LOCALE +wint_t towlower(wint_t wc) +{ + return __C_towlower(wc); +} + +#else /* __LOCALE_C_ONLY */ #ifdef SMALL_UPLOW +#if defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) + wint_t towlower(wint_t wc) { - return towctrans(wc, _CTYPE_tolower); + return __towctrans_l(wc, _CTYPE_tolower, __UCLIBC_CURLOCALE); } -#else +#else /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */ + +wint_t TOWLOWER(wint_t wc) +{ + return TOWCTRANS(wc, _CTYPE_tolower); +} + +#endif /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */ + +#else /* SMALL_UPLOW */ + +#if defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) wint_t towlower(wint_t wc) +{ + return __towlower_l(wc, __UCLIBC_CURLOCALE); +} + +#else /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */ + +wint_t TOWLOWER(wint_t wc) { unsigned int sc, n, i; __uwchar_t u = wc; @@ -202,33 +362,78 @@ wint_t towlower(wint_t wc) return wc; } -#endif +#endif /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */ -#else /* __WCTYPE_WITH_LOCALE */ +#endif /* SMALL_UPLOW */ -wint_t towlower(wint_t wc) -{ - return __C_towlower(wc); -} +#ifdef L_towlower_l +weak_alias(__towlower_l, towlower_l) +#endif /* L_towlower_l */ -#endif /* __WCTYPE_WITH_LOCALE */ +#endif /* __LOCALE_C_ONLY */ #endif /**********************************************************************/ +#if defined(L_towupper) || defined(L_towupper_l) + #ifdef L_towupper +#define TOWUPPER(w) towupper(w) +#else /* L_towupper */ +#define TOWUPPER(w) __towupper_l(w, __locale_t locale) +#undef __UCLIBC_CURLOCALE_DATA +#undef __UCLIBC_CURLOCALE +#define __UCLIBC_CURLOCALE_DATA (*locale) +#define __UCLIBC_CURLOCALE (locale) +#endif /* L_towupper */ + +#ifdef __UCLIBC_HAS_XLOCALE__ +#define TOWCTRANS(w,d) __towctrans_l(w,d, __UCLIBC_CURLOCALE) +#else /* __UCLIBC_HAS_XLOCALE__ */ +#define TOWCTRANS(w,d) towctrans(w,d) +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +#define __C_towupper(wc) \ + ((((__uwchar_t)(wc)) <= 0x7f) ? (__C_ctype_toupper)[(wc)] : (wc)) + +#ifdef __LOCALE_C_ONLY -#ifdef __WCTYPE_WITH_LOCALE +wint_t towupper(wint_t wc) +{ + return __C_towupper(wc); +} + +#else /* __LOCALE_C_ONLY */ #ifdef SMALL_UPLOW +#if defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) + wint_t towupper(wint_t wc) { - return towctrans(wc, _CTYPE_toupper); + return __towctrans_l(wc, _CTYPE_toupper, __UCLIBC_CURLOCALE); } -#else +#else /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */ + +wint_t TOWUPPER(wint_t wc) +{ + return TOWCTRANS(wc, _CTYPE_toupper); +} + +#endif /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */ + +#else /* SMALL_UPLOW */ + +#if defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) wint_t towupper(wint_t wc) +{ + return __towupper_l(wc, __UCLIBC_CURLOCALE); +} + +#else /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */ + +wint_t TOWUPPER(wint_t wc) { unsigned int sc, n, i; __uwchar_t u = wc; @@ -254,16 +459,15 @@ wint_t towupper(wint_t wc) return wc; } -#endif +#endif /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */ -#else /* __WCTYPE_WITH_LOCALE */ +#endif /* SMALL_UPLOW */ -wint_t towupper(wint_t wc) -{ - return __C_towupper(wc); -} +#ifdef L_towupper_l +weak_alias(__towupper_l, towupper_l) +#endif /* L_towupper_l */ -#endif /* __WCTYPE_WITH_LOCALE */ +#endif /* __LOCALE_C_ONLY */ #endif /**********************************************************************/ @@ -293,33 +497,102 @@ wctype_t wctype(const char *property) #endif /**********************************************************************/ -#ifdef L_iswctype +#ifdef L_wctype_l #ifdef __UCLIBC_MJN3_ONLY__ -#warning duh... replace the range-based classification with table lookup! -#endif +#warning REMINDER: Currently wctype_l simply calls wctype. +#endif /* __UCLIBC_MJN3_ONLY__ */ -#ifdef __WCTYPE_WITH_LOCALE +wctype_t __wctype_l (const char *property, __locale_t locale) +{ + return wctype(property); +} + +weak_alias(__wctype_l, wctype_l) + +#endif +/**********************************************************************/ +#if defined(L_iswctype) || defined(L_iswctype_l) + +#define __C_iswdigit(c) \ + ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((c) - '0')) < 10) \ + : (((__uwchar_t)((c) - '0')) < 10)) +#define __C_iswxdigit(c) \ + (__C_iswdigit(c) \ + || ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((((c)) | 0x20) - 'a')) < 6) \ + : (((__uwchar_t)((((c)) | 0x20) - 'a')) < 6))) #ifdef __UCLIBC_MJN3_ONLY__ -#warning TODO: need to fix locale ctype table lookup stuff +#ifdef L_iswctype +#warning CONSIDER: Change to bit shift? would need to sync with wctype.h #endif -#if 0 -extern const char ctype_range[]; -#else -static const char ctype_range[] = { - __CTYPE_RANGES +#endif /* __UCLIBC_MJN3_ONLY__ */ + + +#if !defined(__UCLIBC_HAS_XLOCALE__) || defined(L_iswctype_l) + +static const unsigned short int desc2flag[] = { + [_CTYPE_unclassified] = 0, + [_CTYPE_isalnum] = (unsigned short int) _ISwalnum, + [_CTYPE_isalpha] = (unsigned short int) _ISwalpha, + [_CTYPE_isblank] = (unsigned short int) _ISwblank, + [_CTYPE_iscntrl] = (unsigned short int) _ISwcntrl, + [_CTYPE_isdigit] = (unsigned short int) _ISwdigit, + [_CTYPE_isgraph] = (unsigned short int) _ISwgraph, + [_CTYPE_islower] = (unsigned short int) _ISwlower, + [_CTYPE_isprint] = (unsigned short int) _ISwprint, + [_CTYPE_ispunct] = (unsigned short int) _ISwpunct, + [_CTYPE_isspace] = (unsigned short int) _ISwspace, + [_CTYPE_isupper] = (unsigned short int) _ISwupper, + [_CTYPE_isxdigit] = (unsigned short int) _ISwxdigit, }; -#endif + +#endif /* defined(L_iswctype_L) || defined(__LOCALE_C_ONLY) */ + +#ifdef __LOCALE_C_ONLY + +int __iswctype(wint_t wc, wctype_t desc) +{ + /* Note... wctype_t is unsigned. */ + + if ((((__uwchar_t) wc) <= 0x7f) + && (desc < (sizeof(desc2flag)/sizeof(desc2flag[0]))) + ) { + return __isctype(wc, desc2flag[desc]); + } + return 0; +} + +#else /* __LOCALE_C_ONLY */ #ifdef __UCLIBC_MJN3_ONLY__ -#warning TODO: need to handle combining class! +#ifdef L_iswctype +#warning CONSIDER: Handle combining class? #endif +#endif /* __UCLIBC_MJN3_ONLY__ */ -#define WCctype_TI_MASK ((1 << WCctype_TI_SHIFT) - 1) -#define WCctype_II_MASK ((1 << WCctype_II_SHIFT) - 1) +#ifdef L_iswctype +#define ISWCTYPE(w,d) __iswctype(w,d) +#else /* L_iswctype */ +#define ISWCTYPE(w,d) __iswctype_l(w,d, __locale_t locale) +#undef __UCLIBC_CURLOCALE_DATA +#undef __UCLIBC_CURLOCALE +#define __UCLIBC_CURLOCALE_DATA (*locale) +#define __UCLIBC_CURLOCALE (locale) +#endif /* L_iswctype */ + +#if defined(L_iswctype) && defined(__UCLIBC_HAS_XLOCALE__) + +int __iswctype(wint_t wc, wctype_t desc) +{ + return __iswctype_l(wc, desc, __UCLIBC_CURLOCALE); +} -int iswctype(wint_t wc, wctype_t desc) +#else /* defined(L_iswctype) && defined(__UCLIBC_HAS_XLOCALE__) */ + +int ISWCTYPE(wint_t wc, wctype_t desc) { unsigned int sc, n, i0, i1; unsigned char d = __CTYPE_unclassified; @@ -348,122 +621,100 @@ int iswctype(wint_t wc, wctype_t desc) d = __CTYPE_punct; } +#if 0 return ( ((unsigned char)(d - ctype_range[2*desc])) <= ctype_range[2*desc + 1] ) && ((desc != _CTYPE_iswblank) || (d & 1)); +#else + return (__UCLIBC_CURLOCALE_DATA).code2flag[d] & desc2flag[desc]; +#endif } +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: xdigit really needs to be handled better. Remember only for ascii! +#endif /* __UCLIBC_MJN3_ONLY__ */ /* TODO - Add locale-specific classifications. */ return (desc == _CTYPE_iswxdigit) ? __C_iswxdigit(wc) : 0; } return 0; } -#else +#endif /* defined(L_iswctype) && defined(__UCLIBC_HAS_XLOCALE__) */ -static const unsigned char WCctype[] = { - __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4), - __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4), - __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4), - __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4), - __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_space_blank << 4), - __CTYPE_cntrl_space_nonblank | (__CTYPE_cntrl_space_nonblank << 4), - __CTYPE_cntrl_space_nonblank | (__CTYPE_cntrl_space_nonblank << 4), - __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4), - __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4), - __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4), - __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4), - __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4), - __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4), - __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4), - __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4), - __CTYPE_cntrl_nonspace | (__CTYPE_cntrl_nonspace << 4), - __CTYPE_print_space_blank | (__CTYPE_punct << 4), - __CTYPE_punct | (__CTYPE_punct << 4), - __CTYPE_punct | (__CTYPE_punct << 4), - __CTYPE_punct | (__CTYPE_punct << 4), - __CTYPE_punct | (__CTYPE_punct << 4), - __CTYPE_punct | (__CTYPE_punct << 4), - __CTYPE_punct | (__CTYPE_punct << 4), - __CTYPE_punct | (__CTYPE_punct << 4), - __CTYPE_digit | (__CTYPE_digit << 4), - __CTYPE_digit | (__CTYPE_digit << 4), - __CTYPE_digit | (__CTYPE_digit << 4), - __CTYPE_digit | (__CTYPE_digit << 4), - __CTYPE_digit | (__CTYPE_digit << 4), - __CTYPE_punct | (__CTYPE_punct << 4), - __CTYPE_punct | (__CTYPE_punct << 4), - __CTYPE_punct | (__CTYPE_punct << 4), - __CTYPE_punct | (__CTYPE_alpha_upper << 4), - __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4), - __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4), - __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4), - __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4), - __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4), - __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4), - __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4), - __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4), - __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4), - __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4), - __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4), - __CTYPE_alpha_upper | (__CTYPE_alpha_upper << 4), - __CTYPE_alpha_upper | (__CTYPE_punct << 4), - __CTYPE_punct | (__CTYPE_punct << 4), - __CTYPE_punct | (__CTYPE_punct << 4), - __CTYPE_punct | (__CTYPE_alpha_lower << 4), - __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4), - __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4), - __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4), - __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4), - __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4), - __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4), - __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4), - __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4), - __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4), - __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4), - __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4), - __CTYPE_alpha_lower | (__CTYPE_alpha_lower << 4), - __CTYPE_alpha_lower | (__CTYPE_punct << 4), - __CTYPE_punct | (__CTYPE_punct << 4), - __CTYPE_punct | (__CTYPE_cntrl_nonspace << 4), -}; +#ifdef L_iswctype_l +weak_alias(__iswctype_l, iswctype_l) +#endif /* L_iswctype_l */ -static const char ctype_range[] = { - __CTYPE_RANGES -}; +#endif /* __LOCALE_C_ONLY */ -int iswctype(wint_t wc, wctype_t desc) -{ - unsigned char d = __CTYPE_unclassified; +#ifdef L_iswctype +weak_alias(__iswctype, iswctype) +#endif /* L_iswctype */ - if (((__uwchar_t) wc) <= 0x7f) { - if (desc < _CTYPE_iswxdigit) { - d = WCctype[wc >> 1]; - d = (wc & 1) ? (d >> 4) : (d & 0xf); +#endif +/**********************************************************************/ +#if defined(L_towctrans) || defined(L_towctrans_l) - return ( ((unsigned char)(d - ctype_range[2*desc])) - <= ctype_range[2*desc + 1] ) - && ((desc != _CTYPE_iswblank) || (d & 1)); - } +#ifdef __LOCALE_C_ONLY + +/* Minimal support for C/POSIX locale. */ + +#ifndef _tolower +#warning _tolower is undefined! +#define _tolower(c) tolower(c) +#endif +#ifndef _toupper +#warning _toupper is undefined! +#define _toupper(c) toupper(c) +#endif - if (desc == _CTYPE_iswxdigit) { - return __C_isxdigit(((char) wc)); +wint_t towctrans(wint_t wc, wctrans_t desc) +{ + if (((unsigned int)(desc - _CTYPE_tolower)) + <= (_CTYPE_toupper - _CTYPE_tolower) + ) { + /* Transliteration is either tolower or toupper. */ + if (((__uwchar_t) wc) <= 0x7f) { + return (desc == _CTYPE_tolower) ? _tolower(wc) : _toupper(wc); } + } else { + __set_errno(EINVAL); /* Invalid transliteration. */ } - return 0; + return wc; } -#endif +#else /* __LOCALE_C_ONLY */ -#endif -/**********************************************************************/ #ifdef L_towctrans +#define TOWCTRANS(w,d) towctrans(w,d) +#else /* L_towctrans */ +#define TOWCTRANS(w,d) __towctrans_l(w,d, __locale_t locale) +#undef __UCLIBC_CURLOCALE_DATA +#undef __UCLIBC_CURLOCALE +#define __UCLIBC_CURLOCALE_DATA (*locale) +#define __UCLIBC_CURLOCALE (locale) +#endif /* L_towctrans */ + +#ifdef __UCLIBC_HAS_XLOCALE__ +#define TOWLOWER(w,l) __towlower_l(w,l) +#define TOWUPPER(w,l) __towupper_l(w,l) +#else /* __UCLIBC_HAS_XLOCALE__ */ +#define TOWLOWER(w,l) towlower(w) +#define TOWUPPER(w,l) towupper(w) +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +#if defined(L_towctrans) && defined(__UCLIBC_HAS_XLOCALE__) -#ifdef __WCTYPE_WITH_LOCALE +wint_t towctrans(wint_t wc, wctrans_t desc) +{ + return __towctrans_l(wc, desc, __UCLIBC_CURLOCALE); +} + +#else /* defined(L_towctrans) && defined(__UCLIBC_HAS_XLOCALE__) */ #ifdef SMALL_UPLOW -wint_t towctrans(wint_t wc, wctrans_t desc) +wint_t TOWCTRANS(wint_t wc, wctrans_t desc) { unsigned int sc, n, i; __uwchar_t u = wc; @@ -499,6 +750,9 @@ wint_t towctrans(wint_t wc, wctrans_t desc) } wc += WCuplow_diff[i]; if (desc == _CTYPE_totitle) { +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Verify totitle special cases! +#endif /* __UCLIBC_MJN3_ONLY__ */ /* WARNING! These special cases work for glibc 2.2.4. Changes * may be needed if the glibc locale tables are updated. */ if ( (((__uwchar_t)(wc - 0x1c4)) <= (0x1cc - 0x1c4)) @@ -516,9 +770,9 @@ wint_t towctrans(wint_t wc, wctrans_t desc) return wc; } -#else +#else /* SMALL_UPLOW */ -wint_t towctrans(wint_t wc, wctrans_t desc) +wint_t TOWCTRANS(wint_t wc, wctrans_t desc) { if (ENCODING == __ctype_encoding_7_bit) { if ((((__uwchar_t) wc) > 0x7f) @@ -532,12 +786,15 @@ wint_t towctrans(wint_t wc, wctrans_t desc) } if (desc == _CTYPE_tolower) { - return towlower(wc); + return TOWLOWER(wc, __UCLIBC_CURLOCALE); } else if (((unsigned int)(desc - _CTYPE_toupper)) <= (_CTYPE_totitle - _CTYPE_toupper) ) { - wc = towupper(wc); + wc = TOWUPPER(wc, __UCLIBC_CURLOCALE); if (desc == _CTYPE_totitle) { +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Verify totitle special cases! +#endif /* __UCLIBC_MJN3_ONLY__ */ /* WARNING! These special cases work for glibc 2.2.4. Changes * may be needed if the glibc locale tables are updated. */ if ( (((__uwchar_t)(wc - 0x1c4)) <= (0x1cc - 0x1c4)) @@ -553,28 +810,15 @@ wint_t towctrans(wint_t wc, wctrans_t desc) return wc; } -#endif +#endif /* SMALL_UPLOW */ -#else /* __WCTYPE_WITH_LOCALE */ +#endif /* defined(L_towctrans) && defined(__UCLIBC_HAS_XLOCALE__) */ -/* Minimal support for C/POSIX locale. */ +#ifdef L_towctrans_l +weak_alias(__towctrans_l, towctrans_l) +#endif /* L_towctrans_l */ -wint_t towctrans(wint_t wc, wctrans_t desc) -{ - if (((unsigned int)(desc - _CTYPE_tolower)) - <= (_CTYPE_toupper - _CTYPE_tolower) - ) { - /* Transliteration is either tolower or toupper. */ - if (((__uwchar_t) wc) <= 0x7f) { - return (desc == _CTYPE_tolower) ? _tolower(wc) : _toupper(wc); - } - } else { - __set_errno(EINVAL); /* Invalid transliteration. */ - } - return wc; -} - -#endif /* __WCTYPE_WITH_LOCALE */ +#endif /* __LOCALE_C_ONLY */ #endif /**********************************************************************/ @@ -603,3 +847,18 @@ wctrans_t wctrans(const char *property) #endif /**********************************************************************/ +#ifdef L_wctrans_l + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: Currently wctrans_l simply calls wctrans. +#endif /* __UCLIBC_MJN3_ONLY__ */ + +wctrans_t __wctrans_l(const char *property, __locale_t locale) +{ + return wctrans(property); +} + +weak_alias(__wctrans_l, wctrans_l) + +#endif +/**********************************************************************/ -- cgit v1.2.3