1 1.1 christos /* atof_generic.c - turn a string of digits into a Flonum 2 1.10 christos Copyright (C) 1987-2025 Free Software Foundation, Inc. 3 1.1 christos 4 1.1 christos This file is part of GAS, the GNU Assembler. 5 1.1 christos 6 1.1 christos GAS is free software; you can redistribute it and/or modify 7 1.1 christos it under the terms of the GNU General Public License as published by 8 1.1 christos the Free Software Foundation; either version 3, or (at your option) 9 1.1 christos any later version. 10 1.1 christos 11 1.1 christos GAS is distributed in the hope that it will be useful, but WITHOUT 12 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 1.1 christos License for more details. 15 1.1 christos 16 1.1 christos You should have received a copy of the GNU General Public License 17 1.1 christos along with GAS; see the file COPYING. If not, write to the Free 18 1.1 christos Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 19 1.1 christos 02110-1301, USA. */ 20 1.1 christos 21 1.1 christos #include "as.h" 22 1.1 christos #include "safe-ctype.h" 23 1.8 christos #include <limits.h> 24 1.1 christos 25 1.1 christos #ifdef TRACE 26 1.1 christos static void flonum_print (const FLONUM_TYPE *); 27 1.1 christos #endif 28 1.1 christos 29 1.1 christos #define ASSUME_DECIMAL_MARK_IS_DOT 30 1.1 christos 31 1.1 christos /***********************************************************************\ 32 1.1 christos * * 33 1.1 christos * Given a string of decimal digits , with optional decimal * 34 1.1 christos * mark and optional decimal exponent (place value) of the * 35 1.1 christos * lowest_order decimal digit: produce a floating point * 36 1.1 christos * number. The number is 'generic' floating point: our * 37 1.1 christos * caller will encode it for a specific machine architecture. * 38 1.1 christos * * 39 1.1 christos * Assumptions * 40 1.1 christos * uses base (radix) 2 * 41 1.1 christos * this machine uses 2's complement binary integers * 42 1.1 christos * target flonums use " " " " * 43 1.1 christos * target flonums exponents fit in a long * 44 1.1 christos * * 45 1.1 christos \***********************************************************************/ 46 1.1 christos 47 1.1 christos /* 48 1.1 christos 49 1.1 christos Syntax: 50 1.1 christos 51 1.1 christos <flonum> ::= <optional-sign> <decimal-number> <optional-exponent> 52 1.1 christos <optional-sign> ::= '+' | '-' | {empty} 53 1.1 christos <decimal-number> ::= <integer> 54 1.1 christos | <integer> <radix-character> 55 1.1 christos | <integer> <radix-character> <integer> 56 1.1 christos | <radix-character> <integer> 57 1.1 christos 58 1.1 christos <optional-exponent> ::= {empty} 59 1.1 christos | <exponent-character> <optional-sign> <integer> 60 1.1 christos 61 1.1 christos <integer> ::= <digit> | <digit> <integer> 62 1.1 christos <digit> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' 63 1.1 christos <exponent-character> ::= {one character from "string_of_decimal_exponent_marks"} 64 1.1 christos <radix-character> ::= {one character from "string_of_decimal_marks"} 65 1.1 christos 66 1.1 christos */ 67 1.1 christos 68 1.1 christos int 69 1.1 christos atof_generic (/* return pointer to just AFTER number we read. */ 70 1.1 christos char **address_of_string_pointer, 71 1.1 christos /* At most one per number. */ 72 1.1 christos const char *string_of_decimal_marks, 73 1.1 christos const char *string_of_decimal_exponent_marks, 74 1.1 christos FLONUM_TYPE *address_of_generic_floating_point_number) 75 1.1 christos { 76 1.8 christos int return_value = 0; /* 0 means OK. */ 77 1.1 christos char *first_digit; 78 1.1 christos unsigned int number_of_digits_before_decimal; 79 1.1 christos unsigned int number_of_digits_after_decimal; 80 1.8 christos unsigned long decimal_exponent; 81 1.1 christos unsigned int number_of_digits_available; 82 1.1 christos char digits_sign_char; 83 1.1 christos 84 1.1 christos /* 85 1.1 christos * Scan the input string, abstracting (1)digits (2)decimal mark (3) exponent. 86 1.1 christos * It would be simpler to modify the string, but we don't; just to be nice 87 1.1 christos * to caller. 88 1.1 christos * We need to know how many digits we have, so we can allocate space for 89 1.1 christos * the digits' value. 90 1.1 christos */ 91 1.1 christos 92 1.1 christos char *p; 93 1.1 christos char c; 94 1.1 christos int seen_significant_digit; 95 1.1 christos 96 1.1 christos #ifdef ASSUME_DECIMAL_MARK_IS_DOT 97 1.1 christos gas_assert (string_of_decimal_marks[0] == '.' 98 1.1 christos && string_of_decimal_marks[1] == 0); 99 1.1 christos #define IS_DECIMAL_MARK(c) ((c) == '.') 100 1.1 christos #else 101 1.1 christos #define IS_DECIMAL_MARK(c) (0 != strchr (string_of_decimal_marks, (c))) 102 1.1 christos #endif 103 1.1 christos 104 1.1 christos first_digit = *address_of_string_pointer; 105 1.1 christos c = *first_digit; 106 1.1 christos 107 1.1 christos if (c == '-' || c == '+') 108 1.1 christos { 109 1.1 christos digits_sign_char = c; 110 1.1 christos first_digit++; 111 1.1 christos } 112 1.1 christos else 113 1.1 christos digits_sign_char = '+'; 114 1.1 christos 115 1.1 christos switch (first_digit[0]) 116 1.1 christos { 117 1.1 christos case 's': 118 1.1 christos case 'S': 119 1.1 christos case 'q': 120 1.1 christos case 'Q': 121 1.8 christos if (!strncasecmp ("nan", first_digit + 1, 3)) 122 1.1 christos { 123 1.8 christos address_of_generic_floating_point_number->sign = 124 1.8 christos digits_sign_char == '+' ? TOUPPER (first_digit[0]) 125 1.8 christos : TOLOWER (first_digit[0]); 126 1.1 christos address_of_generic_floating_point_number->exponent = 0; 127 1.1 christos address_of_generic_floating_point_number->leader = 128 1.1 christos address_of_generic_floating_point_number->low; 129 1.1 christos *address_of_string_pointer = first_digit + 4; 130 1.1 christos return 0; 131 1.1 christos } 132 1.1 christos break; 133 1.1 christos 134 1.1 christos case 'n': 135 1.1 christos case 'N': 136 1.1 christos if (!strncasecmp ("nan", first_digit, 3)) 137 1.1 christos { 138 1.8 christos address_of_generic_floating_point_number->sign = 139 1.8 christos digits_sign_char == '+' ? 0 : 'q'; 140 1.1 christos address_of_generic_floating_point_number->exponent = 0; 141 1.1 christos address_of_generic_floating_point_number->leader = 142 1.1 christos address_of_generic_floating_point_number->low; 143 1.1 christos *address_of_string_pointer = first_digit + 3; 144 1.1 christos return 0; 145 1.1 christos } 146 1.1 christos break; 147 1.1 christos 148 1.1 christos case 'i': 149 1.1 christos case 'I': 150 1.1 christos if (!strncasecmp ("inf", first_digit, 3)) 151 1.1 christos { 152 1.1 christos address_of_generic_floating_point_number->sign = 153 1.1 christos digits_sign_char == '+' ? 'P' : 'N'; 154 1.1 christos address_of_generic_floating_point_number->exponent = 0; 155 1.1 christos address_of_generic_floating_point_number->leader = 156 1.1 christos address_of_generic_floating_point_number->low; 157 1.1 christos 158 1.1 christos first_digit += 3; 159 1.1 christos if (!strncasecmp ("inity", first_digit, 5)) 160 1.1 christos first_digit += 5; 161 1.1 christos 162 1.1 christos *address_of_string_pointer = first_digit; 163 1.1 christos 164 1.1 christos return 0; 165 1.1 christos } 166 1.1 christos break; 167 1.1 christos } 168 1.1 christos 169 1.1 christos number_of_digits_before_decimal = 0; 170 1.1 christos number_of_digits_after_decimal = 0; 171 1.1 christos decimal_exponent = 0; 172 1.1 christos seen_significant_digit = 0; 173 1.1 christos for (p = first_digit; 174 1.1 christos (((c = *p) != '\0') 175 1.1 christos && (!c || !IS_DECIMAL_MARK (c)) 176 1.1 christos && (!c || !strchr (string_of_decimal_exponent_marks, c))); 177 1.1 christos p++) 178 1.1 christos { 179 1.1 christos if (ISDIGIT (c)) 180 1.1 christos { 181 1.1 christos if (seen_significant_digit || c > '0') 182 1.1 christos { 183 1.1 christos ++number_of_digits_before_decimal; 184 1.1 christos seen_significant_digit = 1; 185 1.1 christos } 186 1.1 christos else 187 1.1 christos { 188 1.1 christos first_digit++; 189 1.1 christos } 190 1.1 christos } 191 1.1 christos else 192 1.1 christos { 193 1.1 christos break; /* p -> char after pre-decimal digits. */ 194 1.1 christos } 195 1.1 christos } /* For each digit before decimal mark. */ 196 1.1 christos 197 1.1 christos #ifndef OLD_FLOAT_READS 198 1.1 christos /* Ignore trailing 0's after the decimal point. The original code here 199 1.7 christos (ifdef'd out) does not do this, and numbers like 200 1.7 christos 4.29496729600000000000e+09 (2**31) 201 1.7 christos come out inexact for some reason related to length of the digit 202 1.7 christos string. */ 203 1.7 christos 204 1.7 christos /* The case number_of_digits_before_decimal = 0 is handled for 205 1.7 christos deleting zeros after decimal. In this case the decimal mark and 206 1.7 christos the first zero digits after decimal mark are skipped. */ 207 1.7 christos seen_significant_digit = 0; 208 1.8 christos unsigned long subtract_decimal_exponent = 0; 209 1.7 christos 210 1.1 christos if (c && IS_DECIMAL_MARK (c)) 211 1.1 christos { 212 1.7 christos unsigned int zeros = 0; /* Length of current string of zeros. */ 213 1.7 christos 214 1.7 christos if (number_of_digits_before_decimal == 0) 215 1.7 christos /* Skip decimal mark. */ 216 1.7 christos first_digit++; 217 1.1 christos 218 1.1 christos for (p++; (c = *p) && ISDIGIT (c); p++) 219 1.1 christos { 220 1.1 christos if (c == '0') 221 1.1 christos { 222 1.7 christos if (number_of_digits_before_decimal == 0 223 1.7 christos && !seen_significant_digit) 224 1.7 christos { 225 1.7 christos /* Skip '0' and the decimal mark. */ 226 1.7 christos first_digit++; 227 1.7 christos subtract_decimal_exponent--; 228 1.7 christos } 229 1.7 christos else 230 1.7 christos zeros++; 231 1.1 christos } 232 1.1 christos else 233 1.1 christos { 234 1.7 christos seen_significant_digit = 1; 235 1.1 christos number_of_digits_after_decimal += 1 + zeros; 236 1.1 christos zeros = 0; 237 1.1 christos } 238 1.1 christos } 239 1.1 christos } 240 1.1 christos #else 241 1.1 christos if (c && IS_DECIMAL_MARK (c)) 242 1.1 christos { 243 1.1 christos for (p++; 244 1.1 christos (((c = *p) != '\0') 245 1.1 christos && (!c || !strchr (string_of_decimal_exponent_marks, c))); 246 1.1 christos p++) 247 1.1 christos { 248 1.1 christos if (ISDIGIT (c)) 249 1.1 christos { 250 1.1 christos /* This may be retracted below. */ 251 1.1 christos number_of_digits_after_decimal++; 252 1.1 christos 253 1.1 christos if ( /* seen_significant_digit || */ c > '0') 254 1.1 christos { 255 1.8 christos seen_significant_digit = true; 256 1.1 christos } 257 1.1 christos } 258 1.1 christos else 259 1.1 christos { 260 1.1 christos if (!seen_significant_digit) 261 1.1 christos { 262 1.1 christos number_of_digits_after_decimal = 0; 263 1.1 christos } 264 1.1 christos break; 265 1.1 christos } 266 1.1 christos } /* For each digit after decimal mark. */ 267 1.1 christos } 268 1.1 christos 269 1.1 christos while (number_of_digits_after_decimal 270 1.1 christos && first_digit[number_of_digits_before_decimal 271 1.1 christos + number_of_digits_after_decimal] == '0') 272 1.1 christos --number_of_digits_after_decimal; 273 1.1 christos #endif 274 1.1 christos 275 1.1 christos if (flag_m68k_mri) 276 1.1 christos { 277 1.1 christos while (c == '_') 278 1.1 christos c = *++p; 279 1.1 christos } 280 1.1 christos if (c && strchr (string_of_decimal_exponent_marks, c)) 281 1.1 christos { 282 1.1 christos char digits_exponent_sign_char; 283 1.1 christos 284 1.1 christos c = *++p; 285 1.1 christos if (flag_m68k_mri) 286 1.1 christos { 287 1.1 christos while (c == '_') 288 1.1 christos c = *++p; 289 1.1 christos } 290 1.1 christos if (c && strchr ("+-", c)) 291 1.1 christos { 292 1.1 christos digits_exponent_sign_char = c; 293 1.1 christos c = *++p; 294 1.1 christos } 295 1.1 christos else 296 1.1 christos { 297 1.1 christos digits_exponent_sign_char = '+'; 298 1.1 christos } 299 1.1 christos 300 1.1 christos for (; (c); c = *++p) 301 1.1 christos { 302 1.1 christos if (ISDIGIT (c)) 303 1.1 christos { 304 1.8 christos if (decimal_exponent > LONG_MAX / 10 305 1.8 christos || (decimal_exponent == LONG_MAX / 10 306 1.10 christos && c > '0' + (LONG_MAX - LONG_MAX / 10 * 10))) 307 1.8 christos return_value = ERROR_EXPONENT_OVERFLOW; 308 1.1 christos decimal_exponent = decimal_exponent * 10 + c - '0'; 309 1.1 christos } 310 1.1 christos else 311 1.1 christos { 312 1.1 christos break; 313 1.1 christos } 314 1.1 christos } 315 1.1 christos 316 1.1 christos if (digits_exponent_sign_char == '-') 317 1.1 christos { 318 1.1 christos decimal_exponent = -decimal_exponent; 319 1.1 christos } 320 1.1 christos } 321 1.1 christos 322 1.7 christos #ifndef OLD_FLOAT_READS 323 1.7 christos /* Subtract_decimal_exponent != 0 when number_of_digits_before_decimal = 0 324 1.7 christos and first digit after decimal is '0'. */ 325 1.7 christos decimal_exponent += subtract_decimal_exponent; 326 1.7 christos #endif 327 1.7 christos 328 1.1 christos *address_of_string_pointer = p; 329 1.1 christos 330 1.1 christos number_of_digits_available = 331 1.1 christos number_of_digits_before_decimal + number_of_digits_after_decimal; 332 1.1 christos if (number_of_digits_available == 0) 333 1.1 christos { 334 1.1 christos address_of_generic_floating_point_number->exponent = 0; /* Not strictly necessary */ 335 1.1 christos address_of_generic_floating_point_number->leader 336 1.1 christos = -1 + address_of_generic_floating_point_number->low; 337 1.1 christos address_of_generic_floating_point_number->sign = digits_sign_char; 338 1.1 christos /* We have just concocted (+/-)0.0E0 */ 339 1.1 christos 340 1.1 christos } 341 1.1 christos else 342 1.1 christos { 343 1.1 christos int count; /* Number of useful digits left to scan. */ 344 1.1 christos 345 1.5 christos LITTLENUM_TYPE *temporary_binary_low = NULL; 346 1.5 christos LITTLENUM_TYPE *power_binary_low = NULL; 347 1.1 christos LITTLENUM_TYPE *digits_binary_low; 348 1.1 christos unsigned int precision; 349 1.1 christos unsigned int maximum_useful_digits; 350 1.1 christos unsigned int number_of_digits_to_use; 351 1.1 christos unsigned int more_than_enough_bits_for_digits; 352 1.1 christos unsigned int more_than_enough_littlenums_for_digits; 353 1.1 christos unsigned int size_of_digits_in_littlenums; 354 1.1 christos FLONUM_TYPE power_of_10_flonum; 355 1.1 christos FLONUM_TYPE digits_flonum; 356 1.1 christos 357 1.1 christos precision = (address_of_generic_floating_point_number->high 358 1.1 christos - address_of_generic_floating_point_number->low 359 1.1 christos + 1); /* Number of destination littlenums. */ 360 1.1 christos 361 1.7 christos /* precision includes two littlenums worth of guard bits, 362 1.7 christos so this gives us 10 decimal guard digits here. */ 363 1.7 christos maximum_useful_digits = (precision 364 1.7 christos * LITTLENUM_NUMBER_OF_BITS 365 1.7 christos * 1000000 / 3321928 366 1.7 christos + 1); /* round up. */ 367 1.1 christos 368 1.1 christos if (number_of_digits_available > maximum_useful_digits) 369 1.1 christos { 370 1.1 christos number_of_digits_to_use = maximum_useful_digits; 371 1.1 christos } 372 1.1 christos else 373 1.1 christos { 374 1.1 christos number_of_digits_to_use = number_of_digits_available; 375 1.1 christos } 376 1.1 christos 377 1.10 christos decimal_exponent += number_of_digits_before_decimal; 378 1.10 christos decimal_exponent -= number_of_digits_to_use; 379 1.1 christos 380 1.1 christos more_than_enough_bits_for_digits 381 1.1 christos = (number_of_digits_to_use * 3321928 / 1000000 + 1); 382 1.1 christos 383 1.1 christos more_than_enough_littlenums_for_digits 384 1.1 christos = (more_than_enough_bits_for_digits 385 1.1 christos / LITTLENUM_NUMBER_OF_BITS) 386 1.1 christos + 2; 387 1.1 christos 388 1.1 christos /* Compute (digits) part. In "12.34E56" this is the "1234" part. 389 1.1 christos Arithmetic is exact here. If no digits are supplied then this 390 1.1 christos part is a 0 valued binary integer. Allocate room to build up 391 1.1 christos the binary number as littlenums. We want this memory to 392 1.1 christos disappear when we leave this function. Assume no alignment 393 1.1 christos problems => (room for n objects) == n * (room for 1 394 1.1 christos object). */ 395 1.1 christos 396 1.1 christos size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits; 397 1.1 christos 398 1.10 christos digits_binary_low = xcalloc (size_of_digits_in_littlenums, 399 1.10 christos sizeof (LITTLENUM_TYPE)); 400 1.1 christos 401 1.1 christos /* Digits_binary_low[] is allocated and zeroed. */ 402 1.1 christos 403 1.1 christos /* 404 1.1 christos * Parse the decimal digits as if * digits_low was in the units position. 405 1.1 christos * Emit a binary number into digits_binary_low[]. 406 1.1 christos * 407 1.1 christos * Use a large-precision version of: 408 1.1 christos * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit 409 1.1 christos */ 410 1.1 christos 411 1.1 christos for (p = first_digit, count = number_of_digits_to_use; count; p++, --count) 412 1.1 christos { 413 1.1 christos c = *p; 414 1.1 christos if (ISDIGIT (c)) 415 1.1 christos { 416 1.1 christos /* 417 1.1 christos * Multiply by 10. Assume can never overflow. 418 1.1 christos * Add this digit to digits_binary_low[]. 419 1.1 christos */ 420 1.1 christos 421 1.1 christos long carry; 422 1.1 christos LITTLENUM_TYPE *littlenum_pointer; 423 1.1 christos LITTLENUM_TYPE *littlenum_limit; 424 1.1 christos 425 1.1 christos littlenum_limit = digits_binary_low 426 1.1 christos + more_than_enough_littlenums_for_digits 427 1.1 christos - 1; 428 1.1 christos 429 1.1 christos carry = c - '0'; /* char -> binary */ 430 1.1 christos 431 1.1 christos for (littlenum_pointer = digits_binary_low; 432 1.1 christos littlenum_pointer <= littlenum_limit; 433 1.1 christos littlenum_pointer++) 434 1.1 christos { 435 1.1 christos long work; 436 1.1 christos 437 1.1 christos work = carry + 10 * (long) (*littlenum_pointer); 438 1.1 christos *littlenum_pointer = work & LITTLENUM_MASK; 439 1.1 christos carry = work >> LITTLENUM_NUMBER_OF_BITS; 440 1.1 christos } 441 1.1 christos 442 1.1 christos if (carry != 0) 443 1.1 christos { 444 1.1 christos /* 445 1.1 christos * We have a GROSS internal error. 446 1.1 christos * This should never happen. 447 1.1 christos */ 448 1.1 christos as_fatal (_("failed sanity check")); 449 1.1 christos } 450 1.1 christos } 451 1.1 christos else 452 1.1 christos { 453 1.1 christos ++count; /* '.' doesn't alter digits used count. */ 454 1.1 christos } 455 1.1 christos } 456 1.1 christos 457 1.1 christos /* 458 1.1 christos * Digits_binary_low[] properly encodes the value of the digits. 459 1.1 christos * Forget about any high-order littlenums that are 0. 460 1.1 christos */ 461 1.1 christos while (digits_binary_low[size_of_digits_in_littlenums - 1] == 0 462 1.1 christos && size_of_digits_in_littlenums >= 2) 463 1.1 christos size_of_digits_in_littlenums--; 464 1.1 christos 465 1.1 christos digits_flonum.low = digits_binary_low; 466 1.1 christos digits_flonum.high = digits_binary_low + size_of_digits_in_littlenums - 1; 467 1.1 christos digits_flonum.leader = digits_flonum.high; 468 1.1 christos digits_flonum.exponent = 0; 469 1.1 christos /* 470 1.1 christos * The value of digits_flonum . sign should not be important. 471 1.1 christos * We have already decided the output's sign. 472 1.1 christos * We trust that the sign won't influence the other parts of the number! 473 1.1 christos * So we give it a value for these reasons: 474 1.1 christos * (1) courtesy to humans reading/debugging 475 1.1 christos * these numbers so they don't get excited about strange values 476 1.1 christos * (2) in future there may be more meaning attached to sign, 477 1.1 christos * and what was 478 1.1 christos * harmless noise may become disruptive, ill-conditioned (or worse) 479 1.1 christos * input. 480 1.1 christos */ 481 1.1 christos digits_flonum.sign = '+'; 482 1.1 christos 483 1.1 christos { 484 1.1 christos /* 485 1.6 christos * Compute the mantissa (& exponent) of the power of 10. 486 1.1 christos * If successful, then multiply the power of 10 by the digits 487 1.1 christos * giving return_binary_mantissa and return_binary_exponent. 488 1.1 christos */ 489 1.1 christos 490 1.1 christos int decimal_exponent_is_negative; 491 1.1 christos /* This refers to the "-56" in "12.34E-56". */ 492 1.1 christos /* FALSE: decimal_exponent is positive (or 0) */ 493 1.1 christos /* TRUE: decimal_exponent is negative */ 494 1.1 christos FLONUM_TYPE temporary_flonum; 495 1.1 christos unsigned int size_of_power_in_littlenums; 496 1.1 christos unsigned int size_of_power_in_chars; 497 1.1 christos 498 1.1 christos size_of_power_in_littlenums = precision; 499 1.1 christos /* Precision has a built-in fudge factor so we get a few guard bits. */ 500 1.1 christos 501 1.8 christos decimal_exponent_is_negative = (long) decimal_exponent < 0; 502 1.1 christos if (decimal_exponent_is_negative) 503 1.1 christos { 504 1.1 christos decimal_exponent = -decimal_exponent; 505 1.1 christos } 506 1.1 christos 507 1.1 christos /* From now on: the decimal exponent is > 0. Its sign is separate. */ 508 1.1 christos 509 1.10 christos size_of_power_in_chars = (size_of_power_in_littlenums 510 1.10 christos * sizeof (LITTLENUM_TYPE)) + 2; 511 1.1 christos 512 1.10 christos power_binary_low = xmalloc (size_of_power_in_chars); 513 1.10 christos temporary_binary_low = xmalloc (size_of_power_in_chars); 514 1.5 christos 515 1.10 christos memset (power_binary_low, '\0', size_of_power_in_chars); 516 1.1 christos *power_binary_low = 1; 517 1.1 christos power_of_10_flonum.exponent = 0; 518 1.1 christos power_of_10_flonum.low = power_binary_low; 519 1.1 christos power_of_10_flonum.leader = power_binary_low; 520 1.1 christos power_of_10_flonum.high = power_binary_low + size_of_power_in_littlenums - 1; 521 1.1 christos power_of_10_flonum.sign = '+'; 522 1.1 christos temporary_flonum.low = temporary_binary_low; 523 1.1 christos temporary_flonum.high = temporary_binary_low + size_of_power_in_littlenums - 1; 524 1.1 christos /* 525 1.1 christos * (power) == 1. 526 1.1 christos * Space for temporary_flonum allocated. 527 1.1 christos */ 528 1.1 christos 529 1.1 christos /* 530 1.1 christos * ... 531 1.1 christos * 532 1.1 christos * WHILE more bits 533 1.1 christos * DO find next bit (with place value) 534 1.1 christos * multiply into power mantissa 535 1.1 christos * OD 536 1.1 christos */ 537 1.1 christos { 538 1.1 christos int place_number_limit; 539 1.1 christos /* Any 10^(2^n) whose "n" exceeds this */ 540 1.1 christos /* value will fall off the end of */ 541 1.1 christos /* flonum_XXXX_powers_of_ten[]. */ 542 1.1 christos int place_number; 543 1.1 christos const FLONUM_TYPE *multiplicand; /* -> 10^(2^n) */ 544 1.1 christos 545 1.1 christos place_number_limit = table_size_of_flonum_powers_of_ten; 546 1.1 christos 547 1.1 christos multiplicand = (decimal_exponent_is_negative 548 1.1 christos ? flonum_negative_powers_of_ten 549 1.1 christos : flonum_positive_powers_of_ten); 550 1.1 christos 551 1.1 christos for (place_number = 1;/* Place value of this bit of exponent. */ 552 1.1 christos decimal_exponent;/* Quit when no more 1 bits in exponent. */ 553 1.1 christos decimal_exponent >>= 1, place_number++) 554 1.1 christos { 555 1.1 christos if (decimal_exponent & 1) 556 1.1 christos { 557 1.1 christos if (place_number > place_number_limit) 558 1.1 christos { 559 1.1 christos /* The decimal exponent has a magnitude so great 560 1.1 christos that our tables can't help us fragment it. 561 1.1 christos Although this routine is in error because it 562 1.1 christos can't imagine a number that big, signal an 563 1.1 christos error as if it is the user's fault for 564 1.1 christos presenting such a big number. */ 565 1.1 christos return_value = ERROR_EXPONENT_OVERFLOW; 566 1.1 christos /* quit out of loop gracefully */ 567 1.1 christos decimal_exponent = 0; 568 1.1 christos } 569 1.1 christos else 570 1.1 christos { 571 1.1 christos #ifdef TRACE 572 1.1 christos printf ("before multiply, place_number = %d., power_of_10_flonum:\n", 573 1.1 christos place_number); 574 1.1 christos 575 1.1 christos flonum_print (&power_of_10_flonum); 576 1.1 christos (void) putchar ('\n'); 577 1.1 christos #endif 578 1.1 christos #ifdef TRACE 579 1.1 christos printf ("multiplier:\n"); 580 1.1 christos flonum_print (multiplicand + place_number); 581 1.1 christos (void) putchar ('\n'); 582 1.1 christos #endif 583 1.1 christos flonum_multip (multiplicand + place_number, 584 1.1 christos &power_of_10_flonum, &temporary_flonum); 585 1.1 christos #ifdef TRACE 586 1.1 christos printf ("after multiply:\n"); 587 1.1 christos flonum_print (&temporary_flonum); 588 1.1 christos (void) putchar ('\n'); 589 1.1 christos #endif 590 1.1 christos flonum_copy (&temporary_flonum, &power_of_10_flonum); 591 1.1 christos #ifdef TRACE 592 1.1 christos printf ("after copy:\n"); 593 1.1 christos flonum_print (&power_of_10_flonum); 594 1.1 christos (void) putchar ('\n'); 595 1.1 christos #endif 596 1.1 christos } /* If this bit of decimal_exponent was computable.*/ 597 1.1 christos } /* If this bit of decimal_exponent was set. */ 598 1.1 christos } /* For each bit of binary representation of exponent */ 599 1.1 christos #ifdef TRACE 600 1.1 christos printf ("after computing power_of_10_flonum:\n"); 601 1.1 christos flonum_print (&power_of_10_flonum); 602 1.1 christos (void) putchar ('\n'); 603 1.1 christos #endif 604 1.1 christos } 605 1.1 christos } 606 1.1 christos 607 1.1 christos /* 608 1.1 christos * power_of_10_flonum is power of ten in binary (mantissa) , (exponent). 609 1.1 christos * It may be the number 1, in which case we don't NEED to multiply. 610 1.1 christos * 611 1.1 christos * Multiply (decimal digits) by power_of_10_flonum. 612 1.1 christos */ 613 1.1 christos 614 1.1 christos flonum_multip (&power_of_10_flonum, &digits_flonum, address_of_generic_floating_point_number); 615 1.1 christos /* Assert sign of the number we made is '+'. */ 616 1.1 christos address_of_generic_floating_point_number->sign = digits_sign_char; 617 1.1 christos 618 1.8 christos free (temporary_binary_low); 619 1.8 christos free (power_binary_low); 620 1.5 christos free (digits_binary_low); 621 1.1 christos } 622 1.1 christos return return_value; 623 1.1 christos } 624 1.1 christos 625 1.1 christos #ifdef TRACE 626 1.1 christos static void 627 1.10 christos flonum_print (const FLONUM_TYPE *f) 628 1.1 christos { 629 1.1 christos LITTLENUM_TYPE *lp; 630 1.1 christos char littlenum_format[10]; 631 1.1 christos sprintf (littlenum_format, " %%0%dx", sizeof (LITTLENUM_TYPE) * 2); 632 1.1 christos #define print_littlenum(LP) (printf (littlenum_format, LP)) 633 1.1 christos printf ("flonum @%p %c e%ld", f, f->sign, f->exponent); 634 1.1 christos if (f->low < f->high) 635 1.1 christos for (lp = f->high; lp >= f->low; lp--) 636 1.1 christos print_littlenum (*lp); 637 1.1 christos else 638 1.1 christos for (lp = f->low; lp <= f->high; lp++) 639 1.1 christos print_littlenum (*lp); 640 1.1 christos printf ("\n"); 641 1.1 christos fflush (stdout); 642 1.1 christos } 643 1.1 christos #endif 644 1.1 christos 645 1.1 christos /* end of atof_generic.c */ 646