mirror of
https://github.com/neovim/neovim.git
synced 2024-12-20 11:15:14 -07:00
34b5cee533
Pattern matching failed, because the preprocessor added additional linemarkers around type Bool.
262 lines
5.9 KiB
Lua
Executable File
262 lines
5.9 KiB
Lua
Executable File
#!/usr/bin/lua
|
|
|
|
local fname = arg[1]
|
|
local static_fname = arg[2]
|
|
local non_static_fname = arg[3]
|
|
local preproc_fname = arg[4]
|
|
|
|
|
|
local lpeg = require('lpeg')
|
|
|
|
local fold = function (func, ...)
|
|
local result = nil
|
|
for i, v in ipairs({...}) do
|
|
if result == nil then
|
|
result = v
|
|
else
|
|
result = func(result, v)
|
|
end
|
|
end
|
|
return result
|
|
end
|
|
|
|
local folder = function (func)
|
|
return function (...)
|
|
return fold(func, ...)
|
|
end
|
|
end
|
|
|
|
local lit = lpeg.P
|
|
local set = function(...)
|
|
return lpeg.S(fold(function (a, b) return a .. b end, ...))
|
|
end
|
|
local any_character = lpeg.P(1)
|
|
local rng = function(s, e) return lpeg.R(s .. e) end
|
|
local concat = folder(function (a, b) return a * b end)
|
|
local branch = folder(function (a, b) return a + b end)
|
|
local one_or_more = function(v) return v ^ 1 end
|
|
local two_or_more = function(v) return v ^ 2 end
|
|
local any_amount = function(v) return v ^ 0 end
|
|
local one_or_no = function(v) return v ^ -1 end
|
|
local look_behind = lpeg.B
|
|
local look_ahead = function(v) return #v end
|
|
local neg_look_ahead = function(v) return -v end
|
|
local neg_look_behind = function(v) return -look_behind(v) end
|
|
|
|
local w = branch(
|
|
rng('a', 'z'),
|
|
rng('A', 'Z'),
|
|
lit('_')
|
|
)
|
|
local aw = branch(
|
|
w,
|
|
rng('0', '9')
|
|
)
|
|
local s = set(' ', '\n', '\t')
|
|
local raw_word = concat(w, any_amount(aw))
|
|
local right_word = concat(
|
|
raw_word,
|
|
neg_look_ahead(aw)
|
|
)
|
|
local word = branch(
|
|
concat(
|
|
branch(lit('ArrayOf('), lit('DictionaryOf(')), -- typed container macro
|
|
one_or_more(any_character - lit(')')),
|
|
lit(')')
|
|
),
|
|
concat(
|
|
neg_look_behind(aw),
|
|
right_word
|
|
)
|
|
)
|
|
local spaces = any_amount(branch(
|
|
s,
|
|
-- Comments are really handled by preprocessor, so the following is not needed
|
|
concat(
|
|
lit('/*'),
|
|
any_amount(concat(
|
|
neg_look_ahead(lit('*/')),
|
|
any_character
|
|
)),
|
|
lit('*/')
|
|
),
|
|
concat(
|
|
lit('//'),
|
|
any_amount(concat(
|
|
neg_look_ahead(lit('\n')),
|
|
any_character
|
|
)),
|
|
lit('\n')
|
|
),
|
|
-- Linemarker inserted by preprocessor
|
|
concat(
|
|
lit('# '),
|
|
any_amount(concat(
|
|
neg_look_ahead(lit('\n')),
|
|
any_character
|
|
)),
|
|
lit('\n')
|
|
)
|
|
))
|
|
local typ_part = concat(
|
|
word,
|
|
any_amount(concat(
|
|
spaces,
|
|
lit('*')
|
|
)),
|
|
spaces
|
|
)
|
|
local typ = one_or_more(typ_part)
|
|
local typ_id = two_or_more(typ_part)
|
|
local arg = typ_id -- argument name is swallowed by typ
|
|
local pattern = concat(
|
|
typ_id, -- return type with function name
|
|
spaces,
|
|
lit('('),
|
|
spaces,
|
|
one_or_no(branch( -- function arguments
|
|
concat(
|
|
arg, -- first argument, does not require comma
|
|
any_amount(concat( -- following arguments, start with a comma
|
|
spaces,
|
|
lit(','),
|
|
spaces,
|
|
arg,
|
|
any_amount(concat(
|
|
lit('['),
|
|
spaces,
|
|
any_amount(aw),
|
|
spaces,
|
|
lit(']')
|
|
))
|
|
)),
|
|
one_or_no(concat(
|
|
spaces,
|
|
lit(','),
|
|
spaces,
|
|
lit('...')
|
|
))
|
|
),
|
|
lit('void') -- also accepts just void
|
|
)),
|
|
spaces,
|
|
lit(')'),
|
|
any_amount(concat( -- optional attributes
|
|
spaces,
|
|
lit('FUNC_ATTR_'),
|
|
any_amount(aw),
|
|
one_or_no(concat( -- attribute argument
|
|
spaces,
|
|
lit('('),
|
|
any_amount(concat(
|
|
neg_look_ahead(lit(')')),
|
|
any_character
|
|
)),
|
|
lit(')')
|
|
))
|
|
)),
|
|
look_ahead(concat( -- definition must be followed by "{"
|
|
spaces,
|
|
lit('{')
|
|
))
|
|
)
|
|
|
|
if fname == '--help' then
|
|
print'Usage:'
|
|
print()
|
|
print' gendeclarations.lua definitions.c static.h non-static.h preprocessor.i'
|
|
os.exit()
|
|
end
|
|
|
|
local preproc_f = io.open(preproc_fname)
|
|
local text = preproc_f:read("*all")
|
|
preproc_f:close()
|
|
|
|
|
|
local header = [[
|
|
#ifndef DEFINE_FUNC_ATTRIBUTES
|
|
# define DEFINE_FUNC_ATTRIBUTES
|
|
#endif
|
|
#include "nvim/func_attr.h"
|
|
#undef DEFINE_FUNC_ATTRIBUTES
|
|
]]
|
|
|
|
local footer = [[
|
|
#include "nvim/func_attr.h"
|
|
]]
|
|
|
|
local non_static = header
|
|
local static = header
|
|
|
|
local filepattern = '^#%a* %d+ "[^"]-/?([^"/]+)"'
|
|
local curfile
|
|
|
|
init = 0
|
|
curfile = nil
|
|
neededfile = fname:match('[^/]+$')
|
|
while init ~= nil do
|
|
init = text:find('\n', init)
|
|
if init == nil then
|
|
break
|
|
end
|
|
init = init + 1
|
|
if text:sub(init, init) == '#' then
|
|
file = text:match(filepattern, init)
|
|
if file ~= nil then
|
|
curfile = file
|
|
end
|
|
elseif curfile == neededfile then
|
|
s = init
|
|
e = pattern:match(text, init)
|
|
if e ~= nil then
|
|
local declaration = text:sub(s, e - 1)
|
|
-- Comments are really handled by preprocessor, so the following is not
|
|
-- needed
|
|
declaration = declaration:gsub('/%*.-%*/', '')
|
|
declaration = declaration:gsub('//.-\n', '\n')
|
|
|
|
declaration = declaration:gsub('# .-\n', '')
|
|
|
|
declaration = declaration:gsub('\n', ' ')
|
|
declaration = declaration:gsub('%s+', ' ')
|
|
declaration = declaration:gsub(' ?%( ?', '(')
|
|
-- declaration = declaration:gsub(' ?%) ?', ')')
|
|
declaration = declaration:gsub(' ?, ?', ', ')
|
|
declaration = declaration:gsub(' ?(%*+) ?', ' %1')
|
|
declaration = declaration:gsub(' ?(FUNC_ATTR_)', ' %1')
|
|
declaration = declaration:gsub(' $', '')
|
|
declaration = declaration .. ';\n'
|
|
if text:sub(s, s + 5) == 'static' then
|
|
static = static .. declaration
|
|
else
|
|
non_static = non_static .. declaration
|
|
end
|
|
init = e
|
|
end
|
|
end
|
|
end
|
|
|
|
non_static = non_static .. footer
|
|
static = static .. footer
|
|
|
|
local F
|
|
F = io.open(static_fname, 'w')
|
|
F:write(static)
|
|
F:close()
|
|
|
|
-- Before generating the non-static headers, check if the current file(if
|
|
-- exists) is different from the new one. If they are the same, we won't touch
|
|
-- the current version to avoid triggering an unnecessary rebuilds of modules
|
|
-- that depend on this one
|
|
F = io.open(non_static_fname, 'r')
|
|
if F ~= nil then
|
|
if F:read('*a') == non_static then
|
|
os.exit(0)
|
|
end
|
|
io.close(F)
|
|
end
|
|
|
|
F = io.open(non_static_fname, 'w')
|
|
F:write(non_static)
|
|
F:close()
|