/* atof_generic.c - turn a string of digits into a Flonum
- Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 1998
+ Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
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. */
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <ctype.h>
#include <string.h>
#include "as.h"
-#ifdef __GNUC__
-#define alloca __builtin_alloca
-#else
-#ifdef sparc
-#include <alloca.h>
-#endif
-#endif
-
#ifndef FALSE
#define FALSE (0)
#endif
#define TRUE (1)
#endif
+#ifdef TRACE
+static void flonum_print PARAMS ((const FLONUM_TYPE *));
+#endif
+
+#define ASSUME_DECIMAL_MARK_IS_DOT
+
/***********************************************************************\
* *
* Given a string of decimal digits , with optional decimal *
{
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;
/*
char c;
int seen_significant_digit;
+#ifdef ASSUME_DECIMAL_MARK_IS_DOT
+ 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;
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'))
+ switch (first_digit[0])
{
- 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'))
- {
- 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;
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 ((unsigned char) c))
{
if (seen_significant_digit || c > '0')
{
* come out inexact for some reason related to length of the digit
* string.
*/
- if (c && strchr (string_of_decimal_marks, c))
+ 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++)
+ for (p++; (c = *p) && isdigit ((unsigned char) c); p++)
{
if (c == '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 ((unsigned char) c))
{
/* This may be retracted below. */
number_of_digits_after_decimal++;
--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;
for (; (c); c = *++p)
{
- if (isdigit (c))
+ if (isdigit ((unsigned char) c))
{
decimal_exponent = decimal_exponent * 10 + c - '0';
/*
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
for (p = first_digit, count = number_of_digits_to_use; count; p++, --count)
{
c = *p;
- if (isdigit (c))
+ if (isdigit ((unsigned char) c))
{
/*
* Multiply by 10. Assume can never overflow.
* We have a GROSS internal error.
* This should never happen.
*/
- as_fatal ("failed sanity check.");
+ as_fatal (_("failed sanity check."));
}
}
else
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;
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;
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. */
} /* 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
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 */