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 + -
显示快捷键?