1 /*
2  * strtod.c --
3  *
4  *	Source code for the "strtod" library procedure.
5  *
6  * Copyright (c) 1988-1993 The Regents of the University of California.
7  * Copyright (c) 1994 Sun Microsystems, Inc.
8  *
9  * See the file "license.terms" for information on usage and redistribution
10  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11  */
12 
13 #include "tclInt.h"
14 #include <ctype.h>
15 
16 #ifndef TRUE
17 #define TRUE 1
18 #define FALSE 0
19 #endif
20 #ifndef NULL
21 #define NULL 0
22 #endif
23 
24 static int maxExponent = 511;	/* Largest possible base 10 exponent.  Any
25 				 * exponent larger than this will already
26 				 * produce underflow or overflow, so there's
27 				 * no need to worry about additional digits.
28 				 */
29 static double powersOf10[] = {	/* Table giving binary powers of 10.  Entry */
30     10.,			/* is 10^2^i.  Used to convert decimal */
31     100.,			/* exponents into floating-point numbers. */
32     1.0e4,
33     1.0e8,
34     1.0e16,
35     1.0e32,
36     1.0e64,
37     1.0e128,
38     1.0e256
39 };
40 
41 /*
42  *----------------------------------------------------------------------
43  *
44  * strtod --
45  *
46  *	This procedure converts a floating-point number from an ASCII
47  *	decimal representation to internal double-precision format.
48  *
49  * Results:
50  *	The return value is the double-precision floating-point
51  *	representation of the characters in string.  If endPtr isn't
52  *	NULL, then *endPtr is filled in with the address of the
53  *	next character after the last one that was part of the
54  *	floating-point number.
55  *
56  * Side effects:
57  *	None.
58  *
59  *----------------------------------------------------------------------
60  */
61 
62 double
strtod(CONST char * string,char ** endPtr)63 strtod(
64     CONST char *string,		/* A decimal ASCII floating-point number,
65 				 * optionally preceded by white space. Must
66 				 * have form "-I.FE-X", where I is the integer
67 				 * part of the mantissa, F is the fractional
68 				 * part of the mantissa, and X is the
69 				 * exponent. Either of the signs may be "+",
70 				 * "-", or omitted. Either I or F may be
71 				 * omitted, or both. The decimal point isn't
72 				 * necessary unless F is present. The "E" may
73 				 * actually be an "e". E and X may both be
74 				 * omitted (but not just one). */
75     char **endPtr)		/* If non-NULL, store terminating character's
76 				 * address here. */
77 {
78     int sign, expSign = FALSE;
79     double fraction, dblExp, *d;
80     register CONST char *p;
81     register int c;
82     int exp = 0;		/* Exponent read from "EX" field. */
83     int fracExp = 0;		/* Exponent that derives from the fractional
84 				 * part. Under normal circumstatnces, it is
85 				 * the negative of the number of digits in F.
86 				 * However, if I is very long, the last digits
87 				 * of I get dropped (otherwise a long I with a
88 				 * large negative exponent could cause an
89 				 * unnecessary overflow on I alone). In this
90 				 * case, fracExp is incremented one for each
91 				 * dropped digit. */
92     int mantSize;		/* Number of digits in mantissa. */
93     int decPt;			/* Number of mantissa digits BEFORE decimal
94 				 * point. */
95     CONST char *pExp;		/* Temporarily holds location of exponent in
96 				 * string. */
97 
98     /*
99      * Strip off leading blanks and check for a sign.
100      */
101 
102     p = string;
103     while (isspace(UCHAR(*p))) {
104 	p += 1;
105     }
106     if (*p == '-') {
107 	sign = TRUE;
108 	p += 1;
109     } else {
110 	if (*p == '+') {
111 	    p += 1;
112 	}
113 	sign = FALSE;
114     }
115 
116     /*
117      * Count the number of digits in the mantissa (including the decimal
118      * point), and also locate the decimal point.
119      */
120 
121     decPt = -1;
122     for (mantSize = 0; ; mantSize += 1)
123     {
124 	c = *p;
125 	if (!isdigit(c)) {
126 	    if ((c != '.') || (decPt >= 0)) {
127 		break;
128 	    }
129 	    decPt = mantSize;
130 	}
131 	p += 1;
132     }
133 
134     /*
135      * Now suck up the digits in the mantissa. Use two integers to collect 9
136      * digits each (this is faster than using floating-point). If the mantissa
137      * has more than 18 digits, ignore the extras, since they can't affect the
138      * value anyway.
139      */
140 
141     pExp  = p;
142     p -= mantSize;
143     if (decPt < 0) {
144 	decPt = mantSize;
145     } else {
146 	mantSize -= 1;		/* One of the digits was the point. */
147     }
148     if (mantSize > 18) {
149 	fracExp = decPt - 18;
150 	mantSize = 18;
151     } else {
152 	fracExp = decPt - mantSize;
153     }
154     if (mantSize == 0) {
155 	fraction = 0.0;
156 	p = string;
157 	goto done;
158     } else {
159 	int frac1, frac2;
160 
161 	frac1 = 0;
162 	for ( ; mantSize > 9; mantSize -= 1) {
163 	    c = *p;
164 	    p += 1;
165 	    if (c == '.') {
166 		c = *p;
167 		p += 1;
168 	    }
169 	    frac1 = 10*frac1 + (c - '0');
170 	}
171 	frac2 = 0;
172 	for (; mantSize > 0; mantSize -= 1) {
173 	    c = *p;
174 	    p += 1;
175 	    if (c == '.') {
176 		c = *p;
177 		p += 1;
178 	    }
179 	    frac2 = 10*frac2 + (c - '0');
180 	}
181 	fraction = (1.0e9 * frac1) + frac2;
182     }
183 
184     /*
185      * Skim off the exponent.
186      */
187 
188     p = pExp;
189     if ((*p == 'E') || (*p == 'e')) {
190 	p += 1;
191 	if (*p == '-') {
192 	    expSign = TRUE;
193 	    p += 1;
194 	} else {
195 	    if (*p == '+') {
196 		p += 1;
197 	    }
198 	    expSign = FALSE;
199 	}
200 	if (!isdigit(UCHAR(*p))) {
201 	    p = pExp;
202 	    goto done;
203 	}
204 	while (isdigit(UCHAR(*p))) {
205 	    exp = exp * 10 + (*p - '0');
206 	    p += 1;
207 	}
208     }
209     if (expSign) {
210 	exp = fracExp - exp;
211     } else {
212 	exp = fracExp + exp;
213     }
214 
215     /*
216      * Generate a floating-point number that represents the exponent. Do this
217      * by processing the exponent one bit at a time to combine many powers of
218      * 2 of 10. Then combine the exponent with the fraction.
219      */
220 
221     if (exp < 0) {
222 	expSign = TRUE;
223 	exp = -exp;
224     } else {
225 	expSign = FALSE;
226     }
227     if (exp > maxExponent) {
228 	exp = maxExponent;
229 	errno = ERANGE;
230     }
231     dblExp = 1.0;
232     for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
233 	if (exp & 01) {
234 	    dblExp *= *d;
235 	}
236     }
237     if (expSign) {
238 	fraction /= dblExp;
239     } else {
240 	fraction *= dblExp;
241     }
242 
243   done:
244     if (endPtr != NULL) {
245 	*endPtr = (char *) p;
246     }
247 
248     if (sign) {
249 	return -fraction;
250     }
251     return fraction;
252 }
253