xref: /plan9-contrib/sys/src/ape/lib/fmt/charstod.c (revision 40ef9009116dd37656783aaadc8782c1d8bfb056)
1*40ef9009SDavid du Colombier /*
2*40ef9009SDavid du Colombier  * The authors of this software are Rob Pike and Ken Thompson.
3*40ef9009SDavid du Colombier  *              Copyright (c) 2002 by Lucent Technologies.
4*40ef9009SDavid du Colombier  * Permission to use, copy, modify, and distribute this software for any
5*40ef9009SDavid du Colombier  * purpose without fee is hereby granted, provided that this entire notice
6*40ef9009SDavid du Colombier  * is included in all copies of any software which is or includes a copy
7*40ef9009SDavid du Colombier  * or modification of this software and in all copies of the supporting
8*40ef9009SDavid du Colombier  * documentation for such software.
9*40ef9009SDavid du Colombier  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
10*40ef9009SDavid du Colombier  * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
11*40ef9009SDavid du Colombier  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
12*40ef9009SDavid du Colombier  * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
13*40ef9009SDavid du Colombier  */
14*40ef9009SDavid du Colombier #include <stdarg.h>
15*40ef9009SDavid du Colombier #include <string.h>
16*40ef9009SDavid du Colombier #include "utf.h"
17*40ef9009SDavid du Colombier #include "fmt.h"
18*40ef9009SDavid du Colombier #include "fmtdef.h"
19*40ef9009SDavid du Colombier 
20*40ef9009SDavid du Colombier /*
21*40ef9009SDavid du Colombier  * Reads a floating-point number by interpreting successive characters
22*40ef9009SDavid du Colombier  * returned by (*f)(vp).  The last call it makes to f terminates the
23*40ef9009SDavid du Colombier  * scan, so is not a character in the number.  It may therefore be
24*40ef9009SDavid du Colombier  * necessary to back up the input stream up one byte after calling charstod.
25*40ef9009SDavid du Colombier  */
26*40ef9009SDavid du Colombier 
27*40ef9009SDavid du Colombier double
fmtcharstod(int (* f)(void *),void * vp)28*40ef9009SDavid du Colombier fmtcharstod(int(*f)(void*), void *vp)
29*40ef9009SDavid du Colombier {
30*40ef9009SDavid du Colombier 	double num, dem;
31*40ef9009SDavid du Colombier 	int neg, eneg, dig, exp, c;
32*40ef9009SDavid du Colombier 
33*40ef9009SDavid du Colombier 	num = 0;
34*40ef9009SDavid du Colombier 	neg = 0;
35*40ef9009SDavid du Colombier 	dig = 0;
36*40ef9009SDavid du Colombier 	exp = 0;
37*40ef9009SDavid du Colombier 	eneg = 0;
38*40ef9009SDavid du Colombier 
39*40ef9009SDavid du Colombier 	c = (*f)(vp);
40*40ef9009SDavid du Colombier 	while(c == ' ' || c == '\t')
41*40ef9009SDavid du Colombier 		c = (*f)(vp);
42*40ef9009SDavid du Colombier 	if(c == '-' || c == '+'){
43*40ef9009SDavid du Colombier 		if(c == '-')
44*40ef9009SDavid du Colombier 			neg = 1;
45*40ef9009SDavid du Colombier 		c = (*f)(vp);
46*40ef9009SDavid du Colombier 	}
47*40ef9009SDavid du Colombier 	while(c >= '0' && c <= '9'){
48*40ef9009SDavid du Colombier 		num = num*10 + c-'0';
49*40ef9009SDavid du Colombier 		c = (*f)(vp);
50*40ef9009SDavid du Colombier 	}
51*40ef9009SDavid du Colombier 	if(c == '.')
52*40ef9009SDavid du Colombier 		c = (*f)(vp);
53*40ef9009SDavid du Colombier 	while(c >= '0' && c <= '9'){
54*40ef9009SDavid du Colombier 		num = num*10 + c-'0';
55*40ef9009SDavid du Colombier 		dig++;
56*40ef9009SDavid du Colombier 		c = (*f)(vp);
57*40ef9009SDavid du Colombier 	}
58*40ef9009SDavid du Colombier 	if(c == 'e' || c == 'E'){
59*40ef9009SDavid du Colombier 		c = (*f)(vp);
60*40ef9009SDavid du Colombier 		if(c == '-' || c == '+'){
61*40ef9009SDavid du Colombier 			if(c == '-'){
62*40ef9009SDavid du Colombier 				dig = -dig;
63*40ef9009SDavid du Colombier 				eneg = 1;
64*40ef9009SDavid du Colombier 			}
65*40ef9009SDavid du Colombier 			c = (*f)(vp);
66*40ef9009SDavid du Colombier 		}
67*40ef9009SDavid du Colombier 		while(c >= '0' && c <= '9'){
68*40ef9009SDavid du Colombier 			exp = exp*10 + c-'0';
69*40ef9009SDavid du Colombier 			c = (*f)(vp);
70*40ef9009SDavid du Colombier 		}
71*40ef9009SDavid du Colombier 	}
72*40ef9009SDavid du Colombier 	exp -= dig;
73*40ef9009SDavid du Colombier 	if(exp < 0){
74*40ef9009SDavid du Colombier 		exp = -exp;
75*40ef9009SDavid du Colombier 		eneg = !eneg;
76*40ef9009SDavid du Colombier 	}
77*40ef9009SDavid du Colombier 	dem = __fmtpow10(exp);
78*40ef9009SDavid du Colombier 	if(eneg)
79*40ef9009SDavid du Colombier 		num /= dem;
80*40ef9009SDavid du Colombier 	else
81*40ef9009SDavid du Colombier 		num *= dem;
82*40ef9009SDavid du Colombier 	if(neg)
83*40ef9009SDavid du Colombier 		return -num;
84*40ef9009SDavid du Colombier 	return num;
85*40ef9009SDavid du Colombier }
86