X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fatof-generic.c;h=6dfd61bb81df6c9030e3f2d702f5b42eb87684c8;hb=d16c467a501547e37b111f775396e28f8bf27c1e;hp=2d7a32b77b416e62d2f535a91dca6d8e5f8538ac;hpb=0e389e770d54185d8107db1972d3ae0576d0fa1d;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/atof-generic.c b/gas/atof-generic.c index 2d7a32b77b..6dfd61bb81 100644 --- a/gas/atof-generic.c +++ b/gas/atof-generic.c @@ -1,28 +1,25 @@ /* atof_generic.c - turn a string of digits into a Flonum - Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2000 - Free Software Foundation, Inc. + Copyright (C) 1987-2020 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) + the Free Software Foundation; either version 3, or (at your option) any later version. - GAS 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 General Public License for more details. + GAS 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 General Public + License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free - Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ - -#include -#include + Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ #include "as.h" +#include "safe-ctype.h" #ifndef FALSE #define FALSE (0) @@ -32,7 +29,7 @@ #endif #ifdef TRACE -static void flonum_print PARAMS ((const FLONUM_TYPE *)); +static void flonum_print (const FLONUM_TYPE *); #endif #define ASSUME_DECIMAL_MARK_IS_DOT @@ -75,16 +72,12 @@ static void flonum_print PARAMS ((const FLONUM_TYPE *)); */ int -atof_generic (address_of_string_pointer, - string_of_decimal_marks, - string_of_decimal_exponent_marks, - address_of_generic_floating_point_number) - /* return pointer to just AFTER number we read. */ - char **address_of_string_pointer; - /* At most one per number. */ - const char *string_of_decimal_marks; - const char *string_of_decimal_exponent_marks; - FLONUM_TYPE *address_of_generic_floating_point_number; +atof_generic (/* return pointer to just AFTER number we read. */ + char **address_of_string_pointer, + /* At most one per number. */ + const char *string_of_decimal_marks, + const char *string_of_decimal_exponent_marks, + FLONUM_TYPE *address_of_generic_floating_point_number) { int return_value; /* 0 means OK. */ char *first_digit; @@ -107,7 +100,7 @@ atof_generic (address_of_string_pointer, int seen_significant_digit; #ifdef ASSUME_DECIMAL_MARK_IS_DOT - assert (string_of_decimal_marks[0] == '.' + gas_assert (string_of_decimal_marks[0] == '.' && string_of_decimal_marks[1] == 0); #define IS_DECIMAL_MARK(c) ((c) == '.') #else @@ -171,7 +164,7 @@ atof_generic (address_of_string_pointer, && (!c || !strchr (string_of_decimal_exponent_marks, c))); p++) { - if (isdigit ((unsigned char) c)) + if (ISDIGIT (c)) { if (seen_significant_digit || c > '0') { @@ -191,23 +184,42 @@ atof_generic (address_of_string_pointer, #ifndef OLD_FLOAT_READS /* Ignore trailing 0's after the decimal point. The original code here - * (ifdef'd out) does not do this, and numbers like - * 4.29496729600000000000e+09 (2**31) - * come out inexact for some reason related to length of the digit - * string. - */ + (ifdef'd out) does not do this, and numbers like + 4.29496729600000000000e+09 (2**31) + come out inexact for some reason related to length of the digit + string. */ + + /* The case number_of_digits_before_decimal = 0 is handled for + deleting zeros after decimal. In this case the decimal mark and + the first zero digits after decimal mark are skipped. */ + seen_significant_digit = 0; + signed long subtract_decimal_exponent = 0; + if (c && IS_DECIMAL_MARK (c)) { - unsigned int zeros = 0; /* Length of current string of zeros */ + unsigned int zeros = 0; /* Length of current string of zeros. */ + + if (number_of_digits_before_decimal == 0) + /* Skip decimal mark. */ + first_digit++; - for (p++; (c = *p) && isdigit ((unsigned char) c); p++) + for (p++; (c = *p) && ISDIGIT (c); p++) { if (c == '0') { - zeros++; + if (number_of_digits_before_decimal == 0 + && !seen_significant_digit) + { + /* Skip '0' and the decimal mark. */ + first_digit++; + subtract_decimal_exponent--; + } + else + zeros++; } else { + seen_significant_digit = 1; number_of_digits_after_decimal += 1 + zeros; zeros = 0; } @@ -221,7 +233,7 @@ atof_generic (address_of_string_pointer, && (!c || !strchr (string_of_decimal_exponent_marks, c))); p++) { - if (isdigit ((unsigned char) c)) + if (ISDIGIT (c)) { /* This may be retracted below. */ number_of_digits_after_decimal++; @@ -275,7 +287,7 @@ atof_generic (address_of_string_pointer, for (; (c); c = *++p) { - if (isdigit ((unsigned char) c)) + if (ISDIGIT (c)) { decimal_exponent = decimal_exponent * 10 + c - '0'; /* @@ -294,6 +306,12 @@ atof_generic (address_of_string_pointer, } } +#ifndef OLD_FLOAT_READS + /* Subtract_decimal_exponent != 0 when number_of_digits_before_decimal = 0 + and first digit after decimal is '0'. */ + decimal_exponent += subtract_decimal_exponent; +#endif + *address_of_string_pointer = p; number_of_digits_available = @@ -312,6 +330,8 @@ atof_generic (address_of_string_pointer, { int count; /* Number of useful digits left to scan. */ + LITTLENUM_TYPE *temporary_binary_low = NULL; + LITTLENUM_TYPE *power_binary_low = NULL; LITTLENUM_TYPE *digits_binary_low; unsigned int precision; unsigned int maximum_useful_digits; @@ -327,20 +347,12 @@ atof_generic (address_of_string_pointer, - address_of_generic_floating_point_number->low + 1); /* Number of destination littlenums. */ - /* Includes guard bits (two littlenums worth) */ -#if 0 /* The integer version below is very close, and it doesn't - require floating point support (which is currently buggy on - the Alpha). */ - maximum_useful_digits = (((double) (precision - 2)) - * ((double) (LITTLENUM_NUMBER_OF_BITS)) - / (LOG_TO_BASE_2_OF_10)) - + 2; /* 2 :: guard digits. */ -#else - maximum_useful_digits = (((precision - 2)) - * ( (LITTLENUM_NUMBER_OF_BITS)) - * 1000000 / 3321928) - + 2; /* 2 :: guard digits. */ -#endif + /* precision includes two littlenums worth of guard bits, + so this gives us 10 decimal guard digits here. */ + maximum_useful_digits = (precision + * LITTLENUM_NUMBER_OF_BITS + * 1000000 / 3321928 + + 1); /* round up. */ if (number_of_digits_available > maximum_useful_digits) { @@ -357,13 +369,8 @@ atof_generic (address_of_string_pointer, decimal_exponent += ((long) number_of_digits_before_decimal - (long) number_of_digits_to_use); -#if 0 - more_than_enough_bits_for_digits - = ((((double) number_of_digits_to_use) * LOG_TO_BASE_2_OF_10) + 1); -#else more_than_enough_bits_for_digits = (number_of_digits_to_use * 3321928 / 1000000 + 1); -#endif more_than_enough_littlenums_for_digits = (more_than_enough_bits_for_digits @@ -383,7 +390,7 @@ atof_generic (address_of_string_pointer, * sizeof (LITTLENUM_TYPE); digits_binary_low = (LITTLENUM_TYPE *) - alloca (size_of_digits_in_chars); + xmalloc (size_of_digits_in_chars); memset ((char *) digits_binary_low, '\0', size_of_digits_in_chars); @@ -400,7 +407,7 @@ atof_generic (address_of_string_pointer, for (p = first_digit, count = number_of_digits_to_use; count; p++, --count) { c = *p; - if (isdigit ((unsigned char) c)) + if (ISDIGIT (c)) { /* * Multiply by 10. Assume can never overflow. @@ -471,18 +478,16 @@ atof_generic (address_of_string_pointer, { /* - * Compute the mantssa (& exponent) of the power of 10. - * If sucessful, then multiply the power of 10 by the digits + * Compute the mantissa (& exponent) of the power of 10. + * If successful, then multiply the power of 10 by the digits * giving return_binary_mantissa and return_binary_exponent. */ - LITTLENUM_TYPE *power_binary_low; int decimal_exponent_is_negative; /* This refers to the "-56" in "12.34E-56". */ /* FALSE: decimal_exponent is positive (or 0) */ /* TRUE: decimal_exponent is negative */ FLONUM_TYPE temporary_flonum; - LITTLENUM_TYPE *temporary_binary_low; unsigned int size_of_power_in_littlenums; unsigned int size_of_power_in_chars; @@ -500,8 +505,9 @@ atof_generic (address_of_string_pointer, size_of_power_in_chars = size_of_power_in_littlenums * sizeof (LITTLENUM_TYPE) + 2; - power_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars); - temporary_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars); + power_binary_low = (LITTLENUM_TYPE *) xmalloc (size_of_power_in_chars); + temporary_binary_low = (LITTLENUM_TYPE *) xmalloc (size_of_power_in_chars); + memset ((char *) power_binary_low, '\0', size_of_power_in_chars); *power_binary_low = 1; power_of_10_flonum.exponent = 0; @@ -592,7 +598,6 @@ atof_generic (address_of_string_pointer, (void) putchar ('\n'); #endif } - } /* @@ -606,6 +611,11 @@ atof_generic (address_of_string_pointer, /* Assert sign of the number we made is '+'. */ address_of_generic_floating_point_number->sign = digits_sign_char; + if (temporary_binary_low) + free (temporary_binary_low); + if (power_binary_low) + free (power_binary_low); + free (digits_binary_low); } return return_value; }