JS_DELETE( nas );
free( nas );
static struct NumArgState* BuildArgArray( const char *fmt, va_list ap, int* rv, struct NumArgState* nasArray ){    int number = 0, cn = 0, i;    const char* p;    char  c;    struct NumArgState* nas;    /*    **  first pass:    **  detemine how many legal % I have got, then allocate space    */    p = fmt;    *rv = 0;    i = 0;    while( ( c = *p++ ) != 0 ){        if( c != '%' )            continue;        if( ( c = *p++ ) == '%' )       /* skip %% case */            continue;        while( c != 0 ){            if( c > '9' || c < '0' ){                if( c == '$' ){         /* numbered argument csae */                    if( i > 0 ){                        *rv = -1;                        return NULL;                    }                    number++;                } else {                /* non-numbered argument case */                    if( number > 0 ){                        *rv = -1;                        return NULL;                    }                    i = 1;                }                break;            }            c = *p++;        }    }    if( number == 0 ){        return NULL;    }    if( number > NAS_DEFAULT_NUM ){        nas = (struct NumArgState*)malloc( number * sizeof( struct NumArgState ) );        if( !nas ){            *rv = -1;            return NULL;        }    } else {        nas = nasArray;    }    for( i = 0; i < number; i++ ){        nas[i].type = TYPE_UNKNOWN;    }    /*    ** second pass:    ** set nas[].type    */    p = fmt;    while( ( c = *p++ ) != 0 ){        if( c != '%' )  continue;            c = *p++;        if( c == '%' )  continue;        cn = 0;        while( c && c != '$' ){     /* should imporve error check later */            cn = cn*10 + c - '0';            c = *p++;        }        if( !c || cn < 1 || cn > number ){            *rv = -1;            break;        }        /* nas[cn] starts from 0, and make sure nas[cn].type is not assigned */        cn--;        if( nas[cn].type != TYPE_UNKNOWN )            continue;        c = *p++;        /* width */        if (c == '*') {            /* not supported feature, for the argument is not numbered */            *rv = -1;            break;        }        while ((c >= '0') && (c <= '9')) {            c = *p++;        }        /* precision */        if (c == '.') {            c = *p++;            if (c == '*') {                /* not supported feature, for the argument is not numbered */                *rv = -1;                break;            }            while ((c >= '0') && (c <= '9')) {                c = *p++;            }        }        /* size */        nas[cn].type = TYPE_INTN;        if (c == 'h') {            nas[cn].type = TYPE_INT16;            c = *p++;        } else if (c == 'L') {            /* XXX not quite sure here */            nas[cn].type = TYPE_INT64;            c = *p++;        } else if (c == 'l') {            nas[cn].type = TYPE_INT32;            c = *p++;            if (c == 'l') {                nas[cn].type = TYPE_INT64;                c = *p++;            }        }        /* format */        switch (c) {        case 'd':        case 'c':        case 'i':        case 'o':        case 'u':        case 'x':        case 'X':            break;        case 'e':        case 'f':        case 'g':            nas[ cn ].type = TYPE_DOUBLE;            break;        case 'p':            /* XXX should use cpp */            if (sizeof(void *) == sizeof(JSInt32)) {                nas[ cn ].type = TYPE_UINT32;            } else if (sizeof(void *) == sizeof(JSInt64)) {                nas[ cn ].type = TYPE_UINT64;            } else if (sizeof(void *) == sizeof(JSIntn)) {                nas[ cn ].type = TYPE_UINTN;            } else {                nas[ cn ].type = TYPE_UNKNOWN;            }            break;        case 'C':        case 'S':        case 'E':        case 'G':            /* XXX not supported I suppose */            JS_ASSERT(0);            nas[ cn ].type = TYPE_UNKNOWN;            break;        case 's':            nas[ cn ].type = TYPE_STRING;            break;        case 'n':            nas[ cn ].type = TYPE_INTSTR;            break;        default:            JS_ASSERT(0);            nas[ cn ].type = TYPE_UNKNOWN;            break;        }        /* get a legal para. */        if( nas[ cn ].type == TYPE_UNKNOWN ){            *rv = -1;            break;        }    }    /*    ** third pass    ** fill the nas[cn].ap    */    if( *rv < 0 ){        if( nas != nasArray )            JS_DELETE( nas );        return NULL;    }    cn = 0;    while( cn < number ){        if( nas[cn].type == TYPE_UNKNOWN ){            cn++;            continue;        }        VARARGS_ASSIGN(nas[cn].ap, ap);        switch( nas[cn].type ){        case TYPE_INT16:        case TYPE_UINT16:        case TYPE_INTN:        case TYPE_UINTN:                (void)va_arg( ap, JSIntn );             break;        case TYPE_INT32:                (void)va_arg( ap, JSInt32 );            break;        case TYPE_UINT32:       (void)va_arg( ap, JSUint32 );   break;        case TYPE_INT64:        (void)va_arg( ap, JSInt64 );            break;        case TYPE_UINT64:       (void)va_arg( ap, JSUint64 );           break;        case TYPE_STRING:       (void)va_arg( ap, char* );              break;        case TYPE_INTSTR:       (void)va_arg( ap, JSIntn* );            break;        case TYPE_DOUBLE:       (void)va_arg( ap, double );             break;        default:            if( nas != nasArray )                JS_DELETE( nas );            *rv = -1;            return NULL;        }        cn++;    }    return nas;}