diff options
Diffstat (limited to 'contrib/binutils/gas/atof-generic.c')
| -rw-r--r-- | contrib/binutils/gas/atof-generic.c | 636 | 
1 files changed, 0 insertions, 636 deletions
diff --git a/contrib/binutils/gas/atof-generic.c b/contrib/binutils/gas/atof-generic.c deleted file mode 100644 index de29f21341f8d..0000000000000 --- a/contrib/binutils/gas/atof-generic.c +++ /dev/null @@ -1,636 +0,0 @@ -/* atof_generic.c - turn a string of digits into a Flonum -   Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 1998 -   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) -   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. - -   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> - -#include "as.h" - -#ifndef FALSE -#define FALSE (0) -#endif -#ifndef TRUE -#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	* - *	mark and optional decimal exponent (place value) of the		* - *	lowest_order decimal digit: produce a floating point		* - *	number. The number is 'generic' floating point: our		* - *	caller will encode it for a specific machine architecture.	* - *									* - *	Assumptions							* - *		uses base (radix) 2					* - *		this machine uses 2's complement binary integers	* - *		target flonums use "      "         "       "		* - *		target flonums exponents fit in a long			* - *									* - \***********************************************************************/ - -/* - -  Syntax: - -  <flonum> ::= <optional-sign> <decimal-number> <optional-exponent> -  <optional-sign> ::= '+' | '-' | {empty} -  <decimal-number> ::= <integer> -  | <integer> <radix-character> -  | <integer> <radix-character> <integer> -  | <radix-character> <integer> - -  <optional-exponent> ::= {empty} -  | <exponent-character> <optional-sign> <integer> - -  <integer> ::= <digit> | <digit> <integer> -  <digit> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' -  <exponent-character> ::= {one character from "string_of_decimal_exponent_marks"} -  <radix-character> ::= {one character from "string_of_decimal_marks"} - -  */ - -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; -{ -  int return_value;		/* 0 means OK. */ -  char *first_digit; -  unsigned int number_of_digits_before_decimal; -  unsigned int number_of_digits_after_decimal; -  long decimal_exponent; -  unsigned int number_of_digits_available; -  char digits_sign_char; - -  /* -   * Scan the input string, abstracting (1)digits (2)decimal mark (3) exponent. -   * It would be simpler to modify the string, but we don't; just to be nice -   * to caller. -   * We need to know how many digits we have, so we can allocate space for -   * the digits' value. -   */ - -  char *p; -  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; - -  if (c == '-' || c == '+') -    { -      digits_sign_char = c; -      first_digit++; -    } -  else -    digits_sign_char = '+'; - -  switch (first_digit[0]) -    { -    case 'n': -    case 'N': -      if (!strncasecmp ("nan", first_digit, 3)) -	{ -	  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; -	} -      break; - -    case 'i': -    case 'I': -      if (!strncasecmp ("inf", 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; -	} -      break; -    } - -  number_of_digits_before_decimal = 0; -  number_of_digits_after_decimal = 0; -  decimal_exponent = 0; -  seen_significant_digit = 0; -  for (p = first_digit; -       (((c = *p) != '\0') -	&& (!c || !IS_DECIMAL_MARK (c)) -	&& (!c || !strchr (string_of_decimal_exponent_marks, c))); -       p++) -    { -      if (isdigit ((unsigned char) c)) -	{ -	  if (seen_significant_digit || c > '0') -	    { -	      ++number_of_digits_before_decimal; -	      seen_significant_digit = 1; -	    } -	  else -	    { -	      first_digit++; -	    } -	} -      else -	{ -	  break;		/* p -> char after pre-decimal digits. */ -	} -    }				/* 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 && IS_DECIMAL_MARK (c)) -    { -      unsigned int zeros = 0;	/* Length of current string of zeros */ - -      for (p++; (c = *p) && isdigit ((unsigned char) c); p++) -	{ -	  if (c == '0') -	    { -	      zeros++; -	    } -	  else -	    { -	      number_of_digits_after_decimal += 1 + zeros; -	      zeros = 0; -	    } -	} -    } -#else -  if (c && IS_DECIMAL_MARK (c)) -    { -      for (p++; -	   (((c = *p) != '\0') -	    && (!c || !strchr (string_of_decimal_exponent_marks, c))); -	   p++) -	{ -	  if (isdigit ((unsigned char) c)) -	    { -	      /* This may be retracted below. */ -	      number_of_digits_after_decimal++; - -	      if ( /* seen_significant_digit || */ c > '0') -		{ -		  seen_significant_digit = TRUE; -		} -	    } -	  else -	    { -	      if (!seen_significant_digit) -		{ -		  number_of_digits_after_decimal = 0; -		} -	      break; -	    } -	}			/* For each digit after decimal mark. */ -    } - -  while (number_of_digits_after_decimal -	 && first_digit[number_of_digits_before_decimal -			+ number_of_digits_after_decimal] == '0') -    --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; -	  c = *++p; -	} -      else -	{ -	  digits_exponent_sign_char = '+'; -	} - -      for (; (c); c = *++p) -	{ -	  if (isdigit ((unsigned char) c)) -	    { -	      decimal_exponent = decimal_exponent * 10 + c - '0'; -	      /* -	       * BUG! If we overflow here, we lose! -	       */ -	    } -	  else -	    { -	      break; -	    } -	} - -      if (digits_exponent_sign_char == '-') -	{ -	  decimal_exponent = -decimal_exponent; -	} -    } - -  *address_of_string_pointer = p; - - - -  number_of_digits_available = -    number_of_digits_before_decimal + number_of_digits_after_decimal; -  return_value = 0; -  if (number_of_digits_available == 0) -    { -      address_of_generic_floating_point_number->exponent = 0;	/* Not strictly necessary */ -      address_of_generic_floating_point_number->leader -	= -1 + address_of_generic_floating_point_number->low; -      address_of_generic_floating_point_number->sign = digits_sign_char; -      /* We have just concocted (+/-)0.0E0 */ - -    } -  else -    { -      int count;		/* Number of useful digits left to scan. */ - -      LITTLENUM_TYPE *digits_binary_low; -      unsigned int precision; -      unsigned int maximum_useful_digits; -      unsigned int number_of_digits_to_use; -      unsigned int more_than_enough_bits_for_digits; -      unsigned int more_than_enough_littlenums_for_digits; -      unsigned int size_of_digits_in_littlenums; -      unsigned int size_of_digits_in_chars; -      FLONUM_TYPE power_of_10_flonum; -      FLONUM_TYPE digits_flonum; - -      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 - -      if (number_of_digits_available > maximum_useful_digits) -	{ -	  number_of_digits_to_use = maximum_useful_digits; -	} -      else -	{ -	  number_of_digits_to_use = number_of_digits_available; -	} - -      /* Cast these to SIGNED LONG first, otherwise, on systems with -	 LONG wider than INT (such as Alpha OSF/1), unsignedness may -	 cause unexpected results.  */ -      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 -	   / LITTLENUM_NUMBER_OF_BITS) -	+ 2; - -      /* Compute (digits) part. In "12.34E56" this is the "1234" part. -	 Arithmetic is exact here. If no digits are supplied then this -	 part is a 0 valued binary integer.  Allocate room to build up -	 the binary number as littlenums.  We want this memory to -	 disappear when we leave this function.  Assume no alignment -	 problems => (room for n objects) == n * (room for 1 -	 object).  */ - -      size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits; -      size_of_digits_in_chars = size_of_digits_in_littlenums -	* sizeof (LITTLENUM_TYPE); - -      digits_binary_low = (LITTLENUM_TYPE *) -	alloca (size_of_digits_in_chars); - -      memset ((char *) digits_binary_low, '\0', size_of_digits_in_chars); - -      /* Digits_binary_low[] is allocated and zeroed. */ - -      /* -       * Parse the decimal digits as if * digits_low was in the units position. -       * Emit a binary number into digits_binary_low[]. -       * -       * Use a large-precision version of: -       * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit -       */ - -      for (p = first_digit, count = number_of_digits_to_use; count; p++, --count) -	{ -	  c = *p; -	  if (isdigit ((unsigned char) c)) -	    { -	      /* -	       * Multiply by 10. Assume can never overflow. -	       * Add this digit to digits_binary_low[]. -	       */ - -	      long carry; -	      LITTLENUM_TYPE *littlenum_pointer; -	      LITTLENUM_TYPE *littlenum_limit; - -	      littlenum_limit = digits_binary_low -		+ more_than_enough_littlenums_for_digits -		- 1; - -	      carry = c - '0';	/* char -> binary */ - -	      for (littlenum_pointer = digits_binary_low; -		   littlenum_pointer <= littlenum_limit; -		   littlenum_pointer++) -		{ -		  long work; - -		  work = carry + 10 * (long) (*littlenum_pointer); -		  *littlenum_pointer = work & LITTLENUM_MASK; -		  carry = work >> LITTLENUM_NUMBER_OF_BITS; -		} - -	      if (carry != 0) -		{ -		  /* -		   * We have a GROSS internal error. -		   * This should never happen. -		   */ -		  as_fatal (_("failed sanity check.")); -		} -	    } -	  else -	    { -	      ++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. -       */ -      while (digits_binary_low[size_of_digits_in_littlenums - 1] == 0 -	     && size_of_digits_in_littlenums >= 2) -	size_of_digits_in_littlenums--; - -      digits_flonum.low = digits_binary_low; -      digits_flonum.high = digits_binary_low + size_of_digits_in_littlenums - 1; -      digits_flonum.leader = digits_flonum.high; -      digits_flonum.exponent = 0; -      /* -       * The value of digits_flonum . sign should not be important. -       * We have already decided the output's sign. -       * We trust that the sign won't influence the other parts of the number! -       * So we give it a value for these reasons: -       * (1) courtesy to humans reading/debugging -       *     these numbers so they don't get excited about strange values -       * (2) in future there may be more meaning attached to sign, -       *     and what was -       *     harmless noise may become disruptive, ill-conditioned (or worse) -       *     input. -       */ -      digits_flonum.sign = '+'; - -      { -	/* -	 * Compute the mantssa (& exponent) of the power of 10. -	 * If sucessful, 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_littlenums = precision; -	/* 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) -	  { -	    decimal_exponent = -decimal_exponent; -	  } - -	/* 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); -	memset ((char *) power_binary_low, '\0', size_of_power_in_chars); -	*power_binary_low = 1; -	power_of_10_flonum.exponent = 0; -	power_of_10_flonum.low = power_binary_low; -	power_of_10_flonum.leader = power_binary_low; -	power_of_10_flonum.high = power_binary_low + size_of_power_in_littlenums - 1; -	power_of_10_flonum.sign = '+'; -	temporary_flonum.low = temporary_binary_low; -	temporary_flonum.high = temporary_binary_low + size_of_power_in_littlenums - 1; -	/* -	 * (power) == 1. -	 * Space for temporary_flonum allocated. -	 */ - -	/* -	 * ... -	 * -	 * WHILE	more bits -	 * DO	find next bit (with place value) -	 *	multiply into power mantissa -	 * OD -	 */ -	{ -	  int place_number_limit; -	  /* Any 10^(2^n) whose "n" exceeds this */ -	  /* value will fall off the end of */ -	  /* flonum_XXXX_powers_of_ten[]. */ -	  int place_number; -	  const FLONUM_TYPE *multiplicand;	/* -> 10^(2^n) */ - -	  place_number_limit = table_size_of_flonum_powers_of_ten; - -	  multiplicand = (decimal_exponent_is_negative -			  ? 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. */ -	       decimal_exponent >>= 1, place_number++) -	    { -	      if (decimal_exponent & 1) -		{ -		  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.  */ -		      return_value = ERROR_EXPONENT_OVERFLOW; -		      /* quit out of loop gracefully */ -		      decimal_exponent = 0; -		    } -		  else -		    { -#ifdef TRACE -		      printf ("before multiply, place_number = %d., power_of_10_flonum:\n", -			      place_number); - -		      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:\n"); -	  flonum_print (&power_of_10_flonum); -	  (void) putchar ('\n'); -#endif -	} - -      } - -      /* -       * power_of_10_flonum is power of ten in binary (mantissa) , (exponent). -       * It may be the number 1, in which case we don't NEED to multiply. -       * -       * Multiply (decimal digits) by power_of_10_flonum. -       */ - -      flonum_multip (&power_of_10_flonum, &digits_flonum, address_of_generic_floating_point_number); -      /* Assert sign of the number we made is '+'. */ -      address_of_generic_floating_point_number->sign = digits_sign_char; - -    } -  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 */  | 
