]>
git.saurik.com Git - apple/libc.git/blob - gdtoa/FreeBSD/gdtoa-gethex.c
1 /****************************************************************
3 The author of this software is David M. Gay.
5 Copyright (C) 1998 by Lucent Technologies
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
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
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 "xlocale_private.h"
36 #include <sys/types.h>
44 gethex(sp
, fpi
, exp
, bp
, sign
, loc
)
45 CONST
char **sp
; CONST FPI
*fpi
; Long
*exp
; Bigint
**bp
; int sign
; locale_t loc
;
47 gethex( CONST
char **sp
, CONST FPI
*fpi
, Long
*exp
, Bigint
**bp
, int sign
, locale_t loc
)
51 CONST
unsigned char *decpt
, *s0
, *s
, *s1
;
52 unsigned char *strunc
;
53 int big
, esign
, havedig
, irv
, j
, k
, n
, n0
, nbits
, up
, zret
;
54 ULong L
, lostbits
, *x
;
58 NORMALIZE_LOCALE(loc
);
59 #ifdef NO_LOCALE_CACHE
60 const unsigned char *decimalpoint
= (unsigned char*)localeconv_l(loc
)->decimal_point
;
62 const unsigned char *decimalpoint
;
63 static unsigned char *decimalpoint_cache
;
64 if (!(s0
= decimalpoint_cache
)) {
65 s0
= (unsigned char*)localeconv_l(loc
)->decimal_point
;
66 if ((decimalpoint_cache
= (char*)MALLOC(strlen(s0
) + 1))) {
67 strcpy(decimalpoint_cache
, s0
);
68 s0
= decimalpoint_cache
;
79 s0
= *(CONST
unsigned char **)sp
+ 2;
80 while(s0
[havedig
] == '0')
92 for(i
= 0; decimalpoint
[i
]; ++i
) {
93 if (s
[i
] != decimalpoint
[i
])
114 if (*s
== *decimalpoint
&& !decpt
) {
115 for(i
= 1; decimalpoint
[i
]; ++i
) {
116 if (s
[i
] != decimalpoint
[i
])
121 if (*s
== '.' && !decpt
) {
128 e
= -(((Long
)(s
-decpt
)) << 2);
142 if ((n
= hexdig
[*s
]) == 0 || n
> 0x19) {
147 while((n
= hexdig
[*++s
]) !=0 && n
<= 0x19) {
150 e1
= 10*e1
+ n
- 0x10;
163 switch(fpi
->rounding
) {
180 switch(fpi
->rounding
) {
194 n0
= n
= nbits
>> kshift
;
197 for(j
= n
, k
= 0; j
>>= 1; ++k
);
200 for(j
= 0; j
< n0
; ++j
)
203 b
->x
[j
] = ULbits
>> (ULbits
- (nbits
& kmask
));
205 return STRTOG_Normal
| STRTOG_Inexlo
;
208 * Truncate the hex string if it is longer than the precision needed,
209 * to avoid denial-of-service issues with very large strings. Use
210 * additional digits to insure precision. Scan to-be-truncated digits
211 * and replace with either '1' or '0' to ensure proper rounding.
214 int maxdigits
= ((fpi
->nbits
+ 3) >> 2) + 2;
217 int dplen
= strlen((const char *)decimalpoint
);
222 if (decpt
&& s0
< decpt
)
224 if (nd
> maxdigits
&& (strunc
= alloca(maxdigits
+ dplen
+ 2)) != NULL
) {
225 ssize_t nd0
= decpt
? decpt
- s0
- dplen
: nd
;
226 unsigned char *tp
= strunc
+ maxdigits
;
228 if ((nd0
-= maxdigits
) >= 0 || s0
>= decpt
)
229 memcpy(strunc
, s0
, maxdigits
);
231 memcpy(strunc
, s0
, maxdigits
+ dplen
);
235 e
+= (nd
- (maxdigits
+ 1)) << 2;
244 if (!found
&& decpt
) {
251 *tp
++ = found
? '1' : '0';
259 for(k
= 0; n
> (1 << (kshift
-2)) - 1; n
>>= 1)
266 for(i
= 0; decimalpoint
[i
+1]; ++i
);
270 if (*--s1
== decimalpoint
[i
]) {
283 L
|= (hexdig
[*s1
] & 0x0f) << n
;
287 b
->wds
= n
= x
- b
->x
;
288 n
= ULbits
*n
- hi0bits(L
);
297 if (x
[k
>>kshift
] & 1 << (k
& kmask
)) {
299 if (k
> 0 && any_on(b
,k
))
306 else if (n
< nbits
) {
319 return STRTOG_Infinite
| STRTOG_Overflow
| STRTOG_Inexhi
;
323 irv
= STRTOG_Denormal
;
326 switch (fpi
->rounding
) {
328 if (n
== nbits
&& (n
< 2 || any_on(b
,n
-1)))
345 return STRTOG_Denormal
| STRTOG_Inexhi
354 return STRTOG_Zero
| STRTOG_Inexlo
| STRTOG_Underflow
;
360 lostbits
= any_on(b
,k
);
361 if (x
[k
>>kshift
] & 1 << (k
& kmask
))
369 switch(fpi
->rounding
) {
374 && (lostbits
| x
[0]) & 1)
387 if (irv
== STRTOG_Denormal
) {
388 if (nbits
== fpi
->nbits
- 1
389 && x
[nbits
>> kshift
] & 1 << (nbits
& kmask
))
393 || ((n
= nbits
& kmask
) !=0
394 && hi0bits(x
[k
-1]) < 32-n
)) {
399 irv
|= STRTOG_Inexhi
;
402 irv
|= STRTOG_Inexlo
;