From d28e3a861f97b138a542a335b3f7603bf1794d70 Mon Sep 17 00:00:00 2001 From: "Peter S. Mazinger" Date: Mon, 13 Feb 2006 07:47:26 +0000 Subject: More renames for IMA --- libc/stdlib/Makefile.in | 4 +- libc/stdlib/_atexit.c | 356 +++++++++++++++++++++++++++ libc/stdlib/_strtod.c | 623 ++++++++++++++++++++++++++++++++++++++++++++++++ libc/stdlib/atexit.c | 356 --------------------------- libc/stdlib/strtod.c | 623 ------------------------------------------------ 5 files changed, 981 insertions(+), 981 deletions(-) create mode 100644 libc/stdlib/_atexit.c create mode 100644 libc/stdlib/_strtod.c delete mode 100644 libc/stdlib/atexit.c delete mode 100644 libc/stdlib/strtod.c (limited to 'libc/stdlib') diff --git a/libc/stdlib/Makefile.in b/libc/stdlib/Makefile.in index d8983389d..e6573cfad 100644 --- a/libc/stdlib/Makefile.in +++ b/libc/stdlib/Makefile.in @@ -20,7 +20,7 @@ MOBJ1x:=strtol_l.o strtoul_l.o _stdlib_strto_l_l.o \ strtoll_l.o strtoull_l.o _stdlib_strto_ll_l.o endif -MSRC2:=strtod.c +MSRC2:=_strtod.c MOBJ2:= MOBJ2x:= @@ -50,7 +50,7 @@ endif # (aliases) wcstoq.o wcstouq.o # wcstod wcstof wcstold -MSRC3:=atexit.c +MSRC3:=_atexit.c MOBJ3:=on_exit.o __cxa_atexit.o __cxa_finalize.o __exit_handler.o exit.o ifeq ($(COMPAT_ATEXIT),y) MOBJ3+=old_atexit.o diff --git a/libc/stdlib/_atexit.c b/libc/stdlib/_atexit.c new file mode 100644 index 000000000..959d08edb --- /dev/null +++ b/libc/stdlib/_atexit.c @@ -0,0 +1,356 @@ +/* Copyright (C) 1995,1996 Robert de Bath + * This file is part of the Linux-8086 C library and is distributed + * under the GNU Library General Public License. + */ + +/* + * Dec 2000 Manuel Novoa III + * + * Made atexit handling conform to standards... i.e. no args. + * Removed on_exit since it did not match gnu libc definition. + * Combined atexit and __do_exit into one object file. + * + * Feb 2001 Manuel Novoa III + * + * Reworked file after addition of __uClibc_main. + * Changed name of __do_exit to atexit_handler. + * Changed name of __cleanup to __uClibc_cleanup. + * Moved declaration of __uClibc_cleanup to __uClibc_main + * where it is initialized with (possibly weak alias) + * _stdio_term. + * + * Jul 2001 Steve Thayer + * + * Added an on_exit implementation (that now matches gnu libc definition.) + * Pulled atexit_handler out of the atexit object since it is now required by + * on_exit as well. Renamed it to __exit_handler. + * Fixed a problem where exit functions stop getting called if one of + * them calls exit(). + * As a side effect of these changes, abort() no longer calls the exit + * functions (it now matches the gnu libc definition). + * + * August 2002 Erik Andersen + * Added locking so atexit and friends can be thread safe + * + * August 2005 Stephen Warren + * Added __cxa_atexit and __cxa_finalize support + * + */ + +#include +#include +#include +#include +#include + +libc_hidden_proto(exit) +libc_hidden_proto(_exit) + +#ifdef __UCLIBC_HAS_THREADS__ +# include +extern pthread_mutex_t mylock; +libc_hidden_proto(mylock) +#endif +#define LOCK __pthread_mutex_lock(&mylock) +#define UNLOCK __pthread_mutex_unlock(&mylock) + + +typedef void (*aefuncp) (void); /* atexit function pointer */ +typedef void (*oefuncp) (int, void *); /* on_exit function pointer */ +typedef void (*cxaefuncp) (void *); /* __cxa_atexit function pointer */ +typedef enum { + ef_free, + ef_in_use, + ef_on_exit, + ef_cxa_atexit +} ef_type; /* exit function types */ + +/* this is in the L_exit object */ +extern void (*__exit_cleanup) (int) attribute_hidden; + +/* these are in the L___do_exit object */ +extern int __exit_slots attribute_hidden; +extern int __exit_count attribute_hidden; +extern void __exit_handler(int) attribute_hidden; +struct exit_function { + /* + * 'type' should be of type of the 'enum ef_type' above but since we + * need this element in an atomic operation we have to use 'long int'. + */ + long int type; /* enum ef_type */ + union { + struct { + oefuncp func; + void *arg; + } on_exit; + struct { + cxaefuncp func; + void *arg; + void* dso_handle; + } cxa_atexit; + } funcs; +}; +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ +extern struct exit_function *__exit_function_table attribute_hidden; +#else +extern struct exit_function __exit_function_table[__UCLIBC_MAX_ATEXIT] attribute_hidden; +#endif +extern struct exit_function *__new_exitfn (void) attribute_hidden; + +/* this is in the L___cxa_atexit object */ +extern int __cxa_atexit (cxaefuncp, void *arg, void *dso_handle); + + +/* remove old_atexit after 0.9.29 */ +#if defined(L_atexit) || defined(L_old_atexit) +extern void *__dso_handle __attribute__ ((__weak__)); + +/* + * register a function to be called at normal program termination + * (the registered function takes no arguments) + */ +#ifdef L_atexit +int attribute_hidden atexit(aefuncp func) +#else +int old_atexit(aefuncp func) +#endif +{ + /* + * glibc casts aefuncp to cxaefuncp. + * This seems dodgy, but I guess callling a function with more + * parameters than it needs will work everywhere? + */ + return __cxa_atexit((cxaefuncp)func, NULL, + &__dso_handle == NULL ? NULL : __dso_handle); +} +#ifndef L_atexit +weak_alias(old_atexit,atexit) +#endif +#endif + +#ifdef L_on_exit +/* + * register a function to be called at normal program termination + * the registered function takes two arguments: + * status - the exit status that was passed to the exit() function + * arg - generic argument + */ +int on_exit(oefuncp func, void *arg) +{ + struct exit_function *efp; + + if (func == NULL) { + return 0; + } + + efp = __new_exitfn(); + if (efp == NULL) { + return -1; + } + + efp->funcs.on_exit.func = func; + efp->funcs.on_exit.arg = arg; + /* assign last for thread safety, since we're now unlocked */ + efp->type = ef_on_exit; + + return 0; +} +#endif + +#ifdef L___cxa_atexit +libc_hidden_proto(__cxa_atexit) +int __cxa_atexit (cxaefuncp func, void *arg, void *dso_handle) +{ + struct exit_function *efp; + + if (func == NULL) { + return 0; + } + + efp = __new_exitfn(); + if (efp == NULL) { + return -1; + } + + efp->funcs.cxa_atexit.func = func; + efp->funcs.cxa_atexit.arg = arg; + efp->funcs.cxa_atexit.dso_handle = dso_handle; + /* assign last for thread safety, since we're now unlocked */ + efp->type = ef_cxa_atexit; + + return 0; +} +libc_hidden_def(__cxa_atexit) +#endif + +#ifdef L___cxa_finalize +/* + * If D is non-NULL, call all functions registered with `__cxa_atexit' + * with the same dso handle. Otherwise, if D is NULL, call all of the + * registered handlers. + */ +void __cxa_finalize (void *dso_handle); +void __cxa_finalize (void *dso_handle) +{ + struct exit_function *efp; + int exit_count_snapshot = __exit_count; + + /* In reverse order */ + while (exit_count_snapshot) { + efp = &__exit_function_table[--exit_count_snapshot]; + + /* + * We check dso_handle match before we verify the type of the union entry. + * However, the atomic_exchange will validate that we were really "allowed" + * to read dso_handle... + */ + if ((dso_handle == NULL || dso_handle == efp->funcs.cxa_atexit.dso_handle) + /* We don't want to run this cleanup more than once. */ + && !atomic_compare_and_exchange_bool_acq(&efp->type, ef_free, ef_cxa_atexit) + ) { + /* glibc passes status (0) too, but that's not in the prototype */ + (*efp->funcs.cxa_atexit.func)(efp->funcs.cxa_atexit.arg); + } + } + +#if 0 /* haven't looked into this yet... */ + /* + * Remove the registered fork handlers. We do not have to + * unregister anything if the program is going to terminate anyway. + */ +#ifdef UNREGISTER_ATFORK + if (d != NULL) { + UNREGISTER_ATFORK (d); + } +#endif +#endif +} +#endif + +#ifdef L___exit_handler +int __exit_count = 0; /* Number of registered exit functions */ +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ +struct exit_function *__exit_function_table = NULL; +int __exit_slots = 0; /* Size of __exit_function_table */ +#else +struct exit_function __exit_function_table[__UCLIBC_MAX_ATEXIT]; +#endif + +/* + * Find and return a new exit_function pointer, for atexit, + * onexit and __cxa_atexit to initialize + */ +struct exit_function attribute_hidden *__new_exitfn(void) +{ + struct exit_function *efp; + + LOCK; + +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ + /* If we are out of function table slots, make some more */ + if (__exit_slots < __exit_count+1) { + efp=realloc(__exit_function_table, + (__exit_slots+20)*sizeof(struct exit_function)); + if (efp == NULL) { + UNLOCK; + __set_errno(ENOMEM); + return 0; + } + __exit_function_table = efp; + __exit_slots += 20; + } +#else + if (__exit_count >= __UCLIBC_MAX_ATEXIT) { + UNLOCK; + __set_errno(ENOMEM); + return 0; + } +#endif + + __exit_cleanup = __exit_handler; /* enable cleanup */ + efp = &__exit_function_table[__exit_count++]; + efp->type = ef_in_use; + + UNLOCK; + + return efp; +} + +/* + * Handle the work of executing the registered exit functions + * This is called while we are locked, so no additional locking + * is needed... + */ +void __exit_handler(int status) +{ + struct exit_function *efp; + + /* In reverse order */ + while ( __exit_count ) { + efp = &__exit_function_table[--__exit_count]; + switch (efp->type) { + case ef_on_exit: + if (efp->funcs.on_exit.func) { + (efp->funcs.on_exit.func) (status, efp->funcs.on_exit.arg); + } + break; + case ef_cxa_atexit: + if (efp->funcs.cxa_atexit.func) { + /* glibc passes status too, but that's not in the prototype */ + (efp->funcs.cxa_atexit.func) (efp->funcs.cxa_atexit.arg); + } + break; + } + } +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ + /* Free up memory used by the __exit_function_table structure */ + if (__exit_function_table) + free(__exit_function_table); +#endif +} +#endif + +#ifdef L_exit +extern void weak_function _stdio_term(void) attribute_hidden; +attribute_hidden void (*__exit_cleanup) (int) = 0; +#ifdef __UCLIBC_HAS_THREADS__ +pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +libc_hidden_data_def(mylock) +#endif + +#ifdef __UCLIBC_CTOR_DTOR__ +extern void (*__app_fini)(void); +#endif + +extern void (*__rtld_fini)(void); + +/* + * Normal program termination + */ +void exit(int rv) +{ + /* Perform exit-specific cleanup (atexit and on_exit) */ + LOCK; + if (__exit_cleanup) { + __exit_cleanup(rv); + } + UNLOCK; + +#ifdef __UCLIBC_CTOR_DTOR__ + if (__app_fini != NULL) + (__app_fini)(); +#endif + if (__rtld_fini != NULL) + (__rtld_fini)(); + + /* If we are using stdio, try to shut it down. At the very least, + * this will attempt to commit all buffered writes. It may also + * unbuffer all writable files, or close them outright. + * Check the stdio routines for details. */ + if (_stdio_term) + _stdio_term(); + + _exit(rv); +} +libc_hidden_def(exit) +#endif diff --git a/libc/stdlib/_strtod.c b/libc/stdlib/_strtod.c new file mode 100644 index 000000000..c4447d9ea --- /dev/null +++ b/libc/stdlib/_strtod.c @@ -0,0 +1,623 @@ +/* + * Copyright (C) 2000-2005 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Notes: + * + * The primary objective of this implementation was minimal size and + * portablility, while providing robustness and resonable accuracy. + * + * This implementation depends on IEEE floating point behavior and expects + * to be able to generate +/- infinity as a result. + * + * There are a number of compile-time options below. + */ + +/* July 27, 2003 + * + * General cleanup and some minor size optimizations. + * Change implementation to support __strtofpmax() rather than strtod(). + * Now all the strto{floating pt}() funcs are implemented in terms of + * of the internal __strtofpmax() function. + * Support "nan", "inf", and "infinity" strings (case-insensitive). + * Support hexadecimal floating point notation. + * Support wchar variants. + * Support xlocale variants. + * + * TODO: + * + * Consider accumulating blocks of digits in longs to save floating pt mults. + * This would likely be much better on anything that only supported floats + * where DECIMAL_DIG == 9. Actually, if floats have FLT_MAX_10_EXP == 38, + * we could calculate almost all the exponent multipliers (p_base) in + * long arithmetic as well. + */ + +/**********************************************************************/ +/* OPTIONS */ +/**********************************************************************/ + +/* Defined if we want to recognize "nan", "inf", and "infinity". (C99) */ +#define _STRTOD_NAN_INF_STRINGS 1 + +/* Defined if we want support hexadecimal floating point notation. (C99) */ +/* Note! Now controlled by uClibc configuration. See below. */ +#define _STRTOD_HEXADECIMAL_FLOATS 1 + +/* Defined if we want to scale with a O(log2(exp)) multiplications. + * This is generally a good thing to do unless you are really tight + * on space and do not expect to convert values of large magnitude. */ + +#define _STRTOD_LOG_SCALING 1 + +/* WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! + * + * Clearing any of the options below this point is not advised (or tested). + * + * WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! */ + +/* Defined if we want strtod to set errno appropriately. */ +/* NOTE: Implies all options below. */ +#define _STRTOD_ERRNO 1 + +/* Defined if we want support for the endptr arg. */ +/* Implied by _STRTOD_ERRNO. */ +#define _STRTOD_ENDPTR 1 + +/* Defined if we want to prevent overflow in accumulating the exponent. */ +/* Implied by _STRTOD_ERRNO. */ +#define _STRTOD_RESTRICT_EXP 1 + +/* Defined if we want to process mantissa digits more intelligently. */ +/* Implied by _STRTOD_ERRNO. */ +#define _STRTOD_RESTRICT_DIGITS 1 + +/* Defined if we want to skip scaling 0 for the exponent. */ +/* Implied by _STRTOD_ERRNO. */ +#define _STRTOD_ZERO_CHECK 1 + +/**********************************************************************/ +/* Don't change anything that follows. */ +/**********************************************************************/ + +#ifdef _STRTOD_ERRNO +#undef _STRTOD_ENDPTR +#undef _STRTOD_RESTRICT_EXP +#undef _STRTOD_RESTRICT_DIGITS +#undef _STRTOD_ZERO_CHECK +#define _STRTOD_ENDPTR 1 +#define _STRTOD_RESTRICT_EXP 1 +#define _STRTOD_RESTRICT_DIGITS 1 +#define _STRTOD_ZERO_CHECK 1 +#endif + +/**********************************************************************/ + +#define _ISOC99_SOURCE 1 +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef __UCLIBC_HAS_WCHAR__ + +#include +#include +#include +libc_hidden_proto(iswspace) +#endif + +#ifdef __UCLIBC_HAS_XLOCALE__ +#include +libc_hidden_proto(iswspace_l) +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +/* Handle _STRTOD_HEXADECIMAL_FLOATS via uClibc config now. */ +#undef _STRTOD_HEXADECIMAL_FLOATS +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ +#define _STRTOD_HEXADECIMAL_FLOATS 1 +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + +/**********************************************************************/ + +#undef _STRTOD_FPMAX + +#if FPMAX_TYPE == 3 + +#define NEED_STRTOLD_WRAPPER +#define NEED_STRTOD_WRAPPER +#define NEED_STRTOF_WRAPPER + +#elif FPMAX_TYPE == 2 + +#define NEED_STRTOD_WRAPPER +#define NEED_STRTOF_WRAPPER + +#elif FPMAX_TYPE == 1 + +#define NEED_STRTOF_WRAPPER + +#else + +#error unknown FPMAX_TYPE! + +#endif + +extern void __fp_range_check(__fpmax_t y, __fpmax_t x) attribute_hidden; + +/**********************************************************************/ + +#ifdef _STRTOD_RESTRICT_DIGITS +#define EXP_DENORM_ADJUST DECIMAL_DIG +#define MAX_ALLOWED_EXP (DECIMAL_DIG + EXP_DENORM_ADJUST - FPMAX_MIN_10_EXP) + +#if MAX_ALLOWED_EXP > INT_MAX +#error size assumption violated for MAX_ALLOWED_EXP +#endif +#else +/* We want some excess if we're not restricting mantissa digits. */ +#define MAX_ALLOWED_EXP ((20 - FPMAX_MIN_10_EXP) * 2) +#endif + + +#if defined(_STRTOD_RESTRICT_DIGITS) || defined(_STRTOD_ENDPTR) || defined(_STRTOD_HEXADECIMAL_FLOATS) +#undef _STRTOD_NEED_NUM_DIGITS +#define _STRTOD_NEED_NUM_DIGITS 1 +#endif + +/**********************************************************************/ +#if defined(L___strtofpmax) || defined(L___strtofpmax_l) || defined(L___wcstofpmax) || defined(L___wcstofpmax_l) + +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b_loc) +#else +#ifdef __UCLIBC_HAS_LOCALE__ +libc_hidden_proto(__global_locale) +#endif +libc_hidden_proto(__ctype_b) +libc_hidden_proto(__ctype_tolower) +#endif + +#if defined(L___wcstofpmax) || defined(L___wcstofpmax_l) + +#define __strtofpmax __wcstofpmax +#define __strtofpmax_l __wcstofpmax_l + +#define Wchar wchar_t +#ifdef __UCLIBC_DO_XLOCALE +#define ISSPACE(C) iswspace_l((C), locale_arg) +#else +#define ISSPACE(C) iswspace((C)) +#endif + +#else /* defined(L___wcstofpmax) || defined(L___wcstofpmax_l) */ + +#define Wchar char +#ifdef __UCLIBC_DO_XLOCALE +#define ISSPACE(C) isspace_l((C), locale_arg) +#else +#define ISSPACE(C) isspace((C)) +#endif + +#endif /* defined(L___wcstofpmax) || defined(L___wcstofpmax_l) */ + + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +__fpmax_t attribute_hidden __strtofpmax(const Wchar *str, Wchar **endptr, int exponent_power) +{ + return __strtofpmax_l(str, endptr, exponent_power, __UCLIBC_CURLOCALE); +} + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +libc_hidden_proto(memcmp) + +__fpmax_t attribute_hidden __XL_NPP(__strtofpmax)(const Wchar *str, Wchar **endptr, int exponent_power + __LOCALE_PARAM ) +{ + __fpmax_t number; + __fpmax_t p_base = 10; /* Adjusted to 16 in the hex case. */ + Wchar *pos0; +#ifdef _STRTOD_ENDPTR + Wchar *pos1; +#endif + Wchar *pos = (Wchar *) str; + int exponent_temp; + int negative; /* A flag for the number, a multiplier for the exponent. */ +#ifdef _STRTOD_NEED_NUM_DIGITS + int num_digits; +#endif +#ifdef __UCLIBC_HAS_LOCALE__ +#if defined(L___wcstofpmax) || defined(L___wcstofpmax_l) + wchar_t decpt_wc = __LOCALE_PTR->decimal_point; +#else + const char *decpt = __LOCALE_PTR->decimal_point; + int decpt_len = __LOCALE_PTR->decimal_point_len; +#endif +#endif + +#ifdef _STRTOD_HEXADECIMAL_FLOATS + Wchar expchar = 'e'; + Wchar *poshex = NULL; + __uint16_t is_mask = _ISdigit; +#define EXPCHAR expchar +#define IS_X_DIGIT(C) __isctype((C), is_mask) +#else /* _STRTOD_HEXADECIMAL_FLOATS */ +#define EXPCHAR 'e' +#define IS_X_DIGIT(C) isdigit((C)) +#endif /* _STRTOD_HEXADECIMAL_FLOATS */ + + while (ISSPACE(*pos)) { /* Skip leading whitespace. */ + ++pos; + } + + negative = 0; + switch(*pos) { /* Handle optional sign. */ + case '-': negative = 1; /* Fall through to increment position. */ + case '+': ++pos; + } + +#ifdef _STRTOD_HEXADECIMAL_FLOATS + if ((*pos == '0') && (((pos[1])|0x20) == 'x')) { + poshex = ++pos; /* Save position of 'x' in case no digits */ + ++pos; /* and advance past it. */ + is_mask = _ISxdigit; /* Used by IS_X_DIGIT. */ + expchar = 'p'; /* Adjust exponent char. */ + p_base = 16; /* Adjust base multiplier. */ + } +#endif + + number = 0.; +#ifdef _STRTOD_NEED_NUM_DIGITS + num_digits = -1; +#endif +/* exponent_power = 0; */ + pos0 = NULL; + + LOOP: + while (IS_X_DIGIT(*pos)) { /* Process string of (hex) digits. */ +#ifdef _STRTOD_RESTRICT_DIGITS + if (num_digits < 0) { /* First time through? */ + ++num_digits; /* We've now seen a digit. */ + } + if (num_digits || (*pos != '0')) { /* Had/have nonzero. */ + ++num_digits; + if (num_digits <= DECIMAL_DIG) { /* Is digit significant? */ +#ifdef _STRTOD_HEXADECIMAL_FLOATS + number = number * p_base + + (isdigit(*pos) + ? (*pos - '0') + : (((*pos)|0x20) - ('a' - 10))); +#else /* _STRTOD_HEXADECIMAL_FLOATS */ + number = number * p_base + (*pos - '0'); +#endif /* _STRTOD_HEXADECIMAL_FLOATS */ + } + } +#else /* _STRTOD_RESTRICT_DIGITS */ +#ifdef _STRTOD_NEED_NUM_DIGITS + ++num_digits; +#endif +#ifdef _STRTOD_HEXADECIMAL_FLOATS + number = number * p_base + + (isdigit(*pos) + ? (*pos - '0') + : (((*pos)|0x20) - ('a' - 10))); +#else /* _STRTOD_HEXADECIMAL_FLOATS */ + number = number * p_base + (*pos - '0'); +#endif /* _STRTOD_HEXADECIMAL_FLOATS */ +#endif /* _STRTOD_RESTRICT_DIGITS */ + ++pos; + } + +#ifdef __UCLIBC_HAS_LOCALE__ +#if defined(L___wcstofpmax) || defined(L___wcstofpmax_l) + if (!pos0 && (*pos == decpt_wc)) { /* First decimal point? */ + pos0 = ++pos; + goto LOOP; + } +#else + if (!pos0 && !memcmp(pos, decpt, decpt_len)) { /* First decimal point? */ + pos0 = (pos += decpt_len); + goto LOOP; + } +#endif +#else /* __UCLIBC_HAS_LOCALE__ */ + if ((*pos == '.') && !pos0) { /* First decimal point? */ + pos0 = ++pos; /* Save position of decimal point */ + goto LOOP; /* and process rest of digits. */ + } +#endif /* __UCLIBC_HAS_LOCALE__ */ + +#ifdef _STRTOD_NEED_NUM_DIGITS + if (num_digits<0) { /* Must have at least one digit. */ +#ifdef _STRTOD_HEXADECIMAL_FLOATS + if (poshex) { /* Back up to '0' in '0x' prefix. */ + pos = poshex; + goto DONE; + } +#endif /* _STRTOD_HEXADECIMAL_FLOATS */ + +#ifdef _STRTOD_NAN_INF_STRINGS + if (!pos0) { /* No decimal point, so check for inf/nan. */ + /* Note: nan is the first string so 'number = i/0.;' works. */ + static const char nan_inf_str[] = "\05nan\0\012infinity\0\05inf\0"; + int i = 0; + +#ifdef __UCLIBC_HAS_LOCALE__ + /* Avoid tolower problems for INFINITY in the tr_TR locale. (yuk)*/ +#undef _tolower +#define _tolower(C) ((C)|0x20) +#endif /* __UCLIBC_HAS_LOCALE__ */ + + do { + /* Unfortunately, we have no memcasecmp(). */ + int j = 0; + while (_tolower(pos[j]) == nan_inf_str[i+1+j]) { + ++j; + if (!nan_inf_str[i+1+j]) { + number = i / 0.; + if (negative) { /* Correct for sign. */ + number = -number; + } + pos += nan_inf_str[i] - 2; + goto DONE; + } + } + i += nan_inf_str[i]; + } while (nan_inf_str[i]); + } + +#endif /* STRTOD_NAN_INF_STRINGS */ +#ifdef _STRTOD_ENDPTR + pos = (Wchar *) str; +#endif + goto DONE; + } +#endif /* _STRTOD_NEED_NUM_DIGITS */ + +#ifdef _STRTOD_RESTRICT_DIGITS + if (num_digits > DECIMAL_DIG) { /* Adjust exponent for skipped digits. */ + exponent_power += num_digits - DECIMAL_DIG; + } +#endif + + if (pos0) { + exponent_power += pos0 - pos; /* Adjust exponent for decimal point. */ + } + +#ifdef _STRTOD_HEXADECIMAL_FLOATS + if (poshex) { + exponent_power *= 4; /* Above is 2**4, but below is 2. */ + p_base = 2; + } +#endif /* _STRTOD_HEXADECIMAL_FLOATS */ + + if (negative) { /* Correct for sign. */ + number = -number; + } + + /* process an exponent string */ + if (((*pos)|0x20) == EXPCHAR) { +#ifdef _STRTOD_ENDPTR + pos1 = pos; +#endif + negative = 1; + switch(*++pos) { /* Handle optional sign. */ + case '-': negative = -1; /* Fall through to increment pos. */ + case '+': ++pos; + } + + pos0 = pos; + exponent_temp = 0; + while (isdigit(*pos)) { /* Process string of digits. */ +#ifdef _STRTOD_RESTRICT_EXP + if (exponent_temp < MAX_ALLOWED_EXP) { /* Avoid overflow. */ + exponent_temp = exponent_temp * 10 + (*pos - '0'); + } +#else + exponent_temp = exponent_temp * 10 + (*pos - '0'); +#endif + ++pos; + } + +#ifdef _STRTOD_ENDPTR + if (pos == pos0) { /* No digits? */ + pos = pos1; /* Back up to {e|E}/{p|P}. */ + } /* else */ +#endif + + exponent_power += negative * exponent_temp; + } + +#ifdef _STRTOD_ZERO_CHECK + if (number == 0.) { + goto DONE; + } +#endif + + /* scale the result */ +#ifdef _STRTOD_LOG_SCALING + exponent_temp = exponent_power; + + if (exponent_temp < 0) { + exponent_temp = -exponent_temp; + } + + while (exponent_temp) { + if (exponent_temp & 1) { + if (exponent_power < 0) { + /* Warning... caluclating a factor for the exponent and + * then dividing could easily be faster. But doing so + * might cause problems when dealing with denormals. */ + number /= p_base; + } else { + number *= p_base; + } + } + exponent_temp >>= 1; + p_base *= p_base; + } + +#else /* _STRTOD_LOG_SCALING */ + while (exponent_power) { + if (exponent_power < 0) { + number /= p_base; + exponent_power++; + } else { + number *= p_base; + exponent_power--; + } + } +#endif /* _STRTOD_LOG_SCALING */ + +#ifdef _STRTOD_ERRNO + if (__FPMAX_ZERO_OR_INF_CHECK(number)) { + __set_errno(ERANGE); + } +#endif + + DONE: +#ifdef _STRTOD_ENDPTR + if (endptr) { + *endptr = pos; + } +#endif + + return number; +} + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +#endif +/**********************************************************************/ +#ifdef L___fp_range_check +#if defined(NEED_STRTOF_WRAPPER) || defined(NEED_STRTOD_WRAPPER) + +void attribute_hidden __fp_range_check(__fpmax_t y, __fpmax_t x) +{ + if (__FPMAX_ZERO_OR_INF_CHECK(y) /* y is 0 or +/- infinity */ + && (y != 0) /* y is not 0 (could have x>0, y==0 if underflow) */ + && !__FPMAX_ZERO_OR_INF_CHECK(x) /* x is not 0 or +/- infinity */ + ) { + __set_errno(ERANGE); /* Then x is not in y's range. */ + } +} + +#endif +#endif +/**********************************************************************/ +#if defined(L_strtof) || defined(L_strtof_l) || defined(L_wcstof) || defined(L_wcstof_l) +#if defined(NEED_STRTOF_WRAPPER) + +#if defined(L_wcstof) || defined(L_wcstof_l) +#define strtof wcstof +#define strtof_l wcstof_l +#define __strtofpmax __wcstofpmax +#define __strtofpmax_l __wcstofpmax_l +#define Wchar wchar_t +#else +#define Wchar char +#endif + + +libc_hidden_proto(__XL_NPP(strtof)) +float __XL_NPP(strtof)(const Wchar *str, Wchar **endptr __LOCALE_PARAM ) +{ +#if FPMAX_TYPE == 1 + return __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); +#else + __fpmax_t x; + float y; + + x = __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); + y = (float) x; + + __fp_range_check(y, x); + + return y; +#endif +} +libc_hidden_def(__XL_NPP(strtof)) + +#endif +#endif +/**********************************************************************/ +#if defined(L_strtod) || defined(L_strtod_l) || defined(L_wcstod) || defined(L_wcstod_l) +#if defined(NEED_STRTOD_WRAPPER) + +#if defined(L_wcstod) || defined(L_wcstod_l) +#define strtod wcstod +#define strtod_l wcstod_l +#define __strtofpmax __wcstofpmax +#define __strtofpmax_l __wcstofpmax_l +#define Wchar wchar_t +#else +#define Wchar char +#endif + +libc_hidden_proto(__XL_NPP(strtod)) +double __XL_NPP(strtod)(const Wchar *__restrict str, + Wchar **__restrict endptr __LOCALE_PARAM ) +{ +#if FPMAX_TYPE == 2 + return __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); +#else + __fpmax_t x; + double y; + + x = __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); + y = (double) x; + + __fp_range_check(y, x); + + return y; +#endif +} +libc_hidden_def(__XL_NPP(strtod)) + +#endif +#endif +/**********************************************************************/ +#if defined(L_strtold) || defined(L_strtold_l) || defined(L_wcstold) || defined(L_wcstold_l) +#if defined(NEED_STRTOLD_WRAPPER) + +#if defined(L_wcstold) || defined(L_wcstold_l) +#define strtold wcstold +#define strtold_l wcstold_l +#define __strtofpmax __wcstofpmax +#define __strtofpmax_l __wcstofpmax_l +#define Wchar wchar_t +#else +#define Wchar char +#endif + +libc_hidden_proto(__XL_NPP(strtold)) +long double __XL_NPP(strtold) (const Wchar *str, Wchar **endptr __LOCALE_PARAM ) +{ +#if FPMAX_TYPE == 3 + return __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); +#else + __fpmax_t x; + long double y; + + x = __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); + y = (long double) x; + + __fp_range_check(y, x); + + return y; +#endif +} +libc_hidden_def(__XL_NPP(strtold)) + +#endif +#endif +/**********************************************************************/ diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c deleted file mode 100644 index 959d08edb..000000000 --- a/libc/stdlib/atexit.c +++ /dev/null @@ -1,356 +0,0 @@ -/* Copyright (C) 1995,1996 Robert de Bath - * This file is part of the Linux-8086 C library and is distributed - * under the GNU Library General Public License. - */ - -/* - * Dec 2000 Manuel Novoa III - * - * Made atexit handling conform to standards... i.e. no args. - * Removed on_exit since it did not match gnu libc definition. - * Combined atexit and __do_exit into one object file. - * - * Feb 2001 Manuel Novoa III - * - * Reworked file after addition of __uClibc_main. - * Changed name of __do_exit to atexit_handler. - * Changed name of __cleanup to __uClibc_cleanup. - * Moved declaration of __uClibc_cleanup to __uClibc_main - * where it is initialized with (possibly weak alias) - * _stdio_term. - * - * Jul 2001 Steve Thayer - * - * Added an on_exit implementation (that now matches gnu libc definition.) - * Pulled atexit_handler out of the atexit object since it is now required by - * on_exit as well. Renamed it to __exit_handler. - * Fixed a problem where exit functions stop getting called if one of - * them calls exit(). - * As a side effect of these changes, abort() no longer calls the exit - * functions (it now matches the gnu libc definition). - * - * August 2002 Erik Andersen - * Added locking so atexit and friends can be thread safe - * - * August 2005 Stephen Warren - * Added __cxa_atexit and __cxa_finalize support - * - */ - -#include -#include -#include -#include -#include - -libc_hidden_proto(exit) -libc_hidden_proto(_exit) - -#ifdef __UCLIBC_HAS_THREADS__ -# include -extern pthread_mutex_t mylock; -libc_hidden_proto(mylock) -#endif -#define LOCK __pthread_mutex_lock(&mylock) -#define UNLOCK __pthread_mutex_unlock(&mylock) - - -typedef void (*aefuncp) (void); /* atexit function pointer */ -typedef void (*oefuncp) (int, void *); /* on_exit function pointer */ -typedef void (*cxaefuncp) (void *); /* __cxa_atexit function pointer */ -typedef enum { - ef_free, - ef_in_use, - ef_on_exit, - ef_cxa_atexit -} ef_type; /* exit function types */ - -/* this is in the L_exit object */ -extern void (*__exit_cleanup) (int) attribute_hidden; - -/* these are in the L___do_exit object */ -extern int __exit_slots attribute_hidden; -extern int __exit_count attribute_hidden; -extern void __exit_handler(int) attribute_hidden; -struct exit_function { - /* - * 'type' should be of type of the 'enum ef_type' above but since we - * need this element in an atomic operation we have to use 'long int'. - */ - long int type; /* enum ef_type */ - union { - struct { - oefuncp func; - void *arg; - } on_exit; - struct { - cxaefuncp func; - void *arg; - void* dso_handle; - } cxa_atexit; - } funcs; -}; -#ifdef __UCLIBC_DYNAMIC_ATEXIT__ -extern struct exit_function *__exit_function_table attribute_hidden; -#else -extern struct exit_function __exit_function_table[__UCLIBC_MAX_ATEXIT] attribute_hidden; -#endif -extern struct exit_function *__new_exitfn (void) attribute_hidden; - -/* this is in the L___cxa_atexit object */ -extern int __cxa_atexit (cxaefuncp, void *arg, void *dso_handle); - - -/* remove old_atexit after 0.9.29 */ -#if defined(L_atexit) || defined(L_old_atexit) -extern void *__dso_handle __attribute__ ((__weak__)); - -/* - * register a function to be called at normal program termination - * (the registered function takes no arguments) - */ -#ifdef L_atexit -int attribute_hidden atexit(aefuncp func) -#else -int old_atexit(aefuncp func) -#endif -{ - /* - * glibc casts aefuncp to cxaefuncp. - * This seems dodgy, but I guess callling a function with more - * parameters than it needs will work everywhere? - */ - return __cxa_atexit((cxaefuncp)func, NULL, - &__dso_handle == NULL ? NULL : __dso_handle); -} -#ifndef L_atexit -weak_alias(old_atexit,atexit) -#endif -#endif - -#ifdef L_on_exit -/* - * register a function to be called at normal program termination - * the registered function takes two arguments: - * status - the exit status that was passed to the exit() function - * arg - generic argument - */ -int on_exit(oefuncp func, void *arg) -{ - struct exit_function *efp; - - if (func == NULL) { - return 0; - } - - efp = __new_exitfn(); - if (efp == NULL) { - return -1; - } - - efp->funcs.on_exit.func = func; - efp->funcs.on_exit.arg = arg; - /* assign last for thread safety, since we're now unlocked */ - efp->type = ef_on_exit; - - return 0; -} -#endif - -#ifdef L___cxa_atexit -libc_hidden_proto(__cxa_atexit) -int __cxa_atexit (cxaefuncp func, void *arg, void *dso_handle) -{ - struct exit_function *efp; - - if (func == NULL) { - return 0; - } - - efp = __new_exitfn(); - if (efp == NULL) { - return -1; - } - - efp->funcs.cxa_atexit.func = func; - efp->funcs.cxa_atexit.arg = arg; - efp->funcs.cxa_atexit.dso_handle = dso_handle; - /* assign last for thread safety, since we're now unlocked */ - efp->type = ef_cxa_atexit; - - return 0; -} -libc_hidden_def(__cxa_atexit) -#endif - -#ifdef L___cxa_finalize -/* - * If D is non-NULL, call all functions registered with `__cxa_atexit' - * with the same dso handle. Otherwise, if D is NULL, call all of the - * registered handlers. - */ -void __cxa_finalize (void *dso_handle); -void __cxa_finalize (void *dso_handle) -{ - struct exit_function *efp; - int exit_count_snapshot = __exit_count; - - /* In reverse order */ - while (exit_count_snapshot) { - efp = &__exit_function_table[--exit_count_snapshot]; - - /* - * We check dso_handle match before we verify the type of the union entry. - * However, the atomic_exchange will validate that we were really "allowed" - * to read dso_handle... - */ - if ((dso_handle == NULL || dso_handle == efp->funcs.cxa_atexit.dso_handle) - /* We don't want to run this cleanup more than once. */ - && !atomic_compare_and_exchange_bool_acq(&efp->type, ef_free, ef_cxa_atexit) - ) { - /* glibc passes status (0) too, but that's not in the prototype */ - (*efp->funcs.cxa_atexit.func)(efp->funcs.cxa_atexit.arg); - } - } - -#if 0 /* haven't looked into this yet... */ - /* - * Remove the registered fork handlers. We do not have to - * unregister anything if the program is going to terminate anyway. - */ -#ifdef UNREGISTER_ATFORK - if (d != NULL) { - UNREGISTER_ATFORK (d); - } -#endif -#endif -} -#endif - -#ifdef L___exit_handler -int __exit_count = 0; /* Number of registered exit functions */ -#ifdef __UCLIBC_DYNAMIC_ATEXIT__ -struct exit_function *__exit_function_table = NULL; -int __exit_slots = 0; /* Size of __exit_function_table */ -#else -struct exit_function __exit_function_table[__UCLIBC_MAX_ATEXIT]; -#endif - -/* - * Find and return a new exit_function pointer, for atexit, - * onexit and __cxa_atexit to initialize - */ -struct exit_function attribute_hidden *__new_exitfn(void) -{ - struct exit_function *efp; - - LOCK; - -#ifdef __UCLIBC_DYNAMIC_ATEXIT__ - /* If we are out of function table slots, make some more */ - if (__exit_slots < __exit_count+1) { - efp=realloc(__exit_function_table, - (__exit_slots+20)*sizeof(struct exit_function)); - if (efp == NULL) { - UNLOCK; - __set_errno(ENOMEM); - return 0; - } - __exit_function_table = efp; - __exit_slots += 20; - } -#else - if (__exit_count >= __UCLIBC_MAX_ATEXIT) { - UNLOCK; - __set_errno(ENOMEM); - return 0; - } -#endif - - __exit_cleanup = __exit_handler; /* enable cleanup */ - efp = &__exit_function_table[__exit_count++]; - efp->type = ef_in_use; - - UNLOCK; - - return efp; -} - -/* - * Handle the work of executing the registered exit functions - * This is called while we are locked, so no additional locking - * is needed... - */ -void __exit_handler(int status) -{ - struct exit_function *efp; - - /* In reverse order */ - while ( __exit_count ) { - efp = &__exit_function_table[--__exit_count]; - switch (efp->type) { - case ef_on_exit: - if (efp->funcs.on_exit.func) { - (efp->funcs.on_exit.func) (status, efp->funcs.on_exit.arg); - } - break; - case ef_cxa_atexit: - if (efp->funcs.cxa_atexit.func) { - /* glibc passes status too, but that's not in the prototype */ - (efp->funcs.cxa_atexit.func) (efp->funcs.cxa_atexit.arg); - } - break; - } - } -#ifdef __UCLIBC_DYNAMIC_ATEXIT__ - /* Free up memory used by the __exit_function_table structure */ - if (__exit_function_table) - free(__exit_function_table); -#endif -} -#endif - -#ifdef L_exit -extern void weak_function _stdio_term(void) attribute_hidden; -attribute_hidden void (*__exit_cleanup) (int) = 0; -#ifdef __UCLIBC_HAS_THREADS__ -pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; -libc_hidden_data_def(mylock) -#endif - -#ifdef __UCLIBC_CTOR_DTOR__ -extern void (*__app_fini)(void); -#endif - -extern void (*__rtld_fini)(void); - -/* - * Normal program termination - */ -void exit(int rv) -{ - /* Perform exit-specific cleanup (atexit and on_exit) */ - LOCK; - if (__exit_cleanup) { - __exit_cleanup(rv); - } - UNLOCK; - -#ifdef __UCLIBC_CTOR_DTOR__ - if (__app_fini != NULL) - (__app_fini)(); -#endif - if (__rtld_fini != NULL) - (__rtld_fini)(); - - /* If we are using stdio, try to shut it down. At the very least, - * this will attempt to commit all buffered writes. It may also - * unbuffer all writable files, or close them outright. - * Check the stdio routines for details. */ - if (_stdio_term) - _stdio_term(); - - _exit(rv); -} -libc_hidden_def(exit) -#endif diff --git a/libc/stdlib/strtod.c b/libc/stdlib/strtod.c deleted file mode 100644 index c4447d9ea..000000000 --- a/libc/stdlib/strtod.c +++ /dev/null @@ -1,623 +0,0 @@ -/* - * Copyright (C) 2000-2005 Manuel Novoa III - * - * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. - */ - -/* Notes: - * - * The primary objective of this implementation was minimal size and - * portablility, while providing robustness and resonable accuracy. - * - * This implementation depends on IEEE floating point behavior and expects - * to be able to generate +/- infinity as a result. - * - * There are a number of compile-time options below. - */ - -/* July 27, 2003 - * - * General cleanup and some minor size optimizations. - * Change implementation to support __strtofpmax() rather than strtod(). - * Now all the strto{floating pt}() funcs are implemented in terms of - * of the internal __strtofpmax() function. - * Support "nan", "inf", and "infinity" strings (case-insensitive). - * Support hexadecimal floating point notation. - * Support wchar variants. - * Support xlocale variants. - * - * TODO: - * - * Consider accumulating blocks of digits in longs to save floating pt mults. - * This would likely be much better on anything that only supported floats - * where DECIMAL_DIG == 9. Actually, if floats have FLT_MAX_10_EXP == 38, - * we could calculate almost all the exponent multipliers (p_base) in - * long arithmetic as well. - */ - -/**********************************************************************/ -/* OPTIONS */ -/**********************************************************************/ - -/* Defined if we want to recognize "nan", "inf", and "infinity". (C99) */ -#define _STRTOD_NAN_INF_STRINGS 1 - -/* Defined if we want support hexadecimal floating point notation. (C99) */ -/* Note! Now controlled by uClibc configuration. See below. */ -#define _STRTOD_HEXADECIMAL_FLOATS 1 - -/* Defined if we want to scale with a O(log2(exp)) multiplications. - * This is generally a good thing to do unless you are really tight - * on space and do not expect to convert values of large magnitude. */ - -#define _STRTOD_LOG_SCALING 1 - -/* WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! - * - * Clearing any of the options below this point is not advised (or tested). - * - * WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! */ - -/* Defined if we want strtod to set errno appropriately. */ -/* NOTE: Implies all options below. */ -#define _STRTOD_ERRNO 1 - -/* Defined if we want support for the endptr arg. */ -/* Implied by _STRTOD_ERRNO. */ -#define _STRTOD_ENDPTR 1 - -/* Defined if we want to prevent overflow in accumulating the exponent. */ -/* Implied by _STRTOD_ERRNO. */ -#define _STRTOD_RESTRICT_EXP 1 - -/* Defined if we want to process mantissa digits more intelligently. */ -/* Implied by _STRTOD_ERRNO. */ -#define _STRTOD_RESTRICT_DIGITS 1 - -/* Defined if we want to skip scaling 0 for the exponent. */ -/* Implied by _STRTOD_ERRNO. */ -#define _STRTOD_ZERO_CHECK 1 - -/**********************************************************************/ -/* Don't change anything that follows. */ -/**********************************************************************/ - -#ifdef _STRTOD_ERRNO -#undef _STRTOD_ENDPTR -#undef _STRTOD_RESTRICT_EXP -#undef _STRTOD_RESTRICT_DIGITS -#undef _STRTOD_ZERO_CHECK -#define _STRTOD_ENDPTR 1 -#define _STRTOD_RESTRICT_EXP 1 -#define _STRTOD_RESTRICT_DIGITS 1 -#define _STRTOD_ZERO_CHECK 1 -#endif - -/**********************************************************************/ - -#define _ISOC99_SOURCE 1 -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef __UCLIBC_HAS_WCHAR__ - -#include -#include -#include -libc_hidden_proto(iswspace) -#endif - -#ifdef __UCLIBC_HAS_XLOCALE__ -#include -libc_hidden_proto(iswspace_l) -#endif /* __UCLIBC_HAS_XLOCALE__ */ - -/* Handle _STRTOD_HEXADECIMAL_FLOATS via uClibc config now. */ -#undef _STRTOD_HEXADECIMAL_FLOATS -#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ -#define _STRTOD_HEXADECIMAL_FLOATS 1 -#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ - -/**********************************************************************/ - -#undef _STRTOD_FPMAX - -#if FPMAX_TYPE == 3 - -#define NEED_STRTOLD_WRAPPER -#define NEED_STRTOD_WRAPPER -#define NEED_STRTOF_WRAPPER - -#elif FPMAX_TYPE == 2 - -#define NEED_STRTOD_WRAPPER -#define NEED_STRTOF_WRAPPER - -#elif FPMAX_TYPE == 1 - -#define NEED_STRTOF_WRAPPER - -#else - -#error unknown FPMAX_TYPE! - -#endif - -extern void __fp_range_check(__fpmax_t y, __fpmax_t x) attribute_hidden; - -/**********************************************************************/ - -#ifdef _STRTOD_RESTRICT_DIGITS -#define EXP_DENORM_ADJUST DECIMAL_DIG -#define MAX_ALLOWED_EXP (DECIMAL_DIG + EXP_DENORM_ADJUST - FPMAX_MIN_10_EXP) - -#if MAX_ALLOWED_EXP > INT_MAX -#error size assumption violated for MAX_ALLOWED_EXP -#endif -#else -/* We want some excess if we're not restricting mantissa digits. */ -#define MAX_ALLOWED_EXP ((20 - FPMAX_MIN_10_EXP) * 2) -#endif - - -#if defined(_STRTOD_RESTRICT_DIGITS) || defined(_STRTOD_ENDPTR) || defined(_STRTOD_HEXADECIMAL_FLOATS) -#undef _STRTOD_NEED_NUM_DIGITS -#define _STRTOD_NEED_NUM_DIGITS 1 -#endif - -/**********************************************************************/ -#if defined(L___strtofpmax) || defined(L___strtofpmax_l) || defined(L___wcstofpmax) || defined(L___wcstofpmax_l) - -#ifdef __UCLIBC_HAS_XLOCALE__ -libc_hidden_proto(__ctype_b_loc) -#else -#ifdef __UCLIBC_HAS_LOCALE__ -libc_hidden_proto(__global_locale) -#endif -libc_hidden_proto(__ctype_b) -libc_hidden_proto(__ctype_tolower) -#endif - -#if defined(L___wcstofpmax) || defined(L___wcstofpmax_l) - -#define __strtofpmax __wcstofpmax -#define __strtofpmax_l __wcstofpmax_l - -#define Wchar wchar_t -#ifdef __UCLIBC_DO_XLOCALE -#define ISSPACE(C) iswspace_l((C), locale_arg) -#else -#define ISSPACE(C) iswspace((C)) -#endif - -#else /* defined(L___wcstofpmax) || defined(L___wcstofpmax_l) */ - -#define Wchar char -#ifdef __UCLIBC_DO_XLOCALE -#define ISSPACE(C) isspace_l((C), locale_arg) -#else -#define ISSPACE(C) isspace((C)) -#endif - -#endif /* defined(L___wcstofpmax) || defined(L___wcstofpmax_l) */ - - -#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) - -__fpmax_t attribute_hidden __strtofpmax(const Wchar *str, Wchar **endptr, int exponent_power) -{ - return __strtofpmax_l(str, endptr, exponent_power, __UCLIBC_CURLOCALE); -} - -#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ - -libc_hidden_proto(memcmp) - -__fpmax_t attribute_hidden __XL_NPP(__strtofpmax)(const Wchar *str, Wchar **endptr, int exponent_power - __LOCALE_PARAM ) -{ - __fpmax_t number; - __fpmax_t p_base = 10; /* Adjusted to 16 in the hex case. */ - Wchar *pos0; -#ifdef _STRTOD_ENDPTR - Wchar *pos1; -#endif - Wchar *pos = (Wchar *) str; - int exponent_temp; - int negative; /* A flag for the number, a multiplier for the exponent. */ -#ifdef _STRTOD_NEED_NUM_DIGITS - int num_digits; -#endif -#ifdef __UCLIBC_HAS_LOCALE__ -#if defined(L___wcstofpmax) || defined(L___wcstofpmax_l) - wchar_t decpt_wc = __LOCALE_PTR->decimal_point; -#else - const char *decpt = __LOCALE_PTR->decimal_point; - int decpt_len = __LOCALE_PTR->decimal_point_len; -#endif -#endif - -#ifdef _STRTOD_HEXADECIMAL_FLOATS - Wchar expchar = 'e'; - Wchar *poshex = NULL; - __uint16_t is_mask = _ISdigit; -#define EXPCHAR expchar -#define IS_X_DIGIT(C) __isctype((C), is_mask) -#else /* _STRTOD_HEXADECIMAL_FLOATS */ -#define EXPCHAR 'e' -#define IS_X_DIGIT(C) isdigit((C)) -#endif /* _STRTOD_HEXADECIMAL_FLOATS */ - - while (ISSPACE(*pos)) { /* Skip leading whitespace. */ - ++pos; - } - - negative = 0; - switch(*pos) { /* Handle optional sign. */ - case '-': negative = 1; /* Fall through to increment position. */ - case '+': ++pos; - } - -#ifdef _STRTOD_HEXADECIMAL_FLOATS - if ((*pos == '0') && (((pos[1])|0x20) == 'x')) { - poshex = ++pos; /* Save position of 'x' in case no digits */ - ++pos; /* and advance past it. */ - is_mask = _ISxdigit; /* Used by IS_X_DIGIT. */ - expchar = 'p'; /* Adjust exponent char. */ - p_base = 16; /* Adjust base multiplier. */ - } -#endif - - number = 0.; -#ifdef _STRTOD_NEED_NUM_DIGITS - num_digits = -1; -#endif -/* exponent_power = 0; */ - pos0 = NULL; - - LOOP: - while (IS_X_DIGIT(*pos)) { /* Process string of (hex) digits. */ -#ifdef _STRTOD_RESTRICT_DIGITS - if (num_digits < 0) { /* First time through? */ - ++num_digits; /* We've now seen a digit. */ - } - if (num_digits || (*pos != '0')) { /* Had/have nonzero. */ - ++num_digits; - if (num_digits <= DECIMAL_DIG) { /* Is digit significant? */ -#ifdef _STRTOD_HEXADECIMAL_FLOATS - number = number * p_base - + (isdigit(*pos) - ? (*pos - '0') - : (((*pos)|0x20) - ('a' - 10))); -#else /* _STRTOD_HEXADECIMAL_FLOATS */ - number = number * p_base + (*pos - '0'); -#endif /* _STRTOD_HEXADECIMAL_FLOATS */ - } - } -#else /* _STRTOD_RESTRICT_DIGITS */ -#ifdef _STRTOD_NEED_NUM_DIGITS - ++num_digits; -#endif -#ifdef _STRTOD_HEXADECIMAL_FLOATS - number = number * p_base - + (isdigit(*pos) - ? (*pos - '0') - : (((*pos)|0x20) - ('a' - 10))); -#else /* _STRTOD_HEXADECIMAL_FLOATS */ - number = number * p_base + (*pos - '0'); -#endif /* _STRTOD_HEXADECIMAL_FLOATS */ -#endif /* _STRTOD_RESTRICT_DIGITS */ - ++pos; - } - -#ifdef __UCLIBC_HAS_LOCALE__ -#if defined(L___wcstofpmax) || defined(L___wcstofpmax_l) - if (!pos0 && (*pos == decpt_wc)) { /* First decimal point? */ - pos0 = ++pos; - goto LOOP; - } -#else - if (!pos0 && !memcmp(pos, decpt, decpt_len)) { /* First decimal point? */ - pos0 = (pos += decpt_len); - goto LOOP; - } -#endif -#else /* __UCLIBC_HAS_LOCALE__ */ - if ((*pos == '.') && !pos0) { /* First decimal point? */ - pos0 = ++pos; /* Save position of decimal point */ - goto LOOP; /* and process rest of digits. */ - } -#endif /* __UCLIBC_HAS_LOCALE__ */ - -#ifdef _STRTOD_NEED_NUM_DIGITS - if (num_digits<0) { /* Must have at least one digit. */ -#ifdef _STRTOD_HEXADECIMAL_FLOATS - if (poshex) { /* Back up to '0' in '0x' prefix. */ - pos = poshex; - goto DONE; - } -#endif /* _STRTOD_HEXADECIMAL_FLOATS */ - -#ifdef _STRTOD_NAN_INF_STRINGS - if (!pos0) { /* No decimal point, so check for inf/nan. */ - /* Note: nan is the first string so 'number = i/0.;' works. */ - static const char nan_inf_str[] = "\05nan\0\012infinity\0\05inf\0"; - int i = 0; - -#ifdef __UCLIBC_HAS_LOCALE__ - /* Avoid tolower problems for INFINITY in the tr_TR locale. (yuk)*/ -#undef _tolower -#define _tolower(C) ((C)|0x20) -#endif /* __UCLIBC_HAS_LOCALE__ */ - - do { - /* Unfortunately, we have no memcasecmp(). */ - int j = 0; - while (_tolower(pos[j]) == nan_inf_str[i+1+j]) { - ++j; - if (!nan_inf_str[i+1+j]) { - number = i / 0.; - if (negative) { /* Correct for sign. */ - number = -number; - } - pos += nan_inf_str[i] - 2; - goto DONE; - } - } - i += nan_inf_str[i]; - } while (nan_inf_str[i]); - } - -#endif /* STRTOD_NAN_INF_STRINGS */ -#ifdef _STRTOD_ENDPTR - pos = (Wchar *) str; -#endif - goto DONE; - } -#endif /* _STRTOD_NEED_NUM_DIGITS */ - -#ifdef _STRTOD_RESTRICT_DIGITS - if (num_digits > DECIMAL_DIG) { /* Adjust exponent for skipped digits. */ - exponent_power += num_digits - DECIMAL_DIG; - } -#endif - - if (pos0) { - exponent_power += pos0 - pos; /* Adjust exponent for decimal point. */ - } - -#ifdef _STRTOD_HEXADECIMAL_FLOATS - if (poshex) { - exponent_power *= 4; /* Above is 2**4, but below is 2. */ - p_base = 2; - } -#endif /* _STRTOD_HEXADECIMAL_FLOATS */ - - if (negative) { /* Correct for sign. */ - number = -number; - } - - /* process an exponent string */ - if (((*pos)|0x20) == EXPCHAR) { -#ifdef _STRTOD_ENDPTR - pos1 = pos; -#endif - negative = 1; - switch(*++pos) { /* Handle optional sign. */ - case '-': negative = -1; /* Fall through to increment pos. */ - case '+': ++pos; - } - - pos0 = pos; - exponent_temp = 0; - while (isdigit(*pos)) { /* Process string of digits. */ -#ifdef _STRTOD_RESTRICT_EXP - if (exponent_temp < MAX_ALLOWED_EXP) { /* Avoid overflow. */ - exponent_temp = exponent_temp * 10 + (*pos - '0'); - } -#else - exponent_temp = exponent_temp * 10 + (*pos - '0'); -#endif - ++pos; - } - -#ifdef _STRTOD_ENDPTR - if (pos == pos0) { /* No digits? */ - pos = pos1; /* Back up to {e|E}/{p|P}. */ - } /* else */ -#endif - - exponent_power += negative * exponent_temp; - } - -#ifdef _STRTOD_ZERO_CHECK - if (number == 0.) { - goto DONE; - } -#endif - - /* scale the result */ -#ifdef _STRTOD_LOG_SCALING - exponent_temp = exponent_power; - - if (exponent_temp < 0) { - exponent_temp = -exponent_temp; - } - - while (exponent_temp) { - if (exponent_temp & 1) { - if (exponent_power < 0) { - /* Warning... caluclating a factor for the exponent and - * then dividing could easily be faster. But doing so - * might cause problems when dealing with denormals. */ - number /= p_base; - } else { - number *= p_base; - } - } - exponent_temp >>= 1; - p_base *= p_base; - } - -#else /* _STRTOD_LOG_SCALING */ - while (exponent_power) { - if (exponent_power < 0) { - number /= p_base; - exponent_power++; - } else { - number *= p_base; - exponent_power--; - } - } -#endif /* _STRTOD_LOG_SCALING */ - -#ifdef _STRTOD_ERRNO - if (__FPMAX_ZERO_OR_INF_CHECK(number)) { - __set_errno(ERANGE); - } -#endif - - DONE: -#ifdef _STRTOD_ENDPTR - if (endptr) { - *endptr = pos; - } -#endif - - return number; -} - -#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ - -#endif -/**********************************************************************/ -#ifdef L___fp_range_check -#if defined(NEED_STRTOF_WRAPPER) || defined(NEED_STRTOD_WRAPPER) - -void attribute_hidden __fp_range_check(__fpmax_t y, __fpmax_t x) -{ - if (__FPMAX_ZERO_OR_INF_CHECK(y) /* y is 0 or +/- infinity */ - && (y != 0) /* y is not 0 (could have x>0, y==0 if underflow) */ - && !__FPMAX_ZERO_OR_INF_CHECK(x) /* x is not 0 or +/- infinity */ - ) { - __set_errno(ERANGE); /* Then x is not in y's range. */ - } -} - -#endif -#endif -/**********************************************************************/ -#if defined(L_strtof) || defined(L_strtof_l) || defined(L_wcstof) || defined(L_wcstof_l) -#if defined(NEED_STRTOF_WRAPPER) - -#if defined(L_wcstof) || defined(L_wcstof_l) -#define strtof wcstof -#define strtof_l wcstof_l -#define __strtofpmax __wcstofpmax -#define __strtofpmax_l __wcstofpmax_l -#define Wchar wchar_t -#else -#define Wchar char -#endif - - -libc_hidden_proto(__XL_NPP(strtof)) -float __XL_NPP(strtof)(const Wchar *str, Wchar **endptr __LOCALE_PARAM ) -{ -#if FPMAX_TYPE == 1 - return __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); -#else - __fpmax_t x; - float y; - - x = __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); - y = (float) x; - - __fp_range_check(y, x); - - return y; -#endif -} -libc_hidden_def(__XL_NPP(strtof)) - -#endif -#endif -/**********************************************************************/ -#if defined(L_strtod) || defined(L_strtod_l) || defined(L_wcstod) || defined(L_wcstod_l) -#if defined(NEED_STRTOD_WRAPPER) - -#if defined(L_wcstod) || defined(L_wcstod_l) -#define strtod wcstod -#define strtod_l wcstod_l -#define __strtofpmax __wcstofpmax -#define __strtofpmax_l __wcstofpmax_l -#define Wchar wchar_t -#else -#define Wchar char -#endif - -libc_hidden_proto(__XL_NPP(strtod)) -double __XL_NPP(strtod)(const Wchar *__restrict str, - Wchar **__restrict endptr __LOCALE_PARAM ) -{ -#if FPMAX_TYPE == 2 - return __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); -#else - __fpmax_t x; - double y; - - x = __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); - y = (double) x; - - __fp_range_check(y, x); - - return y; -#endif -} -libc_hidden_def(__XL_NPP(strtod)) - -#endif -#endif -/**********************************************************************/ -#if defined(L_strtold) || defined(L_strtold_l) || defined(L_wcstold) || defined(L_wcstold_l) -#if defined(NEED_STRTOLD_WRAPPER) - -#if defined(L_wcstold) || defined(L_wcstold_l) -#define strtold wcstold -#define strtold_l wcstold_l -#define __strtofpmax __wcstofpmax -#define __strtofpmax_l __wcstofpmax_l -#define Wchar wchar_t -#else -#define Wchar char -#endif - -libc_hidden_proto(__XL_NPP(strtold)) -long double __XL_NPP(strtold) (const Wchar *str, Wchar **endptr __LOCALE_PARAM ) -{ -#if FPMAX_TYPE == 3 - return __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); -#else - __fpmax_t x; - long double y; - - x = __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); - y = (long double) x; - - __fp_range_check(y, x); - - return y; -#endif -} -libc_hidden_def(__XL_NPP(strtold)) - -#endif -#endif -/**********************************************************************/ -- cgit v1.2.3