14bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes/**************************************************************** 24bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes 34bd97cee28dd815fff54fc97560be60d566c1fa5Elliott HughesThe author of this software is David M. Gay. 44bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes 54bd97cee28dd815fff54fc97560be60d566c1fa5Elliott HughesCopyright (C) 1998 by Lucent Technologies 64bd97cee28dd815fff54fc97560be60d566c1fa5Elliott HughesAll Rights Reserved 74bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes 84bd97cee28dd815fff54fc97560be60d566c1fa5Elliott HughesPermission to use, copy, modify, and distribute this software and 94bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughesits documentation for any purpose and without fee is hereby 104bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughesgranted, provided that the above copyright notice appear in all 114bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughescopies and that both that the copyright notice and this 124bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughespermission notice and warranty disclaimer appear in supporting 134bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughesdocumentation, and that the name of Lucent or any of its entities 144bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughesnot be used in advertising or publicity pertaining to 154bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughesdistribution of the software without specific, written prior 164bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughespermission. 174bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes 184bd97cee28dd815fff54fc97560be60d566c1fa5Elliott HughesLUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 194bd97cee28dd815fff54fc97560be60d566c1fa5Elliott HughesINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 204bd97cee28dd815fff54fc97560be60d566c1fa5Elliott HughesIN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 214bd97cee28dd815fff54fc97560be60d566c1fa5Elliott HughesSPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 224bd97cee28dd815fff54fc97560be60d566c1fa5Elliott HughesWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 234bd97cee28dd815fff54fc97560be60d566c1fa5Elliott HughesIN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 244bd97cee28dd815fff54fc97560be60d566c1fa5Elliott HughesARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 254bd97cee28dd815fff54fc97560be60d566c1fa5Elliott HughesTHIS SOFTWARE. 264bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes 274bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes****************************************************************/ 284bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes 294bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes/* Please send bug reports to David M. Gay (dmg at acm dot org, 304bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes * with " at " changed at "@" and " dot " changed to "."). */ 314bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes 324bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#include "gdtoaimp.h" 334bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes 344bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#ifdef USE_LOCALE 354bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#include "locale.h" 364bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#endif 374bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes 384bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes int 394bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#ifdef KR_headers 404bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughesgethex(sp, fpi, exp, bp, sign) 414bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes CONST char **sp; FPI *fpi; Long *exp; Bigint **bp; int sign; 424bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#else 434bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughesgethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign) 444bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#endif 454bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes{ 464bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes Bigint *b; 474bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes CONST unsigned char *decpt, *s0, *s, *s1; 484bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes int big, esign, havedig, irv, j, k, n, n0, nbits, up, zret; 494bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes ULong L, lostbits, *x; 504bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes Long e, e1; 514bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#ifdef USE_LOCALE 524bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes int i; 534bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#ifdef NO_LOCALE_CACHE 544bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes const unsigned char *decimalpoint = (unsigned char*)localeconv()->decimal_point; 554bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#else 564bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes const unsigned char *decimalpoint; 574bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes static unsigned char *decimalpoint_cache; 584bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (!(s0 = decimalpoint_cache)) { 594bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes s0 = (unsigned char*)localeconv()->decimal_point; 604bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { 614bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes strlcpy(decimalpoint_cache, s0, strlen(s0) + 1); 624bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes s0 = decimalpoint_cache; 634bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 644bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 654bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes decimalpoint = s0; 664bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#endif 674bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#endif 684bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes 694bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (!hexdig['0']) 704bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes hexdig_init_D2A(); 714bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes *bp = 0; 724bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes havedig = 0; 734bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes s0 = *(CONST unsigned char **)sp + 2; 744bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes while(s0[havedig] == '0') 754bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes havedig++; 764bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes s0 += havedig; 774bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes s = s0; 784bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes decpt = 0; 794bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes zret = 0; 804bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes e = 0; 814bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (hexdig[*s]) 824bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes havedig++; 834bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes else { 844bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes zret = 1; 854bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#ifdef USE_LOCALE 864bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes for(i = 0; decimalpoint[i]; ++i) { 874bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (s[i] != decimalpoint[i]) 884bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes goto pcheck; 894bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 904bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes decpt = s += i; 914bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#else 924bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (*s != '.') 934bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes goto pcheck; 944bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes decpt = ++s; 954bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#endif 964bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (!hexdig[*s]) 974bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes goto pcheck; 984bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes while(*s == '0') 994bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes s++; 1004bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (hexdig[*s]) 1014bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes zret = 0; 1024bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes havedig = 1; 1034bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes s0 = s; 1044bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 1054bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes while(hexdig[*s]) 1064bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes s++; 1074bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#ifdef USE_LOCALE 1084bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (*s == *decimalpoint && !decpt) { 1094bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes for(i = 1; decimalpoint[i]; ++i) { 1104bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (s[i] != decimalpoint[i]) 1114bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes goto pcheck; 1124bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 1134bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes decpt = s += i; 1144bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#else 1154bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (*s == '.' && !decpt) { 1164bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes decpt = ++s; 1174bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#endif 1184bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes while(hexdig[*s]) 1194bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes s++; 1204bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes }/*}*/ 1214bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (decpt) 1224bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes e = -(((Long)(s-decpt)) << 2); 1234bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes pcheck: 1244bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes s1 = s; 1254bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes big = esign = 0; 1264bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes switch(*s) { 1274bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes case 'p': 1284bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes case 'P': 1294bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes switch(*++s) { 1304bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes case '-': 1314bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes esign = 1; 1324bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes /* no break */ 1334bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes case '+': 1344bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes s++; 1354bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 1364bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if ((n = hexdig[*s]) == 0 || n > 0x19) { 1374bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes s = s1; 1384bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes break; 1394bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 1404bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes e1 = n - 0x10; 1414bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes while((n = hexdig[*++s]) !=0 && n <= 0x19) { 1424bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (e1 & 0xf8000000) 1434bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes big = 1; 1444bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes e1 = 10*e1 + n - 0x10; 1454bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 1464bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (esign) 1474bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes e1 = -e1; 1484bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes e += e1; 1494bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 1504bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes *sp = (char*)s; 1514bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (!havedig) 1524bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes *sp = (char*)s0 - 1; 1534bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (zret) 1544bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes return STRTOG_Zero; 1554bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (big) { 1564bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (esign) { 1574bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes switch(fpi->rounding) { 1584bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes case FPI_Round_up: 1594bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (sign) 1604bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes break; 1614bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes goto ret_tiny; 1624bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes case FPI_Round_down: 1634bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (!sign) 1644bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes break; 1654bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes goto ret_tiny; 1664bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 1674bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes goto retz; 1684bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes ret_tiny: 1694bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes b = Balloc(0); 1704bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (b == NULL) 1714bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes return (STRTOG_NoMemory); 1724bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes b->wds = 1; 1734bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes b->x[0] = 1; 1744bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes goto dret; 1754bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 1764bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes switch(fpi->rounding) { 1774bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes case FPI_Round_near: 1784bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes goto ovfl1; 1794bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes case FPI_Round_up: 1804bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (!sign) 1814bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes goto ovfl1; 1824bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes goto ret_big; 1834bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes case FPI_Round_down: 1844bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (sign) 1854bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes goto ovfl1; 1864bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes goto ret_big; 1874bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 1884bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes ret_big: 1894bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes nbits = fpi->nbits; 1904bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes n0 = n = nbits >> kshift; 1914bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (nbits & kmask) 1924bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes ++n; 1934bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes for(j = n, k = 0; j >>= 1; ++k); 1944bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes *bp = b = Balloc(k); 1954bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (*bp == NULL) 1964bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes return (STRTOG_NoMemory); 1974bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes b->wds = n; 1984bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes for(j = 0; j < n0; ++j) 1994bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes b->x[j] = ALL_ON; 2004bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (n > n0) 2014bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes b->x[j] = ULbits >> (ULbits - (nbits & kmask)); 2024bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes *exp = fpi->emin; 2034bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes return STRTOG_Normal | STRTOG_Inexlo; 2044bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 2054bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes n = s1 - s0 - 1; 2064bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1) 2074bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes k++; 2084bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes b = Balloc(k); 2094bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (b == NULL) 2104bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes return (STRTOG_NoMemory); 2114bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes x = b->x; 2124bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes n = 0; 2134bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes L = 0; 2144bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#ifdef USE_LOCALE 2154bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes for(i = 0; decimalpoint[i+1]; ++i); 2164bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#endif 2174bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes while(s1 > s0) { 2184bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#ifdef USE_LOCALE 2194bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (*--s1 == decimalpoint[i]) { 2204bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes s1 -= i; 2214bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes continue; 2224bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 2234bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#else 2244bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (*--s1 == '.') 2254bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes continue; 2264bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#endif 2274bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (n == ULbits) { 2284bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes *x++ = L; 2294bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes L = 0; 2304bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes n = 0; 2314bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 2324bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes L |= (hexdig[*s1] & 0x0f) << n; 2334bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes n += 4; 2344bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 2354bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes *x++ = L; 2364bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes b->wds = n = x - b->x; 2374bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes n = ULbits*n - hi0bits(L); 2384bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes nbits = fpi->nbits; 2394bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes lostbits = 0; 2404bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes x = b->x; 2414bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (n > nbits) { 2424bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes n -= nbits; 2434bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (any_on(b,n)) { 2444bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes lostbits = 1; 2454bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes k = n - 1; 2464bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (x[k>>kshift] & 1 << (k & kmask)) { 2474bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes lostbits = 2; 2484bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (k > 0 && any_on(b,k)) 2494bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes lostbits = 3; 2504bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 2514bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 2524bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes rshift(b, n); 2534bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes e += n; 2544bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 2554bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes else if (n < nbits) { 2564bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes n = nbits - n; 2574bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes b = lshift(b, n); 2584bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (b == NULL) 2594bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes return (STRTOG_NoMemory); 2604bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes e -= n; 2614bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes x = b->x; 2624bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 2634bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (e > fpi->emax) { 2644bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes ovfl: 2654bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes Bfree(b); 2664bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes ovfl1: 2674bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#ifndef NO_ERRNO 2684bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes errno = ERANGE; 2694bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#endif 2704bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi; 2714bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 2724bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes irv = STRTOG_Normal; 2734bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (e < fpi->emin) { 2744bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes irv = STRTOG_Denormal; 2754bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes n = fpi->emin - e; 2764bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (n >= nbits) { 2774bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes switch (fpi->rounding) { 2784bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes case FPI_Round_near: 2794bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (n == nbits && (n < 2 || any_on(b,n-1))) 2804bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes goto one_bit; 2814bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes break; 2824bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes case FPI_Round_up: 2834bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (!sign) 2844bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes goto one_bit; 2854bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes break; 2864bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes case FPI_Round_down: 2874bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (sign) { 2884bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes one_bit: 2894bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes x[0] = b->wds = 1; 2904bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes dret: 2914bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes *bp = b; 2924bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes *exp = fpi->emin; 2934bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#ifndef NO_ERRNO 2944bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes errno = ERANGE; 2954bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#endif 2964bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes return STRTOG_Denormal | STRTOG_Inexhi 2974bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes | STRTOG_Underflow; 2984bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 2994bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 3004bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes Bfree(b); 3014bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes retz: 3024bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#ifndef NO_ERRNO 3034bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes errno = ERANGE; 3044bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes#endif 3054bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow; 3064bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 3074bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes k = n - 1; 3084bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (lostbits) 3094bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes lostbits = 1; 3104bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes else if (k > 0) 3114bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes lostbits = any_on(b,k); 3124bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (x[k>>kshift] & 1 << (k & kmask)) 3134bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes lostbits |= 2; 3144bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes nbits -= n; 3154bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes rshift(b,n); 3164bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes e = fpi->emin; 3174bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 3184bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (lostbits) { 3194bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes up = 0; 3204bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes switch(fpi->rounding) { 3214bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes case FPI_Round_zero: 3224bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes break; 3234bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes case FPI_Round_near: 3244bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (lostbits & 2 3254bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes && (lostbits | x[0]) & 1) 3264bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes up = 1; 3274bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes break; 3284bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes case FPI_Round_up: 3294bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes up = 1 - sign; 3304bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes break; 3314bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes case FPI_Round_down: 3324bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes up = sign; 3334bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 3344bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (up) { 3354bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes k = b->wds; 3364bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes b = increment(b); 3374bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (b == NULL) 3384bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes return (STRTOG_NoMemory); 3394bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes x = b->x; 3404bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (irv == STRTOG_Denormal) { 3414bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (nbits == fpi->nbits - 1 3424bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes && x[nbits >> kshift] & 1 << (nbits & kmask)) 3434bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes irv = STRTOG_Normal; 3444bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 3454bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes else if (b->wds > k 3464bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes || ((n = nbits & kmask) !=0 3474bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes && hi0bits(x[k-1]) < 32-n)) { 3484bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes rshift(b,1); 3494bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes if (++e > fpi->emax) 3504bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes goto ovfl; 3514bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 3524bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes irv |= STRTOG_Inexhi; 3534bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 3544bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes else 3554bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes irv |= STRTOG_Inexlo; 3564bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 3574bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes *bp = b; 3584bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes *exp = e; 3594bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes return irv; 3604bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes } 361