an assembler macro, similar to preprocessor macro handles local labels
# File metasm/parse.rb, line 104 def initialize(name) @name = name @args, @body, @labels = [], [], [] end
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 111 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
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 138 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