| /* | |
| * The authors of this software are Rob Pike and Ken Thompson, | |
| * with contributions from Mike Burrows and Sean Dorward. | |
| * | |
| * Copyright (c) 2002-2006 by Lucent Technologies. | |
| * Portions Copyright (c) 2004 Google Inc. | |
| * | |
| * Permission to use, copy, modify, and distribute this software for any | |
| * purpose without fee is hereby granted, provided that this entire notice | |
| * is included in all copies of any software which is or includes a copy | |
| * or modification of this software and in all copies of the supporting | |
| * documentation for such software. | |
| * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED | |
| * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES | |
| * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING | |
| * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. | |
| */ | |
| #include <u.h> | |
| #include <libc.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; | |
| } |