]> git.saurik.com Git - apple/libc.git/blob - gdtoa/FreeBSD/gdtoa-gethex.c
Libc-763.11.tar.gz
[apple/libc.git] / gdtoa / FreeBSD / gdtoa-gethex.c
1 /****************************************************************
2
3 The author of this software is David M. Gay.
4
5 Copyright (C) 1998 by Lucent Technologies
6 All Rights Reserved
7
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.
17
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.
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 #include "gdtoaimp.h"
33
34 #ifdef USE_LOCALE
35 #include "locale.h"
36 #endif
37
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
45 {
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 int i;
53 #ifdef NO_LOCALE_CACHE
54 const unsigned char *decimalpoint = (unsigned char*)localeconv()->decimal_point;
55 #else
56 const unsigned char *decimalpoint;
57 static unsigned char *decimalpoint_cache;
58 if (!(s0 = decimalpoint_cache)) {
59 s0 = (unsigned char*)localeconv()->decimal_point;
60 if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
61 strcpy(decimalpoint_cache, s0);
62 s0 = decimalpoint_cache;
63 }
64 }
65 decimalpoint = s0;
66 #endif
67 #endif
68
69 if (!hexdig['0'])
70 hexdig_init_D2A();
71 *bp = 0;
72 havedig = 0;
73 s0 = *(CONST unsigned char **)sp + 2;
74 while(s0[havedig] == '0')
75 havedig++;
76 s0 += havedig;
77 s = s0;
78 decpt = 0;
79 zret = 0;
80 e = 0;
81 if (hexdig[*s])
82 havedig++;
83 else {
84 zret = 1;
85 #ifdef USE_LOCALE
86 for(i = 0; decimalpoint[i]; ++i) {
87 if (s[i] != decimalpoint[i])
88 goto pcheck;
89 }
90 decpt = s += i;
91 #else
92 if (*s != '.')
93 goto pcheck;
94 decpt = ++s;
95 #endif
96 if (!hexdig[*s])
97 goto pcheck;
98 while(*s == '0')
99 s++;
100 if (hexdig[*s])
101 zret = 0;
102 havedig = 1;
103 s0 = s;
104 }
105 while(hexdig[*s])
106 s++;
107 #ifdef USE_LOCALE
108 if (*s == *decimalpoint && !decpt) {
109 for(i = 1; decimalpoint[i]; ++i) {
110 if (s[i] != decimalpoint[i])
111 goto pcheck;
112 }
113 decpt = s += i;
114 #else
115 if (*s == '.' && !decpt) {
116 decpt = ++s;
117 #endif
118 while(hexdig[*s])
119 s++;
120 }/*}*/
121 if (decpt)
122 e = -(((Long)(s-decpt)) << 2);
123 pcheck:
124 s1 = s;
125 big = esign = 0;
126 switch(*s) {
127 case 'p':
128 case 'P':
129 switch(*++s) {
130 case '-':
131 esign = 1;
132 /* no break */
133 case '+':
134 s++;
135 }
136 if ((n = hexdig[*s]) == 0 || n > 0x19) {
137 s = s1;
138 break;
139 }
140 e1 = n - 0x10;
141 while((n = hexdig[*++s]) !=0 && n <= 0x19) {
142 if (e1 & 0xf8000000)
143 big = 1;
144 e1 = 10*e1 + n - 0x10;
145 }
146 if (esign)
147 e1 = -e1;
148 e += e1;
149 }
150 *sp = (char*)s;
151 if (!havedig)
152 *sp = (char*)s0 - 1;
153 if (zret)
154 return STRTOG_Zero;
155 if (big) {
156 if (esign) {
157 switch(fpi->rounding) {
158 case FPI_Round_up:
159 if (sign)
160 break;
161 goto ret_tiny;
162 case FPI_Round_down:
163 if (!sign)
164 break;
165 goto ret_tiny;
166 }
167 goto retz;
168 ret_tiny:
169 b = Balloc(0);
170 b->wds = 1;
171 b->x[0] = 1;
172 goto dret;
173 }
174 switch(fpi->rounding) {
175 case FPI_Round_near:
176 goto ovfl1;
177 case FPI_Round_up:
178 if (!sign)
179 goto ovfl1;
180 goto ret_big;
181 case FPI_Round_down:
182 if (sign)
183 goto ovfl1;
184 goto ret_big;
185 }
186 ret_big:
187 nbits = fpi->nbits;
188 n0 = n = nbits >> kshift;
189 if (nbits & kmask)
190 ++n;
191 for(j = n, k = 0; j >>= 1; ++k);
192 *bp = b = Balloc(k);
193 b->wds = n;
194 for(j = 0; j < n0; ++j)
195 b->x[j] = ALL_ON;
196 if (n > n0)
197 b->x[j] = ULbits >> (ULbits - (nbits & kmask));
198 *exp = fpi->emin;
199 return STRTOG_Normal | STRTOG_Inexlo;
200 }
201 n = s1 - s0 - 1;
202 for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1)
203 k++;
204 b = Balloc(k);
205 x = b->x;
206 n = 0;
207 L = 0;
208 #ifdef USE_LOCALE
209 for(i = 0; decimalpoint[i+1]; ++i);
210 #endif
211 while(s1 > s0) {
212 #ifdef USE_LOCALE
213 if (*--s1 == decimalpoint[i]) {
214 s1 -= i;
215 continue;
216 }
217 #else
218 if (*--s1 == '.')
219 continue;
220 #endif
221 if (n == ULbits) {
222 *x++ = L;
223 L = 0;
224 n = 0;
225 }
226 L |= (hexdig[*s1] & 0x0f) << n;
227 n += 4;
228 }
229 *x++ = L;
230 b->wds = n = x - b->x;
231 n = ULbits*n - hi0bits(L);
232 nbits = fpi->nbits;
233 lostbits = 0;
234 x = b->x;
235 if (n > nbits) {
236 n -= nbits;
237 if (any_on(b,n)) {
238 lostbits = 1;
239 k = n - 1;
240 if (x[k>>kshift] & 1 << (k & kmask)) {
241 lostbits = 2;
242 if (k > 0 && any_on(b,k))
243 lostbits = 3;
244 }
245 }
246 rshift(b, n);
247 e += n;
248 }
249 else if (n < nbits) {
250 n = nbits - n;
251 b = lshift(b, n);
252 e -= n;
253 x = b->x;
254 }
255 if (e > fpi->emax) {
256 ovfl:
257 Bfree(b);
258 ovfl1:
259 #ifndef NO_ERRNO
260 errno = ERANGE;
261 #endif
262 return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
263 }
264 irv = STRTOG_Normal;
265 if (e < fpi->emin) {
266 irv = STRTOG_Denormal;
267 n = fpi->emin - e;
268 if (n >= nbits) {
269 switch (fpi->rounding) {
270 case FPI_Round_near:
271 if (n == nbits && (n < 2 || any_on(b,n-1)))
272 goto one_bit;
273 break;
274 case FPI_Round_up:
275 if (!sign)
276 goto one_bit;
277 break;
278 case FPI_Round_down:
279 if (sign) {
280 one_bit:
281 x[0] = b->wds = 1;
282 dret:
283 *bp = b;
284 *exp = fpi->emin;
285 #ifndef NO_ERRNO
286 errno = ERANGE;
287 #endif
288 return STRTOG_Denormal | STRTOG_Inexhi
289 | STRTOG_Underflow;
290 }
291 }
292 Bfree(b);
293 retz:
294 #ifndef NO_ERRNO
295 errno = ERANGE;
296 #endif
297 return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
298 }
299 k = n - 1;
300 if (lostbits)
301 lostbits = 1;
302 else if (k > 0)
303 lostbits = any_on(b,k);
304 if (x[k>>kshift] & 1 << (k & kmask))
305 lostbits |= 2;
306 nbits -= n;
307 rshift(b,n);
308 e = fpi->emin;
309 }
310 if (lostbits) {
311 up = 0;
312 switch(fpi->rounding) {
313 case FPI_Round_zero:
314 break;
315 case FPI_Round_near:
316 if (lostbits & 2
317 && (lostbits | x[0]) & 1)
318 up = 1;
319 break;
320 case FPI_Round_up:
321 up = 1 - sign;
322 break;
323 case FPI_Round_down:
324 up = sign;
325 }
326 if (up) {
327 k = b->wds;
328 b = increment(b);
329 x = b->x;
330 if (irv == STRTOG_Denormal) {
331 if (nbits == fpi->nbits - 1
332 && x[nbits >> kshift] & 1 << (nbits & kmask))
333 irv = STRTOG_Normal;
334 }
335 else if (b->wds > k
336 || ((n = nbits & kmask) !=0
337 && hi0bits(x[k-1]) < 32-n)) {
338 rshift(b,1);
339 if (++e > fpi->emax)
340 goto ovfl;
341 }
342 irv |= STRTOG_Inexhi;
343 }
344 else
345 irv |= STRTOG_Inexlo;
346 }
347 *bp = b;
348 *exp = e;
349 return irv;
350 }