Esempio n. 1
0
unsigned char *ws_utf8_to_latin1(const WsUtf8String *string,
                                 unsigned char unknown_char,
                                 size_t *len_return)
{
    unsigned char *cstr;
    size_t i;
    size_t pos = 0;

    if (string == NULL)
        return NULL;

    cstr = ws_malloc(string->num_chars + 1);
    if (cstr == NULL)
        return NULL;

    for (i = 0; i < string->num_chars; i++) {
        unsigned long ch;

        if (!ws_utf8_get_char(string, &ch, &pos))
            ws_fatal("ws_utf8_to_latin1_cstr(): internal inconsistency");

        if (ch > 0xff)
            cstr[i] = unknown_char;
        else
            cstr[i] = (unsigned char) ch;
    }

    cstr[i] = '\0';

    if (len_return)
        *len_return = string->num_chars;

    return cstr;
}
Esempio n. 2
0
int ws_utf8_append_char(WsUtf8String *string, unsigned long ch)
{
    unsigned char *d;
    unsigned int num_bytes = WS_UTF8_ENC_TYPE(ch);
    unsigned int len, i;

    if (num_bytes == 0)
        ws_fatal("ws_utf8_append_char(): 0x%lx is not a valid UTF-8 character",
                 ch);

    d = ws_realloc(string->data, string->len + num_bytes);
    if (d == NULL)
        return 0;

    len = string->len;

    /* Encode the continuation bytes (n > 1). */
    for (i = num_bytes - 1; i > 0; i--) {
        d[len + i] = WS_UTF8_ENC_C_BITS;
        d[len + i] |= ch & WS_UTF8_CONT_DATA_MASK;
        ch >>= 6;
    }

    /* And continue the first byte. */
    d[len] = utf8_hibits[num_bytes];
    d[len] |= ch;

    string->data = d;
    string->len += num_bytes;
    string->num_chars++;

    return 1;
}
Esempio n. 3
0
static void remove_block(WsMemBlockHdr *b)
{
    if (b->magic != MAGIC)
        ws_fatal("remove_block(): invalid magic\n");

    if (b->next)
        b->next->prev = b->prev;
    if (b->prev)
        b->prev->next = b->next;
    else
        blocks = b->next;

    balance -= b->size;
    num_blocks--;

    memset(b, 0xfe, SIZE(b->size));
}
Esempio n. 4
0
File: ws.c Progetto: markjeee/kannel
void ws_lexer_free_block(WsCompiler *compiler, void *ptr)
{
    int i;

    if (ptr == NULL)
        return;

    for (i = compiler->lexer_active_list_size - 1; i >= 0; i--) {
        if (compiler->lexer_active_list[i] == ptr) {
            memmove(&compiler->lexer_active_list[i],
                    &compiler->lexer_active_list[i + 1],
                    (compiler->lexer_active_list_size - i - 1) * sizeof(void *));
            compiler->lexer_active_list_size--;

            ws_free(ptr);
            return;
        }
    }

    ws_fatal("ws_lexer_free_block(): unknown block 0x%lx",
             (unsigned long) ptr);
}
Esempio n. 5
0
void ws_expr_linearize(WsCompiler *compiler, WsExpression *expr)
{
    WsListItem *li;
    WsAsmIns *ins;

    switch (expr->type) {
    case WS_EXPR_COMMA:
        /* Linearize left. */
        ws_expr_linearize(compiler, expr->u.comma.left);

        /* Pop its result. */
        ws_asm_link(compiler, ws_asm_ins(compiler, expr->line, WS_ASM_POP));

        /* Linearize right */
        ws_expr_linearize(compiler, expr->u.comma.right);
        break;

    case WS_EXPR_ASSIGN:
        {
            WsNamespace *ns = ws_variable_lookup(compiler,
                                                 expr->u.assign.identifier);

            if (ns == NULL) {
                /* Unknown identifier. */
                ws_src_error(compiler, expr->line, "unknown variable `%s'",
                             expr->u.symbol);
                return;
            }

            if (expr->u.assign.op == '=') {
                /* Evaluate the expression. */
                ws_expr_linearize(compiler, expr->u.assign.expr);

                /* Store the value to the variable. */
                ws_asm_link(compiler,
                            ws_asm_variable(compiler, expr->line,
                                            WS_ASM_P_STORE_VAR, ns->vindex));
            } else if (expr->u.assign.op == tADDA) {
                /* Linearize the expression. */
                ws_expr_linearize(compiler, expr->u.assign.expr);

                /* Add it to the variable. */
                ws_asm_link(compiler,
                            ws_asm_variable(compiler, expr->line,
                                            WS_ASM_ADD_ASG, ns->vindex));
            } else if (expr->u.assign.op == tSUBA) {
                /* Linearize the expression. */
                ws_expr_linearize(compiler, expr->u.assign.expr);

                /* Substract it from the variable. */
                ws_asm_link(compiler,
                            ws_asm_variable(compiler, expr->line,
                                            WS_ASM_SUB_ASG, ns->vindex));
            } else {
                /* Load the old value from the variable. */
                ws_asm_link(compiler,
                            ws_asm_variable(compiler, expr->line,
                                            WS_ASM_P_LOAD_VAR, ns->vindex));

                /* Evaluate the expression. */
                ws_expr_linearize(compiler, expr->u.assign.expr);

                /* Perform the operand. */
                ins = NULL;
                switch (expr->u.assign.op) {
                case tMULA:
                    ins = ws_asm_ins(compiler, expr->line, WS_ASM_MUL);
                    break;

                case tDIVA:
                    ins = ws_asm_ins(compiler, expr->line, WS_ASM_DIV);
                    break;

                case tREMA:
                    ins = ws_asm_ins(compiler, expr->line, WS_ASM_REM);
                    break;

                case tADDA:
                    ins = ws_asm_ins(compiler, expr->line, WS_ASM_ADD);
                    break;

                case tSUBA:
                    ins = ws_asm_ins(compiler, expr->line, WS_ASM_SUB);
                    break;

                case tLSHIFTA:
                    ins = ws_asm_ins(compiler, expr->line, WS_ASM_B_LSHIFT);
                    break;

                case tRSSHIFTA:
                    ins = ws_asm_ins(compiler, expr->line, WS_ASM_B_RSSHIFT);
                    break;

                case tRSZSHIFTA:
                    ins = ws_asm_ins(compiler, expr->line, WS_ASM_B_RSZSHIFT);
                    break;

                case tANDA:
                    ins = ws_asm_ins(compiler, expr->line, WS_ASM_B_AND);
                    break;

                case tXORA:
                    ins = ws_asm_ins(compiler, expr->line, WS_ASM_B_XOR);
                    break;

                case tORA:
                    ins = ws_asm_ins(compiler, expr->line, WS_ASM_B_OR);
                    break;

                case tIDIVA:
                    ins = ws_asm_ins(compiler, expr->line, WS_ASM_IDIV);
                    break;

                default:
                    ws_fatal("ws_expr_linearize(): unknown assignment operand %x",
                             expr->u.assign.op);
                    break;
                }
                ws_asm_link(compiler, ins);

                /* Store the value to the variable. */
                ws_asm_link(compiler,
                            ws_asm_variable(compiler, expr->line,
                                            WS_ASM_P_STORE_VAR, ns->vindex));
            }
            /* The value of the assignment expression is the value
               assigned.  So, we must load the value from the variable.
               This would also be a good place for the `dup' operand but
               we lose since we don't have it. */
            ws_asm_link(compiler, ws_asm_variable(compiler, expr->line,
                                                  WS_ASM_P_LOAD_VAR, ns->vindex));
        }
        break;

    case WS_EXPR_CONDITIONAL:
        {
            WsAsmIns *l_else = ws_asm_label(compiler, expr->line);
            WsAsmIns *l_end = ws_asm_label(compiler, expr->line);

            /* Linearize condition. */
            ws_expr_linearize(compiler, expr->u.conditional.e_cond);

            /* If the result if false, jump to the else-branch. */
            ws_asm_link(compiler, ws_asm_branch(compiler, expr->line,
                                                WS_ASM_P_TJUMP, l_else));

            /* Linearize the then-expression and jump out. */
            ws_expr_linearize(compiler, expr->u.conditional.e_then);
            ws_asm_link(compiler, ws_asm_branch(compiler, expr->line,
                                                WS_ASM_P_JUMP, l_end));

            /* The else-branch. */
            ws_asm_link(compiler, l_else);
            ws_expr_linearize(compiler, expr->u.conditional.e_else);

            /* Insert the end label. */
            ws_asm_link(compiler, l_end);
        }
        break;

    case WS_EXPR_LOGICAL:
        {
            WsAsmIns *l_out = ws_asm_label(compiler, expr->line);

            /* Linearize the left-hand size expression. */
            ws_expr_linearize(compiler, expr->u.logical.left);

            /* Short-circuit check.  The type of the logical expression is
                      the short-circuit byte-code operand. */
            ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
                                             expr->u.logical.type));
            ws_asm_link(compiler, ws_asm_branch(compiler, expr->line,
                                                WS_ASM_P_TJUMP, l_out));

            /* Linearize the right-hand size expression. */
            ws_expr_linearize(compiler, expr->u.logical.right);

            /* The result of a logical expression should be boolean.
             * Control statements do automatic conversion, but typeof()
	     * does not. */
            ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
                                         WS_ASM_TOBOOL));

            /* Insert the end label. */
            ws_asm_link(compiler, l_out);
        }
        break;

    case WS_EXPR_BINARY:
        /* Linearize left and right. */
        ws_expr_linearize(compiler, expr->u.binary.left);
        ws_expr_linearize(compiler, expr->u.binary.right);

        /* The type of the binary expression is the byte-code opcode. */
        ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
                                         expr->u.binary.type));
        break;

    case WS_EXPR_UNARY:
        /* Linearize the expression. */
        ws_expr_linearize(compiler, expr->u.unary.expr);

        /* The type of the unary expression is the byte-code opcode. */
        ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
                                         expr->u.unary.type));
        break;

    case WS_EXPR_UNARY_VAR:
        {
            WsNamespace *ns = ws_variable_lookup(compiler,
                                                 expr->u.unary_var.variable);
            if (ns == NULL) {
                /* An unknown identifier. */
                ws_src_error(compiler, expr->line, "unknown variable `%s'",
                             expr->u.unary_var.variable);
                return;
            }

            /* First, do the operation. */
            if (expr->u.unary_var.addp)
                ws_asm_link(compiler,
                            ws_asm_variable(compiler, expr->line, WS_ASM_P_INCR_VAR,
                                            ns->vindex));
            else
                ws_asm_link(compiler,
                            ws_asm_variable(compiler, expr->line, WS_ASM_DECR_VAR,
                                            ns->vindex));

            /* Second, load the new value of the variable. */
            ws_asm_link(compiler, ws_asm_variable(compiler, expr->line,
                                                  WS_ASM_P_LOAD_VAR, ns->vindex));
        }
        break;

    case WS_EXPR_POSTFIX_VAR:
        {
            WsNamespace *ns = ws_variable_lookup(compiler,
                                                 expr->u.postfix_var.variable);
            if (ns == NULL) {
                /* An unknown identifier. */
                ws_src_error(compiler, expr->line, "unknown variable `%s'",
                             expr->u.postfix_var.variable);
                return;
            }

            /* First, load the old value of the variable. */
            ws_asm_link(compiler, ws_asm_variable(compiler, expr->line,
                                                  WS_ASM_P_LOAD_VAR, ns->vindex));

            /* Second, do the operation. */
            if (expr->u.unary_var.addp)
                ws_asm_link(compiler,
                            ws_asm_variable(compiler, expr->line, WS_ASM_P_INCR_VAR,
                                            ns->vindex));
            else
                ws_asm_link(compiler,
                            ws_asm_variable(compiler, expr->line, WS_ASM_DECR_VAR,
                                            ns->vindex));
        }
        break;

    case WS_EXPR_CALL:
        /* First, evaluate the arguments. */
        for (li = expr->u.call.arguments->head; li; li = li->next)
            ws_expr_linearize(compiler, li->data);

        /* Second, emit the call instruction. */
        switch (expr->u.call.type) {
        case ' ': 		/* LocalScriptFunctionCall */
            {
                WsFunctionHash *f = ws_function_hash(compiler, expr->u.call.name);

                if (f == NULL || !f->defined)
                {
                    ws_src_error(compiler, expr->line,
                                 "unknown local function `%s'",
                                 expr->u.call.name);
                    return;
                }

                /* Check that the function is called with correct amount
                          of arguments. */
                if (expr->u.call.arguments->num_items
                    != compiler->functions[f->findex].params->num_items)
                {
                    ws_src_error(compiler, expr->line,
                                 "invalid amount of arguments for `%s': "
                                 "expected %u, got %u",
                                 expr->u.call.name,
                                 compiler->functions[f->findex].params->num_items,
                                 expr->u.call.arguments->num_items);
                    return;
                }

                /* Emit assembler. */
                ws_asm_link(compiler, ws_asm_call(compiler, expr->line,
                                                  f->findex));
            }
            break;

        case '#': 		/* ExternalScriptFunctionCall */
            {
                WsPragmaUse *use = ws_hash_get(compiler->pragma_use_hash,
                                               expr->u.call.base);
                WsUInt16 findex;

                if (use == NULL)
                {
                    ws_src_error(compiler, expr->line,
                                 "unknown external compilation unit `%s'",
                                 expr->u.call.base);
                    return;
                }

                /* Insert the function name to the byte-code pool. */
                if (!ws_bc_add_const_utf8_string(
                        compiler->bc, &findex,
                        (unsigned char *) expr->u.call.name,
                        strlen(expr->u.call.name)))
                {
                    ws_error_memory(compiler);
                    return;
                }

                /* Emit assembler. */
                ws_asm_link(compiler,
                            ws_asm_call_url(compiler, expr->line,
                                            findex, use->urlindex,
                                            expr->u.call.arguments->num_items));
            }
            break;

        case '.': 		/* LibraryFunctionCall */
            {
                WsUInt16 lindex;
                WsUInt8 findex;
                WsUInt8 num_args;
                WsBool lindex_found;
                WsBool findex_found;

                if (!ws_stdlib_function(expr->u.call.base, expr->u.call.name,
                                        &lindex, &findex, &num_args,
                                        &lindex_found, &findex_found))
                {
                    if (!lindex_found)
                        ws_src_error(compiler, expr->line,
                                     "unknown system library `%s'",
                                     expr->u.call.base);
                    else
                        ws_src_error(compiler, expr->line,
                                     "unknown library function `%s.%s'",
                                     expr->u.call.base, expr->u.call.name);

                    return;
                }
                /* Check the argument count. */
                if (expr->u.call.arguments->num_items != num_args)
                {
                    ws_src_error(compiler, expr->line,
                                 "invalid amount of arguments for `%s.%s': "
                                 "expected %u, got %u",
                                 expr->u.call.base, expr->u.call.name,
                                 num_args, expr->u.call.arguments->num_items);
                    return;
                }

                /* Emit assembler. */
                ws_asm_link(compiler, ws_asm_call_lib(compiler, expr->line, findex,
                                                      lindex));
            }
            break;

        default:
            ws_fatal("ws_expr_linearize(): unknown call expression type %x",
                     expr->u.call.type);
            break;
        }
        break;

    case WS_EXPR_SYMBOL:
        {
            WsNamespace *ns = ws_variable_lookup(compiler, expr->u.symbol);

            if (ns == NULL) {
                /* An unknown identifier. */
                ws_src_error(compiler, expr->line, "unknown variable `%s'",
                             expr->u.symbol);
                return;
            }

            /* Create a load instruction for the variable. */
            ws_asm_link(compiler, ws_asm_variable(compiler, expr->line,
                                                  WS_ASM_P_LOAD_VAR, ns->vindex));
        }
        break;

    case WS_EXPR_CONST_INVALID:
        ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
                                         WS_ASM_CONST_INVALID));
        break;

    case WS_EXPR_CONST_TRUE:
        ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
                                         WS_ASM_CONST_TRUE));
        break;

    case WS_EXPR_CONST_FALSE:
        ws_asm_link(compiler, ws_asm_ins(compiler, expr->line,
                                         WS_ASM_CONST_FALSE));
        break;


    case WS_EXPR_CONST_INTEGER:
        if (expr->u.integer.ival == 0)
            ins = ws_asm_ins(compiler, expr->line, WS_ASM_CONST_0);
        else if (expr->u.integer.ival == 1 && expr->u.integer.sign == 1)
            ins = ws_asm_ins(compiler, expr->line, WS_ASM_CONST_1);
        else {
            WsUInt16 cindex;
	    WsInt32 ival;

            if (expr->u.integer.sign >= 0) {
		if (expr->u.integer.ival > (WsUInt32) WS_INT32_MAX)
		    ws_src_error(compiler, expr->line,
                                 "integer literal too large");
                ival = expr->u.integer.ival;
	    } else {
                if (expr->u.integer.ival > (WsUInt32) WS_INT32_MAX + 1)
		    ws_src_error(compiler, expr->line, "integer too small");
                ival = - (WsInt32) expr->u.integer.ival;
	    }

            if (!ws_bc_add_const_int(compiler->bc, &cindex, ival)) {
                ws_error_memory(compiler);
                return;
            }
            ins = ws_asm_load_const(compiler, expr->line, cindex);
        }

        ws_asm_link(compiler, ins);
        break;

    case WS_EXPR_CONST_FLOAT:
        {
            WsUInt16 cindex;

            if (!ws_bc_add_const_float(compiler->bc, &cindex, expr->u.fval)) {
                ws_error_memory(compiler);
                return;
            }

            ws_asm_link(compiler, ws_asm_load_const(compiler, expr->line, cindex));
        }
        break;

    case WS_EXPR_CONST_STRING:
        if (expr->u.string.len == 0)
            ins = ws_asm_ins(compiler, expr->line, WS_ASM_CONST_ES);
        else {
            WsUInt16 cindex;

            if (!ws_bc_add_const_utf8_string(compiler->bc, &cindex,
                                             expr->u.string.data,
                                             expr->u.string.len)) {
                ws_error_memory(compiler);
                return;
            }
            ins = ws_asm_load_const(compiler, expr->line, cindex);
        }

        ws_asm_link(compiler, ins);
        break;
    }
}
Esempio n. 6
0
WsBool ws_encode_buffer(WsBuffer *buffer, ...)
{
    va_list ap;
    WsEncodingSpec spec;
    int ival;
    unsigned char *p;
    unsigned char *cp;
    size_t len;
    WsUInt32 ui32;
    unsigned char data[64];

    va_start(ap, buffer);

    while ((spec = va_arg(ap, int)) != WS_ENC_END)
    {
        switch (spec)
        {
        case WS_ENC_BYTE:
        case WS_ENC_INT8:
        case WS_ENC_UINT8:
            ival = va_arg(ap, int);

            if (!ws_buffer_append_space(buffer, &p, 1))
                goto error;

            WS_PUT_UINT8(p, ival);
            break;

        case WS_ENC_INT16:
        case WS_ENC_UINT16:
            ival = va_arg(ap, int);

            if (!ws_buffer_append_space(buffer, &p, 2))
                goto error;

            WS_PUT_UINT16(p, ival);
            break;

        case WS_ENC_INT32:
        case WS_ENC_UINT32:
            ival = va_arg(ap, long);

            if (!ws_buffer_append_space(buffer, &p, 4))
                goto error;

            WS_PUT_UINT32(p, ival);
            break;

        case WS_ENC_MB_UINT16:
        case WS_ENC_MB_UINT32:
            if (spec == WS_ENC_MB_UINT16)
                ui32 = va_arg(ap, int);
            else
                ui32 = va_arg(ap, long);

            len = sizeof(data);
            cp = ws_encode_mb_uint32(ui32, data, &len);

            if (!ws_buffer_append_space(buffer, &p, len))
                goto error;

            memcpy(p, cp, len);
            break;

        case WS_ENC_DATA:
            cp = va_arg(ap, unsigned char *);
            len = va_arg(ap, unsigned int);

            if (!ws_buffer_append_space(buffer, &p, len))
                goto error;

            memcpy(p, cp, len);
            break;

        default:
            ws_fatal("ws_encode_buffer(): unknown type %d: probably a missing "
                     "WS_ENC_END",
                     spec);
            break;
        }
    }
Esempio n. 7
0
WsBc *ws_bc_decode(const unsigned char *data, size_t data_len)
{
    WsBc *bc = ws_bc_alloc(WS_BC_STRING_ENC_ISO_8859_1);
    WsByte b;
    WsUInt32 ui32;
    WsUInt16 ui16, j;
    WsUInt16 ui16b;
    WsUInt8 ui8, num_functions, k, l;
    WsInt8 i8;
    WsInt16 i16;
    WsInt32 i32;
    WsIeee754Result ieee754;
    unsigned char *ucp;
    size_t decoded;

    /* Decode the byte-code header. */
    decoded = ws_decode_buffer(data, data_len,
                               WS_ENC_BYTE, &b,
                               WS_ENC_MB_UINT32, &ui32,
                               WS_ENC_END);

    if (!decoded
            || b != WS_BC_VERSION
            || ui32 != data_len - decoded)
        /* This is not a valid (or supported) byte-code header. */
        goto error;

    WS_UPDATE_DATA;

    /* Constant pool. */

    decoded = ws_decode_buffer(data, data_len,
                               WS_ENC_MB_UINT16, &ui16,
                               WS_ENC_MB_UINT16, &ui16b,
                               WS_ENC_END);
    if (!decoded)
        goto error;

    bc->string_encoding = ui16b;

    bc->constants = ws_calloc(ui16, sizeof(WsBcConstant));
    if (bc->constants == NULL)
        goto error;
    bc->num_constants = ui16;

    WS_UPDATE_DATA;

    for (j = 0; j < bc->num_constants; j++) {
        WsBcConstant *c = &bc->constants[j];

        decoded = ws_decode_buffer(data, data_len,
                                   WS_ENC_UINT8, &ui8,
                                   WS_ENC_END);
        if (decoded != 1)
            goto error;

        WS_UPDATE_DATA;

        switch (ui8) {
        case WS_BC_CONST_INT8:
            decoded = ws_decode_buffer(data, data_len,
                                       WS_ENC_INT8, &i8,
                                       WS_ENC_END);
            if (decoded != 1)
                goto error;

            WS_UPDATE_DATA;

            c->type = WS_BC_CONST_TYPE_INT;
            c->u.v_int = i8;
            break;

        case WS_BC_CONST_INT16:
            decoded = ws_decode_buffer(data, data_len,
                                       WS_ENC_INT16, &i16,
                                       WS_ENC_END);
            if (decoded != 2)
                goto error;

            WS_UPDATE_DATA;

            c->type = WS_BC_CONST_TYPE_INT;
            c->u.v_int = i16;
            break;

        case WS_BC_CONST_INT32:
            decoded = ws_decode_buffer(data, data_len,
                                       WS_ENC_INT32, &i32,
                                       WS_ENC_END);
            if (decoded != 4)
                goto error;

            WS_UPDATE_DATA;

            c->type = WS_BC_CONST_TYPE_INT;
            c->u.v_int = i32;
            break;

        case WS_BC_CONST_FLOAT32:
            decoded = ws_decode_buffer(data, data_len,
                                       WS_ENC_DATA, &ucp, (size_t) 4,
                                       WS_ENC_END);
            if (decoded != 4)
                goto error;

            WS_UPDATE_DATA;

            ieee754 = ws_ieee754_decode_single(ucp, &c->u.v_float);

            switch (ieee754) {
            case WS_IEEE754_OK:
                c->type = WS_BC_CONST_TYPE_FLOAT32;
                break;

            case WS_IEEE754_NAN:
                c->type = WS_BC_CONST_TYPE_FLOAT32_NAN;
                break;

            case WS_IEEE754_POSITIVE_INF:
                c->type = WS_BC_CONST_TYPE_FLOAT32_POSITIVE_INF;
                break;

            case WS_IEEE754_NEGATIVE_INF:
                c->type = WS_BC_CONST_TYPE_FLOAT32_NEGATIVE_INF;
                break;
            }

            break;

        case WS_BC_CONST_UTF8_STRING:
            decoded = ws_decode_buffer(data, data_len,
                                       WS_ENC_MB_UINT32, &ui32,
                                       WS_ENC_END);
            if (decoded == 0)
                goto error;

            WS_UPDATE_DATA;

            c->type = WS_BC_CONST_TYPE_UTF8_STRING;
            c->u.v_string.len = ui32;

            decoded = ws_decode_buffer(data, data_len,
                                       WS_ENC_DATA, &ucp, c->u.v_string.len,
                                       WS_ENC_END);
            if (decoded != ui32)
                goto error;

            WS_UPDATE_DATA;

            c->u.v_string.data = ws_memdup(ucp, ui32);
            if (c->u.v_string.data == NULL)
                goto error;

            /* Check the validity of the data. */
            if (!ws_utf8_verify(c->u.v_string.data, c->u.v_string.len,
                                &c->u.v_string.num_chars))
                goto error;
            break;

        case WS_BC_CONST_EMPTY_STRING:
            c->type = WS_BC_CONST_TYPE_EMPTY_STRING;
            break;

        case WS_BC_CONST_EXT_ENC_STRING:
            ws_fatal("external character encoding not implemented yet");
            break;

        default:
            /* Reserved. */
            goto error;
            break;
        }
    }

    /* Pragma pool. */

    decoded = ws_decode_buffer(data, data_len,
                               WS_ENC_MB_UINT16, &ui16,
                               WS_ENC_END);
    if (!decoded)
        goto error;

    bc->pragmas = ws_calloc(ui16, sizeof(WsBcPragma));
    if (bc->pragmas == NULL)
        goto error;
    bc->num_pragmas = ui16;

    WS_UPDATE_DATA;

    for (j = 0; j < bc->num_pragmas; j++) {
        WsBcPragma *p = &bc->pragmas[j];

        decoded = ws_decode_buffer(data, data_len,
                                   WS_ENC_UINT8, &ui8,
                                   WS_ENC_END);
        if (decoded != 1)
            goto error;

        WS_UPDATE_DATA;

        p->type = ui8;

        switch (ui8) {
        case WS_BC_PRAGMA_ACCESS_DOMAIN:
            decoded = ws_decode_buffer(data, data_len,
                                       WS_ENC_MB_UINT16, &p->index_1,
                                       WS_ENC_END);
            if (!decoded)
                goto error;

            WS_CHECK_STRING(p->index_1);
            break;

        case WS_BC_PRAGMA_ACCESS_PATH:
            decoded = ws_decode_buffer(data, data_len,
                                       WS_ENC_MB_UINT16, &p->index_1,
                                       WS_ENC_END);
            if (!decoded)
                goto error;

            WS_CHECK_STRING(p->index_1);
            break;

        case WS_BC_PRAGMA_USER_AGENT_PROPERTY:
            decoded = ws_decode_buffer(data, data_len,
                                       WS_ENC_MB_UINT16, &p->index_1,
                                       WS_ENC_MB_UINT16, &p->index_2,
                                       WS_ENC_END);
            if (!decoded)
                goto error;

            WS_CHECK_STRING(p->index_1);
            WS_CHECK_STRING(p->index_2);
            break;

        case WS_BC_PRAGMA_USER_AGENT_PROPERTY_AND_SCHEME:
            decoded = ws_decode_buffer(data, data_len,
                                       WS_ENC_MB_UINT16, &p->index_1,
                                       WS_ENC_MB_UINT16, &p->index_2,
                                       WS_ENC_MB_UINT16, &p->index_3,
                                       WS_ENC_END);
            if (!decoded)
                goto error;

            WS_CHECK_STRING(p->index_1);
            WS_CHECK_STRING(p->index_2);
            WS_CHECK_STRING(p->index_3);
            break;

        default:
            goto error;
            break;
        }

        WS_UPDATE_DATA;
    }

    /* Function pool. */

    decoded = ws_decode_buffer(data, data_len,
                               WS_ENC_UINT8, &num_functions,
                               WS_ENC_END);
    if (decoded != 1)
        goto error;

    WS_UPDATE_DATA;

    /* Function names. */

    decoded = ws_decode_buffer(data, data_len,
                               WS_ENC_UINT8, &ui8,
                               WS_ENC_END);
    if (decoded != 1)
        goto error;

    WS_UPDATE_DATA;

    if (ui8) {
        /* We have function names. */
        bc->function_names = ws_calloc(ui8, sizeof(WsBcFunctionName));
        if (bc->function_names == NULL)
            goto error;
        bc->num_function_names = ui8;

        for (k = 0; k < bc->num_function_names; k++) {
            WsBcFunctionName *n = &bc->function_names[k];

            decoded = ws_decode_buffer(data, data_len,
                                       WS_ENC_UINT8, &n->index,
                                       WS_ENC_UINT8, &ui8,
                                       WS_ENC_END);
            if (decoded != 2)
                goto error;

            WS_UPDATE_DATA;

            decoded = ws_decode_buffer(data, data_len,
                                       WS_ENC_DATA, &ucp, (size_t) ui8,
                                       WS_ENC_END);
            if (decoded != ui8)
                goto error;

            WS_UPDATE_DATA;

            n->name = ws_memdup(ucp, ui8);
            if (n->name == NULL)
                goto error;

            /* Check the validity of the name. */

            if (!ws_utf8_verify((unsigned char *) n->name, ui8, NULL))
                goto error;

            /* Just check that the data contains only valid characters. */
            for (l = 0; l < ui8; l++) {
                unsigned int ch = (unsigned char) n->name[l];

                if (('a' <= ch && ch <= 'z')
                        || ('A' <= ch && ch <= 'Z')
                        || ch == '_'
                        || (l > 0 && ('0' <= ch && ch <= '9')))
                    /* Ok. */
                    continue;

                /* Invalid character in the function name. */
                goto error;
            }

            /* Is the index valid? */
            if (n->index >= num_functions)
                goto error;
        }
    }

    /* Functions. */

    if (num_functions) {
        /* We have functions. */
        bc->functions = ws_calloc(num_functions, sizeof(WsBcFunction));
        if (bc->functions == NULL)
            goto error;
        bc->num_functions = num_functions;

        for (k = 0; k < bc->num_functions; k++) {
            WsBcFunction *f = &bc->functions[k];

            decoded = ws_decode_buffer(data, data_len,
                                       WS_ENC_UINT8, &f->num_arguments,
                                       WS_ENC_UINT8, &f->num_locals,
                                       WS_ENC_MB_UINT32, &f->code_size,
                                       WS_ENC_END);
            if (!decoded)
                goto error;

            WS_UPDATE_DATA;

            decoded = ws_decode_buffer(data, data_len,
                                       WS_ENC_DATA, &ucp, f->code_size,
                                       WS_ENC_END);
            if (decoded != f->code_size)
                goto error;

            WS_UPDATE_DATA;

            if (f->code_size) {
                /* It is not an empty function. */
                f->code = ws_memdup(ucp, f->code_size);
                if (f->code == NULL)
                    goto error;
            }
        }
    }

    /* Did we process it all? */
    if (data_len != 0)
        goto error;

    /* All done. */
    return bc;

    /*
     * Error handling.
     */

error:

    ws_bc_free(bc);

    return NULL;
}
Esempio n. 8
0
WsBool ws_bc_encode(WsBc *bc, unsigned char **data_return,
                    size_t *data_len_return)
{
    WsBuffer buffer;
    WsUInt32 ui;
    unsigned char data[64];
    unsigned char *p, *mb;
    size_t len;

    ws_buffer_init(&buffer);

    /* Append space for the header.  We do not know yet the size of the
       resulting byte-code. */
    if (!ws_buffer_append_space(&buffer, NULL, WS_BC_MAX_HEADER_LEN))
        goto error;


    /* Constants. */

    if (!ws_encode_buffer(&buffer,
                          WS_ENC_MB_UINT16, bc->num_constants,
                          WS_ENC_MB_UINT16, (WsUInt16) bc->string_encoding,
                          WS_ENC_END))
        goto error;

    for (ui = 0 ; ui < bc->num_constants; ui++) {
        switch (bc->constants[ui].type) {
        case WS_BC_CONST_TYPE_INT:
            if (WS_INT8_MIN <= bc->constants[ui].u.v_int
                    && bc->constants[ui].u.v_int <= WS_INT8_MAX) {
                if (!ws_encode_buffer(&buffer,
                                      WS_ENC_UINT8, (WsUInt8) WS_BC_CONST_INT8,
                                      WS_ENC_INT8,
                                      (WsInt8) bc->constants[ui].u.v_int,
                                      WS_ENC_END))
                    goto error;
            } else if (WS_INT16_MIN <= bc->constants[ui].u.v_int
                       && bc->constants[ui].u.v_int <= WS_INT16_MAX) {
                if (!ws_encode_buffer(&buffer,
                                      WS_ENC_UINT8, (WsUInt8) WS_BC_CONST_INT16,
                                      WS_ENC_INT16,
                                      (WsInt16) bc->constants[ui].u.v_int,
                                      WS_ENC_END))
                    goto error;
            } else {
                if (!ws_encode_buffer(&buffer,
                                      WS_ENC_UINT8, (WsUInt8) WS_BC_CONST_INT32,
                                      WS_ENC_INT32, bc->constants[ui].u.v_int,
                                      WS_ENC_END))
                    goto error;
            }
            break;

        case WS_BC_CONST_TYPE_FLOAT32:
        case WS_BC_CONST_TYPE_FLOAT32_NAN:
        case WS_BC_CONST_TYPE_FLOAT32_POSITIVE_INF:
        case WS_BC_CONST_TYPE_FLOAT32_NEGATIVE_INF:
            switch (bc->constants[ui].type) {
            case WS_BC_CONST_TYPE_FLOAT32:
                ws_ieee754_encode_single(bc->constants[ui].u.v_float, data);
                p = data;
                break;

            case WS_BC_CONST_TYPE_FLOAT32_NAN:
                p = ws_ieee754_nan;
                break;

            case WS_BC_CONST_TYPE_FLOAT32_POSITIVE_INF:
                p = ws_ieee754_positive_inf;
                break;

            case WS_BC_CONST_TYPE_FLOAT32_NEGATIVE_INF:
                p = ws_ieee754_negative_inf;
                break;

            default:
                ws_fatal("ws_bc_encode(): internal inconsistency");
                /* NOTREACHED */
                p = NULL; 		/* Initialized to keep compiler quiet. */
                break;
            }

            if (!ws_encode_buffer(&buffer,
                                  WS_ENC_UINT8, (WsUInt8) WS_BC_CONST_FLOAT32,
                                  WS_ENC_DATA, p, 4,
                                  WS_ENC_END))
                goto error;
            break;

            break;

        case WS_BC_CONST_TYPE_UTF8_STRING:
            /* Encode the strings as requested. */
            switch (bc->string_encoding) {
            case WS_BC_STRING_ENC_ISO_8859_1:
            {
                WsUtf8String *string = ws_utf8_alloc();
                unsigned char *latin1;
                size_t latin1_len;
                WsBool success;

                if (string == NULL)
                    goto error;

                /* Create an UTF-8 string. */
                if (!ws_utf8_set_data(string,
                                      bc->constants[ui].u.v_string.data,
                                      bc->constants[ui].u.v_string.len)) {
                    ws_utf8_free(string);
                    goto error;
                }

                /* Convert it to latin1. */
                latin1 = ws_utf8_to_latin1(string, '?', &latin1_len);

                /* We'r done with the UTF-8 string. */
                ws_utf8_free(string);

                if (latin1 == NULL)
                    goto error;

                /* Encode it. */
                success = ws_encode_buffer(
                              &buffer,
                              WS_ENC_UINT8,
                              (WsUInt8) WS_BC_CONST_EXT_ENC_STRING,

                              WS_ENC_MB_UINT32, (WsUInt32) latin1_len,
                              WS_ENC_DATA, latin1, latin1_len,

                              WS_ENC_END);
                ws_utf8_free_data(latin1);

                if (!success)
                    goto error;
            }
            break;

            case WS_BC_STRING_ENC_UTF8:
                if (!ws_encode_buffer(
                            &buffer,
                            WS_ENC_UINT8,
                            (WsUInt8) WS_BC_CONST_UTF8_STRING,

                            WS_ENC_MB_UINT32,
                            (WsUInt32) bc->constants[ui].u.v_string.len,

                            WS_ENC_DATA,
                            bc->constants[ui].u.v_string.data,
                            bc->constants[ui].u.v_string.len,

                            WS_ENC_END))
                    goto error;
                break;
            }
            break;

        case WS_BC_CONST_TYPE_EMPTY_STRING:
            if (!ws_encode_buffer(&buffer,
                                  WS_ENC_UINT8,
                                  (WsUInt8) WS_BC_CONST_EMPTY_STRING,
                                  WS_ENC_END))
                goto error;
            break;
        }
    }


    /* Pragmas. */

    if (!ws_encode_buffer(&buffer,
                          WS_ENC_MB_UINT16, bc->num_pragmas,
                          WS_ENC_END))
        goto error;

    for (ui = 0; ui < bc->num_pragmas; ui++) {
        switch (bc->pragmas[ui].type) {
        case WS_BC_PRAGMA_TYPE_ACCESS_DOMAIN:
            if (!ws_encode_buffer(&buffer,
                                  WS_ENC_UINT8,
                                  (WsUInt8) WS_BC_PRAGMA_ACCESS_DOMAIN,

                                  WS_ENC_MB_UINT16, bc->pragmas[ui].index_1,
                                  WS_ENC_END))
                goto error;
            break;

        case WS_BC_PRAGMA_TYPE_ACCESS_PATH:
            if (!ws_encode_buffer(&buffer,
                                  WS_ENC_UINT8,
                                  (WsUInt8) WS_BC_PRAGMA_ACCESS_PATH,
                                  WS_ENC_MB_UINT16, bc->pragmas[ui].index_1,
                                  WS_ENC_END))
                goto error;
            break;

        case WS_BC_PRAGMA_TYPE_USER_AGENT_PROPERTY:
            if (!ws_encode_buffer(&buffer,
                                  WS_ENC_UINT8,
                                  (WsUInt8) WS_BC_PRAGMA_USER_AGENT_PROPERTY,
                                  WS_ENC_MB_UINT16, bc->pragmas[ui].index_1,
                                  WS_ENC_MB_UINT16, bc->pragmas[ui].index_2,
                                  WS_ENC_END))
                goto error;
            break;

        case WS_BC_PRAGMA_TYPE_USER_AGENT_PROPERTY_AND_SCHEME:
            if (!ws_encode_buffer(
                        &buffer,
                        WS_ENC_UINT8,
                        (WsUInt8) WS_BC_PRAGMA_USER_AGENT_PROPERTY_AND_SCHEME,
                        WS_ENC_MB_UINT16, bc->pragmas[ui].index_1,
                        WS_ENC_MB_UINT16, bc->pragmas[ui].index_2,
                        WS_ENC_MB_UINT16, bc->pragmas[ui].index_3,
                        WS_ENC_END))
                goto error;
            break;
        }
    }


    /* Function pool. */

    if (!ws_encode_buffer(&buffer,
                          WS_ENC_UINT8, bc->num_functions,
                          WS_ENC_END))
        goto error;

    /* Function names. */

    if (!ws_encode_buffer(&buffer,
                          WS_ENC_UINT8, bc->num_function_names,
                          WS_ENC_END))
        goto error;

    for (ui = 0; ui < bc->num_function_names; ui++) {
        size_t name_len = strlen(bc->function_names[ui].name);

        if (!ws_encode_buffer(&buffer,
                              WS_ENC_UINT8, bc->function_names[ui].index,
                              WS_ENC_UINT8, (WsUInt8) name_len,
                              WS_ENC_DATA, bc->function_names[ui].name, name_len,
                              WS_ENC_END))
            goto error;
    }

    /* Functions. */

    for (ui = 0; ui < bc->num_functions; ui++) {
        if (!ws_encode_buffer(&buffer,
                              WS_ENC_UINT8, bc->functions[ui].num_arguments,
                              WS_ENC_UINT8, bc->functions[ui].num_locals,
                              WS_ENC_MB_UINT32, bc->functions[ui].code_size,
                              WS_ENC_DATA, bc->functions[ui].code,
                              (size_t) bc->functions[ui].code_size,
                              WS_ENC_END))
            goto error;
    }


    /* Fix the byte-code header. */

    p = ws_buffer_ptr(&buffer);

    /* Encode the size of the byte-code excluding the byte-code header. */
    mb = ws_encode_mb_uint32(ws_buffer_len(&buffer) - WS_BC_MAX_HEADER_LEN,
                             data, &len);
    memcpy(p + WS_BC_MAX_HEADER_LEN - len, mb, len);

    /* Set the byte-code file version information. */
    WS_PUT_UINT8(p + WS_BC_MAX_HEADER_LEN - len - 1, WS_BC_VERSION);

    /* Calculate the beginning of the bc-array and its size. */
    *data_return = p + WS_BC_MAX_HEADER_LEN - len - 1;
    *data_len_return = ws_buffer_len(&buffer) - WS_BC_MAX_HEADER_LEN + len + 1;

    /* All done. */
    return WS_TRUE;


    /*
     * Error handling.
     */

error:

    ws_buffer_uninit(&buffer);
    *data_return = NULL;
    *data_len_return = 0;

    return WS_FALSE;
}
Esempio n. 9
0
void
ws_asm_linearize(WsCompiler *compiler)
{
    WsAsmIns *ins;
    WsBool process_again = WS_TRUE;

    /* Calculate all offsets and select real assembler instructions for
       our internal pseudo instructions.  This is continued as long as
       the code changes. */
    while (process_again) {
        WsUInt32 offset = 1;

        process_again = WS_FALSE;

        for (ins = compiler->asm_head; ins; ins = ins->next) {
            ins->offset = offset;

            switch (ins->type) {
            case WS_ASM_JUMP_FW_S:
                ins->ws_offset = (ins->ws_label->offset
                                  - (offset + WS_OPSIZE(ins->type)));
                break;

            case WS_ASM_JUMP_FW:
                ins->ws_offset = (ins->ws_label->offset
                                  - (offset + WS_OPSIZE(ins->type)));

                if (ins->ws_offset <= 31) {
                    ins->type = WS_ASM_JUMP_FW_S;
                    process_again = WS_TRUE;
                }
                break;

            case WS_ASM_JUMP_FW_W:
                ins->ws_offset = (ins->ws_label->offset
                                  - (offset + WS_OPSIZE(ins->type)));

                if (ins->ws_offset <= 31) {
                    ins->type = WS_ASM_JUMP_FW_S;
                    process_again = WS_TRUE;
                } else if (ins->ws_offset <= 255) {
                    ins->type = WS_ASM_JUMP_FW;
                    process_again = WS_TRUE;
                }
                break;

            case WS_ASM_JUMP_BW_S:
                ins->ws_offset = offset - ins->ws_label->offset;
                break;

            case WS_ASM_JUMP_BW:
                ins->ws_offset = offset - ins->ws_label->offset;

                if (ins->ws_offset <= 31) {
                    ins->type = WS_ASM_JUMP_BW_S;
                    process_again = WS_TRUE;
                }
                break;

            case WS_ASM_JUMP_BW_W:
                ins->ws_offset = offset - ins->ws_label->offset;

                if (ins->ws_offset <= 31) {
                    ins->type = WS_ASM_JUMP_BW_S;
                    process_again = WS_TRUE;
                } else if (ins->ws_offset <= 255) {
                    ins->type = WS_ASM_JUMP_BW;
                    process_again = WS_TRUE;
                }
                break;

            case WS_ASM_TJUMP_FW_S:
                ins->ws_offset = (ins->ws_label->offset
                                  - (offset + WS_OPSIZE(ins->type)));
                break;

            case WS_ASM_TJUMP_FW:
                ins->ws_offset = (ins->ws_label->offset
                                  - (offset + WS_OPSIZE(ins->type)));

                if (ins->ws_offset <= 31) {
                    ins->type = WS_ASM_TJUMP_FW_S;
                    process_again = WS_TRUE;
                }
                break;

            case WS_ASM_TJUMP_FW_W:
                ins->ws_offset = (ins->ws_label->offset
                                  - (offset + WS_OPSIZE(ins->type)));

                if (ins->ws_offset <= 31) {
                    ins->type = WS_ASM_TJUMP_FW_S;
                    process_again = WS_TRUE;
                } else if (ins->ws_offset <= 255) {
                    ins->type = WS_ASM_TJUMP_FW;
                    process_again = WS_TRUE;
                }
                break;

            case WS_ASM_TJUMP_BW:
                 ins->ws_offset = offset - ins->ws_label->offset;
                 break;

            case WS_ASM_TJUMP_BW_W:
                ins->ws_offset = offset - ins->ws_label->offset;

                if (ins->ws_offset <= 255) {
                    ins->type = WS_ASM_TJUMP_BW;
                    process_again = WS_TRUE;
                }
                break;

                /*
                 * The pseudo instructions.
                 */

            case WS_ASM_P_LABEL:
                /* Nothing here. */
                break;

            case WS_ASM_P_JUMP:
                if (ins->ws_label->offset == 0) {
                    /* A forward jump.  Let's assume the widest form. */
                    ins->type = WS_ASM_JUMP_FW_W;
                } else {
                    ins->ws_offset = offset - ins->ws_label->offset;

                    /* Jump backwards. */
                    if (ins->ws_offset <= 31) {
                        ins->type = WS_ASM_JUMP_BW_S;
                    } else if (ins->ws_offset <= 255) {
                        ins->type = WS_ASM_JUMP_BW;
                    } else {
                        ins->type = WS_ASM_JUMP_BW_W;
                    }
                }
                break;

            case WS_ASM_P_TJUMP:
                if (ins->ws_label->offset == 0) {
                    /* A forward jump.  Let's assume the widest form. */
                    ins->type = WS_ASM_TJUMP_FW_W;
                    process_again = WS_TRUE;
                } else {
                    ins->ws_offset = offset - ins->ws_label->offset;

                    /* Jump backwards. */
                    if (ins->ws_offset <= 255) {
                        ins->type = WS_ASM_TJUMP_BW;
                    } else {
                        ins->type = WS_ASM_TJUMP_BW_W;
                    }
                }
                break;

            case WS_ASM_P_CALL:
                if (ins->ws_findex <= 7) {
                    /* The most compact form. */
                    ins->type = WS_ASM_CALL_S;
                } else {
                    /* The wider form. */
                    ins->type = WS_ASM_CALL;
                }
                break;

            case WS_ASM_P_CALL_LIB:
                if (ins->ws_findex <= 7 && ins->ws_lindex <= 255) {
                    /* The most compact form. */
                    ins->type = WS_ASM_CALL_LIB_S;
                } else if (ins->ws_findex <= 255 && ins->ws_lindex <= 255) {
                    /* The quite compact form. */
                    ins->type = WS_ASM_CALL_LIB;
                } else {
                    /* The most liberal form. */
                    ins->type = WS_ASM_CALL_LIB_W;
                }
                break;

            case WS_ASM_P_CALL_URL:
                if (ins->ws_findex <= 255 && ins->ws_lindex <= 255)
                    /* The compact form. */
                    ins->type = WS_ASM_CALL_URL;
                else
                    ins->type = WS_ASM_CALL_URL_W;
                break;

            case WS_ASM_P_LOAD_VAR:
                if (ins->ws_vindex <= 31)
                    /* The compact form. */
                    ins->type = WS_ASM_LOAD_VAR_S;
                else
                    ins->type = WS_ASM_LOAD_VAR;
                break;

            case WS_ASM_P_STORE_VAR:
                if (ins->ws_vindex <= 15)
                    ins->type = WS_ASM_STORE_VAR_S;
                else
                    ins->type = WS_ASM_STORE_VAR;
                break;

            case WS_ASM_P_INCR_VAR:
                if (ins->ws_vindex <= 7)
                    ins->type = WS_ASM_INCR_VAR_S;
                else
                    ins->type = WS_ASM_INCR_VAR;
                break;

            case WS_ASM_P_LOAD_CONST:
                if (ins->ws_cindex <= 15)
                    ins->type = WS_ASM_LOAD_CONST_S;
                else if (ins->ws_cindex <= 255)
                    ins->type = WS_ASM_LOAD_CONST;
                else
                    ins->type = WS_ASM_LOAD_CONST_W;
                break;
            }

            gw_assert(ins->type == WS_ASM_P_LABEL || ins->type < 0x100);

            if (ins->type != WS_ASM_P_LABEL) {
                gw_assert(operands[ins->type].name != NULL);
                offset += operands[ins->type].size;
            }
        }
    }

    /* Ok, ready to linearize the byte-code. */
    for (ins = compiler->asm_head; ins; ins = ins->next) {
        if (ins->type == WS_ASM_P_LABEL)
            continue;

        gw_assert(ins->type <= 0xff);

        switch (ins->type) {
        case WS_ASM_JUMP_FW_S:
        case WS_ASM_JUMP_BW_S:
        case WS_ASM_TJUMP_FW_S:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE,
                                  WS_ASM_GLUE(ins->type, ins->ws_offset),
                                  WS_ENC_END))
                goto error;
            break;

        case WS_ASM_JUMP_FW:
        case WS_ASM_JUMP_BW:
        case WS_ASM_TJUMP_FW:
        case WS_ASM_TJUMP_BW:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE, ins->type,
                                  WS_ENC_UINT8, (WsUInt8) ins->ws_offset,
                                  WS_ENC_END))
                goto error;
            break;

        case WS_ASM_JUMP_FW_W:
        case WS_ASM_JUMP_BW_W:
        case WS_ASM_TJUMP_FW_W:
        case WS_ASM_TJUMP_BW_W:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE, ins->type,
                                  WS_ENC_UINT16, (WsUInt16) ins->ws_offset,
                                  WS_ENC_END))
                goto error;
            break;

        case WS_ASM_CALL_S:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE,
                                  WS_ASM_GLUE(ins->type, ins->ws_findex),
                                  WS_ENC_END))
                goto error;
            break;

        case WS_ASM_CALL:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE, (WsByte) ins->type,
                                  WS_ENC_UINT8, (WsUInt8) ins->ws_findex,
                                  WS_ENC_END))
                goto error;
            break;

        case WS_ASM_CALL_LIB_S:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE,
                                  WS_ASM_GLUE(ins->type, ins->ws_findex),
                                  WS_ENC_UINT8, (WsUInt8) ins->ws_lindex,
                                  WS_ENC_END))
                goto error;
            break;

        case WS_ASM_CALL_LIB:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE, (WsByte) ins->type,
                                  WS_ENC_UINT8, (WsUInt8) ins->ws_findex,
                                  WS_ENC_UINT8, (WsUInt8) ins->ws_lindex,
                                  WS_ENC_END))
                goto error;
            break;

        case WS_ASM_CALL_LIB_W:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE, (WsByte) ins->type,
                                  WS_ENC_UINT8, (WsUInt8) ins->ws_findex,
                                  WS_ENC_UINT16, (WsUInt16) ins->ws_lindex,
                                  WS_ENC_END))
                goto error;
            break;

        case WS_ASM_CALL_URL:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE, (WsByte) ins->type,
                                  WS_ENC_UINT8, (WsUInt8) ins->ws_lindex,
                                  WS_ENC_UINT8, (WsUInt8) ins->ws_findex,
                                  WS_ENC_UINT8, (WsUInt8) ins->ws_args,
                                  WS_ENC_END))
                goto error;
            break;

        case WS_ASM_CALL_URL_W:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE, (WsByte) ins->type,
                                  WS_ENC_UINT16, (WsUInt16) ins->ws_lindex,
                                  WS_ENC_UINT16, (WsUInt16) ins->ws_findex,
                                  WS_ENC_UINT8, (WsUInt8) ins->ws_args,
                                  WS_ENC_END))
                goto error;
            break;

        case WS_ASM_LOAD_VAR_S:
        case WS_ASM_STORE_VAR_S:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE,
                                  WS_ASM_GLUE(ins->type, ins->ws_vindex),
                                  WS_ENC_END))
                goto error;
            break;

        case WS_ASM_LOAD_VAR:
        case WS_ASM_STORE_VAR:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE, (WsByte) ins->type,
                                  WS_ENC_UINT8, (WsUInt8) ins->ws_vindex,
                                  WS_ENC_END))
                goto error;
            break;

        case WS_ASM_INCR_VAR_S:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE,
                                  WS_ASM_GLUE(ins->type, ins->ws_vindex),
                                  WS_ENC_END))
                goto error;
            break;

        case WS_ASM_INCR_VAR:
        case WS_ASM_DECR_VAR:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE, (WsByte) ins->type,
                                  WS_ENC_UINT8, (WsUInt8) ins->ws_vindex,
                                  WS_ENC_END))
                goto error;
            break;

        case WS_ASM_LOAD_CONST_S:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE,
                                  WS_ASM_GLUE(ins->type, ins->ws_cindex),
                                  WS_ENC_END))
                goto error;
            break;

        case WS_ASM_LOAD_CONST:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE, (WsByte) ins->type,
                                  WS_ENC_UINT8, (WsUInt8) ins->ws_cindex,
                                  WS_ENC_END))
                goto error;
            break;

        case WS_ASM_LOAD_CONST_W:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE, (WsByte) ins->type,
                                  WS_ENC_UINT16, (WsUInt16) ins->ws_cindex,
                                  WS_ENC_END))
                goto error;
            break;

        case WS_ASM_ADD_ASG:
        case WS_ASM_SUB_ASG:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE, (WsByte) ins->type,
                                  WS_ENC_UINT8, (WsUInt8) ins->ws_vindex,
                                  WS_ENC_END))
                goto error;
            break;

        case WS_ASM_CONST_0:
        case WS_ASM_CONST_1:
        case WS_ASM_CONST_M1:
        case WS_ASM_CONST_ES:
        case WS_ASM_CONST_INVALID:
        case WS_ASM_CONST_TRUE:
        case WS_ASM_CONST_FALSE:
        case WS_ASM_INCR:
        case WS_ASM_DECR:
        case WS_ASM_UMINUS:
        case WS_ASM_ADD:
        case WS_ASM_SUB:
        case WS_ASM_MUL:
        case WS_ASM_DIV:
        case WS_ASM_IDIV:
        case WS_ASM_REM:
        case WS_ASM_B_AND:
        case WS_ASM_B_OR:
        case WS_ASM_B_XOR:
        case WS_ASM_B_NOT:
        case WS_ASM_B_LSHIFT:
        case WS_ASM_B_RSSHIFT:
        case WS_ASM_B_RSZSHIFT:
        case WS_ASM_EQ:
        case WS_ASM_LE:
        case WS_ASM_LT:
        case WS_ASM_GE:
        case WS_ASM_GT:
        case WS_ASM_NE:
        case WS_ASM_NOT:
        case WS_ASM_SCAND:
        case WS_ASM_SCOR:
        case WS_ASM_TOBOOL:
        case WS_ASM_POP:
        case WS_ASM_TYPEOF:
        case WS_ASM_ISVALID:
        case WS_ASM_RETURN:
        case WS_ASM_RETURN_ES:
        case WS_ASM_DEBUG:
            if (!ws_encode_buffer(&compiler->byte_code,
                                  WS_ENC_BYTE, (WsByte) ins->type,
                                  WS_ENC_END))
                goto error;
            break;

        default:
            ws_fatal("ws_asm_linearize(): unknown instruction 0x%02x",
                     ins->type);
            break;
        }
    }

    /*
     * Avoid generating 0-length functions, because not all clients
     * handle them correctly.
     */
    if (ws_buffer_len(&compiler->byte_code) == 0) {
	if (!ws_encode_buffer(&compiler->byte_code,
	   		      WS_ENC_BYTE, (WsByte) WS_ASM_RETURN_ES,
			      WS_ENC_END))
	    goto error;
    }

    return;

    /*
     * Error handling.
     */

