Mercurial > flash_v2
annotate packages/language/c/libc/current/src/stdlib/strtod.cxx @ 64:c38311975d4f ecos-sw-2000-01-28
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
| author | jlarmour |
|---|---|
| date | Fri, 28 Jan 2000 04:59:39 +0000 |
| parents | 443894e2e912 |
| children | bf00f99aec69 |
| rev | line source |
|---|---|
| 0 | 1 //=========================================================================== |
| 2 // | |
| 3 // strtod.cxx | |
| 4 // | |
| 5 // ANSI String to double-precision floating point conversion | |
| 6 // | |
| 7 //=========================================================================== | |
| 8 //####COPYRIGHTBEGIN#### | |
|
64
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
9 // |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
10 // ------------------------------------------- |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
11 // The contents of this file are subject to the Red Hat eCos Public License |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
12 // Version 1.0 (the "License"); you may not use this file except in |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
13 // compliance with the License. You may obtain a copy of the License at |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
14 // http://sourceware.cygnus.com/ecos |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
15 // |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
16 // Software distributed under the License is distributed on an |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
18 // License for the specific language governing rights and limitations under |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
19 // the License. |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
20 // |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
21 // The Original Code is eCos - Embedded Configurable Operating System, |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
22 // released September 30, 1998. |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
23 // |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
24 // The Initial Developer of the Original Code is Red Hat. |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
25 // Portions created by Red Hat are |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
26 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc. |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
27 // All Rights Reserved. |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
28 // ------------------------------------------- |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
2
diff
changeset
|
29 // |
| 0 | 30 //####COPYRIGHTEND#### |
| 31 //=========================================================================== | |
| 32 //#####DESCRIPTIONBEGIN#### | |
| 33 // | |
| 34 // Author(s): jlarmour | |
| 2 | 35 // Contributors: jlarmour |
| 0 | 36 // Date: 1998-02-13 |
| 37 // Purpose: | |
| 38 // Description: | |
| 39 // Usage: | |
| 40 // | |
| 41 //####DESCRIPTIONEND#### | |
| 42 // | |
| 43 //=========================================================================== | |
| 44 | |
| 45 // CONFIGURATION | |
| 46 | |
| 47 #include <pkgconf/libc.h> // Configuration header | |
| 48 | |
| 49 // Include the C library? And strtod()? | |
| 50 #if defined(CYGPKG_LIBC) && defined(CYGFUN_LIBC_strtod) | |
| 51 | |
| 52 // INCLUDES | |
| 53 | |
| 54 #include <cyg/infra/cyg_type.h> // Common type definitions and support | |
| 55 #include <cyg/infra/cyg_trac.h> // Tracing support | |
| 56 #include <cyg/infra/cyg_ass.h> // Assertion support | |
| 57 #include <stddef.h> // NULL, wchar_t and size_t from compiler | |
| 58 #include <stdlib.h> // Main header for stdlib functions | |
| 59 #include <ctype.h> // isspace() and isdigit() | |
| 60 #include "clibincl/stdlibsupp.hxx" // Support for stdlib functions | |
| 61 #include <float.h> // DBL_MIN_10_EXP and DBL_MAX_10_EXP | |
| 62 #include <math.h> // HUGE_VAL | |
| 63 #include <errno.h> // errno | |
| 64 | |
| 65 // EXPORTED SYMBOLS | |
| 66 | |
| 67 externC double | |
| 68 strtod( const char *, char ** ) CYGPRI_LIBC_WEAK_ALIAS("_strtod"); | |
| 69 | |
| 70 // CONSTANTS | |
| 71 | |
| 72 #define MAXE (DBL_MAX_10_EXP) | |
| 73 #define MINE (DBL_MIN_10_EXP) | |
| 74 | |
| 75 // flags | |
| 76 #define SIGN 0x01 | |
| 77 #define ESIGN 0x02 | |
| 78 #define DECP 0x04 | |
| 79 | |
| 80 | |
| 81 // MACROS | |
| 82 | |
| 83 #define Ise(c) ((c == 'e') || (c == 'E') || (c == 'd') || (c == 'D')) | |
| 84 #define Issign(c) ((c == '-') || (c == '+')) | |
| 85 #define Val(c) ((c - '0')) | |
| 86 | |
| 87 | |
| 88 // FUNCTIONS | |
| 89 | |
| 90 /* | |
| 91 * [atw] multiply 64 bit accumulator by 10 and add digit. | |
| 92 * The KA/CA way to do this should be to use | |
| 93 * a 64-bit integer internally and use "adjust" to | |
| 94 * convert it to float at the end of processing. | |
| 95 */ | |
| 96 static int | |
| 97 ten_mul(double *acc, int digit) | |
| 98 { | |
| 99 /* [atw] Crude, but effective (at least on a KB)... | |
| 100 */ | |
| 101 *acc *= 10; | |
| 102 *acc += digit; | |
| 103 | |
| 104 return 0; /* no overflow */ | |
| 105 } // ten_mul() | |
| 106 | |
| 107 | |
| 108 /* | |
| 109 * compute 10**x by successive squaring. | |
| 110 */ | |
| 111 | |
| 112 static const double | |
| 113 exp10(unsigned x) | |
| 114 { | |
| 115 static double powtab[] = {1.0, | |
| 116 10.0, | |
| 117 100.0, | |
| 118 1000.0, | |
| 119 10000.0}; | |
| 120 | |
| 121 if (x < (sizeof(powtab)/sizeof(double))) | |
| 122 return powtab[x]; | |
| 123 else if (x & 1) | |
| 124 return 10.0 * exp10(x-1); | |
| 125 else | |
| 126 return exp10(x/2) * exp10(x/2); | |
| 127 } // exp10() | |
| 128 | |
| 129 | |
| 130 /* | |
| 131 * return (*acc) scaled by 10**dexp. | |
| 132 */ | |
| 133 | |
| 134 static double | |
| 135 adjust(double *acc, int dexp, int sign) | |
| 136 /* *acc the 64 bit accumulator */ | |
| 137 /* dexp decimal exponent */ | |
| 138 /* sign sign flag */ | |
| 139 { | |
| 140 double r; | |
| 141 | |
| 142 if (dexp > MAXE) | |
| 143 { | |
| 144 errno = ERANGE; | |
| 145 return (sign) ? -HUGE_VAL : HUGE_VAL; | |
| 146 } | |
| 147 else if (dexp < MINE) | |
| 148 { | |
| 149 errno = ERANGE; | |
| 150 return 0.0; | |
| 151 } | |
| 152 | |
| 153 r = *acc; | |
| 154 if (sign) | |
| 155 r = -r; | |
| 156 if (dexp==0) | |
| 157 return r; | |
| 158 | |
| 159 if (dexp < 0) | |
| 160 return r / exp10(abs(dexp)); | |
| 161 else | |
| 162 return r * exp10(dexp); | |
| 163 } // adjust() | |
| 164 | |
| 165 | |
| 166 externC double | |
| 167 _strtod( const char *nptr, char **endptr ) | |
| 168 { | |
| 169 const char *start=nptr; | |
| 170 double accum = 0.0; | |
| 171 int flags = 0; | |
| 172 int texp = 0; | |
| 173 int e = 0; | |
| 174 int conv_done = 0; | |
| 175 | |
| 176 double retval; | |
| 177 | |
| 178 CYG_REPORT_FUNCNAMETYPE( "_strtod", "returning %f" ); | |
| 179 | |
| 180 CYG_CHECK_DATA_PTR( nptr, "nptr is an invalid pointer!" ); | |
| 181 | |
| 182 // endptr is allowed to be NULL, but if it isn't, we check it | |
| 183 if (endptr != NULL) | |
| 184 CYG_CHECK_DATA_PTR( endptr, "endptr is an invalid pointer!" ); | |
| 185 | |
| 186 while(isspace(*nptr)) nptr++; | |
| 187 if(*nptr == '\0') | |
| 188 { /* just leading spaces */ | |
| 189 if(endptr != NULL) *endptr = (char *)start; | |
| 190 return 0.0; | |
| 191 } | |
| 192 | |
| 193 | |
| 194 if(Issign(*nptr)) | |
| 195 { | |
| 196 if(*nptr == '-') flags = SIGN; | |
| 197 if(*++nptr == '\0') | |
| 198 { /* "+|-" : should be an error ? */ | |
| 199 if(endptr != NULL) *endptr = (char *)start; | |
| 200 return 0.0; | |
| 201 } | |
| 202 } | |
| 203 | |
| 204 for(; (isdigit(*nptr) || (*nptr == '.')); nptr++) | |
| 205 { | |
| 206 conv_done = 1; | |
| 207 if(*nptr == '.') | |
| 208 flags |= DECP; | |
| 209 else | |
| 210 { | |
| 211 if( ten_mul(&accum, Val(*nptr)) ) texp++; | |
| 212 if(flags & DECP) texp--; | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 if(Ise(*nptr)) | |
| 217 { | |
| 218 conv_done = 1; | |
| 219 if(*++nptr != '\0') /* skip e|E|d|D */ | |
| 220 { /* ! ([nptr]xxx[.[yyy]]e) */ | |
| 221 | |
| 222 while(isspace(*nptr)) nptr++; /* Ansi allows spaces after e */ | |
| 223 if(*nptr != '\0') | |
| 224 { /* ! ([nptr]xxx[.[yyy]]e[space]) */ | |
| 225 | |
| 226 if(Issign(*nptr)) | |
| 227 if(*nptr++ == '-') flags |= ESIGN; | |
| 228 | |
| 229 if(*nptr != '\0') | |
| 230 { /* ! ([nptr]xxx[.[yyy]]e[nptr]) -- error?? */ | |
| 231 | |
| 232 for(; isdigit(*nptr); nptr++) | |
| 233 if (e < MAXE) /* prevent from grossly overflowing */ | |
| 234 e = e*10 + Val(*nptr); | |
| 235 | |
| 236 /* dont care what comes after this */ | |
| 237 if(flags & ESIGN) | |
| 238 texp -= e; | |
| 239 else | |
| 240 texp += e; | |
| 241 } | |
| 242 } | |
| 243 } | |
| 244 } | |
| 245 | |
| 246 if(endptr != NULL) | |
| 247 *endptr = (char *)((conv_done) ? nptr : start); | |
| 248 | |
| 249 retval = adjust(&accum, (int)texp, (int)(flags & SIGN)); | |
| 250 | |
| 251 | |
| 252 CYG_REPORT_RETVAL( retval ); | |
| 253 | |
| 254 return retval; | |
| 255 } // _strtod() | |
| 256 | |
| 257 | |
| 258 #endif // if defined(CYGPKG_LIBC) && defined(CYGFUN_LIBC_strtod) | |
| 259 | |
| 260 // EOF strtod.cxx |
