📄 atof-generic.c
字号:
/* atof_generic.c - turn a string of digits into a Flonum Copyright (C) 1987 Free Software Foundation, Inc.This file is part of GAS, the GNU Assembler.GAS is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 1, 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GAS; see the file COPYING. If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#include <ctype.h>#include "flonum.h"#ifdef __GNUC__#define alloca __builtin_alloca#else#ifdef sparc#include <alloca.h>#endif#endif#ifdef USG#define bzero(s,n) memset(s,0,n)#define index strchr#endif#define FALSE (0)#define TRUE (1)char *index();/***********************************************************************\* ** 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 int ** *\***********************************************************************//* 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 /* 0 if OK */atof_generic ( address_of_string_pointer, /* return pointer to just AFTER number we read. */ string_of_decimal_marks, /* At most one per number. */ string_of_decimal_exponent_marks, address_of_generic_floating_point_number) char * * address_of_string_pointer; 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; /* char * last_digit; JF unused */ int number_of_digits_before_decimal; int number_of_digits_after_decimal; long int decimal_exponent; 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; first_digit = * address_of_string_pointer; c= *first_digit; if (c=='-' || c=='+') { digits_sign_char = 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')) { 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')) (*address_of_string_pointer)=first_digit+8; else (*address_of_string_pointer)=first_digit+3; return 0; } number_of_digits_before_decimal = 0; number_of_digits_after_decimal = 0; decimal_exponent = 0; seen_significant_digit = FALSE; for (p = first_digit; (c = * p) && (!c || ! index (string_of_decimal_marks, c) ) && (!c || ! index (string_of_decimal_exponent_marks, c) ); p ++) { if (isdigit(c)) { if (seen_significant_digit || c > '0') { number_of_digits_before_decimal ++; seen_significant_digit = TRUE; } else { first_digit++; } } else { break; /* p -> char after pre-decimal digits. */ } } /* For each digit before decimal mark. */ if (c && index (string_of_decimal_marks, c)) { for (p ++; (c = * p) && (!c || ! index (string_of_decimal_exponent_marks, c) ); p ++) { if (isdigit(c)) { number_of_digits_after_decimal ++; /* This may be retracted below. */ 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;/* last_digit = p; JF unused */ if (c && index (string_of_decimal_exponent_marks, c) ) { char digits_exponent_sign_char; c = * ++ p; if (c && index ("+-",c)) { digits_exponent_sign_char = c; c = * ++ p; } else { digits_exponent_sign_char = '+'; } for (; (c); c = * ++ p) { if (isdigit(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 { LITTLENUM_TYPE * digits_binary_low; int precision; int maximum_useful_digits; int number_of_digits_to_use; int more_than_enough_bits_for_digits; int more_than_enough_littlenums_for_digits; int size_of_digits_in_littlenums; int size_of_digits_in_chars; FLONUM_TYPE power_of_10_flonum; FLONUM_TYPE digits_flonum;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -