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