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