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