diff options
author | Thiago de Arruda <tpadilha84@gmail.com> | 2014-08-30 11:56:52 -0300 |
---|---|---|
committer | Nicolas Hillegeer <nicolas@hillegeer.com> | 2014-08-31 14:50:49 +0200 |
commit | 3a951112c099fc1b93766fabccd39cc65238cac5 (patch) | |
tree | f194311dbf66d8dab4efeadd4037cf81302b2dee /test/unit/preprocess.lua | |
parent | d74ae5be9de985eee3e5026ffe0c639161ce82fc (diff) | |
download | rneovim-3a951112c099fc1b93766fabccd39cc65238cac5.tar.gz rneovim-3a951112c099fc1b93766fabccd39cc65238cac5.tar.bz2 rneovim-3a951112c099fc1b93766fabccd39cc65238cac5.zip |
unittest: convert preprocess.moon to lua
Diffstat (limited to 'test/unit/preprocess.lua')
-rw-r--r-- | test/unit/preprocess.lua | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/test/unit/preprocess.lua b/test/unit/preprocess.lua new file mode 100644 index 0000000000..2405270328 --- /dev/null +++ b/test/unit/preprocess.lua @@ -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 +} |