mirror of
https://github.com/neovim/neovim.git
synced 2025-09-18 17:28:23 +00:00
build: move all generator scripts to src/gen/
- Move all generator Lua scripts to the `src/gen/` - Add a `.luarc.json` to `src/gen/` - Add a `preload.lua` to `src/gen/` - Add `src` to `package.path` so it aligns with `.luarc.json' - Fix all `require` statements in `src/gen/` so they are consistent: - `require('scripts.foo')` -> `require('gen.foo')` - `require('src.nvim.options')` -> `require('nvim.options')` - `require('api.dispatch_deprecated')` -> `require('nvim.api.dispatch_deprecated')`
This commit is contained in:

committed by
Lewis Russell

parent
85caaa70d4
commit
0f24b0826a
186
src/gen/gen_declarations.lua
Normal file
186
src/gen/gen_declarations.lua
Normal file
@@ -0,0 +1,186 @@
|
||||
local grammar = require('gen.c_grammar').grammar
|
||||
|
||||
--- @param fname string
|
||||
--- @return string?
|
||||
local function read_file(fname)
|
||||
local f = io.open(fname, 'r')
|
||||
if not f then
|
||||
return
|
||||
end
|
||||
local contents = f:read('*a')
|
||||
f:close()
|
||||
return contents
|
||||
end
|
||||
|
||||
--- @param fname string
|
||||
--- @param contents string[]
|
||||
local function write_file(fname, contents)
|
||||
local contents_s = table.concat(contents, '\n') .. '\n'
|
||||
local fcontents = read_file(fname)
|
||||
if fcontents == contents_s then
|
||||
return
|
||||
end
|
||||
local f = assert(io.open(fname, 'w'))
|
||||
f:write(contents_s)
|
||||
f:close()
|
||||
end
|
||||
|
||||
--- @param fname string
|
||||
--- @param non_static_fname string
|
||||
--- @return string? non_static
|
||||
local function add_iwyu_non_static(fname, non_static_fname)
|
||||
if fname:find('.*/src/nvim/.*%.c$') then
|
||||
-- Add an IWYU pragma comment if the corresponding .h file exists.
|
||||
local header_fname = fname:sub(1, -3) .. '.h'
|
||||
local header_f = io.open(header_fname, 'r')
|
||||
if header_f then
|
||||
header_f:close()
|
||||
return (header_fname:gsub('.*/src/nvim/', 'nvim/'))
|
||||
end
|
||||
elseif non_static_fname:find('/include/api/private/dispatch_wrappers%.h%.generated%.h$') then
|
||||
return 'nvim/api/private/dispatch.h'
|
||||
elseif non_static_fname:find('/include/ui_events_call%.h%.generated%.h$') then
|
||||
return 'nvim/ui.h'
|
||||
elseif non_static_fname:find('/include/ui_events_client%.h%.generated%.h$') then
|
||||
return 'nvim/ui_client.h'
|
||||
elseif non_static_fname:find('/include/ui_events_remote%.h%.generated%.h$') then
|
||||
return 'nvim/api/ui.h'
|
||||
end
|
||||
end
|
||||
|
||||
--- @param d string
|
||||
local function process_decl(d)
|
||||
-- Comments are really handled by preprocessor, so the following is not
|
||||
-- needed
|
||||
d = d:gsub('/%*.-%*/', '')
|
||||
d = d:gsub('//.-\n', '\n')
|
||||
d = d:gsub('# .-\n', '')
|
||||
d = d:gsub('\n', ' ')
|
||||
d = d:gsub('%s+', ' ')
|
||||
d = d:gsub(' ?%( ?', '(')
|
||||
d = d:gsub(' ?, ?', ', ')
|
||||
d = d:gsub(' ?(%*+) ?', ' %1')
|
||||
d = d:gsub(' ?(FUNC_ATTR_)', ' %1')
|
||||
d = d:gsub(' $', '')
|
||||
d = d:gsub('^ ', '')
|
||||
return d .. ';'
|
||||
end
|
||||
|
||||
--- @param fname string
|
||||
--- @param text string
|
||||
--- @return string[] static
|
||||
--- @return string[] non_static
|
||||
--- @return boolean any_static
|
||||
local function gen_declarations(fname, text)
|
||||
local non_static = {} --- @type string[]
|
||||
local static = {} --- @type string[]
|
||||
|
||||
local neededfile = fname:match('[^/]+$')
|
||||
local curfile = nil
|
||||
local any_static = false
|
||||
for _, node in ipairs(grammar:match(text)) do
|
||||
if node[1] == 'preproc' then
|
||||
curfile = node.content:match('^%a* %d+ "[^"]-/?([^"/]+)"') or curfile
|
||||
elseif node[1] == 'proto' and curfile == neededfile then
|
||||
local node_text = text:sub(node.pos, node.endpos - 1)
|
||||
local declaration = process_decl(node_text)
|
||||
|
||||
if node.static then
|
||||
if not any_static and declaration:find('FUNC_ATTR_') then
|
||||
any_static = true
|
||||
end
|
||||
static[#static + 1] = declaration
|
||||
else
|
||||
non_static[#non_static + 1] = 'DLLEXPORT ' .. declaration
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return static, non_static, any_static
|
||||
end
|
||||
|
||||
local usage = [[
|
||||
Usage:
|
||||
|
||||
gen_declarations.lua definitions.c static.h non-static.h definitions.i
|
||||
|
||||
Generates declarations for a C file definitions.c, putting declarations for
|
||||
static functions into static.h and declarations for non-static functions into
|
||||
non-static.h. File `definitions.i' should contain an already preprocessed
|
||||
version of definitions.c and it is the only one which is actually parsed,
|
||||
definitions.c is needed only to determine functions from which file out of all
|
||||
functions found in definitions.i are needed and to generate an IWYU comment.
|
||||
]]
|
||||
|
||||
local function main()
|
||||
local fname = arg[1]
|
||||
local static_fname = arg[2]
|
||||
local non_static_fname = arg[3]
|
||||
local preproc_fname = arg[4]
|
||||
local static_basename = arg[5]
|
||||
|
||||
if fname == '--help' or #arg < 5 then
|
||||
print(usage)
|
||||
os.exit()
|
||||
end
|
||||
|
||||
local text = assert(read_file(preproc_fname))
|
||||
|
||||
local static_decls, non_static_decls, any_static = gen_declarations(fname, text)
|
||||
|
||||
local static = {} --- @type string[]
|
||||
if fname:find('.*/src/nvim/.*%.h$') then
|
||||
static[#static + 1] = ('// IWYU pragma: private, include "%s"'):format(
|
||||
fname:gsub('.*/src/nvim/', 'nvim/')
|
||||
)
|
||||
end
|
||||
vim.list_extend(static, {
|
||||
'#define DEFINE_FUNC_ATTRIBUTES',
|
||||
'#include "nvim/func_attr.h"',
|
||||
'#undef DEFINE_FUNC_ATTRIBUTES',
|
||||
})
|
||||
vim.list_extend(static, static_decls)
|
||||
vim.list_extend(static, {
|
||||
'#define DEFINE_EMPTY_ATTRIBUTES',
|
||||
'#include "nvim/func_attr.h" // IWYU pragma: export',
|
||||
'',
|
||||
})
|
||||
|
||||
write_file(static_fname, static)
|
||||
|
||||
if any_static then
|
||||
local orig_text = assert(read_file(fname))
|
||||
local pat = '\n#%s?include%s+"' .. static_basename .. '"\n'
|
||||
local pat_comment = '\n#%s?include%s+"' .. static_basename .. '"%s*//'
|
||||
if not orig_text:find(pat) and not orig_text:find(pat_comment) then
|
||||
error(('fail: missing include for %s in %s'):format(static_basename, fname))
|
||||
end
|
||||
end
|
||||
|
||||
if non_static_fname ~= 'SKIP' then
|
||||
local non_static = {} --- @type string[]
|
||||
local iwyu_non_static = add_iwyu_non_static(fname, non_static_fname)
|
||||
if iwyu_non_static then
|
||||
non_static[#non_static + 1] = ('// IWYU pragma: private, include "%s"'):format(
|
||||
iwyu_non_static
|
||||
)
|
||||
end
|
||||
vim.list_extend(non_static, {
|
||||
'#define DEFINE_FUNC_ATTRIBUTES',
|
||||
'#include "nvim/func_attr.h"',
|
||||
'#undef DEFINE_FUNC_ATTRIBUTES',
|
||||
'#ifndef DLLEXPORT',
|
||||
'# ifdef MSWIN',
|
||||
'# define DLLEXPORT __declspec(dllexport)',
|
||||
'# else',
|
||||
'# define DLLEXPORT',
|
||||
'# endif',
|
||||
'#endif',
|
||||
})
|
||||
vim.list_extend(non_static, non_static_decls)
|
||||
non_static[#non_static + 1] = '#include "nvim/func_attr.h"'
|
||||
write_file(non_static_fname, non_static)
|
||||
end
|
||||
end
|
||||
|
||||
return main()
|
Reference in New Issue
Block a user