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