master
  1/****************************************************************
  2
  3The author of this software is David M. Gay.
  4
  5Copyright (C) 2000 by Lucent Technologies
  6All Rights Reserved
  7
  8Permission to use, copy, modify, and distribute this software and
  9its documentation for any purpose and without fee is hereby
 10granted, provided that the above copyright notice appear in all
 11copies and that both that the copyright notice and this
 12permission notice and warranty disclaimer appear in supporting
 13documentation, and that the name of Lucent or any of its entities
 14not be used in advertising or publicity pertaining to
 15distribution of the software without specific, written prior
 16permission.
 17
 18LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 19INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
 20IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
 21SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 22WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 23IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 24ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
 25THIS SOFTWARE.
 26
 27****************************************************************/
 28
 29/* Please send bug reports to David M. Gay (dmg at acm dot org,
 30 * with " at " changed at "@" and " dot " changed to ".").	*/
 31
 32#include "gdtoaimp.h"
 33
 34static void L_shift (ULong *x, ULong *x1, int i)
 35{
 36	int j;
 37
 38	i = 8 - i;
 39	i <<= 2;
 40	j = ULbits - i;
 41	do {
 42		*x |= x[1] << j;
 43		x[1] >>= i;
 44	} while(++x < x1);
 45}
 46
 47int hexnan (const char **sp, const FPI *fpi, ULong *x0)
 48{
 49	ULong c, h, *x, *x1, *xe;
 50	const char *s;
 51	int havedig, hd0, i, nbits;
 52
 53	/**** if (!hexdig['0']) hexdig_init_D2A(); ****/
 54	nbits = fpi->nbits;
 55	x = x0 + (nbits >> kshift);
 56	if (nbits & kmask)
 57		x++;
 58	*--x = 0;
 59	x1 = xe = x;
 60	havedig = hd0 = i = 0;
 61	s = *sp;
 62	/* allow optional initial 0x or 0X */
 63	while((c = *(const unsigned char*)(s+1)) && c <= ' ') {
 64		if (!c)
 65			goto retnan;
 66		++s;
 67	}
 68	if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
 69	 && *(const unsigned char*)(s+3) > ' ')
 70		s += 2;
 71	while((c = *(const unsigned char*)++s)) {
 72		if (!(h = hexdig[c])) {
 73			if (c <= ' ') {
 74				if (hd0 < havedig) {
 75					if (x < x1 && i < 8)
 76						L_shift(x, x1, i);
 77					if (x <= x0) {
 78						i = 8;
 79						continue;
 80					}
 81					hd0 = havedig;
 82					*--x = 0;
 83					x1 = x;
 84					i = 0;
 85				}
 86				while((c = *(const unsigned char*)(s+1)) <= ' ') {
 87					if (!c)
 88						goto retnan;
 89					++s;
 90				}
 91				if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
 92				 && *(const unsigned char*)(s+3) > ' ')
 93					s += 2;
 94				continue;
 95			}
 96			if (/*(*/ c == ')' && havedig) {
 97				*sp = s + 1;
 98				break;
 99			}
100#ifndef GDTOA_NON_PEDANTIC_NANCHECK
101			do {
102				if (/*(*/ c == ')') {
103					*sp = s + 1;
104					goto break2;
105				}
106			} while((c = *++s));
107#endif
108 retnan:
109			return STRTOG_NaN;
110		}
111		havedig++;
112		if (++i > 8) {
113			if (x <= x0)
114				continue;
115			i = 1;
116			*--x = 0;
117		}
118		*x = (*x << 4) | (h & 0xf);
119	}
120#ifndef GDTOA_NON_PEDANTIC_NANCHECK
121 break2:
122#endif
123	if (!havedig)
124		return STRTOG_NaN;
125	if (x < x1 && i < 8)
126		L_shift(x, x1, i);
127	if (x > x0) {
128		x1 = x0;
129		do *x1++ = *x++;
130			while(x <= xe);
131		do *x1++ = 0;
132			while(x1 <= xe);
133	}
134	else {
135		/* truncate high-order word if necessary */
136		if ( (i = nbits & (ULbits-1)) !=0)
137			*xe &= ((ULong)0xffffffff) >> (ULbits - i);
138	}
139	for(x1 = xe;; --x1) {
140		if (*x1 != 0)
141			break;
142		if (x1 == x0) {
143			*x1 = 1;
144			break;
145		}
146	}
147	return STRTOG_NaNbits;
148}