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