diff options
-rw-r--r-- | scripts/gendispatch.lua | 18 | ||||
-rw-r--r-- | scripts/geneval.lua | 21 | ||||
-rw-r--r-- | src/nvim/CMakeLists.txt | 9 | ||||
-rw-r--r-- | src/nvim/api/private/dispatch.h | 10 | ||||
-rw-r--r-- | src/nvim/eval.c | 52 | ||||
-rw-r--r-- | src/nvim/eval.lua | 2 |
6 files changed, 77 insertions, 35 deletions
diff --git a/scripts/gendispatch.lua b/scripts/gendispatch.lua index 54bfdab45b..ce1d8be222 100644 --- a/scripts/gendispatch.lua +++ b/scripts/gendispatch.lua @@ -41,18 +41,20 @@ c_proto = Ct( ) grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1) --- we need at least 2 arguments since the last one is the output file -assert(#arg >= 1) +-- we need at least 3 arguments since the last two are output files +assert(#arg >= 2) functions = {} -- names of all headers relative to the source root (for inclusion in the -- generated file) headers = {} --- output file(dispatch function + metadata serialized with msgpack) -outputf = arg[#arg] +-- output c file(dispatch function + metadata serialized with msgpack) +outputf = arg[#arg-1] +-- output mpack file (metadata) +mpack_outputf = arg[#arg] -- read each input file, parse and append to the api metadata -for i = 1, #arg - 1 do +for i = 1, #arg - 2 do local full_path = arg[i] local parts = {} for part in string.gmatch(full_path, '[^/]+') do @@ -165,7 +167,7 @@ for i = 1, #functions do local fn = functions[i] local args = {} - output:write('static Object handle_'..fn.name..'(uint64_t channel_id, uint64_t request_id, Array args, Error *error)') + output:write('Object handle_'..fn.name..'(uint64_t channel_id, uint64_t request_id, Array args, Error *error)') output:write('\n{') output:write('\n Object ret = NIL;') -- Declare/initialize variables that will hold converted arguments @@ -311,3 +313,7 @@ MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name, ]]) output:close() + +mpack_output = io.open(mpack_outputf, 'wb') +mpack_output:write(packed) +mpack_output:close() diff --git a/scripts/geneval.lua b/scripts/geneval.lua index c9533d7908..396e7b81db 100644 --- a/scripts/geneval.lua +++ b/scripts/geneval.lua @@ -1,5 +1,8 @@ +mpack = require('mpack') + local nvimsrcdir = arg[1] local autodir = arg[2] +local metadata_file = arg[3] if nvimsrcdir == '--help' then print([[ @@ -18,9 +21,20 @@ local funcsfname = autodir .. '/funcs.generated.h' local funcspipe = io.open(funcsfname .. '.hsh', 'w') -local funcs = require('eval') +local funcs = require('eval').funcs + +local metadata = mpack.unpack(io.open(arg[3], 'rb'):read("*all")) + +for i,fun in ipairs(metadata) do + funcs['api_'..fun.name] = { + args=#fun.parameters, + func='api_wrapper', + data='handle_'..fun.name, + } +end + -for name, def in pairs(funcs.funcs) do +for name, def in pairs(funcs) do args = def.args or 0 if type(args) == 'number' then args = {args, args} @@ -28,7 +42,8 @@ for name, def in pairs(funcs.funcs) do args[2] = 'MAX_FUNC_ARGS' end func = def.func or ('f_' .. name) - local val = ('{ %s, %s, &%s }'):format(args[1], args[2], func) + data = def.data or "NULL" + local val = ('{ %s, %s, &%s, %s }'):format(args[1], args[2], func, data) funcspipe:write(name .. '\n' .. val .. '\n') end funcspipe:close() diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 71d48a5df1..8d0be4190c 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -14,6 +14,7 @@ set(GENERATED_DIR ${PROJECT_BINARY_DIR}/src/nvim/auto) set(DISPATCH_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gendispatch.lua) file(GLOB API_HEADERS api/*.h) file(GLOB MSGPACK_RPC_HEADERS msgpack_rpc/*.h) +set(API_METADATA ${PROJECT_BINARY_DIR}/api_metadata.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) @@ -192,8 +193,8 @@ add_custom_command(OUTPUT ${GENERATED_UNICODE_TABLES} ${EASTASIANWIDTH_FILE} ) -add_custom_command(OUTPUT ${GENERATED_API_DISPATCH} - COMMAND ${LUA_PRG} ${DISPATCH_GENERATOR} ${API_HEADERS} ${GENERATED_API_DISPATCH} +add_custom_command(OUTPUT ${GENERATED_API_DISPATCH} ${API_METADATA} + COMMAND ${LUA_PRG} ${DISPATCH_GENERATOR} ${API_HEADERS} ${GENERATED_API_DISPATCH} ${API_METADATA} DEPENDS ${API_HEADERS} ${MSGPACK_RPC_HEADERS} @@ -220,10 +221,10 @@ add_custom_command(OUTPUT ${GENERATED_EX_CMDS_ENUM} ${GENERATED_EX_CMDS_DEFS} add_custom_command(OUTPUT ${GENERATED_FUNCS} COMMAND ${LUA_PRG} ${FUNCS_GENERATOR} - ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_DIR} + ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_DIR} ${API_METADATA} COMMAND $<TARGET_FILE:genhash> ${GENERATED_FUNCS_HASH_INPUT} ${GENERATED_FUNCS} functions functions VimLFuncDef "NOFUNC" - DEPENDS ${FUNCS_GENERATOR} ${EVAL_DEFS_FILE} genhash + DEPENDS ${FUNCS_GENERATOR} ${EVAL_DEFS_FILE} ${API_METADATA} genhash ) add_custom_command(OUTPUT ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP} diff --git a/src/nvim/api/private/dispatch.h b/src/nvim/api/private/dispatch.h index 9047752026..d91456c306 100644 --- a/src/nvim/api/private/dispatch.h +++ b/src/nvim/api/private/dispatch.h @@ -3,13 +3,15 @@ #include "nvim/api/private/defs.h" +typedef Object (*ApiDispatchWrapper)(uint64_t channel_id, + uint64_t request_id, + Array args, + Error *error); + /// The rpc_method_handlers table, used in msgpack_rpc_dispatch(), stores /// functions of this type. typedef struct { - Object (*fn)(uint64_t channel_id, - uint64_t request_id, - Array args, - Error *error); + ApiDispatchWrapper fn; bool async; // function is always safe to run immediately instead of being // put in a request queue for handling when nvim waits for input. } MsgpackRpcRequestHandler; diff --git a/src/nvim/eval.c b/src/nvim/eval.c index c5b5866f56..f731d2406a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -445,13 +445,14 @@ typedef struct { } timer_T; /// Prototype of C function that implements VimL function -typedef void (*VimLFunc)(typval_T *args, typval_T *rvar); +typedef void (*VimLFunc)(typval_T *args, typval_T *rvar, void *data); /// Structure holding VimL function definition typedef struct fst { uint8_t min_argc; ///< Minimal number of arguments. uint8_t max_argc; ///< Maximal number of arguments. VimLFunc func; ///< Function implementation. + void *data; ///< Userdata for function implementation. } VimLFuncDef; KHASH_MAP_INIT_STR(functions, VimLFuncDef) @@ -6981,7 +6982,7 @@ call_func ( } } else { // Find the function name in the table, call its implementation. - VimLFuncDef *const fdef = find_internal_func((char *) fname); + VimLFuncDef *const fdef = find_internal_func((char *)fname); if (fdef != NULL) { if (argcount < fdef->min_argc) { error = ERROR_TOOFEW; @@ -6989,7 +6990,7 @@ call_func ( error = ERROR_TOOMANY; } else { argvars[argcount].v_type = VAR_UNKNOWN; - fdef->func(argvars, rettv); + fdef->func(argvars, rettv, fdef->data); error = ERROR_NONE; } } @@ -7100,13 +7101,10 @@ static inline int get_float_arg(typval_T *argvars, float_T *f) // Some versions of glibc on i386 have an optimization that makes it harder to // call math functions indirectly from inside an inlined function, causing // compile-time errors. Avoid `inline` in that case. #3072 -#ifndef ARCH_32 -inline -#endif -static void float_op_wrapper(typval_T *argvars, typval_T *rettv, - float_T (*function)(float_T)) +static void float_op_wrapper(typval_T *argvars, typval_T *rettv, void *data) { float_T f; + float_T (*function)(float_T) = data; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) { @@ -7116,6 +7114,34 @@ static void float_op_wrapper(typval_T *argvars, typval_T *rettv, } } +static void api_wrapper(typval_T *argvars, typval_T *rettv, void *data) +{ + ApiDispatchWrapper fn = data; + + Array args = ARRAY_DICT_INIT; + + for (typval_T *tv = argvars; tv->v_type != VAR_UNKNOWN; tv++) { + ADD(args, vim_to_object(tv)); + } + + Error err = ERROR_INIT; + Object result = fn(-1, -1, args, &err); + + if (err.set) { + vim_report_error(cstr_as_string(err.msg)); + goto end; + } + + if (!object_to_vim(result, rettv, &err)) { + EMSG2(_("Error converting the call result: %s"), err.msg); + } + +end: + // All arguments were freed already, but we still need to free the array + xfree(args.items); + api_free_object(result); +} + /* * "abs(expr)" function */ @@ -7516,14 +7542,6 @@ static void f_asin(typval_T *argvars, typval_T *rettv) } /* - * "atan()" function - */ -static void f_atan(typval_T *argvars, typval_T *rettv) -{ - float_op_wrapper(argvars, rettv, &atan); -} - -/* * "atan2()" function */ static void f_atan2(typval_T *argvars, typval_T *rettv) @@ -20115,7 +20133,7 @@ void free_all_functions(void) int translated_function_exists(char_u *name) { if (builtin_function(name, -1)) { - return find_internal_func((char *) name) != NULL; + return find_internal_func((char *)name) != NULL; } return find_func(name) != NULL; } diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 627925cd58..bbac27c7db 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -33,7 +33,7 @@ return { assert_notequal={args={2, 3}}, assert_notmatch={args={2, 3}}, assert_true={args={1, 2}}, - atan={args=1}, + atan={args=1, func="float_op_wrapper", data="atan"}, atan2={args=2}, browse={args=4}, browsedir={args=2}, |