mhi = mlo = 0;
JS_dtoa(double d, int mode, JSBool biasUp, int ndigits,    int *decpt, int *sign, char **rve, char *buf, size_t bufsize){    /*  Arguments ndigits, decpt, sign are similar to those        of ecvt and fcvt; trailing zeros are suppressed from        the returned string.  If not null, *rve is set to point        to the end of the return value.  If d is +-Infinity or NaN,        then *decpt is set to 9999.        mode:        0 ==> shortest string that yields d when read in        and rounded to nearest.        1 ==> like 0, but with Steele & White stopping rule;        e.g. with IEEE P754 arithmetic , mode 0 gives        1e23 whereas mode 1 gives 9.999999999999999e22.        2 ==> max(1,ndigits) significant digits.  This gives a        return value similar to that of ecvt, except        that trailing zeros are suppressed.        3 ==> through ndigits past the decimal point.  This        gives a return value similar to that from fcvt,        except that trailing zeros are suppressed, and        ndigits can be negative.        4-9 should give the same return values as 2-3, i.e.,        4 <= mode <= 9 ==> same return as mode        2 + (mode & 1).  These modes are mainly for        debugging; often they run slower but sometimes        faster than modes 2-3.        4,5,8,9 ==> left-to-right digit generation.        6-9 ==> don't try fast floating-point estimate        (if applicable).        Values of mode other than 0-9 are treated as mode 0.        Sufficient space is allocated to the return value        to hold the suppressed trailing zeros.    */    int32 bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,        j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,        spec_case, try_quick;    Long L;#ifndef Sudden_Underflow    int32 denorm;    ULong x;#endif    Bigint *b, *b1, *delta, *mlo, *mhi, *S;    double d2, ds, eps;    char *s;#ifdef JS_THREADSAFE    if (!initialized) InitDtoa();#endif    if (word0(d) & Sign_bit) {        /* set sign for everything, including 0's and NaNs */        *sign = 1;        set_word0(d, word0(d) & ~Sign_bit);  /* clear sign bit */    }    else        *sign = 0;    if ((word0(d) & Exp_mask) == Exp_mask) {        /* Infinity or NaN */        *decpt = 9999;        s = !word1(d) && !(word0(d) & Frac_mask) ? "Infinity" : "NaN";        if ((s[0] == 'I' && bufsize < 9) || (s[0] == 'N' && bufsize < 4)) {            JS_ASSERT(JS_FALSE);/*          JS_SetError(JS_BUFFER_OVERFLOW_ERROR, 0); */            return JS_FALSE;        }        strcpy(buf, s);        if (rve) {            *rve = buf[3] ? buf + 8 : buf + 3;            JS_ASSERT(**rve == '\0');        }        return JS_TRUE;    }    b = NULL;                           /* initialize for abort protection */    if (!d) {      no_digits:        *decpt = 1;        if (bufsize < 2) {            JS_ASSERT(JS_FALSE);/*          JS_SetError(JS_BUFFER_OVERFLOW_ERROR, 0); */            return JS_FALSE;        }        buf[0] = '0'; buf[1] = '\0';  /* copy "0" to buffer */        if (rve)            *rve = buf + 1;        /* We might have jumped to "no_digits" from below, so we need         * to be sure to free "b" to avoid memory leaks. */        Bfree(b);        return JS_TRUE;    }    b = d2b(d, &be, &bbits);#ifdef Sudden_Underflow    i = (int32)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));#else    if ((i = (int32)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) {#endif        d2 = d;        set_word0(d2, word0(d2) & Frac_mask1);        set_word0(d2, word0(d2) | Exp_11);        /* log(x)   ~=~ log(1.5) + (x-1.5)/1.5         * log10(x)  =  log(x) / log(10)         *      ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))         * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)         *         * This suggests computing an approximation k to log10(d) by         *         * k = (i - Bias)*0.301029995663981         *  + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );         *         * We want k to be too large rather than too small.         * The error in the first-order Taylor series approximation         * is in our favor, so we just round up the constant enough         * to compensate for any error in the multiplication of         * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,         * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,         * adding 1e-13 to the constant term more than suffices.         * Hence we adjust the constant term to 0.1760912590558.         * (We could get a more accurate k by invoking log10,         *  but this is probably not worthwhile.)         */        i -= Bias;#ifndef Sudden_Underflow        denorm = 0;    }    else {        /* d is denormalized */        i = bbits + be + (Bias + (P-1) - 1);        x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32) : word1(d) << (32 - i);        d2 = x;        set_word0(d2, word0(d2) - 31*Exp_msk1); /* adjust exponent */        i -= (Bias + (P-1) - 1) + 1;        denorm = 1;    }#endif    /* At this point d = f*2^i, where 1 <= f < 2.  d2 is an approximation of f. */    ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;    k = (int32)ds;    if (ds < 0. && ds != k)        k--;    /* want k = floor(ds) */    k_check = 1;    if (k >= 0 && k <= Ten_pmax) {        if (d < tens[k])            k--;        k_check = 0;    }    /* At this point floor(log10(d)) <= k <= floor(log10(d))+1.       If k_check is zero, we're guaranteed that k = floor(log10(d)). */    j = bbits - i - 1;    /* At this point d = b/2^j, where b is an odd integer. */    if (j >= 0) {        b2 = 0;        s2 = j;    }    else {        b2 = -j;        s2 = 0;    }    if (k >= 0) {        b5 = 0;        s5 = k;        s2 += k;    }    else {        b2 -= k;        b5 = -k;        s5 = 0;    }    /* At this point d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5), where b is an odd integer,       b2 >= 0, b5 >= 0, s2 >= 0, and s5 >= 0. */    if (mode < 0 || mode > 9)        mode = 0;    try_quick = 1;    if (mode > 5) {        mode -= 4;        try_quick = 0;    }    leftright = 1;    ilim = ilim1 = 0;    switch(mode) {    case 0:    case 1:        ilim = ilim1 = -1;        i = 18;        ndigits = 0;        break;    case 2:        leftright = 0;        /* no break */    case 4:        if (ndigits <= 0)            ndigits = 1;        ilim = ilim1 = i = ndigits;        break;    case 3:        leftright = 0;        /* no break */    case 5:        i = ndigits + k + 1;        ilim = i;        ilim1 = i - 1;        if (i <= 0)            i = 1;    }    /* ilim is the maximum number of significant digits we want, based on k and ndigits. */    /* ilim1 is the maximum number of significant digits we want, based on k and ndigits,       when it turns out that k was computed too high by one. */    /* Ensure space for at least i+1 characters, including trailing null. */    if (bufsize <= (size_t)i) {        Bfree(b);        JS_ASSERT(JS_FALSE);        return JS_FALSE;    }    s = buf;    if (ilim >= 0 && ilim <= Quick_max && try_quick) {        /* Try to get by with floating-point arithmetic. */        i = 0;        d2 = d;        k0 = k;        ilim0 = ilim;        ieps = 2; /* conservative */        /* Divide d by 10^k, keeping track of the roundoff error and avoiding overflows. */        if (k > 0) {            ds = tens[k&0xf];            j = k >> 4;            if (j & Bletch) {                /* prevent overflows */                j &= Bletch - 1;                d /= bigtens[n_bigtens-1];                ieps++;            }            for(; j; j >>= 1, i++)                if (j & 1) {                    ieps++;                    ds *= bigtens[i];                }            d /= ds;        }        else if ((j1 = -k) != 0) {            d *= tens[j1 & 0xf];            for(j = j1 >> 4; j; j >>= 1, i++)                if (j & 1) {                    ieps++;                    d *= bigtens[i];                }        }        /* Check that k was computed correctly. */        if (k_check && d < 1. && ilim > 0) {            if (ilim1 <= 0)                goto fast_failed;            ilim = ilim1;            k--;            d *= 10.;            ieps++;        }        /* eps bounds the cumulative error. */        eps = ieps*d + 7.;        set_word0(eps, word0(eps) - (P-1)*Exp_msk1);        if (ilim == 0) {            S = mhi = 0;            d -= 5.;            if (d > eps)                goto one_digit;            if (d < -eps)                goto no_digits;            goto fast_failed;        }#ifndef No_leftright        if (leftright) {            /* Use Steele & White method of only             * generating digits needed.             */            eps = 0.5/tens[ilim-1] - eps;            for(i = 0;;) {                L = (Long)d;                d -= L;                *s++ = '0' + (char)L;                if (d < eps)                    goto ret1;                if (1. - d < eps)                    goto bump_up;                if (++i >= ilim)                    break;                eps *= 10.;                d *= 10.;            }        }        else {#endif            /* Generate ilim digits, then fix them up. */            eps *= tens[ilim-1];            for(i = 1;; i++, d *= 10.) {                L = (Long)d;                d -= L;                *s++ = '0' + (char)L;                if (i == ilim) {                    if (d > 0.5 + eps)                        goto bump_up;                    else if (d < 0.5 - eps) {                        while(*--s == '0') ;                        s++;                        goto ret1;                    }                    break;                }            }#ifndef No_leftright        }#endif    fast_failed:        s = buf;        d = d2;        k = k0;        ilim = ilim0;    }    /* Do we have a "small" integer? */    if (be >= 0 && k <= Int_max) {        /* Yes. */        ds = tens[k];        if (ndigits < 0 && ilim <= 0) {            S = mhi = 0;            if (ilim < 0 || d < 5*ds || (!biasUp && d == 5*ds))                goto no_digits;            goto one_digit;        }        for(i = 1;; i++) {            L = (Long) (d / ds);            d -= L*ds;#ifdef Check_FLT_ROUNDS            /* If FLT_ROUNDS == 2, L will usually be high by 1 */            if (d < 0) {                L--;                d += ds;            }#endif            *s++ = '0' + (char)L;            if (i == ilim) {                d += d;                if ((d > ds) || (d == ds && (L & 1 || biasUp))) {                bump_up:                    while(*--s == '9')                        if (s == buf) {                            k++;                            *s = '0';                            break;                        }                    ++*s++;                }                break;            }            if (!(d *= 10.))                break;        }        goto ret1;    }    m2 = b2;    m5 = b5;    mhi = mlo = 0;    if (leftright) {        if (mode < 2) {            i =#ifndef Sudden_Underflow                denorm ? be + (Bias + (P-1) - 1 + 1) :#endif            1 + P - bbits;            /* i is 1 plus the number of trailing zero bits in d's significand. Thus,               (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 lsb of d)/10^k. */        }        else {            j = ilim - 1;            if (m5 >= j)                m5 -= j;            else {                s5 += j -= m5;                b5 += j;                m5 = 0;            }            if ((i = ilim) < 0) {                m2 -= i;                i = 0;            }            /* (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 * 10^(1-ilim))/10^k. */        }        b2 += i;        s2 += i;        mhi = i2b(1);        /* (mhi * 2^m2 * 5^m5) / (2^s2 * 5^s5) = one-half of last printed (when mode >= 2) or           input (when mode < 2) significant digit, divided by 10^k. */    }    /* We still have d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5).  Reduce common factors in       b2, m2, and s2 without changing the equalities. */    if (m2 > 0 && s2 > 0) {        i = m2 < s2 ? m2 : s2;        b2 -= i;        m2 -= i;        s2 -= i;    }    /* Fold b5 into b and m5 into mhi. */    if (b5 > 0) {        if (leftright) {            if (m5 > 0) {                mhi = pow5mult(mhi, m5);                b1 = mult(mhi, b);                Bfree(b);                b = b1;            }            if ((j = b5 - m5) != 0)                b = pow5mult(b, j);        }        else            b = pow5mult(b, b5);    }    /* Now we have d/10^k = (b * 2^b2) / (2^s2 * 5^s5) and       (mhi * 2^m2) / (2^s2 * 5^s5) = one-half of last printed or input significant digit, divided by 10^k. */    S = i2b(1);    if (s5 > 0)        S = pow5mult(S, s5);    /* Now we have d/10^k = (b * 2^b2) / (S * 2^s2) and       (mhi * 2^m2) / (S * 2^s2) = one-half of last printed or input significant digit, divided by 10^k. */    /* Check for special case that d is a normalized power of 2. */    spec_case = 0;    if (mode < 2) {        if (!word1(d) && !(word0(d) & Bndry_mask)#ifndef Sudden_Underflow            && word0(d) & (Exp_mask & Exp_mask << 1)#endif            ) {            /* The special case.  Here we want to be within a quarter of the last input               significant digit instead of one half of it when the decimal output string's value is less than d.  */            b2 += Log2P;            s2 += Log2P;            spec_case = 1;        }    }    /* Arrange for convenient computation of quotients:     * shift left if necessary so divisor has 4 leading 0 bits.     *     * Perhaps we should just compute leading 28 bits of S once     * and for all and pass them and a shift to quorem, so it     * can do shifts and ors to compute the numerator for q.     */    if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) != 0)        i = 32 - i;    /* i is the number of leading zero bits in the most significant word of S*2^s2. */    if (i > 4) {        i -= 4;        b2 += i;        m2 += i;        s2 += i;    }    else if (i < 4) {        i += 28;        b2 += i;        m2 += i;        s2 += i;    }    /* Now S*2^s2 has exactly four leading zero bits in its most significant word. */    if (b2 > 0)        b = lshift(b, b2);    if (s2 > 0)        S = lshift(S, s2);    /* Now we have d/10^k = b/S and       (mhi * 2^m2) / S = maximum acceptable error, divided by 10^k. */    if (k_check) {        if (cmp(b,S) < 0) {            k--;            b = multadd(b, 10, 0);  /* we botched the k estimate */            if (leftright)                mhi = multadd(mhi, 10, 0);            ilim = ilim1;        }    }    /* At this point 1 <= d/10^k = b/S < 10. */    if (ilim <= 0 && mode > 2) {        /* We're doing fixed-mode output and d is less than the minimum nonzero output in this mode.           Output either zero or the minimum nonzero output depending on which is closer to d. */        if (ilim < 0 || (i = cmp(b,S = multadd(S,5,0))) < 0 || (i == 0 && !biasUp)) {        /* Always emit at least one digit.  If the number appears to be zero           using the current mode, then emit one '0' digit and set decpt to 1. */        /*no_digits:            k = -1 - ndigits;            goto ret; */            goto no_digits;        }    one_digit:        *s++ = '1';        k++;        goto ret;    }    if (leftright) {        if (m2 > 0)            mhi = lshift(mhi, m2);        /* Compute mlo -- check for special case         * that d is a normalized power of 2.         */        mlo = mhi;        if (spec_case) {            mhi = Balloc(mhi->k);            Bcopy(mhi, mlo);            mhi = lshift(mhi, Log2P);        }        /* mlo/S = maximum acceptable error, divided by 10^k, if the output is less than d. */        /* mhi/S = maximum acceptable error, divided by 10^k, if the output is greater than d. */        for(i = 1;;i++) {            dig = quorem(b,S) + '0';            /* Do we yet have the shortest decimal string             * that will round to d?             */            j = cmp(b, mlo);            /* j is b/S compared with mlo/S. */            delta = diff(S, mhi);            j1 = delta->sign ? 1 : cmp(b, delta);            Bfree(delta);            /* j1 is b/S compared with 1 - mhi/S. */#ifndef ROUND_BIASED            if (j1 == 0 && !mode && !(word1(d) & 1)) {                if (dig == '9')                    goto round_9_up;                if (j > 0)                    dig++;                *s++ = (char)dig;                goto ret;            }#endif            if ((j < 0) || (j == 0 && !mode#ifndef ROUND_BIASED                && !(word1(d) & 1)#endif                )) {                if (j1 > 0) {                    /* Either dig or dig+1 would work here as the least significant decimal digit.                       Use whichever would produce a decimal value closer to d. */                    b = lshift(b, 1);                    j1 = cmp(b, S);                    if (((j1 > 0) || (j1 == 0 && (dig & 1 || biasUp)))                        && (dig++ == '9'))                        goto round_9_up;                }                *s++ = (char)dig;                goto ret;            }            if (j1 > 0) {                if (dig == '9') { /* possible if i == 1 */                round_9_up:                    *s++ = '9';                    goto roundoff;                }                *s++ = dig + 1;                goto ret;            }            *s++ = (char)dig;            if (i == ilim)                break;            b = multadd(b, 10, 0);            if (mlo == mhi)                mlo = mhi = multadd(mhi, 10, 0);            else {                mlo = multadd(mlo, 10, 0);                mhi = multadd(mhi, 10, 0);            }        }    }    else        for(i = 1;; i++) {            *s++ = (char)(dig = quorem(b,S) + '0');            if (i >= ilim)                break;            b = multadd(b, 10, 0);        }    /* Round off last digit */    b = lshift(b, 1);    j = cmp(b, S);    if ((j > 0) || (j == 0 && (dig & 1 || biasUp))) {    roundoff:        while(*--s == '9')            if (s == buf) {                k++;                *s++ = '1';                goto ret;            }        ++*s++;    }    else {        /* Strip trailing zeros */        while(*--s == '0') ;        s++;    }  ret:    Bfree(S);    if (mhi) {        if (mlo && mlo != mhi)            Bfree(mlo);        Bfree(mhi);    }  ret1:    Bfree(b);    JS_ASSERT(s < buf + bufsize);    *s = '\0';    if (rve)        *rve = s;    *decpt = k + 1;    return JS_TRUE;}