1112158Sdas/****************************************************************
2112158Sdas
3112158SdasThe author of this software is David M. Gay.
4112158Sdas
5112158SdasCopyright (C) 2000 by Lucent Technologies
6112158SdasAll Rights Reserved
7112158Sdas
8112158SdasPermission to use, copy, modify, and distribute this software and
9112158Sdasits documentation for any purpose and without fee is hereby
10112158Sdasgranted, provided that the above copyright notice appear in all
11112158Sdascopies and that both that the copyright notice and this
12112158Sdaspermission notice and warranty disclaimer appear in supporting
13112158Sdasdocumentation, and that the name of Lucent or any of its entities
14112158Sdasnot be used in advertising or publicity pertaining to
15112158Sdasdistribution of the software without specific, written prior
16112158Sdaspermission.
17112158Sdas
18112158SdasLUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19112158SdasINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20112158SdasIN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21112158SdasSPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22112158SdasWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23112158SdasIN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24112158SdasARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
25112158SdasTHIS SOFTWARE.
26112158Sdas
27112158Sdas****************************************************************/
28112158Sdas
29165743Sdas/* Please send bug reports to David M. Gay (dmg at acm dot org,
30165743Sdas * with " at " changed at "@" and " dot " changed to ".").	*/
31112158Sdas
32112158Sdas#include "gdtoaimp.h"
33112158Sdas
34112158Sdas static void
35112158Sdas#ifdef KR_headers
36112158SdasL_shift(x, x1, i) ULong *x; ULong *x1; int i;
37112158Sdas#else
38112158SdasL_shift(ULong *x, ULong *x1, int i)
39112158Sdas#endif
40112158Sdas{
41112158Sdas	int j;
42112158Sdas
43112158Sdas	i = 8 - i;
44112158Sdas	i <<= 2;
45112158Sdas	j = ULbits - i;
46112158Sdas	do {
47112158Sdas		*x |= x[1] << j;
48112158Sdas		x[1] >>= i;
49112158Sdas		} while(++x < x1);
50112158Sdas	}
51112158Sdas
52112158Sdas int
53112158Sdas#ifdef KR_headers
54112158Sdashexnan(sp, fpi, x0)
55112158Sdas	CONST char **sp; FPI *fpi; ULong *x0;
56112158Sdas#else
57112158Sdashexnan( CONST char **sp, FPI *fpi, ULong *x0)
58112158Sdas#endif
59112158Sdas{
60112158Sdas	ULong c, h, *x, *x1, *xe;
61112158Sdas	CONST char *s;
62112158Sdas	int havedig, hd0, i, nbits;
63112158Sdas
64112158Sdas	if (!hexdig['0'])
65112158Sdas		hexdig_init_D2A();
66112158Sdas	nbits = fpi->nbits;
67112158Sdas	x = x0 + (nbits >> kshift);
68112158Sdas	if (nbits & kmask)
69112158Sdas		x++;
70112158Sdas	*--x = 0;
71112158Sdas	x1 = xe = x;
72112158Sdas	havedig = hd0 = i = 0;
73112158Sdas	s = *sp;
74219557Sdas	/* allow optional initial 0x or 0X */
75219557Sdas	while((c = *(CONST unsigned char*)(s+1)) && c <= ' ')
76219557Sdas		++s;
77219557Sdas	if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
78219557Sdas	 && *(CONST unsigned char*)(s+3) > ' ')
79174678Sdas		s += 2;
80219557Sdas	while((c = *(CONST unsigned char*)++s)) {
81112158Sdas		if (!(h = hexdig[c])) {
82112158Sdas			if (c <= ' ') {
83112158Sdas				if (hd0 < havedig) {
84112158Sdas					if (x < x1 && i < 8)
85112158Sdas						L_shift(x, x1, i);
86112158Sdas					if (x <= x0) {
87112158Sdas						i = 8;
88112158Sdas						continue;
89112158Sdas						}
90112158Sdas					hd0 = havedig;
91112158Sdas					*--x = 0;
92112158Sdas					x1 = x;
93112158Sdas					i = 0;
94112158Sdas					}
95219557Sdas				while(*(CONST unsigned char*)(s+1) <= ' ')
96219557Sdas					++s;
97219557Sdas				if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')
98219557Sdas				 && *(CONST unsigned char*)(s+3) > ' ')
99219557Sdas					s += 2;
100112158Sdas				continue;
101112158Sdas				}
102112158Sdas			if (/*(*/ c == ')' && havedig) {
103112158Sdas				*sp = s + 1;
104112158Sdas				break;
105112158Sdas				}
106219557Sdas#ifndef GDTOA_NON_PEDANTIC_NANCHECK
107219557Sdas			do {
108219557Sdas				if (/*(*/ c == ')') {
109219557Sdas					*sp = s + 1;
110219557Sdas					break;
111219557Sdas					}
112219557Sdas				} while((c = *++s));
113174678Sdas#endif
114219557Sdas			return STRTOG_NaN;
115112158Sdas			}
116112158Sdas		havedig++;
117112158Sdas		if (++i > 8) {
118112158Sdas			if (x <= x0)
119112158Sdas				continue;
120112158Sdas			i = 1;
121112158Sdas			*--x = 0;
122112158Sdas			}
123219557Sdas		*x = (*x << 4) | (h & 0xf);
124112158Sdas		}
125219557Sdas	if (!havedig)
126219557Sdas		return STRTOG_NaN;
127219557Sdas	if (x < x1 && i < 8)
128112158Sdas		L_shift(x, x1, i);
129112158Sdas	if (x > x0) {
130112158Sdas		x1 = x0;
131112158Sdas		do *x1++ = *x++;
132112158Sdas			while(x <= xe);
133112158Sdas		do *x1++ = 0;
134112158Sdas			while(x1 <= xe);
135112158Sdas		}
136112158Sdas	else {
137112158Sdas		/* truncate high-order word if necessary */
138112158Sdas		if ( (i = nbits & (ULbits-1)) !=0)
139112158Sdas			*xe &= ((ULong)0xffffffff) >> (ULbits - i);
140112158Sdas		}
141112158Sdas	for(x1 = xe;; --x1) {
142112158Sdas		if (*x1 != 0)
143112158Sdas			break;
144112158Sdas		if (x1 == x0) {
145112158Sdas			*x1 = 1;
146112158Sdas			break;
147112158Sdas			}
148112158Sdas		}
149112158Sdas	return STRTOG_NaNbits;
150112158Sdas	}
151