RELEASE_DTOA_LOCK();
JS_strtod(CONST char *s00, char **se, int *err){    int32 scale;    int32 bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,        e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;    CONST char *s, *s0, *s1;    double aadj, aadj1, adj, rv, rv0;    Long L;    ULong y, z;    Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;#ifdef JS_THREADSAFE    if (!initialized) InitDtoa();#endif    *err = 0;	bb = bd = bs = delta = NULL;    sign = nz0 = nz = 0;    rv = 0.;    for(s = s00;;s++) switch(*s) {    case '-':        sign = 1;        /* no break */    case '+':        if (*++s)            goto break2;        /* no break */    case 0:        s = s00;        goto ret;    case '\t':    case '\n':    case '\v':    case '\f':    case '\r':    case ' ':        continue;    default:        goto break2;    }break2:    if (*s == '0') {        nz0 = 1;        while(*++s == '0') ;        if (!*s)            goto ret;    }    s0 = s;    y = z = 0;    for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)        if (nd < 9)            y = 10*y + c - '0';        else if (nd < 16)            z = 10*z + c - '0';    nd0 = nd;    if (c == '.') {        c = *++s;        if (!nd) {            for(; c == '0'; c = *++s)                nz++;            if (c > '0' && c <= '9') {                s0 = s;                nf += nz;                nz = 0;                goto have_dig;            }            goto dig_done;        }        for(; c >= '0' && c <= '9'; c = *++s) {        have_dig:            nz++;            if (c -= '0') {                nf += nz;                for(i = 1; i < nz; i++)                    if (nd++ < 9)                        y *= 10;                    else if (nd <= DBL_DIG + 1)                        z *= 10;                if (nd++ < 9)                    y = 10*y + c;                else if (nd <= DBL_DIG + 1)                    z = 10*z + c;                nz = 0;            }        }    }dig_done:    e = 0;    if (c == 'e' || c == 'E') {        if (!nd && !nz && !nz0) {            s = s00;            goto ret;        }        s00 = s;        esign = 0;        switch(c = *++s) {        case '-':            esign = 1;        case '+':            c = *++s;        }        if (c >= '0' && c <= '9') {            while(c == '0')                c = *++s;            if (c > '0' && c <= '9') {                L = c - '0';                s1 = s;                while((c = *++s) >= '0' && c <= '9')                    L = 10*L + c - '0';                if (s - s1 > 8 || L > 19999)                    /* Avoid confusion from exponents                     * so large that e might overflow.                     */                    e = 19999; /* safe for 16 bit ints */                else                    e = (int32)L;                if (esign)                    e = -e;            }            else                e = 0;        }        else            s = s00;    }    if (!nd) {        if (!nz && !nz0) {#ifdef INFNAN_CHECK            /* Check for Nan and Infinity */            switch(c) {              case 'i':              case 'I':                if (match(&s,"nfinity")) {                    word0(rv) = 0x7ff00000;                    word1(rv) = 0;                    goto ret;                    }                break;              case 'n':              case 'N':                if (match(&s, "an")) {                    word0(rv) = NAN_WORD0;                    word1(rv) = NAN_WORD1;                    goto ret;                    }              }#endif /* INFNAN_CHECK */            s = s00;            }        goto ret;    }    e1 = e -= nf;    /* Now we have nd0 digits, starting at s0, followed by a     * decimal point, followed by nd-nd0 digits.  The number we're     * after is the integer represented by those digits times     * 10**e */    if (!nd0)        nd0 = nd;    k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;    rv = y;    if (k > 9)        rv = tens[k - 9] * rv + z;    bd0 = 0;    if (nd <= DBL_DIG#ifndef RND_PRODQUOT        && FLT_ROUNDS == 1#endif        ) {        if (!e)            goto ret;        if (e > 0) {            if (e <= Ten_pmax) {                /* rv = */ rounded_product(rv, tens[e]);                goto ret;            }            i = DBL_DIG - nd;            if (e <= Ten_pmax + i) {                /* A fancier test would sometimes let us do                 * this for larger i values.                 */                e -= i;                rv *= tens[i];                /* rv = */ rounded_product(rv, tens[e]);                goto ret;            }        }#ifndef Inaccurate_Divide        else if (e >= -Ten_pmax) {            /* rv = */ rounded_quotient(rv, tens[-e]);            goto ret;        }#endif    }    e1 += nd - k;    scale = 0;    /* Get starting approximation = rv * 10**e1 */    if (e1 > 0) {        if ((i = e1 & 15) != 0)            rv *= tens[i];        if (e1 &= ~15) {            if (e1 > DBL_MAX_10_EXP) {            ovfl:                *err = ERANGE;#ifdef __STDC__                rv = HUGE_VAL;#else                /* Can't trust HUGE_VAL */                word0(rv) = Exp_mask;                word1(rv) = 0;#endif                if (bd0)                    goto retfree;                goto ret;            }            e1 >>= 4;            for(j = 0; e1 > 1; j++, e1 >>= 1)                if (e1 & 1)                    rv *= bigtens[j];            /* The last multiplication could overflow. */            set_word0(rv, word0(rv) - P*Exp_msk1);            rv *= bigtens[j];            if ((z = word0(rv) & Exp_mask) > Exp_msk1*(DBL_MAX_EXP+Bias-P))                goto ovfl;            if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {                /* set to largest number */                /* (Can't trust DBL_MAX) */                set_word0(rv, Big0);                set_word1(rv, Big1);                }            else                set_word0(rv, word0(rv) + P*Exp_msk1);            }    }    else if (e1 < 0) {        e1 = -e1;        if ((i = e1 & 15) != 0)            rv /= tens[i];        if (e1 &= ~15) {            e1 >>= 4;            if (e1 >= 1 << n_bigtens)                goto undfl;#ifdef Avoid_Underflow            if (e1 & Scale_Bit)                scale = P;            for(j = 0; e1 > 0; j++, e1 >>= 1)                if (e1 & 1)                    rv *= tinytens[j];            if (scale && (j = P + 1 - ((word0(rv) & Exp_mask)                        >> Exp_shift)) > 0) {                /* scaled rv is denormal; zap j low bits */                if (j >= 32) {                    set_word1(rv, 0);                    set_word0(rv, word0(rv) & (0xffffffff << (j-32)));                    if (!word0(rv))                        set_word0(rv, 1);                    }                else                    set_word1(rv, word1(rv) & (0xffffffff << j));                }#else            for(j = 0; e1 > 1; j++, e1 >>= 1)                if (e1 & 1)                    rv *= tinytens[j];            /* The last multiplication could underflow. */            rv0 = rv;            rv *= tinytens[j];            if (!rv) {                rv = 2.*rv0;                rv *= tinytens[j];#endif                if (!rv) {                undfl:                    rv = 0.;                    *err = ERANGE;                    if (bd0)                        goto retfree;                    goto ret;                }#ifndef Avoid_Underflow                set_word0(rv, Tiny0);                set_word1(rv, Tiny1);                /* The refinement below will clean                 * this approximation up.                 */            }#endif        }    }    /* Now the hard part -- adjusting rv to the correct value.*/    /* Put digits into bd: true value = bd * 10^e */    bd0 = s2b(s0, nd0, nd, y);    for(;;) {        bd = Balloc(bd0->k);        Bcopy(bd, bd0);        bb = d2b(rv, &bbe, &bbbits);    /* rv = bb * 2^bbe */        bs = i2b(1);        if (e >= 0) {            bb2 = bb5 = 0;            bd2 = bd5 = e;        }        else {            bb2 = bb5 = -e;            bd2 = bd5 = 0;        }        if (bbe >= 0)            bb2 += bbe;        else            bd2 -= bbe;        bs2 = bb2;#ifdef Sudden_Underflow        j = P + 1 - bbbits;#else#ifdef Avoid_Underflow        j = bbe - scale;#else        j = bbe;#endif        i = j + bbbits - 1; /* logb(rv) */        if (i < Emin)   /* denormal */            j += P - Emin;        else            j = P + 1 - bbbits;#endif        bb2 += j;        bd2 += j;#ifdef Avoid_Underflow        bd2 += scale;#endif        i = bb2 < bd2 ? bb2 : bd2;        if (i > bs2)            i = bs2;        if (i > 0) {            bb2 -= i;            bd2 -= i;            bs2 -= i;        }        if (bb5 > 0) {            bs = pow5mult(bs, bb5);            bb1 = mult(bs, bb);            Bfree(bb);            bb = bb1;        }        if (bb2 > 0)            bb = lshift(bb, bb2);        if (bd5 > 0)            bd = pow5mult(bd, bd5);        if (bd2 > 0)            bd = lshift(bd, bd2);        if (bs2 > 0)            bs = lshift(bs, bs2);        delta = diff(bb, bd);        dsign = delta->sign;        delta->sign = 0;        i = cmp(delta, bs);        if (i < 0) {            /* Error is less than half an ulp -- check for             * special case of mantissa a power of two.             */            if (dsign || word1(rv) || word0(rv) & Bndry_mask#ifdef Avoid_Underflow             || (word0(rv) & Exp_mask) <= Exp_msk1 + P*Exp_msk1#else             || (word0(rv) & Exp_mask) <= Exp_msk1#endif                ) {#ifdef Avoid_Underflow                if (!delta->x[0] && delta->wds == 1)                    dsign = 2;#endif                break;                }            delta = lshift(delta,Log2P);            if (cmp(delta, bs) > 0)                goto drop_down;            break;        }        if (i == 0) {            /* exactly half-way between */            if (dsign) {                if ((word0(rv) & Bndry_mask1) == Bndry_mask1                    &&  word1(rv) == 0xffffffff) {                    /*boundary case -- increment exponent*/                    set_word0(rv, (word0(rv) & Exp_mask) + Exp_msk1);                    set_word1(rv, 0);#ifdef Avoid_Underflow                    dsign = 0;#endif                    break;                }            }            else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {#ifdef Avoid_Underflow                dsign = 2;#endif            drop_down:                /* boundary case -- decrement exponent */#ifdef Sudden_Underflow                L = word0(rv) & Exp_mask;                if (L <= Exp_msk1)                    goto undfl;                L -= Exp_msk1;#else                L = (word0(rv) & Exp_mask) - Exp_msk1;#endif                set_word0(rv, L | Bndry_mask1);                set_word1(rv, 0xffffffff);                break;            }#ifndef ROUND_BIASED            if (!(word1(rv) & LSB))                break;#endif            if (dsign)                rv += ulp(rv);#ifndef ROUND_BIASED            else {                rv -= ulp(rv);#ifndef Sudden_Underflow                if (!rv)                    goto undfl;#endif            }#ifdef Avoid_Underflow            dsign = 1 - dsign;#endif#endif            break;        }        if ((aadj = ratio(delta, bs)) <= 2.) {            if (dsign)                aadj = aadj1 = 1.;            else if (word1(rv) || word0(rv) & Bndry_mask) {#ifndef Sudden_Underflow                if (word1(rv) == Tiny1 && !word0(rv))                    goto undfl;#endif                aadj = 1.;                aadj1 = -1.;            }            else {                /* special case -- power of FLT_RADIX to be */                /* rounded down... */                if (aadj < 2./FLT_RADIX)                    aadj = 1./FLT_RADIX;                else                    aadj *= 0.5;                aadj1 = -aadj;            }        }        else {            aadj *= 0.5;            aadj1 = dsign ? aadj : -aadj;#ifdef Check_FLT_ROUNDS            switch(FLT_ROUNDS) {            case 2: /* towards +infinity */                aadj1 -= 0.5;                break;            case 0: /* towards 0 */            case 3: /* towards -infinity */                aadj1 += 0.5;            }#else            if (FLT_ROUNDS == 0)                aadj1 += 0.5;#endif        }        y = word0(rv) & Exp_mask;        /* Check for overflow */        if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {            rv0 = rv;            set_word0(rv, word0(rv) - P*Exp_msk1);            adj = aadj1 * ulp(rv);            rv += adj;            if ((word0(rv) & Exp_mask) >=                Exp_msk1*(DBL_MAX_EXP+Bias-P)) {                if (word0(rv0) == Big0 && word1(rv0) == Big1)                    goto ovfl;                set_word0(rv, Big0);                set_word1(rv, Big1);                goto cont;            }            else                set_word0(rv, word0(rv) + P*Exp_msk1);        }        else {#ifdef Sudden_Underflow            if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {                rv0 = rv;                set_word0(rv, word0(rv) + P*Exp_msk1);                adj = aadj1 * ulp(rv);                rv += adj;                    if ((word0(rv) & Exp_mask) <= P*Exp_msk1)                        {                            if (word0(rv0) == Tiny0                                && word1(rv0) == Tiny1)                                goto undfl;                            set_word0(rv, Tiny0);                            set_word1(rv, Tiny1);                            goto cont;                        }                    else                        set_word0(rv, word0(rv) - P*Exp_msk1);            }            else {                adj = aadj1 * ulp(rv);                rv += adj;            }#else            /* Compute adj so that the IEEE rounding rules will             * correctly round rv + adj in some half-way cases.             * If rv * ulp(rv) is denormalized (i.e.,             * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid             * trouble from bits lost to denormalization;             * example: 1.2e-307 .             */#ifdef Avoid_Underflow            if (y <= P*Exp_msk1 && aadj > 1.)#else            if (y <= (P-1)*Exp_msk1 && aadj > 1.)#endif                {                aadj1 = (double)(int32)(aadj + 0.5);                if (!dsign)                    aadj1 = -aadj1;            }#ifdef Avoid_Underflow            if (scale && y <= P*Exp_msk1)                set_word0(aadj1, word0(aadj1) + (P+1)*Exp_msk1 - y);#endif            adj = aadj1 * ulp(rv);            rv += adj;#endif        }        z = word0(rv) & Exp_mask;#ifdef Avoid_Underflow        if (!scale)#endif        if (y == z) {            /* Can we stop now? */            L = (Long)aadj;            aadj -= L;            /* The tolerances below are conservative. */            if (dsign || word1(rv) || word0(rv) & Bndry_mask) {                if (aadj < .4999999 || aadj > .5000001)                    break;            }            else if (aadj < .4999999/FLT_RADIX)                break;        }    cont:        Bfree(bb);        Bfree(bd);        Bfree(bs);        Bfree(delta);    }#ifdef Avoid_Underflow    if (scale) {        set_word0(rv0, Exp_1 - P*Exp_msk1);        set_word1(rv0, 0);        if ((word0(rv) & Exp_mask) <= P*Exp_msk1              && word1(rv) & 1              && dsign != 2) {            if (dsign) {#ifdef Sudden_Underflow                /* rv will be 0, but this would give the  */                /* right result if only rv *= rv0 worked. */                set_word0(rv, word0(rv) + P*Exp_msk1);                set_word0(rv0, Exp_1 - 2*P*Exp_msk1);#endif                rv += ulp(rv);                }            else                set_word1(rv, word1(rv) & ~1);        }        rv *= rv0;    }#endif /* Avoid_Underflow */retfree:    Bfree(bb);    Bfree(bd);    Bfree(bs);    Bfree(bd0);    Bfree(delta);ret:    if (se)        *se = (char *)s;    return sign ? -rv : rv;}