mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 01:34:25 +00:00 
			
		
		
		
	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()
 |