xref: /inferno-os/libkern/charstod.c (revision 3cd4f1d15146c08f05206d6328ecbc1c7fdc8dfa)
1*3cd4f1d1SCharles Forsyth #include "lib9.h"
237da2899SCharles.Forsyth 
337da2899SCharles.Forsyth /*
437da2899SCharles.Forsyth  * Reads a floating-point number by interpreting successive characters
537da2899SCharles.Forsyth  * returned by (*f)(vp).  The last call it makes to f terminates the
637da2899SCharles.Forsyth  * scan, so is not a character in the number.  It may therefore be
737da2899SCharles.Forsyth  * necessary to back up the input stream up one byte after calling charstod.
837da2899SCharles.Forsyth  */
937da2899SCharles.Forsyth 
10*3cd4f1d1SCharles Forsyth #define ADVANCE *s++ = c; if(s>=e) return NaN(); c = (*f)(vp)
11*3cd4f1d1SCharles Forsyth 
1237da2899SCharles.Forsyth double
charstod(int (* f)(void *),void * vp)1337da2899SCharles.Forsyth charstod(int(*f)(void*), void *vp)
1437da2899SCharles.Forsyth {
15*3cd4f1d1SCharles Forsyth 	char str[400], *s, *e, *start;
16*3cd4f1d1SCharles Forsyth 	int c;
1737da2899SCharles.Forsyth 
18*3cd4f1d1SCharles Forsyth 	s = str;
19*3cd4f1d1SCharles Forsyth 	e = str + sizeof str - 1;
2037da2899SCharles.Forsyth 	c = (*f)(vp);
2137da2899SCharles.Forsyth 	while(c == ' ' || c == '\t')
2237da2899SCharles.Forsyth 		c = (*f)(vp);
2337da2899SCharles.Forsyth 	if(c == '-' || c == '+'){
24*3cd4f1d1SCharles Forsyth 		ADVANCE;
2537da2899SCharles.Forsyth 	}
26*3cd4f1d1SCharles Forsyth 	start = s;
2737da2899SCharles.Forsyth 	while(c >= '0' && c <= '9'){
28*3cd4f1d1SCharles Forsyth 		ADVANCE;
2937da2899SCharles.Forsyth 	}
30*3cd4f1d1SCharles Forsyth 	if(c == '.'){
31*3cd4f1d1SCharles Forsyth 		ADVANCE;
3237da2899SCharles.Forsyth 		while(c >= '0' && c <= '9'){
33*3cd4f1d1SCharles Forsyth 			ADVANCE;
3437da2899SCharles.Forsyth 		}
35*3cd4f1d1SCharles Forsyth 	}
36*3cd4f1d1SCharles Forsyth 	if(s > start && (c == 'e' || c == 'E')){
37*3cd4f1d1SCharles Forsyth 		ADVANCE;
3837da2899SCharles.Forsyth 		if(c == '-' || c == '+'){
39*3cd4f1d1SCharles Forsyth 			ADVANCE;
4037da2899SCharles.Forsyth 		}
4137da2899SCharles.Forsyth 		while(c >= '0' && c <= '9'){
42*3cd4f1d1SCharles Forsyth 			ADVANCE;
4337da2899SCharles.Forsyth 		}
44*3cd4f1d1SCharles Forsyth 	}else if(s == start && (c == 'i' || c == 'I')){
45*3cd4f1d1SCharles Forsyth 		ADVANCE;
46*3cd4f1d1SCharles Forsyth 		if(c != 'n' && c != 'N')
47*3cd4f1d1SCharles Forsyth 			return NaN();
48*3cd4f1d1SCharles Forsyth 		ADVANCE;
49*3cd4f1d1SCharles Forsyth 		if(c != 'f' && c != 'F')
50*3cd4f1d1SCharles Forsyth 			return NaN();
51*3cd4f1d1SCharles Forsyth 		ADVANCE;
52*3cd4f1d1SCharles Forsyth 		if(c != 'i' && c != 'I')
53*3cd4f1d1SCharles Forsyth 			return NaN();
54*3cd4f1d1SCharles Forsyth 		ADVANCE;
55*3cd4f1d1SCharles Forsyth 		if(c != 'n' && c != 'N')
56*3cd4f1d1SCharles Forsyth 			return NaN();
57*3cd4f1d1SCharles Forsyth 		ADVANCE;
58*3cd4f1d1SCharles Forsyth 		if(c != 'i' && c != 'I')
59*3cd4f1d1SCharles Forsyth 			return NaN();
60*3cd4f1d1SCharles Forsyth 		ADVANCE;
61*3cd4f1d1SCharles Forsyth 		if(c != 't' && c != 'T')
62*3cd4f1d1SCharles Forsyth 			return NaN();
63*3cd4f1d1SCharles Forsyth 		ADVANCE;
64*3cd4f1d1SCharles Forsyth 		if(c != 'y' && c != 'Y')
65*3cd4f1d1SCharles Forsyth 			return NaN();
66*3cd4f1d1SCharles Forsyth 		ADVANCE;  /* so caller can back up uniformly */
67*3cd4f1d1SCharles Forsyth 		USED(c);
68*3cd4f1d1SCharles Forsyth 	}else if(s == str && (c == 'n' || c == 'N')){
69*3cd4f1d1SCharles Forsyth 		ADVANCE;
70*3cd4f1d1SCharles Forsyth 		if(c != 'a' && c != 'A')
71*3cd4f1d1SCharles Forsyth 			return NaN();
72*3cd4f1d1SCharles Forsyth 		ADVANCE;
73*3cd4f1d1SCharles Forsyth 		if(c != 'n' && c != 'N')
74*3cd4f1d1SCharles Forsyth 			return NaN();
75*3cd4f1d1SCharles Forsyth 		ADVANCE;  /* so caller can back up uniformly */
76*3cd4f1d1SCharles Forsyth 		USED(c);
7737da2899SCharles.Forsyth 	}
78*3cd4f1d1SCharles Forsyth 	*s = 0;
79*3cd4f1d1SCharles Forsyth 	return strtod(str, &s);
8037da2899SCharles.Forsyth }
81