]> git.saurik.com Git - apple/libc.git/blobdiff - gdtoa/FreeBSD/gdtoa-gethex.c
Libc-391.5.22.tar.gz
[apple/libc.git] / gdtoa / FreeBSD / gdtoa-gethex.c
index 0f9ae3348c6b2a55ff86caa598b175d2af6f282f..610f74735e98c314823dde21438f06c063166b38 100644 (file)
@@ -26,10 +26,8 @@ THIS SOFTWARE.
 
 ****************************************************************/
 
-/* Please send bug reports to
-       David M. Gay
-       dmg@acm.org
- */
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to ".").     */
 
 #include "gdtoaimp.h"
 
@@ -47,11 +45,11 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
 {
        Bigint *b;
        CONST unsigned char *decpt, *s0, *s, *s1;
-       int esign, havedig, irv, k, n, nbits, up;
+       int esign, havedig, irv, k, n, nbits, up, zret;
        ULong L, lostbits, *x;
        Long e, e1;
 #ifdef USE_LOCALE
-       char decimalpoint = *localeconv()->decimal_point;
+       unsigned char decimalpoint = *localeconv()->decimal_point;
 #else
 #define decimalpoint '.'
 #endif
@@ -65,22 +63,20 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
        s0 += havedig;
        s = s0;
        decpt = 0;
+       zret = 0;
+       e = 0;
        if (!hexdig[*s]) {
-               if (*s == decimalpoint) {
-                       decpt = ++s;
-                       if (!hexdig[*s])
-                               goto ret0;
-                       }
-               else {
- ret0:
-                       *sp = (char*)s;
-                       return havedig ? STRTOG_Zero : STRTOG_NoNumber;
-                       }
+               zret = 1;
+               if (*s != decimalpoint)
+                       goto pcheck;
+               decpt = ++s;
+               if (!hexdig[*s])
+                       goto pcheck;
                while(*s == '0')
                        s++;
+               if (hexdig[*s])
+                       zret = 0;
                havedig = 1;
-               if (!hexdig[*s])
-                       goto ret0;
                s0 = s;
                }
        while(hexdig[*s])
@@ -90,9 +86,9 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
                while(hexdig[*s])
                        s++;
                }
-       e = 0;
        if (decpt)
                e = -(((Long)(s-decpt)) << 2);
+ pcheck:
        s1 = s;
        switch(*s) {
          case 'p':
@@ -117,6 +113,8 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
                e += e1;
          }
        *sp = (char*)s;
+       if (zret)
+               return havedig ? STRTOG_Zero : STRTOG_NoNumber;
        n = s1 - s0 - 1;
        for(k = 0; n > 7; n >>= 1)
                k++;
@@ -164,6 +162,7 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
        if (e > fpi->emax) {
  ovfl:
                Bfree(b);
+               *bp = 0;
                return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
                }
        irv = STRTOG_Normal;
@@ -173,7 +172,7 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
                if (n >= nbits) {
                        switch (fpi->rounding) {
                          case FPI_Round_near:
-                               if (n == nbits && n < 2 || any_on(b,n-1))
+                               if (n == nbits && (n < 2 || any_on(b,n-1)))
                                        goto one_bit;
                                break;
                          case FPI_Round_up:
@@ -191,6 +190,7 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
                                        }
                          }
                        Bfree(b);
+                       *bp = 0;
                        return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
                        }
                k = n - 1;
@@ -224,18 +224,18 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
                        k = b->wds;
                        b = increment(b);
                        x = b->x;
-                       if (b->wds > k
+                       if (irv == STRTOG_Denormal) {
+                               if (nbits == fpi->nbits - 1
+                                && x[nbits >> kshift] & 1 << (nbits & kmask))
+                                       irv =  STRTOG_Normal;
+                               }
+                       else if (b->wds > k
                         || (n = nbits & kmask) !=0
                             && hi0bits(x[k-1]) < 32-n) {
                                rshift(b,1);
                                if (++e > fpi->emax)
                                        goto ovfl;
                                }
-                       else if (irv == STRTOG_Denormal) {
-                               k = nbits - 1;
-                               if (x[k >> kshift] & 1 << (k & kmask))
-                                       irv = STRTOG_Normal;
-                               }
                        irv |= STRTOG_Inexhi;
                        }
                else