xref: /plan9/sys/src/cmd/unix/drawterm/libc/charstod.c (revision 2282df4ee19682a10ae95200202320ff2912f104)
18ccd4a63SDavid du Colombier #include <u.h>
28ccd4a63SDavid du Colombier #include <libc.h>
3*0d601874SDavid du Colombier #include "fmtdef.h"
48ccd4a63SDavid du Colombier 
58ccd4a63SDavid du Colombier /*
68ccd4a63SDavid du Colombier  * Reads a floating-point number by interpreting successive characters
78ccd4a63SDavid du Colombier  * returned by (*f)(vp).  The last call it makes to f terminates the
88ccd4a63SDavid du Colombier  * scan, so is not a character in the number.  It may therefore be
98ccd4a63SDavid du Colombier  * necessary to back up the input stream up one byte after calling charstod.
108ccd4a63SDavid du Colombier  */
118ccd4a63SDavid du Colombier 
128ccd4a63SDavid du Colombier double
fmtcharstod(int (* f)(void *),void * vp)13*0d601874SDavid du Colombier fmtcharstod(int(*f)(void*), void *vp)
148ccd4a63SDavid du Colombier {
15*0d601874SDavid du Colombier 	double num, dem;
16*0d601874SDavid du Colombier 	int neg, eneg, dig, exp, c;
178ccd4a63SDavid du Colombier 
18*0d601874SDavid du Colombier 	num = 0;
19*0d601874SDavid du Colombier 	neg = 0;
20*0d601874SDavid du Colombier 	dig = 0;
21*0d601874SDavid du Colombier 	exp = 0;
22*0d601874SDavid du Colombier 	eneg = 0;
23*0d601874SDavid du Colombier 
248ccd4a63SDavid du Colombier 	c = (*f)(vp);
258ccd4a63SDavid du Colombier 	while(c == ' ' || c == '\t')
268ccd4a63SDavid du Colombier 		c = (*f)(vp);
278ccd4a63SDavid du Colombier 	if(c == '-' || c == '+'){
28*0d601874SDavid du Colombier 		if(c == '-')
29*0d601874SDavid du Colombier 			neg = 1;
30*0d601874SDavid du Colombier 		c = (*f)(vp);
318ccd4a63SDavid du Colombier 	}
328ccd4a63SDavid du Colombier 	while(c >= '0' && c <= '9'){
33*0d601874SDavid du Colombier 		num = num*10 + c-'0';
34*0d601874SDavid du Colombier 		c = (*f)(vp);
358ccd4a63SDavid du Colombier 	}
36*0d601874SDavid du Colombier 	if(c == '.')
37*0d601874SDavid du Colombier 		c = (*f)(vp);
388ccd4a63SDavid du Colombier 	while(c >= '0' && c <= '9'){
39*0d601874SDavid du Colombier 		num = num*10 + c-'0';
40*0d601874SDavid du Colombier 		dig++;
41*0d601874SDavid du Colombier 		c = (*f)(vp);
428ccd4a63SDavid du Colombier 	}
43*0d601874SDavid du Colombier 	if(c == 'e' || c == 'E'){
44*0d601874SDavid du Colombier 		c = (*f)(vp);
458ccd4a63SDavid du Colombier 		if(c == '-' || c == '+'){
46*0d601874SDavid du Colombier 			if(c == '-'){
47*0d601874SDavid du Colombier 				dig = -dig;
48*0d601874SDavid du Colombier 				eneg = 1;
49*0d601874SDavid du Colombier 			}
50*0d601874SDavid du Colombier 			c = (*f)(vp);
518ccd4a63SDavid du Colombier 		}
528ccd4a63SDavid du Colombier 		while(c >= '0' && c <= '9'){
53*0d601874SDavid du Colombier 			exp = exp*10 + c-'0';
54*0d601874SDavid du Colombier 			c = (*f)(vp);
558ccd4a63SDavid du Colombier 		}
568ccd4a63SDavid du Colombier 	}
57*0d601874SDavid du Colombier 	exp -= dig;
58*0d601874SDavid du Colombier 	if(exp < 0){
59*0d601874SDavid du Colombier 		exp = -exp;
60*0d601874SDavid du Colombier 		eneg = !eneg;
61*0d601874SDavid du Colombier 	}
62*0d601874SDavid du Colombier 	dem = __fmtpow10(exp);
63*0d601874SDavid du Colombier 	if(eneg)
64*0d601874SDavid du Colombier 		num /= dem;
65*0d601874SDavid du Colombier 	else
66*0d601874SDavid du Colombier 		num *= dem;
67*0d601874SDavid du Colombier 	if(neg)
68*0d601874SDavid du Colombier 		return -num;
69*0d601874SDavid du Colombier 	return num;
708ccd4a63SDavid du Colombier }
71