diff options
Diffstat (limited to 'libc/stdlib/stdlib.c')
-rw-r--r-- | libc/stdlib/stdlib.c | 263 |
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)) |