atof-generic.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 635 行 · 第 1/2 页

C
635
字号
/* 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.   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 TRACEstatic 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"}  */intatof_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;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?