class Metasm::C::Declaration
found in a block's Statements, used to know the initialization order eg { int i; i = 4; struct foo { int k; } toto = {i}; }
Attributes
var[RW]
Public Class Methods
new(var)
click to toggle source
# File metasm/parse_c.rb, line 791 def initialize(var) @var = var end
precompile_dyn_initializer(compiler, scope, var, type, init)
click to toggle source
turns an initializer to CExpressions in scope.statements
# File metasm/compile_c.rb, line 614 def self.precompile_dyn_initializer(compiler, scope, var, type, init) case type = type.untypedef when Array # XXX TODO type.length may be dynamic !! case init when CExpression # char toto[] = "42" if not init.kind_of? CExpression or init.op or init.lexpr or not init.rexpr.kind_of? ::String raise "unknown initializer #{init.inspect} for #{var.inspect}" end init = init.rexpr.unpack('C*') + [0] init.map! { |chr| CExpression.new(nil, nil, chr, type.type) } precompile_dyn_initializer(compiler, scope, var, type, init) when ::Array type.length ||= init.length # len is an Integer init.each_with_index { |it, idx| next if not it break if idx >= type.length idx = CExpression.new(nil, nil, idx, BaseType.new(:long, :unsigned)) v = CExpression.new(var, :'[]', idx, type.type) precompile_dyn_initializer(compiler, scope, v, type.type, it) } else raise "unknown initializer #{init.inspect} for #{var.inspect}" end when Union case init when CExpression, Variable if init.type.untypedef.kind_of? BaseType # works for struct foo bar[] = {0}; ... type.members.each { |m| v = CExpression.new(var, :'.', m.name, m.type) precompile_dyn_initializer(compiler, scope, v, v.type, init) } elsif init.type.untypedef.kind_of? type.class CExpression.new(var, :'=', init, type).precompile(compiler, scope) else raise "bad initializer #{init.inspect} for #{var.inspect}" end when ::Array init.each_with_index{ |it, idx| next if not it m = type.members[idx] v = CExpression.new(var, :'.', m.name, m.type) precompile_dyn_initializer(compiler, scope, v, m.type, it) } else raise "unknown initializer #{init.inspect} for #{var.inspect}" end else case init when CExpression CExpression.new(var, :'=', init, type).precompile(compiler, scope) else raise "unknown initializer #{init.inspect} for #{var.inspect}" end end end
precompile_static_initializer(compiler, type, init)
click to toggle source
returns a precompiled static initializer (eg string constants)
# File metasm/compile_c.rb, line 673 def self.precompile_static_initializer(compiler, type, init) # TODO case type = type.untypedef when Array if init.kind_of? ::Array init.map { |i| precompile_static_initializer(compiler, type.type, i) } else init end when Union if init.kind_of? ::Array init.zip(type.members).map { |i, m| precompile_static_initializer(compiler, m.type, i) } else init end else if init.kind_of? CExpression and init = init.reduce(compiler) and init.kind_of? CExpression if not init.op and init.rexpr.kind_of? ::String v = Variable.new v.storage = :static v.name = 'char_' + init.rexpr.gsub(/[^a-zA-Z]/, '')[0, 8] v.type = Array.new(type.type) v.type.length = init.rexpr.length + 1 v.type.type.qualifier = [:const] v.initializer = CExpression.new(nil, nil, init.rexpr, type) Declaration.new(v).precompile(compiler, compiler.toplevel) init.rexpr = v end init.rexpr = precompile_static_initializer(compiler, init.rexpr.type, init.rexpr) if init.rexpr.kind_of? CExpression init.lexpr = precompile_static_initializer(compiler, init.lexpr.type, init.lexpr) if init.lexpr.kind_of? CExpression end init end end
Public Instance Methods
dump(scope, r=[CRenderString.new], dep=[])
click to toggle source
# File metasm/parse_c.rb, line 3480 def dump(scope, r=[CRenderString.new], dep=[]) tr, dep = @var.dump_def(scope, [CRenderString.new], dep) if @var.kind_of?(Variable) and @var.type.kind_of?(Function) and @var.initializer r << CRenderString.new r.concat tr else r.pop if r.last == '' r.concat tr r.last << ';' end [r, dep] end
precompile(compiler, scope)
click to toggle source
# File metasm/compile_c.rb, line 551 def precompile(compiler, scope) if (@var.type.kind_of? Function and @var.initializer and scope != compiler.toplevel) or @var.storage == :static or compiler.check_reserved_name(@var) old = @var.name ref = scope.symbol.delete old if scope == compiler.toplevel or (@var.type.kind_of?(Function) and not @var.initializer) if n = compiler.label_oldname.index(old) # reuse same name as predeclarations @var.name = n else newname = old newname = compiler.new_label newname until newname != old if not compiler.check_reserved_name(@var) compiler.label_oldname[newname] = old end @var.name = newname end ref ||= scope.symbol[@var.name] || @var # append only one actual declaration for all predecls (the one with init, or the last uninit) scope.statements << self if ref.eql?(@var) else @var.name = compiler.new_label @var.name until @var.name != old compiler.toplevel.statements << self end compiler.toplevel.symbol[@var.name] = ref else scope.symbol[@var.name] ||= @var appendme = true if scope.symbol[@var.name].eql?(@var) end if i = @var.initializer if @var.type.kind_of? Function if @var.type.type.kind_of? Union s = @var.type.type v = Variable.new v.name = compiler.new_label('return_struct_ptr') v.type = Pointer.new(s) CExpression.precompile_type(compiler, scope, v) @var.type.args.unshift v @var.type.type = v.type end i.function = @var i.return_label = compiler.new_label('epilog') i.nonauto_label = {} i.precompile(compiler) Label.new(i.return_label).precompile(compiler, i) i.precompile_optimize # append now so that static dependencies are declared before us # TODO no pure inline if addrof(func) needed scope.statements << self if appendme and not @var.attributes.to_a.include? 'inline' elsif scope != compiler.toplevel and @var.storage != :static scope.statements << self if appendme Declaration.precompile_dyn_initializer(compiler, scope, @var, @var.type, i) @var.initializer = nil else scope.statements << self if appendme @var.initializer = Declaration.precompile_static_initializer(compiler, @var.type, i) end else scope.statements << self if appendme end end
to_s()
click to toggle source
# File metasm/parse_c.rb, line 3493 def to_s dump(Block.new(nil))[0].join(' ') end