|
|
1.1 ! root 1: /* atof_generic.c - turn a string of digits into a Flonum ! 2: Copyright (C) 1987 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GAS, the GNU Assembler. ! 5: ! 6: GAS is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 1, or (at your option) ! 9: any later version. ! 10: ! 11: GAS is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GAS; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: #include <ctype.h> ! 21: #include <stdlib.h> ! 22: #include <string.h> ! 23: #include "flonum.h" ! 24: ! 25: #define FALSE (0) ! 26: #define TRUE (1) ! 27: ! 28: /***********************************************************************\ ! 29: * * ! 30: * Given a string of decimal digits , with optional decimal * ! 31: * mark and optional decimal exponent (place value) of the * ! 32: * lowest_order decimal digit: produce a floating point * ! 33: * number. The number is 'generic' floating point: our * ! 34: * caller will encode it for a specific machine architecture. * ! 35: * * ! 36: * Assumptions * ! 37: * uses base (radix) 2 * ! 38: * this machine uses 2's complement binary integers * ! 39: * target flonums use " " " " * ! 40: * target flonums exponents fit in a long int * ! 41: * * ! 42: \***********************************************************************/ ! 43: ! 44: /* ! 45: ! 46: Syntax: ! 47: ! 48: <flonum> ::= <optional-sign> <decimal-number> <optional-exponent> ! 49: <optional-sign> ::= '+' | '-' | {empty} ! 50: <decimal-number> ::= <integer> ! 51: | <integer> <radix-character> ! 52: | <integer> <radix-character> <integer> ! 53: | <radix-character> <integer> ! 54: <optional-exponent> ::= {empty} | <exponent-character> <optional-sign> <integer> ! 55: <integer> ::= <digit> | <digit> <integer> ! 56: <digit> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ! 57: <exponent-character> ::= {one character from "string_of_decimal_exponent_marks"} ! 58: <radix-character> ::= {one character from "string_of_decimal_marks"} ! 59: ! 60: */ ! 61: ! 62: /* 0 if OK */ ! 63: int ! 64: atof_generic ( ! 65: char **address_of_string_pointer, /* return pointer to just AFTER number read */ ! 66: const char *string_of_decimal_marks, /* at most one per number */ ! 67: const char *string_of_decimal_exponent_marks, ! 68: FLONUM_TYPE *address_of_generic_floating_point_number) ! 69: { ! 70: ! 71: int return_value; /* 0 means OK. */ ! 72: char * first_digit; ! 73: /* char * last_digit; JF unused */ ! 74: int number_of_digits_before_decimal; ! 75: int number_of_digits_after_decimal; ! 76: long int decimal_exponent; ! 77: int number_of_digits_available; ! 78: char digits_sign_char; ! 79: ! 80: { ! 81: /* ! 82: * Scan the input string, abstracting (1)digits (2)decimal mark (3) exponent. ! 83: * It would be simpler to modify the string, but we don't; just to be nice ! 84: * to caller. ! 85: * We need to know how many digits we have, so we can allocate space for ! 86: * the digits' value. ! 87: */ ! 88: ! 89: char * p; ! 90: char c; ! 91: int seen_significant_digit; ! 92: ! 93: first_digit = * address_of_string_pointer; ! 94: c= *first_digit; ! 95: if (c=='-' || c=='+') ! 96: { ! 97: digits_sign_char = c; ! 98: first_digit ++; ! 99: } ! 100: else ! 101: digits_sign_char = '+'; ! 102: ! 103: if( (first_digit[0]=='n' || first_digit[0]=='N') ! 104: && (first_digit[1]=='a' || first_digit[1]=='A') ! 105: && (first_digit[2]=='n' || first_digit[2]=='N')) { ! 106: address_of_generic_floating_point_number->sign=0; ! 107: address_of_generic_floating_point_number->exponent=0; ! 108: address_of_generic_floating_point_number->leader=address_of_generic_floating_point_number->low; ! 109: (*address_of_string_pointer)=first_digit+3; ! 110: return 0; ! 111: } ! 112: if( (first_digit[0]=='i' || first_digit[0]=='I') ! 113: && (first_digit[1]=='n' || first_digit[1]=='N') ! 114: && (first_digit[2]=='f' || first_digit[2]=='F')) { ! 115: address_of_generic_floating_point_number->sign= digits_sign_char=='+' ? 'P' : 'N'; ! 116: address_of_generic_floating_point_number->exponent=0; ! 117: address_of_generic_floating_point_number->leader=address_of_generic_floating_point_number->low; ! 118: if( (first_digit[3]=='i' || first_digit[3]=='I') ! 119: && (first_digit[4]=='n' || first_digit[4]=='N') ! 120: && (first_digit[5]=='i' || first_digit[5]=='I') ! 121: && (first_digit[6]=='t' || first_digit[6]=='T') ! 122: && (first_digit[7]=='y' || first_digit[7]=='Y')) ! 123: (*address_of_string_pointer)=first_digit+8; ! 124: else ! 125: (*address_of_string_pointer)=first_digit+3; ! 126: return 0; ! 127: } ! 128: ! 129: number_of_digits_before_decimal = 0; ! 130: number_of_digits_after_decimal = 0; ! 131: decimal_exponent = 0; ! 132: seen_significant_digit = FALSE; ! 133: for (p = first_digit; ! 134: (c = * p) ! 135: && (!c || ! strchr(string_of_decimal_marks, c) ) ! 136: && (!c || ! strchr(string_of_decimal_exponent_marks, c) ); ! 137: p ++) ! 138: { ! 139: if (isdigit(c)) ! 140: { ! 141: if (seen_significant_digit || c > '0') ! 142: { ! 143: number_of_digits_before_decimal ++; ! 144: seen_significant_digit = TRUE; ! 145: } ! 146: else ! 147: { ! 148: first_digit++; ! 149: } ! 150: } ! 151: else ! 152: { ! 153: break; /* p -> char after pre-decimal digits. */ ! 154: } ! 155: } /* For each digit before decimal mark. */ ! 156: if (c && strchr(string_of_decimal_marks, c)) ! 157: { ! 158: for (p ++; ! 159: (c = * p) ! 160: && (!c || ! strchr(string_of_decimal_exponent_marks, c) ); ! 161: p ++) ! 162: { ! 163: if (isdigit(c)) ! 164: { ! 165: number_of_digits_after_decimal ++; /* This may be retracted below. */ ! 166: if (/* seen_significant_digit || */ c > '0') ! 167: { ! 168: seen_significant_digit = TRUE; ! 169: } ! 170: } ! 171: else ! 172: { ! 173: if ( ! seen_significant_digit) ! 174: { ! 175: number_of_digits_after_decimal = 0; ! 176: } ! 177: break; ! 178: } ! 179: } /* For each digit after decimal mark. */ ! 180: } ! 181: while(number_of_digits_after_decimal && first_digit[number_of_digits_before_decimal+number_of_digits_after_decimal]=='0') ! 182: --number_of_digits_after_decimal; ! 183: /* last_digit = p; JF unused */ ! 184: ! 185: if (c && strchr(string_of_decimal_exponent_marks, c) ) ! 186: { ! 187: char digits_exponent_sign_char; ! 188: ! 189: c = * ++ p; ! 190: if (c && strchr("+-",c)) ! 191: { ! 192: digits_exponent_sign_char = c; ! 193: c = * ++ p; ! 194: } ! 195: else ! 196: { ! 197: digits_exponent_sign_char = '+'; ! 198: } ! 199: for (; ! 200: (c); ! 201: c = * ++ p) ! 202: { ! 203: if (isdigit(c)) ! 204: { ! 205: decimal_exponent = decimal_exponent * 10 + c - '0'; ! 206: /* ! 207: * BUG! If we overflow here, we lose! ! 208: */ ! 209: } ! 210: else ! 211: { ! 212: break; ! 213: } ! 214: } ! 215: if (digits_exponent_sign_char == '-') ! 216: { ! 217: decimal_exponent = - decimal_exponent; ! 218: } ! 219: } ! 220: * address_of_string_pointer = p; ! 221: } ! 222: ! 223: number_of_digits_available = ! 224: number_of_digits_before_decimal ! 225: + number_of_digits_after_decimal; ! 226: return_value = 0; ! 227: if (number_of_digits_available == 0) ! 228: { ! 229: address_of_generic_floating_point_number -> exponent = 0; /* Not strictly necessary */ ! 230: address_of_generic_floating_point_number -> leader ! 231: = -1 + address_of_generic_floating_point_number -> low; ! 232: address_of_generic_floating_point_number -> sign = digits_sign_char; ! 233: /* We have just concocted (+/-)0.0E0 */ ! 234: } ! 235: else ! 236: { ! 237: LITTLENUM_TYPE * digits_binary_low; ! 238: int precision; ! 239: int maximum_useful_digits; ! 240: int number_of_digits_to_use; ! 241: int more_than_enough_bits_for_digits; ! 242: int more_than_enough_littlenums_for_digits; ! 243: int size_of_digits_in_littlenums; ! 244: int size_of_digits_in_chars; ! 245: FLONUM_TYPE power_of_10_flonum; ! 246: FLONUM_TYPE digits_flonum; ! 247: ! 248: ! 249: precision = (address_of_generic_floating_point_number -> high ! 250: - address_of_generic_floating_point_number -> low ! 251: + 1 ! 252: ); /* Number of destination littlenums. */ ! 253: /* Includes guard bits (two littlenums worth) */ ! 254: maximum_useful_digits = ( ((double) (precision - 2)) ! 255: * ((double) (LITTLENUM_NUMBER_OF_BITS)) ! 256: / (LOG_TO_BASE_2_OF_10) ! 257: ) ! 258: + 2; /* 2 :: guard digits. */ ! 259: if (number_of_digits_available > maximum_useful_digits) ! 260: { ! 261: number_of_digits_to_use = maximum_useful_digits; ! 262: } ! 263: else ! 264: { ! 265: number_of_digits_to_use = number_of_digits_available; ! 266: } ! 267: decimal_exponent += number_of_digits_before_decimal - number_of_digits_to_use; ! 268: ! 269: more_than_enough_bits_for_digits ! 270: = ((((double)number_of_digits_to_use) * LOG_TO_BASE_2_OF_10) + 1); ! 271: more_than_enough_littlenums_for_digits ! 272: = ( more_than_enough_bits_for_digits ! 273: / LITTLENUM_NUMBER_OF_BITS ! 274: ) ! 275: + 2; ! 276: ! 277: /* ! 278: * Compute (digits) part. In "12.34E56" this is the "1234" part. ! 279: * Arithmetic is exact here. If no digits are supplied then ! 280: * this part is a 0 valued binary integer. ! 281: * Allocate room to build up the binary number as littlenums. ! 282: * We want this memory to disappear when we leave this function. ! 283: * Assume no alignment problems => (room for n objects) == ! 284: * n * (room for 1 object). ! 285: */ ! 286: ! 287: size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits; ! 288: size_of_digits_in_chars = size_of_digits_in_littlenums ! 289: * sizeof( LITTLENUM_TYPE ); ! 290: digits_binary_low = (LITTLENUM_TYPE *) ! 291: alloca (size_of_digits_in_chars); ! 292: memset((char *)digits_binary_low, '\0', size_of_digits_in_chars); ! 293: ! 294: /* Digits_binary_low[] is allocated and zeroed. */ ! 295: ! 296: { ! 297: /* ! 298: * Parse the decimal digits as if * digits_low was in the units position. ! 299: * Emit a binary number into digits_binary_low[]. ! 300: * ! 301: * Use a large-precision version of: ! 302: * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit ! 303: */ ! 304: ! 305: char * p; ! 306: char c; ! 307: int count; /* Number of useful digits left to scan. */ ! 308: ! 309: for (p = first_digit, count = number_of_digits_to_use; ! 310: count; ! 311: p ++, -- count) ! 312: { ! 313: c = * p; ! 314: if (isdigit(c)) ! 315: { ! 316: /* ! 317: * Multiply by 10. Assume can never overflow. ! 318: * Add this digit to digits_binary_low[]. ! 319: */ ! 320: ! 321: long int carry; ! 322: LITTLENUM_TYPE * littlenum_pointer; ! 323: LITTLENUM_TYPE * littlenum_limit; ! 324: ! 325: littlenum_limit ! 326: = digits_binary_low ! 327: + more_than_enough_littlenums_for_digits ! 328: - 1; ! 329: carry = c - '0'; /* char -> binary */ ! 330: for (littlenum_pointer = digits_binary_low; ! 331: littlenum_pointer <= littlenum_limit; ! 332: littlenum_pointer ++) ! 333: { ! 334: long int work; ! 335: ! 336: work = carry + 10 * (long)(*littlenum_pointer); ! 337: * littlenum_pointer = work & LITTLENUM_MASK; ! 338: carry = work >> LITTLENUM_NUMBER_OF_BITS; ! 339: } ! 340: if (carry != 0) ! 341: { ! 342: /* ! 343: * We have a GROSS internal error. ! 344: * This should never happen. ! 345: */ ! 346: abort(); /* RMS prefers abort() to any message. */ ! 347: } ! 348: } ! 349: else ! 350: { ! 351: ++ count; /* '.' doesn't alter digits used count. */ ! 352: } /* if valid digit */ ! 353: } /* for each digit */ ! 354: } ! 355: ! 356: /* ! 357: * Digits_binary_low[] properly encodes the value of the digits. ! 358: * Forget about any high-order littlenums that are 0. ! 359: */ ! 360: while (digits_binary_low [size_of_digits_in_littlenums - 1] == 0 ! 361: && size_of_digits_in_littlenums >= 2) ! 362: size_of_digits_in_littlenums --; ! 363: ! 364: digits_flonum . low = digits_binary_low; ! 365: digits_flonum . high = digits_binary_low + size_of_digits_in_littlenums - 1; ! 366: digits_flonum . leader = digits_flonum . high; ! 367: digits_flonum . exponent = 0; ! 368: /* ! 369: * The value of digits_flonum . sign should not be important. ! 370: * We have already decided the output's sign. ! 371: * We trust that the sign won't influence the other parts of the number! ! 372: * So we give it a value for these reasons: ! 373: * (1) courtesy to humans reading/debugging ! 374: * these numbers so they don't get excited about strange values ! 375: * (2) in future there may be more meaning attached to sign, ! 376: * and what was ! 377: * harmless noise may become disruptive, ill-conditioned (or worse) ! 378: * input. ! 379: */ ! 380: digits_flonum . sign = '+'; ! 381: ! 382: { ! 383: /* ! 384: * Compute the mantssa (& exponent) of the power of 10. ! 385: * If sucessful, then multiply the power of 10 by the digits ! 386: * giving return_binary_mantissa and return_binary_exponent. ! 387: */ ! 388: ! 389: LITTLENUM_TYPE *power_binary_low; ! 390: int decimal_exponent_is_negative; ! 391: /* This refers to the "-56" in "12.34E-56". */ ! 392: /* FALSE: decimal_exponent is positive (or 0) */ ! 393: /* TRUE: decimal_exponent is negative */ ! 394: FLONUM_TYPE temporary_flonum; ! 395: LITTLENUM_TYPE *temporary_binary_low; ! 396: int size_of_power_in_littlenums; ! 397: int size_of_power_in_chars; ! 398: ! 399: size_of_power_in_littlenums = precision; ! 400: /* Precision has a built-in fudge factor so we get a few guard bits. */ ! 401: ! 402: ! 403: decimal_exponent_is_negative = decimal_exponent < 0; ! 404: if (decimal_exponent_is_negative) ! 405: { ! 406: decimal_exponent = - decimal_exponent; ! 407: } ! 408: /* From now on: the decimal exponent is > 0. Its sign is seperate. */ ! 409: ! 410: size_of_power_in_chars ! 411: = size_of_power_in_littlenums ! 412: * sizeof( LITTLENUM_TYPE ) + 2; ! 413: power_binary_low = (LITTLENUM_TYPE *) alloca ( size_of_power_in_chars ); ! 414: temporary_binary_low = (LITTLENUM_TYPE *) alloca ( size_of_power_in_chars ); ! 415: memset((char *)power_binary_low, '\0', size_of_power_in_chars); ! 416: * power_binary_low = 1; ! 417: power_of_10_flonum . exponent = 0; ! 418: power_of_10_flonum . low = power_binary_low; ! 419: power_of_10_flonum . leader = power_binary_low; ! 420: power_of_10_flonum . high = power_binary_low + size_of_power_in_littlenums - 1; ! 421: power_of_10_flonum . sign = '+'; ! 422: temporary_flonum . low = temporary_binary_low; ! 423: temporary_flonum . high = temporary_binary_low + size_of_power_in_littlenums - 1; ! 424: /* ! 425: * (power) == 1. ! 426: * Space for temporary_flonum allocated. ! 427: */ ! 428: ! 429: /* ! 430: * ... ! 431: * ! 432: * WHILE more bits ! 433: * DO find next bit (with place value) ! 434: * multiply into power mantissa ! 435: * OD ! 436: */ ! 437: { ! 438: int place_number_limit; ! 439: /* Any 10^(2^n) whose "n" exceeds this */ ! 440: /* value will fall off the end of */ ! 441: /* flonum_XXXX_powers_of_ten[]. */ ! 442: int place_number; ! 443: const const_FLONUM_TYPE * multiplicand; /* -> 10^(2^n) */ ! 444: ! 445: place_number_limit = table_size_of_flonum_powers_of_ten; ! 446: multiplicand ! 447: = ( decimal_exponent_is_negative ! 448: ? flonum_negative_powers_of_ten ! 449: : flonum_positive_powers_of_ten); ! 450: for (place_number = 1; /* Place value of this bit of exponent. */ ! 451: decimal_exponent; /* Quit when no more 1 bits in exponent. */ ! 452: decimal_exponent >>= 1 ! 453: , place_number ++) ! 454: { ! 455: if (decimal_exponent & 1) ! 456: { ! 457: if (place_number > place_number_limit) ! 458: { ! 459: /* ! 460: * The decimal exponent has a magnitude so great that ! 461: * our tables can't help us fragment it. Although this ! 462: * routine is in error because it can't imagine a ! 463: * number that big, signal an error as if it is the ! 464: * user's fault for presenting such a big number. ! 465: */ ! 466: return_value = ERROR_EXPONENT_OVERFLOW; ! 467: /* ! 468: * quit out of loop gracefully ! 469: */ ! 470: decimal_exponent = 0; ! 471: } ! 472: else ! 473: { ! 474: #ifdef TRACE ! 475: printf("before multiply, place_number = %d., power_of_10_flonum:\n", place_number); ! 476: flonum_print( & power_of_10_flonum ); ! 477: (void)putchar('\n'); ! 478: #endif ! 479: flonum_multip ((const_FLONUM_TYPE *)multiplicand + place_number, & power_of_10_flonum, & temporary_flonum); ! 480: flonum_copy (& temporary_flonum, & power_of_10_flonum); ! 481: } /* If this bit of decimal_exponent was computable.*/ ! 482: } /* If this bit of decimal_exponent was set. */ ! 483: } /* For each bit of binary representation of exponent */ ! 484: #ifdef TRACE ! 485: printf( " after computing power_of_10_flonum: " ); ! 486: flonum_print( & power_of_10_flonum ); ! 487: (void)putchar('\n'); ! 488: #endif ! 489: } ! 490: ! 491: } ! 492: ! 493: /* ! 494: * power_of_10_flonum is power of ten in binary (mantissa) , (exponent). ! 495: * It may be the number 1, in which case we don't NEED to multiply. ! 496: * ! 497: * Multiply (decimal digits) by power_of_10_flonum. ! 498: */ ! 499: ! 500: flonum_multip ((const_FLONUM_TYPE *)&power_of_10_flonum, & digits_flonum, address_of_generic_floating_point_number); ! 501: /* Assert sign of the number we made is '+'. */ ! 502: address_of_generic_floating_point_number -> sign = digits_sign_char; ! 503: ! 504: } /* If we had any significant digits. */ ! 505: return (return_value); ! 506: } /* atof_generic () */ ! 507: ! 508: /* end: atof_generic.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.