/* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ | |
#include <stdarg.h> | |
#include <string.h> | |
#include "plan9.h" | |
#include "fmt.h" | |
#include "fmtdef.h" | |
/* | |
* Reads a floating-point number by interpreting successive characters | |
* returned by (*f)(vp). The last call it makes to f terminates the | |
* scan, so is not a character in the number. It may therefore be | |
* necessary to back up the input stream up one byte after calling charstod. | |
*/ | |
double | |
fmtcharstod(int(*f)(void*), void *vp) | |
{ | |
double num, dem; | |
int neg, eneg, dig, exp, c; | |
num = 0; | |
neg = 0; | |
dig = 0; | |
exp = 0; | |
eneg = 0; | |
c = (*f)(vp); | |
while(c == ' ' || c == '\t') | |
c = (*f)(vp); | |
if(c == '-' || c == '+'){ | |
if(c == '-') | |
neg = 1; | |
c = (*f)(vp); | |
} | |
while(c >= '0' && c <= '9'){ | |
num = num*10 + c-'0'; | |
c = (*f)(vp); | |
} | |
if(c == '.') | |
c = (*f)(vp); | |
while(c >= '0' && c <= '9'){ | |
num = num*10 + c-'0'; | |
dig++; | |
c = (*f)(vp); | |
} | |
if(c == 'e' || c == 'E'){ | |
c = (*f)(vp); | |
if(c == '-' || c == '+'){ | |
if(c == '-'){ | |
dig = -dig; | |
eneg = 1; | |
} | |
c = (*f)(vp); | |
} | |
while(c >= '0' && c <= '9'){ | |
exp = exp*10 + c-'0'; | |
c = (*f)(vp); | |
} | |
} | |
exp -= dig; | |
if(exp < 0){ | |
exp = -exp; | |
eneg = !eneg; | |
} | |
dem = __fmtpow10(exp); | |
if(eneg) | |
num /= dem; | |
else | |
num *= dem; | |
if(neg) | |
return -num; | |
return num; | |
} |