12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- #include <math.h>
- #include <errno.h>
- /*
- * bug: should detect overflow, set errno = ERANGE, and return +/- HUGE_VAL
- */
- double
- strtod(const char *cp, char **endptr)
- {
- double num, dem;
- extern double pow10(int);
- int neg, eneg, dig, predig, exp, c;
- const char *p;
- p = cp;
- num = 0;
- neg = 0;
- dig = 0;
- predig = 0;
- exp = 0;
- eneg = 0;
- c = *p++;
- while(c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\v' || c == '\r')
- c = *p++;
- if(c == '-' || c == '+'){
- if(c == '-')
- neg = 1;
- c = *p++;
- }
- while(c >= '0' && c <= '9'){
- num = num*10 + c-'0';
- predig++;
- c = *p++;
- }
- if(c == '.')
- c = *p++;
- while(c >= '0' && c <= '9'){
- num = num*10 + c-'0';
- dig++;
- c = *p++;
- }
- if(dig+predig == 0){
- if(endptr)
- *endptr = (char *)cp;
- return 0.0;
- }
- if(c == 'e' || c == 'E'){
- c = *p++;
- if(c == '-' || c == '+'){
- if(c == '-'){
- dig = -dig;
- eneg = 1;
- }
- c = *p++;
- }
- while(c >= '0' && c <= '9'){
- exp = exp*10 + c-'0';
- c = *p++;
- }
- }
- exp -= dig;
- if(exp < 0){
- exp = -exp;
- eneg = !eneg;
- }
- dem = pow10(exp);
- if(dem==HUGE_VAL)
- num = eneg? 0.0 : HUGE_VAL;
- else if(dem==0)
- num = eneg? HUGE_VAL : 0.0;
- else if(eneg)
- num /= dem;
- else
- num *= dem;
- if(neg)
- num = -num;
- if(endptr){
- *endptr = (char *)--p;
- /*
- * Fix cases like 2.3e+
- */
- while(p > cp){
- c = *--p;
- if(c!='-' && c!='+' && c!='e' && c!='E')
- break;
- (*endptr)--;
- }
- }
- return num;
- }
|