diff --git a/src/system/libroot/posix/glibc/stdlib/Jamfile b/src/system/libroot/posix/glibc/stdlib/Jamfile index 41ea3a5e36..cba4284783 100644 --- a/src/system/libroot/posix/glibc/stdlib/Jamfile +++ b/src/system/libroot/posix/glibc/stdlib/Jamfile @@ -34,6 +34,13 @@ for architectureObject in [ MultiArchSubDirSetup ] { random_r.c seed48.c srand48.c + strtod.c + strtold.c + strtof.c + strtol.c + strtoll.c + strtoul.c + strtoull.c # These are nonstandard but were declared in BeOS's headers. erand48_r.c diff --git a/src/system/libroot/posix/glibc/stdlib/strtod.c b/src/system/libroot/posix/glibc/stdlib/strtod.c new file mode 100644 index 0000000000..e7c5ca52dd --- /dev/null +++ b/src/system/libroot/posix/glibc/stdlib/strtod.c @@ -0,0 +1,1593 @@ +/* Read decimal floating point numbers. + This file is part of the GNU C Library. + Copyright (C) 1995,96,97,98,99,2000,2001 Free Software Foundation, Inc. + Contributed by Ulrich Drepper , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Configuration part. These macros are defined by `strtold.c', + `strtof.c', `wcstod.c', `wcstold.c', and `wcstof.c' to produce the + `long double' and `float' versions of the reader. */ +#ifndef FLOAT +# define FLOAT double +# define FLT DBL +# ifdef USE_WIDE_CHAR +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define STRTOF __wcstod_l +# else +# define STRTOF wcstod +# endif +# else +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define STRTOF __strtod_l +# else +# define STRTOF strtod +# endif +# endif +# define MPN2FLOAT __mpn_construct_double +# define FLOAT_HUGE_VAL HUGE_VAL +# define SET_MANTISSA(flt, mant) \ + do { union ieee754_double u; \ + u.d = (flt); \ + if ((mant & 0xfffffffffffffULL) == 0) \ + mant = 0x8000000000000ULL; \ + u.ieee.mantissa0 = ((mant) >> 32) & 0xfffff; \ + u.ieee.mantissa1 = (mant) & 0xffffffff; \ + (flt) = u.d; \ + } while (0) +#endif +/* End of configuration part. */ + +#include +#include +#include +#include +#include "../locale/localeinfo.h" +#include +#include +#include +#include + +/* The gmp headers need some configuration frobs. */ +#define HAVE_ALLOCA 1 + +#include +#include +#include +#include +#include "fpioconst.h" + +#define NDEBUG 1 +#include + + +/* We use this code also for the extended locale handling where the + function gets as an additional argument the locale which has to be + used. To access the values we have to redefine the _NL_CURRENT + macro. */ +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +# undef _NL_CURRENT +# define _NL_CURRENT(category, item) \ + (current->values[_NL_ITEM_INDEX (item)].string) +# define LOCALE_PARAM , loc +# define LOCALE_PARAM_DECL __locale_t loc; +#else +# define LOCALE_PARAM +# define LOCALE_PARAM_DECL +#endif + +#if defined _LIBC || defined HAVE_WCHAR_H +# include +#endif + +#ifdef USE_WIDE_CHAR +# include +# define STRING_TYPE wchar_t +# define CHAR_TYPE wint_t +# define L_(Ch) L##Ch +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define ISSPACE(Ch) __iswspace_l ((Ch), loc) +# define ISDIGIT(Ch) __iswdigit_l ((Ch), loc) +# define ISXDIGIT(Ch) __iswxdigit_l ((Ch), loc) +# define TOLOWER(Ch) __towlower_l ((Ch), loc) +# define STRNCASECMP(S1, S2, N) __wcsncasecmp_l ((S1), (S2), (N), loc) +# define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, loc) +# else +# define ISSPACE(Ch) iswspace (Ch) +# define ISDIGIT(Ch) iswdigit (Ch) +# define ISXDIGIT(Ch) iswxdigit (Ch) +# define TOLOWER(Ch) towlower (Ch) +# define STRNCASECMP(S1, S2, N) __wcsncasecmp ((S1), (S2), (N)) +# define STRTOULL(S, E, B) __wcstoull_internal ((S), (E), (B), 0) +# endif +#else +# define STRING_TYPE char +# define CHAR_TYPE char +# define L_(Ch) Ch +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define ISSPACE(Ch) __isspace_l ((Ch), loc) +# define ISDIGIT(Ch) __isdigit_l ((Ch), loc) +# define ISXDIGIT(Ch) __isxdigit_l ((Ch), loc) +# define TOLOWER(Ch) __tolower_l ((Ch), loc) +# define STRNCASECMP(S1, S2, N) __strncasecmp_l ((S1), (S2), (N), loc) +# define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0, loc) +# else +# define ISSPACE(Ch) isspace (Ch) +# define ISDIGIT(Ch) isdigit (Ch) +# define ISXDIGIT(Ch) isxdigit (Ch) +# define TOLOWER(Ch) tolower (Ch) +# define STRNCASECMP(S1, S2, N) strncasecmp ((S1), (S2), (N)) +# define STRTOULL(S, E, B) __strtoull_internal ((S), (E), 0, (B)) +# endif +#endif + + +/* Constants we need from float.h; select the set for the FLOAT precision. */ +#define MANT_DIG PASTE(FLT,_MANT_DIG) +#define DIG PASTE(FLT,_DIG) +#define MAX_EXP PASTE(FLT,_MAX_EXP) +#define MIN_EXP PASTE(FLT,_MIN_EXP) +#define MAX_10_EXP PASTE(FLT,_MAX_10_EXP) +#define MIN_10_EXP PASTE(FLT,_MIN_10_EXP) + +/* Extra macros required to get FLT expanded before the pasting. */ +#define PASTE(a,b) PASTE1(a,b) +#define PASTE1(a,b) a##b + +/* Function to construct a floating point number from an MP integer + containing the fraction bits, a base 2 exponent, and a sign flag. */ +extern FLOAT MPN2FLOAT (mp_srcptr mpn, int exponent, int negative); + +/* Definitions according to limb size used. */ +#if BITS_PER_MP_LIMB == 32 +# define MAX_DIG_PER_LIMB 9 +# define MAX_FAC_PER_LIMB 1000000000UL +#elif BITS_PER_MP_LIMB == 64 +# define MAX_DIG_PER_LIMB 19 +# define MAX_FAC_PER_LIMB 10000000000000000000UL +#else +# error "mp_limb_t size " BITS_PER_MP_LIMB "not accounted for" +#endif + + +/* Local data structure. */ +static const mp_limb_t _tens_in_limb[MAX_DIG_PER_LIMB + 1] = +{ 0, 10, 100, + 1000, 10000, 100000, + 1000000, 10000000, 100000000, + 1000000000 +#if BITS_PER_MP_LIMB > 32 + , 10000000000U, 100000000000U, + 1000000000000U, 10000000000000U, 100000000000000U, + 1000000000000000U, 10000000000000000U, 100000000000000000U, + 1000000000000000000U, 10000000000000000000U +#endif +#if BITS_PER_MP_LIMB > 64 + #error "Need to expand tens_in_limb table to" MAX_DIG_PER_LIMB +#endif +}; + +#ifndef howmany +#define howmany(x,y) (((x)+((y)-1))/(y)) +#endif +#define SWAP(x, y) ({ typeof(x) _tmp = x; x = y; y = _tmp; }) + +#define NDIG (MAX_10_EXP - MIN_10_EXP + 2 * MANT_DIG) +#define HEXNDIG ((MAX_EXP - MIN_EXP + 7) / 8 + 2 * MANT_DIG) +#define RETURN_LIMB_SIZE howmany (MANT_DIG, BITS_PER_MP_LIMB) + +#define RETURN(val,end) \ + do { if (endptr != NULL) *endptr = (STRING_TYPE *) (end); \ + return val; } while (0) + +/* Maximum size necessary for mpn integers to hold floating point numbers. */ +#define MPNSIZE (howmany (MAX_EXP + 2 * MANT_DIG, BITS_PER_MP_LIMB) \ + + 2) +/* Declare an mpn integer variable that big. */ +#define MPN_VAR(name) mp_limb_t name[MPNSIZE]; mp_size_t name##size +/* Copy an mpn integer value. */ +#define MPN_ASSIGN(dst, src) \ + memcpy (dst, src, (dst##size = src##size) * sizeof (mp_limb_t)) + + +/* Return a floating point number of the needed type according to the given + multi-precision number after possible rounding. */ +static inline FLOAT +round_and_return (mp_limb_t *retval, int exponent, int negative, + mp_limb_t round_limb, mp_size_t round_bit, int more_bits) +{ + if (exponent < MIN_EXP - 1) + { + mp_size_t shift = MIN_EXP - 1 - exponent; + + if (shift > MANT_DIG) + { + __set_errno (EDOM); + return 0.0; + } + + more_bits |= (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0; + if (shift == MANT_DIG) + /* This is a special case to handle the very seldom case where + the mantissa will be empty after the shift. */ + { + int i; + + round_limb = retval[RETURN_LIMB_SIZE - 1]; + round_bit = (MANT_DIG - 1) % BITS_PER_MP_LIMB; + for (i = 0; i < RETURN_LIMB_SIZE; ++i) + more_bits |= retval[i] != 0; + MPN_ZERO (retval, RETURN_LIMB_SIZE); + } + else if (shift >= BITS_PER_MP_LIMB) + { + int i; + + round_limb = retval[(shift - 1) / BITS_PER_MP_LIMB]; + round_bit = (shift - 1) % BITS_PER_MP_LIMB; + for (i = 0; i < (shift - 1) / BITS_PER_MP_LIMB; ++i) + more_bits |= retval[i] != 0; + more_bits |= ((round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) + != 0); + + (void) __mpn_rshift (retval, &retval[shift / BITS_PER_MP_LIMB], + RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB), + shift % BITS_PER_MP_LIMB); + MPN_ZERO (&retval[RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB)], + shift / BITS_PER_MP_LIMB); + } + else if (shift > 0) + { + round_limb = retval[0]; + round_bit = shift - 1; + (void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, shift); + } + /* This is a hook for the m68k long double format, where the + exponent bias is the same for normalized and denormalized + numbers. */ +#ifndef DENORM_EXP +# define DENORM_EXP (MIN_EXP - 2) +#endif + exponent = DENORM_EXP; + } + + if ((round_limb & (((mp_limb_t) 1) << round_bit)) != 0 + && (more_bits || (retval[0] & 1) != 0 + || (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0)) + { + mp_limb_t cy = __mpn_add_1 (retval, retval, RETURN_LIMB_SIZE, 1); + + if (((MANT_DIG % BITS_PER_MP_LIMB) == 0 && cy) || + ((MANT_DIG % BITS_PER_MP_LIMB) != 0 && + (retval[RETURN_LIMB_SIZE - 1] + & (((mp_limb_t) 1) << (MANT_DIG % BITS_PER_MP_LIMB))) != 0)) + { + ++exponent; + (void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, 1); + retval[RETURN_LIMB_SIZE - 1] + |= ((mp_limb_t) 1) << ((MANT_DIG - 1) % BITS_PER_MP_LIMB); + } + else if (exponent == DENORM_EXP + && (retval[RETURN_LIMB_SIZE - 1] + & (((mp_limb_t) 1) << ((MANT_DIG - 1) % BITS_PER_MP_LIMB))) + != 0) + /* The number was denormalized but now normalized. */ + exponent = MIN_EXP - 1; + } + + if (exponent > MAX_EXP) + return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; + + return MPN2FLOAT (retval, exponent, negative); +} + + +/* Read a multi-precision integer starting at STR with exactly DIGCNT digits + into N. Return the size of the number limbs in NSIZE at the first + character od the string that is not part of the integer as the function + value. If the EXPONENT is small enough to be taken as an additional + factor for the resulting number (see code) multiply by it. */ +static inline const STRING_TYPE * +str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize, + int *exponent +#ifndef USE_WIDE_CHAR + , const char *decimal, size_t decimal_len, const char *thousands +#endif + + ) +{ + /* Number of digits for actual limb. */ + int cnt = 0; + mp_limb_t low = 0; + mp_limb_t start; + + *nsize = 0; + assert (digcnt > 0); + do + { + if (cnt == MAX_DIG_PER_LIMB) + { + if (*nsize == 0) + { + n[0] = low; + *nsize = 1; + } + else + { + mp_limb_t cy; + cy = __mpn_mul_1 (n, n, *nsize, MAX_FAC_PER_LIMB); + cy += __mpn_add_1 (n, n, *nsize, low); + if (cy != 0) + { + n[*nsize] = cy; + ++(*nsize); + } + } + cnt = 0; + low = 0; + } + + /* There might be thousands separators or radix characters in + the string. But these all can be ignored because we know the + format of the number is correct and we have an exact number + of characters to read. */ +#ifdef USE_WIDE_CHAR + if (*str < L'0' || *str > L'9') + ++str; +#else + if (*str < '0' || *str > '9') + { + int inner = 0; + if (thousands != NULL && *str == *thousands + && ({ for (inner = 1; thousands[inner] != '\0'; ++inner) + if (thousands[inner] != str[inner]) + break; + thousands[inner] == '\0'; })) + str += inner; + else + str += decimal_len; + } +#endif + low = low * 10 + *str++ - L_('0'); + ++cnt; + } + while (--digcnt > 0); + + if (*exponent > 0 && cnt + *exponent <= MAX_DIG_PER_LIMB) + { + low *= _tens_in_limb[*exponent]; + start = _tens_in_limb[cnt + *exponent]; + *exponent = 0; + } + else + start = _tens_in_limb[cnt]; + + if (*nsize == 0) + { + n[0] = low; + *nsize = 1; + } + else + { + mp_limb_t cy; + cy = __mpn_mul_1 (n, n, *nsize, start); + cy += __mpn_add_1 (n, n, *nsize, low); + if (cy != 0) + n[(*nsize)++] = cy; + } + + return str; +} + + +/* Shift {PTR, SIZE} COUNT bits to the left, and fill the vacated bits + with the COUNT most significant bits of LIMB. + + Tege doesn't like this function so I have to write it here myself. :) + --drepper */ +static inline void +__mpn_lshift_1 (mp_limb_t *ptr, mp_size_t size, unsigned int count, + mp_limb_t limb) +{ + if (count == BITS_PER_MP_LIMB) + { + /* Optimize the case of shifting by exactly a word: + just copy words, with no actual bit-shifting. */ + mp_size_t i; + for (i = size - 1; i > 0; --i) + ptr[i] = ptr[i - 1]; + ptr[0] = limb; + } + else + { + (void) __mpn_lshift (ptr, ptr, size, count); + ptr[0] |= limb >> (BITS_PER_MP_LIMB - count); + } +} + + +#define INTERNAL(x) INTERNAL1(x) +#define INTERNAL1(x) __##x##_internal + +/* This file defines a function to check for correct grouping. */ +#include "grouping.h" + + +/* Return a floating point number with the value of the given string NPTR. + Set *ENDPTR to the character after the last used one. If the number is + smaller than the smallest representable number, set `errno' to ERANGE and + return 0.0. If the number is too big to be represented, set `errno' to + ERANGE and return HUGE_VAL with the appropriate sign. */ +FLOAT +INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM) + const STRING_TYPE *nptr; + STRING_TYPE **endptr; + int group; + LOCALE_PARAM_DECL +{ + int negative; /* The sign of the number. */ + MPN_VAR (num); /* MP representation of the number. */ + int exponent; /* Exponent of the number. */ + + /* Numbers starting `0X' or `0x' have to be processed with base 16. */ + int base = 10; + + /* When we have to compute fractional digits we form a fraction with a + second multi-precision number (and we sometimes need a second for + temporary results). */ + MPN_VAR (den); + + /* Representation for the return value. */ + mp_limb_t retval[RETURN_LIMB_SIZE]; + /* Number of bits currently in result value. */ + int bits; + + /* Running pointer after the last character processed in the string. */ + const STRING_TYPE *cp, *tp; + /* Start of significant part of the number. */ + const STRING_TYPE *startp, *start_of_digits; + /* Points at the character following the integer and fractional digits. */ + const STRING_TYPE *expp; + /* Total number of digit and number of digits in integer part. */ + int dig_no, int_no, lead_zero; + /* Contains the last character read. */ + CHAR_TYPE c; + +/* We should get wint_t from , but not all GCC versions define it + there. So define it ourselves if it remains undefined. */ +#ifndef _WINT_T + typedef unsigned int wint_t; +#endif + /* The radix character of the current locale. */ +#ifdef USE_WIDE_CHAR + wchar_t decimal; +#else + const char *decimal; + size_t decimal_len; +#endif + /* The thousands character of the current locale. */ +#ifdef USE_WIDE_CHAR + wchar_t thousands = L'\0'; +#else + const char *thousands = NULL; +#endif + /* The numeric grouping specification of the current locale, + in the format described in . */ + const char *grouping; + /* Used in several places. */ + int cnt; + +#ifdef USE_IN_EXTENDED_LOCALE_MODEL + struct locale_data *current = loc->__locales[LC_NUMERIC]; +#endif + + if (nptr == NULL) + { + __set_errno (EINVAL); + return NAN; + } + + if (group) + { + grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); + if (*grouping <= 0 || *grouping == CHAR_MAX) + grouping = NULL; + else + { + /* Figure out the thousands separator character. */ +#ifdef USE_WIDE_CHAR + thousands = _NL_CURRENT_WORD (LC_NUMERIC, + _NL_NUMERIC_THOUSANDS_SEP_WC); + if (thousands == L'\0') + grouping = NULL; +#else + thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP); + if (*thousands == '\0') + { + thousands = NULL; + grouping = NULL; + } +#endif + } + } + else + grouping = NULL; + + /* Find the locale's decimal point character. */ +#ifdef USE_WIDE_CHAR + decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC); + assert (decimal != L'\0'); +# define decimal_len 1 +#else + decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); + decimal_len = strlen (decimal); + assert (decimal_len > 0); +#endif + + /* Prepare number representation. */ + exponent = 0; + negative = 0; + bits = 0; + + /* Parse string to get maximal legal prefix. We need the number of + characters of the integer part, the fractional part and the exponent. */ + cp = nptr - 1; + /* Ignore leading white space. */ + do + c = *++cp; + while (ISSPACE (c)); + + /* Get sign of the result. */ + if (c == L_('-')) + { + negative = 1; + c = *++cp; + } + else if (c == L_('+')) + c = *++cp; + + /* Return 0.0 if no legal string is found. + No character is used even if a sign was found. */ +#ifdef USE_WIDE_CHAR + if (c == decimal && cp[1] >= L'0' && cp[1] <= L'9') + { + /* We accept it. This funny construct is here only to indent + the code directly. */ + } +#else + for (cnt = 0; decimal[cnt] != '\0'; ++cnt) + if (cp[cnt] != decimal[cnt]) + break; + if (decimal[cnt] == '\0' && cp[1] >= '0' && cp[1] <= '9') + { + /* We accept it. This funny construct is here only to indent + the code directly. */ + } +#endif + else if (c < L_('0') || c > L_('9')) + { + /* Check for `INF' or `INFINITY'. */ + if (TOLOWER (c) == L_('i') && STRNCASECMP (cp, L_("inf"), 3) == 0) + { + /* Return +/- infinity. */ + if (endptr != NULL) + *endptr = (STRING_TYPE *) + (cp + (STRNCASECMP (cp + 3, L_("inity"), 5) == 0 + ? 8 : 3)); + + return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; + } + + if (TOLOWER (c) == L_('n') && STRNCASECMP (cp, L_("nan"), 3) == 0) + { + /* Return NaN. */ + FLOAT retval = NAN; + + cp += 3; + + /* Match `(n-char-sequence-digit)'. */ + if (*cp == L_('(')) + { + const STRING_TYPE *startp = cp; + do + ++cp; + while ((*cp >= L_('0') && *cp <= L_('9')) + || (TOLOWER (*cp) >= L_('a') && TOLOWER (*cp) <= L_('z')) + || *cp == L_('_')); + + if (*cp != L_(')')) + /* The closing brace is missing. Only match the NAN + part. */ + cp = startp; + else + { + /* This is a system-dependent way to specify the + bitmask used for the NaN. We expect it to be + a number which is put in the mantissa of the + number. */ + STRING_TYPE *endp; + unsigned long long int mant; + + mant = STRTOULL (startp + 1, &endp, 0); + if (endp == cp) + SET_MANTISSA (retval, mant); + } + } + + if (endptr != NULL) + *endptr = (STRING_TYPE *) cp; + + return retval; + } + + /* It is really a text we do not recognize. */ + RETURN (0.0, nptr); + } + + /* First look whether we are faced with a hexadecimal number. */ + if (c == L_('0') && TOLOWER (cp[1]) == L_('x')) + { + /* Okay, it is a hexa-decimal number. Remember this and skip + the characters. BTW: hexadecimal numbers must not be + grouped. */ + base = 16; + cp += 2; + c = *cp; + grouping = NULL; + } + + /* Record the start of the digits, in case we will check their grouping. */ + start_of_digits = startp = cp; + + /* Ignore leading zeroes. This helps us to avoid useless computations. */ +#ifdef USE_WIDE_CHAR + while (c == L'0' || (thousands != L'\0' && c == thousands)) + c = *++cp; +#else + if (thousands == NULL) + while (c == '0') + c = *++cp; + else + { + /* We also have the multibyte thousands string. */ + while (1) + { + if (c != '0') + { + for (cnt = 0; thousands[cnt] != '\0'; ++cnt) + if (c != thousands[cnt]) + break; + if (thousands[cnt] != '\0') + break; + } + c = *++cp; + } + } +#endif + + /* If no other digit but a '0' is found the result is 0.0. + Return current read pointer. */ + if (!((c >= L_('0') && c <= L_('9')) + || (base == 16 && ((CHAR_TYPE) TOLOWER (c) >= L_('a') + && (CHAR_TYPE) TOLOWER (c) <= L_('f'))) + || ( +#ifdef USE_WIDE_CHAR + c == (wint_t) decimal +#else + ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt) + if (decimal[cnt] != cp[cnt]) + break; + decimal[cnt] == '\0'; }) +#endif + /* '0x.' alone is not a valid hexadecimal number. + '.' alone is not valid either, but that has been checked + already earlier. */ + && (base != 16 + || cp != start_of_digits + || (cp[decimal_len] >= L_('0') && cp[decimal_len] <= L_('9')) + || ((CHAR_TYPE) TOLOWER (cp[decimal_len]) >= L_('a') + && (CHAR_TYPE) TOLOWER (cp[decimal_len]) <= L_('f')))) + || (base == 16 && (cp != start_of_digits + && (CHAR_TYPE) TOLOWER (c) == L_('p'))) + || (base != 16 && (CHAR_TYPE) TOLOWER (c) == L_('e')))) + { + tp = correctly_grouped_prefix (start_of_digits, cp, thousands, grouping); + /* If TP is at the start of the digits, there was no correctly + grouped prefix of the string; so no number found. */ + RETURN (0.0, tp == start_of_digits ? (base == 16 ? cp - 1 : nptr) : tp); + } + + /* Remember first significant digit and read following characters until the + decimal point, exponent character or any non-FP number character. */ + startp = cp; + dig_no = 0; + while (1) + { + if ((c >= L_('0') && c <= L_('9')) + || (base == 16 && TOLOWER (c) >= L_('a') && TOLOWER (c) <= L_('f'))) + ++dig_no; + else + { +#ifdef USE_WIDE_CHAR + if (thousands == L'\0' || c != thousands) + /* Not a digit or separator: end of the integer part. */ + break; +#else + if (thousands == NULL) + break; + else + { + for (cnt = 0; thousands[cnt] != '\0'; ++cnt) + if (thousands[cnt] != cp[cnt]) + break; + if (thousands[cnt] != '\0') + break; + } +#endif + } + c = *++cp; + } + + if (grouping && dig_no > 0) + { + /* Check the grouping of the digits. */ + tp = correctly_grouped_prefix (start_of_digits, cp, thousands, grouping); + if (cp != tp) + { + /* Less than the entire string was correctly grouped. */ + + if (tp == start_of_digits) + /* No valid group of numbers at all: no valid number. */ + RETURN (0.0, nptr); + + if (tp < startp) + /* The number is validly grouped, but consists + only of zeroes. The whole value is zero. */ + RETURN (0.0, tp); + + /* Recompute DIG_NO so we won't read more digits than + are properly grouped. */ + cp = tp; + dig_no = 0; + for (tp = startp; tp < cp; ++tp) + if (*tp >= L_('0') && *tp <= L_('9')) + ++dig_no; + + int_no = dig_no; + lead_zero = 0; + + goto number_parsed; + } + } + + /* We have the number digits in the integer part. Whether these are all or + any is really a fractional digit will be decided later. */ + int_no = dig_no; + lead_zero = int_no == 0 ? -1 : 0; + + /* Read the fractional digits. A special case are the 'american style' + numbers like `16.' i.e. with decimal but without trailing digits. */ + if ( +#ifdef USE_WIDE_CHAR + c == decimal +#else + ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt) + if (decimal[cnt] != cp[cnt]) + break; + decimal[cnt] == '\0'; }) +#endif + ) + { + cp += decimal_len; + c = *cp; + while ((c >= L_('0') && c <= L_('9')) || + (base == 16 && TOLOWER (c) >= L_('a') && TOLOWER (c) <= L_('f'))) + { + if (c != L_('0') && lead_zero == -1) + lead_zero = dig_no - int_no; + ++dig_no; + c = *++cp; + } + } + + /* Remember start of exponent (if any). */ + expp = cp; + + /* Read exponent. */ + if ((base == 16 && TOLOWER (c) == L_('p')) + || (base != 16 && TOLOWER (c) == L_('e'))) + { + int exp_negative = 0; + + c = *++cp; + if (c == L_('-')) + { + exp_negative = 1; + c = *++cp; + } + else if (c == L_('+')) + c = *++cp; + + if (c >= L_('0') && c <= L_('9')) + { + int exp_limit; + + /* Get the exponent limit. */ + if (base == 16) + exp_limit = (exp_negative ? + -MIN_EXP + MANT_DIG + 4 * int_no : + MAX_EXP - 4 * int_no + lead_zero); + else + exp_limit = (exp_negative ? + -MIN_10_EXP + MANT_DIG + int_no : + MAX_10_EXP - int_no + lead_zero); + + do + { + exponent *= 10; + + if (exponent > exp_limit) + /* The exponent is too large/small to represent a valid + number. */ + { + FLOAT result; + + /* We have to take care for special situation: a joker + might have written "0.0e100000" which is in fact + zero. */ + if (lead_zero == -1) + result = negative ? -0.0 : 0.0; + else + { + /* Overflow or underflow. */ + __set_errno (ERANGE); + result = (exp_negative ? 0.0 : + negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL); + } + + /* Accept all following digits as part of the exponent. */ + do + ++cp; + while (*cp >= L_('0') && *cp <= L_('9')); + + RETURN (result, cp); + /* NOTREACHED */ + } + + exponent += c - L_('0'); + c = *++cp; + } + while (c >= L_('0') && c <= L_('9')); + + if (exp_negative) + exponent = -exponent; + } + else + cp = expp; + } + + /* We don't want to have to work with trailing zeroes after the radix. */ + if (dig_no > int_no) + { + while (expp[-1] == L_('0')) + { + --expp; + --dig_no; + } + assert (dig_no >= int_no); + } + + if (dig_no == int_no && dig_no > 0 && exponent < 0) + do + { + while (expp[-1] < L_('0') || expp[-1] > L_('9')) + --expp; + + if (expp[-1] != L_('0')) + break; + + --expp; + --dig_no; + --int_no; + ++exponent; + } + while (dig_no > 0 && exponent < 0); + + number_parsed: + + /* The whole string is parsed. Store the address of the next character. */ + if (endptr) + *endptr = (STRING_TYPE *) cp; + + if (dig_no == 0) + return negative ? -0.0 : 0.0; + + if (lead_zero) + { + /* Find the decimal point */ +#ifdef USE_WIDE_CHAR + while (*startp != decimal) + ++startp; +#else + while (1) + { + if (*startp == decimal[0]) + { + for (cnt = 1; decimal[cnt] != '\0'; ++cnt) + if (decimal[cnt] != startp[cnt]) + break; + if (decimal[cnt] == '\0') + break; + } + ++startp; + } +#endif + startp += lead_zero + decimal_len; + exponent -= base == 16 ? 4 * lead_zero : lead_zero; + dig_no -= lead_zero; + } + + /* If the BASE is 16 we can use a simpler algorithm. */ + if (base == 16) + { + static const int nbits[16] = { 0, 1, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4 }; + int idx = (MANT_DIG - 1) / BITS_PER_MP_LIMB; + int pos = (MANT_DIG - 1) % BITS_PER_MP_LIMB; + mp_limb_t val; + + while (!ISXDIGIT (*startp)) + ++startp; + while (*startp == L_('0')) + ++startp; + if (ISDIGIT (*startp)) + val = *startp++ - L_('0'); + else + val = 10 + TOLOWER (*startp++) - L_('a'); + bits = nbits[val]; + /* We cannot have a leading zero. */ + assert (bits != 0); + + if (pos + 1 >= 4 || pos + 1 >= bits) + { + /* We don't have to care for wrapping. This is the normal + case so we add the first clause in the `if' expression as + an optimization. It is a compile-time constant and so does + not cost anything. */ + retval[idx] = val << (pos - bits + 1); + pos -= bits; + } + else + { + retval[idx--] = val >> (bits - pos - 1); + retval[idx] = val << (BITS_PER_MP_LIMB - (bits - pos - 1)); + pos = BITS_PER_MP_LIMB - 1 - (bits - pos - 1); + } + + /* Adjust the exponent for the bits we are shifting in. */ + exponent += bits - 1 + (int_no - 1) * 4; + + while (--dig_no > 0 && idx >= 0) + { + if (!ISXDIGIT (*startp)) + startp += decimal_len; + if (ISDIGIT (*startp)) + val = *startp++ - L_('0'); + else + val = 10 + TOLOWER (*startp++) - L_('a'); + + if (pos + 1 >= 4) + { + retval[idx] |= val << (pos - 4 + 1); + pos -= 4; + } + else + { + retval[idx--] |= val >> (4 - pos - 1); + val <<= BITS_PER_MP_LIMB - (4 - pos - 1); + if (idx < 0) + return round_and_return (retval, exponent, negative, val, + BITS_PER_MP_LIMB - 1, dig_no > 0); + + retval[idx] = val; + pos = BITS_PER_MP_LIMB - 1 - (4 - pos - 1); + } + } + + /* We ran out of digits. */ + MPN_ZERO (retval, idx); + + return round_and_return (retval, exponent, negative, 0, 0, 0); + } + + /* Now we have the number of digits in total and the integer digits as well + as the exponent and its sign. We can decide whether the read digits are + really integer digits or belong to the fractional part; i.e. we normalize + 123e-2 to 1.23. */ + { + register int incr = (exponent < 0 ? MAX (-int_no, exponent) + : MIN (dig_no - int_no, exponent)); + int_no += incr; + exponent -= incr; + } + + if (int_no + exponent > MAX_10_EXP + 1) + { + __set_errno (ERANGE); + return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; + } + + if (exponent < MIN_10_EXP - (DIG + 1)) + { + __set_errno (ERANGE); + return 0.0; + } + + if (int_no > 0) + { + /* Read the integer part as a multi-precision number to NUM. */ + startp = str_to_mpn (startp, int_no, num, &numsize, &exponent +#ifndef USE_WIDE_CHAR + , decimal, decimal_len, thousands +#endif + ); + + if (exponent > 0) + { + /* We now multiply the gained number by the given power of ten. */ + mp_limb_t *psrc = num; + mp_limb_t *pdest = den; + int expbit = 1; + const struct mp_power *ttab = &_fpioconst_pow10[0]; + + do + { + if ((exponent & expbit) != 0) + { + size_t size = ttab->arraysize - _FPIO_CONST_OFFSET; + mp_limb_t cy; + exponent ^= expbit; + + /* FIXME: not the whole multiplication has to be + done. If we have the needed number of bits we + only need the information whether more non-zero + bits follow. */ + if (numsize >= ttab->arraysize - _FPIO_CONST_OFFSET) + cy = __mpn_mul (pdest, psrc, numsize, + &__tens[ttab->arrayoff + + _FPIO_CONST_OFFSET], + size); + else + cy = __mpn_mul (pdest, &__tens[ttab->arrayoff + + _FPIO_CONST_OFFSET], + size, psrc, numsize); + numsize += size; + if (cy == 0) + --numsize; + (void) SWAP (psrc, pdest); + } + expbit <<= 1; + ++ttab; + } + while (exponent != 0); + + if (psrc == den) + memcpy (num, den, numsize * sizeof (mp_limb_t)); + } + + /* Determine how many bits of the result we already have. */ + count_leading_zeros (bits, num[numsize - 1]); + bits = numsize * BITS_PER_MP_LIMB - bits; + + /* Now we know the exponent of the number in base two. + Check it against the maximum possible exponent. */ + if (bits > MAX_EXP) + { + __set_errno (ERANGE); + return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; + } + + /* We have already the first BITS bits of the result. Together with + the information whether more non-zero bits follow this is enough + to determine the result. */ + if (bits > MANT_DIG) + { + int i; + const mp_size_t least_idx = (bits - MANT_DIG) / BITS_PER_MP_LIMB; + const mp_size_t least_bit = (bits - MANT_DIG) % BITS_PER_MP_LIMB; + const mp_size_t round_idx = least_bit == 0 ? least_idx - 1 + : least_idx; + const mp_size_t round_bit = least_bit == 0 ? BITS_PER_MP_LIMB - 1 + : least_bit - 1; + + if (least_bit == 0) + memcpy (retval, &num[least_idx], + RETURN_LIMB_SIZE * sizeof (mp_limb_t)); + else + { + for (i = least_idx; i < numsize - 1; ++i) + retval[i - least_idx] = (num[i] >> least_bit) + | (num[i + 1] + << (BITS_PER_MP_LIMB - least_bit)); + if (i - least_idx < RETURN_LIMB_SIZE) + retval[RETURN_LIMB_SIZE - 1] = num[i] >> least_bit; + } + + /* Check whether any limb beside the ones in RETVAL are non-zero. */ + for (i = 0; num[i] == 0; ++i) + ; + + return round_and_return (retval, bits - 1, negative, + num[round_idx], round_bit, + int_no < dig_no || i < round_idx); + /* NOTREACHED */ + } + else if (dig_no == int_no) + { + const mp_size_t target_bit = (MANT_DIG - 1) % BITS_PER_MP_LIMB; + const mp_size_t is_bit = (bits - 1) % BITS_PER_MP_LIMB; + + if (target_bit == is_bit) + { + memcpy (&retval[RETURN_LIMB_SIZE - numsize], num, + numsize * sizeof (mp_limb_t)); + /* FIXME: the following loop can be avoided if we assume a + maximal MANT_DIG value. */ + MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize); + } + else if (target_bit > is_bit) + { + (void) __mpn_lshift (&retval[RETURN_LIMB_SIZE - numsize], + num, numsize, target_bit - is_bit); + /* FIXME: the following loop can be avoided if we assume a + maximal MANT_DIG value. */ + MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize); + } + else + { + mp_limb_t cy; + assert (numsize < RETURN_LIMB_SIZE); + + cy = __mpn_rshift (&retval[RETURN_LIMB_SIZE - numsize], + num, numsize, is_bit - target_bit); + retval[RETURN_LIMB_SIZE - numsize - 1] = cy; + /* FIXME: the following loop can be avoided if we assume a + maximal MANT_DIG value. */ + MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize - 1); + } + + return round_and_return (retval, bits - 1, negative, 0, 0, 0); + /* NOTREACHED */ + } + + /* Store the bits we already have. */ + memcpy (retval, num, numsize * sizeof (mp_limb_t)); +#if RETURN_LIMB_SIZE > 1 + if (numsize < RETURN_LIMB_SIZE) + retval[numsize] = 0; +#endif + } + + /* We have to compute at least some of the fractional digits. */ + { + /* We construct a fraction and the result of the division gives us + the needed digits. The denominator is 1.0 multiplied by the + exponent of the lowest digit; i.e. 0.123 gives 123 / 1000 and + 123e-6 gives 123 / 1000000. */ + + int expbit; + int neg_exp; + int more_bits; + mp_limb_t cy; + mp_limb_t *psrc = den; + mp_limb_t *pdest = num; + const struct mp_power *ttab = &_fpioconst_pow10[0]; + + assert (dig_no > int_no && exponent <= 0); + + + /* For the fractional part we need not process too many digits. One + decimal digits gives us log_2(10) ~ 3.32 bits. If we now compute + ceil(BITS / 3) =: N + digits we should have enough bits for the result. The remaining + decimal digits give us the information that more bits are following. + This can be used while rounding. (One added as a safety margin.) */ + if (dig_no - int_no > (MANT_DIG - bits + 2) / 3 + 1) + { + dig_no = int_no + (MANT_DIG - bits + 2) / 3 + 1; + more_bits = 1; + } + else + more_bits = 0; + + neg_exp = dig_no - int_no - exponent; + + /* Construct the denominator. */ + densize = 0; + expbit = 1; + do + { + if ((neg_exp & expbit) != 0) + { + mp_limb_t cy; + neg_exp ^= expbit; + + if (densize == 0) + { + densize = ttab->arraysize - _FPIO_CONST_OFFSET; + memcpy (psrc, &__tens[ttab->arrayoff + _FPIO_CONST_OFFSET], + densize * sizeof (mp_limb_t)); + } + else + { + cy = __mpn_mul (pdest, &__tens[ttab->arrayoff + + _FPIO_CONST_OFFSET], + ttab->arraysize - _FPIO_CONST_OFFSET, + psrc, densize); + densize += ttab->arraysize - _FPIO_CONST_OFFSET; + if (cy == 0) + --densize; + (void) SWAP (psrc, pdest); + } + } + expbit <<= 1; + ++ttab; + } + while (neg_exp != 0); + + if (psrc == num) + memcpy (den, num, densize * sizeof (mp_limb_t)); + + /* Read the fractional digits from the string. */ + (void) str_to_mpn (startp, dig_no - int_no, num, &numsize, &exponent +#ifndef USE_WIDE_CHAR + , decimal, decimal_len, thousands +#endif + ); + + /* We now have to shift both numbers so that the highest bit in the + denominator is set. In the same process we copy the numerator to + a high place in the array so that the division constructs the wanted + digits. This is done by a "quasi fix point" number representation. + + num: ddddddddddd . 0000000000000000000000 + |--- m ---| + den: ddddddddddd n >= m + |--- n ---| + */ + + count_leading_zeros (cnt, den[densize - 1]); + + if (cnt > 0) + { + /* Don't call `mpn_shift' with a count of zero since the specification + does not allow this. */ + (void) __mpn_lshift (den, den, densize, cnt); + cy = __mpn_lshift (num, num, numsize, cnt); + if (cy != 0) + num[numsize++] = cy; + } + + /* Now we are ready for the division. But it is not necessary to + do a full multi-precision division because we only need a small + number of bits for the result. So we do not use __mpn_divmod + here but instead do the division here by hand and stop whenever + the needed number of bits is reached. The code itself comes + from the GNU MP Library by Torbj\"orn Granlund. */ + + exponent = bits; + + switch (densize) + { + case 1: + { + mp_limb_t d, n, quot; + int used = 0; + + n = num[0]; + d = den[0]; + assert (numsize == 1 && n < d); + + do + { + udiv_qrnnd (quot, n, n, 0, d); + +#define got_limb \ + if (bits == 0) \ + { \ + register int cnt; \ + if (quot == 0) \ + cnt = BITS_PER_MP_LIMB; \ + else \ + count_leading_zeros (cnt, quot); \ + exponent -= cnt; \ + if (BITS_PER_MP_LIMB - cnt > MANT_DIG) \ + { \ + used = MANT_DIG + cnt; \ + retval[0] = quot >> (BITS_PER_MP_LIMB - used); \ + bits = MANT_DIG + 1; \ + } \ + else \ + { \ + /* Note that we only clear the second element. */ \ + /* The conditional is determined at compile time. */ \ + if (RETURN_LIMB_SIZE > 1) \ + retval[1] = 0; \ + retval[0] = quot; \ + bits = -cnt; \ + } \ + } \ + else if (bits + BITS_PER_MP_LIMB <= MANT_DIG) \ + __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, BITS_PER_MP_LIMB, \ + quot); \ + else \ + { \ + used = MANT_DIG - bits; \ + if (used > 0) \ + __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, quot); \ + } \ + bits += BITS_PER_MP_LIMB + + got_limb; + } + while (bits <= MANT_DIG); + + return round_and_return (retval, exponent - 1, negative, + quot, BITS_PER_MP_LIMB - 1 - used, + more_bits || n != 0); + } + case 2: + { + mp_limb_t d0, d1, n0, n1; + mp_limb_t quot = 0; + int used = 0; + + d0 = den[0]; + d1 = den[1]; + + if (numsize < densize) + { + if (num[0] >= d1) + { + /* The numerator of the number occupies fewer bits than + the denominator but the one limb is bigger than the + high limb of the numerator. */ + n1 = 0; + n0 = num[0]; + } + else + { + if (bits <= 0) + exponent -= BITS_PER_MP_LIMB; + else + { + if (bits + BITS_PER_MP_LIMB <= MANT_DIG) + __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, + BITS_PER_MP_LIMB, 0); + else + { + used = MANT_DIG - bits; + if (used > 0) + __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0); + } + bits += BITS_PER_MP_LIMB; + } + n1 = num[0]; + n0 = 0; + } + } + else + { + n1 = num[1]; + n0 = num[0]; + } + + while (bits <= MANT_DIG) + { + mp_limb_t r; + + if (n1 == d1) + { + /* QUOT should be either 111..111 or 111..110. We need + special treatment of this rare case as normal division + would give overflow. */ + quot = ~(mp_limb_t) 0; + + r = n0 + d1; + if (r < d1) /* Carry in the addition? */ + { + add_ssaaaa (n1, n0, r - d0, 0, 0, d0); + goto have_quot; + } + n1 = d0 - (d0 != 0); + n0 = -d0; + } + else + { + udiv_qrnnd (quot, r, n1, n0, d1); + umul_ppmm (n1, n0, d0, quot); + } + + q_test: + if (n1 > r || (n1 == r && n0 > 0)) + { + /* The estimated QUOT was too large. */ + --quot; + + sub_ddmmss (n1, n0, n1, n0, 0, d0); + r += d1; + if (r >= d1) /* If not carry, test QUOT again. */ + goto q_test; + } + sub_ddmmss (n1, n0, r, 0, n1, n0); + + have_quot: + got_limb; + } + + return round_and_return (retval, exponent - 1, negative, + quot, BITS_PER_MP_LIMB - 1 - used, + more_bits || n1 != 0 || n0 != 0); + } + default: + { + int i; + mp_limb_t cy, dX, d1, n0, n1; + mp_limb_t quot = 0; + int used = 0; + + dX = den[densize - 1]; + d1 = den[densize - 2]; + + /* The division does not work if the upper limb of the two-limb + numerator is greater than the denominator. */ + if (__mpn_cmp (num, &den[densize - numsize], numsize) > 0) + num[numsize++] = 0; + + if (numsize < densize) + { + mp_size_t empty = densize - numsize; + + if (bits <= 0) + { + register int i; + for (i = numsize; i > 0; --i) + num[i + empty] = num[i - 1]; + MPN_ZERO (num, empty + 1); + exponent -= empty * BITS_PER_MP_LIMB; + } + else + { + if (bits + empty * BITS_PER_MP_LIMB <= MANT_DIG) + { + /* We make a difference here because the compiler + cannot optimize the `else' case that good and + this reflects all currently used FLOAT types + and GMP implementations. */ + register int i; +#if RETURN_LIMB_SIZE <= 2 + assert (empty == 1); + __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, + BITS_PER_MP_LIMB, 0); +#else + for (i = RETURN_LIMB_SIZE; i > empty; --i) + retval[i] = retval[i - empty]; +#endif +#if RETURN_LIMB_SIZE > 1 + retval[1] = 0; +#endif + for (i = numsize; i > 0; --i) + num[i + empty] = num[i - 1]; + MPN_ZERO (num, empty + 1); + } + else + { + used = MANT_DIG - bits; + if (used >= BITS_PER_MP_LIMB) + { + register int i; + (void) __mpn_lshift (&retval[used + / BITS_PER_MP_LIMB], + retval, RETURN_LIMB_SIZE, + used % BITS_PER_MP_LIMB); + for (i = used / BITS_PER_MP_LIMB; i >= 0; --i) + retval[i] = 0; + } + else if (used > 0) + __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0); + } + bits += empty * BITS_PER_MP_LIMB; + } + } + else + { + int i; + assert (numsize == densize); + for (i = numsize; i > 0; --i) + num[i] = num[i - 1]; + } + + den[densize] = 0; + n0 = num[densize]; + + while (bits <= MANT_DIG) + { + if (n0 == dX) + /* This might over-estimate QUOT, but it's probably not + worth the extra code here to find out. */ + quot = ~(mp_limb_t) 0; + else + { + mp_limb_t r; + + udiv_qrnnd (quot, r, n0, num[densize - 1], dX); + umul_ppmm (n1, n0, d1, quot); + + while (n1 > r || (n1 == r && n0 > num[densize - 2])) + { + --quot; + r += dX; + if (r < dX) /* I.e. "carry in previous addition?" */ + break; + n1 -= n0 < d1; + n0 -= d1; + } + } + + /* Possible optimization: We already have (q * n0) and (1 * n1) + after the calculation of QUOT. Taking advantage of this, we + could make this loop make two iterations less. */ + + cy = __mpn_submul_1 (num, den, densize + 1, quot); + + if (num[densize] != cy) + { + cy = __mpn_add_n (num, num, den, densize); + assert (cy != 0); + --quot; + } + n0 = num[densize] = num[densize - 1]; + for (i = densize - 1; i > 0; --i) + num[i] = num[i - 1]; + + got_limb; + } + + for (i = densize; num[i] == 0 && i >= 0; --i) + ; + return round_and_return (retval, exponent - 1, negative, + quot, BITS_PER_MP_LIMB - 1 - used, + more_bits || i >= 0); + } + } + } + + /* NOTREACHED */ +} + +/* External user entry point. */ + +FLOAT +#ifdef weak_function +weak_function +#endif +STRTOF (nptr, endptr LOCALE_PARAM) + const STRING_TYPE *nptr; + STRING_TYPE **endptr; + LOCALE_PARAM_DECL +{ + return INTERNAL (STRTOF) (nptr, endptr, 0 LOCALE_PARAM); +} diff --git a/src/system/libroot/posix/glibc/stdlib/strtof.c b/src/system/libroot/posix/glibc/stdlib/strtof.c new file mode 100644 index 0000000000..9d070279f8 --- /dev/null +++ b/src/system/libroot/posix/glibc/stdlib/strtof.c @@ -0,0 +1,22 @@ +/* The actual implementation for all floating point sizes is in strtod.c. + These macros tell it to produce the `float' version, `strtof'. */ + +#define FLOAT float +#define FLT FLT +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define STRTOF __strtof_l +#else +# define STRTOF strtof +#endif +#define MPN2FLOAT __mpn_construct_float +#define FLOAT_HUGE_VAL HUGE_VALF +#define SET_MANTISSA(flt, mant) \ + do { union ieee754_float u; \ + u.f = (flt); \ + if ((mant & 0x7fffff) == 0) \ + mant = 0x400000; \ + u.ieee.mantissa = (mant) & 0x7fffff; \ + (flt) = u.f; \ + } while (0) + +#include "strtod.c" diff --git a/src/system/libroot/posix/glibc/stdlib/strtol.c b/src/system/libroot/posix/glibc/stdlib/strtol.c new file mode 100644 index 0000000000..c4da0073a0 --- /dev/null +++ b/src/system/libroot/posix/glibc/stdlib/strtol.c @@ -0,0 +1,556 @@ +/* Convert string representation of a number into an integer value. + Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if HAVE_CONFIG_H +# include +#endif + +#ifdef _LIBC +# define USE_NUMBER_GROUPING +# define STDC_HEADERS +# define HAVE_LIMITS_H +#endif + +#include +#include + +#ifdef HAVE_LIMITS_H +# include +#endif + +#ifdef STDC_HEADERS +# include +# include +# include +# include +#else +# ifndef NULL +# define NULL 0 +# endif +#endif + +#ifdef USE_NUMBER_GROUPING +# include "../locale/localeinfo.h" +#endif + +/* Nonzero if we are defining `strtoul' or `strtoull', operating on + unsigned integers. */ +#ifndef UNSIGNED +# define UNSIGNED 0 +# define INT LONG int +#else +# define INT unsigned LONG int +#endif + +/* Determine the name. */ +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +# if UNSIGNED +# ifdef USE_WIDE_CHAR +# ifdef QUAD +# define strtol __wcstoull_l +# else +# define strtol __wcstoul_l +# endif +# else +# ifdef QUAD +# define strtol __strtoull_l +# else +# define strtol __strtoul_l +# endif +# endif +# else +# ifdef USE_WIDE_CHAR +# ifdef QUAD +# define strtol __wcstoll_l +# else +# define strtol __wcstol_l +# endif +# else +# ifdef QUAD +# define strtol __strtoll_l +# else +# define strtol __strtol_l +# endif +# endif +# endif +#else +# if UNSIGNED +# ifdef USE_WIDE_CHAR +# ifdef QUAD +# define strtol wcstoull +# else +# define strtol wcstoul +# endif +# else +# ifdef QUAD +# define strtol strtoull +# else +# define strtol strtoul +# endif +# endif +# else +# ifdef USE_WIDE_CHAR +# ifdef QUAD +# define strtol wcstoll +# else +# define strtol wcstol +# endif +# else +# ifdef QUAD +# define strtol strtoll +# endif +# endif +# endif +#endif + +/* If QUAD is defined, we are defining `strtoll' or `strtoull', + operating on `long long int's. */ +#ifdef QUAD +# define LONG long long +# define STRTOL_LONG_MIN LONG_LONG_MIN +# define STRTOL_LONG_MAX LONG_LONG_MAX +# define STRTOL_ULONG_MAX ULONG_LONG_MAX +# if __GNUC__ == 2 && __GNUC_MINOR__ < 7 + /* Work around gcc bug with using this constant. */ + static const unsigned long long int maxquad = ULONG_LONG_MAX; +# undef STRTOL_ULONG_MAX +# define STRTOL_ULONG_MAX maxquad +# endif +#else +# define LONG long + +# ifndef ULONG_MAX +# define ULONG_MAX ((unsigned long) ~(unsigned long) 0) +# endif +# ifndef LONG_MAX +# define LONG_MAX ((long int) (ULONG_MAX >> 1)) +# endif +# define STRTOL_LONG_MIN LONG_MIN +# define STRTOL_LONG_MAX LONG_MAX +# define STRTOL_ULONG_MAX ULONG_MAX +#endif + + +/* We use this code also for the extended locale handling where the + function gets as an additional argument the locale which has to be + used. To access the values we have to redefine the _NL_CURRENT + macro. */ +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +# undef _NL_CURRENT +# define _NL_CURRENT(category, item) \ + (current->values[_NL_ITEM_INDEX (item)].string) +# define LOCALE_PARAM , loc +# define LOCALE_PARAM_DECL __locale_t loc; +#else +# define LOCALE_PARAM +# define LOCALE_PARAM_DECL +#endif + +#if defined _LIBC || defined HAVE_WCHAR_H +# include +#endif + +#ifdef USE_WIDE_CHAR +# include +# define L_(Ch) L##Ch +# define UCHAR_TYPE wint_t +# define STRING_TYPE wchar_t +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define ISSPACE(Ch) __iswspace_l ((Ch), loc) +# define ISALPHA(Ch) __iswalpha_l ((Ch), loc) +# define TOUPPER(Ch) __towupper_l ((Ch), loc) +# else +# define ISSPACE(Ch) iswspace (Ch) +# define ISALPHA(Ch) iswalpha (Ch) +# define TOUPPER(Ch) towupper (Ch) +# endif +# else +# if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII) +# define IN_CTYPE_DOMAIN(c) 1 +# else +# define IN_CTYPE_DOMAIN(c) isascii(c) +# endif +# define L_(Ch) Ch +# define UCHAR_TYPE unsigned char +# define STRING_TYPE char +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define ISSPACE(Ch) __isspace_l ((Ch), loc) +# define ISALPHA(Ch) __isalpha_l ((Ch), loc) +# define TOUPPER(Ch) __toupper_l ((Ch), loc) +# else +# define ISSPACE(Ch) (IN_CTYPE_DOMAIN (Ch) && isspace (Ch)) +# define ISALPHA(Ch) (IN_CTYPE_DOMAIN (Ch) && isalpha (Ch)) +# define TOUPPER(Ch) (IN_CTYPE_DOMAIN (Ch) ? toupper (Ch) : (Ch)) +# endif +#endif + +#ifdef __STDC__ +# define INTERNAL(X) INTERNAL1(X) +# define INTERNAL1(X) __##X##_internal +# define WEAKNAME(X) WEAKNAME1(X) +#else +# define INTERNAL(X) __/**/X/**/_internal +#endif + +#ifdef USE_NUMBER_GROUPING +/* This file defines a function to check for correct grouping. */ +# include "grouping.h" +#endif + + + +/* Convert NPTR to an `unsigned long int' or `long int' in base BASE. + If BASE is 0 the base is determined by the presence of a leading + zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal. + If BASE is < 2 or > 36, it is reset to 10. + If ENDPTR is not NULL, a pointer to the character after the last + one converted is stored in *ENDPTR. */ + +INT +INTERNAL (strtol) (nptr, endptr, base, group LOCALE_PARAM) + const STRING_TYPE *nptr; + STRING_TYPE **endptr; + int base; + int group; + LOCALE_PARAM_DECL +{ + int negative; + register unsigned LONG int cutoff; + register unsigned int cutlim; + register unsigned LONG int i; + register const STRING_TYPE *s; + register UCHAR_TYPE c; + const STRING_TYPE *save, *end; + int overflow; +#ifndef USE_WIDE_CHAR + size_t cnt; +#endif + +#ifdef USE_NUMBER_GROUPING +# ifdef USE_IN_EXTENDED_LOCALE_MODEL + struct locale_data *current = loc->__locales[LC_NUMERIC]; +# endif + /* The thousands character of the current locale. */ +# ifdef USE_WIDE_CHAR + wchar_t thousands = L'\0'; +# else + const char *thousands = NULL; + size_t thousands_len = 0; +# endif + /* The numeric grouping specification of the current locale, + in the format described in . */ + const char *grouping; + + if (__builtin_expect (group, 0)) + { + grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); + if (*grouping <= 0 || *grouping == CHAR_MAX) + grouping = NULL; + else + { + /* Figure out the thousands separator character. */ +# ifdef USE_WIDE_CHAR +# ifdef _LIBC + thousands = _NL_CURRENT_WORD (LC_NUMERIC, + _NL_NUMERIC_THOUSANDS_SEP_WC); +# endif + if (thousands == L'\0') + grouping = NULL; +# else +# ifdef _LIBC + thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP); +# endif + if (*thousands == '\0') + { + thousands = NULL; + grouping = NULL; + } +# endif + } + } + else + grouping = NULL; +#endif + + if (base < 0 || base == 1 || base > 36 || nptr == NULL) + { + __set_errno (EINVAL); + return 0; + } + + save = s = nptr; + + /* Skip white space. */ + while (ISSPACE (*s)) + ++s; + if (__builtin_expect (*s == L_('\0'), 0)) + goto noconv; + + /* Check for a sign. */ + negative = 0; + if (*s == L_('-')) + { + negative = 1; + ++s; + } + else if (*s == L_('+')) + ++s; + + /* Recognize number prefix and if BASE is zero, figure it out ourselves. */ + if (*s == L_('0')) + { + if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X')) + { + s += 2; + base = 16; + } + else if (base == 0) + base = 8; + } + else if (base == 0) + base = 10; + + /* Save the pointer so we can check later if anything happened. */ + save = s; + +#ifdef USE_NUMBER_GROUPING + if (base != 10) + grouping = NULL; + + if (__builtin_expect (grouping != NULL, 0)) + { +# ifndef USE_WIDE_CHAR + thousands_len = strlen (thousands); +# endif + + /* Find the end of the digit string and check its grouping. */ + end = s; + if ( +# ifdef USE_WIDE_CHAR + *s != thousands +# else + ({ for (cnt = 0; cnt < thousands_len; ++cnt) + if (thousands[cnt] != end[cnt]) + break; + cnt < thousands_len; }) +# endif + ) + { + for (c = *end; c != L_('\0'); c = *++end) + if (((wchar_t) c < L_('0') || (wchar_t) c > L_('9')) +# ifdef USE_WIDE_CHAR + && c != thousands +# else + && ({ for (cnt = 0; cnt < thousands_len; ++cnt) + if (thousands[cnt] != end[cnt]) + break; + cnt < thousands_len; }) +# endif + && (!ISALPHA (c) + || (int) (TOUPPER (c) - L_('A') + 10) >= base)) + break; + + end = correctly_grouped_prefix (s, end, thousands, grouping); + } + } + else +#endif + end = NULL; + + cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base; + cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base; + + overflow = 0; + i = 0; + c = *s; + if (sizeof (long int) != sizeof (LONG int)) + { + unsigned long int j = 0; + unsigned long int jmax = ULONG_MAX / base; + + for (;c != L_('\0'); c = *++s) + { + if (s == end) + break; + if (c >= L_('0') && c <= L_('9')) + c -= L_('0'); +#ifdef USE_NUMBER_GROUPING +# ifdef USE_WIDE_CHAR + else if (grouping && c == thousands) + continue; +# else + else if (thousands_len) + { + for (cnt = 0; cnt < thousands_len; ++cnt) + if (thousands[cnt] != s[cnt]) + break; + if (cnt == thousands_len) + { + s += thousands_len - 1; + continue; + } + if (ISALPHA (c)) + c = TOUPPER (c) - L_('A') + 10; + else + break; + } +# endif +#endif + else if (ISALPHA (c)) + c = TOUPPER (c) - L_('A') + 10; + else + break; + if ((int) c >= base) + break; + /* Note that we never can have an overflow. */ + else if (j >= jmax) + { + /* We have an overflow. Now use the long representation. */ + i = (unsigned LONG int) j; + goto use_long; + } + else + j = j * (unsigned long int) base + c; + } + + i = (unsigned LONG int) j; + } + else + for (;c != L_('\0'); c = *++s) + { + if (s == end) + break; + if (c >= L_('0') && c <= L_('9')) + c -= L_('0'); +#ifdef USE_NUMBER_GROUPING +# ifdef USE_WIDE_CHAR + else if (grouping && c == thousands) + continue; +# else + else if (thousands_len) + { + for (cnt = 0; cnt < thousands_len; ++cnt) + if (thousands[cnt] != s[cnt]) + break; + if (cnt == thousands_len) + { + s += thousands_len - 1; + continue; + } + if (ISALPHA (c)) + c = TOUPPER (c) - L_('A') + 10; + else + break; + } +# endif +#endif + else if (ISALPHA (c)) + c = TOUPPER (c) - L_('A') + 10; + else + break; + if ((int) c >= base) + break; + /* Check for overflow. */ + if (i > cutoff || (i == cutoff && c > cutlim)) + overflow = 1; + else + { + use_long: + i *= (unsigned LONG int) base; + i += c; + } + } + + /* Check if anything actually happened. */ + if (s == save) + goto noconv; + + /* Store in ENDPTR the address of one character + past the last character we converted. */ + if (endptr != NULL) + *endptr = (STRING_TYPE *) s; + +#if !UNSIGNED + /* Check for a value that is within the range of + `unsigned LONG int', but outside the range of `LONG int'. */ + if (overflow == 0 + && i > (negative + ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1 + : (unsigned LONG int) STRTOL_LONG_MAX)) + overflow = 1; +#endif + + if (__builtin_expect (overflow, 0)) + { + __set_errno (ERANGE); +#if UNSIGNED + return STRTOL_ULONG_MAX; +#else + return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX; +#endif + } + + /* Return the result of the appropriate sign. */ + return negative ? -i : i; + +noconv: + /* We must handle a special case here: the base is 0 or 16 and the + first two characters are '0' and 'x', but the rest are no + hexadecimal digits. This is no error case. We return 0 and + ENDPTR points to the `x`. */ + if (endptr != NULL) + { + if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X') + && save[-2] == L_('0')) + *endptr = (STRING_TYPE *) &save[-1]; + else + /* There was no number to convert. */ + *endptr = (STRING_TYPE *) nptr; + } + + return 0L; +} + +/* External user entry point. */ + +#if _LIBC - 0 == 0 +# undef PARAMS +# if defined (__STDC__) && __STDC__ +# define PARAMS(Args) Args +# else +# define PARAMS(Args) () +# endif + +/* Prototype. */ +INT strtol PARAMS ((const STRING_TYPE *nptr, STRING_TYPE **endptr, int base)); +#endif + + +INT +#ifdef weak_function +weak_function +#endif +strtol (nptr, endptr, base LOCALE_PARAM) + const STRING_TYPE *nptr; + STRING_TYPE **endptr; + int base; + LOCALE_PARAM_DECL +{ + return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM); +} diff --git a/src/system/libroot/posix/glibc/stdlib/strtold.c b/src/system/libroot/posix/glibc/stdlib/strtold.c new file mode 100644 index 0000000000..f6f6eb9103 --- /dev/null +++ b/src/system/libroot/posix/glibc/stdlib/strtold.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* There is no `long double' type, use the `double' implementations. */ +long double +__strtold_internal (const char *nptr, char **endptr, int group) +{ + return __strtod_internal (nptr, endptr, group); +} + +long double +strtold (const char *nptr, char **endptr) +{ + return __strtod_internal (nptr, endptr, 0); +} diff --git a/src/system/libroot/posix/glibc/stdlib/strtoll.c b/src/system/libroot/posix/glibc/stdlib/strtoll.c new file mode 100644 index 0000000000..847d860cb5 --- /dev/null +++ b/src/system/libroot/posix/glibc/stdlib/strtoll.c @@ -0,0 +1,2 @@ +#define QUAD 1 +#include "strtol.c" diff --git a/src/system/libroot/posix/glibc/stdlib/strtoul.c b/src/system/libroot/posix/glibc/stdlib/strtoul.c new file mode 100644 index 0000000000..b263cd3cab --- /dev/null +++ b/src/system/libroot/posix/glibc/stdlib/strtoul.c @@ -0,0 +1,2 @@ +#define UNSIGNED 1 +#include "strtol.c" diff --git a/src/system/libroot/posix/glibc/stdlib/strtoull.c b/src/system/libroot/posix/glibc/stdlib/strtoull.c new file mode 100644 index 0000000000..7b276ba0bd --- /dev/null +++ b/src/system/libroot/posix/glibc/stdlib/strtoull.c @@ -0,0 +1,3 @@ +#define UNSIGNED 1 +#define QUAD 1 +#include "strtol.c" diff --git a/src/system/libroot/posix/glibc/wcsmbs/Depend b/src/system/libroot/posix/glibc/wcsmbs/Depend new file mode 100644 index 0000000000..f3e1156a4e --- /dev/null +++ b/src/system/libroot/posix/glibc/wcsmbs/Depend @@ -0,0 +1 @@ +localedata diff --git a/src/system/libroot/posix/glibc/wcsmbs/Jamfile b/src/system/libroot/posix/glibc/wcsmbs/Jamfile index c4fba8f817..5380f28cb6 100644 --- a/src/system/libroot/posix/glibc/wcsmbs/Jamfile +++ b/src/system/libroot/posix/glibc/wcsmbs/Jamfile @@ -24,6 +24,13 @@ for architectureObject in [ MultiArchSubDirSetup ] { MergeObject <$(architecture)>posix_gnu_wcsmbs.o : wcsmbsload.c + wcstod.c + wcstof.c + wcstol.c + wcstoll.c + wcstold.c + wcstoul.c + wcstoull.c ; } } diff --git a/src/system/libroot/posix/glibc/wcsmbs/Versions b/src/system/libroot/posix/glibc/wcsmbs/Versions new file mode 100644 index 0000000000..6f2e72eb2a --- /dev/null +++ b/src/system/libroot/posix/glibc/wcsmbs/Versions @@ -0,0 +1,27 @@ +libc { + GLIBC_2.0 { + # functions used in inline functions or macros + __wcsto*_internal; __mbrlen; __mbrtowc; + + # b* + btowc; + + # w* + wcpcpy; wcpncpy; wcrtomb; wcscat; wcschr; wcscmp; wcscoll; + wcscpy; wcscspn; wcsdup; wcslen; wcsncat; wcsncmp; + wcsncpy; wcsnrtombs; wcspbrk; wcsrchr; wcsrtombs; wcsspn; wcsstr; + wcstod; wcstof; wcstok; wcstol; wcstold; wcstoq; wcstoul; + wcstouq; wcswidth; wcsxfrm; wctob; + + wmemchr; wmemcmp; wmemcpy; wmemmove; wmemset; + } + GLIBC_2.1 { + # w* + wcscasecmp; wcsncasecmp; wcsnlen; wcstoll; + wcstoimax; wcstoumax; wcstoull; wcswcs; wmemrtombs; wmemrtowcs; + } + GLIBC_2.2 { + # w* + wcschrnul; wmempcpy; + } +} diff --git a/src/system/libroot/posix/glibc/wcsmbs/wcstod.c b/src/system/libroot/posix/glibc/wcsmbs/wcstod.c new file mode 100644 index 0000000000..5a39091c25 --- /dev/null +++ b/src/system/libroot/posix/glibc/wcsmbs/wcstod.c @@ -0,0 +1,25 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* The actual implementation for all floating point sizes is in strtod.c. */ + +#define USE_WIDE_CHAR 1 + +#include diff --git a/src/system/libroot/posix/glibc/wcsmbs/wcstof.c b/src/system/libroot/posix/glibc/wcsmbs/wcstof.c new file mode 100644 index 0000000000..02f91ef904 --- /dev/null +++ b/src/system/libroot/posix/glibc/wcsmbs/wcstof.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* The actual implementation for all floating point sizes is in strtod.c. + These macros tell it to produce the `float' version, `wcstof'. */ + +#define FLOAT float +#define FLT FLT +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define STRTOF __wcstof_l +#else +# define STRTOF wcstof +#endif +#define MPN2FLOAT __mpn_construct_float +#define FLOAT_HUGE_VAL HUGE_VALF +#define USE_WIDE_CHAR 1 +#define SET_MANTISSA(flt, mant) \ + do { union ieee754_float u; \ + u.f = (flt); \ + if ((mant & 0x7fffff) == 0) \ + mant = 0x400000; \ + u.ieee.mantissa = (mant) & 0x7fffff; \ + (flt) = u.f; \ + } while (0) + +#include diff --git a/src/system/libroot/posix/glibc/wcsmbs/wcstol.c b/src/system/libroot/posix/glibc/wcsmbs/wcstol.c new file mode 100644 index 0000000000..b238d04b19 --- /dev/null +++ b/src/system/libroot/posix/glibc/wcsmbs/wcstol.c @@ -0,0 +1,23 @@ +/* Function to parse a `long int' from text. + Copyright (C) 1996, 1997, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define USE_WIDE_CHAR 1 + +#include diff --git a/src/system/libroot/posix/glibc/wcsmbs/wcstold.c b/src/system/libroot/posix/glibc/wcsmbs/wcstold.c new file mode 100644 index 0000000000..5c58aa69e6 --- /dev/null +++ b/src/system/libroot/posix/glibc/wcsmbs/wcstold.c @@ -0,0 +1,62 @@ +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#ifndef __NO_LONG_DOUBLE_MATH +/* The actual implementation for all floating point sizes is in strtod.c. + These macros tell it to produce the `long double' version, `wcstold'. */ + +# define FLOAT long double +# define FLT LDBL +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define STRTOF __wcstold_l +# else +# define STRTOF wcstold +# endif +# define MPN2FLOAT __mpn_construct_long_double +# define FLOAT_HUGE_VAL HUGE_VALL +# define USE_WIDE_CHAR 1 +# define SET_MANTISSA(flt, mant) \ + do { union ieee854_long_double u; \ + u.d = (flt); \ + if ((mant & 0x7fffffffffffffffULL) == 0) \ + mant = 0x4000000000000000ULL; \ + u.ieee.mantissa0 = (((mant) >> 32) & 0x7fffffff) | 0x80000000; \ + u.ieee.mantissa1 = (mant) & 0xffffffff; \ + (flt) = u.d; \ + } while (0) + +# include +#else +/* There is no `long double' type, use the `double' implementations. */ +long double +__wcstold_internal (const wchar_t *nptr, wchar_t **endptr, int group) +{ + return __wcstod_internal (nptr, endptr, group); +} +libc_hidden_def (__wcstold_internal) + +long double +wcstold (const wchar_t *nptr, wchar_t **endptr) +{ + return __wcstod_internal (nptr, endptr, 0); +} +#endif diff --git a/src/system/libroot/posix/glibc/wcsmbs/wcstoll.c b/src/system/libroot/posix/glibc/wcsmbs/wcstoll.c new file mode 100644 index 0000000000..b666762da4 --- /dev/null +++ b/src/system/libroot/posix/glibc/wcsmbs/wcstoll.c @@ -0,0 +1,25 @@ +/* Function to parse a `long long int' from text. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define QUAD 1 + +#include "wcstol.c" + +weak_alias (wcstoll, wcstoq) diff --git a/src/system/libroot/posix/glibc/wcsmbs/wcstoul.c b/src/system/libroot/posix/glibc/wcsmbs/wcstoul.c new file mode 100644 index 0000000000..f25f7a9bff --- /dev/null +++ b/src/system/libroot/posix/glibc/wcsmbs/wcstoul.c @@ -0,0 +1,23 @@ +/* Function to parse an `unsigned long int' from text. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define UNSIGNED 1 + +#include "wcstol.c" diff --git a/src/system/libroot/posix/glibc/wcsmbs/wcstoull.c b/src/system/libroot/posix/glibc/wcsmbs/wcstoull.c new file mode 100644 index 0000000000..a69a103515 --- /dev/null +++ b/src/system/libroot/posix/glibc/wcsmbs/wcstoull.c @@ -0,0 +1,25 @@ +/* Function to parse an `unsigned long long int' from text. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define QUAD 1 + +#include "wcstoul.c" + +weak_alias (wcstoull, wcstouq) diff --git a/src/system/libroot/posix/musl/Jamfile b/src/system/libroot/posix/musl/Jamfile index 5321f960e4..493fa49e1e 100644 --- a/src/system/libroot/posix/musl/Jamfile +++ b/src/system/libroot/posix/musl/Jamfile @@ -10,7 +10,6 @@ for architectureObject in [ MultiArchSubDirSetup ] { <$(architecture)>posix_musl_crypt.o <$(architecture)>posix_musl_complex.o <$(architecture)>posix_musl_dirent.o - <$(architecture)>posix_musl_internal.o <$(architecture)>posix_musl_math.o <$(architecture)>posix_musl_misc.o <$(architecture)>posix_musl_prng.o @@ -31,7 +30,6 @@ for arch in $(TARGET_ARCHS) { HaikuSubInclude crypt ; HaikuSubInclude complex ; HaikuSubInclude dirent ; -HaikuSubInclude internal ; HaikuSubInclude misc ; HaikuSubInclude prng ; HaikuSubInclude regex ; diff --git a/src/system/libroot/posix/musl/internal/Jamfile b/src/system/libroot/posix/musl/internal/Jamfile deleted file mode 100644 index 9957f89e8f..0000000000 --- a/src/system/libroot/posix/musl/internal/Jamfile +++ /dev/null @@ -1,17 +0,0 @@ -SubDir HAIKU_TOP src system libroot posix musl internal ; - -SubDirSysHdrs [ FDirName $(SUBDIR) .. include ] ; -UseHeaders [ FDirName $(SUBDIR) .. internal ] ; - -local architectureObject ; -for architectureObject in [ MultiArchSubDirSetup ] { - on $(architectureObject) { - local architecture = $(TARGET_PACKAGING_ARCH) ; - - MergeObject <$(architecture)>posix_musl_internal.o : - floatscan.c - intscan.c - shgetc.c - ; - } -} diff --git a/src/system/libroot/posix/musl/internal/floatscan.c b/src/system/libroot/posix/musl/internal/floatscan.c deleted file mode 100644 index 661e72b859..0000000000 --- a/src/system/libroot/posix/musl/internal/floatscan.c +++ /dev/null @@ -1,509 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "shgetc.h" -#include "floatscan.h" - -#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 - -#define LD_B1B_DIG 2 -#define LD_B1B_MAX 9007199, 254740991 -#define KMAX 128 - -#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 - -#define LD_B1B_DIG 3 -#define LD_B1B_MAX 18, 446744073, 709551615 -#define KMAX 2048 - -#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 - -#define LD_B1B_DIG 4 -#define LD_B1B_MAX 10384593, 717069655, 257060992, 658440191 -#define KMAX 2048 - -#else -#error Unsupported long double representation -#endif - -#define MASK (KMAX-1) - -static long long scanexp(FILE *f, int pok) -{ - int c; - int x; - long long y; - int neg = 0; - - c = shgetc(f); - if (c=='+' || c=='-') { - neg = (c=='-'); - c = shgetc(f); - if (c-'0'>=10U && pok) shunget(f); - } - if (c-'0'>=10U) { - shunget(f); - return LLONG_MIN; - } - for (x=0; c-'0'<10U && x=0) { - shunget(f); - } - if (!gotdig) { - errno = EINVAL; - shlim(f, 0); - return 0; - } - - /* Handle zero specially to avoid nasty special cases later */ - if (!x[0]) return sign * 0.0; - - /* Optimize small integers (w/no exponent) and over/under-flow */ - if (lrp==dc && dc<10 && (bits>30 || x[0]>>bits==0)) - return sign * (long double)x[0]; - if (lrp > -emin/2) { - errno = ERANGE; - return sign * LDBL_MAX * LDBL_MAX; - } - if (lrp < emin-2*LDBL_MANT_DIG) { - errno = ERANGE; - return sign * LDBL_MIN * LDBL_MIN; - } - - /* Align incomplete final B1B digit */ - if (j) { - for (; j<9; j++) x[k]*=10; - k++; - j=0; - } - - a = 0; - z = k; - e2 = 0; - rp = lrp; - - /* Optimize small to mid-size integers (even in exp. notation) */ - if (lnz<9 && lnz<=rp && rp < 18) { - if (rp == 9) return sign * (long double)x[0]; - if (rp < 9) return sign * (long double)x[0] / p10s[8-rp]; - { - int bitlim = bits-3*(int)(rp-9); - if (bitlim>30 || x[0]>>bitlim==0) - return sign * (long double)x[0] * p10s[rp-10]; - } - } - - /* Drop trailing zeros */ - for (; !x[z-1]; z--); - - /* Align radix point to B1B digit boundary */ - if (rp % 9) { - int rpm9 = rp>=0 ? rp%9 : rp%9+9; - int p10 = p10s[8-rpm9]; - uint32_t carry = 0; - for (k=a; k!=z; k++) { - uint32_t tmp = x[k] % p10; - x[k] = x[k]/p10 + carry; - carry = 1000000000/p10 * tmp; - if (k==a && !x[k]) { - a = (a+1 & MASK); - rp -= 9; - } - } - if (carry) x[z++] = carry; - rp += 9-rpm9; - } - - /* Upscale until desired number of bits are left of radix point */ - while (rp < 9*LD_B1B_DIG || (rp == 9*LD_B1B_DIG && x[a] 1000000000) { - carry = tmp / 1000000000; - x[k] = tmp % 1000000000; - } else { - carry = 0; - x[k] = tmp; - } - if (k==(z-1 & MASK) && k!=a && !x[k]) z = k; - if (k==a) break; - } - if (carry) { - rp += 9; - a = (a-1 & MASK); - if (a == z) { - z = (z-1 & MASK); - x[z-1 & MASK] |= x[z]; - } - x[a] = carry; - } - } - - /* Downscale until exactly number of bits are left of radix point */ - for (;;) { - uint32_t carry = 0; - int sh = 1; - for (i=0; i th[i]) break; - } - if (i==LD_B1B_DIG && rp==9*LD_B1B_DIG) break; - /* FIXME: find a way to compute optimal sh */ - if (rp > 9+9*LD_B1B_DIG) sh = 9; - e2 += sh; - for (k=a; k!=z; k=(k+1 & MASK)) { - uint32_t tmp = x[k] & (1<>sh) + carry; - carry = (1000000000>>sh) * tmp; - if (k==a && !x[k]) { - a = (a+1 & MASK); - i--; - rp -= 9; - } - } - if (carry) { - if ((z+1 & MASK) != a) { - x[z] = carry; - z = (z+1 & MASK); - } else x[z-1 & MASK] |= 1; - } - } - - /* Assemble desired bits into floating point variable */ - for (y=i=0; i LDBL_MANT_DIG+e2-emin) { - bits = LDBL_MANT_DIG+e2-emin; - if (bits<0) bits=0; - denormal = 1; - } - - /* Calculate bias term to force rounding, move out lower bits */ - if (bits < LDBL_MANT_DIG) { - bias = copysignl(scalbn(1, 2*LDBL_MANT_DIG-bits-1), y); - frac = fmodl(y, scalbn(1, LDBL_MANT_DIG-bits)); - y -= frac; - y += bias; - } - - /* Process tail of decimal input so it can affect rounding */ - if ((a+i & MASK) != z) { - uint32_t t = x[a+i & MASK]; - if (t < 500000000 && (t || (a+i+1 & MASK) != z)) - frac += 0.25*sign; - else if (t > 500000000) - frac += 0.75*sign; - else if (t == 500000000) { - if ((a+i+1 & MASK) == z) - frac += 0.5*sign; - else - frac += 0.75*sign; - } - if (LDBL_MANT_DIG-bits >= 2 && !fmodl(frac, 1)) - frac++; - } - - y += frac; - y -= bias; - - if ((e2+LDBL_MANT_DIG & INT_MAX) > emax-5) { - if (fabsl(y) >= 2/LDBL_EPSILON) { - if (denormal && bits==LDBL_MANT_DIG+e2-emin) - denormal = 0; - y *= 0.5; - e2++; - } - if (e2+LDBL_MANT_DIG>emax || (denormal && frac)) - errno = ERANGE; - } - - return scalbnl(y, e2); -} - -static long double hexfloat(FILE *f, int bits, int emin, int sign, int pok) -{ - uint32_t x = 0; - long double y = 0; - long double scale = 1; - long double bias = 0; - int gottail = 0, gotrad = 0, gotdig = 0; - long long rp = 0; - long long dc = 0; - long long e2 = 0; - int d; - int c; - - c = shgetc(f); - - /* Skip leading zeros */ - for (; c=='0'; c = shgetc(f)) gotdig = 1; - - if (c=='.') { - gotrad = 1; - c = shgetc(f); - /* Count zeros after the radix point before significand */ - for (rp=0; c=='0'; c = shgetc(f), rp--) gotdig = 1; - } - - for (; c-'0'<10U || (c|32)-'a'<6U || c=='.'; c = shgetc(f)) { - if (c=='.') { - if (gotrad) break; - rp = dc; - gotrad = 1; - } else { - gotdig = 1; - if (c > '9') d = (c|32)+10-'a'; - else d = c-'0'; - if (dc<8) { - x = x*16 + d; - } else if (dc < LDBL_MANT_DIG/4+1) { - y += d*(scale/=16); - } else if (d && !gottail) { - y += 0.5*scale; - gottail = 1; - } - dc++; - } - } - if (!gotdig) { - shunget(f); - if (pok) { - shunget(f); - if (gotrad) shunget(f); - } else { - shlim(f, 0); - } - return sign * 0.0; - } - if (!gotrad) rp = dc; - while (dc<8) x *= 16, dc++; - if ((c|32)=='p') { - e2 = scanexp(f, pok); - if (e2 == LLONG_MIN) { - if (pok) { - shunget(f); - } else { - shlim(f, 0); - return 0; - } - e2 = 0; - } - } else { - shunget(f); - } - e2 += 4*rp - 32; - - if (!x) return sign * 0.0; - if (e2 > -emin) { - errno = ERANGE; - return sign * LDBL_MAX * LDBL_MAX; - } - if (e2 < emin-2*LDBL_MANT_DIG) { - errno = ERANGE; - return sign * LDBL_MIN * LDBL_MIN; - } - - while (x < 0x80000000) { - if (y>=0.5) { - x += x + 1; - y += y - 1; - } else { - x += x; - y += y; - } - e2--; - } - - if (bits > 32+e2-emin) { - bits = 32+e2-emin; - if (bits<0) bits=0; - } - - if (bits < LDBL_MANT_DIG) - bias = copysignl(scalbn(1, 32+LDBL_MANT_DIG-bits-1), sign); - - if (bits<32 && y && !(x&1)) x++, y=0; - - y = bias + sign*(long double)x + sign*y; - y -= bias; - - if (!y) errno = ERANGE; - - return scalbnl(y, e2); -} - -long double __floatscan(FILE *f, int prec, int pok) -{ - int sign = 1; - size_t i; - int bits; - int emin; - int c; - - switch (prec) { - case 0: - bits = FLT_MANT_DIG; - emin = FLT_MIN_EXP-bits; - break; - case 1: - bits = DBL_MANT_DIG; - emin = DBL_MIN_EXP-bits; - break; - case 2: - bits = LDBL_MANT_DIG; - emin = LDBL_MIN_EXP-bits; - break; - default: - return 0; - } - - while (isspace((c=shgetc(f)))); - - if (c=='+' || c=='-') { - sign -= 2*(c=='-'); - c = shgetc(f); - } - - for (i=0; i<8 && (c|32)=="infinity"[i]; i++) - if (i<7) c = shgetc(f); - if (i==3 || i==8 || (i>3 && pok)) { - if (i!=8) { - shunget(f); - if (pok) for (; i>3; i--) shunget(f); - } - return sign * INFINITY; - } - if (!i) for (i=0; i<3 && (c|32)=="nan"[i]; i++) - if (i<2) c = shgetc(f); - if (i==3) { - if (shgetc(f) != '(') { - shunget(f); - return NAN; - } - for (i=1; ; i++) { - c = shgetc(f); - if (c-'0'<10U || c-'A'<26U || c-'a'<26U || c=='_') - continue; - if (c==')') return NAN; - shunget(f); - if (!pok) { - errno = EINVAL; - shlim(f, 0); - return 0; - } - while (i--) shunget(f); - return NAN; - } - return NAN; - } - - if (i) { - shunget(f); - errno = EINVAL; - shlim(f, 0); - return 0; - } - - if (c=='0') { - c = shgetc(f); - if ((c|32) == 'x') - return hexfloat(f, bits, emin, sign, pok); - shunget(f); - c = '0'; - } - - return decfloat(f, c, bits, emin, sign, pok); -} diff --git a/src/system/libroot/posix/musl/internal/floatscan.h b/src/system/libroot/posix/musl/internal/floatscan.h deleted file mode 100644 index f2b1dcf459..0000000000 --- a/src/system/libroot/posix/musl/internal/floatscan.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef FLOATSCAN_H -#define FLOATSCAN_H - -#include - -hidden long double __floatscan(FILE *, int, int); - -#endif diff --git a/src/system/libroot/posix/musl/internal/intscan.c b/src/system/libroot/posix/musl/internal/intscan.c deleted file mode 100644 index a4a5ae8612..0000000000 --- a/src/system/libroot/posix/musl/internal/intscan.c +++ /dev/null @@ -1,100 +0,0 @@ -#include -#include -#include -#include "shgetc.h" - -/* Lookup table for digit values. -1==255>=36 -> invalid */ -static const unsigned char table[] = { -1, --1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, --1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, --1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, --1,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,-1,-1,-1,-1,-1, --1,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,-1,-1,-1,-1,-1, --1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, --1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, --1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, --1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, --1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, --1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, --1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, --1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -}; - -unsigned long long __intscan(FILE *f, unsigned base, int pok, unsigned long long lim) -{ - const unsigned char *val = table+1; - int c, neg=0; - unsigned x; - unsigned long long y; - if (base > 36 || base == 1) { - errno = EINVAL; - return 0; - } - while (isspace((c=shgetc(f)))); - if (c=='+' || c=='-') { - neg = -(c=='-'); - c = shgetc(f); - } - if ((base == 0 || base == 16) && c=='0') { - c = shgetc(f); - if ((c|32)=='x') { - c = shgetc(f); - if (val[c]>=16) { - shunget(f); - if (pok) shunget(f); - else shlim(f, 0); - return 0; - } - base = 16; - } else if (base == 0) { - base = 8; - } - } else { - if (base == 0) base = 10; - if (val[c] >= base) { - shunget(f); - shlim(f, 0); - errno = EINVAL; - return 0; - } - } - if (base == 10) { - for (x=0; c-'0'<10U && x<=UINT_MAX/10-1; c=shgetc(f)) - x = x*10 + (c-'0'); - for (y=x; c-'0'<10U && y<=ULLONG_MAX/10 && 10*y<=ULLONG_MAX-(c-'0'); c=shgetc(f)) - y = y*10 + (c-'0'); - if (c-'0'>=10U) goto done; - } else if (!(base & base-1)) { - int bs = "\0\1\2\4\7\3\6\5"[(0x17*base)>>5&7]; - for (x=0; val[c]>bs; c=shgetc(f)) - y = y<=lim) { - if (!(lim&1) && !neg) { - errno = ERANGE; - return lim-1; - } else if (y>lim) { - errno = ERANGE; - return lim; - } - } - return (y^neg)-neg; -} diff --git a/src/system/libroot/posix/musl/internal/intscan.h b/src/system/libroot/posix/musl/internal/intscan.h deleted file mode 100644 index ccf9f112a9..0000000000 --- a/src/system/libroot/posix/musl/internal/intscan.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef INTSCAN_H -#define INTSCAN_H - -#include - -hidden unsigned long long __intscan(FILE *, unsigned, int, unsigned long long); - -#endif diff --git a/src/system/libroot/posix/musl/internal/shgetc.c b/src/system/libroot/posix/musl/internal/shgetc.c deleted file mode 100644 index 422faa9869..0000000000 --- a/src/system/libroot/posix/musl/internal/shgetc.c +++ /dev/null @@ -1,61 +0,0 @@ -#include "shgetc.h" - -#ifdef __HAIKU__ -#define __toread toread -static int __toread(FILE *f) -{ - f->mode |= f->mode-1; - if (f->wpos != f->wbase) f->write(f, 0, 0); - f->wpos = f->wbase = f->wend = 0; - if (f->flags & F_NORD) { - f->flags |= F_ERR; - return EOF; - } - f->rpos = f->rend = f->buf + f->buf_size; - return (f->flags & F_EOF) ? EOF : 0; -} - -#define __uflow uflow -static int __uflow(FILE *f) -{ - unsigned char c; - if (!__toread(f) && f->read(f, &c, 1)==1) return c; - return EOF; -} -#endif - -/* The shcnt field stores the number of bytes read so far, offset by - * the value of buf-rpos at the last function call (__shlim or __shgetc), - * so that between calls the inline shcnt macro can add rpos-buf to get - * the actual count. */ - -void __shlim(FILE *f, off_t lim) -{ - f->shlim = lim; - f->shcnt = f->buf - f->rpos; - /* If lim is nonzero, rend must be a valid pointer. */ - if (lim && f->rend - f->rpos > lim) - f->shend = f->rpos + lim; - else - f->shend = f->rend; -} - -int __shgetc(FILE *f) -{ - int c; - off_t cnt = shcnt(f); - if (f->shlim && cnt >= f->shlim || (c=__uflow(f)) < 0) { - f->shcnt = f->buf - f->rpos + cnt; - f->shend = f->rpos; - f->shlim = -1; - return EOF; - } - cnt++; - if (f->shlim && f->rend - f->rpos > f->shlim - cnt) - f->shend = f->rpos + (f->shlim - cnt); - else - f->shend = f->rend; - f->shcnt = f->buf - f->rpos + cnt; - if (f->rpos <= f->buf) f->rpos[-1] = c; - return c; -} diff --git a/src/system/libroot/posix/musl/internal/shgetc.h b/src/system/libroot/posix/musl/internal/shgetc.h deleted file mode 100644 index 9435381a61..0000000000 --- a/src/system/libroot/posix/musl/internal/shgetc.h +++ /dev/null @@ -1,32 +0,0 @@ -#include "stdio_impl.h" - -/* Scan helper "stdio" functions for use by scanf-family and strto*-family - * functions. These accept either a valid stdio FILE, or a minimal pseudo - * FILE whose buffer pointers point into a null-terminated string. In the - * latter case, the sh_fromstring macro should be used to setup the FILE; - * the rest of the structure can be left uninitialized. - * - * To begin using these functions, shlim must first be called on the FILE - * to set a field width limit, or 0 for no limit. For string pseudo-FILEs, - * a nonzero limit is not valid and produces undefined behavior. After that, - * shgetc, shunget, and shcnt are valid as long as no other stdio functions - * are called on the stream. - * - * When used with a real FILE object, shunget has only one byte of pushback - * available. Further shunget (up to a limit of the stdio UNGET buffer size) - * will adjust the position but will not restore the data to be read again. - * This functionality is needed for the wcsto*-family functions, where it's - * okay because the FILE will be discarded immediately anyway. When used - * with string pseudo-FILEs, shunget has unlimited pushback, back to the - * beginning of the string. */ - -hidden void __shlim(FILE *, off_t); -hidden int __shgetc(FILE *); - -#define shcnt(f) ((f)->shcnt + ((f)->rpos - (f)->buf)) -#define shlim(f, lim) __shlim((f), (lim)) -#define shgetc(f) (((f)->rpos != (f)->shend) ? *(f)->rpos++ : __shgetc(f)) -#define shunget(f) ((f)->shlim>=0 ? (void)(f)->rpos-- : (void)0) - -#define sh_fromstring(f, s) \ - ((f)->buf = (f)->rpos = (void *)(s), (f)->rend = (void*)-1) diff --git a/src/system/libroot/posix/musl/internal/stdio_impl.h b/src/system/libroot/posix/musl/internal/stdio_impl.h deleted file mode 100644 index ee88e26faf..0000000000 --- a/src/system/libroot/posix/musl/internal/stdio_impl.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef _STDIO_IMPL_H -#define _STDIO_IMPL_H - -#include -#include "features.h" - -#define UNGET 8 - -#define FFINALLOCK(f) ((f)->lock>=0 ? __lockfile((f)) : 0) -#define FLOCK(f) int __need_unlock = ((f)->lock>=0 ? __lockfile((f)) : 0) -#define FUNLOCK(f) do { if (__need_unlock) __unlockfile((f)); } while (0) - -#define F_PERM 1 -#define F_NORD 4 -#define F_NOWR 8 -#define F_EOF 16 -#define F_ERR 32 -#define F_SVB 64 -#define F_APP 128 - -struct _IO_FILE { - unsigned flags; - unsigned char *rpos, *rend; - int (*close)(FILE *); - unsigned char *wend, *wpos; - unsigned char *mustbezero_1; - unsigned char *wbase; - size_t (*read)(FILE *, unsigned char *, size_t); - size_t (*write)(FILE *, const unsigned char *, size_t); - off_t (*seek)(FILE *, off_t, int); - unsigned char *buf; - size_t buf_size; - FILE *prev, *next; - int fd; - int pipe_pid; - long lockcount; - int mode; - volatile int lock; - int lbf; - void *cookie; - off_t off; - char *getln_buf; - void *mustbezero_2; - unsigned char *shend; - off_t shlim, shcnt; - FILE *prev_locked, *next_locked; - struct __locale_struct *locale; -}; - -extern hidden FILE *volatile __stdin_used; -extern hidden FILE *volatile __stdout_used; -extern hidden FILE *volatile __stderr_used; - -hidden int __lockfile(FILE *); -hidden void __unlockfile(FILE *); - -hidden size_t __stdio_read(FILE *, unsigned char *, size_t); -hidden size_t __stdio_write(FILE *, const unsigned char *, size_t); -hidden size_t __stdout_write(FILE *, const unsigned char *, size_t); -hidden off_t __stdio_seek(FILE *, off_t, int); -hidden int __stdio_close(FILE *); - -hidden int __toread(FILE *); -hidden int __towrite(FILE *); - -hidden void __stdio_exit(void); -hidden void __stdio_exit_needed(void); - -#if defined(__PIC__) && (100*__GNUC__+__GNUC_MINOR__ >= 303) -__attribute__((visibility("protected"))) -#endif -int __overflow(FILE *, int), __uflow(FILE *); - -hidden int __fseeko(FILE *, off_t, int); -hidden int __fseeko_unlocked(FILE *, off_t, int); -hidden off_t __ftello(FILE *); -hidden off_t __ftello_unlocked(FILE *); -hidden size_t __fwritex(const unsigned char *, size_t, FILE *); -hidden int __putc_unlocked(int, FILE *); - -hidden FILE *__fdopen(int, const char *); -hidden int __fmodeflags(const char *); - -hidden FILE *__ofl_add(FILE *f); -hidden FILE **__ofl_lock(void); -hidden void __ofl_unlock(void); - -struct __pthread; -hidden void __register_locked_file(FILE *, struct __pthread *); -hidden void __unlist_locked_file(FILE *); -hidden void __do_orphaned_stdio_locks(void); - -#define MAYBE_WAITERS 0x40000000 - -hidden void __getopt_msg(const char *, const char *, const char *, size_t); - -#define feof(f) ((f)->flags & F_EOF) -#define ferror(f) ((f)->flags & F_ERR) - -#define getc_unlocked(f) \ - ( ((f)->rpos != (f)->rend) ? *(f)->rpos++ : __uflow((f)) ) - -#define putc_unlocked(c, f) \ - ( (((unsigned char)(c)!=(f)->lbf && (f)->wpos!=(f)->wend)) \ - ? *(f)->wpos++ = (unsigned char)(c) \ - : __overflow((f),(unsigned char)(c)) ) - -/* Caller-allocated FILE * operations */ -hidden FILE *__fopen_rb_ca(const char *, FILE *, unsigned char *, size_t); -hidden int __fclose_ca(FILE *); - -#endif diff --git a/src/system/libroot/posix/musl/stdlib/Jamfile b/src/system/libroot/posix/musl/stdlib/Jamfile index c70e53d9f6..ad8b3bffa6 100644 --- a/src/system/libroot/posix/musl/stdlib/Jamfile +++ b/src/system/libroot/posix/musl/stdlib/Jamfile @@ -12,11 +12,6 @@ for architectureObject in [ MultiArchSubDirSetup ] { ecvt.c fcvt.c gcvt.c - - strtod.c - strtol.c - wcstod.c - wcstol.c ; } } diff --git a/src/system/libroot/posix/musl/stdlib/strtod.c b/src/system/libroot/posix/musl/stdlib/strtod.c deleted file mode 100644 index 7d33a5c89f..0000000000 --- a/src/system/libroot/posix/musl/stdlib/strtod.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include "shgetc.h" -#include "floatscan.h" -#include "stdio_impl.h" - -static long double strtox(const char *s, char **p, int prec) -{ - FILE f; - sh_fromstring(&f, s); - shlim(&f, 0); - { - long double y = __floatscan(&f, prec, 1); - off_t cnt = shcnt(&f); - if (p) *p = cnt ? (char *)s + cnt : (char *)s; - return y; - } -} - -float strtof(const char *restrict s, char **restrict p) -{ - return strtox(s, p, 0); -} - -double strtod(const char *restrict s, char **restrict p) -{ - return strtox(s, p, 1); -} - -long double strtold(const char *restrict s, char **restrict p) -{ - return strtox(s, p, 2); -} - -#ifdef __HAIKU__ -weak_alias(strtof, __strtof_internal); -weak_alias(strtod, __strtod_internal); -weak_alias(strtold, __strtold_internal); -#endif diff --git a/src/system/libroot/posix/musl/stdlib/strtol.c b/src/system/libroot/posix/musl/stdlib/strtol.c deleted file mode 100644 index b71fd1ab2f..0000000000 --- a/src/system/libroot/posix/musl/stdlib/strtol.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "stdio_impl.h" -#include "intscan.h" -#include "shgetc.h" -#include -#include -#include - -static unsigned long long strtox(const char *s, char **p, int base, unsigned long long lim) -{ - FILE f; - sh_fromstring(&f, s); - shlim(&f, 0); - { - unsigned long long y = __intscan(&f, base, 1, lim); - if (p) { - size_t cnt = shcnt(&f); - *p = (char *)s + cnt; - } - return y; - } -} - -unsigned long long strtoull(const char *restrict s, char **restrict p, int base) -{ - return strtox(s, p, base, ULLONG_MAX); -} - -long long strtoll(const char *restrict s, char **restrict p, int base) -{ - return strtox(s, p, base, LLONG_MIN); -} - -unsigned long strtoul(const char *restrict s, char **restrict p, int base) -{ - return strtox(s, p, base, ULONG_MAX); -} - -long strtol(const char *restrict s, char **restrict p, int base) -{ - return strtox(s, p, base, 0UL+LONG_MIN); -} - -weak_alias(strtol, __strtol_internal); -weak_alias(strtoul, __strtoul_internal); -weak_alias(strtoll, __strtoll_internal); -weak_alias(strtoull, __strtoull_internal); diff --git a/src/system/libroot/posix/musl/stdlib/wcstod.c b/src/system/libroot/posix/musl/stdlib/wcstod.c deleted file mode 100644 index 79d4499d09..0000000000 --- a/src/system/libroot/posix/musl/stdlib/wcstod.c +++ /dev/null @@ -1,72 +0,0 @@ -#include "shgetc.h" -#include "floatscan.h" -#include "stdio_impl.h" -#include -#include - -/* This read function heavily cheats. It knows: - * (1) len will always be 1 - * (2) non-ascii characters don't matter */ - -static size_t do_read(FILE *f, unsigned char *buf, size_t len) -{ - size_t i; - const wchar_t *wcs = f->cookie; - - if (!wcs[0]) wcs=L"@"; - for (i=0; ibuf_size && wcs[i]; i++) - f->buf[i] = wcs[i] < 128 ? wcs[i] : '@'; - f->rpos = f->buf; - f->rend = f->buf + i; - f->cookie = (void *)(wcs+i); - - if (i && len) { - *buf = *f->rpos++; - return 1; - } - return 0; -} - -static long double wcstox(const wchar_t *s, wchar_t **p, int prec) -{ - wchar_t *t = (wchar_t *)s; - unsigned char buf[64]; - FILE f = {0}; - f.flags = 0; - f.rpos = f.rend = f.buf = buf + 4; - f.buf_size = sizeof buf - 4; - f.lock = -1; - f.read = do_read; - while (iswspace(*t)) t++; - f.cookie = (void *)t; - shlim(&f, 0); - { - long double y = __floatscan(&f, prec, 1); - if (p) { - size_t cnt = shcnt(&f); - *p = cnt ? t + cnt : (wchar_t *)s; - } - return y; - } -} - -float wcstof(const wchar_t *restrict s, wchar_t **restrict p) -{ - return wcstox(s, p, 0); -} - -double wcstod(const wchar_t *restrict s, wchar_t **restrict p) -{ - return wcstox(s, p, 1); -} - -long double wcstold(const wchar_t *restrict s, wchar_t **restrict p) -{ - return wcstox(s, p, 2); -} - -#ifdef __HAIKU__ -weak_alias(wcstof, __wcstof_internal); -weak_alias(wcstod, __wcstod_internal); -weak_alias(wcstold, __wcstold_internal); -#endif diff --git a/src/system/libroot/posix/musl/stdlib/wcstol.c b/src/system/libroot/posix/musl/stdlib/wcstol.c deleted file mode 100644 index 6996209538..0000000000 --- a/src/system/libroot/posix/musl/stdlib/wcstol.c +++ /dev/null @@ -1,90 +0,0 @@ -#include "stdio_impl.h" -#include "intscan.h" -#include "shgetc.h" -#include -#include -#include -#include - -/* This read function heavily cheats. It knows: - * (1) len will always be 1 - * (2) non-ascii characters don't matter */ - -static size_t do_read(FILE *f, unsigned char *buf, size_t len) -{ - size_t i; - const wchar_t *wcs = f->cookie; - - if (!wcs[0]) wcs=L"@"; - for (i=0; ibuf_size && wcs[i]; i++) - f->buf[i] = wcs[i] < 128 ? wcs[i] : '@'; - f->rpos = f->buf; - f->rend = f->buf + i; - f->cookie = (void *)(wcs+i); - - if (i && len) { - *buf = *f->rpos++; - return 1; - } - return 0; -} - -static unsigned long long wcstox(const wchar_t *s, wchar_t **p, int base, unsigned long long lim) -{ - wchar_t *t = (wchar_t *)s; - unsigned char buf[64]; - FILE f = {0}; - f.flags = 0; - f.rpos = f.rend = f.buf = buf + 4; - f.buf_size = sizeof buf - 4; - f.lock = -1; - f.read = do_read; - while (iswspace(*t)) t++; - f.cookie = (void *)t; - shlim(&f, 0); - { - unsigned long long y = __intscan(&f, base, 1, lim); - if (p) { - size_t cnt = shcnt(&f); - *p = cnt ? t + cnt : (wchar_t *)s; - } - return y; - } -} - -unsigned long long wcstoull(const wchar_t *restrict s, wchar_t **restrict p, int base) -{ - return wcstox(s, p, base, ULLONG_MAX); -} - -long long wcstoll(const wchar_t *restrict s, wchar_t **restrict p, int base) -{ - return wcstox(s, p, base, LLONG_MIN); -} - -unsigned long wcstoul(const wchar_t *restrict s, wchar_t **restrict p, int base) -{ - return wcstox(s, p, base, ULONG_MAX); -} - -long wcstol(const wchar_t *restrict s, wchar_t **restrict p, int base) -{ - return wcstox(s, p, base, 0UL+LONG_MIN); -} - -intmax_t wcstoimax(const wchar_t *restrict s, wchar_t **restrict p, int base) -{ - return wcstoll(s, p, base); -} - -uintmax_t wcstoumax(const wchar_t *restrict s, wchar_t **restrict p, int base) -{ - return wcstoull(s, p, base); -} - -#ifdef __HAIKU__ -weak_alias(wcstol, __wcstol_internal); -weak_alias(wcstoul, __wcstoul_internal); -weak_alias(wcstoll, __wcstoll_internal); -weak_alias(wcstoull, __wcstoull_internal); -#endif