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