xref: /inferno-os/lib9/charstod.c (revision 7ded4a527bdfd0e8b3a9049955f2af89e5f039ee)
1 #include "lib9.h"
2 
3 /*
4  * Reads a floating-point number by interpreting successive characters
5  * returned by (*f)(vp).  The last call it makes to f terminates the
6  * scan, so is not a character in the number.  It may therefore be
7  * necessary to back up the input stream up one byte after calling charstod.
8  */
9 
10 #define ADVANCE *s++ = c; if(s>=e) return NaN(); c = (*f)(vp)
11 
12 double
charstod(int (* f)(void *),void * vp)13 charstod(int(*f)(void*), void *vp)
14 {
15 	char str[400], *s, *e, *start;
16 	int c;
17 
18 	s = str;
19 	e = str + sizeof str - 1;
20 	c = (*f)(vp);
21 	while(c == ' ' || c == '\t')
22 		c = (*f)(vp);
23 	if(c == '-' || c == '+'){
24 		ADVANCE;
25 	}
26 	start = s;
27 	while(c >= '0' && c <= '9'){
28 		ADVANCE;
29 	}
30 	if(c == '.'){
31 		ADVANCE;
32 		while(c >= '0' && c <= '9'){
33 			ADVANCE;
34 		}
35 	}
36 	if(s > start && (c == 'e' || c == 'E')){
37 		ADVANCE;
38 		if(c == '-' || c == '+'){
39 			ADVANCE;
40 		}
41 		while(c >= '0' && c <= '9'){
42 			ADVANCE;
43 		}
44 	}else if(s == start && (c == 'i' || c == 'I')){
45 		ADVANCE;
46 		if(c != 'n' && c != 'N')
47 			return NaN();
48 		ADVANCE;
49 		if(c != 'f' && c != 'F')
50 			return NaN();
51 		ADVANCE;
52 		if(c != 'i' && c != 'I')
53 			return NaN();
54 		ADVANCE;
55 		if(c != 'n' && c != 'N')
56 			return NaN();
57 		ADVANCE;
58 		if(c != 'i' && c != 'I')
59 			return NaN();
60 		ADVANCE;
61 		if(c != 't' && c != 'T')
62 			return NaN();
63 		ADVANCE;
64 		if(c != 'y' && c != 'Y')
65 			return NaN();
66 		ADVANCE;  /* so caller can back up uniformly */
67 		USED(c);
68 	}else if(s == str && (c == 'n' || c == 'N')){
69 		ADVANCE;
70 		if(c != 'a' && c != 'A')
71 			return NaN();
72 		ADVANCE;
73 		if(c != 'n' && c != 'N')
74 			return NaN();
75 		ADVANCE;  /* so caller can back up uniformly */
76 		USED(c);
77 	}
78 	*s = 0;
79 	return strtod(str, &s);
80 }
81