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