X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fstrtod.c;h=371476ee4d2b5e99a33291866dc29e1d77159166;hb=40b243881abcf500cb03c7274e8ed1fb31468546;hp=a2a4d3db65d82008dc9ba249e034b62f0a15d7f2;hpb=17959d7c83195b5568ac4c311d2754971efd4b90;p=gnulib.git diff --git a/lib/strtod.c b/lib/strtod.c index a2a4d3db6..371476ee4 100644 --- a/lib/strtod.c +++ b/lib/strtod.c @@ -1,5 +1,5 @@ -/* Copyright (C) 1991, 1992, 1997, 1999, 2003, 2006, 2008 Free - Software Foundation, Inc. +/* Copyright (C) 1991-1992, 1997, 1999, 2003, 2006, 2008-2010 Free Software + Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,6 +16,10 @@ #include +/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc + optimizes away the nptr == NULL test below. */ +#define _GL_ARG_NONNULL(params) + #include #include @@ -38,9 +42,9 @@ strtod (const char *nptr, char **endptr) /* The number so far. */ double num; - bool got_dot; /* Found a decimal point. */ - bool got_digit; /* Seen any digits. */ - bool hex = false; /* Look for hex float exponent. */ + bool got_dot; /* Found a decimal point. */ + bool got_digit; /* Seen any digits. */ + bool hex = false; /* Look for hex float exponent. */ /* The exponent of the number. */ long int exponent; @@ -75,114 +79,114 @@ strtod (const char *nptr, char **endptr) hex = true; s += 2; for (;; ++s) - { - if (c_isxdigit (*s)) - { - got_digit = true; - - /* Make sure that multiplication by 16 will not overflow. */ - if (num > DBL_MAX / 16) - /* The value of the digit doesn't matter, since we have already - gotten as many digits as can be represented in a `double'. - This doesn't necessarily mean the result will overflow. - The exponent may reduce it to within range. - - We just need to record that there was another - digit so that we can multiply by 16 later. */ - ++exponent; - else - num = ((num * 16.0) - + (c_tolower (*s) - (c_isdigit (*s) ? '0' : 'a' - 10))); - - /* Keep track of the number of digits after the decimal point. - If we just divided by 16 here, we would lose precision. */ - if (got_dot) - --exponent; - } - else if (!got_dot && *s == '.') - /* Record that we have found the decimal point. */ - got_dot = true; - else - /* Any other character terminates the number. */ - break; - } + { + if (c_isxdigit (*s)) + { + got_digit = true; + + /* Make sure that multiplication by 16 will not overflow. */ + if (num > DBL_MAX / 16) + /* The value of the digit doesn't matter, since we have already + gotten as many digits as can be represented in a `double'. + This doesn't necessarily mean the result will overflow. + The exponent may reduce it to within range. + + We just need to record that there was another + digit so that we can multiply by 16 later. */ + ++exponent; + else + num = ((num * 16.0) + + (c_tolower (*s) - (c_isdigit (*s) ? '0' : 'a' - 10))); + + /* Keep track of the number of digits after the decimal point. + If we just divided by 16 here, we would lose precision. */ + if (got_dot) + --exponent; + } + else if (!got_dot && *s == '.') + /* Record that we have found the decimal point. */ + got_dot = true; + else + /* Any other character terminates the number. */ + break; + } } /* Not a hex float. */ else { for (;; ++s) - { - if (c_isdigit (*s)) - { - got_digit = true; - - /* Make sure that multiplication by 10 will not overflow. */ - if (num > DBL_MAX * 0.1) - /* The value of the digit doesn't matter, since we have already - gotten as many digits as can be represented in a `double'. - This doesn't necessarily mean the result will overflow. - The exponent may reduce it to within range. - - We just need to record that there was another - digit so that we can multiply by 10 later. */ - ++exponent; - else - num = (num * 10.0) + (*s - '0'); - - /* Keep track of the number of digits after the decimal point. - If we just divided by 10 here, we would lose precision. */ - if (got_dot) - --exponent; - } - else if (!got_dot && *s == '.') - /* Record that we have found the decimal point. */ - got_dot = true; - else - /* Any other character terminates the number. */ - break; - } + { + if (c_isdigit (*s)) + { + got_digit = true; + + /* Make sure that multiplication by 10 will not overflow. */ + if (num > DBL_MAX * 0.1) + /* The value of the digit doesn't matter, since we have already + gotten as many digits as can be represented in a `double'. + This doesn't necessarily mean the result will overflow. + The exponent may reduce it to within range. + + We just need to record that there was another + digit so that we can multiply by 10 later. */ + ++exponent; + else + num = (num * 10.0) + (*s - '0'); + + /* Keep track of the number of digits after the decimal point. + If we just divided by 10 here, we would lose precision. */ + if (got_dot) + --exponent; + } + else if (!got_dot && *s == '.') + /* Record that we have found the decimal point. */ + got_dot = true; + else + /* Any other character terminates the number. */ + break; + } } if (!got_digit) { /* Check for infinities and NaNs. */ if (c_tolower (*s) == 'i' - && c_tolower (s[1]) == 'n' - && c_tolower (s[2]) == 'f') - { - s += 3; - num = HUGE_VAL; - if (c_tolower (*s) == 'i' - && c_tolower (s[1]) == 'n' - && c_tolower (s[2]) == 'i' - && c_tolower (s[3]) == 't' - && c_tolower (s[4]) == 'y') - s += 5; - goto valid; - } + && c_tolower (s[1]) == 'n' + && c_tolower (s[2]) == 'f') + { + s += 3; + num = HUGE_VAL; + if (c_tolower (*s) == 'i' + && c_tolower (s[1]) == 'n' + && c_tolower (s[2]) == 'i' + && c_tolower (s[3]) == 't' + && c_tolower (s[4]) == 'y') + s += 5; + goto valid; + } #ifdef NAN else if (c_tolower (*s) == 'n' - && c_tolower (s[1]) == 'a' - && c_tolower (s[2]) == 'n') - { - s += 3; - num = NAN; - /* Since nan() is implementation-defined, - we define it by ignoring . A nicer - implementation would populate the bits of the NaN - according to interpreting n-char-sequence as a - hexadecimal number, but the result is still a NaN. */ - if (*s == '(') - { - const unsigned char *p = s + 1; - while (c_isalnum (*p)) - p++; - if (*p == ')') - s = p + 1; - } - goto valid; - } + && c_tolower (s[1]) == 'a' + && c_tolower (s[2]) == 'n') + { + s += 3; + num = NAN; + /* Since nan() is implementation-defined, + we define it by ignoring . A nicer + implementation would populate the bits of the NaN + according to interpreting n-char-sequence as a + hexadecimal number, but the result is still a NaN. */ + if (*s == '(') + { + const unsigned char *p = s + 1; + while (c_isalnum (*p)) + p++; + if (*p == ')') + s = p + 1; + } + goto valid; + } #endif goto noconv; } @@ -198,21 +202,21 @@ strtod (const char *nptr, char **endptr) ++s; value = strtol ((char *) s, &end, 10); if (errno == ERANGE && num) - { - /* The exponent overflowed a `long int'. It is probably a safe - assumption that an exponent that cannot be represented by - a `long int' exceeds the limits of a `double'. */ - if (endptr != NULL) - *endptr = end; - if (value < 0) - goto underflow; - else - goto overflow; - } + { + /* The exponent overflowed a `long int'. It is probably a safe + assumption that an exponent that cannot be represented by + a `long int' exceeds the limits of a `double'. */ + if (endptr != NULL) + *endptr = end; + if (value < 0) + goto underflow; + else + goto overflow; + } else if (end == (char *) s) - /* There was no exponent. Reset END to point to - the 'e' or 'E', so *ENDPTR will be set there. */ - end = (char *) s - 1; + /* There was no exponent. Reset END to point to + the 'e' or 'E', so *ENDPTR will be set there. */ + end = (char *) s - 1; errno = save; s = (unsigned char *) end; exponent += value; @@ -234,12 +238,12 @@ strtod (const char *nptr, char **endptr) if (exponent < 0) { if (num < DBL_MIN * pow (10.0, (double) -exponent)) - goto underflow; + goto underflow; } else if (exponent > 0) { if (num > DBL_MAX * pow (10.0, (double) -exponent)) - goto overflow; + goto overflow; } num *= pow (10.0, (double) exponent);