class Metasm::C::If
Attributes
belse[RW]
bthen[RW]
test[RW]
Public Class Methods
new(test, bthen, belse=nil)
click to toggle source
# File metasm/parse_c.rb, line 799 def initialize(test, bthen, belse=nil) @test = test @bthen = bthen @belse = belse if belse end
parse(parser, scope, nest)
click to toggle source
# File metasm/parse_c.rb, line 805 def self.parse(parser, scope, nest) tok = nil raise tok || self, '"(" 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.arithmetic? raise tok || self, '")" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != ')' bthen = parser.parse_statement scope, nest if tok = parser.skipspaces and tok.type == :string and tok.raw == 'else' belse = parser.parse_statement scope, nest else parser.unreadtok tok end new expr, bthen, belse end
Public Instance Methods
dump(scope, r=[CRenderString.new], dep=[])
click to toggle source
# File metasm/parse_c.rb, line 3791 def dump(scope, r=[CRenderString.new], dep=[]) r.last << CRenderString.new(self, 'if (') r, dep = CExpression.dump(@test, scope, r, dep) r.last << ')' r, dep = Statement.dump(@bthen, scope, r, dep) if belse @bthen.kind_of?(Block) ? (r.last << CRenderString.new(' else')) : (r << CRenderString.new(self, 'else')) if @belse.kind_of?(If) # skip indent r.last << ' ' r, dep = @belse.dump(scope, r, dep) else r, dep = Statement.dump(@belse, scope, r, dep) end end [r, dep] end
precompile(compiler, scope)
click to toggle source
# File metasm/compile_c.rb, line 710 def precompile(compiler, scope) expr = lambda { |e| e.kind_of?(CExpression) ? e : CExpression.new(nil, nil, e, e.type) } if @bthen.kind_of? Goto or @bthen.kind_of? Break or @bthen.kind_of? Continue # if () goto l; else b; => if () goto l; b; if belse t1 = @belse @belse = nil end # need to convert user-defined Goto target ! @bthen.precompile(compiler, scope) @bthen = scope.statements.pop # break => goto break_label elsif belse # if () a; else b; => if () goto then; b; goto end; then: a; end: t1 = @belse t2 = @bthen l2 = compiler.new_label('if_then') @bthen = Goto.new(l2) @belse = nil l3 = compiler.new_label('if_end') else # if () a; => if (!) goto end; a; end: t1 = @bthen l2 = compiler.new_label('if_end') @bthen = Goto.new(l2) @test = CExpression.negate(@test) end @test = expr[@test] case @test.op when :'&&' # if (c1 && c2) goto a; => if (!c1) goto b; if (c2) goto a; b: l1 = compiler.new_label('if_nand') If.new(CExpression.negate(@test.lexpr), Goto.new(l1)).precompile(compiler, scope) @test = expr[@test.rexpr] precompile(compiler, scope) when :'||' l1 = compiler.new_label('if_or') If.new(expr[@test.lexpr], Goto.new(@bthen.target)).precompile(compiler, scope) @test = expr[@test.rexpr] precompile(compiler, scope) else @test = CExpression.precompile_inner(compiler, scope, @test) t = @test.reduce(compiler) if t.kind_of? ::Integer if t == 0 Label.new(l1, nil).precompile(compiler, scope) if l1 t1.precompile(compiler, scope) if t1 Label.new(l2, nil).precompile(compiler, scope) if l2 Label.new(l3, nil).precompile(compiler, scope) if l3 else scope.statements << @bthen Label.new(l1, nil).precompile(compiler, scope) if l1 Label.new(l2, nil).precompile(compiler, scope) if l2 t2.precompile(compiler, scope) if t2 Label.new(l3, nil).precompile(compiler, scope) if l3 end return end scope.statements << self end Label.new(l1, nil).precompile(compiler, scope) if l1 t1.precompile(compiler, scope) if t1 Goto.new(l3).precompile(compiler, scope) if l3 Label.new(l2, nil).precompile(compiler, scope) if l2 t2.precompile(compiler, scope) if t2 Label.new(l3, nil).precompile(compiler, scope) if l3 end