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