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