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 879 def initialize(test, body) @test = test @body = body end
parse(parser, scope, nest)
click to toggle source
# File metasm/parse_c.rb, line 884 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=[CRenderString.new], dep=[])
click to toggle source
# File metasm/parse_c.rb, line 3855 def dump(scope, r=[CRenderString.new], dep=[]) r.last << CRenderString.new(self, 'switch (') r, dep = CExpression.dump(@test, scope, r, dep) r.last << ')' r.last << ' {' if @body.kind_of?(Block) tr, dep = @body.dump(scope, [CRenderString.new], dep) r.concat tr.map { |s| Case.dump_indent(s, true) } r << CRenderString.new('}') 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_#{s.expr}") 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