Ejemplo n.º 1
0
static struct block *primary_expression(struct block *block)
{
    const struct symbol *sym;
    struct token tok;

    switch ((tok = next()).token) {
    case IDENTIFIER:
        sym = sym_lookup(&ns_ident, tok.strval);
        if (!sym) {
            error("Undefined symbol '%s'.", tok.strval);
            exit(1);
        }
        /* Special handling for builtin pseudo functions. These are expected to
         * behave as macros, thus should be no problem parsing as function call
         * in primary expression. Constructs like (va_arg)(args, int) will not
         * work with this scheme. */
        if (!strcmp("__builtin_va_start", sym->name)) {
            block = parse__builtin_va_start(block);
        } else if (!strcmp("__builtin_va_arg", sym->name)) {
            block = parse__builtin_va_arg(block);
        } else {
            block->expr = var_direct(sym);
        }
        break;
    case INTEGER_CONSTANT:
        block->expr = var_int(tok.intval);
        break;
    case '(':
        block = expression(block);
        consume(')');
        break;
    case STRING:
        sym =
            sym_add(&ns_ident,
                ".LC",
                type_init(T_ARRAY, &basic_type__char, strlen(tok.strval) + 1),
                SYM_STRING_VALUE,
                LINK_INTERN);

        /* Store string value directly on symbol, memory ownership is in string
         * table from previously called str_register. The symbol now exists as
         * if it was declared static char .LC[] = "...". */
        ((struct symbol *) sym)->string_value = tok.strval;

        /* Result is an IMMEDIATE of type [] char, with a reference to the new
         * symbol containing the string literal. Will decay into char * on
         * evaluation. */
        block->expr = var_direct(sym);
        assert(block->expr.kind == IMMEDIATE);
        break;
    default:
        error("Unexpected '%s', not a valid primary expression.", tok.strval);
        exit(1);
    }

    return block;
}
Ejemplo n.º 2
0
static struct block *equality_expression(struct block *block)
{
    struct var value;

    block = relational_expression(block);
    while (1) {
        value = block->expr;
        if (peek().token == EQ) {
            consume(EQ);
            block = relational_expression(block);
            block->expr = eval_expr(block, IR_OP_EQ, value, block->expr);
        } else if (peek().token == NEQ) {
            consume(NEQ);
            block = relational_expression(block);
            block->expr = 
                eval_expr(block, IR_OP_EQ, var_int(0),
                    eval_expr(block, IR_OP_EQ, value, block->expr));
        } else break;
    }

    return block;
}
Ejemplo n.º 3
0
static struct block *unary_expression(struct block *block)
{
    struct var value;

    switch (peek().token) {
    case '&':
        consume('&');
        block = cast_expression(block);
        block->expr = eval_addr(block, block->expr);
        break;
    case '*':
        consume('*');
        block = cast_expression(block);
        block->expr = eval_deref(block, block->expr);
        break;
    case '!':
        consume('!');
        block = cast_expression(block);
        block->expr = eval_expr(block, IR_OP_EQ, var_int(0), block->expr);
        break;
    case '~':
        consume('~');
        block = cast_expression(block);
        block->expr = eval_expr(block, IR_NOT, block->expr);
        break;
    case '+':
        consume('+');
        block = cast_expression(block);
        block->expr.lvalue = 0;
        break;
    case '-':
        consume('-');
        block = cast_expression(block);
        block->expr = eval_expr(block, IR_OP_SUB, var_int(0), block->expr);
        break;
    case SIZEOF: {
        struct typetree *type;
        struct block *head = cfg_block_init(), *tail;
        consume(SIZEOF);
        if (peek().token == '(') {
            switch (peekn(2).token) {
            case FIRST(type_name):
                consume('(');
                type = declaration_specifiers(NULL);
                if (peek().token != ')') {
                    type = declarator(type, NULL);
                }
                consume(')');
                break;
            default:
                tail = unary_expression(head);
                type = (struct typetree *) tail->expr.type;
                break;
            }
        } else {
            tail = unary_expression(head);
            type = (struct typetree *) tail->expr.type;
        }
        if (is_function(type)) {
            error("Cannot apply 'sizeof' to function type.");
        }
        if (!size_of(type)) {
            error("Cannot apply 'sizeof' to incomplete type.");
        }
        block->expr = var_int(size_of(type));
        break;
    }
    case INCREMENT:
        consume(INCREMENT);
        block = unary_expression(block);
        value = block->expr;
        block->expr = eval_expr(block, IR_OP_ADD, value, var_int(1));
        block->expr = eval_assign(block, value, block->expr);
        break;
    case DECREMENT:
        consume(DECREMENT);
        block = unary_expression(block);
        value = block->expr;
        block->expr = eval_expr(block, IR_OP_SUB, value, var_int(1));
        block->expr = eval_assign(block, value, block->expr);
        break;
    default:
        block = postfix_expression(block);
        break;
    }

