turns printfs back on
[freebsd-src/fkvm-freebsd.git] / contrib / gdtoa / gethex.c
blobb3f7c508d38075702deac5de937cee09b797cb35
1 /****************************************************************
3 The author of this software is David M. Gay.
5 Copyright (C) 1998 by Lucent Technologies
6 All Rights Reserved
8 Permission to use, copy, modify, and distribute this software and
9 its documentation for any purpose and without fee is hereby
10 granted, provided that the above copyright notice appear in all
11 copies and that both that the copyright notice and this
12 permission notice and warranty disclaimer appear in supporting
13 documentation, and that the name of Lucent or any of its entities
14 not be used in advertising or publicity pertaining to
15 distribution of the software without specific, written prior
16 permission.
18 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
25 THIS SOFTWARE.
27 ****************************************************************/
29 /* Please send bug reports to David M. Gay (dmg at acm dot org,
30 * with " at " changed at "@" and " dot " changed to "."). */
32 #include "gdtoaimp.h"
34 #ifdef USE_LOCALE
35 #include "locale.h"
36 #endif
38 int
39 #ifdef KR_headers
40 gethex(sp, fpi, exp, bp, sign)
41 CONST char **sp; FPI *fpi; Long *exp; Bigint **bp; int sign;
42 #else
43 gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
44 #endif
46 Bigint *b;
47 CONST unsigned char *decpt, *s0, *s, *s1;
48 int big, esign, havedig, irv, j, k, n, n0, nbits, up, zret;
49 ULong L, lostbits, *x;
50 Long e, e1;
51 #ifdef USE_LOCALE
52 unsigned char decimalpoint = *localeconv()->decimal_point;
53 #else
54 #define decimalpoint '.'
55 #endif
57 if (!hexdig['0'])
58 hexdig_init_D2A();
59 *bp = 0;
60 havedig = 0;
61 s0 = *(CONST unsigned char **)sp + 2;
62 while(s0[havedig] == '0')
63 havedig++;
64 s0 += havedig;
65 s = s0;
66 decpt = 0;
67 zret = 0;
68 e = 0;
69 if (!hexdig[*s]) {
70 zret = 1;
71 if (*s != decimalpoint)
72 goto pcheck;
73 decpt = ++s;
74 if (!hexdig[*s])
75 goto pcheck;
76 while(*s == '0')
77 s++;
78 if (hexdig[*s])
79 zret = 0;
80 havedig = 1;
81 s0 = s;
83 while(hexdig[*s])
84 s++;
85 if (*s == decimalpoint && !decpt) {
86 decpt = ++s;
87 while(hexdig[*s])
88 s++;
90 if (decpt)
91 e = -(((Long)(s-decpt)) << 2);
92 pcheck:
93 s1 = s;
94 big = esign = 0;
95 switch(*s) {
96 case 'p':
97 case 'P':
98 switch(*++s) {
99 case '-':
100 esign = 1;
101 /* no break */
102 case '+':
103 s++;
105 if ((n = hexdig[*s]) == 0 || n > 0x19) {
106 s = s1;
107 break;
109 e1 = n - 0x10;
110 while((n = hexdig[*++s]) !=0 && n <= 0x19) {
111 if (e1 & 0xf8000000)
112 big = 1;
113 e1 = 10*e1 + n - 0x10;
115 if (esign)
116 e1 = -e1;
117 e += e1;
119 *sp = (char*)s;
120 if (!havedig)
121 *sp = s0 - 1;
122 if (zret)
123 return STRTOG_Zero;
124 if (big) {
125 if (esign) {
126 switch(fpi->rounding) {
127 case FPI_Round_up:
128 if (sign)
129 break;
130 goto ret_tiny;
131 case FPI_Round_down:
132 if (!sign)
133 break;
134 goto ret_tiny;
136 goto retz;
137 ret_tiny:
138 b = Balloc(0);
139 b->wds = 1;
140 b->x[0] = 1;
141 goto dret;
143 switch(fpi->rounding) {
144 case FPI_Round_near:
145 goto ovfl1;
146 case FPI_Round_up:
147 if (!sign)
148 goto ovfl1;
149 goto ret_big;
150 case FPI_Round_down:
151 if (sign)
152 goto ovfl1;
153 goto ret_big;
155 ret_big:
156 nbits = fpi->nbits;
157 n0 = n = nbits >> kshift;
158 if (nbits & kmask)
159 ++n;
160 for(j = n, k = 0; j >>= 1; ++k);
161 *bp = b = Balloc(k);
162 b->wds = n;
163 for(j = 0; j < n0; ++j)
164 b->x[j] = ALL_ON;
165 if (n > n0)
166 b->x[j] = ULbits >> (ULbits - (nbits & kmask));
167 *exp = fpi->emin;
168 return STRTOG_Normal | STRTOG_Inexlo;
170 n = s1 - s0 - 1;
171 for(k = 0; n > 7; n >>= 1)
172 k++;
173 b = Balloc(k);
174 x = b->x;
175 n = 0;
176 L = 0;
177 while(s1 > s0) {
178 if (*--s1 == decimalpoint)
179 continue;
180 if (n == 32) {
181 *x++ = L;
182 L = 0;
183 n = 0;
185 L |= (hexdig[*s1] & 0x0f) << n;
186 n += 4;
188 *x++ = L;
189 b->wds = n = x - b->x;
190 n = 32*n - hi0bits(L);
191 nbits = fpi->nbits;
192 lostbits = 0;
193 x = b->x;
194 if (n > nbits) {
195 n -= nbits;
196 if (any_on(b,n)) {
197 lostbits = 1;
198 k = n - 1;
199 if (x[k>>kshift] & 1 << (k & kmask)) {
200 lostbits = 2;
201 if (k > 0 && any_on(b,k))
202 lostbits = 3;
205 rshift(b, n);
206 e += n;
208 else if (n < nbits) {
209 n = nbits - n;
210 b = lshift(b, n);
211 e -= n;
212 x = b->x;
214 if (e > fpi->emax) {
215 ovfl:
216 Bfree(b);
217 ovfl1:
218 #ifndef NO_ERRNO
219 errno = ERANGE;
220 #endif
221 return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
223 irv = STRTOG_Normal;
224 if (e < fpi->emin) {
225 irv = STRTOG_Denormal;
226 n = fpi->emin - e;
227 if (n >= nbits) {
228 switch (fpi->rounding) {
229 case FPI_Round_near:
230 if (n == nbits && (n < 2 || any_on(b,n-1)))
231 goto one_bit;
232 break;
233 case FPI_Round_up:
234 if (!sign)
235 goto one_bit;
236 break;
237 case FPI_Round_down:
238 if (sign) {
239 one_bit:
240 x[0] = b->wds = 1;
241 dret:
242 *bp = b;
243 *exp = fpi->emin;
244 #ifndef NO_ERRNO
245 errno = ERANGE;
246 #endif
247 return STRTOG_Denormal | STRTOG_Inexhi
248 | STRTOG_Underflow;
251 Bfree(b);
252 retz:
253 #ifndef NO_ERRNO
254 errno = ERANGE;
255 #endif
256 return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
258 k = n - 1;
259 if (lostbits)
260 lostbits = 1;
261 else if (k > 0)
262 lostbits = any_on(b,k);
263 if (x[k>>kshift] & 1 << (k & kmask))
264 lostbits |= 2;
265 nbits -= n;
266 rshift(b,n);
267 e = fpi->emin;
269 if (lostbits) {
270 up = 0;
271 switch(fpi->rounding) {
272 case FPI_Round_zero:
273 break;
274 case FPI_Round_near:
275 if (lostbits & 2
276 && (lostbits & 1) | x[0] & 1)
277 up = 1;
278 break;
279 case FPI_Round_up:
280 up = 1 - sign;
281 break;
282 case FPI_Round_down:
283 up = sign;
285 if (up) {
286 k = b->wds;
287 b = increment(b);
288 x = b->x;
289 if (irv == STRTOG_Denormal) {
290 if (nbits == fpi->nbits - 1
291 && x[nbits >> kshift] & 1 << (nbits & kmask))
292 irv = STRTOG_Normal;
294 else if (b->wds > k
295 || (n = nbits & kmask) !=0
296 && hi0bits(x[k-1]) < 32-n) {
297 rshift(b,1);
298 if (++e > fpi->emax)
299 goto ovfl;
301 irv |= STRTOG_Inexhi;
303 else
304 irv |= STRTOG_Inexlo;
306 *bp = b;
307 *exp = e;
308 return irv;