error:

    ws_error_memory(compiler);
    return;
}
Esempio n. 10
0
void ws_asm_print(WsCompiler *compiler)
{
    WsAsmIns *ins;

    for (ins = compiler->asm_head; ins; ins = ins->next) {
        if (ins->type > 0xff) {
            /* A symbolic operand. */
            switch (ins->type) {
            case WS_ASM_P_LABEL:
                ws_fprintf(WS_STDOUT, ".L%d:\t\t\t\t/* refcount=%d */\n",
                           ins->ws_label_idx, ins->ws_label_refcount);
                break;

            case WS_ASM_P_JUMP:
                ws_fprintf(WS_STDOUT, "\tjump*\t\tL%d\n",
                           ins->ws_label->ws_label_idx);
                break;

            case WS_ASM_P_TJUMP:
                ws_fprintf(WS_STDOUT, "\ttjump*\t\tL%d\n",
                           ins->ws_label->ws_label_idx);
                break;

            case WS_ASM_P_CALL:
                ws_fprintf(WS_STDOUT, "\tcall*\t\t%s\n",
                           compiler->functions[ins->ws_findex].name);
                break;

            case WS_ASM_P_CALL_LIB:
                {
                    const char *lib;
                    const char *func;

                    ws_stdlib_function_name(ins->ws_lindex,
                                            ins->ws_findex,
                                            &lib, &func);
                    ws_fprintf(WS_STDOUT, "\tcall_lib*\t%s.%s\n",
                               lib ? lib : "???",
                               func ? func : "???");
                }
                break;

            case WS_ASM_P_CALL_URL:
                ws_fprintf(WS_STDOUT, "\tcall_url*\t%u %u %u\n",
                           ins->ws_lindex, ins->ws_findex, ins->ws_args);
                break;

            case WS_ASM_P_LOAD_VAR:
                ws_fprintf(WS_STDOUT, "\tload_var*\t%u\n", ins->ws_vindex);
                break;

            case WS_ASM_P_STORE_VAR:
                ws_fprintf(WS_STDOUT, "\tstore_var*\t%u\n", ins->ws_vindex);
                break;

            case WS_ASM_P_INCR_VAR:
                ws_fprintf(WS_STDOUT, "\tincr_var*\t%u\n", ins->ws_vindex);
                break;

            case WS_ASM_P_LOAD_CONST:
                ws_fprintf(WS_STDOUT, "\tload_const*\t%u\n", ins->ws_cindex);
                break;
            }
        } else {
            WsUInt8 op = WS_ASM_OP(ins->type);

            if (operands[op].name) {
                /* Operands add_asg and sub_asg are special. */
                if (op == WS_ASM_ADD_ASG || op == WS_ASM_SUB_ASG)
                    ws_fprintf(WS_STDOUT, "\t%s\t\t%u\n", operands[ins->type].name,
                               ins->ws_vindex);
                else
                    ws_fprintf(WS_STDOUT, "\t%s\n", operands[ins->type].name);
            } else
                ws_fatal("ws_asm_print(): unknown operand 0x%x", op);
        }
    }
}