Exemplo n.º 1
0
static WsUInt32 buffer_to_int(WsCompilerPtr compiler, WsBuffer *buffer)
{
    unsigned char *p;
    unsigned long value;

    /* Terminate the string. */
    if (!ws_buffer_append_space(buffer, &p, 1)) {
        ws_error_memory(compiler);
        return 0;
    }
    p[0] = '\0';

    /* Convert the buffer into an integer number.  The base is taken
       from the bufer. */
    errno = 0;
    value = strtoul((char *) ws_buffer_ptr(buffer), NULL, 0);

    /* Check for overflow.  We accept WS_INT32_MAX + 1 because we might
     * be parsing the numeric part of '-2147483648'. */
    if (errno == ERANGE || value > (WsUInt32) WS_INT32_MAX + 1)
        ws_src_error(compiler, 0, "integer literal too large");

    /* All done. */
    return (WsUInt32) value;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
Arquivo: ws.c Projeto: markjeee/kannel
static WsResult compile_stream(WsCompilerPtr compiler, const char *input_name,
                               WsStream *input, unsigned char **output_return,
                               size_t *output_len_return)
{
    WsResult result = WS_OK;
    WsUInt32 i;
    WsListItem *li;
    WsUInt8 findex;
    WsUInt8 num_locals;
    WsBcStringEncoding string_encoding = WS_BC_STRING_ENC_UTF8;

    /* Initialize the compiler context. */

    compiler->linenum = 1;
    compiler->input_name = input_name;

    compiler->num_errors = 0;
    compiler->num_warnings = 0;
    compiler->num_extern_functions = 0;
    compiler->num_local_functions = 0;
    compiler->errors = 0;
    compiler->last_syntax_error_line = 0;

    /* Allocate fast-malloc pool for the syntax tree. */

    compiler->pool_stree = ws_f_create(1024 * 1024);
    if (compiler->pool_stree == NULL) {
        result = WS_ERROR_OUT_OF_MEMORY;
        goto out;
    }

    /* Allocate hash tables. */

    compiler->pragma_use_hash = ws_pragma_use_hash_create();
    if (compiler->pragma_use_hash == NULL) {
        result = WS_ERROR_OUT_OF_MEMORY;
        goto out;
    }

    compiler->functions_hash = ws_function_hash_create();
    if (compiler->functions_hash == NULL) {
        result = WS_ERROR_OUT_OF_MEMORY;
        goto out;
    }

    /* Allocate a byte-code module. */

    if (compiler->params.use_latin1_strings)
        string_encoding = WS_BC_STRING_ENC_ISO_8859_1;

    compiler->bc = ws_bc_alloc(string_encoding);
    if (compiler->bc == NULL) {
        result = WS_ERROR_OUT_OF_MEMORY;
        goto out;
    }

    /* Save the input stream. */
    compiler->input = input;

    /* Parse the input. */
#if WS_DEBUG
    global_compiler = compiler;
#endif /* WS_DEBUG */

    ws_yy_parse(compiler);

    /* Free all lexer's active not freed blocks.  If we have any blocks
       on the used list, our compilation was not successful. */
    {
        size_t j;

        for (j = 0; j < compiler->lexer_active_list_size; j++)
            ws_free(compiler->lexer_active_list[j]);
        ws_free(compiler->lexer_active_list);

        compiler->lexer_active_list = NULL;
    }

    WS_CHECK_COMPILE_ERROR();

    /* Sort functions if allowed and it helps. */
    if (!compiler->params.no_opt_sort_bc_functions
        && compiler->num_functions > 7) {
        WsUInt32 i;

        ws_info(compiler, "optimize: sorting functions");

        /* Fetch the usage counts from the functions hash. */
        for (i = 0; i < compiler->num_functions; i++) {
            WsFunctionHash *fh = ws_function_hash(compiler,
                                                  compiler->functions[i].name);
            compiler->functions[i].usage_count = fh->usage_count;
        }

        /* Sort functions.  */
        qsort(compiler->functions, compiler->num_functions,
              sizeof(compiler->functions[0]), sort_functions_cmp);

        /* Patch the function indexes. */
        for (i = 0; i < compiler->num_functions; i++) {
            WsFunctionHash *fh = ws_function_hash(compiler,
                                                  compiler->functions[i].name);
            compiler->functions[i].findex = i;
            fh->findex = i;
        }
    }

    /* Linearize functions */
    for (i = 0; i < compiler->num_functions; i++) {
        WsFunction *func = &compiler->functions[i];

        ws_info(compiler, "linearizing function `%s'...", func->name);

        compiler->pool_asm = ws_f_create(100 * 1024);
        if (compiler->pool_asm == NULL) {
            result = WS_ERROR_OUT_OF_MEMORY;
            goto out;
        }

        compiler->next_label = 0;
        compiler->asm_head = compiler->asm_tail = NULL;

        /* Create variables namespace. */
        compiler->next_vindex = 0;
        compiler->variables_hash = ws_variable_hash_create();
        if (compiler->variables_hash == NULL) {
            result = WS_ERROR_OUT_OF_MEMORY;
            goto out;
        }

        /* Define the formal arguments to the namespace. */
        for (li = func->params->head; li; li = li->next) {
            WsFormalParm *parm = li->data;

            ws_variable_define(compiler, parm->line, WS_FALSE, parm->name);
        }

        WS_CHECK_COMPILE_ERROR();

        /* Linearize it. */
        for (li = func->block->head; li; li = li->next)
            ws_stmt_linearize(compiler, li->data);

        WS_CHECK_COMPILE_ERROR();

        /* Optimize symbolic assembler.  This function does nothing if
           no optimizations were requested. */
        ws_asm_optimize(compiler);

        /* Print the resulting symbolic assembler if requested. */
        if (compiler->params.print_symbolic_assembler)
            ws_asm_print(compiler);

        WS_CHECK_COMPILE_ERROR();

        /* Generate byte-code */

        ws_buffer_init(&compiler->byte_code);
        ws_asm_linearize(compiler);

        WS_CHECK_COMPILE_ERROR();

        /* Disassemble the output if requested. */
        if (compiler->params.print_assembler)
            ws_asm_dasm(compiler, ws_buffer_ptr(&compiler->byte_code),
                        ws_buffer_len(&compiler->byte_code));

        /* Calculate the number of local variables */
        num_locals = compiler->next_vindex - func->params->num_items;

        /* Add the function to the byte-code module. */
        if (!ws_bc_add_function(compiler->bc, &findex,
                                func->externp ? func->name : NULL,
                                func->params->num_items,
                                num_locals,
                                ws_buffer_len(&compiler->byte_code),
                                ws_buffer_ptr(&compiler->byte_code))) {
            result = WS_ERROR_OUT_OF_MEMORY;
            goto out;
        }

        /* Cleanup and prepare for the next function. */

        ws_buffer_uninit(&compiler->byte_code);

        ws_hash_destroy(compiler->variables_hash);
        compiler->variables_hash = NULL;

        ws_f_destroy(compiler->pool_asm);
        compiler->pool_asm = NULL;
    }

    /* Linearize the byte-code structure. */
    if (!ws_bc_encode(compiler->bc, output_return, output_len_return))
        result = WS_ERROR_OUT_OF_MEMORY;

out:

    /* Cleanup. */

    ws_f_destroy(compiler->pool_stree);
    compiler->pool_stree = NULL;

    ws_hash_destroy(compiler->pragma_use_hash);
    compiler->pragma_use_hash = NULL;

    /* Free functions. */
    for (i = 0; i < compiler->num_functions; i++)
        ws_free(compiler->functions[i].name);
    ws_free(compiler->functions);

    ws_hash_destroy(compiler->functions_hash);
    compiler->functions_hash = NULL;

    ws_bc_free(compiler->bc);
    compiler->bc = NULL;

    compiler->input = NULL;

    ws_f_destroy(compiler->pool_asm);
    compiler->pool_asm = NULL;

    ws_hash_destroy(compiler->variables_hash);
    compiler->variables_hash = NULL;

    ws_buffer_uninit(&compiler->byte_code);

    /* All done. */
    return result;
}
Exemplo n.º 4
0
static WsBool read_float_from_exp(WsCompiler *compiler, WsBuffer *buffer,
                                  WsFloat *result)
{
    WsUInt32 ch;
    unsigned char *p;
    int sign = '+';
    unsigned char buf[4];

    /* Do we have an exponent part. */
    if (!ws_stream_getc(compiler->input, &ch))
        goto done;
    if (ch != 'e' && ch != 'E') {
        /* No exponent part. */
        ws_stream_ungetc(compiler->input, ch);
        goto done;
    }

    /* Sign. */
    if (!ws_stream_getc(compiler->input, &ch)) {
        /* This is an error. */
        ws_src_error(compiler, 0, "truncated float literal");
        return WS_FALSE;
    }
    if (ch == '-')
        sign = '-';
    else if (ch == '+')
        sign = '+';
    else
        ws_stream_ungetc(compiler->input, ch);

    /* DecimalDigits. */
    if (!ws_stream_getc(compiler->input, &ch)) {
        ws_src_error(compiler, 0, "truncated float literal");
        return WS_FALSE;
    }
    if (!WS_IS_DECIMAL_DIGIT(ch)) {
        ws_src_error(compiler, 0, "no decimal digits in exponent part");
        return WS_FALSE;
    }

    /* Append exponent part read so far. */
    if (!ws_buffer_append_space(buffer, &p, 2)) {
        ws_error_memory(compiler);
        return WS_FALSE;
    }
    p[0] = 'e';
    p[1] = sign;

    /* Read decimal digits. */
    while (WS_IS_DECIMAL_DIGIT(ch)) {
        if (!ws_buffer_append_space(buffer, &p, 1)) {
            ws_error_memory(compiler);
            return WS_FALSE;
        }
        p[0] = (unsigned char) ch;

        if (!ws_stream_getc(compiler->input, &ch))
            /* EOF.  This is ok. */
            goto done;
    }
    /* Unget the extra character. */
    ws_stream_ungetc(compiler->input, ch);

    /* FALLTHROUGH */

done:

    if (!ws_buffer_append_space(buffer, &p, 1)) {
        ws_error_memory(compiler);
        return WS_FALSE;
    }
    p[0] = 0;

    /* Now the buffer contains a valid floating point number. */
    *result = (WsFloat) strtod((char *) ws_buffer_ptr(buffer), NULL);

    /* Check that the generated floating point number fits to
       `float32'. */
    if (*result == HUGE_VAL || *result == -HUGE_VAL
        || ws_ieee754_encode_single(*result, buf) != WS_IEEE754_OK)
        ws_src_error(compiler, 0, "floating point literal too large");

    return WS_TRUE;
}