1 #include <ctype.h>
2 #include "string.h"
3 #include <math.h>
4
5 double
strtod(str,ptr)6 strtod(str, ptr)
7 char *str;
8 char **ptr;
9 {
10 int sign = 1;
11 register char c;
12 register char *s = str;
13 register char *p;
14 register i;
15 int expon, expon_s;
16 double mult, mant, atof();
17
18 /* Skip whitespace */
19 while (isspace(*s))
20 s++;
21
22 /* Check for sign */
23 c = *s;
24 if (c == '+') {
25 sign = 1;
26 s++;
27 } else if (c == '-') {
28 sign = -1;
29 s++;
30 } else if (!isdigit(c)) {
31 /* String has to be one of INF INFINITY NAN(string w/o ')') */
32 char buf[10]; /* to make a lowercase comparison */
33 double big = 1000000.0;
34 int slen = strlen(s);
35
36 (void) strncpy(buf, s, 10);
37 for (p = buf, i=slen; i-- != 0; p++ ) {
38 if (isupper(*p))
39 *p = tolower(*p);
40 }
41
42 if (strncmp(buf, "inf", 3) == 0) {
43 if (ptr)
44 *ptr = s+3;
45 return (sign * exp(big));
46 } else if (strncmp(buf, "infinity",8) == 0) {
47 if (ptr)
48 *ptr = s+8;
49 return (sign * exp(big));
50 } else if (strncmp(buf, "nan",3) == 0 && *(buf+3) != '(') {
51 if (ptr)
52 *ptr = s+3;
53 return (sign * exp(big)) / exp(big);
54 } else if (strncmp(buf, "nan(", 4) == 0) {
55 /* Rest has to end in ')' and not include ')' */
56 p = strchr(buf, ')');
57 if (p == (char *) 0) {
58 /* No closing ')' */
59 if (ptr)
60 *ptr = str;
61 return 0.0;
62 }
63 if (ptr)
64 *ptr = s + (p + 1 - buf);
65 return exp(big) / exp(big);
66 }
67 }
68
69 /* To get here: we've got a sign, now need mantissa[+exponent] */
70 for (mant = 0.0; isdigit(*s);)
71 mant = (mant * 10.0) + (*s++ - '0');
72 if (*s == '.') {
73 /* Collect fraction */
74 s++;
75 for ( mult = 0.1; isdigit(*s); mult *= 0.1 )
76 mant += (*s++ - '0') * mult;
77 }
78 /* Check for exponent character */
79 c = *s;
80 if (c != 'e' && c != 'E' && c != 'd' && c != 'D') {
81 if (ptr)
82 *ptr = s;
83 return sign * mant;
84 }
85 /* Check for <sign><digit> or <digit> following exponent character */
86 c = *(s+1);
87 if (c == '+' || c == '-') {
88 if (!isdigit(*(s+2))) {
89 if (ptr)
90 *ptr = s;
91 return sign * mant;
92 }
93 } else if (!isdigit(c)) {
94 if (ptr)
95 *ptr = s;
96 return sign * mant;
97 }
98 /* Move past exponent character */
99 s++;
100 /* Check for sign */
101 switch (*s) {
102 case '+':
103 expon_s = 1;
104 s++;
105 break;
106 case '-':
107 expon_s = -1;
108 s++;
109 break;
110 default:
111 expon_s = 1;
112 }
113 /* Collect exponent */
114 for (expon = 0; isdigit(*s);)
115 expon = (expon * 10) + (*s++ - '0');
116 if (expon_s == -1)
117 expon = -expon;
118 if (ptr)
119 *ptr = s;
120 return sign * mant * pow(10.0, (double) expon);
121 }
122