RELEASE_DTOA_LOCK();
JS_dtobasestr(int base, double d){    char *buffer;        /* The output string */    char *p;             /* Pointer to current position in the buffer */    char *pInt;          /* Pointer to the beginning of the integer part of the string */    char *q;    uint32 digit;    double di;           /* d truncated to an integer */    double df;           /* The fractional part of d */    JS_ASSERT(base >= 2 && base <= 36);    buffer = (char*) malloc(DTOBASESTR_BUFFER_SIZE);    if (buffer) {        p = buffer;        if (d < 0.0#ifdef XP_PC            && !((word0(d) & Exp_mask) == Exp_mask && ((word0(d) & Frac_mask) || word1(d))) /* Visual C++ doesn't know how to compare against NaN */#endif           ) {            *p++ = '-';            d = -d;        }        /* Check for Infinity and NaN */        if ((word0(d) & Exp_mask) == Exp_mask) {            strcpy(p, !word1(d) && !(word0(d) & Frac_mask) ? "Infinity" : "NaN");            return buffer;        }        /* Output the integer part of d with the digits in reverse order. */        pInt = p;        di = fd_floor(d);        if (di <= 4294967295.0) {            uint32 n = (uint32)di;            if (n)                do {                    uint32 m = n / base;                    digit = n - m*base;                    n = m;                    JS_ASSERT(digit < (uint32)base);                    *p++ = BASEDIGIT(digit);                } while (n);            else *p++ = '0';        } else {            /* XXX We really should check for null here, but none of the routines we call is out-of-memory-safe,             * so this change would need to be made pervasively in this file. */            int32 e;            int32 bits;  /* Number of significant bits in di; not used. */            Bigint *b = d2b(di, &e, &bits);            b = lshift(b, e);            do {                digit = divrem(b, base);                JS_ASSERT(digit < (uint32)base);                *p++ = BASEDIGIT(digit);            } while (b->wds);            Bfree(b);        }        /* Reverse the digits of the integer part of d. */        q = p-1;        while (q > pInt) {            char ch = *pInt;            *pInt++ = *q;            *q-- = ch;        }                df = d - di;        if (df != 0.0) {            /* We have a fraction. */            int32 e, bbits, s2, done;            Bigint *b, *s, *mlo, *mhi;                        *p++ = '.';            b = d2b(df, &e, &bbits);            JS_ASSERT(e < 0);            /* At this point df = b * 2^e.  e must be less than zero because 0 < df < 1. */                        s2 = -(int32)(word0(d) >> Exp_shift1 & Exp_mask>>Exp_shift1);#ifndef Sudden_Underflow            if (!s2)                s2 = -1;#endif            s2 += Bias + P;            /* 1/2^s2 = (nextDouble(d) - d)/2 */            JS_ASSERT(-s2 < e);            mlo = i2b(1);            mhi = mlo;            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 output string's value is less than d.  */                s2 += Log2P;                mhi = i2b(1<<Log2P);            }            b = lshift(b, e + s2);            s = i2b(1);            s = lshift(s, s2);            /* At this point we have the following:             *   s = 2^s2;             *   1 > df = b/2^s2 > 0;             *   (d - prevDouble(d))/2 = mlo/2^s2;             *   (nextDouble(d) - d)/2 = mhi/2^s2. */            done = JS_FALSE;            do {                int32 j, j1;                Bigint *delta;                b = multadd(b, base, 0);                digit = quorem2(b, s2);                if (mlo == mhi)                    mlo = mhi = multadd(mlo, base, 0);                else {                    mlo = multadd(mlo, base, 0);                    mhi = multadd(mhi, base, 0);                }                /* Do we yet have the shortest string that will round to d? */                j = cmp(b, mlo);                /* j is b/2^s2 compared with mlo/2^s2. */                delta = diff(s, mhi);                j1 = delta->sign ? 1 : cmp(b, delta);                Bfree(delta);                /* j1 is b/2^s2 compared with 1 - mhi/2^s2. */#ifndef ROUND_BIASED                if (j1 == 0 && !(word1(d) & 1)) {                    if (j > 0)                        digit++;                    done = JS_TRUE;                } else#endif                if (j < 0 || (j == 0#ifndef ROUND_BIASED                    && !(word1(d) & 1)#endif                    )) {                    if (j1 > 0) {                        /* Either dig or dig+1 would work here as the least significant digit.                           Use whichever would produce an output value closer to d. */                        b = lshift(b, 1);                        j1 = cmp(b, s);                        if (j1 > 0) /* The even test (|| (j1 == 0 && (digit & 1))) is not here because it messes up odd base output                                     * such as 3.5 in base 3.  */                            digit++;                    }                    done = JS_TRUE;                } else if (j1 > 0) {                    digit++;                    done = JS_TRUE;                }                JS_ASSERT(digit < (uint32)base);                *p++ = BASEDIGIT(digit);            } while (!done);            Bfree(b);            Bfree(s);            if (mlo != mhi)                Bfree(mlo);            Bfree(mhi);        }        JS_ASSERT(p < buffer + DTOBASESTR_BUFFER_SIZE);        *p = '\0';    }    return buffer;}