JS_DELETE( nas );
free( nas );
static int dosprintf(SprintfState *ss, const char *fmt, va_list ap){    char c;    int flags, width, prec, radix, type;    union {        char ch;        int i;        long l;        JSInt64 ll;        double d;        const char *s;        int *ip;    } u;    const char *fmt0;    static char *hex = "0123456789abcdef";    static char *HEX = "0123456789ABCDEF";    char *hexp;    int rv, i;    struct NumArgState* nas = NULL;    struct NumArgState  nasArray[ NAS_DEFAULT_NUM ];    char  pattern[20];    const char* dolPt = NULL;  /* in "%4$.2f", dolPt will poiont to . */    /*    ** build an argument array, IF the fmt is numbered argument    ** list style, to contain the Numbered Argument list pointers    */    nas = BuildArgArray( fmt, ap, &rv, nasArray );    if( rv < 0 ){        /* the fmt contains error Numbered Argument format, jliu@netscape.com */        JS_ASSERT(0);        return rv;    }    while ((c = *fmt++) != 0) {        if (c != '%') {            rv = (*ss->stuff)(ss, fmt - 1, 1);            if (rv < 0) {                return rv;            }            continue;        }        fmt0 = fmt - 1;        /*        ** Gobble up the % format string. Hopefully we have handled all        ** of the strange cases!        */        flags = 0;        c = *fmt++;        if (c == '%') {            /* quoting a % with %% */            rv = (*ss->stuff)(ss, fmt - 1, 1);            if (rv < 0) {                return rv;            }            continue;        }        if( nas != NULL ){            /* the fmt contains the Numbered Arguments feature */            i = 0;            while( c && c != '$' ){         /* should imporve error check later */                i = ( i * 10 ) + ( c - '0' );                c = *fmt++;            }            if( nas[i-1].type == TYPE_UNKNOWN ){                if( nas && ( nas != nasArray ) )                    JS_DELETE( nas );                return -1;            }            ap = nas[i-1].ap;            dolPt = fmt;            c = *fmt++;        }        /*         * Examine optional flags.  Note that we do not implement the         * '#' flag of sprintf().  The ANSI C spec. of the '#' flag is         * somewhat ambiguous and not ideal, which is perhaps why         * the various sprintf() implementations are inconsistent         * on this feature.         */        while ((c == '-') || (c == '+') || (c == ' ') || (c == '0')) {            if (c == '-') flags |= FLAG_LEFT;            if (c == '+') flags |= FLAG_SIGNED;            if (c == ' ') flags |= FLAG_SPACED;            if (c == '0') flags |= FLAG_ZEROS;            c = *fmt++;        }        if (flags & FLAG_SIGNED) flags &= ~FLAG_SPACED;        if (flags & FLAG_LEFT) flags &= ~FLAG_ZEROS;        /* width */        if (c == '*') {            c = *fmt++;            width = va_arg(ap, int);        } else {            width = 0;            while ((c >= '0') && (c <= '9')) {                width = (width * 10) + (c - '0');                c = *fmt++;            }        }        /* precision */        prec = -1;        if (c == '.') {            c = *fmt++;            if (c == '*') {                c = *fmt++;                prec = va_arg(ap, int);            } else {                prec = 0;                while ((c >= '0') && (c <= '9')) {                    prec = (prec * 10) + (c - '0');                    c = *fmt++;                }            }        }        /* size */        type = TYPE_INTN;        if (c == 'h') {            type = TYPE_INT16;            c = *fmt++;        } else if (c == 'L') {            /* XXX not quite sure here */            type = TYPE_INT64;            c = *fmt++;        } else if (c == 'l') {            type = TYPE_INT32;            c = *fmt++;            if (c == 'l') {                type = TYPE_INT64;                c = *fmt++;            }        }        /* format */        hexp = hex;        switch (c) {          case 'd': case 'i':                   /* decimal/integer */            radix = 10;            goto fetch_and_convert;          case 'o':                             /* octal */            radix = 8;            type |= 1;            goto fetch_and_convert;          case 'u':                             /* unsigned decimal */            radix = 10;            type |= 1;            goto fetch_and_convert;          case 'x':                             /* unsigned hex */            radix = 16;            type |= 1;            goto fetch_and_convert;          case 'X':                             /* unsigned HEX */            radix = 16;            hexp = HEX;            type |= 1;            goto fetch_and_convert;          fetch_and_convert:            switch (type) {              case TYPE_INT16:                u.l = va_arg(ap, int);                if (u.l < 0) {                    u.l = -u.l;                    flags |= FLAG_NEG;                }                goto do_long;              case TYPE_UINT16:                u.l = va_arg(ap, int) & 0xffff;                goto do_long;              case TYPE_INTN:                u.l = va_arg(ap, int);                if (u.l < 0) {                    u.l = -u.l;                    flags |= FLAG_NEG;                }                goto do_long;              case TYPE_UINTN:                u.l = (long)va_arg(ap, unsigned int);                goto do_long;              case TYPE_INT32:                u.l = va_arg(ap, JSInt32);                if (u.l < 0) {                    u.l = -u.l;                    flags |= FLAG_NEG;                }                goto do_long;              case TYPE_UINT32:                u.l = (long)va_arg(ap, JSUint32);              do_long:                rv = cvt_l(ss, u.l, width, prec, radix, type, flags, hexp);                if (rv < 0) {                    return rv;                }                break;              case TYPE_INT64:                u.ll = va_arg(ap, JSInt64);                if (!JSLL_GE_ZERO(u.ll)) {                    JSLL_NEG(u.ll, u.ll);                    flags |= FLAG_NEG;                }                goto do_longlong;              case TYPE_UINT64:                u.ll = va_arg(ap, JSUint64);              do_longlong:                rv = cvt_ll(ss, u.ll, width, prec, radix, type, flags, hexp);                if (rv < 0) {                    return rv;                }                break;            }            break;          case 'e':          case 'E':          case 'f':          case 'g':            u.d = va_arg(ap, double);            if( nas != NULL ){                i = fmt - dolPt;                if( i < (int)sizeof( pattern ) ){                    pattern[0] = '%';                    memcpy( &pattern[1], dolPt, (size_t)i );                    rv = cvt_f(ss, u.d, pattern, &pattern[i+1] );                }            } else                rv = cvt_f(ss, u.d, fmt0, fmt);            if (rv < 0) {                return rv;            }            break;          case 'c':            u.ch = va_arg(ap, int);            if ((flags & FLAG_LEFT) == 0) {                while (width-- > 1) {                    rv = (*ss->stuff)(ss, " ", 1);                    if (rv < 0) {                        return rv;                    }                }            }            rv = (*ss->stuff)(ss, &u.ch, 1);            if (rv < 0) {                return rv;            }            if (flags & FLAG_LEFT) {                while (width-- > 1) {                    rv = (*ss->stuff)(ss, " ", 1);                    if (rv < 0) {                        return rv;                    }                }            }            break;          case 'p':            if (sizeof(void *) == sizeof(JSInt32)) {                type = TYPE_UINT32;            } else if (sizeof(void *) == sizeof(JSInt64)) {                type = TYPE_UINT64;            } else if (sizeof(void *) == sizeof(int)) {                type = TYPE_UINTN;            } else {                JS_ASSERT(0);                break;            }            radix = 16;            goto fetch_and_convert;#if 0          case 'C':          case 'S':          case 'E':          case 'G':            /* XXX not supported I suppose */            JS_ASSERT(0);            break;#endif          case 's':            u.s = va_arg(ap, const char*);            rv = cvt_s(ss, u.s, width, prec, flags);            if (rv < 0) {                return rv;            }            break;          case 'n':            u.ip = va_arg(ap, int*);            if (u.ip) {                *u.ip = ss->cur - ss->base;            }            break;          default:            /* Not a % token after all... skip it */#if 0            JS_ASSERT(0);#endif            rv = (*ss->stuff)(ss, "%", 1);            if (rv < 0) {                return rv;            }            rv = (*ss->stuff)(ss, fmt - 1, 1);            if (rv < 0) {                return rv;            }        }    }    /* Stuff trailing NUL */    rv = (*ss->stuff)(ss, "\0", 1);    if( nas && ( nas != nasArray ) ){        JS_DELETE( nas );    }    return rv;}