diff options
author | Nicolas Hillegeer <nicolas@hillegeer.com> | 2014-04-28 14:12:51 +0200 |
---|---|---|
committer | Thiago de Arruda <tpadilha84@gmail.com> | 2014-04-28 16:17:25 -0300 |
commit | d699ccfb0c3500becfec9b02c24dc858d54c5a6e (patch) | |
tree | 7178b1a7c0a1b90275f94a71851fbc106eae8d0a /test/unit/helpers.moon | |
parent | 349f9da850fe46853663bff4ca199045a4678837 (diff) | |
download | rneovim-d699ccfb0c3500becfec9b02c24dc858d54c5a6e.tar.gz rneovim-d699ccfb0c3500becfec9b02c24dc858d54c5a6e.tar.bz2 rneovim-d699ccfb0c3500becfec9b02c24dc858d54c5a6e.zip |
test: fix the cimport method
This commit will hopefully allow the cimport method to be used just as one
would use #inclue <header.h> in C. It follows the following method:
1. create a pseudoheader file that #include's all the requested header files
2. runs the pseudoheader through the C preprocessor (it will try various
compilers if available on the system).
3. runs the preprocessed file through a C formatter, which attempts to group
statements on one line. For example, a struct definition that was
formerly on several lines will take just one line after formatting. This
is done so that unique declarations can be detected. Duplicates are thus
easy to remove.
4. remove lines that are too complex for the LuaJIT C parser (such as:
Objective-C block syntax, crazy enums defined on linux, ...)
5. remove duplicate declarations
6. pass result to ffi.cdef
Diffstat (limited to 'test/unit/helpers.moon')
-rw-r--r-- | test/unit/helpers.moon | 97 |
1 files changed, 81 insertions, 16 deletions
diff --git a/test/unit/helpers.moon b/test/unit/helpers.moon index 77d491a008..e84c569143 100644 --- a/test/unit/helpers.moon +++ b/test/unit/helpers.moon @@ -1,4 +1,19 @@ ffi = require 'ffi' +lpeg = require 'lpeg' +formatc = require 'test.unit.formatc' +Set = require 'test.unit.set' +Preprocess = require 'test.unit.preprocess' + +-- add some standard header locations +-- TODO(aktau, jszakmeister): optionally pass more header locations via env +Preprocess.add_to_include_path('./src') +Preprocess.add_to_include_path('./.deps/usr/include') +Preprocess.add_to_include_path('./build/config') + +if ffi.abi('32bit') + Preprocess.add_to_include_path('/opt/neovim-deps/32/include') +else + Preprocess.add_to_include_path('/opt/neovim-deps/include') -- load neovim shared library testlib = os.getenv 'NVIM_TEST_LIB' @@ -7,22 +22,72 @@ unless testlib libnvim = ffi.load testlib --- Luajit ffi parser doesn't understand preprocessor directives, so --- this helper function removes common directives before passing it the to ffi. --- It will return a pointer to the library table, emulating 'requires' -cimport = (path) -> - header_file = io.open path, 'rb' - - if not header_file - error "cannot find #{path}" - - header = header_file\read '*a' - header_file.close! - header = string.gsub header, '#include[^\n]*\n', '' - header = string.gsub header, '#ifndef[^\n]*\n', '' - header = string.gsub header, '#define[^\n]*\n', '' - header = string.gsub header, '#endif[^\n]*\n', '' - ffi.cdef header +trim = (s) -> + s\match'^%s*(.*%S)' or '' + +-- a Set that keeps around the lines we've already seen +export cdefs +if cdefs == nil + cdefs = Set! + +export imported +if imported == nil + imported = Set! + +-- some things are just too complex for the LuaJIT C parser to digest. We +-- usually don't need them anyway. +filter_complex_blocks = (body) -> + result = {} + for line in body\gmatch("[^\r\n]+") + -- remove all lines that contain Objective-C block syntax, the LuaJIT ffi + -- doesn't understand it. + if string.find(line, "(^)", 1, true) ~= nil + continue + if string.find(line, "_ISwupper", 1, true) ~= nil + continue + result[#result + 1] = line + table.concat(result, "\n") + +-- use this helper to import C files, you can pass multiple paths at once, +-- this helper will return the C namespace of the nvim library. +-- cimport = (path) -> +cimport = (...) -> + -- filter out paths we've already imported + paths = [path for path in *{...} when not imported\contains(path)] + for path in *paths + imported\add(path) + + if #paths == 0 + return libnvim + + -- preprocess the header + stream = Preprocess.preprocess_stream(unpack(paths)) + body = stream\read("*a") + stream\close! + + -- format it (so that the lines are "unique" statements), also filter out + -- Objective-C blocks + body = formatc(body) + body = filter_complex_blocks(body) + + -- add the formatted lines to a set + new_cdefs = Set! + for line in body\gmatch("[^\r\n]+") + new_cdefs\add(trim(line)) + + -- subtract the lines we've already imported from the new lines, then add + -- the new unique lines to the old lines (so they won't be imported again) + new_cdefs\diff(cdefs) + cdefs\union(new_cdefs) + + if new_cdefs\size! == 0 + -- if there's no new lines, just return + return libnvim + + -- request a sorted version of the new lines (same relative order as the + -- original preprocessed file) and feed that to the LuaJIT ffi + new_lines = new_cdefs\to_table! + ffi.cdef(table.concat(new_lines, "\n")) return libnvim |