You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.2 KiB
Ruby
94 lines
2.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require_relative '../ext/ffi-clang/lib/ffi/clang'
|
|
require_relative '../tools/ci_lib'
|
|
|
|
class Parser
|
|
CLANG_VERSION = FFI::Clang.clang_version_string.match(/\d+\.\d+\.\d+/).match 0
|
|
alias inspect to_s
|
|
|
|
@@opts = %w(
|
|
-std=c++17 -Wno-undefined-inline -Wno-undefined-internal -Wno-assume
|
|
)
|
|
clangdir = File.join ENV['PREFIX'] || '/usr', 'lib/clang', CLANG_VERSION
|
|
if File.exist? File.join clangdir, 'include/stddef.h'
|
|
@@opts << "-resource-dir=#{clangdir}"
|
|
end
|
|
|
|
def self.add_opts opts
|
|
@@opts.concat opts
|
|
end
|
|
|
|
@@src = {}
|
|
def self.add_src handlers, src
|
|
src.each do |s|
|
|
(@@src[s] ||= Set.new).merge handlers
|
|
end
|
|
end
|
|
def self.src = @@src
|
|
|
|
def self.gen_binding src, dst, args
|
|
new.gen_binding src, dst, args
|
|
end
|
|
|
|
attr_reader :tu, :filter
|
|
|
|
def parse src, args
|
|
src_noext = src.gsub(/\.[^.]*$/, '')
|
|
fname_map = {}
|
|
@filter = ->c, parent do
|
|
c.visit_children do |c2|
|
|
if c2.kind == :annotate_attr && c2.spelling.start_with?('alias_file ')
|
|
fname_map[c2.location.file] = c2.spelling[11..]
|
|
end
|
|
:break
|
|
end
|
|
|
|
loc = c.location.file or return true
|
|
loc = fname_map[loc] || loc
|
|
loc.gsub(/\.[^.]*$/, '') == src_noext
|
|
end
|
|
|
|
parse_tu src, args
|
|
end
|
|
|
|
def parse_tu fname, extra_opts
|
|
index = FFI::Clang::Index.new
|
|
@tu = index.parse_translation_unit fname, @@opts + extra_opts, [],
|
|
%i(keep_going skip_function_bodies)
|
|
@tu.diagnostics.each do |d|
|
|
if d.severity == :error || d.severity == :fatal
|
|
CI.eerror d.format
|
|
else
|
|
CI.ewarn d.format
|
|
end
|
|
end
|
|
self
|
|
end
|
|
|
|
def gen dst
|
|
dst.puts <<EOS
|
|
// Auto generated code, do not edit. See gen_binding in project root.
|
|
#ifndef LIBSHIT_BINDING_GENERATOR
|
|
EOS
|
|
@hs.each {|h| h.generate dst }
|
|
dst.puts '#endif'
|
|
self
|
|
end
|
|
|
|
def gen_binding src, dst, args
|
|
dst ||= "#{src.sub /\.[^.]+\z/, ''}.binding.hpp"
|
|
hs = @@src[src] or fail "Unknown source #{src.inspect}"
|
|
parse src, args
|
|
@hs = hs.map {|h| h.new self }
|
|
@hs.each &:parse
|
|
|
|
if dst == '-'
|
|
gen $stdout
|
|
else
|
|
File.open(dst, 'w') {|f| gen f }
|
|
end
|
|
self
|
|
end
|
|
end
|