aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--test/unit/preprocess.lua198
-rw-r--r--test/unit/preprocess.moon158
2 files changed, 198 insertions, 158 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
+}
diff --git a/test/unit/preprocess.moon b/test/unit/preprocess.moon
deleted file mode 100644
index cb734da2f7..0000000000
--- a/test/unit/preprocess.moon
+++ /dev/null
@@ -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(...)
-}