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