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