hexnan.c revision 208753
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/* $FreeBSD: head/contrib/gdtoa/hexnan.c 208753 2010-06-02 18:31:04Z uqs $ */
33
34#include <ctype.h>
35
36#include "gdtoaimp.h"
37
38 static void
39#ifdef KR_headers
40L_shift(x, x1, i) ULong *x; ULong *x1; int i;
41#else
42L_shift(ULong *x, ULong *x1, int i)
43#endif
44{
45	int j;
46
47	i = 8 - i;
48	i <<= 2;
49	j = ULbits - i;
50	do {
51		*x |= x[1] << j;
52		x[1] >>= i;
53		} while(++x < x1);
54	}
55
56 int
57#ifdef KR_headers
58hexnan(sp, fpi, x0)
59	CONST char **sp; FPI *fpi; ULong *x0;
60#else
61hexnan( CONST char **sp, FPI *fpi, ULong *x0)
62#endif
63{
64	ULong c, h, *x, *x1, *xe;
65	CONST char *s;
66	int havedig, hd0, i, nbits;
67
68	if (!hexdig['0'])
69		hexdig_init_D2A();
70	nbits = fpi->nbits;
71	x = x0 + (nbits >> kshift);
72	if (nbits & kmask)
73		x++;
74	*--x = 0;
75	x1 = xe = x;
76	havedig = hd0 = i = 0;
77	s = *sp;
78
79	/* FreeBSD local: Accept (but ignore) the '0x' prefix. */
80	if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X'))
81		s += 2;
82
83	while(c = *(CONST unsigned char*)++s) {
84		if (!(h = hexdig[c])) {
85#if 0
86			if (c <= ' ') {
87				if (hd0 < havedig) {
88					if (x < x1 && i < 8)
89						L_shift(x, x1, i);
90					if (x <= x0) {
91						i = 8;
92						continue;
93						}
94					hd0 = havedig;
95					*--x = 0;
96					x1 = x;
97					i = 0;
98					}
99				continue;
100				}
101			if (/*(*/ c == ')' && havedig) {
102				*sp = s + 1;
103				break;
104				}
105#endif
106			break;
107			}
108		havedig++;
109		if (++i > 8) {
110			if (x <= x0)
111				continue;
112			i = 1;
113			*--x = 0;
114			}
115		*x = (*x << 4) | h & 0xf;
116		}
117	if (havedig && x < x1 && i < 8)
118		L_shift(x, x1, i);
119	if (x > x0) {
120		x1 = x0;
121		do *x1++ = *x++;
122			while(x <= xe);
123		do *x1++ = 0;
124			while(x1 <= xe);
125		}
126	else {
127		/* truncate high-order word if necessary */
128		if ( (i = nbits & (ULbits-1)) !=0)
129			*xe &= ((ULong)0xffffffff) >> (ULbits - i);
130		}
131	if (havedig) {
132	for(x1 = xe;; --x1) {
133		if (*x1 != 0)
134			break;
135		if (x1 == x0) {
136			*x1 = 1;
137			break;
138			}
139		}
140	}
141
142	/*
143	 * FreeBSD local: Accept all the sequences allowed by C99 and update
144	 * the tail pointer correctly. Don't accept any invalid sequences.
145	 */
146	if (c == '\0')	/* nan() calls this, too; tolerate a missing ')' */
147		return STRTOG_NaNbits;
148	if (c != ')') {
149		while(c = *(CONST unsigned char*)++s) {
150			if (c == ')')
151				break;
152			if (!isalnum(c) && c != '_')
153				return STRTOG_NaNbits;
154		}
155	}
156	*sp = s + 1;
157	return STRTOG_NaNbits;
158	}
159