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