mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 01:34:25 +00:00 
			
		
		
		
	api: move verbatim c code out of gendispatch.lua and into c files
Remove max_fname_len check, which caused false successful lookups, and was an optimization for a very rare case.
This commit is contained in:
		@@ -52,16 +52,18 @@ package.path = nvimsrcdir .. '/?.lua;' .. package.path
 | 
			
		||||
-- names of all headers relative to the source root (for inclusion in the
 | 
			
		||||
-- generated file)
 | 
			
		||||
headers = {}
 | 
			
		||||
-- output c file(dispatch function + metadata serialized with msgpack)
 | 
			
		||||
outputf = arg[#arg-1]
 | 
			
		||||
-- output mpack file (metadata)
 | 
			
		||||
-- output h file with generated dispatch functions
 | 
			
		||||
dispatch_outputf = arg[#arg-2]
 | 
			
		||||
-- output h file with packed metadata
 | 
			
		||||
funcs_metadata_outputf = arg[#arg-1]
 | 
			
		||||
-- output metadata mpack file, for use by other build scripts
 | 
			
		||||
mpack_outputf = arg[#arg]
 | 
			
		||||
 | 
			
		||||
-- set of function names, used to detect duplicates
 | 
			
		||||
function_names = {}
 | 
			
		||||
 | 
			
		||||
-- read each input file, parse and append to the api metadata
 | 
			
		||||
for i = 2, #arg - 2 do
 | 
			
		||||
for i = 2, #arg - 3 do
 | 
			
		||||
  local full_path = arg[i]
 | 
			
		||||
  local parts = {}
 | 
			
		||||
  for part in string.gmatch(full_path, '[^/]+') do
 | 
			
		||||
@@ -165,66 +167,27 @@ for _,f in ipairs(functions) do
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
-- start building the output
 | 
			
		||||
output = io.open(outputf, 'wb')
 | 
			
		||||
 | 
			
		||||
output:write([[
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <msgpack.h>
 | 
			
		||||
 | 
			
		||||
#include "nvim/map.h"
 | 
			
		||||
#include "nvim/log.h"
 | 
			
		||||
#include "nvim/vim.h"
 | 
			
		||||
#include "nvim/msgpack_rpc/helpers.h"
 | 
			
		||||
#include "nvim/api/private/dispatch.h"
 | 
			
		||||
#include "nvim/api/private/helpers.h"
 | 
			
		||||
#include "nvim/api/private/defs.h"
 | 
			
		||||
funcs_metadata_output = io.open(funcs_metadata_outputf, 'wb')
 | 
			
		||||
funcs_metadata_output:write([[
 | 
			
		||||
static const uint8_t funcs_metadata[] = {
 | 
			
		||||
]])
 | 
			
		||||
 | 
			
		||||
for i = 1, #headers do
 | 
			
		||||
  if headers[i]:sub(-12) ~= '.generated.h' then
 | 
			
		||||
    output:write('\n#include "nvim/'..headers[i]..'"')
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
output:write([[
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static const uint8_t msgpack_metadata[] = {
 | 
			
		||||
 | 
			
		||||
]])
 | 
			
		||||
-- serialize the API metadata using msgpack and embed into the resulting
 | 
			
		||||
-- binary for easy querying by clients
 | 
			
		||||
packed_exported_functions = mpack.pack(exported_functions)
 | 
			
		||||
for i = 1, #packed_exported_functions do
 | 
			
		||||
  output:write(string.byte(packed_exported_functions, i)..', ')
 | 
			
		||||
  funcs_metadata_output:write(string.byte(packed_exported_functions, i)..', ')
 | 
			
		||||
  if i % 10 == 0 then
 | 
			
		||||
    output:write('\n  ')
 | 
			
		||||
    funcs_metadata_output:write('\n  ')
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
output:write([[
 | 
			
		||||
funcs_metadata_output:write([[
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void msgpack_rpc_init_function_metadata(Dictionary *metadata)
 | 
			
		||||
{
 | 
			
		||||
  msgpack_unpacked unpacked;
 | 
			
		||||
  msgpack_unpacked_init(&unpacked);
 | 
			
		||||
  if (msgpack_unpack_next(&unpacked,
 | 
			
		||||
                          (const char *)msgpack_metadata,
 | 
			
		||||
                          sizeof(msgpack_metadata),
 | 
			
		||||
                          NULL) != MSGPACK_UNPACK_SUCCESS) {
 | 
			
		||||
    abort();
 | 
			
		||||
  }
 | 
			
		||||
  Object functions;
 | 
			
		||||
  msgpack_rpc_to_object(&unpacked.data, &functions);
 | 
			
		||||
  msgpack_unpacked_destroy(&unpacked);
 | 
			
		||||
  PUT(*metadata, "functions", functions);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
]])
 | 
			
		||||
funcs_metadata_output:close()
 | 
			
		||||
 | 
			
		||||
-- start building the dispatch wrapper output
 | 
			
		||||
output = io.open(dispatch_outputf, 'wb')
 | 
			
		||||
 | 
			
		||||
local function real_type(type)
 | 
			
		||||
  local rv = type
 | 
			
		||||
@@ -336,22 +299,12 @@ end
 | 
			
		||||
 | 
			
		||||
-- Generate a function that initializes method names with handler functions
 | 
			
		||||
output:write([[
 | 
			
		||||
static Map(String, MsgpackRpcRequestHandler) *methods = NULL;
 | 
			
		||||
 | 
			
		||||
void msgpack_rpc_add_method_handler(String method, MsgpackRpcRequestHandler handler)
 | 
			
		||||
{
 | 
			
		||||
  map_put(String, MsgpackRpcRequestHandler)(methods, method, handler);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void msgpack_rpc_init_method_table(void)
 | 
			
		||||
{
 | 
			
		||||
  methods = map_new(String, MsgpackRpcRequestHandler)();
 | 
			
		||||
 | 
			
		||||
]])
 | 
			
		||||
 | 
			
		||||
-- Keep track of the maximum method name length in order to avoid walking
 | 
			
		||||
-- strings longer than that when searching for a method handler
 | 
			
		||||
local max_fname_len = 0
 | 
			
		||||
for i = 1, #functions do
 | 
			
		||||
  local fn = functions[i]
 | 
			
		||||
  output:write('  msgpack_rpc_add_method_handler('..
 | 
			
		||||
@@ -360,32 +313,9 @@ for i = 1, #functions do
 | 
			
		||||
               '(MsgpackRpcRequestHandler) {.fn = handle_'..  (fn.impl_name or fn.name)..
 | 
			
		||||
               ', .async = '..tostring(fn.async)..'});\n')
 | 
			
		||||
 | 
			
		||||
  if #fn.name > max_fname_len then
 | 
			
		||||
    max_fname_len = #fn.name
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
output:write('\n}\n\n')
 | 
			
		||||
 | 
			
		||||
output:write([[
 | 
			
		||||
MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name,
 | 
			
		||||
                                                     size_t name_len)
 | 
			
		||||
{
 | 
			
		||||
  String m = {
 | 
			
		||||
    .data=(char *)name,
 | 
			
		||||
    .size=MIN(name_len, ]]..max_fname_len..[[)
 | 
			
		||||
  };
 | 
			
		||||
  MsgpackRpcRequestHandler rv =
 | 
			
		||||
    map_get(String, MsgpackRpcRequestHandler)(methods, m);
 | 
			
		||||
 | 
			
		||||
  if (!rv.fn) {
 | 
			
		||||
    rv.fn = msgpack_rpc_handle_missing_method;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return rv;
 | 
			
		||||
}
 | 
			
		||||
]])
 | 
			
		||||
 | 
			
		||||
output:close()
 | 
			
		||||
 | 
			
		||||
mpack_output = io.open(mpack_outputf, 'wb')
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,8 @@ set(API_METADATA ${PROJECT_BINARY_DIR}/api_metadata.mpack)
 | 
			
		||||
set(FUNCS_DATA ${PROJECT_BINARY_DIR}/funcs_data.mpack)
 | 
			
		||||
set(HEADER_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gendeclarations.lua)
 | 
			
		||||
set(GENERATED_INCLUDES_DIR ${PROJECT_BINARY_DIR}/include)
 | 
			
		||||
set(GENERATED_API_DISPATCH ${GENERATED_DIR}/api/private/dispatch.c)
 | 
			
		||||
set(GENERATED_API_DISPATCH ${GENERATED_DIR}/api/private/dispatch_wrappers.generated.h)
 | 
			
		||||
set(GENERATED_FUNCS_METADATA ${GENERATED_DIR}/api/private/funcs_metadata.generated.h)
 | 
			
		||||
set(GENERATED_EX_CMDS_ENUM ${GENERATED_INCLUDES_DIR}/ex_cmds_enum.generated.h)
 | 
			
		||||
set(GENERATED_EX_CMDS_DEFS ${GENERATED_DIR}/ex_cmds_defs.generated.h)
 | 
			
		||||
set(GENERATED_FUNCS_HASH_INPUT ${GENERATED_DIR}/funcs.generated.h.gperf)
 | 
			
		||||
@@ -197,8 +198,11 @@ add_custom_command(OUTPUT ${GENERATED_UNICODE_TABLES}
 | 
			
		||||
    ${UNICODE_FILES}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
add_custom_command(OUTPUT ${GENERATED_API_DISPATCH} ${API_METADATA}
 | 
			
		||||
    COMMAND ${LUA_PRG} ${DISPATCH_GENERATOR} ${CMAKE_CURRENT_LIST_DIR} ${API_HEADERS} ${GENERATED_API_DISPATCH} ${API_METADATA}
 | 
			
		||||
add_custom_command(OUTPUT ${GENERATED_API_DISPATCH} ${GENERATED_FUNCS_METADATA}
 | 
			
		||||
                          ${API_METADATA}
 | 
			
		||||
  COMMAND ${LUA_PRG} ${DISPATCH_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}
 | 
			
		||||
                     ${API_HEADERS} ${GENERATED_API_DISPATCH}
 | 
			
		||||
                     ${GENERATED_FUNCS_METADATA} ${API_METADATA}
 | 
			
		||||
  DEPENDS
 | 
			
		||||
    ${API_HEADERS}
 | 
			
		||||
    ${MSGPACK_RPC_HEADERS}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										45
									
								
								src/nvim/api/private/dispatch.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/nvim/api/private/dispatch.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <msgpack.h>
 | 
			
		||||
 | 
			
		||||
#include "nvim/map.h"
 | 
			
		||||
#include "nvim/log.h"
 | 
			
		||||
#include "nvim/vim.h"
 | 
			
		||||
#include "nvim/msgpack_rpc/helpers.h"
 | 
			
		||||
#include "nvim/api/private/dispatch.h"
 | 
			
		||||
#include "nvim/api/private/helpers.h"
 | 
			
		||||
#include "nvim/api/private/defs.h"
 | 
			
		||||
 | 
			
		||||
#include "nvim/api/buffer.h"
 | 
			
		||||
#include "nvim/api/tabpage.h"
 | 
			
		||||
#include "nvim/api/ui.h"
 | 
			
		||||
#include "nvim/api/vim.h"
 | 
			
		||||
#include "nvim/api/window.h"
 | 
			
		||||
 | 
			
		||||
static Map(String, MsgpackRpcRequestHandler) *methods = NULL;
 | 
			
		||||
 | 
			
		||||
static void msgpack_rpc_add_method_handler(String method,
 | 
			
		||||
                                           MsgpackRpcRequestHandler handler)
 | 
			
		||||
{
 | 
			
		||||
  map_put(String, MsgpackRpcRequestHandler)(methods, method, handler);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name,
 | 
			
		||||
                                                     size_t name_len)
 | 
			
		||||
{
 | 
			
		||||
  String m = { .data = (char *)name, .size = name_len };
 | 
			
		||||
  MsgpackRpcRequestHandler rv =
 | 
			
		||||
    map_get(String, MsgpackRpcRequestHandler)(methods, m);
 | 
			
		||||
 | 
			
		||||
  if (!rv.fn) {
 | 
			
		||||
    rv.fn = msgpack_rpc_handle_missing_method;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return rv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
			
		||||
#include "api/private/dispatch_wrappers.generated.h"
 | 
			
		||||
#endif
 | 
			
		||||
@@ -18,6 +18,7 @@ typedef struct {
 | 
			
		||||
 | 
			
		||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
			
		||||
# include "api/private/dispatch.h.generated.h"
 | 
			
		||||
# include "api/private/dispatch_wrappers.h.generated.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif  // NVIM_API_PRIVATE_DISPATCH_H
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@
 | 
			
		||||
#include "nvim/api/private/helpers.h"
 | 
			
		||||
#include "nvim/api/private/defs.h"
 | 
			
		||||
#include "nvim/api/private/handle.h"
 | 
			
		||||
#include "nvim/msgpack_rpc/helpers.h"
 | 
			
		||||
#include "nvim/ascii.h"
 | 
			
		||||
#include "nvim/vim.h"
 | 
			
		||||
#include "nvim/buffer.h"
 | 
			
		||||
@@ -27,6 +28,7 @@ typedef struct {
 | 
			
		||||
 | 
			
		||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
			
		||||
# include "api/private/helpers.c.generated.h"
 | 
			
		||||
# include "api/private/funcs_metadata.generated.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/// Start block that may cause vimscript exceptions
 | 
			
		||||
@@ -761,7 +763,7 @@ Dictionary api_metadata(void)
 | 
			
		||||
  static Dictionary metadata = ARRAY_DICT_INIT;
 | 
			
		||||
 | 
			
		||||
  if (!metadata.size) {
 | 
			
		||||
    msgpack_rpc_init_function_metadata(&metadata);
 | 
			
		||||
    init_function_metadata(&metadata);
 | 
			
		||||
    init_error_type_metadata(&metadata);
 | 
			
		||||
    init_type_metadata(&metadata);
 | 
			
		||||
  }
 | 
			
		||||
@@ -769,6 +771,22 @@ Dictionary api_metadata(void)
 | 
			
		||||
  return copy_object(DICTIONARY_OBJ(metadata)).data.dictionary;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void init_function_metadata(Dictionary *metadata)
 | 
			
		||||
{
 | 
			
		||||
  msgpack_unpacked unpacked;
 | 
			
		||||
  msgpack_unpacked_init(&unpacked);
 | 
			
		||||
  if (msgpack_unpack_next(&unpacked,
 | 
			
		||||
                          (const char *)funcs_metadata,
 | 
			
		||||
                          sizeof(funcs_metadata),
 | 
			
		||||
                          NULL) != MSGPACK_UNPACK_SUCCESS) {
 | 
			
		||||
    abort();
 | 
			
		||||
  }
 | 
			
		||||
  Object functions;
 | 
			
		||||
  msgpack_rpc_to_object(&unpacked.data, &functions);
 | 
			
		||||
  msgpack_unpacked_destroy(&unpacked);
 | 
			
		||||
  PUT(*metadata, "functions", functions);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void init_error_type_metadata(Dictionary *metadata)
 | 
			
		||||
{
 | 
			
		||||
  Dictionary types = ARRAY_DICT_INIT;
 | 
			
		||||
@@ -784,6 +802,7 @@ static void init_error_type_metadata(Dictionary *metadata)
 | 
			
		||||
 | 
			
		||||
  PUT(*metadata, "error_types", DICTIONARY_OBJ(types));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void init_type_metadata(Dictionary *metadata)
 | 
			
		||||
{
 | 
			
		||||
  Dictionary types = ARRAY_DICT_INIT;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user