class Metasm::C::Array
Attributes
length[RW]
Public Class Methods
new(type=nil, length=nil)
click to toggle source
Calls superclass method
Metasm::C::Pointer::new
# File metasm/parse_c.rb, line 639 def initialize(type=nil, length=nil) super(type) @length = length if length end
Public Instance Methods
align(parser)
click to toggle source
# File metasm/parse_c.rb, line 644 def align(parser) @type.align(parser) end
dump_declarator(decl, scope, r=[''], dep=[])
click to toggle source
# File metasm/parse_c.rb, line 3542 def dump_declarator(decl, scope, r=[''], dep=[]) decl.last << '()' if decl.last.empty? decl.last << '[' decl, dep = CExpression.dump(@length, scope, decl, dep) if length decl.last << ']' @type.dump_declarator(decl, scope, r, dep) end
dump_initializer(init, scope, r=[''], dep=[])
click to toggle source
Calls superclass method
Metasm::C::Type#dump_initializer
# File metasm/parse_c.rb, line 3549 def dump_initializer(init, scope, r=[''], dep=[]) return super(init, scope, r, dep) if not init.kind_of? ::Array r.last << '{ ' showname = false init.each_with_index { |v, i| if not v showname = true next end r.last << ', ' if r.last[-2, 2] != '{ ' rt = [''] if showname showname = false rt << "[#{i}] = " end rt, dep = @type.dump_initializer(v, scope, rt, dep) r.last << rt.shift r.concat rt.map { |s| "\t" << s } } r.last << ' }' [r, dep] end
expand_member_offset(c_parser, off, str)
click to toggle source
see Union#expand_member_offset
# File metasm/parse_c.rb, line 747 def expand_member_offset(c_parser, off, str) tsz = c_parser.sizeof(@type) str << "[#{off/tsz}]" if @type.respond_to?(:expand_member_offset) @type.expand_member_offset(c_parser, off%tsz, str) else @type end end
parse_initializer(parser, scope)
click to toggle source
Calls superclass method
Metasm::C::Type#parse_initializer
# File metasm/parse_c.rb, line 646 def parse_initializer(parser, scope) raise parser, 'cannot initialize dynamic array' if @length.kind_of? CExpression if tok = parser.skipspaces and tok.type == :punct and tok.raw == '{' # struct x foo[] = { { 4 }, [12].tutu = 2 }; ret = [] if tok = parser.skipspaces and (tok.type != :punct or tok.raw != '}') parser.unreadtok tok idx = 0 loop do idx = parse_initializer_designator(parser, scope, ret, idx, true) raise tok || parser, '"," or "}" expected' if not tok = parser.skipspaces or tok.type != :punct or (tok.raw != '}' and tok.raw != ',') break if tok.raw == '}' # allow int x[] = {1, 2, 3, }; break if tok = parser.skipspaces and tok.type == :punct and tok.raw == '}' parser.unreadtok tok raise tok, 'array is smaller than that' if length and idx >= @length end end ret else parser.unreadtok tok i = super(parser, scope) if i.kind_of? CExpression and not i.op and i.rexpr.kind_of? String and @length and i.rexpr.length > @length puts tok.exception("initializer is too long (#{i.rexpr.length} for #@length)").message if $VERBOSE i.rexpr = i.rexpr[0, @length] end i end end
parse_initializer_designator(parser, scope, value, idx, root=true)
click to toggle source
parses a designator+initializer eg '[12] = 4' or '[42].bla = 16' or '[3 … 8] = 28'
# File metasm/parse_c.rb, line 708 def parse_initializer_designator(parser, scope, value, idx, root=true) # root = true for 1st invocation (x = { 4 }) => immediate value allowed # or false for recursive invocations (x = { .y = 4 }) => need '=' sign before immediate if nt = parser.skipspaces and nt.type == :punct and nt.raw == '[' if not root value[idx] ||= [] # AryRecorder may change [] to AryRec.new, can't do v = v[i] ||= [] value = value[idx] end raise nt, 'const expected' if not idx = CExpression.parse(parser, scope) or not idx.constant? or not idx = idx.reduce(parser) or not idx.kind_of? ::Integer nt = parser.skipspaces if nt and nt.type == :punct and nt.raw == '.' # range raise nt || parser, '".." expected' if not nt = parser.skipspaces or nt.type != :punct or nt.raw != '.' raise nt || parser, '"." expected' if not nt = parser.skipspaces or nt.type != :punct or nt.raw != '.' raise nt, 'const expected' if not eidx = CExpression.parse(parser, scope) or not eidx.constant? or not eidx = eidx.reduce(parser) or not eidx.kind_of? ::Integer raise nt, 'bad range' if eidx < idx nt = parser.skipspaces realvalue = value value = AryRecorder.new end raise nt || parser, '"]" expected' if not nt or nt.type != :punct or nt.raw != ']' raise nt, 'array is smaller than that' if length and (eidx||idx) >= @length @type.untypedef.parse_initializer_designator(parser, scope, value, idx, false) if eidx (idx..eidx).each { |i| realvalue[i] = value.playback_idx(idx) } idx = eidx # next default value = eidx+1 (eg int x[] = { [1 ... 3] = 4, 5 } => x[4] = 5) end else if root parser.unreadtok nt value[idx] = @type.parse_initializer(parser, scope) else raise nt || parser, '"=" expected' if not nt or nt.type != :punct or nt.raw != '=' value[idx] = parse_initializer(parser, scope) end end idx + 1 end