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