* Updating common/lib * Updating lib/csu * Updating lib/libc * Updating libexec/ld.elf_so * Corrected test on __minix in featuretest to actually follow the meaning of the comment. * Cleaned up _REENTRANT-related defintions. * Disabled -D_REENTRANT for libfetch * Removing some unneeded __NBSD_LIBC defines and tests Change-Id: Ic1394baef74d11b9f86b312f5ff4bbc3cbf72ce2
		
			
				
	
	
		
			357 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			357 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $NetBSD: gethex.c,v 1.5 2011/03/20 23:15:35 christos Exp $ */
 | 
						|
 | 
						|
/****************************************************************
 | 
						|
 | 
						|
The author of this software is David M. Gay.
 | 
						|
 | 
						|
Copyright (C) 1998 by Lucent Technologies
 | 
						|
All Rights Reserved
 | 
						|
 | 
						|
Permission to use, copy, modify, and distribute this software and
 | 
						|
its documentation for any purpose and without fee is hereby
 | 
						|
granted, provided that the above copyright notice appear in all
 | 
						|
copies and that both that the copyright notice and this
 | 
						|
permission notice and warranty disclaimer appear in supporting
 | 
						|
documentation, and that the name of Lucent or any of its entities
 | 
						|
not be used in advertising or publicity pertaining to
 | 
						|
distribution of the software without specific, written prior
 | 
						|
permission.
 | 
						|
 | 
						|
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | 
						|
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
 | 
						|
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
 | 
						|
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 | 
						|
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 | 
						|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
 | 
						|
THIS SOFTWARE.
 | 
						|
 | 
						|
****************************************************************/
 | 
						|
 | 
						|
/* Please send bug reports to David M. Gay (dmg at acm dot org,
 | 
						|
 * with " at " changed at "@" and " dot " changed to ".").	*/
 | 
						|
 | 
						|
#include "gdtoaimp.h"
 | 
						|
 | 
						|
#ifdef USE_LOCALE
 | 
						|
#include "locale.h"
 | 
						|
#endif
 | 
						|
 | 
						|
 int
 | 
						|
#ifdef KR_headers
 | 
						|
gethex(sp, fpi, expt, bp, sign)
 | 
						|
	CONST char **sp; CONST FPI *fpi; Long *expt; Bigint **bp; int sign;
 | 
						|
#else
 | 
						|
gethex( CONST char **sp, CONST FPI *fpi, Long *expt, Bigint **bp, int sign)
 | 
						|
