summaryrefslogtreecommitdiffstats
path: root/libc/stdlib/stdlib.c
diff options
context:
space:
mode:
authorCarmelo Amoroso <carmelo.amoroso@st.com>2008-07-09 16:47:01 +0000
committerCarmelo Amoroso <carmelo.amoroso@st.com>2008-07-09 16:47:01 +0000
commit62a21af8006ab04282fdc354c5b4dc765f56d058 (patch)
tree568761d58289238aa14cced3f0010809d4d28c00 /libc/stdlib/stdlib.c
parentef250238dc1572caf859c2b64652f9cdfb0d9e42 (diff)
downloaduClibc-alpine-62a21af8006ab04282fdc354c5b4dc765f56d058.tar.bz2
uClibc-alpine-62a21af8006ab04282fdc354c5b4dc765f56d058.tar.xz
BIG BIG commit: all left files merged from trunk [rev 22714]. Currenntly NPTL sh4 port build and work fine. All committed to allow Khem Ray working on a working branch to integrate the ARM nptl port. MIPS nptl port not tested but should still building and working fine. There are some other part non yet merged with trunk (misc/internals and some headers file that need some more work). Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
Diffstat (limited to 'libc/stdlib/stdlib.c')
-rw-r--r--libc/stdlib/stdlib.c263
1 files changed, 144 insertions, 119 deletions
diff --git a/libc/stdlib/stdlib.c b/libc/stdlib/stdlib.c
index ccd3c015d..a864dd574 100644
--- a/libc/stdlib/stdlib.c
+++ b/libc/stdlib/stdlib.c
@@ -34,6 +34,7 @@
#define _ISOC99_SOURCE /* for ULLONG primarily... */
#include <limits.h>
+#include <stdint.h>
/* Work around gcc's refusal to create aliases.
* TODO: Add in a define to disable the aliases? */
@@ -327,9 +328,9 @@ long long atoll(const char *nptr)
libc_hidden_proto(__XL_NPP(strtol))
long __XL_NPP(strtol)(const char * __restrict str, char ** __restrict endptr,
- int base __LOCALE_PARAM )
+ int base __LOCALE_PARAM)
{
- return __XL_NPP(_stdlib_strto_l)(str, endptr, base, 1 __LOCALE_ARG );
+ return __XL_NPP(_stdlib_strto_l)(str, endptr, base, 1 __LOCALE_ARG);
}
libc_hidden_def(__XL_NPP(strtol))
@@ -358,10 +359,9 @@ libc_hidden_def(__XL_NPP(strtoll))
libc_hidden_proto(__XL_NPP(strtoll))
long long __XL_NPP(strtoll)(const char * __restrict str,
char ** __restrict endptr, int base
- __LOCALE_PARAM )
+ __LOCALE_PARAM)
{
- return (long long) __XL_NPP(_stdlib_strto_ll)(str, endptr, base, 1
- __LOCALE_ARG );
+ return (long long) __XL_NPP(_stdlib_strto_ll)(str, endptr, base, 1 __LOCALE_ARG);
}
libc_hidden_def(__XL_NPP(strtoll))
@@ -381,9 +381,9 @@ strong_alias(strtoll,strtoq)
libc_hidden_proto(__XL_NPP(strtoul))
unsigned long __XL_NPP(strtoul)(const char * __restrict str,
char ** __restrict endptr, int base
- __LOCALE_PARAM )
+ __LOCALE_PARAM)
{
- return __XL_NPP(_stdlib_strto_l)(str, endptr, base, 0 __LOCALE_ARG );
+ return __XL_NPP(_stdlib_strto_l)(str, endptr, base, 0 __LOCALE_ARG);
}
libc_hidden_def(__XL_NPP(strtoul))
@@ -413,9 +413,9 @@ libc_hidden_def(__XL_NPP(strtoull))
libc_hidden_proto(__XL_NPP(strtoull))
unsigned long long __XL_NPP(strtoull)(const char * __restrict str,
char ** __restrict endptr, int base
- __LOCALE_PARAM )
+ __LOCALE_PARAM)
{
- return __XL_NPP(_stdlib_strto_ll)(str, endptr, base, 0 __LOCALE_ARG );
+ return __XL_NPP(_stdlib_strto_ll)(str, endptr, base, 0 __LOCALE_ARG);
}
libc_hidden_def(__XL_NPP(strtoull))
@@ -502,39 +502,39 @@ unsigned long attribute_hidden _stdlib_strto_l(register const Wchar * __restrict
#ifdef __UCLIBC_HAS_XLOCALE__
libc_hidden_proto(__ctype_b_loc)
-#elif __UCLIBC_HAS_CTYPE_TABLES__
+#elif defined __UCLIBC_HAS_CTYPE_TABLES__
libc_hidden_proto(__ctype_b)
#endif
unsigned long attribute_hidden __XL_NPP(_stdlib_strto_l)(register const Wchar * __restrict str,
Wchar ** __restrict endptr, int base,
- int sflag __LOCALE_PARAM )
+ int sflag __LOCALE_PARAM)
{
- unsigned long number, cutoff;
+ unsigned long number, cutoff;
#if _STRTO_ENDPTR
- const Wchar *fail_char;
-#define SET_FAIL(X) fail_char = (X)
+ const Wchar *fail_char;
+#define SET_FAIL(X) fail_char = (X)
#else
-#define SET_FAIL(X) ((void)(X)) /* Keep side effects. */
+#define SET_FAIL(X) ((void)(X)) /* Keep side effects. */
#endif
- unsigned char negative, digit, cutoff_digit;
+ unsigned char negative, digit, cutoff_digit;
assert(((unsigned int)sflag) <= 1);
SET_FAIL(str);
- while (ISSPACE(*str)) { /* Skip leading whitespace. */
+ while (ISSPACE(*str)) { /* Skip leading whitespace. */
++str;
- }
+ }
- /* Handle optional sign. */
- negative = 0;
- switch(*str) {
+ /* Handle optional sign. */
+ negative = 0;
+ switch (*str) {
case '-': negative = 1; /* Fall through to increment str. */
case '+': ++str;
- }
+ }
- if (!(base & ~0x10)) { /* Either dynamic (base = 0) or base 16. */
+ if (!(base & ~0x10)) { /* Either dynamic (base = 0) or base 16. */
base += 10; /* Default is 10 (26). */
if (*str == '0') {
SET_FAIL(++str);
@@ -548,19 +548,19 @@ unsigned long attribute_hidden __XL_NPP(_stdlib_strto_l)(register const Wchar *
if (base > 16) { /* Adjust in case base wasn't dynamic. */
base = 16;
}
- }
+ }
number = 0;
- if (((unsigned)(base - 2)) < 35) { /* Legal base. */
+ if (((unsigned)(base - 2)) < 35) { /* Legal base. */
cutoff_digit = ULONG_MAX % base;
cutoff = ULONG_MAX / base;
do {
- digit = (((Wuchar)(*str - '0')) <= 9)
- ? (*str - '0')
- : ((*str >= 'A')
- ? (((0x20|(*str)) - 'a' + 10)) /* WARNING: assumes ascii. */
- : 40);
+ digit = ((Wuchar)(*str - '0') <= 9)
+ ? /* 0..9 */ (*str - '0')
+ : /* else */ (((Wuchar)(0x20 | *str) >= 'a') /* WARNING: assumes ascii. */
+ ? /* >= A/a */ ((Wuchar)(0x20 | *str) - ('a' - 10))
+ : /* else */ 40 /* bad value */);
if (digit >= base) {
break;
@@ -580,13 +580,13 @@ unsigned long attribute_hidden __XL_NPP(_stdlib_strto_l)(register const Wchar *
}
#if _STRTO_ENDPTR
- if (endptr) {
+ if (endptr) {
*endptr = (Wchar *) fail_char;
- }
+ }
#endif
{
- unsigned long tmp = ((negative)
+ unsigned long tmp = (negative
? ((unsigned long)(-(1+LONG_MIN)))+1
: LONG_MAX);
if (sflag && (number > tmp)) {
@@ -660,34 +660,34 @@ libc_hidden_proto(__ctype_b)
unsigned long long attribute_hidden __XL_NPP(_stdlib_strto_ll)(register const Wchar * __restrict str,
Wchar ** __restrict endptr, int base,
- int sflag __LOCALE_PARAM )
+ int sflag __LOCALE_PARAM)
{
- unsigned long long number;
+ unsigned long long number;
#if _STRTO_ENDPTR
- const Wchar *fail_char;
-#define SET_FAIL(X) fail_char = (X)
+ const Wchar *fail_char;
+#define SET_FAIL(X) fail_char = (X)
#else
-#define SET_FAIL(X) ((void)(X)) /* Keep side effects. */
+#define SET_FAIL(X) ((void)(X)) /* Keep side effects. */
#endif
unsigned int n1;
- unsigned char negative, digit;
+ unsigned char negative, digit;
assert(((unsigned int)sflag) <= 1);
SET_FAIL(str);
- while (ISSPACE(*str)) { /* Skip leading whitespace. */
+ while (ISSPACE(*str)) { /* Skip leading whitespace. */
++str;
- }
+ }
- /* Handle optional sign. */
- negative = 0;
- switch(*str) {
+ /* Handle optional sign. */
+ negative = 0;
+ switch (*str) {
case '-': negative = 1; /* Fall through to increment str. */
case '+': ++str;
- }
+ }
- if (!(base & ~0x10)) { /* Either dynamic (base = 0) or base 16. */
+ if (!(base & ~0x10)) { /* Either dynamic (base = 0) or base 16. */
base += 10; /* Default is 10 (26). */
if (*str == '0') {
SET_FAIL(++str);
@@ -701,17 +701,17 @@ unsigned long long attribute_hidden __XL_NPP(_stdlib_strto_ll)(register const Wc
if (base > 16) { /* Adjust in case base wasn't dynamic. */
base = 16;
}
- }
+ }
number = 0;
- if (((unsigned)(base - 2)) < 35) { /* Legal base. */
+ if (((unsigned)(base - 2)) < 35) { /* Legal base. */
do {
- digit = (((Wuchar)(*str - '0')) <= 9)
- ? (*str - '0')
- : ((*str >= 'A')
- ? (((0x20|(*str)) - 'a' + 10)) /* WARNING: assumes ascii. */
- : 40);
+ digit = ((Wuchar)(*str - '0') <= 9)
+ ? /* 0..9 */ (*str - '0')
+ : /* else */ (((Wuchar)(0x20 | *str) >= 'a') /* WARNING: assumes ascii. */
+ ? /* >= A/a */ ((Wuchar)(0x20 | *str) - ('a' - 10))
+ : /* else */ 40 /* bad value */);
if (digit >= base) {
break;
@@ -742,9 +742,9 @@ unsigned long long attribute_hidden __XL_NPP(_stdlib_strto_ll)(register const Wc
}
#if _STRTO_ENDPTR
- if (endptr) {
+ if (endptr) {
*endptr = (Wchar *) fail_char;
- }
+ }
#endif
{
@@ -817,16 +817,16 @@ void *bsearch(const void *key, const void *base, size_t /* nmemb */ high,
* bcc and gcc. */
libc_hidden_proto(qsort)
-void qsort (void *base,
- size_t nel,
- size_t width,
- int (*comp)(const void *, const void *))
+void qsort(void *base,
+ size_t nel,
+ size_t width,
+ int (*comp)(const void *, const void *))
{
size_t wgap, i, j, k;
char tmp;
if ((nel > 1) && (width > 0)) {
- assert( nel <= ((size_t)(-1)) / width ); /* check for overflow */
+ assert(nel <= ((size_t)(-1)) / width); /* check for overflow */
wgap = 0;
do {
wgap = 3 * wgap + 1;
@@ -846,7 +846,7 @@ void qsort (void *base,
j -= wgap;
a = j + ((char *)base);
b = a + wgap;
- if ( (*comp)(a, b) <= 0 ) {
+ if ((*comp)(a, b) <= 0) {
break;
}
k = width;
@@ -854,7 +854,7 @@ void qsort (void *base,
tmp = *a;
*a++ = *b;
*b++ = tmp;
- } while ( --k );
+ } while (--k);
} while (j >= wgap);
i += width;
} while (i < nel);
@@ -875,40 +875,36 @@ libc_hidden_def(qsort)
#include <stddef.h>
-void ssort (void *base,
- size_t nel,
- size_t width,
- int (*comp)(const void *, const void *))
+void ssort(void *base,
+ size_t nel,
+ size_t width,
+ int (*comp)(const void *, const void *))
{
- size_t wnel, gap, wgap, i, j, k;
- char *a, *b, tmp;
-
- wnel = width * nel;
- for (gap = 0; ++gap < nel;)
- gap *= 3;
- while ( gap /= 3 )
- {
- wgap = width * gap;
- for (i = wgap; i < wnel; i += width)
- {
- for (j = i - wgap; ;j -= wgap)
- {
- a = j + (char *)base;
- b = a + wgap;
- if ( (*comp)(a, b) <= 0 )
- break;
- k = width;
- do
- {
- tmp = *a;
- *a++ = *b;
- *b++ = tmp;
- } while ( --k );
- if (j < wgap)
- break;
- }
- }
- }
+ size_t wnel, gap, wgap, i, j, k;
+ char *a, *b, tmp;
+
+ wnel = width * nel;
+ for (gap = 0; ++gap < nel;)
+ gap *= 3;
+ while ((gap /= 3) != 0) {
+ wgap = width * gap;
+ for (i = wgap; i < wnel; i += width) {
+ for (j = i - wgap; ;j -= wgap) {
+ a = j + (char *)base;
+ b = a + wgap;
+ if ((*comp)(a, b) <= 0)
+ break;
+ k = width;
+ do {
+ tmp = *a;
+ *a++ = *b;
+ *b++ = tmp;
+ } while (--k);
+ if (j < wgap)
+ break;
+ }
+ }
+ }
}
#endif
@@ -933,6 +929,31 @@ size_t _stdlib_mb_cur_max(void)
libc_hidden_def(_stdlib_mb_cur_max)
#endif
+
+#ifdef __UCLIBC_HAS_LOCALE__
+/*
+ * The following function return 1 if the encoding is stateful, 0 if stateless.
+ * To note, until now all the supported encoding are stateless.
+ */
+
+static inline int
+is_stateful(unsigned char encoding)
+{
+ switch (encoding)
+ {
+ case __ctype_encoding_7_bit:
+ case __ctype_encoding_utf8:
+ case __ctype_encoding_8_bit:
+ return 0;
+ default:
+ assert(0);
+ return -1;
+ }
+}
+#else
+#define is_stateful(encoding) 0
+#endif
+
/**********************************************************************/
#ifdef L_mblen
@@ -945,13 +966,16 @@ int mblen(register const char *s, size_t n)
if (!s) {
state.__mask = 0;
-#ifdef __CTYPE_HAS_UTF_8_LOCALES
- return ENCODING == __ctype_encoding_utf8;
-#else
- return 0;
-#endif
+/* In this case we have to return 0 because the only multibyte supported encoding
+ is utf-8, that is a stateless encoding. See mblen() documentation.*/
+
+ return is_stateful(ENCODING);
}
+ if (*s == '\0')
+ /* According to the ISO C 89 standard this is the expected behaviour. */
+ return 0;
+
if ((r = mbrlen(s, n, &state)) == (size_t) -2) {
/* TODO: Should we set an error state? */
state.__wc = 0xffffU; /* Make sure we're in an error state. */
@@ -973,13 +997,16 @@ int mbtowc(wchar_t *__restrict pwc, register const char *__restrict s, size_t n)
if (!s) {
state.__mask = 0;
-#ifdef __CTYPE_HAS_UTF_8_LOCALES
- return ENCODING == __ctype_encoding_utf8;
-#else
- return 0;
-#endif
+/* In this case we have to return 0 because the only multibyte supported encoding
+ is utf-8, that is a stateless encoding. See mbtowc() documentation.*/
+
+ return is_stateful(ENCODING);
}
+ if (*s == '\0')
+ /* According to the ISO C 89 standard this is the expected behaviour. */
+ return 0;
+
if ((r = mbrtowc(pwc, s, n, &state)) == (size_t) -2) {
/* TODO: Should we set an error state? */
state.__wc = 0xffffU; /* Make sure we're in an error state. */
@@ -1000,11 +1027,10 @@ int wctomb(register char *__restrict s, wchar_t swc)
{
return (!s)
?
-#ifdef __CTYPE_HAS_UTF_8_LOCALES
- (ENCODING == __ctype_encoding_utf8)
-#else
- 0 /* Encoding is stateless. */
-#endif
+/* In this case we have to return 0 because the only multibyte supported encoding
+ is utf-8, that is a stateless encoding. See wctomb() documentation.*/
+
+ is_stateful(ENCODING)
: ((ssize_t) wcrtomb(s, swc, NULL));
}
@@ -1044,9 +1070,9 @@ size_t wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n)
libc_hidden_proto(__XL_NPP(wcstol))
long __XL_NPP(wcstol)(const wchar_t * __restrict str,
- wchar_t ** __restrict endptr, int base __LOCALE_PARAM )
+ wchar_t ** __restrict endptr, int base __LOCALE_PARAM)
{
- return __XL_NPP(_stdlib_wcsto_l)(str, endptr, base, 1 __LOCALE_ARG );
+ return __XL_NPP(_stdlib_wcsto_l)(str, endptr, base, 1 __LOCALE_ARG);
}
libc_hidden_def(__XL_NPP(wcstol))
@@ -1075,10 +1101,9 @@ libc_hidden_def(__XL_NPP(wcstoll))
libc_hidden_proto(__XL_NPP(wcstoll))
long long __XL_NPP(wcstoll)(const wchar_t * __restrict str,
wchar_t ** __restrict endptr, int base
- __LOCALE_PARAM )
+ __LOCALE_PARAM)
{
- return (long long) __XL_NPP(_stdlib_wcsto_ll)(str, endptr, base, 1
- __LOCALE_ARG );
+ return (long long) __XL_NPP(_stdlib_wcsto_ll)(str, endptr, base, 1 __LOCALE_ARG);
}
libc_hidden_def(__XL_NPP(wcstoll))
@@ -1098,9 +1123,9 @@ strong_alias(wcstoll,wcstoq)
libc_hidden_proto(__XL_NPP(wcstoul))
unsigned long __XL_NPP(wcstoul)(const wchar_t * __restrict str,
wchar_t ** __restrict endptr, int base
- __LOCALE_PARAM )
+ __LOCALE_PARAM)
{
- return __XL_NPP(_stdlib_wcsto_l)(str, endptr, base, 0 __LOCALE_ARG );
+ return __XL_NPP(_stdlib_wcsto_l)(str, endptr, base, 0 __LOCALE_ARG);
}
libc_hidden_def(__XL_NPP(wcstoul))
@@ -1129,9 +1154,9 @@ libc_hidden_def(__XL_NPP(wcstoull))
libc_hidden_proto(__XL_NPP(wcstoull))
unsigned long long __XL_NPP(wcstoull)(const wchar_t * __restrict str,
wchar_t ** __restrict endptr, int base
- __LOCALE_PARAM )
+ __LOCALE_PARAM)
{
- return __XL_NPP(_stdlib_wcsto_ll)(str, endptr, base, 0 __LOCALE_ARG );
+ return __XL_NPP(_stdlib_wcsto_ll)(str, endptr, base, 0 __LOCALE_ARG);
}
libc_hidden_def(__XL_NPP(wcstoull))