X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fatof-generic.c;h=6dfd61bb81df6c9030e3f2d702f5b42eb87684c8;hb=63ffd7c9131c0e9723016d33cf8d435cc508d02b;hp=6d6d1955fb2eee1c7f10f1e3a7af781d2d140157;hpb=a5ac3a14a11e6028c79cc21898bc5f96fcb7fc6e;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/atof-generic.c b/gas/atof-generic.c index 6d6d1955fb..6dfd61bb81 100644 --- a/gas/atof-generic.c +++ b/gas/atof-generic.c @@ -1,34 +1,25 @@ /* atof_generic.c - turn a string of digits into a Flonum - Copyright (C) 1987, 1990, 1991, 1992 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include -#include + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ #include "as.h" - -#ifdef __GNUC__ -#define alloca __builtin_alloca -#else -#ifdef sparc -#include -#endif -#endif +#include "safe-ctype.h" #ifndef FALSE #define FALSE (0) @@ -37,6 +28,12 @@ #define TRUE (1) #endif +#ifdef TRACE +static void flonum_print (const FLONUM_TYPE *); +#endif + +#define ASSUME_DECIMAL_MARK_IS_DOT + /***********************************************************************\ * * * Given a string of decimal digits , with optional decimal * @@ -75,24 +72,19 @@ */ 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. */ + int return_value; /* 0 means OK. */ char *first_digit; - /* char *last_digit; JF unused */ - int number_of_digits_before_decimal; - int number_of_digits_after_decimal; + unsigned int number_of_digits_before_decimal; + unsigned int number_of_digits_after_decimal; long decimal_exponent; - int number_of_digits_available; + unsigned int number_of_digits_available; char digits_sign_char; /* @@ -107,6 +99,14 @@ atof_generic (address_of_string_pointer, char c; int seen_significant_digit; +#ifdef ASSUME_DECIMAL_MARK_IS_DOT + gas_assert (string_of_decimal_marks[0] == '.' + && string_of_decimal_marks[1] == 0); +#define IS_DECIMAL_MARK(c) ((c) == '.') +#else +#define IS_DECIMAL_MARK(c) (0 != strchr (string_of_decimal_marks, (c))) +#endif + first_digit = *address_of_string_pointer; c = *first_digit; @@ -118,46 +118,40 @@ atof_generic (address_of_string_pointer, else digits_sign_char = '+'; - if ((first_digit[0] == 'n' || first_digit[0] == 'N') - && (first_digit[1] == 'a' || first_digit[1] == 'A') - && (first_digit[2] == 'n' || first_digit[2] == 'N')) - { - address_of_generic_floating_point_number->sign = 0; - address_of_generic_floating_point_number->exponent = 0; - address_of_generic_floating_point_number->leader = - address_of_generic_floating_point_number->low; - *address_of_string_pointer = first_digit + 3; - return 0; - } - - if ((first_digit[0] == 'i' || first_digit[0] == 'I') - && (first_digit[1] == 'n' || first_digit[1] == 'N') - && (first_digit[2] == 'f' || first_digit[2] == 'F')) + switch (first_digit[0]) { - address_of_generic_floating_point_number->sign = - digits_sign_char == '+' ? 'P' : 'N'; - address_of_generic_floating_point_number->exponent = 0; - address_of_generic_floating_point_number->leader = - address_of_generic_floating_point_number->low; - - if ((first_digit[3] == 'i' - || first_digit[3] == 'I') - && (first_digit[4] == 'n' - || first_digit[4] == 'N') - && (first_digit[5] == 'i' - || first_digit[5] == 'I') - && (first_digit[6] == 't' - || first_digit[6] == 'T') - && (first_digit[7] == 'y' - || first_digit[7] == 'Y')) + case 'n': + case 'N': + if (!strncasecmp ("nan", first_digit, 3)) { - *address_of_string_pointer = first_digit + 8; + address_of_generic_floating_point_number->sign = 0; + address_of_generic_floating_point_number->exponent = 0; + address_of_generic_floating_point_number->leader = + address_of_generic_floating_point_number->low; + *address_of_string_pointer = first_digit + 3; + return 0; } - else + break; + + case 'i': + case 'I': + if (!strncasecmp ("inf", first_digit, 3)) { - *address_of_string_pointer = first_digit + 3; + address_of_generic_floating_point_number->sign = + digits_sign_char == '+' ? 'P' : 'N'; + address_of_generic_floating_point_number->exponent = 0; + address_of_generic_floating_point_number->leader = + address_of_generic_floating_point_number->low; + + first_digit += 3; + if (!strncasecmp ("inity", first_digit, 5)) + first_digit += 5; + + *address_of_string_pointer = first_digit; + + return 0; } - return 0; + break; } number_of_digits_before_decimal = 0; @@ -166,11 +160,11 @@ atof_generic (address_of_string_pointer, seen_significant_digit = 0; for (p = first_digit; (((c = *p) != '\0') - && (!c || !strchr (string_of_decimal_marks, c)) + && (!c || !IS_DECIMAL_MARK (c)) && (!c || !strchr (string_of_decimal_exponent_marks, c))); p++) { - if (isdigit (c)) + if (ISDIGIT (c)) { if (seen_significant_digit || c > '0') { @@ -184,45 +178,64 @@ atof_generic (address_of_string_pointer, } else { - break; /* p -> char after pre-decimal digits. */ + break; /* p -> char after pre-decimal digits. */ } - } /* For each digit before decimal mark. */ + } /* For each digit before decimal mark. */ #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. - */ - if (c && strchr (string_of_decimal_marks, c)) + (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)) { - int zeros = 0; /* Length of current string of zeros */ + unsigned int zeros = 0; /* Length of current string of zeros. */ - for (p++; (c = *p) && isdigit (c); p++) + if (number_of_digits_before_decimal == 0) + /* Skip decimal mark. */ + first_digit++; + + 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; } } } #else - if (c && strchr (string_of_decimal_marks, c)) + if (c && IS_DECIMAL_MARK (c)) { for (p++; (((c = *p) != '\0') && (!c || !strchr (string_of_decimal_exponent_marks, c))); p++) { - if (isdigit (c)) + if (ISDIGIT (c)) { - /* This may be retracted below. */ + /* This may be retracted below. */ number_of_digits_after_decimal++; if ( /* seen_significant_digit || */ c > '0') @@ -238,7 +251,7 @@ atof_generic (address_of_string_pointer, } break; } - } /* For each digit after decimal mark. */ + } /* For each digit after decimal mark. */ } while (number_of_digits_after_decimal @@ -247,11 +260,21 @@ atof_generic (address_of_string_pointer, --number_of_digits_after_decimal; #endif + if (flag_m68k_mri) + { + while (c == '_') + c = *++p; + } if (c && strchr (string_of_decimal_exponent_marks, c)) { char digits_exponent_sign_char; c = *++p; + if (flag_m68k_mri) + { + while (c == '_') + c = *++p; + } if (c && strchr ("+-", c)) { digits_exponent_sign_char = c; @@ -264,7 +287,7 @@ atof_generic (address_of_string_pointer, for (; (c); c = *++p) { - if (isdigit (c)) + if (ISDIGIT (c)) { decimal_exponent = decimal_exponent * 10 + c - '0'; /* @@ -283,9 +306,13 @@ atof_generic (address_of_string_pointer, } } - *address_of_string_pointer = p; - +#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 = number_of_digits_before_decimal + number_of_digits_after_decimal; @@ -301,8 +328,10 @@ atof_generic (address_of_string_pointer, } else { - int count; /* Number of useful digits left to scan. */ + 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; @@ -316,22 +345,14 @@ atof_generic (address_of_string_pointer, precision = (address_of_generic_floating_point_number->high - 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 + + 1); /* Number of destination littlenums. */ + + /* 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) { @@ -349,7 +370,7 @@ atof_generic (address_of_string_pointer, - (long) number_of_digits_to_use); more_than_enough_bits_for_digits - = ((((double) number_of_digits_to_use) * LOG_TO_BASE_2_OF_10) + 1); + = (number_of_digits_to_use * 3321928 / 1000000 + 1); more_than_enough_littlenums_for_digits = (more_than_enough_bits_for_digits @@ -369,11 +390,11 @@ 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); - /* Digits_binary_low[] is allocated and zeroed. */ + /* Digits_binary_low[] is allocated and zeroed. */ /* * Parse the decimal digits as if * digits_low was in the units position. @@ -386,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 (c)) + if (ISDIGIT (c)) { /* * Multiply by 10. Assume can never overflow. @@ -420,16 +441,15 @@ atof_generic (address_of_string_pointer, * We have a GROSS internal error. * This should never happen. */ - as_fatal ("failed sanity check."); + as_fatal (_("failed sanity check")); } } else { - ++count; /* '.' doesn't alter digits used count. */ + ++count; /* '.' doesn't alter digits used count. */ } } - /* * Digits_binary_low[] properly encodes the value of the digits. * Forget about any high-order littlenums that are 0. @@ -458,23 +478,21 @@ 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". */ + /* 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; size_of_power_in_littlenums = precision; - /* Precision has a built-in fudge factor so we get a few guard bits. */ + /* Precision has a built-in fudge factor so we get a few guard bits. */ decimal_exponent_is_negative = decimal_exponent < 0; if (decimal_exponent_is_negative) @@ -482,13 +500,14 @@ atof_generic (address_of_string_pointer, decimal_exponent = -decimal_exponent; } - /* From now on: the decimal exponent is > 0. Its sign is seperate. */ + /* From now on: the decimal exponent is > 0. Its sign is separate. */ 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; @@ -515,7 +534,7 @@ atof_generic (address_of_string_pointer, int place_number_limit; /* Any 10^(2^n) whose "n" exceeds this */ /* value will fall off the end of */ - /* flonum_XXXX_powers_of_ten[]. */ + /* flonum_XXXX_powers_of_ten[]. */ int place_number; const FLONUM_TYPE *multiplicand; /* -> 10^(2^n) */ @@ -525,8 +544,8 @@ atof_generic (address_of_string_pointer, ? flonum_negative_powers_of_ten : flonum_positive_powers_of_ten); - for (place_number = 1;/* Place value of this bit of exponent. */ - decimal_exponent;/* Quit when no more 1 bits in exponent. */ + for (place_number = 1;/* Place value of this bit of exponent. */ + decimal_exponent;/* Quit when no more 1 bits in exponent. */ decimal_exponent >>= 1, place_number++) { if (decimal_exponent & 1) @@ -534,11 +553,11 @@ atof_generic (address_of_string_pointer, if (place_number > place_number_limit) { /* The decimal exponent has a magnitude so great - that our tables can't help us fragment it. - Although this routine is in error because it - can't imagine a number that big, signal an - error as if it is the user's fault for - presenting such a big number. */ + that our tables can't help us fragment it. + Although this routine is in error because it + can't imagine a number that big, signal an + error as if it is the user's fault for + presenting such a big number. */ return_value = ERROR_EXPONENT_OVERFLOW; /* quit out of loop gracefully */ decimal_exponent = 0; @@ -551,20 +570,34 @@ atof_generic (address_of_string_pointer, flonum_print (&power_of_10_flonum); (void) putchar ('\n'); +#endif +#ifdef TRACE + printf ("multiplier:\n"); + flonum_print (multiplicand + place_number); + (void) putchar ('\n'); #endif flonum_multip (multiplicand + place_number, &power_of_10_flonum, &temporary_flonum); +#ifdef TRACE + printf ("after multiply:\n"); + flonum_print (&temporary_flonum); + (void) putchar ('\n'); +#endif flonum_copy (&temporary_flonum, &power_of_10_flonum); +#ifdef TRACE + printf ("after copy:\n"); + flonum_print (&power_of_10_flonum); + (void) putchar ('\n'); +#endif } /* If this bit of decimal_exponent was computable.*/ - } /* If this bit of decimal_exponent was set. */ + } /* If this bit of decimal_exponent was set. */ } /* For each bit of binary representation of exponent */ #ifdef TRACE - printf (" after computing power_of_10_flonum: "); + printf ("after computing power_of_10_flonum:\n"); flonum_print (&power_of_10_flonum); (void) putchar ('\n'); #endif } - } /* @@ -575,11 +608,37 @@ atof_generic (address_of_string_pointer, */ flonum_multip (&power_of_10_flonum, &digits_flonum, address_of_generic_floating_point_number); - /* Assert sign of the number we made is '+'. */ + /* 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; } +#ifdef TRACE +static void +flonum_print (f) + const FLONUM_TYPE *f; +{ + LITTLENUM_TYPE *lp; + char littlenum_format[10]; + sprintf (littlenum_format, " %%0%dx", sizeof (LITTLENUM_TYPE) * 2); +#define print_littlenum(LP) (printf (littlenum_format, LP)) + printf ("flonum @%p %c e%ld", f, f->sign, f->exponent); + if (f->low < f->high) + for (lp = f->high; lp >= f->low; lp--) + print_littlenum (*lp); + else + for (lp = f->low; lp <= f->high; lp++) + print_littlenum (*lp); + printf ("\n"); + fflush (stdout); +} +#endif + /* end of atof_generic.c */