#endif
 | 
						|
{
 | 
						|
	Bigint *b;
 | 
						|
	CONST char *decpt, *s, *s0, *s1;
 | 
						|
	int big, esign, havedig, irv, j, k, n, n0, nbits, up, zret;
 | 
						|
	ULong L, lostbits, *x;
 | 
						|
	Long e, e1;
 | 
						|
#ifdef USE_LOCALE
 | 
						|
	int i;
 | 
						|
#ifdef NO_LOCALE_CACHE
 | 
						|
	const char *decimalpoint = localeconv()->decimal_point;
 | 
						|
#else
 | 
						|
	const unsigned char *decimalpoint;
 | 
						|
	static char *decimalpoint_cache;
 | 
						|
	if (!(s0 = decimalpoint_cache)) {
 | 
						|
		s0 = localeconv()->decimal_point;
 | 
						|
		if ((decimalpoint_cache = MALLOC(strlen(s0) + 1)) != NULL) {
 | 
						|
			strcpy(decimalpoint_cache, s0);
 | 
						|
			s0 = decimalpoint_cache;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	decimalpoint = __UNCONST(s0);
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
	if (!hexdig[(unsigned char)'0'])
 | 
						|
		hexdig_init_D2A();
 | 
						|
	*bp = 0;
 | 
						|
	havedig = 0;
 | 
						|
	s0 = *(CONST char **)sp + 2;
 | 
						|
	while(s0[havedig] == '0')
 | 
						|
		havedig++;
 | 
						|
	s0 += havedig;
 | 
						|
	s = s0;
 | 
						|
	decpt = 0;
 | 
						|
	zret = 0;
 | 
						|
	e = 0;
 | 
						|
	if (hexdig[(unsigned char)*s])
 | 
						|
		havedig++;
 | 
						|
	else {
 | 
						|
		zret = 1;
 | 
						|
#ifdef USE_LOCALE
 | 
						|
		for(i = 0; decimalpoint[i]; ++i) {
 | 
						|
			if (s[i] != decimalpoint[i])
 | 
						|
				goto pcheck;
 | 
						|
			}
 | 
						|
		decpt = s += i;
 | 
						|
#else
 | 
						|
		if (*s != '.')
 | 
						|
			goto pcheck;
 | 
						|
		decpt = ++s;
 | 
						|
#endif
 | 
						|
		if (!hexdig[(unsigned char)*s])
 | 
						|
			goto pcheck;
 | 
						|
		while(*s == '0')
 | 
						|
			s++;
 | 
						|
		if (hexdig[(unsigned char)*s])
 | 
						|
			zret = 0;
 | 
						|
		havedig = 1;
 | 
						|
		s0 = s;
 | 
						|
		}
 | 
						|
	while(hexdig[(unsigned char)*s])
 | 
						|
		s++;
 | 
						|
#ifdef USE_LOCALE
 | 
						|
	if (*s == *decimalpoint && !decpt) {
 | 
						|
		for(i = 1; decimalpoint[i]; ++i) {
 | 
						|
			if (s[i] != decimalpoint[i])
 | 
						|
				goto pcheck;
 | 
						|
			}
 | 
						|
		decpt = s += i;
 | 
						|
#else
 | 
						|
	if (*s == '.' && !decpt) {
 | 
						|
		decpt = ++s;
 | 
						|
#endif
 | 
						|
		while(hexdig[(unsigned char)*s])
 | 
						|
			s++;
 | 
						|
		}/*}*/
 | 
						|
	if (decpt)
 | 
						|
		e = -(((Long)(s-decpt)) << 2);
 | 
						|
 pcheck:
 | 
						|
	s1 = s;
 | 
						|
	big = esign = 0;
 | 
						|
	switch(*s) {
 | 
						|
	  case 'p':
 | 
						|
	  case 'P':
 | 
						|
		switch(*++s) {
 | 
						|
		  case '-':
 | 
						|
			esign = 1;
 | 
						|
			/* FALLTHROUGH */
 | 
						|
		  case '+':
 | 
						|
			s++;
 | 
						|
		  }
 | 
						|
		if ((n = hexdig[(unsigned char)*s]) == 0 || n > 0x19) {
 | 
						|
			s = s1;
 | 
						|
			break;
 | 
						|
			}
 | 
						|
		e1 = n - 0x10;
 | 
						|
		while((n = hexdig[(unsigned char)*++s]) !=0 && n <= 0x19) {
 | 
						|
			if (e1 & 0xf8000000)
 | 
						|
				big = 1;
 | 
						|
			e1 = 10*e1 + n - 0x10;
 | 
						|
			}
 | 
						|
		if (esign)
 | 
						|
			e1 = -e1;
 | 
						|
		e += e1;
 | 
						|
	  }
 | 
						|
	*sp = __UNCONST(s);
 | 
						|
	if (!havedig)
 | 
						|
		*sp = (char*)__UNCONST(s0) - 1;
 | 
						|
	if (zret)
 | 
						|
		return STRTOG_Zero;
 | 
						|
	if (big) {
 | 
						|
		if (esign) {
 | 
						|
			switch(fpi->rounding) {
 | 
						|
			  case FPI_Round_up:
 | 
						|
				if (sign)
 | 
						|
					break;
 | 
						|
				goto ret_tiny;
 | 
						|
			  case FPI_Round_down:
 | 
						|
				if (!sign)
 | 
						|
					break;
 | 
						|
				goto ret_tiny;
 | 
						|
			  }
 | 
						|
			goto retz;
 | 
						|
 ret_tiny:
 | 
						|
			b = Balloc(0);
 | 
						|
			b->wds = 1;
 | 
						|
			b->x[0] = 1;
 | 
						|
			goto dret;
 | 
						|
			}
 | 
						|
		switch(fpi->rounding) {
 | 
						|
		  case FPI_Round_near:
 | 
						|
			goto ovfl1;
 | 
						|
		  case FPI_Round_up:
 | 
						|
			if (!sign)
 | 
						|
				goto ovfl1;
 | 
						|
			goto ret_big;
 | 
						|
		  case FPI_Round_down:
 | 
						|
			if (sign)
 | 
						|
				goto ovfl1;
 | 
						|
			goto ret_big;
 | 
						|
		  }
 | 
						|
 ret_big:
 | 
						|
		nbits = fpi->nbits;
 | 
						|
		n0 = n = (unsigned int)nbits >> kshift;
 | 
						|
		if (nbits & kmask)
 | 
						|
			++n;
 | 
						|
		for(j = n, k = 0; (j = (unsigned int)j >> 1) != 0; ++k);
 | 
						|
		*bp = b = Balloc(k);
 | 
						|
		b->wds = n;
 | 
						|
		for(j = 0; j < n0; ++j)
 | 
						|
			b->x[j] = ALL_ON;
 | 
						|
		if (n > n0)
 | 
						|
			b->x[j] = ULbits >> (ULbits - (nbits & kmask));
 | 
						|
		*expt = fpi->emin;
 | 
						|
		return STRTOG_Normal | STRTOG_Inexlo;
 | 
						|
		}
 | 
						|
	n = (int)(s1 - s0) - 1;
 | 
						|
	for(k = 0; n > (1 << (kshift-2)) - 1; n = (unsigned int)n >> 1)
 | 
						|
		k++;
 | 
						|
	b = Balloc(k);
 | 
						|
	if (b == NULL)
 | 
						|
		return STRTOG_NoMemory;
 | 
						|
	x = b->x;
 | 
						|
	n = 0;
 | 
						|
	L = 0;
 | 
						|
#ifdef USE_LOCALE
 | 
						|
	for(i = 0; decimalpoint[i+1]; ++i);
 | 
						|
#endif
 | 
						|
	while(s1 > s0) {
 | 
						|
#ifdef USE_LOCALE
 | 
						|
		if (*--s1 == decimalpoint[i]) {
 | 
						|
			s1 -= i;
 | 
						|
			continue;
 | 
						|
			}
 | 
						|
#else
 | 
						|
		if (*--s1 == '.')
 | 
						|
			continue;
 | 
						|
#endif
 | 
						|
		if (n == ULbits) {
 | 
						|
			*x++ = L;
 | 
						|
			L = 0;
 | 
						|
			n = 0;
 | 
						|
			}
 | 
						|
		L |= (hexdig[(unsigned char)*s1] & 0x0f) << n;
 | 
						|
		n += 4;
 | 
						|
		}
 | 
						|
	*x++ = L;
 | 
						|
	b->wds = n = (int)(x - b->x);
 | 
						|
	n = ULbits*n - hi0bits(L);
 | 
						|
	nbits = fpi->nbits;
 | 
						|
	lostbits = 0;
 | 
						|
	x = b->x;
 | 
						|
	if (n > nbits) {
 | 
						|
		n -= nbits;
 | 
						|
		if (any_on(b,n)) {
 | 
						|
			lostbits = 1;
 | 
						|
			k = n - 1;
 | 
						|
			if (x[(unsigned int)k>>kshift] & 1 << (k & kmask)) {
 | 
						|
				lostbits = 2;
 | 
						|
				if (k > 0 && any_on(b,k))
 | 
						|
					lostbits = 3;
 | 
						|
				}
 | 
						|
			}
 | 
						|
		rshift(b, n);
 | 
						|
		e += n;
 | 
						|
		}
 | 
						|
	else if (n < nbits) {
 | 
						|
		n = nbits - n;
 | 
						|
		b = lshift(b, n);
 | 
						|
		if (b == NULL)
 | 
						|
			return STRTOG_NoMemory;
 | 
						|
		e -= n;
 | 
						|
		x = b->x;
 | 
						|
		}
 | 
						|
	if (e > fpi->emax) {
 | 
						|
 ovfl:
 | 
						|
		Bfree(b);
 | 
						|
 ovfl1:
 | 
						|
#ifndef NO_ERRNO
 | 
						|
		errno = ERANGE;
 | 
						|
#endif
 | 
						|
		return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
 | 
						|
		}
 | 
						|
	irv = STRTOG_Normal;
 | 
						|
	if (e < fpi->emin) {
 | 
						|
		irv = STRTOG_Denormal;
 | 
						|
		n = fpi->emin - e;
 | 
						|
		if (n >= nbits) {
 | 
						|
			switch (fpi->rounding) {
 | 
						|
			  case FPI_Round_near:
 | 
						|
				if (n == nbits && (n < 2 || any_on(b,n-1)))
 | 
						|
					goto one_bit;
 | 
						|
				break;
 | 
						|
			  case FPI_Round_up:
 | 
						|
				if (!sign)
 | 
						|
					goto one_bit;
 | 
						|
				break;
 | 
						|
			  case FPI_Round_down:
 | 
						|
				if (sign) {
 | 
						|
 one_bit:
 | 
						|
					x[0] = b->wds = 1;
 | 
						|
 dret:
 | 
						|
					*bp = b;
 | 
						|
					*expt = fpi->emin;
 | 
						|
#ifndef NO_ERRNO
 | 
						|
					errno = ERANGE;
 | 
						|
#endif
 | 
						|
					return STRTOG_Denormal | STRTOG_Inexhi
 | 
						|
						| STRTOG_Underflow;
 | 
						|
					}
 | 
						|
			  }
 | 
						|
			Bfree(b);
 | 
						|
 retz:
 | 
						|
#ifndef NO_ERRNO
 | 
						|
			errno = ERANGE;
 | 
						|
#endif
 | 
						|
			return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
 | 
						|
			}
 | 
						|
		k = n - 1;
 | 
						|
		if (lostbits)
 | 
						|
			lostbits = 1;
 | 
						|
		else if (k > 0)
 | 
						|
			lostbits = any_on(b,k);
 | 
						|
		if (x[(unsigned int)k>>kshift] & 1 << (k & kmask))
 | 
						|
			lostbits |= 2;
 | 
						|
		nbits -= n;
 | 
						|
		rshift(b,n);
 | 
						|
		e = fpi->emin;
 | 
						|
		}
 | 
						|
	if (lostbits) {
 | 
						|
		up = 0;
 | 
						|
		switch(fpi->rounding) {
 | 
						|
		  case FPI_Round_zero:
 | 
						|
			break;
 | 
						|
		  case FPI_Round_near:
 | 
						|
			if (lostbits & 2
 | 
						|
			 && (lostbits | x[0]) & 1)
 | 
						|
				up = 1;
 | 
						|
			break;
 | 
						|
		  case FPI_Round_up:
 | 
						|
			up = 1 - sign;
 | 
						|
			break;
 | 
						|
		  case FPI_Round_down:
 | 
						|
			up = sign;
 | 
						|
		  }
 | 
						|
		if (up) {
 | 
						|
			k = b->wds;
 | 
						|
			b = increment(b);
 | 
						|
			x = b->x;
 | 
						|
			if (irv == STRTOG_Denormal) {
 | 
						|
				if (nbits == fpi->nbits - 1
 | 
						|
				 && x[(unsigned int)nbits >> kshift] & 1 << (nbits & kmask))
 | 
						|
					irv =  STRTOG_Normal;
 | 
						|
				}
 | 
						|
			else if (b->wds > k
 | 
						|
			 || ((n = nbits & kmask) !=0
 | 
						|
			      && hi0bits(x[k-1]) < 32-n)) {
 | 
						|
				rshift(b,1);
 | 
						|
				if (++e > fpi->emax)
 | 
						|
					goto ovfl;
 | 
						|
				}
 | 
						|
			irv |= STRTOG_Inexhi;
 | 
						|
			}
 | 
						|
		else
 | 
						|
			irv |= STRTOG_Inexlo;
 | 
						|
		}
 | 
						|
	*bp = b;
 | 
						|
	*expt = e;
 | 
						|
	return irv;
 | 
						|
	}
 |