reorganize
This commit is contained in:
parent
5612fac90f
commit
bd7b76a461
1 changed files with 113 additions and 127 deletions
240
generate.rb
240
generate.rb
|
|
@ -53,13 +53,12 @@ def encode_size(type)
|
|||
end
|
||||
|
||||
class HeaderFile
|
||||
attr_reader :file, :name, :declared_names, :required_names, :included
|
||||
attr_reader :file, :name, :declared_names, :required_names, :included, :included_why, :data
|
||||
def initialize(file, filter_key:nil)
|
||||
@file = file
|
||||
@name = File.basename(@file, ".yaml")
|
||||
|
||||
@data = YAML::load(File.read(@file))
|
||||
@out = ""
|
||||
|
||||
@data.reject! do |item|
|
||||
onlyfor = item["only-for"]
|
||||
|
|
@ -89,52 +88,6 @@ private
|
|||
item.each { |key, value| return key, value }
|
||||
end
|
||||
|
||||
def starredtext(str, align, lchar:'*', rchar:'*')
|
||||
maxlinelen = str.lines.map{|s| s.rstrip.length}.max
|
||||
|
||||
str.each_line do |s|
|
||||
s.rstrip!
|
||||
c = (75 - s.length)
|
||||
b = case align
|
||||
when "center" then c/2
|
||||
when "left" then c - 1
|
||||
when "right" then 1
|
||||
end
|
||||
a = c - b
|
||||
a = 0 if a < 0
|
||||
b = 0 if b < 0
|
||||
@out << " #{lchar}#{' '*a}#{s}#{' '*b}#{rchar}\n"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def starline
|
||||
@out << "/#{'*'*77}/\n"
|
||||
end
|
||||
|
||||
def box(title, comment=nil, order:1)
|
||||
if title or comment then
|
||||
@out << "/#{'*'*77}\n"
|
||||
#print " *#{' '*75}*\n"
|
||||
starredtext(title, 'center') if title
|
||||
@out << " *#{' '*75}*\n" if title and comment
|
||||
starredtext(comment, 'left') if comment
|
||||
|
||||
@out << " #{'*'*77}/\n"
|
||||
else
|
||||
starline
|
||||
end
|
||||
end
|
||||
|
||||
def decl(type, thing)
|
||||
if thing then
|
||||
type =~ /(const +)?([A-Za-z0-9_]+) *((\* *)*)(.*)/
|
||||
return "#{$1}#{$2} #{$3}#{thing}#{$5}"
|
||||
else
|
||||
return type
|
||||
end
|
||||
end
|
||||
|
||||
def collect_dep(str)
|
||||
tmp = str.to_s.dup
|
||||
tmp.gsub!(/'[^']+'/,"")
|
||||
|
|
@ -196,6 +149,104 @@ public
|
|||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Defs
|
||||
attr_reader :headers, :declared_names, :topsort
|
||||
def initialize(filter_key:nil)
|
||||
@headers = {}
|
||||
@declared_names = {}
|
||||
|
||||
Dir.glob('defs/*.yaml') do |file|
|
||||
print "Reading #{file}...\n"
|
||||
|
||||
header = HeaderFile.new(file, filter_key: filter_key)
|
||||
@headers[header.name] = header
|
||||
|
||||
header.declared_names.each { |n| @declared_names[n] = header.name }
|
||||
end
|
||||
|
||||
print "Linking things up...\n"
|
||||
headers.each do |name, header|
|
||||
header.collect_includes(declared_names)
|
||||
end
|
||||
|
||||
@topsort = []
|
||||
done = Set.new
|
||||
headers.each do |name, header|
|
||||
do_topsort(name, done)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def do_topsort(name, done, active=Set.new, stack=[])
|
||||
print "INCLUDE CYCLE #{stack.join('=>')} => #{name}\n" if active.include?(name)
|
||||
return if done.include?(name)
|
||||
active << name
|
||||
done << name
|
||||
stack << name
|
||||
|
||||
@headers[name].included.each do |incname|
|
||||
do_topsort(incname, done, active, stack)
|
||||
end
|
||||
@topsort << name
|
||||
active.delete?(name)
|
||||
stack.pop
|
||||
end
|
||||
end
|
||||
|
||||
class Generator
|
||||
def first_elem(item)
|
||||
item.each { |key, value| return key, value }
|
||||
end
|
||||
|
||||
def starredtext(str, align, lchar:'*', rchar:'*')
|
||||
maxlinelen = str.lines.map{|s| s.rstrip.length}.max
|
||||
|
||||
str.each_line do |s|
|
||||
s.rstrip!
|
||||
c = (75 - s.length)
|
||||
b = case align
|
||||
when "center" then c/2
|
||||
when "left" then c - 1
|
||||
when "right" then 1
|
||||
end
|
||||
a = c - b
|
||||
a = 0 if a < 0
|
||||
b = 0 if b < 0
|
||||
@out << " #{lchar}#{' '*a}#{s}#{' '*b}#{rchar}\n"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def starline
|
||||
@out << "/#{'*'*77}/\n"
|
||||
end
|
||||
|
||||
def box(title, comment=nil, order:1)
|
||||
if title or comment then
|
||||
@out << "/#{'*'*77}\n"
|
||||
#print " *#{' '*75}*\n"
|
||||
starredtext(title, 'center') if title
|
||||
@out << " *#{' '*75}*\n" if title and comment
|
||||
starredtext(comment, 'left') if comment
|
||||
|
||||
@out << " #{'*'*77}/\n"
|
||||
else
|
||||
starline
|
||||
end
|
||||
end
|
||||
|
||||
def decl(type, thing)
|
||||
if thing then
|
||||
type =~ /(const +)?([A-Za-z0-9_]+) *((\* *)*)(.*)/
|
||||
return "#{$1}#{$2} #{$3}#{thing}#{$5}"
|
||||
else
|
||||
return type
|
||||
end
|
||||
end
|
||||
|
||||
def declare_members(members)
|
||||
members.each do |member|
|
||||
sub = (member["struct"] or member["union"])
|
||||
|
|
@ -385,19 +436,19 @@ public
|
|||
end
|
||||
end
|
||||
|
||||
def document_dependencies
|
||||
def document_dependencies(header)
|
||||
out = ""
|
||||
if @included.size > 0 then
|
||||
if header.included.size > 0 then
|
||||
out << "Needs:\n"
|
||||
|
||||
colwidth = @included.map(&:size).max + 4 + 2 + 4
|
||||
colwidth = header.included.map(&:size).max + 4 + 2 + 4
|
||||
maxlinelen = 70
|
||||
|
||||
@included.each do |inc|
|
||||
header.included.each do |inc|
|
||||
line = " " * 4 + inc + ".h"
|
||||
line << " " * (colwidth - line.length)
|
||||
indent = line.length
|
||||
whys = @included_why[inc].to_a
|
||||
whys = header.included_why[inc].to_a
|
||||
whys.each_index do |idx|
|
||||
why = whys[idx]
|
||||
last = (idx == whys.size - 1)
|
||||
|
|
@ -414,14 +465,14 @@ public
|
|||
return out
|
||||
end
|
||||
|
||||
def generate_header(add_includes:true)
|
||||
def generate_header(header, add_includes:true)
|
||||
@out = ""
|
||||
@impl_out = ""
|
||||
|
||||
title = "\n" + name + ".h\n" + "="*(name.length+2) + "\n"
|
||||
title = "\n" + header.name + ".h\n" + "="*(header.name.length+2) + "\n"
|
||||
titlecomment = nil
|
||||
if not add_includes and @included.size > 0 then
|
||||
titlecomment = document_dependencies
|
||||
if not add_includes and header.included.size > 0 then
|
||||
titlecomment = document_dependencies(header)
|
||||
titlecomment << "\n\n"
|
||||
else
|
||||
title << "\n"
|
||||
|
|
@ -433,7 +484,7 @@ public
|
|||
if add_includes then
|
||||
@out << "#pragma once\n"
|
||||
@out << "#include <stdint.h>\n"
|
||||
@included.each do |file|
|
||||
header.included.each do |file|
|
||||
@out << "#include \"#{file}.h\"\n"
|
||||
end
|
||||
@out << "\n\n"
|
||||
|
|
@ -441,7 +492,7 @@ public
|
|||
@out << "#pragma pack(push, 2)\n"
|
||||
@out << "\n\n"
|
||||
|
||||
@data.each do |item|
|
||||
header.data.each do |item|
|
||||
key, value = first_elem(item)
|
||||
|
||||
box(value["name"], value["comment"]) unless key == "executor_only"
|
||||
|
|
@ -573,54 +624,9 @@ public
|
|||
return @out, @impl_out
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
class Defs
|
||||
attr_reader :headers, :declared_names, :topsort
|
||||
def initialize(filter_key:nil)
|
||||
@headers = {}
|
||||
@declared_names = {}
|
||||
|
||||
Dir.glob('defs/*.yaml') do |file|
|
||||
print "Reading #{file}...\n"
|
||||
|
||||
header = HeaderFile.new(file, filter_key: filter_key)
|
||||
@headers[header.name] = header
|
||||
|
||||
header.declared_names.each { |n| @declared_names[n] = header.name }
|
||||
end
|
||||
|
||||
print "Linking things up...\n"
|
||||
headers.each do |name, header|
|
||||
header.collect_includes(declared_names)
|
||||
end
|
||||
|
||||
@topsort = []
|
||||
done = Set.new
|
||||
headers.each do |name, header|
|
||||
do_topsort(name, done)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def do_topsort(name, done, active=Set.new, stack=[])
|
||||
print "INCLUDE CYCLE #{stack.join('=>')} => #{name}\n" if active.include?(name)
|
||||
return if done.include?(name)
|
||||
active << name
|
||||
done << name
|
||||
stack << name
|
||||
|
||||
@headers[name].included.each do |incname|
|
||||
do_topsort(incname, done, active, stack)
|
||||
end
|
||||
@topsort << name
|
||||
active.delete?(name)
|
||||
stack.pop
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
FileUtils.mkdir_p "out/CIncludes"
|
||||
FileUtils.mkdir_p "out/RIncludes"
|
||||
FileUtils.mkdir_p "out/src"
|
||||
|
|
@ -629,27 +635,7 @@ FileUtils.mkdir_p "out/lib"
|
|||
|
||||
defs = Defs.new(filter_key: "CIncludes")
|
||||
|
||||
def write_ordered(file, header, headers, visited)
|
||||
return if visited.member?(header.name)
|
||||
visited << header.name
|
||||
print "Generating #{header.name}\n"
|
||||
|
||||
header.included.each do |incname|
|
||||
write_ordered(file, headers[incname], headers, visited)
|
||||
end
|
||||
|
||||
inc, src = header.generate_header(add_includes: false)
|
||||
|
||||
file << inc
|
||||
|
||||
if src and src.length > 0 then
|
||||
IO.popen("clang-format | grep -v \"// clang-format o\" > out/src/#{header.name}.c", "w") do |f|
|
||||
f << "#include \"Multiverse.h\"\n"
|
||||
f << src
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
gen = Generator.new
|
||||
|
||||
IO.popen("clang-format | grep -v \"// clang-format o\" > out/CIncludes/Multiverse.h", "w") do |f|
|
||||
f << <<~PREAMBLE
|
||||
|
|
@ -689,7 +675,7 @@ IO.popen("clang-format | grep -v \"// clang-format o\" > out/CIncludes/Multivers
|
|||
|
||||
defs.topsort.each do |name|
|
||||
header = defs.headers[name]
|
||||
inc, src = header.generate_header(add_includes: false)
|
||||
inc, src = gen.generate_header(header, add_includes: false)
|
||||
|
||||
f << inc
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue