class Metasm::C::Switch

Attributes

body[RW]
test[RW]

Public Class Methods

new(test, body) click to toggle source
# File metasm/parse_c.rb, line 865
def initialize(test, body)
        @test = test
        @body = body
end
parse(parser, scope, nest) click to toggle source
# File metasm/parse_c.rb, line 870
def self.parse(parser, scope, nest)
        raise tok || parser, '"(" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != '('
        raise tok, 'expr expected' if not expr = CExpression.parse(parser, scope) or not expr.type.integral?
        raise tok || parser, '")" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != ')'

        new expr, parser.parse_statement(scope, nest + [:switch])
end

Public Instance Methods

dump(scope, r=[''], dep=[]) click to toggle source
# File metasm/parse_c.rb, line 3805
def dump(scope, r=[''], dep=[])
        r.last << 'switch ('
        r, dep = CExpression.dump(@test, scope, r, dep)
        r.last << ')'
        r.last << ' {' if @body.kind_of? Block
        tr, dep = @body.dump(scope, [''], dep)
        r.concat tr.map { |s| Case.dump_indent(s, true) }
        r << '}' if @body.kind_of? Block
        [r, dep]
end
precompile(compiler, scope) click to toggle source
# File metasm/compile_c.rb, line 848
def precompile(compiler, scope)
        var = Variable.new
        var.storage = :register
        var.name = compiler.new_label('switch')
        var.type = @test.type
        var.initializer = @test
        CExpression.precompile_type(compiler, scope, var)
        Declaration.new(var).precompile(compiler, scope)

        @body = @body.precompile_make_block scope
        @body.break_label = compiler.new_label('switch_break')
        @body.precompile(compiler)
        default = @body.break_label
        # recursive lambda to change Case to Labels
        # dynamically creates the If sequence
        walk = lambda { |blk|
                blk.statements.each_with_index { |s, i|
                        case s
                        when Case
                                label = compiler.new_label('case')
                                if s.expr == 'default'
                                        default = label
                                elsif s.exprup
                                        If.new(CExpression.new(CExpression.new(var, :'>=', s.expr, BaseType.new(:int)), :'&&',
                                                                CExpression.new(var, :'<=', s.exprup, BaseType.new(:int)),
                                                                BaseType.new(:int)), Goto.new(label)).precompile(compiler, scope)
                                else
                                        If.new(CExpression.new(var, :'==', s.expr, BaseType.new(:int)),
                                                Goto.new(label)).precompile(compiler, scope)
                                end
                                blk.statements[i] = Label.new(label)
                        when Block
                                walk[s]
                        end
                }
        }
        walk[@body]
        Goto.new(default).precompile(compiler, scope)
        scope.statements << @body
        Label.new(@body.break_label).precompile(compiler, scope)
end