| 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 | } |
|---|