1*3e12c5d1SDavid du Colombier #include <math.h>
2*3e12c5d1SDavid du Colombier #include <errno.h>
3*3e12c5d1SDavid du Colombier
4*3e12c5d1SDavid du Colombier /*
5*3e12c5d1SDavid du Colombier * bug: should detect overflow, set errno = ERANGE, and return +/- HUGE_VAL
6*3e12c5d1SDavid du Colombier */
7*3e12c5d1SDavid du Colombier double
strtod(const char * cp,char ** endptr)8*3e12c5d1SDavid du Colombier strtod(const char *cp, char **endptr)
9*3e12c5d1SDavid du Colombier {
10*3e12c5d1SDavid du Colombier double num, dem;
11*3e12c5d1SDavid du Colombier extern double pow10(int);
12*3e12c5d1SDavid du Colombier int neg, eneg, dig, predig, exp, c;
13*3e12c5d1SDavid du Colombier const char *p;
14*3e12c5d1SDavid du Colombier
15*3e12c5d1SDavid du Colombier p = cp;
16*3e12c5d1SDavid du Colombier num = 0;
17*3e12c5d1SDavid du Colombier neg = 0;
18*3e12c5d1SDavid du Colombier dig = 0;
19*3e12c5d1SDavid du Colombier predig = 0;
20*3e12c5d1SDavid du Colombier exp = 0;
21*3e12c5d1SDavid du Colombier eneg = 0;
22*3e12c5d1SDavid du Colombier
23*3e12c5d1SDavid du Colombier c = *p++;
24*3e12c5d1SDavid du Colombier while(c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\v' || c == '\r')
25*3e12c5d1SDavid du Colombier c = *p++;
26*3e12c5d1SDavid du Colombier if(c == '-' || c == '+'){
27*3e12c5d1SDavid du Colombier if(c == '-')
28*3e12c5d1SDavid du Colombier neg = 1;
29*3e12c5d1SDavid du Colombier c = *p++;
30*3e12c5d1SDavid du Colombier }
31*3e12c5d1SDavid du Colombier while(c >= '0' && c <= '9'){
32*3e12c5d1SDavid du Colombier num = num*10 + c-'0';
33*3e12c5d1SDavid du Colombier predig++;
34*3e12c5d1SDavid du Colombier c = *p++;
35*3e12c5d1SDavid du Colombier }
36*3e12c5d1SDavid du Colombier if(c == '.')
37*3e12c5d1SDavid du Colombier c = *p++;
38*3e12c5d1SDavid du Colombier while(c >= '0' && c <= '9'){
39*3e12c5d1SDavid du Colombier num = num*10 + c-'0';
40*3e12c5d1SDavid du Colombier dig++;
41*3e12c5d1SDavid du Colombier c = *p++;
42*3e12c5d1SDavid du Colombier }
43*3e12c5d1SDavid du Colombier if(dig+predig == 0){
44*3e12c5d1SDavid du Colombier if(endptr)
45*3e12c5d1SDavid du Colombier *endptr = (char *)cp;
46*3e12c5d1SDavid du Colombier return 0.0;
47*3e12c5d1SDavid du Colombier }
48*3e12c5d1SDavid du Colombier if(c == 'e' || c == 'E'){
49*3e12c5d1SDavid du Colombier c = *p++;
50*3e12c5d1SDavid du Colombier if(c == '-' || c == '+'){
51*3e12c5d1SDavid du Colombier if(c == '-'){
52*3e12c5d1SDavid du Colombier dig = -dig;
53*3e12c5d1SDavid du Colombier eneg = 1;
54*3e12c5d1SDavid du Colombier }
55*3e12c5d1SDavid du Colombier c = *p++;
56*3e12c5d1SDavid du Colombier }
57*3e12c5d1SDavid du Colombier while(c >= '0' && c <= '9'){
58*3e12c5d1SDavid du Colombier exp = exp*10 + c-'0';
59*3e12c5d1SDavid du Colombier c = *p++;
60*3e12c5d1SDavid du Colombier }
61*3e12c5d1SDavid du Colombier }
62*3e12c5d1SDavid du Colombier exp -= dig;
63*3e12c5d1SDavid du Colombier if(exp < 0){
64*3e12c5d1SDavid du Colombier exp = -exp;
65*3e12c5d1SDavid du Colombier eneg = !eneg;
66*3e12c5d1SDavid du Colombier }
67*3e12c5d1SDavid du Colombier dem = pow10(exp);
68*3e12c5d1SDavid du Colombier if(dem==HUGE_VAL)
69*3e12c5d1SDavid du Colombier num = eneg? 0.0 : HUGE_VAL;
70*3e12c5d1SDavid du Colombier else if(dem==0)
71*3e12c5d1SDavid du Colombier num = eneg? HUGE_VAL : 0.0;
72*3e12c5d1SDavid du Colombier else if(eneg)
73*3e12c5d1SDavid du Colombier num /= dem;
74*3e12c5d1SDavid du Colombier else
75*3e12c5d1SDavid du Colombier num *= dem;
76*3e12c5d1SDavid du Colombier if(neg)
77*3e12c5d1SDavid du Colombier num = -num;
78*3e12c5d1SDavid du Colombier if(endptr){
79*3e12c5d1SDavid du Colombier *endptr = (char *)--p;
80*3e12c5d1SDavid du Colombier /*
81*3e12c5d1SDavid du Colombier * Fix cases like 2.3e+
82*3e12c5d1SDavid du Colombier */
83*3e12c5d1SDavid du Colombier while(p > cp){
84*3e12c5d1SDavid du Colombier c = *--p;
85*3e12c5d1SDavid du Colombier if(c!='-' && c!='+' && c!='e' && c!='E')
86*3e12c5d1SDavid du Colombier break;
87*3e12c5d1SDavid du Colombier (*endptr)--;
88*3e12c5d1SDavid du Colombier }
89*3e12c5d1SDavid du Colombier }
90*3e12c5d1SDavid du Colombier return num;
91*3e12c5d1SDavid du Colombier }
92