|
|
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.