xref: /plan9/sys/src/libc/port/charstod.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include <u.h>
2 #include <libc.h>
3 
4 /*
5  * Reads a floating-point number by interpreting successive characters
6  * returned by (*f)(vp).  The last call it makes to f terminates the
7  * scan, so is not a character in the number.  It may therefore be
8  * necessary to back up the input stream up one byte after calling charstod.
9  */
10 
11 double
12 charstod(int(*f)(void*), void *vp)
13 {
14 	double num, dem;
15 	int neg, eneg, dig, exp, c;
16 
17 	num = 0;
18 	neg = 0;
19 	dig = 0;
20 	exp = 0;
21 	eneg = 0;
22 
23 	c = (*f)(vp);
24 	while(c == ' ' || c == '\t')
25 		c = (*f)(vp);
26 	if(c == '-' || c == '+'){
27 		if(c == '-')
28 			neg = 1;
29 		c = (*f)(vp);
30 	}
31 	while(c >= '0' && c <= '9'){
32 		num = num*10 + c-'0';
33 		c = (*f)(vp);
34 	}
35 	if(c == '.')
36 		c = (*f)(vp);
37 	while(c >= '0' && c <= '9'){
38 		num = num*10 + c-'0';
39 		dig++;
40 		c = (*f)(vp);
41 	}
42 	if(c == 'e' || c == 'E'){
43 		c = (*f)(vp);
44 		if(c == '-' || c == '+'){
45 			if(c == '-'){
46 				dig = -dig;
47 				eneg = 1;
48 			}
49 			c = (*f)(vp);
50 		}
51 		while(c >= '0' && c <= '9'){
52 			exp = exp*10 + c-'0';
53 			c = (*f)(vp);
54 		}
55 	}
56 	exp -= dig;
57 	if(exp < 0){
58 		exp = -exp;
59 		eneg = !eneg;
60 	}
61 	dem = pow10(exp);
62 	if(eneg)
63 		num /= dem;
64 	else
65 		num *= dem;
66 	if(neg)
67 		return -num;
68 	return num;
69 }
70