summaryrefslogtreecommitdiffstats
path: root/libc/stdlib/stdlib.c
diff options
context:
space:
mode:
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))