ff4ff35918
Red Bear OS is a full fork. All sources must be available from git clone with zero network access. Removed gitignore rules that excluded fetched source trees under recipes/*/source/, local/recipes/kde/*/source/, local/recipes/qt/*/source/, and vendor source trees. Build artifacts (target/, build/, source.tar, *.o, *.so) remain excluded. 127291 files added — kernel, relibc, base, bootloader, pkgar, all KDE/Qt frameworks, mesa, wayland, DRM drivers, and every other recipe source.
167 lines
4.5 KiB
Ruby
167 lines
4.5 KiB
Ruby
module MRuby
|
|
class Presym
|
|
OPERATORS = {
|
|
"!" => "not",
|
|
"%" => "mod",
|
|
"&" => "and",
|
|
"*" => "mul",
|
|
"+" => "add",
|
|
"-" => "sub",
|
|
"/" => "div",
|
|
"<" => "lt",
|
|
">" => "gt",
|
|
"^" => "xor",
|
|
"`" => "tick",
|
|
"|" => "or",
|
|
"~" => "neg",
|
|
"!=" => "neq",
|
|
"!~" => "nmatch",
|
|
"&&" => "andand",
|
|
"**" => "pow",
|
|
"+@" => "plus",
|
|
"-@" => "minus",
|
|
"<<" => "lshift",
|
|
"<=" => "le",
|
|
"==" => "eq",
|
|
"=~" => "match",
|
|
">=" => "ge",
|
|
">>" => "rshift",
|
|
"[]" => "aref",
|
|
"||" => "oror",
|
|
"<=>" => "cmp",
|
|
"===" => "eqq",
|
|
"[]=" => "aset",
|
|
}.freeze
|
|
|
|
SYMBOL_TO_MACRO = {
|
|
# Symbol => Macro
|
|
# [prefix, suffix] => [prefix, suffix]
|
|
["@@" , "" ] => ["CV" , "" ],
|
|
["@" , "" ] => ["IV" , "" ],
|
|
["" , "!" ] => ["" , "_B" ],
|
|
["" , "?" ] => ["" , "_Q" ],
|
|
["" , "=" ] => ["" , "_E" ],
|
|
["" , "" ] => ["" , "" ],
|
|
}.freeze
|
|
|
|
C_STR_LITERAL_RE = /"(?:[^\\\"]|\\.)*"/
|
|
|
|
ESCAPE_SEQUENCE_MAP = {
|
|
"a" => "\a",
|
|
"b" => "\b",
|
|
"e" => "\e",
|
|
"f" => "\f",
|
|
"n" => "\n",
|
|
"r" => "\r",
|
|
"t" => "\t",
|
|
"v" => "\v",
|
|
}
|
|
ESCAPE_SEQUENCE_MAP.keys.each { |k| ESCAPE_SEQUENCE_MAP[ESCAPE_SEQUENCE_MAP[k]] = k }
|
|
|
|
def initialize(build)
|
|
@build = build
|
|
end
|
|
|
|
def scan(paths)
|
|
presym_hash = {}
|
|
paths.each {|path| read_preprocessed(presym_hash, path)}
|
|
presym_hash.keys.sort_by!{|sym| [c_literal_size(sym), sym]}
|
|
end
|
|
|
|
def read_list
|
|
File.readlines(list_path, mode: "r:binary").each(&:chomp!)
|
|
end
|
|
|
|
def write_list(presyms)
|
|
_pp "GEN", list_path.relative_path
|
|
File.binwrite(list_path, presyms.join("\n") << "\n")
|
|
end
|
|
|
|
def write_id_header(presyms)
|
|
prefix_re = Regexp.union(*SYMBOL_TO_MACRO.keys.map(&:first).uniq)
|
|
suffix_re = Regexp.union(*SYMBOL_TO_MACRO.keys.map(&:last).uniq)
|
|
sym_re = /\A(#{prefix_re})?([\w&&\D]\w*)(#{suffix_re})?\z/o
|
|
_pp "GEN", id_header_path.relative_path
|
|
File.open(id_header_path, "w:binary") do |f|
|
|
f.puts "enum mruby_presym {"
|
|
presyms.each.with_index(1) do |sym, num|
|
|
if sym_re =~ sym && (affixes = SYMBOL_TO_MACRO[[$1, $3]])
|
|
f.puts " MRB_#{affixes * 'SYM'}__#{$2} = #{num},"
|
|
elsif name = OPERATORS[sym]
|
|
f.puts " MRB_OPSYM__#{name} = #{num},"
|
|
end
|
|
end
|
|
f.puts "};"
|
|
f.puts
|
|
f.puts "#define MRB_PRESYM_MAX #{presyms.size}"
|
|
end
|
|
end
|
|
|
|
def write_table_header(presyms)
|
|
_pp "GEN", table_header_path.relative_path
|
|
File.open(table_header_path, "w:binary") do |f|
|
|
f.puts "static const uint16_t presym_length_table[] = {"
|
|
presyms.each{|sym| f.puts " #{sym.bytesize},\t/* #{sym} */"}
|
|
f.puts "};"
|
|
f.puts
|
|
f.puts "static const char * const presym_name_table[] = {"
|
|
presyms.each do |sym|
|
|
sym = sym.gsub(/([\x01-\x1f\x7f-\xff])|("|\\)/n) {
|
|
case
|
|
when $1
|
|
e = ESCAPE_SEQUENCE_MAP[$1]
|
|
e ? "\\#{e}" : '\\x%02x""' % $1.ord
|
|
when $2
|
|
"\\#$2"
|
|
end
|
|
}
|
|
f.puts %| "#{sym}",|
|
|
end
|
|
f.puts "};"
|
|
end
|
|
end
|
|
|
|
def list_path
|
|
@list_path ||= "#{@build.build_dir}/presym".freeze
|
|
end
|
|
|
|
def header_dir
|
|
@header_dir ||= "#{@build.build_dir}/include/mruby/presym".freeze
|
|
end
|
|
|
|
def id_header_path
|
|
@id_header_path ||= "#{header_dir}/id.h".freeze
|
|
end
|
|
|
|
def table_header_path
|
|
@table_header_path ||= "#{header_dir}/table.h".freeze
|
|
end
|
|
|
|
private
|
|
|
|
def read_preprocessed(presym_hash, path)
|
|
File.binread(path).scan(/<@! (.*?) !@>/) do |part,|
|
|
literals = part.scan(C_STR_LITERAL_RE)
|
|
unless literals.empty?
|
|
literals = literals.map{|l| l[1..-2]}
|
|
literals.each do |e|
|
|
e.gsub!(/\\x([0-9A-Fa-f]{1,2})|\\(0[0-7]{,3})|\\([abefnrtv])|\\(.)/) do
|
|
case
|
|
when $1; $1.hex.chr(Encoding::BINARY)
|
|
when $2; $2.oct.chr(Encoding::BINARY)
|
|
when $3; ESCAPE_SEQUENCE_MAP[$3]
|
|
when $4; $4
|
|
end
|
|
end
|
|
end
|
|
presym_hash[literals.join] = true
|
|
end
|
|
end
|
|
end
|
|
|
|
def c_literal_size(literal_without_quote)
|
|
literal_without_quote.size # TODO: consider escape sequence
|
|
end
|
|
end
|
|
end
|