ref: 3c8246a31ce776976ee95310efa2c6e64a471993
dir: /sys/src/ape/lib/ap/gen/strtod.c/
#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; }