summaryrefslogtreecommitdiff
path: root/libc/misc
diff options
context:
space:
mode:
authorManuel Novoa III <mjn3@codepoet.org>2003-08-01 20:08:59 +0000
committerManuel Novoa III <mjn3@codepoet.org>2003-08-01 20:08:59 +0000
commit1217289737588e65b088b3535428b27c7287d699 (patch)
tree6a292ac767d219702e26a6a2111737f84a96900c /libc/misc
parent32b76c5ec3c257b7287913d0d1a96e0cbb2e9c6a (diff)
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.
Diffstat (limited to 'libc/misc')
-rw-r--r--libc/misc/Makefile4
-rw-r--r--libc/misc/assert/__assert.c16
-rw-r--r--libc/misc/ctype/Makefile29
-rw-r--r--libc/misc/ctype/ctype.c1041
-rw-r--r--libc/misc/intl/Makefile50
-rw-r--r--libc/misc/intl/intl.c149
-rw-r--r--libc/misc/locale/Makefile31
-rw-r--r--libc/misc/locale/locale.c1103
-rw-r--r--libc/misc/time/Makefile13
-rw-r--r--libc/misc/time/time.c245
-rw-r--r--libc/misc/wchar/Makefile1
-rw-r--r--libc/misc/wchar/wchar.c111
-rw-r--r--libc/misc/wchar/wstdio.c37
-rw-r--r--libc/misc/wctype/Makefile20
-rw-r--r--libc/misc/wctype/wctype.c661
15 files changed, 2667 insertions, 844 deletions
diff --git a/libc/misc/Makefile b/libc/misc/Makefile
index 46de813da..037e2154d 100644
--- a/libc/misc/Makefile
+++ b/libc/misc/Makefile
@@ -26,8 +26,8 @@ include $(TOPDIR)Rules.mak
DIRS = assert ctype dirent file fnmatch glob internals \
- mntent syslog time utmp locale sysvipc statfs \
- error ttyent gnu search
+ mntent syslog time utmp sysvipc statfs \
+ error ttyent gnu search intl locale
ifeq ($(strip $(UCLIBC_HAS_REGEX)),y)
DIRS += regex
endif
diff --git a/libc/misc/assert/__assert.c b/libc/misc/assert/__assert.c
index efffff1de..26bcc6516 100644
--- a/libc/misc/assert/__assert.c
+++ b/libc/misc/assert/__assert.c
@@ -37,15 +37,21 @@
#include <assert.h>
#undef assert
+
+#define ASSERT_SHOW_PROGNAME 1
+
+#ifdef ASSERT_SHOW_PROGNAME
+extern const char *__progname;
+#endif
+
#if 1
void __assert(const char *assertion, const char * filename,
int linenumber, register const char * function)
{
fprintf(stderr,
-#if 0
- /* TODO: support program_name like glibc? */
- "%s: %s: %d: %s: Assertion `%s' failed.\n", program_name,
+#ifdef ASSERT_SHOW_PROGNAME
+ "%s: %s: %d: %s: Assertion `%s' failed.\n", __progname,
#else
"%s: %d: %s: Assertion `%s' failed.\n",
#endif
@@ -66,8 +72,8 @@ void __assert(const char *assertion, const char * filename,
char buf[__BUFLEN_INT10TOSTR];
_stdio_fdout(STDERR_FILENO,
-#if 0
- program_name, /* TODO: support program_name like glibc? */
+#ifdef ASSERT_SHOW_PROGNAME
+ __progname,
": ",
#endif
filename,
diff --git a/libc/misc/ctype/Makefile b/libc/misc/ctype/Makefile
index 1d7c24535..2f1dd65f0 100644
--- a/libc/misc/ctype/Makefile
+++ b/libc/misc/ctype/Makefile
@@ -25,17 +25,26 @@ TOPDIR=../../../
include $(TOPDIR)Rules.mak
MSRC=ctype.c
-MOBJ= isalnum.o isalpha.o isascii.o iscntrl.o isdigit.o isgraph.o \
- islower.o isprint.o ispunct.o isspace.o isupper.o isxdigit.o \
- isxlower.o isxupper.o toascii.o tolower.o toupper.o isblank.o \
- __isctype_loc.o
+MOBJ= isalnum.o isalpha.o isascii.o iscntrl.o isdigit.o \
+ isgraph.o islower.o isprint.o ispunct.o isspace.o \
+ isupper.o isxdigit.o toascii.o tolower.o toupper.o \
+ isblank.o isctype.o isxlower.o isxupper.o \
+ __C_ctype_b.o __C_ctype_tolower.o __C_ctype_toupper.o \
+ __ctype_b_loc.o __ctype_tolower_loc.o __ctype_toupper_loc.o \
+ __ctype_assert.o
-CSRC=junk.c
-COBJS=$(patsubst %.c,%.o, $(CSRC))
+MOBJx= isalnum_l.o isalpha_l.o isascii_l.o iscntrl_l.o isdigit_l.o \
+ isgraph_l.o islower_l.o isprint_l.o ispunct_l.o isspace_l.o \
+ isupper_l.o isxdigit_l.o toascii_l.o tolower_l.o toupper_l.o \
+ isblank_l.o # isxlower_l.o isxupper_l.o
+OBJS=$(MOBJ)
-OBJS=$(MOBJ) $(COBJS)
-all: $(MOBJ) $(LIBC)
+ifeq ($(UCLIBC_HAS_XLOCALE),y)
+ OBJS += $(MOBJx)
+endif
+
+all: $(OBJS) $(LIBC)
$(LIBC): ar-target
@@ -46,8 +55,8 @@ $(MOBJ): $(MSRC)
$(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
$(STRIPTOOL) -x -R .note -R .comment $*.o
-$(COBJS): %.o : %.c
- $(CC) $(CFLAGS) -c $< -o $@
+$(MOBJx): $(MSRC)
+ $(CC) $(CFLAGS) -DL_$* -D__UCLIBC_DO_XLOCALE $< -c -o $*.o
$(STRIPTOOL) -x -R .note -R .comment $*.o
$(OBJS): Makefile
diff --git a/libc/misc/ctype/ctype.c b/libc/misc/ctype/ctype.c
index dedd5c00a..0eb97140d 100644
--- a/libc/misc/ctype/ctype.c
+++ b/libc/misc/ctype/ctype.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Manuel Novoa III
+/* Copyright (C) 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
@@ -31,299 +31,1026 @@
#include <ctype.h>
#include <stdio.h>
+#include <stdlib.h>
#include <limits.h>
+#include <stdint.h>
#include <assert.h>
#include <locale.h>
+#ifdef __UCLIBC_HAS_XLOCALE__
+#include <xlocale.h>
+#endif /* __UCLIBC_HAS_XLOCALE__ */
+
/**********************************************************************/
-extern int __isctype_loc(int c, int ct);
+#ifdef __UCLIBC_HAS_CTYPE_SIGNED__
-/* Some macros used throughout the file. */
-#define U ((unsigned char)c)
-/* #define LCT (__cur_locale->ctype) */
-#define LCT (&__global_locale)
+#if EOF >= CHAR_MIN
+#define CTYPE_DOMAIN_CHECK(C) \
+ (((unsigned int)((C) - CHAR_MIN)) <= (UCHAR_MAX - CHAR_MIN))
+#else
+#define CTYPE_DOMAIN_CHECK(C) \
+ ((((unsigned int)((C) - CHAR_MIN)) <= (UCHAR_MAX - CHAR_MIN)) || ((C) == EOF))
+#endif
-/**********************************************************************/
+#else /* __UCLIBC_HAS_CTYPE_SIGNED__ */
-#ifndef __PASTE
-#define __PASTE(X,Y) X ## Y
+#if EOF == -1
+#define CTYPE_DOMAIN_CHECK(C) \
+ (((unsigned int)((C) - EOF)) <= (UCHAR_MAX - EOF))
+#else
+#define CTYPE_DOMAIN_CHECK(C) \
+ ((((unsigned int)(C)) <= UCHAR_MAX) || ((C) == EOF))
#endif
-#define C_MACRO(X) __PASTE(__C_,X)(c)
-
-#define CT_MACRO(X) __PASTE(__ctype_,X)(c)
+#endif /* __UCLIBC_HAS_CTYPE_SIGNED__ */
/**********************************************************************/
+#ifdef __UCLIBC_MJN3_ONLY__
+#ifdef L_isspace
+/* emit only once */
+#warning CONSIDER: Should we assert when debugging and __UCLIBC_HAS_CTYPE_CHECKED?
+#warning TODO: Fix asserts in to{upper|lower}{_l}.
+#warning TODO: Optimize the isx*() funcs.
+#endif
+#endif /* __UCLIBC_MJN3_ONLY__ */
+
+#undef CTYPE_NAME
+#undef ISCTYPE
+#undef CTYPE_ALIAS
+#ifdef __UCLIBC_DO_XLOCALE
+#define CTYPE_NAME(X) __is ## X ## _l
+#define ISCTYPE(C,F) __isctype_l( C, F, locale_arg)
+#define CTYPE_ALIAS(NAME) weak_alias( __is ## NAME ## _l , is ## NAME ## _l)
+#else
+#define CTYPE_NAME(X) is ## X
+#define ISCTYPE(C,F) __isctype( C, F )
+#define CTYPE_ALIAS(NAME)
+#endif
+#undef PASTE2
+#define PASTE2(X,Y) X ## Y
-#ifndef __CTYPE_HAS_8_BIT_LOCALES
-#define IS_FUNC_BODY(NAME) \
-int NAME (int c) \
-{ \
- return C_MACRO(NAME); \
-}
+#undef CTYPE_BODY
+
+#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__)
+/* Make sure assert is active for to*() funcs below. */
+#undef NDEBUG
+#include <assert.h>
+
+extern void __isctype_assert(int c, int mask) __attribute__ ((__noreturn__));
+
+#define CTYPE_BODY(NAME,C,MASK) \
+ if (CTYPE_DOMAIN_CHECK(C)) { \
+ return ISCTYPE(C, MASK); \
+ } \
+ __isctype_assert(C, MASK);
+
+#elif defined(__UCLIBC_HAS_CTYPE_CHECKED__)
+
+#define CTYPE_BODY(NAME,C,MASK) \
+ return CTYPE_DOMAIN_CHECK(C) \
+ ? ISCTYPE(C, MASK) \
+ : 0;
+
+#elif defined(__UCLIBC_HAS_CTYPE_UNSAFE__)
+
+#define CTYPE_BODY(NAME,C,MASK) \
+ return ISCTYPE(C, MASK);
+
+
+#else /* No checking done. */
+
+#error Unknown type of ctype checking!
+
+#endif
-#else
-/* It may be worth defining __isctype_loc over the whole range of char. */
-/* #define IS_FUNC_BODY(NAME) \ */
-/* int NAME (int c) \ */
-/* { \ */
-/* return __isctype_loc(c, __PASTE(_CTYPE_,NAME)); \ */
-/* } */
#define IS_FUNC_BODY(NAME) \
-int NAME (int c) \
+int CTYPE_NAME(NAME) (int c __LOCALE_PARAM ) \
{ \
- if (((unsigned int) c) <= 0x7f) { \
- return C_MACRO(NAME); \
- } \
- return __isctype_loc(c, __PASTE(_CTYPE_,NAME)); \
+ CTYPE_BODY(NAME,c,PASTE2(_IS,NAME)) \
+} \
+CTYPE_ALIAS(NAME)
+
+
+/**********************************************************************/
+#ifdef L___ctype_assert
+#ifdef __UCLIBC_HAS_CTYPE_ENFORCED__
+
+extern const char *__progname;
+
+void __isctype_assert(int c, int mask)
+{
+ fprintf(stderr, "%s: __is*{_l}(%d,%#x {locale})\n", __progname, c, mask);
+ abort();
}
-#endif /* __CTYPE_HAS_8_BIT_LOCALES */
+#endif
+#endif
+/**********************************************************************/
+#if defined(L_isalnum) || defined(L_isalnum_l)
+
+IS_FUNC_BODY(alnum);
+
+#endif
+/**********************************************************************/
+#if defined(L_isalpha) || defined(L_isalpha_l)
+IS_FUNC_BODY(alpha);
+
+#endif
/**********************************************************************/
-#ifdef L_isalnum
+#if defined(L_isblank) || defined(L_isblank_l)
-IS_FUNC_BODY(isalnum);
+IS_FUNC_BODY(blank);
#endif
/**********************************************************************/
-#ifdef L_isalpha
+#if defined(L_iscntrl) || defined(L_iscntrl_l)
-IS_FUNC_BODY(isalpha);
+IS_FUNC_BODY(cntrl);
#endif
/**********************************************************************/
-#ifdef L_isblank
+#if defined(L_isdigit) || defined(L_isdigit_l)
-/* Warning!!! This is correct for all the currently supported 8-bit locales.
- * If any are added though, this will need to be verified. */
+/* The standards require EOF < 0. */
+#if EOF >= CHAR_MIN
+#define __isdigit_char_or_EOF(C) __isdigit_char((C))
+#else
+#define __isdigit_char_or_EOF(C) __isdigit_int((C))
+#endif
-int isblank(int c)
+int CTYPE_NAME(digit) (int C __LOCALE_PARAM)
{
- return __isblank(c);
+#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__)
+ if (CTYPE_DOMAIN_CHECK(C)) {
+ return __isdigit_char_or_EOF(C); /* C is (unsigned) char or EOF. */
+ }
+ __isctype_assert(C, _ISdigit);
+#else
+ return __isdigit_int(C); /* C could be invalid. */
+#endif
}
+CTYPE_ALIAS(digit)
+
#endif
/**********************************************************************/
-#ifdef L_iscntrl
+#if defined(L_isgraph) || defined(L_isgraph_l)
-IS_FUNC_BODY(iscntrl);
+IS_FUNC_BODY(graph);
#endif
/**********************************************************************/
-#ifdef L_isdigit
+#if defined(L_islower) || defined(L_islower_l)
-int isdigit(int c)
-{
- return __isdigit(c);
-}
+IS_FUNC_BODY(lower);
#endif
/**********************************************************************/
-#ifdef L_isgraph
+#if defined(L_isprint) || defined(L_isprint_l)
-IS_FUNC_BODY(isgraph);
+IS_FUNC_BODY(print);
#endif
/**********************************************************************/
-#ifdef L_islower
+#if defined(L_ispunct) || defined(L_ispunct_l)
-IS_FUNC_BODY(islower);
+IS_FUNC_BODY(punct);
#endif
/**********************************************************************/
-#ifdef L_isprint
+#if defined(L_isspace) || defined(L_isspace_l)
-IS_FUNC_BODY(isprint);
+IS_FUNC_BODY(space);
#endif
/**********************************************************************/
-#ifdef L_ispunct
+#if defined(L_isupper) || defined(L_isupper_l)
-IS_FUNC_BODY(ispunct);
+IS_FUNC_BODY(upper);
#endif
/**********************************************************************/
-#ifdef L_isspace
+#if defined(L_isxdigit) || defined(L_isxdigit_l)
-/* Warning!!! This is correct for all the currently supported 8-bit locales.
- * If any are added though, this will need to be verified. */
+IS_FUNC_BODY(xdigit);
-int isspace(int c)
+#endif
+/**********************************************************************/
+#ifdef L_tolower
+
+int tolower(int c)
{
- return __isspace(c);
+#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__)
+ assert(CTYPE_DOMAIN_CHECK(c));
+#endif
+ return __UCLIBC_CTYPE_IN_TO_DOMAIN(c) ? (__UCLIBC_CTYPE_TOLOWER)[c] : c;
}
#endif
/**********************************************************************/
-#ifdef L_isupper
+#ifdef L_tolower_l
+
+#undef tolower_l
-IS_FUNC_BODY(isupper);
+int tolower_l(int c, __locale_t l)
+{
+#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__)
+ assert(CTYPE_DOMAIN_CHECK(c));
+#endif
+ return __UCLIBC_CTYPE_IN_TO_DOMAIN(c) ? l->__ctype_tolower[c] : c;
+}
#endif
/**********************************************************************/
-#ifdef L_isxdigit
+#ifdef L_toupper
-int isxdigit(int c)
+int toupper(int c)
{
- return __isxdigit(c);
+#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__)
+ assert(CTYPE_DOMAIN_CHECK(c));
+#endif
+ return __UCLIBC_CTYPE_IN_TO_DOMAIN(c) ? (__UCLIBC_CTYPE_TOUPPER)[c] : c;
}
#endif
/**********************************************************************/
-#ifdef L_tolower
+#ifdef L_toupper_l
-#ifdef __CTYPE_HAS_8_BIT_LOCALES
+#undef toupper_l
-int tolower(int c)
+int toupper_l(int c, __locale_t l)
{
- return ((((unsigned int) c) <= 0x7f)
- || (LCT->encoding != __ctype_encoding_8_bit))
- ? __C_tolower(c)
- : ( __isctype_loc(c, _CTYPE_isupper)
- ? (unsigned char)
- ( U - LCT->tbl8uplow[ ((int)
- (LCT->idx8uplow[(U & 0x7f)
- >> Cuplow_IDX_SHIFT])
- << Cuplow_IDX_SHIFT)
- + (U & ((1 << Cuplow_IDX_SHIFT) - 1)) ])
- : c );
+#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__)
+ assert(CTYPE_DOMAIN_CHECK(c));
+#endif
+ return __UCLIBC_CTYPE_IN_TO_DOMAIN(c) ? l->__ctype_toupper[c] : c;
}
-#else /* __CTYPE_HAS_8_BIT_LOCALES */
+#endif
+/**********************************************************************/
+#if defined(L_isascii) || defined(L_isascii_l)
-int tolower(int c)
+int __XL(isascii)(int c)
{
- return __C_tolower(c);
+ return __isascii(c); /* locale-independent */
}
-#endif /* __CTYPE_HAS_8_BIT_LOCALES */
-
#endif
/**********************************************************************/
-#ifdef L_toupper
-
-#ifdef __CTYPE_HAS_8_BIT_LOCALES
+#if defined(L_toascii) || defined(L_toascii_l)
-int toupper(int c)
+int __XL(toascii)(int c)
{
- return ((((unsigned int) c) <= 0x7f)
- || (LCT->encoding != __ctype_encoding_8_bit))
- ? __C_toupper(c)
- : ( __isctype_loc(c, _CTYPE_islower)
- ? (unsigned char)
- ( U + LCT->tbl8uplow[ ((int)
- (LCT->idx8uplow[(U & 0x7f)
- >> Cuplow_IDX_SHIFT])
- << Cuplow_IDX_SHIFT)
- + (U & ((1 << Cuplow_IDX_SHIFT) - 1)) ])
- : c );
+ return __toascii(c); /* locale-independent */
}
-#else /* __CTYPE_HAS_8_BIT_LOCALES */
+#endif
+/**********************************************************************/
+/* old uClibc extensions */
+/**********************************************************************/
+#ifdef L_isxlower
-int toupper(int c)
+int isxlower(int C)
{
- return __C_toupper(c);
+#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__)
+ assert(CTYPE_DOMAIN_CHECK(C));
+ return (__isctype(C, (_ISxdigit|_ISupper)) == _ISxdigit);
+#elif defined(__UCLIBC_HAS_CTYPE_CHECKED__)
+ return CTYPE_DOMAIN_CHECK(C)
+ ? (__isctype(C, (_ISxdigit|_ISupper)) == _ISxdigit)
+ : 0;
+#elif defined(__UCLIBC_HAS_CTYPE_UNSAFE__)
+ return (__isctype(C, (_ISxdigit|_ISupper)) == _ISxdigit);
+#else /* No checking done. */
+#error Unknown type of ctype checking!
+#endif
}
-#endif /* __CTYPE_HAS_8_BIT_LOCALES */
+#endif
+/**********************************************************************/
+#ifdef L_isxupper
+
+int isxupper(int C)
+{
+#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__)
+ assert(CTYPE_DOMAIN_CHECK(C));
+ return (__isctype(C, (_ISxdigit|_ISlower)) == _ISxdigit);
+#elif defined(__UCLIBC_HAS_CTYPE_CHECKED__)
+ return CTYPE_DOMAIN_CHECK(C)
+ ? (__isctype(C, (_ISxdigit|_ISlower)) == _ISxdigit)
+ : 0;
+#elif defined(__UCLIBC_HAS_CTYPE_UNSAFE__)
+ return (__isctype(C, (_ISxdigit|_ISlower)) == _ISxdigit);
+#else /* No checking done. */
+#error Unknown type of ctype checking!
+#endif
+}
#endif
/**********************************************************************/
-#ifdef L_isascii
+/* glibc extensions */
+/**********************************************************************/
+#ifdef L_isctype
-int isascii(int c)
+int isctype(int c, int mask)
{
- return __isascii(c);
+ CTYPE_BODY(NAME,c,mask)
}
#endif
/**********************************************************************/
-#ifdef L_toascii
+#if L___ctype_b_loc
+
+#ifdef __UCLIBC_HAS_XLOCALE__
-int toascii(int c)
+const uint16_t **__ctype_b_loc(void)
{
- return __toascii(c);
+ return &(__UCLIBC_CURLOCALE_DATA).__ctype_b;
}
#endif
+
+#endif
/**********************************************************************/
-#ifdef L_isxlower
+#if L___ctype_tolower_loc
+
+#ifdef __UCLIBC_HAS_XLOCALE__
-int isxlower(int c)
+const __ctype_touplow_t **__ctype_tolower_loc(void)
{
- return __isxlower(c);
+ return &(__UCLIBC_CURLOCALE_DATA).__ctype_tolower;
}
#endif
+
+#endif
/**********************************************************************/
-#ifdef L_isxupper
+#if L___ctype_toupper_loc
+
+#ifdef __UCLIBC_HAS_XLOCALE__
-int isxupper(int c)
+const __ctype_touplow_t **__ctype_toupper_loc(void)
{
- return __isxupper(c);
+ return &(__UCLIBC_CURLOCALE_DATA).__ctype_toupper;
}
#endif
+
+#endif
/**********************************************************************/
-#ifdef L___isctype_loc
-#ifdef __CTYPE_HAS_8_BIT_LOCALES
+#ifdef L___C_ctype_b
+
+const uint16_t __C_ctype_b_data[] = {
+#ifdef __UCLIBC_HAS_CTYPE_SIGNED__
+ /* -128 M-^@ */ 0,
+ /* -127 M-^A */ 0,
+ /* -126 M-^B */ 0,
+ /* -125 M-^C */ 0,
+ /* -124 M-^D */ 0,
+ /* -123 M-^E */ 0,
+ /* -122 M-^F */ 0,
+ /* -121 M-^G */ 0,
+ /* -120 M-^H */ 0,
+ /* -119 M-^I */ 0,
+ /* -118 M-^J */ 0,
+ /* -117 M-^K */ 0,
+ /* -116 M-^L */ 0,
+ /* -115 M-^M */ 0,
+ /* -114 M-^N */ 0,
+ /* -113 M-^O */ 0,
+ /* -112 M-^P */ 0,
+ /* -111 M-^Q */ 0,
+ /* -110 M-^R */ 0,
+ /* -109 M-^S */ 0,
+ /* -108 M-^T */ 0,
+ /* -107 M-^U */ 0,
+ /* -106 M-^V */ 0,
+ /* -105 M-^W */ 0,
+ /* -104 M-^X */ 0,
+ /* -103 M-^Y */ 0,
+ /* -102 M-^Z */ 0,
+ /* -101 M-^[ */ 0,
+ /* -100 M-^\ */ 0,
+ /* -99 M-^] */ 0,
+ /* -98 M-^^ */ 0,
+ /* -97 M-^_ */ 0,
+ /* -96 M- */ 0,
+ /* -95 M-! */ 0,
+ /* -94 M-" */ 0,
+ /* -93 M-# */ 0,
+ /* -92 M-$ */ 0,
+ /* -91 M-% */ 0,
+ /* -90 M-& */ 0,
+ /* -89 M-' */ 0,
+ /* -88 M-( */ 0,
+ /* -87 M-) */ 0,
+ /* -86 M-* */ 0,
+ /* -85 M-+ */ 0,
+ /* -84 M-, */ 0,
+ /* -83 M-- */ 0,
+ /* -82 M-. */ 0,
+ /* -81 M-/ */ 0,
+ /* -80 M-0 */ 0,
+ /* -79 M-1 */ 0,
+ /* -78 M-2 */ 0,
+ /* -77 M-3 */ 0,
+ /* -76 M-4 */ 0,
+ /* -75 M-5 */ 0,
+ /* -74 M-6 */ 0,
+ /* -73 M-7 */ 0,
+ /* -72 M-8 */ 0,
+ /* -71 M-9 */ 0,
+ /* -70 M-: */ 0,
+ /* -69 M-; */ 0,
+ /* -68 M-< */ 0,
+ /* -67 M-= */ 0,
+ /* -66 M-> */ 0,
+ /* -65 M-? */ 0,
+ /* -64 M-@ */ 0,
+ /* -63 M-A */ 0,
+ /* -62 M-B */ 0,
+ /* -61 M-C */ 0,
+ /* -60 M-D */ 0,
+ /* -59 M-E */ 0,
+ /* -58 M-F */ 0,
+ /* -57 M-G */ 0,
+ /* -56 M-H */ 0,
+ /* -55 M-I */ 0,
+ /* -54 M-J */ 0,
+ /* -53 M-K */ 0,
+ /* -52 M-L */ 0,
+ /* -51 M-M */ 0,
+ /* -50 M-N */ 0,
+ /* -49 M-O */ 0,
+ /* -48 M-P */ 0,
+ /* -47 M-Q */ 0,
+ /* -46 M-R */ 0,
+ /* -45 M-S */ 0,
+ /* -44 M-T */ 0,
+ /* -43 M-U */ 0,
+ /* -42 M-V */ 0,
+ /* -41 M-W */ 0,
+ /* -40 M-X */ 0,
+ /* -39 M-Y */ 0,
+ /* -38 M-Z */ 0,
+ /* -37 M-[ */ 0,
+ /* -36 M-\ */ 0,
+ /* -35 M-] */ 0,
+ /* -34 M-^ */ 0,
+ /* -33 M-_ */ 0,
+ /* -32 M-` */ 0,
+ /* -31 M-a */ 0,
+ /* -30 M-b */ 0,
+ /* -29 M-c */ 0,
+ /* -28 M-d */ 0,
+ /* -27 M-e */ 0,
+ /* -26 M-f */ 0,
+ /* -25 M-g */ 0,
+ /* -24 M-h */ 0,
+ /* -23 M-i */ 0,
+ /* -22 M-j */ 0,
+ /* -21 M-k */ 0,
+ /* -20 M-l */ 0,
+ /* -19 M-m */ 0,
+ /* -18 M-n */ 0,
+ /* -17 M-o */ 0,
+ /* -16 M-p */ 0,
+ /* -15 M-q */ 0,
+ /* -14 M-r */ 0,
+ /* -13 M-s */ 0,
+ /* -12 M-t */ 0,
+ /* -11 M-u */ 0,
+ /* -10 M-v */ 0,
+ /* -9 M-w */ 0,
+ /* -8 M-x */ 0,
+ /* -7 M-y */ 0,
+ /* -6 M-z */ 0,
+ /* -5 M-{ */ 0,
+ /* -4 M-| */ 0,
+ /* -3 M-} */ 0,
+ /* -2 M-~ */ 0,
+#endif /* __UCLIBC_HAS_CTYPE_SIGNED__*/
+ /* -1 M-^? */ 0,
+ /* 0 ^@ */ _IScntrl,
+ /* 1 ^A */ _IScntrl,
+ /* 2 ^B */ _IScntrl,
+ /* 3 ^C */ _IScntrl,
+ /* 4 ^D */ _IScntrl,
+ /* 5 ^E */ _IScntrl,
+ /* 6 ^F */ _IScntrl,
+ /* 7 ^G */ _IScntrl,
+ /* 8 ^H */ _IScntrl,
+ /* 9 ^I */ _ISspace|_ISblank|_IScntrl,
+ /* 10 ^J */ _ISspace|_IScntrl,
+ /* 11 ^K */ _ISspace|_IScntrl,
+ /* 12 ^L */ _ISspace|_IScntrl,
+ /* 13 ^M */ _ISspace|_IScntrl,
+ /* 14 ^N */ _IScntrl,
+ /* 15 ^O */ _IScntrl,
+ /* 16 ^P */ _IScntrl,
+ /* 17 ^Q */ _IScntrl,
+ /* 18 ^R */ _IScntrl,
+ /* 19 ^S */ _IScntrl,
+ /* 20 ^T */ _IScntrl,
+ /* 21 ^U */ _IScntrl,
+ /* 22 ^V */ _IScntrl,
+ /* 23 ^W */ _IScntrl,
+ /* 24 ^X */ _IScntrl,
+ /* 25 ^Y */ _IScntrl,
+ /* 26 ^Z */ _IScntrl,
+ /* 27 ^[ */ _IScntrl,
+ /* 28 ^\ */ _IScntrl,
+ /* 29 ^] */ _IScntrl,
+ /* 30 ^^ */ _IScntrl,
+ /* 31 ^_ */ _IScntrl,
+ /* 32 */ _ISspace|_ISprint|_ISblank,
+ /* 33 ! */ _ISprint|_ISgraph|_ISpunct,
+ /* 34 " */ _ISprint|_ISgraph|_ISpunct,
+ /* 35 # */ _ISprint|_ISgraph|_ISpunct,
+ /* 36 $ */ _ISprint|_ISgraph|_ISpunct,
+ /* 37 % */ _ISprint|_ISgraph|_ISpunct,
+ /* 38 & */ _ISprint|_ISgraph|_ISpunct,
+ /* 39 ' */ _ISprint|_ISgraph|_ISpunct,
+ /* 40 ( */ _ISprint|_ISgraph|_ISpunct,
+ /* 41 ) */ _ISprint|_ISgraph|_ISpunct,
+ /* 42 * */ _ISprint|_ISgraph|_ISpunct,
+ /* 43 + */ _ISprint|_ISgraph|_ISpunct,
+ /* 44 , */ _ISprint|_ISgraph|_ISpunct,
+ /* 45 - */ _ISprint|_ISgraph|_ISpunct,
+ /* 46 . */ _ISprint|_ISgraph|_ISpunct,
+ /* 47 / */ _ISprint|_ISgraph|_ISpunct,
+ /* 48 0 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 49 1 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 50 2 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 51 3 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 52 4 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 53 5 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 54 6 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 55 7 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 56 8 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 57 9 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 58 : */ _ISprint|_ISgraph|_ISpunct,
+ /* 59 ; */ _ISprint|_ISgraph|_ISpunct,
+ /* 60 < */ _ISprint|_ISgraph|_ISpunct,
+ /* 61 = */ _ISprint|_ISgraph|_ISpunct,
+ /* 62 > */ _ISprint|_ISgraph|_ISpunct,
+ /* 63 ? */ _ISprint|_ISgraph|_ISpunct,
+ /* 64 @ */ _ISprint|_ISgraph|_ISpunct,
+ /* 65 A */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 66 B */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 67 C */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 68 D */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 69 E */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 70 F */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 71 G */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 72 H */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 73 I */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 74 J */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 75 K */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 76 L */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 77 M */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 78 N */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 79 O */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 80 P */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 81 Q */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 82 R */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 83 S */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 84 T */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 85 U */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 86 V */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 87 W */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 88 X */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 89 Y */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 90 Z */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 91 [ */ _ISprint|_ISgraph|_ISpunct,
+ /* 92 \ */ _ISprint|_ISgraph|_ISpunct,
+ /* 93 ] */ _ISprint|_ISgraph|_ISpunct,
+ /* 94 ^ */ _ISprint|_ISgraph|_ISpunct,
+ /* 95 _ */ _ISprint|_ISgraph|_ISpunct,
+ /* 96 ` */ _ISprint|_ISgraph|_ISpunct,
+ /* 97 a */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 98 b */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 99 c */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 100 d */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 101 e */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 102 f */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum,
+ /* 103 g */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 104 h */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 105 i */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 106 j */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 107 k */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 108 l */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 109 m */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 110 n */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 111 o */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 112 p */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 113 q */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 114 r */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 115 s */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 116 t */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 117 u */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 118 v */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 119 w */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 120 x */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 121 y */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 122 z */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum,
+ /* 123 { */ _ISprint|_ISgraph|_ISpunct,
+ /* 124 | */ _ISprint|_ISgraph|_ISpunct,
+ /* 125 } */ _ISprint|_ISgraph|_ISpunct,
+ /* 126 ~ */ _ISprint|_ISgraph|_ISpunct,
+ /* 127 ^? */ _IScntrl,
+ /* 128 M-^@ */ 0,
+ /* 129 M-^A */ 0,
+ /* 130 M-^B */ 0,
+ /* 131 M-^C */ 0,
+ /* 132 M-^D */ 0,
+ /* 133 M-^E */ 0,
+ /* 134 M-^F */ 0,
+ /* 135 M-^G */ 0,
+ /* 136 M-^H */ 0,
+ /* 137 M-^I */ 0,
+ /* 138 M-^J */ 0,
+ /* 139 M-^K */ 0,
+ /* 140 M-^L */ 0,
+ /* 141 M-^M */ 0,
+ /* 142 M-^N */ 0,
+ /* 143 M-^O */ 0,
+ /* 144 M-^P */ 0,
+ /* 145 M-^Q */ 0,
+ /* 146 M-^R */ 0,
+ /* 147 M-^S */ 0,
+ /* 148 M-^T */ 0,
+ /* 149 M-^U */ 0,
+ /* 150 M-^V */ 0,
+ /* 151 M-^W */ 0,
+ /* 152 M-^X */ 0,
+ /* 153 M-^Y */ 0,
+ /* 154 M-^Z */ 0,
+ /* 155 M-^[ */ 0,
+ /* 156 M-^\ */ 0,
+ /* 157 M-^] */ 0,
+ /* 158 M-^^ */ 0,
+ /* 159 M-^_ */ 0,
+ /* 160 M- */ 0,
+ /* 161 M-! */ 0,
+ /* 162 M-" */ 0,
+ /* 163 M-# */ 0,
+ /* 164 M-$ */ 0,
+ /* 165 M-% */ 0,
+ /* 166 M-& */ 0,
+ /* 167 M-' */ 0,
+ /* 168 M-( */ 0,
+ /* 169 M-) */ 0,
+ /* 170 M-* */ 0,
+ /* 171 M-+ */ 0,
+ /* 172 M-, */ 0,
+ /* 173 M-- */ 0,
+ /* 174 M-. */ 0,
+ /* 175 M-/ */ 0,
+ /* 176 M-0 */ 0,
+ /* 177 M-1 */ 0,
+ /* 178 M-2 */ 0,
+ /* 179 M-3 */ 0,
+ /* 180 M-4 */ 0,
+ /* 181 M-5 */ 0,
+ /* 182 M-6 */ 0,
+ /* 183 M-7 */ 0,
+ /* 184 M-8 */ 0,
+ /* 185 M-9 */ 0,
+ /* 186 M-: */ 0,
+ /* 187 M-; */ 0,
+ /* 188 M-< */ 0,
+ /* 189 M-= */ 0,
+ /* 190 M-> */ 0,
+ /* 191 M-? */ 0,
+ /* 192 M-@ */ 0,
+ /* 193 M-A */ 0,
+ /* 194 M-B */ 0,
+ /* 195 M-C */ 0,
+ /* 196 M-D */ 0,
+ /* 197 M-E */ 0,
+ /* 198 M-F */ 0,
+ /* 199 M-G */ 0,
+ /* 200 M-H */ 0,
+ /* 201 M-I */ 0,
+ /* 202 M-J */ 0,
+ /* 203 M-K */ 0,
+ /* 204 M-L */ 0,
+ /* 205 M-M */ 0,
+ /* 206 M-N */ 0,
+ /* 207 M-O */ 0,
+ /* 208 M-P */ 0,
+ /* 209 M-Q */ 0,
+ /* 210 M-R */ 0,
+ /* 211 M-S */ 0,
+ /* 212 M-T */ 0,
+ /* 213 M-U */ 0,
+ /* 214 M-V */ 0,
+ /* 215 M-W */ 0,
+ /* 216 M-X */ 0,
+ /* 217 M-Y */ 0,
+ /* 218 M-Z */ 0,
+ /* 219 M-[ */ 0,
+ /* 220 M-\ */ 0,
+ /* 221 M-] */ 0,
+ /* 222 M-^ */ 0,
+ /* 223 M-_ */ 0,
+ /* 224 M-` */ 0,
+ /* 225 M-a */ 0,
+ /* 226 M-b */ 0,
+ /* 227 M-c */ 0,
+ /* 228 M-d */ 0,
+ /* 229 M-e */ 0,
+ /* 230 M-f */ 0,
+ /* 231 M-g */ 0,
+ /* 232 M-h */ 0,
+ /* 233 M-i */ 0,
+ /* 234 M-j */ 0,
+ /* 235 M-k */ 0,
+ /* 236 M-l */ 0,
+ /* 237 M-m */ 0,
+ /* 238 M-n */ 0,
+ /* 239 M-o */ 0,
+ /* 240 M-p */ 0,
+ /* 241 M-q */ 0,
+ /* 242 M-r */ 0,
+ /* 243 M-s */ 0,
+ /* 244 M-t */ 0,
+ /* 245 M-u */ 0,
+ /* 246 M-v */ 0,
+ /* 247 M-w */ 0,
+ /* 248 M-x */ 0,
+ /* 249 M-y */ 0,
+ /* 250 M-z */ 0,
+ /* 251 M-{ */ 0,
+ /* 252 M-| */ 0,
+ /* 253 M-} */ 0,
+ /* 254 M-~ */ 0,
+ /* 255 M-^? */ 0
+};
+
+const uint16_t *__C_ctype_b = __C_ctype_b_data + 1
+#ifdef __UCLIBC_HAS_CTYPE_SIGNED__
+ + 127
+#endif
+ ;
+
+#ifndef __UCLIBC_HAS_XLOCALE__
+
+const uint16_t *__ctype_b = __C_ctype_b_data + 1
+#ifdef __UCLIBC_HAS_CTYPE_SIGNED__
+ + 127
+#endif
+ ;
-/* This internal routine is similar to iswctype(), but it doesn't
- * work for any non-standard types, itdoesn't work for "xdigit"s,
- * and it doesn't work for chars between 0 and 0x7f (although that
- * may change). */
+#endif
-static const char ctype_range[] = {
- __CTYPE_RANGES
+#endif
+/**********************************************************************/
+#ifdef L___C_ctype_tolower
+
+const __ctype_touplow_t __C_ctype_tolower_data[] = {
+#ifdef __UCLIBC_HAS_CTYPE_SIGNED__
+ -128, -127, -126, -125,
+ -124, -123, -122, -121,
+ -120, -119, -118, -117,
+ -116, -115, -114, -113,
+ -112, -111, -110, -109,
+ -108, -107, -106, -105,
+ -104, -103, -102, -101,
+ -100, -99, -98, -97,
+ -96, -95, -94, -93,
+ -92, -91, -90, -89,
+ -88, -87, -86, -85,
+ -84, -83, -82, -81,
+ -80, -79, -78, -77,
+ -76, -75, -74, -73,
+ -72, -71, -70, -69,
+ -68, -67, -66, -65,
+ -64, -63, -62, -61,
+ -60, -59, -58, -57,
+ -56, -55, -54, -53,
+ -52, -51, -50, -49,
+ -48, -47, -46, -45,
+ -44, -43, -42, -41,
+ -40, -39, -38, -37,
+ -36, -35, -34, -33,
+ -32, -31, -30, -29,
+ -28, -27, -26, -25,
+ -24, -23, -22, -21,
+ -20, -19, -18, -17,
+ -16, -15, -14, -13,
+ -12, -11, -10, -9,
+ -8, -7, -6, -5,
+ -4, -3, -2, -1,
+#endif /* __UCLIBC_HAS_CTYPE_SIGNED__*/
+ 0, 1, 2, 3,
+ 4, 5, 6, 7,
+ 8, 9, 10, 11,
+ 12, 13, 14, 15,
+ 16, 17, 18, 19,
+ 20, 21, 22, 23,
+ 24, 25, 26, 27,
+ 28, 29, 30, 31,
+ 32, 33, 34, 35,
+ 36, 37, 38, 39,
+ 40, 41, 42, 43,
+ 44, 45, 46, 47,
+ 48, 49, 50, 51,
+ 52, 53, 54, 55,
+ 56, 57, 58, 59,
+ 60, 61, 62, 63,
+ 64, 97 /* a */, 98 /* b */, 99 /* c */,
+ 100 /* d */, 101 /* e */, 102 /* f */, 103 /* g */,
+ 104 /* h */, 105 /* i */, 106 /* j */, 107 /* k */,
+ 108 /* l */, 109 /* m */, 110 /* n */, 111 /* o */,
+ 112 /* p */, 113 /* q */, 114 /* r */, 115 /* s */,
+ 116 /* t */, 117 /* u */, 118 /* v */, 119 /* w */,
+ 120 /* x */, 121 /* y */, 122 /* z */, 91,
+ 92, 93, 94, 95,
+ 96, 97, 98, 99,
+ 100, 101, 102, 103,
+ 104, 105, 106, 107,
+ 108, 109, 110, 111,
+ 112, 113, 114, 115,
+ 116, 117, 118, 119,
+ 120, 121, 122, 123,
+ 124, 125, 126, 127,
+ 128, 129, 130, 131,
+ 132, 133, 134, 135,
+ 136, 137, 138, 139,
+ 140, 141, 142, 143,
+ 144, 145, 146, 147,
+ 148, 149, 150, 151,
+ 152, 153, 154, 155,
+ 156, 157, 158, 159,
+ 160, 161, 162, 163,
+ 164, 165, 166, 167,
+ 168, 169, 170, 171,
+ 172, 173, 174, 175,
+ 176, 177, 178, 179,
+ 180, 181, 182, 183,
+ 184, 185, 186, 187,
+ 188, 189, 190, 191,
+ 192, 193, 194, 195,
+ 196, 197, 198, 199,
+ 200, 201, 202, 203,
+ 204, 205, 206, 207,
+ 208, 209, 210, 211,
+ 212, 213, 214, 215,
+ 216, 217, 218, 219,
+ 220, 221, 222, 223,
+ 224, 225, 226, 227,
+ 228, 229, 230, 231,
+ 232, 233, 234, 235,
+ 236, 237, 238, 239,
+ 240, 241, 242, 243,
+ 244, 245, 246, 247,
+ 248, 249, 250, 251,
+ 252, 253, 254, 255
};
-int __isctype_loc(int c, int ct)
-{
- unsigned char d;
+const __ctype_touplow_t *__C_ctype_tolower = __C_ctype_tolower_data
+#ifdef __UCLIBC_HAS_CTYPE_SIGNED__
+ + 128
+#endif
+ ;
- assert(((unsigned int)ct) < _CTYPE_isxdigit);
- assert(((unsigned int)c) > 0x7f);
+#ifndef __UCLIBC_HAS_XLOCALE__
-#if (CHAR_MIN == 0) /* We don't have signed chars... */
- if ((LCT->encoding != __ctype_encoding_8_bit)
- || (((unsigned int) c) > UCHAR_MAX)
- ) {
- return 0;
- }
-#else
- /* Allow non-EOF negative char values for glibc compatiblity. */
- if ((LCT->encoding != __ctype_encoding_8_bit) || (c == EOF)
- || ( ((unsigned int)(c - CHAR_MIN)) > (UCHAR_MAX - CHAR_MIN))
- ) {
- return 0;
- }
+const __ctype_touplow_t *__ctype_tolower = __C_ctype_tolower_data
+#ifdef __UCLIBC_HAS_CTYPE_SIGNED__
+ + 128
#endif
+ ;
- /* TODO - test assumptions??? 8-bit chars -- or ensure in generator. */
+#endif
-#define Cctype_TBL_MASK ((1 << Cctype_IDX_SHIFT) - 1)
-#define Cctype_IDX_OFFSET (128 >> Cctype_IDX_SHIFT)
+#endif
+/**********************************************************************/
+#ifdef L___C_ctype_toupper
+
+const __ctype_touplow_t __C_ctype_toupper_data[] = {
+#ifdef __UCLIBC_HAS_CTYPE_SIGNED__
+ -128, -127, -126, -125,
+ -124, -123, -122, -121,
+ -120, -119, -118, -117,
+ -116, -115, -114, -113,
+ -112, -111, -110, -109,
+ -108, -107, -106, -105,
+ -104, -103, -102, -101,
+ -100, -99, -98, -97,
+ -96, -95, -94, -93,
+ -92, -91, -90, -89,
+ -88, -87, -86, -85,
+ -84, -83, -82, -81,
+ -80, -79, -78, -77,
+ -76, -75, -74, -73,
+ -72, -71, -70, -69,
+ -68, -67, -66, -65,
+ -64, -63, -62, -61,
+ -60, -59, -58, -57,
+ -56, -55, -54, -53,
+ -52, -51, -50, -49,
+ -48, -47, -46, -45,
+ -44, -43, -42, -41,
+ -40, -39, -38, -37,
+ -36, -35, -34, -33,
+ -32, -31, -30, -29,
+ -28, -27, -26, -25,
+ -24, -23, -22, -21,
+ -20, -19, -18, -17,
+ -16, -15, -14, -13,
+ -12, -11, -10, -9,
+ -8, -7, -6, -5,
+ -4, -3, -2, -1,
+#endif /* __UCLIBC_HAS_CTYPE_SIGNED__*/
+ 0, 1, 2, 3,
+ 4, 5, 6, 7,
+ 8, 9, 10, 11,
+ 12, 13, 14, 15,
+ 16, 17, 18, 19,
+ 20, 21, 22, 23,
+ 24, 25, 26, 27,
+ 28, 29, 30, 31,
+ 32, 33, 34, 35,
+ 36, 37, 38, 39,
+ 40, 41, 42, 43,
+ 44, 45, 46, 47,
+ 48, 49, 50, 51,
+ 52, 53, 54, 55,
+ 56, 57, 58, 59,
+ 60, 61, 62, 63,
+ 64, 65, 66, 67,
+ 68, 69, 70, 71,
+ 72, 73, 74, 75,
+ 76, 77, 78, 79,
+ 80, 81, 82, 83,
+ 84, 85, 86, 87,
+ 88, 89, 90, 91,
+ 92, 93, 94, 95,
+ 96, 65 /* A */, 66 /* B */, 67 /* C */,
+ 68 /* D */, 69 /* E */, 70 /* F */, 71 /* G */,
+ 72 /* H */, 73 /* I */, 74 /* J */, 75 /* K */,
+ 76 /* L */, 77 /* M */, 78 /* N */, 79 /* O */,
+ 80 /* P */, 81 /* Q */, 82 /* R */, 83 /* S */,
+ 84 /* T */, 85 /* U */, 86 /* V */, 87 /* W */,
+ 88 /* X */, 89 /* Y */, 90 /* Z */, 123,
+ 124, 125, 126, 127,
+ 128, 129, 130, 131,
+ 132, 133, 134, 135,
+ 136, 137, 138, 139,
+ 140, 141, 142, 143,
+ 144, 145, 146, 147,
+ 148, 149, 150, 151,
+ 152, 153, 154, 155,
+ 156, 157, 158, 159,
+ 160, 161, 162, 163,
+ 164, 165, 166, 167,
+ 168, 169, 170, 171,
+ 172, 173, 174, 175,
+ 176, 177, 178, 179,
+ 180, 181, 182, 183,
+ 184, 185, 186, 187,
+ 188, 189, 190, 191,
+ 192, 193, 194, 195,
+ 196, 197, 198, 199,
+ 200, 201, 202, 203,
+ 204, 205, 206, 207,
+ 208, 209, 210, 211,
+ 212, 213, 214, 215,
+ 216, 217, 218, 219,
+ 220, 221, 222, 223,
+ 224, 225, 226, 227,
+ 228, 229, 230, 231,
+ 232, 233, 234, 235,
+ 236, 237, 238, 239,
+ 240, 241, 242, 243,
+ 244, 245, 246, 247,
+ 248, 249, 250, 251,
+ 252, 253, 254, 255
+};
+
+const __ctype_touplow_t *__C_ctype_toupper = __C_ctype_toupper_data
+#ifdef __UCLIBC_HAS_CTYPE_SIGNED__
+ + 128
+#endif
+ ;
+
+#ifndef __UCLIBC_HAS_XLOCALE__
+
+const __ctype_touplow_t *__ctype_toupper = __C_ctype_toupper_data
+#ifdef __UCLIBC_HAS_CTYPE_SIGNED__
+ + 128
+#endif
+ ;
- c &= 0x7f;
-#ifdef Cctype_PACKED
- d = LCT->tbl8ctype[ ((int)(LCT->idx8ctype[(U >> Cctype_IDX_SHIFT) ])
- << (Cctype_IDX_SHIFT - 1))
- + ((U & Cctype_TBL_MASK) >> 1)];
- d = (U & 1) ? (d >> 4) : (d & 0xf);
-#else
- d = LCT->tbl8ctype[ ((int)(LCT->idx8ctype[(U >> Cctype_IDX_SHIFT) ])
- << Cctype_IDX_SHIFT)
- + (U & Cctype_TBL_MASK) ];
#endif
- return ( ((unsigned char)(d - ctype_range[2*ct])) <= ctype_range[2*ct+1] );
-}
-#endif /* __CTYPE_HAS_8_BIT_LOCALES */
#endif
/**********************************************************************/
diff --git a/libc/misc/intl/Makefile b/libc/misc/intl/Makefile
new file mode 100644
index 000000000..75fbb321f
--- /dev/null
+++ b/libc/misc/intl/Makefile
@@ -0,0 +1,50 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000 by Lineo, inc.
+# Copyright (C) 2000,2001 Erik Andersen <andersen@uclibc.org>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Library General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Library General Public License
+# along with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Derived in part from the Linux-8086 C library, the GNU C Library, and several
+# other sundry sources. Files within this library are copyright by their
+# respective copyright holders.
+
+TOPDIR=../../../
+include $(TOPDIR)Rules.mak
+
+MSRC= intl.c
+MOBJ= gettext.o ngettext.o dgettext.o dcgettext.o dngettext.o dcngettext.o \
+ textdomain.o bindtextdomain.o bind_textdomain_codeset.o
+
+OBJS=$(MOBJ)
+
+all: $(OBJS) $(LIBC)
+
+$(LIBC): ar-target
+
+ar-target: $(OBJS)
+ $(AR) $(ARFLAGS) $(LIBC) $(OBJS)
+
+$(MOBJ): $(MSRC)
+ $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
+ $(STRIPTOOL) -x -R .note -R .comment $*.o
+
+$(COBJS): %.o : %.c
+ $(CC) $(CFLAGS) -c $< -o $@
+ $(STRIPTOOL) -x -R .note -R .comment $*.o
+
+clean:
+ rm -f *.[oa] *~ core
+
diff --git a/libc/misc/intl/intl.c b/libc/misc/intl/intl.c
new file mode 100644
index 000000000..183ffcc92
--- /dev/null
+++ b/libc/misc/intl/intl.c
@@ -0,0 +1,149 @@
+/* Copyright (C) 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Supply some weaks for gettext and friends. Used by strerror*().
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#undef __OPTIMIZE__
+#include <libintl.h>
+
+/**********************************************************************/
+#ifdef L_gettext
+
+char *weak_function gettext(const char *msgid)
+{
+ return (char *) msgid;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_dgettext
+
+char *__uClibc_dgettext(const char *domainname,
+ const char *msgid)
+{
+ return (char *) msgid;
+}
+
+weak_alias (__uClibc_dgettext, __dgettext)
+weak_alias (__uClibc_dgettext, dgettext)
+
+#endif
+/**********************************************************************/
+#ifdef L_dcgettext
+
+char * __uClibc_dcgettext(const char *domainname,
+ const char *msgid, int category)
+{
+ return (char *) msgid;
+}
+
+weak_alias (__uClibc_dcgettext, __dcgettext)
+weak_alias (__uClibc_dcgettext, dcgettext)
+
+#endif
+/**********************************************************************/
+#ifdef L_ngettext
+
+char *weak_function ngettext(const char *msgid1, const char *msgid2,
+ unsigned long int n)
+{
+ return (char *) ((n == 1) ? msgid1 : msgid2);
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_dngettext
+
+char *weak_function dngettext(const char *domainname, const char *msgid1,
+ const char *msgid2, unsigned long int n)
+{
+ return (char *) ((n == 1) ? msgid1 : msgid2);
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_dcngettext
+
+char *weak_function dcngettext(const char *domainname, const char *msgid1,
+ const char *msgid2, unsigned long int n,
+ int category)
+{
+ return (char *) ((n == 1) ? msgid1 : msgid2);
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_textdomain
+
+char *weak_function textdomain(const char *domainname)
+{
+ static const char default_str[] = "messages";
+
+ if (domainname && *domainname && strcmp(domainname, default_str)) {
+ __set_errno(EINVAL);
+ return NULL;
+ }
+ return (char *) default_str;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_bindtextdomain
+
+char *weak_function bindtextdomain(const char *domainname, const char *dirname)
+{
+ static const char dir[] = "/";
+
+ if (!domainname || !*domainname
+ || (dirname
+#if 1
+ && ((dirname[0] != '/') || dirname[1])
+#else
+ && strcmp(dirname, dir)
+#endif
+ )
+ ) {
+ __set_errno(EINVAL);
+ return NULL;
+ }
+
+ return (char *) dir;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_bind_textdomain_codeset
+
+/* Specify the character encoding in which the messages from the
+ DOMAINNAME message catalog will be returned. */
+char *weak_function bind_textdomain_codeset(const char *domainname,
+ const char *codeset)
+{
+ if (!domainname || !*domainname || codeset) {
+ __set_errno(EINVAL);
+ }
+ return NULL;
+}
+
+#endif
+/**********************************************************************/
diff --git a/libc/misc/locale/Makefile b/libc/misc/locale/Makefile
index 29c8cd5a0..8ad041e69 100644
--- a/libc/misc/locale/Makefile
+++ b/libc/misc/locale/Makefile
@@ -26,14 +26,29 @@ include $(TOPDIR)Rules.mak
MSRC= locale.c
MOBJ= setlocale.o localeconv.o _locale_init.o nl_langinfo.o
+MOBJx=
-OBJS= $(MOBJ)
+ifeq ($(UCLIBC_HAS_LOCALE),y)
+ MOBJ += newlocale.o __locale_mbrtowc_l.o
+endif
+
+ifeq ($(UCLIBC_HAS_XLOCALE),y)
+ MOBJx += nl_langinfo_l.o duplocale.o freelocale.o uselocale.o __curlocale.o
+endif
+
+OBJS= $(MOBJ) $(MOBJx)
ifeq ($(UCLIBC_HAS_LOCALE),y)
- OBJS += locale_data.o
+ OBJS += $(COBJS) locale_data.o
endif
-all: data $(OBJS) $(LIBC)
+DATA=
+ifeq ($(UCLIBC_HAS_LOCALE),y)
+ DATA += locale_data.o
+endif
+
+all: $(DATA) $(OBJS) $(LIBC)
+
$(LIBC): ar-target
@@ -44,12 +59,14 @@ $(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
+
$(OBJS): Makefile
-data:
-ifeq ($(UCLIBC_HAS_LOCALE),y)
- make -C $(TOPDIR)/extra/locale
-endif
+# locale_data.o:
+# make -C $(TOPDIR)/extra/locale
clean:
rm -f *.[oa] *~ core
diff --git a/libc/misc/locale/locale.c b/libc/misc/locale/locale.c
index 9c162a980..071a8df71 100644
--- a/libc/misc/locale/locale.c
+++ b/libc/misc/locale/locale.c
@@ -36,28 +36,94 @@
*/
#define _GNU_SOURCE
-#include <locale.h>
+
+#define __CTYPE_HAS_8_BIT_LOCALES 1
+
+
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <limits.h>
#include <stdint.h>
#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+
+#undef __LOCALE_C_ONLY
+#ifndef __UCLIBC_HAS_LOCALE__
+#define __LOCALE_C_ONLY
+#endif /* __UCLIBC_HAS_LOCALE__ */
+
+
+#ifdef __LOCALE_C_ONLY
+
+#include <locale.h>
+
+#else /* __LOCALE_C_ONLY */
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#ifdef L_setlocale
+#warning TODO: Fix the __CTYPE_HAS_8_BIT_LOCALES define at the top of the file.
+#warning TODO: Fix __WCHAR_ENABLED.
+#endif
+#endif
-#ifndef __LOCALE_C_ONLY
+/* Need to include this before locale.h and xlocale.h! */
+#include <bits/uClibc_locale.h>
-#define CUR_LOCALE_SPEC (__global_locale.cur_locale)
#undef CODESET_LIST
#define CODESET_LIST (__locale_mmap->codeset_list)
+#ifdef __UCLIBC_HAS_XLOCALE__
+#include <xlocale.h>
+#include <locale.h>
+#else /* __UCLIBC_HAS_XLOCALE__ */
+/* We need this internally... */
+#define __UCLIBC_HAS_XLOCALE__ 1
+#include <xlocale.h>
+#include <locale.h>
+#undef __UCLIBC_HAS_XLOCALE__
+#endif /* __UCLIBC_HAS_XLOCALE__ */
+
+#include <wchar.h>
+
+#define LOCALE_NAMES (__locale_mmap->locale_names5)
+#define LOCALES (__locale_mmap->locales)
+#define LOCALE_AT_MODIFIERS (__locale_mmap->locale_at_modifiers)
+#define CATEGORY_NAMES (__locale_mmap->lc_names)
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: redo the MAX_LOCALE_STR stuff...
+#endif
+#define MAX_LOCALE_STR 256 /* TODO: Only sufficient for current case. */
+#define MAX_LOCALE_CATEGORY_STR 32 /* TODO: Only sufficient for current case. */
+/* Note: Best if MAX_LOCALE_CATEGORY_STR is a power of 2. */
+
+extern int _locale_set_l(const unsigned char *p, __locale_t base);
+extern void _locale_init_l(__locale_t base);
+
#endif /* __LOCALE_C_ONLY */
+#undef LOCALE_STRING_SIZE
+#define LOCALE_SELECTOR_SIZE (2 * __LC_ALL + 2)
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#ifdef L_setlocale
+#warning TODO: Create a C locale selector string.
+#endif
+#endif
+#define C_LOCALE_SELECTOR "\x23\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80"
+
+
+#include <langinfo.h>
+#include <nl_types.h>
+
/**********************************************************************/
#ifdef L_setlocale
#ifdef __LOCALE_C_ONLY
-link_warning(setlocale,"the 'setlocale' function supports only C|POSIX locales")
+link_warning(setlocale,"REMINDER: The 'setlocale' function supports only C|POSIX locales.")
static const char C_string[] = "C";
@@ -74,273 +140,125 @@ char *setlocale(int category, register const char *locale)
#else /* ---------------------------------------------- __LOCALE_C_ONLY */
-#if !defined(NUM_LOCALES) || (NUM_LOCALES <= 1)
-#error locales enabled, but not data other than for C locale!
+#ifdef __UCLIBC_HAS_THREADS__
+link_warning(setlocale,"REMINDER: The 'setlocale' function is _not_ threadsafe except for simple queries.")
#endif
-#define LOCALE_NAMES (__locale_mmap->locale_names5)
-#define LOCALES (__locale_mmap->locales)
-#define LOCALE_AT_MODIFIERS (__locale_mmap->locale_at_modifiers)
-#define CATEGORY_NAMES (__locale_mmap->lc_names)
+#if !defined(__LOCALE_DATA_NUM_LOCALES) || (__LOCALE_DATA_NUM_LOCALES <= 1)
+#error locales enabled, but not data other than for C locale!
+#endif
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Move posix and utf8 strings.
+#endif
static const char posix[] = "POSIX";
static const char utf8[] = "UTF-8";
#ifdef __UCLIBC_MJN3_ONLY__
-#warning REMINDER: redo the MAX_LOCALE_STR stuff...
+#warning TODO: Fix dimensions of hr_locale.
#endif
-#define MAX_LOCALE_STR 256 /* TODO: Only sufficient for current case. */
-
-static char hr_locale[MAX_LOCALE_STR];
+/* Individual category strings start at hr_locale + category * MAX_LOCALE_CATEGORY.
+ * This holds for LC_ALL as well.
+ */
+static char hr_locale[(MAX_LOCALE_CATEGORY_STR * LC_ALL) + MAX_LOCALE_STR];
-static __inline char *human_readable_locale(int category, const unsigned char *s)
+static void update_hr_locale(const unsigned char *spec)
{
const unsigned char *loc;
+ const unsigned char *s;
char *n;
- int i;
-
- ++s;
-
- if (category == LC_ALL) {
- for (i = 0 ; i < LC_ALL-1 ; i += 2) {
- if ((s[i] != s[i+2]) || (s[i+1] != s[i+3])) {
- goto SKIP;
- }
- }
- /* All categories the same, so simplify string by using a single
- * category. */
- category = LC_CTYPE;
- }
-
- SKIP:
- i = (category == LC_ALL) ? 0 : category;
- s += 2*i;
- n = hr_locale;
+ int i, category, done;
+ done = category = 0;
do {
- if ((*s != 0xff) || (s[1] != 0xff)) {
- loc = LOCALES + WIDTH_LOCALES * ((((int)(*s & 0x7f)) << 7) + (s[1] & 0x7f));
- if (category == LC_ALL) {
- n = stpcpy(n, CATEGORY_NAMES + (int) CATEGORY_NAMES[i]);
- *n++ = '=';
- }
- if (*loc == 0) {
- *n++ = 'C';
- *n = 0;
- } else {
- char at = 0;
- memcpy(n, LOCALE_NAMES + 5*((*loc)-1), 5);
- if (n[2] != '_') {
- at = n[2];
- n[2] = '_';
- }
- n += 5;
- *n++ = '.';
- if (loc[2] == 2) {
- n = stpcpy(n, utf8);
- } else if (loc[2] >= 3) {
- n = stpcpy(n, CODESET_LIST + (int)(CODESET_LIST[loc[2] - 3]));
- }
- if (at) {
- const char *q;
- *n++ = '@';
- q = LOCALE_AT_MODIFIERS;
- do {
- if (q[1] == at) {
- n = stpcpy(n, q+2);
- break;
- }
- q += 2 + *q;
- } while (*q);
+ s = spec + 1;
+ n = hr_locale + category * MAX_LOCALE_CATEGORY_STR;
+
+ if (category == LC_ALL) {
+ done = 1;
+ for (i = 0 ; i < LC_ALL-1 ; i += 2) {
+ if ((s[i] != s[i+2]) || (s[i+1] != s[i+3])) {
+ goto SKIP;
}
}
- *n++ = ';';
+ /* All categories the same, so simplify string by using a single
+ * category. */
+ category = LC_CTYPE;
}
- s += 2;
- } while (++i < category);
- *--n = 0; /* Remove trailing ';' and nul-terminate. */
- assert(n-hr_locale < MAX_LOCALE_STR);
- return hr_locale;
-}
-
-static int find_locale(int category, const char *p, unsigned char *new_locale)
-{
- int i;
- const unsigned char *s;
- uint16_t n;
- unsigned char lang_cult, codeset;
-
-#if defined(LOCALE_AT_MODIFIERS_LENGTH) && 1
- /* Support standard locale handling for @-modifiers. */
+ SKIP:
+ i = (category == LC_ALL) ? 0 : category;
+ s += 2*i;
-#ifdef __UCLIBC_MJN3_ONLY__
-#warning REMINDER: fix buf size in find_locale
-#endif
- char buf[18]; /* TODO: 7+{max codeset name length} */
- const char *q;
-
- if ((q = strchr(p,'@')) != NULL) {
- if ((((size_t)((q-p)-5)) > (sizeof(buf) - 5)) || (p[2] != '_')) {
- return 0;
- }
- /* locale name at least 5 chars long and 3rd char is '_' */
- s = LOCALE_AT_MODIFIERS;
do {
- if (!strcmp(s+2, q+1)) {
- break;
- }
- s += 2 + *s; /* TODO - fix this throughout */
- } while (*s);
- if (!*s) {
- return 0;
- }
- assert(q - p < sizeof(buf));
- memcpy(buf, p, q-p);
- buf[q-p] = 0;
- buf[2] = s[1];
- p = buf;
- }
-#endif
-
- lang_cult = codeset = 0; /* Assume C and default codeset. */
- if (((*p == 'C') && !p[1]) || !strcmp(p, posix)) {
- goto FIND_LOCALE;
- }
-
- if ((strlen(p) > 5) && (p[5] == '.')) { /* Codeset in locale name? */
- /* TODO: maybe CODESET_LIST + *s ??? */
- /* 7bit is 1, UTF-8 is 2, 8-bit is >= 3 */
- codeset = 2;
- if (strcmp(utf8,p+6) != 0) {/* TODO - fix! */
- s = CODESET_LIST;
- do {
- ++codeset; /* Increment codeset first. */
- if (!strcmp(CODESET_LIST+*s, p+6)) {
- goto FIND_LANG_CULT;
+ if ((*s != 0xff) || (s[1] != 0xff)) {
+ loc = LOCALES
+ + __LOCALE_DATA_WIDTH_LOCALES * ((((int)(*s & 0x7f)) << 7)
+ + (s[1] & 0x7f));
+ if (category == LC_ALL) {
+ n = stpcpy(n, CATEGORY_NAMES + (int) CATEGORY_NAMES[i]);
+ *n++ = '=';
}
- } while (*++s);
- return 0; /* No matching codeset! */
- }
- }
-
- FIND_LANG_CULT: /* Find language_culture number. */
- s = LOCALE_NAMES;
- do { /* TODO -- do a binary search? */
- /* TODO -- fix gen_mmap!*/
- ++lang_cult; /* Increment first since C/POSIX is 0. */
- if (!strncmp(s,p,5)) { /* Found a matching locale name; */
- goto FIND_LOCALE;
- }
- s += 5;
- } while (lang_cult < NUM_LOCALE_NAMES);
- return 0; /* No matching language_culture! */
-
- FIND_LOCALE: /* Find locale row matching name and codeset */
- s = LOCALES;
- n = 0;
- do { /* TODO -- do a binary search? */
- if ((lang_cult == *s) && ((codeset == s[1]) || (codeset == s[2]))) {
- i = ((category == LC_ALL) ? 0 : category);
- s = new_locale + 2*i;
- do {
- /* Encode current locale row number. */
- *((unsigned char *) ++s) = (n >> 7) | 0x80;
- *((unsigned char *) ++s) = (n & 0x7f) | 0x80;
- } while (++i < category);
-
- return i; /* Return non-zero */
- }
- s += WIDTH_LOCALES;
- ++n;
- } while (n <= NUM_LOCALES); /* We started at 1!!! */
-
- return 0; /* Unsupported locale. */
-}
-
-static unsigned char *composite_locale(int category, const char *locale, unsigned char *new_locale)
-{
- char buf[MAX_LOCALE_STR];
- char *t;
- char *e;
- int c;
-
- if (!strchr(locale,'=')) {
- if (!find_locale(category, locale, new_locale)) {
- return NULL;
- }
- return new_locale;
- }
-
- if (strlen(locale) >= sizeof(buf)) {
- return NULL;
- }
- stpcpy(buf, locale);
-
- t = strtok_r(buf, "=", &e); /* This can't fail because of strchr test above. */
- do {
- for (c = 0 ; c < LC_ALL ; c++) { /* Find the category... */
- if (!strcmp(CATEGORY_NAMES + (int) CATEGORY_NAMES[c], t)) {
- break;
- }
- }
- t = strtok_r(NULL, ";", &e);
- if ((category == LC_ALL) || (c == category)) {
- if (!t || !find_locale(c, t, new_locale)) {
- return NULL;
+ if (*loc == 0) {
+ *n++ = 'C';
+ *n = 0;
+ } else {
+ char at = 0;
+ memcpy(n, LOCALE_NAMES + 5*((*loc)-1), 5);
+ if (n[2] != '_') {
+ at = n[2];
+ n[2] = '_';
+ }
+ n += 5;
+ *n++ = '.';
+ if (loc[2] == 2) {
+ n = stpcpy(n, utf8);
+ } else if (loc[2] >= 3) {
+ n = stpcpy(n, CODESET_LIST + (int)(CODESET_LIST[loc[2] - 3]));
+ }
+ if (at) {
+ const char *q;
+ *n++ = '@';
+ q = LOCALE_AT_MODIFIERS;
+ do {
+ if (q[1] == at) {
+ n = stpcpy(n, q+2);
+ break;
+ }
+ q += 2 + *q;
+ } while (*q);
+ }
+ }
+ *n++ = ';';
}
- }
- } while ((t = strtok_r(NULL, "=", &e)) != NULL);
+ s += 2;
+ } while (++i < category);
+ *--n = 0; /* Remove trailing ';' and nul-terminate. */
- return new_locale;
+ ++category;
+ } while (!done);
}
char *setlocale(int category, const char *locale)
{
- const unsigned char *p;
- int i;
- unsigned char new_locale[LOCALE_STRING_SIZE];
-
if (((unsigned int)(category)) > LC_ALL) {
- /* TODO - set errno? SUSv3 doesn't say too. */
+#if 0
+ __set_errno(EINVAL); /* glibc sets errno -- SUSv3 doesn't say. */
+#endif
return NULL; /* Illegal/unsupported category. */
}
- if (locale != NULL) { /* Not just a query... */
- stpcpy(new_locale, CUR_LOCALE_SPEC); /* Start with current. */
-
- if (!*locale) { /* locale == "", so check environment. */
- i = ((category == LC_ALL) ? 0 : category);
- do {
- /* Note: SUSv3 doesn't define a fallback mechanism here. So,
- * if LC_ALL is invalid, we do _not_ continue trying the other
- * environment vars. */
- if (!(p = getenv("LC_ALL"))) {
- if (!(p = getenv(CATEGORY_NAMES + CATEGORY_NAMES[i]))) {
- if (!(p = getenv("LANG"))) {
- p = posix;
- }
- }
- }
-
- /* The user set something... is it valid? */
- /* Note: Since we don't support user-supplied locales and
- * alternate paths, we don't need to worry about special
- * handling for suid/sgid apps. */
- if (!find_locale(i, p, new_locale)) {
- return NULL;
- }
- } while (++i < category);
- } else if (!composite_locale(category, locale, new_locale)) {
+ if (locale != NULL) { /* Not just a query... */
+ if (!__newlocale((category == LC_ALL) ? LC_ALL_MASK : (1 << category),
+ locale, __global_locale)
+ ) { /* Failed! */
return NULL;
}
-
- /* TODO: Ok, everything checks out, so install the new locale. */
- _locale_set(new_locale);
+ update_hr_locale(__global_locale->cur_locale);
}
/* Either a query or a successful set, so return current locale string. */
- return human_readable_locale(category, CUR_LOCALE_SPEC);
+ return hr_locale + (category * MAX_LOCALE_CATEGORY_STR);
}
#endif /* __LOCALE_C_ONLY */
@@ -355,7 +273,7 @@ char *setlocale(int category, const char *locale)
#ifdef __LOCALE_C_ONLY
-link_warning(localeconv,"the 'localeconv' function is hardwired for C/POSIX locale only")
+link_warning(localeconv,"REMINDER: The 'localeconv' function is hardwired for C/POSIX locale only.")
static struct lconv the_lconv;
@@ -387,7 +305,7 @@ static struct lconv the_lconv;
struct lconv *localeconv(void)
{
register char *p = (char *) &the_lconv;
- register char **q = (char **) &__global_locale.decimal_point;
+ register char **q = (char **) &(__UCLIBC_CURLOCALE_DATA).decimal_point;
do {
*((char **)p) = *q;
@@ -408,16 +326,22 @@ struct lconv *localeconv(void)
#endif
/**********************************************************************/
-#ifdef L__locale_init
+#if defined(L__locale_init) && !defined(__LOCALE_C_ONLY)
-#ifndef __LOCALE_C_ONLY
+static __uclibc_locale_t __global_locale_data;
-#define C_LOCALE_SELECTOR "\x23\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80"
-#define LOCALE_INIT_FAILED "locale init failed!\n"
+__locale_t __global_locale = &__global_locale_data;
-#define CUR_LOCALE_SPEC (__global_locale.cur_locale)
+#ifdef __UCLIBC_HAS_XLOCALE__
+__locale_t __curlocale_var = &__global_locale_data;
+#endif
-__locale_t __global_locale;
+/*----------------------------------------------------------------------*/
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Move utf8 and ascii strings.
+#endif
+static const char utf8[] = "UTF-8";
+static const char ascii[] = "ASCII";
typedef struct {
uint16_t num_base;
@@ -461,9 +385,8 @@ typedef struct {
uint16_t multistart_offset;
} coldata_der_t;
-static int init_cur_collate(int der_num)
+static int init_cur_collate(int der_num, __collate_t *cur_collate)
{
- __collate_t *cur_collate = &__global_locale.collate;
const uint16_t *__locale_collate_tbl = __locale_mmap->collate_data;
coldata_header_t *cdh;
coldata_base_t *cdb;
@@ -485,9 +408,16 @@ static int init_cur_collate(int der_num)
cdh = (coldata_header_t *) __locale_collate_tbl;
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning CONSIDER: Should we assert here?
+#endif
+#if 0
if (der_num >= cdh->num_der) {
return 0;
}
+#else
+ assert((der_num < cdh->num_der));
+#endif
cdd = (coldata_der_t *)(__locale_collate_tbl
+ (sizeof(coldata_header_t)
@@ -539,14 +469,17 @@ static int init_cur_collate(int der_num)
cur_collate->MAX_WEIGHTS = cdh->MAX_WEIGHTS;
#ifdef __UCLIBC_MJN3_ONLY__
-#warning if calloc fails, this is WRONG. there is also a memory leak here at the moment
-#warning fix the +1 by increasing max_col_index?
+#warning CONSIDER: Fix the +1 by increasing max_col_index?
+#warning CONSIDER: Since this collate info is dependent only on LC_COLLATE ll_cc and not on codeset, we could just globally allocate this for each in a table
#endif
- cur_collate->index2weight = calloc(2*cur_collate->max_col_index+2, sizeof(uint16_t));
+
+ cur_collate->index2weight = calloc(2*cur_collate->max_col_index+2,
+ sizeof(uint16_t));
if (!cur_collate->index2weight) {
return 0;
}
- cur_collate->index2ruleidx = cur_collate->index2weight + cur_collate->max_col_index + 1;
+ cur_collate->index2ruleidx = cur_collate->index2weight
+ + cur_collate->max_col_index + 1;
memcpy(cur_collate->index2weight, cur_collate->index2weight_tbl,
cur_collate->num_col_base * sizeof(uint16_t));
@@ -602,61 +535,10 @@ static int init_cur_collate(int der_num)
return 1;
}
-void _locale_init(void)
-{
- /* TODO: mmap the locale file */
-
- /* TODO - ??? */
- memset(CUR_LOCALE_SPEC, 0, LOCALE_STRING_SIZE);
- CUR_LOCALE_SPEC[0] = '#';
-
- memcpy(__global_locale.category_item_count,
- __locale_mmap->lc_common_item_offsets_LEN,
- LC_ALL);
-
- ++__global_locale.category_item_count[0]; /* Increment for codeset entry. */
- __global_locale.category_offsets[0] = offsetof(__locale_t, outdigit0_mb);
- __global_locale.category_offsets[1] = offsetof(__locale_t, decimal_point);
- __global_locale.category_offsets[2] = offsetof(__locale_t, int_curr_symbol);
- __global_locale.category_offsets[3] = offsetof(__locale_t, abday_1);
-/* __global_locale.category_offsets[4] = offsetof(__locale_t, collate???); */
- __global_locale.category_offsets[5] = offsetof(__locale_t, yesexpr);
-
-#ifdef __CTYPE_HAS_8_BIT_LOCALES
- __global_locale.tbl8ctype
- = (const unsigned char *) &__locale_mmap->tbl8ctype;
- __global_locale.tbl8uplow
- = (const unsigned char *) &__locale_mmap->tbl8uplow;
-#ifdef __WCHAR_ENABLED
- __global_locale.tbl8c2wc
- = (const uint16_t *) &__locale_mmap->tbl8c2wc;
- __global_locale.tbl8wc2c
- = (const unsigned char *) &__locale_mmap->tbl8wc2c;
- /* translit */
-#endif /* __WCHAR_ENABLED */
-#endif /* __CTYPE_HAS_8_BIT_LOCALES */
-#ifdef __WCHAR_ENABLED
- __global_locale.tblwctype
- = (const unsigned char *) &__locale_mmap->tblwctype;
- __global_locale.tblwuplow
- = (const unsigned char *) &__locale_mmap->tblwuplow;
- __global_locale.tblwuplow_diff
- = (const uint16_t *) &__locale_mmap->tblwuplow_diff;
-/* __global_locale.tblwcomb */
-/* = (const unsigned char *) &__locale_mmap->tblwcomb; */
- /* width?? */
-#endif /* __WCHAR_ENABLED */
-
- _locale_set(C_LOCALE_SELECTOR);
-}
-
-static const char ascii[] = "ASCII";
-static const char utf8[] = "UTF-8";
-
-void _locale_set(const unsigned char *p)
+int _locale_set_l(const unsigned char *p, __locale_t base)
{
const char **x;
- unsigned char *s = CUR_LOCALE_SPEC + 1;
+ unsigned char *s = base->cur_locale + 1;
const size_t *stp;
const unsigned char *r;
const uint16_t *io;
@@ -667,12 +549,30 @@ void _locale_set(const unsigned char *p)
int len;
int c;
int i = 0;
+ __collate_t newcol;
++p;
+
+ newcol.index2weight = NULL;
+ if ((p[2*LC_COLLATE] != s[2*LC_COLLATE])
+ || (p[2*LC_COLLATE + 1] != s[2*LC_COLLATE + 1])
+ ) {
+ row = (((int)(*p & 0x7f)) << 7) + (p[1] & 0x7f);
+ assert(row < __LOCALE_DATA_NUM_LOCALES);
+ if (!init_cur_collate(__locale_mmap->locales[ __LOCALE_DATA_WIDTH_LOCALES
+ * row + 3 + i ],
+ &newcol)
+ ) {
+ return 0; /* calloc failed. */
+ }
+ free(base->collate.index2weight);
+ memcpy(&base->collate, &newcol, sizeof(__collate_t));
+ }
+
do {
if ((*p != *s) || (p[1] != s[1])) {
row = (((int)(*p & 0x7f)) << 7) + (p[1] & 0x7f);
- assert(row < NUM_LOCALES);
+ assert(row < __LOCALE_DATA_NUM_LOCALES);
*s = *p;
s[1] = p[1];
@@ -680,10 +580,13 @@ void _locale_set(const unsigned char *p)
if ((i != LC_COLLATE)
&& ((len = __locale_mmap->lc_common_item_offsets_LEN[i]) != 0)
) {
- crow = __locale_mmap->locales[ WIDTH_LOCALES * row + 3 + i ]
+ crow = __locale_mmap->locales[ __LOCALE_DATA_WIDTH_LOCALES * row
+ + 3 + i ]
* len;
- x = (const char **)(((char *) &__global_locale)
- + __global_locale.category_offsets[i]);
+
+ x = (const char **)(((char *) base)
+ + base->category_offsets[i]);
+
stp = __locale_mmap->lc_common_tbl_offsets + 4*i;
r = (const unsigned char *)( ((char *)__locale_mmap) + *stp );
io = (const uint16_t *)( ((char *)__locale_mmap) + *++stp );
@@ -694,67 +597,176 @@ void _locale_set(const unsigned char *p)
}
}
if (i == LC_CTYPE) {
- c = __locale_mmap->locales[ WIDTH_LOCALES * row + 2 ]; /* codeset */
+ c = __locale_mmap->locales[ __LOCALE_DATA_WIDTH_LOCALES * row
+ + 2 ]; /* codeset */
if (c <= 2) {
if (c == 2) {
- __global_locale.codeset = utf8;
- __global_locale.encoding = __ctype_encoding_utf8;
+ base->codeset = utf8;
+ base->encoding = __ctype_encoding_utf8;
/* TODO - fix for bcc */
- __global_locale.mb_cur_max = 6;
+ base->mb_cur_max = 6;
} else {
assert(c==1);
- __global_locale.codeset = ascii;
- __global_locale.encoding = __ctype_encoding_7_bit;
- __global_locale.mb_cur_max = 1;
+ base->codeset = ascii;
+ base->encoding = __ctype_encoding_7_bit;
+ base->mb_cur_max = 1;
}
} else {
- const codeset_8_bit_t *c8b;
+ const __codeset_8_bit_t *c8b;
r = CODESET_LIST;
- __global_locale.codeset = r + r[c -= 3];
- __global_locale.encoding = __ctype_encoding_8_bit;
+ base->codeset = r + r[c -= 3];
+ base->encoding = __ctype_encoding_8_bit;
#ifdef __UCLIBC_MJN3_ONLY__
-#warning REMINDER: update 8 bit mb_cur_max when trasnlit implemented!
+#warning REMINDER: update 8 bit mb_cur_max when translit implemented!
#endif
/* TODO - update when translit implemented! */
- __global_locale.mb_cur_max = 1;
+ base->mb_cur_max = 1;
c8b = __locale_mmap->codeset_8_bit + c;
#ifdef __CTYPE_HAS_8_BIT_LOCALES
- __global_locale.idx8ctype = c8b->idx8ctype;
- __global_locale.idx8uplow = c8b->idx8uplow;
-#ifdef __WCHAR_ENABLED
- __global_locale.idx8c2wc = c8b->idx8c2wc;
- __global_locale.idx8wc2c = c8b->idx8wc2c;
+ base->idx8ctype = c8b->idx8ctype;
+ base->idx8uplow = c8b->idx8uplow;
+#ifdef __UCLIBC_HAS_WCHAR__
+ base->idx8c2wc = c8b->idx8c2wc;
+ base->idx8wc2c = c8b->idx8wc2c;
/* translit */
-#endif /* __WCHAR_ENABLED */
+#endif /* __UCLIBC_HAS_WCHAR__ */
#endif /* __CTYPE_HAS_8_BIT_LOCALES */
}
#ifdef __UCLIBC_MJN3_ONLY__
-#warning might want to just put this in the locale_mmap object
+#warning TODO: Put the outdigit string length in the locale_mmap object.
#endif
- d = __global_locale.outdigit_length;
- x = &__global_locale.outdigit0_mb;
+ d = base->outdigit_length;
+ x = &base->outdigit0_mb;
for (c = 0 ; c < 10 ; c++) {
((unsigned char *)d)[c] = strlen(x[c]);
assert(d[c] > 0);
}
- } else if (i == LC_COLLATE) {
- init_cur_collate(__locale_mmap->locales[ WIDTH_LOCALES * row + 3 + i ]);
+ } else if (i == LC_NUMERIC) {
+ assert(LC_NUMERIC > LC_CTYPE); /* Need ctype initialized. */
+
+ base->decimal_point_len
+ = __locale_mbrtowc_l(&base->decimal_point_wc,
+ base->decimal_point, base);
+ assert(base->decimal_point_len > 0);
+ assert(base->decimal_point[base->decimal_point_len] == 0);
+
+ if (*base->grouping) {
+ base->thousands_sep_len
+ = __locale_mbrtowc_l(&base->thousands_sep_wc,
+ base->thousands_sep, base);
+ assert(base->thousands_sep_len > 0);
+ assert(base->thousands_sep[base->thousands_sep_len] == 0);
+ }
+
+/* } else if (i == LC_COLLATE) { */
+/* init_cur_collate(__locale_mmap->locales[ __LOCALE_DATA_WIDTH_LOCALES */
+/* * row + 3 + i ], */
+/* &base->collate); */
}
}
++i;
p += 2;
s += 2;
} while (i < LC_ALL);
+
+ return 1;
}
-#endif /* __LOCALE_C_ONLY */
+static const uint16_t __code2flag[16] = {
+ 0, /* unclassified = 0 */
+ _ISprint|_ISgraph|_ISalnum|_ISalpha, /* alpha_nonupper_nonlower */
+ _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, /* alpha_lower */
+ _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower|_ISupper, /* alpha_upper_lower */
+ _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, /* alpha_upper */
+ _ISprint|_ISgraph|_ISalnum|_ISdigit, /* digit */
+ _ISprint|_ISgraph|_ISpunct, /* punct */
+ _ISprint|_ISgraph, /* graph */
+ _ISprint|_ISspace, /* print_space_nonblank */
+ _ISprint|_ISspace|_ISblank, /* print_space_blank */
+ _ISspace, /* space_nonblank_noncntrl */
+ _ISspace|_ISblank, /* space_blank_noncntrl */
+ _IScntrl|_ISspace, /* cntrl_space_nonblank */
+ _IScntrl|_ISspace|_ISblank, /* cntrl_space_blank */
+ _IScntrl /* cntrl_nonspace */
+};
+
+void _locale_init_l(__locale_t base)
+{
+ memset(base->cur_locale, 0, LOCALE_SELECTOR_SIZE);
+ base->cur_locale[0] = '#';
+
+ memcpy(base->category_item_count,
+ __locale_mmap->lc_common_item_offsets_LEN,
+ LC_ALL);
+
+ ++base->category_item_count[0]; /* Increment for codeset entry. */
+ base->category_offsets[0] = offsetof(__uclibc_locale_t, outdigit0_mb);
+ base->category_offsets[1] = offsetof(__uclibc_locale_t, decimal_point);
+ base->category_offsets[2] = offsetof(__uclibc_locale_t, int_curr_symbol);
+ base->category_offsets[3] = offsetof(__uclibc_locale_t, abday_1);
+/* base->category_offsets[4] = offsetof(__uclibc_locale_t, collate???); */
+ base->category_offsets[5] = offsetof(__uclibc_locale_t, yesexpr);
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+ base->tbl8ctype
+ = (const unsigned char *) &__locale_mmap->tbl8ctype;
+ base->tbl8uplow
+ = (const unsigned char *) &__locale_mmap->tbl8uplow;
+#ifdef __UCLIBC_HAS_WCHAR__
+ base->tbl8c2wc
+ = (const uint16_t *) &__locale_mmap->tbl8c2wc;
+ base->tbl8wc2c
+ = (const unsigned char *) &__locale_mmap->tbl8wc2c;
+ /* translit */
+#endif /* __UCLIBC_HAS_WCHAR__ */
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
+#ifdef __UCLIBC_HAS_WCHAR__
+ base->tblwctype
+ = (const unsigned char *) &__locale_mmap->tblwctype;
+ base->tblwuplow
+ = (const unsigned char *) &__locale_mmap->tblwuplow;
+ base->tblwuplow_diff
+ = (const uint16_t *) &__locale_mmap->tblwuplow_diff;
+/* base->tblwcomb */
+/* = (const unsigned char *) &__locale_mmap->tblwcomb; */
+ /* width?? */
+#endif /* __UCLIBC_HAS_WCHAR__ */
+
+
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning wrong for now, but always set ctype arrays to global C version
#endif
-/**********************************************************************/
-#ifdef L_nl_langinfo
+#ifdef __UCLIBC_HAS_XLOCALE__
+ base->__ctype_b = __C_ctype_b;
+ base->__ctype_tolower = __C_ctype_tolower;
+ base->__ctype_toupper = __C_ctype_toupper;
+#else /* __UCLIBC_HAS_XLOCALE__ */
+ __ctype_b = __C_ctype_b;
+ __ctype_tolower = __C_ctype_tolower;
+ __ctype_toupper = __C_ctype_toupper;
+#endif /* __UCLIBC_HAS_XLOCALE__ */
-#include <langinfo.h>
-#include <nl_types.h>
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Initialize code2flag correctly based on locale_mmap.
+#endif
+ base->code2flag = __code2flag;
+
+
+ _locale_set_l(C_LOCALE_SELECTOR, base);
+}
+
+void _locale_init(void)
+{
+ /* TODO: mmap the locale file */
+
+ /* TODO - ??? */
+ _locale_init_l(__global_locale);
+}
+
+#endif
+/**********************************************************************/
+#if defined(L_nl_langinfo) || defined(L_nl_langinfo_l)
#ifdef __LOCALE_C_ONLY
@@ -853,22 +865,435 @@ char *nl_langinfo(nl_item item)
#else /* __LOCALE_C_ONLY */
-static const char empty[] = "";
+#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
char *nl_langinfo(nl_item item)
{
+ return nl_langinfo_l(item, __UCLIBC_CURLOCALE);
+}
+
+#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
+
+static const char empty[] = "";
+
+char *__XL(nl_langinfo)(nl_item item __LOCALE_PARAM )
+{
unsigned int c = _NL_ITEM_CATEGORY(item);
unsigned int i = _NL_ITEM_INDEX(item);
- if ((c < LC_ALL) && (i < __global_locale.category_item_count[c])) {
- return ((char **)(((char *) &__global_locale)
- + __global_locale.category_offsets[c]))[i];
-
+ if ((c < LC_ALL) && (i < __LOCALE_PTR->category_item_count[c])) {
+ return ((char **)(((char *) __LOCALE_PTR)
+ + __LOCALE_PTR->category_offsets[c]))[i];
}
+
return (char *) empty;
}
+#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
+
#endif /* __LOCALE_C_ONLY */
#endif
/**********************************************************************/
+#ifdef L_newlocale
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Move posix and utf8 strings.
+#endif
+static const char posix[] = "POSIX";
+static const char utf8[] = "UTF-8";
+
+static int find_locale(int category_mask, const char *p,
+ unsigned char *new_locale)
+{
+ int i;
+ const unsigned char *s;
+ uint16_t n;
+ unsigned char lang_cult, codeset;
+
+#if defined(__LOCALE_DATA_AT_MODIFIERS_LENGTH) && 1
+ /* Support standard locale handling for @-modifiers. */
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: Fix buf size in find_locale.
+#endif
+ char buf[18]; /* TODO: 7+{max codeset name length} */
+ const char *q;
+
+ if ((q = strchr(p,'@')) != NULL) {
+ if ((((size_t)((q-p)-5)) > (sizeof(buf) - 5)) || (p[2] != '_')) {
+ return 0;
+ }
+ /* locale name at least 5 chars long and 3rd char is '_' */
+ s = LOCALE_AT_MODIFIERS;
+ do {
+ if (!strcmp(s+2, q+1)) {
+ break;
+ }
+ s += 2 + *s; /* TODO - fix this throughout */
+ } while (*s);
+ if (!*s) {
+ return 0;
+ }
+ assert(q - p < sizeof(buf));
+ memcpy(buf, p, q-p);
+ buf[q-p] = 0;
+ buf[2] = s[1];
+ p = buf;
+ }
+#endif
+
+ lang_cult = codeset = 0; /* Assume C and default codeset. */
+ if (((*p == 'C') && !p[1]) || !strcmp(p, posix)) {
+ goto FIND_LOCALE;
+ }
+
+ if ((strlen(p) > 5) && (p[5] == '.')) { /* Codeset in locale name? */
+ /* TODO: maybe CODESET_LIST + *s ??? */
+ /* 7bit is 1, UTF-8 is 2, 8-bit is >= 3 */
+ codeset = 2;
+ if (strcmp(utf8,p+6) != 0) {/* TODO - fix! */
+ s = CODESET_LIST;
+ do {
+ ++codeset; /* Increment codeset first. */
+ if (!strcmp(CODESET_LIST+*s, p+6)) {
+ goto FIND_LANG_CULT;
+ }
+ } while (*++s);
+ return 0; /* No matching codeset! */
+ }
+ }
+
+ FIND_LANG_CULT: /* Find language_culture number. */
+ s = LOCALE_NAMES;
+ do { /* TODO -- do a binary search? */
+ /* TODO -- fix gen_mmap!*/
+ ++lang_cult; /* Increment first since C/POSIX is 0. */
+ if (!strncmp(s,p,5)) { /* Found a matching locale name; */
+ goto FIND_LOCALE;
+ }
+ s += 5;
+ } while (lang_cult < __LOCALE_DATA_NUM_LOCALE_NAMES);
+ return 0; /* No matching language_culture! */
+
+ FIND_LOCALE: /* Find locale row matching name and codeset */
+ s = LOCALES;
+ n = 0;
+ do { /* TODO -- do a binary search? */
+ if ((lang_cult == *s) && ((codeset == s[1]) || (codeset == s[2]))) {
+ i = 1;
+ s = new_locale + 1;
+ do {
+ if (category_mask & i) {
+ /* Encode current locale row number. */
+ ((unsigned char *) s)[0] = (n >> 7) | 0x80;
+ ((unsigned char *) s)[1] = (n & 0x7f) | 0x80;
+ }
+ s += 2;
+ i += i;
+ } while (i < (1 << LC_ALL));
+
+ return i; /* Return non-zero */
+ }
+ s += __LOCALE_DATA_WIDTH_LOCALES;
+ ++n;
+ } while (n <= __LOCALE_DATA_NUM_LOCALES); /* We started at 1!!! */
+
+ return 0; /* Unsupported locale. */
+}
+
+static unsigned char *composite_locale(int category_mask, const char *locale,
+ unsigned char *new_locale)
+{
+ char buf[MAX_LOCALE_STR];
+ char *t;
+ char *e;
+ int c;
+ int component_mask;
+
+ if (!strchr(locale,'=')) {
+ if (!find_locale(category_mask, locale, new_locale)) {
+ return NULL;
+ }
+ return new_locale;
+ }
+
+ if (strlen(locale) >= sizeof(buf)) {
+ return NULL;
+ }
+ stpcpy(buf, locale);
+
+ component_mask = 0;
+ t = strtok_r(buf, "=", &e); /* This can't fail because of strchr test above. */
+ do {
+ c = 0;
+ while (strcmp(CATEGORY_NAMES + (int) CATEGORY_NAMES[c], t)) {
+ if (++c == LC_ALL) { /* Unknown category name! */
+ return NULL;
+ }
+ }
+ t = strtok_r(NULL, ";", &e);
+ c = (1 << c);
+ if (component_mask & c) { /* Multiple components for one category. */
+ return NULL;
+ }
+ component_mask |= c;
+ if ((category_mask & c) && (!t || !find_locale(c, t, new_locale))) {
+ return NULL;
+ }
+ } while ((t = strtok_r(NULL, "=", &e)) != NULL);
+
+ if (category_mask & ~component_mask) { /* Category component(s) missing. */
+ return NULL;
+ }
+
+ return new_locale;
+}
+
+__locale_t __newlocale(int category_mask, const char *locale, __locale_t base)
+{
+ const unsigned char *p;
+ int i, j, k;
+ unsigned char new_selector[LOCALE_SELECTOR_SIZE];
+
+ if (!locale || (((unsigned int)(category_mask)) > LC_ALL_MASK)) {
+ INVALID:
+ __set_errno(EINVAL);
+ return NULL; /* No locale or illegal/unsupported category. */
+ }
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Rename cur_locale to locale_selector.
+#endif
+ strcpy((char *) new_selector,
+ (base ? (char *) base->cur_locale : C_LOCALE_SELECTOR));
+
+ if (!*locale) { /* locale == "", so check environment. */
+#ifndef __UCLIBC_HAS_THREADS__
+ static /* If no threads, then envstr can be static. */
+#endif /* __UCLIBC_HAS_THREADS__ */
+ const char *envstr[4] = { "LC_ALL", NULL, "LANG", posix };
+
+ i = 1;
+ k = 0;
+ do {
+ if (category_mask & i) {
+ /* Note: SUSv3 doesn't define a fallback mechanism here.
+ * So, if LC_ALL is invalid, we do _not_ continue trying
+ * the other environment vars. */
+ envstr[1] = CATEGORY_NAMES + CATEGORY_NAMES[k];
+ j = 0;
+ do {
+ p = envstr[j];
+ } while ((++j < 4) && (!(p = getenv(p)) || !*p));
+
+
+ /* The user set something... is it valid? */
+ /* Note: Since we don't support user-supplied locales and
+ * alternate paths, we don't need to worry about special
+ * handling for suid/sgid apps. */
+ if (!find_locale(i, p, new_selector)) {
+ goto INVALID;
+ }
+ }
+ i += i;
+ } while (++k < LC_ALL);
+ } else if (!composite_locale(category_mask, locale, new_selector)) {
+ goto INVALID;
+ }
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Do a compatible codeset check!
+#endif
+
+ /* If we get here, the new selector corresponds to a valid locale. */
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning CONSIDER: Probably want a _locale_new func to allow for caching of locales.
+#endif
+#if 0
+ if (base) {
+ _locale_set_l(new_selector, base);
+ } else {
+ base = _locale_new(new_selector);
+ }
+#else
+ if (!base) {
+ if ((base = malloc(sizeof(__uclibc_locale_t))) == NULL) {
+ return base;
+ }
+ _locale_init_l(base);
+ }
+
+ _locale_set_l(new_selector, base);
+#endif
+
+ return base;
+}
+
+weak_alias(__newlocale, newlocale)
+
+#endif
+/**********************************************************************/
+#ifdef L_duplocale
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: When we allocate ctype tables, remember to dup them.
+#endif
+
+__locale_t duplocale(__locale_t dataset)
+{
+ __locale_t r;
+ uint16_t * i2w;
+
+ assert(dataset != LC_GLOBAL_LOCALE);
+
+ if ((r = malloc(sizeof(__uclibc_locale_t))) != NULL) {
+ if ((i2w = calloc(2*dataset->collate.max_col_index+2,
+ sizeof(uint16_t)))
+ != NULL
+ ) {
+ memcpy(r, dataset, sizeof(__uclibc_locale_t));
+ r->collate.index2weight = i2w;
+ } else {
+ free(r);
+ r = NULL;
+ }
+ }
+ return r;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_freelocale
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: When we allocate ctype tables, remember to free them.
+#endif
+
+void freelocale(__locale_t dataset)
+{
+ assert(dataset != __global_locale);
+ assert(dataset != LC_GLOBAL_LOCALE);
+
+ free(dataset->collate.index2weight); /* Free collation data. */
+ free(dataset); /* Free locale */
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_uselocale
+
+__locale_t uselocale(__locale_t dataset)
+{
+ __locale_t old;
+
+ if (!dataset) {
+ old = __UCLIBC_CURLOCALE;
+ } else {
+ if (dataset == LC_GLOBAL_LOCALE) {
+ dataset = __global_locale;
+ }
+#ifdef __UCLIBC_HAS_THREADS__
+ old = __curlocale_set(dataset);
+#else
+ old = __curlocale_var;
+ __curlocale_var = dataset;
+#endif
+ }
+
+ if (old == __global_locale) {
+ return LC_GLOBAL_LOCALE;
+ }
+ return old;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L___curlocale
+
+#ifdef __UCLIBC_HAS_THREADS__
+
+__locale_t weak_const_function __curlocale(void)
+{
+ return __curlocale_var; /* This is overriden by the thread version. */
+}
+
+__locale_t weak_function __curlocale_set(__locale_t newloc)
+{
+ assert(newloc != LC_GLOBAL_LOCALE);
+
+ __locale_t oldloc = __curlocale_var;
+ __curlocale_var = newloc;
+ return oldloc;
+}
+
+#endif
+
+#endif
+/**********************************************************************/
+#ifdef L___locale_mbrtowc_l
+
+/* NOTE: This returns an int... not size_t. Also, it is not a general
+ * routine. It is actually a very stripped-down version of mbrtowc
+ * that takes a __locale_t arg. This is used by strcoll and strxfrm.
+ * It is also used above to generate wchar_t versions of the decimal point
+ * and thousands seperator. */
+
+
+#ifndef __CTYPE_HAS_UTF_8_LOCALES
+#warning __CTYPE_HAS_UTF_8_LOCALES not set!
+#endif
+#ifndef __CTYPE_HAS_8_BIT_LOCALES
+#warning __CTYPE_HAS_8_BIT_LOCALES not set!
+#endif
+
+#define Cc2wc_IDX_SHIFT __LOCALE_DATA_Cc2wc_IDX_SHIFT
+#define Cc2wc_ROW_LEN __LOCALE_DATA_Cc2wc_ROW_LEN
+
+extern size_t _wchar_utf8sntowcs(wchar_t *__restrict pwc, size_t wn,
+ const char **__restrict src, size_t n,
+ mbstate_t *ps, int allow_continuation);
+
+int __locale_mbrtowc_l(wchar_t *__restrict dst,
+ const char *__restrict src,
+ __locale_t loc )
+{
+#ifdef __CTYPE_HAS_UTF_8_LOCALES
+ if (loc->encoding == __ctype_encoding_utf8) {
+ mbstate_t ps;
+ const char *p = src;
+ size_t r;
+ ps.mask = 0;
+ r = _wchar_utf8sntowcs(dst, 1, &p, SIZE_MAX, &ps, 1);
+ return (r == 1) ? (p-src) : r; /* Need to return 0 if nul char. */
+ }
+#endif
+
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+ assert((loc->encoding == __ctype_encoding_7_bit) || (loc->encoding == __ctype_encoding_8_bit));
+#else
+ assert(loc->encoding == __ctype_encoding_7_bit);
+#endif
+
+ if ((*dst = ((unsigned char)(*src))) < 0x80) { /* ASCII... */
+ return (*src != 0);
+ }
+
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+ if (loc->encoding == __ctype_encoding_8_bit) {
+ wchar_t wc = *dst - 0x80;
+ *dst = __LOCALE_PTR->tbl8c2wc[
+ (__LOCALE_PTR->idx8c2wc[wc >> Cc2wc_IDX_SHIFT]
+ << Cc2wc_IDX_SHIFT) + (wc & (Cc2wc_ROW_LEN - 1))];
+ if (*dst) {
+ return 1;
+ }
+ }
+#endif
+
+ return -1;
+}
+
+#endif
+/**********************************************************************/
diff --git a/libc/misc/time/Makefile b/libc/misc/time/Makefile
index b5714e511..302214baf 100644
--- a/libc/misc/time/Makefile
+++ b/libc/misc/time/Makefile
@@ -28,15 +28,22 @@ MSRC= time.c
MOBJ= asctime.o asctime_r.o clock.o ctime.o ctime_r.o gmtime.o gmtime_r.o \
localtime.o localtime_r.o mktime.o strftime.o strptime.o tzset.o \
_time_t2tm.o __time_tm.o _time_mktime.o dysize.o timegm.o
+MOBJx=
ifeq ($(UCLIBC_HAS_FLOATS),y)
MOBJ += difftime.o
endif
+ifeq ($(UCLIBC_HAS_XLOCALE),y)
+ MOBJx += strftime_l.o strptime_l.o
+endif
+
+ifeq ($(UCLIBC_HAS_WCHAR),y)
+endif
CSRC= adjtime.c ftime.c
COBJS=$(patsubst %.c,%.o, $(CSRC))
-OBJS=$(COBJS) $(MOBJ)
+OBJS=$(COBJS) $(MOBJ) $(MOBJx)
all: $(OBJS) $(LIBC)
@@ -49,6 +56,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
+
$(COBJS): %.o : %.c
$(CC) $(CFLAGS) -c $< -o $@
$(STRIPTOOL) -x -R .note -R .comment $*.o
diff --git a/libc/misc/time/time.c b/libc/misc/time/time.c
index 8d3cbc3b4..0ae91f69a 100644
--- a/libc/misc/time/time.c
+++ b/libc/misc/time/time.c
@@ -95,9 +95,32 @@
*
* Nov 26, 2002 Fix bug in setting daylight and timezone when no (valid) TZ.
* Bug reported by Arne Bernin <arne@alamut.de> in regards to freeswan.
+ *
+ * July 27, 2003 Adjust the struct tm extension field support.
+ * Change __tm_tzone back to a ptr and add the __tm_tzname[] buffer for
+ * __tm_tzone to point to. This gets around complaints from g++.
+ * Who knows... it might even fix the PPC timezone init problem.
+ *
+ * July 29, 2003 Fix a bug in mktime behavior when tm_isdst was -1.
+ * Bug reported by "Sid Wade" <sid@vivato.net> in regards to busybox.
+ *
+ * NOTE: uClibc mktime behavior is different than glibc's when
+ * the struct tm has tm_isdst == -1 and also had fields outside of
+ * the normal ranges.
+ *
+ * Apparently, glibc examines (at least) tm_sec and guesses the app's
+ * intention of assuming increasing or decreasing time when entering an
+ * ambiguous time period at the dst<->st boundaries.
+ *
+ * The uClibc behavior is to always normalize the struct tm and then
+ * try to determing the dst setting.
+ *
+ * As long as tm_isdst != -1 or the time specifiec by struct tm is
+ * unambiguous (not falling in the dst<->st transition region) both
+ * uClibc and glibc should produce the same result for mktime.
+ *
*/
-
#define _GNU_SOURCE
#define _STDIO_UTILITY
#include <stdio.h>
@@ -112,6 +135,10 @@
#include <langinfo.h>
#include <locale.h>
+#ifdef __UCLIBC_HAS_XLOCALE__
+#include <xlocale.h>
+#endif
+
#ifndef __isleap
#define __isleap(y) ( !((y) % 4) && ( ((y) % 100) || !((y) % 400) ) )
#endif
@@ -121,27 +148,26 @@
#endif
/**********************************************************************/
-
/* The era code is currently unfinished. */
/* #define ENABLE_ERA_CODE */
-#define __TIME_TZ_FILE
-/* #define __TIME_TZ_FILE_ONCE */
-
-#define __TIME_TZ_OPT_SPEED
-
#define TZ_BUFLEN (2*TZNAME_MAX + 56)
-#ifdef __TIME_TZ_FILE
+#ifdef __UCLIBC_HAS_TZ_FILE__
+
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "paths.h"
/* ":<tzname>+hh:mm:ss<tzname>+hh:mm:ss,Mmm.w.d/hh:mm:ss,Mmm.w.d/hh:mm:ss" + nul */
/* 1 + 2*(1+TZNAME_MAX+1 + 9 + 7 + 9) + 1 = 2*TZNAME_MAX + 56 */
-#else /* __TIME_TZ_FILE */
-#undef __TIME_TZ_FILE_ONCE
-#endif /* __TIME_TZ_FILE */
+
+#else /* __UCLIBC_HAS_TZ_FILE__ */
+
+/* Probably no longer needed. */
+#undef __UCLIBC_HAS_TZ_FILE_READ_MANY__
+
+#endif /* __UCLIBC_HAS_TZ_FILE__ */
/**********************************************************************/
@@ -592,7 +618,8 @@ struct tm *localtime_r(register const time_t *__restrict timer,
result->tm_isdst = dst;
#ifdef __UCLIBC_HAS_TM_EXTENSIONS__
result->tm_gmtoff = - _time_tzinfo[dst].gmt_offset;
- strcpy( (char *)(result->tm_zone), _time_tzinfo[dst].tzname);
+ result->tm_zone = result->__tm_tzname;
+ strcpy(result->__tm_tzname, _time_tzinfo[dst].tzname);
#endif /* __UCLIBC_HAS_TM_EXTENSIONS__ */
} while ((++dst < 2) && (result->tm_isdst = tm_isdst(result)) != 0);
@@ -617,7 +644,18 @@ time_t mktime(struct tm *timeptr)
#endif
/**********************************************************************/
-#ifdef L_strftime
+#if defined(L_strftime) || defined(L_strftime_l)
+
+#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
+
+size_t strftime(char *__restrict s, size_t maxsize,
+ const char *__restrict format,
+ const struct tm *__restrict timeptr)
+{
+ return strftime_l(s, maxsize, format, timeptr, __UCLIBC_CURLOCALE);
+}
+
+#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
#define NO_E_MOD 0x80
#define NO_O_MOD 0x40
@@ -811,9 +849,13 @@ static int load_field(int k, const struct tm *__restrict timeptr)
#define MAX_PUSH 4
-size_t strftime(char *__restrict s, size_t maxsize,
- const char *__restrict format,
- const struct tm *__restrict timeptr)
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Check multibyte format string validity.
+#endif
+
+size_t __XL(strftime)(char *__restrict s, size_t maxsize,
+ const char *__restrict format,
+ const struct tm *__restrict timeptr __LOCALE_PARAM )
{
long tzo;
register const char *p;
@@ -882,16 +924,19 @@ size_t strftime(char *__restrict s, size_t maxsize,
+ (code & 7);
#ifdef ENABLE_ERA_CODE
if ((mod & NO_E_MOD) /* Actually, this means E modifier present. */
- && (*(o = nl_langinfo(_NL_ITEM(LC_TIME,
- (int)(((unsigned char *)p)[4]))
+ && (*(o = __XL(nl_langinfo)(_NL_ITEM(LC_TIME,
+ (int)(((unsigned char *)p)[4]))
+ __LOCALE_ARG
)))
) {
p = o;
goto LOOP;
}
#endif
- p = nl_langinfo(_NL_ITEM(LC_TIME,
- (int)(*((unsigned char *)p))));
+ p = __XL(nl_langinfo)(_NL_ITEM(LC_TIME,
+ (int)(*((unsigned char *)p)))
+ __LOCALE_ARG
+ );
goto LOOP;
}
@@ -1037,7 +1082,7 @@ size_t strftime(char *__restrict s, size_t maxsize,
if ((code & MASK_SPEC) == STRING_SPEC) {
o_count = SIZE_MAX;
field_val += spec[STRINGS_NL_ITEM_START + (code & 0xf)];
- o = nl_langinfo(_NL_ITEM(LC_TIME, field_val));
+ o = __XL(nl_langinfo)(_NL_ITEM(LC_TIME, field_val) __LOCALE_ARG );
} else {
o_count = ((i >> 1) & 3) + 1;
o = buf + o_count;
@@ -1061,9 +1106,31 @@ size_t strftime(char *__restrict s, size_t maxsize,
goto LOOP;
}
+#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
+
#endif
/**********************************************************************/
-#ifdef L_strptime
+#if defined(L_strptime) || defined(L_strptime_l)
+
+#if defined(L_strptime) || defined(L_strptime_l)
+#define ISDIGIT(C) __isdigit_char((C))
+#endif
+
+#ifdef __UCLIBC_DO_XLOCALE
+#define ISSPACE(C) isspace_l((C), locale_arg)
+#else
+#define ISSPACE(C) isspace((C))
+#endif
+
+#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
+
+char *strptime(const char *__restrict buf, const char *__restrict format,
+ struct tm *__restrict tm)
+{
+ return strptime_l(buf, format, tm, __UCLIBC_CURLOCALE);
+}
+
+#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
/* TODO:
* 1) %l and %k are space-padded, so "%l" by itself fails while " %l" succeeds.
@@ -1207,8 +1274,8 @@ static const unsigned char spec[] = {
#define MAX_PUSH 4
-char *strptime(const char *__restrict buf, const char *__restrict format,
- struct tm *__restrict tm)
+char *__XL(strptime)(const char *__restrict buf, const char *__restrict format,
+ struct tm *__restrict tm __LOCALE_PARAM)
{
register const char *p;
char *o;
@@ -1273,16 +1340,18 @@ char *strptime(const char *__restrict buf, const char *__restrict format,
+ (code & 7);
#ifdef ENABLE_ERA_CODE
if ((mod & NO_E_MOD) /* Actually, this means E modifier present. */
- && (*(o = nl_langinfo(_NL_ITEM(LC_TIME,
- (int)(((unsigned char *)p)[4]))
- )))
+ && (*(o = __XL(nl_langinfo)(_NL_ITEM(LC_TIME,
+ (int)(((unsigned char *)p)[4]))
+ __LOCALE_ARG
+ )))
) {
p = o;
goto LOOP;
}
#endif
- p = nl_langinfo(_NL_ITEM(LC_TIME,
- (int)(*((unsigned char *)p))));
+ p = __XL(nl_langinfo)(_NL_ITEM(LC_TIME,
+ (int)(*((unsigned char *)p)))
+ __LOCALE_ARG );
goto LOOP;
}
@@ -1295,9 +1364,9 @@ char *strptime(const char *__restrict buf, const char *__restrict format,
/* Go backwards to check full names before abreviations. */
do {
--j;
- o = nl_langinfo(i+j);
- if (!strncasecmp(buf,o,strlen(o)) && *o) { /* Found a match. */
- do {
+ o = __XL(nl_langinfo)(i+j __LOCALE_ARG);
+ if (!__XL(strncasecmp)(buf,o,strlen(o) __LOCALE_ARG) && *o) {
+ do { /* Found a match. */
++buf;
} while (*++o);
if (!code) { /* am/pm */
@@ -1322,11 +1391,11 @@ char *strptime(const char *__restrict buf, const char *__restrict format,
o = (char *) buf;
i = errno;
__set_errno(0);
- if (!isspace(*buf)) { /* Signal an error if whitespace. */
+ if (!ISSPACE(*buf)) { /* Signal an error if whitespace. */
#ifdef TIME_T_IS_UNSIGNED
- t = strtoul(buf, &o, 10);
+ t = __XL(strtoul)(buf, &o, 10 __LOCALE_ARG);
#else
- t = strtol(buf, &o, 10);
+ t = __XL(strtol)(buf, &o, 10 __LOCALE_ARG);
#endif
}
if ((o == buf) || errno) { /* Not a number or overflow. */
@@ -1356,7 +1425,7 @@ char *strptime(const char *__restrict buf, const char *__restrict format,
j = ((j==1) ? 366 : 9999);
}
i = -1;
- while (isdigit(*buf)) {
+ while (ISDIGIT(*buf)) {
if (i < 0) {
i = 0;
}
@@ -1401,9 +1470,9 @@ char *strptime(const char *__restrict buf, const char *__restrict format,
}
}
goto LOOP;
- } else if (isspace(*p)) {
+ } else if (ISSPACE(*p)) {
++p;
- while (isspace(*buf)) {
+ while (ISSPACE(*buf)) {
++buf;
}
goto LOOP;
@@ -1413,6 +1482,8 @@ char *strptime(const char *__restrict buf, const char *__restrict format,
return NULL;
}
+#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
+
#endif
/**********************************************************************/
#ifdef L_time
@@ -1478,10 +1549,10 @@ static const char *getoffset(register const char *e, long *pn)
f = -1;
do {
++s;
- if (isdigit(*e)) {
+ if (__isdigit_char(*e)) {
f = *e++ - '0';
}
- if (isdigit(*e)) {
+ if (__isdigit_char(*e)) {
f = 10 * f + (*e++ - '0');
}
if (((unsigned int)f) >= *s) {
@@ -1507,7 +1578,7 @@ static const char *getnumber(register const char *e, int *pn)
int f;
f = 0;
- while (n && isdigit(*e)) {
+ while (n && __isdigit_char(*e)) {
f = 10 * f + (*e++ - '0');
--n;
}
@@ -1519,7 +1590,7 @@ static const char *getnumber(register const char *e, int *pn)
n = 3;
f = 0;
- while (n && isdigit(*e)) {
+ while (n && __isdigit_char(*e)) {
f = 10 * f + (*e++ - '0');
--n;
}
@@ -1529,11 +1600,16 @@ static const char *getnumber(register const char *e, int *pn)
#endif /* __BCC__ */
}
-#ifdef __TIME_TZ_FILE
-#ifdef __TIME_TZ_FILE_ONCE
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning CONSIDER: Should we preserve errno from open/read/close errors re TZ file?
+#endif
+
+#ifdef __UCLIBC_HAS_TZ_FILE__
+
+#ifndef __UCLIBC_HAS_TZ_FILE_READ_MANY__
static int TZ_file_read; /* Let BSS initialization set this to 0. */
-#endif /* __TIME_TZ_FILE_ONCE */
+#endif /* __UCLIBC_HAS_TZ_FILE_READ_MANY__ */
static char *read_TZ_file(char *buf)
{
@@ -1542,7 +1618,7 @@ static char *read_TZ_file(char *buf)
size_t todo;
char *p = NULL;
- if ((fd = open("/etc/TZ", O_RDONLY)) >= 0) {
+ if ((fd = open(__UCLIBC_TZ_FILE_PATH__, O_RDONLY)) >= 0) {
todo = TZ_BUFLEN;
p = buf;
do {
@@ -1559,9 +1635,9 @@ static char *read_TZ_file(char *buf)
if ((p > buf) && (p[-1] == '\n')) { /* Must end with newline. */
p[-1] = 0;
p = buf;
-#ifdef __TIME_TZ_FILE_ONCE
+#ifndef __UCLIBC_HAS_TZ_FILE_READ_MANY__
++TZ_file_read;
-#endif /* __TIME_TZ_FILE_ONCE */
+#endif /* __UCLIBC_HAS_TZ_FILE_READ_MANY__ */
} else {
ERROR:
p = NULL;
@@ -1571,7 +1647,7 @@ static char *read_TZ_file(char *buf)
return p;
}
-#endif /* __TIME_TZ_FILE */
+#endif /* __UCLIBC_HAS_TZ_FILE__ */
void tzset(void)
{
@@ -1582,18 +1658,18 @@ void tzset(void)
rule_struct new_rules[2];
int n, count, f;
char c;
-#ifdef __TIME_TZ_FILE
+#ifdef __UCLIBC_HAS_TZ_FILE__
char buf[TZ_BUFLEN];
-#endif /* __TIME_TZ_FILE */
-#ifdef __TIME_TZ_OPT_SPEED
+#endif /* __UCLIBC_HAS_TZ_FILE__ */
+#ifdef __UCLIBC_HAS_TZ_CACHING__
static char oldval[TZ_BUFLEN]; /* BSS-zero'd. */
-#endif /* __TIME_TZ_OPT_SPEED */
+#endif /* __UCLIBC_HAS_TZ_CACHING__ */
TZLOCK;
e = getenv(TZ); /* TZ env var always takes precedence. */
-#ifdef __TIME_TZ_FILE_ONCE
+#if defined(__UCLIBC_HAS_TZ_FILE__) && !defined(__UCLIBC_HAS_TZ_FILE_READ_MANY__)
/* Put this inside the lock to prevent the possiblity of two different
* timezones being used in a threaded app. */
@@ -1602,7 +1678,7 @@ void tzset(void)
} else if (TZ_file_read > 0) {
goto FAST_DONE;
}
-#endif /* __TIME_TZ_FILE_ONCE */
+#endif /* defined(__UCLIBC_HAS_TZ_FILE__) && !defined(__UCLIBC_HAS_TZ_FILE_READ_MANY__) */
/* Warning!!! Since uClibc doesn't do lib locking, the following is
* potentially unsafe in a multi-threaded program since it is remotely
@@ -1610,14 +1686,14 @@ void tzset(void)
* the string being parsed. So, don't do that... */
if ((!e /* TZ env var not set... */
-#ifdef __TIME_TZ_FILE
+#ifdef __UCLIBC_HAS_TZ_FILE__
&& !(e = read_TZ_file(buf)) /* and no file or invalid file */
-#endif /* __TIME_TZ_FILE */
+#endif /* __UCLIBC_HAS_TZ_FILE__ */
) || !*e) { /* or set to empty string. */
ILLEGAL: /* TODO: Clean up the following... */
-#ifdef __TIME_TZ_OPT_SPEED
+#ifdef __UCLIBC_HAS_TZ_CACHING__
*oldval = 0; /* Set oldval to an empty string. */
-#endif /* __TIME_TZ_OPT_SPEED */
+#endif /* __UCLIBC_HAS_TZ_CACHING__ */
s = _time_tzinfo[0].tzname;
*s = 'U';
*++s = 'T';
@@ -1632,7 +1708,7 @@ void tzset(void)
++e;
}
-#ifdef __TIME_TZ_OPT_SPEED
+#ifdef __UCLIBC_HAS_TZ_CACHING__
if (strcmp(e, oldval) == 0) { /* Same string as last time... */
goto FAST_DONE; /* So nothing to do. */
}
@@ -1640,7 +1716,7 @@ void tzset(void)
* it is too long, but it that case it will be illegal and will be reset
* to the empty string anyway. */
strncpy(oldval, e, TZ_BUFLEN);
-#endif /* __TIME_TZ_OPT_SPEED */
+#endif /* __UCLIBC_HAS_TZ_CACHING__ */
count = 0;
new_rules[1].tzname[0] = 0;
@@ -1675,7 +1751,7 @@ void tzset(void)
/* Get offset */
s = (char *) e;
if ((*e != '-') && (*e != '+')) {
- if (count && !isdigit(*e)) {
+ if (count && !__isdigit_char(*e)) {
off -= 3600; /* Default to 1 hour ahead of std. */
goto SKIP_OFFSET;
}
@@ -1938,8 +2014,9 @@ struct tm *_time_t2tm(const time_t *__restrict timer,
p[4] = 0; /* result[8] .. tm_isdst */
#ifdef __UCLIBC_HAS_TM_EXTENSIONS__
result->tm_gmtoff = 0;
+ result->tm_zone = result->__tm_tzname;
{
- register char *s = (char *) result->tm_zone;
+ register char *s = result->__tm_tzname;
*s = 'U';
*++s = 'T';
*++s = 'C';
@@ -1977,12 +2054,16 @@ time_t _time_mktime(struct tm *timeptr, int store_on_success)
/* 0:sec 1:min 2:hour 3:mday 4:mon 5:year 6:wday 7:yday 8:isdst */
register int *p = (int *) &x;
register const unsigned char *s;
- int d;
+ int d, default_dst;
tzset();
memcpy(p, timeptr, sizeof(struct tm));
+ if ((default_dst = p[8]) < 0) {
+ default_dst = 1; /* Assume advancing */
+ }
+
d = 400;
p[5] = (p[5] - ((p[6] = p[5]/d) * d)) + (p[7] = p[4]/12);
if ((p[4] -= 12 * p[7]) < 0) {
@@ -2007,49 +2088,69 @@ time_t _time_mktime(struct tm *timeptr, int store_on_success)
--d;
}
+ TZLOCK;
+
#ifdef __BCC__
d = p[5] - 1;
days = -719163L + ((long)d)*365 + ((d/4) - (d/100) + (d/400) + p[3] + p[7]);
secs = p[0] + 60*( p[1] + 60*((long)(p[2])) )
- + _time_tzinfo[timeptr->tm_isdst > 0].gmt_offset;
+ + _time_tzinfo[default_dst].gmt_offset;
+ DST_CORRECT:
if (secs < 0) {
secs += 120009600L;
days -= 1389;
}
if ( ((unsigned long)(days + secs/86400L)) > 49710L) {
- return -1;
+ t = ((time_t)(-1));
+ goto DONE;
}
secs += (days * 86400L);
#else
- TZLOCK;
d = p[5] - 1;
d = -719163L + d*365 + (d/4) - (d/100) + (d/400);
secs = p[0]
- + _time_tzinfo[timeptr->tm_isdst > 0].gmt_offset
+ + _time_tzinfo[default_dst].gmt_offset
+ 60*( p[1]
+ 60*(p[2]
+ 24*(((146073L * ((long long)(p[6])) + d)
+ p[3]) + p[7])));
- TZUNLOCK;
+
+ DST_CORRECT:
if (((unsigned long long)(secs - LONG_MIN))
> (((unsigned long long)LONG_MAX) - LONG_MIN)
) {
- return -1;
+ t = ((time_t)(-1));
+ goto DONE;
}
#endif
+ d = ((struct tm *)p)->tm_isdst;
t = secs;
localtime_r(&t, (struct tm *)p);
- if (t < 0) {
- return -1;
+ if (t == ((time_t)(-1))) { /* Remember, time_t can be unsigned. */
+ goto DONE;
+ }
+
+ if ((d < 0) && (((struct tm *)p)->tm_isdst != default_dst)) {
+#ifdef __BCC__
+ secs -= (days * 86400L);
+#endif
+ secs += (_time_tzinfo[1-default_dst].gmt_offset
+ - _time_tzinfo[default_dst].gmt_offset);
+ goto DST_CORRECT;
}
+
if (store_on_success) {
memcpy(timeptr, p, sizeof(struct tm));
}
+
+ DONE:
+ TZUNLOCK;
+
return t;
}
diff --git a/libc/misc/wchar/Makefile b/libc/misc/wchar/Makefile
index acc852195..4a3e2fc7a 100644
--- a/libc/misc/wchar/Makefile
+++ b/libc/misc/wchar/Makefile
@@ -42,7 +42,6 @@ MOBJ2= fwide.o \
# getwc (fgetwc alias) getwc_unlocked (fgetwc_unlocked alias)
# putwc (fputwc alias) putwc_unlocked (fputwc_unlocked alias)
-# fwscanf wscanf swscanf vfwscanf vwscanf vswscanf
# wcsftime
OBJS=$(MOBJ1) $(MOBJ2)
diff --git a/libc/misc/wchar/wchar.c b/libc/misc/wchar/wchar.c
index ff3e42a84..aa0c2735a 100644
--- a/libc/misc/wchar/wchar.c
+++ b/libc/misc/wchar/wchar.c
@@ -86,6 +86,9 @@
* Add a couple of ugly hacks to support *wprintf.
* Add a mini iconv() and iconv implementation (requires locale support).
*
+ * Aug 1, 2003
+ * Bug fix for mbrtowc.
+ *
* Manuel
*/
@@ -101,13 +104,39 @@
#include <assert.h>
#include <locale.h>
#include <wchar.h>
+#include <bits/uClibc_uwchar.h>
+/**********************************************************************/
#ifdef __UCLIBC_HAS_LOCALE__
-#define ENCODING (__global_locale.encoding)
+#ifdef __UCLIBC_MJN3_ONLY__
+#ifdef L_iswspace
+/* generates one warning */
+#warning TODO: Fix Cc2wc* and Cwc2c* defines!
+#endif
+#endif /* __UCLIBC_MJN3_ONLY__ */
+
+#define ENCODING ((__UCLIBC_CURLOCALE_DATA).encoding)
+
+#define Cc2wc_IDX_SHIFT __LOCALE_DATA_Cc2wc_IDX_SHIFT
+#define Cc2wc_ROW_LEN __LOCALE_DATA_Cc2wc_ROW_LEN
+#define Cwc2c_DOMAIN_MAX __LOCALE_DATA_Cwc2c_DOMAIN_MAX
+#define Cwc2c_TI_SHIFT __LOCALE_DATA_Cwc2c_TI_SHIFT
+#define Cwc2c_TT_SHIFT __LOCALE_DATA_Cwc2c_TT_SHIFT
+#define Cwc2c_TI_LEN __LOCALE_DATA_Cwc2c_TI_LEN
+
#ifndef __CTYPE_HAS_UTF_8_LOCALES
#warning __CTYPE_HAS_UTF_8_LOCALES not set!
#endif
-#else
+
+#else /* __UCLIBC_HAS_LOCALE__ */
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#ifdef L_btowc
+/* emit only once */
+#warning fix preprocessor logic testing locale settings
+#endif
+#endif
+
#define ENCODING (__ctype_encoding_7_bit)
#ifdef __CTYPE_HAS_8_BIT_LOCALES
#error __CTYPE_HAS_8_BIT_LOCALES is defined!
@@ -117,7 +146,9 @@
#endif
#undef L__wchar_utf8sntowcs
#undef L__wchar_wcsntoutf8s
-#endif
+
+#endif /* __UCLIBC_HAS_LOCALE__ */
+/**********************************************************************/
#if WCHAR_MAX > 0xffffUL
#define UTF_8_MAX_LEN 6
@@ -266,11 +297,18 @@ size_t mbrtowc(wchar_t *__restrict pwc, const char *__restrict s,
#ifdef __CTYPE_HAS_UTF_8_LOCALES
/* Need to do this here since mbsrtowcs doesn't allow incompletes. */
if (ENCODING == __ctype_encoding_utf8) {
+ if (!pwc) {
+ pwc = wcbuf;
+ }
r = _wchar_utf8sntowcs(pwc, 1, &p, n, ps, 1);
return (r == 1) ? (p-s) : r; /* Need to return 0 if nul char. */
}
#endif
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: This adds a trailing nul!
+#endif /* __UCLIBC_MJN3_ONLY__ */
+
r = __mbsnrtowcs(wcbuf, &p, SIZE_MAX, 1, ps);
if (((ssize_t) r) >= 0) {
@@ -291,7 +329,10 @@ size_t mbrtowc(wchar_t *__restrict pwc, const char *__restrict s,
size_t wcrtomb(register char *__restrict s, wchar_t wc,
mbstate_t *__restrict ps)
{
- wchar_t wcbuf[2];
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning TODO: Should wcsnrtombs nul-terminate unconditionally? Check glibc.
+#endif /* __UCLIBC_MJN3_ONLY__ */
+ wchar_t wcbuf[1];
const wchar_t *pwc;
size_t r;
char buf[MB_LEN_MAX];
@@ -303,9 +344,8 @@ size_t wcrtomb(register char *__restrict s, wchar_t wc,
pwc = wcbuf;
wcbuf[0] = wc;
- wcbuf[1] = 0;
- r = __wcsnrtombs(s, &pwc, SIZE_MAX, MB_LEN_MAX, ps);
+ r = __wcsnrtombs(s, &pwc, 1, MB_LEN_MAX, ps);
return (r != 0) ? r : 1;
}
@@ -418,7 +458,7 @@ size_t _wchar_utf8sntowcs(wchar_t *__restrict pwc, size_t wn,
if ((wc = ((unsigned char) *s++)) >= 0x80) { /* Not ASCII... */
mask = 0x40;
#ifdef __UCLIBC_MJN3_ONLY__
-#warning fix range for 16 bit wides
+#warning TODO: Fix range for 16 bit wchar_t case.
#endif
if ( ((unsigned char)(s[-1] - 0xc0)) < (0xfe - 0xc0) ) {
goto START;
@@ -495,7 +535,6 @@ size_t _wchar_utf8sntowcs(wchar_t *__restrict pwc, size_t wn,
COMPLETE:
*pwc = wc;
pwc += incr;
-
}
#ifdef DECODER
while (--count);
@@ -684,8 +723,8 @@ size_t __mbsnrtowcs(wchar_t *__restrict dst, const char **__restrict src,
while (count) {
if ((wc = ((unsigned char)(*s))) >= 0x80) { /* Non-ASCII... */
wc -= 0x80;
- wc = __global_locale.tbl8c2wc[
- (__global_locale.idx8c2wc[wc >> Cc2wc_IDX_SHIFT]
+ wc = __UCLIBC_CURLOCALE_DATA.tbl8c2wc[
+ (__UCLIBC_CURLOCALE_DATA.idx8c2wc[wc >> Cc2wc_IDX_SHIFT]
<< Cc2wc_IDX_SHIFT) + (wc & (Cc2wc_ROW_LEN - 1))];
if (!wc) {
goto BAD;
@@ -797,12 +836,12 @@ size_t __wcsnrtombs(char *__restrict dst, const wchar_t **__restrict src,
} else {
u = 0;
if (wc <= Cwc2c_DOMAIN_MAX) {
- u = __global_locale.idx8wc2c[wc >> (Cwc2c_TI_SHIFT
+ u = __UCLIBC_CURLOCALE_DATA.idx8wc2c[wc >> (Cwc2c_TI_SHIFT
+ Cwc2c_TT_SHIFT)];
- u = __global_locale.tbl8wc2c[(u << Cwc2c_TI_SHIFT)
+ u = __UCLIBC_CURLOCALE_DATA.tbl8wc2c[(u << Cwc2c_TI_SHIFT)
+ ((wc >> Cwc2c_TT_SHIFT)
& ((1 << Cwc2c_TI_SHIFT)-1))];
- u = __global_locale.tbl8wc2c[Cwc2c_TI_LEN
+ u = __UCLIBC_CURLOCALE_DATA.tbl8wc2c[Cwc2c_TI_LEN
+ (u << Cwc2c_TT_SHIFT)
+ (wc & ((1 << Cwc2c_TT_SHIFT)-1))];
}
@@ -859,7 +898,8 @@ size_t __wcsnrtombs(char *__restrict dst, const wchar_t **__restrict src,
#ifdef L_wcswidth
#ifdef __UCLIBC_MJN3_ONLY__
-#warning if we start doing translit, wcwidth and wcswidth will need updating.
+#warning REMINDER: If we start doing translit, wcwidth and wcswidth will need updating.
+#warning TODO: Update wcwidth to match latest by Kuhn.
#endif
#if defined(__UCLIBC_HAS_LOCALE__) && \
@@ -1163,7 +1203,7 @@ enum {
*
*/
-const unsigned char codesets[] =
+const unsigned char __iconv_codesets[] =
"\x0a\xe0""WCHAR_T\x00" /* superset of UCS-4 but platform-endian */
#if __BYTE_ORDER == __BIG_ENDIAN
"\x08\xec""UCS-4\x00" /* always BE */
@@ -1201,7 +1241,7 @@ static int find_codeset(const char *name)
const unsigned char *s;
int codeset;
- for (s = codesets ; *s ; s += *s) {
+ for (s = __iconv_codesets ; *s ; s += *s) {
if (!strcasecmp(s+2, name)) {
return s[1];
}
@@ -1212,10 +1252,10 @@ static int find_codeset(const char *name)
/* TODO: maybe CODESET_LIST + *s ??? */
/* 7bit is 1, UTF-8 is 2, 8-bit is >= 3 */
codeset = 2;
- s = CODESET_LIST;
+ s = __LOCALE_DATA_CODESET_LIST;
do {
++codeset; /* Increment codeset first. */
- if (!strcasecmp(CODESET_LIST+*s, name)) {
+ if (!strcasecmp(__LOCALE_DATA_CODESET_LIST+*s, name)) {
return codeset;
}
} while (*++s);
@@ -1223,7 +1263,7 @@ static int find_codeset(const char *name)
return 0; /* No matching codeset! */
}
-iconv_t iconv_open(const char *tocode, const char *fromcode)
+iconv_t weak_function iconv_open(const char *tocode, const char *fromcode)
{
register _UC_iconv_t *px;
int tocodeset, fromcodeset;
@@ -1244,16 +1284,17 @@ iconv_t iconv_open(const char *tocode, const char *fromcode)
return (iconv_t)(-1);
}
-int iconv_close(iconv_t cd)
+int weak_function iconv_close(iconv_t cd)
{
free(cd);
return 0;
}
-size_t iconv(iconv_t cd, char **__restrict inbuf,
- size_t *__restrict inbytesleft,
- char **__restrict outbuf, size_t *__restrict outbytesleft)
+size_t weak_function iconv(iconv_t cd, char **__restrict inbuf,
+ size_t *__restrict inbytesleft,
+ char **__restrict outbuf,
+ size_t *__restrict outbytesleft)
{
_UC_iconv_t *px = (_UC_iconv_t *) cd;
size_t nrcount, r;
@@ -1362,9 +1403,9 @@ size_t iconv(iconv_t cd, char **__restrict inbuf,
return (size_t)(-1);
}
#ifdef __UCLIBC_MJN3_ONLY__
-#warning optimize this
+#warning TODO: optimize this.
#endif
- if (p != NULL) { /* incomplet char case */
+ if (p != NULL) { /* incomplete char case */
goto INVALID;
}
p = *inbuf + 1; /* nul */
@@ -1374,10 +1415,10 @@ size_t iconv(iconv_t cd, char **__restrict inbuf,
if (px->fromcodeset == IC_ASCII) { /* US-ASCII codeset */
goto ILLEGAL;
} else { /* some other 8-bit ascii-extension codeset */
- const codeset_8_bit_t *c8b
+ const __codeset_8_bit_t *c8b
= __locale_mmap->codeset_8_bit + px->fromcodeset - 3;
wc -= 0x80;
- wc = __global_locale.tbl8c2wc[
+ wc = __UCLIBC_CURLOCALE_DATA.tbl8c2wc[
(c8b->idx8c2wc[wc >> Cc2wc_IDX_SHIFT]
<< Cc2wc_IDX_SHIFT) + (wc & (Cc2wc_ROW_LEN - 1))];
if (!wc) {
@@ -1439,7 +1480,7 @@ size_t iconv(iconv_t cd, char **__restrict inbuf,
r = _wchar_wcsntoutf8s(*outbuf, *outbytesleft, &pw, 1);
if (r != (size_t)(-1)) {
#ifdef __UCLIBC_MJN3_ONLY__
-#warning what happens for a nul?
+#warning TODO: What happens for a nul?
#endif
if (r == 0) {
if (wc != 0) {
@@ -1458,14 +1499,14 @@ size_t iconv(iconv_t cd, char **__restrict inbuf,
**outbuf = wc;
} else {
if ((px->tocodeset != 0x01) && (wc <= Cwc2c_DOMAIN_MAX)) {
- const codeset_8_bit_t *c8b
+ const __codeset_8_bit_t *c8b
= __locale_mmap->codeset_8_bit + px->tocodeset - 3;
__uwchar_t u;
u = c8b->idx8wc2c[wc >> (Cwc2c_TI_SHIFT + Cwc2c_TT_SHIFT)];
- u = __global_locale.tbl8wc2c[(u << Cwc2c_TI_SHIFT)
+ u = __UCLIBC_CURLOCALE_DATA.tbl8wc2c[(u << Cwc2c_TI_SHIFT)
+ ((wc >> Cwc2c_TT_SHIFT)
& ((1 << Cwc2c_TI_SHIFT)-1))];
- wc = __global_locale.tbl8wc2c[Cwc2c_TI_LEN
+ wc = __UCLIBC_CURLOCALE_DATA.tbl8wc2c[Cwc2c_TI_LEN
+ (u << Cwc2c_TT_SHIFT)
+ (wc & ((1 << Cwc2c_TT_SHIFT)-1))];
if (wc) {
@@ -1497,7 +1538,7 @@ size_t iconv(iconv_t cd, char **__restrict inbuf,
#include <stdarg.h>
#include <libgen.h>
-extern const unsigned char codesets[];
+extern const unsigned char __iconv_codesets[];
#define IBUF BUFSIZ
#define OBUF BUFSIZ
@@ -1572,12 +1613,12 @@ int main(int argc, char **argv)
if (opts[5]) { /* -l */
fprintf(stderr, "Recognized codesets:\n");
- for (s = codesets ; *s ; s += *s) {
+ for (s = __iconv_codesets ; *s ; s += *s) {
fprintf(stderr," %s\n", s+2);
}
- s = CODESET_LIST;
+ s = __LOCALE_DATA_CODESET_LIST;
do {
- fprintf(stderr," %s\n", CODESET_LIST+ (unsigned char)(*s));
+ fprintf(stderr," %s\n", __LOCALE_DATA_CODESET_LIST+ (unsigned char)(*s));
} while (*++s);
return EXIT_SUCCESS;
diff --git a/libc/misc/wchar/wstdio.c b/libc/misc/wchar/wstdio.c
index dfeb35c30..1069ee938 100644
--- a/libc/misc/wchar/wstdio.c
+++ b/libc/misc/wchar/wstdio.c
@@ -171,7 +171,6 @@ UNLOCKED(wint_t,fgetwc,(register FILE *stream),(stream))
size_t r;
unsigned char c[1];
unsigned char sbuf[1];
- unsigned char ungot_width; /* Support ftell after wscanf ungetwc. */
wi = WEOF; /* Prepare for failure. */
@@ -183,8 +182,18 @@ UNLOCKED(wint_t,fgetwc,(register FILE *stream),(stream))
stream->modeflags |= __FLAG_WIDE;
if (stream->modeflags & __MASK_UNGOT) {/* Any ungetwc()s? */
- assert( (stream->modeflags & (__FLAG_READING|__FLAG_ERROR))
- == __FLAG_READING);
+
+ assert(stream->modeflags & __FLAG_READING);
+
+/* assert( (stream->modeflags & (__FLAG_READING|__FLAG_ERROR)) */
+/* == __FLAG_READING); */
+
+ if ((((stream->modeflags & __MASK_UNGOT) > 1) || stream->ungot[1])) {
+ stream->ungot_width[0] = 0; /* Application ungot... */
+ } else {
+ stream->ungot_width[0] = stream->ungot_width[1]; /* scanf ungot */
+ }
+
wi = stream->ungot[(--stream->modeflags) & __MASK_UNGOT];
stream->ungot[1] = 0;
goto DONE;
@@ -196,7 +205,9 @@ UNLOCKED(wint_t,fgetwc,(register FILE *stream),(stream))
++stream->bufend;
}
- ungot_width = 0;
+ if (stream->state.mask == 0) { /* If last was a complete char */
+ stream->ungot_width[0] = 0; /* then reset the width. */
+ }
LOOP:
if ((n = stream->bufread - stream->bufpos) == 0) {
@@ -204,12 +215,12 @@ UNLOCKED(wint_t,fgetwc,(register FILE *stream),(stream))
}
r = mbrtowc(wc, stream->bufpos, n, &stream->state);
- if (((ssize_t) r) >= 0) { /* Single byte... */
+ if (((ssize_t) r) >= 0) { /* Success... */
if (r == 0) { /* Nul wide char... means 0 byte for us so */
++r; /* increment r and handle below as single. */
}
stream->bufpos += r;
- stream->ungot_width[0] = ungot_width + r;
+ stream->ungot_width[0] += r;
wi = *wc;
goto DONE;
}
@@ -217,7 +228,7 @@ UNLOCKED(wint_t,fgetwc,(register FILE *stream),(stream))
if (r == ((size_t) -2)) {
/* Potentially valid but incomplete and no more buffered. */
stream->bufpos += n; /* Update bufpos for stream. */
- ungot_width += n;
+ stream->ungot_width[0] += n;
FILL_BUFFER:
if (_stdio_fread(c, (size_t) 1, stream) > 0) {
assert(stream->bufpos == stream->bufstart + 1);
@@ -371,7 +382,8 @@ UNLOCKED(int,fputws,(const wchar_t *__restrict ws,
#ifdef L_ungetwc
/*
* Note: This is the application-callable ungetwc. If wscanf calls this, it
- * should also set stream->ungot[1] to 0 if this is the only ungot.
+ * should also set stream->ungot[1] to 0 if this is the only ungot, as well
+ * as reset stream->ungot_width[1] for use by _stdio_adjpos().
*/
/* Reentrant. */
@@ -389,8 +401,7 @@ wint_t ungetwc(wint_t c, register FILE *stream)
}
stream->modeflags |= __FLAG_WIDE;
- /* If can't read or there's been an error, or c == EOF, or ungot slots
- * already filled, then return EOF */
+ /* If can't read or c == WEOF or ungot slots already filled, then fail. */
if ((stream->modeflags
& (__MASK_UNGOT2|__FLAG_WRITEONLY
#ifndef __STDIO_AUTO_RW_TRANSITION
@@ -406,14 +417,18 @@ wint_t ungetwc(wint_t c, register FILE *stream)
/* ungot_width */
#ifdef __STDIO_BUFFERS
- /* TODO: shouldn't allow writing??? */
+#ifdef __STDIO_AUTO_RW_TRANSITION
if (stream->modeflags & __FLAG_WRITING) {
fflush_unlocked(stream); /* Commit any write-buffered chars. */
}
+#endif /* __STDIO_AUTO_RW_TRANSITION */
#endif /* __STDIO_BUFFERS */
/* Clear EOF and WRITING flags, and set READING FLAG */
stream->modeflags &= ~(__FLAG_EOF|__FLAG_WRITING);
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning CONSIDER: Is setting the reading flag after an ungetwc necessary?
+#endif /* __UCLIBC_MJN3_ONLY__ */
stream->modeflags |= __FLAG_READING;
stream->ungot[1] = 1; /* Flag as app ungetc call; wscanf fixes up. */
stream->ungot[(stream->modeflags++) & __MASK_UNGOT] = c;
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,149 +35,309 @@
#include <errno.h>
#include <locale.h>
#include <ctype.h>
+#include <stdint.h>
+#include <bits/uClibc_uwchar.h>
+
+#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 <xlocale.h>
+
+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,34 +362,79 @@ 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
+/**********************************************************************/