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