node/lib/metasm/metasm/preprocessor.rb
# parses the argument list and the body from lexer
# converts # + # to ## in body
parses the argument list and the body from lexer
converts # + # to ## in body
parses the argument list and the body from lexer converts # + # to ## in body
def parse_definition(lexer)
			varg = nil
			if tok = lexer.readtok_nopp and tok.type == :punct and tok.raw == '('
				@args = []
				loop do
					nil while tok = lexer.readtok_nopp and tok.type == :space
					if tok and tok.type == :punct and tok.raw == '.'
						t1 = lexer.readtok_nopp
						t2 = lexer.readtok_nopp
						t3 = lexer.readtok_nopp
						t3 = lexer.readtok_nopp while t3 and t3.type == :space
						raise @name, 'booh'  if not t1 or t1.type != :punct or t1.raw != '.' or
									not t2 or t2.type != :punct or t2.raw != '.' or
									not t3 or t3.type != :punct or t3.raw != ')'
						@varargs = true
						break
					end
					break if tok and tok.type == :punct and tok.raw == ')' and @args.empty?	
					raise @name, 'invalid arg definition' if not tok or tok.type != :string
					@args << tok
					nil while tok = lexer.readtok_nopp and tok.type == :space
					if tok and tok.type == :punct and tok.raw == '.'
						t1 = lexer.readtok_nopp
						t2 = lexer.readtok_nopp
						t3 = lexer.readtok_nopp
						t3 = lexer.readtok_nopp while t3 and t3.type == :space
						raise @name, 'booh'  if not t1 or t1.type != :punct or t1.raw != '.' or
									not t2 or t2.type != :punct or t2.raw != '.' or
									not t3 or t3.type != :punct or t3.raw != ')'
						@varargs = true
						varg = @args.pop.raw
						break
					end
					raise @name, 'invalid arg separator' if not tok or tok.type != :punct or (tok.raw != ')' and tok.raw != ',')
					break if tok.raw == ')'
				end
			else lexer.unreadtok tok
			end
			nil while tok = lexer.readtok_nopp and tok.type == :space
			lexer.unreadtok tok
			while tok = lexer.readtok_nopp
				tok = tok.dup
				case tok.type
				when :eol
					lexer.unreadtok tok
					break
				when :space
					next if @body.last and @body.last.type == :space
					tok.raw = ' '
				when :string
					tok.raw = '__VA_ARGS__' if varg and tok.raw == varg
				when :punct
					if tok.raw == '#'
						ntok = lexer.readtok_nopp
						if ntok and ntok.type == :punct and ntok.raw == '#'
							tok.raw << '#'
						else
							lexer.unreadtok ntok
						end
					end
				end
				@body << tok
			end
			@body.pop if @body.last and @body.last.type == :space
			invalid_body = nil
			if (@body[-1] and @body[-1].raw == '##') or (@body[0] and @body[0].raw == '##')
				invalid_body ||= 'cannot have ## at begin or end of macro body'
			end
			if args
				if @args.map { |a| a.raw }.uniq.length != @args.length
					invalid_body ||= 'duplicate macro parameter'
				end
				@body.each_with_index { |tok_, i|
					if tok_.type == :punct and tok_.raw == '#'
						a = @body[i+1]
						a = @body[i+2] if not a or a.type == :space
						if not a.type == :string or (not @args.find { |aa| aa.raw == a.raw } and (not varargs or a.raw != '__VA_ARGS__'))
							invalid_body ||= 'cannot have # followed by non-argument'
						end
					end
				}
			end
			if invalid_body
				puts "W: #{lexer.filename}:#{lexer.lineno}, in #{@name.raw}: #{invalid_body}" if $VERBOSE
				false
			else
				true
			end
		end
def parse_definition ( lexer ) varg = nil if tok = lexer . readtok_nopp and tok . type == :punct and tok . raw == '(' @args = [ ] loop do nil while tok = lexer . readtok_nopp and tok . type == :space if tok and tok . type == :punct and tok . raw == '.' t1 = lexer . readtok_nopp t2 = lexer . readtok_nopp t3 = lexer . readtok_nopp t3 = lexer . readtok_nopp while t3 and t3 . type == :space raise @name , 'booh' if not t1 or t1 . type != :punct or t1 . raw != '.' or not t2 or t2 . type != :punct or t2 . raw != '.' or not t3 or t3 . type != :punct or t3 . raw != ')' @varargs = true break end break if tok and tok . type == :punct and tok . raw == ')' and @args . empty? raise @name , 'invalid arg definition' if not tok or tok . type != :string @args << tok nil while tok = lexer . readtok_nopp and tok . type == :space if tok and tok . type == :punct and tok . raw == '.' t1 = lexer . readtok_nopp t2 = lexer . readtok_nopp t3 = lexer . readtok_nopp t3 = lexer . readtok_nopp while t3 and t3 . type == :space raise @name , 'booh' if not t1 or t1 . type != :punct or t1 . raw != '.' or not t2 or t2 . type != :punct or t2 . raw != '.' or not t3 or t3 . type != :punct or t3 . raw != ')' @varargs = true varg = @args . pop . raw break end raise @name , 'invalid arg separator' if not tok or tok . type != :punct or ( tok . raw != ')' and tok . raw != ',' ) break if tok . raw == ')' end else lexer . unreadtok tok end nil while tok = lexer . readtok_nopp and tok . type == :space lexer . unreadtok tok while tok = lexer . readtok_nopp tok = tok . dup case tok . type when :eol lexer . unreadtok tok break when :space next if @body . last and @body . last . type == :space tok . raw = ' ' when :string tok . raw = '__VA_ARGS__' if varg and tok . raw == varg when :punct if tok . raw == '#' ntok = lexer . readtok_nopp if ntok and ntok . type == :punct and ntok . raw == '#' tok . raw << '#' else lexer . unreadtok ntok end end end @body << tok end @body . pop if @body . last and @body . last . type == :space invalid_body = nil if ( @body [ - 1 ] and @body [ - 1 ] . raw == '##' ) or ( @body [ 0 ] and @body [ 0 ] . raw == '##' ) invalid_body ||= 'cannot have ## at begin or end of macro body' end if args if @args . map { | a | a . raw } . uniq . length != @args . length invalid_body ||= 'duplicate macro parameter' end @body . each_with_index { | tok_ , i | if tok_ . type == :punct and tok_ . raw == '#' a = @body [ i + 1 ] a = @body [ i + 2 ] if not a or a . type == :space if not a . type == :string or ( not @args . find { | aa | aa . raw == a . raw } and ( not varargs or a . raw != '__VA_ARGS__' ) ) invalid_body ||= 'cannot have # followed by non-argument' end end } end if invalid_body puts "W: #{lexer.filename}:#{lexer.lineno}, in #{@name.raw}: #{invalid_body}" if $VERBOSE false else true end end
parses the argument list and the body from lexer
converts # + # to ## in body
parses the argument list and the body from lexer converts # + # to ## in body
# check '...' # allow empty list # check '...' # check macro is correct
lexer