133965Sjdp/* atof_generic.c - turn a string of digits into a Flonum 2218822Sdim Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2000, 3218822Sdim 2001, 2003, 2005, 2006 Free Software Foundation, Inc. 433965Sjdp 533965Sjdp This file is part of GAS, the GNU Assembler. 633965Sjdp 733965Sjdp GAS is free software; you can redistribute it and/or modify 833965Sjdp it under the terms of the GNU General Public License as published by 933965Sjdp the Free Software Foundation; either version 2, or (at your option) 1033965Sjdp any later version. 1133965Sjdp 1233965Sjdp GAS is distributed in the hope that it will be useful, 1333965Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1433965Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1533965Sjdp GNU General Public License for more details. 1633965Sjdp 1733965Sjdp You should have received a copy of the GNU General Public License 1877298Sobrien along with GAS; see the file COPYING. If not, write to the Free 19218822Sdim Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 20218822Sdim 02110-1301, USA. */ 2133965Sjdp 2233965Sjdp#include "as.h" 2389857Sobrien#include "safe-ctype.h" 2433965Sjdp 2533965Sjdp#ifndef FALSE 2633965Sjdp#define FALSE (0) 2733965Sjdp#endif 2833965Sjdp#ifndef TRUE 2933965Sjdp#define TRUE (1) 3033965Sjdp#endif 3133965Sjdp 3233965Sjdp#ifdef TRACE 33130561Sobrienstatic void flonum_print (const FLONUM_TYPE *); 3433965Sjdp#endif 3533965Sjdp 3633965Sjdp#define ASSUME_DECIMAL_MARK_IS_DOT 3733965Sjdp 3833965Sjdp/***********************************************************************\ 3933965Sjdp * * 4033965Sjdp * Given a string of decimal digits , with optional decimal * 4133965Sjdp * mark and optional decimal exponent (place value) of the * 4233965Sjdp * lowest_order decimal digit: produce a floating point * 4333965Sjdp * number. The number is 'generic' floating point: our * 4433965Sjdp * caller will encode it for a specific machine architecture. * 4533965Sjdp * * 4633965Sjdp * Assumptions * 4733965Sjdp * uses base (radix) 2 * 4833965Sjdp * this machine uses 2's complement binary integers * 4933965Sjdp * target flonums use " " " " * 5033965Sjdp * target flonums exponents fit in a long * 5133965Sjdp * * 5233965Sjdp \***********************************************************************/ 5333965Sjdp 5433965Sjdp/* 5533965Sjdp 5633965Sjdp Syntax: 5733965Sjdp 5833965Sjdp <flonum> ::= <optional-sign> <decimal-number> <optional-exponent> 5933965Sjdp <optional-sign> ::= '+' | '-' | {empty} 6033965Sjdp <decimal-number> ::= <integer> 6133965Sjdp | <integer> <radix-character> 6233965Sjdp | <integer> <radix-character> <integer> 6333965Sjdp | <radix-character> <integer> 6433965Sjdp 6533965Sjdp <optional-exponent> ::= {empty} 6633965Sjdp | <exponent-character> <optional-sign> <integer> 6733965Sjdp 6833965Sjdp <integer> ::= <digit> | <digit> <integer> 6933965Sjdp <digit> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' 7033965Sjdp <exponent-character> ::= {one character from "string_of_decimal_exponent_marks"} 7133965Sjdp <radix-character> ::= {one character from "string_of_decimal_marks"} 7233965Sjdp 7333965Sjdp */ 7433965Sjdp 7533965Sjdpint 76130561Sobrienatof_generic (/* return pointer to just AFTER number we read. */ 77130561Sobrien char **address_of_string_pointer, 78130561Sobrien /* At most one per number. */ 79130561Sobrien const char *string_of_decimal_marks, 80130561Sobrien const char *string_of_decimal_exponent_marks, 81130561Sobrien FLONUM_TYPE *address_of_generic_floating_point_number) 8233965Sjdp{ 8377298Sobrien int return_value; /* 0 means OK. */ 8433965Sjdp char *first_digit; 8538889Sjdp unsigned int number_of_digits_before_decimal; 8638889Sjdp unsigned int number_of_digits_after_decimal; 8733965Sjdp long decimal_exponent; 8838889Sjdp unsigned int number_of_digits_available; 8933965Sjdp char digits_sign_char; 9033965Sjdp 9133965Sjdp /* 9233965Sjdp * Scan the input string, abstracting (1)digits (2)decimal mark (3) exponent. 9333965Sjdp * It would be simpler to modify the string, but we don't; just to be nice 9433965Sjdp * to caller. 9533965Sjdp * We need to know how many digits we have, so we can allocate space for 9633965Sjdp * the digits' value. 9733965Sjdp */ 9833965Sjdp 9933965Sjdp char *p; 10033965Sjdp char c; 10133965Sjdp int seen_significant_digit; 10233965Sjdp 10333965Sjdp#ifdef ASSUME_DECIMAL_MARK_IS_DOT 10433965Sjdp assert (string_of_decimal_marks[0] == '.' 10533965Sjdp && string_of_decimal_marks[1] == 0); 10633965Sjdp#define IS_DECIMAL_MARK(c) ((c) == '.') 10733965Sjdp#else 10833965Sjdp#define IS_DECIMAL_MARK(c) (0 != strchr (string_of_decimal_marks, (c))) 10933965Sjdp#endif 11033965Sjdp 11133965Sjdp first_digit = *address_of_string_pointer; 11233965Sjdp c = *first_digit; 11333965Sjdp 11433965Sjdp if (c == '-' || c == '+') 11533965Sjdp { 11633965Sjdp digits_sign_char = c; 11733965Sjdp first_digit++; 11833965Sjdp } 11933965Sjdp else 12033965Sjdp digits_sign_char = '+'; 12133965Sjdp 12233965Sjdp switch (first_digit[0]) 12333965Sjdp { 12433965Sjdp case 'n': 12533965Sjdp case 'N': 12633965Sjdp if (!strncasecmp ("nan", first_digit, 3)) 12733965Sjdp { 12833965Sjdp address_of_generic_floating_point_number->sign = 0; 12933965Sjdp address_of_generic_floating_point_number->exponent = 0; 13033965Sjdp address_of_generic_floating_point_number->leader = 13133965Sjdp address_of_generic_floating_point_number->low; 13233965Sjdp *address_of_string_pointer = first_digit + 3; 13333965Sjdp return 0; 13433965Sjdp } 13533965Sjdp break; 13633965Sjdp 13733965Sjdp case 'i': 13833965Sjdp case 'I': 13933965Sjdp if (!strncasecmp ("inf", first_digit, 3)) 14033965Sjdp { 14133965Sjdp address_of_generic_floating_point_number->sign = 14233965Sjdp digits_sign_char == '+' ? 'P' : 'N'; 14333965Sjdp address_of_generic_floating_point_number->exponent = 0; 14433965Sjdp address_of_generic_floating_point_number->leader = 14533965Sjdp address_of_generic_floating_point_number->low; 14633965Sjdp 14733965Sjdp first_digit += 3; 14833965Sjdp if (!strncasecmp ("inity", first_digit, 5)) 14933965Sjdp first_digit += 5; 15033965Sjdp 15133965Sjdp *address_of_string_pointer = first_digit; 15233965Sjdp 15333965Sjdp return 0; 15433965Sjdp } 15533965Sjdp break; 15633965Sjdp } 15733965Sjdp 15833965Sjdp number_of_digits_before_decimal = 0; 15933965Sjdp number_of_digits_after_decimal = 0; 16033965Sjdp decimal_exponent = 0; 16133965Sjdp seen_significant_digit = 0; 16233965Sjdp for (p = first_digit; 16333965Sjdp (((c = *p) != '\0') 16433965Sjdp && (!c || !IS_DECIMAL_MARK (c)) 16533965Sjdp && (!c || !strchr (string_of_decimal_exponent_marks, c))); 16633965Sjdp p++) 16733965Sjdp { 16889857Sobrien if (ISDIGIT (c)) 16933965Sjdp { 17033965Sjdp if (seen_significant_digit || c > '0') 17133965Sjdp { 17233965Sjdp ++number_of_digits_before_decimal; 17333965Sjdp seen_significant_digit = 1; 17433965Sjdp } 17533965Sjdp else 17633965Sjdp { 17733965Sjdp first_digit++; 17833965Sjdp } 17933965Sjdp } 18033965Sjdp else 18133965Sjdp { 18277298Sobrien break; /* p -> char after pre-decimal digits. */ 18333965Sjdp } 18477298Sobrien } /* For each digit before decimal mark. */ 18533965Sjdp 18633965Sjdp#ifndef OLD_FLOAT_READS 18733965Sjdp /* Ignore trailing 0's after the decimal point. The original code here 18833965Sjdp * (ifdef'd out) does not do this, and numbers like 18933965Sjdp * 4.29496729600000000000e+09 (2**31) 19033965Sjdp * come out inexact for some reason related to length of the digit 19133965Sjdp * string. 19233965Sjdp */ 19333965Sjdp if (c && IS_DECIMAL_MARK (c)) 19433965Sjdp { 19538889Sjdp unsigned int zeros = 0; /* Length of current string of zeros */ 19633965Sjdp 19789857Sobrien for (p++; (c = *p) && ISDIGIT (c); p++) 19833965Sjdp { 19933965Sjdp if (c == '0') 20033965Sjdp { 20133965Sjdp zeros++; 20233965Sjdp } 20333965Sjdp else 20433965Sjdp { 20533965Sjdp number_of_digits_after_decimal += 1 + zeros; 20633965Sjdp zeros = 0; 20733965Sjdp } 20833965Sjdp } 20933965Sjdp } 21033965Sjdp#else 21133965Sjdp if (c && IS_DECIMAL_MARK (c)) 21233965Sjdp { 21333965Sjdp for (p++; 21433965Sjdp (((c = *p) != '\0') 21533965Sjdp && (!c || !strchr (string_of_decimal_exponent_marks, c))); 21633965Sjdp p++) 21733965Sjdp { 21889857Sobrien if (ISDIGIT (c)) 21933965Sjdp { 22077298Sobrien /* This may be retracted below. */ 22133965Sjdp number_of_digits_after_decimal++; 22233965Sjdp 22333965Sjdp if ( /* seen_significant_digit || */ c > '0') 22433965Sjdp { 22533965Sjdp seen_significant_digit = TRUE; 22633965Sjdp } 22733965Sjdp } 22833965Sjdp else 22933965Sjdp { 23033965Sjdp if (!seen_significant_digit) 23133965Sjdp { 23233965Sjdp number_of_digits_after_decimal = 0; 23333965Sjdp } 23433965Sjdp break; 23533965Sjdp } 23677298Sobrien } /* For each digit after decimal mark. */ 23733965Sjdp } 23833965Sjdp 23933965Sjdp while (number_of_digits_after_decimal 24033965Sjdp && first_digit[number_of_digits_before_decimal 24133965Sjdp + number_of_digits_after_decimal] == '0') 24233965Sjdp --number_of_digits_after_decimal; 24333965Sjdp#endif 24433965Sjdp 24533965Sjdp if (flag_m68k_mri) 24633965Sjdp { 24733965Sjdp while (c == '_') 24833965Sjdp c = *++p; 24933965Sjdp } 25033965Sjdp if (c && strchr (string_of_decimal_exponent_marks, c)) 25133965Sjdp { 25233965Sjdp char digits_exponent_sign_char; 25333965Sjdp 25433965Sjdp c = *++p; 25533965Sjdp if (flag_m68k_mri) 25633965Sjdp { 25733965Sjdp while (c == '_') 25833965Sjdp c = *++p; 25933965Sjdp } 26033965Sjdp if (c && strchr ("+-", c)) 26133965Sjdp { 26233965Sjdp digits_exponent_sign_char = c; 26333965Sjdp c = *++p; 26433965Sjdp } 26533965Sjdp else 26633965Sjdp { 26733965Sjdp digits_exponent_sign_char = '+'; 26833965Sjdp } 26933965Sjdp 27033965Sjdp for (; (c); c = *++p) 27133965Sjdp { 27289857Sobrien if (ISDIGIT (c)) 27333965Sjdp { 27433965Sjdp decimal_exponent = decimal_exponent * 10 + c - '0'; 27533965Sjdp /* 27633965Sjdp * BUG! If we overflow here, we lose! 27733965Sjdp */ 27833965Sjdp } 27933965Sjdp else 28033965Sjdp { 28133965Sjdp break; 28233965Sjdp } 28333965Sjdp } 28433965Sjdp 28533965Sjdp if (digits_exponent_sign_char == '-') 28633965Sjdp { 28733965Sjdp decimal_exponent = -decimal_exponent; 28833965Sjdp } 28933965Sjdp } 29033965Sjdp 29133965Sjdp *address_of_string_pointer = p; 29233965Sjdp 29333965Sjdp number_of_digits_available = 29433965Sjdp number_of_digits_before_decimal + number_of_digits_after_decimal; 29533965Sjdp return_value = 0; 29633965Sjdp if (number_of_digits_available == 0) 29733965Sjdp { 29833965Sjdp address_of_generic_floating_point_number->exponent = 0; /* Not strictly necessary */ 29933965Sjdp address_of_generic_floating_point_number->leader 30033965Sjdp = -1 + address_of_generic_floating_point_number->low; 30133965Sjdp address_of_generic_floating_point_number->sign = digits_sign_char; 30233965Sjdp /* We have just concocted (+/-)0.0E0 */ 30333965Sjdp 30433965Sjdp } 30533965Sjdp else 30633965Sjdp { 30777298Sobrien int count; /* Number of useful digits left to scan. */ 30833965Sjdp 30933965Sjdp LITTLENUM_TYPE *digits_binary_low; 31033965Sjdp unsigned int precision; 31133965Sjdp unsigned int maximum_useful_digits; 31233965Sjdp unsigned int number_of_digits_to_use; 31333965Sjdp unsigned int more_than_enough_bits_for_digits; 31433965Sjdp unsigned int more_than_enough_littlenums_for_digits; 31533965Sjdp unsigned int size_of_digits_in_littlenums; 31633965Sjdp unsigned int size_of_digits_in_chars; 31733965Sjdp FLONUM_TYPE power_of_10_flonum; 31833965Sjdp FLONUM_TYPE digits_flonum; 31933965Sjdp 32033965Sjdp precision = (address_of_generic_floating_point_number->high 32133965Sjdp - address_of_generic_floating_point_number->low 32277298Sobrien + 1); /* Number of destination littlenums. */ 32333965Sjdp 32433965Sjdp /* Includes guard bits (two littlenums worth) */ 32533965Sjdp maximum_useful_digits = (((precision - 2)) 32633965Sjdp * ( (LITTLENUM_NUMBER_OF_BITS)) 32733965Sjdp * 1000000 / 3321928) 32877298Sobrien + 2; /* 2 :: guard digits. */ 32933965Sjdp 33033965Sjdp if (number_of_digits_available > maximum_useful_digits) 33133965Sjdp { 33233965Sjdp number_of_digits_to_use = maximum_useful_digits; 33333965Sjdp } 33433965Sjdp else 33533965Sjdp { 33633965Sjdp number_of_digits_to_use = number_of_digits_available; 33733965Sjdp } 33833965Sjdp 33933965Sjdp /* Cast these to SIGNED LONG first, otherwise, on systems with 34033965Sjdp LONG wider than INT (such as Alpha OSF/1), unsignedness may 34133965Sjdp cause unexpected results. */ 34233965Sjdp decimal_exponent += ((long) number_of_digits_before_decimal 34333965Sjdp - (long) number_of_digits_to_use); 34433965Sjdp 34533965Sjdp more_than_enough_bits_for_digits 34633965Sjdp = (number_of_digits_to_use * 3321928 / 1000000 + 1); 34733965Sjdp 34833965Sjdp more_than_enough_littlenums_for_digits 34933965Sjdp = (more_than_enough_bits_for_digits 35033965Sjdp / LITTLENUM_NUMBER_OF_BITS) 35133965Sjdp + 2; 35233965Sjdp 35333965Sjdp /* Compute (digits) part. In "12.34E56" this is the "1234" part. 35433965Sjdp Arithmetic is exact here. If no digits are supplied then this 35533965Sjdp part is a 0 valued binary integer. Allocate room to build up 35633965Sjdp the binary number as littlenums. We want this memory to 35733965Sjdp disappear when we leave this function. Assume no alignment 35833965Sjdp problems => (room for n objects) == n * (room for 1 35933965Sjdp object). */ 36033965Sjdp 36133965Sjdp size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits; 36233965Sjdp size_of_digits_in_chars = size_of_digits_in_littlenums 36333965Sjdp * sizeof (LITTLENUM_TYPE); 36433965Sjdp 36533965Sjdp digits_binary_low = (LITTLENUM_TYPE *) 36633965Sjdp alloca (size_of_digits_in_chars); 36733965Sjdp 36833965Sjdp memset ((char *) digits_binary_low, '\0', size_of_digits_in_chars); 36933965Sjdp 37077298Sobrien /* Digits_binary_low[] is allocated and zeroed. */ 37133965Sjdp 37233965Sjdp /* 37333965Sjdp * Parse the decimal digits as if * digits_low was in the units position. 37433965Sjdp * Emit a binary number into digits_binary_low[]. 37533965Sjdp * 37633965Sjdp * Use a large-precision version of: 37733965Sjdp * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit 37833965Sjdp */ 37933965Sjdp 38033965Sjdp for (p = first_digit, count = number_of_digits_to_use; count; p++, --count) 38133965Sjdp { 38233965Sjdp c = *p; 38389857Sobrien if (ISDIGIT (c)) 38433965Sjdp { 38533965Sjdp /* 38633965Sjdp * Multiply by 10. Assume can never overflow. 38733965Sjdp * Add this digit to digits_binary_low[]. 38833965Sjdp */ 38933965Sjdp 39033965Sjdp long carry; 39133965Sjdp LITTLENUM_TYPE *littlenum_pointer; 39233965Sjdp LITTLENUM_TYPE *littlenum_limit; 39333965Sjdp 39433965Sjdp littlenum_limit = digits_binary_low 39533965Sjdp + more_than_enough_littlenums_for_digits 39633965Sjdp - 1; 39733965Sjdp 39833965Sjdp carry = c - '0'; /* char -> binary */ 39933965Sjdp 40033965Sjdp for (littlenum_pointer = digits_binary_low; 40133965Sjdp littlenum_pointer <= littlenum_limit; 40233965Sjdp littlenum_pointer++) 40333965Sjdp { 40433965Sjdp long work; 40533965Sjdp 40633965Sjdp work = carry + 10 * (long) (*littlenum_pointer); 40733965Sjdp *littlenum_pointer = work & LITTLENUM_MASK; 40833965Sjdp carry = work >> LITTLENUM_NUMBER_OF_BITS; 40933965Sjdp } 41033965Sjdp 41133965Sjdp if (carry != 0) 41233965Sjdp { 41333965Sjdp /* 41433965Sjdp * We have a GROSS internal error. 41533965Sjdp * This should never happen. 41633965Sjdp */ 41789857Sobrien as_fatal (_("failed sanity check")); 41833965Sjdp } 41933965Sjdp } 42033965Sjdp else 42133965Sjdp { 42277298Sobrien ++count; /* '.' doesn't alter digits used count. */ 42333965Sjdp } 42433965Sjdp } 42533965Sjdp 42633965Sjdp /* 42733965Sjdp * Digits_binary_low[] properly encodes the value of the digits. 42833965Sjdp * Forget about any high-order littlenums that are 0. 42933965Sjdp */ 43033965Sjdp while (digits_binary_low[size_of_digits_in_littlenums - 1] == 0 43133965Sjdp && size_of_digits_in_littlenums >= 2) 43233965Sjdp size_of_digits_in_littlenums--; 43333965Sjdp 43433965Sjdp digits_flonum.low = digits_binary_low; 43533965Sjdp digits_flonum.high = digits_binary_low + size_of_digits_in_littlenums - 1; 43633965Sjdp digits_flonum.leader = digits_flonum.high; 43733965Sjdp digits_flonum.exponent = 0; 43833965Sjdp /* 43933965Sjdp * The value of digits_flonum . sign should not be important. 44033965Sjdp * We have already decided the output's sign. 44133965Sjdp * We trust that the sign won't influence the other parts of the number! 44233965Sjdp * So we give it a value for these reasons: 44333965Sjdp * (1) courtesy to humans reading/debugging 44433965Sjdp * these numbers so they don't get excited about strange values 44533965Sjdp * (2) in future there may be more meaning attached to sign, 44633965Sjdp * and what was 44733965Sjdp * harmless noise may become disruptive, ill-conditioned (or worse) 44833965Sjdp * input. 44933965Sjdp */ 45033965Sjdp digits_flonum.sign = '+'; 45133965Sjdp 45233965Sjdp { 45333965Sjdp /* 45433965Sjdp * Compute the mantssa (& exponent) of the power of 10. 455130561Sobrien * If successful, then multiply the power of 10 by the digits 45633965Sjdp * giving return_binary_mantissa and return_binary_exponent. 45733965Sjdp */ 45833965Sjdp 45933965Sjdp LITTLENUM_TYPE *power_binary_low; 46033965Sjdp int decimal_exponent_is_negative; 46177298Sobrien /* This refers to the "-56" in "12.34E-56". */ 46233965Sjdp /* FALSE: decimal_exponent is positive (or 0) */ 46333965Sjdp /* TRUE: decimal_exponent is negative */ 46433965Sjdp FLONUM_TYPE temporary_flonum; 46533965Sjdp LITTLENUM_TYPE *temporary_binary_low; 46633965Sjdp unsigned int size_of_power_in_littlenums; 46733965Sjdp unsigned int size_of_power_in_chars; 46833965Sjdp 46933965Sjdp size_of_power_in_littlenums = precision; 47077298Sobrien /* Precision has a built-in fudge factor so we get a few guard bits. */ 47133965Sjdp 47233965Sjdp decimal_exponent_is_negative = decimal_exponent < 0; 47333965Sjdp if (decimal_exponent_is_negative) 47433965Sjdp { 47533965Sjdp decimal_exponent = -decimal_exponent; 47633965Sjdp } 47733965Sjdp 47877298Sobrien /* From now on: the decimal exponent is > 0. Its sign is separate. */ 47933965Sjdp 48033965Sjdp size_of_power_in_chars = size_of_power_in_littlenums 48133965Sjdp * sizeof (LITTLENUM_TYPE) + 2; 48233965Sjdp 48333965Sjdp power_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars); 48433965Sjdp temporary_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars); 48533965Sjdp memset ((char *) power_binary_low, '\0', size_of_power_in_chars); 48633965Sjdp *power_binary_low = 1; 48733965Sjdp power_of_10_flonum.exponent = 0; 48833965Sjdp power_of_10_flonum.low = power_binary_low; 48933965Sjdp power_of_10_flonum.leader = power_binary_low; 49033965Sjdp power_of_10_flonum.high = power_binary_low + size_of_power_in_littlenums - 1; 49133965Sjdp power_of_10_flonum.sign = '+'; 49233965Sjdp temporary_flonum.low = temporary_binary_low; 49333965Sjdp temporary_flonum.high = temporary_binary_low + size_of_power_in_littlenums - 1; 49433965Sjdp /* 49533965Sjdp * (power) == 1. 49633965Sjdp * Space for temporary_flonum allocated. 49733965Sjdp */ 49833965Sjdp 49933965Sjdp /* 50033965Sjdp * ... 50133965Sjdp * 50233965Sjdp * WHILE more bits 50333965Sjdp * DO find next bit (with place value) 50433965Sjdp * multiply into power mantissa 50533965Sjdp * OD 50633965Sjdp */ 50733965Sjdp { 50833965Sjdp int place_number_limit; 50933965Sjdp /* Any 10^(2^n) whose "n" exceeds this */ 51033965Sjdp /* value will fall off the end of */ 51177298Sobrien /* flonum_XXXX_powers_of_ten[]. */ 51233965Sjdp int place_number; 51333965Sjdp const FLONUM_TYPE *multiplicand; /* -> 10^(2^n) */ 51433965Sjdp 51533965Sjdp place_number_limit = table_size_of_flonum_powers_of_ten; 51633965Sjdp 51733965Sjdp multiplicand = (decimal_exponent_is_negative 51833965Sjdp ? flonum_negative_powers_of_ten 51933965Sjdp : flonum_positive_powers_of_ten); 52033965Sjdp 52177298Sobrien for (place_number = 1;/* Place value of this bit of exponent. */ 52277298Sobrien decimal_exponent;/* Quit when no more 1 bits in exponent. */ 52333965Sjdp decimal_exponent >>= 1, place_number++) 52433965Sjdp { 52533965Sjdp if (decimal_exponent & 1) 52633965Sjdp { 52733965Sjdp if (place_number > place_number_limit) 52833965Sjdp { 52933965Sjdp /* The decimal exponent has a magnitude so great 53033965Sjdp that our tables can't help us fragment it. 53133965Sjdp Although this routine is in error because it 53233965Sjdp can't imagine a number that big, signal an 53333965Sjdp error as if it is the user's fault for 53433965Sjdp presenting such a big number. */ 53533965Sjdp return_value = ERROR_EXPONENT_OVERFLOW; 53633965Sjdp /* quit out of loop gracefully */ 53733965Sjdp decimal_exponent = 0; 53833965Sjdp } 53933965Sjdp else 54033965Sjdp { 54133965Sjdp#ifdef TRACE 54233965Sjdp printf ("before multiply, place_number = %d., power_of_10_flonum:\n", 54333965Sjdp place_number); 54433965Sjdp 54533965Sjdp flonum_print (&power_of_10_flonum); 54633965Sjdp (void) putchar ('\n'); 54733965Sjdp#endif 54833965Sjdp#ifdef TRACE 54933965Sjdp printf ("multiplier:\n"); 55033965Sjdp flonum_print (multiplicand + place_number); 55133965Sjdp (void) putchar ('\n'); 55233965Sjdp#endif 55333965Sjdp flonum_multip (multiplicand + place_number, 55433965Sjdp &power_of_10_flonum, &temporary_flonum); 55533965Sjdp#ifdef TRACE 55633965Sjdp printf ("after multiply:\n"); 55733965Sjdp flonum_print (&temporary_flonum); 55833965Sjdp (void) putchar ('\n'); 55933965Sjdp#endif 56033965Sjdp flonum_copy (&temporary_flonum, &power_of_10_flonum); 56133965Sjdp#ifdef TRACE 56233965Sjdp printf ("after copy:\n"); 56333965Sjdp flonum_print (&power_of_10_flonum); 56433965Sjdp (void) putchar ('\n'); 56533965Sjdp#endif 56633965Sjdp } /* If this bit of decimal_exponent was computable.*/ 56777298Sobrien } /* If this bit of decimal_exponent was set. */ 56833965Sjdp } /* For each bit of binary representation of exponent */ 56933965Sjdp#ifdef TRACE 57033965Sjdp printf ("after computing power_of_10_flonum:\n"); 57133965Sjdp flonum_print (&power_of_10_flonum); 57233965Sjdp (void) putchar ('\n'); 57333965Sjdp#endif 57433965Sjdp } 57533965Sjdp 57633965Sjdp } 57733965Sjdp 57833965Sjdp /* 57933965Sjdp * power_of_10_flonum is power of ten in binary (mantissa) , (exponent). 58033965Sjdp * It may be the number 1, in which case we don't NEED to multiply. 58133965Sjdp * 58233965Sjdp * Multiply (decimal digits) by power_of_10_flonum. 58333965Sjdp */ 58433965Sjdp 58533965Sjdp flonum_multip (&power_of_10_flonum, &digits_flonum, address_of_generic_floating_point_number); 58677298Sobrien /* Assert sign of the number we made is '+'. */ 58733965Sjdp address_of_generic_floating_point_number->sign = digits_sign_char; 58833965Sjdp 58933965Sjdp } 59033965Sjdp return return_value; 59133965Sjdp} 59233965Sjdp 59333965Sjdp#ifdef TRACE 59433965Sjdpstatic void 59533965Sjdpflonum_print (f) 59633965Sjdp const FLONUM_TYPE *f; 59733965Sjdp{ 59833965Sjdp LITTLENUM_TYPE *lp; 59933965Sjdp char littlenum_format[10]; 60033965Sjdp sprintf (littlenum_format, " %%0%dx", sizeof (LITTLENUM_TYPE) * 2); 60133965Sjdp#define print_littlenum(LP) (printf (littlenum_format, LP)) 60233965Sjdp printf ("flonum @%p %c e%ld", f, f->sign, f->exponent); 60333965Sjdp if (f->low < f->high) 60433965Sjdp for (lp = f->high; lp >= f->low; lp--) 60533965Sjdp print_littlenum (*lp); 60633965Sjdp else 60733965Sjdp for (lp = f->low; lp <= f->high; lp++) 60833965Sjdp print_littlenum (*lp); 60933965Sjdp printf ("\n"); 61033965Sjdp fflush (stdout); 61133965Sjdp} 61233965Sjdp#endif 61333965Sjdp 61433965Sjdp/* end of atof_generic.c */ 615