xref: /plan9-contrib/sys/src/cmd/unix/drawterm/libc/charstod.c (revision 0d601874851962e88c6c60fdd2e637bba04e13c2)
1*0d601874SDavid du Colombier /*
2*0d601874SDavid du Colombier  * The authors of this software are Rob Pike and Ken Thompson.
3*0d601874SDavid du Colombier  *              Copyright (c) 2002 by Lucent Technologies.
4*0d601874SDavid du Colombier  * Permission to use, copy, modify, and distribute this software for any
5*0d601874SDavid du Colombier  * purpose without fee is hereby granted, provided that this entire notice
6*0d601874SDavid du Colombier  * is included in all copies of any software which is or includes a copy
7*0d601874SDavid du Colombier  * or modification of this software and in all copies of the supporting
8*0d601874SDavid du Colombier  * documentation for such software.
9*0d601874SDavid du Colombier  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
10*0d601874SDavid du Colombier  * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE
11*0d601874SDavid du Colombier  * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
12*0d601874SDavid du Colombier  * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
13*0d601874SDavid du Colombier  */
148ccd4a63SDavid du Colombier #include <u.h>
158ccd4a63SDavid du Colombier #include <libc.h>
16*0d601874SDavid du Colombier #include "fmtdef.h"
178ccd4a63SDavid du Colombier 
188ccd4a63SDavid du Colombier /*
198ccd4a63SDavid du Colombier  * Reads a floating-point number by interpreting successive characters
208ccd4a63SDavid du Colombier  * returned by (*f)(vp).  The last call it makes to f terminates the
218ccd4a63SDavid du Colombier  * scan, so is not a character in the number.  It may therefore be
228ccd4a63SDavid du Colombier  * necessary to back up the input stream up one byte after calling charstod.
238ccd4a63SDavid du Colombier  */
248ccd4a63SDavid du Colombier 
258ccd4a63SDavid du Colombier double
26*0d601874SDavid du Colombier fmtcharstod(int(*f)(void*), void *vp)
278ccd4a63SDavid du Colombier {
28*0d601874SDavid du Colombier 	double num, dem;
29*0d601874SDavid du Colombier 	int neg, eneg, dig, exp, c;
308ccd4a63SDavid du Colombier 
31*0d601874SDavid du Colombier 	num = 0;
32*0d601874SDavid du Colombier 	neg = 0;
33*0d601874SDavid du Colombier 	dig = 0;
34*0d601874SDavid du Colombier 	exp = 0;
35*0d601874SDavid du Colombier 	eneg = 0;
36*0d601874SDavid du Colombier 
378ccd4a63SDavid du Colombier 	c = (*f)(vp);
388ccd4a63SDavid du Colombier 	while(c == ' ' || c == '\t')
398ccd4a63SDavid du Colombier 		c = (*f)(vp);
408ccd4a63SDavid du Colombier 	if(c == '-' || c == '+'){
41*0d601874SDavid du Colombier 		if(c == '-')
42*0d601874SDavid du Colombier 			neg = 1;
43*0d601874SDavid du Colombier 		c = (*f)(vp);
448ccd4a63SDavid du Colombier 	}
458ccd4a63SDavid du Colombier 	while(c >= '0' && c <= '9'){
46*0d601874SDavid du Colombier 		num = num*10 + c-'0';
47*0d601874SDavid du Colombier 		c = (*f)(vp);
488ccd4a63SDavid du Colombier 	}
49*0d601874SDavid du Colombier 	if(c == '.')
50*0d601874SDavid du Colombier 		c = (*f)(vp);
518ccd4a63SDavid du Colombier 	while(c >= '0' && c <= '9'){
52*0d601874SDavid du Colombier 		num = num*10 + c-'0';
53*0d601874SDavid du Colombier 		dig++;
54*0d601874SDavid du Colombier 		c = (*f)(vp);
558ccd4a63SDavid du Colombier 	}
56*0d601874SDavid du Colombier 	if(c == 'e' || c == 'E'){
57*0d601874SDavid du Colombier 		c = (*f)(vp);
588ccd4a63SDavid du Colombier 		if(c == '-' || c == '+'){
59*0d601874SDavid du Colombier 			if(c == '-'){
60*0d601874SDavid du Colombier 				dig = -dig;
61*0d601874SDavid du Colombier 				eneg = 1;
62*0d601874SDavid du Colombier 			}
63*0d601874SDavid du Colombier 			c = (*f)(vp);
648ccd4a63SDavid du Colombier 		}
658ccd4a63SDavid du Colombier 		while(c >= '0' && c <= '9'){
66*0d601874SDavid du Colombier 			exp = exp*10 + c-'0';
67*0d601874SDavid du Colombier 			c = (*f)(vp);
688ccd4a63SDavid du Colombier 		}
698ccd4a63SDavid du Colombier 	}
70*0d601874SDavid du Colombier 	exp -= dig;
71*0d601874SDavid du Colombier 	if(exp < 0){
72*0d601874SDavid du Colombier 		exp = -exp;
73*0d601874SDavid du Colombier 		eneg = !eneg;
74*0d601874SDavid du Colombier 	}
75*0d601874SDavid du Colombier 	dem = __fmtpow10(exp);
76*0d601874SDavid du Colombier 	if(eneg)
77*0d601874SDavid du Colombier 		num /= dem;
78*0d601874SDavid du Colombier 	else
79*0d601874SDavid du Colombier 		num *= dem;
80*0d601874SDavid du Colombier 	if(neg)
81*0d601874SDavid du Colombier 		return -num;
82*0d601874SDavid du Colombier 	return num;
838ccd4a63SDavid du Colombier }
84