~ubuntu-branches/ubuntu/maverick/ruby1.8/maverick-security

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