class Metasm::AsmPreprocessor::Macro

an assembler macro, similar to preprocessor macro handles local labels

Attributes

args[RW]
body[RW]
labels[RW]
name[RW]

Public Class Methods

new(name) click to toggle source
# File metasm/parse.rb, line 113
def initialize(name)
        @name = name
        @args, @body, @labels = [], [], []
end

Public Instance Methods

apply(macro, lexer, program) click to toggle source

returns the array of token resulting from the application of the macro parses arguments if needed, handles macro-local labels

# File metasm/parse.rb, line 120
def apply(macro, lexer, program)
        args = Preprocessor::Macro.parse_arglist(lexer).to_a
        raise @name, 'invalid argument count' if args.length != @args.length

        labels = @labels.inject({}) { |h, l| h.update l => program.new_label(l) }
        args = @args.zip(args).inject({}) { |h, (fa, a)| h.update fa.raw => a }

        # apply macro
        @body.map { |t|
                t = t.dup
                t.backtrace += macro.backtrace[-2..-1] if not macro.backtrace.empty?
                if labels[t.raw]
                        t.raw = labels[t.raw]
                        t
                elsif args[t.raw]
                        # XXX update toks backtrace ?
                        args[t.raw]
                else
                        t
                end
        }.flatten
end
parse_definition(lexer) click to toggle source

parses the argument list and the body from lexer recognize the local labels XXX add eax,

toto db 42     ; zomg h4x
# File metasm/parse.rb, line 147
def parse_definition(lexer)
        lexer.skip_space
        while tok = lexer.nexttok and tok.type != :eol
                # no preprocess argument list
                raise @name, 'invalid arg definition' if not tok = lexer.readtok or tok.type != :string
                @args << tok
                lexer.skip_space
                raise @name, 'invalid arg separator' if not tok = lexer.readtok or ((tok.type != :punct or tok.raw != ',') and tok.type != :eol)
                break if tok.type == :eol
                lexer.skip_space
        end

        lexer.skip_space_eol
        while tok = lexer.readtok and (tok.type != :string or tok.raw != 'endm')
                @body << tok
                if @body[-2] and @body[-2].type == :string and @body[-1].raw == ':' and (not @body[-3] or @body[-3].type == :eol) and @body[-2].raw !~ /^[1-9][0-9]*$/
                        @labels << @body[-2].raw
                elsif @body[-3] and @body[-3].type == :string and @body[-2].type == :space and Data::DataSpec.include?(@body[-1].raw) and (not @body[-4] or @body[-4].type == :eol)
                        @labels << @body[-3].raw
                end
        end
end