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