|
|
1.1 ! root 1: /* ! 2: * C general utilities library. ! 3: * atof() ! 4: * ANSI 4.10.1.1. ! 5: * Convert ASCII to double (the old fashioned way). ! 6: * Builds significand in an unsigned long, for efficiency. ! 7: * Does not use any knowledge about floating point representation. ! 8: */ ! 9: ! 10: #if __STDC__ ! 11: #include <stdlib.h> ! 12: #include <limits.h> ! 13: #include <locale.h> ! 14: #else ! 15: #define _decimal_point '.' ! 16: extern double _pow10(); ! 17: #endif ! 18: #include <ctype.h> ! 19: ! 20: /* Flag bits. */ ! 21: #define NEG 1 /* negative significand */ ! 22: #define DOT 2 /* decimal point seen */ ! 23: #define NEGEXP 4 /* negative exponent */ ! 24: #define BIG 8 /* significand too big for ulong */ ! 25: ! 26: double ! 27: atof(nptr) register char *nptr; ! 28: { ! 29: register int c, flag, eexp; ! 30: register unsigned long val; ! 31: int exp, vdigits; ! 32: double d; ! 33: ! 34: val = flag = exp = vdigits = 0; ! 35: ! 36: /* Leading white space. */ ! 37: while (isspace(c = *nptr++)) ! 38: ; ! 39: ! 40: /* Optional sign. */ ! 41: switch (c) { ! 42: case '-': ! 43: flag |= NEG; ! 44: case '+': ! 45: c = *nptr++; ! 46: } ! 47: ! 48: /* Number: sequence of decimal digits with optional '.'. */ ! 49: for (; ; c = *nptr++) { ! 50: if (isdigit(c)) { ! 51: c -= '0'; ! 52: #if __STDC__ ! 53: if (val > (ULONG_MAX-9) / 10) { ! 54: #else ! 55: /* The pre-ANSI compiler gets the test above wrong. */ ! 56: if (val > 429496728L) { ! 57: #endif ! 58: /* Significand too big for val, use d. */ ! 59: if (flag & BIG) ! 60: d = d * _pow10(vdigits) + val; ! 61: else { ! 62: d = val; ! 63: flag |= BIG; ! 64: } ! 65: vdigits = 1; ! 66: val = c; ! 67: } else { ! 68: ++vdigits; /* decimal digits in val */ ! 69: /* val = val * 10 + c; */ ! 70: val <<= 1; ! 71: val = val + (val << 2) + c; ! 72: } ! 73: if (flag & DOT) ! 74: --exp; ! 75: } else if (c == _decimal_point && (flag & DOT) == 0) ! 76: flag |= DOT; ! 77: else ! 78: break; ! 79: } ! 80: if (flag & BIG) ! 81: d = d * _pow10(vdigits) + val; ! 82: else ! 83: d = val; ! 84: ! 85: /* Optional exponent: 'E' or 'e', optional sign, decimal digits. */ ! 86: if (c == 'e' || c == 'E') { ! 87: ! 88: /* Optional sign. */ ! 89: switch (c = *nptr++) { ! 90: case '-': ! 91: flag |= NEGEXP; ! 92: case '+': ! 93: c = *nptr++; ! 94: } ! 95: ! 96: /* Decimal digits. */ ! 97: for (eexp = 0; isdigit(c); c = *nptr++) ! 98: eexp = eexp * 10 + c - '0'; ! 99: ! 100: /* Adjust explicit exponent for digits read after '.'. */ ! 101: if (flag & NEGEXP) ! 102: exp -= eexp; ! 103: else ! 104: exp += eexp; ! 105: } ! 106: ! 107: /* Reconcile the significand with the exponent and sign. */ ! 108: if (exp != 0) ! 109: d *= _pow10(exp); ! 110: return ((flag & NEG) ? -d : d); ! 111: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.