    return block;
}
Ejemplo n.º 4
0
static struct block *postfix_expression(struct block *block)
{
    struct var root;

    block = primary_expression(block);
    root = block->expr;

    while (1) {
        const struct member *field;
        const struct typetree *type;
        struct var expr, copy, *arg;
        struct token tok;
        int i, j;

        switch ((tok = peek()).token) {
        case '[':
            do {
                /* Evaluate a[b] = *(a + b). The semantics of pointer arithmetic
                 * takes care of multiplying b with the correct width. */
                consume('[');
                block = expression(block);
                root = eval_expr(block, IR_OP_ADD, root, block->expr);
                root = eval_deref(block, root);
                consume(']');
            } while (peek().token == '[');
            break;
        case '(':
            type = root.type;
            if (is_pointer(root.type) && is_function(root.type->next))
                type = type_deref(root.type);
            else if (!is_function(root.type)) {
                error("Expression must have type pointer to function, was %t.",
                    root.type);
                exit(1);
            }
            consume('(');
            arg = calloc(nmembers(type), sizeof(*arg));
            for (i = 0; i < nmembers(type); ++i) {
                if (peek().token == ')') {
                    error("Too few arguments, expected %d but got %d.",
                        nmembers(type), i);
                    exit(1);
                }
                block = assignment_expression(block);
                arg[i] = block->expr;
                /* todo: type check here. */
                if (i < nmembers(type) - 1) {
                    consume(',');
                }
            }
            while (is_vararg(type) && peek().token != ')') {
                consume(',');
                arg = realloc(arg, (i + 1) * sizeof(*arg));
                block = assignment_expression(block);
                arg[i] = block->expr;
                i++;
            }
            consume(')');
            for (j = 0; j < i; ++j)
                param(block, arg[j]);
            free(arg);
            root = eval_call(block, root);
            break;
        case '.':
            consume('.');
            tok = consume(IDENTIFIER);
            field = find_type_member(root.type, tok.strval);
            if (!field) {
                error("Invalid field access, no member named '%s'.",
                    tok.strval);
                exit(1);
            }
            root.type = field->type;
            root.offset += field->offset;
            break;
        case ARROW:
            consume(ARROW);
            tok = consume(IDENTIFIER);
            if (is_pointer(root.type) && is_struct_or_union(root.type->next)) {
                field = find_type_member(type_deref(root.type), tok.strval);
                if (!field) {
                    error("Invalid field access, no member named '%s'.",
                        tok.strval);
                    exit(1);
                }

                /* Make it look like a pointer to the field type, then perform
                 * normal dereferencing. */
                root.type = type_init(T_POINTER, field->type);
                root = eval_deref(block, root);
                root.offset = field->offset;
            } else {
                error("Invalid field access.");
                exit(1);
            }
            break;
        case INCREMENT:
            consume(INCREMENT);
            copy = create_var(root.type);
            eval_assign(block, copy, root);
            expr = eval_expr(block, IR_OP_ADD, root, var_int(1));
            eval_assign(block, root, expr);
            root = copy;
            break;
        case DECREMENT:
            consume(DECREMENT);
            copy = create_var(root.type);
            eval_assign(block, copy, root);
            expr = eval_expr(block, IR_OP_SUB, root, var_int(1));
            eval_assign(block, root, expr);
            root = copy;
            break;
        default:
            block->expr = root;
            return block;
        }
    }
}
Ejemplo n.º 5
0
//---------------------------------------------------------------------------
void Var::fromString( const string &value ) {
    if ( type == Var_Float ) var_float() = ofToFloat( value );
    if ( type == Var_Int ) var_int() = ofToInt( value );
    if ( type == Var_String ) var_string() = value;
}
Ejemplo n.º 6
0
//---------------------------------------------------------------------------
void Var::loadIni( ParamMap &ini ) {
    if ( type == Var_Float ) {
        var_float() = ini.getFloat(name, var_float() ); }
    if ( type == Var_Int ) { var_int() = ini.getInt(name, var_int() ); }
    if ( type == Var_String ) { var_string() = ini.getString(name, var_string() ); }
}
Ejemplo n.º 7
0
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void Var::saveIni( ParamMap &ini ) {
    if ( type == Var_Float ) { ini.setFloat(name, var_float() ); }
    if ( type == Var_Int ) { ini.setInt(name, var_int() ); }
    if ( type == Var_String ) { ini.setString(name, var_string() ); }
}
Ejemplo n.º 8
0
//~~ var_str(const Payload& data, unsigned int& index) [var_str] ~~
unsigned int len = var_int(data,index).getValue();

if (index+len > data.size())
    throw Malformated();

std::string::operator=(std::string((const char*)&(*data)[index],len));

index += len;