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