mirror of
https://github.com/neovim/neovim.git
synced 2025-10-26 12:27:24 +00:00
unittest: convert preprocess.moon to lua
This commit is contained in:
committed by
Nicolas Hillegeer
parent
d74ae5be9d
commit
3a951112c0
198
test/unit/preprocess.lua
Normal file
198
test/unit/preprocess.lua
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
-- helps managing loading different headers into the LuaJIT ffi. Untested on
|
||||||
|
-- windows, will probably need quite a bit of adjustment to run there.
|
||||||
|
|
||||||
|
local ffi = require("ffi")
|
||||||
|
|
||||||
|
local ccs = {}
|
||||||
|
|
||||||
|
local env_cc = os.getenv("CC")
|
||||||
|
if env_cc then
|
||||||
|
table.insert(ccs, {path = "/usr/bin/env " .. tostring(env_cc), type = "gcc"})
|
||||||
|
end
|
||||||
|
|
||||||
|
if ffi.os == "Windows" then
|
||||||
|
table.insert(ccs, {path = "cl", type = "msvc"})
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(ccs, {path = "/usr/bin/env cc", type = "gcc"})
|
||||||
|
table.insert(ccs, {path = "/usr/bin/env gcc", type = "gcc"})
|
||||||
|
table.insert(ccs, {path = "/usr/bin/env gcc-4.9", type = "gcc"})
|
||||||
|
table.insert(ccs, {path = "/usr/bin/env gcc-4.8", type = "gcc"})
|
||||||
|
table.insert(ccs, {path = "/usr/bin/env gcc-4.7", type = "gcc"})
|
||||||
|
table.insert(ccs, {path = "/usr/bin/env clang", type = "clang"})
|
||||||
|
table.insert(ccs, {path = "/usr/bin/env icc", type = "gcc"})
|
||||||
|
|
||||||
|
local quote_me = '[^%w%+%-%=%@%_%/]' -- complement (needn't quote)
|
||||||
|
function shell_quote(str)
|
||||||
|
if string.find(str, quote_me) or str == '' then
|
||||||
|
return "'" .. string.gsub(str, "'", [['"'"']]) .. "'"
|
||||||
|
else
|
||||||
|
return str
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- parse Makefile format dependencies into a Lua table
|
||||||
|
function parse_make_deps(deps)
|
||||||
|
-- remove line breaks and line concatenators
|
||||||
|
deps = deps:gsub("\n", ""):gsub("\\", "")
|
||||||
|
-- remove the Makefile "target:" element
|
||||||
|
deps = deps:gsub(".+:", "")
|
||||||
|
-- remove redundant spaces
|
||||||
|
deps = deps:gsub(" +", " ")
|
||||||
|
|
||||||
|
-- split according to token (space in this case)
|
||||||
|
local headers = {}
|
||||||
|
for token in deps:gmatch("[^%s]+") do
|
||||||
|
-- headers[token] = true
|
||||||
|
headers[#headers + 1] = token
|
||||||
|
end
|
||||||
|
|
||||||
|
-- resolve path redirections (..) to normalize all paths
|
||||||
|
for i, v in ipairs(headers) do
|
||||||
|
-- double dots (..)
|
||||||
|
headers[i] = v:gsub("/[^/%s]+/%.%.", "")
|
||||||
|
-- single dot (.)
|
||||||
|
headers[i] = v:gsub("%./", "")
|
||||||
|
end
|
||||||
|
|
||||||
|
return headers
|
||||||
|
end
|
||||||
|
|
||||||
|
-- will produce a string that represents a meta C header file that includes
|
||||||
|
-- all the passed in headers. I.e.:
|
||||||
|
--
|
||||||
|
-- headerize({"stdio.h", "math.h", true}
|
||||||
|
-- produces:
|
||||||
|
-- #include <stdio.h>
|
||||||
|
-- #include <math.h>
|
||||||
|
--
|
||||||
|
-- headerize({"vim.h", "memory.h", false}
|
||||||
|
-- produces:
|
||||||
|
-- #include "vim.h"
|
||||||
|
-- #include "memory.h"
|
||||||
|
function headerize(headers, global)
|
||||||
|
local pre = '"'
|
||||||
|
local post = pre
|
||||||
|
if global then
|
||||||
|
pre = "<"
|
||||||
|
post = ">"
|
||||||
|
end
|
||||||
|
|
||||||
|
local formatted = {}
|
||||||
|
for i = 1, #headers do
|
||||||
|
local hdr = headers[i]
|
||||||
|
formatted[#formatted + 1] = "#include " ..
|
||||||
|
tostring(pre) ..
|
||||||
|
tostring(hdr) ..
|
||||||
|
tostring(post)
|
||||||
|
end
|
||||||
|
|
||||||
|
return table.concat(formatted, "\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
local Gcc = {
|
||||||
|
-- preprocessor flags that will hopefully make the compiler produce C
|
||||||
|
-- declarations that the LuaJIT ffi understands.
|
||||||
|
preprocessor_extra_flags = {
|
||||||
|
'-D "aligned(ARGS)="',
|
||||||
|
'-D "__attribute__(ARGS)="',
|
||||||
|
'-D "__asm(ARGS)="',
|
||||||
|
'-D "__asm__(ARGS)="',
|
||||||
|
'-D "__inline__="',
|
||||||
|
'-D "EXTERN=extern"',
|
||||||
|
'-D "INIT(...)="',
|
||||||
|
'-D_GNU_SOURCE',
|
||||||
|
'-DINCLUDE_GENERATED_DECLARATIONS'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Gcc:new(obj)
|
||||||
|
obj = obj or {}
|
||||||
|
setmetatable(obj, self)
|
||||||
|
self.__index = self
|
||||||
|
return obj
|
||||||
|
end
|
||||||
|
|
||||||
|
function Gcc:add_to_include_path(...)
|
||||||
|
local paths = {...}
|
||||||
|
for i = 1, #paths do
|
||||||
|
local path = paths[i]
|
||||||
|
local directive = '-I ' .. '"' .. path .. '"'
|
||||||
|
local ef = self.preprocessor_extra_flags
|
||||||
|
ef[#ef + 1] = directive
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- returns a list of the headers files upon which this file relies
|
||||||
|
function Gcc:dependencies(hdr)
|
||||||
|
local out = io.popen(tostring(self.path) .. " -M " .. tostring(hdr) .. " 2>&1")
|
||||||
|
local deps = out:read("*a")
|
||||||
|
out:close()
|
||||||
|
if deps then
|
||||||
|
return parse_make_deps(deps)
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- returns a stream representing a preprocessed form of the passed-in headers.
|
||||||
|
-- Don't forget to close the stream by calling the close() method on it.
|
||||||
|
function Gcc:preprocess_stream(...)
|
||||||
|
-- create pseudo-header
|
||||||
|
local pseudoheader = headerize({...}, false)
|
||||||
|
local defines = table.concat(self.preprocessor_extra_flags, ' ')
|
||||||
|
local cmd = ("echo $hdr | " ..
|
||||||
|
tostring(self.path) ..
|
||||||
|
" " ..
|
||||||
|
tostring(defines) ..
|
||||||
|
" -std=c99 -P -E -"):gsub('$hdr', shell_quote(pseudoheader))
|
||||||
|
-- lfs = require("lfs")
|
||||||
|
-- print("CWD: #{lfs.currentdir!}")
|
||||||
|
-- print("CMD: #{cmd}")
|
||||||
|
-- io.stderr\write("CWD: #{lfs.currentdir!}\n")
|
||||||
|
-- io.stderr\write("CMD: #{cmd}\n")
|
||||||
|
return io.popen(cmd)
|
||||||
|
end
|
||||||
|
|
||||||
|
local Clang = Gcc:new()
|
||||||
|
local Msvc = Gcc:new()
|
||||||
|
|
||||||
|
local type_to_class = {
|
||||||
|
["gcc"] = Gcc,
|
||||||
|
["clang"] = Clang,
|
||||||
|
["msvc"] = Msvc
|
||||||
|
}
|
||||||
|
|
||||||
|
-- find the best cc. If os.exec causes problems on windows (like popping up
|
||||||
|
-- a console window) we might consider using something like this:
|
||||||
|
-- http://scite-ru.googlecode.com/svn/trunk/pack/tools/LuaLib/shell.html#exec
|
||||||
|
function find_best_cc(ccs)
|
||||||
|
for _, meta in pairs(ccs) do
|
||||||
|
local version = io.popen(tostring(meta.path) .. " -v 2>&1")
|
||||||
|
version:close()
|
||||||
|
if version then
|
||||||
|
return type_to_class[meta.type]:new({path = meta.path})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- find the best cc. If os.exec causes problems on windows (like popping up
|
||||||
|
-- a console window) we might consider using something like this:
|
||||||
|
-- http://scite-ru.googlecode.com/svn/trunk/pack/tools/LuaLib/shell.html#exec
|
||||||
|
local cc = nil
|
||||||
|
if cc == nil then
|
||||||
|
cc = find_best_cc(ccs)
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
includes = function(hdr)
|
||||||
|
return cc:dependencies(hdr)
|
||||||
|
end,
|
||||||
|
preprocess_stream = function(...)
|
||||||
|
return cc:preprocess_stream(...)
|
||||||
|
end,
|
||||||
|
add_to_include_path = function(...)
|
||||||
|
return cc:add_to_include_path(...)
|
||||||
|
end
|
||||||
|
}
|
||||||
@@ -1,158 +0,0 @@
|
|||||||
-- helps managing loading different headers into the LuaJIT ffi. Untested on
|
|
||||||
-- windows, will probably need quite a bit of adjustment to run there.
|
|
||||||
|
|
||||||
ffi = require("ffi")
|
|
||||||
|
|
||||||
ccs = {}
|
|
||||||
|
|
||||||
env_cc = os.getenv("CC")
|
|
||||||
if env_cc
|
|
||||||
table.insert(ccs, {path: "/usr/bin/env #{env_cc}", type: "gcc"})
|
|
||||||
|
|
||||||
if ffi.os == "Windows"
|
|
||||||
table.insert(ccs, {path: "cl", type: "msvc"})
|
|
||||||
|
|
||||||
table.insert(ccs, {path: "/usr/bin/env cc", type: "gcc"})
|
|
||||||
table.insert(ccs, {path: "/usr/bin/env gcc", type: "gcc"})
|
|
||||||
table.insert(ccs, {path: "/usr/bin/env gcc-4.9", type: "gcc"})
|
|
||||||
table.insert(ccs, {path: "/usr/bin/env gcc-4.8", type: "gcc"})
|
|
||||||
table.insert(ccs, {path: "/usr/bin/env gcc-4.7", type: "gcc"})
|
|
||||||
table.insert(ccs, {path: "/usr/bin/env clang", type: "clang"})
|
|
||||||
table.insert(ccs, {path: "/usr/bin/env icc", type: "gcc"})
|
|
||||||
|
|
||||||
quote_me = '[^%w%+%-%=%@%_%/]' -- complement (needn't quote)
|
|
||||||
shell_quote = (str) ->
|
|
||||||
if string.find(str, quote_me) or str == '' then
|
|
||||||
"'" .. string.gsub(str, "'", [['"'"']]) .. "'"
|
|
||||||
else
|
|
||||||
str
|
|
||||||
|
|
||||||
-- parse Makefile format dependencies into a Lua table
|
|
||||||
parse_make_deps = (deps) ->
|
|
||||||
-- remove line breaks and line concatenators
|
|
||||||
deps = deps\gsub("\n", "")\gsub("\\", "")
|
|
||||||
|
|
||||||
-- remove the Makefile "target:" element
|
|
||||||
deps = deps\gsub(".+:", "")
|
|
||||||
|
|
||||||
-- remove redundant spaces
|
|
||||||
deps = deps\gsub(" +", " ")
|
|
||||||
|
|
||||||
-- split according to token (space in this case)
|
|
||||||
headers = {}
|
|
||||||
for token in deps\gmatch("[^%s]+")
|
|
||||||
-- headers[token] = true
|
|
||||||
headers[#headers + 1] = token
|
|
||||||
|
|
||||||
-- resolve path redirections (..) to normalize all paths
|
|
||||||
for i, v in ipairs(headers)
|
|
||||||
-- double dots (..)
|
|
||||||
headers[i] = v\gsub("/[^/%s]+/%.%.", "")
|
|
||||||
|
|
||||||
-- single dot (.)
|
|
||||||
headers[i] = v\gsub("%./", "")
|
|
||||||
|
|
||||||
headers
|
|
||||||
|
|
||||||
-- will produce a string that represents a meta C header file that includes
|
|
||||||
-- all the passed in headers. I.e.:
|
|
||||||
--
|
|
||||||
-- headerize({"stdio.h", "math.h", true}
|
|
||||||
-- produces:
|
|
||||||
-- #include <stdio.h>
|
|
||||||
-- #include <math.h>
|
|
||||||
--
|
|
||||||
-- headerize({"vim.h", "memory.h", false}
|
|
||||||
-- produces:
|
|
||||||
-- #include "vim.h"
|
|
||||||
-- #include "memory.h"
|
|
||||||
headerize = (headers, global) ->
|
|
||||||
pre = '"'
|
|
||||||
post = pre
|
|
||||||
if global
|
|
||||||
pre = "<"
|
|
||||||
post = ">"
|
|
||||||
|
|
||||||
formatted = ["#include #{pre}#{hdr}#{post}" for hdr in *headers]
|
|
||||||
table.concat(formatted, "\n")
|
|
||||||
|
|
||||||
class Gcc
|
|
||||||
-- preprocessor flags that will hopefully make the compiler produce C
|
|
||||||
-- declarations that the LuaJIT ffi understands.
|
|
||||||
@@preprocessor_extra_flags = {
|
|
||||||
'-D "aligned(ARGS)="',
|
|
||||||
'-D "__attribute__(ARGS)="',
|
|
||||||
'-D "__asm(ARGS)="',
|
|
||||||
'-D "__asm__(ARGS)="',
|
|
||||||
'-D "__inline__="',
|
|
||||||
'-D "EXTERN=extern"',
|
|
||||||
'-D "INIT(...)="',
|
|
||||||
'-D_GNU_SOURCE',
|
|
||||||
'-DINCLUDE_GENERATED_DECLARATIONS'
|
|
||||||
}
|
|
||||||
|
|
||||||
new: (path) =>
|
|
||||||
@path = path
|
|
||||||
|
|
||||||
add_to_include_path: (...) =>
|
|
||||||
paths = {...}
|
|
||||||
for path in *paths
|
|
||||||
directive = '-I ' .. '"' .. path .. '"'
|
|
||||||
@@preprocessor_extra_flags[#@@preprocessor_extra_flags + 1] = directive
|
|
||||||
|
|
||||||
-- returns a list of the headers files upon which this file relies
|
|
||||||
dependencies: (hdr) =>
|
|
||||||
out = io.popen("#{@path} -M #{hdr} 2>&1")
|
|
||||||
deps = out\read("*a")
|
|
||||||
out\close!
|
|
||||||
|
|
||||||
if deps
|
|
||||||
parse_make_deps(deps)
|
|
||||||
else
|
|
||||||
nil
|
|
||||||
|
|
||||||
-- returns a stream representing a preprocessed form of the passed-in
|
|
||||||
-- headers. Don't forget to close the stream by calling the close() method
|
|
||||||
-- on it.
|
|
||||||
preprocess_stream: (...) =>
|
|
||||||
paths = {...}
|
|
||||||
-- create pseudo-header
|
|
||||||
pseudoheader = headerize(paths, false)
|
|
||||||
defines = table.concat(@@preprocessor_extra_flags, ' ')
|
|
||||||
cmd = ("echo $hdr | #{@path} #{defines} -std=c99 -P -E -")\gsub('$hdr', shell_quote(pseudoheader))
|
|
||||||
-- lfs = require("lfs")
|
|
||||||
-- print("CWD: #{lfs.currentdir!}")
|
|
||||||
-- print("CMD: #{cmd}")
|
|
||||||
-- io.stderr\write("CWD: #{lfs.currentdir!}\n")
|
|
||||||
-- io.stderr\write("CMD: #{cmd}\n")
|
|
||||||
io.popen(cmd)
|
|
||||||
|
|
||||||
class Clang extends Gcc
|
|
||||||
class Msvc extends Gcc
|
|
||||||
|
|
||||||
type_to_class = {
|
|
||||||
"gcc": Gcc,
|
|
||||||
"clang": Clang,
|
|
||||||
"msvc": Msvc
|
|
||||||
}
|
|
||||||
|
|
||||||
find_best_cc = (ccs) ->
|
|
||||||
for _, meta in pairs(ccs)
|
|
||||||
version = io.popen("#{meta.path} -v 2>&1")
|
|
||||||
version\close!
|
|
||||||
if version
|
|
||||||
return type_to_class[meta.type](meta.path)
|
|
||||||
nil
|
|
||||||
|
|
||||||
-- find the best cc. If os.exec causes problems on windows (like popping up
|
|
||||||
-- a console window) we might consider using something like this:
|
|
||||||
-- http://scite-ru.googlecode.com/svn/trunk/pack/tools/LuaLib/shell.html#exec
|
|
||||||
cc = nil
|
|
||||||
if cc == nil
|
|
||||||
cc = find_best_cc(ccs)
|
|
||||||
|
|
||||||
return {
|
|
||||||
includes: (hdr) -> cc\dependencies(hdr)
|
|
||||||
preprocess_stream: (...) -> cc\preprocess_stream(...)
|
|
||||||
add_to_include_path: (...) -> cc\add_to_include_path(...)
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user