You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
2.5 KiB
115 lines
2.5 KiB
3 years ago
|
require "sys"
|
||
|
require "filesystem"
|
||
|
require "util"
|
||
|
require "mpq_util"
|
||
|
|
||
|
native = {}
|
||
|
native.list = {}
|
||
|
native.file = {}
|
||
|
|
||
|
local function slice_cut(slice, pattern)
|
||
|
for i, s in ipairs(slice) do
|
||
|
local f, l = s:find(pattern)
|
||
|
if f then
|
||
|
slice[i] = s:sub(1, f-1)
|
||
|
table.insert(slice, i+1, s:sub(l+1))
|
||
|
return true
|
||
|
end
|
||
|
end
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
function native:inject(input, output)
|
||
|
local inbuf = io.load(input)
|
||
|
if not inbuf then
|
||
|
return false
|
||
|
end
|
||
|
local first, last = inbuf:find('endglobals\r')
|
||
|
if not first then
|
||
|
return false
|
||
|
end
|
||
|
local inject = {}
|
||
|
local inglobal = inbuf:sub(1, first-1)
|
||
|
local infunc = { inbuf:sub(last+1) }
|
||
|
for native, file in pairs(self.list) do
|
||
|
if slice_cut(infunc, native) then
|
||
|
inject[file] = self.file[file]
|
||
|
end
|
||
|
end
|
||
|
if not next(inject) then
|
||
|
return false
|
||
|
end
|
||
|
local global = { }
|
||
|
local func = { }
|
||
|
for _, buf in pairs(inject) do
|
||
|
local _, globals_first = buf:find('globals\r')
|
||
|
local globals_last, function_first = buf:find('endglobals\r')
|
||
|
if globals_first and globals_last then
|
||
|
table.insert(global, buf:sub(globals_first+1, globals_last-1))
|
||
|
else
|
||
|
function_first = -1
|
||
|
end
|
||
|
table.insert(func, buf:sub(function_first+1))
|
||
|
end
|
||
|
|
||
|
local t = {}
|
||
|
table.insert(t, inglobal)
|
||
|
table.move(global, 1, #global, #t+1, t)
|
||
|
table.insert(t, 'endglobals\r\n')
|
||
|
table.move(func, 1, #func, #t+1, t)
|
||
|
table.move(infunc, 1, #infunc, #t+1, t)
|
||
|
return io.save(output, table.concat(t))
|
||
|
end
|
||
|
|
||
|
function native:compile(op)
|
||
|
local native = fs.ydwe_path() / "jass" / "native"
|
||
|
if not fs.exists(native) or not next(self.list) then
|
||
|
return
|
||
|
end
|
||
|
log.info('Native compilation start.')
|
||
|
return mpq_util:update_file(op.map_path, 'war3map.j',
|
||
|
function (_, input)
|
||
|
local output = fs.ydwe_path() / "logs" / "native.j"
|
||
|
if not self:inject(input, output) then
|
||
|
return input
|
||
|
end
|
||
|
return output
|
||
|
end
|
||
|
)
|
||
|
end
|
||
|
|
||
|
function native:scan(path)
|
||
|
local buf = io.load(path)
|
||
|
if not buf then
|
||
|
return
|
||
|
end
|
||
|
local t = {}
|
||
|
local pos = 1
|
||
|
while true do
|
||
|
local f, l = buf:find('native %w+ takes [%w, ]+', pos)
|
||
|
if not f then
|
||
|
table.insert(t, buf:sub(pos+1))
|
||
|
break
|
||
|
end
|
||
|
local native = buf:sub(f, l)
|
||
|
self.list[native] = path
|
||
|
log.info('Native scan ', path, 'found', native)
|
||
|
table.insert(t, buf:sub(pos, f-1))
|
||
|
pos = l+1
|
||
|
end
|
||
|
self.file[path] = table.concat(t)
|
||
|
end
|
||
|
|
||
|
function native:initialize()
|
||
|
local native = fs.ydwe_path() / "jass" / "native"
|
||
|
if not fs.exists(native) then
|
||
|
return
|
||
|
end
|
||
|
for fullpath in native:list_directory() do
|
||
|
if fs.is_directory(fullpath) then
|
||
|
elseif fullpath:extension():string() == ".j" then
|
||
|
self:scan(fullpath)
|
||
|
end
|
||
|
end
|
||
|
end
|