aboutsummaryrefslogtreecommitdiff
path: root/test/unit/preprocess.lua
diff options
context:
space:
mode:
authorThiago de Arruda <tpadilha84@gmail.com>2014-08-30 11:56:52 -0300
committerNicolas Hillegeer <nicolas@hillegeer.com>2014-08-31 14:50:49 +0200
commit3a951112c099fc1b93766fabccd39cc65238cac5 (patch)
treef194311dbf66d8dab4efeadd4037cf81302b2dee /test/unit/preprocess.lua
parentd74ae5be9de985eee3e5026ffe0c639161ce82fc (diff)
downloadrneovim-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.lua198
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
+}