diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/lib/ap/gen/strtod.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/lib/ap/gen/strtod.c')
-rwxr-xr-x | sys/src/ape/lib/ap/gen/strtod.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/sys/src/ape/lib/ap/gen/strtod.c b/sys/src/ape/lib/ap/gen/strtod.c new file mode 100755 index 000000000..ca4939100 --- /dev/null +++ b/sys/src/ape/lib/ap/gen/strtod.c @@ -0,0 +1,91 @@ +#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; +} |