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