/* 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-2019 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 <ctype.h>
-#include <string.h>
+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
#include "as.h"
+#include "safe-ctype.h"
#ifndef FALSE
#define FALSE (0)
#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
*/
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;
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
&& (!c || !strchr (string_of_decimal_exponent_marks, c)));
p++)
{
- if (isdigit ((unsigned char) c))
+ if (ISDIGIT (c))
{
if (seen_significant_digit || c > '0')
{
{
unsigned int zeros = 0; /* Length of current string of zeros */
- for (p++; (c = *p) && isdigit ((unsigned char) c); p++)
+ for (p++; (c = *p) && ISDIGIT (c); p++)
{
if (c == '0')
{
&& (!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++;
for (; (c); c = *++p)
{
- if (isdigit ((unsigned char) c))
+ if (ISDIGIT (c))
{
decimal_exponent = decimal_exponent * 10 + c - '0';
/*
{
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;
+ 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
if (number_of_digits_available > maximum_useful_digits)
{
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
* 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);
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.
{
/*
- * 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;
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;
(void) putchar ('\n');
#endif
}
-
}
/*
/* 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;
}