1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * Phong Vo <kpv@research.att.com> * 20 * * 21 ***********************************************************************/ 22 /* 23 * AT&T Research 24 * Glenn Fowler & Phong Vo 25 * 26 * common header and implementation for 27 * 28 * strtof strtod strtold _sfdscan 29 * strntof strntod strntold 30 * 31 * define these macros to instantiate an implementation: 32 * 33 * S2F_function the function name 34 * S2F_static <0:export =0:extern >0:static 35 * S2F_type 0:float 1:double 2:long.double 36 * S2F_size 1 for interface with size_t second arg 37 * S2F_scan 1 for alternate interface with these arguments: 38 * void* handle 39 * int (*getchar)(void* handle, int flag) 40 * exactly one extra (*getchar)() is done, i.e., 41 * the caller must do the pushback 42 * flag==0 get next char 43 * flag==1 no number seen 44 * return 0 on error or EOF 45 */ 46 47 #include "sfhdr.h" 48 #include "FEATURE/float" 49 50 /* 51 * the default is _sfdscan for standalone sfio compatibility 52 */ 53 54 #if !defined(S2F_function) 55 #define S2F_function _sfdscan 56 #define S2F_static 1 57 #define S2F_type 2 58 #define S2F_scan 1 59 #ifndef elementsof 60 #define elementsof(a) (sizeof(a)/sizeof(a[0])) 61 #endif 62 #endif 63 64 #if S2F_type == 2 && _ast_fltmax_double 65 #undef S2F_type 66 #define S2F_type 1 67 #endif 68 69 #if S2F_type == 0 70 #define S2F_number float 71 #define S2F_ldexp ldexp 72 #define S2F_pow10 _Sffpow10 73 #define S2F_inf _Sffinf 74 #define S2F_nan _Sffnan 75 #define S2F_min (FLT_MIN) 76 #define S2F_max (FLT_MAX) 77 #define S2F_exp_10_min (FLT_MIN_10_EXP) 78 #define S2F_exp_10_max (FLT_MAX_10_EXP) 79 #define S2F_exp_2_min (FLT_MIN_EXP) 80 #define S2F_exp_2_max (FLT_MAX_EXP) 81 #endif 82 #if S2F_type == 1 83 #define S2F_number double 84 #define S2F_ldexp ldexp 85 #define S2F_pow10 _Sfdpow10 86 #define S2F_inf _Sfdinf 87 #define S2F_nan _Sfdnan 88 #define S2F_min (DBL_MIN) 89 #define S2F_max (DBL_MAX) 90 #define S2F_exp_10_min (DBL_MIN_10_EXP) 91 #define S2F_exp_10_max (DBL_MAX_10_EXP) 92 #define S2F_exp_2_min (DBL_MIN_EXP) 93 #define S2F_exp_2_max (DBL_MAX_EXP) 94 #endif 95 #if S2F_type == 2 96 #define S2F_number long double 97 #define S2F_ldexp ldexpl 98 #define S2F_pow10 _Sflpow10 99 #define S2F_inf _Sflinf 100 #define S2F_nan _Sflnan 101 #define S2F_min (LDBL_MIN) 102 #define S2F_max (LDBL_MAX) 103 #define S2F_exp_10_min (LDBL_MIN_10_EXP) 104 #define S2F_exp_10_max (LDBL_MAX_10_EXP) 105 #define S2F_exp_2_min (LDBL_MIN_EXP) 106 #define S2F_exp_2_max (LDBL_MAX_EXP) 107 #endif 108 109 #if -S2F_exp_10_min < S2F_exp_10_max 110 #define S2F_exp_10_abs (-S2F_exp_10_min) 111 #else 112 #define S2F_exp_10_abs S2F_exp_10_max 113 #endif 114 115 #define S2F_batch _ast_flt_unsigned_max_t 116 117 #undef ERR /* who co-opted this namespace? */ 118 119 #if S2F_scan 120 121 typedef int (*S2F_get_f)_ARG_((void*, int)); 122 123 #define ERR(e) 124 #define GET(p) (*get)(p,0) 125 #define NON(p) (*get)(p,1) 126 #define PUT(p) 127 #define REV(p,t,b) 128 #define SET(p,t,b) 129 130 #else 131 132 #define ERR(e) (errno=(e)) 133 #define NON(p) 134 135 #if S2F_size 136 #define GET(p) (((p)<(z))?(*p++):(back=0)) 137 #define PUT(p) (end?(*end=(char*)p-back):(char*)0) 138 #define REV(p,t,b) (p=t,back=b) 139 #define SET(p,t,b) (t=p,b=back) 140 #else 141 #define GET(p) (*p++) 142 #define PUT(p) (end?(*end=(char*)p-1):(char*)0) 143 #define REV(p,t,b) (p=t) 144 #define SET(p,t,b) (t=p) 145 #endif 146 147 #endif 148 149 typedef struct S2F_part_s 150 { 151 S2F_batch batch; 152 int digits; 153 } S2F_part_t; 154 155 #if !defined(ERANGE) 156 #define ERANGE EINVAL 157 #endif 158 159 #if S2F_static > 0 160 static 161 #else 162 #if S2F_static < 0 || !defined(S2F_static) 163 #if defined(__EXPORT__) 164 #define extern __EXPORT__ 165 #endif 166 extern 167 #undef extern 168 #endif 169 #endif 170 S2F_number 171 #if S2F_scan 172 #if __STD_C 173 S2F_function(void* s, S2F_get_f get) 174 #else 175 S2F_function(s, get) void* s; S2F_get_f get; 176 #endif 177 #else 178 #if S2F_size 179 #if __STD_C 180 S2F_function(const char* str, size_t size, char** end) 181 #else 182 S2F_function(str, size, end) char* str; size_t size; char** end; 183 #endif 184 #else 185 #if __STD_C 186 S2F_function(const char* str, char** end) 187 #else 188 S2F_function(str, end) char* str; char** end; 189 #endif 190 #endif 191 #endif 192 { 193 #if !S2F_scan 194 register unsigned char* s = (unsigned char*)str; 195 #if S2F_size 196 register unsigned char* z = s + size; 197 int back = 1; 198 int b; 199 #endif 200 unsigned char* t; 201 #endif 202 register S2F_batch n; 203 register int c; 204 register int digits; 205 register int m; 206 register unsigned char* cv; 207 int negative; 208 int enegative; 209 int fraction; 210 int decimal = 0; 211 int thousand = 0; 212 int part = 0; 213 S2F_number v; 214 S2F_number p; 215 S2F_part_t parts[16]; 216 217 /* 218 * radix char and thousands separator are locale specific 219 */ 220 221 SFSETLOCALE(&decimal, &thousand); 222 SFCVINIT(); 223 224 /* 225 * skip initial blanks 226 */ 227 228 do c = GET(s); while (isspace(c)); 229 SET(s, t, b); 230 231 /* 232 * get the sign 233 */ 234 235 if ((negative = (c == '-')) || c == '+') 236 c = GET(s); 237 238 /* 239 * drop leading 0's 240 */ 241 242 digits = 0; 243 fraction = -1; 244 if (c == '0') 245 { 246 c = GET(s); 247 if (c == 'x' || c == 'X') 248 { 249 /* 250 * hex floating point -- easy 251 */ 252 253 cv = _Sfcv36; 254 v = 0; 255 for (;;) 256 { 257 c = GET(s); 258 if ((part = cv[c]) < 16) 259 { 260 digits++; 261 v *= 16; 262 v += part; 263 } 264 else if (c == decimal) 265 { 266 decimal = -1; 267 fraction = digits; 268 } 269 else 270 break; 271 } 272 m = 0; 273 if (c == 'p' || c == 'P') 274 { 275 c = GET(s); 276 if ((enegative = c == '-') || c == '+') 277 c = GET(s); 278 while (c >= '0' && c <= '9') 279 { 280 m = (m << 3) + (m << 1) + (c - '0'); 281 c = GET(s); 282 } 283 if (enegative) 284 m = -m; 285 } 286 287 /* 288 * consume the optional suffix 289 */ 290 291 switch (c) 292 { 293 case 'f': 294 case 'F': 295 case 'l': 296 case 'L': 297 c = GET(s); 298 break; 299 } 300 PUT(s); 301 if (v == 0) 302 return v; 303 if (fraction >= 0) 304 m -= 4 * (digits - fraction); 305 if (m < S2F_exp_2_min) 306 { 307 if ((m -= S2F_exp_2_min) < S2F_exp_2_min) 308 { 309 ERR(ERANGE); 310 return 0; 311 } 312 v = S2F_ldexp(v, S2F_exp_2_min); 313 } 314 else if (m > S2F_exp_2_max) 315 { 316 ERR(ERANGE); 317 return negative ? -S2F_inf : S2F_inf; 318 } 319 v = S2F_ldexp(v, m); 320 goto check; 321 } 322 while (c == '0') 323 c = GET(s); 324 } 325 else if (c == decimal) 326 { 327 decimal = -1; 328 fraction = 0; 329 for (;;) 330 { 331 c = GET(s); 332 if (c != '0') 333 break; 334 digits++; 335 } 336 } 337 else if (c == 'i' || c == 'I') 338 { 339 if ((c = GET(s)) != 'n' && c != 'N' || 340 (c = GET(s)) != 'f' && c != 'F') 341 { 342 REV(s, t, b); 343 PUT(s); 344 return 0; 345 } 346 c = GET(s); 347 SET(s, t, b); 348 if (((c) == 'i' || c == 'I') && 349 ((c = GET(s)) == 'n' || c == 'N') && 350 ((c = GET(s)) == 'i' || c == 'I') && 351 ((c = GET(s)) == 't' || c == 'T') && 352 ((c = GET(s)) == 'y' || c == 'Y')) 353 { 354 c = GET(s); 355 SET(s, t, b); 356 } 357 REV(s, t, b); 358 PUT(s); 359 return negative ? -S2F_inf : S2F_inf; 360 } 361 else if (c == 'n' || c == 'N') 362 { 363 if ((c = GET(s)) != 'a' && c != 'A' || 364 (c = GET(s)) != 'n' && c != 'N') 365 { 366 REV(s, t, b); 367 PUT(s); 368 return 0; 369 } 370 do c = GET(s); while (c && !isspace(c)); 371 PUT(s); 372 return S2F_nan; 373 } 374 else if (c < '1' || c > '9') 375 { 376 REV(s, t, b); 377 PUT(s); 378 NON(s); 379 return 0; 380 } 381 382 /* 383 * consume the integral and fractional parts 384 */ 385 386 n = 0; 387 m = 0; 388 for (;;) 389 { 390 if (c >= '0' && c <= '9') 391 { 392 digits++; 393 n = (n << 3) + (n << 1) + (c - '0'); 394 if (n >= ((~((S2F_batch)0)) / 10) && part < elementsof(parts)) 395 { 396 parts[part].batch = n; 397 n = 0; 398 parts[part].digits = digits; 399 part++; 400 } 401 } 402 else if (m && (digits - m) != 3) 403 break; 404 else if (c == decimal) 405 { 406 decimal = -1; 407 thousand = -1; 408 m = 0; 409 fraction = digits; 410 } 411 else if (c != thousand) 412 break; 413 else if (!(m = digits)) 414 break; 415 c = GET(s); 416 } 417 418 /* 419 * don't forget the last part 420 */ 421 422 if (n && part < elementsof(parts)) 423 { 424 parts[part].batch = n; 425 parts[part].digits = digits; 426 part++; 427 } 428 429 /* 430 * consume the exponent 431 */ 432 433 if (fraction >= 0) 434 digits = fraction; 435 if (c == 'e' || c == 'E') 436 { 437 c = GET(s); 438 if ((enegative = (c == '-')) || c == '+') 439 c = GET(s); 440 n = 0; 441 while (c >= '0' && c <= '9') 442 { 443 n = (n << 3) + (n << 1) + (c - '0'); 444 c = GET(s); 445 } 446 if (enegative) 447 digits -= n; 448 else 449 digits += n; 450 } 451 452 /* 453 * consume the optional suffix 454 */ 455 456 switch (c) 457 { 458 case 'f': 459 case 'F': 460 case 'l': 461 case 'L': 462 c = GET(s); 463 break; 464 } 465 PUT(s); 466 467 /* 468 * adjust for at most one multiply per part 469 * and at most one divide overall 470 */ 471 472 if (!part) 473 return 0; 474 else if ((m = parts[part-1].digits - digits) > 0) 475 digits += m; 476 else 477 m = 0; 478 479 /* 480 * combine the parts 481 */ 482 483 v = 0; 484 while (part--) 485 { 486 p = parts[part].batch; 487 c = digits - parts[part].digits; 488 if (c > S2F_exp_10_max) 489 { 490 ERR(ERANGE); 491 return negative ? -S2F_inf : S2F_inf; 492 } 493 if (c > 0) 494 { 495 #if _ast_mpy_overflow_fpe 496 if ((S2F_max / p) < S2F_pow10[c]) 497 { 498 ERR(ERANGE); 499 return negative ? -S2F_inf : S2F_inf; 500 } 501 #endif 502 p *= S2F_pow10[c]; 503 } 504 v += p; 505 } 506 if (m) 507 { 508 while (m > S2F_exp_10_max) 509 { 510 m -= S2F_exp_10_max; 511 v /= S2F_pow10[S2F_exp_10_max]; 512 } 513 #if _ast_div_underflow_fpe 514 if ((S2F_min * p) > S2F_pow10[c]) 515 { 516 ERR(ERANGE); 517 return negative ? -S2F_inf : S2F_inf; 518 } 519 #endif 520 v /= S2F_pow10[m]; 521 } 522 523 /* 524 * check the range 525 */ 526 527 check: 528 if (v < S2F_min) 529 { 530 ERR(ERANGE); 531 v = 0; 532 } 533 else if (v > S2F_max) 534 { 535 ERR(ERANGE); 536 v = S2F_inf; 537 } 538 539 /* 540 * done 541 */ 542 543 return negative ? -v : v; 544 } 545