]> git.saurik.com Git - apple/libc.git/blobdiff - gdtoa/FreeBSD/gdtoa-strtodg.c
Libc-583.tar.gz
[apple/libc.git] / gdtoa / FreeBSD / gdtoa-strtodg.c
index cbdf4aadf29964abda9f8a55eba74fca651ea3fc..41ead32decb9ca6706d685ec7d2b06f59aa33126 100644 (file)
@@ -89,7 +89,7 @@ increment(Bigint *b)
        return b;
        }
 
- int
+ void
 #ifdef KR_headers
 decrement(b) Bigint *b;
 #else
@@ -119,7 +119,6 @@ decrement(Bigint *b)
                *x++ = y & 0xffff;
                } while(borrow && x < xe);
 #endif
-       return STRTOG_Inexlo;
        }
 
  static int
@@ -206,9 +205,9 @@ rvOK
                goto ret;
                }
        switch(rd) {
-         case 1:
+         case 1: /* round down (toward -Infinity) */
                goto trunc;
-         case 2:
+         case 2: /* round up (toward +Infinity) */
                break;
          default: /* round near */
                k = bdif - 1;
@@ -330,8 +329,24 @@ strtodg
        CONST char *s, *s0, *s1;
        double adj, adj0, rv, tol;
        Long L;
-       ULong y, z;
+       ULong *b, *be, y, z;
        Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
+#ifdef USE_LOCALE
+#ifdef NO_LOCALE_CACHE
+       char *decimalpoint = localeconv()->decimal_point;
+#else
+       char *decimalpoint;
+       static char *decimalpoint_cache;
+       if (!(s0 = decimalpoint_cache)) {
+               s0 = localeconv()->decimal_point;
+               if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+                       strcpy(decimalpoint_cache, s0);
+                       s0 = decimalpoint_cache;
+                       }
+               }
+       decimalpoint = (char*)s0;
+#endif
+#endif
 
        irv = STRTOG_Zero;
        denorm = sign = nz0 = nz = 0;
@@ -390,13 +405,17 @@ strtodg
                        z = 10*z + c - '0';
        nd0 = nd;
 #ifdef USE_LOCALE
-       if (c == *localeconv()->decimal_point)
+       if (c == *decimalpoint) {
+               for(i = 1; decimalpoint[i]; ++i)
+                       if (s[i] != decimalpoint[i])
+                               goto dig_done;
+               s += i;
+               c = *s;
 #else
-       if (c == '.')
+       if (c == '.') {
+               c = *++s;
 #endif
-               {
                decpt = 1;
-               c = *++s;
                if (!nd) {
                        for(; c == '0'; c = *++s)
                                nz++;
@@ -425,7 +444,7 @@ strtodg
                                nz = 0;
                                }
                        }
-               }
+               }/*}*/
  dig_done:
        e = 0;
        if (c == 'e' || c == 'E') {
@@ -822,10 +841,8 @@ strtodg
                                break;
                        if (dsign) {
                                rvb = increment(rvb);
-                               if ( (j = rvbits & kmask) !=0)
-                                       j = ULbits - j;
-                               if (hi0bits(rvb->x[(rvb->wds - 1) >> kshift])
-                                               != j)
+                               j = kmask & (ULbits - (rvbits & kmask));
+                               if (hi0bits(rvb->x[rvb->wds - 1]) != j)
                                        rvbits++;
                                irv = STRTOG_Normal | STRTOG_Inexhi;
                                }
@@ -978,6 +995,29 @@ strtodg
        Bfree(bd0);
        Bfree(delta);
        if (rve > fpi->emax) {
+               switch(fpi->rounding & 3) {
+                 case FPI_Round_near:
+                       goto huge;
+                 case FPI_Round_up:
+                       if (!sign)
+                               goto huge;
+                       break;
+                 case FPI_Round_down:
+                       if (sign)
+                               goto huge;
+                 }
+               /* Round to largest representable magnitude */
+               Bfree(rvb);
+               rvb = 0;
+               irv = STRTOG_Normal | STRTOG_Inexlo;
+               *exp = fpi->emax;
+               b = bits;
+               be = b + ((fpi->nbits + 31) >> 5);
+               while(b < be)
+                       *b++ = -1;
+               if ((j = fpi->nbits & 0x1f))
+                       *--be >>= (32 - j);
+               goto ret;
  huge:
                rvb->wds = 0;
                irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
@@ -992,12 +1032,19 @@ strtodg
                if (sudden_underflow) {
                        rvb->wds = 0;
                        irv = STRTOG_Underflow | STRTOG_Inexlo;
+#ifndef NO_ERRNO
+                       errno = ERANGE;
+#endif
                        }
                else  {
                        irv = (irv & ~STRTOG_Retmask) |
                                (rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero);
-                       if (irv & STRTOG_Inexact)
+                       if (irv & STRTOG_Inexact) {
                                irv |= STRTOG_Underflow;
+#ifndef NO_ERRNO
+                               errno = ERANGE;
+#endif
+                               }
                        }
                }
        if (se)