14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1985-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * David Korn <dgk@research.att.com> * 194887Schin * Phong Vo <kpv@research.att.com> * 204887Schin * * 214887Schin ***********************************************************************/ 224887Schin /* 234887Schin * AT&T Research 244887Schin * Glenn Fowler & Phong Vo 254887Schin * 264887Schin * common header and implementation for 274887Schin * 284887Schin * strtof strtod strtold _sfdscan 294887Schin * strntof strntod strntold 304887Schin * 314887Schin * define these macros to instantiate an implementation: 324887Schin * 334887Schin * S2F_function the function name 344887Schin * S2F_static <0:export =0:extern >0:static 354887Schin * S2F_type 0:float 1:double 2:long.double 364887Schin * S2F_size 1 for interface with size_t second arg 374887Schin * S2F_scan 1 for alternate interface with these arguments: 384887Schin * void* handle 394887Schin * int (*getchar)(void* handle, int flag) 404887Schin * exactly one extra (*getchar)() is done, i.e., 414887Schin * the caller must do the pushback 424887Schin * flag==0 get next char 434887Schin * flag==1 no number seen 444887Schin * return 0 on error or EOF 454887Schin */ 464887Schin 474887Schin #include "sfhdr.h" 484887Schin #include "FEATURE/float" 494887Schin 504887Schin /* 514887Schin * the default is _sfdscan for standalone sfio compatibility 524887Schin */ 534887Schin 544887Schin #if !defined(S2F_function) 554887Schin #define S2F_function _sfdscan 564887Schin #define S2F_static 1 574887Schin #define S2F_type 2 584887Schin #define S2F_scan 1 594887Schin #ifndef elementsof 604887Schin #define elementsof(a) (sizeof(a)/sizeof(a[0])) 614887Schin #endif 624887Schin #endif 634887Schin 644887Schin #if S2F_type == 2 && _ast_fltmax_double 654887Schin #undef S2F_type 664887Schin #define S2F_type 1 674887Schin #endif 684887Schin 694887Schin #if S2F_type == 0 704887Schin #define S2F_number float 714887Schin #define S2F_ldexp ldexp 724887Schin #define S2F_pow10 _Sffpow10 734887Schin #define S2F_inf _Sffinf 744887Schin #define S2F_nan _Sffnan 754887Schin #define S2F_min (FLT_MIN) 764887Schin #define S2F_max (FLT_MAX) 774887Schin #define S2F_exp_10_min (FLT_MIN_10_EXP) 784887Schin #define S2F_exp_10_max (FLT_MAX_10_EXP) 794887Schin #define S2F_exp_2_min (FLT_MIN_EXP) 804887Schin #define S2F_exp_2_max (FLT_MAX_EXP) 814887Schin #endif 824887Schin #if S2F_type == 1 834887Schin #define S2F_number double 844887Schin #define S2F_ldexp ldexp 854887Schin #define S2F_pow10 _Sfdpow10 864887Schin #define S2F_inf _Sfdinf 874887Schin #define S2F_nan _Sfdnan 884887Schin #define S2F_min (DBL_MIN) 894887Schin #define S2F_max (DBL_MAX) 904887Schin #define S2F_exp_10_min (DBL_MIN_10_EXP) 914887Schin #define S2F_exp_10_max (DBL_MAX_10_EXP) 924887Schin #define S2F_exp_2_min (DBL_MIN_EXP) 934887Schin #define S2F_exp_2_max (DBL_MAX_EXP) 944887Schin #endif 954887Schin #if S2F_type == 2 964887Schin #define S2F_number long double 974887Schin #define S2F_ldexp ldexpl 984887Schin #define S2F_pow10 _Sflpow10 994887Schin #define S2F_inf _Sflinf 1004887Schin #define S2F_nan _Sflnan 1014887Schin #define S2F_min (LDBL_MIN) 1024887Schin #define S2F_max (LDBL_MAX) 1034887Schin #define S2F_exp_10_min (LDBL_MIN_10_EXP) 1044887Schin #define S2F_exp_10_max (LDBL_MAX_10_EXP) 1054887Schin #define S2F_exp_2_min (LDBL_MIN_EXP) 1064887Schin #define S2F_exp_2_max (LDBL_MAX_EXP) 1074887Schin #endif 1084887Schin 1094887Schin #if -S2F_exp_10_min < S2F_exp_10_max 1104887Schin #define S2F_exp_10_abs (-S2F_exp_10_min) 1114887Schin #else 1124887Schin #define S2F_exp_10_abs S2F_exp_10_max 1134887Schin #endif 1144887Schin 1154887Schin #define S2F_batch _ast_flt_unsigned_max_t 1164887Schin 1174887Schin #undef ERR /* who co-opted this namespace? */ 1184887Schin 1194887Schin #if S2F_scan 1204887Schin 1214887Schin typedef int (*S2F_get_f)_ARG_((void*, int)); 1224887Schin 1234887Schin #define ERR(e) 1244887Schin #define GET(p) (*get)(p,0) 1254887Schin #define NON(p) (*get)(p,1) 1264887Schin #define PUT(p) 1274887Schin #define REV(p,t,b) 1284887Schin #define SET(p,t,b) 1294887Schin 1304887Schin #else 1314887Schin 1324887Schin #define ERR(e) (errno=(e)) 1334887Schin #define NON(p) 1344887Schin 1354887Schin #if S2F_size 1364887Schin #define GET(p) (((p)<(z))?(*p++):(back=0)) 1374887Schin #define PUT(p) (end?(*end=(char*)p-back):(char*)0) 1384887Schin #define REV(p,t,b) (p=t,back=b) 1394887Schin #define SET(p,t,b) (t=p,b=back) 1404887Schin #else 1414887Schin #define GET(p) (*p++) 1424887Schin #define PUT(p) (end?(*end=(char*)p-1):(char*)0) 1434887Schin #define REV(p,t,b) (p=t) 1444887Schin #define SET(p,t,b) (t=p) 1454887Schin #endif 1464887Schin 1474887Schin #endif 1484887Schin 1494887Schin typedef struct S2F_part_s 1504887Schin { 1514887Schin S2F_batch batch; 1524887Schin int digits; 1534887Schin } S2F_part_t; 1544887Schin 1554887Schin #if !defined(ERANGE) 1564887Schin #define ERANGE EINVAL 1574887Schin #endif 1584887Schin 1594887Schin #if S2F_static > 0 1604887Schin static 1614887Schin #else 1624887Schin #if S2F_static < 0 || !defined(S2F_static) 1634887Schin #if defined(__EXPORT__) 1644887Schin #define extern __EXPORT__ 1654887Schin #endif 1664887Schin extern 1674887Schin #undef extern 1684887Schin #endif 1694887Schin #endif 1704887Schin S2F_number 1714887Schin #if S2F_scan 1724887Schin #if __STD_C 1734887Schin S2F_function(void* s, S2F_get_f get) 1744887Schin #else 1754887Schin S2F_function(s, get) void* s; S2F_get_f get; 1764887Schin #endif 1774887Schin #else 1784887Schin #if S2F_size 1794887Schin #if __STD_C 1804887Schin S2F_function(const char* str, size_t size, char** end) 1814887Schin #else 1824887Schin S2F_function(str, size, end) char* str; size_t size; char** end; 1834887Schin #endif 1844887Schin #else 1854887Schin #if __STD_C 1864887Schin S2F_function(const char* str, char** end) 1874887Schin #else 1884887Schin S2F_function(str, end) char* str; char** end; 1894887Schin #endif 1904887Schin #endif 1914887Schin #endif 1924887Schin { 1934887Schin #if !S2F_scan 1944887Schin register unsigned char* s = (unsigned char*)str; 1954887Schin #if S2F_size 1964887Schin register unsigned char* z = s + size; 1974887Schin int back = 1; 1984887Schin int b; 1994887Schin #endif 2004887Schin unsigned char* t; 2014887Schin #endif 2024887Schin register S2F_batch n; 2034887Schin register int c; 2044887Schin register int digits; 2054887Schin register int m; 2064887Schin register unsigned char* cv; 2074887Schin int negative; 2084887Schin int enegative; 2094887Schin int fraction; 2104887Schin int decimal = 0; 2114887Schin int thousand = 0; 2124887Schin int part = 0; 2134887Schin S2F_number v; 2144887Schin S2F_number p; 2154887Schin S2F_part_t parts[16]; 2164887Schin 2174887Schin /* 2184887Schin * radix char and thousands separator are locale specific 2194887Schin */ 2204887Schin 2214887Schin SFSETLOCALE(&decimal, &thousand); 2224887Schin SFCVINIT(); 2234887Schin 2244887Schin /* 2254887Schin * skip initial blanks 2264887Schin */ 2274887Schin 2284887Schin do c = GET(s); while (isspace(c)); 2294887Schin SET(s, t, b); 2304887Schin 2314887Schin /* 2324887Schin * get the sign 2334887Schin */ 2344887Schin 2354887Schin if ((negative = (c == '-')) || c == '+') 2364887Schin c = GET(s); 2374887Schin 2384887Schin /* 2394887Schin * drop leading 0's 2404887Schin */ 2414887Schin 2424887Schin digits = 0; 2434887Schin fraction = -1; 2444887Schin if (c == '0') 2454887Schin { 2464887Schin c = GET(s); 2474887Schin if (c == 'x' || c == 'X') 2484887Schin { 2494887Schin /* 2504887Schin * hex floating point -- easy 2514887Schin */ 2524887Schin 2534887Schin cv = _Sfcv36; 2544887Schin v = 0; 2554887Schin for (;;) 2564887Schin { 2574887Schin c = GET(s); 2584887Schin if ((part = cv[c]) < 16) 2594887Schin { 2604887Schin digits++; 2614887Schin v *= 16; 2624887Schin v += part; 2634887Schin } 2644887Schin else if (c == decimal) 2654887Schin { 2664887Schin decimal = -1; 2674887Schin fraction = digits; 2684887Schin } 2694887Schin else 2704887Schin break; 2714887Schin } 2724887Schin m = 0; 2734887Schin if (c == 'p' || c == 'P') 2744887Schin { 2754887Schin c = GET(s); 2764887Schin if ((enegative = c == '-') || c == '+') 2774887Schin c = GET(s); 2784887Schin while (c >= '0' && c <= '9') 2794887Schin { 2804887Schin m = (m << 3) + (m << 1) + (c - '0'); 2814887Schin c = GET(s); 2824887Schin } 2834887Schin if (enegative) 2844887Schin m = -m; 2854887Schin } 2864887Schin 2874887Schin /* 2884887Schin * consume the optional suffix 2894887Schin */ 2904887Schin 2914887Schin switch (c) 2924887Schin { 2934887Schin case 'f': 2944887Schin case 'F': 2954887Schin case 'l': 2964887Schin case 'L': 2974887Schin c = GET(s); 2984887Schin break; 2994887Schin } 3004887Schin PUT(s); 3014887Schin if (v == 0) 302*8462SApril.Chin@Sun.COM return negative ? -v : v; 3034887Schin if (fraction >= 0) 3044887Schin m -= 4 * (digits - fraction); 3054887Schin if (m < S2F_exp_2_min) 3064887Schin { 3074887Schin if ((m -= S2F_exp_2_min) < S2F_exp_2_min) 3084887Schin { 3094887Schin ERR(ERANGE); 3104887Schin return 0; 3114887Schin } 3124887Schin v = S2F_ldexp(v, S2F_exp_2_min); 3134887Schin } 3144887Schin else if (m > S2F_exp_2_max) 3154887Schin { 3164887Schin ERR(ERANGE); 3174887Schin return negative ? -S2F_inf : S2F_inf; 3184887Schin } 3194887Schin v = S2F_ldexp(v, m); 3204887Schin goto check; 3214887Schin } 3224887Schin while (c == '0') 3234887Schin c = GET(s); 3244887Schin } 3254887Schin else if (c == decimal) 3264887Schin { 3274887Schin decimal = -1; 3284887Schin fraction = 0; 3294887Schin for (;;) 3304887Schin { 3314887Schin c = GET(s); 3324887Schin if (c != '0') 3334887Schin break; 3344887Schin digits++; 3354887Schin } 3364887Schin } 3374887Schin else if (c == 'i' || c == 'I') 3384887Schin { 3394887Schin if ((c = GET(s)) != 'n' && c != 'N' || 3404887Schin (c = GET(s)) != 'f' && c != 'F') 3414887Schin { 3424887Schin REV(s, t, b); 3434887Schin PUT(s); 3444887Schin return 0; 3454887Schin } 3464887Schin c = GET(s); 3474887Schin SET(s, t, b); 3484887Schin if (((c) == 'i' || c == 'I') && 3494887Schin ((c = GET(s)) == 'n' || c == 'N') && 3504887Schin ((c = GET(s)) == 'i' || c == 'I') && 3514887Schin ((c = GET(s)) == 't' || c == 'T') && 3524887Schin ((c = GET(s)) == 'y' || c == 'Y')) 3534887Schin { 3544887Schin c = GET(s); 3554887Schin SET(s, t, b); 3564887Schin } 3574887Schin REV(s, t, b); 3584887Schin PUT(s); 3594887Schin return negative ? -S2F_inf : S2F_inf; 3604887Schin } 3614887Schin else if (c == 'n' || c == 'N') 3624887Schin { 3634887Schin if ((c = GET(s)) != 'a' && c != 'A' || 3644887Schin (c = GET(s)) != 'n' && c != 'N') 3654887Schin { 3664887Schin REV(s, t, b); 3674887Schin PUT(s); 3684887Schin return 0; 3694887Schin } 3704887Schin do c = GET(s); while (c && !isspace(c)); 3714887Schin PUT(s); 372*8462SApril.Chin@Sun.COM return negative ? -S2F_nan : S2F_nan; 3734887Schin } 3744887Schin else if (c < '1' || c > '9') 3754887Schin { 3764887Schin REV(s, t, b); 3774887Schin PUT(s); 3784887Schin NON(s); 3794887Schin return 0; 3804887Schin } 3814887Schin 3824887Schin /* 3834887Schin * consume the integral and fractional parts 3844887Schin */ 3854887Schin 3864887Schin n = 0; 3874887Schin m = 0; 3884887Schin for (;;) 3894887Schin { 3904887Schin if (c >= '0' && c <= '9') 3914887Schin { 3924887Schin digits++; 3934887Schin n = (n << 3) + (n << 1) + (c - '0'); 3944887Schin if (n >= ((~((S2F_batch)0)) / 10) && part < elementsof(parts)) 3954887Schin { 3964887Schin parts[part].batch = n; 3974887Schin n = 0; 3984887Schin parts[part].digits = digits; 3994887Schin part++; 4004887Schin } 4014887Schin } 4024887Schin else if (m && (digits - m) != 3) 4034887Schin break; 4044887Schin else if (c == decimal) 4054887Schin { 4064887Schin decimal = -1; 4074887Schin thousand = -1; 4084887Schin m = 0; 4094887Schin fraction = digits; 4104887Schin } 4114887Schin else if (c != thousand) 4124887Schin break; 4134887Schin else if (!(m = digits)) 4144887Schin break; 4154887Schin c = GET(s); 4164887Schin } 4174887Schin 4184887Schin /* 4194887Schin * don't forget the last part 4204887Schin */ 4214887Schin 4224887Schin if (n && part < elementsof(parts)) 4234887Schin { 4244887Schin parts[part].batch = n; 4254887Schin parts[part].digits = digits; 4264887Schin part++; 4274887Schin } 4284887Schin 4294887Schin /* 4304887Schin * consume the exponent 4314887Schin */ 4324887Schin 4334887Schin if (fraction >= 0) 4344887Schin digits = fraction; 4354887Schin if (c == 'e' || c == 'E') 4364887Schin { 4374887Schin c = GET(s); 4384887Schin if ((enegative = (c == '-')) || c == '+') 4394887Schin c = GET(s); 4404887Schin n = 0; 4414887Schin while (c >= '0' && c <= '9') 4424887Schin { 4434887Schin n = (n << 3) + (n << 1) + (c - '0'); 4444887Schin c = GET(s); 4454887Schin } 4464887Schin if (enegative) 4474887Schin digits -= n; 4484887Schin else 4494887Schin digits += n; 4504887Schin } 4514887Schin 4524887Schin /* 4534887Schin * consume the optional suffix 4544887Schin */ 4554887Schin 4564887Schin switch (c) 4574887Schin { 4584887Schin case 'f': 4594887Schin case 'F': 4604887Schin case 'l': 4614887Schin case 'L': 4624887Schin c = GET(s); 4634887Schin break; 4644887Schin } 4654887Schin PUT(s); 4664887Schin 4674887Schin /* 4684887Schin * adjust for at most one multiply per part 4694887Schin * and at most one divide overall 4704887Schin */ 4714887Schin 472*8462SApril.Chin@Sun.COM v = 0; 4734887Schin if (!part) 474*8462SApril.Chin@Sun.COM return negative ? -v : v; 4754887Schin else if ((m = parts[part-1].digits - digits) > 0) 4764887Schin digits += m; 4774887Schin else 4784887Schin m = 0; 4794887Schin 4804887Schin /* 4814887Schin * combine the parts 4824887Schin */ 4834887Schin 4844887Schin while (part--) 4854887Schin { 4864887Schin p = parts[part].batch; 4874887Schin c = digits - parts[part].digits; 4884887Schin if (c > S2F_exp_10_max) 4894887Schin { 4904887Schin ERR(ERANGE); 4914887Schin return negative ? -S2F_inf : S2F_inf; 4924887Schin } 4934887Schin if (c > 0) 4944887Schin { 4954887Schin #if _ast_mpy_overflow_fpe 4964887Schin if ((S2F_max / p) < S2F_pow10[c]) 4974887Schin { 4984887Schin ERR(ERANGE); 4994887Schin return negative ? -S2F_inf : S2F_inf; 5004887Schin } 5014887Schin #endif 5024887Schin p *= S2F_pow10[c]; 5034887Schin } 5044887Schin v += p; 5054887Schin } 5064887Schin if (m) 5074887Schin { 5084887Schin while (m > S2F_exp_10_max) 5094887Schin { 5104887Schin m -= S2F_exp_10_max; 5114887Schin v /= S2F_pow10[S2F_exp_10_max]; 5124887Schin } 5134887Schin #if _ast_div_underflow_fpe 5144887Schin if ((S2F_min * p) > S2F_pow10[c]) 5154887Schin { 5164887Schin ERR(ERANGE); 5174887Schin return negative ? -S2F_inf : S2F_inf; 5184887Schin } 5194887Schin #endif 5204887Schin v /= S2F_pow10[m]; 5214887Schin } 5224887Schin 5234887Schin /* 5244887Schin * check the range 5254887Schin */ 5264887Schin 5274887Schin check: 5284887Schin if (v < S2F_min) 5294887Schin { 5304887Schin ERR(ERANGE); 5314887Schin v = 0; 5324887Schin } 5334887Schin else if (v > S2F_max) 5344887Schin { 5354887Schin ERR(ERANGE); 5364887Schin v = S2F_inf; 5374887Schin } 5384887Schin 5394887Schin /* 5404887Schin * done 5414887Schin */ 5424887Schin 5434887Schin return negative ? -v : v; 5444887Schin } 545