00001 #ifndef _STRTOD_H_
00002 #define _STRTOD_H_
00003
00004 #include <nlibc.h>
00005
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 #define _STRTOD_NAN_INF_STRINGS 1
00063
00064
00065
00066 #define _STRTOD_HEXADECIMAL_FLOATS 1
00067
00068
00069
00070
00071
00072 #define _STRTOD_LOG_SCALING 1
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 #define _STRTOD_ERRNO 1
00083
00084
00085
00086 #define _STRTOD_ENDPTR 1
00087
00088
00089
00090 #define _STRTOD_RESTRICT_EXP 1
00091
00092
00093
00094 #define _STRTOD_RESTRICT_DIGITS 1
00095
00096
00097
00098 #define _STRTOD_ZERO_CHECK 1
00099
00100
00101
00102
00103
00104 #ifdef _STRTOD_ERRNO
00105 #undef _STRTOD_ENDPTR
00106 #undef _STRTOD_RESTRICT_EXP
00107 #undef _STRTOD_RESTRICT_DIGITS
00108 #undef _STRTOD_ZERO_CHECK
00109 #define _STRTOD_ENDPTR 1
00110 #define _STRTOD_RESTRICT_EXP 1
00111 #define _STRTOD_RESTRICT_DIGITS 1
00112 #define _STRTOD_ZERO_CHECK 1
00113 #endif
00114
00115
00116
00117 #define _ISOC99_SOURCE 1
00118
00119 #define _STRTOD_HEXADECIMAL_FLOATS 1
00120
00121
00122
00123 #undef _STRTOD_FPMAX
00124
00125 #define FPMAX_TYPE 2 // double is largest FP type
00126 typedef double __fpmax_t;
00127 #define FPMAX_MIN_10_EXP DBL_MIN_10_EXP
00128
00129 #define NEED_STRTOD_WRAPPER
00130 #define NEED_STRTOF_WRAPPER
00131
00137 #define __FPMAX_ZERO_OR_INF_CHECK(x) ((x) == ((x)/4) )
00138
00139
00140
00141 #ifdef _STRTOD_RESTRICT_DIGITS
00142 #define EXP_DENORM_ADJUST DECIMAL_DIG
00143 #define MAX_ALLOWED_EXP (DECIMAL_DIG + EXP_DENORM_ADJUST - FPMAX_MIN_10_EXP)
00144
00145 #if MAX_ALLOWED_EXP > INT_MAX
00146 #error size assumption violated for MAX_ALLOWED_EXP
00147 #endif
00148 #else
00149
00150 #define MAX_ALLOWED_EXP ((20 - FPMAX_MIN_10_EXP) * 2)
00151 #endif
00152
00153
00154 #if defined(_STRTOD_RESTRICT_DIGITS) || defined(_STRTOD_ENDPTR) || defined(_STRTOD_HEXADECIMAL_FLOATS)
00155 #undef _STRTOD_NEED_NUM_DIGITS
00156 #define _STRTOD_NEED_NUM_DIGITS 1
00157 #endif
00158
00159
00160
00246 #ifndef __HAS_MAIN
00247 extern __fpmax_t strtod( const char *cstr, char **endptr );
00248 #else
00249 #if !defined(__cflow_processed) || defined(_uses_strtod_strtod_h)
00250 __fpmax_t strtod( const char *cstr, char **endptr )
00251 {
00252 __fpmax_t number;
00253 __fpmax_t p_base = 10;
00254 __fpmax_t exponent_power = 0;
00255 char *pos0;
00256 #ifdef _STRTOD_ENDPTR
00257 char *pos1;
00258 #endif
00259 char *pos;
00260 int exponent_temp;
00261 int negative;
00262 #ifdef _STRTOD_NEED_NUM_DIGITS
00263 int num_digits;
00264 #endif
00265
00266 #ifdef _STRTOD_HEXADECIMAL_FLOATS
00267 char expchar = 'e';
00268 char *poshex = NULL;
00269 typedef enum { ISdigit=0, ISXdigit=1 } cclass_t;
00270 cclass_t is_mask = ISdigit;
00271 #define EXPCHAR expchar
00272 #define IS_X_DIGIT(c) ((is_mask==ISdigit) ? (isdigit((c))) : (isxdigit((c))))
00273 #else
00274 #define EXPCHAR 'e'
00275 #define IS_X_DIGIT(C) isdigit((C))
00276 #endif
00277
00278
00279
00280
00281
00282 char *str;
00283 int len = strlen( cstr );
00284 str = stringexpand( cstr, len );
00285
00286 pos = (char *)str;
00287 while (isspace(*pos)) {
00288 ++pos;
00289 }
00290
00291 negative = 0;
00292 switch(*pos) {
00293 case '-': negative = 1;
00294 case '+': ++pos;
00295 }
00296
00297 #ifdef _STRTOD_HEXADECIMAL_FLOATS
00298 if ((*pos == '0') && (((pos[1])|0x20) == 'x')) {
00299 poshex = ++pos;
00300 ++pos;
00301 is_mask = ISXdigit;
00302 expchar = 'p';
00303 p_base = 16;
00304 }
00305 #endif
00306
00307 number = 0.;
00308 #ifdef _STRTOD_NEED_NUM_DIGITS
00309 num_digits = -1;
00310 #endif
00311 pos0 = NULL;
00312
00313 LOOP:
00314 while (IS_X_DIGIT(*pos)) {
00315 #ifdef _STRTOD_RESTRICT_DIGITS
00316 if (num_digits < 0) {
00317 ++num_digits;
00318 }
00319 if (num_digits || (*pos != '0')) {
00320 ++num_digits;
00321 if (num_digits <= DECIMAL_DIG) {
00322 #ifdef _STRTOD_HEXADECIMAL_FLOATS
00323 number = number * p_base
00324 + (isdigit(*pos)
00325 ? (*pos - '0')
00326 : (((*pos)|0x20) - ('a' - 10)));
00327 #else
00328 number = number * p_base + (*pos - '0');
00329 #endif
00330 }
00331 }
00332 #else
00333 #ifdef _STRTOD_NEED_NUM_DIGITS
00334 ++num_digits;
00335 #endif
00336 #ifdef _STRTOD_HEXADECIMAL_FLOATS
00337 number = number * p_base
00338 + (isdigit(*pos)
00339 ? (*pos - '0')
00340 : (((*pos)|0x20) - ('a' - 10)));
00341 #else
00342 number = number * p_base + (*pos - '0');
00343 #endif
00344 #endif
00345 ++pos;
00346 }
00347 if ((*pos == '.') && !pos0) {
00348 pos0 = ++pos;
00349 goto LOOP;
00350 }
00351
00352 #ifdef _STRTOD_NEED_NUM_DIGITS
00353 if (num_digits<0) {
00354 #ifdef _STRTOD_HEXADECIMAL_FLOATS
00355 if (poshex) {
00356 pos = poshex;
00357 goto DONE;
00358 }
00359 #endif
00360
00361 #ifdef _STRTOD_NAN_INF_STRINGS
00362 if (!pos0) {
00363
00364 static const char nan_inf_str[] = "\05nan\0\012infinity\0\05inf\0";
00365 int i = 0;
00366
00367 do {
00368
00369 int j = 0;
00370 while (tolower(pos[j]) == nan_inf_str[i+1+j]) {
00371 ++j;
00372 if (!nan_inf_str[i+1+j]) {
00373 number = i / 0.;
00374 if (negative) {
00375 number = -number;
00376 }
00377 pos += nan_inf_str[i] - 2;
00378 goto DONE;
00379 }
00380 }
00381 i += nan_inf_str[i];
00382 } while (nan_inf_str[i]);
00383 }
00384
00385 #endif
00386 #ifdef _STRTOD_ENDPTR
00387 pos = (char *) str;
00388 #endif
00389 goto DONE;
00390 }
00391 #endif
00392
00393 #ifdef _STRTOD_RESTRICT_DIGITS
00394 if (num_digits > DECIMAL_DIG) {
00395 exponent_power += num_digits - DECIMAL_DIG;
00396 }
00397 #endif
00398
00399 if (pos0) {
00400 exponent_power += pos0 - pos;
00401 }
00402
00403 #ifdef _STRTOD_HEXADECIMAL_FLOATS
00404 if (poshex) {
00405 exponent_power *= 4;
00406 p_base = 2;
00407 }
00408 #endif
00409
00410 if (negative) {
00411 number = -number;
00412 }
00413
00414
00415 if (((*pos)|0x20) == EXPCHAR) {
00416 #ifdef _STRTOD_ENDPTR
00417 pos1 = pos;
00418 #endif
00419 negative = 1;
00420 switch(*++pos) {
00421 case '-': negative = -1;
00422 case '+': ++pos;
00423 }
00424
00425 pos0 = pos;
00426 exponent_temp = 0;
00427 while (isdigit(*pos)) {
00428 #ifdef _STRTOD_RESTRICT_EXP
00429 if (exponent_temp < MAX_ALLOWED_EXP) {
00430 exponent_temp = exponent_temp * 10 + (*pos - '0');
00431 }
00432 #else
00433 exponent_temp = exponent_temp * 10 + (*pos - '0');
00434 #endif
00435 ++pos;
00436 }
00437
00438 #ifdef _STRTOD_ENDPTR
00439 if (pos == pos0) {
00440 pos = pos1;
00441 }
00442 #endif
00443
00444 exponent_power += negative * exponent_temp;
00445 }
00446
00447 #ifdef _STRTOD_ZERO_CHECK
00448 if (number == 0.) {
00449 goto DONE;
00450 }
00451 #endif
00452
00453
00454 #ifdef _STRTOD_LOG_SCALING
00455 exponent_temp = exponent_power;
00456
00457 if (exponent_temp < 0) {
00458 exponent_temp = -exponent_temp;
00459 }
00460
00461 while (exponent_temp) {
00462 if (exponent_temp & 1) {
00463 if (exponent_power < 0) {
00464
00465
00466
00467 number /= p_base;
00468 } else {
00469 number *= p_base;
00470 }
00471 }
00472 exponent_temp >>= 1;
00473 p_base *= p_base;
00474 }
00475
00476 #else
00477 while (exponent_power) {
00478 if (exponent_power < 0) {
00479 number /= p_base;
00480 exponent_power++;
00481 } else {
00482 number *= p_base;
00483 exponent_power--;
00484 }
00485 }
00486 #endif
00487
00488 #ifdef _STRTOD_ERRNO
00489 if (__FPMAX_ZERO_OR_INF_CHECK(number)) {
00490 errno = ERANGE;
00491 }
00492 #endif
00493
00494 DONE:
00495 #ifdef _STRTOD_ENDPTR
00496 if (endptr) {
00497 *endptr = cstr + (pos-str);
00498 }
00499 #endif
00500
00501 return number;
00502 }
00503 #endif // _uses_strtod_strtod_h
00504 #endif // Has Main
00505
00506
00507
00508 #define strtof(NPTR,ENDPTR) strtod((NPTR),(ENDPTR))
00509 #define strtold(NPTR,ENDPTR) strtod((NPTR),(ENDPTR))
00510
00511
00512 #endif // _STRTOD_H_